commit 46584e5358dbd32b8549b15ce543c33482bc6d60
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Fri Jun 3 20:58:09 2022 +0200

    add support for Maildir Paths with suffixes
    
    that is, Path not ending with a slash.
    
    pedantically, this is a bugfix, as the manual already suggested that
    this is possible (and at least one user got the hint, though he was
    disappointed).
    
    the IMAP driver already supports this.

 NEWS                |  2 ++
 src/drv_maildir.c   | 38 ++++++++++++++++++++++++++++++++------
 src/mbsyncrc.sample | 26 ++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/NEWS b/NEWS
index 5472b94c..04389920 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ MaxMessages and MaxSize can be used together now.
 
 Added support for IMAP mailbox names with non-ASCII characters.
 
+Added support for Maildir Paths with suffixes.
+
 The unfiltered list of mailboxes in each Store can be printed now.
 
 A proper summary is now printed prior to exiting.
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 8327d233..64e7718a 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -35,6 +35,7 @@ typedef union maildir_store_conf {
        struct {
                STORE_CONF
                char *path;
+               char *path_sfx;
                char *inbox;
 #ifdef USE_DB
                int alt_map;
@@ -121,16 +122,20 @@ static char *
 maildir_join_path( maildir_store_conf_t *conf, int in_inbox, const char *box )
 {
        char *out, *p;
-       const char *prefix;
-       uint pl, bl, n;
+       const char *prefix, *infix;
+       uint pl, il, bl, n;
        char c;
 
        if (in_inbox || conf->sub_style == SUB_MAILDIRPP) {
                prefix = conf->inbox;
+               infix = NULL;
+               il = 0;
        } else {
                if (maildir_ensure_path( conf ) < 0)
                        return NULL;
                prefix = conf->path;
+               infix = conf->path_sfx;
+               il = strlen( infix ) + 1;
        }
        pl = strlen( prefix );
        for (bl = 0, n = 0; (c = box[bl]); bl++) {
@@ -157,12 +162,16 @@ maildir_join_path( maildir_store_conf_t *conf, int 
in_inbox, const char *box )
        default: /* SUB_LEGACY and SUB_UNSET */
                break;
        }
-       out = nfmalloc( pl + bl + n + 1 );
+       out = nfmalloc( pl + il + bl + n + 1 );
        memcpy( out, prefix, pl );
        p = out + pl;
        if (conf->sub_style == SUB_MAILDIRPP) {
                *p++ = '/';
                *p++ = '.';
+       } else if (il) {
+               *p++ = '/';
+               memcpy( p, infix, il - 1 );
+               p += il - 1;
        }
        while ((c = *box++)) {
                if (c == '/') {
@@ -366,6 +375,7 @@ maildir_list_maildirpp( maildir_store_t *ctx, int flags, 
const char *inbox )
 static int
 maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags,
                       const char *inbox, uint inboxLen,
+                      char *suffix, int suffixLen,
                       char *path, int pathLen, char *name, int nameLen )
 {
        DIR *dir;
@@ -399,6 +409,16 @@ maildir_list_recurse( maildir_store_t *ctx, int isBox, int 
flags,
                pl = nfsnprintf( path + pathLen, _POSIX_PATH_MAX - pathLen, 
"%s", ent );
                if (pl == 3 && (!memcmp( ent, "cur", 3 ) || !memcmp( ent, 
"new", 3 ) || !memcmp( ent, "tmp", 3 )))
                        continue;
+               if (suffixLen) {
+                       if (!starts_with( ent, pl, suffix, suffixLen ))
+                               continue;
+                       if (pl == suffixLen) {
+                               error( "Maildir error: empty mailbox name under 
%s - did you forget the trailing slash?\n", path );
+                               closedir( dir );
+                               return -1;
+                       }
+                       ent += suffixLen;
+               }
                pl += pathLen;
                if (inbox && equals( path, pl, inbox, inboxLen )) {
                        // Inbox nested into Path.
@@ -429,7 +449,7 @@ maildir_list_recurse( maildir_store_t *ctx, int isBox, int 
flags,
                                add_string_list( &ctx->boxes, name );
                        path[pl] = 0;
                        name[nl++] = '/';
-                       if (maildir_list_recurse( ctx, isBox + 1, flags, inbox, 
inboxLen, path, pl, name, nl ) < 0) {
+                       if (maildir_list_recurse( ctx, isBox + 1, flags, inbox, 
inboxLen, NULL, 0, path, pl, name, nl ) < 0) {
                                closedir( dir );
                                return -1;
                        }
@@ -450,7 +470,7 @@ maildir_list_inbox( maildir_store_t *ctx, int flags )
 
        add_string_list( &ctx->boxes, "INBOX" );
        return maildir_list_recurse(
-               ctx, 1, flags, NULL, 0,
+               ctx, 1, flags, NULL, 0, NULL, 0,
                path, nfsnprintf( path, _POSIX_PATH_MAX, "%s/", 
ctx->conf->inbox ),
                name, nfsnprintf( name, _POSIX_PATH_MAX, "INBOX/" ) );
 }
@@ -469,7 +489,8 @@ maildir_list_path( maildir_store_t *ctx, int flags )
        const char *inbox = ctx->conf->inbox;
        return maildir_list_recurse(
                ctx, 0, flags, inbox, strlen( inbox ),
-               path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", ctx->conf->path 
),
+               ctx->conf->path_sfx, strlen( ctx->conf->path_sfx ),
+               path, nfsnprintf( path, _POSIX_PATH_MAX, "%s/", ctx->conf->path 
),
                name, 0 );
 }
 
@@ -1914,6 +1935,11 @@ maildir_parse_store( conffile_t *cfg, store_conf_t 
**storep )
                        if (starts_with( store->path, -1, store->inbox, 
inboxLen ) && store->path[inboxLen] == '/') {
                                error( "Maildir store '%s': Path cannot be 
nested under Inbox\n", store->name );
                                cfg->err = 1;
+                       } else {
+                               char *s = strrchr( store->path, '/' );
+                               assert( s );  // due to expand_strdup()
+                               store->path_sfx = s + 1;
+                               *s = 0;
                        }
                }
        }
diff --git a/src/mbsyncrc.sample b/src/mbsyncrc.sample
index 50e4981a..e7c61966 100644
--- a/src/mbsyncrc.sample
+++ b/src/mbsyncrc.sample
@@ -57,6 +57,32 @@ Group boxes
 Channels work personal remote
 
 
+# Due to the divergent Path suffixes, it's possible to have
+# multiple Stores homed in the same directory.
+# You could even put them all directly into $HOME.
+
+MaildirStore local-personal
+Path ~/Mail/personal-
+Inbox ~/Mail/personal-INBOX
+
+MaildirStore local-work
+Path ~/Mail/work-
+# Just because.
+Inbox ~/Mail/w0rk_InBoX
+
+Channel personal-joined
+Far :personal:
+Near :local-personal:
+Paterns *
+
+Channel work-joined
+Far :work:
+Near :local-work:
+Paterns *
+
+Group joined personal-joined work-joined
+
+
 IMAPStore st1
 Host st1.domain.com
 AuthMech CRAM-MD5


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to