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;