From f06691c8d9db402f47bb6b3ad06ff5ecbbd9e8b8 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Sun, 17 May 2015 13:33:21 +0200 Subject: [PATCH] factor out imap_server --- src/drv_imap.c | 298 ++++++++++++++++++++++++++----------------------- 1 file changed, 157 insertions(+), 141 deletions(-) diff --git a/src/drv_imap.c b/src/drv_imap.c index 4911f18..3e6beeb 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -94,22 +94,14 @@ typedef struct parse_list_state { struct imap_cmd; -typedef struct imap_store { - store_t gen; - const char *label; /* foreign */ - const char *prefix; - const char *name; - int ref_count; - 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 */ - message_t **msgapp; /* FETCH results */ +typedef struct imap_server { + int got_namespace; uint caps; /* CAPABILITY results */ + list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */ string_list_t *auth_mechs; + parse_list_state_t parse_list_sts; + /* command queue */ int nexttag, num_in_progress; struct imap_cmd *pending, **pending_append; @@ -121,17 +113,37 @@ typedef struct imap_store { 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; #endif conn_t conn; /* this is BIG, so put it last */ +} imap_server_t; + +typedef struct imap_store { + store_t gen; + imap_server_t *server; + const char *label; /* foreign */ + const char *prefix; + const char *name; + int ref_count; + /* XXX this doesn't really make sense in the new world: + bad: bad server + half: good server + good: good server+store + */ + enum { SST_BAD, SST_HALF, SST_GOOD } state; + /* trash folder's existence is not confirmed yet */ + enum { TrashUnknown, TrashChecking, TrashKnown } trashnc; + char delimiter[2]; /* hierarchy delimiter */ + message_t **msgapp; /* FETCH results */ + + union { + void (*imap_open)( int, void *aux ); + void (*imap_cancel)( void *aux ); + } callbacks; + void *callback_aux; } imap_store_t; struct imap_cmd { @@ -189,7 +201,7 @@ struct imap_cmd_refcounted { struct imap_cmd_refcounted_state *state; }; -#define CAP(cap) (ctx->caps & (1 << (cap))) +#define CAP(cap) (ctx->server->caps & (1 << (cap))) enum CAPABILITY { NOLOGIN = 0, @@ -262,7 +274,7 @@ done_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd, int response ) cmd->param.done( ctx, cmd, response ); if (cmd->param.data) { free( cmd->param.data ); - ctx->buffer_mem -= cmd->param.data_len; + ctx->server->buffer_mem -= cmd->param.data_len; } free( cmd->cmd ); free( cmd ); @@ -276,7 +288,7 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd ) conn_iovec_t iov[3]; char buf[1024]; - cmd->tag = ++ctx->nexttag; + cmd->tag = ++ctx->server->nexttag; if (!cmd->param.data) { buffmt = "%d %s\r\n"; litplus = 0; @@ -290,8 +302,8 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd ) bufl = nfsnprintf( buf, sizeof(buf), buffmt, cmd->tag, cmd->cmd, cmd->param.data_len ); if (DFlags & DEBUG_NET) { - if (ctx->num_in_progress) - printf( "(%d in progress) ", ctx->num_in_progress ); + if (ctx->server->num_in_progress) + printf( "(%d in progress) ", ctx->server->num_in_progress ); if (starts_with( cmd->cmd, -1, "LOGIN", 5 )) printf( "%s>>> %d LOGIN \n", ctx->label, cmd->tag ); else if (starts_with( cmd->cmd, -1, "AUTHENTICATE PLAIN", 18 )) @@ -308,20 +320,20 @@ send_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd ) iov[1].len = cmd->param.data_len; iov[1].takeOwn = GiveOwn; cmd->param.data = 0; - ctx->buffer_mem -= cmd->param.data_len; + ctx->server->buffer_mem -= cmd->param.data_len; iov[2].buf = "\r\n"; iov[2].len = 2; iov[2].takeOwn = KeepOwn; iovcnt = 3; } - socket_write( &ctx->conn, iov, iovcnt ); + socket_write( &ctx->server->conn, iov, iovcnt ); if (cmd->param.to_trash && ctx->trashnc == TrashUnknown) ctx->trashnc = TrashChecking; cmd->next = 0; - *ctx->in_progress_append = cmd; - ctx->in_progress_append = &cmd->next; - ctx->num_in_progress++; - socket_expect_read( &ctx->conn, 1 ); + *ctx->server->in_progress_append = cmd; + ctx->server->in_progress_append = &cmd->next; + ctx->server->num_in_progress++; + socket_expect_read( &ctx->server->conn, 1 ); } static int @@ -329,13 +341,13 @@ cmd_sendable( imap_store_t *ctx, struct imap_cmd *cmd ) { struct imap_cmd *cmdp; - return !ctx->conn.write_buf && - !(ctx->in_progress && - (cmdp = (struct imap_cmd *)((char *)ctx->in_progress_append - + return !ctx->server->conn.write_buf && + !(ctx->server->in_progress && + (cmdp = (struct imap_cmd *)((char *)ctx->server->in_progress_append - offsetof(struct imap_cmd, next)), 1) && (cmdp->param.cont || cmdp->param.data)) && !(cmd->param.to_trash && ctx->trashnc == TrashChecking) && - ctx->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress; + ctx->server->num_in_progress < ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress; } static void @@ -343,9 +355,9 @@ flush_imap_cmds( imap_store_t *ctx ) { struct imap_cmd *cmd; - if ((cmd = ctx->pending) && cmd_sendable( ctx, cmd )) { - if (!(ctx->pending = cmd->next)) - ctx->pending_append = &ctx->pending; + if ((cmd = ctx->server->pending) && cmd_sendable( ctx, cmd )) { + if (!(ctx->server->pending = cmd->next)) + ctx->server->pending_append = &ctx->server->pending; send_imap_cmd( ctx, cmd ); } } @@ -355,9 +367,9 @@ cancel_pending_imap_cmds( imap_store_t *ctx ) { struct imap_cmd *cmd; - while ((cmd = ctx->pending)) { - if (!(ctx->pending = cmd->next)) - ctx->pending_append = &ctx->pending; + while ((cmd = ctx->server->pending)) { + if (!(ctx->server->pending = cmd->next)) + ctx->server->pending_append = &ctx->server->pending; done_imap_cmd( ctx, cmd, RESP_CANCEL ); } } @@ -367,9 +379,9 @@ cancel_sent_imap_cmds( imap_store_t *ctx ) { struct imap_cmd *cmd; - socket_expect_read( &ctx->conn, 0 ); - while ((cmd = ctx->in_progress)) { - ctx->in_progress = cmd->next; + socket_expect_read( &ctx->server->conn, 0 ); + while ((cmd = ctx->server->in_progress)) { + ctx->server->in_progress = cmd->next; /* don't update num_in_progress and in_progress_append - store is dead */ done_imap_cmd( ctx, cmd, RESP_CANCEL ); } @@ -383,14 +395,14 @@ submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd ) assert( cmd ); assert( cmd->param.done ); - if ((ctx->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) { - if (ctx->pending && cmd->param.high_prio) { - cmd->next = ctx->pending; - ctx->pending = cmd; + if ((ctx->server->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) { + if (ctx->server->pending && cmd->param.high_prio) { + cmd->next = ctx->server->pending; + ctx->server->pending = cmd; } else { cmd->next = 0; - *ctx->pending_append = cmd; - ctx->pending_append = &cmd->next; + *ctx->server->pending_append = cmd; + ctx->server->pending_append = &cmd->next; } } else { send_imap_cmd( ctx, cmd ); @@ -729,10 +741,10 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts ) s[cur->len] = 0; getbytes: - n = socket_read( &ctx->conn, s, bytes ); + n = socket_read( &ctx->server->conn, s, bytes ); if (n < 0) { badeof: - error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name ); + error( "IMAP error: unexpected EOF from %s\n", ctx->server->conn.name ); goto bail; } bytes -= n; @@ -747,7 +759,7 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts ) } getline: - if (!(s = socket_read_line( &ctx->conn ))) + if (!(s = socket_read_line( &ctx->server->conn ))) goto postpone; if (s == (void *)~0) goto badeof; @@ -821,10 +833,10 @@ parse_list_continue( imap_store_t *ctx, char *s ) { list_t *list; int resp; - if ((resp = parse_imap_list( ctx, &s, &ctx->parse_list_sts )) != LIST_PARTIAL) { - list = (resp == LIST_BAD) ? 0 : ctx->parse_list_sts.head; - ctx->parse_list_sts.head = 0; - resp = ctx->parse_list_sts.callback( ctx, list, s ); + if ((resp = parse_imap_list( ctx, &s, &ctx->server->parse_list_sts )) != LIST_PARTIAL) { + list = (resp == LIST_BAD) ? 0 : ctx->server->parse_list_sts.head; + ctx->server->parse_list_sts.head = 0; + resp = ctx->server->parse_list_sts.callback( ctx, list, s ); } return resp; } @@ -832,8 +844,8 @@ parse_list_continue( imap_store_t *ctx, char *s ) static int parse_list( imap_store_t *ctx, char *s, int (*cb)( imap_store_t *ctx, list_t *list, char *s ) ) { - parse_list_init( &ctx->parse_list_sts ); - ctx->parse_list_sts.callback = cb; + parse_list_init( &ctx->server->parse_list_sts ); + ctx->server->parse_list_sts.callback = cb; return parse_list_continue( ctx, s ); } @@ -850,7 +862,7 @@ parse_namespace_rsp_fail( void ) static int parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s ) { - if (!(ctx->ns_personal = list)) + if (!(ctx->server->ns_personal = list)) return parse_namespace_rsp_fail(); return parse_list( ctx, s, parse_namespace_rsp_p2 ); } @@ -858,7 +870,7 @@ parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s ) static int parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s ) { - if (!(ctx->ns_other = list)) + if (!(ctx->server->ns_other = list)) return parse_namespace_rsp_fail(); return parse_list( ctx, s, parse_namespace_rsp_p3 ); } @@ -866,7 +878,7 @@ parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s ) static int parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) { - if (!(ctx->ns_shared = list)) + if (!(ctx->server->ns_shared = list)) return parse_namespace_rsp_fail(); return LIST_OK; } @@ -982,7 +994,7 @@ parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) } if (body) { - for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) + for (cmdp = ctx->server->in_progress; cmdp; cmdp = cmdp->next) if (cmdp->param.uid == uid) goto gotuid; error( "IMAP error: unexpected FETCH response (UID %d)\n", uid ); @@ -1024,21 +1036,21 @@ parse_capability( imap_store_t *ctx, char *cmd ) char *arg; uint i; - free_string_list( ctx->auth_mechs ); - ctx->auth_mechs = 0; - ctx->caps = 0x80000000; + free_string_list( ctx->server->auth_mechs ); + ctx->server->auth_mechs = 0; + ctx->server->caps = 0x80000000; while ((arg = next_arg( &cmd ))) { if (starts_with( arg, -1, "AUTH=", 5 )) { - add_string_list( &ctx->auth_mechs, arg + 5 ); + add_string_list( &ctx->server->auth_mechs, arg + 5 ); } else { for (i = 0; i < as(cap_list); i++) if (!strcmp( cap_list[i], arg )) - ctx->caps |= 1 << i; + ctx->server->caps |= 1 << i; } } - ctx->caps &= ~((imap_store_conf_t *)ctx->gen.conf)->server->cap_mask; + ctx->server->caps &= ~((imap_store_conf_t *)ctx->gen.conf)->server->cap_mask; if (!CAP(NOLOGIN)) - add_string_list( &ctx->auth_mechs, "LOGIN" ); + add_string_list( &ctx->server->auth_mechs, "LOGIN" ); } static int @@ -1218,7 +1230,7 @@ imap_socket_read( void *aux ) conn_iovec_t iov[2]; for (;;) { - if (ctx->parse_list_sts.level) { + if (ctx->server->parse_list_sts.level) { resp = parse_list_continue( ctx, 0 ); listret: if (resp == LIST_PARTIAL) @@ -1227,11 +1239,11 @@ imap_socket_read( void *aux ) break; continue; } - if (!(cmd = socket_read_line( &ctx->conn ))) + if (!(cmd = socket_read_line( &ctx->server->conn ))) return; if (cmd == (void *)~0) { - if (!ctx->expectEOF) - error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name ); + if (!ctx->server->expectEOF) + error( "IMAP error: unexpected EOF from %s\n", ctx->server->conn.name ); /* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */ break; } @@ -1252,9 +1264,9 @@ imap_socket_read( void *aux ) break; } - if (ctx->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) { + if (ctx->server->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) { parse_response_code( ctx, 0, cmd ); - ctx->greeting = GreetingPreauth; + ctx->server->greeting = GreetingPreauth; dogreet: imap_ref( ctx ); imap_open_store_greeted( ctx ); @@ -1262,20 +1274,20 @@ imap_socket_read( void *aux ) return; } else if (!strcmp( "OK", arg )) { parse_response_code( ctx, 0, cmd ); - if (ctx->greeting == GreetingPending) { - ctx->greeting = GreetingOk; + if (ctx->server->greeting == GreetingPending) { + ctx->server->greeting = GreetingOk; goto dogreet; } } else if (!strcmp( "BYE", arg )) { - if (!ctx->expectBYE) { - ctx->greeting = GreetingBad; + if (!ctx->server->expectBYE) { + ctx->server->greeting = GreetingBad; error( "IMAP error: unexpected BYE response: %s\n", cmd ); /* We just wait for the server to close the connection now. */ - ctx->expectEOF = 1; + ctx->server->expectEOF = 1; } else { /* We still need to wait for the LOGOUT's tagged OK. */ } - } else if (ctx->greeting == GreetingPending) { + } else if (ctx->server->greeting == GreetingPending) { error( "IMAP error: bogus greeting response %s\n", arg ); break; } else if (!strcmp( "NO", arg )) { @@ -1304,14 +1316,14 @@ imap_socket_read( void *aux ) break; /* this may mean anything, so prefer not to spam the log */ } continue; - } else if (!ctx->in_progress) { + } else if (!ctx->server->in_progress) { error( "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" ); break; /* this may mean anything, so prefer not to spam the log */ } else if (*arg == '+') { - socket_expect_read( &ctx->conn, 0 ); + socket_expect_read( &ctx->server->conn, 0 ); /* There can be any number of commands in flight, but only the last * one can require a continuation, as it enforces a round-trip. */ - cmdp = (struct imap_cmd *)((char *)ctx->in_progress_append - + cmdp = (struct imap_cmd *)((char *)ctx->server->in_progress_append - offsetof(struct imap_cmd, next)); if (cmdp->param.data) { if (cmdp->param.to_trash) @@ -1320,11 +1332,11 @@ imap_socket_read( void *aux ) iov[0].len = cmdp->param.data_len; iov[0].takeOwn = GiveOwn; cmdp->param.data = 0; - ctx->buffer_mem -= cmdp->param.data_len; + ctx->server->buffer_mem -= cmdp->param.data_len; iov[1].buf = "\r\n"; iov[1].len = 2; iov[1].takeOwn = KeepOwn; - socket_write( &ctx->conn, iov, 2 ); + socket_write( &ctx->server->conn, iov, 2 ); } else if (cmdp->param.cont) { if (cmdp->param.cont( ctx, cmdp, cmd )) return; @@ -1332,19 +1344,19 @@ imap_socket_read( void *aux ) error( "IMAP error: unexpected command continuation request\n" ); break; } - socket_expect_read( &ctx->conn, 1 ); + socket_expect_read( &ctx->server->conn, 1 ); } else { tag = atoi( arg ); - for (pcmdp = &ctx->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next) + for (pcmdp = &ctx->server->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next) if (cmdp->tag == tag) goto gottag; error( "IMAP error: unexpected tag %s\n", arg ); break; gottag: if (!(*pcmdp = cmdp->next)) - ctx->in_progress_append = pcmdp; - if (!--ctx->num_in_progress) - socket_expect_read( &ctx->conn, 0 ); + ctx->server->in_progress_append = pcmdp; + if (!--ctx->server->num_in_progress) + socket_expect_read( &ctx->server->conn, 0 ); arg = next_arg( &cmd ); if (!arg) { error( "IMAP error: malformed tagged response\n" ); @@ -1388,8 +1400,8 @@ imap_socket_read( void *aux ) done_imap_cmd( ctx, cmdp, resp ); if (imap_deref( ctx )) return; - if (ctx->canceling && !ctx->in_progress) { - ctx->canceling = 0; + if (ctx->server->canceling && !ctx->server->in_progress) { + ctx->server->canceling = 0; ctx->callbacks.imap_cancel( ctx->callback_aux ); return; } @@ -1421,10 +1433,11 @@ get_cmd_result_p2( imap_store_t *ctx, struct imap_cmd *cmd, int response ) static void -imap_cleanup_store( imap_store_t *ctx ) +imap_cancel_store_only( imap_store_t *ctx ) { free_generic_messages( ctx->gen.msgs ); free_string_list( ctx->gen.boxes ); + imap_deref( ctx ); } static void @@ -1433,17 +1446,16 @@ imap_cancel_store( store_t *gctx ) imap_store_t *ctx = (imap_store_t *)gctx; #ifdef HAVE_LIBSASL - sasl_dispose( &ctx->sasl ); + sasl_dispose( &ctx->server->sasl ); #endif - socket_close( &ctx->conn ); + socket_close( &ctx->server->conn ); cancel_sent_imap_cmds( ctx ); cancel_pending_imap_cmds( ctx ); - free_list( ctx->ns_personal ); - free_list( ctx->ns_other ); - free_list( ctx->ns_shared ); - free_string_list( ctx->auth_mechs ); - imap_cleanup_store( ctx ); - imap_deref( ctx ); + free_list( ctx->server->ns_personal ); + free_list( ctx->server->ns_other ); + free_list( ctx->server->ns_shared ); + free_string_list( ctx->server->auth_mechs ); + imap_cancel_store_only( ctx ); } static int @@ -1502,7 +1514,7 @@ imap_cleanup( void ) nctx = ctx->next; set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx ); if (((imap_store_t *)ctx)->state != SST_BAD) { - ((imap_store_t *)ctx)->expectBYE = 1; + ((imap_store_t *)ctx)->server->expectBYE = 1; imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" ); } else { imap_cancel_store( ctx ); @@ -1517,7 +1529,7 @@ imap_cleanup_p2( imap_store_t *ctx, if (response == RESP_NO) imap_cancel_store( &ctx->gen ); else if (response == RESP_OK) - ctx->expectEOF = 1; + ctx->server->expectEOF = 1; } /******************* imap_open_store *******************/ @@ -1554,6 +1566,7 @@ imap_alloc_store( store_conf_t *conf, const char *label ) imap_store_conf_t *cfg = (imap_store_conf_t *)conf; imap_server_conf_t *srvc = cfg->server; imap_store_t *ctx; + imap_server_t *server = 0; store_t **ctxp; /* First try to recycle a whole store. */ @@ -1568,7 +1581,8 @@ imap_alloc_store( store_conf_t *conf, const char *label ) for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next) if (ctx->state != SST_BAD && ((imap_store_conf_t *)ctx->gen.conf)->server == srvc) { *ctxp = ctx->gen.next; - imap_cleanup_store( ctx ); + server = ctx->server; + imap_cancel_store_only( ctx ); /* One could ping the server here, but given that the idle timeout * is at least 30 minutes, this sounds pretty pointless. */ ctx->state = SST_HALF; @@ -1576,15 +1590,17 @@ imap_alloc_store( store_conf_t *conf, const char *label ) } /* Finally, schedule opening a new server connection. */ - ctx = nfcalloc( sizeof(*ctx) ); - socket_init( &ctx->conn, &srvc->sconf, + server = nfcalloc( sizeof(*server) ); + socket_init( &server->conn, &srvc->sconf, (void (*)( void * ))imap_invoke_bad_callback, imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx ); - ctx->in_progress_append = &ctx->in_progress; - ctx->pending_append = &ctx->pending; + server->in_progress_append = &server->in_progress; + server->pending_append = &server->pending; gotsrv: + ctx = nfcalloc( sizeof(*ctx) ); ctx->gen.conf = conf; + ctx->server = server; ctx->label = label; ctx->ref_count = 1; return &ctx->gen; @@ -1604,7 +1620,7 @@ imap_connect_store( store_t *gctx, if (ctx->state == SST_HALF) imap_open_store_namespace( ctx ); else - socket_connect( &ctx->conn, imap_open_store_connected ); + socket_connect( &ctx->server->conn, imap_open_store_connected ); } } @@ -1621,10 +1637,10 @@ imap_open_store_connected( int ok, void *aux ) imap_open_store_bail( ctx, FAIL_WAIT ); #ifdef HAVE_LIBSSL else if (srvc->ssl_type == SSL_IMAPS) - socket_start_tls( &ctx->conn, imap_open_store_tlsstarted1 ); + socket_start_tls( &ctx->server->conn, imap_open_store_tlsstarted1 ); #endif else - socket_expect_read( &ctx->conn, 1 ); + socket_expect_read( &ctx->server->conn, 1 ); } #ifdef HAVE_LIBSSL @@ -1636,15 +1652,15 @@ imap_open_store_tlsstarted1( int ok, void *aux ) if (!ok) imap_open_store_ssl_bail( ctx ); else - socket_expect_read( &ctx->conn, 1 ); + socket_expect_read( &ctx->server->conn, 1 ); } #endif static void imap_open_store_greeted( imap_store_t *ctx ) { - socket_expect_read( &ctx->conn, 0 ); - if (!ctx->caps) + socket_expect_read( &ctx->server->conn, 0 ); + if (!ctx->server->caps) imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" ); else imap_open_store_authenticate( ctx ); @@ -1667,7 +1683,7 @@ imap_open_store_authenticate( imap_store_t *ctx ) imap_server_conf_t *srvc = cfg->server; #endif - if (ctx->greeting != GreetingPreauth) { + if (ctx->server->greeting != GreetingPreauth) { #ifdef HAVE_LIBSSL if (srvc->ssl_type == SSL_STARTTLS) { if (CAP(STARTTLS)) { @@ -1700,7 +1716,7 @@ imap_open_store_authenticate_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UN if (response == RESP_NO) imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) - socket_start_tls( &ctx->conn, imap_open_store_tlsstarted2 ); + socket_start_tls( &ctx->server->conn, imap_open_store_tlsstarted2 ); } static void @@ -1836,14 +1852,14 @@ process_sasl_step( imap_store_t *ctx, int rc, const char *in, uint in_len, while (rc == SASL_INTERACT) { if (process_sasl_interact( interact, srvc ) < 0) return -1; - rc = sasl_client_step( ctx->sasl, in, in_len, &interact, out, out_len ); + rc = sasl_client_step( ctx->server->sasl, in, in_len, &interact, out, out_len ); } if (rc == SASL_CONTINUE) { - ctx->sasl_cont = 1; + ctx->server->sasl_cont = 1; } else if (rc == SASL_OK) { - ctx->sasl_cont = 0; + ctx->server->sasl_cont = 0; } else { - error( "Error: %s\n", sasl_errdetail( ctx->sasl ) ); + error( "Error: %s\n", sasl_errdetail( ctx->server->sasl ) ); return -1; } return 0; @@ -1895,13 +1911,13 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char * sasl_interact_t *interact = NULL; conn_iovec_t iov[2]; - if (!ctx->sasl_cont) { + if (!ctx->server->sasl_cont) { error( "Error: IMAP wants more steps despite successful SASL authentication.\n" ); goto bail; } if (decode_sasl_data( prompt, &in, &in_len ) < 0) goto bail; - rc = sasl_client_step( ctx->sasl, in, in_len, &interact, &out, &out_len ); + rc = sasl_client_step( ctx->server->sasl, in, in_len, &interact, &out, &out_len ); ret = process_sasl_step( ctx, rc, in, in_len, interact, &out, &out_len ); free( in ); if (ret < 0) @@ -1930,7 +1946,7 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char * iov[iovcnt].len = 2; iov[iovcnt].takeOwn = KeepOwn; iovcnt++; - socket_write( &ctx->conn, iov, iovcnt ); + socket_write( &ctx->server->conn, iov, iovcnt ); return 0; bail: @@ -1941,11 +1957,11 @@ do_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmdp ATTR_UNUSED, const char * static void done_sasl_auth( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED, int response ) { - if (response == RESP_OK && ctx->sasl_cont) { + if (response == RESP_OK && ctx->server->sasl_cont) { sasl_interact_t *interact = NULL; const char *out; uint out_len; - int rc = sasl_client_step( ctx->sasl, NULL, 0, &interact, &out, &out_len ); + int rc = sasl_client_step( ctx->server->sasl, NULL, 0, &interact, &out, &out_len ); if (process_sasl_step( ctx, rc, NULL, 0, interact, &out, &out_len ) < 0) warn( "Warning: SASL reported failure despite successful IMAP authentication. Ignoring...\n" ); else if (out) @@ -1971,11 +1987,11 @@ imap_open_store_authenticate2( imap_store_t *ctx ) info( "Logging in...\n" ); for (mech = srvc->auth_mechs; mech; mech = mech->next) { int any = !strcmp( mech->string, "*" ); - for (cmech = ctx->auth_mechs; cmech; cmech = cmech->next) { + for (cmech = ctx->server->auth_mechs; cmech; cmech = cmech->next) { if (any || !strcasecmp( mech->string, cmech->string )) { if (!strcasecmp( cmech->string, "LOGIN" )) { #ifdef HAVE_LIBSSL - if (ctx->conn.ssl || !any) + if (ctx->server->conn.ssl || !any) #endif auth_login = 1; } else { @@ -2014,15 +2030,15 @@ imap_open_store_authenticate2( imap_store_t *ctx ) sasl_inited = 1; } - rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->sasl ); + rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->server->sasl ); if (rc != SASL_OK) { - if (!ctx->sasl) + if (!ctx->server->sasl) goto saslbail; - error( "Error: %s\n", sasl_errdetail( ctx->sasl ) ); + error( "Error: %s\n", sasl_errdetail( ctx->server->sasl ) ); goto bail; } - rc = sasl_client_start( ctx->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech ); + rc = sasl_client_start( ctx->server->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech ); if (gotmech) info( "Authenticating with SASL mechanism %s...\n", gotmech ); /* Technically, we are supposed to loop over sasl_client_start(), @@ -2047,7 +2063,7 @@ imap_open_store_authenticate2( imap_store_t *ctx ) if (!ensure_user( srvc ) || !ensure_password( srvc )) goto bail; #ifdef HAVE_LIBSSL - if (!ctx->conn.ssl) + if (!ctx->server->conn.ssl) #endif warn( "*** IMAP Warning *** Password is being sent in the clear\n" ); imap_exec( ctx, 0, imap_open_store_authenticate2_p2, @@ -2089,7 +2105,7 @@ imap_open_store_compress_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSED /* We already reported an error, but it's not fatal to us. */ imap_open_store_namespace( ctx ); } else if (response == RESP_OK) { - socket_start_deflate( &ctx->conn ); + socket_start_deflate( &ctx->server->conn ); imap_open_store_namespace( ctx ); } } @@ -2105,7 +2121,7 @@ imap_open_store_namespace( imap_store_t *ctx ) ctx->delimiter[0] = cfg->delimiter ? cfg->delimiter : 0; if (((!ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) { /* get NAMESPACE info */ - if (!ctx->got_namespace) + if (!ctx->server->got_namespace) imap_exec( ctx, 0, imap_open_store_namespace_p2, "NAMESPACE" ); else imap_open_store_namespace2( ctx ); @@ -2120,7 +2136,7 @@ imap_open_store_namespace_p2( imap_store_t *ctx, struct imap_cmd *cmd ATTR_UNUSE if (response == RESP_NO) { imap_open_store_bail( ctx, FAIL_FINAL ); } else if (response == RESP_OK) { - ctx->got_namespace = 1; + ctx->server->got_namespace = 1; imap_open_store_namespace2( ctx ); } } @@ -2132,7 +2148,7 @@ imap_open_store_namespace2( imap_store_t *ctx ) list_t *nsp, *nsp_1st, *nsp_1st_ns, *nsp_1st_dl; /* XXX for now assume 1st personal namespace */ - if (is_list( (nsp = ctx->ns_personal) ) && + if (is_list( (nsp = ctx->server->ns_personal) ) && is_list( (nsp_1st = nsp->child) ) && is_atom( (nsp_1st_ns = nsp_1st->child) ) && is_atom( (nsp_1st_dl = nsp_1st_ns->next) )) @@ -2162,7 +2178,7 @@ static void imap_open_store_ssl_bail( imap_store_t *ctx ) { /* This avoids that we try to send LOGOUT to an unusable socket. */ - socket_close( &ctx->conn ); + socket_close( &ctx->server->conn ); imap_open_store_bail( ctx, FAIL_FINAL ); } #endif @@ -2545,7 +2561,7 @@ imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash, flagstr[d] = 0; INIT_IMAP_CMD(imap_cmd_out_uid, cmd, cb, aux) - ctx->buffer_mem += data->len; + ctx->server->buffer_mem += data->len; cmd->gen.param.data_len = data->len; cmd->gen.param.data = data->data; cmd->out_uid = -2; @@ -2642,8 +2658,8 @@ imap_cancel_cmds( store_t *gctx, imap_store_t *ctx = (imap_store_t *)gctx; cancel_pending_imap_cmds( ctx ); - if (ctx->in_progress) { - ctx->canceling = 1; + if (ctx->server->in_progress) { + ctx->server->canceling = 1; ctx->callbacks.imap_cancel = cb; ctx->callback_aux = aux; } else { @@ -2666,7 +2682,7 @@ imap_memory_usage( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; - return ctx->buffer_mem + ctx->conn.buffer_mem; + return ctx->server->buffer_mem + ctx->server->conn.buffer_mem; } /******************* imap_fail_state *******************/