changeset: 6500:bd2c2a6058a7
user:      Kevin McCarthy <[email protected]>
date:      Thu Jul 17 16:05:47 2014 +0200
link:      http://dev.mutt.org/hg/mutt/rev/bd2c2a6058a7

Add support for utf-8 mailboxes in imap.

This adds support for RFC6855 to imap/*.c.

Thanks to Arnt Gulbrandsen for the original patch.

diffs (349 lines):

diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/browse.c
--- a/imap/browse.c     Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/browse.c     Thu Jul 17 16:05:47 2014 +0200
@@ -75,7 +75,7 @@
     char *ptr;
     imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
     ptr = safe_strdup (mbox);
-    imap_utf7_encode (&ptr);
+    imap_utf_encode (idata, &ptr);
     mbox[sizeof (mbox) - 1] = '\0';
     strncpy (mbox, ptr, sizeof (mbox) - 1);
     FREE (&ptr);
@@ -400,11 +400,14 @@
   char tmp[LONG_STRING];
   char relpath[LONG_STRING];
   IMAP_MBOX mx;
+  IMAP_DATA* idata;
 
   if (imap_parse_path (state->folder, &mx))
     return;
+  if (!(idata = imap_conn_find (&(mx.account), 0)))
+    return;
 
-  imap_unmunge_mbox_name (folder);
+  imap_unmunge_mbox_name (idata, folder);
 
   if (state->entrylen + 1 == state->entrymax)
   {
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/command.c
--- a/imap/command.c    Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/command.c    Thu Jul 17 16:05:47 2014 +0200
@@ -51,6 +51,7 @@
 static void cmd_parse_myrights (IMAP_DATA* idata, const char* s);
 static void cmd_parse_search (IMAP_DATA* idata, const char* s);
 static void cmd_parse_status (IMAP_DATA* idata, char* s);
+static void cmd_parse_enabled (IMAP_DATA* idata, const char* s);
 
 static const char * const Capabilities[] = {
   "IMAP4",
@@ -65,6 +66,7 @@
   "LOGINDISABLED",
   "IDLE",
   "SASL-IR",
+  "ENABLE",
 
   NULL
 };
@@ -522,6 +524,8 @@
     cmd_parse_search (idata, s);
   else if (ascii_strncasecmp ("STATUS", s, 6) == 0)
     cmd_parse_status (idata, s);
+  else if (ascii_strncasecmp ("ENABLED", s, 7) == 0)
+    cmd_parse_enabled (idata, s);
   else if (ascii_strncasecmp ("BYE", s, 3) == 0)
   {
     dprint (2, (debugfile, "Handling BYE\n"));
@@ -728,7 +732,7 @@
   }
   else
   {
-    imap_unmunge_mbox_name (s);
+    imap_unmunge_mbox_name (idata, s);
     list->name = s;
   }
 
@@ -917,7 +921,7 @@
   {
     s = imap_next_word (mailbox);
     *(s - 1) = '\0';
-    imap_unmunge_mbox_name (mailbox);
+    imap_unmunge_mbox_name (idata, mailbox);
   }
 
   status = imap_mboxcache_get (idata, mailbox, 1);
@@ -1022,3 +1026,16 @@
     FREE (&mx.mbox);
   }
 }
+
+/* cmd_parse_enabled: record what the server has enabled */
+static void cmd_parse_enabled (IMAP_DATA* idata, const char* s)
+{
+  dprint (2, (debugfile, "Handling ENABLED\n"));
+
+  while ((s = imap_next_word ((char*)s)) && *s != '\0')
+  {
+    if (ascii_strncasecmp(s, "UTF8=ACCEPT", 11) == 0 ||
+        ascii_strncasecmp(s, "UTF8=ONLY", 9) == 0)
+      idata->unicode = 1;
+  }
+}
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/imap.c
--- a/imap/imap.c       Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/imap.c       Thu Jul 17 16:05:47 2014 +0200
@@ -92,7 +92,7 @@
     return 0;
   }
 
-  imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
+  imap_munge_mbox_name (idata, mbox, sizeof (mbox), mailbox);
 
   if (mutt_bit_isset (idata->capabilities, IMAP4REV1))
     snprintf (buf, sizeof (buf), "STATUS %s (UIDVALIDITY)", mbox);
@@ -117,7 +117,7 @@
 {
   char buf[LONG_STRING], mbox[LONG_STRING];
 
-  imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
+  imap_munge_mbox_name (idata, mbox, sizeof (mbox), mailbox);
   snprintf (buf, sizeof (buf), "CREATE %s", mbox);
 
   if (imap_exec (idata, buf, 0) != 0)
@@ -135,8 +135,8 @@
   char newmbox[LONG_STRING];
   char buf[LONG_STRING];
 
-  imap_munge_mbox_name (oldmbox, sizeof (oldmbox), mx->mbox);
-  imap_munge_mbox_name (newmbox, sizeof (newmbox), newname);
+  imap_munge_mbox_name (idata, oldmbox, sizeof (oldmbox), mx->mbox);
+  imap_munge_mbox_name (idata, newmbox, sizeof (newmbox), newname);
 
   snprintf (buf, sizeof (buf), "RENAME %s %s", oldmbox, newmbox);
 
@@ -162,7 +162,7 @@
     idata = ctx->data;
   }
 
-  imap_munge_mbox_name (mbox, sizeof (mbox), mx.mbox);
+  imap_munge_mbox_name (idata, mbox, sizeof (mbox), mx.mbox);
   snprintf (buf, sizeof (buf), "DELETE %s", mbox);
 
   if (imap_exec ((IMAP_DATA*) idata, buf, 0) != 0)
