@ -50,6 +50,11 @@
# include <db.h>
# include <db.h>
# endif /* USE_DB */
# endif /* USE_DB */
# define SUB_UNSET 0
# define SUB_VERBATIM 1
# define SUB_MAILDIRPP 2
# define SUB_LEGACY 3
typedef struct maildir_store_conf {
typedef struct maildir_store_conf {
store_conf_t gen ;
store_conf_t gen ;
char * inbox ;
char * inbox ;
@ -57,6 +62,7 @@ typedef struct maildir_store_conf {
int alt_map ;
int alt_map ;
# endif /* USE_DB */
# endif /* USE_DB */
char info_delimiter ;
char info_delimiter ;
char sub_style ;
char failed ;
char failed ;
char * info_prefix , * info_stop ; /* precalculated from info_delimiter */
char * info_prefix , * info_stop ; /* precalculated from info_delimiter */
} maildir_store_conf_t ;
} maildir_store_conf_t ;
@ -113,23 +119,50 @@ maildir_parse_flags( const char *info_prefix, const char *base )
}
}
static char *
static char *
maildir_join_path ( const char * prefix , const char * box )
maildir_join_path ( maildir_store_conf_t * conf , const char * prefix , const char * box )
{
{
char * out , * p ;
char * out , * p ;
int pl , bl , n ;
int pl , bl , n , sub = 0 ;
char c ;
char c ;
pl = strlen ( prefix ) ;
pl = strlen ( prefix ) ;
for ( bl = 0 , n = 0 ; ( c = box [ bl ] ) ; bl + + )
for ( bl = 0 , n = 0 ; ( c = box [ bl ] ) ; bl + + )
if ( c = = ' / ' )
if ( c = = ' / ' ) {
if ( conf - > sub_style = = SUB_UNSET ) {
error ( " Maildir error: accessing subfolder '%s', but store '%s' does not specify SubFolders style \n " ,
box , conf - > gen . name ) ;
return 0 ;
}
n + + ;
n + + ;
} else if ( c = = ' . ' & & conf - > sub_style = = SUB_MAILDIRPP ) {
error ( " Maildir error: store '%s', folder '%s': SubFolders style Maildir++ does not support dots in mailbox names \n " ,
conf - > gen . name , box ) ;
return 0 ;
}
out = nfmalloc ( pl + bl + n + 1 ) ;
out = nfmalloc ( pl + bl + n + 1 ) ;
memcpy ( out , prefix , pl ) ;
memcpy ( out , prefix , pl ) ;
p = out + pl ;
p = out + pl ;
while ( ( c = * box + + ) ) {
while ( ( c = * box + + ) ) {
* p + + = c ;
if ( c = = ' / ' ) {
if ( c = = ' / ' )
switch ( conf - > sub_style ) {
* p + + = ' . ' ;
case SUB_VERBATIM :
* p + + = c ;
break ;
case SUB_MAILDIRPP :
if ( ! sub ) {
sub = 1 ;
* p + + = c ;
}
* p + + = ' . ' ;
break ;
case SUB_LEGACY :
* p + + = c ;
* p + + = ' . ' ;
break ;
}
} else {
* p + + = c ;
}
}
}
* p = 0 ;
* p = 0 ;
return out ;
return out ;
@ -172,7 +205,11 @@ maildir_open_store( store_conf_t *gconf, const char *label ATTR_UNUSED,
cb ( 0 , aux ) ;
cb ( 0 , aux ) ;
return ;
return ;
}
}
ctx - > trash = maildir_join_path ( gconf - > path , gconf - > trash ) ;
if ( ! ( ctx - > trash = maildir_join_path ( conf , gconf - > path , gconf - > trash ) ) ) {
free ( ctx ) ;
cb ( 0 , aux ) ;
return ;
}
}
}
cb ( & ctx - > gen , aux ) ;
cb ( & ctx - > gen , aux ) ;
}
}
@ -239,7 +276,8 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags,
char * path , int pathLen , char * name , int nameLen )
char * path , int pathLen , char * name , int nameLen )
{
{
DIR * dir ;
DIR * dir ;
int pl , nl ;
int style = ( ( maildir_store_conf_t * ) gctx - > conf ) - > sub_style ;
int pl , nl , i ;
struct dirent * de ;
struct dirent * de ;
struct stat st ;
struct stat st ;
@ -249,9 +287,20 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags,
sys_error ( " Maildir error: cannot list %s " , path ) ;
sys_error ( " Maildir error: cannot list %s " , path ) ;
return - 1 ;
return - 1 ;
}
}
if ( isBox > 1 & & style = = SUB_UNSET ) {
error ( " Maildir error: found subfolder '%.*s', but store '%s' does not specify SubFolders style \n " ,
nameLen - 1 , name , gctx - > conf - > name ) ;
closedir ( dir ) ;
return - 1 ;
}
while ( ( de = readdir ( dir ) ) ) {
while ( ( de = readdir ( dir ) ) ) {
const char * ent = de - > d_name ;
const char * ent = de - > d_name ;
pl = pathLen + nfsnprintf ( path + pathLen , _POSIX_PATH_MAX - pathLen , " %s " , ent ) ;
if ( ent [ 0 ] = = ' . ' & & ( ! ent [ 1 ] | | ( ent [ 1 ] = = ' . ' & & ! ent [ 2 ] ) ) )
continue ;
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 ;
pl + = pathLen ;
if ( inbox & & equals ( path , pl , inbox , inboxLen ) ) {
if ( inbox & & equals ( path , pl , inbox , inboxLen ) ) {
/* Inbox nested into Path. List now if it won't be listed separately anyway. */
/* Inbox nested into Path. List now if it won't be listed separately anyway. */
if ( ! ( flags & LIST_INBOX ) & & maildir_list_inbox ( gctx , flags , 0 ) < 0 ) {
if ( ! ( flags & LIST_INBOX ) & & maildir_list_inbox ( gctx , flags , 0 ) < 0 ) {
@ -265,29 +314,39 @@ maildir_list_recurse( store_t *gctx, int isBox, int flags,
return - 1 ;
return - 1 ;
}
}
} else {
} else {
if ( * ent = = ' . ' ) {
if ( style = = SUB_MAILDIRPP | | style = = SUB_LEGACY ) {
if ( ! isBox )
if ( * ent = = ' . ' ) {
continue ;
if ( ! isBox )
if ( ! ent [ 1 ] | | ent [ 1 ] = = ' . ' )
continue ;
continue ;
ent + + ;
ent + + ;
} else {
} else {
if ( isBox )
if ( isBox )
continue ;
continue ;
if ( ! nameLen & & equals ( ent , - 1 , " INBOX " , 5 ) ) {
path [ pathLen ] = 0 ;
warn ( " Maildir warning: ignoring INBOX in %s \n " , path ) ;
continue ;
}
}
}
}
nl = nameLen + nfsnprintf ( name + nameLen , _POSIX_PATH_MAX - nameLen , " %s " , ent ) ;
nl = nameLen + nfsnprintf ( name + nameLen , _POSIX_PATH_MAX - nameLen , " %s " , ent ) ;
if ( style = = SUB_MAILDIRPP & & isBox ) {
for ( i = nameLen ; i < nl ; i + + ) {
if ( name [ i ] = = ' . ' )
name [ i ] = ' / ' ;
}
}
if ( ! nameLen & & equals ( name , nl , " INBOX " , 5 ) & & ( ! name [ 5 ] | | name [ 5 ] = = ' / ' ) ) {
path [ pathLen ] = 0 ;
warn ( " Maildir warning: ignoring INBOX in %s \n " , path ) ;
continue ;
}
path [ pl + + ] = ' / ' ;
path [ pl + + ] = ' / ' ;
nfsnprintf ( path + pl , _POSIX_PATH_MAX - pl , " cur " ) ;
nfsnprintf ( path + pl , _POSIX_PATH_MAX - pl , " cur " ) ;
if ( ! stat ( path , & st ) & & S_ISDIR ( st . st_mode ) )
if ( ! stat ( path , & st ) & & S_ISDIR ( st . st_mode ) )
add_string_list ( & gctx - > boxes , name ) ;
add_string_list ( & gctx - > boxes , name ) ;
if ( style = = SUB_MAILDIRPP & & isBox ) {
/* Maildir++ subfolder - don't recurse further. */
continue ;
}
path [ pl ] = 0 ;
path [ pl ] = 0 ;
name [ nl + + ] = ' / ' ;
name [ nl + + ] = ' / ' ;
if ( maildir_list_recurse ( gctx , 1 , flags , inbox , inboxLen , basePath , basePathLen , path , pl , name , nl ) < 0 ) {
if ( maildir_list_recurse ( gctx , isBox + 1 , flags , inbox , inboxLen , basePath , basePathLen , path , pl , name , nl ) < 0 ) {
closedir ( dir ) ;
closedir ( dir ) ;
return - 1 ;
return - 1 ;
}
}
@ -404,10 +463,6 @@ make_box_dir( char *buf, int bl )
if ( ! mkdir ( buf , 0700 ) | | errno = = EEXIST )
if ( ! mkdir ( buf , 0700 ) | | errno = = EEXIST )
return 0 ;
return 0 ;
p = memrchr ( buf , ' / ' , bl - 1 ) ;
p = memrchr ( buf , ' / ' , bl - 1 ) ;
if ( * ( p + 1 ) ! = ' . ' ) {
errno = ENOENT ;
return - 1 ;
}
* p = 0 ;
* p = 0 ;
if ( make_box_dir ( buf , ( int ) ( p - buf ) ) )
if ( make_box_dir ( buf , ( int ) ( p - buf ) ) )
return - 1 ;
return - 1 ;
@ -1055,17 +1110,17 @@ maildir_select_box( store_t *gctx, const char *name )
# endif /* USE_DB */
# endif /* USE_DB */
ctx - > fresh [ 0 ] = ctx - > fresh [ 1 ] = 0 ;
ctx - > fresh [ 0 ] = ctx - > fresh [ 1 ] = 0 ;
if ( starts_with ( name , - 1 , " INBOX " , 5 ) & & ( ! name [ 5 ] | | name [ 5 ] = = ' / ' ) ) {
if ( starts_with ( name , - 1 , " INBOX " , 5 ) & & ( ! name [ 5 ] | | name [ 5 ] = = ' / ' ) ) {
gctx - > path = maildir_join_path ( conf - > inbox , name + 5 ) ;
gctx - > path = maildir_join_path ( conf , conf - > inbox , name + 5 ) ;
ctx - > is_inbox = ! name [ 5 ] ;
ctx - > is_inbox = ! name [ 5 ] ;
} else {
} else {
if ( maildir_validate_path ( conf ) < 0 ) {
if ( maildir_validate_path ( conf ) < 0 ) {
gctx - > path = 0 ;
gctx - > path = 0 ;
return DRV_CANCELED ;
return DRV_CANCELED ;
}
}
gctx - > path = maildir_join_path ( gctx - > conf - > path , name ) ;
gctx - > path = maildir_join_path ( conf , conf - > gen . path , name ) ;
ctx - > is_inbox = 0 ;
ctx - > is_inbox = 0 ;
}
}
return DRV_OK ;
return gctx - > path ? DRV_OK : DRV_BOX_BAD ;
}
}
static void
static void
@ -1670,6 +1725,17 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
cfg - > err = 1 ;
cfg - > err = 1 ;
continue ;
continue ;
}
}
} else if ( ! strcasecmp ( " SubFolders " , cfg - > cmd ) ) {
if ( ! strcasecmp ( " Verbatim " , cfg - > val ) ) {
store - > sub_style = SUB_VERBATIM ;
} else if ( ! strcasecmp ( " Maildir++ " , cfg - > val ) ) {
store - > sub_style = SUB_MAILDIRPP ;
} else if ( ! strcasecmp ( " Legacy " , cfg - > val ) ) {
store - > sub_style = SUB_LEGACY ;
} else {
error ( " %s:%d: Unrecognized SubFolders style \n " , cfg - > file , cfg - > line ) ;
cfg - > err = 1 ;
}
} else
} else
parse_generic_store ( & store - > gen , cfg ) ;
parse_generic_store ( & store - > gen , cfg ) ;
if ( ! store - > inbox )
if ( ! store - > inbox )