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.
2193 lines
77 KiB
2193 lines
77 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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <stephan@rename-it.nl> |
|
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 <stephan@rename-it.nl> |
|
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 <stephan@rename-it.nl> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 <tss@iki.fi> |
|
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 |
|
|
|
|