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.
 
 
 
 
 
 

3730 lines
128 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
From bdd2a13e6d7292808def824df21f6372411f1064 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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 <tss@iki.fi>
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