123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204moduleStable=structopenCore.Core_stablemoduleEncoding=structmoduleV1=structtypet=[`Base64|`Bit7|`Bit8|`Binary|`Quoted_printable|`Unknownofstring][@@derivingsexp,bin_io]endendmoduleV1=structtypet={encoding:Encoding.V1.t;content:Bigstring_shared.Stable.V1.t}[@@derivingsexp,bin_io]endendopenCoremoduleEncoding=struct(** Text or binary are the type of the plaintext. For Base64, if the mode is
text, '\n' is turned into '\r\n' when encoding, and viceversa. *)typeknown=[`Base64|`Bit7|`Bit8|`Binary|`Quoted_printable][@@derivingsexp_of,compare,hash]typet=(* Stable.Encoding.V1.t = *)[known|`Unknownofstring][@@derivingsexp_of,compare,hash]letof_stringencoding=matchencoding|>String.strip|>String.lowercasewith|"base64"->`Base64|"7bit"->`Bit7|"8bit"->`Bit8|"binary"->`Binary|"quoted-printable"->`Quoted_printable|unknown->`Unknownunknown;;letto_string=function|`Base64->"base64"|`Bit7->"7bit"|`Bit8->"8bit"|`Binary->"binary"|`Quoted_printable->"quoted-printable"|`Unknownunknown->unknown;;letdefault=`Bit7letdefault'=`Bit7letof_headers?(ignore_base64_for_multipart=true)headers=Headers.lastheaders"content-transfer-encoding"|>Option.map~f:of_string|>function|Some`Base64whenignore_base64_for_multipart->letis_multipart=matchMedia_type.from_headersheaderswith|Somemedia_type->Media_type.is_multipartmedia_type|None->falseinifis_multipartthenSomedefaultelseSome`Base64|_asencoding->encoding;;letof_headers_or_default?ignore_base64_for_multipartheaders=matchof_headers?ignore_base64_for_multipartheaderswith|Somet->t|None->default;;endtypet=Stable.V1.t={encoding:Encoding.t;content:Bigstring_shared.t}[@@derivingsexp_of,compare,hash]letencodingt=t.encodingletencoded_contentst=t.contentletencoded_contents_stringt=Bigstring_shared.to_string(encoded_contentst)letof_bigstring_shared~encodingcontent={encoding;content}letof_string~encodingstr=of_bigstring_shared~encoding(Bigstring_shared.of_stringstr);;letempty=of_bigstring_shared~encoding:Encoding.defaultBigstring_shared.emptymoduleIdentity=structletencodebstr=bstrletdecodebstr=bstrendmoduleBase64=structincludeBase64.Make(structletchar62='+'letchar63='/'letpad_char='='letpad_when_encoding=true(* Permissive - ignore anything that would be an invalid base64 character... *)letignore_char=function|'0'..'9'|'a'..'z'|'A'..'Z'|'+'|'/'|'='->false|_->true;;end)letdecodebstr=bstr|>Bigstring_shared.to_string|>decode(* Ignore unconsumed data *)|>fst|>Bigstring_shared.of_string;;letsplit~len=letrecgoaccbstr=ifBigstring_shared.lengthbstr<=lenthenList.rev(bstr::acc)elsego(Bigstring_shared.subbstr~len::acc)(Bigstring_shared.subbstr~pos:len)ingo[];;letencoded_line_length=76letdecoded_block_length=encoded_line_length/4*3letencodebstr=split~len:decoded_block_lengthbstr|>List.map~f:(funbstr->Bigstring_shared.to_stringbstr|>encode)|>String_monoid.concat_string~sep:"\n"|>Bigstring_shared.of_string_monoid;;endmoduleQuoted_printable=structletdecodebstr=(* The RFC2045 says that newlines can be converted to the platforms native
format, so that's what we'll do. It's the same for both binary data and
text data. If a CRLF sequence appears in the decoded data, that's because
it was encoded as =0D=0A, which means the characters shouldn't be
interpreted as EOL. *)letbigbuffer,_=Quoted_printable_lexer.decode_quoted_printable(Bigstring_shared.lengthbstr)(Bigstring_shared.to_lexbufbstr)inBigstring_shared.of_bigbuffer_volatilebigbuffer;;letencodebstr=letbigbuffer=Quoted_printable_lexer.encode_quoted_printable(Bigstring_shared.lengthbstr)(Bigstring_shared.to_lexbufbstr)inBigstring_shared.of_bigbuffer_volatilebigbuffer;;endletdecodet=matcht.encodingwith|`Base64->Some(Base64.decodet.content)|`Quoted_printable->Some(Quoted_printable.decodet.content)|`Bit7->Some(Identity.decodet.content)|`Bit8->Some(Identity.decodet.content)|`Binary->Some(Identity.decodet.content)|`Unknown_->None;;letencode~encodingbstr=letbstr=matchencodingwith|`Base64->Base64.encodebstr|`Quoted_printable->Quoted_printable.encodebstr|`Bit7->Identity.encodebstr|`Bit8->Identity.encodebstr|`Binary->Identity.encodebstrinletencoding=(encoding:>Encoding.t)inof_bigstring_shared~encodingbstr;;