Todd, thanks for looking into this.  Would you be willing to look at the
keywords patch located here: https://bitbucket.org/dgc/mutt-dgc/qseries
and adapt your fix to that patch queue?  I'd love for this new approach
to keyword handling to fully support Google's labels as well.

If you can't do this I'll see about integrating it when I have a chance.
But if you can do it I can just add your patch to my series.

* On 29 Jan 2012, Todd Hoffmann wrote: 
> 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;
>  


-- 
David Champion • [email protected] • IT Services • University of Chicago

Reply via email to