From d8feb67dae1971b08696d529d9ada6bf6fae6faa Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 19 Mar 2021 18:21:34 +0100 Subject: [PATCH] tolerate INBOX mis-casing in Path while it's technically reasonable to expect the user to match the server's casing of INBOX if they set Path, this might come as a surprise to those who know that the IMAP INBOX is case-insensitive. so tolerate any casing instead. as a minor side effect, we'd now even be able to deal with a server using different casing in NAMESPACE and LIST. --- src/driver.h | 1 - src/drv_imap.c | 52 +++++++++++++++++++++++++---------------------- src/drv_maildir.c | 1 + 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/driver.h b/src/driver.h index fa394b2..fb048ee 100644 --- a/src/driver.h +++ b/src/driver.h @@ -35,7 +35,6 @@ typedef struct driver driver_t; struct store_conf *next; \ char *name; \ driver_t *driver; \ - const char *path; /* should this be here? its interpretation is driver-specific */ \ const char *flat_delim; \ const char *map_inbox; \ const char *trash; \ diff --git a/src/drv_imap.c b/src/drv_imap.c index f18500d..d4fcc1f 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -74,6 +74,7 @@ typedef union imap_store_conf { struct { STORE_CONF imap_server_conf_t *server; + char *path; // Note: this may be modified after the delimiter is determined. char delimiter; char use_namespace; char use_lsub; @@ -114,8 +115,8 @@ union imap_store { struct { STORE(union imap_store) const char *label; // foreign - const char *prefix; const char *name; + char *prefix; uint ref_count; uint opts; enum { SST_BAD, SST_HALF, SST_GOOD } state; @@ -1374,6 +1375,13 @@ is_INBOX( imap_store_t *ctx, const char *arg, int argl ) return 1; } +static void +normalize_INBOX( imap_store_t *ctx, char *arg, int argl ) +{ + if (is_inbox( ctx, arg, argl )) + memcpy( arg, "INBOX", 5 ); +} + static int parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) { @@ -1388,33 +1396,27 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) } arg = list->val; argl = (int)list->len; + // The server might be weird and have a non-uppercase INBOX. It + // may legitimately do so, but we need the canonical spelling. + normalize_INBOX( ctx, arg, argl ); if ((l = strlen( ctx->prefix ))) { if (!starts_with( arg, argl, ctx->prefix, l )) { - if (is_inbox( ctx, arg, argl )) { - // INBOX and its subfolders bypass the namespace. - goto inbox; + if (!is_INBOX( ctx, arg, argl )) + return LIST_OK; + // INBOX and its subfolders bypass the namespace. + } else { + arg += l; + argl -= l; + // A folder named "INBOX" would be indistinguishable from the + // actual INBOX after prefix stripping, so drop it. This applies + // only to the fully uppercased spelling, as our canonical box + // names are case-sensitive (unlike IMAP's INBOX). + if (is_INBOX( ctx, arg, argl )) { + if (!arg[5]) // No need to complain about subfolders as well. + warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); + return LIST_OK; } - return LIST_OK; } - arg += l; - argl -= l; - // A folder named "INBOX" would be indistinguishable from the - // actual INBOX after prefix stripping, so drop it. This applies - // only to the fully uppercased spelling, as our canonical box - // names are case-sensitive (unlike IMAP's INBOX). - if (is_INBOX( ctx, arg, argl )) { - if (!arg[5]) // No need to complain about subfolders as well. - warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); - return LIST_OK; - } - } else if (is_inbox( ctx, arg, argl )) { - inbox: - // The server might be weird and have a non-uppercase INBOX. It - // may legitimately do so, but we need the canonical spelling. - // Note that we do that only after prefix matching, under the - // assumption that the NAMESPACE (or Path) matches the - // capitalization of LIST. - memcpy( arg, "INBOX", 5 ); } if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */ return LIST_OK; @@ -2539,6 +2541,8 @@ imap_open_store_finalize( imap_store_t *ctx ) ctx->state = SST_GOOD; if (!ctx->prefix) ctx->prefix = ""; + else + normalize_INBOX( ctx, ctx->prefix, -1 ); ctx->trashnc = TrashUnknown; ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux ); } diff --git a/src/drv_maildir.c b/src/drv_maildir.c index 07b20f6..5ba83f7 100644 --- a/src/drv_maildir.c +++ b/src/drv_maildir.c @@ -54,6 +54,7 @@ typedef union maildir_store_conf { store_conf_t gen; struct { STORE_CONF + char *path; char *inbox; #ifdef USE_DB int alt_map;