mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Core/POP3: InetMessage header decoder refactored (thanks Oblivion)
git-svn-id: svn://ultimatepp.org/upp/trunk@7111 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
453889fdd9
commit
972873408c
1 changed files with 70 additions and 86 deletions
|
|
@ -1,98 +1,82 @@
|
|||
#include "POP3.h"
|
||||
|
||||
String QDecode(const String& s)
|
||||
{
|
||||
String r, begin, end, chs, enc, txt;
|
||||
// q-encoded text format (RFC 2047):
|
||||
// =?(charset)?(encoding)?(encoded text)?=
|
||||
if(!SplitTo(s, '?', begin, chs, enc, txt, end))
|
||||
return s;
|
||||
if(begin != "=" || end != "=")
|
||||
return s;
|
||||
if(ToUpper(enc) == "B")
|
||||
r = Base64Decode(txt);
|
||||
else
|
||||
if(ToUpper(enc) == "Q") {
|
||||
txt.Replace(" ", "_");
|
||||
r = QPDecode(txt);
|
||||
r.Replace("_", " ");
|
||||
}
|
||||
else
|
||||
return s;
|
||||
int charset = CharsetByName(chs);
|
||||
return charset >= 0 ? ToCharset(CHARSET_DEFAULT, r, charset, '?') : r;
|
||||
}
|
||||
|
||||
String DecodeHeaderValue(const String& s)
|
||||
{
|
||||
String decodedstring;
|
||||
|
||||
for(int begin = 0, end = 0, pos = 0; pos <= s.GetCharCount(); pos++) {
|
||||
pos = s.Find("=?", begin);
|
||||
if(pos < begin || pos > begin) {
|
||||
if(pos == -1) {
|
||||
if(begin >= 0)
|
||||
pos = s.GetCharCount();
|
||||
else
|
||||
break;
|
||||
}
|
||||
end = pos;
|
||||
for(int c = begin; c < end; c++) {
|
||||
if(!IsSpace(s[c])) {
|
||||
decodedstring << s.Mid(begin, end - begin);
|
||||
String r, p, q;
|
||||
int pos = 0, part = 0, length = s.GetLength();
|
||||
bool isq = false;
|
||||
while(pos < length) {
|
||||
if(s[pos] == '=' && s[pos + 1] == '?') {
|
||||
// Process q-encoded text.
|
||||
q.Cat(s.Mid(pos, 2));
|
||||
pos += 2;
|
||||
while(pos < length) {
|
||||
if(s[pos] == '?' && s[pos + 1] == '=' && part == 2) {
|
||||
q.Cat(s.Mid(pos, 2));
|
||||
r.Cat(QDecode(q));
|
||||
q.Clear();
|
||||
pos++;
|
||||
isq = true;
|
||||
part = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
begin = end;
|
||||
}
|
||||
else
|
||||
if(begin == pos) {
|
||||
String decodebuffer;
|
||||
begin = pos += 2;
|
||||
for(int n = 0; pos <= s.GetCharCount(); pos++) {
|
||||
// Quoted-Printable Word Format:
|
||||
// (Character set) ? (Encoding) ? (Word)
|
||||
if(n < 2) {
|
||||
if(s[pos] == '?') {
|
||||
decodebuffer.Cat(" ", 1);
|
||||
n++;
|
||||
}
|
||||
else
|
||||
decodebuffer.Cat(s[pos], 1);
|
||||
}
|
||||
else {
|
||||
// Find ending token.
|
||||
if((end = s.Find("?=", pos)) == -1)
|
||||
return decodedstring = t_("<Parser Error: Cannot Find ending token.>");
|
||||
else {
|
||||
// Check for spaces within the qp word. Some older mail clients do
|
||||
// not encode ' ' spaces to '_'. This behaviour is against the rules.
|
||||
// We have to fix their fault.
|
||||
for(pos; pos < end; pos++) {
|
||||
if(IsSpace(s[pos]))
|
||||
decodebuffer.Cat("_");
|
||||
else
|
||||
decodebuffer.Cat(s[pos], 1);
|
||||
}
|
||||
pos = end += 2;
|
||||
begin = pos;
|
||||
Buffer<char> chs(32), enc(2), txt;
|
||||
txt.Alloc(decodebuffer.GetLength());
|
||||
sscanf(decodebuffer, "%s %s %s",
|
||||
&chs[0],
|
||||
&enc[0],
|
||||
&txt[0]);
|
||||
int charset = CharsetByName(chs);
|
||||
// Now we are ready to decode the quoted-printable text.
|
||||
// QP text should be either base64 or "Q" encoded.
|
||||
if(String(enc) == "B") {
|
||||
decodedstring << ToUnicode(Base64Decode(String(txt)), charset);
|
||||
break;
|
||||
}
|
||||
else if(String(enc) == "Q") {
|
||||
String qtext(txt);
|
||||
for(int i = 0; i < qtext.GetCharCount(); i++) {
|
||||
if(qtext[i] == '=') {
|
||||
String ascii;
|
||||
unsigned int chr1 = ctoi(qtext[++i]);
|
||||
unsigned int chr2 = ctoi(qtext[++i]);
|
||||
ascii.Cat(16 * chr1 + chr2);
|
||||
decodedstring << ToUnicode(ascii, charset);
|
||||
}
|
||||
else
|
||||
if(qtext[i] == '_') {
|
||||
decodedstring.Cat(" ");
|
||||
}
|
||||
else
|
||||
decodedstring.Cat(qtext[i], 1);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(s[pos] == '?' && part < 2)
|
||||
part++;
|
||||
q.Cat(s[pos]);
|
||||
pos++;
|
||||
if(pos == length && !q.IsEmpty())
|
||||
r.Cat(q);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Process plain text
|
||||
while(pos < length) {
|
||||
if(s[pos] == '=' && s[pos + 1] == '?') {
|
||||
pos--;
|
||||
break;
|
||||
}
|
||||
p.Cat(s[pos], 1);
|
||||
pos++;
|
||||
if(pos == length)
|
||||
isq = false;
|
||||
}
|
||||
bool haschar = false;
|
||||
for(int i = 0; i < p.GetLength(); i++)
|
||||
if(!IsSpace(p[i])) {
|
||||
haschar = true;
|
||||
break;
|
||||
}
|
||||
if((isq && haschar) || !isq)
|
||||
r.Cat(p);
|
||||
p.Clear();
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
return decodedstring;
|
||||
return r;
|
||||
}
|
||||
|
||||
bool InetMessage::ReadHeader(VectorMap<String, String>& hdr, Stream& ss)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue