diff --git a/src/driver.c b/src/driver.c index e522d14..e28d817 100644 --- a/src/driver.c +++ b/src/driver.c @@ -27,6 +27,15 @@ driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver }; +int +count_generic_messages( message_t *msgs ) +{ + int count = 0; + for (; msgs; msgs = msgs->next) + count++; + return count; +} + void free_generic_messages( message_t *msgs ) { diff --git a/src/driver.h b/src/driver.h index 00c5581..08edf20 100644 --- a/src/driver.h +++ b/src/driver.h @@ -261,6 +261,7 @@ struct driver { int (*get_fail_state)( store_conf_t *conf ); }; +int count_generic_messages( message_t * ); void free_generic_messages( message_t * ); void parse_generic_store( store_conf_t *store, conffile_t *cfg ); diff --git a/src/drv_imap.c b/src/drv_imap.c index 03eaf30..58fc9d3 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -291,7 +291,7 @@ send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) int bufl, litplus, iovcnt = 1; const char *buffmt; conn_iovec_t iov[3]; - char buf[1024]; + char buf[4096]; cmd->tag = ++ctx->nexttag; if (!cmd->param.data) { @@ -448,7 +448,7 @@ imap_vprintf( const char *fmt, va_list ap ) char *d, *ed; int maxlen; char c; - char buf[1024]; /* Minimal supported command buffer size per IMAP spec. */ + char buf[4096]; d = buf; ed = d + sizeof(buf); @@ -601,8 +601,9 @@ imap_refcounted_new_cmd( imap_cmd_refcounted_state_t *sts ) free( sts ); \ } -#define DONE_REFCOUNTED_STATE_ARGS(sts, ...) \ +#define DONE_REFCOUNTED_STATE_ARGS(sts, finalize, ...) \ if (!--sts->gen.ref_count) { \ + finalize \ sts->callback( sts->gen.ret_val, __VA_ARGS__, sts->callback_aux ); \ free( sts ); \ } @@ -1108,7 +1109,6 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) if (status & M_FLAGS) msgdata->flags = mask; } else { - /* XXX this will need sorting for out-of-order (multiple queries) */ cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = &cur->gen; ctx->msgapp = &cur->gen.next; @@ -2593,6 +2593,47 @@ imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenui } } +static int +imap_sort_msgs_comp( const void *a_, const void *b_ ) +{ + const message_t *a = *(const message_t * const *)a_; + const message_t *b = *(const message_t * const *)b_; + + if (a->uid < b->uid) + return -1; + if (a->uid > b->uid) + return 1; + return 0; +} + +static void +imap_sort_msgs( imap_store_t *ctx ) +{ + int count = count_generic_messages( ctx->msgs ); + if (count <= 1) + return; + + message_t **t = nfmalloc( sizeof(*t) * count ); + + message_t *m = ctx->msgs; + for (int i = 0; i < count; i++) { + t[i] = m; + m = m->next; + } + + qsort( t, count, sizeof(*t), imap_sort_msgs_comp ); + + ctx->msgs = t[0]; + + int j; + for (j = 0; j < count - 1; j++) + t[j]->next = t[j + 1]; + ctx->msgapp = &t[j]->next; + *ctx->msgapp = NULL; + + free( t ); +} + static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int ); static void @@ -2621,7 +2662,10 @@ imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) + DONE_REFCOUNTED_STATE_ARGS(sts, { + if (sts->gen.ret_val == DRV_OK) + imap_sort_msgs( ctx ); + }, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) } /******************* imap_fetch_msg *******************/ @@ -3018,7 +3062,7 @@ imap_list_store_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) static void imap_list_store_p3( imap_store_t *ctx, imap_list_store_state_t *sts ) { - DONE_REFCOUNTED_STATE_ARGS(sts, ctx->boxes) + DONE_REFCOUNTED_STATE_ARGS(sts, , ctx->boxes) } /******************* imap_cancel_cmds *******************/ diff --git a/src/socket.c b/src/socket.c index dd79619..e3fda42 100644 --- a/src/socket.c +++ b/src/socket.c @@ -271,6 +271,8 @@ socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) ) init_wakeup( &conn->ssl_fake, ssl_fake_cb, conn ); conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ); + if (ssl_return( "set server name", conn, SSL_set_tlsext_host_name( conn->ssl, conn->conf->host ) ) < 0) + return; SSL_set_fd( conn->ssl, conn->fd ); SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); socket_expect_read( conn, 1 );