support multi-character path separators
this applies to both the IMAP PathDelimiter (which is needed by Lotus Domino), as well as the Flatten-ed separators.
This commit is contained in:
parent
1b67c49965
commit
0b59ee0df3
18
src/config.c
18
src/config.c
|
@ -497,16 +497,14 @@ parse_generic_store( store_conf_t *store, conffile_t *cfg )
|
||||||
else if (!strcasecmp( "MapInbox", cfg->cmd ))
|
else if (!strcasecmp( "MapInbox", cfg->cmd ))
|
||||||
store->map_inbox = nfstrdup( cfg->val );
|
store->map_inbox = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "Flatten", cfg->cmd )) {
|
else if (!strcasecmp( "Flatten", cfg->cmd )) {
|
||||||
int sl = strlen( cfg->val );
|
const char *p;
|
||||||
if (sl != 1) {
|
for (p = cfg->val; *p; p++)
|
||||||
error( "%s:%d: malformed flattened hierarchy delimiter\n", cfg->file, cfg->line );
|
if (*p == '/') {
|
||||||
cfg->err = 1;
|
error( "%s:%d: flattened hierarchy delimiter cannot contain the canonical delimiter '/'\n", cfg->file, cfg->line );
|
||||||
} else if (cfg->val[0] == '/') {
|
cfg->err = 1;
|
||||||
error( "%s:%d: flattened hierarchy delimiter cannot be the canonical delimiter '/'\n", cfg->file, cfg->line );
|
return;
|
||||||
cfg->err = 1;
|
}
|
||||||
} else {
|
store->flat_delim = nfstrdup( cfg->val );
|
||||||
store->flat_delim = cfg->val[0];
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error( "%s:%d: unknown keyword '%s'\n", cfg->file, cfg->line, cfg->cmd );
|
error( "%s:%d: unknown keyword '%s'\n", cfg->file, cfg->line, cfg->cmd );
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
|
|
|
@ -52,7 +52,7 @@ typedef struct imap_store_conf {
|
||||||
store_conf_t gen;
|
store_conf_t gen;
|
||||||
imap_server_conf_t *server;
|
imap_server_conf_t *server;
|
||||||
unsigned use_namespace:1;
|
unsigned use_namespace:1;
|
||||||
char delimiter;
|
char *delimiter;
|
||||||
} imap_store_conf_t;
|
} imap_store_conf_t;
|
||||||
|
|
||||||
typedef struct imap_message {
|
typedef struct imap_message {
|
||||||
|
@ -88,7 +88,7 @@ typedef struct imap_store {
|
||||||
/* trash folder's existence is not confirmed yet */
|
/* trash folder's existence is not confirmed yet */
|
||||||
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
|
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
|
||||||
unsigned got_namespace:1;
|
unsigned got_namespace:1;
|
||||||
char delimiter; /* hierarchy delimiter */
|
char *delimiter; /* hierarchy delimiter */
|
||||||
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
|
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
|
||||||
message_t **msgapp; /* FETCH results */
|
message_t **msgapp; /* FETCH results */
|
||||||
unsigned caps; /* CAPABILITY results */
|
unsigned caps; /* CAPABILITY results */
|
||||||
|
@ -913,13 +913,29 @@ parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd )
|
||||||
free_list( list );
|
free_list( list );
|
||||||
arg = next_arg( &cmd );
|
arg = next_arg( &cmd );
|
||||||
if (!ctx->delimiter)
|
if (!ctx->delimiter)
|
||||||
ctx->delimiter = *arg;
|
ctx->delimiter = nfstrdup( arg );
|
||||||
return parse_list( ctx, cmd, parse_list_rsp_p2 );
|
return parse_list( ctx, cmd, parse_list_rsp_p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_inbox( imap_store_t *ctx, const char *arg )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
if (memcmp( arg, "INBOX", 5 ))
|
||||||
|
return 0;
|
||||||
|
if (arg[5])
|
||||||
|
for (i = 0; (c = ctx->delimiter[i]); i++)
|
||||||
|
if (arg[i + 5] != c)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
|
parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
|
||||||
{
|
{
|
||||||
|
string_list_t *narg;
|
||||||
char *arg;
|
char *arg;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
|
@ -929,12 +945,12 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
|
||||||
return LIST_BAD;
|
return LIST_BAD;
|
||||||
}
|
}
|
||||||
arg = list->val;
|
arg = list->val;
|
||||||
if (memcmp( arg, "INBOX", 5 ) || (arg[5] && arg[5] != ctx->delimiter)) {
|
if (!is_inbox( ctx, arg )) {
|
||||||
l = strlen( ctx->gen.conf->path );
|
l = strlen( ctx->gen.conf->path );
|
||||||
if (memcmp( arg, ctx->gen.conf->path, l ))
|
if (memcmp( arg, ctx->gen.conf->path, l ))
|
||||||
goto skip;
|
goto skip;
|
||||||
arg += l;
|
arg += l;
|
||||||
if (!memcmp( arg, "INBOX", 5 ) && (!arg[5] || arg[5] == ctx->delimiter)) {
|
if (is_inbox( ctx, arg )) {
|
||||||
if (!arg[5])
|
if (!arg[5])
|
||||||
warn( "IMAP warning: ignoring INBOX in %s\n", ctx->gen.conf->path );
|
warn( "IMAP warning: ignoring INBOX in %s\n", ctx->gen.conf->path );
|
||||||
goto skip;
|
goto skip;
|
||||||
|
@ -942,36 +958,37 @@ parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED )
|
||||||
}
|
}
|
||||||
if (!memcmp( arg + strlen( arg ) - 5, ".lock", 5 )) /* workaround broken servers */
|
if (!memcmp( arg + strlen( arg ) - 5, ".lock", 5 )) /* workaround broken servers */
|
||||||
goto skip;
|
goto skip;
|
||||||
if (map_name( arg, ctx->delimiter, '/') < 0) {
|
if (map_name( arg, (char **)&narg, offsetof(string_list_t, string), ctx->delimiter, "/") < 0) {
|
||||||
warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg );
|
warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg );
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
add_string_list( &ctx->gen.boxes, arg );
|
narg->next = ctx->gen.boxes;
|
||||||
|
ctx->gen.boxes = narg;
|
||||||
skip:
|
skip:
|
||||||
free_list( list );
|
free_list( list );
|
||||||
return LIST_OK;
|
return LIST_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_name( char *buf, const imap_store_t *ctx, const char *prefix, const char *name )
|
prepare_name( char **buf, const imap_store_t *ctx, const char *prefix, const char *name )
|
||||||
{
|
{
|
||||||
int pl;
|
int pl = strlen( prefix );
|
||||||
|
|
||||||
nfsnprintf( buf, 1024, "%s%n%s", prefix, &pl, name );
|
switch (map_name( name, buf, pl, "/", ctx->delimiter )) {
|
||||||
switch (map_name( buf + pl, '/', ctx->delimiter )) {
|
|
||||||
case -1:
|
case -1:
|
||||||
error( "IMAP error: mailbox name %s contains server's hierarchy delimiter\n", buf + pl );
|
error( "IMAP error: mailbox name %s contains server's hierarchy delimiter\n", name );
|
||||||
return -1;
|
return -1;
|
||||||
case -2:
|
case -2:
|
||||||
error( "IMAP error: server's hierarchy delimiter not known\n" );
|
error( "IMAP error: server's hierarchy delimiter not known\n" );
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
|
memcpy( *buf, prefix, pl );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_box( char *buf, const imap_store_t *ctx )
|
prepare_box( char **buf, const imap_store_t *ctx )
|
||||||
{
|
{
|
||||||
const char *name = ctx->gen.name;
|
const char *name = ctx->gen.name;
|
||||||
|
|
||||||
|
@ -980,7 +997,7 @@ prepare_box( char *buf, const imap_store_t *ctx )
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
prepare_trash( char *buf, const imap_store_t *ctx )
|
prepare_trash( char **buf, const imap_store_t *ctx )
|
||||||
{
|
{
|
||||||
return prepare_name( buf, ctx, ctx->prefix, ctx->gen.conf->trash );
|
return prepare_name( buf, ctx, ctx->prefix, ctx->gen.conf->trash );
|
||||||
}
|
}
|
||||||
|
@ -1183,6 +1200,7 @@ imap_cancel_store( store_t *gctx )
|
||||||
free_list( ctx->ns_personal );
|
free_list( ctx->ns_personal );
|
||||||
free_list( ctx->ns_other );
|
free_list( ctx->ns_other );
|
||||||
free_list( ctx->ns_shared );
|
free_list( ctx->ns_shared );
|
||||||
|
free( ctx->delimiter );
|
||||||
imap_deref( ctx );
|
imap_deref( ctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1330,6 +1348,7 @@ imap_open_store( store_conf_t *conf,
|
||||||
ctx->gen.boxes = 0;
|
ctx->gen.boxes = 0;
|
||||||
ctx->gen.listed = 0;
|
ctx->gen.listed = 0;
|
||||||
ctx->gen.conf = conf;
|
ctx->gen.conf = conf;
|
||||||
|
free( ctx->delimiter );
|
||||||
ctx->delimiter = 0;
|
ctx->delimiter = 0;
|
||||||
ctx->callbacks.imap_open = cb;
|
ctx->callbacks.imap_open = cb;
|
||||||
ctx->callback_aux = aux;
|
ctx->callback_aux = aux;
|
||||||
|
@ -1570,7 +1589,7 @@ imap_open_store_namespace( imap_store_t *ctx )
|
||||||
imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
|
imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf;
|
||||||
|
|
||||||
ctx->prefix = cfg->gen.path;
|
ctx->prefix = cfg->gen.path;
|
||||||
ctx->delimiter = cfg->delimiter;
|
ctx->delimiter = cfg->delimiter ? nfstrdup( cfg->delimiter ) : 0;
|
||||||
if (((!*ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) {
|
if (((!*ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) {
|
||||||
/* get NAMESPACE info */
|
/* get NAMESPACE info */
|
||||||
if (!ctx->got_namespace)
|
if (!ctx->got_namespace)
|
||||||
|
@ -1608,7 +1627,7 @@ imap_open_store_namespace2( imap_store_t *ctx )
|
||||||
if (!*ctx->prefix && cfg->use_namespace)
|
if (!*ctx->prefix && cfg->use_namespace)
|
||||||
ctx->prefix = nsp_1st_ns->val;
|
ctx->prefix = nsp_1st_ns->val;
|
||||||
if (!ctx->delimiter)
|
if (!ctx->delimiter)
|
||||||
ctx->delimiter = *nsp_1st_dl->val;
|
ctx->delimiter = nfstrdup( nsp_1st_dl->val );
|
||||||
}
|
}
|
||||||
imap_open_store_finalize( ctx );
|
imap_open_store_finalize( ctx );
|
||||||
}
|
}
|
||||||
|
@ -1656,12 +1675,12 @@ imap_select( store_t *gctx, int create,
|
||||||
{
|
{
|
||||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||||
struct imap_cmd_simple *cmd;
|
struct imap_cmd_simple *cmd;
|
||||||
char buf[1024];
|
char *buf;
|
||||||
|
|
||||||
free_generic_messages( gctx->msgs );
|
free_generic_messages( gctx->msgs );
|
||||||
gctx->msgs = 0;
|
gctx->msgs = 0;
|
||||||
|
|
||||||
if (prepare_box( buf, ctx ) < 0) {
|
if (prepare_box( &buf, ctx ) < 0) {
|
||||||
cb( DRV_BOX_BAD, aux );
|
cb( DRV_BOX_BAD, aux );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1673,6 +1692,7 @@ imap_select( store_t *gctx, int create,
|
||||||
cmd->gen.param.trycreate = 1;
|
cmd->gen.param.trycreate = 1;
|
||||||
imap_exec( ctx, &cmd->gen, imap_done_simple_box,
|
imap_exec( ctx, &cmd->gen, imap_done_simple_box,
|
||||||
"SELECT \"%s\"", buf );
|
"SELECT \"%s\"", buf );
|
||||||
|
free( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************* imap_load *******************/
|
/******************* imap_load *******************/
|
||||||
|
@ -1878,17 +1898,18 @@ imap_trash_msg( store_t *gctx, message_t *msg,
|
||||||
{
|
{
|
||||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||||
struct imap_cmd_simple *cmd;
|
struct imap_cmd_simple *cmd;
|
||||||
char buf[1024];
|
char *buf;
|
||||||
|
|
||||||
INIT_IMAP_CMD(imap_cmd_simple, cmd, cb, aux)
|
INIT_IMAP_CMD(imap_cmd_simple, cmd, cb, aux)
|
||||||
cmd->gen.param.create = 1;
|
cmd->gen.param.create = 1;
|
||||||
cmd->gen.param.to_trash = 1;
|
cmd->gen.param.to_trash = 1;
|
||||||
if (prepare_trash( buf, ctx ) < 0) {
|
if (prepare_trash( &buf, ctx ) < 0) {
|
||||||
cb( DRV_BOX_BAD, aux );
|
cb( DRV_BOX_BAD, aux );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
imap_exec( ctx, &cmd->gen, imap_done_simple_msg,
|
imap_exec( ctx, &cmd->gen, imap_done_simple_msg,
|
||||||
"UID COPY %d \"%s\"", msg->uid, buf );
|
"UID COPY %d \"%s\"", msg->uid, buf );
|
||||||
|
free( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************* imap_store_msg *******************/
|
/******************* imap_store_msg *******************/
|
||||||
|
@ -1901,8 +1922,9 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||||
{
|
{
|
||||||
imap_store_t *ctx = (imap_store_t *)gctx;
|
imap_store_t *ctx = (imap_store_t *)gctx;
|
||||||
struct imap_cmd_out_uid *cmd;
|
struct imap_cmd_out_uid *cmd;
|
||||||
|
char *buf;
|
||||||
int d;
|
int d;
|
||||||
char flagstr[128], datestr[64], buf[1024];
|
char flagstr[128], datestr[64];
|
||||||
|
|
||||||
d = 0;
|
d = 0;
|
||||||
if (data->flags) {
|
if (data->flags) {
|
||||||
|
@ -1919,12 +1941,12 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||||
if (to_trash) {
|
if (to_trash) {
|
||||||
cmd->gen.param.create = 1;
|
cmd->gen.param.create = 1;
|
||||||
cmd->gen.param.to_trash = 1;
|
cmd->gen.param.to_trash = 1;
|
||||||
if (prepare_trash( buf, ctx ) < 0) {
|
if (prepare_trash( &buf, ctx ) < 0) {
|
||||||
cb( DRV_BOX_BAD, -1, aux );
|
cb( DRV_BOX_BAD, -1, aux );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (prepare_box( buf, ctx ) < 0) {
|
if (prepare_box( &buf, ctx ) < 0) {
|
||||||
cb( DRV_BOX_BAD, -1, aux );
|
cb( DRV_BOX_BAD, -1, aux );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1945,6 +1967,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
|
||||||
imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
|
imap_exec( ctx, &cmd->gen, imap_store_msg_p2,
|
||||||
"APPEND \"%s\" %s", buf, flagstr );
|
"APPEND \"%s\" %s", buf, flagstr );
|
||||||
}
|
}
|
||||||
|
free( buf );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2143,7 +2166,7 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
else if (!strcasecmp( "Path", cfg->cmd ))
|
else if (!strcasecmp( "Path", cfg->cmd ))
|
||||||
store->gen.path = nfstrdup( cfg->val );
|
store->gen.path = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "PathDelimiter", cfg->cmd ))
|
else if (!strcasecmp( "PathDelimiter", cfg->cmd ))
|
||||||
store->delimiter = *cfg->val;
|
store->delimiter = nfstrdup( cfg->val );
|
||||||
else
|
else
|
||||||
parse_generic_store( &store->gen, cfg );
|
parse_generic_store( &store->gen, cfg );
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -142,11 +142,11 @@ typedef struct store_conf {
|
||||||
char *name;
|
char *name;
|
||||||
driver_t *driver;
|
driver_t *driver;
|
||||||
const char *path; /* should this be here? its interpretation is driver-specific */
|
const char *path; /* should this be here? its interpretation is driver-specific */
|
||||||
|
const char *flat_delim;
|
||||||
const char *map_inbox;
|
const char *map_inbox;
|
||||||
const char *trash;
|
const char *trash;
|
||||||
unsigned max_size; /* off_t is overkill */
|
unsigned max_size; /* off_t is overkill */
|
||||||
unsigned trash_remote_new:1, trash_only_new:1;
|
unsigned trash_remote_new:1, trash_only_new:1;
|
||||||
char flat_delim;
|
|
||||||
} store_conf_t;
|
} store_conf_t;
|
||||||
|
|
||||||
typedef struct string_list {
|
typedef struct string_list {
|
||||||
|
@ -440,7 +440,7 @@ void ATTR_NORETURN oob( void );
|
||||||
|
|
||||||
char *expand_strdup( const char *s );
|
char *expand_strdup( const char *s );
|
||||||
|
|
||||||
int map_name( char *arg, char in, char out );
|
int map_name(const char *arg, char **result, int reserve, const char *in, const char *out );
|
||||||
|
|
||||||
void sort_ints( int *arr, int len );
|
void sort_ints( int *arr, int len );
|
||||||
|
|
||||||
|
|
13
src/main.c
13
src/main.c
|
@ -744,7 +744,7 @@ static void
|
||||||
store_listed( int sts, void *aux )
|
store_listed( int sts, void *aux )
|
||||||
{
|
{
|
||||||
MVARS(aux)
|
MVARS(aux)
|
||||||
string_list_t *box;
|
string_list_t **box;
|
||||||
|
|
||||||
switch (sts) {
|
switch (sts) {
|
||||||
case DRV_CANCELED:
|
case DRV_CANCELED:
|
||||||
|
@ -752,10 +752,15 @@ store_listed( int sts, void *aux )
|
||||||
case DRV_OK:
|
case DRV_OK:
|
||||||
mvars->ctx[t]->listed = 1;
|
mvars->ctx[t]->listed = 1;
|
||||||
if (mvars->ctx[t]->conf->flat_delim) {
|
if (mvars->ctx[t]->conf->flat_delim) {
|
||||||
for (box = mvars->ctx[t]->boxes; box; box = box->next) {
|
for (box = &mvars->ctx[t]->boxes; *box; box = &(*box)->next) {
|
||||||
if (map_name( box->string, mvars->ctx[t]->conf->flat_delim, '/' ) < 0) {
|
string_list_t *nbox;
|
||||||
error( "Error: flattened mailbox name '%s' contains canonical hierarchy delimiter\n", box->string );
|
if (map_name( (*box)->string, (char **)&nbox, offsetof(string_list_t, string), mvars->ctx[t]->conf->flat_delim, "/" ) < 0) {
|
||||||
|
error( "Error: flattened mailbox name '%s' contains canonical hierarchy delimiter\n", (*box)->string );
|
||||||
mvars->ret = mvars->skip = 1;
|
mvars->ret = mvars->skip = 1;
|
||||||
|
} else {
|
||||||
|
nbox->next = (*box)->next;
|
||||||
|
free( *box );
|
||||||
|
*box = nbox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
\" As a special exception, mbsync may be linked with the OpenSSL library,
|
\" As a special exception, mbsync may be linked with the OpenSSL library,
|
||||||
\" despite that library's more restrictive license.
|
\" despite that library's more restrictive license.
|
||||||
..
|
..
|
||||||
.TH mbsync 1 "2013 Apr 20"
|
.TH mbsync 1 "2013 Aug 3"
|
||||||
..
|
..
|
||||||
.SH NAME
|
.SH NAME
|
||||||
mbsync - synchronize IMAP4 and Maildir mailboxes
|
mbsync - synchronize IMAP4 and Maildir mailboxes
|
||||||
|
@ -352,7 +352,7 @@ This option is meaningless if a \fBPath\fR was specified.
|
||||||
..
|
..
|
||||||
.TP
|
.TP
|
||||||
\fBPathDelimiter\fR \fIdelim\fR
|
\fBPathDelimiter\fR \fIdelim\fR
|
||||||
Specify the server's hierarchy delimiter character.
|
Specify the server's hierarchy delimiter.
|
||||||
(Default: taken from the server's first "personal" NAMESPACE)
|
(Default: taken from the server's first "personal" NAMESPACE)
|
||||||
.br
|
.br
|
||||||
Do \fBNOT\fR abuse this to re-interpret the hierarchy.
|
Do \fBNOT\fR abuse this to re-interpret the hierarchy.
|
||||||
|
|
|
@ -618,8 +618,9 @@ sync_boxes( store_t *ctx[], const char *names[], channel_conf_t *chan,
|
||||||
ctx[t]->orig_name =
|
ctx[t]->orig_name =
|
||||||
(!names[t] || (ctx[t]->conf->map_inbox && !strcmp( ctx[t]->conf->map_inbox, names[t] ))) ?
|
(!names[t] || (ctx[t]->conf->map_inbox && !strcmp( ctx[t]->conf->map_inbox, names[t] ))) ?
|
||||||
"INBOX" : names[t];
|
"INBOX" : names[t];
|
||||||
ctx[t]->name = nfstrdup( ctx[t]->orig_name );
|
if (!ctx[t]->conf->flat_delim) {
|
||||||
if (ctx[t]->conf->flat_delim && map_name( ctx[t]->name, '/', ctx[t]->conf->flat_delim ) < 0) {
|
ctx[t]->name = nfstrdup( ctx[t]->orig_name );
|
||||||
|
} else if (map_name( ctx[t]->orig_name, &ctx[t]->name, 0, "/", ctx[t]->conf->flat_delim ) < 0) {
|
||||||
error( "Error: canonical mailbox name '%s' contains flattened hierarchy delimiter\n", ctx[t]->name );
|
error( "Error: canonical mailbox name '%s' contains flattened hierarchy delimiter\n", ctx[t]->name );
|
||||||
svars->ret = SYNC_FAIL;
|
svars->ret = SYNC_FAIL;
|
||||||
sync_bail3( svars );
|
sync_bail3( svars );
|
||||||
|
|
61
src/util.c
61
src/util.c
|
@ -361,24 +361,59 @@ expand_strdup( const char *s )
|
||||||
|
|
||||||
/* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */
|
/* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */
|
||||||
int
|
int
|
||||||
map_name( char *arg, char in, char out )
|
map_name( const char *arg, char **result, int reserve, const char *in, const char *out )
|
||||||
{
|
{
|
||||||
int l, k;
|
char *p;
|
||||||
|
int i, l, ll, num, inl, outl;
|
||||||
|
|
||||||
if (!in || in == out)
|
l = strlen( arg );
|
||||||
|
if (!in) {
|
||||||
|
copy:
|
||||||
|
*result = nfmalloc( reserve + l + 1 );
|
||||||
|
memcpy( *result + reserve, arg, l + 1 );
|
||||||
return 0;
|
return 0;
|
||||||
for (l = 0; arg[l]; l++)
|
}
|
||||||
if (arg[l] == in) {
|
inl = strlen( in );
|
||||||
if (!out)
|
if (out) {
|
||||||
return -2;
|
outl = strlen( out );
|
||||||
arg[l] = out;
|
if (inl == outl && !memcmp( in, out, inl ))
|
||||||
} else if (arg[l] == out) {
|
goto copy;
|
||||||
/* restore original name for printing error message */
|
}
|
||||||
for (k = 0; k < l; k++)
|
for (num = 0, i = 0; i < l; ) {
|
||||||
if (arg[k] == out)
|
for (ll = 0; ll < inl; ll++)
|
||||||
arg[k] = in;
|
if (arg[i + ll] != in[ll])
|
||||||
|
goto fout;
|
||||||
|
num++;
|
||||||
|
i += inl;
|
||||||
|
continue;
|
||||||
|
fout:
|
||||||
|
if (out) {
|
||||||
|
for (ll = 0; ll < outl; ll++)
|
||||||
|
if (arg[i + ll] != out[ll])
|
||||||
|
goto fnexti;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
fnexti:
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (!num)
|
||||||
|
goto copy;
|
||||||
|
if (!out)
|
||||||
|
return -2;
|
||||||
|
*result = nfmalloc( reserve + l + num * (outl - inl) + 1 );
|
||||||
|
p = *result + reserve;
|
||||||
|
for (i = 0; i < l; ) {
|
||||||
|
for (ll = 0; ll < inl; ll++)
|
||||||
|
if (arg[i + ll] != in[ll])
|
||||||
|
goto rnexti;
|
||||||
|
memcpy( p, out, outl );
|
||||||
|
p += outl;
|
||||||
|
i += inl;
|
||||||
|
continue;
|
||||||
|
rnexti:
|
||||||
|
*p++ = arg[i++];
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user