You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7177 lines
244 KiB

# --- 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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <ctype.h>
#include <sys/wait.h>
-#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 <secs>] [-m <mailbox>] [-n <namespace>] [-s <state>] <dest>"
+ "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-x <exclude>] [-s <state>] <dest>"
};
struct doveadm_mail_cmd cmd_dsync_backup = {
cmd_dsync_backup_alloc, "backup",
- "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-s <state>] <dest>"
+ "[-dfR] [-l <secs>] [-m <mailbox>] [-n <namespace>] [-x <exclude>] [-s <state>] <dest>"
};
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <unistd.h>
#include <ctype.h>
-#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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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, "<lmtp DATA>");
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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 <[email protected]>
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