Allow for "INBOX." namespace.
* imap4d/imap4d.h (io_send_astring): New proto. * imap4d/io.c (io_send_astring): New function. * imap4d/list.c (list_fun): Use io_send_astring. (list_ref): Special handling for empty wcard (imap4d_list): Remove special handling for empty wcard and INBOX. Leave that to list_ref. This makes it possible to declare namespaces like "INBOX." ("." being the delimiter). * imap4d/lsub.c (imap4d_lsub): Use io_send_astring. * imap4d/namespace.c (namespace_translate_name): Check for declared namespace first.
Showing
6 changed files
with
66 additions
and
42 deletions
... | @@ -229,6 +229,7 @@ extern int io_untagged_response (int, const char *, ...) MU_PRINTFLIKE(2,3); | ... | @@ -229,6 +229,7 @@ extern int io_untagged_response (int, const char *, ...) MU_PRINTFLIKE(2,3); |
229 | extern int io_sendf (const char *, ...) MU_PRINTFLIKE(1,2); | 229 | extern int io_sendf (const char *, ...) MU_PRINTFLIKE(1,2); |
230 | extern int io_send_bytes (const char *buf, size_t size); | 230 | extern int io_send_bytes (const char *buf, size_t size); |
231 | extern int io_send_qstring (const char *); | 231 | extern int io_send_qstring (const char *); |
232 | extern int io_send_astring (const char *); | ||
232 | extern int io_send_literal (const char *); | 233 | extern int io_send_literal (const char *); |
233 | extern int io_copy_out (mu_stream_t str, size_t size); | 234 | extern int io_copy_out (mu_stream_t str, size_t size); |
234 | extern int io_completion_response (struct imap4d_command *, int, | 235 | extern int io_completion_response (struct imap4d_command *, int, | ... | ... |
... | @@ -256,6 +256,27 @@ io_send_qstring (const char *buffer) | ... | @@ -256,6 +256,27 @@ io_send_qstring (const char *buffer) |
256 | } | 256 | } |
257 | 257 | ||
258 | int | 258 | int |
259 | io_send_astring (const char *buffer) | ||
260 | { | ||
261 | if (buffer == NULL) | ||
262 | return io_sendf ("NIL"); | ||
263 | else if (*buffer == 0) | ||
264 | return io_sendf ("\"\""); | ||
265 | if (strpbrk (buffer, "\"\r\n\\")) | ||
266 | { | ||
267 | char *s; | ||
268 | int ret; | ||
269 | char *b = mu_strdup (buffer); | ||
270 | while ((s = strchr (b, '\n')) || (s = strchr (b, '\r'))) | ||
271 | *s = ' '; | ||
272 | ret = io_send_literal (b); | ||
273 | free (b); | ||
274 | return ret; | ||
275 | } | ||
276 | return io_sendf ("\"%s\"", buffer); | ||
277 | } | ||
278 | |||
279 | int | ||
259 | io_send_literal (const char *buffer) | 280 | io_send_literal (const char *buffer) |
260 | { | 281 | { |
261 | return io_sendf ("{%lu}\n%s", (unsigned long) strlen (buffer), buffer); | 282 | return io_sendf ("{%lu}\n%s", (unsigned long) strlen (buffer), buffer); | ... | ... |
... | @@ -97,7 +97,7 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) | ... | @@ -97,7 +97,7 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) |
97 | io_sendf ("%s\n", name); | 97 | io_sendf ("%s\n", name); |
98 | else | 98 | else |
99 | { | 99 | { |
100 | io_send_qstring (name); | 100 | io_send_astring (name); |
101 | io_sendf ("\n"); | 101 | io_sendf ("\n"); |
102 | } | 102 | } |
103 | return 0; | 103 | return 0; |
... | @@ -128,6 +128,26 @@ list_ref (char const *ref, char const *wcard, char const *cwd, | ... | @@ -128,6 +128,26 @@ list_ref (char const *ref, char const *wcard, char const *cwd, |
128 | char const *dir; | 128 | char const *dir; |
129 | mu_url_t url; | 129 | mu_url_t url; |
130 | 130 | ||
131 | if (!wcard[0]) | ||
132 | { | ||
133 | /* An empty ("" string) mailbox name argument is a special request to | ||
134 | return the hierarchy delimiter and the root name of the name given | ||
135 | in the reference. | ||
136 | */ | ||
137 | io_sendf ("* LIST (\\NoSelect) "); | ||
138 | if (mu_c_strcasecmp (ref, "INBOX") == 0) | ||
139 | { | ||
140 | io_sendf ("NIL \"\""); | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | io_sendf ("\"%c\" ", pfx->delim); | ||
145 | io_send_astring (pfx->prefix); | ||
146 | } | ||
147 | io_sendf ("\n"); | ||
148 | return RESP_OK; | ||
149 | } | ||
150 | |||
131 | if (pfx->ns == NS_OTHER && match_pfx (pfx, ref) && strpbrk (wcard, "*%")) | 151 | if (pfx->ns == NS_OTHER && match_pfx (pfx, ref) && strpbrk (wcard, "*%")) |
132 | { | 152 | { |
133 | /* [A] server MAY return NO to such a LIST command, requiring that a | 153 | /* [A] server MAY return NO to such a LIST command, requiring that a |
... | @@ -226,6 +246,8 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -226,6 +246,8 @@ imap4d_list (struct imap4d_session *session, |
226 | [RESP_NO] = "The requested item could not be found", | 246 | [RESP_NO] = "The requested item could not be found", |
227 | [RESP_BAD] = "System error" | 247 | [RESP_BAD] = "System error" |
228 | }; | 248 | }; |
249 | char *cwd = NULL; | ||
250 | struct namespace_prefix const *pfx = NULL; | ||
229 | 251 | ||
230 | if (imap4d_tokbuf_argc (tok) != 4) | 252 | if (imap4d_tokbuf_argc (tok) != 4) |
231 | return io_completion_response (command, RESP_BAD, "Invalid arguments"); | 253 | return io_completion_response (command, RESP_BAD, "Invalid arguments"); |
... | @@ -233,40 +255,21 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -233,40 +255,21 @@ imap4d_list (struct imap4d_session *session, |
233 | ref = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); | 255 | ref = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); |
234 | wcard = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2); | 256 | wcard = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2); |
235 | 257 | ||
236 | /* If wildcard is empty, it is a special case: we have to | ||
237 | return the hierarchy. */ | ||
238 | if (*wcard == '\0') | ||
239 | { | ||
240 | if (*ref) | ||
241 | io_untagged_response (RESP_NONE, | ||
242 | "LIST (\\NoSelect) \"%c\" \"%c\"", | ||
243 | MU_HIERARCHY_DELIMITER, | ||
244 | MU_HIERARCHY_DELIMITER); | ||
245 | else | ||
246 | io_untagged_response (RESP_NONE, | ||
247 | "LIST (\\NoSelect) \"%c\" \"\"", | ||
248 | MU_HIERARCHY_DELIMITER); | ||
249 | } | ||
250 | |||
251 | /* There is only one mailbox in the "INBOX" hierarchy ... INBOX. */ | ||
252 | else if (mu_c_strcasecmp (ref, "INBOX") == 0 | ||
253 | || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0)) | ||
254 | { | ||
255 | io_untagged_response (RESP_NONE, "LIST (\\NoInferiors) NIL INBOX"); | ||
256 | } | ||
257 | else | ||
258 | { | ||
259 | char *cwd = NULL; | ||
260 | struct namespace_prefix const *pfx = NULL; | ||
261 | |||
262 | if (ref[0] == 0) | 258 | if (ref[0] == 0) |
263 | { | 259 | { |
264 | cwd = namespace_translate_name (wcard, &pfx); | 260 | cwd = namespace_translate_name (wcard, &pfx); |
265 | if (cwd) | 261 | if (cwd) |
266 | { | 262 | { |
267 | char *p = wcard + strlen (pfx->prefix); | 263 | size_t p_len = strlen (pfx->prefix); |
264 | size_t w_len = strlen (wcard); | ||
265 | |||
266 | if (p_len <= w_len) | ||
267 | { | ||
268 | memmove (wcard, wcard + p_len, w_len - p_len + 1); | ||
268 | ref = mu_strdup (pfx->prefix); | 269 | ref = mu_strdup (pfx->prefix); |
269 | memmove (wcard, p, strlen (p) + 1); | 270 | } |
271 | else | ||
272 | ref = mu_strdup (ref); | ||
270 | free (cwd); | 273 | free (cwd); |
271 | } | 274 | } |
272 | else | 275 | else |
... | @@ -313,7 +316,6 @@ imap4d_list (struct imap4d_session *session, | ... | @@ -313,7 +316,6 @@ imap4d_list (struct imap4d_session *session, |
313 | 316 | ||
314 | free (cwd); | 317 | free (cwd); |
315 | free (ref); | 318 | free (ref); |
316 | } | ||
317 | 319 | ||
318 | return io_completion_response (command, status, resp_text[status]); | 320 | return io_completion_response (command, status, resp_text[status]); |
319 | } | 321 | } | ... | ... |
... | @@ -68,7 +68,7 @@ imap4d_lsub (struct imap4d_session *session, | ... | @@ -68,7 +68,7 @@ imap4d_lsub (struct imap4d_session *session, |
68 | { | 68 | { |
69 | mu_stream_printf (iostream, "* LSUB () \"%c\" ", | 69 | mu_stream_printf (iostream, "* LSUB () \"%c\" ", |
70 | MU_HIERARCHY_DELIMITER); | 70 | MU_HIERARCHY_DELIMITER); |
71 | io_send_qstring (name); | 71 | io_send_astring (name); |
72 | io_sendf ("\n"); | 72 | io_sendf ("\n"); |
73 | } | 73 | } |
74 | } | 74 | } | ... | ... |
... | @@ -279,12 +279,6 @@ namespace_translate_name (char const *name, | ... | @@ -279,12 +279,6 @@ namespace_translate_name (char const *name, |
279 | char *res = NULL; | 279 | char *res = NULL; |
280 | struct namespace_prefix const *pfx; | 280 | struct namespace_prefix const *pfx; |
281 | 281 | ||
282 | if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) | ||
283 | { | ||
284 | res = mu_strdup (auth_data->mailbox); | ||
285 | pfx = mu_assoc_get (prefixes, ""); | ||
286 | } | ||
287 | else | ||
288 | res = translate_name (name, &pfx); | 282 | res = translate_name (name, &pfx); |
289 | 283 | ||
290 | if (res) | 284 | if (res) |
... | @@ -347,10 +341,16 @@ namespace_translate_name (char const *name, | ... | @@ -347,10 +341,16 @@ namespace_translate_name (char const *name, |
347 | 341 | ||
348 | res = dir; | 342 | res = dir; |
349 | trim_delim (res, '/'); | 343 | trim_delim (res, '/'); |
344 | } | ||
345 | else if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) | ||
346 | { | ||
347 | res = mu_strdup (auth_data->mailbox); | ||
348 | pfx = mu_assoc_get (prefixes, ""); | ||
349 | } | ||
350 | 350 | ||
351 | if (return_pfx) | 351 | if (res && return_pfx) |
352 | *return_pfx = pfx; | 352 | *return_pfx = pfx; |
353 | } | 353 | |
354 | return res; | 354 | return res; |
355 | } | 355 | } |
356 | 356 | ... | ... |
... | @@ -446,10 +446,10 @@ mu_folder_delete (mu_folder_t folder, const char *name) | ... | @@ -446,10 +446,10 @@ mu_folder_delete (mu_folder_t folder, const char *name) |
446 | undesired results. For example, a MH mailbox can hold another | 446 | undesired results. For example, a MH mailbox can hold another |
447 | mailboxes, i.e. be a folder itself. Removing it blindly would | 447 | mailboxes, i.e. be a folder itself. Removing it blindly would |
448 | result in removing these mailboxes as well, which is clearly not | 448 | result in removing these mailboxes as well, which is clearly not |
449 | indended. | 449 | intended. |
450 | 450 | ||
451 | To solve this folder and mailbox delete methods are tightly paired, | 451 | To solve this, both folder and mailbox delete methods are tightly |
452 | but without looking into each-others internal mechanisms. */ | 452 | paired, but without looking into each-others internal mechanisms. */ |
453 | mu_mailbox_t mbox; | 453 | mu_mailbox_t mbox; |
454 | rc = mu_mailbox_create_at (&mbox, folder, name); | 454 | rc = mu_mailbox_create_at (&mbox, folder, name); |
455 | if (rc == 0) | 455 | if (rc == 0) | ... | ... |
-
Please register or sign in to post a comment