@@ -386,6 +386,9 @@
   {
     /* capabilities may have changed */
     imap_exec (idata, "CAPABILITY", IMAP_CMD_QUEUE);
+    /* enable RFC6855, if the server supports that */
+    if (mutt_bit_isset (idata->capabilities, ENABLE))
+      imap_exec (idata, "ENABLE UTF8=ACCEPT", IMAP_CMD_QUEUE);
     /* get root delimiter, '/' as default */
     idata->delim = '/';
     imap_exec (idata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
@@ -596,7 +599,7 @@
   idata->newMailCount = 0;
 
   mutt_message (_("Selecting %s..."), idata->mailbox);
-  imap_munge_mbox_name (buf, sizeof(buf), idata->mailbox);
+  imap_munge_mbox_name (idata, buf, sizeof(buf), idata->mailbox);
 
   /* pipeline ACL test */
   if (mutt_bit_isset (idata->capabilities, ACL))
@@ -1521,7 +1524,7 @@
     if (!lastdata)
       lastdata = idata;
 
-    imap_munge_mbox_name (munged, sizeof (munged), name);
+    imap_munge_mbox_name (idata, munged, sizeof (munged), name);
     snprintf (command, sizeof (command),
              "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
 
@@ -1569,9 +1572,9 @@
   else if (mutt_bit_isset(idata->capabilities,IMAP4REV1) ||
           mutt_bit_isset(idata->capabilities,STATUS))
   {
-    imap_munge_mbox_name (mbox, sizeof(mbox), buf);
+    imap_munge_mbox_name (idata, mbox, sizeof(mbox), buf);
     snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox, "MESSAGES");
-    imap_unmunge_mbox_name (mbox);
+    imap_unmunge_mbox_name (idata, mbox);
   }
   else
     /* Server does not support STATUS, and this is not the current mailbox.
@@ -1851,14 +1854,14 @@
     mutt_message (_("Subscribing to %s..."), buf);
   else
     mutt_message (_("Unsubscribing from %s..."), buf);
-  imap_munge_mbox_name (mbox, sizeof(mbox), buf);
+  imap_munge_mbox_name (idata, mbox, sizeof(mbox), buf);
 
   snprintf (buf, sizeof (buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mbox);
 
   if (imap_exec (idata, buf, 0) < 0)
     goto fail;
 
-  imap_unmunge_mbox_name(mx.mbox);
+  imap_unmunge_mbox_name(idata, mx.mbox);
   if (subscribe)
     mutt_message (_("Subscribed to %s"), mx.mbox);
   else
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/imap_private.h
--- a/imap/imap_private.h       Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/imap_private.h       Thu Jul 17 16:05:47 2014 +0200
@@ -115,6 +115,7 @@
   LOGINDISABLED,               /*           LOGINDISABLED */
   IDLE,                         /* RFC 2177: IDLE */
   SASL_IR,                      /* SASL initial response draft */
+  ENABLE,                       /* RFC 5161 */
 
   CAPMAX
 };
@@ -144,7 +145,7 @@
 typedef struct
 {
   char* name;
-  
+
   char delim;
   /* if we end up storing a lot of these we could turn this into a bitfield */
   unsigned char noselect;
@@ -186,6 +187,10 @@
   char* buf;
   unsigned int blen;
   
+  /* If nonzero, we can send UTF-8, and the server will use UTF8 rather
+   * than mUTF7 */
+  int unicode;
+
   /* if set, the response parser will store results for complicated commands
    * here. */
   IMAP_COMMAND_TYPE cmdtype;
@@ -289,13 +294,13 @@
 void imap_qualify_path (char *dest, size_t len, IMAP_MBOX *mx, char* path);
 void imap_quote_string (char* dest, size_t slen, const char* src);
 void imap_unquote_string (char* s);
-void imap_munge_mbox_name (char *dest, size_t dlen, const char *src);
-void imap_unmunge_mbox_name (char *s);
+void imap_munge_mbox_name (IMAP_DATA *idata, char *dest, size_t dlen, const 
char *src);
+void imap_unmunge_mbox_name (IMAP_DATA *idata, char *s);
 int imap_wordcasecmp(const char *a, const char *b);
 
 /* utf7.c */
-void imap_utf7_encode (char **s);
-void imap_utf7_decode (char **s);
+void imap_utf_encode (IMAP_DATA *idata, char **s);
+void imap_utf_decode (IMAP_DATA *idata, char **s);
 
 #if USE_HCACHE
 /* typedef size_t (*hcache_keylen_t)(const char* fn); */
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/message.c
--- a/imap/message.c    Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/message.c    Thu Jul 17 16:05:47 2014 +0200
@@ -642,7 +642,7 @@
   mutt_progress_init (&progressbar, _("Uploading message..."),
                      M_PROGRESS_SIZE, NetInc, len);
 
-  imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
+  imap_munge_mbox_name (idata, mbox, sizeof (mbox), mailbox);
   imap_make_date (internaldate, msg->received);
 
   imap_flags[0] = imap_flags[1] = 0;
@@ -773,7 +773,7 @@
   imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
   if (!*mbox)
     strfcpy (mbox, "INBOX", sizeof (mbox));
-  imap_munge_mbox_name (mmbox, sizeof (mmbox), mbox);
+  imap_munge_mbox_name (idata, mmbox, sizeof (mmbox), mbox);
 
   /* loop in case of TRYCREATE */
   do
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/utf7.c
--- a/imap/utf7.c       Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/utf7.c       Thu Jul 17 16:05:47 2014 +0200
@@ -252,30 +252,40 @@
   return 0;
 }
 
-void imap_utf7_encode (char **s)
+void imap_utf_encode (IMAP_DATA *idata, char **s)
 {
   if (Charset)
   {
     char *t = safe_strdup (*s);
-    if (!mutt_convert_string (&t, Charset, "utf-8", 0))
+    if (t && !mutt_convert_string (&t, Charset, "utf-8", 0))
     {
-      char *u7 = utf8_to_utf7 (t, strlen (t), NULL, 0);
       FREE (s);                /* __FREE_CHECKED__ */
-      *s = u7;
+      if (idata->unicode)
+        *s = safe_strdup (t);
+      else
+        *s = utf8_to_utf7 (t, strlen (t), NULL, 0);
     }
     FREE (&t);
   }
 }
 
-void imap_utf7_decode (char **s)
+void imap_utf_decode (IMAP_DATA *idata, char **s)
 {
+  char *t;
+
   if (Charset)
   {
-    char *t = utf7_to_utf8 (*s, strlen (*s), 0, 0);
+    if (idata->unicode)
+      t = safe_strdup (*s);
+    else
+      t = utf7_to_utf8 (*s, strlen (*s), 0, 0);
+
     if (t && !mutt_convert_string (&t, "utf-8", Charset, 0))
     {
       FREE (s);                /* __FREE_CHECKED__ */
       *s = t;
     }
+    else
+      FREE (&t);
   }
 }
diff -r 5700b43f1e5b -r bd2c2a6058a7 imap/util.c
--- a/imap/util.c       Wed Sep 02 18:14:26 2015 -0700
+++ b/imap/util.c       Thu Jul 17 16:05:47 2014 +0200
@@ -673,23 +673,24 @@
   *d = '\0';
 }
 
+
 /*
  * Quoting and UTF-7 conversion
  */
 
-void imap_munge_mbox_name (char *dest, size_t dlen, const char *src)
+void imap_munge_mbox_name (IMAP_DATA *idata, char *dest, size_t dlen, const 
char *src)
 {
   char *buf;
 
   buf = safe_strdup (src);
-  imap_utf7_encode (&buf);
+  imap_utf_encode (idata, &buf);
 
   imap_quote_string (dest, dlen, buf);
 
   FREE (&buf);
 }
 
-void imap_unmunge_mbox_name (char *s)
+void imap_unmunge_mbox_name (IMAP_DATA *idata, char *s)
 {
   char *buf;
 
@@ -698,7 +699,7 @@
   buf = safe_strdup (s);
   if (buf)
   {
-    imap_utf7_decode (&buf);
+    imap_utf_decode (idata, &buf);
     strncpy (s, buf, strlen (s));
   }
 

Reply via email to