Version: 0.4.0 (using KDE 3.5.6, compiled sources) Compiler: Target: x86_64-suse-linux OS: Linux (x86_64) release 2.6.18.2-34-default the folder name "Gösing" is displayed as "G&APY-sing"
SVN commit 630300 by toma: Make it possible to use international characters in foldernames read and write. Resync mailbox list to see it. Thanks for reporting. BUG:141181 M +267 -8 imap.cpp M +5 -0 imap.h --- trunk/playground/pim/mailody/src/imap.cpp #630299:630300 @@ -321,6 +321,8 @@ if (y.startsWith("\"") && y.endsWith("\"")) y=y.mid(1, y.length()-2); + y = decodeIMAPFolderName(y); + // kdDebug() << "Mailbox found.. " << y << endl; newList[y] = true; @@ -831,20 +833,23 @@ emit messageCount( box, 0); emit unseenCount( box, 0); emit allUidsKnown( box ); // clear the view - m_queue.prepend(Queue(Queue::SyncMailBox, box, "SELECT \""+box+"\"")); + const QString box2 = encodeIMAPFolderName(box); + m_queue.prepend(Queue(Queue::SyncMailBox, box, "SELECT \""+box2+"\"")); } void Imap::selectMailBox(const QString& box) { // kdDebug() << k_funcinfo << box << endl; - m_queue.prepend(Queue(Queue::SelectMailBox, box, "SELECT \""+box+"\"")); + const QString box2 = encodeIMAPFolderName(box); + m_queue.prepend(Queue(Queue::SelectMailBox, box, "SELECT \""+box2+"\"")); } void Imap::checkMail(const QString& box) { // kdDebug() << k_funcinfo << box << endl; + const QString box2 = encodeIMAPFolderName(box); m_queue.append(Queue(Queue::CheckMail, box, - "STATUS \""+box+"\" (MESSAGES UNSEEN)")); + "STATUS \""+box2+"\" (MESSAGES UNSEEN)")); } void Imap::slotSendNoop() @@ -856,26 +861,31 @@ void Imap::expungeMailBox(const QString& box) { // kdDebug() << k_funcinfo << box << endl; + const QString box2 = encodeIMAPFolderName(box); m_queue.append(Queue(Queue::Expunge, box, "EXPUNGE")); } void Imap::createMailBox(const QString& box) { // kdDebug() << k_funcinfo << box << endl; - m_queue.append(Queue(Queue::CreateMailBox, box, "CREATE \"" + box + "\"")); + const QString box2 = encodeIMAPFolderName(box); + m_queue.append(Queue(Queue::CreateMailBox, box, "CREATE \"" + box2 + "\"")); } void Imap::deleteMailBox(const QString& box) { // kdDebug() << k_funcinfo << box << endl; - m_queue.append(Queue(Queue::DeleteMailBox, box, "DELETE \"" + box + "\"")); + const QString box2 = encodeIMAPFolderName(box); + m_queue.append(Queue(Queue::DeleteMailBox, box, "DELETE \"" + box2 + "\"")); } void Imap::renameMailBox(const QString& oldbox, const QString& newbox) { // kdDebug() << k_funcinfo << oldbox << "->" << newbox << endl; + const QString oldbox2 = encodeIMAPFolderName(oldbox); + const QString newbox2 = encodeIMAPFolderName(newbox); m_queue.append(Queue(Queue::RenameMailBox, oldbox + "~" + newbox, - "RENAME \"" + oldbox + "\" \"" + newbox + "\"")); + "RENAME \"" + oldbox2 + "\" \"" + newbox2 + "\"")); } //---------------- Messages -----------------------------// @@ -885,8 +895,9 @@ { // kdDebug() << k_funcinfo << origbox // << " - " << uid << " -> " << destbox << endl; + const QString destbox2 = encodeIMAPFolderName(destbox); m_queue.append(Queue(Queue::Move, origbox, - "UID COPY " + QString::number(uid) + " \"" + destbox+ "\"")); + "UID COPY " + QString::number(uid) + " \"" + destbox2+ "\"")); addFlag(uid, origbox, "\\Deleted"); } @@ -935,8 +946,9 @@ void Imap::saveMessage(const QString& mb, const QString& message) { // kdDebug() << k_funcinfo << message << endl; + const QString mb2 = encodeIMAPFolderName(mb); m_queue.append( Queue(Queue::SaveMessage, mb, - "APPEND \"" + mb + "\" (\\Seen) {" + "APPEND \"" + mb2 + "\" (\\Seen) {" + QString::number(message.length()) + "}")); m_queue.append( Queue(Queue::SaveMessageData, mb, message)); @@ -1211,6 +1223,8 @@ return true; } +//---------------------------------- ----------------------------------// + /* Copy from KDE/3.5/kdepim/kioslaves/imap4/rfcdecoder.cc */ /* Copyright (C) 2000 s.carstens@gmx.de */ /* replace " with \" and \ with \\ " and \ characters */ @@ -1229,6 +1243,251 @@ return result; } +//--------------------------------------------------------------------------- + +/* Copy from KDE/3.5/kdepim/kioslaves/imap4/rfcdecoder.cc */ +// This part taken from rfc 2192 IMAP URL Scheme. C. Newman. September 1997. +// adapted to QT-Toolkit by Sven Carstens <s.carstens@gmx.de> 2000 + +static unsigned char base64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; +#define UNDEFINED 64 +#define MAXLINE 76 + +/* UTF16 definitions */ +#define UTF16MASK 0x03FFUL +#define UTF16SHIFT 10 +#define UTF16BASE 0x10000UL +#define UTF16HIGHSTART 0xD800UL +#define UTF16HIGHEND 0xDBFFUL +#define UTF16LOSTART 0xDC00UL +#define UTF16LOEND 0xDFFFUL + +/* Convert an IMAP mailbox to a Unicode path + */ +QString Imap::decodeIMAPFolderName(const QString & inSrc) +{ + unsigned char c, i, bitcount; + unsigned long ucs4, utf16, bitbuf; + unsigned char base64[256], utf8[6]; + unsigned long srcPtr = 0; + QCString dst; + QCString src = inSrc.ascii (); + uint srcLen = inSrc.length(); + + /* 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 < srcLen) + { + 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 ()); } +/* Convert Unicode path to modified UTF-7 IMAP mailbox + */ +QString Imap::encodeIMAPFolderName (const QString & inSrc) +{ + unsigned int utf8pos, utf8total, c, utf7mode, bitstogo, utf16flag; + unsigned long ucs4, bitbuf; + QCString src = inSrc.utf8 (); + QString dst; + + ulong srcPtr = 0; + utf7mode = 0; + utf8total = 0; + bitstogo = 0; + utf8pos = 0; + bitbuf = 0; + ucs4 = 0; + while (srcPtr < src.length ()) + { + c = (unsigned char) src[srcPtr++]; + /* normal character? */ + if (c >= ' ' && c <= '~') + { + /* switch out of UTF-7 mode */ + if (utf7mode) + { + if (bitstogo) + { + dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F]; + bitstogo = 0; + } + dst += '-'; + utf7mode = 0; + } + dst += c; + /* encode '&' as '&-' */ + if (c == '&') + { + dst += '-'; + } + continue; + } + /* switch to UTF-7 mode */ + if (!utf7mode) + { + dst += '&'; + utf7mode = 1; + } + /* Encode US-ASCII characters as themselves */ + if (c < 0x80) + { + ucs4 = c; + utf8total = 1; + } + else if (utf8total) + { + /* save UTF8 bits into UCS4 */ + ucs4 = (ucs4 << 6) | (c & 0x3FUL); + if (++utf8pos < utf8total) + { + continue; + } + } + else + { + utf8pos = 1; + if (c < 0xE0) + { + utf8total = 2; + ucs4 = c & 0x1F; + } + else if (c < 0xF0) + { + utf8total = 3; + ucs4 = c & 0x0F; + } + else + { + /* NOTE: can't convert UTF8 sequences longer than 4 */ + utf8total = 4; + ucs4 = c & 0x03; + } + continue; + } + /* loop to split ucs4 into two utf16 chars if necessary */ + utf8total = 0; + do + { + if (ucs4 >= UTF16BASE) + { + ucs4 -= UTF16BASE; + bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT) + UTF16HIGHSTART); + ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART; + utf16flag = 1; + } + else + { + bitbuf = (bitbuf << 16) | ucs4; + utf16flag = 0; + } + bitstogo += 16; + /* spew out base64 */ + while (bitstogo >= 6) + { + bitstogo -= 6; + dst += base64chars[(bitstogo ? (bitbuf >> bitstogo) : bitbuf) & 0x3F]; + } + } + while (utf16flag); + } + /* if in UTF-7 mode, finish in ASCII */ + if (utf7mode) + { + if (bitstogo) + { + dst += base64chars[(bitbuf << (6 - bitstogo)) & 0x3F]; + } + dst += '-'; + } + return quoteIMAP(dst); +} + +} + #include "imap.moc" --- trunk/playground/pim/mailody/src/imap.h #630299:630300 @@ -238,8 +238,13 @@ void integrity(const QString& mb, int); void timerEvent( QTimerEvent * ); void getCapabilities(); + + /* taken from rfcencoder */ QString quoteIMAP(const QString &src); + QString decodeIMAPFolderName(const QString & inSrc); + QString encodeIMAPFolderName(const QString & inSrc); + signals: /** * Emitted when the mailbox list is updated