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;