commit 93c5595d4baa2e183c77d1cd5a8e934eb78e15ed
Author: Oswald Buddenhagen <[email protected]>
Date: Mon Nov 15 10:38:50 2010 +0100
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.
src/drv_imap.c | 68 ++++++++++++++++++++++++++---------------------
1 files changed, 38 insertions(+), 30 deletions(-)
diff --git a/src/drv_imap.c b/src/drv_imap.c
index a553464..ae9399b 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -120,7 +120,7 @@ typedef struct imap_store {
unsigned got_namespace:1;
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
message_t **msgapp; /* FETCH results */
- unsigned caps, rcaps; /* CAPABILITY results */
+ unsigned caps; /* CAPABILITY results */
/* command queue */
int nexttag, num_in_progress, literal_pending;
struct imap_cmd *in_progress, **in_progress_append;
@@ -143,6 +143,7 @@ struct imap_cmd {
int data_len;
int uid; /* to identify fetch responses */
unsigned
+ to_trash:1, /* we are storing to trash, not current. */
create:1, /* create the mailbox if we get an error ...
*/
trycreate:1; /* ... but only if this is true or the
server says so. */
} param;
@@ -498,7 +499,8 @@ static struct imap_cmd *
v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
const char *fmt, va_list ap )
{
- int n, bufl;
+ int n, bufl, litplus;
+ const char *buffmt;
char buf[1024];
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->tag = ++ctx->nexttag;
nfvasprintf( &cmd->cmd, fmt, ap );
- bufl = nfsnprintf( buf, sizeof(buf), cmd->param.data ? CAP(LITERALPLUS)
?
- "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
+ if (!cmd->param.data) {
+ 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 );
if (DFlags & VERBOSE) {
if (ctx->num_in_progress)
@@ -521,31 +532,28 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd
*cmd,
}
if (socket_write( &ctx->buf.sock, buf, bufl ) != bufl) {
free( cmd->param.data );
- free( cmd->cmd );
- free( cmd );
- return NULL;
+ 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 );
- 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;
- } else
- ctx->literal_pending = 1;
- } else if (cmd->param.cont)
+ if (litplus) {
+ n = socket_write( &ctx->buf.sock, cmd->param.data,
cmd->param.data_len );
+ free( cmd->param.data );
+ if (n != cmd->param.data_len ||
+ (n = socket_write( &ctx->buf.sock, "\r\n", 2 )) != 2)
+ goto bail;
+ cmd->param.data = 0;
+ } else if (cmd->param.cont || cmd->param.data) {
ctx->literal_pending = 1;
+ }
cmd->next = 0;
*ctx->in_progress_append = cmd;
ctx->in_progress_append = &cmd->next;
ctx->num_in_progress++;
return cmd;
+
+ bail:
+ free( cmd->cmd );
+ free( cmd );
+ return NULL;
}
static struct imap_cmd *
@@ -884,7 +892,6 @@ parse_capability( imap_store_t *ctx, char *cmd )
for (i = 0; i < as(cap_list); i++)
if (!strcmp( cap_list[i], arg ))
ctx->caps |= 1 << i;
- ctx->rcaps = ctx->caps;
}
static int
@@ -1043,6 +1050,8 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
cmdp = (struct imap_cmd *)((char
*)ctx->in_progress_append -
offsetof(struct imap_cmd, next));
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 );
free( cmdp->param.data );
cmdp->param.data = 0;
@@ -1075,9 +1084,11 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd
)
if (cmdp->param.cont || cmdp->param.data)
ctx->literal_pending = 0;
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;
- else {
+ } else {
if (!strcmp( "NO", arg )) {
if (cmdp->param.create && cmd &&
(cmdp->param.trycreate || !memcmp( cmd, "[TRYCREATE]", 11 ))) { /* SELECT,
APPEND or UID COPY */
p = strchr( cmdp->cmd, '"' );
@@ -1671,6 +1682,7 @@ imap_trash_msg( store_t *gctx, message_t *msg,
imap_store_t *ctx = (imap_store_t *)gctx;
struct imap_cmd *cmd = new_imap_cmd();
cmd->param.create = 1;
+ cmd->param.to_trash = 1;
return cb( imap_exec_m( ctx, cmd, "UID COPY %d \"%s%s\"",
msg->uid, ctx->prefix, gctx->conf->trash ), aux
);
}
@@ -1701,18 +1713,14 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int
to_trash,
box = gctx->conf->trash;
prefix = ctx->prefix;
cmd->param.create = 1;
- if (ctx->trashnc)
- ctx->caps = ctx->rcaps & ~(1 << LITERALPLUS);
+ cmd->param.to_trash = 1;
} else {
box = gctx->name;
prefix = !strcmp( box, "INBOX" ) ? "" : ctx->prefix;
}
ret = imap_exec_m( ctx, cmd, "APPEND \"%s%s\" %s", prefix, box, flagstr
);
- ctx->caps = ctx->rcaps;
if (ret != DRV_OK)
return cb( ret, -1, aux );
- if (to_trash)
- ctx->trashnc = 0;
return cb( DRV_OK, uid, aux );
}
------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel