Commit d569c130 d569c130f2cee770ab0aba6ee2a65382967b324e by Sergey Poznyakoff

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.
1 parent 80d8b59a
...@@ -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)
......