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.
This commit is contained in:
Oswald Buddenhagen 2021-03-19 18:21:34 +01:00
parent 4b185e35fe
commit d8feb67dae
3 changed files with 29 additions and 25 deletions

View File

@ -35,7 +35,6 @@ typedef struct driver driver_t;
struct store_conf *next; \ struct store_conf *next; \
char *name; \ char *name; \
driver_t *driver; \ driver_t *driver; \
const char *path; /* should this be here? its interpretation is driver-specific */ \
const char *flat_delim; \ const char *flat_delim; \
const char *map_inbox; \ const char *map_inbox; \
const char *trash; \ const char *trash; \

View File

@ -74,6 +74,7 @@ typedef union imap_store_conf {
struct { struct {
STORE_CONF STORE_CONF
imap_server_conf_t *server; imap_server_conf_t *server;
char *path; // Note: this may be modified after the delimiter is determined.
char delimiter; char delimiter;
char use_namespace; char use_namespace;
char use_lsub; char use_lsub;
@ -114,8 +115,8 @@ union imap_store {
struct { struct {
STORE(union imap_store) STORE(union imap_store)
const char *label; // foreign const char *label; // foreign
const char *prefix;
const char *name; const char *name;
char *prefix;
uint ref_count; uint ref_count;
uint opts; uint opts;
enum { SST_BAD, SST_HALF, SST_GOOD } state; 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; 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 static int
parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) 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; arg = list->val;
argl = (int)list->len; 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 ((l = strlen( ctx->prefix ))) {
if (!starts_with( arg, argl, ctx->prefix, l )) { if (!starts_with( arg, argl, ctx->prefix, l )) {
if (is_inbox( ctx, arg, argl )) { if (!is_INBOX( ctx, arg, argl ))
// INBOX and its subfolders bypass the namespace. return LIST_OK;
goto inbox; // 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 */ if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */
return LIST_OK; return LIST_OK;
@ -2539,6 +2541,8 @@ imap_open_store_finalize( imap_store_t *ctx )
ctx->state = SST_GOOD; ctx->state = SST_GOOD;
if (!ctx->prefix) if (!ctx->prefix)
ctx->prefix = ""; ctx->prefix = "";
else
normalize_INBOX( ctx, ctx->prefix, -1 );
ctx->trashnc = TrashUnknown; ctx->trashnc = TrashUnknown;
ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux ); ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux );
} }

View File

@ -54,6 +54,7 @@ typedef union maildir_store_conf {
store_conf_t gen; store_conf_t gen;
struct { struct {
STORE_CONF STORE_CONF
char *path;
char *inbox; char *inbox;
#ifdef USE_DB #ifdef USE_DB
int alt_map; int alt_map;