diff --git a/modules/mod_webmail.c b/modules/mod_webmail.c index 50e31b7..d566c03 100644 --- a/modules/mod_webmail.c +++ b/modules/mod_webmail.c @@ -2450,13 +2450,13 @@ static int fetch_mime_recurse(json_t *root, json_t *attachments, struct mailmime } break; case MAILIMF_FIELD_REPLY_TO: - append_recipients(to, f->fld_data.fld_reply_to->rt_addr_list); + append_recipients(replyto, f->fld_data.fld_reply_to->rt_addr_list); break; case MAILIMF_FIELD_TO: append_recipients(to, f->fld_data.fld_to->to_addr_list); break; case MAILIMF_FIELD_CC: - append_recipients(to, f->fld_data.fld_cc->cc_addr_list); + append_recipients(cc, f->fld_data.fld_cc->cc_addr_list); break; case MAILIMF_FIELD_SUBJECT: subject = f->fld_data.fld_subject; @@ -2934,7 +2934,6 @@ static int handle_store(struct imap_client *client, int sign, json_t *uids, cons res = mailimap_flag_list_add(flag_list, flag); if (res != MAILIMAP_NO_ERROR) { bbs_warning("LIST add failed: %s\n", maildriver_strerror(res)); - mailimap_flag_free(flag); mailimap_flag_list_free(flag_list); mailimap_set_free(set); free_if(keyword); @@ -3075,6 +3074,22 @@ static int idle_stop(struct ws_session *ws, struct imap_client *client) return 0; } +static int client_flush_pending_output(struct imap_client *client) +{ + const char *line; + + do { + if ((client->imap->imap_stream && client->imap->imap_stream->read_buffer_len) || bbs_poll(client->imapfd, 50) > 0) { + line = mailimap_read_line(client->imap); + /* Read and discard */ + bbs_debug(4, "Flushing output '%s'", line); + } else { + break; + } + } while (line); + return 0; +} + static int idle_start(struct ws_session *ws, struct imap_client *client) { UNUSED(ws); /* Formerly used to adjust net_ws timeout, not currently used */ @@ -3090,6 +3105,20 @@ static int idle_start(struct ws_session *ws, struct imap_client *client) bbs_error("Attempt to IDLE without an active mailbox?\n"); } bbs_assert_exists(client->imap->imap_selection_info); + + /* Flush any pending input before sending the IDLE command, + * or lack of synchronization could be possible which will confuse libetpan. + * For example, if we issue a MOVE command, we'll get an untagged EXPUNGE, + * and if that hasn't been read, then that may still be in the buffer. + * + * XXX This will cause us to lose updates delivered in that small amount of time + * between when we stop idling and start idling again, which is not ideal. + * In the MOVE case, we already reflect the deletion on our end, + * so we also don't want to handle that twice. */ + if (client_flush_pending_output(client) == -1) { + return MAILIMAP_ERROR_STREAM; + } + res = mailimap_idle(client->imap); if (res != MAILIMAP_NO_ERROR) { bbs_warning("Failed to start IDLE: %s\n", maildriver_strerror(res)); diff --git a/nets/net_imap/imap_server_fetch.c b/nets/net_imap/imap_server_fetch.c index 7798856..86eb466 100644 --- a/nets/net_imap/imap_server_fetch.c +++ b/nets/net_imap/imap_server_fetch.c @@ -779,6 +779,12 @@ int handle_fetch_full(struct imap_session *imap, char *s, int usinguid, int tagg sequences = strsep(&s, " "); /* Messages, specified by sequence number or by UID (if usinguid) */ REQUIRE_ARGS(s); /* What remains are the items to select */ + /* Could be sequence numbers/UIDs, or '$' for saved search */ + if (strlen_zero(sequences) || (!atoi(sequences) && strcmp(sequences, "$"))) { + imap_reply(imap, "BAD Missing message numbers"); + return 0; + } + /* Remove the surrounding parentheses for parsing */ /* Because of CONDSTORE, multiple parenthesized arguments are supported, * e.g. s100 UID FETCH 1:* (FLAGS) (CHANGEDSINCE 12345) diff --git a/nets/net_imap/imap_server_flags.c b/nets/net_imap/imap_server_flags.c index 6f79d5e..03dbd6f 100644 --- a/nets/net_imap/imap_server_flags.c +++ b/nets/net_imap/imap_server_flags.c @@ -39,6 +39,11 @@ void parse_keyword(struct imap_session *imap, const char *s, const char *directo FILE *fp; char index = 0; + if (strlen_zero(directory)) { + bbs_soft_assert(0); + return; + } + /* Many keywords start with $, but not all of them do */ if (imap->numappendkeywords >= MAX_KEYWORDS) { bbs_warning("Can't store any more keywords\n"); /* XXX A NO [LIMIT] response might make sense if the whole STORE has failed */ diff --git a/scripts/libetpan.sh b/scripts/libetpan.sh index 3fbce17..152e4bd 100755 --- a/scripts/libetpan.sh +++ b/scripts/libetpan.sh @@ -1,13 +1,24 @@ #!/bin/sh -# This script can be used to compile libetpan from source. -# However, as of this writing, the package version also suffices. +# This script is used to compile libetpan from source, +# with modifications that are required for LBBS and other software. + +set -e cd /usr/local/src -git clone https://github.com/dinhvh/libetpan.git -cd libetpan +if [ ! -d libetpan ]; then + git clone https://github.com/dinhvh/libetpan.git + cd libetpan +else + cd libetpan + git stash + git pull + make clean +fi wget "https://github.com/dinhvh/libetpan/commit/5ea630e6482422ffa2e26b9afe5fb47a9eb673a2.diff" -git apply "5ea630e6482422ffa2e26b9afe5fb47a9eb673a2.diff" +wget "https://github.com/dinhvh/libetpan/commit/4226610e3dc19f58345ae7c5146fa8cf249ca97b.patch" +git apply "5ea630e6482422ffa2e26b9afe5fb47a9eb673a2.diff" # IMAP STATUS=SIZE +git apply "4226610e3dc19f58345ae7c5146fa8cf249ca97b.patch" # SMTP AUTH ./autogen.sh --with-poll make -make install \ No newline at end of file +make install