diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-01-26 21:56:57 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-01-26 21:56:57 +0200 |
commit | d569c130f2cee770ab0aba6ee2a65382967b324e (patch) | |
tree | 8f5be52d0e20ffe932dd7c9c9522344d31923d4b /imap4d | |
parent | 80d8b59a60d9f529801a52271c8c7ebd3c22ace2 (diff) | |
download | mailutils-d569c130f2cee770ab0aba6ee2a65382967b324e.tar.gz mailutils-d569c130f2cee770ab0aba6ee2a65382967b324e.tar.bz2 |
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.
Diffstat (limited to 'imap4d')
-rw-r--r-- | imap4d/imap4d.h | 1 | ||||
-rw-r--r-- | imap4d/io.c | 21 | ||||
-rw-r--r-- | imap4d/list.c | 138 | ||||
-rw-r--r-- | imap4d/lsub.c | 2 | ||||
-rw-r--r-- | imap4d/namespace.c | 20 |
5 files changed, 103 insertions, 79 deletions
diff --git a/imap4d/imap4d.h b/imap4d/imap4d.h index eb7074f3c..51cac08e9 100644 --- a/imap4d/imap4d.h +++ b/imap4d/imap4d.h @@ -229,6 +229,7 @@ extern int io_untagged_response (int, const char *, ...) MU_PRINTFLIKE(2,3); extern int io_sendf (const char *, ...) MU_PRINTFLIKE(1,2); extern int io_send_bytes (const char *buf, size_t size); extern int io_send_qstring (const char *); +extern int io_send_astring (const char *); extern int io_send_literal (const char *); extern int io_copy_out (mu_stream_t str, size_t size); extern int io_completion_response (struct imap4d_command *, int, diff --git a/imap4d/io.c b/imap4d/io.c index dc32d2567..1d6ae7f8f 100644 --- a/imap4d/io.c +++ b/imap4d/io.c @@ -256,6 +256,27 @@ io_send_qstring (const char *buffer) } int +io_send_astring (const char *buffer) +{ + if (buffer == NULL) + return io_sendf ("NIL"); + else if (*buffer == 0) + return io_sendf ("\"\""); + if (strpbrk (buffer, "\"\r\n\\")) + { + char *s; + int ret; + char *b = mu_strdup (buffer); + while ((s = strchr (b, '\n')) || (s = strchr (b, '\r'))) + *s = ' '; + ret = io_send_literal (b); + free (b); + return ret; + } + return io_sendf ("\"%s\"", buffer); +} + +int io_send_literal (const char *buffer) { return io_sendf ("{%lu}\n%s", (unsigned long) strlen (buffer), buffer); diff --git a/imap4d/list.c b/imap4d/list.c index 069804b56..c8d5124d2 100644 --- a/imap4d/list.c +++ b/imap4d/list.c @@ -97,7 +97,7 @@ list_fun (mu_folder_t folder, struct mu_list_response *resp, void *data) io_sendf ("%s\n", name); else { - io_send_qstring (name); + io_send_astring (name); io_sendf ("\n"); } return 0; @@ -127,6 +127,26 @@ list_ref (char const *ref, char const *wcard, char const *cwd, mu_folder_t folder; char const *dir; mu_url_t url; + + if (!wcard[0]) + { + /* An empty ("" string) mailbox name argument is a special request to + return the hierarchy delimiter and the root name of the name given + in the reference. + */ + io_sendf ("* LIST (\\NoSelect) "); + if (mu_c_strcasecmp (ref, "INBOX") == 0) + { + io_sendf ("NIL \"\""); + } + else + { + io_sendf ("\"%c\" ", pfx->delim); + io_send_astring (pfx->prefix); + } + io_sendf ("\n"); + return RESP_OK; + } if (pfx->ns == NS_OTHER && match_pfx (pfx, ref) && strpbrk (wcard, "*%")) { @@ -226,95 +246,77 @@ imap4d_list (struct imap4d_session *session, [RESP_NO] = "The requested item could not be found", [RESP_BAD] = "System error" }; - + char *cwd = NULL; + struct namespace_prefix const *pfx = NULL; + if (imap4d_tokbuf_argc (tok) != 4) return io_completion_response (command, RESP_BAD, "Invalid arguments"); ref = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1); wcard = imap4d_tokbuf_getarg (tok, IMAP4_ARG_2); - /* If wildcard is empty, it is a special case: we have to - return the hierarchy. */ - if (*wcard == '\0') + if (ref[0] == 0) { - if (*ref) - io_untagged_response (RESP_NONE, - "LIST (\\NoSelect) \"%c\" \"%c\"", - MU_HIERARCHY_DELIMITER, - MU_HIERARCHY_DELIMITER); - else - io_untagged_response (RESP_NONE, - "LIST (\\NoSelect) \"%c\" \"\"", - MU_HIERARCHY_DELIMITER); - } - - /* There is only one mailbox in the "INBOX" hierarchy ... INBOX. */ - else if (mu_c_strcasecmp (ref, "INBOX") == 0 - || (ref[0] == 0 && mu_c_strcasecmp (wcard, "INBOX") == 0)) - { - io_untagged_response (RESP_NONE, "LIST (\\NoInferiors) NIL INBOX"); - } - else - { - char *cwd = NULL; - struct namespace_prefix const *pfx = NULL; - - if (ref[0] == 0) + cwd = namespace_translate_name (wcard, &pfx); + if (cwd) { - cwd = namespace_translate_name (wcard, &pfx); - if (cwd) + size_t p_len = strlen (pfx->prefix); + size_t w_len = strlen (wcard); + + if (p_len <= w_len) { - char *p = wcard + strlen (pfx->prefix); + memmove (wcard, wcard + p_len, w_len - p_len + 1); ref = mu_strdup (pfx->prefix); - memmove (wcard, p, strlen (p) + 1); - free (cwd); } else ref = mu_strdup (ref); + free (cwd); } else ref = mu_strdup (ref); - - if (!pfx) - { - cwd = namespace_translate_name (ref, &pfx); - if (cwd) - free (cwd); - } - - if (pfx) + } + else + ref = mu_strdup (ref); + + if (!pfx) + { + cwd = namespace_translate_name (ref, &pfx); + if (cwd) + free (cwd); + } + + if (pfx) + { + /* Find the longest directory prefix */ + size_t i = strcspn (wcard, "%*"); + if (wcard[i]) { - /* Find the longest directory prefix */ - size_t i = strcspn (wcard, "%*"); - if (wcard[i]) + while (i > 0 && wcard[i - 1] != pfx->delim) + i--; + /* Append it to the reference */ + if (i) { - while (i > 0 && wcard[i - 1] != pfx->delim) - i--; - /* Append it to the reference */ - if (i) - { - size_t reflen = strlen (ref); - size_t len = i + reflen; - - ref = mu_realloc (ref, len); - memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ - ref[len-1] = 0; - - wcard += i; - } + size_t reflen = strlen (ref); + size_t len = i + reflen; + + ref = mu_realloc (ref, len); + memcpy (ref + reflen, wcard, i - 1); /* omit the trailing / */ + ref[len-1] = 0; + + wcard += i; } } - - cwd = namespace_translate_name (ref, &pfx); - if (cwd) - status = list_ref (ref, wcard, cwd, pfx); - else - status = RESP_NO; - - free (cwd); - free (ref); } + + cwd = namespace_translate_name (ref, &pfx); + if (cwd) + status = list_ref (ref, wcard, cwd, pfx); + else + status = RESP_NO; + free (cwd); + free (ref); + return io_completion_response (command, status, resp_text[status]); } diff --git a/imap4d/lsub.c b/imap4d/lsub.c index 13fc9b23b..6191dc1c2 100644 --- a/imap4d/lsub.c +++ b/imap4d/lsub.c @@ -68,7 +68,7 @@ imap4d_lsub (struct imap4d_session *session, { mu_stream_printf (iostream, "* LSUB () \"%c\" ", MU_HIERARCHY_DELIMITER); - io_send_qstring (name); + io_send_astring (name); io_sendf ("\n"); } } diff --git a/imap4d/namespace.c b/imap4d/namespace.c index f391691a9..a9c8b5cc0 100644 --- a/imap4d/namespace.c +++ b/imap4d/namespace.c @@ -279,13 +279,7 @@ namespace_translate_name (char const *name, char *res = NULL; struct namespace_prefix const *pfx; - if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) - { - res = mu_strdup (auth_data->mailbox); - pfx = mu_assoc_get (prefixes, ""); - } - else - res = translate_name (name, &pfx); + res = translate_name (name, &pfx); if (res) { @@ -347,10 +341,16 @@ namespace_translate_name (char const *name, res = dir; trim_delim (res, '/'); - - if (return_pfx) - *return_pfx = pfx; } + else if (mu_c_strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) + { + res = mu_strdup (auth_data->mailbox); + pfx = mu_assoc_get (prefixes, ""); + } + + if (res && return_pfx) + *return_pfx = pfx; + return res; } |