diff --git a/uppsrc/Core/Inet.h b/uppsrc/Core/Inet.h index f677e79fa..52a5336e9 100644 --- a/uppsrc/Core/Inet.h +++ b/uppsrc/Core/Inet.h @@ -12,7 +12,7 @@ String UrlDecode(const char *s, int len); String UrlDecode(const String& s); String QPEncode(const char* s); -String QPDecode(const char *s); +String QPDecode(const char *s, bool undescore_to_space = false); String Base64Encode(const char *s, const char *end); String Base64Encode(const char *s, int len); diff --git a/uppsrc/Core/InetUtil.cpp b/uppsrc/Core/InetUtil.cpp index bc1e61fda..f2fe6f1cc 100644 --- a/uppsrc/Core/InetUtil.cpp +++ b/uppsrc/Core/InetUtil.cpp @@ -175,7 +175,7 @@ String QPEncode(const char* s) int len = 0; const int limit = 70; while(*s) { - if(s[0] >= 33 && s[0] <= 126 && s[0] != '=') { + if(s[0] >= 33 && s[0] <= 126 && s[0] != '=' && s[0] != '_') { r.Cat(s[0]); len++; } @@ -188,8 +188,8 @@ String QPEncode(const char* s) len = 0; } else // Encode HT or SP only if they are at the end of line (before CRLF or EOF) - if((s[0] == ' ' || s[0] == '\t') && - (s[1] && s[1] != '\n') && + if((s[0] == ' ' || s[0] == '\t') && + (s[1] && s[1] != '\n') && (s[1] != '\r' || (s[1] == '\r' && s[2] && s[2] != '\n'))) { r.Cat(s[0]); len++; @@ -212,7 +212,7 @@ String QPEncode(const char* s) return r; } -String QPDecode(const char *s) +String QPDecode(const char *s, bool underscore_to_space) { StringBuffer r; while(*s) { @@ -226,6 +226,9 @@ String QPDecode(const char *s) if(IsXDigit(c1) && IsXDigit(c2)) r.Cat((ctoi(c1) << 4) | ctoi(c2)); } + else + if(underscore_to_space && c == '_') + r.Cat(' '); else r.Cat(c); } diff --git a/uppsrc/Core/POP3/InetMessage.cpp b/uppsrc/Core/POP3/InetMessage.cpp index 7de747570..4241aee19 100644 --- a/uppsrc/Core/POP3/InetMessage.cpp +++ b/uppsrc/Core/POP3/InetMessage.cpp @@ -11,14 +11,12 @@ String QDecode(const String& s) return s; if(begin != "=" || end != "=") return s; - if(ToUpper(enc) == "B") + enc = ToUpper(enc); + if(enc == "B") r = Base64Decode(txt); else - if(ToUpper(enc) == "Q") { - txt.Replace(" ", "_"); - r = QPDecode(txt); - r.Replace("_", " "); - } + if(enc == "Q") + r = QPDecode(txt, true); else return s; int charset = CharsetByName(chs); @@ -88,7 +86,7 @@ String sEncode(const String& text) String txt = ToCharset(CHARSET_UTF8, text); String r = "=?UTF-8?Q?"; for(const char *s = txt; *s; s++) { - if((byte)*s < ' ' || (byte)*s > 127 || findarg(*s, '=', '?', ' ', ',') >= 0) + if((byte)*s < ' ' || (byte)*s > 127 || findarg(*s, '=', '?', ' ', ',', '_') >= 0) r << '=' << FormatIntHexUpper((byte)*s, 2); else r.Cat(*s); diff --git a/uppsrc/Core/src.tpp/Inet$en-us.tpp b/uppsrc/Core/src.tpp/Inet$en-us.tpp index fdb6773dc..85aabd3c2 100644 --- a/uppsrc/Core/src.tpp/Inet$en-us.tpp +++ b/uppsrc/Core/src.tpp/Inet$en-us.tpp @@ -59,13 +59,15 @@ IME type application/x`-www`-form`-urlencoded] (see UrlEncode).&] [s5;:QPEncode`(const char`*`): [_^String^ String]_[* QPEncode]([@(0.0.255) const]_[@(0.0.255) c har`*]_[*@3 s])&] [s2;%% Encodes string to [^http`:`/`/en`.wikipedia`.org`/wiki`/Quoted`-printable^ quote -d`-printable] format .&] +d`-printable] format.&] [s3;%% &] [s4; &] -[s5;:QPDecode`(const char`*`): [_^String^ String]_[* QPDecode]([@(0.0.255) const]_[@(0.0.255) c -har]_`*[*@3 s])&] +[s5;:QPDecode`(const char`*`,bool`): [_^String^ String]_[* QPDecode]([@(0.0.255) const]_[@(0.0.255) c +har]_`*[*@3 s], [@(0.0.255) bool]_[*@3 underscore`_to`_space]_`=_[@(0.0.255) false])&] [s2;%% Decodes string from [^http`:`/`/en`.wikipedia`.org`/wiki`/Quoted`-printable^ quo -ted`-printable] format .&] +ted`-printable] format. If [%-*@3 s] [%-*@3 underscore`_to`_space] +is true, function replaces `'`_`' with space `' `' (as required +by [^http`:`/`/en`.wikipedia`.org`/wiki`/MIME`#Encoded`-Word^ encoded`-word]).&] [s3;%% &] [s4; &] [s5;:Base64Encode`(const char`*`,const char`*`): [_^String^ String]_[* Base64Encode]([@(0.0.255) c