This is a modification of my earlier patch to enable changing the mailbox
delimiter to a different character (eg. a slash), which was based almost
entirely on David Fuchs' original patch to change the delimiter to a
slash.

This patch fixes a problem where the changed delimiter wasn't recognized
in patten searches (eg. LSUB "" %).

The actual change from the previous patches is immediately below, but
I'm including the full patch (including this latest fix) at the end of
this message for completeness.

<---> cyrus-imapd-2.0.12/lib/glob.c     Thu Dec 21 09:53:49 2000
<+++> cyrus-imapd-2.0.12/lib/glob.c     Thu May 17 18:13:21 2001
@@ -80,7 +80,7 @@
     g = (glob *) fs_get(sizeof (glob) + slen + strlen(str) + 1);
     if (g != 0) {
         strcpy(g->inbox, inbox);
-       g->sep_char = '.';
+       g->sep_char = DELIMITER_CHAR;
        dst = g->str;
        /* if we're doing a substring match, put a '*' prefix (1) */
        if (flags & GLOB_SUBSTRING) {


I haven't had time yet to see how this patch applies to the recently
release cyrus-imapd-2.0.13.

Cheers,

Chris,
OnTheNet

--- Full patch with original note ------------------------------------

This is a patch to enable changing the mailbox delimiter to an different
character, such as a slash.  This patch is mostly a modified version of
David Fuchs' original patch to change the dot delimiter to a slash.  The
major differences are:

o You can change the delimiter to any character (within reason!) by
  changing two #defines in imap/mailbox.h:

  #define DELIMITER_CHAR '/'
  #define DELIMITER_STR "/"

o It adds some sanity checking for mailbox names.  In particular it
  explicity disallows mailbox names of cyrus.cache, cyrus.index etc.,
  and explicitly disallows patterns like './' (which includes '../').
  See badmboxpatterns in imap/mboxname.c. 

o There are one or two additional places over David's patch where I
  think the delimiter needs to be changed.

Note: this patch has not yet seen extensive use in a high traffic
environment, so... Buyer Beware!

One thing it might be nice to see, but I haven't had the time to
implement, is setting the delimiter character using the configure
script.

Cheers,

Chris,
OnTheNet


diff -u -r cyrus-imapd-2.0.12/imap/acapmbox.c cyrus-imapd-2.0.12/imap/acapmbox.c
--- cyrus-imapd-2.0.12/imap/acapmbox.c  Sat Feb 17 05:54:43 2001
+++ cyrus-imapd-2.0.12/imap/acapmbox.c  Thu Apr 12 17:26:16 2001
@@ -93,12 +93,12 @@
                            const char *server, const char *name)
 {
     if (!server) server = config_servername;
-    if (!strncmp(name, "user.", 5)) {
+    if (!strncmp(name, "user" DELIMITER_STR, 5)) {
        char *p;
 
        /* user+detail */
        strcpy(postaddr, name + 5);
-       p = strchr(postaddr, '.');
+       p = strchr(postaddr, DELIMITER_CHAR);
        if (p) *p = '+';
        strcat(postaddr, "@");
        strcat(postaddr, server);
@@ -243,9 +243,11 @@
 
     /* needs to convert from mUTF7 to UTF-8 */
     snprintf(ret, MAX_MAILBOX_PATH, "%s/%s",  global_dataset, mailbox_name);
+#if DELIMITER_CHAR != '/'
     for (j = strlen(global_dataset); ret[j] != '\0'; j++) {
-       if (ret[j] == '.') ret[j] = '/';
+       if (ret[j] == DELIMITER_CHAR) ret[j] = '/';
     }
+#endif
 
     return 0;
 }
@@ -266,9 +268,11 @@
     }
 
     strcpy(ret, entryname + gdlen + 1);
+#if DELIMITER_CHAR != '/'
     for (j = 0; ret[j] != '\0'; j++) {
-       if (ret[j] == '/') ret[j] = '.';
+       if (ret[j] == '/') ret[j] = DELIMITER_CHAR;
     }
+#endif
 
     return 0;
 }
diff -u -r cyrus-imapd-2.0.12/imap/arbitron.c cyrus-imapd-2.0.12/imap/arbitron.c
--- cyrus-imapd-2.0.12/imap/arbitron.c  Wed May 24 06:52:12 2000
+++ cyrus-imapd-2.0.12/imap/arbitron.c  Thu Apr 12 13:40:53 2001
@@ -162,10 +162,10 @@
     int useridlen = tab - line;
 
     /* Don't report users reading their own private mailboxes */
-    if (!strncasecmp(arbitronargs->name, "user.", 5) &&
-       !memchr(line, '.', useridlen) &&
+    if (!strncasecmp(arbitronargs->name, "user" DELIMITER_STR, 5) &&
+       !memchr(line, DELIMITER_CHAR, useridlen) &&
        !strncasecmp(arbitronargs->name+5, line, useridlen) &&
-       (arbitronargs->name[5+useridlen] == '.' ||
+       (arbitronargs->name[5+useridlen] == DELIMITER_CHAR ||
         arbitronargs->name[5+useridlen] == '\0')) {
        return 0;
     }
diff -u -r cyrus-imapd-2.0.12/imap/duplicate.c cyrus-imapd-2.0.12/imap/duplicate.c
--- cyrus-imapd-2.0.12/imap/duplicate.c Sat Jan 27 13:05:52 2001
+++ cyrus-imapd-2.0.12/imap/duplicate.c Thu Apr 12 15:08:49 2001
@@ -75,6 +75,7 @@
 #include "imapconf.h"
 #include "exitcodes.h"
 #include "xmalloc.h"
+#include "mailbox.h"
 
 #include "duplicate.h"
 
@@ -160,11 +161,11 @@
     char *idx;
     char c;
   
-    idx = strchr(mbox,'.');   /* skip past user. */
-    if (idx == NULL) {         /* no '.' so just use mbox */
+    idx = strchr(mbox, DELIMITER_CHAR);   /* skip past user. */
+    if (idx == NULL) {         /* no DELIMITER so just use mbox */
        idx = mbox;
     } else {
-       idx++;                   /* skip past '.' */
+       idx++;                   /* skip past DELIMITER */
     }
     c = (char) tolower((int) *idx);
     if (!islower((int) c)) {
diff -u -r cyrus-imapd-2.0.12/imap/idle_idled.c cyrus-imapd-2.0.12/imap/idle_idled.c
--- cyrus-imapd-2.0.12/imap/idle_idled.c        Sat Jan 20 03:48:58 2001
+++ cyrus-imapd-2.0.12/imap/idle_idled.c        Thu Apr 12 13:42:07 2001
@@ -190,7 +190,7 @@
     /* fill the structure */
     idledata.msg = msg;
     idledata.pid = getpid();
-    strcpy(idledata.mboxname, mailbox ? mailbox->name : ".");
+    strcpy(idledata.mboxname, mailbox ? mailbox->name : DELIMITER_STR);
 
     /* send */
     if (sendto(notify_sock, (void *) &idledata,
diff -u -r cyrus-imapd-2.0.12/imap/imapd.c cyrus-imapd-2.0.12/imap/imapd.c
--- cyrus-imapd-2.0.12/imap/imapd.c     Sat Feb 17 05:55:10 2001
+++ cyrus-imapd-2.0.12/imap/imapd.c     Thu Apr 12 13:49:19 2001
@@ -233,9 +233,9 @@
     int r;
     struct auth_state *authstate;
 
-    if (strchr(user, '.') || strlen(user)+6 >= sizeof(inboxname)) return 0;
+    if (strchr(user, DELIMITER_CHAR) || strlen(user)+6 >= sizeof(inboxname)) return 0;
 
-    strcpy(inboxname, "user.");
+    strcpy(inboxname, "user" DELIMITER_STR);
     strcat(inboxname, user);
 
     if (!(authstate = auth_newstate(auth_identity, (char *)0)) ||
@@ -3232,7 +3232,7 @@
        r = IMAP_PERMISSION_DENIED;
     }
 
-    if (name[0] && name[strlen(name)-1] == '.') {
+    if (name[0] && name[strlen(name)-1] == DELIMITER_CHAR) {
        /* We don't care about trailing hierarchy delimiters. */
        name[strlen(name)-1] = '\0';
     }
@@ -3318,7 +3318,7 @@
     }
 
     /* was it a top-level user mailbox? */
-    if (!r && !strncmp(name, "user.", 5) && !strchr(name+5, '.')) {
+    if (!r && !strncmp(name, "user.", 5) && !strchr(name+5, DELIMITER_CHAR)) {
        struct tmplist *l = xmalloc(sizeof(struct tmplist));
        int r2, i;
 
@@ -3389,12 +3389,12 @@
     nmlen = strlen(newmailboxname);
     if (strlen(oldmailboxname) < strlen(newmailboxname)) {
        if (!strncmp(oldmailboxname, newmailboxname, omlen) &&
-           newmailboxname[omlen] == '.') {
+           newmailboxname[omlen] == DELIMITER_CHAR) {
            recursive_rename = 0;
        }
     } else {
        if (!strncmp(oldmailboxname, newmailboxname, nmlen) &&
-           oldmailboxname[nmlen] == '.') {
+           oldmailboxname[nmlen] == DELIMITER_CHAR) {
            recursive_rename = 0;
        }
     }
@@ -3525,10 +3525,10 @@
     
     if (!pattern[0] && !subscribed) {
        /* Special case: query top-level hierarchy separator */
-       prot_printf(imapd_out, "* LIST (\\Noselect) \".\" \"\"\r\n");
+       prot_printf(imapd_out, "* LIST (\\Noselect) \"" DELIMITER_STR "\" \"\"\r\n");
     } else {
        /* Do we need to concatenate fields? */
-       if (!ignorereference || pattern[0] == '.') {
+       if (!ignorereference || pattern[0] == DELIMITER_CHAR) {
            /* Either
             * - name begins with dot
             * - we're configured to honor the reference argument */
@@ -3543,7 +3543,7 @@
 
            if (*reference) {
                /* check for LIST A. .B, change to LIST "" A.B */
-               if (reference[reflen-1] == '.' && pattern[0] == '.') {
+               if (reference[reflen-1] == DELIMITER_CHAR && pattern[0] == 
+DELIMITER_CHAR) {
                    reference[--reflen] = '\0';
                }
                strcpy(buf, reference);
@@ -3728,11 +3728,11 @@
        if (!canon_identifier) {
            rightsdesc = "\"\"";
        }
-       else if (!strncmp(mailboxname, "user.", 5) &&
-                !strchr(canon_identifier, '.') &&
+       else if (!strncmp(mailboxname, "user" DELIMITER_STR, 5) &&
+                !strchr(canon_identifier, DELIMITER_CHAR) &&
                 !strncmp(mailboxname+5, canon_identifier, canonidlen) &&
                 (mailboxname[5+canonidlen] == '\0' ||
-                 mailboxname[5+canonidlen] == '.')) {
+                 mailboxname[5+canonidlen] == DELIMITER_CHAR)) {
            rightsdesc = "lca r s w i p d 0 1 2 3 4 5 6 7 8 9";
        }
        else {
@@ -4274,10 +4274,10 @@
        return 0;
     }
     
-    if (!(strncmp(name, "INBOX.", 6))) {
+    if (!(strncmp(name, "INBOX" DELIMITER_STR, 6))) {
        /* The user has a "personal" namespace. */
        sawone[NAMESPACE_INBOX] = 1;
-    } else if (!(strncmp(name, "user.", 5))) {
+    } else if (!(strncmp(name, "user" DELIMITER_STR, 5))) {
        /* The user can see the "other users" namespace. */
        sawone[NAMESPACE_USER] = 1;
     } else {
@@ -4311,9 +4311,9 @@
     }
 
     prot_printf(imapd_out, "* NAMESPACE %s %s %s\r\n",
-               (sawone[NAMESPACE_INBOX]) ? "((\"INBOX.\" \".\"))" : "NIL",
-               (sawone[NAMESPACE_USER]) ? "((\"user.\" \".\"))" : "NIL",
-               (sawone[NAMESPACE_SHARED]) ? "((\"\" \".\"))" : "NIL");
+               (sawone[NAMESPACE_INBOX]) ? "((\"INBOX.\" \"" DELIMITER_STR "\"))" : 
+"NIL",
+               (sawone[NAMESPACE_USER]) ? "((\"user" DELIMITER_STR "\" \"" 
+DELIMITER_STR "\"))" : "NIL",
+               (sawone[NAMESPACE_SHARED]) ? "((\"\" \"" DELIMITER_STR "\"))" : "NIL");
 
     prot_printf(imapd_out, "%s OK %s\r\n", tag,
                error_message(IMAP_OK_COMPLETED));
@@ -5640,10 +5640,10 @@
     
     if (lastnamedelayed) {
        if (name && strncmp(lastname, name, strlen(lastname)) == 0 &&
-           name[strlen(lastname)] == '.') {
+           name[strlen(lastname)] == DELIMITER_CHAR) {
            lastnamehassub = 1;
        }
-       prot_printf(imapd_out, "* %s (%s) \".\" ", cmd,
+       prot_printf(imapd_out, "* %s (%s) \"" DELIMITER_STR "\" ", cmd,
               lastnamehassub ? "" : "\\Noinferiors");
        printastring(lastname);
        prot_printf(imapd_out, "\r\n");
@@ -5680,7 +5680,7 @@
 
     c = name[matchlen];
     if (c) name[matchlen] = '\0';
-    prot_printf(imapd_out, "* %s (%s) \".\" ", cmd, c ? "\\Noselect" : "");
+    prot_printf(imapd_out, "* %s (%s) \"" DELIMITER_STR "\" ", cmd, c ? "\\Noselect" 
+: "");
     printstring(name);
     prot_printf(imapd_out, "\r\n");
     if (c) name[matchlen] = c;
diff -u -r cyrus-imapd-2.0.12/imap/ipurge.c cyrus-imapd-2.0.12/imap/ipurge.c
--- cyrus-imapd-2.0.12/imap/ipurge.c    Mon Dec 18 15:53:39 2000
+++ cyrus-imapd-2.0.12/imap/ipurge.c    Thu Apr 12 13:50:05 2001
@@ -183,7 +183,7 @@
   mbox_stats_t   stats;
 
   /* DON'T purge INBOX* and user.* */
-  if ((strncasecmp(name,"INBOX",5)==0) || (strncasecmp(name,"user.",5)==0))
+  if ((strncasecmp(name,"INBOX",5)==0) || (strncasecmp(name,"user" 
+DELIMITER_STR,5)==0))
       return 0;
 
   memset(&stats, '\0', sizeof(mbox_stats_t));
diff -u -r cyrus-imapd-2.0.12/imap/lmtpd.c cyrus-imapd-2.0.12/imap/lmtpd.c
--- cyrus-imapd-2.0.12/imap/lmtpd.c     Sat Feb 17 03:06:38 2001
+++ cyrus-imapd-2.0.12/imap/lmtpd.c     Thu Apr 12 17:19:17 2001
@@ -343,7 +343,7 @@
 {
     static char buf[MAX_MAILBOX_PATH];
 
-    buf[0] = '.';
+    buf[0] = DELIMITER_CHAR;
     buf[1] = '\0';
     strcat(buf, user);
     strcat(buf, ".sieve.");
@@ -1100,11 +1100,11 @@
 
     if (user && !strncasecmp(mailboxname, "INBOX", 5)) {
        /* canonicalize mailbox */
-       if (strchr(user, '.') ||
+       if (strchr(user, DELIMITER_CHAR) ||
            strlen(user) + 30 > MAX_MAILBOX_PATH) {
            return IMAP_MAILBOX_NONEXISTENT;
        }
-       strcpy(namebuf, "user.");
+       strcpy(namebuf, "user" DELIMITER_STR);
        strcat(namebuf, user);
        strcat(namebuf, mailboxname + 5);
     } else {
@@ -1185,7 +1185,7 @@
        }
 
        /* case 2: ordinary user, might have Sieve script */
-       else if (!strchr(rcpt, '.') &&
+       else if (!strchr(rcpt, DELIMITER_CHAR) &&
                 strlen(rcpt) + 30 <= MAX_MAILBOX_PATH) {
            FILE *f = sieve_find_script(rcpt);
            char namebuf[MAX_MAILBOX_PATH];
@@ -1346,7 +1346,7 @@
        if (strlen(user) > sizeof(buf)-10) {
            r = IMAP_MAILBOX_NONEXISTENT;
        } else {
-           strcpy(buf, "user.");
+           strcpy(buf, "user" DELIMITER_STR);
            strcat(buf, user);
            plus = strchr(buf, '+');
            if (plus) *plus = '\0';
diff -u -r cyrus-imapd-2.0.12/imap/lmtpproxyd.c cyrus-imapd-2.0.12/imap/lmtpproxyd.c
--- cyrus-imapd-2.0.12/imap/lmtpproxyd.c        Wed Dec 20 06:31:41 2000
+++ cyrus-imapd-2.0.12/imap/lmtpproxyd.c        Thu Apr 12 17:19:32 2001
@@ -344,7 +344,7 @@
 {
     static char buf[MAX_MAILBOX_PATH];
 
-    buf[0] = '.';
+    buf[0] = DELIMITER_CHAR;
     buf[1] = '\0';
     strcat(buf, user);
     strcat(buf, ".sieve.");
@@ -695,7 +695,7 @@
     if (sd->username && !strncasecmp(mailboxname, "INBOX", 5)) {
        /* canonicalize mailbox */
        snprintf(namebuf, sizeof namebuf,
-                "%s+user.%s%s", BB, sd->username, mailboxname + 5);
+                "%s+user" DELIMITER_STR "%s%s", BB, sd->username, mailboxname + 5);
     } else {
        snprintf(namebuf, sizeof namebuf, "%s+%s", BB, mailboxname);
     }
@@ -1090,7 +1090,7 @@
        char buf[MAX_MAILBOX_NAME];
        char *plus;
 
-       strlcpy(buf, "user.", sizeof buf);
+       strlcpy(buf, "user" DELIMITER_STR, sizeof buf);
        strlcat(buf, mailbox, sizeof buf);
        plus = strchr(buf, '+');
        if (plus) *plus = '\0';
@@ -1435,7 +1435,7 @@
            r = IMAP_MAILBOX_NONEXISTENT;
        } else {
            /* just copy before the plus */
-           strcpy(buf, "user.");
+           strcpy(buf, "user" DELIMITER_STR);
            strncat(buf, user, l);
            buf[l + 5] = '\0';
            r = mboxlist_lookup(buf, NULL, NULL, NULL);
diff -u -r cyrus-imapd-2.0.12/imap/mailbox.c cyrus-imapd-2.0.12/imap/mailbox.c
--- cyrus-imapd-2.0.12/imap/mailbox.c   Wed Jan 10 18:23:08 2001
+++ cyrus-imapd-2.0.12/imap/mailbox.c   Thu Apr 12 17:30:54 2001
@@ -1845,7 +1845,7 @@
 
     mailbox_hash_quota(quota_path, start);
     while (stat(quota_path, &sbuf) == -1) {
-       tail = strrchr(start, '.');
+       tail = strrchr(start, DELIMITER_CHAR);
        if (!tail) return 0;
        *tail = '\0';
        mailbox_hash_quota(quota_path, start);
@@ -2285,7 +2285,7 @@
     char c;
 
     if (config_hashimapspool) {
-       idx = strchr(name, '.');
+       idx = strchr(name, DELIMITER_CHAR);
        if (idx == NULL) {
            c = *name;
        } else {
@@ -2301,28 +2301,44 @@
        sprintf(buf, "%s/%s", root, name);
     }
 
-    /* change all '.'s to '/' */
+#if DELIMITER_CHAR != '/'
+    /* change all DELIMITERs to '/' */
     for (p = buf + strlen(root) + 1; *p; p++) {
-       if (*p == '.') *p = '/';
+       if (*p == DELIMITER_CHAR) *p = '/';
     }
+#endif
 }
 
 /* simple hash so it's easy to find these things in the filesystem;
    our human time is worth more than efficiency */
 void mailbox_hash_quota(char *buf, const char *qr)
 {
-    char *idx;
+    const char *idx;
     char c;
-
-    idx = strchr(qr, '.'); /* skip past user. */
-    if (idx == NULL) {
-       c = *qr;
+#if DELIMITER_CHAR == '/'
+    char *p;
+    int len;
+#endif
+
+    idx = strchr(qr, DELIMITER_CHAR); /* skip past user. */
+    if (idx == NULL) {         /* no DELIMITER so just use name */
+       idx = qr;
     } else {
-       c = *(idx + 1);
+       idx++;                   /* skip past DELIMITER */
     }
-    c = (char) tolower((int) c);
+    c = (char) tolower((int) *idx);
     if (!islower((int) c))
        c = 'q';
 
-    sprintf(buf, "%s%s%c/%s", config_dir, FNAME_QUOTADIR, c, qr);
+#if DELIMITER_CHAR == '/'
+    len = sprintf(buf, "%s%s%c/", config_dir, FNAME_QUOTADIR, c);
+    /* change all DELIMITERs to '.' */
+    for (p = buf + len; *idx; ++idx, ++p) {
+      *p = *idx == DELIMITER_CHAR ? '.' : *idx;
+    }
+    *p = '\0';
+#else
+    sprintf(buf, "%s%s%c/%s", config_dir, FNAME_QUOTADIR, c, idx);
+#endif
+
 }
diff -u -r cyrus-imapd-2.0.12/imap/mailbox.h cyrus-imapd-2.0.12/imap/mailbox.h
--- cyrus-imapd-2.0.12/imap/mailbox.h   Wed Jan 10 18:23:04 2001
+++ cyrus-imapd-2.0.12/imap/mailbox.h   Thu Apr 12 18:18:16 2001
@@ -73,6 +73,9 @@
 
 #define MAILBOX_MINOR_VERSION  3
 
+#define DELIMITER_CHAR '/'
+#define DELIMITER_STR  "/"
+
 #define FNAME_HEADER "/cyrus.header"
 #define FNAME_INDEX "/cyrus.index"
 #define FNAME_CACHE "/cyrus.cache"
diff -u -r cyrus-imapd-2.0.12/imap/mboxlist.c cyrus-imapd-2.0.12/imap/mboxlist.c
--- cyrus-imapd-2.0.12/imap/mboxlist.c  Thu Jan 18 08:21:19 2001
+++ cyrus-imapd-2.0.12/imap/mboxlist.c  Thu Apr 12 15:04:59 2001
@@ -357,7 +357,7 @@
     /* Search for a parent */
     strcpy(parent, name);
     parentlen = 0;
-    while ((parentlen==0) && (p = strrchr(parent, '.'))) {
+    while ((parentlen==0) && (p = strrchr(parent, DELIMITER_CHAR))) {
        *p = '\0';
 
        r = mboxlist_mylookup(parent, NULL, NULL, &parentpartition, 
@@ -408,8 +408,8 @@
        }
        
        acl = xstrdup("");
-       if (!strncmp(name, "user.", 5)) {
-           if (strchr(name+5, '.')) {
+       if (!strncmp(name, "user" DELIMITER_STR, 5)) {
+           if (strchr(name+5, DELIMITER_CHAR)) {
                /* Disallow creating user.X.* when no user.X */
                free(acl);
                return IMAP_PERMISSION_DENIED;
@@ -698,7 +698,7 @@
  retry:
     /* Check for request to delete a user:
        user.<x> with no dots after it */
-    if (!strncmp(name, "user.", 5) && !strchr(name+5, '.')) {
+    if (!strncmp(name, "user" DELIMITER_STR, 5) && !strchr(name+5, DELIMITER_CHAR)) {
        /* Can't DELETE INBOX (your own inbox) */
        if (!strcmp(name+5, userid)) {
            r = IMAP_MAILBOX_NOTSUPPORTED;
@@ -898,7 +898,7 @@
            r = IMAP_MAILBOX_EXISTS;
            goto done;
        }
-    } else if (!strncmp(oldname, "user.", 5) && !strchr(oldname+5, '.')) {
+    } else if (!strncmp(oldname, "user" DELIMITER_STR, 5) && !strchr(oldname+5, 
+DELIMITER_CHAR)) {
        if (!strcmp(oldname+5, userid)) {
            /* Special case of renaming inbox */
            access = cyrus_acl_myrights(auth_state, oldacl);
@@ -923,7 +923,7 @@
 
     /* Check ability to create new mailbox */
     if (!partitionmove) {
-       if (!strncmp(newname, "user.", 5) && !strchr(newname+5, '.')) {
+       if (!strncmp(newname, "user" DELIMITER_STR, 5) && !strchr(newname+5, 
+DELIMITER_CHAR)) {
            /* Even admins can't rename to user's inboxes */
            r = IMAP_MAILBOX_NOTSUPPORTED;
            goto done;
@@ -1114,10 +1114,10 @@
     int mbtype;
     struct txn *tid = NULL;
 
-    if (!strncmp(name, "user.", 5) &&
-       !strchr(userid, '.') &&
+    if (!strncmp(name, "user" DELIMITER_STR, 5) &&
+       !strchr(userid, DELIMITER_CHAR) &&
        !strncmp(name+5, userid, useridlen) &&
-       (name[5+useridlen] == '\0' || name[5+useridlen] == '.')) {
+       (name[5+useridlen] == '\0' || name[5+useridlen] == DELIMITER_CHAR)) {
        isusermbox = 1;
     }
 
@@ -1284,7 +1284,7 @@
     if (!rock->inbox && rock->usermboxname &&
        keylen >= rock->usermboxnamelen &&
        (keylen == rock->usermboxnamelen || 
-        key[rock->usermboxnamelen] == '.') &&
+        key[rock->usermboxnamelen] == DELIMITER_CHAR) &&
        !strncmp(key, rock->usermboxname, rock->usermboxnamelen)) {
        /* this would've been output with the inbox stuff, so skip it */
        return 0;
@@ -1351,7 +1351,7 @@
        if (!rock->inbox && rock->usermboxname &&
            !strncmp(namebuf, rock->usermboxname, rock->usermboxnamelen)
            && (keylen == rock->usermboxnamelen || 
-               namebuf[rock->usermboxnamelen] == '.')) {
+               namebuf[rock->usermboxnamelen] == DELIMITER_CHAR)) {
            /* this would've been output with the inbox stuff, so skip it */
            return 0;
        }
@@ -1428,9 +1428,9 @@
     cbrock.procrock = rock;
 
     /* Build usermboxname */
-    if (userid && !strchr(userid, '.') &&
+    if (userid && !strchr(userid, DELIMITER_CHAR) &&
        strlen(userid)+5 < MAX_MAILBOX_NAME) {
-       strcpy(usermboxname, "user.");
+       strcpy(usermboxname, "user" DELIMITER_STR);
        strcat(usermboxname, userid);
        usermboxnamelen = strlen(usermboxname);
     }
@@ -1455,7 +1455,7 @@
                r = (*proc)(usermboxname, usermboxnamelen, 1, rock);
            }
        }
-       strcpy(usermboxname+usermboxnamelen, ".");
+       strcpy(usermboxname+usermboxnamelen, DELIMITER_STR);
        usermboxnamelen++;
 
        cbrock.usermboxname = usermboxname;
@@ -1480,7 +1480,7 @@
      */
     if (userid &&
        (!strncmp(usermboxname, pattern, usermboxnamelen-1) ||
-        !strncasecmp("inbox.", pattern, prefixlen < 6 ? prefixlen : 6))) {
+        !strncasecmp("inbox" DELIMITER_STR, pattern, prefixlen < 6 ? prefixlen : 6))) 
+{
 
        if (!strncmp(usermboxname, pattern, usermboxnamelen-1)) {
            cbrock.inboxoffset = 0;
@@ -1527,7 +1527,10 @@
     struct quota quota;
     int r;
 
-    if (!root[0] || root[0] == '.' || strchr(root, '/')
+    if (!root[0] || root[0] == DELIMITER_CHAR
+#if DELIMITER_CHAR != '/'
+       || strchr(root, '/')
+#endif
        || strchr(root, '*') || strchr(root, '%') || strchr(root, '?')) {
        return IMAP_MAILBOX_BADNAME;
     }
@@ -1570,7 +1573,7 @@
     }
 
     strcpy(pattern, quota.root);
-    strcat(pattern, ".*");
+    strcat(pattern, DELIMITER_STR "*");
     mboxlist_newquota = &quota;
     
     /* top level mailbox */
@@ -1791,10 +1794,10 @@
     char inboxname[MAX_MAILBOX_NAME+1];
 
     /* Users without INBOXes may not keep subscriptions */
-    if (strchr(userid, '.') || strlen(userid) + 6 > MAX_MAILBOX_NAME) {
+    if (strchr(userid, DELIMITER_CHAR) || strlen(userid) + 6 > MAX_MAILBOX_NAME) {
        return IMAP_PERMISSION_DENIED;
     }
-    strcpy(inboxname, "user.");
+    strcpy(inboxname, "user" DELIMITER_STR);
     strcat(inboxname, userid);
     if (mboxlist_lookup(inboxname, NULL, NULL, NULL) != 0) {
        return IMAP_PERMISSION_DENIED;
@@ -1854,9 +1857,9 @@
     }
 
     /* Build usermboxname */
-    if (userid && !strchr(userid, '.') &&
+    if (userid && !strchr(userid, DELIMITER_CHAR) &&
        strlen(userid)+5 < MAX_MAILBOX_NAME) {
-       strcpy(usermboxname, "user.");
+       strcpy(usermboxname, "user" DELIMITER_STR);
        strcat(usermboxname, userid);
        usermboxnamelen = strlen(usermboxname);
     }
@@ -1881,7 +1884,7 @@
                r = (*proc)(usermboxname, usermboxnamelen, 1, rock);
            }
        }
-       strcpy(usermboxname+usermboxnamelen, ".");
+       strcpy(usermboxname+usermboxnamelen, DELIMITER_STR);
        usermboxnamelen++;
 
        cbrock.usermboxname = usermboxname;
@@ -1903,7 +1906,7 @@
      */
     if (userid &&
        (!strncmp(usermboxname, pattern, usermboxnamelen-1) ||
-        !strncasecmp("inbox.", pattern, prefixlen < 6 ? prefixlen : 6))) {
+        !strncasecmp("inbox" DELIMITER_STR, pattern, prefixlen < 6 ? prefixlen : 6))) 
+{
 
        if (!strncmp(usermboxname, pattern, usermboxnamelen-1)) {
            cbrock.inboxoffset = 0;
diff -u -r cyrus-imapd-2.0.12/imap/mboxname.c cyrus-imapd-2.0.12/imap/mboxname.c
--- cyrus-imapd-2.0.12/imap/mboxname.c  Fri Jan  5 17:00:18 2001
+++ cyrus-imapd-2.0.12/imap/mboxname.c  Thu Apr 12 18:35:40 2001
@@ -64,11 +64,23 @@
     "",
     "*\t*",
     "*\n*",
+#if DELIMITER_CHAR != '/'
     "*/*",
+#endif
+#if DELIMITER_CHAR != '.'
     ".*",
     "*.",
-    "*..*",
+#endif
+    DELIMITER_STR "*",
+    "*" DELIMITER_STR,
+    "*" DELIMITER_STR DELIMITER_STR "*",
     "user",
+#if DELIMITER_CHAR == '/'
+    "*/.*",
+    "*" FNAME_HEADER,
+    "*" FNAME_INDEX,
+    "*" FNAME_CACHE,
+#endif
 };
 #define NUM_BADMBOXPATTERNS (sizeof(badmboxpatterns)/sizeof(*badmboxpatterns))
 
@@ -106,9 +118,9 @@
 {
     if ((name[0] == 'i' || name[0] == 'I') &&
        !strncasecmp(name, "inbox", 5) &&
-       (name[5] == '\0' || name[5] == '.')) {
+       (name[5] == '\0' || name[5] == DELIMITER_CHAR)) {
 
-       if (!userid || strchr(userid, '.')) {
+       if (!userid || strchr(userid, DELIMITER_CHAR)) {
            return IMAP_MAILBOX_BADNAME;
        }
 
@@ -116,7 +128,7 @@
            return IMAP_MAILBOX_BADNAME;
        }
 
-       strcpy(result, "user.");
+       strcpy(result, "user" DELIMITER_STR);
        strcat(result, userid);
        strcat(result, name+5);
        return 0;
@@ -134,9 +146,9 @@
  */
 int mboxname_userownsmailbox(char *userid, char *name)
 {
-    if (!strchr(userid, '.') && !strncmp(name, "user.", 5) &&
+    if (!strchr(userid, DELIMITER_CHAR) && !strncmp(name, "user" DELIMITER_STR, 5) &&
        !strncmp(name+5, userid, strlen(userid)) &&
-       name[5+strlen(userid)] == '.') {
+       name[5+strlen(userid)] == DELIMITER_CHAR) {
        return 1;
     }
     return 0;
@@ -153,7 +165,7 @@
 
     while ((c = *name++)!=0) {
        switch (c) {
-       case '.':
+       case DELIMITER_CHAR:
            if (!sawnonnumeric) return IMAP_MAILBOX_BADNAME;
            sawnonnumeric = 0;
            break;
@@ -184,7 +196,7 @@
  * Apply site policy restrictions on mailbox names.
  * Restrictions are hardwired for now.
  */
-#define GOODCHARS " 
+,-.0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"
+#define GOODCHARS " 
++,-.0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~" DELIMITER_STR
 int mboxname_policycheck(char *name)
 {
     int i;
diff -u -r cyrus-imapd-2.0.12/imap/pop3d.c cyrus-imapd-2.0.12/imap/pop3d.c
--- cyrus-imapd-2.0.12/imap/pop3d.c     Sat Feb 17 05:55:10 2001
+++ cyrus-imapd-2.0.12/imap/pop3d.c     Thu Apr 12 14:41:20 2001
@@ -766,7 +766,7 @@
        shut_down(0);
     }
     else if (!(p = auth_canonifyid(user)) ||
-              strchr(p, '.') || strlen(p) + 6 > MAX_MAILBOX_PATH) {
+              strchr(p, DELIMITER_CHAR) || strlen(p) + 6 > MAX_MAILBOX_PATH) {
        prot_printf(popd_out, "-ERR Invalid user\r\n");
        syslog(LOG_NOTICE,
               "badlogin: %s plaintext %s invalid user",
@@ -1045,7 +1045,7 @@
 
     popd_login_time = time(0);
 
-    strcpy(inboxname, "user.");
+    strcpy(inboxname, "user" DELIMITER_STR);
     strcat(inboxname, popd_userid);
     r = mailbox_open_header(inboxname, 0, &mboxstruct);
     if (r) {
diff -u -r cyrus-imapd-2.0.12/imap/pop3proxyd.c cyrus-imapd-2.0.12/imap/pop3proxyd.c
--- cyrus-imapd-2.0.12/imap/pop3proxyd.c        Sat Feb 17 05:55:10 2001
+++ cyrus-imapd-2.0.12/imap/pop3proxyd.c        Thu Apr 12 14:41:52 2001
@@ -595,7 +595,7 @@
 
     shutdown_file(); /* check for shutdown file */
     if (!(p = auth_canonifyid(user)) ||
-              strchr(p, '.') || strlen(p) + 6 > MAX_MAILBOX_PATH) {
+              strchr(p, DELIMITER_CHAR) || strlen(p) + 6 > MAX_MAILBOX_PATH) {
        prot_printf(popd_out, "-ERR Invalid user\r\n");
        syslog(LOG_NOTICE,
               "badlogin: %s plaintext %s invalid user",
@@ -1024,7 +1024,7 @@
     char *server;
 
     /* have to figure out what server to connect to */
-    strcpy(inboxname, "user.");
+    strcpy(inboxname, "user" DELIMITER_STR);
     strcat(inboxname, popd_userid);
     r = mboxlist_lookup(inboxname, &server, NULL, NULL);
     if (!r) fatal("couldn't find backend server", EC_CONFIG);
diff -u -r cyrus-imapd-2.0.12/imap/proxyd.c cyrus-imapd-2.0.12/imap/proxyd.c
--- cyrus-imapd-2.0.12/imap/proxyd.c    Sat Feb 17 05:55:10 2001
+++ cyrus-imapd-2.0.12/imap/proxyd.c    Thu Apr 12 14:45:21 2001
@@ -853,7 +853,7 @@
     struct backend *s = NULL;
 
     if (strlen(proxyd_userid) > MAX_MAILBOX_NAME - 30) return NULL;
-    strcpy(inbox, "user.");
+    strcpy(inbox, "user" DELIMITER_STR);
     strcat(inbox, proxyd_userid);
        
     r = mlookup(inbox, &server, NULL, NULL);
@@ -885,9 +885,9 @@
     int r;
     struct auth_state *authstate;
 
-    if (strchr(user, '.') || strlen(user)+6 >= sizeof(inboxname)) return 0;
+    if (strchr(user, DELIMITER_CHAR) || strlen(user)+6 >= sizeof(inboxname)) return 0;
 
-    strcpy(inboxname, "user.");
+    strcpy(inboxname, "user" DELIMITER_STR);
     strcat(inboxname, user);
 
     if (!(authstate = auth_newstate(auth_identity, (char *)0)) ||
@@ -3342,7 +3342,7 @@
        r = IMAP_PERMISSION_DENIED;
     }
 
-    if (name[0] && name[strlen(name)-1] == '.') {
+    if (name[0] && name[strlen(name)-1] == DELIMITER_CHAR) {
        /* We don't care about trailing hierarchy delimiters. */
        name[strlen(name)-1] = '\0';
     }
@@ -3602,7 +3602,7 @@
     
     if (!pattern[0] && !subscribed) {
        /* Special case: query top-level hierarchy separator */
-       prot_printf(proxyd_out, "* LIST (\\Noselect) \".\" \"\"\r\n");
+       prot_printf(proxyd_out, "* LIST (\\Noselect) \"" DELIMITER_CHAR \" \"\"\r\n");
     } else if (subscribed) {   /* do an LSUB command; contact our INBOX */
        if (!backend_inbox) {
            backend_inbox = proxyd_findinboxserver();
@@ -3619,7 +3619,7 @@
        }
     } else {                   /* do a LIST locally */
        /* Do we need to concatenate fields? */
-       if (!ignorereference || pattern[0] == '.') {
+       if (!ignorereference || pattern[0] == DELIMITER_CHAR) {
            /* Either
             * - name begins with dot
             * - we're configured to honor the reference argument */
@@ -3634,7 +3634,7 @@
 
            if (*reference) {
                /* check for LIST A. .B, change to LIST "" A.B */
-               if (reference[reflen-1] == '.' && pattern[0] == '.') {
+               if (reference[reflen-1] == DELIMITER_CHAR && pattern[0] == 
+DELIMITER_CHAR) {
                    reference[--reflen] = '\0';
                }
                strcpy(buf, reference);
@@ -3806,11 +3806,11 @@
        if (!canon_identifier) {
            rightsdesc = "\"\"";
        }
-       else if (!strncmp(mailboxname, "user.", 5) &&
-                !strchr(canon_identifier, '.') &&
+       else if (!strncmp(mailboxname, "user" DELIMITER_STR, 5) &&
+                !strchr(canon_identifier, DELIMITER_CHAR) &&
                 !strncmp(mailboxname+5, canon_identifier, canonidlen) &&
                 (mailboxname[5+canonidlen] == '\0' ||
-                 mailboxname[5+canonidlen] == '.')) {
+                 mailboxname[5+canonidlen] == DELIMITER_CHAR)) {
            rightsdesc = "lca r s w i p d 0 1 2 3 4 5 6 7 8 9";
        }
        else {
@@ -4203,10 +4203,10 @@
        return 0;
     }
     
-    if (!(strncmp(name, "INBOX.", 6))) {
+    if (!(strncmp(name, "INBOX" DELIMITER_STR, 6))) {
        /* The user has a "personal" namespace. */
        sawone[NAMESPACE_INBOX] = 1;
-    } else if (!(strncmp(name, "user.", 5))) {
+    } else if (!(strncmp(name, "user" DELIMITER_STR, 5))) {
        /* The user can see the "other users" namespace. */
        sawone[NAMESPACE_USER] = 1;
     } else {
@@ -4232,9 +4232,9 @@
                     proxyd_authstate, namespacedata, (void*) sawone);
 
     prot_printf(proxyd_out, "* NAMESPACE %s %s %s\r\n",
-               (sawone[NAMESPACE_INBOX]) ? "((\"INBOX.\" \".\"))" : "NIL",
-               (sawone[NAMESPACE_USER]) ? "((\"user.\" \".\"))" : "NIL",
-               (sawone[NAMESPACE_SHARED]) ? "((\"\" \".\"))" : "NIL");
+               (sawone[NAMESPACE_INBOX]) ? "((\"INBOX.\" \"" DELIMITER_STR \"))" : 
+"NIL",
+               (sawone[NAMESPACE_USER]) ? "((\"user.\" \"" DELIMITER_STR \"))" : 
+"NIL",
+               (sawone[NAMESPACE_SHARED]) ? "((\"\" \"" DELIMITER_STR \"))" : "NIL");
 
     prot_printf(proxyd_out, "%s OK %s\r\n", tag,
                error_message(IMAP_OK_COMPLETED));
@@ -4541,10 +4541,10 @@
     
     if (lastnamedelayed) {
        if (name && strncmp(lastname, name, strlen(lastname)) == 0 &&
-           name[strlen(lastname)] == '.') {
+           name[strlen(lastname)] == DELIMITER_CHAR) {
            lastnamehassub = 1;
        }
-       prot_printf(proxyd_out, "* %s (%s) \".\" ", cmd,
+       prot_printf(proxyd_out, "* %s (%s) \"" DELIMITER_STR "\" ", cmd,
               lastnamehassub ? "" : "\\Noinferiors");
        printastring(lastname);
        prot_printf(proxyd_out, "\r\n");
@@ -4581,7 +4581,7 @@
 
     c = name[matchlen];
     if (c) name[matchlen] = '\0';
-    prot_printf(proxyd_out, "* %s (%s) \".\" ", cmd, c ? "\\Noselect" : "");
+    prot_printf(proxyd_out, "* %s (%s) \"" DELIMITER_STR "\" ", cmd, c ? "\\Noselect" 
+: "");
     printstring(name);
     prot_printf(proxyd_out, "\r\n");
     if (c) name[matchlen] = c;
diff -u -r cyrus-imapd-2.0.12/imap/quota.c cyrus-imapd-2.0.12/imap/quota.c
--- cyrus-imapd-2.0.12/imap/quota.c     Mon Dec 18 15:53:41 2000
+++ cyrus-imapd-2.0.12/imap/quota.c     Thu Apr 12 17:34:01 2001
@@ -277,7 +277,7 @@
         i < quota_num && strcasecmp(name, quota[i].quota.root) >= 0; i++) {
        len = strlen(quota[i].quota.root);
        if (!strncasecmp(name, quota[i].quota.root, len) &&
-           (!name[len] || name[len] == '.')) {
+           (!name[len] || name[len] == DELIMITER_CHAR)) {
            quota[i].refcount++;
            if (len > thisquotalen) {
                thisquota = i;
diff -u -r cyrus-imapd-2.0.12/imap/reconstruct.c cyrus-imapd-2.0.12/imap/reconstruct.c
--- cyrus-imapd-2.0.12/imap/reconstruct.c       Tue Jan  9 11:19:04 2001
+++ cyrus-imapd-2.0.12/imap/reconstruct.c       Thu Apr 12 17:43:16 2001
@@ -562,14 +562,16 @@
        while ((dirent = readdir(dirp)) != NULL) {
            struct discovered *new;
 
+#if DELIMITER_CHAR == '.'
            /* mailbox directories never have a dot in them */
            if (strchr(dirent->d_name, '.')) continue;
+#endif
            if (stat(dirent->d_name, &sbuf) < 0) continue;
            if (!S_ISDIR(sbuf.st_mode)) continue;
 
            /* ok, we found a directory that doesn't have a dot in it */
            strcpy(fnamebuf, name);
-           strcat(fnamebuf, ".");
+           strcat(fnamebuf, DELIMITER_STR);
            strcat(fnamebuf, dirent->d_name);
 
            /* does fnamebuf exist as a mailbox? */
diff -u -r cyrus-imapd-2.0.12/imap/sendmail-map.c 
cyrus-imapd-2.0.12/imap/sendmail-map.c
--- cyrus-imapd-2.0.12/imap/sendmail-map.c      Tue Dec 19 07:30:25 2000
+++ cyrus-imapd-2.0.12/imap/sendmail-map.c      Thu Apr 12 14:46:22 2001
@@ -187,7 +187,7 @@
     server = (char *) xmalloc(sizeof(char) * url->len);
     mailbox = (char *) xmalloc(sizeof(char) * 2 * url->len);
     imapurl_fromURL(server, mailbox, url->data);
-    if (strncmp(mailbox, "user.", 5) || strchr(mailbox + 5, '.')) {
+    if (strncmp(mailbox, "user" DELIMITER_STR, 5) || strchr(mailbox + 5, 
+DELIMITER_CHAR)) {
        syslog(LOG_NOTICE, "%s: not a user mailbox?!?", mailbox);
        goto ret;
     }
@@ -247,7 +247,7 @@
               error_message(r));
     }
 
-    if (strncmp(mailbox, "user.", 5) || strchr(mailbox + 5, '.')) {
+    if (strncmp(mailbox, "user" DELIMITER_STR, 5) || strchr(mailbox + 5, 
+DELIMITER_CHAR)) {
        syslog(LOG_NOTICE, "%s: not a user mailbox?!?", mailbox);
        return;
     }
@@ -328,7 +328,7 @@
     mailbox = (char *) xmalloc(sizeof(char) * 2 * url->len);
 
     imapurl_fromURL(server, mailbox, url->data);
-    if (strncmp(mailbox, "user.", 5) || strchr(mailbox + 5, '.')) {
+    if (strncmp(mailbox, "user" DELIMITER_STR, 5) || strchr(mailbox + 5, 
+DELIMITER_CHAR)) {
        syslog(LOG_NOTICE, "%s: not a user mailbox?!?", mailbox);
        goto ret;
     }
diff -u -r cyrus-imapd-2.0.12/lib/glob.c cyrus-imapd-2.0.12/lib/glob.c
--- cyrus-imapd-2.0.12/lib/glob.c       Thu Dec 21 09:53:49 2000
+++ cyrus-imapd-2.0.12/lib/glob.c       Thu May 17 18:13:21 2001
@@ -52,8 +52,7 @@
 #include "util.h"
 #include "glob.h"
 #include "xmalloc.h"
-
-#define SEPCHAR '.'
+#include "../imap/mailbox.h"
 
 /* name of "INBOX" -- must have no repeated substrings */
 static char inbox[] = "INBOX";
@@ -81,7 +80,7 @@
     g = (glob *) fs_get(sizeof (glob) + slen + strlen(str) + 1);
     if (g != 0) {
         strcpy(g->inbox, inbox);
-       g->sep_char = '.';
+       g->sep_char = DELIMITER_CHAR;
        dst = g->str;
        /* if we're doing a substring match, put a '*' prefix (1) */
        if (flags & GLOB_SUBSTRING) {
@@ -410,7 +409,7 @@
     char* argv[];
 {
     glob *g = glob_init_suppress(argv[1], GLOB_INBOXCASE|GLOB_HIERARCHY,
-                                "user.nifty");
+                                "user" DELIMITER_CHAR "nifty");
     char text[1024];
     int len;
     long min;

Reply via email to