-rw-r--r-- | noncore/net/mail/defines.h | 11 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.cpp | 107 | ||||
-rw-r--r-- | noncore/net/mail/libmailwrapper/mailwrapper.h | 2 | ||||
-rw-r--r-- | noncore/net/mail/mailwrapper.cpp | 107 | ||||
-rw-r--r-- | noncore/net/mail/mailwrapper.h | 2 |
5 files changed, 201 insertions, 28 deletions
diff --git a/noncore/net/mail/defines.h b/noncore/net/mail/defines.h index 9036658..d9cdab0 100644 --- a/noncore/net/mail/defines.h +++ b/noncore/net/mail/defines.h @@ -39,2 +39,13 @@ +/* used for decoding imapfoldername */ +#define UNDEFINED 64 +#define MAXLINE 76 +#define UTF16MASK 0x03FFUL +#define UTF16SHIFT 10 +#define UTF16BASE 0x10000UL +#define UTF16HIGHSTART 0xD800UL +#define UTF16HIGHEND 0xDBFFUL +#define UTF16LOSTART 0xDC00UL +#define UTF16LOEND 0xDFFFUL + #endif diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.cpp b/noncore/net/mail/libmailwrapper/mailwrapper.cpp index 858283f..75c06f9 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.cpp +++ b/noncore/net/mail/libmailwrapper/mailwrapper.cpp @@ -23,16 +23,2 @@ Folder::Folder(const QString&tmp_name, const QString&sep ) nameDisplay = name; - - for ( int pos = nameDisplay.find( '&' ); pos != -1; - pos = nameDisplay.find( '&' ) ) { - int end = nameDisplay.find( '-' ); - if ( end == -1 || end <= pos ) break; - QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 ); - // TODO: do real base64 decoding here ! - if ( str64.compare( "APw" ) == 0 ) { - nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" ); - } else if ( str64.compare( "APY" ) == 0 ) { - nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" ); - } - } - qDebug( "folder " + name + " - displayed as " + nameDisplay ); separator = sep; @@ -48,2 +34,6 @@ IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const Q { + // Decode IMAP foldername + nameDisplay = IMAPFolder::decodeFolderName( name ); + qDebug( "folder " + name + " - displayed as " + nameDisplay ); + if (prefix.length()>0) { @@ -55,2 +45,91 @@ IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const Q +static unsigned char base64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + +/** + * Decodes base64 encoded parts of the imapfolder name + * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc + */ +QString IMAPFolder::decodeFolderName( const QString &name ) +{ + unsigned char c, i, bitcount; + unsigned long ucs4, utf16, bitbuf; + unsigned char base64[256], utf8[6]; + unsigned long srcPtr = 0; + QCString dst; + QCString src = name.ascii(); + + /* initialize modified base64 decoding table */ + memset(base64, UNDEFINED, sizeof(base64)); + for (i = 0; i < sizeof(base64chars); ++i) { + base64[(int)base64chars[i]] = i; + } + + /* loop until end of string */ + while (srcPtr < src.length ()) { + c = src[srcPtr++]; + /* deal with literal characters and &- */ + if (c != '&' || src[srcPtr] == '-') { + /* encode literally */ + dst += c; + /* skip over the '-' if this is an &- sequence */ + if (c == '&') + srcPtr++; + } else { + /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */ + bitbuf = 0; + bitcount = 0; + ucs4 = 0; + while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) { + ++srcPtr; + bitbuf = (bitbuf << 6) | c; + bitcount += 6; + /* enough bits for a UTF-16 character? */ + if (bitcount >= 16) { + bitcount -= 16; + utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff; + /* convert UTF16 to UCS4 */ + if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) { + ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT; + continue; + } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) { + ucs4 += utf16 - UTF16LOSTART + UTF16BASE; + } else { + ucs4 = utf16; + } + /* convert UTF-16 range of UCS4 to UTF-8 */ + if (ucs4 <= 0x7fUL) { + utf8[0] = ucs4; + i = 1; + } else if (ucs4 <= 0x7ffUL) { + utf8[0] = 0xc0 | (ucs4 >> 6); + utf8[1] = 0x80 | (ucs4 & 0x3f); + i = 2; + } else if (ucs4 <= 0xffffUL) { + utf8[0] = 0xe0 | (ucs4 >> 12); + utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[2] = 0x80 | (ucs4 & 0x3f); + i = 3; + } else { + utf8[0] = 0xf0 | (ucs4 >> 18); + utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f); + utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[3] = 0x80 | (ucs4 & 0x3f); + i = 4; + } + /* copy it */ + for (c = 0; c < i; ++c) { + dst += utf8[c]; + } + } + } + /* skip over trailing '-' in modified UTF-7 encoding */ + if (src[srcPtr] == '-') + ++srcPtr; + } + } + + return QString::fromUtf8( dst.data() ); +} + MailWrapper::MailWrapper( Settings *s ) diff --git a/noncore/net/mail/libmailwrapper/mailwrapper.h b/noncore/net/mail/libmailwrapper/mailwrapper.h index d78f8e9..02fe4b7 100644 --- a/noncore/net/mail/libmailwrapper/mailwrapper.h +++ b/noncore/net/mail/libmailwrapper/mailwrapper.h @@ -90,3 +90,5 @@ class IMAPFolder : public Folder private: + static QString decodeFolderName( const QString &name ); bool m_MaySelect; + }; diff --git a/noncore/net/mail/mailwrapper.cpp b/noncore/net/mail/mailwrapper.cpp index 858283f..75c06f9 100644 --- a/noncore/net/mail/mailwrapper.cpp +++ b/noncore/net/mail/mailwrapper.cpp @@ -23,16 +23,2 @@ Folder::Folder(const QString&tmp_name, const QString&sep ) nameDisplay = name; - - for ( int pos = nameDisplay.find( '&' ); pos != -1; - pos = nameDisplay.find( '&' ) ) { - int end = nameDisplay.find( '-' ); - if ( end == -1 || end <= pos ) break; - QString str64 = nameDisplay.mid( pos + 1, end - pos - 1 ); - // TODO: do real base64 decoding here ! - if ( str64.compare( "APw" ) == 0 ) { - nameDisplay = nameDisplay.replace( pos, end - pos + 1, "ue" ); - } else if ( str64.compare( "APY" ) == 0 ) { - nameDisplay = nameDisplay.replace( pos, end - pos + 1, "oe" ); - } - } - qDebug( "folder " + name + " - displayed as " + nameDisplay ); separator = sep; @@ -48,2 +34,6 @@ IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const Q { + // Decode IMAP foldername + nameDisplay = IMAPFolder::decodeFolderName( name ); + qDebug( "folder " + name + " - displayed as " + nameDisplay ); + if (prefix.length()>0) { @@ -55,2 +45,91 @@ IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const Q +static unsigned char base64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + +/** + * Decodes base64 encoded parts of the imapfolder name + * Code taken from kde cvs: kdebase/kioslave/imap4/rfcdecoder.cc + */ +QString IMAPFolder::decodeFolderName( const QString &name ) +{ + unsigned char c, i, bitcount; + unsigned long ucs4, utf16, bitbuf; + unsigned char base64[256], utf8[6]; + unsigned long srcPtr = 0; + QCString dst; + QCString src = name.ascii(); + + /* initialize modified base64 decoding table */ + memset(base64, UNDEFINED, sizeof(base64)); + for (i = 0; i < sizeof(base64chars); ++i) { + base64[(int)base64chars[i]] = i; + } + + /* loop until end of string */ + while (srcPtr < src.length ()) { + c = src[srcPtr++]; + /* deal with literal characters and &- */ + if (c != '&' || src[srcPtr] == '-') { + /* encode literally */ + dst += c; + /* skip over the '-' if this is an &- sequence */ + if (c == '&') + srcPtr++; + } else { + /* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */ + bitbuf = 0; + bitcount = 0; + ucs4 = 0; + while ((c = base64[(unsigned char) src[srcPtr]]) != UNDEFINED) { + ++srcPtr; + bitbuf = (bitbuf << 6) | c; + bitcount += 6; + /* enough bits for a UTF-16 character? */ + if (bitcount >= 16) { + bitcount -= 16; + utf16 = (bitcount ? bitbuf >> bitcount : bitbuf) & 0xffff; + /* convert UTF16 to UCS4 */ + if (utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) { + ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT; + continue; + } else if (utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) { + ucs4 += utf16 - UTF16LOSTART + UTF16BASE; + } else { + ucs4 = utf16; + } + /* convert UTF-16 range of UCS4 to UTF-8 */ + if (ucs4 <= 0x7fUL) { + utf8[0] = ucs4; + i = 1; + } else if (ucs4 <= 0x7ffUL) { + utf8[0] = 0xc0 | (ucs4 >> 6); + utf8[1] = 0x80 | (ucs4 & 0x3f); + i = 2; + } else if (ucs4 <= 0xffffUL) { + utf8[0] = 0xe0 | (ucs4 >> 12); + utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[2] = 0x80 | (ucs4 & 0x3f); + i = 3; + } else { + utf8[0] = 0xf0 | (ucs4 >> 18); + utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f); + utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f); + utf8[3] = 0x80 | (ucs4 & 0x3f); + i = 4; + } + /* copy it */ + for (c = 0; c < i; ++c) { + dst += utf8[c]; + } + } + } + /* skip over trailing '-' in modified UTF-7 encoding */ + if (src[srcPtr] == '-') + ++srcPtr; + } + } + + return QString::fromUtf8( dst.data() ); +} + MailWrapper::MailWrapper( Settings *s ) diff --git a/noncore/net/mail/mailwrapper.h b/noncore/net/mail/mailwrapper.h index d78f8e9..02fe4b7 100644 --- a/noncore/net/mail/mailwrapper.h +++ b/noncore/net/mail/mailwrapper.h @@ -90,3 +90,5 @@ class IMAPFolder : public Folder private: + static QString decodeFolderName( const QString &name ); bool m_MaySelect; + }; |