On Sun, Jan 29, 2012 at 11:21:22AM -0800, Michael Elkins wrote:
> On Sun, Jan 29, 2012 at 01:28:33AM -0700, Todd Hoffmann wrote:
> >It seems like it would be easiest to just put the labels in the x-label
> >field. I started digging into the mutt code to implement this and
> >encountered some issues. The patch I've included does make the labels
> >appear in the message index if I include %y in the index_format setting,
> >but some seem to be encoded. I tried to figure out if I need to use
> >rfc2047_decode or something, but I haven't gotten anything to work so
> 
> I haven't looked at how the gmail labels work, but if they look of
> the form ?Q?UTF-8?something?= then you can use rfc2047_decode() to
> handle them at the time they are parsed.

It turns out the encoding wasn't the issue, it was that I have header
caching turned on. While I was testing some bad data got cached and I never
cleared it out so I kept seeing the bad data.
> 
> >far. Worse still, it segfaults when changing from the inbox to some (not
> >all) other imap folders.
> >
> >static int msg_parse_fetch (IMAP_HEADER *h, char *s)
> >{
> >  char tmp[SHORT_STRING];
> >+  char buffer[LONG_STRING];
> >  char *ptmp;
> >
> >  if (!s)
> >@@ -1137,6 +1139,22 @@ static int msg_parse_fetch (IMAP_HEADER
> >  {
> >    SKIPWS (s);
> >
> >+    if (ascii_strncasecmp ("X-GM-LABELS", s, 11) == 0)
> >+    {
> >+        s += 11;
> >+        SKIPWS (s);
> >+        ptmp = buffer;
> >+        s++; /* skip ( */
> >+        while (*s && *s != ')')
> >+            *ptmp++ = *s++;
> >+        if (*s != ')')
> >+            return -1;
> >+        s++; /* skip ) */
> >+        *ptmp = 0;
> >+        h->data->labels = buffer;
> 
> you need to use safe_strdup() to make a copy of the string.  you are
> trying to return a pointer to an automatic variable, which will be
> invalid once you exit the function.

Ahh, of course. Obviously my c coding experience is a bit lacking.
> 
> note that you will also need to edit the function that frees up the
> data associated with that structure, by adding a
>       FREE(&h->data->labels)
> call.

I was looking for the place to do this, but I could only find the following
function (in imap/message.c): 

/* imap_free_header_data: free IMAP_HEADER structure */
void imap_free_header_data (void** data)
{
  /* this should be safe even if the list wasn't used */
  mutt_free_list (&(((IMAP_HEADER_DATA*) *data)->keywords));

  FREE (data);      /* __FREE_CHECKED__ */
}

Do I need to do something beyond that?

Anyway, I was able to get it working. Just fyi, X-GM-LABELS comes back
something like this:

(family/parents "\\Important")

I don't care about the "\\Important" label, so I don't keep it. Anytime
it's included but not as the first label, I also have to discard the
space before it. "\\Sent" is also used for some messages and I keep it,
but I don't like the "s and \s, so I discard those also.  Anyway, here
are the changes I'm using atm.

Thanks!
diff -udprP -x Makefile -x uid -x config.status mutt-1.5.21/imap/message.c 
mutt-1.5.21-patched/imap/message.c
--- mutt-1.5.21/imap/message.c  2010-08-24 09:34:21.000000000 -0700
+++ mutt-1.5.21-patched/imap/message.c  2012-01-29 16:20:36.000000000 -0700
@@ -242,7 +242,7 @@ int imap_read_headers (IMAP_DATA* idata,
       char *cmd;
 
       fetchlast = msgend + 1;
-      safe_asprintf (&cmd, "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE 
%s)",
+      safe_asprintf (&cmd, "FETCH %d:%d (UID FLAGS INTERNALDATE RFC822.SIZE 
X-GM-LABELS %s)",
                      msgno + 1, fetchlast, hdrreq);
       imap_cmd_start (idata, cmd);
       FREE (&cmd);
@@ -320,6 +320,7 @@ int imap_read_headers (IMAP_DATA* idata,
         0, 0);
       /* content built as a side-effect of mutt_read_rfc822_header */
       ctx->hdrs[idx]->content->length = h.content_length;
+      ctx->hdrs[idx]->env->x_label = h.data->labels;
       ctx->size += h.content_length;
 
 #if USE_HCACHE
@@ -1137,6 +1138,38 @@ static int msg_parse_fetch (IMAP_HEADER
   {
     SKIPWS (s);
 
+    if (ascii_strncasecmp ("X-GM-LABELS", s, 11) == 0)
+    {
+        s += 11;
+        SKIPWS (s);
+        ptmp = tmp;
+        s++; /* skip ( */
+        while (*s && *s != ')')
+            if (ptmp-tmp < sizeof(tmp)/sizeof(char))
+                if (ascii_strncasecmp ("\"", s, 1) == 0)
+                    if (ascii_strncasecmp ("\"\\\\", s, 3) == 0)
+                        if (ascii_strncasecmp ("\"\\\\Important\"", s, 13) == 
0)
+                        {
+                            if (ascii_strncasecmp (" ", s-1, 1) == 0)
+                                ptmp--;
+                            s += 13;
+                        }
+                        else
+                            s += 3;
+                    else
+                        s++;
+                else
+                    *ptmp++ = *s++;
+            else
+                s++;
+        if (*s != ')')
+            return -1;
+        s++; /* skip ) */
+        *ptmp = 0;
+        h->data->labels = safe_strdup(tmp);
+        SKIPWS (s);
+    }
+
     if (ascii_strncasecmp ("FLAGS", s, 5) == 0)
     {
       if ((s = msg_parse_flags (h, s)) == NULL)
diff -udprP -x Makefile -x uid -x config.status mutt-1.5.21/imap/message.h 
mutt-1.5.21-patched/imap/message.h
--- mutt-1.5.21/imap/message.h  2009-01-05 12:20:53.000000000 -0700
+++ mutt-1.5.21-patched/imap/message.h  2012-01-28 21:51:44.000000000 -0700
@@ -37,6 +37,8 @@ typedef struct imap_header_data
   unsigned int parsed : 1;
 
   unsigned int uid;    /* 32-bit Message UID */
+  char *labels;
+
   LIST *keywords;
 } IMAP_HEADER_DATA;
 

Reply via email to