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
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 |
|
|
|
|