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:
		
							parent
							
								
									4b185e35fe
								
							
						
					
					
						commit
						d8feb67dae
					
				
					 3 changed files with 29 additions and 25 deletions
				
			
		|  | @ -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; \ | ||||||
|  |  | ||||||
|  | @ -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,14 +1396,15 @@ 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.
 |  | ||||||
| 				goto inbox; |  | ||||||
| 			} |  | ||||||
| 				return LIST_OK; | 				return LIST_OK; | ||||||
| 		} | 			// INBOX and its subfolders bypass the namespace.
 | ||||||
|  | 		} else { | ||||||
| 			arg += l; | 			arg += l; | ||||||
| 			argl -= l; | 			argl -= l; | ||||||
| 			// A folder named "INBOX" would be indistinguishable from the
 | 			// A folder named "INBOX" would be indistinguishable from the
 | ||||||
|  | @ -1407,14 +1416,7 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) | ||||||
| 					warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); | 					warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); | ||||||
| 				return LIST_OK; | 				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 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue