From: Naveen Nathan Date: Tue, 23 Apr 2019 17:04:05 +0000 (+1000) Subject: Improve hierarchy information accuracy in IMAP browser X-Git-Tag: mutt-1-12-rel~38 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=82b759e89c5fd6b8e360c54e62de5e8393f9a10a;p=mutt Improve hierarchy information accuracy in IMAP browser Currently the IMAP browser relies on LIST and LSUB (for listing subscribed folders) which may not provide the required hierarchy information. RFC3348 section 3 goes as far as stating that a client mustn't rely on LSUB for hierarchy information. This patch implements the LIST command extensions specified in RFC5258 requiring that a server must respond with hierarchy information for listed folders (whether or not filtering on subscribed folders). --- diff --git a/imap/browse.c b/imap/browse.c index 1aa4d357..8a2a9a6a 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -46,7 +46,8 @@ int imap_browse (const char* path, struct browser_state* state) char buf[LONG_STRING*2]; char mbox[LONG_STRING]; char munged_mbox[LONG_STRING]; - char list_cmd[5]; + char list_cmd[18]; + int len; int n; int nsup; char ctmp; @@ -62,11 +63,26 @@ int imap_browse (const char* path, struct browser_state* state) save_lsub = option (OPTIMAPCHECKSUBSCRIBED); unset_option (OPTIMAPCHECKSUBSCRIBED); - strfcpy (list_cmd, option (OPTIMAPLSUB) ? "LSUB" : "LIST", sizeof (list_cmd)); if (!(idata = imap_conn_find (&(mx.account), 0))) goto fail; + if (option (OPTIMAPLSUB)) + { + const char *lsub_cmd = "LSUB"; + + /* RFC3348 section 3 states LSUB is unreliable for hierarchy information. + * The newer LIST extensions are designed for this. + */ + if (mutt_bit_isset (idata->capabilities, LIST_EXTENDED)) + lsub_cmd = "LIST (SUBSCRIBED)"; + strfcpy (list_cmd, lsub_cmd, sizeof (list_cmd)); + } + else + { + strfcpy (list_cmd, "LIST", sizeof (list_cmd)); + } + mutt_message _("Getting folder list..."); /* skip check for parents when at the root */ @@ -89,7 +105,9 @@ int imap_browse (const char* path, struct browser_state* state) /* if our target exists and has inferiors, enter it if we * aren't already going to */ imap_munge_mbox_name (idata, munged_mbox, sizeof (munged_mbox), mbox); - snprintf (buf, sizeof (buf), "%s \"\" %s", list_cmd, munged_mbox); + len = snprintf (buf, sizeof (buf), "%s \"\" %s", list_cmd, munged_mbox); + if (mutt_bit_isset (idata->capabilities, LIST_EXTENDED)) + snprintf (buf + len, sizeof(buf) - len, " RETURN (CHILDREN)"); imap_cmd_start (idata, buf); idata->cmdtype = IMAP_CT_LIST; idata->cmddata = &list; @@ -181,7 +199,9 @@ int imap_browse (const char* path, struct browser_state* state) snprintf (buf, sizeof (buf), "%s%%", mbox); imap_munge_mbox_name (idata, munged_mbox, sizeof (munged_mbox), buf); dprint (3, (debugfile, "%s\n", munged_mbox)); - snprintf (buf, sizeof (buf), "%s \"\" %s", list_cmd, munged_mbox); + len = snprintf (buf, sizeof (buf), "%s \"\" %s", list_cmd, munged_mbox); + if (mutt_bit_isset (idata->capabilities, LIST_EXTENDED)) + snprintf (buf + len, sizeof(buf) - len, " RETURN (CHILDREN)"); if (browse_add_list_result (idata, buf, state, 0)) goto fail; diff --git a/imap/command.c b/imap/command.c index 21f6a40b..91457a11 100644 --- a/imap/command.c +++ b/imap/command.c @@ -73,6 +73,7 @@ static const char * const Capabilities[] = { "ENABLE", "CONDSTORE", "QRESYNC", + "LIST-EXTENDED", NULL }; diff --git a/imap/imap_private.h b/imap/imap_private.h index 07523672..7d12ec25 100644 --- a/imap/imap_private.h +++ b/imap/imap_private.h @@ -120,6 +120,7 @@ enum ENABLE, /* RFC 5161 */ CONDSTORE, /* RFC 7162 */ QRESYNC, /* RFC 7162 */ + LIST_EXTENDED, /* RFC 5258: IMAP4 - LIST Command Extensions */ CAPMAX };