Bug 141181 - Umlaute are not displayed corretly for folder names
Summary: Umlaute are not displayed corretly for folder names
Status: RESOLVED FIXED
Alias: None
Product: mailody
Classification: Unmaintained
Component: general (show other bugs)
Version: 0.4.0
Platform: unspecified Linux
: NOR normal
Target Milestone: ---
Assignee: Tom Albers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-02-04 16:46 UTC by Ferdinand Gassauer
Modified: 2007-02-05 00:31 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ferdinand Gassauer 2007-02-04 16:46:57 UTC
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"
Comment 1 Tom Albers 2007-02-05 00:31:34 UTC
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