summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/mail/defines.h11
-rw-r--r--noncore/net/mail/libmailwrapper/mailwrapper.cpp107
-rw-r--r--noncore/net/mail/libmailwrapper/mailwrapper.h2
-rw-r--r--noncore/net/mail/mailwrapper.cpp107
-rw-r--r--noncore/net/mail/mailwrapper.h2
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
@@ -32,9 +32,20 @@
#define IMAP_SSL_PORT "993"
#define SMTP_PORT "25"
#define SMTP_SSL_PORT "465"
#define POP3_PORT "110"
#define POP3_SSL_PORT "995"
#define NNTP_PORT "119"
#define NNTP_SSL_PORT "563"
+/* 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
@@ -16,48 +16,127 @@ Attachment::Attachment( DocLnk lnk )
doc = lnk;
size = QFileInfo( doc.file() ).size();
}
Folder::Folder(const QString&tmp_name, const QString&sep )
{
name = tmp_name;
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;
}
const QString& Folder::Separator()const
{
return separator;
}
IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix )
: Folder( name,sep ),m_MaySelect(select)
{
+ // Decode IMAP foldername
+ nameDisplay = IMAPFolder::decodeFolderName( name );
+ qDebug( "folder " + name + " - displayed as " + nameDisplay );
+
if (prefix.length()>0) {
if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) {
nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length());
}
}
}
+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 )
: QObject()
{
settings = s;
}
QString MailWrapper::mailsmtpError( int errnum )
{
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
@@ -83,17 +83,19 @@ protected:
};
class IMAPFolder : public Folder
{
public:
IMAPFolder(const QString&name, const QString&sep, bool select=true,const QString&prefix="" );
virtual bool may_select()const{return m_MaySelect;}
private:
+ static QString decodeFolderName( const QString &name );
bool m_MaySelect;
+
};
class MailWrapper : public QObject
{
Q_OBJECT
public:
MailWrapper( Settings *s );
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
@@ -16,48 +16,127 @@ Attachment::Attachment( DocLnk lnk )
doc = lnk;
size = QFileInfo( doc.file() ).size();
}
Folder::Folder(const QString&tmp_name, const QString&sep )
{
name = tmp_name;
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;
}
const QString& Folder::Separator()const
{
return separator;
}
IMAPFolder::IMAPFolder(const QString&name,const QString&sep, bool select,const QString&prefix )
: Folder( name,sep ),m_MaySelect(select)
{
+ // Decode IMAP foldername
+ nameDisplay = IMAPFolder::decodeFolderName( name );
+ qDebug( "folder " + name + " - displayed as " + nameDisplay );
+
if (prefix.length()>0) {
if (nameDisplay.startsWith(prefix) && nameDisplay.length()>prefix.length()) {
nameDisplay=nameDisplay.right(nameDisplay.length()-prefix.length());
}
}
}
+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 )
: QObject()
{
settings = s;
}
QString MailWrapper::mailsmtpError( int errnum )
{
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
@@ -83,17 +83,19 @@ protected:
};
class IMAPFolder : public Folder
{
public:
IMAPFolder(const QString&name, const QString&sep, bool select=true,const QString&prefix="" );
virtual bool may_select()const{return m_MaySelect;}
private:
+ static QString decodeFolderName( const QString &name );
bool m_MaySelect;
+
};
class MailWrapper : public QObject
{
Q_OBJECT
public:
MailWrapper( Settings *s );