coding style: add "superfluous" braces
- wrap flow-controlled statements that contain blocks into blocks themselves - wrap bodies of do-while()s into blocks - use braces on 'else' symmetrically (this obviously has a cascading effect, so this patch touches lots of lines) - attach braces unavoidably, the rules are sometimes broken around #ifdef-ery.
This commit is contained in:
parent
156e9c5058
commit
0f2220634d
112
src/config.c
112
src/config.c
|
@ -46,14 +46,15 @@ get_arg( conffile_t *cfile, int required, int *comment )
|
||||||
if (escaped && c >= 32) {
|
if (escaped && c >= 32) {
|
||||||
escaped = 0;
|
escaped = 0;
|
||||||
*t++ = c;
|
*t++ = c;
|
||||||
} else if (c == '\\')
|
} else if (c == '\\') {
|
||||||
escaped = 1;
|
escaped = 1;
|
||||||
else if (c == '"')
|
} else if (c == '"') {
|
||||||
quoted ^= 1;
|
quoted ^= 1;
|
||||||
else if (!quoted && isspace( (uchar)c ))
|
} else if (!quoted && isspace( (uchar)c )) {
|
||||||
break;
|
break;
|
||||||
else
|
} else {
|
||||||
*t++ = c;
|
*t++ = c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*t = 0;
|
*t = 0;
|
||||||
if (escaped) {
|
if (escaped) {
|
||||||
|
@ -145,53 +146,53 @@ getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf )
|
||||||
|
|
||||||
if (!strcasecmp( "Sync", cfile->cmd )) {
|
if (!strcasecmp( "Sync", cfile->cmd )) {
|
||||||
arg = cfile->val;
|
arg = cfile->val;
|
||||||
do
|
do {
|
||||||
if (!strcasecmp( "Push", arg ))
|
if (!strcasecmp( "Push", arg )) {
|
||||||
*cops |= XOP_PUSH;
|
*cops |= XOP_PUSH;
|
||||||
else if (!strcasecmp( "Pull", arg ))
|
} else if (!strcasecmp( "Pull", arg )) {
|
||||||
*cops |= XOP_PULL;
|
*cops |= XOP_PULL;
|
||||||
else if (!strcasecmp( "ReNew", arg ))
|
} else if (!strcasecmp( "ReNew", arg )) {
|
||||||
*cops |= OP_RENEW;
|
*cops |= OP_RENEW;
|
||||||
else if (!strcasecmp( "New", arg ))
|
} else if (!strcasecmp( "New", arg )) {
|
||||||
*cops |= OP_NEW;
|
*cops |= OP_NEW;
|
||||||
else if (!strcasecmp( "Delete", arg ))
|
} else if (!strcasecmp( "Delete", arg )) {
|
||||||
*cops |= OP_DELETE;
|
*cops |= OP_DELETE;
|
||||||
else if (!strcasecmp( "Flags", arg ))
|
} else if (!strcasecmp( "Flags", arg )) {
|
||||||
*cops |= OP_FLAGS;
|
*cops |= OP_FLAGS;
|
||||||
else if (!strcasecmp( "PullReNew", arg ))
|
} else if (!strcasecmp( "PullReNew", arg )) {
|
||||||
conf->ops[N] |= OP_RENEW;
|
conf->ops[N] |= OP_RENEW;
|
||||||
else if (!strcasecmp( "PullNew", arg ))
|
} else if (!strcasecmp( "PullNew", arg )) {
|
||||||
conf->ops[N] |= OP_NEW;
|
conf->ops[N] |= OP_NEW;
|
||||||
else if (!strcasecmp( "PullDelete", arg ))
|
} else if (!strcasecmp( "PullDelete", arg )) {
|
||||||
conf->ops[N] |= OP_DELETE;
|
conf->ops[N] |= OP_DELETE;
|
||||||
else if (!strcasecmp( "PullFlags", arg ))
|
} else if (!strcasecmp( "PullFlags", arg )) {
|
||||||
conf->ops[N] |= OP_FLAGS;
|
conf->ops[N] |= OP_FLAGS;
|
||||||
else if (!strcasecmp( "PushReNew", arg ))
|
} else if (!strcasecmp( "PushReNew", arg )) {
|
||||||
conf->ops[F] |= OP_RENEW;
|
conf->ops[F] |= OP_RENEW;
|
||||||
else if (!strcasecmp( "PushNew", arg ))
|
} else if (!strcasecmp( "PushNew", arg )) {
|
||||||
conf->ops[F] |= OP_NEW;
|
conf->ops[F] |= OP_NEW;
|
||||||
else if (!strcasecmp( "PushDelete", arg ))
|
} else if (!strcasecmp( "PushDelete", arg )) {
|
||||||
conf->ops[F] |= OP_DELETE;
|
conf->ops[F] |= OP_DELETE;
|
||||||
else if (!strcasecmp( "PushFlags", arg ))
|
} else if (!strcasecmp( "PushFlags", arg )) {
|
||||||
conf->ops[F] |= OP_FLAGS;
|
conf->ops[F] |= OP_FLAGS;
|
||||||
else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg ))
|
} else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg )) {
|
||||||
*cops |= XOP_PULL|XOP_PUSH;
|
*cops |= XOP_PULL|XOP_PUSH;
|
||||||
else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) {
|
} else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) {
|
||||||
error( "%s:%d: invalid Sync arg '%s'\n",
|
error( "%s:%d: invalid Sync arg '%s'\n",
|
||||||
cfile->file, cfile->line, arg );
|
cfile->file, cfile->line, arg );
|
||||||
cfile->err = 1;
|
cfile->err = 1;
|
||||||
}
|
}
|
||||||
while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
|
} while ((arg = get_arg( cfile, ARG_OPTIONAL, NULL )));
|
||||||
conf->ops[F] |= XOP_HAVE_TYPE;
|
conf->ops[F] |= XOP_HAVE_TYPE;
|
||||||
} else if (!strcasecmp( "SyncState", cfile->cmd ))
|
} else if (!strcasecmp( "SyncState", cfile->cmd )) {
|
||||||
conf->sync_state = expand_strdup( cfile->val );
|
conf->sync_state = expand_strdup( cfile->val );
|
||||||
else if (!strcasecmp( "CopyArrivalDate", cfile->cmd ))
|
} else if (!strcasecmp( "CopyArrivalDate", cfile->cmd )) {
|
||||||
conf->use_internal_date = parse_bool( cfile );
|
conf->use_internal_date = parse_bool( cfile );
|
||||||
else if (!strcasecmp( "MaxMessages", cfile->cmd ))
|
} else if (!strcasecmp( "MaxMessages", cfile->cmd )) {
|
||||||
conf->max_messages = parse_int( cfile );
|
conf->max_messages = parse_int( cfile );
|
||||||
else if (!strcasecmp( "ExpireUnread", cfile->cmd ))
|
} else if (!strcasecmp( "ExpireUnread", cfile->cmd )) {
|
||||||
conf->expire_unread = parse_bool( cfile );
|
conf->expire_unread = parse_bool( cfile );
|
||||||
else {
|
} else {
|
||||||
for (i = 0; i < as(boxOps); i++) {
|
for (i = 0; i < as(boxOps); i++) {
|
||||||
if (!strcasecmp( boxOps[i].name, cfile->cmd )) {
|
if (!strcasecmp( boxOps[i].name, cfile->cmd )) {
|
||||||
int op = boxOps[i].op;
|
int op = boxOps[i].op;
|
||||||
|
@ -320,8 +321,9 @@ load_config( const char *where )
|
||||||
if (!where) {
|
if (!where) {
|
||||||
nfsnprintf( path, sizeof(path), "%s/." EXE "rc", Home );
|
nfsnprintf( path, sizeof(path), "%s/." EXE "rc", Home );
|
||||||
cfile.file = path;
|
cfile.file = path;
|
||||||
} else
|
} else {
|
||||||
cfile.file = where;
|
cfile.file = where;
|
||||||
|
}
|
||||||
|
|
||||||
info( "Reading configuration file %s\n", cfile.file );
|
info( "Reading configuration file %s\n", cfile.file );
|
||||||
|
|
||||||
|
@ -344,7 +346,7 @@ load_config( const char *where )
|
||||||
while (getcline( &cfile )) {
|
while (getcline( &cfile )) {
|
||||||
if (!cfile.cmd)
|
if (!cfile.cmd)
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < N_DRIVERS; i++)
|
for (i = 0; i < N_DRIVERS; i++) {
|
||||||
if (drivers[i]->parse_store( &cfile, &store )) {
|
if (drivers[i]->parse_store( &cfile, &store )) {
|
||||||
if (store) {
|
if (store) {
|
||||||
if (!store->max_size)
|
if (!store->max_size)
|
||||||
|
@ -358,8 +360,8 @@ load_config( const char *where )
|
||||||
glob_ok = 0;
|
glob_ok = 0;
|
||||||
goto reloop;
|
goto reloop;
|
||||||
}
|
}
|
||||||
if (!strcasecmp( "Channel", cfile.cmd ))
|
}
|
||||||
{
|
if (!strcasecmp( "Channel", cfile.cmd )) {
|
||||||
channel = nfcalloc( sizeof(*channel) );
|
channel = nfcalloc( sizeof(*channel) );
|
||||||
channel->name = nfstrdup( cfile.val );
|
channel->name = nfstrdup( cfile.val );
|
||||||
channel->max_messages = global_conf.max_messages;
|
channel->max_messages = global_conf.max_messages;
|
||||||
|
@ -368,17 +370,15 @@ load_config( const char *where )
|
||||||
cops = 0;
|
cops = 0;
|
||||||
max_size = UINT_MAX;
|
max_size = UINT_MAX;
|
||||||
while (getcline( &cfile ) && cfile.cmd) {
|
while (getcline( &cfile ) && cfile.cmd) {
|
||||||
if (!strcasecmp( "MaxSize", cfile.cmd ))
|
if (!strcasecmp( "MaxSize", cfile.cmd )) {
|
||||||
max_size = parse_size( &cfile );
|
max_size = parse_size( &cfile );
|
||||||
else if (!strcasecmp( "Pattern", cfile.cmd ) ||
|
} else if (!strcasecmp( "Pattern", cfile.cmd ) ||
|
||||||
!strcasecmp( "Patterns", cfile.cmd ))
|
!strcasecmp( "Patterns", cfile.cmd )) {
|
||||||
{
|
|
||||||
arg = cfile.val;
|
arg = cfile.val;
|
||||||
do
|
do {
|
||||||
add_string_list( &channel->patterns, arg );
|
add_string_list( &channel->patterns, arg );
|
||||||
while ((arg = get_arg( &cfile, ARG_OPTIONAL, NULL )));
|
} while ((arg = get_arg( &cfile, ARG_OPTIONAL, NULL )));
|
||||||
}
|
} else if (!strcasecmp( "Far", cfile.cmd )) {
|
||||||
else if (!strcasecmp( "Far", cfile.cmd )) {
|
|
||||||
fn = F;
|
fn = F;
|
||||||
goto linkst;
|
goto linkst;
|
||||||
} else if (!strcasecmp( "Master", cfile.cmd )) { // Pre-1.4 legacy
|
} else if (!strcasecmp( "Master", cfile.cmd )) { // Pre-1.4 legacy
|
||||||
|
@ -399,11 +399,12 @@ load_config( const char *where )
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*p = 0;
|
*p = 0;
|
||||||
for (store = stores; store; store = store->next)
|
for (store = stores; store; store = store->next) {
|
||||||
if (!strcmp( store->name, cfile.val + 1 )) {
|
if (!strcmp( store->name, cfile.val + 1 )) {
|
||||||
channel->stores[fn] = store;
|
channel->stores[fn] = store;
|
||||||
goto stpcom;
|
goto stpcom;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
error( "%s:%d: unknown store '%s'\n",
|
error( "%s:%d: unknown store '%s'\n",
|
||||||
cfile.file, cfile.line, cfile.val + 1 );
|
cfile.file, cfile.line, cfile.val + 1 );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
|
@ -423,9 +424,9 @@ load_config( const char *where )
|
||||||
} else if (!channel->stores[N]) {
|
} else if (!channel->stores[N]) {
|
||||||
error( "channel '%s' refers to no near side store\n", channel->name );
|
error( "channel '%s' refers to no near side store\n", channel->name );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
} else if (merge_ops( cops, channel->ops ))
|
} else if (merge_ops( cops, channel->ops )) {
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
else {
|
} else {
|
||||||
if (max_size != UINT_MAX) {
|
if (max_size != UINT_MAX) {
|
||||||
if (!max_size)
|
if (!max_size)
|
||||||
max_size = UINT_MAX;
|
max_size = UINT_MAX;
|
||||||
|
@ -436,9 +437,7 @@ load_config( const char *where )
|
||||||
}
|
}
|
||||||
glob_ok = 0;
|
glob_ok = 0;
|
||||||
goto reloop;
|
goto reloop;
|
||||||
}
|
} else if (!strcasecmp( "Group", cfile.cmd )) {
|
||||||
else if (!strcasecmp( "Group", cfile.cmd ))
|
|
||||||
{
|
|
||||||
group = nfmalloc( sizeof(*group) );
|
group = nfmalloc( sizeof(*group) );
|
||||||
group->name = nfstrdup( cfile.val );
|
group->name = nfstrdup( cfile.val );
|
||||||
*groupapp = group;
|
*groupapp = group;
|
||||||
|
@ -457,13 +456,10 @@ load_config( const char *where )
|
||||||
}
|
}
|
||||||
while (getcline( &cfile ) && cfile.cmd) {
|
while (getcline( &cfile ) && cfile.cmd) {
|
||||||
if (!strcasecmp( "Channel", cfile.cmd ) ||
|
if (!strcasecmp( "Channel", cfile.cmd ) ||
|
||||||
!strcasecmp( "Channels", cfile.cmd ))
|
!strcasecmp( "Channels", cfile.cmd )) {
|
||||||
{
|
|
||||||
arg = cfile.val;
|
arg = cfile.val;
|
||||||
goto addone;
|
goto addone;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
error( "%s:%d: keyword '%s' is not recognized in Group sections\n",
|
error( "%s:%d: keyword '%s' is not recognized in Group sections\n",
|
||||||
cfile.file, cfile.line, cfile.cmd );
|
cfile.file, cfile.line, cfile.cmd );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
|
@ -471,13 +467,9 @@ load_config( const char *where )
|
||||||
}
|
}
|
||||||
glob_ok = 0;
|
glob_ok = 0;
|
||||||
goto reloop;
|
goto reloop;
|
||||||
}
|
} else if (!strcasecmp( "FSync", cfile.cmd )) {
|
||||||
else if (!strcasecmp( "FSync", cfile.cmd ))
|
|
||||||
{
|
|
||||||
UseFSync = parse_bool( &cfile );
|
UseFSync = parse_bool( &cfile );
|
||||||
}
|
} else if (!strcasecmp( "FieldDelimiter", cfile.cmd )) {
|
||||||
else if (!strcasecmp( "FieldDelimiter", cfile.cmd ))
|
|
||||||
{
|
|
||||||
if (strlen( cfile.val ) != 1) {
|
if (strlen( cfile.val ) != 1) {
|
||||||
error( "%s:%d: Field delimiter must be exactly one character long\n", cfile.file, cfile.line );
|
error( "%s:%d: Field delimiter must be exactly one character long\n", cfile.file, cfile.line );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
|
@ -488,17 +480,13 @@ load_config( const char *where )
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (!strcasecmp( "BufferLimit", cfile.cmd )) {
|
||||||
else if (!strcasecmp( "BufferLimit", cfile.cmd ))
|
|
||||||
{
|
|
||||||
BufferLimit = parse_size( &cfile );
|
BufferLimit = parse_size( &cfile );
|
||||||
if (!BufferLimit) {
|
if (!BufferLimit) {
|
||||||
error( "%s:%d: BufferLimit cannot be zero\n", cfile.file, cfile.line );
|
error( "%s:%d: BufferLimit cannot be zero\n", cfile.file, cfile.line );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
}
|
}
|
||||||
}
|
} else if (!getopt_helper( &cfile, &gcops, &global_conf )) {
|
||||||
else if (!getopt_helper( &cfile, &gcops, &global_conf ))
|
|
||||||
{
|
|
||||||
error( "%s:%d: '%s' is not a recognized section-starting or global keyword\n",
|
error( "%s:%d: '%s' is not a recognized section-starting or global keyword\n",
|
||||||
cfile.file, cfile.line, cfile.cmd );
|
cfile.file, cfile.line, cfile.cmd );
|
||||||
cfile.err = 1;
|
cfile.err = 1;
|
||||||
|
|
|
@ -1628,13 +1628,13 @@ imap_socket_read( void *aux )
|
||||||
resp = parse_list( ctx, cmd, parse_namespace_rsp );
|
resp = parse_list( ctx, cmd, parse_namespace_rsp );
|
||||||
goto listret;
|
goto listret;
|
||||||
} else if ((arg1 = next_arg( &cmd ))) {
|
} else if ((arg1 = next_arg( &cmd ))) {
|
||||||
if (!strcmp( "EXISTS", arg1 ))
|
if (!strcmp( "EXISTS", arg1 )) {
|
||||||
ctx->total_msgs = atoi( arg );
|
ctx->total_msgs = atoi( arg );
|
||||||
else if (!strcmp( "EXPUNGE", arg1 ))
|
} else if (!strcmp( "EXPUNGE", arg1 )) {
|
||||||
ctx->total_msgs--;
|
ctx->total_msgs--;
|
||||||
else if (!strcmp( "RECENT", arg1 ))
|
} else if (!strcmp( "RECENT", arg1 )) {
|
||||||
ctx->recent_msgs = atoi( arg );
|
ctx->recent_msgs = atoi( arg );
|
||||||
else if(!strcmp ( "FETCH", arg1 )) {
|
} else if (!strcmp( "FETCH", arg1 )) {
|
||||||
resp = parse_list( ctx, cmd, parse_fetch_rsp );
|
resp = parse_list( ctx, cmd, parse_fetch_rsp );
|
||||||
goto listret;
|
goto listret;
|
||||||
}
|
}
|
||||||
|
@ -1714,8 +1714,9 @@ imap_socket_read( void *aux )
|
||||||
resp = RESP_NO;
|
resp = RESP_NO;
|
||||||
if (cmdp->param.failok) // SELECT
|
if (cmdp->param.failok) // SELECT
|
||||||
goto doresp;
|
goto doresp;
|
||||||
} else /*if (!strcmp( "BAD", arg ))*/
|
} else /*if (!strcmp( "BAD", arg ))*/ {
|
||||||
resp = RESP_CANCEL;
|
resp = RESP_CANCEL;
|
||||||
|
}
|
||||||
error( "IMAP command '%s' returned an error: %s %s\n",
|
error( "IMAP command '%s' returned an error: %s %s\n",
|
||||||
starts_with( cmdp->cmd, -1, "LOGIN", 5 ) ?
|
starts_with( cmdp->cmd, -1, "LOGIN", 5 ) ?
|
||||||
"LOGIN <user> <pass>" :
|
"LOGIN <user> <pass>" :
|
||||||
|
@ -1824,11 +1825,12 @@ imap_cancel_unowned( void *gctx )
|
||||||
{
|
{
|
||||||
imap_store_t *store, **storep;
|
imap_store_t *store, **storep;
|
||||||
|
|
||||||
for (storep = &unowned; (store = *storep); storep = &store->next)
|
for (storep = &unowned; (store = *storep); storep = &store->next) {
|
||||||
if (store == gctx) {
|
if (store == gctx) {
|
||||||
*storep = store->next;
|
*storep = store->next;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
imap_cancel_store( gctx );
|
imap_cancel_store( gctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1917,14 +1919,15 @@ imap_alloc_store( store_conf_t *conf, const char *label )
|
||||||
imap_store_t *ctx, **ctxp;
|
imap_store_t *ctx, **ctxp;
|
||||||
|
|
||||||
/* First try to recycle a whole store. */
|
/* First try to recycle a whole store. */
|
||||||
for (ctxp = &unowned; (ctx = *ctxp); ctxp = &ctx->next)
|
for (ctxp = &unowned; (ctx = *ctxp); ctxp = &ctx->next) {
|
||||||
if (ctx->state == SST_GOOD && ctx->conf == cfg) {
|
if (ctx->state == SST_GOOD && ctx->conf == cfg) {
|
||||||
*ctxp = ctx->next;
|
*ctxp = ctx->next;
|
||||||
goto gotstore;
|
goto gotstore;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Then try to recycle a server connection. */
|
/* Then try to recycle a server connection. */
|
||||||
for (ctxp = &unowned; (ctx = *ctxp); ctxp = &ctx->next)
|
for (ctxp = &unowned; (ctx = *ctxp); ctxp = &ctx->next) {
|
||||||
if (ctx->conf->server == srvc) {
|
if (ctx->conf->server == srvc) {
|
||||||
*ctxp = ctx->next;
|
*ctxp = ctx->next;
|
||||||
free_string_list( ctx->boxes );
|
free_string_list( ctx->boxes );
|
||||||
|
@ -1935,6 +1938,7 @@ imap_alloc_store( store_conf_t *conf, const char *label )
|
||||||
ctx->state = SST_HALF;
|
ctx->state = SST_HALF;
|
||||||
goto gotsrv;
|
goto gotsrv;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Finally, schedule opening a new server connection. */
|
/* Finally, schedule opening a new server connection. */
|
||||||
ctx = nfcalloc( sizeof(*ctx) );
|
ctx = nfcalloc( sizeof(*ctx) );
|
||||||
|
@ -3039,12 +3043,13 @@ imap_make_flags( int flags, char *buf )
|
||||||
const char *s;
|
const char *s;
|
||||||
uint i, d;
|
uint i, d;
|
||||||
|
|
||||||
for (i = d = 0; i < as(Flags); i++)
|
for (i = d = 0; i < as(Flags); i++) {
|
||||||
if (flags & (1 << i)) {
|
if (flags & (1 << i)) {
|
||||||
buf[d++] = ' ';
|
buf[d++] = ' ';
|
||||||
for (s = Flags[i]; *s; s++)
|
for (s = Flags[i]; *s; s++)
|
||||||
buf[d++] = *s;
|
buf[d++] = *s;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
buf[0] = '(';
|
buf[0] = '(';
|
||||||
buf[d++] = ')';
|
buf[d++] = ')';
|
||||||
return d;
|
return d;
|
||||||
|
@ -3521,8 +3526,9 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
memset( &sserver, 0, sizeof(sserver) );
|
memset( &sserver, 0, sizeof(sserver) );
|
||||||
server = &sserver;
|
server = &sserver;
|
||||||
type = "IMAP store";
|
type = "IMAP store";
|
||||||
} else
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
server->sconf.timeout = 20;
|
server->sconf.timeout = 20;
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
|
@ -3536,35 +3542,34 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
if (!strcasecmp( "Host", cfg->cmd )) {
|
if (!strcasecmp( "Host", cfg->cmd )) {
|
||||||
/* The imap[s]: syntax is just a backwards compat hack. */
|
/* The imap[s]: syntax is just a backwards compat hack. */
|
||||||
arg = cfg->val;
|
arg = cfg->val;
|
||||||
|
if (starts_with( arg, -1, "imap:", 5 ))
|
||||||
|
arg += 5;
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
if (starts_with( arg, -1, "imaps:", 6 )) {
|
else if (starts_with( arg, -1, "imaps:", 6 )) {
|
||||||
arg += 6;
|
arg += 6;
|
||||||
server->ssl_type = SSL_IMAPS;
|
server->ssl_type = SSL_IMAPS;
|
||||||
if (server->sconf.ssl_versions == -1)
|
if (server->sconf.ssl_versions == -1)
|
||||||
server->sconf.ssl_versions = TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3;
|
server->sconf.ssl_versions = TLSv1 | TLSv1_1 | TLSv1_2 | TLSv1_3;
|
||||||
} else
|
}
|
||||||
#endif
|
#endif
|
||||||
if (starts_with( arg, -1, "imap:", 5 ))
|
|
||||||
arg += 5;
|
|
||||||
if (starts_with( arg, -1, "//", 2 ))
|
if (starts_with( arg, -1, "//", 2 ))
|
||||||
arg += 2;
|
arg += 2;
|
||||||
if (arg != cfg->val)
|
if (arg != cfg->val)
|
||||||
warn( "%s:%d: Notice: URL notation is deprecated; use a plain host name and possibly 'SSLType IMAPS' instead\n", cfg->file, cfg->line );
|
warn( "%s:%d: Notice: URL notation is deprecated; use a plain host name and possibly 'SSLType IMAPS' instead\n", cfg->file, cfg->line );
|
||||||
server->sconf.host = nfstrdup( arg );
|
server->sconf.host = nfstrdup( arg );
|
||||||
}
|
} else if (!strcasecmp( "User", cfg->cmd )) {
|
||||||
else if (!strcasecmp( "User", cfg->cmd ))
|
|
||||||
server->user = nfstrdup( cfg->val );
|
server->user = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "UserCmd", cfg->cmd ))
|
} else if (!strcasecmp( "UserCmd", cfg->cmd )) {
|
||||||
server->user_cmd = nfstrdup( cfg->val );
|
server->user_cmd = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "Pass", cfg->cmd ))
|
} else if (!strcasecmp( "Pass", cfg->cmd )) {
|
||||||
server->pass = nfstrdup( cfg->val );
|
server->pass = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "PassCmd", cfg->cmd ))
|
} else if (!strcasecmp( "PassCmd", cfg->cmd )) {
|
||||||
server->pass_cmd = nfstrdup( cfg->val );
|
server->pass_cmd = nfstrdup( cfg->val );
|
||||||
#ifdef HAVE_MACOS_KEYCHAIN
|
#ifdef HAVE_MACOS_KEYCHAIN
|
||||||
else if (!strcasecmp( "UseKeychain", cfg->cmd ))
|
} else if (!strcasecmp( "UseKeychain", cfg->cmd )) {
|
||||||
server->use_keychain = parse_bool( cfg );
|
server->use_keychain = parse_bool( cfg );
|
||||||
#endif
|
#endif
|
||||||
else if (!strcasecmp( "Port", cfg->cmd )) {
|
} else if (!strcasecmp( "Port", cfg->cmd )) {
|
||||||
int port = parse_int( cfg );
|
int port = parse_int( cfg );
|
||||||
if ((unsigned)port > 0xffff) {
|
if ((unsigned)port > 0xffff) {
|
||||||
error( "%s:%d: Invalid port number\n", cfg->file, cfg->line );
|
error( "%s:%d: Invalid port number\n", cfg->file, cfg->line );
|
||||||
|
@ -3572,9 +3577,9 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
} else {
|
} else {
|
||||||
server->sconf.port = (ushort)port;
|
server->sconf.port = (ushort)port;
|
||||||
}
|
}
|
||||||
} else if (!strcasecmp( "Timeout", cfg->cmd ))
|
} else if (!strcasecmp( "Timeout", cfg->cmd )) {
|
||||||
server->sconf.timeout = parse_int( cfg );
|
server->sconf.timeout = parse_int( cfg );
|
||||||
else if (!strcasecmp( "PipelineDepth", cfg->cmd )) {
|
} else if (!strcasecmp( "PipelineDepth", cfg->cmd )) {
|
||||||
if ((server->max_in_progress = parse_int( cfg )) < 1) {
|
if ((server->max_in_progress = parse_int( cfg )) < 1) {
|
||||||
error( "%s:%d: PipelineDepth must be at least 1\n", cfg->file, cfg->line );
|
error( "%s:%d: PipelineDepth must be at least 1\n", cfg->file, cfg->line );
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
|
@ -3593,9 +3598,8 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
gotcap: ;
|
gotcap: ;
|
||||||
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
||||||
}
|
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
|
} else if (!strcasecmp( "CertificateFile", cfg->cmd )) {
|
||||||
server->sconf.cert_file = expand_strdup( cfg->val );
|
server->sconf.cert_file = expand_strdup( cfg->val );
|
||||||
if (access( server->sconf.cert_file, R_OK )) {
|
if (access( server->sconf.cert_file, R_OK )) {
|
||||||
sys_error( "%s:%d: CertificateFile '%s'",
|
sys_error( "%s:%d: CertificateFile '%s'",
|
||||||
|
@ -3653,34 +3657,34 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
}
|
}
|
||||||
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
||||||
} else if (!strcasecmp( "RequireSSL", cfg->cmd ))
|
} else if (!strcasecmp( "RequireSSL", cfg->cmd )) {
|
||||||
require_ssl = parse_bool( cfg );
|
require_ssl = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseIMAPS", cfg->cmd ))
|
} else if (!strcasecmp( "UseIMAPS", cfg->cmd )) {
|
||||||
use_imaps = parse_bool( cfg );
|
use_imaps = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseSSLv2", cfg->cmd ))
|
} else if (!strcasecmp( "UseSSLv2", cfg->cmd )) {
|
||||||
warn( "Warning: UseSSLv2 is no longer supported\n" );
|
warn( "Warning: UseSSLv2 is no longer supported\n" );
|
||||||
else if (!strcasecmp( "UseSSLv3", cfg->cmd ))
|
} else if (!strcasecmp( "UseSSLv3", cfg->cmd )) {
|
||||||
warn( "Warning: UseSSLv3 is no longer supported\n" );
|
warn( "Warning: UseSSLv3 is no longer supported\n" );
|
||||||
else if (!strcasecmp( "UseTLSv1", cfg->cmd ))
|
} else if (!strcasecmp( "UseTLSv1", cfg->cmd )) {
|
||||||
use_tlsv1 = parse_bool( cfg );
|
use_tlsv1 = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseTLSv1.1", cfg->cmd ))
|
} else if (!strcasecmp( "UseTLSv1.1", cfg->cmd )) {
|
||||||
use_tlsv11 = parse_bool( cfg );
|
use_tlsv11 = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseTLSv1.2", cfg->cmd ))
|
} else if (!strcasecmp( "UseTLSv1.2", cfg->cmd )) {
|
||||||
use_tlsv12 = parse_bool( cfg );
|
use_tlsv12 = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "UseTLSv1.3", cfg->cmd ))
|
} else if (!strcasecmp( "UseTLSv1.3", cfg->cmd )) {
|
||||||
use_tlsv13 = parse_bool( cfg );
|
use_tlsv13 = parse_bool( cfg );
|
||||||
#endif
|
#endif
|
||||||
else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
|
} else if (!strcasecmp( "AuthMech", cfg->cmd ) ||
|
||||||
!strcasecmp( "AuthMechs", cfg->cmd )) {
|
!strcasecmp( "AuthMechs", cfg->cmd )) {
|
||||||
arg = cfg->val;
|
arg = cfg->val;
|
||||||
do
|
do {
|
||||||
add_string_list( &server->auth_mechs, arg );
|
add_string_list( &server->auth_mechs, arg );
|
||||||
while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
} while ((arg = get_arg( cfg, ARG_OPTIONAL, NULL )));
|
||||||
} else if (!strcasecmp( "RequireCRAM", cfg->cmd ))
|
} else if (!strcasecmp( "RequireCRAM", cfg->cmd )) {
|
||||||
require_cram = parse_bool( cfg );
|
require_cram = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "Tunnel", cfg->cmd ))
|
} else if (!strcasecmp( "Tunnel", cfg->cmd )) {
|
||||||
server->sconf.tunnel = nfstrdup( cfg->val );
|
server->sconf.tunnel = nfstrdup( cfg->val );
|
||||||
else if (store) {
|
} else if (store) {
|
||||||
if (!strcasecmp( "Account", cfg->cmd )) {
|
if (!strcasecmp( "Account", cfg->cmd )) {
|
||||||
for (srv = servers; srv; srv = srv->next)
|
for (srv = servers; srv; srv = srv->next)
|
||||||
if (srv->name && !strcmp( srv->name, cfg->val ))
|
if (srv->name && !strcmp( srv->name, cfg->val ))
|
||||||
|
@ -3690,21 +3694,22 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
continue;
|
continue;
|
||||||
gotsrv:
|
gotsrv:
|
||||||
store->server = srv;
|
store->server = srv;
|
||||||
} else if (!strcasecmp( "UseNamespace", cfg->cmd ))
|
} else if (!strcasecmp( "UseNamespace", cfg->cmd )) {
|
||||||
store->use_namespace = parse_bool( cfg );
|
store->use_namespace = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "SubscribedOnly", cfg->cmd ))
|
} else if (!strcasecmp( "SubscribedOnly", cfg->cmd )) {
|
||||||
store->use_lsub = parse_bool( cfg );
|
store->use_lsub = parse_bool( cfg );
|
||||||
else if (!strcasecmp( "Path", cfg->cmd ))
|
} else if (!strcasecmp( "Path", cfg->cmd )) {
|
||||||
store->path = nfstrdup( cfg->val );
|
store->path = nfstrdup( cfg->val );
|
||||||
else if (!strcasecmp( "PathDelimiter", cfg->cmd )) {
|
} else if (!strcasecmp( "PathDelimiter", cfg->cmd )) {
|
||||||
if (strlen( cfg->val ) != 1) {
|
if (strlen( cfg->val ) != 1) {
|
||||||
error( "%s:%d: Path delimiter must be exactly one character long\n", cfg->file, cfg->line );
|
error( "%s:%d: Path delimiter must be exactly one character long\n", cfg->file, cfg->line );
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
store->delimiter = cfg->val[0];
|
store->delimiter = cfg->val[0];
|
||||||
} else
|
} else {
|
||||||
parse_generic_store( &store->gen, cfg, "IMAPStore" );
|
parse_generic_store( &store->gen, cfg, "IMAPStore" );
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
error( "%s:%d: keyword '%s' is not recognized in IMAPAccount sections\n",
|
error( "%s:%d: keyword '%s' is not recognized in IMAPAccount sections\n",
|
||||||
|
@ -3784,12 +3789,13 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
}
|
}
|
||||||
if (!server->auth_mechs)
|
if (!server->auth_mechs)
|
||||||
add_string_list( &server->auth_mechs, "*" );
|
add_string_list( &server->auth_mechs, "*" );
|
||||||
if (!server->sconf.port)
|
if (!server->sconf.port) {
|
||||||
server->sconf.port =
|
server->sconf.port =
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
server->ssl_type == SSL_IMAPS ? 993 :
|
server->ssl_type == SSL_IMAPS ? 993 :
|
||||||
#endif
|
#endif
|
||||||
143;
|
143;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (store) {
|
if (store) {
|
||||||
if (!store->server) {
|
if (!store->server) {
|
||||||
|
|
|
@ -151,7 +151,7 @@ maildir_join_path( maildir_store_conf_t *conf, int in_inbox, const char *box )
|
||||||
prefix = conf->path;
|
prefix = conf->path;
|
||||||
}
|
}
|
||||||
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) {
|
if (conf->sub_style == SUB_UNSET) {
|
||||||
error( "Maildir error: accessing subfolder '%s', but store '%s' does not specify SubFolders style\n",
|
error( "Maildir error: accessing subfolder '%s', but store '%s' does not specify SubFolders style\n",
|
||||||
|
@ -164,6 +164,7 @@ maildir_join_path( maildir_store_conf_t *conf, int in_inbox, const char *box )
|
||||||
conf->name, box );
|
conf->name, box );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
switch (conf->sub_style) {
|
switch (conf->sub_style) {
|
||||||
case SUB_VERBATIM:
|
case SUB_VERBATIM:
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -1046,11 +1047,10 @@ maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist )
|
||||||
}
|
}
|
||||||
#ifdef USE_DB
|
#ifdef USE_DB
|
||||||
if (ctx->usedb) {
|
if (ctx->usedb) {
|
||||||
if (maildir_uidval_lock( ctx ) != DRV_OK)
|
if (maildir_uidval_lock( ctx ) != DRV_OK) {
|
||||||
;
|
} else if ((ret = ctx->db->cursor( ctx->db, NULL, &dbc, 0 ))) {
|
||||||
else if ((ret = ctx->db->cursor( ctx->db, NULL, &dbc, 0 )))
|
|
||||||
ctx->db->err( ctx->db, ret, "Maildir error: db->cursor()" );
|
ctx->db->err( ctx->db, ret, "Maildir error: db->cursor()" );
|
||||||
else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((ret = dbc->c_get( dbc, &key, &value, DB_NEXT ))) {
|
if ((ret = dbc->c_get( dbc, &key, &value, DB_NEXT ))) {
|
||||||
if (ret != DB_NOTFOUND)
|
if (ret != DB_NOTFOUND)
|
||||||
|
@ -1232,8 +1232,9 @@ maildir_init_msg( maildir_store_t *ctx, maildir_message_t *msg, msg_t *entry )
|
||||||
if (ctx->opts & OPEN_FLAGS) {
|
if (ctx->opts & OPEN_FLAGS) {
|
||||||
msg->status |= M_FLAGS;
|
msg->status |= M_FLAGS;
|
||||||
msg->flags = maildir_parse_flags( ctx->conf->info_prefix, msg->base );
|
msg->flags = maildir_parse_flags( ctx->conf->info_prefix, msg->base );
|
||||||
} else
|
} else {
|
||||||
msg->flags = 0;
|
msg->flags = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1821,7 +1822,7 @@ maildir_close_box( store_t *gctx,
|
||||||
for (;;) {
|
for (;;) {
|
||||||
retry = 0;
|
retry = 0;
|
||||||
basel = nfsnprintf( buf, sizeof(buf), "%s/", ctx->path );
|
basel = nfsnprintf( buf, sizeof(buf), "%s/", ctx->path );
|
||||||
for (msg = ctx->msgs; msg; msg = msg->next)
|
for (msg = ctx->msgs; msg; msg = msg->next) {
|
||||||
if (!(msg->status & M_DEAD) && (msg->flags & F_DELETED)) {
|
if (!(msg->status & M_DEAD) && (msg->flags & F_DELETED)) {
|
||||||
nfsnprintf( buf + basel, _POSIX_PATH_MAX - basel, "%s/%s", subdirs[msg->status & M_RECENT], msg->base );
|
nfsnprintf( buf + basel, _POSIX_PATH_MAX - basel, "%s/%s", subdirs[msg->status & M_RECENT], msg->base );
|
||||||
if (unlink( buf )) {
|
if (unlink( buf )) {
|
||||||
|
@ -1840,6 +1841,7 @@ maildir_close_box( store_t *gctx,
|
||||||
#endif /* USE_DB */
|
#endif /* USE_DB */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!retry) {
|
if (!retry) {
|
||||||
cb( DRV_OK, aux );
|
cb( DRV_OK, aux );
|
||||||
return;
|
return;
|
||||||
|
@ -1888,16 +1890,16 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
store->driver = &maildir_driver;
|
store->driver = &maildir_driver;
|
||||||
store->name = nfstrdup( cfg->val );
|
store->name = nfstrdup( cfg->val );
|
||||||
|
|
||||||
while (getcline( cfg ) && cfg->cmd)
|
while (getcline( cfg ) && cfg->cmd) {
|
||||||
if (!strcasecmp( "Inbox", cfg->cmd ))
|
if (!strcasecmp( "Inbox", cfg->cmd )) {
|
||||||
store->inbox = expand_strdup( cfg->val );
|
store->inbox = expand_strdup( cfg->val );
|
||||||
else if (!strcasecmp( "Path", cfg->cmd ))
|
} else if (!strcasecmp( "Path", cfg->cmd )) {
|
||||||
store->path = expand_strdup( cfg->val );
|
store->path = expand_strdup( cfg->val );
|
||||||
#ifdef USE_DB
|
#ifdef USE_DB
|
||||||
else if (!strcasecmp( "AltMap", cfg->cmd ))
|
} else if (!strcasecmp( "AltMap", cfg->cmd )) {
|
||||||
store->alt_map = parse_bool( cfg );
|
store->alt_map = parse_bool( cfg );
|
||||||
#endif /* USE_DB */
|
#endif /* USE_DB */
|
||||||
else if (!strcasecmp( "InfoDelimiter", cfg->cmd )) {
|
} else if (!strcasecmp( "InfoDelimiter", cfg->cmd )) {
|
||||||
if (strlen( cfg->val ) != 1) {
|
if (strlen( cfg->val ) != 1) {
|
||||||
error( "%s:%d: Info delimiter must be exactly one character long\n", cfg->file, cfg->line );
|
error( "%s:%d: Info delimiter must be exactly one character long\n", cfg->file, cfg->line );
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
|
@ -1920,8 +1922,10 @@ maildir_parse_store( conffile_t *cfg, store_conf_t **storep )
|
||||||
error( "%s:%d: Unrecognized SubFolders style\n", cfg->file, cfg->line );
|
error( "%s:%d: Unrecognized SubFolders style\n", cfg->file, cfg->line );
|
||||||
cfg->err = 1;
|
cfg->err = 1;
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
parse_generic_store( &store->gen, cfg, "MaildirStore" );
|
parse_generic_store( &store->gen, cfg, "MaildirStore" );
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!store->inbox)
|
if (!store->inbox)
|
||||||
store->inbox = expand_strdup( "~/Maildir" );
|
store->inbox = expand_strdup( "~/Maildir" );
|
||||||
if (store->sub_style == SUB_MAILDIRPP && store->path) {
|
if (store->sub_style == SUB_MAILDIRPP && store->path) {
|
||||||
|
|
58
src/main.c
58
src/main.c
|
@ -261,8 +261,9 @@ filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns
|
||||||
if (*ps == '!') {
|
if (*ps == '!') {
|
||||||
ps++;
|
ps++;
|
||||||
not = 1;
|
not = 1;
|
||||||
} else
|
} else {
|
||||||
not = 0;
|
not = 0;
|
||||||
|
}
|
||||||
if (matches( boxes->string + pfxl, ps )) {
|
if (matches( boxes->string + pfxl, ps )) {
|
||||||
fnot = not;
|
fnot = not;
|
||||||
break;
|
break;
|
||||||
|
@ -448,17 +449,17 @@ main( int argc, char **argv )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
config = argv[oind++];
|
config = argv[oind++];
|
||||||
} else if (starts_with( opt, -1, "config=", 7 ))
|
} else if (starts_with( opt, -1, "config=", 7 )) {
|
||||||
config = opt + 7;
|
config = opt + 7;
|
||||||
else if (!strcmp( opt, "all" ))
|
} else if (!strcmp( opt, "all" )) {
|
||||||
mvars->all = 1;
|
mvars->all = 1;
|
||||||
else if (!strcmp( opt, "list" ))
|
} else if (!strcmp( opt, "list" )) {
|
||||||
mvars->list = 1;
|
mvars->list = 1;
|
||||||
else if (!strcmp( opt, "help" ))
|
} else if (!strcmp( opt, "help" )) {
|
||||||
usage( 0 );
|
usage( 0 );
|
||||||
else if (!strcmp( opt, "version" ))
|
} else if (!strcmp( opt, "version" )) {
|
||||||
version();
|
version();
|
||||||
else if (!strcmp( opt, "quiet" )) {
|
} else if (!strcmp( opt, "quiet" )) {
|
||||||
if (DFlags & QUIET)
|
if (DFlags & QUIET)
|
||||||
DFlags |= VERYQUIET;
|
DFlags |= VERYQUIET;
|
||||||
else
|
else
|
||||||
|
@ -488,11 +489,11 @@ main( int argc, char **argv )
|
||||||
else
|
else
|
||||||
goto badopt;
|
goto badopt;
|
||||||
DFlags |= op;
|
DFlags |= op;
|
||||||
} else if (!strcmp( opt, "pull" ))
|
} else if (!strcmp( opt, "pull" )) {
|
||||||
cops |= XOP_PULL, ops[F] |= XOP_HAVE_TYPE;
|
cops |= XOP_PULL, ops[F] |= XOP_HAVE_TYPE;
|
||||||
else if (!strcmp( opt, "push" ))
|
} else if (!strcmp( opt, "push" )) {
|
||||||
cops |= XOP_PUSH, ops[F] |= XOP_HAVE_TYPE;
|
cops |= XOP_PUSH, ops[F] |= XOP_HAVE_TYPE;
|
||||||
else if (starts_with( opt, -1, "create", 6 )) {
|
} else if (starts_with( opt, -1, "create", 6 )) {
|
||||||
opt += 6;
|
opt += 6;
|
||||||
op = OP_CREATE|XOP_HAVE_CREATE;
|
op = OP_CREATE|XOP_HAVE_CREATE;
|
||||||
lcop:
|
lcop:
|
||||||
|
@ -517,42 +518,43 @@ main( int argc, char **argv )
|
||||||
opt += 7;
|
opt += 7;
|
||||||
op = OP_EXPUNGE|XOP_HAVE_EXPUNGE;
|
op = OP_EXPUNGE|XOP_HAVE_EXPUNGE;
|
||||||
goto lcop;
|
goto lcop;
|
||||||
} else if (!strcmp( opt, "no-expunge" ))
|
} else if (!strcmp( opt, "no-expunge" )) {
|
||||||
ops[F] |= XOP_HAVE_EXPUNGE;
|
ops[F] |= XOP_HAVE_EXPUNGE;
|
||||||
else if (!strcmp( opt, "no-create" ))
|
} else if (!strcmp( opt, "no-create" )) {
|
||||||
ops[F] |= XOP_HAVE_CREATE;
|
ops[F] |= XOP_HAVE_CREATE;
|
||||||
else if (!strcmp( opt, "no-remove" ))
|
} else if (!strcmp( opt, "no-remove" )) {
|
||||||
ops[F] |= XOP_HAVE_REMOVE;
|
ops[F] |= XOP_HAVE_REMOVE;
|
||||||
else if (!strcmp( opt, "full" ))
|
} else if (!strcmp( opt, "full" )) {
|
||||||
ops[F] |= XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH;
|
ops[F] |= XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH;
|
||||||
else if (!strcmp( opt, "noop" ))
|
} else if (!strcmp( opt, "noop" )) {
|
||||||
ops[F] |= XOP_HAVE_TYPE;
|
ops[F] |= XOP_HAVE_TYPE;
|
||||||
else if (starts_with( opt, -1, "pull", 4 )) {
|
} else if (starts_with( opt, -1, "pull", 4 )) {
|
||||||
op = XOP_PULL;
|
op = XOP_PULL;
|
||||||
lcac:
|
lcac:
|
||||||
opt += 4;
|
opt += 4;
|
||||||
if (!*opt)
|
if (!*opt) {
|
||||||
cops |= op;
|
cops |= op;
|
||||||
else if (*opt == '-') {
|
} else if (*opt == '-') {
|
||||||
opt++;
|
opt++;
|
||||||
goto rlcac;
|
goto rlcac;
|
||||||
} else
|
} else {
|
||||||
goto badopt;
|
goto badopt;
|
||||||
|
}
|
||||||
} else if (starts_with( opt, -1, "push", 4 )) {
|
} else if (starts_with( opt, -1, "push", 4 )) {
|
||||||
op = XOP_PUSH;
|
op = XOP_PUSH;
|
||||||
goto lcac;
|
goto lcac;
|
||||||
} else {
|
} else {
|
||||||
op = 0;
|
op = 0;
|
||||||
rlcac:
|
rlcac:
|
||||||
if (!strcmp( opt, "new" ))
|
if (!strcmp( opt, "new" )) {
|
||||||
op |= OP_NEW;
|
op |= OP_NEW;
|
||||||
else if (!strcmp( opt, "renew" ))
|
} else if (!strcmp( opt, "renew" )) {
|
||||||
op |= OP_RENEW;
|
op |= OP_RENEW;
|
||||||
else if (!strcmp( opt, "delete" ))
|
} else if (!strcmp( opt, "delete" )) {
|
||||||
op |= OP_DELETE;
|
op |= OP_DELETE;
|
||||||
else if (!strcmp( opt, "flags" ))
|
} else if (!strcmp( opt, "flags" )) {
|
||||||
op |= OP_FLAGS;
|
op |= OP_FLAGS;
|
||||||
else {
|
} else {
|
||||||
badopt:
|
badopt:
|
||||||
error( "Unknown option '%s'\n", argv[oind - 1] );
|
error( "Unknown option '%s'\n", argv[oind - 1] );
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -634,14 +636,15 @@ main( int argc, char **argv )
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (op & OP_MASK_TYPE)
|
if (op & OP_MASK_TYPE) {
|
||||||
switch (op & XOP_MASK_DIR) {
|
switch (op & XOP_MASK_DIR) {
|
||||||
case XOP_PULL: ops[N] |= op & OP_MASK_TYPE; break;
|
case XOP_PULL: ops[N] |= op & OP_MASK_TYPE; break;
|
||||||
case XOP_PUSH: ops[F] |= op & OP_MASK_TYPE; break;
|
case XOP_PUSH: ops[F] |= op & OP_MASK_TYPE; break;
|
||||||
default: cops |= op; break;
|
default: cops |= op; break;
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
cops |= op;
|
cops |= op;
|
||||||
|
}
|
||||||
ops[F] |= XOP_HAVE_TYPE;
|
ops[F] |= XOP_HAVE_TYPE;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
case 'L':
|
||||||
|
@ -943,8 +946,9 @@ sync_chans( main_vars_t *mvars, int ent )
|
||||||
syncone:
|
syncone:
|
||||||
if (!mvars->skip)
|
if (!mvars->skip)
|
||||||
goto syncml;
|
goto syncml;
|
||||||
} else
|
} else {
|
||||||
printf( "%s <=> %s\n", nz( mvars->chan->boxes[F], "INBOX" ), nz( mvars->chan->boxes[N], "INBOX" ) );
|
printf( "%s <=> %s\n", nz( mvars->chan->boxes[F], "INBOX" ), nz( mvars->chan->boxes[N], "INBOX" ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next:
|
next:
|
||||||
|
|
|
@ -251,8 +251,9 @@ main( int argc, char **argv )
|
||||||
} else if (argv[oint][0] == '-') {
|
} else if (argv[oint][0] == '-') {
|
||||||
fprintf( stderr, "Unrecognized option '%s'. Try " EXE " -h\n", argv[oint] );
|
fprintf( stderr, "Unrecognized option '%s'. Try " EXE " -h\n", argv[oint] );
|
||||||
return 1;
|
return 1;
|
||||||
} else
|
} else {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oint == argc) {
|
if (oint == argc) {
|
||||||
fprintf( stderr, "Mailbox specification missing. Try " EXE " -h\n" );
|
fprintf( stderr, "Mailbox specification missing. Try " EXE " -h\n" );
|
||||||
|
|
60
src/sync.c
60
src/sync.c
|
@ -95,11 +95,12 @@ parse_flags( const char *buf )
|
||||||
uint i, d;
|
uint i, d;
|
||||||
uchar flags;
|
uchar flags;
|
||||||
|
|
||||||
for (flags = i = d = 0; i < as(Flags); i++)
|
for (flags = i = d = 0; i < as(Flags); i++) {
|
||||||
if (buf[d] == Flags[i]) {
|
if (buf[d] == Flags[i]) {
|
||||||
flags |= (1 << i);
|
flags |= (1 << i);
|
||||||
d++;
|
d++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -755,9 +756,9 @@ prepare_state( sync_vars_t *svars )
|
||||||
nfasprintf( &svars->dname, "%s/." EXE "state", path );
|
nfasprintf( &svars->dname, "%s/." EXE "state", path );
|
||||||
} else {
|
} else {
|
||||||
csname = clean_strdup( svars->box_name[N] );
|
csname = clean_strdup( svars->box_name[N] );
|
||||||
if (chan->sync_state)
|
if (chan->sync_state) {
|
||||||
nfasprintf( &svars->dname, "%s%s", chan->sync_state, csname );
|
nfasprintf( &svars->dname, "%s%s", chan->sync_state, csname );
|
||||||
else {
|
} else {
|
||||||
char c = FieldDelimiter;
|
char c = FieldDelimiter;
|
||||||
cmname = clean_strdup( svars->box_name[F] );
|
cmname = clean_strdup( svars->box_name[F] );
|
||||||
nfasprintf( &svars->dname, "%s%c%s%c%s_%c%s%c%s", global_conf.sync_state,
|
nfasprintf( &svars->dname, "%s%c%s%c%s_%c%s%c%s", global_conf.sync_state,
|
||||||
|
@ -891,19 +892,19 @@ load_state( sync_vars_t *svars )
|
||||||
error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line );
|
error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line );
|
||||||
goto jbail;
|
goto jbail;
|
||||||
}
|
}
|
||||||
if (!strcmp( buf1, "FarUidValidity" ) || !strcmp( buf1, "MasterUidValidity" ) /* Pre-1.4 legacy */)
|
if (!strcmp( buf1, "FarUidValidity" ) || !strcmp( buf1, "MasterUidValidity" ) /* Pre-1.4 legacy */) {
|
||||||
svars->uidval[F] = uid;
|
svars->uidval[F] = uid;
|
||||||
else if (!strcmp( buf1, "NearUidValidity" ) || !strcmp( buf1, "SlaveUidValidity" ) /* Pre-1.4 legacy */)
|
} else if (!strcmp( buf1, "NearUidValidity" ) || !strcmp( buf1, "SlaveUidValidity" ) /* Pre-1.4 legacy */) {
|
||||||
svars->uidval[N] = uid;
|
svars->uidval[N] = uid;
|
||||||
else if (!strcmp( buf1, "MaxPulledUid" ))
|
} else if (!strcmp( buf1, "MaxPulledUid" )) {
|
||||||
svars->maxuid[F] = uid;
|
svars->maxuid[F] = uid;
|
||||||
else if (!strcmp( buf1, "MaxPushedUid" ))
|
} else if (!strcmp( buf1, "MaxPushedUid" )) {
|
||||||
svars->maxuid[N] = uid;
|
svars->maxuid[N] = uid;
|
||||||
else if (!strcmp( buf1, "MaxExpiredFarUid" ) || !strcmp( buf1, "MaxExpiredMasterUid" ) /* Pre-1.4 legacy */)
|
} else if (!strcmp( buf1, "MaxExpiredFarUid" ) || !strcmp( buf1, "MaxExpiredMasterUid" ) /* Pre-1.4 legacy */) {
|
||||||
svars->maxxfuid = uid;
|
svars->maxxfuid = uid;
|
||||||
else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) // Pre-1.3 legacy
|
} else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) { // Pre-1.3 legacy
|
||||||
maxxnuid = uid;
|
maxxnuid = uid;
|
||||||
else {
|
} else {
|
||||||
error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line );
|
error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line );
|
||||||
goto jbail;
|
goto jbail;
|
||||||
}
|
}
|
||||||
|
@ -1033,15 +1034,15 @@ load_state( sync_vars_t *svars )
|
||||||
error( "Error: malformed journal entry at %s:%d\n", svars->jname, line );
|
error( "Error: malformed journal entry at %s:%d\n", svars->jname, line );
|
||||||
goto jbail;
|
goto jbail;
|
||||||
}
|
}
|
||||||
if (c == 'N')
|
if (c == 'N') {
|
||||||
svars->maxuid[t1] = t2;
|
svars->maxuid[t1] = t2;
|
||||||
else if (c == 'F')
|
} else if (c == 'F') {
|
||||||
svars->finduid[t1] = t2;
|
svars->finduid[t1] = t2;
|
||||||
else if (c == 'T')
|
} else if (c == 'T') {
|
||||||
*uint_array_append( &svars->trashed_msgs[t1] ) = t2;
|
*uint_array_append( &svars->trashed_msgs[t1] ) = t2;
|
||||||
else if (c == '!')
|
} else if (c == '!') {
|
||||||
svars->maxxfuid = t1;
|
svars->maxxfuid = t1;
|
||||||
else if (c == '|') {
|
} else if (c == '|') {
|
||||||
svars->uidval[F] = t1;
|
svars->uidval[F] = t1;
|
||||||
svars->uidval[N] = t2;
|
svars->uidval[N] = t2;
|
||||||
} else if (c == '+') {
|
} else if (c == '+') {
|
||||||
|
@ -1409,8 +1410,9 @@ box_opened2( sync_vars_t *svars, int t )
|
||||||
if (!chan->stores[t]->trash_only_new)
|
if (!chan->stores[t]->trash_only_new)
|
||||||
opts[t] |= OPEN_OLD;
|
opts[t] |= OPEN_OLD;
|
||||||
opts[t] |= OPEN_NEW|OPEN_FLAGS;
|
opts[t] |= OPEN_NEW|OPEN_FLAGS;
|
||||||
} else if (chan->stores[1-t]->trash && chan->stores[1-t]->trash_remote_new)
|
} else if (chan->stores[1-t]->trash && chan->stores[1-t]->trash_remote_new) {
|
||||||
opts[t] |= OPEN_NEW|OPEN_FLAGS;
|
opts[t] |= OPEN_NEW|OPEN_FLAGS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// While only new messages can cause expiration due to displacement,
|
// While only new messages can cause expiration due to displacement,
|
||||||
|
@ -1420,7 +1422,7 @@ box_opened2( sync_vars_t *svars, int t )
|
||||||
// OP_RENEW makes sense only for legacy S_SKIPPED entries.
|
// OP_RENEW makes sense only for legacy S_SKIPPED entries.
|
||||||
if ((chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages)
|
if ((chan->ops[N] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages)
|
||||||
opts[N] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
|
opts[N] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS;
|
||||||
if (svars->replayed)
|
if (svars->replayed) {
|
||||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
for (srec = svars->srecs; srec; srec = srec->next) {
|
||||||
if (srec->status & S_DEAD)
|
if (srec->status & S_DEAD)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1442,6 +1444,7 @@ box_opened2( sync_vars_t *svars, int t )
|
||||||
opts[1-t] |= OPEN_OLD;
|
opts[1-t] |= OPEN_OLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] );
|
svars->opts[F] = svars->drv[F]->prepare_load_box( ctx[F], opts[F] );
|
||||||
svars->opts[N] = svars->drv[N]->prepare_load_box( ctx[N], opts[N] );
|
svars->opts[N] = svars->drv[N]->prepare_load_box( ctx[N], opts[N] );
|
||||||
|
|
||||||
|
@ -1885,9 +1888,10 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
|
||||||
} else {
|
} else {
|
||||||
nflags = tmsg->flags;
|
nflags = tmsg->flags;
|
||||||
}
|
}
|
||||||
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED)))
|
if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE | S_EXPIRED))) {
|
||||||
// The message is not deleted, or it is, but only due to being expired.
|
// The message is not deleted, or it is, but only due to being expired.
|
||||||
alive++;
|
alive++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
todel = alive - svars->chan->max_messages;
|
todel = alive - svars->chan->max_messages;
|
||||||
debug( "%d alive messages, %d excess - expiring\n", alive, todel );
|
debug( "%d alive messages, %d excess - expiring\n", alive, todel );
|
||||||
|
@ -2025,8 +2029,9 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux
|
||||||
svars->drv[t]->set_msg_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set, fv );
|
svars->drv[t]->set_msg_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set, fv );
|
||||||
if (check_cancel( svars ))
|
if (check_cancel( svars ))
|
||||||
goto out;
|
goto out;
|
||||||
} else
|
} else {
|
||||||
flags_set_p2( svars, srec, t );
|
flags_set_p2( svars, srec, t );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (t = 0; t < 2; t++) {
|
for (t = 0; t < 2; t++) {
|
||||||
|
@ -2080,11 +2085,10 @@ msg_copied( int sts, uint uid, copy_vars_t *vars )
|
||||||
srec->flags = vars->msg->flags;
|
srec->flags = vars->msg->flags;
|
||||||
JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], srec->flags), "%sed with flags", str_hl[t] );
|
JLOG( "* %u %u %u", (srec->uid[F], srec->uid[N], srec->flags), "%sed with flags", str_hl[t] );
|
||||||
}
|
}
|
||||||
if (!uid) { // Stored to a non-UIDPLUS mailbox
|
if (!uid) // Stored to a non-UIDPLUS mailbox
|
||||||
svars->state[t] |= ST_FIND_NEW;
|
svars->state[t] |= ST_FIND_NEW;
|
||||||
} else {
|
else
|
||||||
ASSIGN_UID( srec, t, uid, "%sed message", str_hl[t] );
|
ASSIGN_UID( srec, t, uid, "%sed message", str_hl[t] );
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case SYNC_NOGOOD:
|
case SYNC_NOGOOD:
|
||||||
srec->status = S_DEAD;
|
srec->status = S_DEAD;
|
||||||
|
@ -2249,7 +2253,7 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
||||||
if ((svars->chan->ops[t] & OP_EXPUNGE) &&
|
if ((svars->chan->ops[t] & OP_EXPUNGE) &&
|
||||||
(svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) {
|
(svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) {
|
||||||
debug( "trashing on %s\n", str_fn[t] );
|
debug( "trashing on %s\n", str_fn[t] );
|
||||||
for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next)
|
for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) {
|
||||||
if ((tmsg->flags & F_DELETED) && !find_uint_array( svars->trashed_msgs[t].array, tmsg->uid ) &&
|
if ((tmsg->flags & F_DELETED) && !find_uint_array( svars->trashed_msgs[t].array, tmsg->uid ) &&
|
||||||
(t == F || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) {
|
(t == F || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) {
|
||||||
if (svars->ctx[t]->conf->trash) {
|
if (svars->ctx[t]->conf->trash) {
|
||||||
|
@ -2264,8 +2268,9 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
||||||
svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, tv );
|
svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, tv );
|
||||||
if (check_cancel( svars ))
|
if (check_cancel( svars ))
|
||||||
goto out;
|
goto out;
|
||||||
} else
|
} else {
|
||||||
debug( "%s: not trashing message %u - not new\n", str_fn[t], tmsg->uid );
|
debug( "%s: not trashing message %u - not new\n", str_fn[t], tmsg->uid );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) {
|
if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) {
|
||||||
if (tmsg->size <= svars->ctx[1-t]->conf->max_size) {
|
if (tmsg->size <= svars->ctx[1-t]->conf->max_size) {
|
||||||
|
@ -2282,12 +2287,15 @@ msgs_flags_set( sync_vars_t *svars, int t )
|
||||||
copy_msg( cv );
|
copy_msg( cv );
|
||||||
if (check_cancel( svars ))
|
if (check_cancel( svars ))
|
||||||
goto out;
|
goto out;
|
||||||
} else
|
} else {
|
||||||
debug( "%s: not remote trashing message %u - too big\n", str_fn[t], tmsg->uid );
|
debug( "%s: not remote trashing message %u - too big\n", str_fn[t], tmsg->uid );
|
||||||
} else
|
}
|
||||||
|
} else {
|
||||||
debug( "%s: not remote trashing message %u - not new\n", str_fn[t], tmsg->uid );
|
debug( "%s: not remote trashing message %u - not new\n", str_fn[t], tmsg->uid );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
svars->state[t] |= ST_SENT_TRASH;
|
svars->state[t] |= ST_SENT_TRASH;
|
||||||
sync_close( svars, t );
|
sync_close( svars, t );
|
||||||
|
|
|
@ -454,16 +454,18 @@ expand_strdup( const char *s )
|
||||||
r = nfstrndup( s, (size_t)(p - s) );
|
r = nfstrndup( s, (size_t)(p - s) );
|
||||||
pw = getpwnam( r );
|
pw = getpwnam( r );
|
||||||
free( r );
|
free( r );
|
||||||
} else
|
} else {
|
||||||
pw = getpwnam( s );
|
pw = getpwnam( s );
|
||||||
|
}
|
||||||
if (!pw)
|
if (!pw)
|
||||||
return NULL;
|
return NULL;
|
||||||
q = pw->pw_dir;
|
q = pw->pw_dir;
|
||||||
}
|
}
|
||||||
nfasprintf( &r, "%s%s", q, p ? p : "" );
|
nfasprintf( &r, "%s%s", q, p ? p : "" );
|
||||||
return r;
|
return r;
|
||||||
} else
|
} else {
|
||||||
return nfstrdup( s );
|
return nfstrdup( 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 */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user