Browse Source

do away with the dreaded rcaps hack

don't pretend that the server has no literal+ for the time of the
first relevant command's synchronous execution. instead, enable the
lower layer to do the processing by telling it for which commands
trashnc ("trash's existence not confirmed") is relevant.
wip/maildir-uid-dupes-test
Oswald Buddenhagen 14 years ago
parent
commit
99cc328f17
  1. 68
      src/drv_imap.c

68
src/drv_imap.c

@ -120,7 +120,7 @@ typedef struct imap_store {
unsigned got_namespace:1; unsigned got_namespace:1;
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, rcaps; /* CAPABILITY results */ unsigned caps; /* CAPABILITY results */
/* command queue */ /* command queue */
int nexttag, num_in_progress, literal_pending; int nexttag, num_in_progress, literal_pending;
struct imap_cmd *in_progress, **in_progress_append; struct imap_cmd *in_progress, **in_progress_append;
@ -143,6 +143,7 @@ struct imap_cmd {
int data_len; int data_len;
int uid; /* to identify fetch responses */ int uid; /* to identify fetch responses */
unsigned unsigned
to_trash:1, /* we are storing to trash, not current. */
create:1, /* create the mailbox if we get an error ... */ create:1, /* create the mailbox if we get an error ... */
trycreate:1; /* ... but only if this is true or the server says so. */ trycreate:1; /* ... but only if this is true or the server says so. */
} param; } param;
@ -498,7 +499,8 @@ static struct imap_cmd *
v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
const char *fmt, va_list ap ) const char *fmt, va_list ap )
{ {
int n, bufl; int bufl, litplus;
const char *buffmt;
char buf[1024]; char buf[1024];
while (ctx->literal_pending) while (ctx->literal_pending)
@ -508,8 +510,17 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
cmd = new_imap_cmd(); cmd = new_imap_cmd();
cmd->tag = ++ctx->nexttag; cmd->tag = ++ctx->nexttag;
nfvasprintf( &cmd->cmd, fmt, ap ); nfvasprintf( &cmd->cmd, fmt, ap );
bufl = nfsnprintf( buf, sizeof(buf), cmd->param.data ? CAP(LITERALPLUS) ? if (!cmd->param.data) {
"%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n", buffmt = "%d %s\r\n";
litplus = 0;
} else if ((cmd->param.to_trash && ctx->trashnc) || !CAP(LITERALPLUS)) {
buffmt = "%d %s{%d}\r\n";
litplus = 0;
} else {
buffmt = "%d %s{%d+}\r\n";
litplus = 1;
}
bufl = nfsnprintf( buf, sizeof(buf), buffmt,
cmd->tag, cmd->cmd, cmd->param.data_len ); cmd->tag, cmd->cmd, cmd->param.data_len );
if (DFlags & VERBOSE) { if (DFlags & VERBOSE) {
if (ctx->num_in_progress) if (ctx->num_in_progress)
@ -519,33 +530,28 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
else else
printf( ">>> %d LOGIN <user> <pass>\n", cmd->tag ); printf( ">>> %d LOGIN <user> <pass>\n", cmd->tag );
} }
if (socket_write( &ctx->buf.sock, buf, bufl ) != bufl) { if (socket_write( &ctx->buf.sock, buf, bufl ) != bufl)
free( cmd->param.data ); goto bail;
free( cmd->cmd ); if (litplus) {
free( cmd ); if (socket_write( &ctx->buf.sock, cmd->param.data, cmd->param.data_len ) != cmd->param.data_len ||
return NULL; socket_write( &ctx->buf.sock, "\r\n", 2 ) != 2)
} goto bail;
if (cmd->param.data) {
if (CAP(LITERALPLUS)) {
n = socket_write( &ctx->buf.sock, cmd->param.data, cmd->param.data_len );
free( cmd->param.data ); free( cmd->param.data );
if (n != cmd->param.data_len ||
(n = socket_write( &ctx->buf.sock, "\r\n", 2 )) != 2)
{
free( cmd->cmd );
free( cmd );
return NULL;
}
cmd->param.data = 0; cmd->param.data = 0;
} else } else if (cmd->param.cont || cmd->param.data) {
ctx->literal_pending = 1;
} else if (cmd->param.cont)
ctx->literal_pending = 1; ctx->literal_pending = 1;
}
cmd->next = 0; cmd->next = 0;
*ctx->in_progress_append = cmd; *ctx->in_progress_append = cmd;
ctx->in_progress_append = &cmd->next; ctx->in_progress_append = &cmd->next;
ctx->num_in_progress++; ctx->num_in_progress++;
return cmd; return cmd;
bail:
free( cmd->param.data );
free( cmd->cmd );
free( cmd );
return NULL;
} }
static struct imap_cmd * static struct imap_cmd *
@ -884,7 +890,6 @@ parse_capability( imap_store_t *ctx, char *cmd )
for (i = 0; i < as(cap_list); i++) for (i = 0; i < as(cap_list); i++)
if (!strcmp( cap_list[i], arg )) if (!strcmp( cap_list[i], arg ))
ctx->caps |= 1 << i; ctx->caps |= 1 << i;
ctx->rcaps = ctx->caps;
} }
static int static int
@ -1042,6 +1047,8 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
it enforces a round-trip. */ it enforces a round-trip. */
cmdp = ctx->in_progress; cmdp = ctx->in_progress;
if (cmdp->param.data) { if (cmdp->param.data) {
if (cmdp->param.to_trash)
ctx->trashnc = 0; /* Can't get NO [TRYCREATE] any more. */
n = socket_write( &ctx->buf.sock, cmdp->param.data, cmdp->param.data_len ); n = socket_write( &ctx->buf.sock, cmdp->param.data, cmdp->param.data_len );
free( cmdp->param.data ); free( cmdp->param.data );
cmdp->param.data = 0; cmdp->param.data = 0;
@ -1074,9 +1081,11 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
if (cmdp->param.cont || cmdp->param.data) if (cmdp->param.cont || cmdp->param.data)
ctx->literal_pending = 0; ctx->literal_pending = 0;
arg = next_arg( &cmd ); arg = next_arg( &cmd );
if (!strcmp( "OK", arg )) if (!strcmp( "OK", arg )) {
if (cmdp->param.to_trash)
ctx->trashnc = 0; /* Can't get NO [TRYCREATE] any more. */
resp = DRV_OK; resp = DRV_OK;
else { } else {
if (!strcmp( "NO", arg )) { if (!strcmp( "NO", arg )) {
if (cmdp->param.create && cmd && (cmdp->param.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */ if (cmdp->param.create && cmd && (cmdp->param.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT, APPEND or UID COPY */
p = strchr( cmdp->cmd, '"' ); p = strchr( cmdp->cmd, '"' );
@ -1661,6 +1670,7 @@ 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 *cmd = new_imap_cmd(); struct imap_cmd *cmd = new_imap_cmd();
cmd->param.create = 1; cmd->param.create = 1;
cmd->param.to_trash = 1;
return cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"", return cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"",
msg->uid, ctx->prefix, gctx->conf->trash ), aux ); msg->uid, ctx->prefix, gctx->conf->trash ), aux );
} }
@ -1691,18 +1701,14 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash,
box = gctx->conf->trash; box = gctx->conf->trash;
prefix = ctx->prefix; prefix = ctx->prefix;
cmd->param.create = 1; cmd->param.create = 1;
if (ctx->trashnc) cmd->param.to_trash = 1;
ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS);
} else { } else {
box = gctx->name; box = gctx->name;
prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix; prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
} }
ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr ); ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr );
ctx->caps = ctx->rcaps;
if (ret != DRV_OK) if (ret != DRV_OK)
return cb( ret, -1, aux ); return cb( ret, -1, aux );
if (to_trash)
ctx->trashnc = 0;
return cb( DRV_OK, uid, aux ); return cb( DRV_OK, uid, aux );
} }

Loading…
Cancel
Save