dovecot-2.2: lib-storage: Added support for "broken_char" settin...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Oct 12 05:46:17 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/22e7322e8601
changeset: 15210:22e7322e8601
user: Timo Sirainen <tss at iki.fi>
date: Fri Oct 12 05:45:42 2012 +0300
description:
lib-storage: Added support for "broken_char" setting for escaping invalid mailbox names.
This is currently enabled only for imapc backend, where '~' character is
used for it.
Most importantly this allows migrating mailboxes from other IMAP servers
that contain mailbox names that Dovecot's imapc backend couldn't otherwise
access.
diffstat:
src/lib-storage/index/imapc/imapc-list.c | 1 +
src/lib-storage/index/imapc/imapc-storage.h | 1 +
src/lib-storage/mailbox-list.c | 121 +++++++++++++++++++++++++--
src/lib-storage/mailbox-list.h | 5 +
4 files changed, 116 insertions(+), 12 deletions(-)
diffs (200 lines):
diff -r a44be96f55c1 -r 22e7322e8601 src/lib-storage/index/imapc/imapc-list.c
--- a/src/lib-storage/index/imapc/imapc-list.c Fri Oct 12 03:47:41 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-list.c Fri Oct 12 05:45:42 2012 +0300
@@ -216,6 +216,7 @@
list_set.layout = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS;
list_set.root_dir = dir;
list_set.escape_char = IMAPC_LIST_ESCAPE_CHAR;
+ list_set.broken_char = IMAPC_LIST_BROKEN_CHAR;
list_set.mailbox_dir_name = "";
list_set.maildir_name = "";
diff -r a44be96f55c1 -r 22e7322e8601 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h Fri Oct 12 03:47:41 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h Fri Oct 12 05:45:42 2012 +0300
@@ -7,6 +7,7 @@
#define IMAPC_STORAGE_NAME "imapc"
#define IMAPC_INDEX_PREFIX "dovecot.index"
#define IMAPC_LIST_ESCAPE_CHAR '%'
+#define IMAPC_LIST_BROKEN_CHAR '~'
struct imap_arg;
struct imapc_untagged_reply;
diff -r a44be96f55c1 -r 22e7322e8601 src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c Fri Oct 12 03:47:41 2012 +0300
+++ b/src/lib-storage/mailbox-list.c Fri Oct 12 05:45:42 2012 +0300
@@ -432,6 +432,53 @@
return str_c(escaped_name);
}
+static int
+mailbox_list_unescape_broken_chars(struct mailbox_list *list, char *name)
+{
+ char *src, *dest;
+ unsigned char chr;
+
+ if ((src = strchr(name, list->set.broken_char)) == NULL)
+ return 0;
+ dest = src;
+
+ while (*src != '\0') {
+ if (*src == list->set.broken_char) {
+ if (src[1] >= '0' && src[1] <= '9')
+ chr = (src[1]-'0') * 0x10;
+ else if (src[1] >= 'a' && src[1] <= 'f')
+ chr = (src[1]-'a' + 10) * 0x10;
+ else
+ return -1;
+
+ if (src[2] >= '0' && src[2] <= '9')
+ chr += src[2]-'0';
+ else if (src[2] >= 'a' && src[2] <= 'f')
+ chr += src[2]-'a' + 10;
+ else
+ return -1;
+ *dest++ = chr;
+ src += 3;
+ } else {
+ *dest++ = *src++;
+ }
+ }
+ *dest++ = '\0';
+ return 0;
+}
+
+static char *mailbox_list_convert_sep(const char *storage_name, char src, char dest)
+{
+ char *ret, *p;
+
+ ret = p_strdup(unsafe_data_stack_pool, storage_name);
+ for (p = ret; *p != '\0'; p++) {
+ if (*p == src)
+ *p = dest;
+ }
+ return ret;
+}
+
const char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
const char *vname)
{
@@ -439,7 +486,7 @@
unsigned int prefix_len = strlen(ns->prefix);
const char *storage_name = vname;
string_t *str;
- char list_sep, ns_sep, *ret, *p;
+ char list_sep, ns_sep, *ret;
if (strcasecmp(storage_name, "INBOX") == 0 &&
(ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0)
@@ -480,19 +527,29 @@
storage_name = "INBOX";
}
- if (list_sep == ns_sep)
+ if (list_sep != ns_sep) {
+ if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
+ (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
+ /* shared namespace root. the backend storage's
+ hierarchy separator isn't known yet, so do
+ nothing. */
+ return storage_name;
+ }
+
+ ret = mailbox_list_convert_sep(storage_name, ns_sep, list_sep);
+ } else if (list->set.broken_char == '\0' ||
+ strchr(storage_name, list->set.broken_char) == NULL) {
+ /* no need to convert broken chars */
return storage_name;
- if (ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
- (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
- /* shared namespace root. the backend storage's hierarchy
- separator isn't known yet, so do nothing. */
- return storage_name;
+ } else {
+ ret = p_strdup(unsafe_data_stack_pool, storage_name);
}
- ret = p_strdup(unsafe_data_stack_pool, storage_name);
- for (p = ret; *p != '\0'; p++) {
- if (*p == ns_sep)
- *p = list_sep;
+ if (list->set.broken_char != '\0') {
+ if (mailbox_list_unescape_broken_chars(list, ret) < 0) {
+ ret = mailbox_list_convert_sep(storage_name,
+ ns_sep, list_sep);
+ }
}
return ret;
}
@@ -539,6 +596,40 @@
return str_c(dest);
}
+static void
+mailbox_list_escape_broken_chars(struct mailbox_list *list, string_t *str)
+{
+ unsigned int i;
+ char buf[3];
+
+ if (strchr(str_c(str), list->set.broken_char) == NULL)
+ return;
+
+ for (i = 0; i < str_len(str); i++) {
+ if (str_c(str)[i] == list->set.broken_char) {
+ i_snprintf(buf, sizeof(buf), "%02x",
+ list->set.broken_char);
+ str_insert(str, i+1, buf);
+ i += 2;
+ }
+ }
+}
+
+static void
+mailbox_list_escape_broken_name(struct mailbox_list *list,
+ const char *vname, string_t *str)
+{
+ str_truncate(str, 0);
+ for (; *vname != '\0'; vname++) {
+ if (*vname == '&' || (unsigned char)*vname >= 0x80) {
+ str_printfa(str, "%c%02x", list->set.broken_char,
+ *vname);
+ } else {
+ str_append_c(str, *vname);
+ }
+ }
+}
+
const char *mailbox_list_default_get_vname(struct mailbox_list *list,
const char *storage_name)
{
@@ -573,8 +664,14 @@
} else if (!list->set.utf8) {
/* mUTF-7 -> UTF-8 conversion */
string_t *str = t_str_new(strlen(vname));
- if (imap_utf7_to_utf8(vname, str) == 0)
+ if (imap_utf7_to_utf8(vname, str) == 0) {
+ if (list->set.broken_char != '\0')
+ mailbox_list_escape_broken_chars(list, str);
vname = str_c(str);
+ } else if (list->set.broken_char != '\0') {
+ mailbox_list_escape_broken_name(list, vname, str);
+ vname = str_c(str);
+ }
}
prefix_len = strlen(list->ns->prefix);
diff -r a44be96f55c1 -r 22e7322e8601 src/lib-storage/mailbox-list.h
--- a/src/lib-storage/mailbox-list.h Fri Oct 12 03:47:41 2012 +0300
+++ b/src/lib-storage/mailbox-list.h Fri Oct 12 05:45:42 2012 +0300
@@ -103,6 +103,11 @@
/* Encode "bad" characters in mailbox names as <escape_char><hex> */
char escape_char;
+ /* If mailbox name can't be changed reversibly to UTF-8 and back,
+ encode the problematic parts using <broken_char><hex> in the
+ user-visible UTF-8 name. The broken_char itself also has to be
+ encoded the same way. */
+ char broken_char;
/* Use UTF-8 mailbox names on filesystem instead of mUTF-7 */
bool utf8;
/* Don't check/create the alt-dir symlink. */
More information about the dovecot-cvs
mailing list