Skipped 2 existing revision(s) on branch '1.4'. commit 444601a1e07b8b3e74a4a20b31c71b16f3c61994 Merge: a86e6f8 ed3bfda Author: Oswald Buddenhagen <o...@users.sf.net> Date: Thu Jun 3 11:04:56 2021 +0200
Merge branch '1.3' into 1.4 Conflicts: configure.ac src/drv_imap.c src/drv_imap.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --cc src/drv_imap.c index edae95c,4cc3b2a..3c85c4d --- a/src/drv_imap.c +++ b/src/drv_imap.c @@@ -110,142 -94,111 +110,141 @@@ typedef struct typedef struct imap_cmd imap_cmd_t; -struct imap_store { +union imap_store { store_t gen; - const char *label; /* foreign */ - const char *prefix; - const char *name; - int ref_count; - uint opts; - enum { SST_BAD, SST_HALF, SST_GOOD } state; - /* trash folder's existence is not confirmed yet */ - enum { TrashUnknown, TrashChecking, TrashKnown } trashnc; - uint got_namespace:1; - char delimiter[2]; /* hierarchy delimiter */ - list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */ - string_list_t *boxes; // _list results - char listed; // was _list already run with these flags? - // note that the message counts do _not_ reflect stats from msgs, - // but mailbox totals. also, don't trust them beyond the initial load. - int total_msgs, recent_msgs; - uint uidvalidity, uidnext; - message_t *msgs; - message_t **msgapp; /* FETCH results */ - uint caps; /* CAPABILITY results */ - string_list_t *auth_mechs; - parse_list_state_t parse_list_sts; - /* command queue */ - int nexttag, num_in_progress; - imap_cmd_t *pending, **pending_append; - imap_cmd_t *in_progress, **in_progress_append; - int buffer_mem; /* memory currently occupied by buffers in the queue */ - - /* Used during sequential operations like connect */ - enum { GreetingPending = 0, GreetingBad, GreetingOk, GreetingPreauth } greeting; - int expectBYE; /* LOGOUT is in progress */ - int expectEOF; /* received LOGOUT's OK or unsolicited BYE */ - int canceling; /* imap_cancel() is in progress */ - union { - void (*imap_open)( int sts, void *aux ); - void (*imap_cancel)( void *aux ); - } callbacks; - void *callback_aux; + struct { + STORE(union imap_store) + const char *label; // foreign + const char *name; + char *prefix; + uint ref_count; + uint opts; + enum { SST_BAD, SST_HALF, SST_GOOD } state; + // The trash folder's existence is not confirmed yet + enum { TrashUnknown, TrashChecking, TrashKnown } trashnc; + // What kind of BODY-less FETCH response we're expecting + enum { FetchNone, FetchMsgs, FetchUidNext } fetch_sts; + uint got_namespace:1; + uint has_forwarded:1; + char delimiter[2]; // Hierarchy delimiter + char *ns_prefix, ns_delimiter; // NAMESPACE info + string_list_t *boxes; // _list results + char listed; // was _list already run with these flags? + // note that the message counts do _not_ reflect stats from msgs, + // but mailbox totals. + int total_msgs, recent_msgs; + uint uidvalidity, uidnext; + imap_message_t **msgapp, *msgs; // FETCH results + uint caps; // CAPABILITY results + string_list_t *auth_mechs; + parse_list_state_t parse_list_sts; + // Command queue + imap_cmd_t *pending, **pending_append; + imap_cmd_t *in_progress, **in_progress_append; + imap_cmd_t *wait_check, **wait_check_append; + int nexttag, num_in_progress, num_wait_check; + uint buffer_mem; // Memory currently occupied by buffers in the queue + + // Used during sequential operations like connect + enum { GreetingPending = 0, GreetingBad, GreetingOk, GreetingPreauth } greeting; + int expectBYE; // LOGOUT is in progress + int expectEOF; // received LOGOUT's OK or unsolicited BYE + int canceling; // imap_cancel() is in progress + union { + void (*imap_open)( int sts, void *aux ); + void (*imap_cancel)( void *aux ); + } callbacks; + void *callback_aux; #ifdef HAVE_LIBSASL - sasl_conn_t *sasl; - int sasl_cont; + sasl_conn_t *sasl; + int sasl_cont; #endif - void (*bad_callback)( void *aux ); - void *bad_callback_aux; + void (*bad_callback)( void *aux ); + void *bad_callback_aux; - conn_t conn; /* this is BIG, so put it last */ + conn_t conn; // This is BIG, so put it last + }; }; -struct imap_cmd { - struct imap_cmd *next; - char *cmd; - int tag; - - struct { - /* Will be called on each continuation request until it resets this pointer. - * Needs to invoke bad_callback and return -1 on error, otherwise return 0. */ - int (*cont)( imap_store_t *ctx, imap_cmd_t *cmd, const char *prompt ); - void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response ); - char *data; - int data_len; - uint uid; /* to identify fetch responses */ - char high_prio; /* if command is queued, put it at the front of the queue. */ - char to_trash; /* we are storing to trash, not current. */ - char create; /* create the mailbox if we get an error which suggests so. */ - char failok; /* Don't complain about NO response. */ - char lastuid; /* querying the last UID in the mailbox. */ +#define IMAP_CMD \ + struct imap_cmd *next; \ + char *cmd; \ + int tag; \ + \ + struct { \ + /* Will be called on each continuation request until it resets this pointer. \ + * Needs to invoke bad_callback and return -1 on error, otherwise return 0. */ \ + int (*cont)( imap_store_t *ctx, imap_cmd_t *cmd, const char *prompt ); \ + void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response ); \ + char *data; \ + uint data_len; \ + uint uid; /* to identify fetch responses */ \ + char high_prio; /* if command is queued, put it at the front of the queue. */ \ + char wait_check; /* Don't report success until subsequent CHECK success. */ \ + char to_trash; /* we are storing to trash, not current. */ \ + char create; /* create the mailbox if we get an error which suggests so. */ \ + char failok; /* Don't complain about NO response. */ \ } param; + +struct imap_cmd { + IMAP_CMD }; -typedef struct { - imap_cmd_t gen; - void (*callback)( int sts, void *aux ); +#define IMAP_CMD_SIMPLE \ + IMAP_CMD \ + void (*callback)( int sts, void *aux ); \ void *callback_aux; + +typedef union { + imap_cmd_t gen; + struct { + IMAP_CMD_SIMPLE + }; } imap_cmd_simple_t; -typedef struct { +typedef union { imap_cmd_simple_t gen; - msg_data_t *msg_data; + struct { + IMAP_CMD_SIMPLE + msg_data_t *msg_data; + }; } imap_cmd_fetch_msg_t; -typedef struct { +typedef union { imap_cmd_t gen; - void (*callback)( int sts, uint uid, void *aux ); - void *callback_aux; + struct { + IMAP_CMD + void (*callback)( int sts, uint uid, void *aux ); + void *callback_aux; - uint out_uid; + }; } imap_cmd_out_uid_t; -typedef struct { +typedef union { imap_cmd_t gen; - void (*callback)( int sts, message_t *msgs, void *aux ); - void *callback_aux; - message_t **out_msgs; - uint uid; + struct { + IMAP_CMD + void (*callback)( int sts, message_t *msgs, void *aux ); + void *callback_aux; + imap_message_t **out_msgs; + uint uid; + }; } imap_cmd_find_new_t; -typedef struct { - int ref_count; +#define IMAP_CMD_REFCOUNTED_STATE \ + uint ref_count; \ int ret_val; -} imap_cmd_refcounted_state_t; typedef struct { + IMAP_CMD_REFCOUNTED_STATE +} imap_cmd_refcounted_state_t; + +typedef union { imap_cmd_t gen; - imap_cmd_refcounted_state_t *state; + struct { + IMAP_CMD + imap_cmd_refcounted_state_t *state; + }; } imap_cmd_refcounted_t; #define CAP(cap) (ctx->caps & (1 << (cap))) @@@ -1283,17 -1181,24 +1282,28 @@@ parse_response_code( imap_store_t *ctx /* RFC2060 says that these messages MUST be displayed * to the user */ - for (; isspace( (uchar)*p ); p++); - error( "*** IMAP ALERT *** %s\n", p ); + if (!s) { + error( "IMAP error: malformed ALERT status\n" ); + return RESP_CANCEL; + } + for (; isspace( (uchar)*s ); s++); + error( "*** IMAP ALERT *** %s\n", s ); - } else if (cmd && !strcmp( "APPENDUID", arg )) { + } else if (!strcmp( "APPENDUID", arg )) { + // The checks ensure that: + // - cmd => this is the final tagged response of a command, at which + // point cmd was already removed from ctx->in_progress, so param.uid + // is available for reuse. + // - !param.uid => the command isn't actually a FETCH. This doesn't + // really matter, as the field is safe to overwrite given the + // previous condition; it just has no effect for non-APPENDs. + if (!cmd || cmd->param.uid) { + error( "IMAP error: unexpected APPENDUID status\n" ); + return RESP_CANCEL; + } if (!(arg = next_arg( &s )) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) || !(arg = next_arg( &s )) || - (((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg != ']')) - (cmd->param.uid = strtoul( arg, &earg, 10 ), *earg)) ++ (cmd->param.uid = strtoul( arg, &earg, 10 ), *earg != ']')) { error( "IMAP error: malformed APPENDUID status\n" ); return RESP_CANCEL; @@@ -3165,15 -2965,14 +3175,14 @@@ imap_store_msg( store_t *gctx, msg_data INIT_IMAP_CMD(imap_cmd_out_uid_t, cmd, cb, aux) ctx->buffer_mem += data->len; - cmd->gen.param.data_len = data->len; - cmd->gen.param.data = data->data; + cmd->param.data_len = data->len; + cmd->param.data = data->data; - cmd->out_uid = 0; if (to_trash) { - cmd->gen.param.create = 1; - cmd->gen.param.to_trash = 1; + cmd->param.create = 1; + cmd->param.to_trash = 1; if (prepare_trash( &buf, ctx ) < 0) { - cb( DRV_BOX_BAD, -1, aux ); + cb( DRV_BOX_BAD, 0, aux ); return; } } else { @@@ -3203,7 -2999,7 +3212,7 @@@ imap_store_msg_p2( imap_store_t *ctx AT imap_cmd_out_uid_t *cmdp = (imap_cmd_out_uid_t *)cmd; transform_msg_response( &response ); - cmdp->callback( response, cmdp->out_uid, cmdp->callback_aux ); - cmdp->callback( response, cmdp->gen.param.uid, cmdp->callback_aux ); ++ cmdp->callback( response, cmdp->param.uid, cmdp->callback_aux ); } /******************* imap_find_new_msgs *******************/ ===== Full diff against 1st parent ===== diff --git a/src/drv_imap.c b/src/drv_imap.c index edae95c..3c85c4d 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -217,7 +217,6 @@ typedef union { IMAP_CMD void (*callback)( int sts, uint uid, void *aux ); void *callback_aux; - uint out_uid; }; } imap_cmd_out_uid_t; @@ -1289,11 +1288,22 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s ) } for (; isspace( (uchar)*s ); s++); error( "*** IMAP ALERT *** %s\n", s ); - } else if (cmd && !strcmp( "APPENDUID", arg )) { + } else if (!strcmp( "APPENDUID", arg )) { + // The checks ensure that: + // - cmd => this is the final tagged response of a command, at which + // point cmd was already removed from ctx->in_progress, so param.uid + // is available for reuse. + // - !param.uid => the command isn't actually a FETCH. This doesn't + // really matter, as the field is safe to overwrite given the + // previous condition; it just has no effect for non-APPENDs. + if (!cmd || cmd->param.uid) { + error( "IMAP error: unexpected APPENDUID status\n" ); + return RESP_CANCEL; + } if (!(arg = next_arg( &s )) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) || !(arg = next_arg( &s )) || - (((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg != ']')) + (cmd->param.uid = strtoul( arg, &earg, 10 ), *earg != ']')) { error( "IMAP error: malformed APPENDUID status\n" ); return RESP_CANCEL; @@ -3167,7 +3177,6 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash, ctx->buffer_mem += data->len; cmd->param.data_len = data->len; cmd->param.data = data->data; - cmd->out_uid = 0; if (to_trash) { cmd->param.create = 1; @@ -3203,7 +3212,7 @@ imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response imap_cmd_out_uid_t *cmdp = (imap_cmd_out_uid_t *)cmd; transform_msg_response( &response ); - cmdp->callback( response, cmdp->out_uid, cmdp->callback_aux ); + cmdp->callback( response, cmdp->param.uid, cmdp->callback_aux ); } /******************* imap_find_new_msgs *******************/ _______________________________________________ isync-devel mailing list isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel