From dca5b887a63004d3b5cf2155a365260faa4fdecb Mon Sep 17 00:00:00 2001 From: Christian Wiese Date: Mon, 17 Jun 2013 15:45:41 +0200 Subject: [PATCH] dovecot: Updated (2.2.2 -> 2.2.3) --- .../dovecot-2.2.2-0000-upstream-fixes.patch | 9949 ----------------- mail/dovecot/dovecot.desc | 4 +- 2 files changed, 2 insertions(+), 9951 deletions(-) delete mode 100644 mail/dovecot/dovecot-2.2.2-0000-upstream-fixes.patch diff --git a/mail/dovecot/dovecot-2.2.2-0000-upstream-fixes.patch b/mail/dovecot/dovecot-2.2.2-0000-upstream-fixes.patch deleted file mode 100644 index 59de31cc8..000000000 --- a/mail/dovecot/dovecot-2.2.2-0000-upstream-fixes.patch +++ /dev/null @@ -1,9949 +0,0 @@ -# --- SDE-COPYRIGHT-NOTE-BEGIN --- -# This copyright note is auto-generated by ./scripts/Create-CopyPatch. -# -# Filename: package/.../dovecot/dovecot-2.2.2-0000-upstream-fixes.patch -# Copyright (C) 2013 The OpenSDE Project -# -# More information can be found in the files COPYING and README. -# -# This patch file is dual-licensed. It is available under the license the -# patched project is licensed under, as long as it is an OpenSource license -# as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms -# of the GNU General Public License as published by the Free Software -# Foundation; either version 2 of the License, or (at your option) any later -# version. -# --- SDE-COPYRIGHT-NOTE-END --- - -From 5dcc6d180aec16d34d60719248a17ec026425fa8 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 20 May 2013 17:30:23 +0300 -Subject: [PATCH] dsync: Fixed unsubscribing from an already deleted mailbox. - - -diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -index 6c878da..6354038 100644 ---- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c -+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -@@ -371,11 +371,24 @@ dsync_brain_mailbox_tree_add_delete(struct dsync_mailbox_tree *tree, - if (node == NULL) - return; - -- if (!other_del->delete_mailbox && -- other_del->timestamp <= node->last_renamed_or_created) { -- /* we don't want to delete this directory, we already have a -- newer timestamp for it */ -- return; -+ switch (other_del->type) { -+ case DSYNC_MAILBOX_DELETE_TYPE_MAILBOX: -+ /* mailbox is always deleted */ -+ break; -+ case DSYNC_MAILBOX_DELETE_TYPE_DIR: -+ if (other_del->timestamp <= node->last_renamed_or_created) { -+ /* we don't want to delete this directory, we already -+ have a newer timestamp for it */ -+ return; -+ } -+ break; -+ case DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE: -+ if (other_del->timestamp <= node->last_subscription_change) { -+ /* we don't want to unsubscribe, since we already have -+ a newer subscription timestamp */ -+ return; -+ } -+ break; - } - - /* make a node for it in the other mailbox tree */ -@@ -384,20 +397,25 @@ dsync_brain_mailbox_tree_add_delete(struct dsync_mailbox_tree *tree, - - if (!guid_128_is_empty(other_node->mailbox_guid) || - (other_node->existence == DSYNC_MAILBOX_NODE_EXISTS && -- !other_del->delete_mailbox)) { -+ other_del->type != DSYNC_MAILBOX_DELETE_TYPE_MAILBOX)) { - /* other side has already created a new mailbox or - directory with this name, we can't delete it */ - return; - } - - /* ok, mark the other node deleted */ -- if (other_del->delete_mailbox) { -+ if (other_del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) { - memcpy(other_node->mailbox_guid, node->mailbox_guid, - sizeof(other_node->mailbox_guid)); - } - i_assert(other_node->ns == NULL || other_node->ns == node->ns); - other_node->ns = node->ns; -- other_node->existence = DSYNC_MAILBOX_NODE_DELETED; -+ if (other_del->type != DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE) -+ other_node->existence = DSYNC_MAILBOX_NODE_DELETED; -+ else { -+ other_node->last_subscription_change = other_del->timestamp; -+ other_node->subscribed = FALSE; -+ } - - if (dsync_mailbox_tree_guid_hash_add(other_tree, other_node, - &old_node) < 0) -diff --git a/src/doveadm/dsync/dsync-ibc-stream.c b/src/doveadm/dsync/dsync-ibc-stream.c -index 729a972..462815a 100644 ---- a/src/doveadm/dsync/dsync-ibc-stream.c -+++ b/src/doveadm/dsync/dsync-ibc-stream.c -@@ -90,7 +90,7 @@ static const struct { - { .name = "mailbox_delete", - .chr = 'D', - .required_keys = "hierarchy_sep", -- .optional_keys = "mailboxes dirs" -+ .optional_keys = "mailboxes dirs unsubscribes" - }, - { .name = "mailbox", - .chr = 'B', -@@ -936,6 +936,28 @@ dsync_ibc_stream_recv_mailbox_tree_node(struct dsync_ibc *_ibc, - } - - static void -+dsync_ibc_stream_encode_delete(string_t *str, -+ struct dsync_serializer_encoder *encoder, -+ const struct dsync_mailbox_delete *deletes, -+ unsigned int count, const char *key, -+ enum dsync_mailbox_delete_type type) -+{ -+ unsigned int i; -+ -+ str_truncate(str, 0); -+ for (i = 0; i < count; i++) { -+ if (deletes[i].type == type) { -+ str_append(str, guid_128_to_string(deletes[i].guid)); -+ str_printfa(str, " %ld ", (long)deletes[i].timestamp); -+ } -+ } -+ if (str_len(str) > 0) { -+ str_truncate(str, str_len(str)-1); -+ dsync_serializer_encode_add(encoder, key, str_c(str)); -+ } -+} -+ -+static void - dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc, - const struct dsync_mailbox_delete *deletes, - unsigned int count, char hierarchy_sep) -@@ -944,7 +966,6 @@ dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc, - struct dsync_serializer_encoder *encoder; - string_t *str, *substr; - char sep[2]; -- unsigned int i; - - str = t_str_new(128); - str_append_c(str, items[ITEM_MAILBOX_DELETE].chr); -@@ -954,29 +975,15 @@ dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc, - dsync_serializer_encode_add(encoder, "hierarchy_sep", sep); - - substr = t_str_new(128); -- for (i = 0; i < count; i++) { -- if (deletes[i].delete_mailbox) { -- str_append(substr, guid_128_to_string(deletes[i].guid)); -- str_printfa(substr, " %ld ", (long)deletes[i].timestamp); -- } -- } -- if (str_len(substr) > 0) { -- str_truncate(substr, str_len(substr)-1); -- dsync_serializer_encode_add(encoder, "mailboxes", -- str_c(substr)); -- } -- -- str_truncate(substr, 0); -- for (i = 0; i < count; i++) { -- if (!deletes[i].delete_mailbox) { -- str_append(substr, guid_128_to_string(deletes[i].guid)); -- str_printfa(substr, " %ld ", (long)deletes[i].timestamp); -- } -- } -- if (str_len(substr) > 0) { -- str_truncate(substr, str_len(substr)-1); -- dsync_serializer_encode_add(encoder, "dirs", str_c(substr)); -- } -+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count, -+ "mailboxes", -+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX); -+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count, -+ "dirs", -+ DSYNC_MAILBOX_DELETE_TYPE_DIR); -+ dsync_ibc_stream_encode_delete(substr, encoder, deletes, count, -+ "unsubscribes", -+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE); - dsync_serializer_encode_finish(&encoder, str); - dsync_ibc_stream_send_string(ibc, str); - } -@@ -984,7 +991,7 @@ dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc, - ARRAY_DEFINE_TYPE(dsync_mailbox_delete, struct dsync_mailbox_delete); - static int - decode_mailbox_deletes(ARRAY_TYPE(dsync_mailbox_delete) *deletes, -- const char *value, bool delete_mailbox) -+ const char *value, enum dsync_mailbox_delete_type type) - { - struct dsync_mailbox_delete *del; - const char *const *tmp; -@@ -993,7 +1000,7 @@ decode_mailbox_deletes(ARRAY_TYPE(dsync_mailbox_delete) *deletes, - tmp = t_strsplit(value, " "); - for (i = 0; tmp[i] != NULL; i += 2) { - del = array_append_space(deletes); -- del->delete_mailbox = delete_mailbox; -+ del->type = type; - if (guid_128_from_string(tmp[i], del->guid) < 0) - return -1; - if (tmp[i+1] == NULL || -@@ -1029,12 +1036,20 @@ dsync_ibc_stream_recv_mailbox_deletes(struct dsync_ibc *_ibc, - *hierarchy_sep_r = value[0]; - - if (dsync_deserializer_decode_try(decoder, "mailboxes", &value) && -- decode_mailbox_deletes(&deletes, value, TRUE) < 0) { -+ decode_mailbox_deletes(&deletes, value, -+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) < 0) { - dsync_ibc_input_error(ibc, decoder, "Invalid mailboxes"); - return DSYNC_IBC_RECV_RET_TRYAGAIN; - } - if (dsync_deserializer_decode_try(decoder, "dirs", &value) && -- decode_mailbox_deletes(&deletes, value, FALSE) < 0) { -+ decode_mailbox_deletes(&deletes, value, -+ DSYNC_MAILBOX_DELETE_TYPE_DIR) < 0) { -+ dsync_ibc_input_error(ibc, decoder, "Invalid dirs"); -+ return DSYNC_IBC_RECV_RET_TRYAGAIN; -+ } -+ if (dsync_deserializer_decode_try(decoder, "unsubscribes", &value) && -+ decode_mailbox_deletes(&deletes, value, -+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE) < 0) { - dsync_ibc_input_error(ibc, decoder, "Invalid dirs"); - return DSYNC_IBC_RECV_RET_TRYAGAIN; - } -diff --git a/src/doveadm/dsync/dsync-mailbox-tree-fill.c b/src/doveadm/dsync/dsync-mailbox-tree-fill.c -index ddf2ebb..9480ebb 100644 ---- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c -+++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c -@@ -163,7 +163,7 @@ dsync_mailbox_tree_add_change_timestamps(struct dsync_mailbox_tree *tree, - break; - } - del = array_append_space(&tree->deletes); -- del->delete_mailbox = TRUE; -+ del->type = DSYNC_MAILBOX_DELETE_TYPE_MAILBOX; - del->timestamp = timestamp; - memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid)); - break; -@@ -177,6 +177,7 @@ dsync_mailbox_tree_add_change_timestamps(struct dsync_mailbox_tree *tree, - dsync side, it can match this deletion to the - name. */ - del = array_append_space(&tree->deletes); -+ del->type = DSYNC_MAILBOX_DELETE_TYPE_DIR; - del->timestamp = timestamp; - memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid)); - break; -@@ -195,10 +196,22 @@ dsync_mailbox_tree_add_change_timestamps(struct dsync_mailbox_tree *tree, - node->last_renamed_or_created = timestamp; - break; - case MAILBOX_LOG_RECORD_SUBSCRIBE: -- case MAILBOX_LOG_RECORD_UNSUBSCRIBE: - if (node != NULL) - node->last_subscription_change = timestamp; - break; -+ case MAILBOX_LOG_RECORD_UNSUBSCRIBE: -+ if (node != NULL) { -+ node->last_subscription_change = timestamp; -+ break; -+ } -+ /* The mailbox is already deleted, but it may still -+ exist on the other side (even the subscription -+ alone). */ -+ del = array_append_space(&tree->deletes); -+ del->type = DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE; -+ del->timestamp = timestamp; -+ memcpy(del->guid, rec->mailbox_guid, sizeof(del->guid)); -+ break; - } - } - if (mailbox_log_iter_deinit(&iter) < 0) { -diff --git a/src/doveadm/dsync/dsync-mailbox-tree.c b/src/doveadm/dsync/dsync-mailbox-tree.c -index 0fa036d..cd8aa9f 100644 ---- a/src/doveadm/dsync/dsync-mailbox-tree.c -+++ b/src/doveadm/dsync/dsync-mailbox-tree.c -@@ -359,7 +359,7 @@ dsync_mailbox_tree_find_delete(struct dsync_mailbox_tree *tree, - i_assert(hash_table_is_created(tree->guid_hash)); - i_assert(tree->remote_sep != '\0'); - -- if (del->delete_mailbox) { -+ if (del->type == DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) { - /* find node by GUID */ - return hash_table_lookup(tree->guid_hash, guid_p); - } -diff --git a/src/doveadm/dsync/dsync-mailbox-tree.h b/src/doveadm/dsync/dsync-mailbox-tree.h -index 58e4531..5a84b0e 100644 ---- a/src/doveadm/dsync/dsync-mailbox-tree.h -+++ b/src/doveadm/dsync/dsync-mailbox-tree.h -@@ -63,10 +63,17 @@ ARRAY_DEFINE_TYPE(dsync_mailbox_node, struct dsync_mailbox_node *); - #define dsync_mailbox_node_is_dir(node) \ - guid_128_is_empty((node)->mailbox_guid) - -+enum dsync_mailbox_delete_type { -+ /* Delete mailbox by given GUID */ -+ DSYNC_MAILBOX_DELETE_TYPE_MAILBOX = 1, -+ /* Delete mailbox directory by given SHA1 name */ -+ DSYNC_MAILBOX_DELETE_TYPE_DIR, -+ /* Unsubscribe mailbox by given SHA1 name */ -+ DSYNC_MAILBOX_DELETE_TYPE_UNSUBSCRIBE, -+}; -+ - struct dsync_mailbox_delete { -- /* true: guid = mailbox GUID -- false: guid = sha1 of directory name */ -- bool delete_mailbox; -+ enum dsync_mailbox_delete_type type; - guid_128_t guid; - time_t timestamp; - }; --- -1.7.10.2 - - -From 25c76e24f77e4f66cdbc3a60be390bbeb2230c9c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 20 May 2013 18:26:16 +0300 -Subject: [PATCH] dsync: Previous have_save_guids change somewhat broke - compatibility with earlier dsync versions. - - -diff --git a/src/doveadm/dsync/dsync-ibc-stream.c b/src/doveadm/dsync/dsync-ibc-stream.c -index 462815a..3dab919 100644 ---- a/src/doveadm/dsync/dsync-ibc-stream.c -+++ b/src/doveadm/dsync/dsync-ibc-stream.c -@@ -28,10 +28,11 @@ - #define DSYNC_IBC_STREAM_OUTBUF_THROTTLE_SIZE (1024*128) - - #define DSYNC_PROTOCOL_VERSION_MAJOR 3 --#define DSYNC_PROTOCOL_VERSION_MINOR 1 -+#define DSYNC_PROTOCOL_VERSION_MINOR 2 - #define DSYNC_HANDSHAKE_VERSION "VERSION\tdsync\t3\t1\n" - - #define DSYNC_PROTOCOL_MINOR_HAVE_ATTRIBUTES 1 -+#define DSYNC_PROTOCOL_MINOR_HAVE_SAVE_GUID 2 - - enum item_type { - ITEM_NONE, -@@ -1227,7 +1228,8 @@ dsync_ibc_stream_recv_mailbox(struct dsync_ibc *_ibc, - box->mailbox_lost = TRUE; - if (dsync_deserializer_decode_try(decoder, "have_guids", &value)) - box->have_guids = TRUE; -- if (dsync_deserializer_decode_try(decoder, "have_save_guids", &value)) -+ if (dsync_deserializer_decode_try(decoder, "have_save_guids", &value) || -+ (box->have_guids && ibc->minor_version < DSYNC_PROTOCOL_MINOR_HAVE_SAVE_GUID)) - box->have_save_guids = TRUE; - value = dsync_deserializer_decode_get(decoder, "uid_validity"); - if (str_to_uint32(value, &box->uid_validity) < 0) { --- -1.7.10.2 - - -From b926a5783dc35da61af12d6a4de992ff2964b0e7 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 21 May 2013 17:09:37 +0300 -Subject: [PATCH] auth: Fixed crash if LDAP query returned multiple results. - - -diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c -index 955e2e6..c61af85 100644 ---- a/src/auth/db-ldap.c -+++ b/src/auth/db-ldap.c -@@ -825,8 +825,10 @@ static void db_ldap_request_free(struct ldap_request *request, LDAPMessage *res) - - if (srequest->result == res) - res = NULL; -- if (srequest->result != NULL) -+ if (srequest->result != NULL) { - ldap_msgfree(srequest->result); -+ srequest->result = NULL; -+ } - - if (array_is_created(&srequest->named_results)) { - array_foreach(&srequest->named_results, named_res) { -@@ -835,6 +837,7 @@ static void db_ldap_request_free(struct ldap_request *request, LDAPMessage *res) - if (named_res->result != NULL) - ldap_msgfree(named_res->result); - } -+ array_clear(&srequest->named_results); - } - } - if (res != NULL) --- -1.7.10.2 - - -From adc71ee1cfc1eaa18b88c15c3eac475bac740076 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Tue, 21 May 2013 22:55:12 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed local URLAUTH fetches that didn't - immediately finish handling content. Local requests are now - also properly counted. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 9801822..eb438a7 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -55,8 +55,10 @@ static void imap_urlauth_fetch_abort_local(struct imap_urlauth_fetch *ufetch) - { - struct imap_urlauth_fetch_url *url, *url_next; - -- if (ufetch->local_url != NULL) -+ if (ufetch->local_url != NULL) { -+ ufetch->pending_requests--; - imap_msgpart_url_free(&ufetch->local_url); -+ } - - i_free_and_null(ufetch->pending_reply.url); - i_free_and_null(ufetch->pending_reply.bodypartstruct); -@@ -153,7 +155,6 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - struct imap_msgpart_url *mpurl = NULL; - int ret; - -- ufetch->pending_requests--; - success = TRUE; - - if (debug) -@@ -226,6 +227,7 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - } - - if (!success && ret < 0) { -+ ufetch->pending_requests--; - (void)ufetch->callback(NULL, TRUE, ufetch->context); - imap_urlauth_fetch_fail(ufetch); - return; -@@ -242,12 +244,14 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - reply.size = mpresult.size; - reply.input = mpresult.input; - -- ret = ufetch->callback(&reply, ufetch->pending_requests == 0, -+ ret = ufetch->callback(&reply, ufetch->pending_requests == 1, - ufetch->context); - if (ret == 0) { - ufetch->local_url = mpurl; - ufetch->waiting = TRUE; - } else { -+ ufetch->pending_requests--; -+ - if (mpurl != NULL) - imap_msgpart_url_free(&mpurl); - if (ret < 0) -@@ -302,26 +306,30 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - enum imap_urlauth_fetch_flags url_flags) - { -+ struct imap_urlauth_context *uctx = ufetch->uctx; - enum imap_url_parse_flags url_parse_flags = - IMAP_URL_PARSE_ALLOW_URLAUTH; -- struct imap_urlauth_context *uctx = ufetch->uctx; - struct mail_user *mail_user = uctx->user; -- struct imap_url *imap_url = NULL; -+ struct imap_url *imap_url; - const char *error, *errormsg; - -- ufetch->failed = FALSE; -- ufetch->pending_requests++; -- - /* parse the url */ - if (imap_url_parse(url, NULL, url_parse_flags, &imap_url, &error) < 0) { - errormsg = t_strdup_printf( - "Failed to fetch URLAUTH \"%s\": %s", url, error); - if (mail_user->mail_debug) - i_debug("%s", errormsg); -+ ufetch->pending_requests++; - imap_urlauth_fetch_error(ufetch, url, url_flags, errormsg); -- -+ return 1; -+ } -+ -+ ufetch->failed = FALSE; -+ ufetch->pending_requests++; -+ - /* if access user and target user match, handle fetch request locally */ -- } else if (strcmp(mail_user->username, imap_url->userid) == 0) { -+ if (imap_url->userid != NULL && -+ strcmp(mail_user->username, imap_url->userid) == 0) { - - if (ufetch->waiting) { - struct imap_urlauth_fetch_url *url_local; -@@ -352,15 +360,11 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - (void)imap_urlauth_request_new(uctx->conn, imap_url->userid, - url, url_flags, - imap_urlauth_fetch_request_callback, ufetch); -- } -- -- if (ufetch->pending_requests > 0) { - i_assert(uctx->conn != NULL); - if (imap_urlauth_connection_connect(uctx->conn) < 0) - return -1; -- return 0; - } -- return 1; -+ return (ufetch->pending_requests > 0 ? 0 : 1); - } - - bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) -@@ -377,8 +381,10 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - return ufetch->pending_requests > 0; - } - -- if (ufetch->local_url != NULL) -+ if (ufetch->local_url != NULL) { -+ ufetch->pending_requests--; - imap_msgpart_url_free(&ufetch->local_url); -+ } - ufetch->waiting = FALSE; - - /* handle pending remote reply */ -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.h b/src/lib-imap-urlauth/imap-urlauth-fetch.h -index 27a96f2..3c5275c 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.h -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h -@@ -31,7 +31,7 @@ struct imap_urlauth_fetch_reply { - - /* Callback to handle fetch reply. Returns 1 if handled completely and ready - for next reply, 0 if not all data was processed, and -1 for error. If a -- callback returns 0, imap_urlauth_connection_continue() must be called once -+ callback returns 0, imap_urlauth_fetch_continue() must be called once - new replies may be processed. If this is the last request to yield a reply, - argument last is TRUE. The callback must not call - imap_urlauth_fetch_deinit(). */ -@@ -45,7 +45,7 @@ imap_urlauth_fetch_init(struct imap_urlauth_context *uctx, - void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch); - - int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, -- enum imap_urlauth_fetch_flags flags); -+ enum imap_urlauth_fetch_flags url_flags); - bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch); - - #endif --- -1.7.10.2 - - -From b65589285715ab3ecbde9053948e96d6d0b0daa5 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Tue, 21 May 2013 22:55:17 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed resuming in URLAUTH fetch handler. - Fixed URLAUTH fetch handler to properly resume the URLAUTH - connection, even when it is deinitialized. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index eb438a7..18cd342 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -48,7 +48,8 @@ struct imap_urlauth_fetch { - } pending_reply; - - unsigned int failed:1; -- unsigned int waiting:1; -+ unsigned int waiting_local:1; -+ unsigned int waiting_service:1; - }; - - static void imap_urlauth_fetch_abort_local(struct imap_urlauth_fetch *ufetch) -@@ -112,6 +113,10 @@ void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch) - *_ufetch = NULL; - - imap_urlauth_fetch_abort(ufetch); -+ -+ /* dont leave the connection in limbo; make sure resume is called */ -+ if (ufetch->waiting_service) -+ imap_urlauth_connection_continue(ufetch->uctx->conn); - i_free(ufetch); - } - -@@ -137,7 +142,7 @@ imap_urlauth_fetch_error(struct imap_urlauth_fetch *ufetch, const char *url, - } T_END; - - if (ret == 0) -- ufetch->waiting = TRUE; -+ ufetch->waiting_local = TRUE; - else if (ret < 0) - imap_urlauth_fetch_fail(ufetch); - } -@@ -248,7 +253,7 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - ufetch->context); - if (ret == 0) { - ufetch->local_url = mpurl; -- ufetch->waiting = TRUE; -+ ufetch->waiting_local = TRUE; - } else { - ufetch->pending_requests--; - -@@ -267,7 +272,7 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - (struct imap_urlauth_fetch *)context; - int ret = 1; - -- if (ufetch->waiting && reply != NULL) { -+ if (ufetch->waiting_local && reply != NULL) { - i_assert(ufetch->pending_reply.url == NULL); - ufetch->pending_reply.url = i_strdup(reply->url); - ufetch->pending_reply.flags = reply->flags; -@@ -284,7 +289,7 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - return 0; - } - -- ufetch->waiting = FALSE; -+ ufetch->waiting_local = FALSE; - ufetch->pending_requests--; - - if (!ufetch->failed) { -@@ -297,6 +302,8 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - if (!ufetch->failed) - imap_urlauth_fetch_abort_local(ufetch); - ufetch->failed = TRUE; -+ } else if (ret == 0) { -+ ufetch->waiting_service = TRUE; - } - if (ret != 0) - imap_urlauth_fetch_deinit(&ufetch); -@@ -331,7 +338,7 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - if (imap_url->userid != NULL && - strcmp(mail_user->username, imap_url->userid) == 0) { - -- if (ufetch->waiting) { -+ if (ufetch->waiting_local) { - struct imap_urlauth_fetch_url *url_local; - - url_local = i_new(struct imap_urlauth_fetch_url, 1); -@@ -375,17 +382,22 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - if (ufetch->failed) - return FALSE; - -- if (!ufetch->waiting) { -+ if (!ufetch->waiting_local && !ufetch->waiting_service) -+ return ufetch->pending_requests > 0; -+ -+ if (!ufetch->waiting_local) { - /* not waiting for local request handling */ -+ ufetch->waiting_service = FALSE; - imap_urlauth_connection_continue(ufetch->uctx->conn); - return ufetch->pending_requests > 0; - } - -+ /* finished local request */ - if (ufetch->local_url != NULL) { - ufetch->pending_requests--; - imap_msgpart_url_free(&ufetch->local_url); - } -- ufetch->waiting = FALSE; -+ ufetch->waiting_local = FALSE; - - /* handle pending remote reply */ - if (ufetch->pending_reply.url != NULL) { -@@ -419,11 +431,9 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - imap_urlauth_fetch_fail(ufetch); - return FALSE; - } -- -- imap_urlauth_connection_continue(ufetch->uctx->conn); - - if (ret == 0) { -- ufetch->waiting = TRUE; -+ ufetch->waiting_service = TRUE; - return TRUE; - } - } -@@ -440,7 +450,7 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - &ufetch->local_urls_tail, url); - i_free(url->url); - i_free(url); -- if (ufetch->waiting) -+ if (ufetch->waiting_local) - return TRUE; - url = url_next; - } --- -1.7.10.2 - - -From 421ec8d0a4072b5f0d2aa63c5aef354a7a1dd659 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Tue, 21 May 2013 22:55:23 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed deinitialization of the URLAUTH - fetch handler. Added reference counting to make sure - callbacks will not deinitialize the handler prematurely. - - -diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c -index 2826cb0..c3fac61 100644 ---- a/src/imap/cmd-urlfetch.c -+++ b/src/imap/cmd-urlfetch.c -@@ -284,7 +284,6 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply, - - if ((last && cmd->state == CLIENT_COMMAND_STATE_WAIT_EXTERNAL) || - ret < 0) { -- ctx->ufetch = NULL; - cmd_urlfetch_finish(cmd); - client_command_free(&cmd); - } -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 18cd342..0ba4dfa 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -22,6 +22,7 @@ struct imap_urlauth_fetch_url { - }; - - struct imap_urlauth_fetch { -+ unsigned int refcount; - struct imap_urlauth_context *uctx; - - imap_urlauth_fetch_callback_t *callback; -@@ -100,17 +101,28 @@ imap_urlauth_fetch_init(struct imap_urlauth_context *uctx, - struct imap_urlauth_fetch *ufetch; - - ufetch = i_new(struct imap_urlauth_fetch, 1); -+ ufetch->refcount = 1; - ufetch->uctx = uctx; - ufetch->callback = callback; - ufetch->context = context; - return ufetch; - } - --void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch) -+static void imap_urlauth_fetch_ref(struct imap_urlauth_fetch *ufetch) -+{ -+ i_assert(ufetch->refcount > 0); -+ ufetch->refcount++; -+} -+ -+static void imap_urlauth_fetch_unref(struct imap_urlauth_fetch **_ufetch) - { - struct imap_urlauth_fetch *ufetch = *_ufetch; - -+ i_assert(ufetch->refcount > 0); -+ - *_ufetch = NULL; -+ if (--ufetch->refcount > 0) -+ return; - - imap_urlauth_fetch_abort(ufetch); - -@@ -120,6 +132,11 @@ void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch) - i_free(ufetch); - } - -+void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch) -+{ -+ imap_urlauth_fetch_unref(_ufetch); -+} -+ - static void - imap_urlauth_fetch_error(struct imap_urlauth_fetch *ufetch, const char *url, - enum imap_urlauth_fetch_flags url_flags, -@@ -232,6 +249,8 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - } - - if (!success && ret < 0) { -+ if (mpurl != NULL) -+ imap_msgpart_url_free(&mpurl); - ufetch->pending_requests--; - (void)ufetch->callback(NULL, TRUE, ufetch->context); - imap_urlauth_fetch_fail(ufetch); -@@ -292,6 +311,8 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - ufetch->waiting_local = FALSE; - ufetch->pending_requests--; - -+ imap_urlauth_fetch_ref(ufetch); -+ - if (!ufetch->failed) { - bool last = ufetch->pending_requests == 0 || reply == NULL; - ret = ufetch->callback(reply, last, ufetch->context); -@@ -305,8 +326,8 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - } else if (ret == 0) { - ufetch->waiting_service = TRUE; - } -- if (ret != 0) -- imap_urlauth_fetch_deinit(&ufetch); -+ -+ imap_urlauth_fetch_unref(&ufetch); - return ret; - } - -@@ -319,6 +340,7 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - struct mail_user *mail_user = uctx->user; - struct imap_url *imap_url; - const char *error, *errormsg; -+ int ret = 0; - - /* parse the url */ - if (imap_url_parse(url, NULL, url_parse_flags, &imap_url, &error) < 0) { -@@ -327,13 +349,17 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - if (mail_user->mail_debug) - i_debug("%s", errormsg); - ufetch->pending_requests++; -+ imap_urlauth_fetch_ref(ufetch); - imap_urlauth_fetch_error(ufetch, url, url_flags, errormsg); -+ imap_urlauth_fetch_unref(&ufetch); - return 1; - } - - ufetch->failed = FALSE; - ufetch->pending_requests++; - -+ imap_urlauth_fetch_ref(ufetch); -+ - /* if access user and target user match, handle fetch request locally */ - if (imap_url->userid != NULL && - strcmp(mail_user->username, imap_url->userid) == 0) { -@@ -364,17 +390,22 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - - /* create request for url */ - if (imap_url != NULL && imap_url->userid != NULL) { -+ i_assert(uctx->conn != NULL); - (void)imap_urlauth_request_new(uctx->conn, imap_url->userid, - url, url_flags, - imap_urlauth_fetch_request_callback, ufetch); - i_assert(uctx->conn != NULL); - if (imap_urlauth_connection_connect(uctx->conn) < 0) -- return -1; -+ ret = -1; - } -- return (ufetch->pending_requests > 0 ? 0 : 1); -+ if (ret >= 0) -+ ret = (ufetch->pending_requests > 0 ? 0 : 1); -+ -+ imap_urlauth_fetch_unref(&ufetch); -+ return ret; - } - --bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) -+static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch) - { - struct imap_urlauth_fetch_url *url, *url_next; - int ret; -@@ -390,7 +421,7 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - ufetch->waiting_service = FALSE; - imap_urlauth_connection_continue(ufetch->uctx->conn); - return ufetch->pending_requests > 0; -- } -+ } - - /* finished local request */ - if (ufetch->local_url != NULL) { -@@ -457,3 +488,15 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - - return ufetch->pending_requests > 0; - } -+ -+bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) -+{ -+ bool pending; -+ -+ imap_urlauth_fetch_ref(ufetch); -+ pending = imap_urlauth_fetch_do_continue(ufetch); -+ imap_urlauth_fetch_unref(&ufetch); -+ -+ return pending; -+} -+ -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.h b/src/lib-imap-urlauth/imap-urlauth-fetch.h -index 3c5275c..55398af 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.h -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h -@@ -33,8 +33,7 @@ struct imap_urlauth_fetch_reply { - for next reply, 0 if not all data was processed, and -1 for error. If a - callback returns 0, imap_urlauth_fetch_continue() must be called once - new replies may be processed. If this is the last request to yield a reply, -- argument last is TRUE. The callback must not call -- imap_urlauth_fetch_deinit(). */ -+ argument last is TRUE. */ - typedef int - imap_urlauth_fetch_callback_t(struct imap_urlauth_fetch_reply *reply, - bool last, void *context); -@@ -42,7 +41,7 @@ imap_urlauth_fetch_callback_t(struct imap_urlauth_fetch_reply *reply, - struct imap_urlauth_fetch * - imap_urlauth_fetch_init(struct imap_urlauth_context *uctx, - imap_urlauth_fetch_callback_t *callback, void *context); --void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **_ufetch); -+void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **ufetch); - - int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - enum imap_urlauth_fetch_flags url_flags); --- -1.7.10.2 - - -From 6547c94d39f42d25dc07f50d52f4e6cd8b57d91c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 21 May 2013 22:57:06 +0300 -Subject: [PATCH] *-login: If auth failed with a specified reason, the reason - wasn't actually shown to client. - - -diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c -index 356d1c4..485a7d3 100644 ---- a/src/login-common/client-common-auth.c -+++ b/src/login-common/client-common-auth.c -@@ -538,7 +538,7 @@ sasl_callback(struct client *client, enum sasl_server_reply sasl_reply, - } else { - client_auth_result(client, - CLIENT_AUTH_RESULT_AUTHFAILED_REASON, NULL, -- AUTH_FAILED_MSG); -+ data); - } - - if (!client->destroyed) --- -1.7.10.2 - - -From e5c91a786027aef441b2d63ec25835bb3b664be7 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 22 May 2013 14:56:41 +0300 -Subject: [PATCH] dsync: Don't notify replicator process about successful - dsync if the dsync failed. - - -diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c -index 1568302..73cfe60 100644 ---- a/src/doveadm/dsync/doveadm-dsync.c -+++ b/src/doveadm/dsync/doveadm-dsync.c -@@ -949,7 +949,7 @@ cmd_dsync_server_run(struct doveadm_mail_cmd_context *_ctx, - o_stream_close(_ctx->conn->output); - } - -- if (ctx->replicator_notify) -+ if (ctx->replicator_notify && _ctx->exit_code == 0) - dsync_replicator_notify(ctx, sync_type, str_c(state_str)); - return _ctx->exit_code == 0 ? 0 : -1; - } --- -1.7.10.2 - - -From 711b2555ff0257b17f155d783ac3053e21b7ecd7 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 22 May 2013 15:16:22 +0300 -Subject: [PATCH] dsync: Fixed unsubscribing from mailbox within same session - as the mailbox's deletion. - - -diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -index 6354038..fb13444 100644 ---- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c -+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -@@ -395,8 +395,8 @@ dsync_brain_mailbox_tree_add_delete(struct dsync_mailbox_tree *tree, - name = dsync_mailbox_node_get_full_name(tree, node); - other_node = dsync_mailbox_tree_get(other_tree, name); - -- if (!guid_128_is_empty(other_node->mailbox_guid) || -- (other_node->existence == DSYNC_MAILBOX_NODE_EXISTS && -+ if (other_node->existence == DSYNC_MAILBOX_NODE_EXISTS && -+ (!guid_128_is_empty(other_node->mailbox_guid) || - other_del->type != DSYNC_MAILBOX_DELETE_TYPE_MAILBOX)) { - /* other side has already created a new mailbox or - directory with this name, we can't delete it */ --- -1.7.10.2 - - -From 9eeaa264e047900b8f3ce836c95e2256cf35de76 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 22 May 2013 15:44:05 +0300 -Subject: [PATCH] lib-storage: Optimize SEARCH_MODSEQ query if it's higher - than HIGHESTMODSEQ. - - -diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c -index 9278b6d..0f10a04 100644 ---- a/src/lib-storage/index/index-search.c -+++ b/src/lib-storage/index/index-search.c -@@ -904,12 +904,13 @@ static void search_limit_lowwater(struct index_search_context *ctx, - *first_seq = seq1; - } - --static bool search_limit_by_flags(struct index_search_context *ctx, -- struct mail_search_arg *args, -- uint32_t *seq1, uint32_t *seq2) -+static bool search_limit_by_hdr(struct index_search_context *ctx, -+ struct mail_search_arg *args, -+ uint32_t *seq1, uint32_t *seq2) - { - const struct mail_index_header *hdr; - enum mail_flags pvt_flags_mask; -+ uint64_t highest_modseq; - - hdr = mail_index_get_header(ctx->view); - /* we can't trust that private view's header is fully up to date, -@@ -918,12 +919,23 @@ static bool search_limit_by_flags(struct index_search_context *ctx, - mailbox_get_private_flags_mask(ctx->box); - - for (; args != NULL; args = args->next) { -- if (args->type != SEARCH_FLAGS) { -- if (args->type == SEARCH_ALL) { -- if (args->match_not) -- return FALSE; -+ switch (args->type) { -+ case SEARCH_ALL: -+ if (args->match_not) { -+ /* NOT ALL - pointless noop query */ -+ return FALSE; - } - continue; -+ case SEARCH_MODSEQ: -+ /* MODSEQ higher than current HIGHESTMODSEQ? */ -+ highest_modseq = mail_index_modseq_get_highest(ctx->view); -+ if (args->value.modseq->modseq > highest_modseq) -+ return FALSE; -+ continue; -+ default: -+ continue; -+ case SEARCH_FLAGS: -+ break; - } - if ((args->value.flags & MAIL_SEEN) != 0 && - (pvt_flags_mask & MAIL_SEEN) == 0) { -@@ -995,8 +1007,10 @@ static void search_get_seqset(struct index_search_context *ctx, - return; - } - -- /* UNSEEN and DELETED in root search level may limit the range */ -- if (!search_limit_by_flags(ctx, args, &ctx->seq1, &ctx->seq2)) { -+ /* See if this search query can never match based on data in index's -+ header. We'll scan only the root level args, which is usually -+ enough. */ -+ if (!search_limit_by_hdr(ctx, args, &ctx->seq1, &ctx->seq2)) { - /* no matches */ - ctx->seq1 = 1; - ctx->seq2 = 0; --- -1.7.10.2 - - -From fd553002dbc884a1c38fadde0c5aa2a62dc0cbf5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 22 May 2013 15:57:13 +0300 -Subject: [PATCH] *-login: ssl=required should imply - disable_plaintext_auth=yes - - -diff --git a/src/imap-login/client.c b/src/imap-login/client.c -index 55f38fd..c5d7097 100644 ---- a/src/imap-login/client.c -+++ b/src/imap-login/client.c -@@ -12,6 +12,7 @@ - #include "imap-id.h" - #include "imap-resp-code.h" - #include "master-service.h" -+#include "master-service-ssl-settings.h" - #include "master-auth.h" - #include "client.h" - #include "client-authenticate.h" -@@ -64,7 +65,8 @@ static const char *get_capability(struct client *client) - - if (client_is_tls_enabled(client) && !client->tls) - str_append(cap_str, " STARTTLS"); -- if (client->set->disable_plaintext_auth && !client->secured) -+ if (!client->secured & (client->set->disable_plaintext_auth || -+ strcmp(client->ssl_set->ssl, "required") == 0)) - str_append(cap_str, " LOGINDISABLED"); - - client_authenticate_get_capabilities(client, cap_str); -diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c -index 485a7d3..99c7f34 100644 ---- a/src/login-common/client-common-auth.c -+++ b/src/login-common/client-common-auth.c -@@ -615,7 +615,8 @@ int client_auth_begin(struct client *client, const char *mech_name, - - bool client_check_plaintext_auth(struct client *client, bool pass_sent) - { -- if (client->secured || !client->set->disable_plaintext_auth) -+ if (client->secured || (!client->set->disable_plaintext_auth && -+ strcmp(client->ssl_set->ssl, "required") != 0)) - return TRUE; - - if (client->set->auth_verbose) { --- -1.7.10.2 - - -From 2918910f33939a19322897061ebfb4b0865aa801 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 22 May 2013 15:59:38 +0300 -Subject: [PATCH] *-login: If ssl=required, don't list any SASL mechanisms - before STARTTLS. - - -diff --git a/src/login-common/sasl-server.c b/src/login-common/sasl-server.c -index 78735a6..3fbc560 100644 ---- a/src/login-common/sasl-server.c -+++ b/src/login-common/sasl-server.c -@@ -13,6 +13,7 @@ - #include "auth-client.h" - #include "ssl-proxy.h" - #include "master-service.h" -+#include "master-service-ssl-settings.h" - #include "master-interface.h" - #include "master-auth.h" - #include "client-common.h" -@@ -38,7 +39,8 @@ sasl_server_get_advertised_mechs(struct client *client, unsigned int *count_r) - unsigned int i, j, count; - - mech = auth_client_get_available_mechs(auth_client, &count); -- if (count == 0) { -+ if (count == 0 || (!client->secured && -+ strcmp(client->ssl_set->ssl, "required") == 0)) { - *count_r = 0; - return NULL; - } --- -1.7.10.2 - - -From 43eeeb4d96640c49ad342e050f7590aca7ad21d6 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 23 May 2013 17:36:54 +0300 -Subject: [PATCH] lib-http: Added ssl_cert|key|key_password settings to be - passed to ssl-iostream. These are used for sending client's - SSL certificate. - - -diff --git a/src/lib-http/http-client.c b/src/lib-http/http-client.c -index b6846f0..f153b51 100644 ---- a/src/lib-http/http-client.c -+++ b/src/lib-http/http-client.c -@@ -86,6 +86,9 @@ struct http_client *http_client_init(const struct http_client_settings *set) - client->set.ssl_ca = p_strdup(pool, set->ssl_ca); - client->set.ssl_crypto_device = p_strdup(pool, set->ssl_crypto_device); - client->set.ssl_allow_invalid_cert = set->ssl_allow_invalid_cert; -+ client->set.ssl_cert = p_strdup(pool, set->ssl_cert); -+ client->set.ssl_key = p_strdup(pool, set->ssl_key); -+ client->set.ssl_key_password = p_strdup(pool, set->ssl_key_password); - client->set.max_idle_time_msecs = set->max_idle_time_msecs; - client->set.max_parallel_connections = - (set->max_parallel_connections > 0 ? set->max_parallel_connections : 1); -@@ -197,6 +200,9 @@ int http_client_init_ssl_ctx(struct http_client *client, const char **error_r) - ssl_set.ca = client->set.ssl_ca; - ssl_set.verify_remote_cert = TRUE; - ssl_set.crypto_device = client->set.ssl_crypto_device; -+ ssl_set.cert = client->set.ssl_cert; -+ ssl_set.key = client->set.ssl_key; -+ ssl_set.key_password = client->set.ssl_key_password; - ssl_set.verbose = client->set.debug; - ssl_set.verbose_invalid_cert = client->set.debug; - -diff --git a/src/lib-http/http-client.h b/src/lib-http/http-client.h -index 69cb448..9c8d131 100644 ---- a/src/lib-http/http-client.h -+++ b/src/lib-http/http-client.h -@@ -36,6 +36,8 @@ struct http_client_settings { - const char *ssl_ca_dir, *ssl_ca_file, *ssl_ca; - const char *ssl_crypto_device; - bool ssl_allow_invalid_cert; -+ /* user cert */ -+ const char *ssl_cert, *ssl_key, *ssl_key_password; - - const char *rawlog_dir; - --- -1.7.10.2 - - -From 7dc8d11c6315150feac47878c9122dc5812a7c1c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 19:04:00 +0300 -Subject: [PATCH] lib-index: mail_cache_lookup*() can now return fields - recently added with mail_cache_add() Previously it was - returning them if they had already been written to - dovecot.index.cache, but not if they were still in the - in-memory buffer. This avoids caching/parsing the same - field multiple times when messages aren't accessed in - ascending order (e.g. when sorting messages). - - -diff --git a/src/lib-index/mail-cache-lookup.c b/src/lib-index/mail-cache-lookup.c -index c48dfc0..39f3eb0 100644 ---- a/src/lib-index/mail-cache-lookup.c -+++ b/src/lib-index/mail-cache-lookup.c -@@ -163,31 +163,58 @@ void mail_cache_lookup_iter_init(struct mail_cache_view *view, uint32_t seq, - memset(&view->loop_track, 0, sizeof(view->loop_track)); - } - -+static bool -+mail_cache_lookup_iter_transaction(struct mail_cache_lookup_iterate_ctx *ctx) -+{ -+ ctx->rec = mail_cache_transaction_lookup_rec(ctx->view->transaction, -+ ctx->seq, -+ &ctx->trans_next_idx); -+ if (ctx->rec == NULL) -+ return FALSE; -+ -+ ctx->remap_counter = ctx->view->cache->remap_counter; -+ ctx->pos = sizeof(*ctx->rec); -+ ctx->rec_size = ctx->rec->size; -+ return TRUE; -+} -+ - static int - mail_cache_lookup_iter_next_record(struct mail_cache_lookup_iterate_ctx *ctx) - { - struct mail_cache_view *view = ctx->view; - -- if (ctx->stop) -- return ctx->failed ? -1 : 0; -+ if (ctx->failed) -+ return -1; - - if (ctx->rec != NULL) - ctx->offset = ctx->rec->prev_offset; - if (ctx->offset == 0) { - /* end of this record list. check newly appended data. */ -- if (ctx->appends_checked || -- view->trans_seq1 > ctx->seq || -+ if (view->trans_seq1 > ctx->seq || - view->trans_seq2 < ctx->seq || -- MAIL_CACHE_IS_UNUSABLE(view->cache) || -+ MAIL_CACHE_IS_UNUSABLE(view->cache)) -+ return 0; -+ /* check data still in memory */ -+ if (!ctx->memory_appends_checked) { -+ if (mail_cache_lookup_iter_transaction(ctx)) -+ return 1; -+ ctx->memory_appends_checked = TRUE; -+ } -+ -+ /* check data already written to cache file */ -+ if (ctx->disk_appends_checked || - mail_cache_lookup_offset(view->cache, view->trans_view, - ctx->seq, &ctx->offset) <= 0) - return 0; - -- ctx->appends_checked = TRUE; -+ ctx->disk_appends_checked = TRUE; - ctx->remap_counter = view->cache->remap_counter; - memset(&view->loop_track, 0, sizeof(view->loop_track)); - } - -+ if (ctx->stop) -+ return 0; -+ - /* look up the next record */ - if (mail_cache_get_record(view->cache, ctx->offset, &ctx->rec) < 0) - return -1; -diff --git a/src/lib-index/mail-cache-private.h b/src/lib-index/mail-cache-private.h -index 7b6f33c..eb57387 100644 ---- a/src/lib-index/mail-cache-private.h -+++ b/src/lib-index/mail-cache-private.h -@@ -202,9 +202,12 @@ struct mail_cache_lookup_iterate_ctx { - unsigned int pos, rec_size; - uint32_t offset; - -+ unsigned int trans_next_idx; -+ - unsigned int stop:1; - unsigned int failed:1; -- unsigned int appends_checked:1; -+ unsigned int memory_appends_checked:1; -+ unsigned int disk_appends_checked:1; - }; - - /* Explicitly lock the cache file. Returns -1 if error / timed out, -@@ -243,6 +246,10 @@ void mail_cache_lookup_iter_init(struct mail_cache_view *view, uint32_t seq, - /* Returns 1 if field was returned, 0 if end of fields, or -1 if error */ - int mail_cache_lookup_iter_next(struct mail_cache_lookup_iterate_ctx *ctx, - struct mail_cache_iterate_field *field_r); -+const struct mail_cache_record * -+mail_cache_transaction_lookup_rec(struct mail_cache_transaction_ctx *ctx, -+ unsigned int seq, -+ unsigned int *trans_next_idx); - - int mail_cache_map(struct mail_cache *cache, size_t offset, size_t size, - const void **data_r); -diff --git a/src/lib-index/mail-cache-transaction.c b/src/lib-index/mail-cache-transaction.c -index 6049d33..b56aa94 100644 ---- a/src/lib-index/mail-cache-transaction.c -+++ b/src/lib-index/mail-cache-transaction.c -@@ -21,6 +21,11 @@ - #define CACHE_TRANS_CONTEXT(obj) \ - MODULE_CONTEXT(obj, cache_mail_index_transaction_module) - -+struct mail_cache_transaction_rec { -+ uint32_t seq; -+ uint32_t cache_data_pos; -+}; -+ - struct mail_cache_transaction_ctx { - union mail_index_transaction_module_context module_ctx; - struct mail_index_transaction_vfuncs super; -@@ -33,7 +38,7 @@ struct mail_cache_transaction_ctx { - uint32_t first_new_seq; - - buffer_t *cache_data; -- ARRAY(uint32_t) cache_data_seq; -+ ARRAY(struct mail_cache_transaction_rec) cache_data_seq; - uint32_t prev_seq, min_seq; - size_t last_rec_pos; - -@@ -272,13 +277,33 @@ static int mail_cache_transaction_lock(struct mail_cache_transaction_ctx *ctx) - return 1; - } - -+const struct mail_cache_record * -+mail_cache_transaction_lookup_rec(struct mail_cache_transaction_ctx *ctx, -+ unsigned int seq, -+ unsigned int *trans_next_idx) -+{ -+ const struct mail_cache_transaction_rec *recs; -+ unsigned int i, count; -+ -+ recs = array_get(&ctx->cache_data_seq, &count); -+ for (i = *trans_next_idx; i < count; i++) { -+ if (recs[i].seq == seq) { -+ *trans_next_idx = i + 1; -+ return CONST_PTR_OFFSET(ctx->cache_data->data, -+ recs[i].cache_data_pos); -+ } -+ } -+ *trans_next_idx = i; -+ return NULL; -+} -+ - static int - mail_cache_transaction_update_index(struct mail_cache_transaction_ctx *ctx, - uint32_t write_offset) - { - struct mail_cache *cache = ctx->cache; - const struct mail_cache_record *rec = ctx->cache_data->data; -- const uint32_t *seqs; -+ const struct mail_cache_transaction_rec *recs; - uint32_t i, seq_count; - - mail_index_ext_using_reset_id(ctx->trans, ctx->cache->ext_id, -@@ -287,9 +312,9 @@ mail_cache_transaction_update_index(struct mail_cache_transaction_ctx *ctx, - /* write the cache_offsets to index file. records' prev_offset - is updated to point to old cache record when index is being - synced. */ -- seqs = array_get(&ctx->cache_data_seq, &seq_count); -+ recs = array_get(&ctx->cache_data_seq, &seq_count); - for (i = 0; i < seq_count; i++) { -- mail_index_update_ext(ctx->trans, seqs[i], cache->ext_id, -+ mail_index_update_ext(ctx->trans, recs[i].seq, cache->ext_id, - &write_offset, NULL); - - write_offset += rec->size; -@@ -304,7 +329,8 @@ mail_cache_link_records(struct mail_cache_transaction_ctx *ctx, - { - struct mail_index_map *map; - struct mail_cache_record *rec; -- const uint32_t *seqs, *prev_offsetp; -+ const struct mail_cache_transaction_rec *recs; -+ const uint32_t *prev_offsetp; - ARRAY_TYPE(uint32_t) seq_offsets; - uint32_t i, seq_count, reset_id, prev_offset, *offsetp; - const void *data; -@@ -312,15 +338,15 @@ mail_cache_link_records(struct mail_cache_transaction_ctx *ctx, - i_assert(ctx->min_seq != 0); - - i_array_init(&seq_offsets, 64); -- seqs = array_get(&ctx->cache_data_seq, &seq_count); -+ recs = array_get(&ctx->cache_data_seq, &seq_count); - rec = buffer_get_modifiable_data(ctx->cache_data, NULL); - for (i = 0; i < seq_count; i++) { - offsetp = array_idx_modifiable(&seq_offsets, -- seqs[i] - ctx->min_seq); -+ recs[i].seq - ctx->min_seq); - if (*offsetp != 0) - prev_offset = *offsetp; - else { -- mail_index_lookup_ext_full(ctx->view->trans_view, seqs[i], -+ mail_index_lookup_ext_full(ctx->view->trans_view, recs[i].seq, - ctx->cache->ext_id, &map, - &data, NULL); - prev_offsetp = data; -@@ -423,6 +449,7 @@ mail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx) - static void - mail_cache_transaction_update_last_rec(struct mail_cache_transaction_ctx *ctx) - { -+ struct mail_cache_transaction_rec *trans_rec; - struct mail_cache_record *rec; - void *data; - size_t size; -@@ -439,7 +466,9 @@ mail_cache_transaction_update_last_rec(struct mail_cache_transaction_ctx *ctx) - - if (ctx->min_seq > ctx->prev_seq || ctx->min_seq == 0) - ctx->min_seq = ctx->prev_seq; -- array_append(&ctx->cache_data_seq, &ctx->prev_seq, 1); -+ trans_rec = array_append_space(&ctx->cache_data_seq); -+ trans_rec->seq = ctx->prev_seq; -+ trans_rec->cache_data_pos = ctx->last_rec_pos; - ctx->last_rec_pos = size; - } - --- -1.7.10.2 - - -From 4b733318b4ff228f7e920adc19d5cb4a7d654a4c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 19:14:21 +0300 -Subject: [PATCH] dbox: Added support for POP3 message order. - - -diff --git a/src/doveadm/doveadm-dump-dbox.c b/src/doveadm/doveadm-dump-dbox.c -index 35aaa8a..17f4c24 100644 ---- a/src/doveadm/doveadm-dump-dbox.c -+++ b/src/doveadm/doveadm-dump-dbox.c -@@ -148,6 +148,9 @@ static void dump_msg_metadata(struct istream *input) - case DBOX_METADATA_POP3_UIDL: - printf("msg.pop3-uidl = %s\n", line + 1); - break; -+ case DBOX_METADATA_POP3_ORDER: -+ printf("msg.pop3-order = %s\n", line + 1); -+ break; - case DBOX_METADATA_RECEIVED_TIME: - dump_timestamp(input, "msg.received", line + 1); - break; -diff --git a/src/lib-storage/index/dbox-common/dbox-file.h b/src/lib-storage/index/dbox-common/dbox-file.h -index 5b94535..f790a35 100644 ---- a/src/lib-storage/index/dbox-common/dbox-file.h -+++ b/src/lib-storage/index/dbox-common/dbox-file.h -@@ -45,6 +45,8 @@ enum dbox_metadata_key { - DBOX_METADATA_GUID = 'G', - /* POP3 UIDL overriding the default format */ - DBOX_METADATA_POP3_UIDL = 'P', -+ /* POP3 message ordering (for migrated mails) */ -+ DBOX_METADATA_POP3_ORDER = 'O', - /* Received UNIX timestamp in hex */ - DBOX_METADATA_RECEIVED_TIME = 'R', - /* Physical message size in hex. Necessary only if it differs from -diff --git a/src/lib-storage/index/dbox-common/dbox-mail.c b/src/lib-storage/index/dbox-common/dbox-mail.c -index 3ec1e1b..90bf176 100644 ---- a/src/lib-storage/index/dbox-common/dbox-mail.c -+++ b/src/lib-storage/index/dbox-common/dbox-mail.c -@@ -165,12 +165,19 @@ dbox_get_cached_metadata(struct dbox_mail *mail, enum dbox_metadata_key key, - INDEX_STORAGE_CONTEXT(imail->mail.mail.box); - const char *value; - string_t *str; -+ uint32_t order; - - str = str_new(imail->mail.data_pool, 64); - if (mail_cache_lookup_field(imail->mail.mail.transaction->cache_view, - str, imail->mail.mail.seq, - ibox->cache_fields[cache_field].idx) > 0) { -- *value_r = str_c(str); -+ if (cache_field != MAIL_CACHE_POP3_ORDER) -+ *value_r = str_c(str); -+ else { -+ i_assert(str_len(str) == sizeof(order)); -+ memcpy(&order, str_data(str), sizeof(order)); -+ *value_r = dec2str(order); -+ } - return 0; - } - -@@ -179,8 +186,15 @@ dbox_get_cached_metadata(struct dbox_mail *mail, enum dbox_metadata_key key, - - if (value == NULL) - value = ""; -- index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx, -- value, strlen(value)+1); -+ if (cache_field != MAIL_CACHE_POP3_ORDER) { -+ index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx, -+ value, strlen(value)+1); -+ } else { -+ if (str_to_uint(value, &order) < 0) -+ order = 0; -+ index_mail_cache_add_idx(imail, ibox->cache_fields[cache_field].idx, -+ &order, sizeof(order)); -+ } - - /* don't return pointer to dbox metadata directly, since it may - change unexpectedly */ -@@ -202,6 +216,9 @@ int dbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field, - case MAIL_FETCH_UIDL_BACKEND: - return dbox_get_cached_metadata(mail, DBOX_METADATA_POP3_UIDL, - MAIL_CACHE_POP3_UIDL, value_r); -+ case MAIL_FETCH_POP3_ORDER: -+ return dbox_get_cached_metadata(mail, DBOX_METADATA_POP3_ORDER, -+ MAIL_CACHE_POP3_ORDER, value_r); - case MAIL_FETCH_GUID: - return dbox_get_cached_metadata(mail, DBOX_METADATA_GUID, - MAIL_CACHE_GUID, value_r); -diff --git a/src/lib-storage/index/dbox-common/dbox-save.c b/src/lib-storage/index/dbox-common/dbox-save.c -index e7d0e4c..1aaa676 100644 ---- a/src/lib-storage/index/dbox-common/dbox-save.c -+++ b/src/lib-storage/index/dbox-common/dbox-save.c -@@ -164,6 +164,10 @@ void dbox_save_write_metadata(struct mail_save_context *_ctx, - str_printfa(str, "%c%s\n", DBOX_METADATA_POP3_UIDL, - mdata->pop3_uidl); - } -+ if (mdata->pop3_order != 0) { -+ str_printfa(str, "%c%u\n", DBOX_METADATA_POP3_ORDER, -+ mdata->pop3_order); -+ } - - guid = mdata->guid; - if (guid != NULL) -diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c -index bb6929d..dc3a25b 100644 ---- a/src/lib-storage/index/index-mail.c -+++ b/src/lib-storage/index/index-mail.c -@@ -46,6 +46,9 @@ struct mail_cache_field global_cache_fields[MAIL_INDEX_CACHE_FIELD_COUNT] = { - .type = MAIL_CACHE_FIELD_STRING }, - { .name = "pop3.uidl", - .type = MAIL_CACHE_FIELD_STRING }, -+ { .name = "pop3.order", -+ .type = MAIL_CACHE_FIELD_FIXED_SIZE, -+ .field_size = sizeof(uint32_t) }, - { .name = "guid", - .type = MAIL_CACHE_FIELD_STRING }, - { .name = "mime.parts", -@@ -1871,6 +1874,8 @@ void index_mail_precache(struct mail *mail) - (void)mail_get_physical_size(mail, &size); - if ((cache & MAIL_FETCH_UIDL_BACKEND) != 0) - (void)mail_get_special(mail, MAIL_FETCH_UIDL_BACKEND, &str); -+ if ((cache & MAIL_FETCH_POP3_ORDER) != 0) -+ (void)mail_get_special(mail, MAIL_FETCH_POP3_ORDER, &str); - if ((cache & MAIL_FETCH_GUID) != 0) - (void)mail_get_special(mail, MAIL_FETCH_GUID, &str); - } -diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h -index 4acf146..bc6d8af 100644 ---- a/src/lib-storage/index/index-mail.h -+++ b/src/lib-storage/index/index-mail.h -@@ -19,6 +19,7 @@ enum index_cache_field { - MAIL_CACHE_IMAP_BODYSTRUCTURE, - MAIL_CACHE_IMAP_ENVELOPE, - MAIL_CACHE_POP3_UIDL, -+ MAIL_CACHE_POP3_ORDER, - MAIL_CACHE_GUID, - MAIL_CACHE_MESSAGE_PARTS, - MAIL_CACHE_BINARY_PARTS, --- -1.7.10.2 - - -From 4a11e3d91412544649014b5edb6376eec1791b28 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 21:07:09 +0300 -Subject: [PATCH] imapc: Pass through SPECIAL-USE LIST flags if imapc is in - INBOX namespace. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index 4f31614..52fbd3a 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -18,6 +18,26 @@ struct imapc_mailbox_list_iterate_context { - - struct mailbox_tree_iterate_context *iter; - struct mailbox_info info; -+ string_t *special_use; -+}; -+ -+static struct { -+ const char *str; -+ enum mailbox_info_flags flag; -+} imap_list_flags[] = { -+ { "\\NoSelect", MAILBOX_NOSELECT }, -+ { "\\NonExistent", MAILBOX_NONEXISTENT }, -+ { "\\NoInferiors", MAILBOX_NOINFERIORS }, -+ { "\\Subscribed", MAILBOX_SUBSCRIBED }, -+ { "\\Subscribed", MAILBOX_SUBSCRIBED }, -+ { "\\All", MAILBOX_SPECIALUSE_ALL }, -+ { "\\Archive", MAILBOX_SPECIALUSE_ARCHIVE }, -+ { "\\Drafts", MAILBOX_SPECIALUSE_DRAFTS }, -+ { "\\Flagged", MAILBOX_SPECIALUSE_FLAGGED }, -+ { "\\Junk", MAILBOX_SPECIALUSE_JUNK }, -+ { "\\Sent", MAILBOX_SPECIALUSE_SENT }, -+ { "\\Trash", MAILBOX_SPECIALUSE_TRASH }, -+ { "\\Important", MAILBOX_SPECIALUSE_IMPORTANT } - }; - - extern struct mailbox_list imapc_mailbox_list; -@@ -63,6 +83,20 @@ static void imapc_list_simple_callback(const struct imapc_command_reply *reply, - } - } - -+static bool -+imap_list_flag_parse(const char *str, enum mailbox_info_flags *flag_r) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < N_ELEMENTS(imap_list_flags); i++) { -+ if (strcasecmp(str, imap_list_flags[i].str) == 0) { -+ *flag_r = imap_list_flags[i].flag; -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ - static struct mailbox_node * - imapc_list_update_tree(struct imapc_mailbox_list *list, - struct mailbox_tree_context *tree, -@@ -71,7 +105,7 @@ imapc_list_update_tree(struct imapc_mailbox_list *list, - struct mailbox_node *node; - const struct imap_arg *flags; - const char *name, *flag; -- enum mailbox_info_flags info_flags = 0; -+ enum mailbox_info_flags info_flag, info_flags = 0; - bool created; - - if (!imap_arg_get_list(&args[0], &flags) || -@@ -80,14 +114,8 @@ imapc_list_update_tree(struct imapc_mailbox_list *list, - return NULL; - - while (imap_arg_get_atom(flags, &flag)) { -- if (strcasecmp(flag, "\\NoSelect") == 0) -- info_flags |= MAILBOX_NOSELECT; -- else if (strcasecmp(flag, "\\NonExistent") == 0) -- info_flags |= MAILBOX_NONEXISTENT; -- else if (strcasecmp(flag, "\\NoInferiors") == 0) -- info_flags |= MAILBOX_NOINFERIORS; -- else if (strcasecmp(flag, "\\Subscribed") == 0) -- info_flags |= MAILBOX_SUBSCRIBED; -+ if (imap_list_flag_parse(flag, &info_flag)) -+ info_flags |= info_flag; - flags++; - } - -@@ -450,6 +478,31 @@ imapc_list_iter_init(struct mailbox_list *_list, const char *const *patterns, - return &ctx->ctx; - } - -+static void -+imapc_list_write_special_use(struct imapc_mailbox_list_iterate_context *ctx, -+ struct mailbox_node *node) -+{ -+ unsigned int i; -+ -+ if (ctx->special_use == NULL) -+ ctx->special_use = str_new(ctx->ctx.pool, 64); -+ str_truncate(ctx->special_use, 0); -+ -+ for (i = 0; i < N_ELEMENTS(imap_list_flags); i++) { -+ if ((node->flags & imap_list_flags[i].flag) != 0) { -+ str_append(ctx->special_use, imap_list_flags[i].str); -+ str_append_c(ctx->special_use, ' '); -+ } -+ } -+ -+ if (str_len(ctx->special_use) > 0) { -+ str_truncate(ctx->special_use, str_len(ctx->special_use) - 1); -+ ctx->info.special_use = str_c(ctx->special_use); -+ } else { -+ ctx->info.special_use = NULL; -+ } -+} -+ - static const struct mailbox_info * - imapc_list_iter_next(struct mailbox_list_iterate_context *_ctx) - { -@@ -472,6 +525,13 @@ imapc_list_iter_next(struct mailbox_list_iterate_context *_ctx) - - ctx->info.vname = vname; - ctx->info.flags = node->flags; -+ if ((_ctx->list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { -+ /* we're iterating the INBOX namespace. pass through the -+ SPECIAL-USE flags if they exist. */ -+ imapc_list_write_special_use(ctx, node); -+ } else { -+ ctx->info.special_use = NULL; -+ } - return &ctx->info; - } - -diff --git a/src/lib-storage/mailbox-list.h b/src/lib-storage/mailbox-list.h -index edd301c..fb4096f 100644 ---- a/src/lib-storage/mailbox-list.h -+++ b/src/lib-storage/mailbox-list.h -@@ -48,7 +48,18 @@ enum mailbox_info_flags { - MAILBOX_CHILD_SUBSCRIBED = 0x100, - MAILBOX_CHILD_SPECIALUSE = 0x200, - -- /* Internally used by lib-storage */ -+ /* Internally used by lib-storage, use mailbox_info.special_use -+ to actually access these: */ -+ MAILBOX_SPECIALUSE_ALL = 0x00010000, -+ MAILBOX_SPECIALUSE_ARCHIVE = 0x00020000, -+ MAILBOX_SPECIALUSE_DRAFTS = 0x00040000, -+ MAILBOX_SPECIALUSE_FLAGGED = 0x00080000, -+ MAILBOX_SPECIALUSE_JUNK = 0x00100000, -+ MAILBOX_SPECIALUSE_SENT = 0x00200000, -+ MAILBOX_SPECIALUSE_TRASH = 0x00400000, -+ MAILBOX_SPECIALUSE_IMPORTANT = 0x00800000, -+ -+ /* Internally used by lib-storage: */ - MAILBOX_SELECT = 0x20000000, - MAILBOX_MATCHED = 0x40000000 - }; --- -1.7.10.2 - - -From 05508c41a5a10da2a2cffe645d0f661c9743b9de Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 21:20:47 +0300 -Subject: [PATCH] dsync: Small code cleanup. - - -diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c -index 73cfe60..895ff46 100644 ---- a/src/doveadm/dsync/doveadm-dsync.c -+++ b/src/doveadm/dsync/doveadm-dsync.c -@@ -486,16 +486,22 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx; - struct dsync_ibc *ibc, *ibc2 = NULL; - struct dsync_brain *brain; -- struct mail_namespace *sync_ns = NULL; -+ struct dsync_brain_settings set; - enum dsync_brain_flags brain_flags; - bool remote_errors_logged = FALSE; - int status = 0, ret = 0; - -+ memset(&set, 0, sizeof(set)); -+ set.sync_box = ctx->mailbox; -+ memcpy(set.sync_box_guid, ctx->mailbox_guid, sizeof(set.sync_box_guid)); -+ set.lock_timeout_secs = ctx->lock_timeout; -+ set.state = ctx->state_input; -+ - user->dsyncing = TRUE; - - if (ctx->namespace_prefix != NULL) { -- sync_ns = mail_namespace_find(user->namespaces, -- ctx->namespace_prefix); -+ set.sync_ns = mail_namespace_find(user->namespaces, -+ ctx->namespace_prefix); - } - - if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL) -@@ -524,12 +530,9 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - brain_flags |= DSYNC_BRAIN_FLAG_NO_MAIL_SYNC; - if (doveadm_debug) - brain_flags |= DSYNC_BRAIN_FLAG_DEBUG; -- brain = dsync_brain_master_init(user, ibc, sync_ns, ctx->mailbox, -- ctx->mailbox_guid, -- ctx->sync_type, brain_flags, -- ctx->lock_timeout, -- ctx->state_input == NULL ? "" : -- ctx->state_input); -+ -+ brain = dsync_brain_master_init(user, ibc, ctx->sync_type, -+ brain_flags, &set); - - if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL) { - if (cmd_dsync_run_local(ctx, user, brain, ibc2) < 0) -diff --git a/src/doveadm/dsync/dsync-brain.c b/src/doveadm/dsync/dsync-brain.c -index f305520..ca48d22 100644 ---- a/src/doveadm/dsync/dsync-brain.c -+++ b/src/doveadm/dsync/dsync-brain.c -@@ -86,32 +86,32 @@ dsync_brain_set_flags(struct dsync_brain *brain, enum dsync_brain_flags flags) - - struct dsync_brain * - dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, -- struct mail_namespace *sync_ns, const char *sync_box, -- const guid_128_t sync_box_guid, - enum dsync_brain_sync_type sync_type, -- enum dsync_brain_flags flags, unsigned int lock_timeout, -- const char *state) -+ enum dsync_brain_flags flags, -+ const struct dsync_brain_settings *set) - { - struct dsync_ibc_settings ibc_set; - struct dsync_brain *brain; - const char *error; - - i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_UNKNOWN); -- i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE || *state != '\0'); -+ i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE || -+ (set->state != NULL && *set->state != '\0')); - - brain = dsync_brain_common_init(user, ibc); - brain->sync_type = sync_type; -- if (sync_ns != NULL) -- brain->sync_ns = sync_ns; -- brain->sync_box = p_strdup(brain->pool, sync_box); -- memcpy(brain->sync_box_guid, sync_box_guid, sizeof(brain->sync_box_guid)); -- brain->lock_timeout = lock_timeout; -+ if (set->sync_ns != NULL) -+ brain->sync_ns = set->sync_ns; -+ brain->sync_box = p_strdup(brain->pool, set->sync_box); -+ memcpy(brain->sync_box_guid, set->sync_box_guid, -+ sizeof(brain->sync_box_guid)); -+ brain->lock_timeout = set->lock_timeout_secs; - brain->master_brain = TRUE; - dsync_brain_set_flags(brain, flags); - - if (sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE && - dsync_mailbox_states_import(brain->mailbox_states, -- brain->pool, state, &error) < 0) { -+ brain->pool, set->state, &error) < 0) { - hash_table_clear(brain->mailbox_states, FALSE); - i_error("Saved sync state is invalid, " - "falling back to full sync: %s", error); -@@ -121,12 +121,13 @@ dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, - - memset(&ibc_set, 0, sizeof(ibc_set)); - ibc_set.hostname = my_hostdomain(); -- ibc_set.sync_ns_prefix = sync_ns == NULL ? NULL : sync_ns->prefix; -- ibc_set.sync_box = sync_box; -- memcpy(ibc_set.sync_box_guid, sync_box_guid, -+ ibc_set.sync_ns_prefix = set->sync_ns == NULL ? NULL : -+ set->sync_ns->prefix; -+ ibc_set.sync_box = set->sync_box; -+ memcpy(ibc_set.sync_box_guid, set->sync_box_guid, - sizeof(ibc_set.sync_box_guid)); - ibc_set.sync_type = sync_type; -- ibc_set.lock_timeout = lock_timeout; -+ ibc_set.lock_timeout = set->lock_timeout_secs; - /* reverse the backup direction for the slave */ - ibc_set.brain_flags = flags & ~(DSYNC_BRAIN_FLAG_BACKUP_SEND | - DSYNC_BRAIN_FLAG_BACKUP_RECV); -diff --git a/src/doveadm/dsync/dsync-brain.h b/src/doveadm/dsync/dsync-brain.h -index 29bf4d2..ff0af27 100644 ---- a/src/doveadm/dsync/dsync-brain.h -+++ b/src/doveadm/dsync/dsync-brain.h -@@ -30,13 +30,25 @@ enum dsync_brain_sync_type { - DSYNC_BRAIN_SYNC_TYPE_STATE - }; - -+struct dsync_brain_settings { -+ /* Sync only this namespace */ -+ struct mail_namespace *sync_ns; -+ /* Sync only this mailbox name */ -+ const char *sync_box; -+ /* Sync only this mailbox GUID */ -+ guid_128_t sync_box_guid; -+ -+ /* If non-zero, use dsync lock file for this user */ -+ unsigned int lock_timeout_secs; -+ /* Input state for DSYNC_BRAIN_SYNC_TYPE_STATE */ -+ const char *state; -+}; -+ - struct dsync_brain * - dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, -- struct mail_namespace *sync_ns, const char *sync_box, -- const guid_128_t sync_box_guid, - enum dsync_brain_sync_type sync_type, -- enum dsync_brain_flags flags, unsigned int lock_timeout, -- const char *state); -+ enum dsync_brain_flags flags, -+ const struct dsync_brain_settings *set); - struct dsync_brain * - dsync_brain_slave_init(struct mail_user *user, struct dsync_ibc *ibc); - /* Returns 0 if everything was successful, -1 if syncing failed in some way */ --- -1.7.10.2 - - -From 1aad34445081a0f35bc964b989b3983918bd6e52 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 21:44:50 +0300 -Subject: [PATCH] imapc: Fixed assert-crash when copying messages. - - -diff --git a/src/lib-storage/index/imapc/imapc-save.c b/src/lib-storage/index/imapc/imapc-save.c -index 7e80c7c..0556b76 100644 ---- a/src/lib-storage/index/imapc/imapc-save.c -+++ b/src/lib-storage/index/imapc/imapc-save.c -@@ -422,6 +422,7 @@ int imapc_copy(struct mail_save_context *_ctx, struct mail *mail) - while (sctx.ret == -2) - imapc_storage_run(src_mbox->storage); - ctx->finished = TRUE; -+ index_save_context_free(_ctx); - return sctx.ret; - } - return mail_storage_copy(_ctx, mail); --- -1.7.10.2 - - -From aea076fdc28d751590981cdb305086526dbb1671 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 26 May 2013 21:57:36 +0300 -Subject: [PATCH] dsync: Added -x parameter to exclude mailboxes from sync. - Multiple -x parameters can be added. Giving \flag as - parameter means that the mailbox with the given SPECIAL-USE - \flag is skipped. For example: - -doveadm sync -x '\All' -x '\Flagged' -x '\Important' mdbox:~/mdbox - -diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c -index 895ff46..a1e6e9d 100644 ---- a/src/doveadm/dsync/doveadm-dsync.c -+++ b/src/doveadm/dsync/doveadm-dsync.c -@@ -36,7 +36,7 @@ - #include - #include - --#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:U" -+#define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:Ux:" - #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 - - enum dsync_run_type { -@@ -51,6 +51,7 @@ struct dsync_cmd_context { - const char *mailbox, *namespace_prefix; - guid_128_t mailbox_guid; - const char *state_input, *rawlog_path; -+ ARRAY_TYPE(const_string) exclude_mailboxes; - - const char *remote_name; - const char *local_location; -@@ -496,6 +497,10 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - memcpy(set.sync_box_guid, ctx->mailbox_guid, sizeof(set.sync_box_guid)); - set.lock_timeout_secs = ctx->lock_timeout; - set.state = ctx->state_input; -+ if (array_count(&ctx->exclude_mailboxes) > 0) { -+ /* array is NULL-terminated in init() */ -+ set.exclude_mailboxes = array_idx(&ctx->exclude_mailboxes, 0); -+ } - - user->dsyncing = TRUE; - -@@ -803,6 +808,8 @@ static void cmd_dsync_init(struct doveadm_mail_cmd_context *_ctx, - if (args[0] == NULL) - doveadm_mail_help_name(_ctx->cmd->name); - } -+ if (array_count(&ctx->exclude_mailboxes) > 0) -+ array_append_zero(&ctx->exclude_mailboxes); - - lib_signals_ignore(SIGHUP, TRUE); - } -@@ -817,6 +824,7 @@ static bool - cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) - { - struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx; -+ const char *str; - - switch (c) { - case 'd': -@@ -847,6 +855,10 @@ cmd_mailbox_dsync_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c) - else - ctx->mailbox = optarg; - break; -+ case 'x': -+ str = optarg; -+ array_append(&ctx->exclude_mailboxes, &str, 1); -+ break; - case 'n': - ctx->namespace_prefix = optarg; - break; -@@ -891,6 +903,7 @@ static struct doveadm_mail_cmd_context *cmd_dsync_alloc(void) - doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); - doveadm_print_header("state", "state", - DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); -+ p_array_init(&ctx->exclude_mailboxes, ctx->ctx.pool, 4); - return &ctx->ctx; - } - -@@ -995,11 +1008,11 @@ static struct doveadm_mail_cmd_context *cmd_dsync_server_alloc(void) - - struct doveadm_mail_cmd cmd_dsync_mirror = { - cmd_dsync_alloc, "sync", -- "[-dfR] [-l ] [-m ] [-n ] [-s ] " -+ "[-dfR] [-l ] [-m ] [-n ] [-x ] [-s ] " - }; - struct doveadm_mail_cmd cmd_dsync_backup = { - cmd_dsync_backup_alloc, "backup", -- "[-dfR] [-l ] [-m ] [-n ] [-s ] " -+ "[-dfR] [-l ] [-m ] [-n ] [-x ] [-s ] " - }; - struct doveadm_mail_cmd cmd_dsync_server = { - cmd_dsync_server_alloc, "dsync-server", &doveadm_mail_cmd_hide -diff --git a/src/doveadm/dsync/dsync-brain-mailbox-tree.c b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -index fb13444..fc9b79e 100644 ---- a/src/doveadm/dsync/dsync-brain-mailbox-tree.c -+++ b/src/doveadm/dsync/dsync-brain-mailbox-tree.c -@@ -83,20 +83,14 @@ void dsync_brain_mailbox_trees_init(struct dsync_brain *brain) - doveadm_settings->dsync_alt_char[0]); - - /* fill the local mailbox tree */ -- if (brain->sync_ns != NULL) { -- if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, -- brain->sync_ns, brain->sync_box, -- brain->sync_box_guid) < 0) -+ for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) { -+ if (!dsync_brain_want_namespace(brain, ns)) -+ continue; -+ if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns, -+ brain->sync_box, -+ brain->sync_box_guid, -+ brain->exclude_mailboxes) < 0) - brain->failed = TRUE; -- } else { -- for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) { -- if (!dsync_brain_want_namespace(brain, ns)) -- continue; -- if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, -- ns, brain->sync_box, -- brain->sync_box_guid) < 0) -- brain->failed = TRUE; -- } - } - - brain->local_tree_iter = -diff --git a/src/doveadm/dsync/dsync-brain-private.h b/src/doveadm/dsync/dsync-brain-private.h -index 0021a03..63b8a75 100644 ---- a/src/doveadm/dsync/dsync-brain-private.h -+++ b/src/doveadm/dsync/dsync-brain-private.h -@@ -52,6 +52,7 @@ struct dsync_brain { - struct mail_namespace *sync_ns; - const char *sync_box; - guid_128_t sync_box_guid; -+ const char *const *exclude_mailboxes; - enum dsync_brain_sync_type sync_type; - - unsigned int lock_timeout; -diff --git a/src/doveadm/dsync/dsync-brain.c b/src/doveadm/dsync/dsync-brain.c -index ca48d22..803c447 100644 ---- a/src/doveadm/dsync/dsync-brain.c -+++ b/src/doveadm/dsync/dsync-brain.c -@@ -103,6 +103,8 @@ dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, - if (set->sync_ns != NULL) - brain->sync_ns = set->sync_ns; - brain->sync_box = p_strdup(brain->pool, set->sync_box); -+ brain->exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL : -+ p_strarray_dup(brain->pool, set->exclude_mailboxes); - memcpy(brain->sync_box_guid, set->sync_box_guid, - sizeof(brain->sync_box_guid)); - brain->lock_timeout = set->lock_timeout_secs; -@@ -124,6 +126,7 @@ dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, - ibc_set.sync_ns_prefix = set->sync_ns == NULL ? NULL : - set->sync_ns->prefix; - ibc_set.sync_box = set->sync_box; -+ ibc_set.exclude_mailboxes = set->exclude_mailboxes; - memcpy(ibc_set.sync_box_guid, set->sync_box_guid, - sizeof(ibc_set.sync_box_guid)); - ibc_set.sync_type = sync_type; -@@ -312,6 +315,8 @@ static bool dsync_brain_slave_recv_handshake(struct dsync_brain *brain) - ibc_set->sync_ns_prefix); - } - brain->sync_box = p_strdup(brain->pool, ibc_set->sync_box); -+ brain->exclude_mailboxes = ibc_set->exclude_mailboxes == NULL ? NULL : -+ p_strarray_dup(brain->pool, ibc_set->exclude_mailboxes); - memcpy(brain->sync_box_guid, ibc_set->sync_box_guid, - sizeof(brain->sync_box_guid)); - i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN); -diff --git a/src/doveadm/dsync/dsync-brain.h b/src/doveadm/dsync/dsync-brain.h -index ff0af27..6d7c218 100644 ---- a/src/doveadm/dsync/dsync-brain.h -+++ b/src/doveadm/dsync/dsync-brain.h -@@ -37,6 +37,9 @@ struct dsync_brain_settings { - const char *sync_box; - /* Sync only this mailbox GUID */ - guid_128_t sync_box_guid; -+ /* Exclude these mailboxes from the sync. They can contain '*' -+ wildcards and be \special-use flags. */ -+ const char *const *exclude_mailboxes; - - /* If non-zero, use dsync lock file for this user */ - unsigned int lock_timeout_secs; -diff --git a/src/doveadm/dsync/dsync-ibc-pipe.c b/src/doveadm/dsync/dsync-ibc-pipe.c -index 6bf962e..da81312 100644 ---- a/src/doveadm/dsync/dsync-ibc-pipe.c -+++ b/src/doveadm/dsync/dsync-ibc-pipe.c -@@ -161,6 +161,8 @@ dsync_ibc_pipe_send_handshake(struct dsync_ibc *ibc, - item->u.set = *set; - item->u.set.sync_ns_prefix = p_strdup(item->pool, set->sync_ns_prefix); - item->u.set.sync_box = p_strdup(item->pool, set->sync_box); -+ item->u.set.exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL : -+ p_strarray_dup(item->pool, set->exclude_mailboxes); - memcpy(item->u.set.sync_box_guid, set->sync_box_guid, - sizeof(item->u.set.sync_box_guid)); - } -diff --git a/src/doveadm/dsync/dsync-ibc-stream.c b/src/doveadm/dsync/dsync-ibc-stream.c -index 3dab919..ef9a1af 100644 ---- a/src/doveadm/dsync/dsync-ibc-stream.c -+++ b/src/doveadm/dsync/dsync-ibc-stream.c -@@ -73,7 +73,7 @@ static const struct { - .chr = 'H', - .required_keys = "hostname", - .optional_keys = "sync_ns_prefix sync_box sync_box_guid sync_type " -- "debug sync_visible_namespaces " -+ "debug sync_visible_namespaces exclude_mailboxes" - "send_mail_requests backup_send backup_recv lock_timeout" - }, - { .name = "mailbox_state", -@@ -594,6 +594,18 @@ dsync_ibc_stream_send_handshake(struct dsync_ibc *_ibc, - } - if (set->sync_box != NULL) - dsync_serializer_encode_add(encoder, "sync_box", set->sync_box); -+ if (set->exclude_mailboxes != NULL) { -+ string_t *substr = t_str_new(64); -+ unsigned int i; -+ -+ for (i = 0; set->exclude_mailboxes[i] != NULL; i++) { -+ if (i != 0) -+ str_append_c(substr, '\t'); -+ str_append_tabescaped(substr, set->exclude_mailboxes[i]); -+ } -+ dsync_serializer_encode_add(encoder, "exclude_mailboxes", -+ str_c(substr)); -+ } - if (!guid_128_is_empty(set->sync_box_guid)) { - dsync_serializer_encode_add(encoder, "sync_box_guid", - guid_128_to_string(set->sync_box_guid)); -@@ -670,6 +682,11 @@ dsync_ibc_stream_recv_handshake(struct dsync_ibc *_ibc, - "Invalid sync_box_guid: %s", value); - return DSYNC_IBC_RECV_RET_TRYAGAIN; - } -+ if (dsync_deserializer_decode_try(decoder, "exclude_mailboxes", &value) && -+ *value != '\0') { -+ char **boxes = p_strsplit_tabescaped(pool, value); -+ set->exclude_mailboxes = (const void *)boxes; -+ } - if (dsync_deserializer_decode_try(decoder, "sync_type", &value)) { - switch (value[0]) { - case 'f': -diff --git a/src/doveadm/dsync/dsync-ibc.h b/src/doveadm/dsync/dsync-ibc.h -index b1d2a26..6700dfb 100644 ---- a/src/doveadm/dsync/dsync-ibc.h -+++ b/src/doveadm/dsync/dsync-ibc.h -@@ -49,6 +49,9 @@ struct dsync_ibc_settings { - const char *sync_box; - /* if non-empty, sync only this mailbox GUID */ - guid_128_t sync_box_guid; -+ /* Exclude these mailboxes from the sync. They can contain '*' -+ wildcards and be \special-use flags. */ -+ const char *const *exclude_mailboxes; - - enum dsync_brain_sync_type sync_type; - enum dsync_brain_flags brain_flags; -diff --git a/src/doveadm/dsync/dsync-mailbox-tree-fill.c b/src/doveadm/dsync/dsync-mailbox-tree-fill.c -index 9480ebb..8af9fad 100644 ---- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c -+++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c -@@ -5,6 +5,7 @@ - #include "hash.h" - #include "guid.h" - #include "str.h" -+#include "wildcard-match.h" - #include "mailbox-log.h" - #include "mail-namespace.h" - #include "mail-storage.h" -@@ -265,9 +266,39 @@ dsync_mailbox_tree_fix_guid_duplicate(struct dsync_mailbox_tree *tree, - return ret; - } - -+static bool -+dsync_mailbox_info_is_excluded(const struct mailbox_info *info, -+ const char *const *exclude_mailboxes) -+{ -+ const char *const *info_specialuses; -+ unsigned int i; -+ -+ if (exclude_mailboxes == NULL) -+ return FALSE; -+ -+ info_specialuses = info->special_use == NULL ? NULL : -+ t_strsplit(info->special_use, " "); -+ for (i = 0; exclude_mailboxes[i] != NULL; i++) { -+ const char *exclude = exclude_mailboxes[i]; -+ -+ if (exclude[0] == '\\') { -+ /* special-use */ -+ if (info_specialuses != NULL && -+ str_array_icase_find(info_specialuses, exclude)) -+ return TRUE; -+ } else { -+ /* mailbox with wildcards */ -+ if (wildcard_match(info->vname, exclude)) -+ return TRUE; -+ } -+ } -+ return FALSE; -+} -+ - int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, - struct mail_namespace *ns, const char *box_name, -- const guid_128_t box_guid) -+ const guid_128_t box_guid, -+ const char *const *exclude_mailboxes) - { - const enum mailbox_list_iter_flags list_flags = - /* FIXME: we'll skip symlinks, because we can't handle them -@@ -298,10 +329,12 @@ int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, - - /* first add all of the existing mailboxes */ - iter = mailbox_list_iter_init(ns->list, list_pattern, list_flags); -- while ((info = mailbox_list_iter_next(iter)) != NULL) { -- if (dsync_mailbox_tree_add(tree, info, box_guid) < 0) -- ret = -1; -- } -+ while ((info = mailbox_list_iter_next(iter)) != NULL) T_BEGIN { -+ if (!dsync_mailbox_info_is_excluded(info, exclude_mailboxes)) { -+ if (dsync_mailbox_tree_add(tree, info, box_guid) < 0) -+ ret = -1; -+ } -+ } T_END; - if (mailbox_list_iter_deinit(&iter) < 0) { - i_error("Mailbox listing for namespace '%s' failed", ns->prefix); - ret = -1; -diff --git a/src/doveadm/dsync/dsync-mailbox-tree.h b/src/doveadm/dsync/dsync-mailbox-tree.h -index 5a84b0e..956a570 100644 ---- a/src/doveadm/dsync/dsync-mailbox-tree.h -+++ b/src/doveadm/dsync/dsync-mailbox-tree.h -@@ -132,7 +132,8 @@ void dsync_mailbox_node_copy_data(struct dsync_mailbox_node *dest, - non-NULL, add only that mailbox to the tree. */ - int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, - struct mail_namespace *ns, const char *box_name, -- const guid_128_t box_guid); -+ const guid_128_t box_guid, -+ const char *const *exclude_mailboxes); - - /* Return all known deleted mailboxes and directories. */ - const struct dsync_mailbox_delete * --- -1.7.10.2 - - -From bdd2a13e6d7292808def824df21f6372411f1064 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 27 May 2013 20:18:35 +0300 -Subject: [PATCH] dbox: Return cached pop3.order=0 as empty string instead to - fix sorting problems. - - -diff --git a/src/lib-storage/index/dbox-common/dbox-mail.c b/src/lib-storage/index/dbox-common/dbox-mail.c -index 90bf176..46ee6b0 100644 ---- a/src/lib-storage/index/dbox-common/dbox-mail.c -+++ b/src/lib-storage/index/dbox-common/dbox-mail.c -@@ -176,7 +176,7 @@ dbox_get_cached_metadata(struct dbox_mail *mail, enum dbox_metadata_key key, - else { - i_assert(str_len(str) == sizeof(order)); - memcpy(&order, str_data(str), sizeof(order)); -- *value_r = dec2str(order); -+ *value_r = order == 0 ? "" : dec2str(order); - } - return 0; - } --- -1.7.10.2 - - -From 638eb02fbd1830b9500320ce5e1900972486511f Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 27 May 2013 20:44:05 +0300 -Subject: [PATCH] lib-index: Create ext-intro records using the latest sizes, - not initial sizes. - - -diff --git a/src/lib-index/mail-index-transaction-export.c b/src/lib-index/mail-index-transaction-export.c -index 5c15c04..f890752 100644 ---- a/src/lib-index/mail-index-transaction-export.c -+++ b/src/lib-index/mail-index-transaction-export.c -@@ -86,6 +86,7 @@ static void log_append_ext_intro(struct mail_index_export_context *ctx, - { - struct mail_index_transaction *t = ctx->trans; - const struct mail_index_registered_ext *rext; -+ const struct mail_index_ext *ext; - struct mail_transaction_ext_intro *intro, *resizes; - buffer_t *buf; - uint32_t idx; -@@ -120,12 +121,19 @@ static void log_append_ext_intro(struct mail_index_export_context *ctx, - /* generate a new intro structure */ - intro = buffer_append_space_unsafe(buf, sizeof(*intro)); - intro->ext_id = idx; -- intro->hdr_size = rext->hdr_size; -- intro->record_size = rext->record_size; -- intro->record_align = rext->record_align; -+ if (idx == (uint32_t)-1) { -+ intro->hdr_size = rext->hdr_size; -+ intro->record_size = rext->record_size; -+ intro->record_align = rext->record_align; -+ intro->name_size = strlen(rext->name); -+ } else { -+ ext = array_idx(&t->view->index->map->extensions, idx); -+ intro->hdr_size = ext->hdr_size; -+ intro->record_size = ext->record_size; -+ intro->record_align = ext->record_align; -+ intro->name_size = 0; -+ } - intro->flags = MAIL_TRANSACTION_EXT_INTRO_FLAG_NO_SHRINK; -- intro->name_size = idx != (uint32_t)-1 ? 0 : -- strlen(rext->name); - } - if (reset_id != 0) { - /* we're going to reset this extension in this transaction */ --- -1.7.10.2 - - -From e8dcf6b8e76d0f1d76d8f10431957386a557eda5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 27 May 2013 20:44:56 +0300 -Subject: [PATCH] lib-index: Fixed resizing header when old&new sizes were the - same when aligned. - - -diff --git a/src/lib-index/mail-index-sync-ext.c b/src/lib-index/mail-index-sync-ext.c -index d9f034c..68c2a2d 100644 ---- a/src/lib-index/mail-index-sync-ext.c -+++ b/src/lib-index/mail-index-sync-ext.c -@@ -289,6 +289,13 @@ sync_ext_resize(const struct mail_transaction_ext_intro *u, - new_size - old_size); - ext->hdr_size = u->hdr_size; - modified = TRUE; -+ } else { -+ if (ext->hdr_size != u->hdr_size) { -+ /* aligned sizes were the same, but the actual sizes -+ had changed */ -+ ext->hdr_size = u->hdr_size; -+ modified = TRUE; -+ } - } - - if (ext->record_align < u->record_align || --- -1.7.10.2 - - -From 9b6d57eef75710f25f87150c951385de789fa66e Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 27 May 2013 20:45:08 +0300 -Subject: [PATCH] lib-index: Added mail_index_ext_resize_hdr() - - -diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c -index aae27e2..fa88b85 100644 ---- a/src/lib-index/mail-index-transaction-update.c -+++ b/src/lib-index/mail-index-transaction-update.c -@@ -717,7 +717,7 @@ void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, - uint16_t record_align) - { - struct mail_transaction_ext_intro intro; -- uint32_t old_record_size, old_record_align; -+ uint32_t old_record_size, old_record_align, old_header_size; - - memset(&intro, 0, sizeof(intro)); - -@@ -730,17 +730,20 @@ void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, - rext = array_idx(&t->view->index->extensions, ext_id); - old_record_size = rext->record_size; - old_record_align = rext->record_align; -+ old_header_size = rext->hdr_size; - } else { - const struct mail_index_ext *ext; - - ext = array_idx(&t->view->map->extensions, intro.ext_id); - old_record_size = ext->record_size; - old_record_align = ext->record_align; -+ old_header_size = ext->hdr_size; - } - - /* allow only header size changes if extension records have already - been changed in transaction */ - i_assert(!array_is_created(&t->ext_rec_updates) || -+ record_size == (uint16_t)-1 || - (old_record_size == record_size && - old_record_align == record_align)); - -@@ -749,13 +752,26 @@ void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, - if (!array_is_created(&t->ext_resizes)) - i_array_init(&t->ext_resizes, ext_id + 2); - -- intro.hdr_size = hdr_size; -- intro.record_size = record_size; -- intro.record_align = record_align; -+ intro.hdr_size = hdr_size != (uint32_t)-1 ? hdr_size : old_header_size; -+ if (record_size != (uint16_t)-1) { -+ i_assert(record_align != (uint16_t)-1); -+ intro.record_size = record_size; -+ intro.record_align = record_align; -+ } else { -+ i_assert(record_align == (uint16_t)-1); -+ intro.record_size = old_record_size; -+ intro.record_align = old_record_align; -+ } - intro.name_size = 1; - array_idx_set(&t->ext_resizes, ext_id, &intro); - } - -+void mail_index_ext_resize_hdr(struct mail_index_transaction *t, -+ uint32_t ext_id, uint32_t hdr_size) -+{ -+ mail_index_ext_resize(t, ext_id, hdr_size, (uint16_t)-1, (uint16_t)-1); -+} -+ - void mail_index_ext_reset(struct mail_index_transaction *t, uint32_t ext_id, - uint32_t reset_id, bool clear_data) - { -diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h -index 1a10843..e3a3362 100644 ---- a/src/lib-index/mail-index.h -+++ b/src/lib-index/mail-index.h -@@ -555,6 +555,9 @@ bool mail_index_ext_lookup(struct mail_index *index, const char *name, - void mail_index_ext_resize(struct mail_index_transaction *t, uint32_t ext_id, - uint32_t hdr_size, uint16_t record_size, - uint16_t record_align); -+/* Resize header, keeping the old record size. */ -+void mail_index_ext_resize_hdr(struct mail_index_transaction *t, -+ uint32_t ext_id, uint32_t hdr_size); - - /* Reset extension. Any updates for this extension which were issued before the - writer had seen this reset are discarded. reset_id is used to figure this --- -1.7.10.2 - - -From d62c4a3e4c326b39e0b511ceff80dbcab65ab6af Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Mon, 27 May 2013 21:03:14 +0300 -Subject: [PATCH] dbox: Don't cache pop3.uidl|order unless index header - indicates there are those. They exist only when doing a - migration, so it's pretty wasteful storing "doesn't exist" - for all other installations. - - -diff --git a/src/doveadm/doveadm-dump-index.c b/src/doveadm/doveadm-dump-index.c -index e0dbdc1..d197430 100644 ---- a/src/doveadm/doveadm-dump-index.c -+++ b/src/doveadm/doveadm-dump-index.c -@@ -36,10 +36,14 @@ struct mbox_index_header { - struct sdbox_index_header { - uint32_t rebuild_count; - guid_128_t mailbox_guid; -+ uint8_t flags; -+ uint8_t unused[3]; - }; - struct mdbox_index_header { - uint32_t map_uid_validity; - guid_128_t mailbox_guid; -+ uint8_t flags; -+ uint8_t unused[3]; - }; - struct mdbox_mail_index_record { - uint32_t map_uid; -@@ -122,11 +126,18 @@ static void dump_extension_header(struct mail_index *index, - const struct mail_index_ext *ext) - { - const void *data; -+ void *buf; - - if (strcmp(ext->name, MAIL_INDEX_EXT_KEYWORDS) == 0) - return; - -+ /* add some padding, since we don't bother to handle undersized -+ headers correctly */ -+ buf = t_malloc0(ext->hdr_size + 128); - data = CONST_PTR_OFFSET(index->map->hdr_base, ext->hdr_offset); -+ memcpy(buf, data, ext->hdr_size); -+ data = buf; -+ - if (strcmp(ext->name, "hdr-vsize") == 0) { - const struct index_vsize_header *hdr = data; - -@@ -164,6 +175,7 @@ static void dump_extension_header(struct mail_index *index, - printf(" - map_uid_validity .. = %u\n", hdr->map_uid_validity); - printf(" - mailbox_guid ...... = %s\n", - guid_128_to_string(hdr->mailbox_guid)); -+ printf(" - flags ............. = 0x%x\n", hdr->flags); - } else if (strcmp(ext->name, "dbox-hdr") == 0) { - const struct sdbox_index_header *hdr = data; - -@@ -171,6 +183,7 @@ static void dump_extension_header(struct mail_index *index, - printf(" - rebuild_count . = %u\n", hdr->rebuild_count); - printf(" - mailbox_guid .. = %s\n", - guid_128_to_string(hdr->mailbox_guid)); -+ printf(" - flags ......... = 0x%x\n", hdr->flags); - } else if (strcmp(ext->name, "modseq") == 0) { - const struct mail_index_modseq_header *hdr = data; - -@@ -241,8 +254,9 @@ static void dump_extensions(struct mail_index *index) - printf("record_offset = %u\n", ext->record_offset); - printf("record_size . = %u\n", ext->record_size); - printf("record_align = %u\n", ext->record_align); -- if (ext->hdr_size > 0) -+ if (ext->hdr_size > 0) T_BEGIN { - dump_extension_header(index, ext); -+ } T_END; - } - } - -diff --git a/src/lib-storage/index/dbox-common/dbox-save.c b/src/lib-storage/index/dbox-common/dbox-save.c -index 1aaa676..ae6ec39 100644 ---- a/src/lib-storage/index/dbox-common/dbox-save.c -+++ b/src/lib-storage/index/dbox-common/dbox-save.c -@@ -163,10 +163,12 @@ void dbox_save_write_metadata(struct mail_save_context *_ctx, - i_assert(strchr(mdata->pop3_uidl, '\n') == NULL); - str_printfa(str, "%c%s\n", DBOX_METADATA_POP3_UIDL, - mdata->pop3_uidl); -+ ctx->have_pop3_uidls = TRUE; - } - if (mdata->pop3_order != 0) { - str_printfa(str, "%c%u\n", DBOX_METADATA_POP3_ORDER, - mdata->pop3_order); -+ ctx->have_pop3_orders = TRUE; - } - - guid = mdata->guid; -@@ -193,3 +195,32 @@ void dbox_save_write_metadata(struct mail_save_context *_ctx, - str_append_c(str, '\n'); - o_stream_nsend(output, str_data(str), str_len(str)); - } -+ -+void dbox_save_update_header_flags(struct dbox_save_context *ctx, -+ struct mail_index_view *sync_view, -+ uint32_t ext_id, -+ unsigned int flags_offset) -+{ -+ const void *data; -+ size_t data_size; -+ uint8_t old_flags = 0, flags; -+ -+ mail_index_get_header_ext(sync_view, ext_id, &data, &data_size); -+ if (flags_offset < data_size) -+ old_flags = *((const uint8_t *)data + flags_offset); -+ else { -+ /* grow old dbox header */ -+ mail_index_ext_resize_hdr(ctx->trans, ext_id, flags_offset+1); -+ } -+ -+ flags = old_flags; -+ if (ctx->have_pop3_uidls) -+ flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS; -+ if (ctx->have_pop3_orders) -+ flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS; -+ if (flags != old_flags) { -+ /* flags changed, update them */ -+ mail_index_update_header_ext(ctx->trans, ext_id, -+ flags_offset, &flags, 1); -+ } -+} -diff --git a/src/lib-storage/index/dbox-common/dbox-save.h b/src/lib-storage/index/dbox-common/dbox-save.h -index 5af8f3b..7b16d1c 100644 ---- a/src/lib-storage/index/dbox-common/dbox-save.h -+++ b/src/lib-storage/index/dbox-common/dbox-save.h -@@ -16,6 +16,8 @@ struct dbox_save_context { - - unsigned int failed:1; - unsigned int finished:1; -+ unsigned int have_pop3_uidls:1; -+ unsigned int have_pop3_orders:1; - }; - - void dbox_save_begin(struct dbox_save_context *ctx, struct istream *input); -@@ -29,4 +31,9 @@ void dbox_save_write_metadata(struct mail_save_context *ctx, - - void dbox_save_add_to_index(struct dbox_save_context *ctx); - -+void dbox_save_update_header_flags(struct dbox_save_context *ctx, -+ struct mail_index_view *sync_view, -+ uint32_t ext_id, -+ unsigned int flags_offset); -+ - #endif -diff --git a/src/lib-storage/index/dbox-common/dbox-storage.c b/src/lib-storage/index/dbox-common/dbox-storage.c -index 0acda1a..7e5b5e2 100644 ---- a/src/lib-storage/index/dbox-common/dbox-storage.c -+++ b/src/lib-storage/index/dbox-common/dbox-storage.c -@@ -336,3 +336,16 @@ int dbox_verify_alt_storage(struct mailbox_list *list) - return -1; - return 0; - } -+ -+bool dbox_header_have_flag(struct mailbox *box, uint32_t ext_id, -+ unsigned int flags_offset, uint8_t flag) -+{ -+ const void *data; -+ size_t data_size; -+ uint8_t flags = 0; -+ -+ mail_index_get_header_ext(box->view, ext_id, &data, &data_size); -+ if (flags_offset < data_size) -+ flags = *((const uint8_t *)data + flags_offset); -+ return (flags & flag) != 0; -+} -diff --git a/src/lib-storage/index/dbox-common/dbox-storage.h b/src/lib-storage/index/dbox-common/dbox-storage.h -index 6a541ef..f4b56ea 100644 ---- a/src/lib-storage/index/dbox-common/dbox-storage.h -+++ b/src/lib-storage/index/dbox-common/dbox-storage.h -@@ -23,6 +23,13 @@ struct dbox_save_context; - /* Flag specifies if the message should be in primary or alternative storage */ - #define DBOX_INDEX_FLAG_ALT MAIL_INDEX_MAIL_FLAG_BACKEND - -+enum dbox_index_header_flags { -+ /* messages' metadata contain POP3 UIDLs */ -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS = 0x01, -+ /* messages' metadata contain POP3 orders */ -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS = 0x02 -+}; -+ - struct dbox_storage_vfuncs { - /* dbox file has zero references now. it should be either freed or - left open in case it's accessed again soon */ -@@ -67,5 +74,7 @@ int dbox_mailbox_open(struct mailbox *box); - int dbox_mailbox_create(struct mailbox *box, - const struct mailbox_update *update, bool directory); - int dbox_verify_alt_storage(struct mailbox_list *list); -+bool dbox_header_have_flag(struct mailbox *box, uint32_t ext_id, -+ unsigned int flags_offset, uint8_t flag); - - #endif -diff --git a/src/lib-storage/index/dbox-multi/mdbox-mail.c b/src/lib-storage/index/dbox-multi/mdbox-mail.c -index 62f6d7e..fe1f519 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-mail.c -+++ b/src/lib-storage/index/dbox-multi/mdbox-mail.c -@@ -21,6 +21,7 @@ int mdbox_mail_lookup(struct mdbox_mailbox *mbox, struct mail_index_view *view, - struct mdbox_index_header hdr; - const void *data; - uint32_t uid, cur_map_uid_validity; -+ bool need_resize; - - mail_index_lookup_ext(view, seq, mbox->ext_id, &data, NULL); - dbox_rec = data; -@@ -34,7 +35,7 @@ int mdbox_mail_lookup(struct mdbox_mailbox *mbox, struct mail_index_view *view, - } - - if (mbox->map_uid_validity == 0) { -- if (mdbox_read_header(mbox, &hdr) < 0) -+ if (mdbox_read_header(mbox, &hdr, &need_resize) < 0) - return -1; - mbox->map_uid_validity = hdr.map_uid_validity; - } -@@ -190,9 +191,26 @@ mdbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field, - *value_r = p_strdup_printf(mail->imail.mail.data_pool, "%u", - refcount); - return 0; -+ case MAIL_FETCH_UIDL_BACKEND: -+ if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, -+ offsetof(struct mdbox_index_header, flags), -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS)) { -+ *value_r = ""; -+ return 0; -+ } -+ break; -+ case MAIL_FETCH_POP3_ORDER: -+ if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, -+ offsetof(struct mdbox_index_header, flags), -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS)) { -+ *value_r = ""; -+ return 0; -+ } -+ break; - default: -- return dbox_mail_get_special(_mail, field, value_r); -+ break; - } -+ return dbox_mail_get_special(_mail, field, value_r); - } - - static void -diff --git a/src/lib-storage/index/dbox-multi/mdbox-save.c b/src/lib-storage/index/dbox-multi/mdbox-save.c -index 06e31e1..8929cdc 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-save.c -+++ b/src/lib-storage/index/dbox-multi/mdbox-save.c -@@ -314,6 +314,10 @@ int mdbox_transaction_save_commit_pre(struct mail_save_context *_ctx) - return -1; - } - -+ /* update dbox header flags */ -+ dbox_save_update_header_flags(&ctx->ctx, ctx->sync_ctx->sync_view, -+ ctx->mbox->hdr_ext_id, offsetof(struct mdbox_index_header, flags)); -+ - /* assign UIDs for new messages */ - hdr = mail_index_get_header(ctx->sync_ctx->sync_view); - mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid, -diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -index 14864c8..96542f4 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -+++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -@@ -58,6 +58,9 @@ struct mdbox_storage_rebuild_context { - struct mailbox_list *default_list; - - struct rebuild_msg_mailbox prev_msg; -+ -+ unsigned int have_pop3_uidls:1; -+ unsigned int have_pop3_orders:1; - }; - - static struct mdbox_storage_rebuild_context * -@@ -126,6 +129,15 @@ static int mdbox_rebuild_msg_uid_cmp(struct mdbox_rebuild_msg *const *m1, - return 0; - } - -+static void rebuild_scan_metadata(struct mdbox_storage_rebuild_context *ctx, -+ struct dbox_file *file) -+{ -+ if (dbox_file_metadata_get(file, DBOX_METADATA_POP3_UIDL) != NULL) -+ ctx->have_pop3_uidls = TRUE; -+ if (dbox_file_metadata_get(file, DBOX_METADATA_POP3_ORDER) != NULL) -+ ctx->have_pop3_orders = TRUE; -+} -+ - static int rebuild_file_mails(struct mdbox_storage_rebuild_context *ctx, - struct dbox_file *file, uint32_t file_id) - { -@@ -177,6 +189,7 @@ static int rebuild_file_mails(struct mdbox_storage_rebuild_context *ctx, - ret = 0; - break; - } -+ rebuild_scan_metadata(ctx, file); - - rec = p_new(ctx->pool, struct mdbox_rebuild_msg, 1); - rec->file_id = file_id; -@@ -476,7 +489,8 @@ mdbox_rebuild_get_header(struct mail_index_view *view, uint32_t hdr_ext_id, - memcpy(hdr_r, data, I_MIN(data_size, sizeof(*hdr_r))); - } - --static void mdbox_header_update(struct index_rebuild_context *rebuild_ctx, -+static void mdbox_header_update(struct mdbox_storage_rebuild_context *ctx, -+ struct index_rebuild_context *rebuild_ctx, - struct mdbox_mailbox *mbox) - { - struct mdbox_index_header hdr, backup_hdr; -@@ -502,6 +516,11 @@ static void mdbox_header_update(struct index_rebuild_context *rebuild_ctx, - /* update map's uid-validity */ - hdr.map_uid_validity = mdbox_map_get_uid_validity(mbox->storage->map); - -+ if (ctx->have_pop3_uidls) -+ hdr.flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS; -+ if (ctx->have_pop3_orders) -+ hdr.flags |= DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS; -+ - /* and write changes */ - mail_index_update_header_ext(rebuild_ctx->trans, mbox->hdr_ext_id, 0, - &hdr, sizeof(hdr)); -@@ -545,7 +564,7 @@ rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx, - } - - rebuild_ctx = index_index_rebuild_init(&mbox->box, view, trans); -- mdbox_header_update(rebuild_ctx, mbox); -+ mdbox_header_update(ctx, rebuild_ctx, mbox); - rebuild_mailbox_multi(ctx, rebuild_ctx, mbox, view, trans); - index_index_rebuild_deinit(&rebuild_ctx, dbox_get_uidvalidity_next); - -@@ -643,6 +662,7 @@ static int rebuild_restore_msg(struct mdbox_storage_rebuild_context *ctx, - mailbox = mailbox_list_get_vname(ctx->default_list, mailbox); - mailbox = t_strdup(mailbox); - } -+ rebuild_scan_metadata(ctx, file); - } - dbox_file_unref(&file); - if (ret <= 0 || deleted) { -diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage.c b/src/lib-storage/index/dbox-multi/mdbox-storage.c -index a6be1f4..bb81b66 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-storage.c -+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c -@@ -197,7 +197,7 @@ static void mdbox_mailbox_close(struct mailbox *box) - } - - int mdbox_read_header(struct mdbox_mailbox *mbox, -- struct mdbox_index_header *hdr) -+ struct mdbox_index_header *hdr, bool *need_resize_r) - { - const void *data; - size_t data_size; -@@ -216,6 +216,7 @@ int mdbox_read_header(struct mdbox_mailbox *mbox, - } - memset(hdr, 0, sizeof(*hdr)); - memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr))); -+ *need_resize_r = data_size < sizeof(*hdr); - return 0; - } - -@@ -224,8 +225,9 @@ void mdbox_update_header(struct mdbox_mailbox *mbox, - const struct mailbox_update *update) - { - struct mdbox_index_header hdr, new_hdr; -+ bool need_resize; - -- if (mdbox_read_header(mbox, &hdr) < 0) -+ if (mdbox_read_header(mbox, &hdr, &need_resize) < 0) - memset(&hdr, 0, sizeof(hdr)); - - new_hdr = hdr; -@@ -239,6 +241,10 @@ void mdbox_update_header(struct mdbox_mailbox *mbox, - - new_hdr.map_uid_validity = - mdbox_map_get_uid_validity(mbox->storage->map); -+ if (need_resize) { -+ mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id, -+ sizeof(new_hdr)); -+ } - if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) { - mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0, - &new_hdr, sizeof(new_hdr)); -@@ -365,14 +371,15 @@ static int - mdbox_mailbox_get_guid(struct mdbox_mailbox *mbox, guid_128_t guid_r) - { - struct mdbox_index_header hdr; -+ bool need_resize; - -- if (mdbox_read_header(mbox, &hdr) < 0) -+ if (mdbox_read_header(mbox, &hdr, &need_resize) < 0) - memset(&hdr, 0, sizeof(hdr)); - - if (guid_128_is_empty(hdr.mailbox_guid)) { - /* regenerate it */ - if (mdbox_write_index_header(&mbox->box, NULL, NULL) < 0 || -- mdbox_read_header(mbox, &hdr) < 0) -+ mdbox_read_header(mbox, &hdr, &need_resize) < 0) - return -1; - } - memcpy(guid_r, hdr.mailbox_guid, GUID_128_SIZE); -diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage.h b/src/lib-storage/index/dbox-multi/mdbox-storage.h -index 3afa0f9..4310500 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-storage.h -+++ b/src/lib-storage/index/dbox-multi/mdbox-storage.h -@@ -17,6 +17,8 @@ - struct mdbox_index_header { - uint32_t map_uid_validity; - guid_128_t mailbox_guid; -+ uint8_t flags; /* enum dbox_index_header_flags */ -+ uint8_t unused[3]; - }; - - struct mdbox_storage { -@@ -69,7 +71,7 @@ int mdbox_mail_lookup(struct mdbox_mailbox *mbox, struct mail_index_view *view, - uint32_t seq, uint32_t *map_uid_r); - uint32_t dbox_get_uidvalidity_next(struct mailbox_list *list); - int mdbox_read_header(struct mdbox_mailbox *mbox, -- struct mdbox_index_header *hdr); -+ struct mdbox_index_header *hdr, bool *need_resize_r); - void mdbox_update_header(struct mdbox_mailbox *mbox, - struct mail_index_transaction *trans, - const struct mailbox_update *update) ATTR_NULL(3); -diff --git a/src/lib-storage/index/dbox-single/sdbox-mail.c b/src/lib-storage/index/dbox-single/sdbox-mail.c -index 2c6956f..1f0383a 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-mail.c -+++ b/src/lib-storage/index/dbox-single/sdbox-mail.c -@@ -65,6 +65,7 @@ static int - sdbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field, - const char **value_r) - { -+ struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)_mail->box; - struct dbox_mail *mail = (struct dbox_mail *)_mail; - struct stat st; - -@@ -82,9 +83,26 @@ sdbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field, - *value_r = p_strdup_printf(mail->imail.mail.data_pool, "%lu", - (unsigned long)st.st_nlink); - return 0; -+ case MAIL_FETCH_UIDL_BACKEND: -+ if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, -+ offsetof(struct sdbox_index_header, flags), -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS)) { -+ *value_r = ""; -+ return 0; -+ } -+ break; -+ case MAIL_FETCH_POP3_ORDER: -+ if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, -+ offsetof(struct sdbox_index_header, flags), -+ DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS)) { -+ *value_r = ""; -+ return 0; -+ } -+ break; - default: -- return dbox_mail_get_special(_mail, field, value_r); -+ break; - } -+ return dbox_mail_get_special(_mail, field, value_r); - } - - int sdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, -diff --git a/src/lib-storage/index/dbox-single/sdbox-save.c b/src/lib-storage/index/dbox-single/sdbox-save.c -index 6c2b36a..f8be4a1 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-save.c -+++ b/src/lib-storage/index/dbox-single/sdbox-save.c -@@ -289,6 +289,10 @@ int sdbox_transaction_save_commit_pre(struct mail_save_context *_ctx) - return -1; - } - -+ /* update dbox header flags */ -+ dbox_save_update_header_flags(&ctx->ctx, ctx->sync_ctx->sync_view, -+ ctx->mbox->hdr_ext_id, offsetof(struct sdbox_index_header, flags)); -+ - /* assign UIDs for new messages */ - hdr = mail_index_get_header(ctx->sync_ctx->sync_view); - mail_index_append_finish_uids(ctx->ctx.trans, hdr->next_uid, -diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.c b/src/lib-storage/index/dbox-single/sdbox-storage.c -index 6e14f74..708a973 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-storage.c -+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c -@@ -138,7 +138,8 @@ sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, - } - - int sdbox_read_header(struct sdbox_mailbox *mbox, -- struct sdbox_index_header *hdr, bool log_error) -+ struct sdbox_index_header *hdr, bool log_error, -+ bool *need_resize_r) - { - struct mail_index_view *view; - const void *data; -@@ -173,6 +174,7 @@ int sdbox_read_header(struct sdbox_mailbox *mbox, - } - } - mail_index_view_close(&view); -+ *need_resize_r = data_size < sizeof(*hdr); - return ret; - } - -@@ -181,8 +183,9 @@ static void sdbox_update_header(struct sdbox_mailbox *mbox, - const struct mailbox_update *update) - { - struct sdbox_index_header hdr, new_hdr; -+ bool need_resize; - -- if (sdbox_read_header(mbox, &hdr, TRUE) < 0) -+ if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) - memset(&hdr, 0, sizeof(hdr)); - - new_hdr = hdr; -@@ -194,6 +197,10 @@ static void sdbox_update_header(struct sdbox_mailbox *mbox, - guid_128_generate(new_hdr.mailbox_guid); - } - -+ if (need_resize) { -+ mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id, -+ sizeof(new_hdr)); -+ } - if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) { - mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0, - &new_hdr, sizeof(new_hdr)); -@@ -278,8 +285,10 @@ void sdbox_set_mailbox_corrupted(struct mailbox *box) - { - struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; - struct sdbox_index_header hdr; -+ bool need_resize; - -- if (sdbox_read_header(mbox, &hdr, TRUE) < 0 || hdr.rebuild_count == 0) -+ if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0 || -+ hdr.rebuild_count == 0) - mbox->corrupted_rebuild_count = 1; - else - mbox->corrupted_rebuild_count = hdr.rebuild_count; -@@ -314,6 +323,7 @@ static int sdbox_mailbox_open(struct mailbox *box) - { - struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box; - struct sdbox_index_header hdr; -+ bool need_resize; - - if (sdbox_mailbox_alloc_index(mbox) < 0) - return -1; -@@ -332,17 +342,17 @@ static int sdbox_mailbox_open(struct mailbox *box) - } - - /* get/generate mailbox guid */ -- if (sdbox_read_header(mbox, &hdr, FALSE) < 0) { -+ if (sdbox_read_header(mbox, &hdr, FALSE, &need_resize) < 0) { - /* looks like the mailbox is corrupted */ - (void)sdbox_sync(mbox, SDBOX_SYNC_FLAG_FORCE); -- if (sdbox_read_header(mbox, &hdr, TRUE) < 0) -+ if (sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) - memset(&hdr, 0, sizeof(hdr)); - } - - if (guid_128_is_empty(hdr.mailbox_guid)) { - /* regenerate it */ - if (sdbox_mailbox_create_indexes(box, NULL, NULL) < 0 || -- sdbox_read_header(mbox, &hdr, TRUE) < 0) -+ sdbox_read_header(mbox, &hdr, TRUE, &need_resize) < 0) - return -1; - } - memcpy(mbox->mailbox_guid, hdr.mailbox_guid, -diff --git a/src/lib-storage/index/dbox-single/sdbox-storage.h b/src/lib-storage/index/dbox-single/sdbox-storage.h -index 3078333..b16a238 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-storage.h -+++ b/src/lib-storage/index/dbox-single/sdbox-storage.h -@@ -13,6 +13,8 @@ struct sdbox_index_header { - /* increased every time a full mailbox rebuild is done */ - uint32_t rebuild_count; - guid_128_t mailbox_guid; -+ uint8_t flags; /* enum dbox_index_header_flags */ -+ uint8_t unused[3]; - }; - - struct sdbox_storage { -@@ -37,7 +39,8 @@ int sdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, - struct dbox_file **file_r); - - int sdbox_read_header(struct sdbox_mailbox *mbox, -- struct sdbox_index_header *hdr, bool log_error); -+ struct sdbox_index_header *hdr, bool log_error, -+ bool *need_resize_r); - void sdbox_set_mailbox_corrupted(struct mailbox *box); - - struct mail_save_context * -diff --git a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c -index e989982..11634b0 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c -+++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c -@@ -140,8 +140,9 @@ static void sdbox_sync_update_header(struct index_rebuild_context *ctx) - { - struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)ctx->box; - struct sdbox_index_header hdr; -+ bool need_resize; - -- if (sdbox_read_header(mbox, &hdr, FALSE) < 0) -+ if (sdbox_read_header(mbox, &hdr, FALSE, &need_resize) < 0) - memset(&hdr, 0, sizeof(hdr)); - if (guid_128_is_empty(hdr.mailbox_guid)) - guid_128_generate(hdr.mailbox_guid); -@@ -187,9 +188,10 @@ int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox, bool force) - struct mail_index_view *view; - struct mail_index_transaction *trans; - struct sdbox_index_header hdr; -+ bool need_resize; - int ret; - -- if (!force && sdbox_read_header(mbox, &hdr, FALSE) == 0) { -+ if (!force && sdbox_read_header(mbox, &hdr, FALSE, &need_resize) == 0) { - if (hdr.rebuild_count != mbox->corrupted_rebuild_count && - hdr.rebuild_count != 0) { - /* already rebuilt by someone else */ -diff --git a/src/lib-storage/index/dbox-single/sdbox-sync.c b/src/lib-storage/index/dbox-single/sdbox-sync.c -index b99299c..b39090a 100644 ---- a/src/lib-storage/index/dbox-single/sdbox-sync.c -+++ b/src/lib-storage/index/dbox-single/sdbox-sync.c -@@ -164,10 +164,11 @@ sdbox_refresh_header(struct sdbox_mailbox *mbox, bool retry, bool log_error) - { - struct mail_index_view *view; - struct sdbox_index_header hdr; -+ bool need_resize; - int ret; - - view = mail_index_view_open(mbox->box.index); -- ret = sdbox_read_header(mbox, &hdr, log_error); -+ ret = sdbox_read_header(mbox, &hdr, log_error, &need_resize); - mail_index_view_close(&view); - - if (ret < 0 && retry) { --- -1.7.10.2 - - -From a935cfb9ab515bad875f1e5f709c4fc766a4546c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 01:03:58 +0300 -Subject: [PATCH] lib-fs: Added fs_get_root_driver() - - -diff --git a/src/lib-fs/fs-api.c b/src/lib-fs/fs-api.c -index 45fa37d..9b1d633 100644 ---- a/src/lib-fs/fs-api.c -+++ b/src/lib-fs/fs-api.c -@@ -140,6 +140,13 @@ void fs_deinit(struct fs **_fs) - str_free(&last_error); - } - -+const char *fs_get_root_driver(struct fs *fs) -+{ -+ while (fs->parent != NULL) -+ fs = fs->parent; -+ return fs->name; -+} -+ - struct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags) - { - struct fs_file *file; -diff --git a/src/lib-fs/fs-api.h b/src/lib-fs/fs-api.h -index 54c852c..d2d9a1d 100644 ---- a/src/lib-fs/fs-api.h -+++ b/src/lib-fs/fs-api.h -@@ -92,6 +92,9 @@ int fs_init(const char *driver, const char *args, - struct fs **fs_r, const char **error_r); - void fs_deinit(struct fs **fs); - -+/* Returns the root fs's driver name (bypassing all wrapper fses) */ -+const char *fs_get_root_driver(struct fs *fs); -+ - struct fs_file *fs_file_init(struct fs *fs, const char *path, int mode_flags); - void fs_file_deinit(struct fs_file **file); - --- -1.7.10.2 - - -From 8777469d6d3c6446b192ad5dcfb8c1a3bfde9711 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 16:30:19 +0300 -Subject: [PATCH] auth: If blocking userdb returns no fields, don't crash when - trying to cache the result. - - -diff --git a/src/auth/userdb-blocking.c b/src/auth/userdb-blocking.c -index f76fc43..fdd24f7 100644 ---- a/src/auth/userdb-blocking.c -+++ b/src/auth/userdb-blocking.c -@@ -36,8 +36,8 @@ static bool user_callback(const char *reply, void *context) - args = ""; - } - -+ request->userdb_reply = auth_fields_init(request->pool); - if (*args != '\0') { -- request->userdb_reply = auth_fields_init(request->pool); - auth_fields_import(request->userdb_reply, args, 0); - if (auth_fields_exists(request->userdb_reply, "tempfail")) - request->userdb_lookup_failed = TRUE; --- -1.7.10.2 - - -From 27e5e1bf843d1f928a51cad542f6e42edf413148 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 16:30:38 +0300 -Subject: [PATCH] auth: Fixed caching empty userdb result. - - -diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c -index 593eec9..53153af 100644 ---- a/src/auth/auth-request.c -+++ b/src/auth/auth-request.c -@@ -32,6 +32,7 @@ - #define AUTH_DNS_DEFAULT_TIMEOUT_MSECS (1000*10) - #define AUTH_DNS_WARN_MSECS 500 - #define CACHED_PASSWORD_SCHEME "SHA1" -+#define AUTH_REQUEST_KEY_IGNORE " " - - struct auth_request_proxy_dns_lookup_ctx { - struct auth_request *request; -@@ -923,6 +924,11 @@ static void auth_request_userdb_save_cache(struct auth_request *request, - auth_fields_append(request->userdb_reply, str, - AUTH_FIELD_FLAG_CHANGED, - AUTH_FIELD_FLAG_CHANGED); -+ if (str_len(str) == 0) { -+ /* no userdb fields. but we can't save an empty string, -+ since that means "user unknown". */ -+ str_append(str, AUTH_REQUEST_KEY_IGNORE); -+ } - cache_value = str_c(str); - } - /* last_success has no meaning with userdb */ -@@ -1503,6 +1509,8 @@ void auth_request_set_userdb_field(struct auth_request *request, - warned = TRUE; - } - name = "system_groups_user"; -+ } else if (strcmp(name, AUTH_REQUEST_KEY_IGNORE) == 0) { -+ return; - } - - auth_fields_add(request->userdb_reply, name, value, 0); --- -1.7.10.2 - - -From 2ecae26a666bc9e4013ac938b434d6f1d48be451 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 17:10:03 +0300 -Subject: [PATCH] doveadm-server: Pass local/remote_ip/port to passdb lookups - so proxy_maybe works. - - -diff --git a/src/doveadm/client-connection.c b/src/doveadm/client-connection.c -index 0afca75..08c3a87 100644 ---- a/src/doveadm/client-connection.c -+++ b/src/doveadm/client-connection.c -@@ -166,6 +166,10 @@ static bool client_handle_command(struct client_connection *conn, char **args) - - memset(&input, 0, sizeof(input)); - input.service = "doveadm"; -+ input.local_ip = conn->local_ip; -+ input.remote_ip = conn->remote_ip; -+ input.local_port = conn->local_port; -+ input.remote_port = conn->remote_port; - - for (argc = 0; args[argc] != NULL; argc++) - args[argc] = str_tabunescape(args[argc]); -@@ -390,7 +394,6 @@ struct client_connection * - client_connection_create(int fd, int listen_fd, bool ssl) - { - struct client_connection *conn; -- unsigned int port; - pool_t pool; - - pool = pool_alloconly_create("doveadm client", 1024*16); -@@ -402,8 +405,8 @@ client_connection_create(int fd, int listen_fd, bool ssl) - conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); - o_stream_set_no_error_handling(conn->output, TRUE); - -- (void)net_getsockname(fd, &conn->local_ip, &port); -- (void)net_getpeername(fd, &conn->remote_ip, &port); -+ (void)net_getsockname(fd, &conn->local_ip, &conn->local_port); -+ (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port); - - if (client_connection_read_settings(conn) < 0) { - client_connection_destroy(&conn); -diff --git a/src/doveadm/client-connection.h b/src/doveadm/client-connection.h -index 020cf86..9cf3c3f 100644 ---- a/src/doveadm/client-connection.h -+++ b/src/doveadm/client-connection.h -@@ -12,6 +12,7 @@ struct client_connection { - struct ostream *output; - struct ssl_iostream *ssl_iostream; - struct ip_addr local_ip, remote_ip; -+ unsigned int local_port, remote_port; - const struct doveadm_settings *set; - - unsigned int handshaked:1; -diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c -index da0fe49..4460cac 100644 ---- a/src/doveadm/doveadm-mail-server.c -+++ b/src/doveadm/doveadm-mail-server.c -@@ -190,6 +190,10 @@ doveadm_mail_server_user_get_host(struct doveadm_mail_cmd_context *ctx, - - memset(&info, 0, sizeof(info)); - info.service = master_service_get_name(master_service); -+ info.local_ip = input->local_ip; -+ info.remote_ip = input->remote_ip; -+ info.local_port = input->local_port; -+ info.remote_port = input->remote_port; - - pool = pool_alloconly_create("auth lookup", 1024); - auth_conn = mail_storage_service_get_auth_conn(ctx->storage_service); --- -1.7.10.2 - - -From d376b3ff4bad22dd772b26b4cc240525d1f98102 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 17:30:42 +0300 -Subject: [PATCH] auth: Keep auth_request referenced during DNS lookup. If the - underlying auth connection gets closed, there's nothing - else referencing the auth_request. - - -diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c -index 53153af..0c00c9a 100644 ---- a/src/auth/auth-request.c -+++ b/src/auth/auth-request.c -@@ -1656,6 +1656,7 @@ auth_request_proxy_dns_callback(const struct dns_lookup_result *result, - } - if (ctx->callback != NULL) - ctx->callback(result->ret == 0, request); -+ auth_request_unref(&request); - } - - static int auth_request_proxy_host_lookup(struct auth_request *request, -@@ -1683,12 +1684,14 @@ static int auth_request_proxy_host_lookup(struct auth_request *request, - - ctx = p_new(request->pool, struct auth_request_proxy_dns_lookup_ctx, 1); - ctx->request = request; -+ auth_request_ref(request); - - if (dns_lookup(host, &dns_set, auth_request_proxy_dns_callback, ctx, - &ctx->dns_lookup) < 0) { - /* failed early */ - request->internal_failure = TRUE; - auth_request_proxy_finish_failure(request); -+ auth_request_unref(&request); - return -1; - } - ctx->callback = callback; --- -1.7.10.2 - - -From ebb91c7f3d907b98730356f50169aa8c89db3b4d Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Tue, 28 May 2013 18:18:45 +0300 -Subject: [PATCH] auth ldap: If ldap debug_level>0, log how long - initialization took. - - -diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c -index c61af85..77706f1 100644 ---- a/src/auth/db-ldap.c -+++ b/src/auth/db-ldap.c -@@ -10,6 +10,7 @@ - #include "hash.h" - #include "aqueue.h" - #include "str.h" -+#include "time-util.h" - #include "env-util.h" - #include "var-expand.h" - #include "settings.h" -@@ -1099,11 +1100,17 @@ static void db_ldap_set_options(struct ldap_connection *conn) - - int db_ldap_connect(struct ldap_connection *conn) - { -+ bool debug = atoi(conn->set.debug_level) > 0; -+ struct timeval start, end; - int ret; - - if (conn->conn_state != LDAP_CONN_STATE_DISCONNECTED) - return 0; - -+ if (debug) { -+ if (gettimeofday(&start, NULL) < 0) -+ memset(&start, 0, sizeof(start)); -+ } - i_assert(conn->pending_count == 0); - if (conn->ld == NULL) { - if (conn->set.uris != NULL) { -@@ -1170,6 +1177,12 @@ int db_ldap_connect(struct ldap_connection *conn) - if (db_ldap_bind(conn) < 0) - return -1; - } -+ if (debug) { -+ if (gettimeofday(&end, NULL) == 0) { -+ int msecs = timeval_diff_msecs(&end, &start); -+ i_debug("LDAP initialization took %d msecs", msecs); -+ } -+ } - - db_ldap_get_fd(conn); - conn->io = io_add(conn->fd, IO_READ, ldap_input, conn); --- -1.7.10.2 - - -From 30dd5a7cc9c7c991c29eeea52455de307b1eb3f6 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 03:18:04 +0300 -Subject: [PATCH] Fixed compiling with gcc v3.3 and older. Perhaps the check - needs to be also for somewhat newer versions?.. - - -diff --git a/src/lib/macros.h b/src/lib/macros.h -index c5e4fed..921055e 100644 ---- a/src/lib/macros.h -+++ b/src/lib/macros.h -@@ -142,7 +142,7 @@ - #endif - - /* Macros to provide type safety for callback functions' context parameters */ --#ifdef __GNUC__ -+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) - # define CALLBACK_TYPECHECK(callback, type) \ - (COMPILE_ERROR_IF_TRUE(!__builtin_types_compatible_p( \ - typeof(&callback), type)) ? 1 : 0) --- -1.7.10.2 - - -From e27ba5f2b2252e1ec35b330e1c52c663447ef219 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 03:23:40 +0300 -Subject: [PATCH] lib-storage: Don't try to mkdir() empty directory with - INDEX=MEMORY - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index 49a4c46..fd7b18d 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -1454,6 +1454,8 @@ int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list) - &index_dir); - if (ret <= 0) - return ret; -+ if (index_dir[0] == '\0') -+ return 0; - ret = mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX, - &root_dir); - if (ret <= 0) --- -1.7.10.2 - - -From 0c3b2aa76d3eb8b46982a3be79ee6017bb932a31 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 03:26:41 +0300 -Subject: [PATCH] lib-storage: Reverted previous change after all. - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index fd7b18d..49a4c46 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -1454,8 +1454,6 @@ int mailbox_list_mkdir_missing_index_root(struct mailbox_list *list) - &index_dir); - if (ret <= 0) - return ret; -- if (index_dir[0] == '\0') -- return 0; - ret = mailbox_list_get_root_path(list, MAILBOX_LIST_PATH_TYPE_MAILBOX, - &root_dir); - if (ret <= 0) --- -1.7.10.2 - - -From 71c056c5d04a6eba8c6437b101b6f8d3ec4ebfb6 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 03:27:09 +0300 -Subject: [PATCH] lib-storage: If INDEX=MEMORY, return index root dir as - nonexistent instead of as "". - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index 49a4c46..5eedf04 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -1271,8 +1271,15 @@ bool mailbox_list_set_get_root_path(const struct mailbox_list_settings *set, - set->control_dir : set->root_dir; - break; - case MAILBOX_LIST_PATH_TYPE_INDEX: -- path = set->index_dir != NULL ? -- set->index_dir : set->root_dir; -+ if (set->index_dir != NULL) { -+ if (set->index_dir[0] == '\0') { -+ /* in-memory indexes */ -+ return 0; -+ } -+ path = set->index_dir; -+ } else { -+ path = set->root_dir; -+ } - break; - case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE: - path = set->index_pvt_dir; --- -1.7.10.2 - - -From a661e145eb2f5a269cb487397c0025779b19f1a0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 03:47:38 +0300 -Subject: [PATCH] lib-index: Fixed mail_cache_lookup_headers() when fields - were still in memory buffer. - - -diff --git a/src/lib-index/mail-cache-lookup.c b/src/lib-index/mail-cache-lookup.c -index 39f3eb0..02c3e3d 100644 ---- a/src/lib-index/mail-cache-lookup.c -+++ b/src/lib-index/mail-cache-lookup.c -@@ -434,17 +434,18 @@ int mail_cache_lookup_field(struct mail_cache_view *view, buffer_t *dest_buf, - } - - struct header_lookup_data { -- uint32_t offset; - uint32_t data_size; -+ const unsigned char *data; - }; - - struct header_lookup_line { - uint32_t line_num; -- struct header_lookup_data *data; -+ struct header_lookup_data *data; - }; - - struct header_lookup_context { - struct mail_cache_view *view; -+ pool_t pool; - ARRAY(struct header_lookup_line) lines; - }; - -@@ -461,7 +462,8 @@ static void header_lines_save(struct header_lookup_context *ctx, - uint32_t data_size = field->size; - struct header_lookup_line hdr_line; - struct header_lookup_data *hdr_data; -- unsigned int i, lines_count; -+ void *data_dup; -+ unsigned int i, lines_count, pos; - - /* data = { line_nums[], 0, "headers" } */ - for (i = 0; data_size >= sizeof(uint32_t); i++) { -@@ -470,10 +472,13 @@ static void header_lines_save(struct header_lookup_context *ctx, - break; - } - lines_count = i; -+ pos = (lines_count+1) * sizeof(uint32_t); - -- hdr_data = t_new(struct header_lookup_data, 1); -- hdr_data->offset = field->offset + (lines_count+1) * sizeof(uint32_t); -+ hdr_data = p_new(ctx->pool, struct header_lookup_data, 1); - hdr_data->data_size = data_size; -+ hdr_data->data = data_dup = data_size == 0 ? NULL : -+ p_malloc(ctx->pool, data_size); -+ memcpy(data_dup, CONST_PTR_OFFSET(field->data, pos), data_size); - - for (i = 0; i < lines_count; i++) { - hdr_line.line_num = lines[i]; -@@ -491,14 +496,13 @@ static int header_lookup_line_cmp(const struct header_lookup_line *l1, - static int - mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest, - uint32_t seq, unsigned int field_idxs[], -- unsigned int fields_count) -+ unsigned int fields_count, pool_t *pool_r) - { - struct mail_cache *cache = view->cache; - struct mail_cache_lookup_iterate_ctx iter; - struct mail_cache_iterate_field field; - struct header_lookup_context ctx; - struct header_lookup_line *lines; -- const void *data; - const unsigned char *p, *start, *end; - uint8_t *field_state; - unsigned int i, count, max_field = 0; -@@ -507,6 +511,8 @@ mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest, - buffer_t *buf; - int ret; - -+ *pool_r = NULL; -+ - if (fields_count == 0) - return 1; - -@@ -534,6 +540,7 @@ mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest, - /* lookup the fields */ - memset(&ctx, 0, sizeof(ctx)); - ctx.view = view; -+ ctx.pool = *pool_r = pool_alloconly_create("mail cache headers", 1024); - t_array_init(&ctx.lines, 32); - - mail_cache_lookup_iter_init(view, seq, &iter); -@@ -563,17 +570,7 @@ mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest, - - /* then start filling dest buffer from the headers */ - for (i = 0; i < count; i++) { -- ret = mail_cache_map(cache, lines[i].data->offset, -- lines[i].data->data_size, &data); -- if (ret <= 0) { -- if (ret < 0) -- return -1; -- -- mail_cache_set_corrupted(cache, -- "header record unexpectedly points outside file"); -- return -1; -- } -- start = data; -+ start = lines[i].data->data; - end = start + lines[i].data->data_size; - - /* find the end of the (multiline) header */ -@@ -589,7 +586,7 @@ mail_cache_lookup_headers_real(struct mail_cache_view *view, string_t *dest, - - /* if there are more lines for this header, the following lines - continue after this one. so skip this line. */ -- lines[i].data->offset += hdr_size; -+ lines[i].data->data += hdr_size; - lines[i].data->data_size -= hdr_size; - } - return 1; -@@ -599,11 +596,15 @@ int mail_cache_lookup_headers(struct mail_cache_view *view, string_t *dest, - uint32_t seq, unsigned int field_idxs[], - unsigned int fields_count) - { -+ pool_t pool; - int ret; - - T_BEGIN { - ret = mail_cache_lookup_headers_real(view, dest, seq, -- field_idxs, fields_count); -+ field_idxs, fields_count, -+ &pool); -+ if (pool != NULL) -+ pool_unref(&pool); - } T_END; - return ret; - } --- -1.7.10.2 - - -From 105cc5415b3c517af47846cf8849cddf58de84d1 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 12:33:17 +0300 -Subject: [PATCH] dsync: Fixed dsync handshaking since recent change. - - -diff --git a/src/doveadm/dsync/dsync-ibc-stream.c b/src/doveadm/dsync/dsync-ibc-stream.c -index ef9a1af..31d2c6a 100644 ---- a/src/doveadm/dsync/dsync-ibc-stream.c -+++ b/src/doveadm/dsync/dsync-ibc-stream.c -@@ -73,7 +73,7 @@ static const struct { - .chr = 'H', - .required_keys = "hostname", - .optional_keys = "sync_ns_prefix sync_box sync_box_guid sync_type " -- "debug sync_visible_namespaces exclude_mailboxes" -+ "debug sync_visible_namespaces exclude_mailboxes " - "send_mail_requests backup_send backup_recv lock_timeout" - }, - { .name = "mailbox_state", --- -1.7.10.2 - - -From 49fbfb8325c40cd30d422e490bec308aa0986ec4 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 12:44:15 +0300 -Subject: [PATCH] lib-settings: Support also "seconds" and "minutes" (instead - of just secs/mins) - - -diff --git a/src/lib-settings/settings-parser.c b/src/lib-settings/settings-parser.c -index 3a0d2c3..74cdc05 100644 ---- a/src/lib-settings/settings-parser.c -+++ b/src/lib-settings/settings-parser.c -@@ -362,12 +362,14 @@ int settings_get_time(const char *str, unsigned int *secs_r, - switch (i_toupper(*p)) { - case 'S': - multiply = 1; -- if (strncasecmp(p, "secs", strlen(p)) == 0) -+ if (strncasecmp(p, "secs", strlen(p)) == 0 || -+ strncasecmp(p, "seconds", strlen(p)) == 0) - p = ""; - break; - case 'M': - multiply = 60; -- if (strncasecmp(p, "mins", strlen(p)) == 0) -+ if (strncasecmp(p, "mins", strlen(p)) == 0 || -+ strncasecmp(p, "minutes", strlen(p)) == 0) - p = ""; - break; - case 'H': --- -1.7.10.2 - - -From 5efe0f11679e0af5f910b268f1f5000bb8f9f7c0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 29 May 2013 16:40:50 +0300 -Subject: [PATCH] lib-imap: imap_append_string_for_humans() returned broken - output for whitespace-only input. This returned broken IMAP - ENVELOPEs, especially for subjects that contained only - whitespace. Since the broken output returned a huge - literal, it basically caused the IMAP client to hang. - - -diff --git a/src/lib-imap/Makefile.am b/src/lib-imap/Makefile.am -index 4382270..3d9f1a2 100644 ---- a/src/lib-imap/Makefile.am -+++ b/src/lib-imap/Makefile.am -@@ -44,6 +44,7 @@ test_programs = \ - test-imap-bodystructure \ - test-imap-match \ - test-imap-parser \ -+ test-imap-quote \ - test-imap-url \ - test-imap-utf7 \ - test-imap-util -@@ -68,6 +69,10 @@ test_imap_parser_SOURCES = test-imap-parser.c - test_imap_parser_LDADD = imap-parser.lo imap-arg.lo $(test_libs) - test_imap_parser_DEPENDENCIES = $(test_deps) - -+test_imap_quote_SOURCES = test-imap-quote.c -+test_imap_quote_LDADD = imap-quote.lo $(test_libs) -+test_imap_quote_DEPENDENCIES = $(test_deps) -+ - test_imap_url_SOURCES = test-imap-url.c - test_imap_url_LDADD = imap-url.lo $(test_libs) - test_imap_url_DEPENDENCIES = $(test_deps) -diff --git a/src/lib-imap/imap-quote.c b/src/lib-imap/imap-quote.c -index 7234df6..73dd5d4 100644 ---- a/src/lib-imap/imap-quote.c -+++ b/src/lib-imap/imap-quote.c -@@ -119,7 +119,7 @@ void imap_append_string_for_humans(string_t *dest, - const unsigned char *src, size_t size) - { - size_t i, pos, remove_count = 0; -- bool last_lwsp = TRUE, modify = FALSE; -+ bool whitespace_prefix = TRUE, last_lwsp = TRUE, modify = FALSE; - - /* first check if there is anything to change */ - for (i = 0; i < size; i++) { -@@ -155,8 +155,10 @@ void imap_append_string_for_humans(string_t *dest, - last_lwsp = FALSE; - break; - } -+ if (!last_lwsp) -+ whitespace_prefix = FALSE; - } -- if (last_lwsp && i > 0) { -+ if (last_lwsp && i > 0 && !whitespace_prefix) { - modify = TRUE; - remove_count++; - } -@@ -168,11 +170,16 @@ void imap_append_string_for_humans(string_t *dest, - str_append_c(dest, '"'); - return; - } -+ if (size == remove_count) { -+ /* contained only whitespace */ -+ str_append(dest, "\"\""); -+ return; -+ } - - str_printfa(dest, "{%"PRIuSIZE_T"}\r\n", size - remove_count); - pos = str_len(dest); - -- last_lwsp = TRUE; -+ last_lwsp = TRUE; whitespace_prefix = TRUE; - for (i = 0; i < size; i++) { - switch (src[i]) { - case 0: -@@ -193,8 +200,10 @@ void imap_append_string_for_humans(string_t *dest, - str_append_c(dest, src[i]); - break; - } -+ if (!last_lwsp) -+ whitespace_prefix = FALSE; - } -- if (last_lwsp) -+ if (last_lwsp && i > 0 && !whitespace_prefix) - str_truncate(dest, str_len(dest)-1); - i_assert(str_len(dest) - pos == size - remove_count); - } -diff --git a/src/lib-imap/test-imap-quote.c b/src/lib-imap/test-imap-quote.c -new file mode 100644 -index 0000000..3edb1dd ---- /dev/null -+++ b/src/lib-imap/test-imap-quote.c -@@ -0,0 +1,47 @@ -+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "str.h" -+#include "imap-quote.h" -+#include "test-common.h" -+ -+static void test_imap_append_string_for_humans(void) -+{ -+ static struct { -+ const char *input, *output; -+ } tests[] = { -+ { "", "\"\"" }, -+ { " ", "\"\"" }, -+ { " ", "\"\"" }, -+ { "\t", "\"\"" }, -+ { " \t", "\"\"" }, -+ { " \t ", "\"\"" }, -+ { " foo", "{3}\r\nfoo" }, -+ { "\tfoo", "{3}\r\nfoo" }, -+ { "\t \tfoo", "{3}\r\nfoo" }, -+ { " foo ", "{3}\r\nfoo" }, -+ { " foo ", "{3}\r\nfoo" }, -+ { " foo \t \t", "{3}\r\nfoo" } -+ }; -+ string_t *str = t_str_new(128); -+ unsigned int i; -+ -+ test_begin("imap_append_string_for_humans()"); -+ -+ for (i = 0; i < N_ELEMENTS(tests); i++) { -+ str_truncate(str, 0); -+ imap_append_string_for_humans(str, (const void *)tests[i].input, -+ strlen(tests[i].input)); -+ test_assert(strcmp(tests[i].output, str_c(str)) == 0); -+ } -+ test_end(); -+} -+ -+int main(void) -+{ -+ static void (*test_functions[])(void) = { -+ test_imap_append_string_for_humans, -+ NULL -+ }; -+ return test_run(test_functions); -+} --- -1.7.10.2 - - -From c04c98b2f0353eb054623b7529ec3b22bf324fd1 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 17:45:27 +0300 -Subject: [PATCH] var_expand(): Added %N, which is the same as %H except based - on MD5. This gives a better distribution of values than %H. - - -diff --git a/src/lib/var-expand.c b/src/lib/var-expand.c -index baec1e2..0e8ec6a 100644 ---- a/src/lib/var-expand.c -+++ b/src/lib/var-expand.c -@@ -88,6 +88,29 @@ static const char *m_str_hash(const char *str, struct var_expand_context *ctx) - } - - static const char * -+m_str_newhash(const char *str, struct var_expand_context *ctx) -+{ -+ string_t *hash = t_str_new(20); -+ unsigned char result[MD5_RESULTLEN]; -+ unsigned int value; -+ -+ md5_get_digest(str, strlen(str), result); -+ memcpy(&value, result, sizeof(value)); -+ -+ if (ctx->width != 0) { -+ value %= ctx->width; -+ ctx->width = 0; -+ } -+ -+ str_printfa(hash, "%x", value); -+ while ((int)str_len(hash) < ctx->offset) -+ str_insert(hash, 0, "0"); -+ ctx->offset = 0; -+ -+ return str_c(hash); -+} -+ -+static const char * - m_str_md5(const char *str, struct var_expand_context *ctx ATTR_UNUSED) - { - unsigned char digest[16]; -@@ -132,6 +155,7 @@ static const struct var_expand_modifier modifiers[] = { - { 'X', m_str_hex }, - { 'R', m_str_reverse }, - { 'H', m_str_hash }, -+ { 'N', m_str_newhash }, - { 'M', m_str_md5 }, - { 'D', m_str_ldap_dn }, - { 'T', m_str_trim }, --- -1.7.10.2 - - -From 112d8e9c40646e286ac3d005436b17acca48540c Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:03:38 +0300 -Subject: [PATCH] lib-imap-urlauth: Made sure callbacks from URLAUTH service - connection are executed only once. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-connection.c b/src/lib-imap-urlauth/imap-urlauth-connection.c -index 2f8df0b..80598f9 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-connection.c -+++ b/src/lib-imap-urlauth/imap-urlauth-connection.c -@@ -320,9 +320,13 @@ static void imap_urlauth_request_free(struct imap_urlauth_request *urlreq) - void imap_urlauth_request_abort(struct imap_urlauth_connection *conn, - struct imap_urlauth_request *urlreq) - { -- if (urlreq->callback != NULL) { -+ imap_urlauth_request_callback_t *callback; -+ -+ callback = urlreq->callback; -+ urlreq->callback = NULL; -+ if (callback != NULL) { - T_BEGIN { -- urlreq->callback(NULL, urlreq->context); -+ callback(NULL, urlreq->context); - } T_END; - } - -@@ -331,7 +335,6 @@ void imap_urlauth_request_abort(struct imap_urlauth_connection *conn, - conn->targets_head->requests_head == urlreq) { - /* cannot just drop pending request without breaking - protocol state */ -- urlreq->callback = NULL; - return; - } - imap_urlauth_request_free(urlreq); -@@ -343,22 +346,26 @@ imap_urlauth_request_fail(struct imap_urlauth_connection *conn, - const char *error) - { - struct imap_urlauth_fetch_reply reply; -+ imap_urlauth_request_callback_t *callback; - -- memset(&reply, 0, sizeof(reply)); -- reply.url = urlreq->url; -- reply.flags = urlreq->flags; -- reply.succeeded = FALSE; -- reply.error = error; -+ callback = urlreq->callback; -+ urlreq->callback = NULL; -+ if (callback != NULL) { -+ memset(&reply, 0, sizeof(reply)); -+ reply.url = urlreq->url; -+ reply.flags = urlreq->flags; -+ reply.succeeded = FALSE; -+ reply.error = error; - -- if (urlreq->callback != NULL) T_BEGIN { -- (void)urlreq->callback(&reply, urlreq->context); -- } T_END; -+ T_BEGIN { -+ (void)callback(&reply, urlreq->context); -+ } T_END; -+ } - - if (conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING && - conn->targets_head != NULL && - conn->targets_head->requests_head == urlreq) { - /* cannot just drop pending request without breaking protocol state */ -- urlreq->callback = NULL; - return; - } - -@@ -617,6 +624,7 @@ imap_urlauth_connection_read_literal(struct imap_urlauth_connection *conn) - { - struct imap_urlauth_request *urlreq = conn->targets_head->requests_head; - struct imap_urlauth_fetch_reply reply; -+ imap_urlauth_request_callback_t *callback; - int ret; - - i_assert(conn->reading_literal); -@@ -643,8 +651,10 @@ imap_urlauth_connection_read_literal(struct imap_urlauth_connection *conn) - reply.succeeded = TRUE; - - ret = 1; -- if (urlreq->callback != NULL) T_BEGIN { -- ret = urlreq->callback(&reply, urlreq->context); -+ callback = urlreq->callback; -+ urlreq->callback = NULL; -+ if (callback != NULL) T_BEGIN { -+ ret = callback(&reply, urlreq->context); - } T_END; - - if (reply.input != NULL) --- -1.7.10.2 - - -From cced625278063273ff1fab87844d5a4e038fd1ae Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:03:46 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed URLAUTH connection resume after - error. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-connection.c b/src/lib-imap-urlauth/imap-urlauth-connection.c -index 80598f9..42a4fc3 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-connection.c -+++ b/src/lib-imap-urlauth/imap-urlauth-connection.c -@@ -317,6 +317,21 @@ static void imap_urlauth_request_free(struct imap_urlauth_request *urlreq) - i_free(urlreq); - } - -+static void imap_urlauth_request_drop(struct imap_urlauth_connection *conn, -+ struct imap_urlauth_request *urlreq) -+{ -+ if ((conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING || -+ conn->state == IMAP_URLAUTH_STATE_REQUEST_WAIT) && -+ conn->targets_head != NULL && -+ conn->targets_head->requests_head == urlreq) { -+ /* cannot just drop pending request without breaking -+ protocol state */ -+ return; -+ } -+ imap_urlauth_request_free(urlreq); -+ -+} -+ - void imap_urlauth_request_abort(struct imap_urlauth_connection *conn, - struct imap_urlauth_request *urlreq) - { -@@ -330,14 +345,7 @@ void imap_urlauth_request_abort(struct imap_urlauth_connection *conn, - } T_END; - } - -- if (conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING && -- conn->targets_head != NULL && -- conn->targets_head->requests_head == urlreq) { -- /* cannot just drop pending request without breaking -- protocol state */ -- return; -- } -- imap_urlauth_request_free(urlreq); -+ imap_urlauth_request_drop(conn, urlreq); - } - - static void -@@ -347,6 +355,7 @@ imap_urlauth_request_fail(struct imap_urlauth_connection *conn, - { - struct imap_urlauth_fetch_reply reply; - imap_urlauth_request_callback_t *callback; -+ int ret = 1; - - callback = urlreq->callback; - urlreq->callback = NULL; -@@ -358,18 +367,19 @@ imap_urlauth_request_fail(struct imap_urlauth_connection *conn, - reply.error = error; - - T_BEGIN { -- (void)callback(&reply, urlreq->context); -+ ret = callback(&reply, urlreq->context); - } T_END; - } - -- if (conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING && -- conn->targets_head != NULL && -- conn->targets_head->requests_head == urlreq) { -- /* cannot just drop pending request without breaking protocol state */ -- return; -+ imap_urlauth_request_drop(conn, urlreq); -+ -+ if (ret < 0) { -+ /* Drop any related requests upon error */ -+ imap_urlauth_request_abort_by_context(conn, urlreq->context); - } - -- imap_urlauth_request_free(urlreq); -+ if (ret != 0) -+ imap_urlauth_connection_continue(conn); - } - - static void -@@ -714,6 +724,7 @@ static int imap_urlauth_input_pending(struct imap_urlauth_connection *conn) - param[6] != '\0') { - error = param+6; - } -+ conn->state = IMAP_URLAUTH_STATE_REQUEST_WAIT; - imap_urlauth_request_fail(conn, - conn->targets_head->requests_head, error); - return 1; --- -1.7.10.2 - - -From 10d17ff202bc77c09c1c2eb52bb331bcff726a24 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:03:53 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed URLAUTH fetch reference counting for - when requests are aborted at deinit. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 0ba4dfa..6174ff0 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -121,11 +121,14 @@ static void imap_urlauth_fetch_unref(struct imap_urlauth_fetch **_ufetch) - i_assert(ufetch->refcount > 0); - - *_ufetch = NULL; -- if (--ufetch->refcount > 0) -+ if (ufetch->refcount-1 > 0) - return; - - imap_urlauth_fetch_abort(ufetch); - -+ ufetch->refcount--; -+ i_assert(ufetch->refcount == 0); -+ - /* dont leave the connection in limbo; make sure resume is called */ - if (ufetch->waiting_service) - imap_urlauth_connection_continue(ufetch->uctx->conn); --- -1.7.10.2 - - -From 29150fb06a67df940253fd08e6c7f468c40e57e4 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:04:10 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed pending_request counter difference - between locally and remotely fetched URLAUTHs. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 6174ff0..674447a 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -121,15 +121,15 @@ static void imap_urlauth_fetch_unref(struct imap_urlauth_fetch **_ufetch) - i_assert(ufetch->refcount > 0); - - *_ufetch = NULL; -- if (ufetch->refcount-1 > 0) -+ if (--ufetch->refcount > 0) - return; - -+ ufetch->refcount++; - imap_urlauth_fetch_abort(ufetch); -- - ufetch->refcount--; - i_assert(ufetch->refcount == 0); - -- /* dont leave the connection in limbo; make sure resume is called */ -+ /* dont leave the connection in limbo; make sure continue is called */ - if (ufetch->waiting_service) - imap_urlauth_connection_continue(ufetch->uctx->conn); - i_free(ufetch); -@@ -161,10 +161,12 @@ imap_urlauth_fetch_error(struct imap_urlauth_fetch *ufetch, const char *url, - ufetch->context); - } T_END; - -- if (ret == 0) -+ if (ret == 0) { - ufetch->waiting_local = TRUE; -- else if (ret < 0) -+ ufetch->pending_requests++; -+ } else if (ret < 0) { - imap_urlauth_fetch_fail(ufetch); -+ } - } - - static void -@@ -251,10 +253,11 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - } - } - -+ ufetch->pending_requests--; -+ - if (!success && ret < 0) { - if (mpurl != NULL) - imap_msgpart_url_free(&mpurl); -- ufetch->pending_requests--; - (void)ufetch->callback(NULL, TRUE, ufetch->context); - imap_urlauth_fetch_fail(ufetch); - return; -@@ -271,13 +274,13 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url, - reply.size = mpresult.size; - reply.input = mpresult.input; - -- ret = ufetch->callback(&reply, ufetch->pending_requests == 1, -+ ret = ufetch->callback(&reply, ufetch->pending_requests == 0, - ufetch->context); - if (ret == 0) { - ufetch->local_url = mpurl; - ufetch->waiting_local = TRUE; -+ ufetch->pending_requests++; - } else { -- ufetch->pending_requests--; - - if (mpurl != NULL) - imap_msgpart_url_free(&mpurl); -@@ -328,6 +331,7 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - ufetch->failed = TRUE; - } else if (ret == 0) { - ufetch->waiting_service = TRUE; -+ ufetch->pending_requests++; - } - - imap_urlauth_fetch_unref(&ufetch); -@@ -416,8 +420,13 @@ static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch) - if (ufetch->failed) - return FALSE; - -- if (!ufetch->waiting_local && !ufetch->waiting_service) -+ if (!ufetch->waiting_local && !ufetch->waiting_service) { -+ /* not currently waiting for anything */ - return ufetch->pending_requests > 0; -+ } -+ -+ /* we finished a request */ -+ ufetch->pending_requests--; - - if (!ufetch->waiting_local) { - /* not waiting for local request handling */ -@@ -428,7 +437,6 @@ static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch) - - /* finished local request */ - if (ufetch->local_url != NULL) { -- ufetch->pending_requests--; - imap_msgpart_url_free(&ufetch->local_url); - } - ufetch->waiting_local = FALSE; -@@ -468,6 +476,7 @@ static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch) - - if (ret == 0) { - ufetch->waiting_service = TRUE; -+ ufetch->pending_requests++; - return TRUE; - } - } --- -1.7.10.2 - - -From acda9675cf40208c6fc2425e6bbc40b1791a6d47 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:04:17 +0300 -Subject: [PATCH] lib-imap-urlauth: Fixed handling of URLAUTH service - connection resume after pending local request. This was - erroneously removed in an earlier commit. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 674447a..2393811 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -311,6 +311,7 @@ imap_urlauth_fetch_request_callback(struct imap_urlauth_fetch_reply *reply, - ufetch->pending_reply.size = reply->size; - ufetch->pending_reply.succeeded = reply->succeeded; - ufetch->pending_reply.binary_has_nuls = reply->binary_has_nuls; -+ ufetch->waiting_service = TRUE; - return 0; - } - -@@ -479,6 +480,9 @@ static bool imap_urlauth_fetch_do_continue(struct imap_urlauth_fetch *ufetch) - ufetch->pending_requests++; - return TRUE; - } -+ -+ ufetch->waiting_service = FALSE; -+ imap_urlauth_connection_continue(ufetch->uctx->conn); - } - - /* handle pending local urls */ --- -1.7.10.2 - - -From 71b14a4768fb9cdee53531487d28f5800d295741 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:04:52 +0300 -Subject: [PATCH] imap: Fixed segfault in URLFETCH command. Command would be - cleaned up while requests were still pending, causing a - segfault once a request finished. Added API determining - whether the URLAUTH fetch interface still has pending - requests. - - -diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c -index c3fac61..0fdfb7b 100644 ---- a/src/imap/cmd-urlfetch.c -+++ b/src/imap/cmd-urlfetch.c -@@ -357,7 +357,6 @@ bool cmd_urlfetch(struct client_command_context *cmd) - const struct cmd_urlfetch_url *url; - const struct imap_arg *args; - struct cmd_urlfetch_url *ufurl; -- int ret; - - if (client->urlauth_ctx == NULL) { - client_send_command_error(cmd, "URLAUTH disabled."); -@@ -387,17 +386,16 @@ bool cmd_urlfetch(struct client_command_context *cmd) - ctx->ufetch = imap_urlauth_fetch_init(client->urlauth_ctx, - cmd_urlfetch_url_callback, cmd); - -- ret = 1; - array_foreach(&urls, url) { -- ret = imap_urlauth_fetch_url(ctx->ufetch, url->url, url->flags); -- if (ret < 0) { -+ if (imap_urlauth_fetch_url(ctx->ufetch, url->url, url->flags) < 0) { - /* fatal error */ - ctx->failed = TRUE; - break; - } - } - -- if (ret != 0 && cmd->client->output_cmd_lock != cmd) { -+ if ((ctx->failed || !imap_urlauth_fetch_is_pending(ctx->ufetch)) -+ && cmd->client->output_cmd_lock != cmd) { - /* finished */ - cmd_urlfetch_finish(cmd); - return TRUE; -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index 2393811..b0836bd 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -516,3 +516,7 @@ bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch) - return pending; - } - -+bool imap_urlauth_fetch_is_pending(struct imap_urlauth_fetch *ufetch) -+{ -+ return ufetch->pending_requests > 0; -+} -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.h b/src/lib-imap-urlauth/imap-urlauth-fetch.h -index 55398af..8d39381 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.h -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h -@@ -45,6 +45,8 @@ void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **ufetch); - - int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - enum imap_urlauth_fetch_flags url_flags); -+ - bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch); -+bool imap_urlauth_fetch_is_pending(struct imap_urlauth_fetch *ufetch); - - #endif --- -1.7.10.2 - - -From 0f01b2b099e4007a572a4f762d4a7407f7d436a0 Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Thu, 30 May 2013 18:04:58 +0300 -Subject: [PATCH] lib-imap-urlauth: Added API for using the fetch interface - with an already parsed IMAP URL object. - - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c -index b0836bd..0af33f6 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.c -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c -@@ -348,7 +348,6 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - struct mail_user *mail_user = uctx->user; - struct imap_url *imap_url; - const char *error, *errormsg; -- int ret = 0; - - /* parse the url */ - if (imap_url_parse(url, NULL, url_parse_flags, &imap_url, &error) < 0) { -@@ -363,6 +362,18 @@ int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - return 1; - } - -+ return imap_urlauth_fetch_url_parsed(ufetch, url, imap_url, url_flags); -+} -+ -+int imap_urlauth_fetch_url_parsed(struct imap_urlauth_fetch *ufetch, -+ const char *url, struct imap_url *imap_url, -+ enum imap_urlauth_fetch_flags url_flags) -+{ -+ struct imap_urlauth_context *uctx = ufetch->uctx; -+ struct mail_user *mail_user = uctx->user; -+ const char *error, *errormsg; -+ int ret = 0; -+ - ufetch->failed = FALSE; - ufetch->pending_requests++; - -diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.h b/src/lib-imap-urlauth/imap-urlauth-fetch.h -index 8d39381..116a477 100644 ---- a/src/lib-imap-urlauth/imap-urlauth-fetch.h -+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.h -@@ -1,6 +1,7 @@ - #ifndef IMAP_URLAUTH_FETCH_H - #define IMAP_URLAUTH_FETCH_H - -+struct imap_url; - struct imap_urlauth_context; - struct imap_urlauth_fetch; - -@@ -45,6 +46,9 @@ void imap_urlauth_fetch_deinit(struct imap_urlauth_fetch **ufetch); - - int imap_urlauth_fetch_url(struct imap_urlauth_fetch *ufetch, const char *url, - enum imap_urlauth_fetch_flags url_flags); -+int imap_urlauth_fetch_url_parsed(struct imap_urlauth_fetch *ufetch, -+ const char *url, struct imap_url *imap_url, -+ enum imap_urlauth_fetch_flags url_flags); - - bool imap_urlauth_fetch_continue(struct imap_urlauth_fetch *ufetch); - bool imap_urlauth_fetch_is_pending(struct imap_urlauth_fetch *ufetch); --- -1.7.10.2 - - -From ebdbf44ab6898eb0a685f0d0aa82d5af0ce823ec Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 19:03:05 +0300 -Subject: [PATCH] lib-index: Fixed a broken assert. - - -diff --git a/src/lib-index/mail-index-transaction-export.c b/src/lib-index/mail-index-transaction-export.c -index f890752..44fe5e3 100644 ---- a/src/lib-index/mail-index-transaction-export.c -+++ b/src/lib-index/mail-index-transaction-export.c -@@ -113,7 +113,7 @@ static void log_append_ext_intro(struct mail_index_export_context *ctx, - /* we're resizing the extension. use the resize struct. */ - intro = &resizes[ext_id]; - -- i_assert(intro->ext_id == idx); -+ i_assert(intro->ext_id == idx || idx == (uint32_t)-1); - intro->name_size = idx != (uint32_t)-1 ? 0 : - strlen(rext->name); - buffer_append(buf, intro, sizeof(*intro)); --- -1.7.10.2 - - -From 3706e34ef1ceee7c07a4e53c084d7bec39706f62 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 21:45:13 +0300 -Subject: [PATCH] layout=index: Allow mailbox create/delete/rename during - mailbox list iteration. - - -diff --git a/src/lib-storage/list/mailbox-list-index-iter.c b/src/lib-storage/list/mailbox-list-index-iter.c -index 659f7ff..2f69163 100644 ---- a/src/lib-storage/list/mailbox-list-index-iter.c -+++ b/src/lib-storage/list/mailbox-list-index-iter.c -@@ -59,7 +59,8 @@ mailbox_list_index_iter_init(struct mailbox_list *list, - ctx->info.ns = list->ns; - ctx->path = str_new(pool, 128); - ctx->next_node = ilist->mailbox_tree; -- ilist->iter_refcount++; -+ ctx->mailbox_pool = ilist->mailbox_pool; -+ pool_ref(ctx->mailbox_pool); - } - return &ctx->ctx; - } -@@ -188,10 +189,8 @@ int mailbox_list_index_iter_deinit(struct mailbox_list_iterate_context *_ctx) - - if (ctx->backend_ctx != NULL) - ret = ilist->module_ctx.super.iter_deinit(ctx->backend_ctx); -- else { -- i_assert(ilist->iter_refcount > 0); -- ilist->iter_refcount--; -- } -+ else -+ pool_unref(&ctx->mailbox_pool); - - pool_unref(&ctx->info_pool); - pool_unref(&_ctx->pool); -diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c -index 61391ea..7fb1b09 100644 ---- a/src/lib-storage/list/mailbox-list-index.c -+++ b/src/lib-storage/list/mailbox-list-index.c -@@ -23,17 +23,25 @@ void mailbox_list_index_set_index_error(struct mailbox_list *list) - mail_index_reset_error(ilist->index); - } - -+static void mailbox_list_index_init_pool(struct mailbox_list_index *ilist) -+{ -+ ilist->mailbox_pool = pool_alloconly_create("mailbox list index", 4096); -+ hash_table_create_direct(&ilist->mailbox_names, ilist->mailbox_pool, 0); -+ hash_table_create_direct(&ilist->mailbox_hash, ilist->mailbox_pool, 0); -+} -+ - void mailbox_list_index_reset(struct mailbox_list_index *ilist) - { -- i_assert(ilist->iter_refcount == 0); -+ hash_table_destroy(&ilist->mailbox_names); -+ hash_table_destroy(&ilist->mailbox_hash); -+ pool_unref(&ilist->mailbox_pool); - -- hash_table_clear(ilist->mailbox_names, TRUE); -- hash_table_clear(ilist->mailbox_hash, TRUE); -- p_clear(ilist->mailbox_pool); - ilist->mailbox_tree = NULL; - ilist->highest_name_id = 0; - ilist->sync_log_file_seq = 0; - ilist->sync_log_file_offset = 0; -+ -+ mailbox_list_index_init_pool(ilist); - } - - static int mailbox_list_index_index_open(struct mailbox_list *list) -@@ -300,8 +308,6 @@ int mailbox_list_index_parse(struct mailbox_list *list, - const struct mail_index_header *hdr; - const char *error; - -- i_assert(ilist->iter_refcount == 0); -- - hdr = mail_index_get_header(view); - if (!force && - hdr->log_file_seq == ilist->sync_log_file_seq && -@@ -357,11 +363,6 @@ int mailbox_list_index_refresh(struct mailbox_list *list) - struct mail_index_view *view; - int ret; - -- if (ilist->iter_refcount > 0) { -- /* someone's already iterating. don't break them. */ -- return 0; -- } -- - if (mailbox_list_index_index_open(list) < 0) - return -1; - if (mail_index_refresh(ilist->index) < 0) { -@@ -608,10 +609,7 @@ static void mailbox_list_index_init_finish(struct mailbox_list *list) - ilist->subs_hdr_ext_id = mail_index_ext_register(ilist->index, "subs", - sizeof(uint32_t), 0, - sizeof(uint32_t)); -- -- ilist->mailbox_pool = pool_alloconly_create("mailbox list index", 4096); -- hash_table_create_direct(&ilist->mailbox_names, ilist->mailbox_pool, 0); -- hash_table_create_direct(&ilist->mailbox_hash, ilist->mailbox_pool, 0); -+ mailbox_list_index_init_pool(ilist); - - mailbox_list_index_status_init_finish(list); - } -diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h -index 6b350aa..7bf99c2 100644 ---- a/src/lib-storage/list/mailbox-list-index.h -+++ b/src/lib-storage/list/mailbox-list-index.h -@@ -87,10 +87,6 @@ struct mailbox_list_index { - struct mail_index *index; - uint32_t ext_id, msgs_ext_id, hmodseq_ext_id, subs_hdr_ext_id; - -- /* Number of iterations going on. Don't refresh mailbox list while -- any iterations are going on. */ -- int iter_refcount; -- - pool_t mailbox_pool; - /* uin32_t id => name */ - HASH_TABLE(void *, char *) mailbox_names; -@@ -115,6 +111,7 @@ struct mailbox_list_index { - struct mailbox_list_index_iterate_context { - struct mailbox_list_iterate_context ctx; - struct mailbox_list_iterate_context *backend_ctx; -+ pool_t mailbox_pool; - - struct mailbox_info info; - pool_t info_pool; --- -1.7.10.2 - - -From b54f404e8d6bc929a8947075d4376f2597b24556 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 22:26:14 +0300 -Subject: [PATCH] auth: Fixed error handling for proxy host dns_lookup() - - -diff --git a/src/auth/auth-worker-server.c b/src/auth/auth-worker-server.c -index 00be552..0521ef5 100644 ---- a/src/auth/auth-worker-server.c -+++ b/src/auth/auth-worker-server.c -@@ -393,6 +393,13 @@ auth_worker_call(pool_t pool, const char *data, - struct auth_worker_connection *conn; - struct auth_worker_request *request; - -+ if (worker_request_queue == NULL) { -+ /* we're deinitializing */ -+ callback(t_strdup_printf("FAIL\t%d", -+ PASSDB_RESULT_INTERNAL_FAILURE), context); -+ return NULL; -+ } -+ - request = p_new(pool, struct auth_worker_request, 1); - request->created = ioloop_time; - request->data = p_strdup(pool, data); --- -1.7.10.2 - - -From a1000fe6b7696d74860d7f873769d8958495da70 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 22:27:23 +0300 -Subject: [PATCH] Reverted previous wrong commit. - - -diff --git a/src/auth/auth-worker-server.c b/src/auth/auth-worker-server.c -index 0521ef5..00be552 100644 ---- a/src/auth/auth-worker-server.c -+++ b/src/auth/auth-worker-server.c -@@ -393,13 +393,6 @@ auth_worker_call(pool_t pool, const char *data, - struct auth_worker_connection *conn; - struct auth_worker_request *request; - -- if (worker_request_queue == NULL) { -- /* we're deinitializing */ -- callback(t_strdup_printf("FAIL\t%d", -- PASSDB_RESULT_INTERNAL_FAILURE), context); -- return NULL; -- } -- - request = p_new(pool, struct auth_worker_request, 1); - request->created = ioloop_time; - request->data = p_strdup(pool, data); --- -1.7.10.2 - - -From 5f80f96983e8965202abc4839e484d53b338279c Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 22:27:57 +0300 -Subject: [PATCH] auth: Fixed error handling for proxy host dns_lookup() - - -diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c -index 0c00c9a..09e21de 100644 ---- a/src/auth/auth-request.c -+++ b/src/auth/auth-request.c -@@ -1689,9 +1689,6 @@ static int auth_request_proxy_host_lookup(struct auth_request *request, - if (dns_lookup(host, &dns_set, auth_request_proxy_dns_callback, ctx, - &ctx->dns_lookup) < 0) { - /* failed early */ -- request->internal_failure = TRUE; -- auth_request_proxy_finish_failure(request); -- auth_request_unref(&request); - return -1; - } - ctx->callback = callback; --- -1.7.10.2 - - -From 795b1c07e2ef8f76fc469d6c1a60658037a70c89 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 30 May 2013 22:44:54 +0300 -Subject: [PATCH] imap: URLFETCH's tagged reply wasn't sent while TCP corked. - - -diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c -index 0fdfb7b..33f9b2d 100644 ---- a/src/imap/cmd-urlfetch.c -+++ b/src/imap/cmd-urlfetch.c -@@ -255,10 +255,11 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply, - bool last, void *context) - { - struct client_command_context *cmd = context; -+ struct client *client = cmd->client; - struct cmd_urlfetch_context *ctx = cmd->context; - int ret; - -- o_stream_cork(cmd->client->output); -+ o_stream_cork(client->output); - if (reply == NULL) { - /* fatal failure */ - ctx->failed = TRUE; -@@ -273,20 +274,20 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply, - str_append(response, "* URLFETCH "); - imap_append_astring(response, reply->url); - str_append(response, " NIL"); -- client_send_line(cmd->client, str_c(response)); -+ client_send_line(client, str_c(response)); - if (reply->error != NULL) { -- client_send_line(cmd->client, t_strdup_printf( -+ client_send_line(client, t_strdup_printf( - "* NO %s.", reply->error)); - } - ret = 1; - } -- o_stream_uncork(cmd->client->output); - - if ((last && cmd->state == CLIENT_COMMAND_STATE_WAIT_EXTERNAL) || - ret < 0) { - cmd_urlfetch_finish(cmd); - client_command_free(&cmd); - } -+ o_stream_uncork(client->output); - return ret; - } - --- -1.7.10.2 - - -From 767257f47cbc2d5397dfe36c8cb788fdb8e9854b Mon Sep 17 00:00:00 2001 -From: Stephan Bosch -Date: Fri, 31 May 2013 02:29:49 +0300 -Subject: [PATCH] imap: URLFETCH's URL callback would prematurely uncork the - output stream when called for a local URL. - - -diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c -index 33f9b2d..c544255 100644 ---- a/src/imap/cmd-urlfetch.c -+++ b/src/imap/cmd-urlfetch.c -@@ -22,6 +22,7 @@ struct cmd_urlfetch_context { - unsigned int failed:1; - unsigned int finished:1; - unsigned int extended:1; -+ unsigned int in_io_handler:1; - }; - - struct cmd_urlfetch_url { -@@ -132,6 +133,7 @@ static bool cmd_urlfetch_continue(struct client_command_context *cmd) - struct client *client = cmd->client; - struct cmd_urlfetch_context *ctx = - (struct cmd_urlfetch_context *)cmd->context; -+ bool urls_pending; - int ret = 1; - - if (cmd->cancel) -@@ -158,7 +160,11 @@ static bool cmd_urlfetch_continue(struct client_command_context *cmd) - client_send_line(client, ""); - client->output_cmd_lock = NULL; - -- if (imap_urlauth_fetch_continue(ctx->ufetch)) { -+ ctx->in_io_handler = TRUE; -+ urls_pending = imap_urlauth_fetch_continue(ctx->ufetch); -+ ctx->in_io_handler = FALSE; -+ -+ if (urls_pending) { - /* waiting for imap urlauth service */ - cmd->state = CLIENT_COMMAND_STATE_WAIT_EXTERNAL; - cmd->func = cmd_urlfetch_cancel; -@@ -257,9 +263,11 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply, - struct client_command_context *cmd = context; - struct client *client = cmd->client; - struct cmd_urlfetch_context *ctx = cmd->context; -+ bool in_io_handler = ctx->in_io_handler; - int ret; - -- o_stream_cork(client->output); -+ if (!in_io_handler) -+ o_stream_cork(client->output); - if (reply == NULL) { - /* fatal failure */ - ctx->failed = TRUE; -@@ -287,7 +295,8 @@ cmd_urlfetch_url_callback(struct imap_urlauth_fetch_reply *reply, - cmd_urlfetch_finish(cmd); - client_command_free(&cmd); - } -- o_stream_uncork(client->output); -+ if (!in_io_handler) -+ o_stream_uncork(client->output); - return ret; - } - -@@ -387,6 +396,7 @@ bool cmd_urlfetch(struct client_command_context *cmd) - ctx->ufetch = imap_urlauth_fetch_init(client->urlauth_ctx, - cmd_urlfetch_url_callback, cmd); - -+ ctx->in_io_handler = TRUE; - array_foreach(&urls, url) { - if (imap_urlauth_fetch_url(ctx->ufetch, url->url, url->flags) < 0) { - /* fatal error */ -@@ -394,6 +404,7 @@ bool cmd_urlfetch(struct client_command_context *cmd) - break; - } - } -+ ctx->in_io_handler = FALSE; - - if ((ctx->failed || !imap_urlauth_fetch_is_pending(ctx->ufetch)) - && cmd->client->output_cmd_lock != cmd) { --- -1.7.10.2 - - -From 77a4bb6374029af5945e604d504645caa8ebb5bf Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 31 May 2013 17:05:13 +0300 -Subject: [PATCH] lib-imap-client: Connect and command timeouts are now - configurable. Also use the same connect timeout for the DNS - lookup's timeout. - - -diff --git a/src/lib-imap-client/imapc-client.c b/src/lib-imap-client/imapc-client.c -index 3e979b7..b5592d3 100644 ---- a/src/lib-imap-client/imapc-client.c -+++ b/src/lib-imap-client/imapc-client.c -@@ -59,6 +59,11 @@ imapc_client_init(const struct imapc_client_settings *set) - p_strdup(pool, set->temp_path_prefix); - client->set.rawlog_dir = p_strdup(pool, set->rawlog_dir); - client->set.max_idle_time = set->max_idle_time; -+ client->set.connect_timeout_msecs = set->connect_timeout_msecs != 0 ? -+ set->connect_timeout_msecs : -+ IMAPC_DEFAULT_CONNECT_TIMEOUT_MSECS; -+ client->set.cmd_timeout_msecs = set->cmd_timeout_msecs != 0 ? -+ set->cmd_timeout_msecs : IMAPC_DEFAULT_COMMAND_TIMEOUT_MSECS; - - if (set->ssl_mode != IMAPC_CLIENT_SSL_MODE_NONE) { - client->set.ssl_mode = set->ssl_mode; -diff --git a/src/lib-imap-client/imapc-client.h b/src/lib-imap-client/imapc-client.h -index 9f59cd6..516763e 100644 ---- a/src/lib-imap-client/imapc-client.h -+++ b/src/lib-imap-client/imapc-client.h -@@ -49,6 +49,9 @@ enum imapc_client_ssl_mode { - IMAPC_CLIENT_SSL_MODE_STARTTLS - }; - -+#define IMAPC_DEFAULT_CONNECT_TIMEOUT_MSECS (1000*30) -+#define IMAPC_DEFAULT_COMMAND_TIMEOUT_MSECS (1000*60*5) -+ - struct imapc_client_settings { - const char *host; - unsigned int port; -@@ -68,6 +71,12 @@ struct imapc_client_settings { - const char *rawlog_dir; - const char *ssl_crypto_device; - bool debug; -+ -+ /* Timeout for logging in. 0 = default. */ -+ unsigned int connect_timeout_msecs; -+ /* Timeout for IMAP commands. Reset every time more data is being -+ sent or received. 0 = default. */ -+ unsigned int cmd_timeout_msecs; - }; - - struct imapc_command_reply { -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index 391a133..11331b1 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -20,9 +20,6 @@ - #include - #include - --#define IMAPC_DNS_LOOKUP_TIMEOUT_MSECS (1000*30) --#define IMAPC_CONNECT_TIMEOUT_MSECS (1000*30) --#define IMAPC_COMMAND_TIMEOUT_MSECS (1000*60*5) - #define IMAPC_MAX_INLINE_LITERAL_SIZE (1024*32) - - enum imapc_input_state { -@@ -1238,11 +1235,11 @@ static void imapc_connection_timeout(struct imapc_connection *conn) - case IMAPC_CONNECTION_STATE_CONNECTING: - i_error("imapc(%s): connect(%s, %u) timed out after %u seconds", - conn->name, net_ip2addr(ip), conn->client->set.port, -- IMAPC_CONNECT_TIMEOUT_MSECS/1000); -+ conn->client->set.connect_timeout_msecs/1000); - break; - case IMAPC_CONNECTION_STATE_AUTHENTICATING: - i_error("imapc(%s): Authentication timed out after %u seconds", -- conn->name, IMAPC_CONNECT_TIMEOUT_MSECS/1000); -+ conn->name, conn->client->set.connect_timeout_msecs/1000); - break; - default: - i_unreached(); -@@ -1307,7 +1304,7 @@ static void imapc_connection_connect_next_ip(struct imapc_connection *conn) - conn); - conn->io = io_add(fd, IO_WRITE, imapc_connection_connected, conn); - conn->parser = imap_parser_create(conn->input, NULL, (size_t)-1); -- conn->to = timeout_add(IMAPC_CONNECT_TIMEOUT_MSECS, -+ conn->to = timeout_add(conn->client->set.connect_timeout_msecs, - imapc_connection_timeout, conn); - conn->to_output = timeout_add(conn->client->set.max_idle_time*1000, - imapc_connection_reset_idle, conn); -@@ -1364,7 +1361,7 @@ void imapc_connection_connect(struct imapc_connection *conn, - memset(&dns_set, 0, sizeof(dns_set)); - dns_set.dns_client_socket_path = - conn->client->set.dns_client_socket_path; -- dns_set.timeout_msecs = IMAPC_DNS_LOOKUP_TIMEOUT_MSECS; -+ dns_set.timeout_msecs = conn->client->set.connect_timeout_msecs; - - imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_CONNECTING); - if (conn->ips_count == 0 && -@@ -1679,7 +1676,7 @@ static void imapc_connection_cmd_send(struct imapc_command *cmd) - /* add timeout for commands if there's not one yet - (pre-login has its own timeout) */ - if (conn->to == NULL) { -- conn->to = timeout_add(IMAPC_COMMAND_TIMEOUT_MSECS, -+ conn->to = timeout_add(conn->client->set.cmd_timeout_msecs, - imapc_command_timeout, conn); - } - } --- -1.7.10.2 - - -From 3460b521fa83e569d086a1b11a1fe446acc71c83 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 31 May 2013 17:36:19 +0300 -Subject: [PATCH] imapc: Empty imapc_user expands to namespace's owner, or - with public namespaces to user itself. The main idea is - that with shared namespaces it now expands to the shared - username, allowing shared mailbox access via imapc. - - -diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c -index 4a3e034..24a0972 100644 ---- a/src/lib-storage/index/imapc/imapc-storage.c -+++ b/src/lib-storage/index/imapc/imapc-storage.c -@@ -230,7 +230,12 @@ imapc_storage_create(struct mail_storage *_storage, - return -1; - } - set.port = storage->set->imapc_port; -- set.username = storage->set->imapc_user; -+ if (storage->set->imapc_user[0] != '\0') -+ set.username = storage->set->imapc_user; -+ else if (ns->owner != NULL) -+ set.username = ns->owner->username; -+ else -+ set.username = ns->user->username; - set.master_user = storage->set->imapc_master_user; - set.password = storage->set->imapc_password; - if (*set.password == '\0') { --- -1.7.10.2 - - -From a3907994b6e72c9c52f3f5b32cac884fc73fbf17 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 31 May 2013 17:36:45 +0300 -Subject: [PATCH] imapc: Changed imapc_user setting's default to empty. - - -diff --git a/src/lib-storage/index/imapc/imapc-settings.c b/src/lib-storage/index/imapc/imapc-settings.c -index dc234d9..feabe02 100644 ---- a/src/lib-storage/index/imapc/imapc-settings.c -+++ b/src/lib-storage/index/imapc/imapc-settings.c -@@ -36,7 +36,7 @@ static const struct imapc_settings imapc_default_settings = { - .imapc_host = "", - .imapc_port = 143, - -- .imapc_user = "%u", -+ .imapc_user = "", - .imapc_master_user = "", - .imapc_password = "", - --- -1.7.10.2 - - -From 74d88d2320db446cf48345c3bbe76f83a193011a Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 02:25:54 +0300 -Subject: [PATCH] Make sure errno is preserved in non-delayed signal handlers. - The current code didn't have any signal handlers that - modified errno, so this doesn't fix any bugs. - - -diff --git a/src/lib/lib-signals.c b/src/lib/lib-signals.c -index b0c7c2c..7043ef3 100644 ---- a/src/lib/lib-signals.c -+++ b/src/lib/lib-signals.c -@@ -97,6 +97,7 @@ static void sig_handler(int signo) - #endif - { - struct signal_handler *h; -+ int saved_errno; - char c = 0; - - #if defined(SI_NOINFO) || !defined(SA_SIGINFO) -@@ -123,21 +124,20 @@ static void sig_handler(int signo) - /* remember that we're inside a signal handler which might have been - called at any time. don't do anything that's unsafe. we might also - get interrupted by another signal while inside this handler. */ -+ saved_errno = errno; - for (h = signal_handlers[signo]; h != NULL; h = h->next) { - if ((h->flags & LIBSIG_FLAG_DELAYED) == 0) - h->handler(si, h->context); - else if (pending_signals[signo].si_signo == 0) { - pending_signals[signo] = *si; - if (!have_pending_signals) { -- int saved_errno = errno; -- - if (write(sig_pipe_fd[1], &c, 1) != 1) - i_error("write(sigpipe) failed: %m"); - have_pending_signals = TRUE; -- errno = saved_errno; - } - } - } -+ errno = saved_errno; - } - - #ifdef SA_SIGINFO --- -1.7.10.2 - - -From e87f8ec304a61f21573e0770d9f6663d7581a183 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 02:56:25 +0300 -Subject: [PATCH] lib-storage: Empty mailbox name isn't valid. - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index 5eedf04..cdf3201 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -1188,10 +1188,14 @@ mailbox_list_is_valid_fs_name(struct mailbox_list *list, const char *name, - bool mailbox_list_is_valid_name(struct mailbox_list *list, - const char *name, const char **error_r) - { -- if (*name == '\0' && *list->ns->prefix != '\0') { -- /* an ugly way to get to mailbox root (e.g. Maildir/ when -- it's not the INBOX) */ -- return TRUE; -+ if (*name == '\0') { -+ if (*list->ns->prefix != '\0') { -+ /* an ugly way to get to mailbox root (e.g. Maildir/ -+ when it's not the INBOX) */ -+ return TRUE; -+ } -+ *error_r = "Name is empty"; -+ return FALSE; - } - - return mailbox_list_is_valid_fs_name(list, name, error_r); --- -1.7.10.2 - - -From 9e886f3af392e924ce444d8bf2bb626cb7ad97f3 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 02:56:57 +0300 -Subject: [PATCH] lib-imap-client: Ask CAPABILITY again after STARTTLS - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index 11331b1..3229885 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -115,6 +115,8 @@ struct imapc_connection { - unsigned int idle_plus_waiting:1; - }; - -+static void imapc_connection_capability_cb(const struct imapc_command_reply *reply, -+ void *context); - static int imapc_connection_output(struct imapc_connection *conn); - static int imapc_connection_ssl_init(struct imapc_connection *conn); - static void imapc_command_free(struct imapc_command *cmd); -@@ -752,6 +754,7 @@ imapc_connection_starttls_cb(const struct imapc_command_reply *reply, - void *context) - { - struct imapc_connection *conn = context; -+ struct imapc_command *cmd; - - if (reply->state != IMAPC_COMMAND_STATE_OK) { - imapc_connection_input_error(conn, "STARTTLS failed: %s", -@@ -761,8 +764,13 @@ imapc_connection_starttls_cb(const struct imapc_command_reply *reply, - - if (imapc_connection_ssl_init(conn) < 0) - imapc_connection_disconnect(conn); -- else -- imapc_connection_authenticate(conn); -+ else { -+ /* get updated capabilities */ -+ cmd = imapc_connection_cmd(conn, imapc_connection_capability_cb, -+ conn); -+ imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN); -+ imapc_command_send(cmd, "CAPABILITY"); -+ } - } - - static void imapc_connection_starttls(struct imapc_connection *conn) --- -1.7.10.2 - - -From ad62819046dbc7c3442bec8b050c54266be88d30 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 03:06:54 +0300 -Subject: [PATCH] imapc: Don't assert-crash when trying to access - imapc_list_prefix itself. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index 52fbd3a..9a644c9 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -225,9 +225,14 @@ imapc_list_get_vname(struct mailbox_list *_list, const char *storage_name) - /* ACL plugin does these lookups */ - } else if (*prefix != '\0' && strcasecmp(storage_name, "INBOX") != 0) { - prefix_len = strlen(prefix); -- i_assert(strncmp(prefix, storage_name, prefix_len) == 0 && -- storage_name[prefix_len] == list->sep); -- storage_name += prefix_len+1; -+ i_assert(strncmp(prefix, storage_name, prefix_len) == 0); -+ storage_name += prefix_len; -+ if (storage_name[0] == '\0') { -+ /* we're looking up the prefix itself */ -+ } else { -+ i_assert(storage_name[0] == list->sep); -+ storage_name++; -+ } - } - return mailbox_list_default_get_vname(_list, storage_name); - } --- -1.7.10.2 - - -From 646c37b5e2e5b575381a63b2a6b1bd311831cd19 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 03:20:15 +0300 -Subject: [PATCH] imapc: Fixed mailbox deletion. - - -diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c -index 24a0972..0e575f1 100644 ---- a/src/lib-storage/index/imapc/imapc-storage.c -+++ b/src/lib-storage/index/imapc/imapc-storage.c -@@ -666,6 +666,12 @@ static void imapc_mailbox_get_selected_status(struct imapc_mailbox *mbox, - status_r->permanent_flags = mbox->permanent_flags; - } - -+static int imapc_mailbox_delete(struct mailbox *box) -+{ -+ box->delete_skip_empty_check = TRUE; -+ return index_storage_mailbox_delete(box); -+} -+ - static int imapc_mailbox_get_status(struct mailbox *box, - enum mailbox_status_items items, - struct mailbox_status *status_r) -@@ -906,7 +912,7 @@ struct mailbox imapc_mailbox = { - index_storage_mailbox_free, - imapc_mailbox_create, - imapc_mailbox_update, -- index_storage_mailbox_delete, -+ imapc_mailbox_delete, - index_storage_mailbox_rename, - imapc_mailbox_get_status, - imapc_mailbox_get_metadata, -diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c -index 727767f..50da9e6 100644 ---- a/src/lib-storage/index/index-storage.c -+++ b/src/lib-storage/index/index-storage.c -@@ -691,13 +691,15 @@ int index_storage_mailbox_delete(struct mailbox *box) - if (mailbox_mark_index_deleted(box, TRUE) < 0) - return -1; - -- if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) -- return -1; -- mailbox_get_open_status(box, STATUS_MESSAGES, &status); -- if (status.messages != 0) { -- mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, -- "New mails were added to mailbox during deletion"); -- return -1; -+ if (!box->delete_skip_empty_check || box->deleting_must_be_empty) { -+ if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) -+ return -1; -+ mailbox_get_open_status(box, STATUS_MESSAGES, &status); -+ if (status.messages != 0) { -+ mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, -+ "New mails were added to mailbox during deletion"); -+ return -1; -+ } - } - - ret_guid = mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata); -diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h -index 4b50d5f..1c31c14 100644 ---- a/src/lib-storage/mail-storage-private.h -+++ b/src/lib-storage/mail-storage-private.h -@@ -320,6 +320,9 @@ struct mailbox { - unsigned int deleting:1; - /* Delete mailbox only if it's empty */ - unsigned int deleting_must_be_empty:1; -+ /* The backend wants to skip checking if there are 0 messages before -+ calling mailbox_list.delete_mailbox() */ -+ unsigned int delete_skip_empty_check:1; - /* Mailbox was already marked as deleted within this allocation. */ - unsigned int marked_deleted:1; - /* TRUE if this is an INBOX for this user */ --- -1.7.10.2 - - -From 1c5aef7a7151cc73bed3250f94d7b582e253afa2 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 03:37:21 +0300 -Subject: [PATCH] imapc: Allow accessing the imapc_list_prefix itself. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index 9a644c9..590a986 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -208,8 +208,8 @@ imapc_list_get_storage_name(struct mailbox_list *_list, const char *vname) - - storage_name = mailbox_list_default_get_storage_name(_list, vname); - if (*prefix != '\0' && strcasecmp(storage_name, "INBOX") != 0) { -- storage_name = t_strdup_printf("%s%c%s", prefix, list->sep, -- storage_name); -+ storage_name = storage_name[0] == '\0' ? prefix : -+ t_strdup_printf("%s%c%s", prefix, list->sep, storage_name); - } - return storage_name; - } --- -1.7.10.2 - - -From f05974d5a38cfa0b233f139cc2b68468f160baff Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 03:48:07 +0300 -Subject: [PATCH] imapc: Return correct mailbox list flags for the imapc - prefix mailbox itself. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index 590a986..c46c241 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -370,8 +370,11 @@ static int imapc_list_refresh(struct imapc_mailbox_list *list) - if (*list->storage->set->imapc_list_prefix == '\0') - pattern = "*"; - else { -- pattern = t_strdup_printf("%s%c*", -- list->storage->set->imapc_list_prefix, list->sep); -+ /* list "prefix*" instead of "prefix.*". this may return a bit -+ more than we want, but we're also interested in the flags -+ of the prefix itself. */ -+ pattern = t_strdup_printf("%s*", -+ list->storage->set->imapc_list_prefix); - } - - cmd = imapc_list_simple_context_init(&ctx, list); --- -1.7.10.2 - - -From af84cdabd2579094aab11b93c3070057cbbcf643 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 04:06:48 +0300 -Subject: [PATCH] lib-storage: If mailbox autocreate fails with "already - exists", ignore the error. This check was supposed to have - been already there, but it was checking for the wrong - error. - - -diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c -index bd4cd71..9ecbd47 100644 ---- a/src/lib-storage/mail-storage.c -+++ b/src/lib-storage/mail-storage.c -@@ -731,7 +731,7 @@ static int mailbox_autocreate(struct mailbox *box) - - if (mailbox_create(box, NULL, FALSE) < 0) { - errstr = mailbox_get_last_error(box, &error); -- if (error != MAIL_ERROR_NOTFOUND) { -+ if (error != MAIL_ERROR_EXISTS) { - mail_storage_set_critical(box->storage, - "Failed to autocreate mailbox %s: %s", - box->vname, errstr); --- -1.7.10.2 - - -From c4b775dfdbb181ea72c865aea83fea1c7e731382 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 04:17:40 +0300 -Subject: [PATCH] imapc: If imapc_list_prefix is set, don't skip it in - filesystem paths. Most importantly this fixes the index - path when accessing the imapc_list_prefix mailbox itself - (so the indexes won't be in the mail root dir, where they - don't get deleted when mailbox is deleted). - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index c46c241..b95df95 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -272,12 +272,37 @@ static const char * - imapc_list_get_fs_name(struct imapc_mailbox_list *list, const char *name) - { - struct mailbox_list *fs_list = imapc_list_get_fs(list); -+ struct mail_namespace *ns = list->list.ns; - const char *vname; -+ char ns_sep = mail_namespace_get_sep(ns); - - if (name == NULL) -- return name; -+ return NULL; - - vname = mailbox_list_get_vname(&list->list, name); -+ if (list->storage->set->imapc_list_prefix[0] != '\0') { -+ /* put back the prefix, so it gets included in the filesystem. */ -+ unsigned int vname_len = strlen(vname); -+ -+ if (ns->prefix_len > 0) { -+ /* skip over the namespace prefix */ -+ i_assert(strncmp(vname, ns->prefix, ns->prefix_len-1) == 0); -+ if (vname_len == ns->prefix_len-1) -+ vname = ""; -+ else { -+ i_assert(vname[ns->prefix_len-1] == ns_sep); -+ vname += ns->prefix_len; -+ } -+ } -+ if (vname[0] == '\0') { -+ vname = t_strconcat(ns->prefix, -+ list->storage->set->imapc_list_prefix, NULL); -+ } else { -+ vname = t_strdup_printf("%s%s%c%s", ns->prefix, -+ list->storage->set->imapc_list_prefix, -+ ns_sep, vname); -+ } -+ } - return mailbox_list_get_storage_name(fs_list, vname); - } - --- -1.7.10.2 - - -From d4503fcbbfbcd468c5cdd9b053f6966d10ccc3db Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 15:33:58 +0300 -Subject: [PATCH] lmtp: Give the DATA input stream a name, so the raw mailbox - gets a name and doesn't fail. - - -diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c -index 3dc9539..4de117f 100644 ---- a/src/lmtp/commands.c -+++ b/src/lmtp/commands.c -@@ -771,6 +771,7 @@ static struct istream *client_get_input(struct client *client) - inputs[2] = NULL; - - cinput = i_stream_create_concat(inputs); -+ i_stream_set_name(cinput, ""); - i_stream_unref(&inputs[0]); - i_stream_unref(&inputs[1]); - return cinput; --- -1.7.10.2 - - -From ec8acf28b7718c09a14e6c8b59d320d295f50729 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 17:08:19 +0300 -Subject: [PATCH] lib-fs: If fs_default_copy() fails, close the copy stream - immediately. The stream's origin may already be freed by - the time the fs_file_close() is trying to close the stream. - - -diff --git a/src/lib-fs/fs-api.c b/src/lib-fs/fs-api.c -index 9b1d633..73f4d3d 100644 ---- a/src/lib-fs/fs-api.c -+++ b/src/lib-fs/fs-api.c -@@ -552,12 +552,16 @@ int fs_default_copy(struct fs_file *src, struct fs_file *dest) - errno = dest->copy_input->stream_errno; - fs_set_error(dest->fs, "read(%s) failed: %m", - i_stream_get_name(dest->copy_input)); -+ i_stream_unref(&dest->copy_input); -+ fs_write_stream_abort(dest, &dest->copy_output); - return -1; - } - if (dest->copy_output->stream_errno != 0) { - errno = dest->copy_output->stream_errno; - fs_set_error(dest->fs, "write(%s) failed: %m", - o_stream_get_name(dest->copy_output)); -+ i_stream_unref(&dest->copy_input); -+ fs_write_stream_abort(dest, &dest->copy_output); - return -1; - } - if (!dest->copy_input->eof) { --- -1.7.10.2 - - -From 55ae6c6cb0b2aa639a35f73ba6f202642b01e754 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 17:11:55 +0300 -Subject: [PATCH] lib-index: Avoid memcpy()ing data over itself. - - -diff --git a/src/lib-index/mail-index-transaction-finish.c b/src/lib-index/mail-index-transaction-finish.c -index 7d4c829..f990d2d 100644 ---- a/src/lib-index/mail-index-transaction-finish.c -+++ b/src/lib-index/mail-index-transaction-finish.c -@@ -293,8 +293,10 @@ static void expunges_convert_to_uids(struct mail_index_transaction *t) - expunges[dest].uid = - mail_index_transaction_get_uid(t, expunges[src].uid); - if (expunges[dest-1].uid != expunges[dest].uid) { -- memcpy(expunges[dest].guid_128, expunges[src].guid_128, -- sizeof(expunges[dest].guid_128)); -+ if (dest != src) { -+ memcpy(expunges[dest].guid_128, expunges[src].guid_128, -+ sizeof(expunges[dest].guid_128)); -+ } - dest++; - } - } --- -1.7.10.2 - - -From bc5f152cafb5ccf45fc0049badb16bb2154ec28f Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sat, 1 Jun 2013 17:17:47 +0300 -Subject: [PATCH] lda/lmtp: If mail delivery fails with tempfail, don't - fallback to saving to INBOX. - - -diff --git a/src/lda/main.c b/src/lda/main.c -index 447168f..4ed8a31 100644 ---- a/src/lda/main.c -+++ b/src/lda/main.c -@@ -436,14 +436,17 @@ int main(int argc, char *argv[]) - lda_set_dest_addr(&ctx, user, destaddr_source); - - if (mail_deliver(&ctx, &storage) < 0) { -- if (storage == NULL) { -+ if (storage != NULL) { -+ errstr = mail_storage_get_last_error(storage, &error); -+ } else if (ctx.tempfail_error != NULL) { -+ errstr = ctx.tempfail_error; -+ error = MAIL_ERROR_TEMP; -+ } else { - /* This shouldn't happen */ - i_error("BUG: Saving failed to unknown storage"); - return EX_TEMPFAIL; - } - -- errstr = mail_storage_get_last_error(storage, &error); -- - if (stderr_rejection) { - /* write to stderr also for tempfails so that MTA - can log the reason if it wants to. */ -diff --git a/src/lib-lda/mail-deliver.c b/src/lib-lda/mail-deliver.c -index 069f878..458dcd2 100644 ---- a/src/lib-lda/mail-deliver.c -+++ b/src/lib-lda/mail-deliver.c -@@ -371,6 +371,20 @@ const char *mail_deliver_get_new_message_id(struct mail_deliver_context *ctx) - count++, ctx->set->hostname); - } - -+static bool mail_deliver_is_tempfailed(struct mail_deliver_context *ctx, -+ struct mail_storage *storage) -+{ -+ enum mail_error error; -+ -+ if (ctx->tempfail_error != NULL) -+ return TRUE; -+ if (storage != NULL) { -+ (void)mail_storage_get_last_error(storage, &error); -+ return error == MAIL_ERROR_TEMP; -+ } -+ return FALSE; -+} -+ - int mail_deliver(struct mail_deliver_context *ctx, - struct mail_storage **storage_r) - { -@@ -390,12 +404,16 @@ int mail_deliver(struct mail_deliver_context *ctx, - ret = 0; - } - duplicate_deinit(&ctx->dup_ctx); -+ if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) -+ return -1; - } - - if (ret < 0 && !ctx->tried_default_save) { - /* plugins didn't handle this. save into the default mailbox. */ - ret = mail_deliver_save(ctx, ctx->dest_mailbox_name, 0, NULL, - storage_r); -+ if (ret < 0 && mail_deliver_is_tempfailed(ctx, *storage_r)) -+ return -1; - } - if (ret < 0 && strcasecmp(ctx->dest_mailbox_name, "INBOX") != 0) { - /* still didn't work. try once more to save it -diff --git a/src/lib-lda/mail-deliver.h b/src/lib-lda/mail-deliver.h -index fbc2941..f0646a2 100644 ---- a/src/lib-lda/mail-deliver.h -+++ b/src/lib-lda/mail-deliver.h -@@ -48,6 +48,10 @@ struct mail_deliver_context { - /* mail_deliver_log() caches the var expand table here */ - struct var_expand_table *var_expand_table; - -+ /* Error message for a temporary failure. This is necessary only when -+ there is no storage where to get the error message from. */ -+ const char *tempfail_error; -+ - bool tried_default_save; - bool saved_mail; - bool save_dest_mail; -diff --git a/src/lmtp/commands.c b/src/lmtp/commands.c -index 4de117f..8d8baa0 100644 ---- a/src/lmtp/commands.c -+++ b/src/lmtp/commands.c -@@ -694,13 +694,7 @@ client_deliver(struct client *client, const struct mail_recipient *rcpt, - client_send_line(client, "250 2.0.0 <%s> %s Saved", - rcpt->address, client->state.session_id); - ret = 0; -- } else if (storage == NULL) { -- /* This shouldn't happen */ -- i_error("BUG: Saving failed to unknown storage"); -- client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, -- rcpt->address); -- ret = -1; -- } else { -+ } else if (storage != NULL) { - error = mail_storage_get_last_error(storage, &mail_error); - if (mail_error == MAIL_ERROR_NOSPACE) { - client_send_line(client, "%s <%s> %s", -@@ -712,6 +706,16 @@ client_deliver(struct client *client, const struct mail_recipient *rcpt, - rcpt->address, error); - } - ret = -1; -+ } else if (dctx.tempfail_error != NULL) { -+ client_send_line(client, "451 4.2.0 <%s> %s", -+ rcpt->address, dctx.tempfail_error); -+ ret = -1; -+ } else { -+ /* This shouldn't happen */ -+ i_error("BUG: Saving failed to unknown storage"); -+ client_send_line(client, ERRSTR_TEMP_MAILBOX_FAIL, -+ rcpt->address); -+ ret = -1; - } - return ret; - } --- -1.7.10.2 - - -From 30c6f2d3af999d5463dd5bafd4fd326ef909f3c3 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 15:08:59 +0300 -Subject: [PATCH] lib-http: Don't create a new HTTP connection when there is - already one connecting. - - -diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c -index 88237d8..12618d0 100644 ---- a/src/lib-http/http-client-peer.c -+++ b/src/lib-http/http-client-peer.c -@@ -147,7 +147,7 @@ http_client_peer_next_request(struct http_client_peer *peer) - finished connecting successfully. */ - new_connections = 0; - } else if (num_urgent == 0) { -- new_connections = 1; -+ new_connections = connecting == 0 ? 1 : 0; - } else { - new_connections = (num_urgent > connecting ? num_urgent - connecting : 0); - } --- -1.7.10.2 - - -From 7f20b65ede32ee3f81f56aa8dfc8baaaa60af5ef Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 15:43:42 +0300 -Subject: [PATCH] lib-http: Mark the HTTP connection connected only after SSL - handshake is finished. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index bf0d80a..127eb40 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -665,6 +665,7 @@ http_client_connection_ssl_handshaked(const char **error_r, void *context) - *error_r = error; - return -1; - } -+ http_client_connection_ready(conn); - return 0; - } - -@@ -703,8 +704,6 @@ http_client_connection_ssl_init(struct http_client_connection *conn, - conn->conn.name, ssl_iostream_get_last_error(conn->ssl_iostream)); - return -1; - } -- -- http_client_connection_ready(conn); - return 0; - } - --- -1.7.10.2 - - -From 79cc711c13e2161a577d0f670c521abc15f46cad Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 16:19:38 +0300 -Subject: [PATCH] lib-http: Added connect and request timeout settings. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index 127eb40..f40b1cd 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -8,6 +8,7 @@ - #include "ioloop.h" - #include "istream.h" - #include "ostream.h" -+#include "time-util.h" - #include "iostream-rawlog.h" - #include "iostream-ssl.h" - #include "http-response-parser.h" -@@ -202,6 +203,17 @@ http_client_connection_check_idle(struct http_client_connection *conn) - } - - static void -+http_client_connection_request_timeout(struct http_client_connection *conn) -+{ -+ unsigned int msecs = conn->client->set.request_timeout_msecs; -+ -+ http_client_connection_abort_temp_error(&conn, -+ HTTP_CLIENT_REQUEST_ERROR_TIMED_OUT, t_strdup_printf( -+ "No response for request in %u.%03u secs", -+ msecs/1000, msecs%1000)); -+} -+ -+static void - http_client_connection_continue_timeout(struct http_client_connection *conn) - { - struct http_client_request *const *req_idx; -@@ -249,6 +261,11 @@ bool http_client_connection_next_request(struct http_client_connection *conn) - if (conn->to_idle != NULL) - timeout_remove(&conn->to_idle); - -+ if (conn->client->set.request_timeout_msecs > 0 && -+ conn->to_requests == NULL) { -+ conn->to_requests = timeout_add(conn->client->set.request_timeout_msecs, -+ http_client_connection_request_timeout, conn); -+ } - req->conn = conn; - conn->payload_continue = FALSE; - if (conn->peer->no_payload_sync) -@@ -293,14 +310,26 @@ static void http_client_connection_destroy(struct connection *_conn) - struct http_client_connection *conn = - (struct http_client_connection *)_conn; - const char *error; -+ unsigned int msecs; - - conn->closing = TRUE; - conn->connected = FALSE; - - switch (_conn->disconnect_reason) { - case CONNECTION_DISCONNECT_CONNECT_TIMEOUT: -- http_client_peer_connection_failure(conn->peer, t_strdup_printf( -- "connect(%s) failed: Connection timed out", _conn->name)); -+ if (conn->connected_timestamp.tv_sec == 0) { -+ msecs = timeval_diff_msecs(&ioloop_timeval, -+ &conn->connect_start_timestamp); -+ http_client_peer_connection_failure(conn->peer, t_strdup_printf( -+ "connect(%s) failed: Connection timed out in %u.%03u secs", -+ _conn->name, msecs/1000, msecs%1000)); -+ } else { -+ msecs = timeval_diff_msecs(&ioloop_timeval, -+ &conn->connected_timestamp); -+ http_client_peer_connection_failure(conn->peer, t_strdup_printf( -+ "SSL handshaking to %s failed: Connection timed out in %u.%03u secs", -+ _conn->name, msecs/1000, msecs%1000)); -+ } - break; - case CONNECTION_DISCONNECT_CONN_CLOSED: - /* retry pending requests if possible */ -@@ -453,6 +482,8 @@ static void http_client_connection_input(struct connection *_conn) - http_client_payload_finished(conn); - finished++; - } -+ if (conn->to_requests != NULL) -+ timeout_reset(conn->to_requests); - - /* get first waiting request */ - if (array_count(&conn->request_wait_list) > 0) { -@@ -560,6 +591,9 @@ static void http_client_connection_input(struct connection *_conn) - req = req_idx[0]; - no_payload = (strcmp(req->method, "HEAD") == 0); - } else { -+ /* no more requests waiting for the connection */ -+ if (conn->to_requests != NULL) -+ timeout_remove(&conn->to_requests); - req = NULL; - no_payload = FALSE; - } -@@ -597,6 +631,9 @@ static int http_client_connection_output(struct http_client_connection *conn) - const char *error; - int ret; - -+ if (conn->to_requests != NULL) -+ timeout_reset(conn->to_requests); -+ - if ((ret = o_stream_flush(output)) <= 0) { - if (ret < 0) { - http_client_connection_abort_temp_error(&conn, -@@ -635,6 +672,8 @@ http_client_connection_ready(struct http_client_connection *conn) - - conn->connected = TRUE; - conn->peer->last_connect_failed = FALSE; -+ if (conn->to_connect != NULL) -+ timeout_remove(&conn->to_connect); - - if (conn->client->set.rawlog_dir != NULL && - stat(conn->client->set.rawlog_dir, &st) == 0) { -@@ -718,6 +757,7 @@ http_client_connection_connected(struct connection *_conn, bool success) - http_client_peer_connection_failure(conn->peer, t_strdup_printf( - "connect(%s) failed: %m", _conn->name)); - } else { -+ conn->connected_timestamp = ioloop_timeval; - http_client_connection_debug(conn, "Connected"); - if (conn->peer->addr.https_name != NULL) { - if (http_client_connection_ssl_init(conn, &error) < 0) { -@@ -758,12 +798,32 @@ http_client_connection_delayed_connect_error(struct http_client_connection *conn - http_client_connection_unref(&conn); - } - -+static void http_client_connect_timeout(struct http_client_connection *conn) -+{ -+ conn->conn.disconnect_reason = CONNECTION_DISCONNECT_CONNECT_TIMEOUT; -+ http_client_connection_destroy(&conn->conn); -+} -+ - static void http_client_connection_connect(struct http_client_connection *conn) - { -+ unsigned int msecs; -+ -+ conn->connect_start_timestamp = ioloop_timeval; - if (connection_client_connect(&conn->conn) < 0) { - conn->connect_errno = errno; - conn->to_input = timeout_add_short(0, - http_client_connection_delayed_connect_error, conn); -+ return; -+ } -+ -+ /* don't use connection.h timeout because we want this timeout -+ to include also the SSL handshake */ -+ msecs = conn->client->set.connect_timeout_msecs; -+ if (msecs == 0) -+ msecs = conn->client->set.request_timeout_msecs; -+ if (msecs > 0) { -+ conn->to_connect = -+ timeout_add(msecs, http_client_connect_timeout, conn); - } - } - -@@ -831,6 +891,10 @@ void http_client_connection_unref(struct http_client_connection **_conn) - ssl_iostream_unref(&conn->ssl_iostream); - connection_deinit(&conn->conn); - -+ if (conn->to_requests != NULL) -+ timeout_remove(&conn->to_requests); -+ if (conn->to_connect != NULL) -+ timeout_remove(&conn->to_connect); - if (conn->to_input != NULL) - timeout_remove(&conn->to_input); - if (conn->to_idle != NULL) -@@ -855,6 +919,10 @@ void http_client_connection_unref(struct http_client_connection **_conn) - - void http_client_connection_switch_ioloop(struct http_client_connection *conn) - { -+ if (conn->to_requests != NULL) -+ conn->to_requests = io_loop_move_timeout(&conn->to_requests); -+ if (conn->to_connect != NULL) -+ conn->to_requests = io_loop_move_timeout(&conn->to_connect); - if (conn->to_input != NULL) - conn->to_input = io_loop_move_timeout(&conn->to_input); - if (conn->to_idle != NULL) -diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h -index 4d7aa64..023f8e9 100644 ---- a/src/lib-http/http-client-private.h -+++ b/src/lib-http/http-client-private.h -@@ -134,10 +134,13 @@ struct http_client_connection { - - unsigned int id; // DEBUG: identify parallel connections - int connect_errno; -+ struct timeval connect_start_timestamp; -+ struct timeval connected_timestamp; - - struct ssl_iostream *ssl_iostream; - struct http_response_parser *http_parser; -- struct timeout *to_input, *to_idle, *to_response; -+ struct timeout *to_connect, *to_input, *to_idle, *to_response; -+ struct timeout *to_requests; - - struct http_client_request *pending_request; - struct istream *incoming_payload; -diff --git a/src/lib-http/http-client.c b/src/lib-http/http-client.c -index f153b51..aa94853 100644 ---- a/src/lib-http/http-client.c -+++ b/src/lib-http/http-client.c -@@ -96,6 +96,8 @@ struct http_client *http_client_init(const struct http_client_settings *set) - (set->max_pipelined_requests > 0 ? set->max_pipelined_requests : 1); - client->set.max_attempts = set->max_attempts; - client->set.max_redirects = set->max_redirects; -+ client->set.request_timeout_msecs = set->request_timeout_msecs; -+ client->set.connect_timeout_msecs = set->connect_timeout_msecs; - client->set.debug = set->debug; - - client->conn_list = http_client_connection_list_init(); -diff --git a/src/lib-http/http-client.h b/src/lib-http/http-client.h -index 9c8d131..8a2c31e 100644 ---- a/src/lib-http/http-client.h -+++ b/src/lib-http/http-client.h -@@ -57,6 +57,13 @@ struct http_client_settings { - /* maximum number of attempts for a request */ - unsigned int max_attempts; - -+ /* max time to wait for HTTP request to finish before retrying -+ (default = unlimited) */ -+ unsigned int request_timeout_msecs; -+ /* max time to wait for connect() (and SSL handshake) to finish before -+ retrying (default = request_timeout_msecs) */ -+ unsigned int connect_timeout_msecs; -+ - bool debug; - }; - --- -1.7.10.2 - - -From 82ee63360c34a556271bc3132109caba873eaed0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 16:28:16 +0300 -Subject: [PATCH] lib-http: When receiving 1xx response while waiting for 100, - don't restart timeout. The 100 response is missing only - from HTTP/1.0 requests, which also didn't allow any 1xx - responses. So if a 1xx response is returned, a 100 response - is definitely also coming. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index f40b1cd..b4c8b23 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -542,9 +542,6 @@ static void http_client_connection_input(struct connection *_conn) - /* ignore them for now */ - http_client_connection_debug(conn, - "Got unexpected %u response; ignoring", response->status); -- /* restart timeout */ -- conn->to_response = timeout_add(HTTP_CLIENT_CONTINUE_TIMEOUT_MSECS, -- http_client_connection_continue_timeout, conn); - continue; - } - --- -1.7.10.2 - - -From 6e737f6bb0e3d83c24905259608454a92a68a5a3 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 16:40:01 +0300 -Subject: [PATCH] lib-http: After peer has received 100 response, don't add - ambiguity timeout anymore. The server should be sending the - 100 responses then, and long delays shouldn't be confused - with them being missing. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index b4c8b23..7282401 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -295,7 +295,7 @@ bool http_client_connection_next_request(struct http_client_connection *conn) - (Continue) status code, the client SHOULD NOT wait for an indefinite - period before sending the payload body. - */ -- if (req->payload_sync) { -+ if (req->payload_sync && !conn->peer->seen_100_response) { - i_assert(req->payload_chunked || req->payload_size > 0); - i_assert(conn->to_response == NULL); - conn->to_response = timeout_add(HTTP_CLIENT_CONTINUE_TIMEOUT_MSECS, -@@ -529,6 +529,8 @@ static void http_client_connection_input(struct connection *_conn) - "Got 100-continue response after timeout"); - return; - } -+ conn->peer->no_payload_sync = FALSE; -+ conn->peer->seen_100_response = TRUE; - conn->payload_continue = TRUE; - http_client_connection_debug(conn, - "Got expected 100-continue response"); -diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h -index 023f8e9..396fc07 100644 ---- a/src/lib-http/http-client-private.h -+++ b/src/lib-http/http-client-private.h -@@ -121,6 +121,7 @@ struct http_client_peer { - - unsigned int destroyed:1; /* peer is being destroyed */ - unsigned int no_payload_sync:1; /* expect: 100-continue failed before */ -+ unsigned int seen_100_response:1;/* expect: 100-continue succeeded before */ - unsigned int last_connect_failed:1; - }; - --- -1.7.10.2 - - -From 22139460f7cb9ff8eb7d9ea614829a617bf478cd Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 17:14:49 +0300 -Subject: [PATCH] dsync: If unexpected changes happened during sync, log a - warning and exit with code 2. This was done by v2.1 dsync, - but the code got temporarily lost in v2.2. - - -diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c -index a1e6e9d..4957a3c 100644 ---- a/src/doveadm/dsync/doveadm-dsync.c -+++ b/src/doveadm/dsync/doveadm-dsync.c -@@ -291,7 +291,8 @@ static bool paths_are_equal(struct mail_user *user1, struct mail_user *user2, - - static int - cmd_dsync_run_local(struct dsync_cmd_context *ctx, struct mail_user *user, -- struct dsync_brain *brain, struct dsync_ibc *ibc2) -+ struct dsync_brain *brain, struct dsync_ibc *ibc2, -+ bool *changes_during_sync_r) - { - struct dsync_brain *brain2; - struct mail_user *user2; -@@ -357,6 +358,7 @@ cmd_dsync_run_local(struct dsync_cmd_context *ctx, struct mail_user *user, - brain2_running = dsync_brain_run(brain2, &changed2); - } - mail_user_unref(&user2); -+ *changes_during_sync_r = dsync_brain_has_unexpected_changes(brain2); - if (dsync_brain_deinit(&brain2) < 0) { - ctx->ctx.exit_code = EX_TEMPFAIL; - return -1; -@@ -490,6 +492,7 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - struct dsync_brain_settings set; - enum dsync_brain_flags brain_flags; - bool remote_errors_logged = FALSE; -+ bool changes_during_sync = FALSE; - int status = 0, ret = 0; - - memset(&set, 0, sizeof(set)); -@@ -540,7 +543,8 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - brain_flags, &set); - - if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL) { -- if (cmd_dsync_run_local(ctx, user, brain, ibc2) < 0) -+ if (cmd_dsync_run_local(ctx, user, brain, ibc2, -+ &changes_during_sync) < 0) - ret = -1; - } else { - cmd_dsync_run_remote(user); -@@ -552,6 +556,11 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - doveadm_print(str_c(state_str)); - } - -+ if (dsync_brain_has_unexpected_changes(brain) || changes_during_sync) { -+ i_warning("Mailbox changes caused a desync. " -+ "You may want to run dsync again."); -+ ctx->ctx.exit_code = 2; -+ } - if (dsync_brain_deinit(&brain) < 0) { - ctx->ctx.exit_code = EX_TEMPFAIL; - ret = -1; -diff --git a/src/doveadm/dsync/dsync-brain.c b/src/doveadm/dsync/dsync-brain.c -index 803c447..a6b4bd4 100644 ---- a/src/doveadm/dsync/dsync-brain.c -+++ b/src/doveadm/dsync/dsync-brain.c -@@ -513,3 +513,8 @@ bool dsync_brain_has_failed(struct dsync_brain *brain) - { - return brain->failed; - } -+ -+bool dsync_brain_has_unexpected_changes(struct dsync_brain *brain) -+{ -+ return brain->changes_during_sync; -+} -diff --git a/src/doveadm/dsync/dsync-brain.h b/src/doveadm/dsync/dsync-brain.h -index 6d7c218..c280908 100644 ---- a/src/doveadm/dsync/dsync-brain.h -+++ b/src/doveadm/dsync/dsync-brain.h -@@ -67,5 +67,7 @@ bool dsync_brain_has_failed(struct dsync_brain *brain); - void dsync_brain_get_state(struct dsync_brain *brain, string_t *output); - /* Returns the sync type that was used. Mainly useful with slave brain. */ - enum dsync_brain_sync_type dsync_brain_get_sync_type(struct dsync_brain *brain); -+/* Returns TRUE if there were any unexpected changes during the sync. */ -+bool dsync_brain_has_unexpected_changes(struct dsync_brain *brain); - - #endif --- -1.7.10.2 - - -From 91eaf566ceb82890e157a50e697ab808077564f5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 17:48:48 +0300 -Subject: [PATCH] lib-imap: Added imap_utf7_is_valid() - - -diff --git a/src/lib-imap/imap-utf7.c b/src/lib-imap/imap-utf7.c -index e499156..4c58a91 100644 ---- a/src/lib-imap/imap-utf7.c -+++ b/src/lib-imap/imap-utf7.c -@@ -271,3 +271,22 @@ int imap_utf7_to_utf8(const char *src, string_t *dest) - } - return 0; - } -+ -+bool imap_utf7_is_valid(const char *src) -+{ -+ const char *p; -+ int ret; -+ -+ for (p = src; *p != '\0'; p++) { -+ if (*p == '&' || (unsigned char)*p >= 0x80) { -+ /* slow scan */ -+ T_BEGIN { -+ string_t *tmp = t_str_new(128); -+ ret = imap_utf7_to_utf8(p, tmp); -+ } T_END; -+ if (ret < 0) -+ return FALSE; -+ } -+ } -+ return TRUE; -+} -diff --git a/src/lib-imap/imap-utf7.h b/src/lib-imap/imap-utf7.h -index f41b8db..5d7875f 100644 ---- a/src/lib-imap/imap-utf7.h -+++ b/src/lib-imap/imap-utf7.h -@@ -8,5 +8,7 @@ int t_imap_utf8_to_utf7(const char *src, const char **dest_r); - /* Convert IMAP-UTF-7 string to UTF-8. Returns 0 if ok, -1 if src isn't - valid IMAP-UTF-7. */ - int imap_utf7_to_utf8(const char *src, string_t *dest); -+/* Returns TRUE if the string is valid IMAP-UTF-7 string. */ -+bool imap_utf7_is_valid(const char *src); - - #endif -diff --git a/src/lib-imap/test-imap-utf7.c b/src/lib-imap/test-imap-utf7.c -index 93360de..e08dbf3 100644 ---- a/src/lib-imap/test-imap-utf7.c -+++ b/src/lib-imap/test-imap-utf7.c -@@ -8,53 +8,46 @@ - - static void test_imap_utf7(void) - { -- static const char *to_utf7[] = { -- "&&x&&", "&-&-x&-&-", -- "~peter/mail/台北/日本語", "~peter/mail/&U,BTFw-/&ZeVnLIqe-", -- "tietäjä", "tiet&AOQ-j&AOQ-", -- "p\xe4\xe4", NULL, -- NULL -- }; -- static const char *invalid_utf7[] = { -- "&Jjo!", -- "&U,BTFw-&ZeVnLIqe-", -- NULL -+ static struct test { -+ const char *utf8; -+ const char *mutf7; -+ } tests[] = { -+ { "&&x&&", "&-&-x&-&-" }, -+ { "~peter/mail/台北/日本語", "~peter/mail/&U,BTFw-/&ZeVnLIqe-" }, -+ { "tietäjä", "tiet&AOQ-j&AOQ-" }, -+ { "p\xe4\xe4", NULL }, -+ { NULL, "&" }, -+ { NULL, "&Jjo" }, -+ { NULL, "&Jjo!" }, -+ { NULL, "&U,BTFw-&ZeVnLIqe-" } - }; - string_t *src, *dest; - const char *orig_src; - unsigned int i, j; - unichar_t chr; -- bool success, all_success = TRUE; - - src = t_str_new(256); - dest = t_str_new(256); - -- for (i = 0; to_utf7[i] != NULL; i += 2) { -- str_truncate(dest, 0); -- if (imap_utf8_to_utf7(to_utf7[i], dest) < 0) -- success = to_utf7[i+1] == NULL; -- else { -- success = to_utf7[i+1] != NULL && -- strcmp(to_utf7[i+1], str_c(dest)) == 0; -+ test_begin("imap mutf7"); -+ for (i = 0; i < N_ELEMENTS(tests); i++) { -+ if (tests[i].utf8 != NULL) { -+ str_truncate(dest, 0); -+ if (imap_utf8_to_utf7(tests[i].utf8, dest) < 0) -+ test_assert(tests[i].mutf7 == NULL); -+ else -+ test_assert(null_strcmp(tests[i].mutf7, str_c(dest)) == 0); - } -- if (!success) { -- test_out(t_strdup_printf("imap_utf8_to_utf7(%d)", i/2), -- FALSE); -- all_success = FALSE; -- } else if (to_utf7[i+1] != NULL) { -+ if (tests[i].mutf7 != NULL) { - str_truncate(dest, 0); -- if (imap_utf7_to_utf8(to_utf7[i+1], dest) < 0 || -- strcmp(to_utf7[i], str_c(dest)) != 0) { -- test_out(t_strdup_printf("imap_utf7_to_utf8(%d)", i/2), -- FALSE); -- all_success = FALSE; -- } -+ if (imap_utf7_to_utf8(tests[i].mutf7, dest) < 0) -+ test_assert(tests[i].utf8 == NULL); -+ else -+ test_assert(null_strcmp(tests[i].utf8, str_c(dest)) == 0); -+ test_assert(imap_utf7_is_valid(tests[i].mutf7) != (tests[i].utf8 == NULL)); - } - } -- if (all_success) -- test_out("imap_utf8_to_utf7()", TRUE); - -- success = TRUE; - for (chr = 0xffff; chr <= 0x10010; chr++) { - for (i = 1; i <= 10; i++) { - str_truncate(src, 0); -@@ -70,28 +63,12 @@ static void test_imap_utf7(void) - orig_src = t_strdup(str_c(src)); - str_truncate(src, 0); - -- if (imap_utf8_to_utf7(orig_src, dest) < 0) -- success = FALSE; -- else if (imap_utf7_to_utf8(str_c(dest), src) < 0) -- success = FALSE; -- else -- success = strcmp(str_c(src), orig_src) == 0; -- if (!success) -- goto end; -- } -- } --end: -- test_out("imap_utf7_to_utf8(reverse)", success); -- for (i = 0; invalid_utf7[i] != NULL; i++) { -- str_truncate(dest, 0); -- if (imap_utf7_to_utf8(invalid_utf7[i], dest) == 0) { -- test_out(t_strdup_printf("imap_utf7_to_utf8(invalid.%d)", i), -- FALSE); -- all_success = FALSE; -+ test_assert(imap_utf8_to_utf7(orig_src, dest) == 0); -+ test_assert(imap_utf7_to_utf8(str_c(dest), src) == 0); -+ test_assert(strcmp(str_c(src), orig_src) == 0); - } - } -- if (all_success) -- test_out("imap_utf7_to_utf8(invalid)", TRUE); -+ test_end(); - } - - int main(void) --- -1.7.10.2 - - -From 5c30c1fbd7aa58f252f08f7526ff0d39bf3b32ff Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 17:49:46 +0300 -Subject: [PATCH] lib-imap: Make sure imap_utf7_to_utf8() doesn't access - invalid input string out of bounds. - - -diff --git a/src/lib-imap/imap-utf7.c b/src/lib-imap/imap-utf7.c -index 4c58a91..bc9c033 100644 ---- a/src/lib-imap/imap-utf7.c -+++ b/src/lib-imap/imap-utf7.c -@@ -179,8 +179,10 @@ static int mbase64_decode_to_utf8(string_t *dest, const char **_src) - - while (*src != '-') { - input[0] = imap_b64dec[(uint8_t)src[0]]; -+ if (input[0] == 0xff) -+ return -1; - input[1] = imap_b64dec[(uint8_t)src[1]]; -- if (input[0] == 0xff || input[1] == 0xff) -+ if (input[1] == 0xff) - return -1; - - output[outpos % 4] = (input[0] << 2) | (input[1] >> 4); --- -1.7.10.2 - - -From a4f74888f251919ca4b313b9cf5835eba32dabce Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 18:15:22 +0300 -Subject: [PATCH] lib-storage: mailbox_list_settings.broken_char wasn't - escaping 8bit chars correctly. - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index cdf3201..4db5433 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -637,7 +637,7 @@ mailbox_list_escape_broken_name(struct mailbox_list *list, - for (; *vname != '\0'; vname++) { - if (*vname == '&' || (unsigned char)*vname >= 0x80) { - str_printfa(str, "%c%02x", list->set.broken_char, -- *vname); -+ (unsigned char)*vname); - } else { - str_append_c(str, *vname); - } --- -1.7.10.2 - - -From f00ed2b3f3744c82d19f4739b383e871f35fc693 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Wed, 5 Jun 2013 18:21:55 +0300 -Subject: [PATCH] dsync: Set broken_char to a control char, so invalid mailbox - names are handled properly. The dsync will now fail if - there are invalid mailbox names (e.g. valid UTF8 when they - should have been mUTF7), instead of simply printing - "mailbox doesn't exist" error and exiting with 0. - - -diff --git a/src/doveadm/dsync/doveadm-dsync.c b/src/doveadm/dsync/doveadm-dsync.c -index 4957a3c..cd28ed2 100644 ---- a/src/doveadm/dsync/doveadm-dsync.c -+++ b/src/doveadm/dsync/doveadm-dsync.c -@@ -19,7 +19,7 @@ - #include "mail-storage-service.h" - #include "mail-user.h" - #include "mail-namespace.h" --#include "mailbox-list.h" -+#include "mailbox-list-private.h" - #include "doveadm-settings.h" - #include "doveadm-mail.h" - #include "doveadm-print.h" -@@ -38,6 +38,12 @@ - - #define DSYNC_COMMON_GETOPT_ARGS "+dEfg:l:m:n:Nr:Rs:Ux:" - #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 -+/* The broken_char is mainly set to get a proper error message when trying to -+ convert a mailbox with a name that can't be used properly translated between -+ vname/storage_name and would otherwise be mixed up with a normal "mailbox -+ doesn't exist" error message. This could be any control character, since -+ none of them are allowed to be created in regular mailbox names. */ -+#define DSYNC_LIST_BROKEN_CHAR '\003' - - enum dsync_run_type { - DSYNC_RUN_TYPE_LOCAL, -@@ -279,6 +285,15 @@ static bool mirror_get_remote_cmd(struct dsync_cmd_context *ctx, - return TRUE; - } - -+static void doveadm_user_init_dsync(struct mail_user *user) -+{ -+ struct mail_namespace *ns; -+ -+ user->dsyncing = TRUE; -+ for (ns = user->namespaces; ns != NULL; ns = ns->next) -+ ns->list->set.broken_char = DSYNC_LIST_BROKEN_CHAR; -+} -+ - static bool paths_are_equal(struct mail_user *user1, struct mail_user *user2, - enum mailbox_list_path_type type) - { -@@ -322,7 +337,7 @@ cmd_dsync_run_local(struct dsync_cmd_context *ctx, struct mail_user *user, - ctx->ctx.exit_code = ret == -1 ? EX_TEMPFAIL : EX_CONFIG; - return -1; - } -- user2->dsyncing = TRUE; -+ doveadm_user_init_dsync(user2); - - if (mail_namespaces_get_root_sep(user->namespaces) != - mail_namespaces_get_root_sep(user2->namespaces)) { -@@ -504,8 +519,7 @@ cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - /* array is NULL-terminated in init() */ - set.exclude_mailboxes = array_idx(&ctx->exclude_mailboxes, 0); - } -- -- user->dsyncing = TRUE; -+ doveadm_user_init_dsync(user); - - if (ctx->namespace_prefix != NULL) { - set.sync_ns = mail_namespace_find(user->namespaces, -@@ -946,7 +960,7 @@ cmd_dsync_server_run(struct doveadm_mail_cmd_context *_ctx, - ctx->output = _ctx->conn->output; - o_stream_nsend(ctx->output, "\n+\n", 3); - } -- user->dsyncing = TRUE; -+ doveadm_user_init_dsync(user); - - i_set_failure_prefix("dsync-remote(%s): ", user->username); - --- -1.7.10.2 - - -From 4abad751dcb2519e037ac351d6ed92e14211a97b Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 05:58:16 +0300 -Subject: [PATCH] lib-http: Fixed previous patch setting connection connected - only after SSL handshake. This just caused crashes. The - main point was anyway to include the SSL handshake as part - of the connect_timeout_msecs. Apparently the easiest way is - to set it immediately connected and delay removing the - timeout. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index 7282401..b966b97 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -671,7 +671,10 @@ http_client_connection_ready(struct http_client_connection *conn) - - conn->connected = TRUE; - conn->peer->last_connect_failed = FALSE; -- if (conn->to_connect != NULL) -+ -+ if (conn->to_connect != NULL && -+ (conn->ssl_iostream == NULL || -+ ssl_iostream_is_handshaked(conn->ssl_iostream))) - timeout_remove(&conn->to_connect); - - if (conn->client->set.rawlog_dir != NULL && -@@ -703,7 +706,8 @@ http_client_connection_ssl_handshaked(const char **error_r, void *context) - *error_r = error; - return -1; - } -- http_client_connection_ready(conn); -+ if (conn->to_connect != NULL) -+ timeout_remove(&conn->to_connect); - return 0; - } - -@@ -742,6 +746,8 @@ http_client_connection_ssl_init(struct http_client_connection *conn, - conn->conn.name, ssl_iostream_get_last_error(conn->ssl_iostream)); - return -1; - } -+ -+ http_client_connection_ready(conn); - return 0; - } - --- -1.7.10.2 - - -From 4bf1d4c6899c959491245f3b2f88134716fd5d41 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 06:32:58 +0300 -Subject: [PATCH] lib-http: Treat connect() timeouts as retryable errors. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index b966b97..6ef4a18 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -320,16 +320,18 @@ static void http_client_connection_destroy(struct connection *_conn) - if (conn->connected_timestamp.tv_sec == 0) { - msecs = timeval_diff_msecs(&ioloop_timeval, - &conn->connect_start_timestamp); -- http_client_peer_connection_failure(conn->peer, t_strdup_printf( -+ error = t_strdup_printf( - "connect(%s) failed: Connection timed out in %u.%03u secs", -- _conn->name, msecs/1000, msecs%1000)); -+ _conn->name, msecs/1000, msecs%1000); - } else { - msecs = timeval_diff_msecs(&ioloop_timeval, - &conn->connected_timestamp); -- http_client_peer_connection_failure(conn->peer, t_strdup_printf( -+ error = t_strdup_printf( - "SSL handshaking to %s failed: Connection timed out in %u.%03u secs", -- _conn->name, msecs/1000, msecs%1000)); -+ _conn->name, msecs/1000, msecs%1000); - } -+ http_client_connection_retry_requests(conn, -+ HTTP_CLIENT_REQUEST_ERROR_TIMED_OUT, error); - break; - case CONNECTION_DISCONNECT_CONN_CLOSED: - /* retry pending requests if possible */ --- -1.7.10.2 - - -From 1735fc06f205ab96211bef87e8452a563f04e90b Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 06:55:34 +0300 -Subject: [PATCH] imapc: Index dirs were being wrongly deleted when - imapc_list_prefix was set. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index b95df95..abf30c6 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -361,7 +361,9 @@ static void imapc_list_delete_unused_indexes(struct imapc_mailbox_list *list) - struct mailbox_list *fs_list = imapc_list_get_fs(list); - struct mailbox_list_iterate_context *iter; - const struct mailbox_info *info; -- const char *fs_name; -+ const char *imapc_list_prefix = list->storage->set->imapc_list_prefix; -+ unsigned int imapc_list_prefix_len = strlen(imapc_list_prefix); -+ const char *fs_name, *vname; - - if (fs_list == NULL) - return; -@@ -370,13 +372,33 @@ static void imapc_list_delete_unused_indexes(struct imapc_mailbox_list *list) - MAILBOX_LIST_ITER_RAW_LIST | - MAILBOX_LIST_ITER_NO_AUTO_BOXES | - MAILBOX_LIST_ITER_RETURN_NO_FLAGS); -- while ((info = mailbox_list_iter_next(iter)) != NULL) { -- if (mailbox_tree_lookup(list->mailboxes, info->vname) == NULL) { -+ while ((info = mailbox_list_iter_next(iter)) != NULL) T_BEGIN { -+ vname = info->vname; -+ if (imapc_list_prefix_len > 0) { -+ /* skip over the namespace prefix */ -+ i_assert(strncmp(vname, fs_list->ns->prefix, -+ fs_list->ns->prefix_len) == 0); -+ vname += fs_list->ns->prefix_len; -+ /* skip over the imapc list prefix */ -+ i_assert(strncmp(vname, imapc_list_prefix, -+ imapc_list_prefix_len) == 0); -+ vname += imapc_list_prefix_len; -+ if (vname[0] != '\0') { -+ i_assert(vname[0] == mail_namespace_get_sep(fs_list->ns)); -+ vname++; -+ } -+ /* put back the namespace prefix */ -+ if (fs_list->ns->prefix_len > 0) { -+ vname = t_strconcat(fs_list->ns->prefix, -+ vname, NULL); -+ } -+ } -+ if (mailbox_tree_lookup(list->mailboxes, vname) == NULL) { - fs_name = mailbox_list_get_storage_name(fs_list, - info->vname); - (void)fs_list->v.delete_mailbox(fs_list, fs_name); - } -- } -+ } T_END; - (void)mailbox_list_iter_deinit(&iter); - } - --- -1.7.10.2 - - -From c4bcfe61acf37f5176755e20dcb444d470470214 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 08:56:07 +0300 -Subject: [PATCH] lib-imap-client: If SELECT/EXAMINE fails, set the connection - as not being selected. - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index 3229885..de2177c 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -1047,6 +1047,13 @@ static int imapc_connection_input_tagged(struct imapc_connection *conn) - imapc_connection_disconnect(conn); - } - -+ if (reply.state == IMAPC_COMMAND_STATE_NO && -+ (cmd->flags & IMAPC_COMMAND_FLAG_SELECT) != 0 && -+ conn->selected_box != NULL) { -+ /* EXAMINE/SELECT failed: mailbox is no longer selected */ -+ imapc_connection_unselect(conn->selected_box); -+ } -+ - imapc_connection_input_reset(conn); - imapc_command_reply_free(cmd, &reply); - imapc_command_send_more(conn); --- -1.7.10.2 - - -From f815388c419a146412a30763e2945f860dbd2730 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 08:56:19 +0300 -Subject: [PATCH] lib-imap-client: Added support for UNSELECT capability. - - -diff --git a/src/lib-imap-client/imapc-client.c b/src/lib-imap-client/imapc-client.c -index b5592d3..b282990 100644 ---- a/src/lib-imap-client/imapc-client.c -+++ b/src/lib-imap-client/imapc-client.c -@@ -23,6 +23,7 @@ const struct imapc_capability_name imapc_capability_names[] = { - { "X-GM-EXT-1", IMAPC_CAPABILITY_X_GM_EXT_1 }, - { "CONDSTORE", IMAPC_CAPABILITY_CONDSTORE }, - { "NAMESPACE", IMAPC_CAPABILITY_NAMESPACE }, -+ { "UNSELECT", IMAPC_CAPABILITY_UNSELECT }, - - { "IMAP4REV1", IMAPC_CAPABILITY_IMAP4REV1 }, - { NULL, 0 } -diff --git a/src/lib-imap-client/imapc-client.h b/src/lib-imap-client/imapc-client.h -index 516763e..e099c93 100644 ---- a/src/lib-imap-client/imapc-client.h -+++ b/src/lib-imap-client/imapc-client.h -@@ -22,6 +22,7 @@ enum imapc_capability { - IMAPC_CAPABILITY_X_GM_EXT_1 = 0x80, - IMAPC_CAPABILITY_CONDSTORE = 0x100, - IMAPC_CAPABILITY_NAMESPACE = 0x200, -+ IMAPC_CAPABILITY_UNSELECT = 0x400, - - IMAPC_CAPABILITY_IMAP4REV1 = 0x40000000 - }; --- -1.7.10.2 - - -From 05ce3c7cdaed5bcfaa9a780489e67f91ef8497df Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 08:57:13 +0300 -Subject: [PATCH] imapc: When deleting a mailbox, unselect the current one - just in case they're the same. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index abf30c6..e04fa99 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -682,9 +682,20 @@ imapc_list_delete_mailbox(struct mailbox_list *_list, const char *name) - { - struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; - struct mailbox_list *fs_list = imapc_list_get_fs(list); -+ enum imapc_capability capa; - struct imapc_command *cmd; - struct imapc_simple_context ctx; - -+ capa = imapc_client_get_capabilities(list->storage->client); -+ -+ cmd = imapc_list_simple_context_init(&ctx, list); -+ imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_SELECT); -+ if ((capa & IMAPC_CAPABILITY_UNSELECT) != 0) -+ imapc_command_sendf(cmd, "UNSELECT"); -+ else -+ imapc_command_sendf(cmd, "SELECT \"~~~\""); -+ imapc_simple_run(&ctx); -+ - cmd = imapc_list_simple_context_init(&ctx, list); - imapc_command_sendf(cmd, "DELETE %s", name); - imapc_simple_run(&ctx); --- -1.7.10.2 - - -From 857621dc473effc032d818fb2584843a2957a81a Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 09:47:39 +0300 -Subject: [PATCH] lib-imap-client: When server sends BYE before disconnection, - log it as the reason. - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index de2177c..886e7b9 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -92,6 +92,7 @@ struct imapc_connection { - - struct imapc_client_mailbox *selecting_box, *selected_box; - enum imapc_connection_state state; -+ char *disconnect_reason; - - enum imapc_capability capabilities; - char **capabilities_list; -@@ -159,6 +160,8 @@ static void imapc_connection_unref(struct imapc_connection **_conn) - if (--conn->refcount > 0) - return; - -+ i_assert(conn->disconnect_reason == NULL); -+ - if (conn->capabilities_list != NULL) - p_strsplit_free(default_pool, conn->capabilities_list); - array_free(&conn->cmd_send_queue); -@@ -299,8 +302,13 @@ static void imapc_connection_set_state(struct imapc_connection *conn, - case IMAPC_CONNECTION_STATE_DISCONNECTED: - memset(&reply, 0, sizeof(reply)); - reply.state = IMAPC_COMMAND_STATE_DISCONNECTED; -- reply.text_without_resp = reply.text_full = -- "Disconnected from server"; -+ reply.text_full = "Disconnected from server"; -+ if (conn->disconnect_reason != NULL) { -+ reply.text_full = t_strdup_printf("%s: %s", -+ reply.text_full, conn->disconnect_reason); -+ i_free_and_null(conn->disconnect_reason); -+ } -+ reply.text_without_resp = reply.text_full; - imapc_login_callback(conn, &reply); - - conn->idling = FALSE; -@@ -899,6 +907,9 @@ static int imapc_connection_input_untagged(struct imapc_connection *conn) - value = imap_args_to_str(imap_args); - if (imapc_connection_parse_capability(conn, value) < 0) - return -1; -+ } else if (strcasecmp(name, "BYE") == 0) { -+ i_free(conn->disconnect_reason); -+ conn->disconnect_reason = i_strdup(imap_args_to_str(imap_args)); - } - - reply.name = name; -@@ -1120,7 +1131,10 @@ static void imapc_connection_input(struct imapc_connection *conn) - - if (ret < 0) { - /* disconnected */ -- if (conn->ssl_iostream == NULL) { -+ if (conn->disconnect_reason != NULL) { -+ i_error("imapc(%s): Server disconnected with message: %s", -+ conn->name, conn->disconnect_reason); -+ } else if (conn->ssl_iostream == NULL) { - i_error("imapc(%s): Server disconnected unexpectedly", - conn->name); - } else { --- -1.7.10.2 - - -From 471057eaf6ddfb261467e597f33fc7309275330a Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 10:52:14 +0300 -Subject: [PATCH] imapc: If imapc isn't the inbox=yes namespace, do the login - and initial LIST in background. - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index e04fa99..c5986bb 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -140,7 +140,7 @@ static void imapc_untagged_list(const struct imapc_untagged_reply *reply, - const struct imap_arg *args = reply->args; - const char *sep, *name; - -- if (list->sep == '\0') { -+ if (storage->root_sep == '\0') { - /* we haven't asked for the separator yet. - lets see if this is the reply for its request. */ - if (args[0].type == IMAP_ARG_EOL || -@@ -149,8 +149,8 @@ static void imapc_untagged_list(const struct imapc_untagged_reply *reply, - return; - - /* we can't handle NIL separator yet */ -- list->sep = sep == NULL ? '/' : sep[0]; -- mailbox_tree_set_separator(list->mailboxes, list->sep); -+ storage->root_sep = sep == NULL ? '/' : sep[0]; -+ mailbox_tree_set_separator(list->mailboxes, storage->root_sep); - } else { - (void)imapc_list_update_tree(list, list->mailboxes, args); - } -@@ -163,7 +163,7 @@ static void imapc_untagged_lsub(const struct imapc_untagged_reply *reply, - const struct imap_arg *args = reply->args; - struct mailbox_node *node; - -- if (list->sep == '\0') { -+ if (storage->root_sep == '\0') { - /* we haven't asked for the separator yet */ - return; - } -@@ -192,11 +192,14 @@ void imapc_list_register_callbacks(struct imapc_mailbox_list *list) - static char imapc_list_get_hierarchy_sep(struct mailbox_list *_list) - { - struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; -+ char sep; - -- /* storage should have looked this up when it was created */ -- i_assert(list->sep != '\0'); -- -- return list->sep; -+ if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) { -+ /* we can't really fail here. just return a common separator -+ and keep failing all list commands until it succeeds. */ -+ return '/'; -+ } -+ return sep; - } - - static const char * -@@ -209,7 +212,9 @@ imapc_list_get_storage_name(struct mailbox_list *_list, const char *vname) - storage_name = mailbox_list_default_get_storage_name(_list, vname); - if (*prefix != '\0' && strcasecmp(storage_name, "INBOX") != 0) { - storage_name = storage_name[0] == '\0' ? prefix : -- t_strdup_printf("%s%c%s", prefix, list->sep, storage_name); -+ t_strdup_printf("%s%c%s", prefix, -+ mailbox_list_get_hierarchy_sep(_list), -+ storage_name); - } - return storage_name; - } -@@ -230,7 +235,8 @@ imapc_list_get_vname(struct mailbox_list *_list, const char *storage_name) - if (storage_name[0] == '\0') { - /* we're looking up the prefix itself */ - } else { -- i_assert(storage_name[0] == list->sep); -+ i_assert(storage_name[0] == -+ mailbox_list_get_hierarchy_sep(_list)); - storage_name++; - } - } -@@ -408,8 +414,12 @@ static int imapc_list_refresh(struct imapc_mailbox_list *list) - struct imapc_simple_context ctx; - struct mailbox_node *node; - const char *pattern; -+ char sep; - -- i_assert(list->sep != '\0'); -+ if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) { -+ mailbox_list_set_internal_error(&list->list); -+ return -1; -+ } - - if (list->refreshed_mailboxes) - return 0; -@@ -427,7 +437,7 @@ static int imapc_list_refresh(struct imapc_mailbox_list *list) - cmd = imapc_list_simple_context_init(&ctx, list); - imapc_command_sendf(cmd, "LIST \"\" %s", pattern); - mailbox_tree_deinit(&list->mailboxes); -- list->mailboxes = mailbox_tree_init(list->sep); -+ list->mailboxes = mailbox_tree_init(sep); - mailbox_tree_set_parents_nonexistent(list->mailboxes); - imapc_simple_run(&ctx); - -@@ -505,7 +515,10 @@ imapc_list_iter_init(struct mailbox_list *_list, const char *const *patterns, - return _ctx; - } - -- sep = mailbox_list_get_hierarchy_sep(_list); -+ if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) { -+ mailbox_list_set_internal_error(_list); -+ ret = -1; -+ } - - pool = pool_alloconly_create("mailbox list imapc iter", 1024); - ctx = p_new(pool, struct imapc_mailbox_list_iterate_context, 1); -@@ -623,23 +636,25 @@ imapc_list_subscriptions_refresh(struct mailbox_list *_src_list, - struct imapc_simple_context ctx; - struct imapc_command *cmd; - const char *pattern; -- char sep; -+ char src_sep, dest_sep; - - i_assert(src_list->tmp_subscriptions == NULL); - - if (src_list->refreshed_subscriptions) { - if (dest_list->subscriptions == NULL) { -- sep = mailbox_list_get_hierarchy_sep(dest_list); -+ dest_sep = mailbox_list_get_hierarchy_sep(dest_list); - dest_list->subscriptions = -- mailbox_tree_init(sep); -+ mailbox_tree_init(dest_sep); - } - return 0; - } - -- if (src_list->sep == '\0') -- (void)mailbox_list_get_hierarchy_sep(_src_list); -+ if (imapc_storage_try_get_root_sep(src_list->storage, &src_sep) < 0) { -+ mailbox_list_set_internal_error(dest_list); -+ return -1; -+ } - -- src_list->tmp_subscriptions = mailbox_tree_init(src_list->sep); -+ src_list->tmp_subscriptions = mailbox_tree_init(src_sep); - - cmd = imapc_list_simple_context_init(&ctx, src_list); - if (*src_list->storage->set->imapc_list_prefix == '\0') -@@ -647,7 +662,7 @@ imapc_list_subscriptions_refresh(struct mailbox_list *_src_list, - else { - pattern = t_strdup_printf("%s%c*", - src_list->storage->set->imapc_list_prefix, -- src_list->sep); -+ src_sep); - } - imapc_command_sendf(cmd, "LSUB \"\" %s", pattern); - imapc_simple_run(&ctx); -@@ -763,8 +778,12 @@ int imapc_list_get_mailbox_flags(struct mailbox_list *_list, const char *name, - struct imapc_simple_context sctx; - struct mailbox_node *node; - const char *vname; -+ char sep; - -- i_assert(list->sep != '\0'); -+ if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) { -+ mailbox_list_set_internal_error(_list); -+ return -1; -+ } - - vname = mailbox_list_get_vname(_list, name); - if (!list->refreshed_mailboxes) { -diff --git a/src/lib-storage/index/imapc/imapc-list.h b/src/lib-storage/index/imapc/imapc-list.h -index a764f21..d3bc242 100644 ---- a/src/lib-storage/index/imapc/imapc-list.h -+++ b/src/lib-storage/index/imapc/imapc-list.h -@@ -13,7 +13,6 @@ struct imapc_mailbox_list { - struct mailbox_list *index_list; - - struct mailbox_tree_context *mailboxes, *tmp_subscriptions; -- char sep; - - unsigned int iter_count; - -diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c -index 0e575f1..cae2e6b 100644 ---- a/src/lib-storage/index/imapc/imapc-storage.c -+++ b/src/lib-storage/index/imapc/imapc-storage.c -@@ -180,36 +180,61 @@ static void imapc_storage_untagged_cb(const struct imapc_untagged_reply *reply, - } - } - --static int --imapc_storage_get_hierarchy_sep(struct imapc_storage *storage, -- const char **error_r) -+static void imapc_storage_sep_verify(struct imapc_storage *storage) - { -- struct imapc_command *cmd; -- struct imapc_simple_context sctx; - const char *imapc_list_prefix = storage->set->imapc_list_prefix; - -- imapc_simple_context_init(&sctx, storage); -- cmd = imapc_client_cmd(storage->client, imapc_simple_callback, &sctx); -- imapc_command_send(cmd, "LIST \"\" \"\""); -- imapc_simple_run(&sctx); -- -- if (sctx.ret < 0) { -- *error_r = t_strdup_printf("LIST failed: %s", -- mail_storage_get_last_error(&storage->storage, NULL)); -- return -1; -+ if (storage->root_sep == '\0') { -+ mail_storage_set_critical(&storage->storage, -+ "imapc: LIST didn't return hierarchy separator"); -+ } else if (imapc_list_prefix[0] != '\0' && -+ imapc_list_prefix[strlen(imapc_list_prefix)-1] == storage->root_sep) { -+ mail_storage_set_critical(&storage->storage, -+ "imapc_list_prefix must not end with hierarchy separator"); - } -+} - -- if (storage->list->sep == '\0') { -- *error_r = "LIST didn't return hierarchy separator"; -- return -1; -+static void imapc_storage_sep_callback(const struct imapc_command_reply *reply, -+ void *context) -+{ -+ struct imapc_storage *storage = context; -+ -+ storage->root_sep_pending = FALSE; -+ if (reply->state == IMAPC_COMMAND_STATE_OK) -+ imapc_storage_sep_verify(storage); -+ else if (reply->state == IMAPC_COMMAND_STATE_NO) -+ imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply); -+ else { -+ mail_storage_set_critical(&storage->storage, -+ "imapc: Command failed: %s", reply->text_full); - } -+ imapc_client_stop(storage->client); -+} - -- if (imapc_list_prefix[0] != '\0' && -- imapc_list_prefix[strlen(imapc_list_prefix)-1] == storage->list->sep) { -- *error_r = "imapc_list_prefix must not end with hierarchy separator"; -- return -1; -+static void imapc_storage_send_hierarcy_sep_lookup(struct imapc_storage *storage) -+{ -+ struct imapc_command *cmd; -+ -+ if (storage->root_sep_pending) -+ return; -+ storage->root_sep_pending = TRUE; -+ -+ cmd = imapc_client_cmd(storage->client, -+ imapc_storage_sep_callback, storage); -+ imapc_command_send(cmd, "LIST \"\" \"\""); -+} -+ -+int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r) -+{ -+ if (storage->root_sep == '\0') { -+ imapc_storage_send_hierarcy_sep_lookup(storage); -+ while (storage->root_sep_pending) -+ imapc_client_run(storage->client); -+ if (storage->root_sep == '\0') -+ return -1; - } -- return sctx.ret; -+ *sep_r = storage->root_sep; -+ return 0; - } - - static int -@@ -220,6 +245,7 @@ imapc_storage_create(struct mail_storage *_storage, - struct imapc_storage *storage = (struct imapc_storage *)_storage; - struct imapc_client_settings set; - string_t *str; -+ char sep; - - storage->set = mail_storage_get_driver_settings(_storage); - -@@ -279,10 +305,19 @@ imapc_storage_create(struct mail_storage *_storage, - imapc_untagged_status); - imapc_storage_register_untagged(storage, "NAMESPACE", - imapc_untagged_namespace); -- /* connect to imap server and get the hierarchy separator. */ -- if (imapc_storage_get_hierarchy_sep(storage, error_r) < 0) { -- imapc_client_deinit(&storage->client); -- return -1; -+ /* start connecting to imap server and get the hierarchy separator. */ -+ imapc_client_login(storage->client, NULL, NULL); -+ imapc_storage_send_hierarcy_sep_lookup(storage); -+ if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { -+ /* we're using imapc for the INBOX namespace. wait and make -+ sure we can successfully access the IMAP server (so if the -+ username is invalid we don't just keep failing every -+ command). */ -+ if (imapc_storage_try_get_root_sep(storage, &sep) < 0) { -+ imapc_client_deinit(&storage->client); -+ *error_r = "Failed to access imapc backend"; -+ return -1; -+ } - } - return 0; - } -@@ -302,10 +337,7 @@ static void imapc_storage_add_list(struct mail_storage *_storage, - struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; - - i_assert(storage->list != NULL); -- i_assert(storage->list->sep != '\0'); -- - list->storage = storage; -- list->sep = storage->list->sep; - } - - void imapc_storage_register_untagged(struct imapc_storage *storage, -diff --git a/src/lib-storage/index/imapc/imapc-storage.h b/src/lib-storage/index/imapc/imapc-storage.h -index 941d7dc..77485cf 100644 ---- a/src/lib-storage/index/imapc/imapc-storage.h -+++ b/src/lib-storage/index/imapc/imapc-storage.h -@@ -47,6 +47,7 @@ struct imapc_storage { - struct ioloop *root_ioloop; - struct imapc_mailbox_list *list; - struct imapc_client *client; -+ char root_sep; - - struct imapc_mailbox *cur_status_box; - struct mailbox_status *cur_status; -@@ -56,6 +57,7 @@ struct imapc_storage { - ARRAY(struct imapc_storage_event_callback) untagged_callbacks; - - unsigned int namespaces_requested:1; -+ unsigned int root_sep_pending:1; - }; - - struct imapc_mail_cache { -@@ -128,6 +130,7 @@ void imapc_transaction_save_rollback(struct mail_save_context *ctx); - void imapc_storage_run(struct imapc_storage *storage); - void imapc_mail_cache_free(struct imapc_mail_cache *cache); - int imapc_mailbox_select(struct imapc_mailbox *mbox); -+int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r); - - void imapc_copy_error_from_reply(struct imapc_storage *storage, - enum mail_error default_error, --- -1.7.10.2 - - -From 8d951ad71dfd0f020936af0233e28102133dd2a3 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 10:55:27 +0300 -Subject: [PATCH] imapc: Minor code cleanup - - -diff --git a/src/lib-storage/index/imapc/imapc-list.c b/src/lib-storage/index/imapc/imapc-list.c -index c5986bb..4835040 100644 ---- a/src/lib-storage/index/imapc/imapc-list.c -+++ b/src/lib-storage/index/imapc/imapc-list.c -@@ -29,7 +29,6 @@ static struct { - { "\\NonExistent", MAILBOX_NONEXISTENT }, - { "\\NoInferiors", MAILBOX_NOINFERIORS }, - { "\\Subscribed", MAILBOX_SUBSCRIBED }, -- { "\\Subscribed", MAILBOX_SUBSCRIBED }, - { "\\All", MAILBOX_SPECIALUSE_ALL }, - { "\\Archive", MAILBOX_SPECIALUSE_ARCHIVE }, - { "\\Drafts", MAILBOX_SPECIALUSE_DRAFTS }, --- -1.7.10.2 - - -From 0fe9d6d52f2c3908776a992540722a8acecee10a Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 11:16:05 +0300 -Subject: [PATCH] lib-storage: Renamed mailbox_list_get_closest_storage() to - ..._get_default_storage() This function wasn't previously - used by anyone. - - -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index 4db5433..a4b06b1 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -781,7 +781,7 @@ int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, - } - } - --void mailbox_list_get_closest_storage(struct mailbox_list *list, -+void mailbox_list_get_default_storage(struct mailbox_list *list, - struct mail_storage **storage) - { - *storage = list->ns->storage; -diff --git a/src/lib-storage/mailbox-list.h b/src/lib-storage/mailbox-list.h -index fb4096f..f3f4d94 100644 ---- a/src/lib-storage/mailbox-list.h -+++ b/src/lib-storage/mailbox-list.h -@@ -171,7 +171,7 @@ struct mail_user * - mailbox_list_get_user(const struct mailbox_list *list) ATTR_PURE; - int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, - struct mail_storage **storage_r); --void mailbox_list_get_closest_storage(struct mailbox_list *list, -+void mailbox_list_get_default_storage(struct mailbox_list *list, - struct mail_storage **storage); - char mailbox_list_get_hierarchy_sep(struct mailbox_list *list); - --- -1.7.10.2 - - -From 93b0ff02b0e5630a9b2db365f5335b36d93477f9 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 11:40:27 +0300 -Subject: [PATCH] Avoid using mail_namespace.storage directly. - - -diff --git a/src/doveadm/doveadm-mail-altmove.c b/src/doveadm/doveadm-mail-altmove.c -index a7d9843..5e1b864 100644 ---- a/src/doveadm/doveadm-mail-altmove.c -+++ b/src/doveadm/doveadm-mail-altmove.c -@@ -40,12 +40,13 @@ cmd_altmove_box(struct doveadm_mail_cmd_context *ctx, - } - - static int --ns_purge(struct doveadm_mail_cmd_context *ctx, struct mail_namespace *ns) -+ns_purge(struct doveadm_mail_cmd_context *ctx, struct mail_namespace *ns, -+ struct mail_storage *storage) - { -- if (mail_storage_purge(ns->storage) < 0) { -+ if (mail_storage_purge(storage) < 0) { - i_error("Purging namespace '%s' failed: %s", ns->prefix, -- mail_storage_get_last_error(ns->storage, NULL)); -- doveadm_mail_failed_storage(ctx, ns->storage); -+ mail_storage_get_last_error(storage, NULL)); -+ doveadm_mail_failed_storage(ctx, storage); - return -1; - } - return 0; -@@ -62,7 +63,7 @@ cmd_altmove_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - const struct mailbox_info *info; - struct mail_namespace *ns, *prev_ns = NULL; - ARRAY(struct mail_storage *) purged_storages; -- struct mail_storage *const *storages; -+ struct mail_storage *const *storages, *ns_storage, *prev_storage = NULL; - unsigned int i, count; - int ret = 0; - -@@ -70,13 +71,15 @@ cmd_altmove_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - iter = doveadm_mailbox_list_iter_init(_ctx, user, _ctx->search_args, - iter_flags); - while ((info = doveadm_mailbox_list_iter_next(iter)) != NULL) T_BEGIN { -- if (info->ns != prev_ns) { -- if (prev_ns != NULL) { -- if (ns_purge(_ctx, prev_ns) < 0) -+ ns_storage = mail_namespace_get_default_storage(info->ns); -+ if (ns_storage != prev_storage) { -+ if (prev_storage != NULL) { -+ if (ns_purge(_ctx, prev_ns, prev_storage) < 0) - ret = -1; - array_append(&purged_storages, -- &prev_ns->storage, 1); -+ &prev_storage, 1); - } -+ prev_storage = ns_storage; - prev_ns = info->ns; - } - if (cmd_altmove_box(_ctx, info, _ctx->search_args, ctx->reverse) < 0) -@@ -85,10 +88,10 @@ cmd_altmove_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - if (doveadm_mailbox_list_iter_deinit(&iter) < 0) - ret = -1; - -- if (prev_ns != NULL) { -- if (ns_purge(_ctx, prev_ns) < 0) -+ if (prev_storage != NULL) { -+ if (ns_purge(_ctx, prev_ns, prev_storage) < 0) - ret = -1; -- array_append(&purged_storages, &prev_ns->storage, 1); -+ array_append(&purged_storages, &prev_storage, 1); - } - - /* make sure all private storages have been purged */ -@@ -97,14 +100,15 @@ cmd_altmove_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user) - if (ns->type != MAIL_NAMESPACE_TYPE_PRIVATE) - continue; - -+ ns_storage = mail_namespace_get_default_storage(ns); - for (i = 0; i < count; i++) { -- if (ns->storage == storages[i]) -+ if (ns_storage == storages[i]) - break; - } - if (i == count) { -- if (ns_purge(_ctx, ns) < 0) -+ if (ns_purge(_ctx, ns, ns_storage) < 0) - ret = -1; -- array_append(&purged_storages, &ns->storage, 1); -+ array_append(&purged_storages, &ns_storage, 1); - storages = array_get(&purged_storages, &count); - } - } -diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c -index 695885b..d035893 100644 ---- a/src/doveadm/doveadm-mail.c -+++ b/src/doveadm/doveadm-mail.c -@@ -107,6 +107,7 @@ static int - cmd_purge_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user) - { - struct mail_namespace *ns; -+ struct mail_storage *storage; - int ret = 0; - - for (ns = user->namespaces; ns != NULL; ns = ns->next) { -@@ -114,10 +115,11 @@ cmd_purge_run(struct doveadm_mail_cmd_context *ctx, struct mail_user *user) - ns->alias_for != NULL) - continue; - -- if (mail_storage_purge(ns->storage) < 0) { -+ storage = mail_namespace_get_default_storage(ns); -+ if (mail_storage_purge(storage) < 0) { - i_error("Purging namespace '%s' failed: %s", ns->prefix, -- mail_storage_get_last_error(ns->storage, NULL)); -- doveadm_mail_failed_storage(ctx, ns->storage); -+ mail_storage_get_last_error(storage, NULL)); -+ doveadm_mail_failed_storage(ctx, storage); - ret = -1; - } - } -diff --git a/src/lib-storage/index/shared/shared-list.c b/src/lib-storage/index/shared/shared-list.c -index d7806fa..a218d78 100644 ---- a/src/lib-storage/index/shared/shared-list.c -+++ b/src/lib-storage/index/shared/shared-list.c -@@ -51,8 +51,7 @@ shared_get_storage(struct mailbox_list **list, const char *vname, - return -1; - } - *list = ns->list; -- *storage_r = ns->storage; -- return 0; -+ return mailbox_list_get_storage(list, vname, storage_r); - } - - static char shared_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED) -@@ -66,7 +65,8 @@ shared_list_get_path(struct mailbox_list *list, const char *name, - { - struct mail_namespace *ns = list->ns; - -- if (list->ns->storage == NULL || name == NULL || -+ if (mail_namespace_get_default_storage(list->ns) == NULL || -+ name == NULL || - shared_storage_get_namespace(&ns, &name) < 0) { - /* we don't have a directory we can use. */ - *path_r = NULL; -diff --git a/src/lib-storage/index/shared/shared-storage.c b/src/lib-storage/index/shared/shared-storage.c -index e17d912..a6a76f3 100644 ---- a/src/lib-storage/index/shared/shared-storage.c -+++ b/src/lib-storage/index/shared/shared-storage.c -@@ -346,7 +346,8 @@ int shared_storage_get_namespace(struct mail_namespace **_ns, - *_ns = new_ns; - if (_storage->class_flags == 0) { - /* flags are unset if we were using "auto" storage */ -- _storage->class_flags = new_ns->storage->class_flags; -+ _storage->class_flags = -+ mail_namespace_get_default_storage(new_ns)->class_flags; - } - - mail_user_add_namespace(user, &new_ns); -diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c -index 9ecbd47..f52b353 100644 ---- a/src/lib-storage/mail-storage.c -+++ b/src/lib-storage/mail-storage.c -@@ -655,8 +655,8 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname, - } - - if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) { -- /* just use the first storage. FIXME: does this break? */ -- storage = list->ns->storage; -+ /* just use the default storage. FIXME: does this break? */ -+ storage = mail_namespace_get_default_storage(list->ns); - } - - T_BEGIN { -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index a4b06b1..29e878d 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -776,7 +776,7 @@ int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, - if ((*list)->v.get_storage != NULL) - return (*list)->v.get_storage(list, vname, storage_r); - else { -- *storage_r = (*list)->ns->storage; -+ *storage_r = mail_namespace_get_default_storage((*list)->ns); - return 0; - } - } -@@ -784,7 +784,7 @@ int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, - void mailbox_list_get_default_storage(struct mailbox_list *list, - struct mail_storage **storage) - { -- *storage = list->ns->storage; -+ *storage = mail_namespace_get_default_storage(list->ns); - } - - char mailbox_list_get_hierarchy_sep(struct mailbox_list *list) -diff --git a/src/plugins/acl/acl-backend-vfile.c b/src/plugins/acl/acl-backend-vfile.c -index ce8f2ae..54426d8 100644 ---- a/src/plugins/acl/acl-backend-vfile.c -+++ b/src/plugins/acl/acl-backend-vfile.c -@@ -127,35 +127,43 @@ static void acl_backend_vfile_deinit(struct acl_backend *_backend) - } - - static const char * --acl_backend_vfile_get_local_dir(struct acl_backend *backend, const char *name) -+acl_backend_vfile_get_local_dir(struct acl_backend *backend, -+ const char *name) - { - struct mail_namespace *ns = mailbox_list_get_namespace(backend->list); -+ struct mailbox_list *list = ns->list; -+ struct mail_storage *storage; - enum mailbox_list_path_type type; -- const char *dir, *inbox, *error; -+ const char *dir, *inbox, *vname, *error; - - if (*name == '\0') - name = NULL; -- else if (!mailbox_list_is_valid_name(ns->list, name, &error)) -+ else if (!mailbox_list_is_valid_name(list, name, &error)) - return NULL; - - /* ACL files are very important. try to keep them among the main - mail files. that's not possible though with a) if the mailbox is - a file or b) if the mailbox path doesn't point to filesystem. */ -- type = mail_storage_is_mailbox_file(ns->storage) || -- (ns->storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0 ? -+ vname = mailbox_list_get_vname(backend->list, name); -+ if (mailbox_list_get_storage(&list, vname, &storage) < 0) -+ return NULL; -+ i_assert(list == ns->list); -+ -+ type = mail_storage_is_mailbox_file(storage) || -+ (storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NO_ROOT) != 0 ? - MAILBOX_LIST_PATH_TYPE_CONTROL : MAILBOX_LIST_PATH_TYPE_MAILBOX; - if (name == NULL) { -- if (!mailbox_list_get_root_path(ns->list, type, &dir)) -+ if (!mailbox_list_get_root_path(list, type, &dir)) - return FALSE; - } else { -- if (mailbox_list_get_path(ns->list, name, type, &dir) <= 0) -+ if (mailbox_list_get_path(list, name, type, &dir) <= 0) - return NULL; - } - - /* verify that the directory isn't same as INBOX's directory. - this is mainly for Maildir. */ - if (name == NULL && -- mailbox_list_get_path(ns->list, "INBOX", -+ mailbox_list_get_path(list, "INBOX", - MAILBOX_LIST_PATH_TYPE_MAILBOX, &inbox) > 0 && - strcmp(inbox, dir) == 0) { - /* can't have default ACLs with this setup */ -@@ -177,15 +185,17 @@ acl_backend_vfile_object_init(struct acl_backend *_backend, - aclobj->aclobj.backend = _backend; - aclobj->aclobj.name = i_strdup(name); - -- if (backend->global_dir != NULL) T_BEGIN { -- vname = mailbox_list_get_vname(backend->backend.list, name); -- aclobj->global_path = i_strconcat(backend->global_dir, "/", -- vname, NULL); -- } T_END; -+ T_BEGIN { -+ if (backend->global_dir != NULL) { -+ vname = mailbox_list_get_vname(backend->backend.list, name); -+ aclobj->global_path = -+ i_strconcat(backend->global_dir, "/", vname, NULL); -+ } - -- dir = acl_backend_vfile_get_local_dir(_backend, name); -- aclobj->local_path = dir == NULL ? NULL : -- i_strconcat(dir, "/"ACL_FILENAME, NULL); -+ dir = acl_backend_vfile_get_local_dir(_backend, name); -+ aclobj->local_path = dir == NULL ? NULL : -+ i_strconcat(dir, "/"ACL_FILENAME, NULL); -+ } T_END; - return &aclobj->aclobj; - } - -diff --git a/src/plugins/acl/acl-shared-storage.c b/src/plugins/acl/acl-shared-storage.c -index 30c5493..a673718 100644 ---- a/src/plugins/acl/acl-shared-storage.c -+++ b/src/plugins/acl/acl-shared-storage.c -@@ -84,7 +84,7 @@ int acl_shared_namespaces_add(struct mail_namespace *ns) - { - struct acl_user *auser = ACL_USER_CONTEXT(ns->user); - struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(ns->list); -- struct mail_storage *storage = ns->storage; -+ struct mail_storage *storage = mail_namespace_get_default_storage(ns); - struct acl_lookup_dict_iter *iter; - const char *name; - --- -1.7.10.2 - - -From a77951a4de706526ac75a3adb72375ee48912cb0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 12:20:54 +0300 -Subject: [PATCH] lib-imap-client: Don't start another DNS lookup if there's - already one ongoing. - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index 886e7b9..b5e769b 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -1374,7 +1374,7 @@ void imapc_connection_connect(struct imapc_connection *conn, - unsigned int ips_count; - int ret; - -- if (conn->fd != -1) { -+ if (conn->fd != -1 || conn->dns_lookup != NULL) { - i_assert(login_callback == NULL); - return; - } --- -1.7.10.2 - - -From 5143e4b2b372d092b3c523b1aaa681292ef123c0 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 12:21:14 +0300 -Subject: [PATCH] lib-imap-client: Make sure DNS lookups get aborted at - disconnect. - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index b5e769b..22722a6 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -352,7 +352,7 @@ void imapc_connection_disconnect(struct imapc_connection *conn) - bool reconnecting = conn->selected_box != NULL && - conn->selected_box->reconnecting; - -- if (conn->fd == -1) -+ if (conn->state == IMAPC_CONNECTION_STATE_DISCONNECTED) - return; - - if (conn->client->set.debug) -@@ -366,14 +366,18 @@ void imapc_connection_disconnect(struct imapc_connection *conn) - timeout_remove(&conn->to); - if (conn->to_output != NULL) - timeout_remove(&conn->to_output); -- imap_parser_unref(&conn->parser); -- io_remove(&conn->io); -+ if (conn->parser != NULL) -+ imap_parser_unref(&conn->parser); -+ if (conn->io != NULL) -+ io_remove(&conn->io); - if (conn->ssl_iostream != NULL) - ssl_iostream_unref(&conn->ssl_iostream); -- i_stream_destroy(&conn->input); -- o_stream_destroy(&conn->output); -- net_disconnect(conn->fd); -- conn->fd = -1; -+ if (conn->fd != -1) { -+ i_stream_destroy(&conn->input); -+ o_stream_destroy(&conn->output); -+ net_disconnect(conn->fd); -+ conn->fd = -1; -+ } - - imapc_connection_set_state(conn, IMAPC_CONNECTION_STATE_DISCONNECTED); - imapc_connection_abort_commands(conn, NULL, reconnecting); --- -1.7.10.2 - - -From 36c347995167a72bc095b8cccc7ccc0f2d1759e5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 12:24:27 +0300 -Subject: [PATCH] lib-imap-client: When switching ioloops, do it also for the - DNS lookup. - - -diff --git a/src/lib-imap-client/imapc-connection.c b/src/lib-imap-client/imapc-connection.c -index 22722a6..0276730 100644 ---- a/src/lib-imap-client/imapc-connection.c -+++ b/src/lib-imap-client/imapc-connection.c -@@ -187,6 +187,8 @@ void imapc_connection_ioloop_changed(struct imapc_connection *conn) - conn->to = io_loop_move_timeout(&conn->to); - if (conn->output != NULL) - o_stream_switch_ioloop(conn->output); -+ if (conn->dns_lookup != NULL) -+ dns_lookup_switch_ioloop(conn->dns_lookup); - - if (conn->client->ioloop == NULL && conn->to_output != NULL) { - /* we're only once moving the to_output to the main ioloop, --- -1.7.10.2 - - -From 1a3032205435548259c5265d8f1637a256fe7464 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 12:36:30 +0300 -Subject: [PATCH] var_expand*(): Fixed %N to work the same with little and big - endian CPUs. Also use 64bit integer to do the MOD from, - which should give somewhat better value distribution than - with 32bit. - - -diff --git a/src/lib/var-expand.c b/src/lib/var-expand.c -index 0e8ec6a..4eab9b6 100644 ---- a/src/lib/var-expand.c -+++ b/src/lib/var-expand.c -@@ -92,17 +92,21 @@ m_str_newhash(const char *str, struct var_expand_context *ctx) - { - string_t *hash = t_str_new(20); - unsigned char result[MD5_RESULTLEN]; -- unsigned int value; -+ unsigned int i; -+ uint64_t value; - - md5_get_digest(str, strlen(str), result); -- memcpy(&value, result, sizeof(value)); -+ for (i = 0; i < sizeof(value); i++) { -+ value <<= 8; -+ value |= result[i]; -+ } - - if (ctx->width != 0) { - value %= ctx->width; - ctx->width = 0; - } - -- str_printfa(hash, "%x", value); -+ str_printfa(hash, "%x", (unsigned int)value); - while ((int)str_len(hash) < ctx->offset) - str_insert(hash, 0, "0"); - ctx->offset = 0; --- -1.7.10.2 - - -From fa2b25d00a014d334c534646abe812c3f711f4b1 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 12:42:34 +0300 -Subject: [PATCH] var_expand*(): Added small unit tests for %H and %N - - -diff --git a/src/lib/test-var-expand.c b/src/lib/test-var-expand.c -index 4ff14c8..a00be13 100644 ---- a/src/lib/test-var-expand.c -+++ b/src/lib/test-var-expand.c -@@ -21,9 +21,15 @@ static void test_var_expand_builtin(void) - static struct var_expand_test tests[] = { - { "%{hostname}", NULL }, - { "%{pid}", NULL }, -- { "a%{env:FOO}b", "abaRb" } -+ { "a%{env:FOO}b", "abaRb" }, -+ { "%50Hv", "1f" }, -+ { "%50Hw", "2e" }, -+ { "%50Nv", "25" }, -+ { "%50Nw", "e" } - }; - static struct var_expand_table table[] = { -+ { 'v', "value", NULL }, -+ { 'w', "value2", NULL }, - { '\0', NULL, NULL } - }; - string_t *str = t_str_new(128); --- -1.7.10.2 - - -From 184696cc389fcf644e67bfe5ceb9a56e6abe0d0b Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Thu, 6 Jun 2013 16:43:01 +0300 -Subject: [PATCH] var_expand(): Fixed initializing variable to %N - - -diff --git a/src/lib/var-expand.c b/src/lib/var-expand.c -index 4eab9b6..e8ad5e8 100644 ---- a/src/lib/var-expand.c -+++ b/src/lib/var-expand.c -@@ -93,7 +93,7 @@ m_str_newhash(const char *str, struct var_expand_context *ctx) - string_t *hash = t_str_new(20); - unsigned char result[MD5_RESULTLEN]; - unsigned int i; -- uint64_t value; -+ uint64_t value = 0; - - md5_get_digest(str, strlen(str), result); - for (i = 0; i < sizeof(value); i++) { --- -1.7.10.2 - - -From e2744cc02dbcd3b2e8c9d6510942c33afc4b5cfe Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 7 Jun 2013 20:12:15 +0300 -Subject: [PATCH] imap-login: If PLAIN mechanism is disabled, advertise - LOGINDISABLED always. - - -diff --git a/src/imap-login/client.c b/src/imap-login/client.c -index c5d7097..e9e291c 100644 ---- a/src/imap-login/client.c -+++ b/src/imap-login/client.c -@@ -48,6 +48,22 @@ bool client_skip_line(struct imap_client *client) - return FALSE; - } - -+static bool is_login_cmd_disabled(struct client *client) -+{ -+ if (client->secured) { -+ if (auth_client_find_mech(auth_client, "PLAIN") == NULL) { -+ /* no PLAIN authentication, can't use LOGIN command */ -+ return TRUE; -+ } -+ return FALSE; -+ } -+ if (client->set->disable_plaintext_auth) -+ return TRUE; -+ if (strcmp(client->ssl_set->ssl, "required") == 0) -+ return TRUE; -+ return FALSE; -+} -+ - static const char *get_capability(struct client *client) - { - struct imap_client *imap_client = (struct imap_client *)client; -@@ -65,8 +81,7 @@ static const char *get_capability(struct client *client) - - if (client_is_tls_enabled(client) && !client->tls) - str_append(cap_str, " STARTTLS"); -- if (!client->secured & (client->set->disable_plaintext_auth || -- strcmp(client->ssl_set->ssl, "required") == 0)) -+ if (is_login_cmd_disabled(client)) - str_append(cap_str, " LOGINDISABLED"); - - client_authenticate_get_capabilities(client, cap_str); --- -1.7.10.2 - - -From cd94da865b183b3a191fcd0dc9c3dd9142847eb5 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Fri, 7 Jun 2013 22:06:24 +0300 -Subject: [PATCH] auth: Don't crash in non-plaintext auth if master user login - is tried without master passdbs. - - -diff --git a/src/auth/auth-request.c b/src/auth/auth-request.c -index 09e21de..1f6abb6 100644 ---- a/src/auth/auth-request.c -+++ b/src/auth/auth-request.c -@@ -836,7 +836,7 @@ void auth_request_lookup_credentials(struct auth_request *request, - const char *scheme, - lookup_credentials_callback_t *callback) - { -- struct passdb_module *passdb = request->passdb->passdb; -+ struct passdb_module *passdb; - const char *cache_key, *cache_cred, *cache_scheme; - enum passdb_result result; - -@@ -846,6 +846,7 @@ void auth_request_lookup_credentials(struct auth_request *request, - callback(PASSDB_RESULT_USER_UNKNOWN, NULL, 0, request); - return; - } -+ passdb = request->passdb->passdb; - - request->credentials_scheme = p_strdup(request->pool, scheme); - request->private_callback.lookup_credentials = callback; --- -1.7.10.2 - - -From b8db8a3814a77beb88c2949b6bf0eef24b7614c4 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 00:06:42 +0300 -Subject: [PATCH] auth: If worker request has been queued for 60 secs, abort - it. - - -diff --git a/src/auth/auth-worker-server.c b/src/auth/auth-worker-server.c -index 00be552..9ff3827 100644 ---- a/src/auth/auth-worker-server.c -+++ b/src/auth/auth-worker-server.c -@@ -19,6 +19,7 @@ - - #define AUTH_WORKER_LOOKUP_TIMEOUT_SECS 60 - #define AUTH_WORKER_MAX_IDLE_SECS (60*5) -+#define AUTH_WORKER_ABORT_SECS 60 - #define AUTH_WORKER_DELAY_WARN_SECS 3 - #define AUTH_WORKER_DELAY_WARN_MIN_INTERVAL_SECS 300 - -@@ -76,20 +77,29 @@ static void auth_worker_call_timeout(struct auth_worker_connection *conn) - auth_worker_destroy(&conn, "Lookup timed out", TRUE); - } - --static void auth_worker_request_send(struct auth_worker_connection *conn, -+static bool auth_worker_request_send(struct auth_worker_connection *conn, - struct auth_worker_request *request) - { - struct const_iovec iov[3]; -- -- if (ioloop_time - request->created > AUTH_WORKER_DELAY_WARN_SECS && -+ unsigned int age_secs = ioloop_time - request->created; -+ -+ if (age_secs >= AUTH_WORKER_ABORT_SECS) { -+ i_error("Aborting auth request that was queued for %d secs, " -+ "%d left in queue", -+ age_secs, aqueue_count(worker_request_queue)); -+ request->callback(t_strdup_printf( -+ "FAIL\t%d", PASSDB_RESULT_INTERNAL_FAILURE), -+ request->context); -+ return FALSE; -+ } -+ if (age_secs >= AUTH_WORKER_DELAY_WARN_SECS && - ioloop_time - auth_worker_last_warn > - AUTH_WORKER_DELAY_WARN_MIN_INTERVAL_SECS) { - auth_worker_last_warn = ioloop_time; - i_warning("auth workers: Auth request was queued for %d " - "seconds, %d left in queue " - "(see auth_worker_max_count)", -- (int)(ioloop_time - request->created), -- aqueue_count(worker_request_queue)); -+ age_secs, aqueue_count(worker_request_queue)); - } - - request->id = ++conn->id_counter; -@@ -110,20 +120,22 @@ static void auth_worker_request_send(struct auth_worker_connection *conn, - conn->to = timeout_add(AUTH_WORKER_LOOKUP_TIMEOUT_SECS * 1000, - auth_worker_call_timeout, conn); - idle_count--; -+ return TRUE; - } - - static void auth_worker_request_send_next(struct auth_worker_connection *conn) - { - struct auth_worker_request *request, *const *requestp; - -- if (aqueue_count(worker_request_queue) == 0) -- return; -+ do { -+ if (aqueue_count(worker_request_queue) == 0) -+ return; - -- requestp = array_idx(&worker_request_array, -- aqueue_idx(worker_request_queue, 0)); -- request = *requestp; -- aqueue_delete_tail(worker_request_queue); -- auth_worker_request_send(conn, request); -+ requestp = array_idx(&worker_request_array, -+ aqueue_idx(worker_request_queue, 0)); -+ request = *requestp; -+ aqueue_delete_tail(worker_request_queue); -+ } while (!auth_worker_request_send(conn, request)); - } - - static void auth_worker_send_handshake(struct auth_worker_connection *conn) -@@ -410,9 +422,10 @@ auth_worker_call(pool_t pool, const char *data, - conn = auth_worker_create(); - } - } -- if (conn != NULL) -- auth_worker_request_send(conn, request); -- else { -+ if (conn != NULL) { -+ if (!auth_worker_request_send(conn, request)) -+ i_unreached(); -+ } else { - /* reached the limit, queue the request */ - aqueue_append(worker_request_queue, &request); - } --- -1.7.10.2 - - -From b2e1165a3fdd0e4f3aaf43088dd3c96a1bbbc5dc Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 00:42:36 +0300 -Subject: [PATCH] imapc: imapc_storage no longer requires imapc_mailbox_list. - - -diff --git a/src/lib-storage/index/imapc/imapc-storage.c b/src/lib-storage/index/imapc/imapc-storage.c -index cae2e6b..a3e30fa 100644 ---- a/src/lib-storage/index/imapc/imapc-storage.c -+++ b/src/lib-storage/index/imapc/imapc-storage.c -@@ -226,6 +226,8 @@ static void imapc_storage_send_hierarcy_sep_lookup(struct imapc_storage *storage - - int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r) - { -+ i_assert(storage->list != NULL); -+ - if (storage->root_sep == '\0') { - imapc_storage_send_hierarcy_sep_lookup(storage); - while (storage->root_sep_pending) -@@ -292,23 +294,28 @@ imapc_storage_create(struct mail_storage *_storage, - set.ssl_mode = IMAPC_CLIENT_SSL_MODE_NONE; - set.ssl_crypto_device = _storage->set->ssl_crypto_device; - -- storage->list = (struct imapc_mailbox_list *)ns->list; -- storage->list->storage = storage; - storage->client = imapc_client_init(&set); - - p_array_init(&storage->remote_namespaces, _storage->pool, 4); - p_array_init(&storage->untagged_callbacks, _storage->pool, 16); -+ if (strcmp(ns->list->name, MAILBOX_LIST_NAME_IMAPC) == 0) { -+ storage->list = (struct imapc_mailbox_list *)ns->list; -+ storage->list->storage = storage; -+ imapc_list_register_callbacks(storage->list); -+ } -+ - imapc_client_register_untagged(storage->client, - imapc_storage_untagged_cb, storage); -- imapc_list_register_callbacks(storage->list); - imapc_storage_register_untagged(storage, "STATUS", - imapc_untagged_status); - imapc_storage_register_untagged(storage, "NAMESPACE", - imapc_untagged_namespace); - /* start connecting to imap server and get the hierarchy separator. */ - imapc_client_login(storage->client, NULL, NULL); -- imapc_storage_send_hierarcy_sep_lookup(storage); -- if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { -+ if (storage->list != NULL) -+ imapc_storage_send_hierarcy_sep_lookup(storage); -+ if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 && -+ storage->list != NULL) { - /* we're using imapc for the INBOX namespace. wait and make - sure we can successfully access the IMAP server (so if the - username is invalid we don't just keep failing every -@@ -336,8 +343,10 @@ static void imapc_storage_add_list(struct mail_storage *_storage, - struct imapc_storage *storage = (struct imapc_storage *)_storage; - struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list; - -- i_assert(storage->list != NULL); -- list->storage = storage; -+ if (strcmp(_list->name, MAILBOX_LIST_NAME_IMAPC) == 0) { -+ i_assert(storage->list != NULL); -+ list->storage = storage; -+ } - } - - void imapc_storage_register_untagged(struct imapc_storage *storage, --- -1.7.10.2 - - -From 188b96af3c02004afc063a37868cf6ce90043043 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 00:46:06 +0300 -Subject: [PATCH] lib-storage: Added support for multiple storages per - namespace. - - -diff --git a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -index 96542f4..bc1c1ff 100644 ---- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -+++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c -@@ -541,7 +541,11 @@ rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx, - - box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY | - MAILBOX_FLAG_IGNORE_ACLS); -- i_assert(box->storage == &ctx->storage->storage.storage); -+ if (box->storage != &ctx->storage->storage.storage) { -+ /* the namespace has multiple storages. */ -+ mailbox_free(&box); -+ return 0; -+ } - if (mailbox_open(box) < 0) { - error = mailbox_get_last_mail_error(box); - i_error("Couldn't open mailbox '%s': %s", -diff --git a/src/lib-storage/mail-namespace.c b/src/lib-storage/mail-namespace.c -index 2383a93..a6ede7a 100644 ---- a/src/lib-storage/mail-namespace.c -+++ b/src/lib-storage/mail-namespace.c -@@ -34,9 +34,9 @@ static struct mail_namespace_settings prefixless_ns_set; - void mail_namespace_add_storage(struct mail_namespace *ns, - struct mail_storage *storage) - { -- /* currently we support only a single storage */ -- i_assert(ns->storage == NULL); -- ns->storage = storage; -+ if (ns->storage == NULL) -+ ns->storage = storage; -+ array_append(&ns->all_storages, &storage, 1); - - if (storage->v.add_list != NULL) - storage->v.add_list(storage, ns->list); -@@ -52,8 +52,11 @@ void mail_namespace_finish_list_init(struct mail_namespace *ns, - - static void mail_namespace_free(struct mail_namespace *ns) - { -- if (ns->storage != NULL) -- mail_storage_unref(&ns->storage); -+ struct mail_storage **storagep; -+ -+ array_foreach_modifiable(&ns->all_storages, storagep) -+ mail_storage_unref(storagep); -+ array_free(&ns->all_storages); - if (ns->list != NULL) - mailbox_list_destroy(&ns->list); - -@@ -150,6 +153,7 @@ namespace_add(struct mail_user *user, - ns->mail_set = mail_set; - ns->prefix = i_strdup(ns_set->prefix); - ns->special_use_mailboxes = namespace_has_special_use_mailboxes(ns_set); -+ i_array_init(&ns->all_storages, 2); - - if (ns->type == MAIL_NAMESPACE_TYPE_SHARED && - (strchr(ns->prefix, '%') != NULL || -@@ -510,9 +514,12 @@ void mail_namespaces_set_storage_callbacks(struct mail_namespace *namespaces, - void *context) - { - struct mail_namespace *ns; -+ struct mail_storage *const *storagep; - -- for (ns = namespaces; ns != NULL; ns = ns->next) -- mail_storage_set_callbacks(ns->storage, callbacks, context); -+ for (ns = namespaces; ns != NULL; ns = ns->next) { -+ array_foreach(&ns->all_storages, storagep) -+ mail_storage_set_callbacks(*storagep, callbacks, context); -+ } - } - - void mail_namespace_ref(struct mail_namespace *ns) -@@ -558,7 +565,6 @@ void mail_namespace_destroy(struct mail_namespace *ns) - struct mail_storage * - mail_namespace_get_default_storage(struct mail_namespace *ns) - { -- /* currently we don't support more than one storage per namespace */ - return ns->storage; - } - -diff --git a/src/lib-storage/mail-namespace.h b/src/lib-storage/mail-namespace.h -index 081bce9..8580015 100644 ---- a/src/lib-storage/mail-namespace.h -+++ b/src/lib-storage/mail-namespace.h -@@ -67,8 +67,8 @@ struct mail_namespace { - - struct mail_user *user, *owner; - struct mailbox_list *list; -- /* FIXME: we should support multiple storages in one namespace */ -- struct mail_storage *storage; -+ struct mail_storage *storage; /* default storage */ -+ ARRAY(struct mail_storage *) all_storages; - - const struct mail_namespace_settings *set, *unexpanded_set; - const struct mail_storage_settings *mail_set; -diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c -index f52b353..7885702 100644 ---- a/src/lib-storage/mail-storage.c -+++ b/src/lib-storage/mail-storage.c -@@ -298,14 +298,15 @@ mail_storage_find(struct mail_user *user, - return NULL; - } - --int mail_storage_create(struct mail_namespace *ns, const char *driver, -- enum mail_storage_flags flags, const char **error_r) -+int mail_storage_create_full(struct mail_namespace *ns, const char *driver, -+ const char *data, enum mail_storage_flags flags, -+ struct mail_storage **storage_r, -+ const char **error_r) - { - struct mail_storage *storage_class, *storage = NULL; - struct mailbox_list *list; - struct mailbox_list_settings list_set; - enum mailbox_list_flags list_flags = 0; -- const char *data = ns->set->location; - const char *p; - - if ((flags & MAIL_STORAGE_FLAG_KEEP_HEADER_MD5) == 0 && -@@ -369,6 +370,7 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver, - /* using an existing storage */ - storage->refcount++; - mail_namespace_add_storage(ns, storage); -+ *storage_r = storage; - return 0; - } - -@@ -392,10 +394,20 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver, - } T_END; - - DLLIST_PREPEND(&ns->user->storages, storage); -- mail_namespace_add_storage(ns, storage); -+ mail_namespace_add_storage(ns, storage); -+ *storage_r = storage; - return 0; - } - -+int mail_storage_create(struct mail_namespace *ns, const char *driver, -+ enum mail_storage_flags flags, const char **error_r) -+{ -+ struct mail_storage *storage; -+ -+ return mail_storage_create_full(ns, driver, ns->set->location, -+ flags, &storage, error_r); -+} -+ - void mail_storage_unref(struct mail_storage **_storage) - { - struct mail_storage *storage = *_storage; -@@ -639,6 +651,8 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname, - struct mailbox_list *new_list = list; - struct mail_storage *storage; - struct mailbox *box; -+ enum mail_error open_error = 0; -+ const char *errstr = NULL; - - i_assert(uni_utf8_str_is_valid(vname)); - -@@ -654,14 +668,19 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname, - vname = t_strconcat("INBOX", vname + 5, NULL); - } - -- if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) { -- /* just use the default storage. FIXME: does this break? */ -- storage = mail_namespace_get_default_storage(list->ns); -- } -- - T_BEGIN { -+ if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) { -+ /* do a delayed failure at mailbox_open() */ -+ storage = mail_namespace_get_default_storage(list->ns); -+ errstr = mailbox_list_get_last_error(new_list, &open_error); -+ errstr = t_strdup(errstr); -+ } -+ - box = storage->v.mailbox_alloc(storage, new_list, vname, flags); - box->set = mailbox_settings_find(storage->user, vname); -+ box->open_error = open_error; -+ if (open_error != 0) -+ mail_storage_set_error(storage, open_error, errstr); - hook_mailbox_allocated(box); - } T_END; - -diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h -index 0a5d5b4..0a91572 100644 ---- a/src/lib-storage/mail-storage.h -+++ b/src/lib-storage/mail-storage.h -@@ -419,6 +419,10 @@ struct mail_storage *mail_storage_find_class(const char *name); - int mail_storage_create(struct mail_namespace *ns, const char *driver, - enum mail_storage_flags flags, const char **error_r) - ATTR_NULL(2); -+int mail_storage_create_full(struct mail_namespace *ns, const char *driver, -+ const char *data, enum mail_storage_flags flags, -+ struct mail_storage **storage_r, -+ const char **error_r) ATTR_NULL(2); - void mail_storage_unref(struct mail_storage **storage); - - /* Returns the mail storage settings. */ --- -1.7.10.2 - - -From 2ae207e9f431b1ebcdef4aa9102a3b490eb6ee98 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 00:48:14 +0300 -Subject: [PATCH] lib-storage: Added mailbox { driver } setting to specify - which storage to use. - - -diff --git a/src/lib-storage/mail-storage-settings.c b/src/lib-storage/mail-storage-settings.c -index 67f724d..6c13dbe 100644 ---- a/src/lib-storage/mail-storage-settings.c -+++ b/src/lib-storage/mail-storage-settings.c -@@ -118,6 +118,7 @@ static const struct setting_define mailbox_setting_defines[] = { - DEF(SET_STR, name), - { SET_ENUM, "auto", offsetof(struct mailbox_settings, autocreate), NULL } , - DEF(SET_STR, special_use), -+ DEF(SET_STR, driver), - - SETTING_DEFINE_LIST_END - }; -@@ -127,7 +128,8 @@ const struct mailbox_settings mailbox_default_settings = { - .autocreate = MAILBOX_SET_AUTO_NO":" - MAILBOX_SET_AUTO_CREATE":" - MAILBOX_SET_AUTO_SUBSCRIBE, -- .special_use = "" -+ .special_use = "", -+ .driver = "" - }; - - const struct setting_parser_info mailbox_setting_parser_info = { -diff --git a/src/lib-storage/mail-storage-settings.h b/src/lib-storage/mail-storage-settings.h -index aeeadc8..7c5e52b 100644 ---- a/src/lib-storage/mail-storage-settings.h -+++ b/src/lib-storage/mail-storage-settings.h -@@ -75,6 +75,7 @@ struct mailbox_settings { - const char *name; - const char *autocreate; - const char *special_use; -+ const char *driver; - }; - - struct mail_user_settings { -diff --git a/src/lib-storage/mailbox-list.c b/src/lib-storage/mailbox-list.c -index 29e878d..03e5fec 100644 ---- a/src/lib-storage/mailbox-list.c -+++ b/src/lib-storage/mailbox-list.c -@@ -15,7 +15,7 @@ - #include "imap-utf7.h" - #include "mailbox-log.h" - #include "mailbox-tree.h" --#include "mail-storage.h" -+#include "mail-storage-private.h" - #include "mail-storage-hooks.h" - #include "mailbox-list-private.h" - -@@ -770,15 +770,50 @@ mailbox_list_get_user(const struct mailbox_list *list) - return list->ns->user; - } - -+static int -+mailbox_list_get_storage_driver(struct mailbox_list *list, const char *driver, -+ struct mail_storage **storage_r) -+{ -+ struct mail_storage *const *storagep; -+ const char *error, *data; -+ -+ array_foreach(&list->ns->all_storages, storagep) { -+ if (strcmp((*storagep)->name, driver) == 0) { -+ *storage_r = *storagep; -+ return 0; -+ } -+ } -+ -+ data = strchr(list->ns->set->location, ':'); -+ if (data == NULL) -+ data = ""; -+ else -+ data++; -+ if (mail_storage_create_full(list->ns, driver, data, 0, -+ storage_r, &error) < 0) { -+ mailbox_list_set_critical(list, -+ "Namespace %s: Failed to create storage '%s': %s", -+ list->ns->prefix, driver, error); -+ return -1; -+ } -+ return 0; -+} -+ - int mailbox_list_get_storage(struct mailbox_list **list, const char *vname, - struct mail_storage **storage_r) - { -+ const struct mailbox_settings *set; -+ - if ((*list)->v.get_storage != NULL) - return (*list)->v.get_storage(list, vname, storage_r); -- else { -- *storage_r = mail_namespace_get_default_storage((*list)->ns); -- return 0; -+ -+ set = mailbox_settings_find((*list)->ns->user, vname); -+ if (set != NULL && set->driver[0] != '\0') { -+ return mailbox_list_get_storage_driver(*list, set->driver, -+ storage_r); - } -+ *storage_r = mail_namespace_get_default_storage((*list)->ns); -+ return 0; - } - - void mailbox_list_get_default_storage(struct mailbox_list *list, --- -1.7.10.2 - - -From 6ccd82c04f112e8e61e5a9312273ec9dc1b00f27 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 02:08:24 +0300 -Subject: [PATCH] lib-http: If connect to peer failed, don't recreate a new - connection to handle pending requests. The new connection - would very likely fail as well. Another peer for the host - should pick up the requests. - - -diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c -index 12618d0..9eb7dc3 100644 ---- a/src/lib-http/http-client-peer.c -+++ b/src/lib-http/http-client-peer.c -@@ -277,12 +277,12 @@ void http_client_peer_connection_failure(struct http_client_peer *peer, - - http_client_peer_debug(peer, "Failed to make connection"); - -+ peer->last_connect_failed = TRUE; - if (array_count(&peer->conns) > 1) { - /* if there are other connections attempting to connect, wait - for them before failing the requests. remember that we had - trouble with connecting so in future we don't try to create - more than one connection until connects work again. */ -- peer->last_connect_failed = TRUE; - } else { - /* this was the only/last connection and connecting to it - failed. a second connect will probably also fail, so just -@@ -306,8 +306,11 @@ void http_client_peer_connection_lost(struct http_client_peer *peer) - http_client_peer_debug(peer, "Lost a connection (%d connections left)", - array_count(&peer->conns)); - -- /* if there are pending requests, create a new connection for them. */ -- http_client_peer_handle_requests(peer); -+ if (!peer->last_connect_failed) { -+ /* if there are pending requests, create a new -+ connection for them. */ -+ http_client_peer_handle_requests(peer); -+ } - if (array_count(&peer->conns) == 0 && - http_client_peer_requests_pending(peer, &num_urgent) == 0) - http_client_peer_free(&peer); --- -1.7.10.2 - - -From 1359a58c3cf91cab51a2c44c8df112e319a9c0f9 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 02:46:50 +0300 -Subject: [PATCH] lib-http: Added soft_connect_timeout_msecs setting to - connect to multiple IPs in parallel. Based on patch by - Stephan Bosch. - - -diff --git a/src/lib-http/http-client-connection.c b/src/lib-http/http-client-connection.c -index 6ef4a18..2fe2659 100644 ---- a/src/lib-http/http-client-connection.c -+++ b/src/lib-http/http-client-connection.c -@@ -672,13 +672,13 @@ http_client_connection_ready(struct http_client_connection *conn) - struct stat st; - - conn->connected = TRUE; -- conn->peer->last_connect_failed = FALSE; -- - if (conn->to_connect != NULL && - (conn->ssl_iostream == NULL || - ssl_iostream_is_handshaked(conn->ssl_iostream))) - timeout_remove(&conn->to_connect); - -+ http_client_peer_connection_success(conn->peer); -+ - if (conn->client->set.rawlog_dir != NULL && - stat(conn->client->set.rawlog_dir, &st) == 0) { - iostream_rawlog_create(conn->client->set.rawlog_dir, -diff --git a/src/lib-http/http-client-host.c b/src/lib-http/http-client-host.c -index ce42ace..3886c61 100644 ---- a/src/lib-http/http-client-host.c -+++ b/src/lib-http/http-client-host.c -@@ -41,6 +41,9 @@ http_client_host_debug(struct http_client_host *host, - * Host:port - */ - -+static void -+http_client_host_port_connection_setup(struct http_client_host_port *hport); -+ - static struct http_client_host_port * - http_client_host_port_find(struct http_client_host *host, - unsigned int port, const char *https_name) -@@ -65,6 +68,7 @@ http_client_host_port_init(struct http_client_host *host, - hport = http_client_host_port_find(host, port, https_name); - if (hport == NULL) { - hport = array_append_space(&host->ports); -+ hport->host = host; - hport->port = port; - hport->https_name = i_strdup(https_name); - hport->ips_connect_idx = 0; -@@ -110,16 +114,38 @@ http_client_host_port_drop_request(struct http_client_host_port *hport, - } - } - --/* -- * Host -- */ -+static void -+http_client_host_port_soft_connect_timeout(struct http_client_host_port *hport) -+{ -+ struct http_client_host *host = hport->host; -+ -+ if (hport->to_connect != NULL) -+ timeout_remove(&hport->to_connect); -+ -+ if (hport->ips_connect_idx + 1 >= host->ips_count) -+ return; -+ -+ /* if our our previous connection attempt takes longer than the -+ soft_connect_timeout we start a connection attempt to the next IP in -+ parallel */ -+ -+ http_client_host_debug(host, "Connection to %s:%u%s is taking a long time; " -+ "starting parallel connection attempt to next IP", -+ net_ip2addr(&host->ips[hport->ips_connect_idx]), hport->port, -+ hport->https_name == NULL ? "" : -+ t_strdup_printf(" (SSL=%s)", hport->https_name)); -+ -+ hport->ips_connect_idx++; -+ http_client_host_port_connection_setup(hport); -+} - - static void --http_client_host_connection_setup(struct http_client_host *host, -- struct http_client_host_port *hport) -+http_client_host_port_connection_setup(struct http_client_host_port *hport) - { -+ struct http_client_host *host = hport->host; - struct http_client_peer *peer = NULL; - struct http_client_peer_addr addr; -+ unsigned int msecs; - - addr.ip = host->ips[hport->ips_connect_idx]; - addr.port = hport->port; -@@ -131,6 +157,107 @@ http_client_host_connection_setup(struct http_client_host *host, - - peer = http_client_peer_get(host->client, &addr); - http_client_peer_add_host(peer, host); -+ hport->pending_connection_count++; -+ -+ /* start soft connect time-out (but only if we have another IP left) */ -+ msecs = host->client->set.soft_connect_timeout_msecs; -+ if (host->ips_count - hport->ips_connect_idx > 1 && msecs > 0 && -+ hport->to_connect == NULL) { -+ hport->to_connect = -+ timeout_add(msecs, http_client_host_port_soft_connect_timeout, hport); -+ } -+} -+ -+static void -+http_client_host_drop_pending_connections(struct http_client_host_port *hport) -+{ -+ struct http_client_peer *peer; -+ struct http_client_connection *const *conns, *conn; -+ unsigned int i, count; -+ -+ for (peer = hport->host->client->peers_list; peer != NULL; peer = peer->next) { -+ if (!http_client_peer_have_host(peer, hport->host)) -+ continue; -+ -+ conns = array_get(&peer->conns, &count); -+ for (i = count; i > 0; i--) { -+ conn = conns[i-1]; -+ if (!conn->connected) { -+ i_assert(conn->refcount == 1); -+ /* avoid recreating the connection */ -+ peer->last_connect_failed = TRUE; -+ http_client_connection_unref(&conn); -+ } -+ } -+ } -+} -+ -+static void -+http_client_host_port_connection_success(struct http_client_host_port *hport) -+{ -+ /* we achieved at least one connection the the addr->ip */ -+ -+ /* stop soft connect time-out */ -+ if (hport->to_connect != NULL) -+ timeout_remove(&hport->to_connect); -+ -+ /* drop all other attempts. note that we get here whenever a connection -+ is successfully created, so pending_connection_count may be 0. */ -+ if (hport->pending_connection_count > 1) -+ http_client_host_drop_pending_connections(hport); -+ /* since this hport is now successfully connected, we won't be -+ getting any connection failures to it anymore. so we need -+ to reset the pending_connection_count count here. */ -+ hport->pending_connection_count = 0; -+} -+ -+static bool -+http_client_host_port_connection_failure(struct http_client_host_port *hport, -+ const char *reason) -+{ -+ struct http_client_host *host = hport->host; -+ -+ i_assert(hport->pending_connection_count > 0); -+ if (--hport->pending_connection_count > 0) -+ return TRUE; -+ -+ /* one of the connections failed. if we're not using soft timeouts, -+ we need to try to connect to the next IP. if we are using soft -+ timeouts, we've already tried all of the IPs by now. */ -+ if (hport->to_connect != NULL) -+ timeout_remove(&hport->to_connect); -+ -+ i_assert(hport->ips_connect_idx < host->ips_count); -+ if (++hport->ips_connect_idx == host->ips_count) { -+ /* all IPs failed, but retry all of them again on the -+ next request. */ -+ hport->ips_connect_idx = 0; -+ http_client_host_port_error(hport, -+ HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, reason); -+ return FALSE; -+ } -+ -+ http_client_host_port_connection_setup(hport); -+ return TRUE; -+} -+ -+/* -+ * Host -+ */ -+ -+void http_client_host_connection_success(struct http_client_host *host, -+ const struct http_client_peer_addr *addr) -+{ -+ struct http_client_host_port *hport; -+ -+ http_client_host_debug(host, "Successfully connected to %s:%u", -+ net_ip2addr(&addr->ip), addr->port); -+ -+ hport = http_client_host_port_find(host, addr->port, addr->https_name); -+ if (hport == NULL) -+ return; -+ -+ http_client_host_port_connection_success(hport); - } - - void http_client_host_connection_failure(struct http_client_host *host, -@@ -145,18 +272,11 @@ void http_client_host_connection_failure(struct http_client_host *host, - if (hport == NULL) - return; - -- i_assert(hport->ips_connect_idx < host->ips_count); -- if (++hport->ips_connect_idx == host->ips_count) { -- /* all IPs failed, but retry all of them again on the -- next request. */ -- hport->ips_connect_idx = 0; -- http_client_host_port_error(hport, -- HTTP_CLIENT_REQUEST_ERROR_CONNECT_FAILED, reason); -+ if (!http_client_host_port_connection_failure(hport, reason)) { -+ /* failed definitively for currently queued requests */ - if (host->client->ioloop != NULL) - io_loop_stop(host->client->ioloop); -- return; - } -- http_client_host_connection_setup(host, hport); - } - - static void -@@ -201,7 +321,7 @@ http_client_host_dns_callback(const struct dns_lookup_result *result, - unsigned int count = array_count(&hport->request_queue); - hport->ips_connect_idx = 0; - if (count > 0) -- http_client_host_connection_setup(host, hport); -+ http_client_host_port_connection_setup(hport); - requests += count; - } - -@@ -306,7 +426,7 @@ void http_client_host_submit_request(struct http_client_host *host, - if (host->ips_count == 0) - return; - i_assert(hport->ips_connect_idx < host->ips_count); -- http_client_host_connection_setup(host, hport); -+ http_client_host_port_connection_setup(hport); - } - - struct http_client_request * -diff --git a/src/lib-http/http-client-peer.c b/src/lib-http/http-client-peer.c -index 9eb7dc3..6d93424 100644 ---- a/src/lib-http/http-client-peer.c -+++ b/src/lib-http/http-client-peer.c -@@ -76,7 +76,8 @@ http_client_peer_connect(struct http_client_peer *peer, unsigned int count) - } - - static unsigned int --http_client_peer_requests_pending(struct http_client_peer *peer, unsigned int *num_urgent_r) -+http_client_peer_requests_pending(struct http_client_peer *peer, -+ unsigned int *num_urgent_r) - { - struct http_client_host *const *host; - unsigned int num_requests = 0, num_urgent = 0, requests, urgent; -@@ -232,20 +233,22 @@ http_client_peer_get(struct http_client *client, - return peer; - } - --void http_client_peer_add_host(struct http_client_peer *peer, -- struct http_client_host *host) -+bool http_client_peer_have_host(struct http_client_peer *peer, -+ struct http_client_host *host) - { - struct http_client_host *const *host_idx; -- bool exists = FALSE; - - array_foreach(&peer->hosts, host_idx) { -- if (*host_idx == host) { -- exists = TRUE; -- break; -- } -+ if (*host_idx == host) -+ return TRUE; - } -+ return FALSE; -+} - -- if (!exists) -+void http_client_peer_add_host(struct http_client_peer *peer, -+ struct http_client_host *host) -+{ -+ if (!http_client_peer_have_host(peer, host)) - array_append(&peer->hosts, &host, 1); - http_client_peer_handle_requests(peer); - } -@@ -267,6 +270,17 @@ http_client_peer_claim_request(struct http_client_peer *peer, bool no_urgent) - return NULL; - } - -+void http_client_peer_connection_success(struct http_client_peer *peer) -+{ -+ struct http_client_host *const *host; -+ -+ peer->last_connect_failed = FALSE; -+ -+ array_foreach(&peer->hosts, host) { -+ http_client_host_connection_success(*host, &peer->addr); -+ } -+} -+ - void http_client_peer_connection_failure(struct http_client_peer *peer, - const char *reason) - { -diff --git a/src/lib-http/http-client-private.h b/src/lib-http/http-client-private.h -index 396fc07..beab561 100644 ---- a/src/lib-http/http-client-private.h -+++ b/src/lib-http/http-client-private.h -@@ -71,15 +71,20 @@ struct http_client_request { - }; - - struct http_client_host_port { -+ struct http_client_host *host; -+ - unsigned int port; -+ char *https_name; - - /* current index in host->ips */ - unsigned int ips_connect_idx; -+ /* number of connections trying to connect for this host+port */ -+ unsigned int pending_connection_count; - - /* requests pending in queue to be picked up by connections */ - ARRAY_TYPE(http_client_request) request_queue; - -- char *https_name; -+ struct timeout *to_connect; - }; - - struct http_client_host { -@@ -228,12 +233,15 @@ struct http_client_peer * - http_client_peer_get(struct http_client *client, - const struct http_client_peer_addr *addr); - void http_client_peer_free(struct http_client_peer **_peer); -+bool http_client_peer_have_host(struct http_client_peer *peer, -+ struct http_client_host *host); - void http_client_peer_add_host(struct http_client_peer *peer, - struct http_client_host *host); - struct http_client_request * - http_client_peer_claim_request(struct http_client_peer *peer, - bool no_urgent); - void http_client_peer_handle_requests(struct http_client_peer *peer); -+void http_client_peer_connection_success(struct http_client_peer *peer); - void http_client_peer_connection_failure(struct http_client_peer *peer, - const char *reason); - void http_client_peer_connection_lost(struct http_client_peer *peer); -@@ -247,6 +255,8 @@ void http_client_host_submit_request(struct http_client_host *host, - struct http_client_request * - http_client_host_claim_request(struct http_client_host *host, - const struct http_client_peer_addr *addr, bool no_urgent); -+void http_client_host_connection_success(struct http_client_host *host, -+ const struct http_client_peer_addr *addr); - void http_client_host_connection_failure(struct http_client_host *host, - const struct http_client_peer_addr *addr, const char *reason); - unsigned int http_client_host_requests_pending(struct http_client_host *host, -diff --git a/src/lib-http/http-client.c b/src/lib-http/http-client.c -index aa94853..02b4b0c 100644 ---- a/src/lib-http/http-client.c -+++ b/src/lib-http/http-client.c -@@ -98,6 +98,7 @@ struct http_client *http_client_init(const struct http_client_settings *set) - client->set.max_redirects = set->max_redirects; - client->set.request_timeout_msecs = set->request_timeout_msecs; - client->set.connect_timeout_msecs = set->connect_timeout_msecs; -+ client->set.soft_connect_timeout_msecs = set->soft_connect_timeout_msecs; - client->set.debug = set->debug; - - client->conn_list = http_client_connection_list_init(); -diff --git a/src/lib-http/http-client.h b/src/lib-http/http-client.h -index 8a2c31e..ecba87c 100644 ---- a/src/lib-http/http-client.h -+++ b/src/lib-http/http-client.h -@@ -63,6 +63,10 @@ struct http_client_settings { - /* max time to wait for connect() (and SSL handshake) to finish before - retrying (default = request_timeout_msecs) */ - unsigned int connect_timeout_msecs; -+ /* time to wait for connect() (and SSL handshake) to finish for the first -+ connection before trying the next IP in parallel -+ (default = 0; wait until current connection attempt finishes) */ -+ unsigned int soft_connect_timeout_msecs; - - bool debug; - }; --- -1.7.10.2 - - -From c64dab7cb022c21ae82cfa15854d91ae6cf607d7 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 02:49:48 +0300 -Subject: [PATCH] man pages: Updated v2.1 -> v2.2 - - -diff --git a/doc/man/doveadm-altmove.1.in b/doc/man/doveadm-altmove.1.in -index 8381fbe..11767b3c 100644 ---- a/doc/man/doveadm-altmove.1.in -+++ b/doc/man/doveadm-altmove.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file --.TH DOVEADM\-ALTMOVE 1 "2011-09-15" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-ALTMOVE 1 "2011-09-15" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-altmove \- Move matching mails to the alternative storage (dbox\-only) - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-auth.1.in b/doc/man/doveadm-auth.1.in -index 4d73e1f..9e9fd45 100644 ---- a/doc/man/doveadm-auth.1.in -+++ b/doc/man/doveadm-auth.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-AUTH 1 "2010-06-09" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-AUTH 1 "2010-06-09" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-auth \- Test authentication for a user - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-director.1.in b/doc/man/doveadm-director.1.in -index f1092ce..63aa3fb 100644 ---- a/doc/man/doveadm-director.1.in -+++ b/doc/man/doveadm-director.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-DIRECTOR 1 "2011-05-11" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-DIRECTOR 1 "2011-05-11" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-director \- Manage Dovecot directors - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-dump.1.in b/doc/man/doveadm-dump.1.in -index 8fc9e71..ba0354e 100644 ---- a/doc/man/doveadm-dump.1.in -+++ b/doc/man/doveadm-dump.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-DUMP 1 "2012-02-21" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-DUMP 1 "2012-02-21" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-dump \- Dump the content of Dovecot\(aqs binary mailbox index/log - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-expunge.1.in b/doc/man/doveadm-expunge.1.in -index f0acd25..62da6bf 100644 ---- a/doc/man/doveadm-expunge.1.in -+++ b/doc/man/doveadm-expunge.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-EXPUNGE 1 "2012-11-27" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-EXPUNGE 1 "2012-11-27" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-expunge \- Expunge messages matching given search query - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-fetch.1.in b/doc/man/doveadm-fetch.1.in -index 6b33444..d6e6ce7 100644 ---- a/doc/man/doveadm-fetch.1.in -+++ b/doc/man/doveadm-fetch.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-FETCH 1 "2012-02-13" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-FETCH 1 "2012-02-13" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-fetch \- Fetch partial/full messages or message information - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-force-resync.1.in b/doc/man/doveadm-force-resync.1.in -index d94bfd6..0b28448 100644 ---- a/doc/man/doveadm-force-resync.1.in -+++ b/doc/man/doveadm-force-resync.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-FORCE\-RESYNC 1 "2010-11-25" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-FORCE\-RESYNC 1 "2010-11-25" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-force\-resync \- Repair broken mailboxes - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-help.1.in b/doc/man/doveadm-help.1.in -index cca530c..d4c1f0e 100644 ---- a/doc/man/doveadm-help.1.in -+++ b/doc/man/doveadm-help.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-HELP 1 "2010-06-22" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-HELP 1 "2010-06-22" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-help \- Show information about doveadm commands - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-import.1.in b/doc/man/doveadm-import.1.in -index 3757f3b..db59375 100644 ---- a/doc/man/doveadm-import.1.in -+++ b/doc/man/doveadm-import.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-IMPORT 1 "2010-11-26" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-IMPORT 1 "2010-11-26" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-import \- Import messages matching given search query - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-index.1.in b/doc/man/doveadm-index.1.in -index d27af35..14ddb95 100644 ---- a/doc/man/doveadm-index.1.in -+++ b/doc/man/doveadm-index.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file --.TH DOVEADM\-INDEX 1 "2011-05-11" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-INDEX 1 "2011-05-11" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-index \- Index mailboxes - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-instance.1.in b/doc/man/doveadm-instance.1.in -index c7915e9..7b9b2d0 100644 ---- a/doc/man/doveadm-instance.1.in -+++ b/doc/man/doveadm-instance.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-INSTANCE 1 "2012-02-16" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-INSTANCE 1 "2012-02-16" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-instance \- Manage the list of running Dovecot instances - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-kick.1.in b/doc/man/doveadm-kick.1.in -index a07f252..4c1ffb6 100644 ---- a/doc/man/doveadm-kick.1.in -+++ b/doc/man/doveadm-kick.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-KICK 1 "2010-06-12" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-KICK 1 "2010-06-12" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-kick \- Disconnect users by user name and/or IP address - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-log.1.in b/doc/man/doveadm-log.1.in -index 482d823..ae63e8f 100644 ---- a/doc/man/doveadm-log.1.in -+++ b/doc/man/doveadm-log.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-LOG 1 "2012-02-22" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-LOG 1 "2012-02-22" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-log \- Locate, test or reopen Dovecot\(aqs log files - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-mailbox.1.in b/doc/man/doveadm-mailbox.1.in -index b3de59a..8679f66 100644 ---- a/doc/man/doveadm-mailbox.1.in -+++ b/doc/man/doveadm-mailbox.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-MAILBOX 1 "2010-11-25" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-MAILBOX 1 "2010-11-25" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-mailbox \- Commands related to handling mailboxes - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-mount.1.in b/doc/man/doveadm-mount.1.in -index 8631a91..837de27 100644 ---- a/doc/man/doveadm-mount.1.in -+++ b/doc/man/doveadm-mount.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-MOUNT 1 "2012-02-16" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-MOUNT 1 "2012-02-16" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-mount \- Manage the list of mountpoints where mails are stored - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-move.1.in b/doc/man/doveadm-move.1.in -index a70c78d..8e316f8 100644 ---- a/doc/man/doveadm-move.1.in -+++ b/doc/man/doveadm-move.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2011 Dovecot authors, see the included COPYING file --.TH DOVEADM\-MOVE 1 "2011-09-25" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-MOVE 1 "2011-09-25" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-move \- Move messages matching the given search query into another - mailbox -diff --git a/doc/man/doveadm-penalty.1.in b/doc/man/doveadm-penalty.1.in -index ecbf821..fbe8666 100644 ---- a/doc/man/doveadm-penalty.1.in -+++ b/doc/man/doveadm-penalty.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-PENALTY 1 "2010-07-12" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-PENALTY 1 "2010-07-12" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-penalty \- Show current penalties - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-purge.1.in b/doc/man/doveadm-purge.1.in -index fb33bbb..aaa5f01 100644 ---- a/doc/man/doveadm-purge.1.in -+++ b/doc/man/doveadm-purge.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-PURGE 1 "2010-11-25" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-PURGE 1 "2010-11-25" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-purge \- Remove messages with refcount=0 from mdbox files - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-pw.1.in b/doc/man/doveadm-pw.1.in -index 7ffe707..b5e83dd 100644 ---- a/doc/man/doveadm-pw.1.in -+++ b/doc/man/doveadm-pw.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVEADM\-PW 1 "2012-02-13" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-PW 1 "2012-02-13" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-pw \- Dovecot\(aqs password hash generator - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-quota.1.in b/doc/man/doveadm-quota.1.in -index 77de49f..4c7a6a9 100644 ---- a/doc/man/doveadm-quota.1.in -+++ b/doc/man/doveadm-quota.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file --.TH DOVEADM\-QUOTA 1 "2011-02-17" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-QUOTA 1 "2011-02-17" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-quota \- Initialize/recalculate or show current quota usage - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-search-query.7 b/doc/man/doveadm-search-query.7 -index fa343f9..8c42b8d 100644 ---- a/doc/man/doveadm-search-query.7 -+++ b/doc/man/doveadm-search-query.7 -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-SEARCH\-QUERY 7 "2011-11-24" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-SEARCH\-QUERY 7 "2011-11-24" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-search\-query \- Overview of search queries for doveadm mailbox \ - commands -diff --git a/doc/man/doveadm-search.1.in b/doc/man/doveadm-search.1.in -index 683bb94..828138d 100644 ---- a/doc/man/doveadm-search.1.in -+++ b/doc/man/doveadm-search.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-SEARCH 1 "2010-11-25" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-SEARCH 1 "2010-11-25" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-search \- Show a list of mailbox GUIDs and message UIDs matching \ - given search query. -diff --git a/doc/man/doveadm-user.1.in b/doc/man/doveadm-user.1.in -index 552ac03..0a64c1c 100644 ---- a/doc/man/doveadm-user.1.in -+++ b/doc/man/doveadm-user.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file --.TH DOVEADM\-USER 1 "2011-11-04" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-USER 1 "2011-11-04" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-user \- Perform a user lookup in Dovecot\(aqs userdbs - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm-who.1.in b/doc/man/doveadm-who.1.in -index 7845396..756f881 100644 ---- a/doc/man/doveadm-who.1.in -+++ b/doc/man/doveadm-who.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM\-WHO 1 "2010-07-12" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM\-WHO 1 "2010-07-12" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm\-who \- Show who is logged in to the Dovecot server - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveadm.1.in b/doc/man/doveadm.1.in -index abade80..9606668 100644 ---- a/doc/man/doveadm.1.in -+++ b/doc/man/doveadm.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVEADM 1 "2011-05-11" "Dovecot v2.1" "Dovecot" -+.TH DOVEADM 1 "2011-05-11" "Dovecot v2.2" "Dovecot" - .SH NAME - doveadm \- Dovecot\(aqs administration utility - .\"------------------------------------------------------------------------ -diff --git a/doc/man/doveconf.1.in b/doc/man/doveconf.1.in -index 8385f5b..4e34f65 100644 ---- a/doc/man/doveconf.1.in -+++ b/doc/man/doveconf.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file --.TH DOVECONF 1 "2012-01-29" "Dovecot v2.1" "Dovecot" -+.TH DOVECONF 1 "2012-01-29" "Dovecot v2.2" "Dovecot" - .SH NAME - doveconf \- Dovecot\(aqs configuration dumping utility - .\"------------------------------------------------------------------------ -diff --git a/doc/man/dovecot-lda.1.in b/doc/man/dovecot-lda.1.in -index a7383c6..0d7421a 100644 ---- a/doc/man/dovecot-lda.1.in -+++ b/doc/man/dovecot-lda.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVECOT\-LDA 1 "2011-01-16" "Dovecot v2.1" "Dovecot" -+.TH DOVECOT\-LDA 1 "2011-01-16" "Dovecot v2.2" "Dovecot" - .SH NAME - dovecot\-lda \- Dovecot\(aqs local mail delivery agent - .\"------------------------------------------------------------------------ -diff --git a/doc/man/dovecot.1.in b/doc/man/dovecot.1.in -index 644cf7e..751c172 100644 ---- a/doc/man/dovecot.1.in -+++ b/doc/man/dovecot.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DOVECOT 1 "2010-07-02" "Dovecot v2.1" "Dovecot" -+.TH DOVECOT 1 "2010-07-02" "Dovecot v2.2" "Dovecot" - .SH NAME - dovecot \- a secure and highly configurable IMAP and POP3 server - .\"------------------------------------------------------------------------ -@@ -148,7 +148,7 @@ Configuration files of different services and settings. - .SH AUTHOR - Dovecot and its manual pages were written by the - Dovecot authors , mainly Timo Sirainen , and are licensed under the terms of the MIT and LGPLv2.1 -+at iki.fi>, and are licensed under the terms of the MIT and LGPLv2.2 - licenses, see for details. - .\"------------------------------------------------------------------------ - .SH SEE ALSO -diff --git a/doc/man/dsync.1.in b/doc/man/dsync.1.in -index 2f34dcb..e1e4c23 100644 ---- a/doc/man/dsync.1.in -+++ b/doc/man/dsync.1.in -@@ -1,5 +1,5 @@ - .\" Copyright (c) 2010 Dovecot authors, see the included COPYING file --.TH DSYNC 1 "2011-01-16" "Dovecot v2.1" "Dovecot" -+.TH DSYNC 1 "2011-01-16" "Dovecot v2.2" "Dovecot" - .SH NAME - dsync \- Dovecot\(aqs mailbox synchronization utility - .\"------------------------------------------------------------------------ --- -1.7.10.2 - - -From 47b780cdcd1531a5554b8782eabe0b6b24d648c2 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 03:10:43 +0300 -Subject: [PATCH] fts-lucene: Support normalize setting also without snowball. - Added no_snowball setting. Snowball seems to be converting - / breaking words down rather annoyingly. - - -diff --git a/src/plugins/fts-lucene/fts-lucene-plugin.c b/src/plugins/fts-lucene/fts-lucene-plugin.c -index d4f078b..be5fcc9 100644 ---- a/src/plugins/fts-lucene/fts-lucene-plugin.c -+++ b/src/plugins/fts-lucene/fts-lucene-plugin.c -@@ -30,6 +30,8 @@ fts_lucene_plugin_init_settings(struct mail_user *user, - set->whitespace_chars = p_strdup(user->pool, *tmp + 17); - } else if (strcmp(*tmp, "normalize") == 0) { - set->normalize = TRUE; -+ } else if (strcmp(*tmp, "no_snowball") == 0) { -+ set->no_snowball = TRUE; - } else { - i_error("fts_lucene: Invalid setting: %s", *tmp); - return -1; -@@ -51,11 +53,6 @@ fts_lucene_plugin_init_settings(struct mail_user *user, - "but Dovecot built without stemmer support"); - return -1; - } -- if (set->normalize) { -- i_error("fts_lucene: normalize not currently supported " -- "without stemmer support"); -- return -1; -- } - #else - if (set->default_language == NULL) - set->default_language = "english"; -@@ -80,6 +77,8 @@ uint32_t fts_lucene_settings_checksum(const struct fts_lucene_settings *set) - crc = crc32_str_more(crc, set->whitespace_chars); - if (set->normalize) - crc = crc32_str_more(crc, "n"); -+ if (set->no_snowball) -+ crc = crc32_str_more(crc, "s"); - return crc; - } - -diff --git a/src/plugins/fts-lucene/fts-lucene-plugin.h b/src/plugins/fts-lucene/fts-lucene-plugin.h -index 42587f3..c5be44c 100644 ---- a/src/plugins/fts-lucene/fts-lucene-plugin.h -+++ b/src/plugins/fts-lucene/fts-lucene-plugin.h -@@ -13,6 +13,7 @@ struct fts_lucene_settings { - const char *textcat_conf, *textcat_dir; - const char *whitespace_chars; - bool normalize; -+ bool no_snowball; - }; - - struct fts_lucene_user { -diff --git a/src/plugins/fts-lucene/lucene-wrapper.cc b/src/plugins/fts-lucene/lucene-wrapper.cc -index c57b676..3eea52e 100644 ---- a/src/plugins/fts-lucene/lucene-wrapper.cc -+++ b/src/plugins/fts-lucene/lucene-wrapper.cc -@@ -67,6 +67,7 @@ struct lucene_index { - IndexWriter *writer; - IndexSearcher *searcher; - -+ buffer_t *normalizer_buf; - Analyzer *default_analyzer, *cur_analyzer; - ARRAY(struct lucene_analyzer) analyzers; - -@@ -118,13 +119,20 @@ struct lucene_index *lucene_index_init(const char *path, - index->set.default_language = ""; - } - #ifdef HAVE_LUCENE_STEMMER -- index->default_analyzer = -- _CLNEW snowball::SnowballAnalyzer(index->normalizer, -- index->set.default_language); --#else -- index->default_analyzer = _CLNEW standard::StandardAnalyzer(); -- i_assert(index->normalizer == NULL); -+ if (!set->no_snowball) { -+ index->default_analyzer = -+ _CLNEW snowball::SnowballAnalyzer(index->normalizer, -+ index->set.default_language); -+ } - #endif -+ else { -+ index->default_analyzer = _CLNEW standard::StandardAnalyzer(); -+ if (index->normalizer != NULL) { -+ index->normalizer_buf = -+ buffer_create_dynamic(default_pool, 1024); -+ } -+ } -+ - i_array_init(&index->analyzers, 32); - textcat_refcount++; - -@@ -155,6 +163,8 @@ void lucene_index_deinit(struct lucene_index *index) - textcat = NULL; - } - _CLDELETE(index->default_analyzer); -+ if (index->normalizer_buf != NULL) -+ buffer_free(&index->normalizer_buf); - i_free(index->path); - i_free(index); - } -@@ -517,6 +527,13 @@ int lucene_index_build_more(struct lucene_index *index, uint32_t uid, - index->doc->add(*_CLNEW Field(_T("box"), index->mailbox_guid, Field::STORE_YES | Field::INDEX_UNTOKENIZED)); - } - -+ if (index->normalizer_buf != NULL) { -+ buffer_set_used_size(index->normalizer_buf, 0); -+ index->normalizer(data, size, index->normalizer_buf); -+ data = (const unsigned char *)index->normalizer_buf->data; -+ size = index->normalizer_buf->used; -+ } -+ - datasize = uni_utf8_strlen_n(data, size) + 1; - wchar_t dest[datasize]; - lucene_utf8_n_to_tchar(data, size, dest, datasize); -@@ -1055,8 +1072,18 @@ static Query * - lucene_get_query_str(struct lucene_index *index, - const TCHAR *key, const char *str, bool fuzzy) - { -- const TCHAR *wvalue = t_lucene_utf8_to_tchar(index, str, TRUE); -- Analyzer *analyzer = guess_analyzer(index, str, strlen(str)); -+ const TCHAR *wvalue; -+ Analyzer *analyzer; -+ -+ if (index->normalizer_buf != NULL) { -+ buffer_set_used_size(index->normalizer_buf, 0); -+ index->normalizer(str, strlen(str), index->normalizer_buf); -+ buffer_append_c(index->normalizer_buf, '\0'); -+ str = (const char *)index->normalizer_buf->data; -+ } -+ -+ wvalue = t_lucene_utf8_to_tchar(index, str, TRUE); -+ analyzer = guess_analyzer(index, str, strlen(str)); - if (analyzer == NULL) - analyzer = index->default_analyzer; - --- -1.7.10.2 - - -From 001ea57f8ce1c3916f07b0ff1f4619d9d0cfe76f Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 06:02:14 +0300 -Subject: [PATCH] Added initial libsasl for implementing client side SASL - library. Initially supports PLAIN and LOGIN mechanisms. - - -diff --git a/configure.ac b/configure.ac -index 6bae121..121082b 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2559,7 +2559,7 @@ if test "$want_shared_libs" = "yes"; then - LIBDOVECOT_COMPRESS='$(top_builddir)/src/lib-compression/libcompression.la' - LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la' - else -- LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la' -+ LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-sasl/libsasl.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la' - LIBDOVECOT="$LIBDOVECOT_DEPS \$(LIBICONV) \$(MODULE_LIBS)" - LIBDOVECOT_STORAGE_LAST='$(top_builddir)/src/lib-storage/list/libstorage_list.la $(top_builddir)/src/lib-storage/index/libstorage_index.la $(top_builddir)/src/lib-storage/libstorage.la $(top_builddir)/src/lib-index/libindex.la $(top_builddir)/src/lib-imap-storage/libimap-storage.la' - LIBDOVECOT_STORAGE_FIRST='$(top_builddir)/src/lib-storage/libstorage_service.la $(top_builddir)/src/lib-storage/register/libstorage_register.la' -@@ -2822,6 +2822,7 @@ src/lib-master/Makefile - src/lib-ntlm/Makefile - src/lib-otp/Makefile - src/lib-dovecot/Makefile -+src/lib-sasl/Makefile - src/lib-settings/Makefile - src/lib-ssl-iostream/Makefile - src/lib-test/Makefile -diff --git a/src/Makefile.am b/src/Makefile.am -index 4e82017..378d614 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -7,6 +7,7 @@ LIBDOVECOT_SUBDIRS = \ - lib-charset \ - lib-dns \ - lib-dict \ -+ lib-sasl \ - lib-ssl-iostream \ - lib-http \ - lib-fs \ -diff --git a/src/lib-dovecot/Makefile.am b/src/lib-dovecot/Makefile.am -index cd7a165..e79e964 100644 ---- a/src/lib-dovecot/Makefile.am -+++ b/src/lib-dovecot/Makefile.am -@@ -7,6 +7,7 @@ libs = \ - ../lib-dict/libdict.la \ - ../lib-imap/libimap.la \ - ../lib-mail/libmail.la \ -+ ../lib-sasl/libsasl.la \ - ../lib-auth/libauth.la \ - ../lib-dns/libdns.la \ - ../lib-charset/libcharset.la \ -diff --git a/src/lib-sasl/Makefile.am b/src/lib-sasl/Makefile.am -new file mode 100644 -index 0000000..5ca1a0e ---- /dev/null -+++ b/src/lib-sasl/Makefile.am -@@ -0,0 +1,16 @@ -+noinst_LTLIBRARIES = libsasl.la -+ -+AM_CPPFLAGS = \ -+ -I$(top_srcdir)/src/lib -+ -+libsasl_la_SOURCES = \ -+ mech-login.c \ -+ mech-plain.c \ -+ sasl-client.c -+ -+headers = \ -+ sasl-client.h \ -+ sasl-client-private.h -+ -+pkginc_libdir=$(pkgincludedir) -+pkginc_lib_HEADERS = $(headers) -diff --git a/src/lib-sasl/mech-login.c b/src/lib-sasl/mech-login.c -new file mode 100644 -index 0000000..e1cbe9b ---- /dev/null -+++ b/src/lib-sasl/mech-login.c -@@ -0,0 +1,73 @@ -+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "str.h" -+#include "sasl-client-private.h" -+ -+enum login_state { -+ STATE_INIT = 0, -+ STATE_USER, -+ STATE_PASS -+}; -+ -+struct login_sasl_client { -+ struct sasl_client client; -+ enum login_state state; -+}; -+ -+static int -+mech_login_input(struct sasl_client *_client, -+ const unsigned char *input ATTR_UNUSED, -+ unsigned int input_len ATTR_UNUSED, -+ const char **error_r) -+{ -+ struct login_sasl_client *client = (struct login_sasl_client *)_client; -+ -+ if (client->state == STATE_PASS) { -+ *error_r = "Server didn't finish authentication"; -+ return -1; -+ } -+ client->state++; -+ return 0; -+} -+ -+static int -+mech_login_output(struct sasl_client *_client, -+ const unsigned char **output_r, unsigned int *output_len_r, -+ const char **error_r) -+{ -+ struct login_sasl_client *client = (struct login_sasl_client *)_client; -+ -+ if (_client->set.authid == NULL) { -+ *error_r = "authid not set"; -+ return -1; -+ } -+ if (_client->password == NULL) { -+ *error_r = "password not set"; -+ return -1; -+ } -+ -+ switch (client->state) { -+ case STATE_INIT: -+ *output_r = &uchar_nul; -+ *output_len_r = 0; -+ return 0; -+ case STATE_USER: -+ *output_r = (const unsigned char *)_client->set.authid; -+ *output_len_r = strlen(_client->set.authid); -+ return 0; -+ case STATE_PASS: -+ *output_r = (const unsigned char *)_client->set.password; -+ *output_len_r = strlen(_client->set.password); -+ return 0; -+ } -+ i_unreached(); -+} -+ -+const struct sasl_client_mech sasl_client_mech_login = { -+ .name = "LOGIN", -+ .struct_size = sizeof(struct login_sasl_client), -+ -+ .input = mech_login_input, -+ .output = mech_login_output -+}; -diff --git a/src/lib-sasl/mech-plain.c b/src/lib-sasl/mech-plain.c -new file mode 100644 -index 0000000..ef3d137 ---- /dev/null -+++ b/src/lib-sasl/mech-plain.c -@@ -0,0 +1,68 @@ -+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "str.h" -+#include "sasl-client-private.h" -+ -+struct plain_sasl_client { -+ struct sasl_client client; -+ bool output_sent; -+}; -+ -+static int -+mech_plain_input(struct sasl_client *_client, -+ const unsigned char *input ATTR_UNUSED, unsigned int input_len, -+ const char **error_r) -+{ -+ struct plain_sasl_client *client = (struct plain_sasl_client *)_client; -+ -+ if (!client->output_sent) { -+ if (input_len > 0) { -+ *error_r = "Server sent non-empty initial response"; -+ return -1; -+ } -+ } else { -+ *error_r = "Server didn't finish authentication"; -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+mech_plain_output(struct sasl_client *_client, -+ const unsigned char **output_r, unsigned int *output_len_r, -+ const char **error_r) -+{ -+ struct plain_sasl_client *client = (struct plain_sasl_client *)_client; -+ string_t *str; -+ -+ if (_client->set.authid == NULL) { -+ *error_r = "authid not set"; -+ return -1; -+ } -+ if (_client->password == NULL) { -+ *error_r = "password not set"; -+ return -1; -+ } -+ -+ str = str_new(_client->pool, 64); -+ if (_client->set.authzid != NULL) -+ str_append(str, _client->set.authzid); -+ str_append_c(str, '\0'); -+ str_append(str, _client->set.authid); -+ str_append_c(str, '\0'); -+ str_append(str, _client->password); -+ -+ *output_r = str_data(str); -+ *output_len_r = str_len(str); -+ client->output_sent = TRUE; -+ return 0; -+} -+ -+const struct sasl_client_mech sasl_client_mech_plain = { -+ .name = "PLAIN", -+ .struct_size = sizeof(struct plain_sasl_client), -+ -+ .input = mech_plain_input, -+ .output = mech_plain_output -+}; -diff --git a/src/lib-sasl/sasl-client-private.h b/src/lib-sasl/sasl-client-private.h -new file mode 100644 -index 0000000..9c5ae22 ---- /dev/null -+++ b/src/lib-sasl/sasl-client-private.h -@@ -0,0 +1,33 @@ -+#ifndef SASL_CLIENT_PRIVATE_H -+#define SASL_CLIENT_PRIVATE_H -+ -+#include "sasl-client.h" -+ -+struct sasl_client { -+ pool_t pool; -+ struct sasl_client_settings set; -+ char *password; -+ const struct sasl_client_mech *mech; -+}; -+ -+struct sasl_client_mech { -+ const char *name; -+ size_t struct_size; -+ -+ int (*input)(struct sasl_client *client, -+ const unsigned char *input, -+ unsigned int input_len, -+ const char **error_r); -+ int (*output)(struct sasl_client *client, -+ const unsigned char **output_r, -+ unsigned int *output_len_r, -+ const char **error_r); -+ void (*free)(struct sasl_client *client); -+}; -+ -+extern const struct sasl_client_mech sasl_client_mech_login; -+ -+void sasl_client_mech_register(const struct sasl_client_mech *mech); -+void sasl_client_mech_unregister(const struct sasl_client_mech *mech); -+ -+#endif -diff --git a/src/lib-sasl/sasl-client.c b/src/lib-sasl/sasl-client.c -new file mode 100644 -index 0000000..78f0eda ---- /dev/null -+++ b/src/lib-sasl/sasl-client.c -@@ -0,0 +1,104 @@ -+/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */ -+ -+#include "lib.h" -+#include "array.h" -+#include "safe-memset.h" -+#include "sasl-client-private.h" -+ -+static ARRAY(const struct sasl_client_mech *) sasl_mechanisms = ARRAY_INIT; -+ -+static const struct sasl_client_mech * -+sasl_client_mech_find_idx(const char *name, unsigned int *idx_r) -+{ -+ const struct sasl_client_mech *const *mechp; -+ -+ array_foreach(&sasl_mechanisms, mechp) { -+ if (strcasecmp((*mechp)->name, name) == 0) { -+ *idx_r = array_foreach_idx(&sasl_mechanisms, mechp); -+ return *mechp; -+ } -+ } -+ return NULL; -+} -+ -+const struct sasl_client_mech *sasl_client_mech_find(const char *name) -+{ -+ unsigned int idx; -+ -+ return sasl_client_mech_find_idx(name, &idx); -+} -+ -+const char *sasl_client_mech_get_name(const struct sasl_client_mech *mech) -+{ -+ return mech->name; -+} -+ -+void sasl_client_mech_register(const struct sasl_client_mech *mech) -+{ -+ array_append(&sasl_mechanisms, &mech, 1); -+} -+ -+void sasl_client_mech_unregister(const struct sasl_client_mech *mech) -+{ -+ unsigned int idx; -+ -+ if (sasl_client_mech_find_idx(mech->name, &idx) == NULL) -+ i_panic("SASL mechanism not registered: %s", mech->name); -+ array_delete(&sasl_mechanisms, idx, 1); -+} -+ -+struct sasl_client *sasl_client_new(const struct sasl_client_mech *mech, -+ const struct sasl_client_settings *set) -+{ -+ struct sasl_client *client; -+ pool_t pool = pool_alloconly_create("sasl client", 512); -+ -+ client = p_malloc(pool, mech->struct_size); -+ client->pool = pool; -+ client->mech = mech; -+ client->set.authid = p_strdup(pool, set->authid); -+ client->set.authzid = p_strdup(pool, set->authzid); -+ client->password = p_strdup(pool, set->password); -+ client->set.password = client->password; -+ return client; -+} -+ -+void sasl_client_free(struct sasl_client **_client) -+{ -+ struct sasl_client *client = *_client; -+ -+ *_client = NULL; -+ -+ if (client->mech->free != NULL) -+ client->mech->free(client); -+ safe_memset(client->password, 0, strlen(client->password)); -+ pool_unref(&client->pool); -+} -+ -+int sasl_client_input(struct sasl_client *client, -+ const unsigned char *input, -+ unsigned int input_len, -+ const char **error_r) -+{ -+ return client->mech->input(client, input, input_len, error_r); -+} -+ -+int sasl_client_output(struct sasl_client *client, -+ const unsigned char **output_r, -+ unsigned int *output_len_r, -+ const char **error_r) -+{ -+ return client->mech->output(client, output_r, output_len_r, error_r); -+} -+ -+void sasl_clients_init(void) -+{ -+ i_array_init(&sasl_mechanisms, 8); -+ sasl_client_mech_register(&sasl_client_mech_plain); -+ sasl_client_mech_register(&sasl_client_mech_login); -+} -+ -+void sasl_clients_deinit(void) -+{ -+ array_free(&sasl_mechanisms); -+} -diff --git a/src/lib-sasl/sasl-client.h b/src/lib-sasl/sasl-client.h -new file mode 100644 -index 0000000..dc969ef ---- /dev/null -+++ b/src/lib-sasl/sasl-client.h -@@ -0,0 +1,38 @@ -+#ifndef SASL_CLIENT_H -+#define SASL_CLIENT_H -+ -+struct sasl_client_settings { -+ /* authentication ID - must be set with most mechanisms */ -+ const char *authid; -+ /* authorization ID ("master user") */ -+ const char *authzid; -+ /* password - must be set with most mechanisms */ -+ const char *password; -+}; -+ -+/* PLAIN mechanism always exists and can be accessed directly via this. */ -+extern const struct sasl_client_mech sasl_client_mech_plain; -+ -+const struct sasl_client_mech *sasl_client_mech_find(const char *name); -+const char *sasl_client_mech_get_name(const struct sasl_client_mech *mech); -+ -+struct sasl_client *sasl_client_new(const struct sasl_client_mech *mech, -+ const struct sasl_client_settings *set); -+void sasl_client_free(struct sasl_client **client); -+ -+/* Call for server input. */ -+int sasl_client_input(struct sasl_client *client, -+ const unsigned char *input, -+ unsigned int input_len, -+ const char **error_r); -+/* Call for getting server output. Also used to get the initial SASL response -+ if supported by the protocol. */ -+int sasl_client_output(struct sasl_client *client, -+ const unsigned char **output_r, -+ unsigned int *output_len_r, -+ const char **error_r); -+ -+void sasl_clients_init(void); -+void sasl_clients_deinit(void); -+ -+#endif --- -1.7.10.2 - - -From e8cf58600cb279c9196b82989a3e8f051605dc12 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 06:03:34 +0300 -Subject: [PATCH] imap/pop3-login: Use libsasl for authenticating to remote - IMAP/POP3 server. Also passdb lookup can return - "proxy_mech" extra field to specify which SASL mechanism to - use. - - -diff --git a/src/imap-login/Makefile.am b/src/imap-login/Makefile.am -index ec95a05..5cc5e8c 100644 ---- a/src/imap-login/Makefile.am -+++ b/src/imap-login/Makefile.am -@@ -6,6 +6,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-auth \ -+ -I$(top_srcdir)/src/lib-sasl \ - -I$(top_srcdir)/src/lib-imap \ - -I$(top_srcdir)/src/lib-master \ - -I$(top_srcdir)/src/login-common -diff --git a/src/imap-login/client.h b/src/imap-login/client.h -index 555d7b7..887c0c2 100644 ---- a/src/imap-login/client.h -+++ b/src/imap-login/client.h -@@ -19,7 +19,6 @@ struct imap_client { - unsigned int cmd_finished:1; - unsigned int proxy_sasl_ir:1; - unsigned int proxy_seen_banner:1; -- unsigned int proxy_wait_auth_continue:1; - unsigned int skip_line:1; - unsigned int id_logged:1; - unsigned int client_ignores_capability_resp_code:1; -diff --git a/src/imap-login/imap-proxy.c b/src/imap-login/imap-proxy.c -index 71ca799..e283d48 100644 ---- a/src/imap-login/imap-proxy.c -+++ b/src/imap-login/imap-proxy.c -@@ -9,6 +9,7 @@ - #include "str.h" - #include "str-sanitize.h" - #include "safe-memset.h" -+#include "sasl-client.h" - #include "client.h" - #include "client-authenticate.h" - #include "imap-resp-code.h" -@@ -55,42 +56,55 @@ static void proxy_free_password(struct client *client) - i_free_and_null(client->proxy_password); - } - --static void get_plain_auth(struct client *client, string_t *dest) -+static int proxy_write_login(struct imap_client *client, string_t *str) - { -- string_t *str; -- -- str = t_str_new(128); -- str_append(str, client->proxy_user); -- str_append_c(str, '\0'); -- str_append(str, client->proxy_master_user); -- str_append_c(str, '\0'); -- str_append(str, client->proxy_password); -- base64_encode(str_data(str), str_len(str), dest); --} -+ struct sasl_client_settings sasl_set; -+ const unsigned char *output; -+ unsigned int len; -+ const char *mech_name, *error; - --static void proxy_write_login(struct imap_client *client, string_t *str) --{ - str_append(str, "C CAPABILITY\r\n"); - -- if (client->common.proxy_master_user == NULL) { -+ if (client->common.proxy_mech == NULL) { - /* logging in normally - use LOGIN command */ - str_append(str, "L LOGIN "); - imap_append_string(str, client->common.proxy_user); - str_append_c(str, ' '); - imap_append_string(str, client->common.proxy_password); -+ str_append(str, "\r\n"); - - proxy_free_password(&client->common); -- } else if (client->proxy_sasl_ir) { -- /* master user login with SASL initial response support */ -- str_append(str, "L AUTHENTICATE PLAIN "); -- get_plain_auth(&client->common, str); -- proxy_free_password(&client->common); -- } else { -- /* master user login without SASL initial response */ -- str_append(str, "L AUTHENTICATE PLAIN"); -- client->proxy_wait_auth_continue = TRUE; -+ return 0; -+ } -+ -+ i_assert(client->common.proxy_sasl_client == NULL); -+ memset(&sasl_set, 0, sizeof(sasl_set)); -+ sasl_set.authid = client->common.proxy_user; -+ sasl_set.authzid = client->common.proxy_master_user; -+ sasl_set.password = client->common.proxy_password; -+ client->common.proxy_sasl_client = -+ sasl_client_new(client->common.proxy_mech, &sasl_set); -+ mech_name = sasl_client_mech_get_name(client->common.proxy_mech); -+ -+ str_append(str, "L AUTHENTICATE "); -+ str_append(str, mech_name); -+ if (client->proxy_sasl_ir) { -+ if (sasl_client_output(client->common.proxy_sasl_client, -+ &output, &len, &error) < 0) { -+ client_log_err(&client->common, t_strdup_printf( -+ "proxy: SASL mechanism %s init failed: %s", -+ mech_name, error)); -+ return -1; -+ } -+ str_append_c(str, ' '); -+ if (len == 0) -+ str_append_c(str, '='); -+ else -+ base64_encode(output, len, str); - } - str_append(str, "\r\n"); -+ proxy_free_password(&client->common); -+ return 0; - } - - static int proxy_input_banner(struct imap_client *client, -@@ -126,7 +140,8 @@ static int proxy_input_banner(struct imap_client *client, - } - str_append(str, "S STARTTLS\r\n"); - } else { -- proxy_write_login(client, str); -+ if (proxy_write_login(client, str) < 0) -+ return -1; - } - - o_stream_nsend(output, str_data(str), str_len(str)); -@@ -173,6 +188,10 @@ int imap_proxy_parse_line(struct client *client, const char *line) - struct imap_client *imap_client = (struct imap_client *)client; - struct ostream *output; - string_t *str; -+ const unsigned char *data; -+ unsigned int data_len; -+ const char *error; -+ int ret; - - i_assert(!client->destroyed); - -@@ -188,17 +207,37 @@ int imap_proxy_parse_line(struct client *client, const char *line) - return 0; - } else if (*line == '+') { - /* AUTHENTICATE started. finish it. */ -- if (!imap_client->proxy_wait_auth_continue) { -+ if (client->proxy_sasl_client == NULL) { - /* used literals with LOGIN command, just ignore. */ - return 0; - } - client->proxy_state = IMAP_PROXY_STATE_AUTH_CONTINUE; -- imap_client->proxy_wait_auth_continue = FALSE; - - str = t_str_new(128); -- get_plain_auth(client, str); -+ if (line[1] != ' ' || -+ base64_decode(line+2, strlen(line+2), NULL, str) < 0) { -+ client_log_err(client, -+ "proxy: Server sent invalid base64 data in AUTHENTICATE response"); -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } -+ ret = sasl_client_input(client->proxy_sasl_client, -+ str_data(str), str_len(str), &error); -+ if (ret == 0) { -+ ret = sasl_client_output(client->proxy_sasl_client, -+ &data, &data_len, &error); -+ } -+ if (ret < 0) { -+ client_log_err(client, t_strdup_printf( -+ "proxy: Server sent invalid authentication data: %s", -+ error)); -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } -+ -+ str_truncate(str, 0); -+ base64_encode(data, data_len, str); - str_append(str, "\r\n"); -- proxy_free_password(client); - - o_stream_nsend(output, str_data(str), str_len(str)); - return 0; -@@ -220,7 +259,10 @@ int imap_proxy_parse_line(struct client *client, const char *line) - /* i/ostreams changed. */ - output = login_proxy_get_ostream(client->login_proxy); - str = t_str_new(128); -- proxy_write_login(imap_client, str); -+ if (proxy_write_login(imap_client, str) < 0) { -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } - o_stream_nsend(output, str_data(str), str_len(str)); - return 1; - } else if (strncmp(line, "L OK ", 5) == 0) { -@@ -305,7 +347,6 @@ void imap_proxy_reset(struct client *client) - - imap_client->proxy_sasl_ir = FALSE; - imap_client->proxy_seen_banner = FALSE; -- imap_client->proxy_wait_auth_continue = FALSE; - client->proxy_state = IMAP_PROXY_STATE_NONE; - } - -diff --git a/src/login-common/Makefile.am b/src/login-common/Makefile.am -index 6db44e7..402ae74 100644 ---- a/src/login-common/Makefile.am -+++ b/src/login-common/Makefile.am -@@ -4,6 +4,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-auth \ -+ -I$(top_srcdir)/src/lib-sasl \ - -I$(top_srcdir)/src/lib-master \ - -I$(top_srcdir)/src/lib-ssl-iostream \ - -I$(top_srcdir)/src/lib-mail \ -diff --git a/src/login-common/client-common-auth.c b/src/login-common/client-common-auth.c -index 99c7f34..604c164 100644 ---- a/src/login-common/client-common-auth.c -+++ b/src/login-common/client-common-auth.c -@@ -9,6 +9,7 @@ - #include "time-util.h" - #include "login-proxy.h" - #include "auth-client.h" -+#include "sasl-client.h" - #include "master-service-ssl-settings.h" - #include "client-common.h" - -@@ -104,6 +105,8 @@ static void client_auth_parse_args(struct client *client, - reply_r->proxy_timeout_msecs = 1000*atoi(value); - else if (strcmp(key, "proxy_refresh") == 0) - reply_r->proxy_refresh_secs = atoi(value); -+ else if (strcmp(key, "proxy_mech") == 0) -+ reply_r->proxy_mech = value; - else if (strcmp(key, "master") == 0) - reply_r->master_user = value; - else if (strcmp(key, "ssl") == 0) { -@@ -198,6 +201,8 @@ void client_proxy_failed(struct client *client, bool send_line) - client_proxy_error(client, PROXY_FAILURE_MSG); - } - -+ if (client->proxy_sasl_client != NULL) -+ sasl_client_free(&client->proxy_sasl_client); - login_proxy_free(&client->login_proxy); - proxy_free_password(client); - i_free_and_null(client->proxy_user); -@@ -270,10 +275,13 @@ static int proxy_start(struct client *client, - const struct client_auth_reply *reply) - { - struct login_proxy_settings proxy_set; -+ const struct sasl_client_mech *sasl_mech = NULL; - - i_assert(reply->destuser != NULL); - i_assert(!client->destroyed); -+ i_assert(client->proxy_sasl_client == NULL); - -+ client->proxy_mech = NULL; - client->v.proxy_reset(client); - - if (reply->password == NULL) { -@@ -287,6 +295,20 @@ static int proxy_start(struct client *client, - return -1; - } - -+ if (reply->proxy_mech != NULL) { -+ sasl_mech = sasl_client_mech_find(reply->proxy_mech); -+ if (sasl_mech == NULL) { -+ client_log_err(client, t_strdup_printf( -+ "proxy: Unsupported SASL mechanism %s", -+ reply->proxy_mech)); -+ client_proxy_error(client, PROXY_FAILURE_MSG); -+ return -1; -+ } -+ } else if (reply->master_user != NULL) { -+ /* have to use PLAIN authentication with master user logins */ -+ sasl_mech = &sasl_client_mech_plain; -+ } -+ - i_assert(client->refcount > 1); - - if (client->destroyed) { -@@ -318,6 +340,7 @@ static int proxy_start(struct client *client, - return -1; - } - -+ client->proxy_mech = sasl_mech; - client->proxy_user = i_strdup(reply->destuser); - client->proxy_master_user = i_strdup(reply->master_user); - client->proxy_password = i_strdup(reply->password); -diff --git a/src/login-common/client-common.c b/src/login-common/client-common.c -index e117bea..454b28e 100644 ---- a/src/login-common/client-common.c -+++ b/src/login-common/client-common.c -@@ -18,6 +18,7 @@ - #include "master-service-ssl-settings.h" - #include "master-auth.h" - #include "auth-client.h" -+#include "sasl-client.h" - #include "login-proxy.h" - #include "ssl-proxy.h" - #include "client-common.h" -@@ -209,6 +210,8 @@ void client_destroy(struct client *client, const char *reason) - i_free_and_null(client->proxy_password); - } - -+ if (client->proxy_sasl_client != NULL) -+ sasl_client_free(&client->proxy_sasl_client); - if (client->login_proxy != NULL) - login_proxy_free(&client->login_proxy); - if (client->v.destroy != NULL) -diff --git a/src/login-common/client-common.h b/src/login-common/client-common.h -index 2758808..a73e9fa 100644 ---- a/src/login-common/client-common.h -+++ b/src/login-common/client-common.h -@@ -55,7 +55,7 @@ enum client_auth_result { - struct client_auth_reply { - const char *master_user, *reason; - /* for proxying */ -- const char *host, *hostip, *destuser, *password; -+ const char *host, *hostip, *destuser, *password, *proxy_mech; - unsigned int port; - unsigned int proxy_timeout_msecs; - unsigned int proxy_refresh_secs; -@@ -122,6 +122,8 @@ struct client { - - struct login_proxy *login_proxy; - char *proxy_user, *proxy_master_user, *proxy_password; -+ const struct sasl_client_mech *proxy_mech; -+ struct sasl_client *proxy_sasl_client; - unsigned int proxy_state; - unsigned int proxy_ttl; - -diff --git a/src/login-common/main.c b/src/login-common/main.c -index 0c95949..24b83ed 100644 ---- a/src/login-common/main.c -+++ b/src/login-common/main.c -@@ -13,6 +13,7 @@ - #include "access-lookup.h" - #include "anvil-client.h" - #include "auth-client.h" -+#include "sasl-client.h" - #include "master-service-ssl-settings.h" - #include "ssl-proxy.h" - #include "login-proxy.h" -@@ -281,6 +282,7 @@ static void main_preinit(bool allow_core_dumps) - /* Initialize SSL proxy so it can read certificate and private - key file. */ - ssl_proxy_init(); -+ sasl_clients_init(); - - /* set the number of fds we want to use. it may get increased or - decreased. leave a couple of extra fds for auth sockets and such. -@@ -356,6 +358,7 @@ static void main_deinit(void) - anvil_client_deinit(&anvil); - if (auth_client_to != NULL) - timeout_remove(&auth_client_to); -+ sasl_clients_deinit(); - login_settings_deinit(); - } - -diff --git a/src/pop3-login/Makefile.am b/src/pop3-login/Makefile.am -index 6d2ad73..a3f831c 100644 ---- a/src/pop3-login/Makefile.am -+++ b/src/pop3-login/Makefile.am -@@ -6,6 +6,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-auth \ -+ -I$(top_srcdir)/src/lib-sasl \ - -I$(top_srcdir)/src/lib-master \ - -I$(top_srcdir)/src/login-common - -diff --git a/src/pop3-login/pop3-proxy.c b/src/pop3-login/pop3-proxy.c -index e0d3f25..dd5c7dc 100644 ---- a/src/pop3-login/pop3-proxy.c -+++ b/src/pop3-login/pop3-proxy.c -@@ -8,6 +8,7 @@ - #include "safe-memset.h" - #include "str.h" - #include "str-sanitize.h" -+#include "sasl-client.h" - #include "client.h" - #include "pop3-proxy.h" - -@@ -20,21 +21,12 @@ static void proxy_free_password(struct client *client) - i_free_and_null(client->proxy_password); - } - --static void get_plain_auth(struct client *client, string_t *dest) --{ -- string_t *str; -- -- str = t_str_new(128); -- str_append(str, client->proxy_user); -- str_append_c(str, '\0'); -- str_append(str, client->proxy_master_user); -- str_append_c(str, '\0'); -- str_append(str, client->proxy_password); -- base64_encode(str_data(str), str_len(str), dest); --} -- --static void proxy_send_login(struct pop3_client *client, struct ostream *output) -+static int proxy_send_login(struct pop3_client *client, struct ostream *output) - { -+ struct sasl_client_settings sasl_set; -+ const unsigned char *sasl_output; -+ unsigned int len; -+ const char *mech_name, *error; - string_t *str; - - i_assert(client->common.proxy_ttl > 1); -@@ -52,16 +44,79 @@ static void proxy_send_login(struct pop3_client *client, struct ostream *output) - } - - str = t_str_new(128); -- if (client->common.proxy_master_user == NULL) { -+ if (client->common.proxy_mech == NULL) { - /* send USER command */ - str_append(str, "USER "); - str_append(str, client->common.proxy_user); - str_append(str, "\r\n"); -- } else { -- /* master user login - use AUTH PLAIN. */ -- str_append(str, "AUTH PLAIN\r\n"); -+ o_stream_nsend(output, str_data(str), str_len(str)); -+ return 0; - } -+ -+ i_assert(client->common.proxy_sasl_client == NULL); -+ memset(&sasl_set, 0, sizeof(sasl_set)); -+ sasl_set.authid = client->common.proxy_user; -+ sasl_set.authzid = client->common.proxy_master_user; -+ sasl_set.password = client->common.proxy_password; -+ client->common.proxy_sasl_client = -+ sasl_client_new(client->common.proxy_mech, &sasl_set); -+ mech_name = sasl_client_mech_get_name(client->common.proxy_mech); -+ -+ str_printfa(str, "AUTH %s ", mech_name); -+ if (sasl_client_output(client->common.proxy_sasl_client, -+ &sasl_output, &len, &error) < 0) { -+ client_log_err(&client->common, t_strdup_printf( -+ "proxy: SASL mechanism %s init failed: %s", -+ mech_name, error)); -+ return -1; -+ } -+ if (len == 0) -+ str_append_c(str, '='); -+ else -+ base64_encode(sasl_output, len, str); -+ str_append(str, "\r\n"); - o_stream_nsend(output, str_data(str), str_len(str)); -+ -+ proxy_free_password(&client->common); -+ if (client->common.proxy_state != POP3_PROXY_XCLIENT) -+ client->common.proxy_state = POP3_PROXY_LOGIN2; -+ return 0; -+} -+ -+static int -+pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output, -+ const char *line) -+{ -+ string_t *str; -+ const unsigned char *data; -+ unsigned int data_len; -+ const char *error; -+ int ret; -+ -+ str = t_str_new(128); -+ if (base64_decode(line, strlen(line), NULL, str) < 0) { -+ client_log_err(client, "proxy: Server sent invalid base64 data in AUTH response"); -+ return -1; -+ } -+ ret = sasl_client_input(client->proxy_sasl_client, -+ str_data(str), str_len(str), &error); -+ if (ret == 0) { -+ ret = sasl_client_output(client->proxy_sasl_client, -+ &data, &data_len, &error); -+ } -+ if (ret < 0) { -+ client_log_err(client, t_strdup_printf( -+ "proxy: Server sent invalid authentication data: %s", -+ error)); -+ return -1; -+ } -+ -+ str_truncate(str, 0); -+ base64_encode(data, data_len, str); -+ str_append(str, "\r\n"); -+ -+ o_stream_nsend(output, str_data(str), str_len(str)); -+ return 0; - } - - int pop3_proxy_parse_line(struct client *client, const char *line) -@@ -69,7 +124,6 @@ int pop3_proxy_parse_line(struct client *client, const char *line) - struct pop3_client *pop3_client = (struct pop3_client *)client; - struct ostream *output; - enum login_proxy_ssl_flags ssl_flags; -- string_t *str; - - i_assert(!client->destroyed); - -@@ -89,7 +143,10 @@ int pop3_proxy_parse_line(struct client *client, const char *line) - - ssl_flags = login_proxy_get_ssl_flags(client->login_proxy); - if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) { -- proxy_send_login(pop3_client, output); -+ if (proxy_send_login(pop3_client, output) < 0) { -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } - } else { - o_stream_nsend_str(output, "STLS\r\n"); - client->proxy_state = POP3_PROXY_STARTTLS; -@@ -109,7 +166,10 @@ int pop3_proxy_parse_line(struct client *client, const char *line) - } - /* i/ostreams changed. */ - output = login_proxy_get_ostream(client->login_proxy); -- proxy_send_login(pop3_client, output); -+ if (proxy_send_login(pop3_client, output) < 0) { -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } - return 1; - case POP3_PROXY_XCLIENT: - if (strncmp(line, "+OK", 3) != 0) { -@@ -119,30 +179,31 @@ int pop3_proxy_parse_line(struct client *client, const char *line) - client_proxy_failed(client, TRUE); - return -1; - } -- client->proxy_state = POP3_PROXY_LOGIN1; -+ client->proxy_state = client->proxy_sasl_client == NULL ? -+ POP3_PROXY_LOGIN1 : POP3_PROXY_LOGIN2; - return 0; - case POP3_PROXY_LOGIN1: -- str = t_str_new(128); -- if (client->proxy_master_user == NULL) { -- if (strncmp(line, "+OK", 3) != 0) -- break; -- -- /* USER successful, send PASS */ -- str_append(str, "PASS "); -- str_append(str, client->proxy_password); -- str_append(str, "\r\n"); -- } else { -- if (*line != '+') -- break; -- /* AUTH successful, send the authentication data */ -- get_plain_auth(client, str); -- str_append(str, "\r\n"); -- } -- o_stream_nsend(output, str_data(str), str_len(str)); -+ i_assert(client->proxy_sasl_client == NULL); -+ if (strncmp(line, "+OK", 3) != 0) -+ break; -+ -+ /* USER successful, send PASS */ -+ o_stream_nsend_str(output, t_strdup_printf( -+ "PASS %s\r\n", client->proxy_password)); - proxy_free_password(client); - client->proxy_state = POP3_PROXY_LOGIN2; - return 0; - case POP3_PROXY_LOGIN2: -+ if (strncmp(line, "+ ", 2) == 0 && -+ client->proxy_sasl_client != NULL) { -+ /* continue SASL authentication */ -+ if (pop3_proxy_continue_sasl_auth(client, output, -+ line+2) < 0) { -+ client_proxy_failed(client, TRUE); -+ return -1; -+ } -+ return 0; -+ } - if (strncmp(line, "+OK", 3) != 0) - break; - --- -1.7.10.2 - - -From 0aa8cb62b76627b2df2e2ee7829e9401ca742a09 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 14:53:31 +0300 -Subject: [PATCH] lib-storage: Fixed crashes caused by recent "multiple - storages per namespace" change. - - -diff --git a/src/lib-storage/index/shared/shared-storage.c b/src/lib-storage/index/shared/shared-storage.c -index a6a76f3..12a2903 100644 ---- a/src/lib-storage/index/shared/shared-storage.c -+++ b/src/lib-storage/index/shared/shared-storage.c -@@ -289,6 +289,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns, - NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN | - NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY; - new_ns->mail_set = _storage->set; -+ i_array_init(&new_ns->all_storages, 2); - - location = t_str_new(256); - if (ret > 0) -diff --git a/src/lib-storage/mail-namespace.c b/src/lib-storage/mail-namespace.c -index a6ede7a..f0176f4 100644 ---- a/src/lib-storage/mail-namespace.c -+++ b/src/lib-storage/mail-namespace.c -@@ -408,6 +408,7 @@ int mail_namespaces_init_location(struct mail_user *user, const char *location, - ns->flags = NAMESPACE_FLAG_INBOX_USER | NAMESPACE_FLAG_INBOX_ANY | - NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS; - ns->owner = user; -+ i_array_init(&ns->all_storages, 2); - - inbox_set = p_new(user->pool, struct mail_namespace_settings, 1); - *inbox_set = mail_namespace_default_settings; -@@ -489,6 +490,7 @@ struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user) - ns->flags = NAMESPACE_FLAG_INBOX_USER | NAMESPACE_FLAG_INBOX_ANY | - NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS; - ns->mail_set = mail_user_set_get_storage_set(user); -+ i_array_init(&ns->all_storages, 2); - user->namespaces = ns; - return ns; - } --- -1.7.10.2 - - -From b59b76cfa2c519df0f4d7cdf90a9eed08af62180 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 14:56:36 +0300 -Subject: [PATCH] acl: Crashfix - - -diff --git a/src/plugins/acl/acl-backend-vfile.c b/src/plugins/acl/acl-backend-vfile.c -index 54426d8..07f36a0 100644 ---- a/src/plugins/acl/acl-backend-vfile.c -+++ b/src/plugins/acl/acl-backend-vfile.c -@@ -144,7 +144,7 @@ acl_backend_vfile_get_local_dir(struct acl_backend *backend, - /* ACL files are very important. try to keep them among the main - mail files. that's not possible though with a) if the mailbox is - a file or b) if the mailbox path doesn't point to filesystem. */ -- vname = mailbox_list_get_vname(backend->list, name); -+ vname = name == NULL ? "" : mailbox_list_get_vname(backend->list, name); - if (mailbox_list_get_storage(&list, vname, &storage) < 0) - return NULL; - i_assert(list == ns->list); --- -1.7.10.2 - - -From 8df64f6ec997b8ce0b9896d6eb926fe50bd3a874 Mon Sep 17 00:00:00 2001 -From: Timo Sirainen -Date: Sun, 9 Jun 2013 21:06:49 +0300 -Subject: [PATCH] man: Recent change accidentally changed LGPLv2.1 -> - LGPLv2.2, reverted. - - -diff --git a/doc/man/dovecot.1.in b/doc/man/dovecot.1.in -index 751c172..b2eac57 100644 ---- a/doc/man/dovecot.1.in -+++ b/doc/man/dovecot.1.in -@@ -148,7 +148,7 @@ Configuration files of different services and settings. - .SH AUTHOR - Dovecot and its manual pages were written by the - Dovecot authors , mainly Timo Sirainen , and are licensed under the terms of the MIT and LGPLv2.2 -+at iki.fi>, and are licensed under the terms of the MIT and LGPLv2.1 - licenses, see for details. - .\"------------------------------------------------------------------------ - .SH SEE ALSO --- -1.7.10.2 - diff --git a/mail/dovecot/dovecot.desc b/mail/dovecot/dovecot.desc index 95919d220..df264d7c9 100644 --- a/mail/dovecot/dovecot.desc +++ b/mail/dovecot/dovecot.desc @@ -33,12 +33,12 @@ [L] LGPL MIT [S] Stable -[V] 2.2.2 +[V] 2.2.3 [P] X -----5---9 194.300 [CV-URL] http://www.dovecot.org/download.html -[D] 1142849094 dovecot-2.2.2.tar.gz http://dovecot.org/releases/2.2/ +[D] 3030261749 dovecot-2.2.3.tar.gz http://dovecot.org/releases/2.2/ # development version #[D] 831575579 dovecot-2.2-82ce71d8625c.tar.bz2 !http://hg.dovecot.org/dovecot-2.2/archive/82ce71d8625c.tar.bz2 #[D] 2417517696 dovecot-unicodedata-2012-08-08.txt !http://www.unicode.org/Public/UNIDATA/UnicodeData.txt