You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kshowmail/kshowmail/decodeRFC2047.cpp

183 lines
4.8 KiB

/***************************************************************************
decodeRFC2047.cpp - description
-------------------
begin : Mon Jan 28 2002
copyright : (C) 2002 by Eggert Ehmke
email : eggert.ehmke@berlin.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "decodeRFC2047.h"
/*
* These functions have been adapted from the KMail program
*/
TQCString decodeQuotedPrintable(const TQCString& aStr)
{
TQCString bStr = aStr;
if (aStr.isNull())
bStr = "";
DwString dwsrc(bStr.data());
DwString dwdest;
DwDecodeQuotedPrintable(dwsrc, dwdest);
return dwdest.c_str();
}
TQCString decodeBase64(const TQCString& aStr)
{
TQCString bStr = aStr;
if (aStr.isNull())
bStr = "";
while (bStr.length() < 16) bStr += "=";
DwString dwsrc(bStr.data(), bStr.length());
DwString dwdest;
TQCString result;
DwDecodeBase64(dwsrc, dwdest);
result = dwdest.c_str();
return result;
}
TQTextCodec* codecForName(const TQCString& _str)
{
if (_str.isEmpty()) return NULL;
if (_str.lower() == "shift_jis" || _str.lower() == "shift-jis")
return TQTextCodec::codecForName("sjis");
return TQTextCodec::codecForName(_str.lower().replace(
TQRegExp("windows"), "cp") );
}
TQString Codecs::decodeRFC2047(const TQCString& aStr)
{
TQString result;
TQCString charset;
char *pos, *beg, *end, *mid;
TQCString str, cstr, LWSP_buffer;
char encoding, ch;
bool valid, lastWasEncodedWord=FALSE;
const int maxLen=200;
int i;
if (aStr.find("=?") < 0)
return TQString::fromLocal8Bit(aStr).replace(TQRegExp("\n[\t ]")," ");
for (pos=aStr.data(); *pos; pos++)
{
// line unfolding
if ( pos[0] == '\r' && pos[1] == '\n' ) {
pos++;
continue;
}
if ( pos[0] == '\n' )
continue;
// collect LWSP after encoded-words,
// because we might need to throw it out
// (when the next word is an encoded-word)
if ( lastWasEncodedWord && ( pos[0] == ' ' || pos[0] == '\t' ) )
{
LWSP_buffer += pos[0];
continue;
}
// verbatimly copy normal text
if (pos[0]!='=' || pos[1]!='?')
{
result += LWSP_buffer + pos[0];
LWSP_buffer = 0;
lastWasEncodedWord = FALSE;
continue;
}
// found possible encoded-word
beg = pos+2;
end = beg;
valid = TRUE;
// parse charset name
charset = "";
for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(*pos==' '||ispunct(*pos)||isalnum(*pos))); i++)
{
charset += *pos;
pos++;
}
if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE;
else
{
// get encoding and check delimiting question marks
encoding = toupper(pos[1]);
if (pos[2]!='?' || (encoding!='Q' && encoding!='B'))
valid = FALSE;
pos+=3;
i+=3;
}
if (valid)
{
mid = pos;
// search for end of encoded part
while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='='))
{
i++;
pos++;
}
end = pos+2;//end now points to the first char after the encoded string
if (i>=maxLen || !*pos)
valid = FALSE;
}
if (valid)
{
// valid encoding: decode and throw away separating LWSP
ch = *pos;
*pos = '\0';
str = TQCString(mid).left((int)(mid - pos - 1));
if (encoding == 'Q')
{
// decode quoted printable text
for (i=str.length()-1; i>=0; i--)
if (str[i]=='_')
str[i]=' ';
cstr = decodeQuotedPrintable(str);
}
else
{
// decode base64 text
cstr = decodeBase64(str);
}
TQTextCodec *codec = codecForName(charset);
if (!codec)
codec = codecForName(TDEGlobal::locale()->encoding());
if (codec)
result += codec->toUnicode(cstr);
else
result += TQString::fromLocal8Bit(cstr);
lastWasEncodedWord = TRUE;
*pos = ch;
pos = end -1;
}
else
{
// invalid encoding, keep separating LWSP.
//result += "=?";
//pos = beg -1; // because pos gets increased shortly afterwards
pos = beg - 2;
result += LWSP_buffer;
result += *pos++;
result += *pos;
lastWasEncodedWord = FALSE;
}
LWSP_buffer = 0;
}
return result;
}