summaryrefslogtreecommitdiff
path: root/imap4d
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2017-01-26 21:56:57 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2017-01-26 21:56:57 +0200
commitd569c130f2cee770ab0aba6ee2a65382967b324e (patch)
tree8f5be52d0e20ffe932dd7c9c9522344d31923d4b /imap4d
parent80d8b59a60d9f529801a52271c8c7ebd3c22ace2 (diff)
downloadmailutils-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.h1
-rw-r--r--imap4d/io.c21
-rw-r--r--imap4d/list.c138
-rw-r--r--imap4d/lsub.c2
-rw-r--r--imap4d/namespace.c20
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;
}

Return to:

Send suggestions and report system problems to the System administrator.