From pigeonhole at rename-it.nl Thu Jan 1 16:17:13 2015 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Thu, 01 Jan 2015 17:17:13 +0100 Subject: dovecot-2.2-pigeonhole: lib-sieve: Added more debug output to bi... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/1bcac73bab61 changeset: 1983:1bcac73bab61 user: Stephan Bosch date: Thu Jan 01 17:12:17 2015 +0100 description: lib-sieve: Added more debug output to binary up-to-date checking. diffstat: src/lib-sieve/sieve-binary.c | 24 +++++++++++++++++++++--- src/lib-sieve/storage/file/sieve-file-script.c | 14 ++++++++++++-- 2 files changed, 33 insertions(+), 5 deletions(-) diffs (82 lines): diff -r b6c55ac6460d -r 1bcac73bab61 src/lib-sieve/sieve-binary.c --- a/src/lib-sieve/sieve-binary.c Tue Dec 30 23:01:04 2014 +0100 +++ b/src/lib-sieve/sieve-binary.c Thu Jan 01 17:12:17 2015 +0100 @@ -315,22 +315,40 @@ struct sieve_binary_block *sblock; sieve_size_t offset = 0; unsigned int ext_count, i; + int ret; i_assert(sbin->file != NULL); sblock = sieve_binary_block_get(sbin, SBIN_SYSBLOCK_SCRIPT_DATA); - if ( sblock == NULL || sbin->script == NULL || - sieve_script_binary_read_metadata(sbin->script, sblock, &offset) <= 0 ) + if ( sblock == NULL || sbin->script == NULL ) return FALSE; + if ( (ret=sieve_script_binary_read_metadata + (sbin->script, sblock, &offset)) <= 0 ) { + if (ret < 0) { + sieve_sys_debug(sbin->svinst, "binary up-to-date: " + "failed to read script metadata from binary %s", + sbin->path); + } else { + sieve_sys_debug(sbin->svinst, "binary up-to-date: " + "script metadata indicates that binary %s is not up-to-date", + sbin->path); + } + return FALSE; + } + regs = array_get(&sbin->extensions, &ext_count); for ( i = 0; i < ext_count; i++ ) { const struct sieve_binary_extension *binext = regs[i]->binext; if ( binext != NULL && binext->binary_up_to_date != NULL && !binext->binary_up_to_date - (regs[i]->extension, sbin, regs[i]->context, cpflags) ) + (regs[i]->extension, sbin, regs[i]->context, cpflags) ) { + sieve_sys_debug(sbin->svinst, "binary up-to-date: " + "the %s extension indicates binary %s is not up-to-date", + sieve_extension_name(regs[i]->extension), sbin->path); return FALSE; + } } return TRUE; diff -r b6c55ac6460d -r 1bcac73bab61 src/lib-sieve/storage/file/sieve-file-script.c --- a/src/lib-sieve/storage/file/sieve-file-script.c Tue Dec 30 23:01:04 2014 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-script.c Thu Jan 01 17:12:17 2015 +0100 @@ -5,6 +5,7 @@ #include "mempool.h" #include "abspath.h" #include "istream.h" +#include "time-util.h" #include "eacces-error.h" #include "sieve-binary.h" @@ -475,12 +476,21 @@ sieve_size_t *offset ATTR_UNUSED) { struct sieve_file_script *fscript = (struct sieve_file_script *)script; + struct sieve_instance *svinst = script->storage->svinst; struct sieve_binary *sbin = sieve_binary_block_get_binary(sblock); - time_t time = ( fscript->st.st_mtime > fscript->lnk_st.st_mtime ? + time_t bmtime = sieve_binary_mtime(sbin); + time_t smtime = ( fscript->st.st_mtime > fscript->lnk_st.st_mtime ? fscript->st.st_mtime : fscript->lnk_st.st_mtime ); - if ( sieve_binary_mtime(sbin) <= time ) + if ( bmtime <= smtime ) { + if (svinst->debug) { + sieve_script_sys_debug(script, + "Sieve binary is not newer than the Sieve script (%s <= %s)", + t_strflocaltime("%Y-%m-%d %H:%M:%S", bmtime), + t_strflocaltime("%Y-%m-%d %H:%M:%S", smtime)); + } return 0; + } return 1; } From dovecot at dovecot.org Mon Jan 5 20:20:34 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:20:34 +0000 Subject: dovecot-2.2: lib: array - new linear search helper Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/1bbec03202e0 changeset: 18132:1bbec03202e0 user: Phil Carmody date: Mon Jan 05 22:12:48 2015 +0200 description: lib: array - new linear search helper There are large numbers of array_foreach loops which do nothing but search for the first element which matches some key. This can be abstracted out into a helper. Signed-off-by: Phil Carmody diffstat: src/lib/array.c | 16 ++++++++++++++++ src/lib/array.h | 20 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 0 deletions(-) diffs (51 lines): diff -r 6078354e6238 -r 1bbec03202e0 src/lib/array.c --- a/src/lib/array.c Fri Dec 26 17:28:30 2014 +0200 +++ b/src/lib/array.c Mon Jan 05 22:12:48 2015 +0200 @@ -138,3 +138,19 @@ return bsearch(key, array->buffer->data, count, array->element_size, cmp); } + +const void *array_lsearch_i(const struct array *array, const void *key, + int (*cmp)(const void *, const void *)) +{ + const void * const data = buffer_get_data(array->buffer, NULL); + const unsigned int s = array->element_size; + unsigned int idx; + + for (idx = 0; idx < array_count_i(array); idx++) { + if (cmp(key, CONST_PTR_OFFSET(data, idx * s)) == 0) { + return PTR_OFFSET(data, idx * s); + } + } + + return NULL; +} diff -r 6078354e6238 -r 1bbec03202e0 src/lib/array.h --- a/src/lib/array.h Fri Dec 26 17:28:30 2014 +0200 +++ b/src/lib/array.h Mon Jan 05 22:12:48 2015 +0200 @@ -316,4 +316,24 @@ typeof(*(array)->v))), \ (const void *)key, (int (*)(const void *, const void *))cmp) +/* Returns pointer to first element for which cmp(key,elem)==0, or NULL */ +const void *array_lsearch_i(const struct array *array, const void *key, + int (*cmp)(const void *, const void *)); +static inline void *array_lsearch_modifiable_i(struct array *array, const void *key, + int (*cmp)(const void *, const void *)) +{ + return (void *)array_lsearch_i(array, key, cmp); +} +#define ARRAY_LSEARCH_CALL(modifiable, array, key, cmp) \ + array_lsearch##modifiable##i( \ + &(array)->arr + \ + CALLBACK_TYPECHECK(cmp, int (*)(typeof(const typeof(*key) *), \ + typeof(*(array)->v))), \ + (const void *)key, \ + (int (*)(const void *, const void *))cmp) +#define array_lsearch(array, key, cmp) \ + ARRAY_TYPE_CAST_CONST(array)ARRAY_LSEARCH_CALL(_, array, key, cmp) +#define array_lsearch_modifiable(array, key, cmp) \ + ARRAY_TYPE_CAST_MODIFIABLE(array)ARRAY_LSEARCH_CALL(_modifiable_, array, key, cmp) + #endif From dovecot at dovecot.org Mon Jan 5 20:20:34 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:20:34 +0000 Subject: dovecot-2.2: lib: test-array - test new lsearch helper Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/fa815914dce6 changeset: 18133:fa815914dce6 user: Phil Carmody date: Mon Jan 05 22:13:59 2015 +0200 description: lib: test-array - test new lsearch helper Just piggy-back on to the current reverse test, as that's got an array nicely set up for us already. Signed-off-by: Phil Carmody diffstat: src/lib/test-array.c | 19 ++++++++++++++++++- 1 files changed, 18 insertions(+), 1 deletions(-) diffs (40 lines): diff -r 1bbec03202e0 -r fa815914dce6 src/lib/test-array.c --- a/src/lib/test-array.c Mon Jan 05 22:12:48 2015 +0200 +++ b/src/lib/test-array.c Mon Jan 05 22:13:59 2015 +0200 @@ -32,11 +32,17 @@ test_end(); } +static int test_int_compare(const int *key, const int *elem) +{ + return (*key < *elem) ? -1 : + (*key > *elem) ? 1 : + 0; +} static void test_array_reverse(void) { ARRAY(int) intarr; int input[] = { -1234567890, -272585721, 272485922, 824725652 }; - const int *output; + const int tmpi = 999, *output; unsigned int i, j; test_begin("array reverse"); @@ -51,6 +57,17 @@ test_assert(input[i-j-1] == output[j]); } test_end(); + + test_begin("array_lsearch"); + for (i = 0; i < N_ELEMENTS(input); i++) { + output = array_lsearch(&intarr, &input[i], test_int_compare); + test_assert(output != NULL); + j = array_ptr_to_idx(&intarr, output); + test_assert_idx(j == N_ELEMENTS(input) - 1 - i, i); + } + output = array_lsearch(&intarr, &tmpi, test_int_compare); + test_assert(output == NULL); + test_end(); } static int test_compare_ushort(const unsigned short *c1, const unsigned short *c2) { From dovecot at dovecot.org Mon Jan 5 20:20:40 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:20:40 +0000 Subject: dovecot-2.2: lib: array - explain implications of ARRAY_TYPE() i... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/17ec2a11cf44 changeset: 18134:17ec2a11cf44 user: Phil Carmody date: Mon Jan 05 22:15:07 2015 +0200 description: lib: array - explain implications of ARRAY_TYPE() in comment If you use ARRAY_TYPE() to pass an array around, then you must also use ARRAY_TYPE() to define the array itself, ARRAY() will no longer do. Reported-by: Arnt Gulbrandsen Signed-off-by: Phil Carmody diffstat: src/lib/array.h | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diffs (29 lines): diff -r fa815914dce6 -r 17ec2a11cf44 src/lib/array.h --- a/src/lib/array.h Mon Jan 05 22:13:59 2015 +0200 +++ b/src/lib/array.h Mon Jan 05 22:15:07 2015 +0200 @@ -20,14 +20,22 @@ If you want to pass an array as a parameter to a function, you'll need to create a type for the array using ARRAY_DEFINE_TYPE() and use the type in - the parameter using ARRAY_TYPE(). + the parameter using ARRAY_TYPE(). Any arrays that you want to be passing + around, such as structure members as in the above example, must also be + defined using ARRAY_TYPE() too, rather than ARRAY(). Example: ARRAY_DEFINE_TYPE(foo, struct foo); - void do_foo(ARRAY_TYPE(foo) *bars) { - struct foo *foo = array_idx(bars, 0); + void do_foo(ARRAY_TYPE(foo) *foos) { + struct foo *foo = array_idx(foos, 0); } + struct foo_manager { + ARRAY_TYPE(foo) foos; // pedantically, ARRAY(struct foo) is a different type + }; + // ... + do_foo(&my_foo_manager->foos); // No compiler warning about mismatched types + */ #include "array-decl.h" #include "buffer.h" From dovecot at dovecot.org Mon Jan 5 20:20:50 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:20:50 +0000 Subject: dovecot-2.2: lib: guid - declare some functions as pure Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4f0f1e10cb53 changeset: 18135:4f0f1e10cb53 user: Phil Carmody date: Mon Jan 05 22:15:31 2015 +0200 description: lib: guid - declare some functions as pure As the functions aren't inline, the compiler can't know if they can be optimised away, so give it a helping hand. Signed-off-by: Phil Carmody diffstat: src/lib/guid.h | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diffs (26 lines): diff -r 17ec2a11cf44 -r 4f0f1e10cb53 src/lib/guid.h --- a/src/lib/guid.h Mon Jan 05 22:15:07 2015 +0200 +++ b/src/lib/guid.h Mon Jan 05 22:15:31 2015 +0200 @@ -11,9 +11,9 @@ /* Generate 128 bit GUID */ void guid_128_generate(guid_128_t guid_r); /* Returns TRUE if GUID is empty (not set / unknown). */ -bool guid_128_is_empty(const guid_128_t guid); +bool guid_128_is_empty(const guid_128_t guid) ATTR_PURE; /* Returns TRUE if two GUIDs are equal. */ -bool guid_128_equals(const guid_128_t guid1, const guid_128_t guid2); +bool guid_128_equals(const guid_128_t guid1, const guid_128_t guid2) ATTR_PURE; /* Copy GUID */ static inline void guid_128_copy(guid_128_t dest, const guid_128_t src) { @@ -26,8 +26,8 @@ int guid_128_from_string(const char *str, guid_128_t guid_r); /* guid_128 hash/cmp functions for hash.h */ -unsigned int guid_128_hash(const guid_128_t guid); -int guid_128_cmp(const guid_128_t guid1, const guid_128_t guid2); +unsigned int guid_128_hash(const guid_128_t guid) ATTR_PURE; +int guid_128_cmp(const guid_128_t guid1, const guid_128_t guid2) ATTR_PURE; /* Return the hash of host used by guid_128_generate(). */ void guid_128_host_hash_get(const char *host, From dovecot at dovecot.org Mon Jan 5 20:20:50 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:20:50 +0000 Subject: dovecot-2.2: lib: guid - centralise a 'reset to the empty value'... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ff30ec13fcb7 changeset: 18136:ff30ec13fcb7 user: Phil Carmody date: Mon Jan 05 22:16:59 2015 +0200 description: lib: guid - centralise a 'reset to the empty value' helper function This helper just ensures that the caller never has to get the sizeof() right. (Were a guid passed as a function parameter, mistakes could happen.) Signed-off-by: Phil Carmody diffstat: src/lib/guid.h | 4 ++++ src/lib/test-guid.c | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diffs (43 lines): diff -r 4f0f1e10cb53 -r ff30ec13fcb7 src/lib/guid.h --- a/src/lib/guid.h Mon Jan 05 22:15:31 2015 +0200 +++ b/src/lib/guid.h Mon Jan 05 22:16:59 2015 +0200 @@ -12,6 +12,10 @@ void guid_128_generate(guid_128_t guid_r); /* Returns TRUE if GUID is empty (not set / unknown). */ bool guid_128_is_empty(const guid_128_t guid) ATTR_PURE; +static inline void guid_128_empty(guid_128_t guid) +{ + memset(guid, 0, GUID_128_SIZE); +} /* Returns TRUE if two GUIDs are equal. */ bool guid_128_equals(const guid_128_t guid1, const guid_128_t guid2) ATTR_PURE; /* Copy GUID */ diff -r 4f0f1e10cb53 -r ff30ec13fcb7 src/lib/test-guid.c --- a/src/lib/test-guid.c Mon Jan 05 22:15:31 2015 +0200 +++ b/src/lib/test-guid.c Mon Jan 05 22:16:59 2015 +0200 @@ -10,13 +10,11 @@ 0xab, 0xcd, 0xef, 0xAB, 0xCD, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00 }; - guid_128_t guid1, guid2, guid3, empty_guid; + guid_128_t guid1, guid2, guid3; const char *str; char guidbuf[GUID_128_SIZE*2 + 2]; unsigned int i; - memset(empty_guid, 0, sizeof(empty_guid)); - test_begin("guid_128_generate()"); guid_128_generate(guid1); guid_128_generate(guid2); @@ -27,7 +25,9 @@ test_begin("guid_128_is_empty()"); test_assert(!guid_128_is_empty(guid1)); test_assert(!guid_128_is_empty(guid2)); - test_assert(guid_128_is_empty(empty_guid)); + guid_128_generate(guid3); + guid_128_empty(guid3); + test_assert(guid_128_is_empty(guid3)); test_end(); test_begin("guid_128_copy()"); From dovecot at dovecot.org Mon Jan 5 20:27:16 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 05 Jan 2015 20:27:16 +0000 Subject: dovecot-2.2: global: freshen copyright Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3009a1a6f6d5 changeset: 18137:3009a1a6f6d5 user: Phil Carmody date: Mon Jan 05 22:20:10 2015 +0200 description: global: freshen copyright Robomatically: git ls-files | xargs perl -p -i -e 's/(\d+)-201[0-4]/$1-2015/g;s/ (201[0-4]) Dovecot/ $1-2015 Dovecot/' Happy 2015 everyone! Signed-off-by: Phil Carmody diffstat: doc/man/doveadm-acl.1.in | 2 +- doc/man/doveadm-altmove.1.in | 2 +- doc/man/doveadm-auth.1.in | 2 +- doc/man/doveadm-batch.1.in | 2 +- doc/man/doveadm-deduplicate.1.in | 2 +- doc/man/doveadm-director.1.in | 2 +- doc/man/doveadm-dump.1.in | 2 +- doc/man/doveadm-exec.1.in | 2 +- doc/man/doveadm-expunge.1.in | 2 +- doc/man/doveadm-fetch.1.in | 2 +- doc/man/doveadm-flags.1.in | 2 +- doc/man/doveadm-force-resync.1.in | 2 +- doc/man/doveadm-fts.1.in | 2 +- doc/man/doveadm-help.1.in | 2 +- doc/man/doveadm-import.1.in | 2 +- doc/man/doveadm-index.1.in | 2 +- doc/man/doveadm-instance.1.in | 2 +- doc/man/doveadm-kick.1.in | 2 +- doc/man/doveadm-log.1.in | 2 +- doc/man/doveadm-mailbox.1.in | 2 +- doc/man/doveadm-mount.1.in | 2 +- doc/man/doveadm-move.1.in | 2 +- doc/man/doveadm-penalty.1.in | 2 +- doc/man/doveadm-proxy.1.in | 2 +- doc/man/doveadm-purge.1.in | 2 +- doc/man/doveadm-pw.1.in | 2 +- doc/man/doveadm-quota.1.in | 2 +- doc/man/doveadm-replicator.1.in | 2 +- doc/man/doveadm-search-query.7 | 2 +- doc/man/doveadm-search.1.in | 2 +- doc/man/doveadm-sync.1.in | 2 +- doc/man/doveadm-user.1.in | 2 +- doc/man/doveadm-who.1.in | 2 +- doc/man/doveadm.1.in | 2 +- doc/man/doveconf.1.in | 2 +- doc/man/dovecot-lda.1.in | 2 +- doc/man/dovecot.1.in | 2 +- src/anvil/anvil-connection.c | 2 +- src/anvil/anvil-settings.c | 2 +- src/anvil/connect-limit.c | 2 +- src/anvil/main.c | 2 +- src/anvil/penalty.c | 2 +- src/anvil/test-penalty.c | 2 +- src/auth/auth-cache.c | 2 +- src/auth/auth-client-connection.c | 2 +- src/auth/auth-fields.c | 2 +- src/auth/auth-master-connection.c | 2 +- src/auth/auth-penalty.c | 2 +- src/auth/auth-postfix-connection.c | 2 +- src/auth/auth-request-handler.c | 2 +- src/auth/auth-request.c | 2 +- src/auth/auth-settings.c | 2 +- src/auth/auth-token.c | 2 +- src/auth/auth-worker-client.c | 2 +- src/auth/auth-worker-server.c | 2 +- src/auth/auth.c | 2 +- src/auth/db-checkpassword.c | 2 +- src/auth/db-dict-cache-key.c | 2 +- src/auth/db-dict.c | 2 +- src/auth/db-ldap.c | 2 +- src/auth/db-passwd-file.c | 2 +- src/auth/db-sql.c | 2 +- src/auth/main.c | 2 +- src/auth/mech-anonymous.c | 2 +- src/auth/mech-cram-md5.c | 2 +- src/auth/mech-digest-md5.c | 2 +- src/auth/mech-dovecot-token.c | 2 +- src/auth/mech-external.c | 2 +- src/auth/mech-plain.c | 2 +- src/auth/mech-scram-sha1.c | 2 +- src/auth/mech.c | 2 +- src/auth/passdb-blocking.c | 2 +- src/auth/passdb-bsdauth.c | 2 +- src/auth/passdb-cache.c | 2 +- src/auth/passdb-checkpassword.c | 2 +- src/auth/passdb-dict.c | 2 +- src/auth/passdb-imap.c | 2 +- src/auth/passdb-ldap.c | 2 +- src/auth/passdb-passwd-file.c | 2 +- src/auth/passdb-passwd.c | 2 +- src/auth/passdb-shadow.c | 2 +- src/auth/passdb-sql.c | 2 +- src/auth/passdb-static.c | 2 +- src/auth/passdb-template.c | 2 +- src/auth/passdb-vpopmail.c | 2 +- src/auth/passdb.c | 2 +- src/auth/password-scheme-crypt.c | 2 +- src/auth/password-scheme.c | 2 +- src/auth/test-auth-cache.c | 2 +- src/auth/test-db-dict.c | 2 +- src/auth/userdb-blocking.c | 2 +- src/auth/userdb-checkpassword.c | 2 +- src/auth/userdb-dict.c | 2 +- src/auth/userdb-ldap.c | 2 +- src/auth/userdb-nss.c | 2 +- src/auth/userdb-passwd-file.c | 2 +- src/auth/userdb-passwd.c | 2 +- src/auth/userdb-prefetch.c | 2 +- src/auth/userdb-sql.c | 2 +- src/auth/userdb-static.c | 2 +- src/auth/userdb-template.c | 2 +- src/auth/userdb-vpopmail.c | 2 +- src/auth/userdb.c | 2 +- src/config/config-connection.c | 2 +- src/config/config-filter.c | 2 +- src/config/config-parser.c | 2 +- src/config/config-request.c | 2 +- src/config/config-settings.c | 2 +- src/config/doveconf.c | 2 +- src/config/main.c | 2 +- src/config/old-set-parser.c | 2 +- src/config/sysinfo-get.c | 2 +- src/dict/dict-commands.c | 2 +- src/dict/dict-connection.c | 2 +- src/dict/dict-settings.c | 2 +- src/dict/main.c | 2 +- src/director/auth-connection.c | 2 +- src/director/director-connection.c | 2 +- src/director/director-host.c | 2 +- src/director/director-request.c | 2 +- src/director/director-settings.c | 2 +- src/director/director-test.c | 2 +- src/director/director.c | 2 +- src/director/doveadm-connection.c | 2 +- src/director/login-connection.c | 2 +- src/director/mail-host.c | 2 +- src/director/main.c | 2 +- src/director/notify-connection.c | 2 +- src/director/test-user-directory.c | 2 +- src/director/user-directory.c | 2 +- src/dns/dns-client-settings.c | 2 +- src/dns/dns-client.c | 2 +- src/doveadm/client-connection.c | 2 +- src/doveadm/doveadm-auth.c | 2 +- src/doveadm/doveadm-cmd.c | 2 +- src/doveadm/doveadm-dict.c | 2 +- src/doveadm/doveadm-director.c | 2 +- src/doveadm/doveadm-dsync.c | 2 +- src/doveadm/doveadm-dump-dbox.c | 2 +- src/doveadm/doveadm-dump-index.c | 2 +- src/doveadm/doveadm-dump-log.c | 2 +- src/doveadm/doveadm-dump-mailboxlog.c | 2 +- src/doveadm/doveadm-dump-thread.c | 2 +- src/doveadm/doveadm-dump.c | 2 +- src/doveadm/doveadm-fs.c | 2 +- src/doveadm/doveadm-instance.c | 2 +- src/doveadm/doveadm-kick.c | 2 +- src/doveadm/doveadm-log.c | 2 +- src/doveadm/doveadm-mail-altmove.c | 2 +- src/doveadm/doveadm-mail-batch.c | 2 +- src/doveadm/doveadm-mail-copymove.c | 2 +- src/doveadm/doveadm-mail-deduplicate.c | 2 +- src/doveadm/doveadm-mail-expunge.c | 2 +- src/doveadm/doveadm-mail-fetch.c | 2 +- src/doveadm/doveadm-mail-flags.c | 2 +- src/doveadm/doveadm-mail-import.c | 2 +- src/doveadm/doveadm-mail-index.c | 2 +- src/doveadm/doveadm-mail-iter.c | 2 +- src/doveadm/doveadm-mail-mailbox-metadata.c | 2 +- src/doveadm/doveadm-mail-mailbox-status.c | 2 +- src/doveadm/doveadm-mail-mailbox.c | 2 +- src/doveadm/doveadm-mail-search.c | 2 +- src/doveadm/doveadm-mail-server.c | 2 +- src/doveadm/doveadm-mail.c | 2 +- src/doveadm/doveadm-mailbox-list-iter.c | 2 +- src/doveadm/doveadm-master.c | 2 +- src/doveadm/doveadm-mount.c | 2 +- src/doveadm/doveadm-mutf7.c | 2 +- src/doveadm/doveadm-penalty.c | 2 +- src/doveadm/doveadm-print-flow.c | 2 +- src/doveadm/doveadm-print-pager.c | 2 +- src/doveadm/doveadm-print-server.c | 2 +- src/doveadm/doveadm-print-tab.c | 2 +- src/doveadm/doveadm-print-table.c | 2 +- src/doveadm/doveadm-print.c | 2 +- src/doveadm/doveadm-proxy.c | 2 +- src/doveadm/doveadm-pw.c | 2 +- src/doveadm/doveadm-replicator.c | 2 +- src/doveadm/doveadm-settings.c | 2 +- src/doveadm/doveadm-sis.c | 2 +- src/doveadm/doveadm-stats.c | 2 +- src/doveadm/doveadm-util.c | 2 +- src/doveadm/doveadm-who.c | 2 +- src/doveadm/doveadm-zlib.c | 2 +- src/doveadm/doveadm.c | 2 +- src/doveadm/dsync/dsync-brain-mailbox-tree-sync.c | 2 +- src/doveadm/dsync/dsync-brain-mailbox-tree.c | 2 +- src/doveadm/dsync/dsync-brain-mailbox.c | 2 +- src/doveadm/dsync/dsync-brain-mails.c | 2 +- src/doveadm/dsync/dsync-brain.c | 2 +- src/doveadm/dsync/dsync-deserializer.c | 2 +- src/doveadm/dsync/dsync-ibc-pipe.c | 2 +- src/doveadm/dsync/dsync-ibc-stream.c | 2 +- src/doveadm/dsync/dsync-ibc.c | 2 +- src/doveadm/dsync/dsync-mail.c | 2 +- src/doveadm/dsync/dsync-mailbox-export.c | 2 +- src/doveadm/dsync/dsync-mailbox-import.c | 2 +- src/doveadm/dsync/dsync-mailbox-state.c | 2 +- src/doveadm/dsync/dsync-mailbox-tree-fill.c | 2 +- src/doveadm/dsync/dsync-mailbox-tree-sync.c | 2 +- src/doveadm/dsync/dsync-mailbox-tree.c | 2 +- src/doveadm/dsync/dsync-mailbox.c | 2 +- src/doveadm/dsync/dsync-serializer.c | 2 +- src/doveadm/dsync/dsync-transaction-log-scan.c | 2 +- src/doveadm/dsync/test-dsync-mailbox-tree-sync.c | 2 +- src/doveadm/main.c | 2 +- src/doveadm/server-connection.c | 2 +- src/imap-login/client-authenticate.c | 2 +- src/imap-login/client.c | 2 +- src/imap-login/imap-login-settings.c | 2 +- src/imap-login/imap-proxy.c | 2 +- src/imap-urlauth/imap-urlauth-client.c | 2 +- src/imap-urlauth/imap-urlauth-login-settings.c | 2 +- src/imap-urlauth/imap-urlauth-login.c | 2 +- src/imap-urlauth/imap-urlauth-settings.c | 2 +- src/imap-urlauth/imap-urlauth-worker-settings.c | 2 +- src/imap-urlauth/imap-urlauth-worker.c | 2 +- src/imap-urlauth/imap-urlauth.c | 2 +- src/imap/cmd-append.c | 2 +- src/imap/cmd-cancelupdate.c | 2 +- src/imap/cmd-capability.c | 2 +- src/imap/cmd-check.c | 2 +- src/imap/cmd-close.c | 2 +- src/imap/cmd-copy.c | 2 +- src/imap/cmd-create.c | 2 +- src/imap/cmd-delete.c | 2 +- src/imap/cmd-enable.c | 2 +- src/imap/cmd-examine.c | 2 +- src/imap/cmd-expunge.c | 2 +- src/imap/cmd-fetch.c | 2 +- src/imap/cmd-genurlauth.c | 2 +- src/imap/cmd-getmetadata.c | 2 +- src/imap/cmd-id.c | 2 +- src/imap/cmd-idle.c | 2 +- src/imap/cmd-list.c | 2 +- src/imap/cmd-logout.c | 2 +- src/imap/cmd-lsub.c | 2 +- src/imap/cmd-namespace.c | 2 +- src/imap/cmd-noop.c | 2 +- src/imap/cmd-notify.c | 2 +- src/imap/cmd-rename.c | 2 +- src/imap/cmd-resetkey.c | 2 +- src/imap/cmd-search.c | 2 +- src/imap/cmd-select.c | 2 +- src/imap/cmd-setmetadata.c | 2 +- src/imap/cmd-sort.c | 2 +- src/imap/cmd-status.c | 2 +- src/imap/cmd-store.c | 2 +- src/imap/cmd-subscribe.c | 2 +- src/imap/cmd-thread.c | 2 +- src/imap/cmd-unselect.c | 2 +- src/imap/cmd-unsubscribe.c | 2 +- src/imap/cmd-urlfetch.c | 2 +- src/imap/cmd-x-cancel.c | 2 +- src/imap/imap-client.c | 2 +- src/imap/imap-commands-util.c | 2 +- src/imap/imap-commands.c | 2 +- src/imap/imap-expunge.c | 2 +- src/imap/imap-fetch-body.c | 2 +- src/imap/imap-fetch.c | 2 +- src/imap/imap-list.c | 2 +- src/imap/imap-notify.c | 2 +- src/imap/imap-search-args.c | 2 +- src/imap/imap-search.c | 2 +- src/imap/imap-settings.c | 2 +- src/imap/imap-status.c | 2 +- src/imap/imap-sync.c | 2 +- src/imap/mail-storage-callbacks.c | 2 +- src/imap/main.c | 2 +- src/indexer/indexer-client.c | 2 +- src/indexer/indexer-queue.c | 2 +- src/indexer/indexer-settings.c | 2 +- src/indexer/indexer-worker-settings.c | 2 +- src/indexer/indexer-worker.c | 2 +- src/indexer/indexer.c | 2 +- src/indexer/master-connection.c | 2 +- src/indexer/worker-connection.c | 2 +- src/indexer/worker-pool.c | 2 +- src/ipc/client.c | 2 +- src/ipc/ipc-connection.c | 2 +- src/ipc/ipc-group.c | 2 +- src/ipc/ipc-settings.c | 2 +- src/ipc/main.c | 2 +- src/lda/main.c | 2 +- src/lib-auth/auth-client-request.c | 2 +- src/lib-auth/auth-client.c | 2 +- src/lib-auth/auth-master.c | 2 +- src/lib-auth/auth-server-connection.c | 2 +- src/lib-charset/charset-iconv.c | 2 +- src/lib-charset/charset-utf8.c | 2 +- src/lib-compression/compression.c | 2 +- src/lib-compression/istream-bzlib.c | 2 +- src/lib-compression/istream-lz4.c | 2 +- src/lib-compression/istream-lzma.c | 2 +- src/lib-compression/istream-zlib.c | 2 +- src/lib-compression/ostream-bzlib.c | 2 +- src/lib-compression/ostream-lz4.c | 2 +- src/lib-compression/ostream-lzma.c | 2 +- src/lib-compression/ostream-zlib.c | 2 +- src/lib-compression/test-compression.c | 2 +- src/lib-dict/dict-cdb.c | 2 +- src/lib-dict/dict-client.c | 2 +- src/lib-dict/dict-db.c | 2 +- src/lib-dict/dict-file.c | 2 +- src/lib-dict/dict-fs.c | 2 +- src/lib-dict/dict-memcached-ascii.c | 2 +- src/lib-dict/dict-memcached.c | 2 +- src/lib-dict/dict-redis.c | 2 +- src/lib-dict/dict-register.c | 2 +- src/lib-dict/dict-sql-settings.c | 2 +- src/lib-dict/dict-sql.c | 2 +- src/lib-dict/dict-transaction-memory.c | 2 +- src/lib-dict/dict.c | 2 +- src/lib-dict/test-dict.c | 2 +- src/lib-dns/dns-lookup.c | 2 +- src/lib-fs/fs-api.c | 2 +- src/lib-fs/fs-metawrap.c | 2 +- src/lib-fs/fs-posix.c | 2 +- src/lib-fs/fs-sis-common.c | 2 +- src/lib-fs/fs-sis-queue.c | 2 +- src/lib-fs/fs-sis.c | 2 +- src/lib-fs/istream-fs-file.c | 2 +- src/lib-fs/istream-metawrap.c | 2 +- src/lib-fs/ostream-cmp.c | 2 +- src/lib-fs/ostream-metawrap.c | 2 +- src/lib-http/http-auth.c | 2 +- src/lib-http/http-client-connection.c | 2 +- src/lib-http/http-client-host.c | 2 +- src/lib-http/http-client-peer.c | 2 +- src/lib-http/http-client-queue.c | 2 +- src/lib-http/http-client-request.c | 2 +- src/lib-http/http-client.c | 2 +- src/lib-http/http-date.c | 2 +- src/lib-http/http-header-parser.c | 2 +- src/lib-http/http-header.c | 2 +- src/lib-http/http-message-parser.c | 2 +- src/lib-http/http-parser.c | 2 +- src/lib-http/http-request-parser.c | 2 +- src/lib-http/http-response-parser.c | 2 +- src/lib-http/http-server-connection.c | 2 +- src/lib-http/http-server-request.c | 2 +- src/lib-http/http-server-response.c | 2 +- src/lib-http/http-server.c | 2 +- src/lib-http/http-transfer-chunked.c | 2 +- src/lib-http/http-url.c | 2 +- src/lib-http/test-http-auth.c | 2 +- src/lib-http/test-http-client.c | 2 +- src/lib-http/test-http-date.c | 2 +- src/lib-http/test-http-header-parser.c | 2 +- src/lib-http/test-http-request-parser.c | 2 +- src/lib-http/test-http-response-parser.c | 2 +- src/lib-http/test-http-server.c | 2 +- src/lib-http/test-http-transfer.c | 2 +- src/lib-http/test-http-url.c | 2 +- src/lib-imap-client/imapc-client.c | 2 +- src/lib-imap-client/imapc-connection.c | 2 +- src/lib-imap-client/imapc-msgmap.c | 2 +- src/lib-imap-storage/imap-metadata.c | 2 +- src/lib-imap-storage/imap-msgpart-url.c | 2 +- src/lib-imap-storage/imap-msgpart.c | 2 +- src/lib-imap-urlauth/imap-urlauth-backend.c | 2 +- src/lib-imap-urlauth/imap-urlauth-connection.c | 2 +- src/lib-imap-urlauth/imap-urlauth-fetch.c | 2 +- src/lib-imap-urlauth/imap-urlauth.c | 2 +- src/lib-imap/imap-arg.c | 2 +- src/lib-imap/imap-base-subject.c | 2 +- src/lib-imap/imap-bodystructure.c | 2 +- src/lib-imap/imap-date.c | 2 +- src/lib-imap/imap-envelope.c | 2 +- src/lib-imap/imap-id.c | 2 +- src/lib-imap/imap-match.c | 2 +- src/lib-imap/imap-parser.c | 2 +- src/lib-imap/imap-quote.c | 2 +- src/lib-imap/imap-seqset.c | 2 +- src/lib-imap/imap-url.c | 2 +- src/lib-imap/imap-utf7.c | 2 +- src/lib-imap/imap-util.c | 2 +- src/lib-imap/test-imap-bodystructure.c | 2 +- src/lib-imap/test-imap-match.c | 2 +- src/lib-imap/test-imap-parser.c | 2 +- src/lib-imap/test-imap-quote.c | 2 +- src/lib-imap/test-imap-url.c | 2 +- src/lib-imap/test-imap-utf7.c | 2 +- src/lib-imap/test-imap-util.c | 2 +- src/lib-index/mail-cache-compress.c | 2 +- src/lib-index/mail-cache-decisions.c | 2 +- src/lib-index/mail-cache-fields.c | 2 +- src/lib-index/mail-cache-lookup.c | 2 +- src/lib-index/mail-cache-sync-update.c | 2 +- src/lib-index/mail-cache-transaction.c | 2 +- src/lib-index/mail-cache.c | 2 +- src/lib-index/mail-index-alloc-cache.c | 2 +- src/lib-index/mail-index-dummy-view.c | 2 +- src/lib-index/mail-index-fsck.c | 2 +- src/lib-index/mail-index-lock.c | 2 +- src/lib-index/mail-index-map-hdr.c | 2 +- src/lib-index/mail-index-map-read.c | 2 +- src/lib-index/mail-index-map.c | 2 +- src/lib-index/mail-index-modseq.c | 2 +- src/lib-index/mail-index-strmap.c | 2 +- src/lib-index/mail-index-sync-ext.c | 2 +- src/lib-index/mail-index-sync-keywords.c | 2 +- src/lib-index/mail-index-sync-update.c | 2 +- src/lib-index/mail-index-sync.c | 2 +- src/lib-index/mail-index-transaction-export.c | 2 +- src/lib-index/mail-index-transaction-finish.c | 2 +- src/lib-index/mail-index-transaction-sort-appends.c | 2 +- src/lib-index/mail-index-transaction-update.c | 2 +- src/lib-index/mail-index-transaction-view.c | 2 +- src/lib-index/mail-index-transaction.c | 2 +- src/lib-index/mail-index-util.c | 2 +- src/lib-index/mail-index-view-sync.c | 2 +- src/lib-index/mail-index-view.c | 2 +- src/lib-index/mail-index-write.c | 2 +- src/lib-index/mail-index.c | 2 +- src/lib-index/mail-transaction-log-append.c | 2 +- src/lib-index/mail-transaction-log-file.c | 2 +- src/lib-index/mail-transaction-log-view.c | 2 +- src/lib-index/mail-transaction-log.c | 2 +- src/lib-index/mailbox-log.c | 2 +- src/lib-index/test-mail-index-sync-ext.c | 2 +- src/lib-index/test-mail-index-transaction-finish.c | 2 +- src/lib-index/test-mail-index-transaction-update.c | 2 +- src/lib-index/test-mail-transaction-log-append.c | 2 +- src/lib-index/test-mail-transaction-log-view.c | 2 +- src/lib-lda/duplicate.c | 2 +- src/lib-lda/lda-settings.c | 2 +- src/lib-lda/lmtp-client.c | 2 +- src/lib-lda/mail-deliver.c | 2 +- src/lib-lda/mail-send.c | 2 +- src/lib-lda/smtp-client.c | 2 +- src/lib-mail/istream-attachment-connector.c | 2 +- src/lib-mail/istream-attachment-extractor.c | 2 +- src/lib-mail/istream-binary-converter.c | 2 +- src/lib-mail/istream-dot.c | 2 +- src/lib-mail/istream-header-filter.c | 2 +- src/lib-mail/istream-nonuls.c | 2 +- src/lib-mail/istream-qp-decoder.c | 2 +- src/lib-mail/mail-user-hash.c | 2 +- src/lib-mail/mbox-from.c | 2 +- src/lib-mail/message-address.c | 2 +- src/lib-mail/message-binary-part.c | 2 +- src/lib-mail/message-date.c | 2 +- src/lib-mail/message-decoder.c | 2 +- src/lib-mail/message-header-decode.c | 2 +- src/lib-mail/message-header-encode.c | 2 +- src/lib-mail/message-header-parser.c | 2 +- src/lib-mail/message-id.c | 2 +- src/lib-mail/message-parser.c | 2 +- src/lib-mail/message-part-serialize.c | 2 +- src/lib-mail/message-part.c | 2 +- src/lib-mail/message-search.c | 2 +- src/lib-mail/message-size.c | 2 +- src/lib-mail/ostream-dot.c | 2 +- src/lib-mail/quoted-printable.c | 2 +- src/lib-mail/rfc2231-parser.c | 2 +- src/lib-mail/rfc822-parser.c | 2 +- src/lib-mail/test-istream-attachment.c | 2 +- src/lib-mail/test-istream-binary-converter.c | 2 +- src/lib-mail/test-istream-dot.c | 2 +- src/lib-mail/test-istream-header-filter.c | 2 +- src/lib-mail/test-istream-qp-decoder.c | 2 +- src/lib-mail/test-mbox-from.c | 2 +- src/lib-mail/test-message-address.c | 2 +- src/lib-mail/test-message-date.c | 2 +- src/lib-mail/test-message-decoder.c | 2 +- src/lib-mail/test-message-header-decode.c | 2 +- src/lib-mail/test-message-header-encode.c | 2 +- src/lib-mail/test-message-header-parser.c | 2 +- src/lib-mail/test-message-id.c | 2 +- src/lib-mail/test-message-parser.c | 2 +- src/lib-mail/test-message-part.c | 2 +- src/lib-mail/test-ostream-dot.c | 2 +- src/lib-mail/test-quoted-printable.c | 2 +- src/lib-mail/test-rfc2231-parser.c | 2 +- src/lib-master/anvil-client.c | 2 +- src/lib-master/ipc-client.c | 2 +- src/lib-master/ipc-server.c | 2 +- src/lib-master/master-auth.c | 2 +- src/lib-master/master-instance.c | 2 +- src/lib-master/master-login-auth.c | 2 +- src/lib-master/master-login.c | 2 +- src/lib-master/master-service-settings-cache.c | 2 +- src/lib-master/master-service-settings.c | 2 +- src/lib-master/master-service-ssl-settings.c | 2 +- src/lib-master/master-service-ssl.c | 2 +- src/lib-master/master-service.c | 2 +- src/lib-master/mountpoint-list.c | 2 +- src/lib-master/syslog-util.c | 2 +- src/lib-master/test-master-service-settings-cache.c | 2 +- src/lib-sasl/dsasl-client.c | 2 +- src/lib-sasl/mech-login.c | 2 +- src/lib-sasl/mech-plain.c | 2 +- src/lib-settings/settings-parser.c | 2 +- src/lib-settings/settings.c | 2 +- src/lib-sql/driver-mysql.c | 2 +- src/lib-sql/driver-pgsql.c | 2 +- src/lib-sql/driver-sqlite.c | 2 +- src/lib-sql/driver-sqlpool.c | 2 +- src/lib-sql/sql-api.c | 2 +- src/lib-sql/sql-db-cache.c | 2 +- src/lib-ssl-iostream/iostream-openssl-common.c | 2 +- src/lib-ssl-iostream/iostream-openssl-context.c | 2 +- src/lib-ssl-iostream/iostream-openssl-params.c | 2 +- src/lib-ssl-iostream/iostream-openssl.c | 2 +- src/lib-ssl-iostream/iostream-ssl.c | 2 +- src/lib-ssl-iostream/istream-openssl.c | 2 +- src/lib-ssl-iostream/ostream-openssl.c | 2 +- src/lib-storage/fail-mail-storage.c | 2 +- src/lib-storage/fail-mail.c | 2 +- src/lib-storage/fail-mailbox.c | 2 +- src/lib-storage/index/cydir/cydir-mail.c | 2 +- src/lib-storage/index/cydir/cydir-save.c | 2 +- src/lib-storage/index/cydir/cydir-storage.c | 2 +- src/lib-storage/index/cydir/cydir-sync.c | 2 +- src/lib-storage/index/dbox-common/dbox-attachment.c | 2 +- src/lib-storage/index/dbox-common/dbox-file-fix.c | 2 +- src/lib-storage/index/dbox-common/dbox-file.c | 2 +- src/lib-storage/index/dbox-common/dbox-mail.c | 2 +- src/lib-storage/index/dbox-common/dbox-save.c | 2 +- src/lib-storage/index/dbox-common/dbox-storage.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-deleted-storage.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-file.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-mail.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-map.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-purge.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-save.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-settings.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-storage.c | 2 +- src/lib-storage/index/dbox-multi/mdbox-sync.c | 2 +- src/lib-storage/index/dbox-single/sdbox-copy.c | 2 +- src/lib-storage/index/dbox-single/sdbox-file.c | 2 +- src/lib-storage/index/dbox-single/sdbox-mail.c | 2 +- src/lib-storage/index/dbox-single/sdbox-save.c | 2 +- src/lib-storage/index/dbox-single/sdbox-storage.c | 2 +- src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c | 2 +- src/lib-storage/index/dbox-single/sdbox-sync.c | 2 +- src/lib-storage/index/imapc/imapc-list.c | 2 +- src/lib-storage/index/imapc/imapc-mail-fetch.c | 2 +- src/lib-storage/index/imapc/imapc-mail.c | 2 +- src/lib-storage/index/imapc/imapc-mailbox.c | 2 +- src/lib-storage/index/imapc/imapc-save.c | 2 +- src/lib-storage/index/imapc/imapc-settings.c | 2 +- src/lib-storage/index/imapc/imapc-storage.c | 2 +- src/lib-storage/index/imapc/imapc-sync.c | 2 +- src/lib-storage/index/index-attachment.c | 2 +- src/lib-storage/index/index-attribute.c | 2 +- src/lib-storage/index/index-mail-binary.c | 2 +- src/lib-storage/index/index-mail-headers.c | 2 +- src/lib-storage/index/index-mail.c | 2 +- src/lib-storage/index/index-mailbox-check.c | 2 +- src/lib-storage/index/index-rebuild.c | 2 +- src/lib-storage/index/index-search-result.c | 2 +- src/lib-storage/index/index-search.c | 2 +- src/lib-storage/index/index-sort-string.c | 2 +- src/lib-storage/index/index-sort.c | 2 +- src/lib-storage/index/index-status.c | 2 +- src/lib-storage/index/index-storage.c | 2 +- src/lib-storage/index/index-sync-changes.c | 2 +- src/lib-storage/index/index-sync-pvt.c | 2 +- src/lib-storage/index/index-sync-search.c | 2 +- src/lib-storage/index/index-sync.c | 2 +- src/lib-storage/index/index-thread-finish.c | 2 +- src/lib-storage/index/index-thread-links.c | 2 +- src/lib-storage/index/index-thread.c | 2 +- src/lib-storage/index/index-transaction.c | 2 +- src/lib-storage/index/istream-mail.c | 2 +- src/lib-storage/index/maildir/maildir-copy.c | 2 +- src/lib-storage/index/maildir/maildir-filename-flags.c | 2 +- src/lib-storage/index/maildir/maildir-filename.c | 2 +- src/lib-storage/index/maildir/maildir-keywords.c | 2 +- src/lib-storage/index/maildir/maildir-mail.c | 2 +- src/lib-storage/index/maildir/maildir-save.c | 2 +- src/lib-storage/index/maildir/maildir-settings.c | 2 +- src/lib-storage/index/maildir/maildir-storage.c | 2 +- src/lib-storage/index/maildir/maildir-sync-index.c | 2 +- src/lib-storage/index/maildir/maildir-sync.c | 2 +- src/lib-storage/index/maildir/maildir-uidlist.c | 2 +- src/lib-storage/index/maildir/maildir-util.c | 2 +- src/lib-storage/index/mbox/istream-raw-mbox.c | 2 +- src/lib-storage/index/mbox/mbox-file.c | 2 +- src/lib-storage/index/mbox/mbox-lock.c | 2 +- src/lib-storage/index/mbox/mbox-mail.c | 2 +- src/lib-storage/index/mbox/mbox-md5-all.c | 2 +- src/lib-storage/index/mbox/mbox-md5-apop3d.c | 2 +- src/lib-storage/index/mbox/mbox-save.c | 2 +- src/lib-storage/index/mbox/mbox-settings.c | 2 +- src/lib-storage/index/mbox/mbox-storage.c | 2 +- src/lib-storage/index/mbox/mbox-sync-list-index.c | 2 +- src/lib-storage/index/mbox/mbox-sync-parse.c | 2 +- src/lib-storage/index/mbox/mbox-sync-rewrite.c | 2 +- src/lib-storage/index/mbox/mbox-sync-update.c | 2 +- src/lib-storage/index/mbox/mbox-sync.c | 2 +- src/lib-storage/index/pop3c/pop3c-client.c | 2 +- src/lib-storage/index/pop3c/pop3c-mail.c | 2 +- src/lib-storage/index/pop3c/pop3c-settings.c | 2 +- src/lib-storage/index/pop3c/pop3c-storage.c | 2 +- src/lib-storage/index/pop3c/pop3c-sync.c | 2 +- src/lib-storage/index/raw/raw-mail.c | 2 +- src/lib-storage/index/raw/raw-storage.c | 2 +- src/lib-storage/index/raw/raw-sync.c | 2 +- src/lib-storage/index/shared/shared-list.c | 2 +- src/lib-storage/index/shared/shared-storage.c | 2 +- src/lib-storage/list/mailbox-list-delete.c | 2 +- src/lib-storage/list/mailbox-list-fs-flags.c | 2 +- src/lib-storage/list/mailbox-list-fs-iter.c | 2 +- src/lib-storage/list/mailbox-list-fs.c | 2 +- src/lib-storage/list/mailbox-list-index-backend.c | 2 +- src/lib-storage/list/mailbox-list-index-iter.c | 2 +- src/lib-storage/list/mailbox-list-index-notify.c | 2 +- src/lib-storage/list/mailbox-list-index-status.c | 2 +- src/lib-storage/list/mailbox-list-index-sync.c | 2 +- src/lib-storage/list/mailbox-list-index.c | 2 +- src/lib-storage/list/mailbox-list-iter.c | 2 +- src/lib-storage/list/mailbox-list-maildir-iter.c | 2 +- src/lib-storage/list/mailbox-list-maildir.c | 2 +- src/lib-storage/list/mailbox-list-none.c | 2 +- src/lib-storage/list/mailbox-list-notify-tree.c | 2 +- src/lib-storage/list/mailbox-list-subscriptions.c | 2 +- src/lib-storage/list/subscription-file.c | 2 +- src/lib-storage/mail-copy.c | 2 +- src/lib-storage/mail-error.c | 2 +- src/lib-storage/mail-namespace.c | 2 +- src/lib-storage/mail-search-build.c | 2 +- src/lib-storage/mail-search-parser-cmdline.c | 2 +- src/lib-storage/mail-search-parser-imap.c | 2 +- src/lib-storage/mail-search-parser.c | 2 +- src/lib-storage/mail-search-register-human.c | 2 +- src/lib-storage/mail-search-register-imap.c | 2 +- src/lib-storage/mail-search-register.c | 2 +- src/lib-storage/mail-search.c | 2 +- src/lib-storage/mail-storage-hooks.c | 2 +- src/lib-storage/mail-storage-service.c | 2 +- src/lib-storage/mail-storage-settings.c | 2 +- src/lib-storage/mail-storage.c | 2 +- src/lib-storage/mail-thread.c | 2 +- src/lib-storage/mail-user.c | 2 +- src/lib-storage/mail.c | 2 +- src/lib-storage/mailbox-get.c | 2 +- src/lib-storage/mailbox-guid-cache.c | 2 +- src/lib-storage/mailbox-header.c | 2 +- src/lib-storage/mailbox-keywords.c | 2 +- src/lib-storage/mailbox-list-notify.c | 2 +- src/lib-storage/mailbox-list.c | 2 +- src/lib-storage/mailbox-search-result.c | 2 +- src/lib-storage/mailbox-tree.c | 2 +- src/lib-storage/mailbox-uidvalidity.c | 2 +- src/lib-storage/test-mailbox-get.c | 2 +- src/lib-test/test-common.c | 2 +- src/lib/abspath.c | 2 +- src/lib/aqueue.c | 2 +- src/lib/array.c | 2 +- src/lib/askpass.c | 2 +- src/lib/backtrace-string.c | 2 +- src/lib/base32.c | 2 +- src/lib/base64.c | 2 +- src/lib/bits.c | 2 +- src/lib/bsearch-insert-pos.c | 2 +- src/lib/buffer.c | 2 +- src/lib/child-wait.c | 2 +- src/lib/compat.c | 2 +- src/lib/connection.c | 2 +- src/lib/crc32.c | 2 +- src/lib/data-stack.c | 2 +- src/lib/eacces-error.c | 2 +- src/lib/env-util.c | 2 +- src/lib/execv-const.c | 2 +- src/lib/failures.c | 2 +- src/lib/fd-close-on-exec.c | 2 +- src/lib/fd-set-nonblock.c | 2 +- src/lib/fdatasync-path.c | 2 +- src/lib/fdpass.c | 2 +- src/lib/file-cache.c | 2 +- src/lib/file-copy.c | 2 +- src/lib/file-dotlock.c | 2 +- src/lib/file-lock.c | 2 +- src/lib/file-set-size.c | 2 +- src/lib/guid.c | 2 +- src/lib/hash-format.c | 2 +- src/lib/hash-method.c | 2 +- src/lib/hash.c | 2 +- src/lib/hash2.c | 2 +- src/lib/hex-binary.c | 2 +- src/lib/hex-dec.c | 2 +- src/lib/hmac.c | 2 +- src/lib/home-expand.c | 2 +- src/lib/hostpid.c | 2 +- src/lib/imem.c | 2 +- src/lib/ioloop-epoll.c | 2 +- src/lib/ioloop-notify-dn.c | 2 +- src/lib/ioloop-notify-fd.c | 2 +- src/lib/ioloop-notify-inotify.c | 2 +- src/lib/ioloop-notify-none.c | 2 +- src/lib/ioloop-poll.c | 2 +- src/lib/ioloop-select.c | 2 +- src/lib/ioloop.c | 2 +- src/lib/iostream-rawlog.c | 2 +- src/lib/iostream-temp.c | 2 +- src/lib/iostream.c | 2 +- src/lib/ipwd.c | 2 +- src/lib/iso8601-date.c | 2 +- src/lib/istream-base64-decoder.c | 2 +- src/lib/istream-base64-encoder.c | 2 +- src/lib/istream-callback.c | 2 +- src/lib/istream-chain.c | 2 +- src/lib/istream-concat.c | 2 +- src/lib/istream-crlf.c | 2 +- src/lib/istream-data.c | 2 +- src/lib/istream-file.c | 2 +- src/lib/istream-hash.c | 2 +- src/lib/istream-jsonstr.c | 2 +- src/lib/istream-limit.c | 2 +- src/lib/istream-mmap.c | 2 +- src/lib/istream-rawlog.c | 2 +- src/lib/istream-seekable.c | 2 +- src/lib/istream-sized.c | 2 +- src/lib/istream-tee.c | 2 +- src/lib/istream-timeout.c | 2 +- src/lib/istream.c | 2 +- src/lib/json-parser.c | 2 +- src/lib/lib-signals.c | 2 +- src/lib/lib.c | 2 +- src/lib/mempool-alloconly.c | 2 +- src/lib/mempool-datastack.c | 2 +- src/lib/mempool-system.c | 2 +- src/lib/mempool-unsafe-datastack.c | 2 +- src/lib/mempool.c | 2 +- src/lib/mkdir-parents.c | 2 +- src/lib/mmap-anon.c | 2 +- src/lib/mmap-util.c | 2 +- src/lib/module-dir.c | 2 +- src/lib/mountpoint.c | 2 +- src/lib/net.c | 2 +- src/lib/nfs-workarounds.c | 2 +- src/lib/numpack.c | 2 +- src/lib/ostream-buffer.c | 2 +- src/lib/ostream-file.c | 2 +- src/lib/ostream-hash.c | 2 +- src/lib/ostream-rawlog.c | 2 +- src/lib/ostream.c | 2 +- src/lib/primes.c | 2 +- src/lib/printf-format-fix.c | 2 +- src/lib/priorityq.c | 2 +- src/lib/process-title.c | 2 +- src/lib/rand.c | 2 +- src/lib/randgen.c | 2 +- src/lib/read-full.c | 2 +- src/lib/restrict-access.c | 2 +- src/lib/restrict-process-size.c | 2 +- src/lib/safe-memset.c | 2 +- src/lib/safe-mkdir.c | 2 +- src/lib/safe-mkstemp.c | 2 +- src/lib/sendfile-util.c | 2 +- src/lib/seq-range-array.c | 2 +- src/lib/str-find.c | 2 +- src/lib/str-sanitize.c | 2 +- src/lib/str-table.c | 2 +- src/lib/str.c | 2 +- src/lib/strescape.c | 2 +- src/lib/strfuncs.c | 2 +- src/lib/strnum.c | 2 +- src/lib/test-aqueue.c | 2 +- src/lib/test-array.c | 2 +- src/lib/test-base32.c | 2 +- src/lib/test-base64.c | 2 +- src/lib/test-bits.c | 2 +- src/lib/test-bsearch-insert-pos.c | 2 +- src/lib/test-buffer.c | 2 +- src/lib/test-crc32.c | 2 +- src/lib/test-data-stack.c | 2 +- src/lib/test-guid.c | 2 +- src/lib/test-hash-format.c | 2 +- src/lib/test-hash-method.c | 2 +- src/lib/test-hash.c | 2 +- src/lib/test-hex-binary.c | 2 +- src/lib/test-iso8601-date.c | 2 +- src/lib/test-istream-base64-decoder.c | 2 +- src/lib/test-istream-base64-encoder.c | 2 +- src/lib/test-istream-concat.c | 2 +- src/lib/test-istream-crlf.c | 2 +- src/lib/test-istream-seekable.c | 2 +- src/lib/test-istream-tee.c | 2 +- src/lib/test-istream.c | 2 +- src/lib/test-json-parser.c | 2 +- src/lib/test-lib.c | 2 +- src/lib/test-llist.c | 2 +- src/lib/test-mempool-alloconly.c | 2 +- src/lib/test-network.c | 2 +- src/lib/test-numpack.c | 2 +- src/lib/test-ostream-file.c | 2 +- src/lib/test-primes.c | 2 +- src/lib/test-printf-format-fix.c | 2 +- src/lib/test-priorityq.c | 2 +- src/lib/test-seq-range-array.c | 2 +- src/lib/test-str-find.c | 2 +- src/lib/test-str-sanitize.c | 2 +- src/lib/test-str-table.c | 2 +- src/lib/test-str.c | 2 +- src/lib/test-strescape.c | 2 +- src/lib/test-strfuncs.c | 2 +- src/lib/test-strnum.c | 2 +- src/lib/test-time-util.c | 2 +- src/lib/test-unichar.c | 2 +- src/lib/test-utc-mktime.c | 2 +- src/lib/test-var-expand.c | 2 +- src/lib/test-wildcard-match.c | 2 +- src/lib/time-util.c | 2 +- src/lib/unichar.c | 2 +- src/lib/unix-socket-create.c | 2 +- src/lib/unlink-directory.c | 2 +- src/lib/unlink-old-files.c | 2 +- src/lib/uri-util.c | 2 +- src/lib/utc-mktime.c | 2 +- src/lib/utc-offset.c | 2 +- src/lib/var-expand.c | 2 +- src/lib/write-full.c | 2 +- src/lmtp/client.c | 2 +- src/lmtp/commands.c | 2 +- src/lmtp/lmtp-proxy.c | 2 +- src/lmtp/lmtp-settings.c | 2 +- src/lmtp/main.c | 2 +- src/log/doveadm-connection.c | 2 +- src/log/log-connection.c | 2 +- src/log/log-error-buffer.c | 2 +- src/log/log-settings.c | 2 +- src/log/main.c | 2 +- src/login-common/access-lookup.c | 2 +- src/login-common/client-common-auth.c | 2 +- src/login-common/client-common.c | 2 +- src/login-common/login-proxy-state.c | 2 +- src/login-common/login-proxy.c | 2 +- src/login-common/login-settings.c | 2 +- src/login-common/main.c | 2 +- src/login-common/sasl-server.c | 2 +- src/login-common/ssl-proxy-gnutls.c | 2 +- src/login-common/ssl-proxy-openssl.c | 2 +- src/login-common/ssl-proxy.c | 2 +- src/master/capabilities-posix.c | 2 +- src/master/dup2-array.c | 2 +- src/master/main.c | 2 +- src/master/master-settings.c | 2 +- src/master/service-anvil.c | 2 +- src/master/service-listen.c | 2 +- src/master/service-log.c | 2 +- src/master/service-monitor.c | 2 +- src/master/service-process-notify.c | 2 +- src/master/service-process.c | 2 +- src/master/service.c | 2 +- src/plugins/acl/acl-api.c | 2 +- src/plugins/acl/acl-attributes.c | 2 +- src/plugins/acl/acl-backend-vfile-acllist.c | 2 +- src/plugins/acl/acl-backend-vfile-update.c | 2 +- src/plugins/acl/acl-backend-vfile.c | 2 +- src/plugins/acl/acl-backend.c | 2 +- src/plugins/acl/acl-cache.c | 2 +- src/plugins/acl/acl-global-file.c | 2 +- src/plugins/acl/acl-lookup-dict.c | 2 +- src/plugins/acl/acl-mailbox-list.c | 2 +- src/plugins/acl/acl-mailbox.c | 2 +- src/plugins/acl/acl-plugin.c | 2 +- src/plugins/acl/acl-shared-storage.c | 2 +- src/plugins/acl/acl-storage.c | 2 +- src/plugins/acl/doveadm-acl.c | 2 +- src/plugins/autocreate/autocreate-plugin.c | 2 +- src/plugins/expire/doveadm-expire.c | 2 +- src/plugins/expire/expire-plugin.c | 2 +- src/plugins/expire/expire-set.c | 2 +- src/plugins/fts-lucene/doveadm-fts-lucene.c | 2 +- src/plugins/fts-lucene/fts-backend-lucene.c | 2 +- src/plugins/fts-lucene/fts-lucene-plugin.c | 2 +- src/plugins/fts-lucene/lucene-wrapper.cc | 2 +- src/plugins/fts-solr/fts-backend-solr-old.c | 2 +- src/plugins/fts-solr/fts-backend-solr.c | 2 +- src/plugins/fts-solr/fts-solr-plugin.c | 2 +- src/plugins/fts-solr/solr-connection.c | 2 +- src/plugins/fts-squat/fts-backend-squat.c | 2 +- src/plugins/fts-squat/fts-squat-plugin.c | 2 +- src/plugins/fts-squat/squat-test.c | 2 +- src/plugins/fts-squat/squat-trie.c | 2 +- src/plugins/fts-squat/squat-uidlist.c | 2 +- src/plugins/fts/doveadm-dump-fts-expunge-log.c | 2 +- src/plugins/fts/doveadm-fts.c | 2 +- src/plugins/fts/fts-api.c | 2 +- src/plugins/fts/fts-build-mail.c | 2 +- src/plugins/fts/fts-expunge-log.c | 2 +- src/plugins/fts/fts-indexer.c | 2 +- src/plugins/fts/fts-parser-html.c | 2 +- src/plugins/fts/fts-parser-script.c | 2 +- src/plugins/fts/fts-parser-tika.c | 2 +- src/plugins/fts/fts-parser.c | 2 +- src/plugins/fts/fts-plugin.c | 2 +- src/plugins/fts/fts-search-serialize.c | 2 +- src/plugins/fts/fts-search.c | 2 +- src/plugins/fts/fts-storage.c | 2 +- src/plugins/fts/xml2text.c | 2 +- src/plugins/imap-acl/imap-acl-plugin.c | 2 +- src/plugins/imap-quota/imap-quota-plugin.c | 2 +- src/plugins/imap-stats/imap-stats-plugin.c | 2 +- src/plugins/imap-zlib/imap-zlib-plugin.c | 2 +- src/plugins/last-login/last-login-plugin.c | 2 +- src/plugins/lazy-expunge/lazy-expunge-plugin.c | 2 +- src/plugins/listescape/listescape-plugin.c | 2 +- src/plugins/mail-filter/istream-ext-filter.c | 2 +- src/plugins/mail-filter/mail-filter-plugin.c | 2 +- src/plugins/mail-filter/ostream-ext-filter.c | 2 +- src/plugins/mail-log/mail-log-plugin.c | 2 +- src/plugins/mailbox-alias/mailbox-alias-plugin.c | 2 +- src/plugins/notify/notify-plugin.c | 2 +- src/plugins/notify/notify-storage.c | 2 +- src/plugins/pop3-migration/pop3-migration-plugin.c | 2 +- src/plugins/quota/doveadm-quota.c | 2 +- src/plugins/quota/quota-count.c | 2 +- src/plugins/quota/quota-dict.c | 2 +- src/plugins/quota/quota-dirsize.c | 2 +- src/plugins/quota/quota-fs.c | 2 +- src/plugins/quota/quota-maildir.c | 2 +- src/plugins/quota/quota-plugin.c | 2 +- src/plugins/quota/quota-status.c | 2 +- src/plugins/quota/quota-storage.c | 2 +- src/plugins/quota/quota-util.c | 2 +- src/plugins/quota/quota.c | 2 +- src/plugins/quota/test-quota-util.c | 2 +- src/plugins/replication/replication-plugin.c | 2 +- src/plugins/snarf/snarf-plugin.c | 2 +- src/plugins/stats/stats-connection.c | 2 +- src/plugins/stats/stats-plugin.c | 2 +- src/plugins/trash/trash-plugin.c | 2 +- src/plugins/virtual/virtual-config.c | 2 +- src/plugins/virtual/virtual-mail.c | 2 +- src/plugins/virtual/virtual-plugin.c | 2 +- src/plugins/virtual/virtual-save.c | 2 +- src/plugins/virtual/virtual-search.c | 2 +- src/plugins/virtual/virtual-storage.c | 2 +- src/plugins/virtual/virtual-sync.c | 2 +- src/plugins/virtual/virtual-transaction.c | 2 +- src/plugins/zlib/zlib-plugin.c | 2 +- src/pop3-login/client-authenticate.c | 2 +- src/pop3-login/client.c | 2 +- src/pop3-login/pop3-login-settings.c | 2 +- src/pop3-login/pop3-proxy.c | 2 +- src/pop3/main.c | 2 +- src/pop3/pop3-client.c | 2 +- src/pop3/pop3-commands.c | 2 +- src/pop3/pop3-settings.c | 2 +- src/replication/aggregator/aggregator-settings.c | 2 +- src/replication/aggregator/aggregator.c | 2 +- src/replication/aggregator/notify-connection.c | 2 +- src/replication/aggregator/replicator-connection.c | 2 +- src/replication/replicator/doveadm-connection.c | 2 +- src/replication/replicator/dsync-client.c | 2 +- src/replication/replicator/notify-connection.c | 2 +- src/replication/replicator/replicator-brain.c | 2 +- src/replication/replicator/replicator-queue-auth.c | 2 +- src/replication/replicator/replicator-queue.c | 2 +- src/replication/replicator/replicator-settings.c | 2 +- src/replication/replicator/replicator.c | 2 +- src/ssl-params/main.c | 2 +- src/ssl-params/ssl-params-settings.c | 2 +- src/ssl-params/ssl-params.c | 2 +- src/stats/client-export.c | 2 +- src/stats/client.c | 2 +- src/stats/global-memory.c | 2 +- src/stats/mail-command.c | 2 +- src/stats/mail-domain.c | 2 +- src/stats/mail-ip.c | 2 +- src/stats/mail-server-connection.c | 2 +- src/stats/mail-session.c | 2 +- src/stats/mail-stats.c | 2 +- src/stats/mail-user.c | 2 +- src/stats/main.c | 2 +- src/stats/stats-settings.c | 2 +- src/util/gdbhelper.c | 2 +- src/util/maildirlock.c | 2 +- src/util/rawlog.c | 2 +- src/util/script-login.c | 2 +- src/util/script.c | 2 +- src/util/tcpwrap-settings.c | 2 +- src/util/tcpwrap.c | 2 +- 979 files changed, 979 insertions(+), 979 deletions(-) diffs (truncated from 8817 to 300 lines): diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-acl.1.in --- a/doc/man/doveadm-acl.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-acl.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-ACL 1 "2014-10-09" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-acl \- Manage Access Control List (ACL) diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-altmove.1.in --- a/doc/man/doveadm-altmove.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-altmove.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-ALTMOVE 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-altmove \- Move matching mails to the alternative storage (dbox\-only) diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-auth.1.in --- a/doc/man/doveadm-auth.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-auth.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-AUTH 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-auth \- Flush/lookup/test authentication data diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-batch.1.in --- a/doc/man/doveadm-batch.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-batch.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-BATCH 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-batch \- Execute multiple commands for multiple users diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-deduplicate.1.in --- a/doc/man/doveadm-deduplicate.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-deduplicate.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-DEDUPLICATE 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-deduplicate \- expunge duplicate messages diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-director.1.in --- a/doc/man/doveadm-director.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-director.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-DIRECTOR 1 "2014-08-30" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-director \- Manage Dovecot directors diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-dump.1.in --- a/doc/man/doveadm-dump.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-dump.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-DUMP 1 "2014-08-24" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-dump \- Dump the content of Dovecot\(aqs binary mailbox index/log diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-exec.1.in --- a/doc/man/doveadm-exec.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-exec.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-EXEC 1 "2013-08-05" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-exec \- easily execute commands from Dovecot\(aqs libexec_dir diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-expunge.1.in --- a/doc/man/doveadm-expunge.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-expunge.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-EXPUNGE 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-expunge \- Expunge messages matching given search query diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-fetch.1.in --- a/doc/man/doveadm-fetch.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-fetch.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-FETCH 1 "2012-02-13" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-fetch \- Fetch partial/full messages or message information diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-flags.1.in --- a/doc/man/doveadm-flags.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-flags.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2013-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2013-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-FLAGS 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-flags \- add, remove or replace messages\(aq flags diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-force-resync.1.in --- a/doc/man/doveadm-force-resync.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-force-resync.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-FORCE\-RESYNC 1 "2010-11-25" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-force\-resync \- Repair broken mailboxes diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-fts.1.in --- a/doc/man/doveadm-fts.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-fts.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-FTS 1 "2014-09-24" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-fts \- Manipulate the Full Text Search (FTS) index diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-help.1.in --- a/doc/man/doveadm-help.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-help.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-HELP 1 "2010-06-22" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-help \- Show information about doveadm commands diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-import.1.in --- a/doc/man/doveadm-import.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-import.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-IMPORT 1 "2013-11-24" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-import \- Import messages matching given search query diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-index.1.in --- a/doc/man/doveadm-index.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-index.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-INDEX 1 "2013-11-23" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-index \- Index mailboxes diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-instance.1.in --- a/doc/man/doveadm-instance.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-instance.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2012 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2012-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-INSTANCE 1 "2012-02-16" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-instance \- Manage the list of running Dovecot instances diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-kick.1.in --- a/doc/man/doveadm-kick.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-kick.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-KICK 1 "2010-06-12" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-kick \- Disconnect users by user name and/or IP address diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-log.1.in --- a/doc/man/doveadm-log.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-log.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-LOG 1 "2013-11-24" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-log \- Locate, test or reopen Dovecot\(aqs log files diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-mailbox.1.in --- a/doc/man/doveadm-mailbox.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-mailbox.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-MAILBOX 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-mailbox \- Commands related to handling mailboxes diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-mount.1.in --- a/doc/man/doveadm-mount.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-mount.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2012 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2012-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-MOUNT 1 "2012-02-16" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-mount \- Manage the list of mountpoints where mails are stored diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-move.1.in --- a/doc/man/doveadm-move.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-move.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2011-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2011-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-MOVE 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-move \- Move messages matching the given search query into another diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-penalty.1.in --- a/doc/man/doveadm-penalty.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-penalty.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-PENALTY 1 "2010-07-12" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-penalty \- Show current penalties diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-proxy.1.in --- a/doc/man/doveadm-proxy.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-proxy.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-PROXY 1 "2014-10-07" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-proxy \- Handle Dovecot proxy connections diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-purge.1.in --- a/doc/man/doveadm-purge.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-purge.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-PURGE 1 "2010-11-25" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-purge \- Remove messages with refcount=0 from mdbox files diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-pw.1.in --- a/doc/man/doveadm-pw.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-pw.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-PW 1 "2013-08-17" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-pw \- Dovecot\(aqs password hash generator diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-quota.1.in --- a/doc/man/doveadm-quota.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-quota.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-QUOTA 1 "2011-02-17" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-quota \- Initialize/recalculate or show current quota usage diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-replicator.1.in --- a/doc/man/doveadm-replicator.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-replicator.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-REPLICATOR 1 "2014-10-05" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-replicator \- Manage users\(aq mail replicaton diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-search-query.7 --- a/doc/man/doveadm-search-query.7 Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-search-query.7 Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-SEARCH\-QUERY 7 "2011-11-24" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-search\-query \- Overview of search queries for doveadm mailbox \ diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-search.1.in --- a/doc/man/doveadm-search.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-search.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-SEARCH 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-search \- Show a list of mailbox GUIDs and message UIDs matching \ diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-sync.1.in --- a/doc/man/doveadm-sync.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-sync.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2014 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2014-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-SYNC 1 "2014-10-19" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-sync \- Dovecot\(aqs two\-way mailbox synchronization utility diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-user.1.in --- a/doc/man/doveadm-user.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-user.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-USER 1 "2013-11-23" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-user \- Perform a user lookup in Dovecot\(aqs userdbs diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm-who.1.in --- a/doc/man/doveadm-who.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm-who.1.in Mon Jan 05 22:20:10 2015 +0200 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file .TH DOVEADM\-WHO 1 "2010-07-12" "Dovecot v2.2" "Dovecot" .SH NAME doveadm\-who \- Show who is logged in to the Dovecot server diff -r ff30ec13fcb7 -r 3009a1a6f6d5 doc/man/doveadm.1.in --- a/doc/man/doveadm.1.in Mon Jan 05 22:16:59 2015 +0200 +++ b/doc/man/doveadm.1.in Mon Jan 05 22:20:10 2015 +0200 From dovecot at dovecot.org Tue Jan 6 00:34:40 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 06 Jan 2015 00:34:40 +0000 Subject: dovecot-2.2: fts: Correct returned value to match type signature. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e23f1f333ada changeset: 18138:e23f1f333ada user: Teemu Huovila date: Mon Jan 05 15:48:55 2015 +0200 description: fts: Correct returned value to match type signature. diffstat: src/plugins/fts/fts-parser.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 3009a1a6f6d5 -r e23f1f333ada src/plugins/fts/fts-parser.c --- a/src/plugins/fts/fts-parser.c Mon Jan 05 22:20:10 2015 +0200 +++ b/src/plugins/fts/fts-parser.c Mon Jan 05 15:48:55 2015 +0200 @@ -21,7 +21,7 @@ if (strcmp(content_type, "text/plain") == 0) { /* we probably don't want/need to allow parsers to handle plaintext? */ - return NULL; + return FALSE; } for (i = 0; i < N_ELEMENTS(parsers); i++) { From dovecot at dovecot.org Tue Jan 6 01:16:25 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 06 Jan 2015 01:16:25 +0000 Subject: dovecot-2.2: lib: Remove OpenBSD workaround in i_getpw*() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/dbd1dbd968ac changeset: 18139:dbd1dbd968ac user: Timo Sirainen date: Tue Jan 06 03:15:11 2015 +0200 description: lib: Remove OpenBSD workaround in i_getpw*() Originally added in 801714cba91b. It was requested to be removed now that 1) it's fixed in OpenBSD v5.6+ and 2) The workaround caused nonexistent users to not work correctly (process running out of memory I guess?) diffstat: src/lib/ipwd.c | 10 ---------- 1 files changed, 0 insertions(+), 10 deletions(-) diffs (27 lines): diff -r e23f1f333ada -r dbd1dbd968ac src/lib/ipwd.c --- a/src/lib/ipwd.c Mon Jan 05 15:48:55 2015 +0200 +++ b/src/lib/ipwd.c Tue Jan 06 03:15:11 2015 +0200 @@ -50,11 +50,6 @@ do { pw_init(); errno = getpwnam_r(name, pwd_r, pwbuf, pwbuf_size, &result); -#ifdef __OpenBSD__ - /* OpenBSD returns 1 for all errors, assume it's ERANGE */ - if (errno == 1) - errno = ERANGE; -#endif } while (errno == ERANGE); if (result != NULL) return 1; @@ -73,11 +68,6 @@ do { pw_init(); errno = getpwuid_r(uid, pwd_r, pwbuf, pwbuf_size, &result); -#ifdef __OpenBSD__ - /* OpenBSD returns 1 for all errors, assume it's ERANGE */ - if (errno == 1) - errno = ERANGE; -#endif } while (errno == ERANGE); if (result != NULL) return 1; From dovecot at dovecot.org Tue Jan 6 22:38:51 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 06 Jan 2015 22:38:51 +0000 Subject: dovecot-2.2: lib: Defined array type for guid_128_t Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/51e8bbc82edd changeset: 18140:51e8bbc82edd user: Timo Sirainen date: Wed Jan 07 00:37:50 2015 +0200 description: lib: Defined array type for guid_128_t diffstat: src/lib/guid.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r dbd1dbd968ac -r 51e8bbc82edd src/lib/guid.h --- a/src/lib/guid.h Tue Jan 06 03:15:11 2015 +0200 +++ b/src/lib/guid.h Wed Jan 07 00:37:50 2015 +0200 @@ -6,6 +6,8 @@ #define GUID_128_HOST_HASH_SIZE 4 +ARRAY_DEFINE_TYPE(guid_128_t, guid_128_t); + /* Generate a GUID (contains host name) */ const char *guid_generate(void); /* Generate 128 bit GUID */ From pigeonhole at rename-it.nl Thu Jan 8 01:08:05 2015 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Thu, 08 Jan 2015 02:08:05 +0100 Subject: dovecot-2.2-pigeonhole: Updated copyright notices to include the... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/efe2a5fdcc25 changeset: 1984:efe2a5fdcc25 user: Stephan Bosch date: Thu Jan 08 02:07:51 2015 +0100 description: Updated copyright notices to include the year 2015. diffstat: doc/man/pigeonhole.7.in | 2 +- doc/man/sieve-dump.1.in | 2 +- doc/man/sieve-filter.1.in | 2 +- doc/man/sieve-test.1.in | 2 +- doc/man/sievec.1.in | 2 +- src/lib-managesieve/managesieve-arg.c | 2 +- src/lib-managesieve/managesieve-arg.h | 2 +- src/lib-managesieve/managesieve-parser.c | 2 +- src/lib-managesieve/managesieve-parser.h | 2 +- src/lib-managesieve/managesieve-quote.c | 2 +- src/lib-managesieve/managesieve-quote.h | 2 +- src/lib-sieve-tool/mail-raw.c | 2 +- src/lib-sieve-tool/mail-raw.h | 2 +- src/lib-sieve-tool/sieve-tool.c | 2 +- src/lib-sieve-tool/sieve-tool.h | 2 +- src/lib-sieve/cmd-discard.c | 2 +- src/lib-sieve/cmd-if.c | 2 +- src/lib-sieve/cmd-keep.c | 2 +- src/lib-sieve/cmd-redirect.c | 2 +- src/lib-sieve/cmd-require.c | 2 +- src/lib-sieve/cmd-stop.c | 2 +- src/lib-sieve/cmp-i-ascii-casemap.c | 2 +- src/lib-sieve/cmp-i-octet.c | 2 +- src/lib-sieve/ext-encoded-character.c | 2 +- src/lib-sieve/ext-envelope.c | 2 +- src/lib-sieve/ext-fileinto.c | 2 +- src/lib-sieve/ext-reject.c | 2 +- src/lib-sieve/mcht-contains.c | 2 +- src/lib-sieve/mcht-is.c | 2 +- src/lib-sieve/mcht-matches.c | 2 +- src/lib-sieve/plugins/body/ext-body-common.c | 2 +- src/lib-sieve/plugins/body/ext-body-common.h | 2 +- src/lib-sieve/plugins/body/ext-body.c | 2 +- src/lib-sieve/plugins/body/tst-body.c | 2 +- src/lib-sieve/plugins/comparator-i-ascii-numeric/ext-cmp-i-ascii-numeric.c | 2 +- src/lib-sieve/plugins/copy/ext-copy.c | 2 +- src/lib-sieve/plugins/copy/sieve-ext-copy.h | 2 +- src/lib-sieve/plugins/date/ext-date-common.c | 2 +- src/lib-sieve/plugins/date/ext-date-common.h | 2 +- src/lib-sieve/plugins/date/ext-date.c | 2 +- src/lib-sieve/plugins/date/tst-date.c | 2 +- src/lib-sieve/plugins/duplicate/ext-duplicate-common.c | 2 +- src/lib-sieve/plugins/duplicate/ext-duplicate-common.h | 2 +- src/lib-sieve/plugins/duplicate/ext-duplicate.c | 2 +- src/lib-sieve/plugins/duplicate/tst-duplicate.c | 2 +- src/lib-sieve/plugins/editheader/cmd-addheader.c | 2 +- src/lib-sieve/plugins/editheader/cmd-deleteheader.c | 2 +- src/lib-sieve/plugins/editheader/ext-editheader-common.c | 2 +- src/lib-sieve/plugins/editheader/ext-editheader-common.h | 2 +- src/lib-sieve/plugins/editheader/ext-editheader-limits.h | 2 +- src/lib-sieve/plugins/editheader/ext-editheader.c | 2 +- src/lib-sieve/plugins/enotify/cmd-notify.c | 2 +- src/lib-sieve/plugins/enotify/ext-enotify-common.c | 2 +- src/lib-sieve/plugins/enotify/ext-enotify-common.h | 2 +- src/lib-sieve/plugins/enotify/ext-enotify-limits.h | 2 +- src/lib-sieve/plugins/enotify/ext-enotify.c | 2 +- src/lib-sieve/plugins/enotify/mailto/ntfy-mailto.c | 2 +- src/lib-sieve/plugins/enotify/mailto/uri-mailto.c | 2 +- src/lib-sieve/plugins/enotify/mailto/uri-mailto.h | 2 +- src/lib-sieve/plugins/enotify/sieve-ext-enotify.h | 2 +- src/lib-sieve/plugins/enotify/tst-notify-method-capability.c | 2 +- src/lib-sieve/plugins/enotify/tst-valid-notify-method.c | 2 +- src/lib-sieve/plugins/enotify/vmodf-encodeurl.c | 2 +- src/lib-sieve/plugins/environment/ext-environment-common.c | 2 +- src/lib-sieve/plugins/environment/ext-environment-common.h | 2 +- src/lib-sieve/plugins/environment/ext-environment.c | 2 +- src/lib-sieve/plugins/environment/sieve-ext-environment.h | 2 +- src/lib-sieve/plugins/environment/tst-environment.c | 2 +- src/lib-sieve/plugins/ihave/cmd-error.c | 2 +- src/lib-sieve/plugins/ihave/ext-ihave-binary.c | 2 +- src/lib-sieve/plugins/ihave/ext-ihave-binary.h | 2 +- src/lib-sieve/plugins/ihave/ext-ihave-common.c | 2 +- src/lib-sieve/plugins/ihave/ext-ihave-common.h | 2 +- src/lib-sieve/plugins/ihave/ext-ihave.c | 2 +- src/lib-sieve/plugins/ihave/tst-ihave.c | 2 +- src/lib-sieve/plugins/imap4flags/cmd-flag.c | 2 +- src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.c | 2 +- src/lib-sieve/plugins/imap4flags/ext-imap4flags-common.h | 2 +- src/lib-sieve/plugins/imap4flags/ext-imap4flags.c | 2 +- src/lib-sieve/plugins/imap4flags/ext-imapflags.c | 2 +- src/lib-sieve/plugins/imap4flags/tag-flags.c | 2 +- src/lib-sieve/plugins/imap4flags/tst-hasflag.c | 2 +- src/lib-sieve/plugins/include/cmd-global.c | 2 +- src/lib-sieve/plugins/include/cmd-include.c | 2 +- src/lib-sieve/plugins/include/cmd-return.c | 2 +- src/lib-sieve/plugins/include/ext-include-binary.c | 2 +- src/lib-sieve/plugins/include/ext-include-binary.h | 2 +- src/lib-sieve/plugins/include/ext-include-common.c | 2 +- src/lib-sieve/plugins/include/ext-include-common.h | 2 +- src/lib-sieve/plugins/include/ext-include-limits.h | 2 +- src/lib-sieve/plugins/include/ext-include-variables.c | 2 +- src/lib-sieve/plugins/include/ext-include-variables.h | 2 +- src/lib-sieve/plugins/include/ext-include.c | 2 +- src/lib-sieve/plugins/index/ext-index-common.c | 2 +- src/lib-sieve/plugins/index/ext-index-common.h | 2 +- src/lib-sieve/plugins/index/ext-index.c | 2 +- src/lib-sieve/plugins/index/tag-index.c | 2 +- src/lib-sieve/plugins/mailbox/ext-mailbox-common.h | 2 +- src/lib-sieve/plugins/mailbox/ext-mailbox.c | 2 +- src/lib-sieve/plugins/mailbox/sieve-ext-mailbox.h | 2 +- src/lib-sieve/plugins/mailbox/tag-mailbox-create.c | 2 +- src/lib-sieve/plugins/mailbox/tst-mailboxexists.c | 2 +- src/lib-sieve/plugins/metadata/ext-metadata-common.h | 2 +- src/lib-sieve/plugins/metadata/ext-metadata.c | 2 +- src/lib-sieve/plugins/metadata/tst-metadata.c | 2 +- src/lib-sieve/plugins/metadata/tst-metadataexists.c | 2 +- src/lib-sieve/plugins/notify/cmd-denotify.c | 2 +- src/lib-sieve/plugins/notify/cmd-notify.c | 2 +- src/lib-sieve/plugins/notify/ext-notify-common.c | 2 +- src/lib-sieve/plugins/notify/ext-notify-common.h | 2 +- src/lib-sieve/plugins/notify/ext-notify-limits.h | 2 +- src/lib-sieve/plugins/notify/ext-notify.c | 2 +- src/lib-sieve/plugins/regex/ext-regex-common.c | 2 +- src/lib-sieve/plugins/regex/ext-regex-common.h | 2 +- src/lib-sieve/plugins/regex/ext-regex.c | 2 +- src/lib-sieve/plugins/regex/mcht-regex.c | 2 +- src/lib-sieve/plugins/relational/ext-relational-common.c | 2 +- src/lib-sieve/plugins/relational/ext-relational-common.h | 2 +- src/lib-sieve/plugins/relational/ext-relational.c | 2 +- src/lib-sieve/plugins/relational/mcht-count.c | 2 +- src/lib-sieve/plugins/relational/mcht-value.c | 2 +- src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.c | 2 +- src/lib-sieve/plugins/spamvirustest/ext-spamvirustest-common.h | 2 +- src/lib-sieve/plugins/spamvirustest/ext-spamvirustest.c | 2 +- src/lib-sieve/plugins/spamvirustest/tst-spamvirustest.c | 2 +- src/lib-sieve/plugins/subaddress/ext-subaddress.c | 2 +- src/lib-sieve/plugins/vacation/cmd-vacation.c | 2 +- src/lib-sieve/plugins/vacation/ext-vacation-common.c | 2 +- src/lib-sieve/plugins/vacation/ext-vacation-common.h | 2 +- src/lib-sieve/plugins/vacation/ext-vacation-seconds.c | 2 +- src/lib-sieve/plugins/vacation/ext-vacation.c | 2 +- src/lib-sieve/plugins/variables/cmd-set.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-arguments.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-arguments.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-common.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-common.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-dump.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-dump.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-limits.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-modifiers.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-modifiers.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-name.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-name.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-namespaces.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-namespaces.h | 2 +- src/lib-sieve/plugins/variables/ext-variables-operands.c | 2 +- src/lib-sieve/plugins/variables/ext-variables-operands.h | 2 +- src/lib-sieve/plugins/variables/ext-variables.c | 2 +- src/lib-sieve/plugins/variables/sieve-ext-variables.h | 2 +- src/lib-sieve/plugins/variables/tst-string.c | 2 +- src/lib-sieve/plugins/vnd.dovecot/debug/cmd-debug-log.c | 2 +- src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug-common.h | 2 +- src/lib-sieve/plugins/vnd.dovecot/debug/ext-debug.c | 2 +- src/lib-sieve/sieve-actions.c | 2 +- src/lib-sieve/sieve-actions.h | 2 +- src/lib-sieve/sieve-address-parts.c | 2 +- src/lib-sieve/sieve-address-parts.h | 2 +- src/lib-sieve/sieve-address.c | 2 +- src/lib-sieve/sieve-address.h | 2 +- src/lib-sieve/sieve-ast.c | 2 +- src/lib-sieve/sieve-ast.h | 2 +- src/lib-sieve/sieve-binary-code.c | 2 +- src/lib-sieve/sieve-binary-debug.c | 2 +- src/lib-sieve/sieve-binary-dumper.c | 2 +- src/lib-sieve/sieve-binary-dumper.h | 2 +- src/lib-sieve/sieve-binary-file.c | 2 +- src/lib-sieve/sieve-binary-private.h | 2 +- src/lib-sieve/sieve-binary.c | 2 +- src/lib-sieve/sieve-binary.h | 2 +- src/lib-sieve/sieve-code-dumper.c | 2 +- src/lib-sieve/sieve-code-dumper.h | 2 +- src/lib-sieve/sieve-code.c | 2 +- src/lib-sieve/sieve-code.h | 2 +- src/lib-sieve/sieve-commands.c | 2 +- src/lib-sieve/sieve-commands.h | 2 +- src/lib-sieve/sieve-common.h | 2 +- src/lib-sieve/sieve-comparators.c | 2 +- src/lib-sieve/sieve-comparators.h | 2 +- src/lib-sieve/sieve-config.h | 2 +- src/lib-sieve/sieve-dump.h | 2 +- src/lib-sieve/sieve-error-private.h | 2 +- src/lib-sieve/sieve-error.c | 2 +- src/lib-sieve/sieve-error.h | 2 +- src/lib-sieve/sieve-extensions.c | 2 +- src/lib-sieve/sieve-extensions.h | 2 +- src/lib-sieve/sieve-generator.c | 2 +- src/lib-sieve/sieve-generator.h | 2 +- src/lib-sieve/sieve-interpreter.c | 2 +- src/lib-sieve/sieve-interpreter.h | 2 +- src/lib-sieve/sieve-lexer.c | 2 +- src/lib-sieve/sieve-lexer.h | 2 +- src/lib-sieve/sieve-limits.h | 2 +- src/lib-sieve/sieve-match-types.c | 2 +- src/lib-sieve/sieve-match-types.h | 2 +- src/lib-sieve/sieve-match.c | 2 +- src/lib-sieve/sieve-match.h | 2 +- src/lib-sieve/sieve-message.c | 2 +- src/lib-sieve/sieve-message.h | 2 +- src/lib-sieve/sieve-objects.c | 2 +- src/lib-sieve/sieve-objects.h | 2 +- src/lib-sieve/sieve-parser.c | 2 +- src/lib-sieve/sieve-parser.h | 2 +- src/lib-sieve/sieve-plugins.c | 2 +- src/lib-sieve/sieve-plugins.h | 2 +- src/lib-sieve/sieve-result.c | 2 +- src/lib-sieve/sieve-result.h | 2 +- src/lib-sieve/sieve-runtime-trace.c | 2 +- src/lib-sieve/sieve-runtime-trace.h | 2 +- src/lib-sieve/sieve-runtime.h | 2 +- src/lib-sieve/sieve-script-private.h | 2 +- src/lib-sieve/sieve-script.c | 2 +- src/lib-sieve/sieve-script.h | 2 +- src/lib-sieve/sieve-settings.c | 2 +- src/lib-sieve/sieve-settings.h | 2 +- src/lib-sieve/sieve-smtp.c | 2 +- src/lib-sieve/sieve-smtp.h | 2 +- src/lib-sieve/sieve-storage-private.h | 2 +- src/lib-sieve/sieve-storage-sync.c | 2 +- src/lib-sieve/sieve-storage.c | 2 +- src/lib-sieve/sieve-storage.h | 2 +- src/lib-sieve/sieve-stringlist.c | 2 +- src/lib-sieve/sieve-stringlist.h | 2 +- src/lib-sieve/sieve-types.h | 2 +- src/lib-sieve/sieve-validator.c | 2 +- src/lib-sieve/sieve-validator.h | 2 +- src/lib-sieve/sieve.c | 2 +- src/lib-sieve/sieve.h | 2 +- src/lib-sieve/storage/dict/sieve-dict-script.c | 2 +- src/lib-sieve/storage/dict/sieve-dict-storage.c | 2 +- src/lib-sieve/storage/dict/sieve-dict-storage.h | 2 +- src/lib-sieve/storage/file/sieve-file-script-sequence.c | 2 +- src/lib-sieve/storage/file/sieve-file-script.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage-active.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage-list.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage-quota.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage-save.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage.c | 2 +- src/lib-sieve/storage/file/sieve-file-storage.h | 2 +- src/lib-sieve/storage/ldap/sieve-ldap-db.c | 2 +- src/lib-sieve/storage/ldap/sieve-ldap-script.c | 2 +- src/lib-sieve/storage/ldap/sieve-ldap-storage-settings.c | 2 +- src/lib-sieve/storage/ldap/sieve-ldap-storage.c | 2 +- src/lib-sieve/storage/ldap/sieve-ldap-storage.h | 2 +- src/lib-sieve/tst-address.c | 2 +- src/lib-sieve/tst-allof.c | 2 +- src/lib-sieve/tst-anyof.c | 2 +- src/lib-sieve/tst-exists.c | 2 +- src/lib-sieve/tst-header.c | 2 +- src/lib-sieve/tst-not.c | 2 +- src/lib-sieve/tst-size.c | 2 +- src/lib-sieve/tst-truefalse.c | 2 +- src/lib-sieve/util/edit-mail.c | 2 +- src/lib-sieve/util/edit-mail.h | 2 +- src/lib-sieve/util/program-client-local.c | 2 +- src/lib-sieve/util/program-client-private.h | 2 +- src/lib-sieve/util/program-client-remote.c | 2 +- src/lib-sieve/util/program-client.c | 2 +- src/lib-sieve/util/program-client.h | 2 +- src/lib-sieve/util/rfc2822.c | 2 +- src/lib-sieve/util/rfc2822.h | 2 +- src/managesieve-login/client-authenticate.c | 2 +- src/managesieve-login/client-authenticate.h | 2 +- src/managesieve-login/client.c | 2 +- src/managesieve-login/client.h | 2 +- src/managesieve-login/managesieve-login-settings-plugin.c | 2 +- src/managesieve-login/managesieve-login-settings-plugin.h | 2 +- src/managesieve-login/managesieve-login-settings.c | 2 +- src/managesieve-login/managesieve-login-settings.h | 2 +- src/managesieve-login/managesieve-proxy.c | 2 +- src/managesieve-login/managesieve-proxy.h | 2 +- src/managesieve/cmd-capability.c | 2 +- src/managesieve/cmd-deletescript.c | 2 +- src/managesieve/cmd-getscript.c | 2 +- src/managesieve/cmd-havespace.c | 2 +- src/managesieve/cmd-listscripts.c | 2 +- src/managesieve/cmd-logout.c | 2 +- src/managesieve/cmd-noop.c | 2 +- src/managesieve/cmd-putscript.c | 2 +- src/managesieve/cmd-renamescript.c | 2 +- src/managesieve/cmd-setactive.c | 2 +- src/managesieve/main.c | 2 +- src/managesieve/managesieve-capabilities.c | 2 +- src/managesieve/managesieve-capabilities.h | 2 +- src/managesieve/managesieve-client.c | 2 +- src/managesieve/managesieve-client.h | 2 +- src/managesieve/managesieve-commands.c | 2 +- src/managesieve/managesieve-commands.h | 2 +- src/managesieve/managesieve-common.h | 2 +- src/managesieve/managesieve-quota.c | 2 +- src/managesieve/managesieve-quota.h | 2 +- src/managesieve/managesieve-settings.c | 2 +- src/managesieve/managesieve-settings.h | 2 +- src/plugins/doveadm-sieve/doveadm-sieve-plugin.c | 2 +- src/plugins/lda-sieve/lda-sieve-plugin.c | 2 +- src/plugins/lda-sieve/lda-sieve-plugin.h | 2 +- src/plugins/settings/pigeonhole-settings.c | 3 ++- src/plugins/sieve-extprograms/cmd-execute.c | 2 +- src/plugins/sieve-extprograms/cmd-filter.c | 2 +- src/plugins/sieve-extprograms/cmd-pipe.c | 2 +- src/plugins/sieve-extprograms/ext-execute.c | 2 +- src/plugins/sieve-extprograms/ext-filter.c | 2 +- src/plugins/sieve-extprograms/ext-pipe.c | 2 +- src/plugins/sieve-extprograms/sieve-extprograms-common.c | 2 +- src/plugins/sieve-extprograms/sieve-extprograms-common.h | 2 +- src/plugins/sieve-extprograms/sieve-extprograms-plugin.c | 2 +- src/plugins/sieve-extprograms/sieve-extprograms-plugin.h | 2 +- src/sieve-tools/sieve-dump.c | 2 +- src/sieve-tools/sieve-filter.c | 2 +- src/sieve-tools/sieve-test.c | 2 +- src/sieve-tools/sievec.c | 2 +- src/testsuite/cmd-test-binary.c | 2 +- src/testsuite/cmd-test-config.c | 2 +- src/testsuite/cmd-test-fail.c | 2 +- src/testsuite/cmd-test-imap-metadata.c | 2 +- src/testsuite/cmd-test-mailbox.c | 2 +- src/testsuite/cmd-test-message.c | 2 +- src/testsuite/cmd-test-result.c | 2 +- src/testsuite/cmd-test-set.c | 2 +- src/testsuite/cmd-test.c | 2 +- src/testsuite/ext-testsuite.c | 2 +- src/testsuite/testsuite-arguments.c | 2 +- src/testsuite/testsuite-arguments.h | 2 +- src/testsuite/testsuite-binary.c | 2 +- src/testsuite/testsuite-binary.h | 2 +- src/testsuite/testsuite-common.c | 2 +- src/testsuite/testsuite-common.h | 2 +- src/testsuite/testsuite-log.c | 2 +- src/testsuite/testsuite-log.h | 2 +- src/testsuite/testsuite-mailstore.c | 2 +- src/testsuite/testsuite-mailstore.h | 2 +- src/testsuite/testsuite-message.c | 2 +- src/testsuite/testsuite-message.h | 2 +- src/testsuite/testsuite-objects.c | 2 +- src/testsuite/testsuite-objects.h | 2 +- src/testsuite/testsuite-result.c | 2 +- src/testsuite/testsuite-result.h | 2 +- src/testsuite/testsuite-script.c | 2 +- src/testsuite/testsuite-script.h | 2 +- src/testsuite/testsuite-settings.c | 2 +- src/testsuite/testsuite-settings.h | 2 +- src/testsuite/testsuite-smtp.c | 2 +- src/testsuite/testsuite-smtp.h | 2 +- src/testsuite/testsuite-substitutions.c | 2 +- src/testsuite/testsuite-substitutions.h | 2 +- src/testsuite/testsuite-variables.c | 2 +- src/testsuite/testsuite-variables.h | 2 +- src/testsuite/testsuite.c | 2 +- src/testsuite/tst-test-error.c | 2 +- src/testsuite/tst-test-multiscript.c | 2 +- src/testsuite/tst-test-result-action.c | 2 +- src/testsuite/tst-test-result-execute.c | 2 +- src/testsuite/tst-test-script-compile.c | 2 +- src/testsuite/tst-test-script-run.c | 2 +- 353 files changed, 354 insertions(+), 353 deletions(-) diffs (truncated from 3178 to 300 lines): diff -r 1bcac73bab61 -r efe2a5fdcc25 doc/man/pigeonhole.7.in --- a/doc/man/pigeonhole.7.in Thu Jan 01 17:12:17 2015 +0100 +++ b/doc/man/pigeonhole.7.in Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Pigeonhole authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Pigeonhole authors, see the included COPYING file .TH "PIGEONHOLE" 7 "2014-01-01" "Pigeonhole for Dovecot v2.2" "Pigeonhole" .\"------------------------------------------------------------------------ .SH NAME diff -r 1bcac73bab61 -r efe2a5fdcc25 doc/man/sieve-dump.1.in --- a/doc/man/sieve-dump.1.in Thu Jan 01 17:12:17 2015 +0100 +++ b/doc/man/sieve-dump.1.in Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Pigeonhole authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Pigeonhole authors, see the included COPYING file .TH "SIEVE\-DUMP" 1 "2014-01-01" "Pigeonhole for Dovecot v2.2" "Pigeonhole" .\"------------------------------------------------------------------------ .SH NAME diff -r 1bcac73bab61 -r efe2a5fdcc25 doc/man/sieve-filter.1.in --- a/doc/man/sieve-filter.1.in Thu Jan 01 17:12:17 2015 +0100 +++ b/doc/man/sieve-filter.1.in Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Pigeonhole authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Pigeonhole authors, see the included COPYING file .TH "SIEVE\-FILTER" 1 "2014-01-01" "Pigeonhole for Dovecot v2.2" "Pigeonhole" .SH NAME sieve\-filter \- Pigeonhole\(aqs Sieve mailbox filter tool diff -r 1bcac73bab61 -r efe2a5fdcc25 doc/man/sieve-test.1.in --- a/doc/man/sieve-test.1.in Thu Jan 01 17:12:17 2015 +0100 +++ b/doc/man/sieve-test.1.in Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Pigeonhole authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Pigeonhole authors, see the included COPYING file .TH "SIEVE\-TEST" 1 "2014-01-01" "Pigeonhole for Dovecot v2.2" "Pigeonhole" .SH NAME sieve\-test \- Pigeonhole\(aqs Sieve script tester diff -r 1bcac73bab61 -r efe2a5fdcc25 doc/man/sievec.1.in --- a/doc/man/sievec.1.in Thu Jan 01 17:12:17 2015 +0100 +++ b/doc/man/sievec.1.in Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -.\" Copyright (c) 2010-2014 Pigeonhole authors, see the included COPYING file +.\" Copyright (c) 2010-2015 Pigeonhole authors, see the included COPYING file .TH "SIEVEC" 1 "2014-01-01" "Pigeonhole for Dovecot v2.2" "Pigeonhole" .\"------------------------------------------------------------------------ .SH NAME diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-arg.c --- a/src/lib-managesieve/managesieve-arg.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-arg.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-arg.h --- a/src/lib-managesieve/managesieve-arg.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-arg.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __MANAGESIEVE_ARG_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-parser.c --- a/src/lib-managesieve/managesieve-parser.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-parser.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-parser.h --- a/src/lib-managesieve/managesieve-parser.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-parser.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __MANAGESIEVE_PARSER_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-quote.c --- a/src/lib-managesieve/managesieve-quote.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-quote.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-managesieve/managesieve-quote.h --- a/src/lib-managesieve/managesieve-quote.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-managesieve/managesieve-quote.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __IMAP_QUOTE_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve-tool/mail-raw.c --- a/src/lib-sieve-tool/mail-raw.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve-tool/mail-raw.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve-tool/mail-raw.h --- a/src/lib-sieve-tool/mail-raw.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve-tool/mail-raw.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __MAIL_RAW_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve-tool/sieve-tool.c --- a/src/lib-sieve-tool/sieve-tool.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve-tool/sieve-tool.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve-tool/sieve-tool.h --- a/src/lib-sieve-tool/sieve-tool.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve-tool/sieve-tool.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __SIEVE_TOOL_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-discard.c --- a/src/lib-sieve/cmd-discard.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-discard.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-if.c --- a/src/lib-sieve/cmd-if.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-if.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "sieve-common.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-keep.c --- a/src/lib-sieve/cmd-keep.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-keep.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-redirect.c --- a/src/lib-sieve/cmd-redirect.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-redirect.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-require.c --- a/src/lib-sieve/cmd-require.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-require.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmd-stop.c --- a/src/lib-sieve/cmd-stop.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmd-stop.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "sieve-common.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmp-i-ascii-casemap.c --- a/src/lib-sieve/cmp-i-ascii-casemap.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmp-i-ascii-casemap.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Comparator 'i;ascii-casemap': diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/cmp-i-octet.c --- a/src/lib-sieve/cmp-i-octet.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/cmp-i-octet.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Comparator 'i;octet': diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/ext-encoded-character.c --- a/src/lib-sieve/ext-encoded-character.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/ext-encoded-character.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Extension encoded-character diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/ext-envelope.c --- a/src/lib-sieve/ext-envelope.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/ext-envelope.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Extension envelope diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/ext-fileinto.c --- a/src/lib-sieve/ext-fileinto.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/ext-fileinto.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Extension fileinto diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/ext-reject.c --- a/src/lib-sieve/ext-reject.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/ext-reject.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Extension reject diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/mcht-contains.c --- a/src/lib-sieve/mcht-contains.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/mcht-contains.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Match-type ':contains' diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/mcht-is.c --- a/src/lib-sieve/mcht-is.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/mcht-is.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Match-type ':is': diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/mcht-matches.c --- a/src/lib-sieve/mcht-matches.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/mcht-matches.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Match-type ':matches' diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/plugins/body/ext-body-common.c --- a/src/lib-sieve/plugins/body/ext-body-common.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/plugins/body/ext-body-common.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #include "lib.h" diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/plugins/body/ext-body-common.h --- a/src/lib-sieve/plugins/body/ext-body-common.h Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/plugins/body/ext-body-common.h Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ #ifndef __EXT_BODY_COMMON_H diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/plugins/body/ext-body.c --- a/src/lib-sieve/plugins/body/ext-body.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/plugins/body/ext-body.c Thu Jan 08 02:07:51 2015 +0100 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002-2014 Pigeonhole authors, see the included COPYING file +/* Copyright (c) 2002-2015 Pigeonhole authors, see the included COPYING file */ /* Extension body diff -r 1bcac73bab61 -r efe2a5fdcc25 src/lib-sieve/plugins/body/tst-body.c --- a/src/lib-sieve/plugins/body/tst-body.c Thu Jan 01 17:12:17 2015 +0100 +++ b/src/lib-sieve/plugins/body/tst-body.c Thu Jan 08 02:07:51 2015 +0100 From dovecot at dovecot.org Thu Jan 8 20:54:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 08 Jan 2015 20:54:11 +0000 Subject: dovecot-2.2: lib-imap-client: Use lib-sasl to perform the AUTHEN... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ee135359faa4 changeset: 18141:ee135359faa4 user: Timo Sirainen date: Thu Jan 08 22:32:20 2015 +0200 description: lib-imap-client: Use lib-sasl to perform the AUTHENTICATE command handling. diffstat: src/lib-imap-client/Makefile.am | 1 + src/lib-imap-client/imapc-connection.c | 142 +++++++++++++++++++++++++------- 2 files changed, 111 insertions(+), 32 deletions(-) diffs (230 lines): diff -r 51e8bbc82edd -r ee135359faa4 src/lib-imap-client/Makefile.am --- a/src/lib-imap-client/Makefile.am Wed Jan 07 00:37:50 2015 +0200 +++ b/src/lib-imap-client/Makefile.am Thu Jan 08 22:32:20 2015 +0200 @@ -3,6 +3,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-dns \ + -I$(top_srcdir)/src/lib-sasl \ -I$(top_srcdir)/src/lib-ssl-iostream \ -I$(top_srcdir)/src/lib-mail \ -I$(top_srcdir)/src/lib-imap diff -r 51e8bbc82edd -r ee135359faa4 src/lib-imap-client/imapc-connection.c --- a/src/lib-imap-client/imapc-connection.c Wed Jan 07 00:37:50 2015 +0200 +++ b/src/lib-imap-client/imapc-connection.c Thu Jan 08 22:32:20 2015 +0200 @@ -9,6 +9,7 @@ #include "write-full.h" #include "str.h" #include "dns-lookup.h" +#include "dsasl-client.h" #include "iostream-rawlog.h" #include "iostream-ssl.h" #include "imap-quote.h" @@ -20,6 +21,7 @@ #include #include +#define IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE INT_MAX #define IMAPC_MAX_INLINE_LITERAL_SIZE (1024*32) enum imapc_input_state { @@ -53,6 +55,8 @@ imapc_command_callback_t *callback; void *context; + /* This is the AUTHENTICATE command */ + unsigned int authenticate:1; /* This is the IDLE command */ unsigned int idle:1; /* Waiting for '+' literal reply before we can continue */ @@ -82,6 +86,7 @@ struct timeout *to; struct timeout *to_output; struct dns_lookup *dns_lookup; + struct dsasl_client *sasl_client; struct ssl_iostream *ssl_iostream; @@ -680,11 +685,10 @@ imapc_connection_lfiles_free(conn); } -static void imapc_connection_login_cb(const struct imapc_command_reply *reply, - void *context) +static void +imapc_connection_auth_finish(struct imapc_connection *conn, + const struct imapc_command_reply *reply) { - struct imapc_connection *conn = context; - if (reply->state != IMAPC_COMMAND_STATE_OK) { if (conn->login_callback != NULL) imapc_login_callback(conn, reply); @@ -706,33 +710,62 @@ imapc_command_send_more(conn); } -static const char * -imapc_connection_get_sasl_plain_request(struct imapc_connection *conn) +static void imapc_connection_login_cb(const struct imapc_command_reply *reply, + void *context) { - const struct imapc_client_settings *set = &conn->client->set; - string_t *in, *out; + struct imapc_connection *conn = context; - in = t_str_new(128); - if (set->master_user != NULL) { - str_append(in, set->username); - str_append_c(in, '\0'); - str_append(in, set->master_user); + imapc_connection_auth_finish(conn, reply); +} + +static void +imapc_connection_authenticate_cb(const struct imapc_command_reply *reply, + void *context) +{ + struct imapc_connection *conn = context; + const unsigned char *sasl_output; + unsigned int sasl_output_len; + unsigned int input_len; + buffer_t *buf; + const char *error; + + if (reply->state != IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE) { + dsasl_client_free(&conn->sasl_client); + imapc_connection_auth_finish(conn, reply); + return; + } + + input_len = strlen(reply->text_full); + buf = buffer_create_dynamic(pool_datastack_create(), + MAX_BASE64_DECODED_SIZE(input_len)); + if (base64_decode(reply->text_full, input_len, NULL, buf) < 0) { + i_error("imapc(%s): Authentication failed: Server sent non-base64 input for AUTHENTICATE: %s", + conn->name, reply->text_full); + } else if (dsasl_client_input(conn->sasl_client, buf->data, buf->used, &error) < 0) { + i_error("imapc(%s): Authentication failed: %s", + conn->name, error); + } else if (dsasl_client_output(conn->sasl_client, &sasl_output, + &sasl_output_len, &error) < 0) { + i_error("imapc(%s): Authentication failed: %s", + conn->name, error); } else { - str_append_c(in, '\0'); - str_append(in, set->username); + string_t *imap_output = + t_str_new(MAX_BASE64_ENCODED_SIZE(sasl_output_len)+2); + base64_encode(sasl_output, sasl_output_len, imap_output); + str_append(imap_output, "\r\n"); + o_stream_nsend(conn->output, str_data(imap_output), + str_len(imap_output)); + return; } - str_append_c(in, '\0'); - str_append(in, set->password); - - out = t_str_new(128); - base64_encode(in->data, in->used, out); - return str_c(out); + imapc_connection_disconnect(conn); } static void imapc_connection_authenticate(struct imapc_connection *conn) { const struct imapc_client_settings *set = &conn->client->set; struct imapc_command *cmd; + struct dsasl_client_settings sasl_set; + const struct dsasl_client_mech *sasl_mech; if (conn->client->set.debug) { if (set->master_user == NULL) { @@ -744,22 +777,56 @@ } } - cmd = imapc_connection_cmd(conn, imapc_connection_login_cb, - conn); - imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN); - if ((set->master_user == NULL && !need_literal(set->username) && !need_literal(set->password)) || (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0) { /* We can use LOGIN command */ + cmd = imapc_connection_cmd(conn, imapc_connection_login_cb, + conn); + imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN); imapc_command_sendf(cmd, "LOGIN %s %s", set->username, set->password); - } else if ((conn->capabilities & IMAPC_CAPABILITY_SASL_IR) != 0) { - imapc_command_sendf(cmd, "AUTHENTICATE PLAIN %1s", - imapc_connection_get_sasl_plain_request(conn)); + return; + } + + memset(&sasl_set, 0, sizeof(sasl_set)); + if (set->master_user == NULL) + sasl_set.authid = set->username; + else { + sasl_set.authid = set->master_user; + sasl_set.authzid = set->username; + } + sasl_set.password = set->password; + + sasl_mech = &dsasl_client_mech_plain; + conn->sasl_client = dsasl_client_new(sasl_mech, &sasl_set); + + cmd = imapc_connection_cmd(conn, imapc_connection_authenticate_cb, conn); + cmd->authenticate = TRUE; + imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_PRELOGIN); + + if ((conn->capabilities & IMAPC_CAPABILITY_SASL_IR) != 0) { + const unsigned char *sasl_output; + unsigned int sasl_output_len; + string_t *sasl_output_base64; + const char *error; + + if (dsasl_client_output(conn->sasl_client, &sasl_output, + &sasl_output_len, &error) < 0) { + i_error("imapc(%s): Failed to create initial SASL reply: %s", + conn->name, error); + imapc_connection_disconnect(conn); + return; + } + sasl_output_base64 = t_str_new(MAX_BASE64_ENCODED_SIZE(sasl_output_len)); + base64_encode(sasl_output, sasl_output_len, sasl_output_base64); + + imapc_command_sendf(cmd, "AUTHENTICATE %1s %1s", + dsasl_client_mech_get_name(sasl_mech), + str_c(sasl_output_base64)); } else { - imapc_command_sendf(cmd, "AUTHENTICATE PLAIN\r\n%1s", - imapc_connection_get_sasl_plain_request(conn)); + imapc_command_sendf(cmd, "AUTHENTICATE %1s", + dsasl_client_mech_get_name(sasl_mech)); } } @@ -960,8 +1027,19 @@ cmds[0]->wait_for_literal = FALSE; imapc_command_send_more(conn); } else { - imapc_connection_input_error(conn, "Unexpected '+': %s", line); - return -1; + cmds = array_get(&conn->cmd_wait_list, &cmds_count); + if (cmds_count > 0 && cmds[0]->authenticate) { + /* continue AUTHENTICATE */ + struct imapc_command_reply reply; + + memset(&reply, 0, sizeof(reply)); + reply.state = IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE; + reply.text_full = line; + cmds[0]->callback(&reply, cmds[0]->context); + } else { + imapc_connection_input_error(conn, "Unexpected '+': %s", line); + return -1; + } } imapc_connection_input_reset(conn); From dovecot at dovecot.org Thu Jan 8 20:54:12 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 08 Jan 2015 20:54:12 +0000 Subject: dovecot-2.2: imapc: Added imapc_sasl_mechanisms setting Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/fba6355ddb8a changeset: 18142:fba6355ddb8a user: Timo Sirainen date: Thu Jan 08 22:52:11 2015 +0200 description: imapc: Added imapc_sasl_mechanisms setting The first supported SASL mechanism is used, otherwise the login fails entirely. diffstat: src/lib-imap-client/imapc-client.c | 1 + src/lib-imap-client/imapc-client.h | 3 + src/lib-imap-client/imapc-connection.c | 61 +++++++++++++++++++++++++-- src/lib-storage/Makefile.am | 1 + src/lib-storage/index/imapc/imapc-settings.c | 2 + src/lib-storage/index/imapc/imapc-settings.h | 1 + src/lib-storage/index/imapc/imapc-storage.c | 1 + src/lib-storage/mail-storage.c | 3 + 8 files changed, 68 insertions(+), 5 deletions(-) diffs (193 lines): diff -r ee135359faa4 -r fba6355ddb8a src/lib-imap-client/imapc-client.c --- a/src/lib-imap-client/imapc-client.c Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-imap-client/imapc-client.c Thu Jan 08 22:52:11 2015 +0200 @@ -54,6 +54,7 @@ client->set.master_user = p_strdup_empty(pool, set->master_user); client->set.username = p_strdup(pool, set->username); client->set.password = p_strdup(pool, set->password); + client->set.sasl_mechanisms = p_strdup(pool, set->sasl_mechanisms); client->set.dns_client_socket_path = p_strdup(pool, set->dns_client_socket_path); client->set.temp_path_prefix = diff -r ee135359faa4 -r fba6355ddb8a src/lib-imap-client/imapc-client.h --- a/src/lib-imap-client/imapc-client.h Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-imap-client/imapc-client.h Thu Jan 08 22:52:11 2015 +0200 @@ -60,6 +60,9 @@ const char *master_user; const char *username; const char *password; + /* Space-separated list of SASL mechanisms to try (in the specified + order). The default is to use only LOGIN command or SASL PLAIN. */ + const char *sasl_mechanisms; unsigned int max_idle_time; const char *dns_client_socket_path; diff -r ee135359faa4 -r fba6355ddb8a src/lib-imap-client/imapc-connection.c --- a/src/lib-imap-client/imapc-connection.c Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-imap-client/imapc-connection.c Thu Jan 08 22:52:11 2015 +0200 @@ -760,12 +760,52 @@ imapc_connection_disconnect(conn); } +static bool imapc_connection_have_auth(struct imapc_connection *conn, + const char *mech_name) +{ + char *const *capa; + + for (capa = conn->capabilities_list; *capa != NULL; capa++) { + if (strncasecmp(*capa, "AUTH=", 5) == 0 && + strcasecmp((*capa)+5, mech_name) == 0) + return TRUE; + } + return FALSE; +} + +static int +imapc_connection_get_sasl_mech(struct imapc_connection *conn, + const struct dsasl_client_mech **mech_r, + const char **error_r) +{ + const struct imapc_client_settings *set = &conn->client->set; + const char *const *mechanisms = + t_strsplit_spaces(set->sasl_mechanisms, ", "); + + /* find one of the specified SASL mechanisms */ + for (; *mechanisms != NULL; mechanisms++) { + if (imapc_connection_have_auth(conn, *mechanisms)) { + *mech_r = dsasl_client_mech_find(*mechanisms); + if (*mech_r != NULL) + return 0; + + *error_r = t_strdup_printf( + "Support for SASL method '%s' is missing", *mechanisms); + return -1; + } + } + *error_r = t_strdup_printf("IMAP server doesn't support any of the requested SASL mechanisms: %s", + set->sasl_mechanisms); + return -1; +} + static void imapc_connection_authenticate(struct imapc_connection *conn) { const struct imapc_client_settings *set = &conn->client->set; struct imapc_command *cmd; struct dsasl_client_settings sasl_set; - const struct dsasl_client_mech *sasl_mech; + const struct dsasl_client_mech *sasl_mech = NULL; + const char *error; if (conn->client->set.debug) { if (set->master_user == NULL) { @@ -777,9 +817,19 @@ } } - if ((set->master_user == NULL && - !need_literal(set->username) && !need_literal(set->password)) || - (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0) { + if (set->sasl_mechanisms != NULL && set->sasl_mechanisms[0] != '\0') { + if (imapc_connection_get_sasl_mech(conn, &sasl_mech, &error) < 0) { + i_error("imapc(%s): Authentication failed: %s", + conn->name, error); + imapc_connection_disconnect(conn); + return; + } + } + + if (sasl_mech == NULL && + ((set->master_user == NULL && + !need_literal(set->username) && !need_literal(set->password)) || + (conn->capabilities & IMAPC_CAPABILITY_AUTH_PLAIN) == 0)) { /* We can use LOGIN command */ cmd = imapc_connection_cmd(conn, imapc_connection_login_cb, conn); @@ -798,7 +848,8 @@ } sasl_set.password = set->password; - sasl_mech = &dsasl_client_mech_plain; + if (sasl_mech == NULL) + sasl_mech = &dsasl_client_mech_plain; conn->sasl_client = dsasl_client_new(sasl_mech, &sasl_set); cmd = imapc_connection_cmd(conn, imapc_connection_authenticate_cb, conn); diff -r ee135359faa4 -r fba6355ddb8a src/lib-storage/Makefile.am --- a/src/lib-storage/Makefile.am Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-storage/Makefile.am Thu Jan 08 22:52:11 2015 +0200 @@ -7,6 +7,7 @@ -I$(top_srcdir)/src/lib-test \ -I$(top_srcdir)/src/lib-auth \ -I$(top_srcdir)/src/lib-dict \ + -I$(top_srcdir)/src/lib-sasl \ -I$(top_srcdir)/src/lib-ssl-iostream \ -I$(top_srcdir)/src/lib-fs \ -I$(top_srcdir)/src/lib-master \ diff -r ee135359faa4 -r fba6355ddb8a src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.c Thu Jan 08 22:52:11 2015 +0200 @@ -20,6 +20,7 @@ DEF(SET_STR_VARS, imapc_user), DEF(SET_STR_VARS, imapc_master_user), DEF(SET_STR, imapc_password), + DEF(SET_STR, imapc_sasl_mechanisms), DEF(SET_ENUM, imapc_ssl), DEF(SET_BOOL, imapc_ssl_verify), @@ -39,6 +40,7 @@ .imapc_user = "", .imapc_master_user = "", .imapc_password = "", + .imapc_sasl_mechanisms = "", .imapc_ssl = "no:imaps:starttls", .imapc_ssl_verify = TRUE, diff -r ee135359faa4 -r fba6355ddb8a src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.h Thu Jan 08 22:52:11 2015 +0200 @@ -16,6 +16,7 @@ const char *imapc_user; const char *imapc_master_user; const char *imapc_password; + const char *imapc_sasl_mechanisms; const char *imapc_ssl; bool imapc_ssl_verify; diff -r ee135359faa4 -r fba6355ddb8a src/lib-storage/index/imapc/imapc-storage.c --- a/src/lib-storage/index/imapc/imapc-storage.c Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.c Thu Jan 08 22:52:11 2015 +0200 @@ -221,6 +221,7 @@ *error_r = "missing imapc_password"; return -1; } + set.sasl_mechanisms = imapc_set->imapc_sasl_mechanisms; set.max_idle_time = imapc_set->imapc_max_idle_time; set.dns_client_socket_path = *ns->user->set->base_dir == '\0' ? "" : t_strconcat(ns->user->set->base_dir, "/", diff -r ee135359faa4 -r fba6355ddb8a src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Thu Jan 08 22:32:20 2015 +0200 +++ b/src/lib-storage/mail-storage.c Thu Jan 08 22:52:11 2015 +0200 @@ -11,6 +11,7 @@ #include "mkdir-parents.h" #include "time-util.h" #include "var-expand.h" +#include "dsasl-client.h" #include "mail-index-private.h" #include "mail-index-alloc-cache.h" #include "mailbox-tree.h" @@ -40,6 +41,7 @@ void mail_storage_init(void) { + dsasl_clients_init(); mailbox_lists_init(); mail_storage_hooks_init(); i_array_init(&mail_storage_classes, 8); @@ -55,6 +57,7 @@ array_free(&mail_storage_classes); mail_storage_hooks_deinit(); mailbox_lists_deinit(); + dsasl_clients_deinit(); } void mail_storage_class_register(struct mail_storage *storage_class) From dovecot at dovecot.org Thu Jan 8 21:09:02 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 08 Jan 2015 21:09:02 +0000 Subject: dovecot-2.2: lib-imap-client: Compiler warning fixes Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/55184e2a689f changeset: 18143:55184e2a689f user: Timo Sirainen date: Thu Jan 08 23:07:54 2015 +0200 description: lib-imap-client: Compiler warning fixes diffstat: src/lib-imap-client/imapc-connection.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (30 lines): diff -r fba6355ddb8a -r 55184e2a689f src/lib-imap-client/imapc-connection.c --- a/src/lib-imap-client/imapc-connection.c Thu Jan 08 22:52:11 2015 +0200 +++ b/src/lib-imap-client/imapc-connection.c Thu Jan 08 23:07:54 2015 +0200 @@ -21,7 +21,7 @@ #include #include -#define IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE INT_MAX +#define IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE 10000 #define IMAPC_MAX_INLINE_LITERAL_SIZE (1024*32) enum imapc_input_state { @@ -729,7 +729,7 @@ buffer_t *buf; const char *error; - if (reply->state != IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE) { + if ((int)reply->state != IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE) { dsasl_client_free(&conn->sasl_client); imapc_connection_auth_finish(conn, reply); return; @@ -1084,7 +1084,7 @@ struct imapc_command_reply reply; memset(&reply, 0, sizeof(reply)); - reply.state = IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE; + reply.state = (enum imapc_command_state)IMAPC_COMMAND_STATE_AUTHENTICATE_CONTINUE; reply.text_full = line; cmds[0]->callback(&reply, cmds[0]->context); } else { From dovecot at dovecot.org Sat Jan 10 02:27:04 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 10 Jan 2015 02:27:04 +0000 Subject: dovecot-2.2: lib-charset: UTF-8 -> UTF-8 translation was never r... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/7459c0891a85 changeset: 18144:7459c0891a85 user: Timo Sirainen date: Sat Jan 10 04:25:21 2015 +0200 description: lib-charset: UTF-8 -> UTF-8 translation was never returning CHARSET_RET_INCOMPLETE_INPUT Instead the incomplete input was just being modified into broken output. diffstat: src/lib-charset/charset-iconv.c | 26 +++++--------------------- src/lib-charset/charset-utf8.c | 26 +++++++++++++++++++++----- src/lib-charset/charset-utf8.h | 5 +++++ 3 files changed, 31 insertions(+), 26 deletions(-) diffs (107 lines): diff -r 55184e2a689f -r 7459c0891a85 src/lib-charset/charset-iconv.c --- a/src/lib-charset/charset-iconv.c Thu Jan 08 23:07:54 2015 +0200 +++ b/src/lib-charset/charset-iconv.c Sat Jan 10 04:25:21 2015 +0200 @@ -53,20 +53,6 @@ (void)iconv(t->cd, NULL, NULL, NULL, NULL); } -static int -charset_append_utf8(struct charset_translation *t, - const void *src, size_t src_size, buffer_t *dest) -{ - if (t->normalizer != NULL) - return t->normalizer(src, src_size, dest); - else if (!uni_utf8_get_valid_data(src, src_size, dest)) - return -1; - else { - buffer_append(dest, src, src_size); - return 0; - } -} - static bool charset_to_utf8_try(struct charset_translation *t, const unsigned char *src, size_t *src_size, buffer_t *dest, @@ -74,15 +60,12 @@ { ICONV_CONST char *ic_srcbuf; char tmpbuf[8192], *ic_destbuf; - size_t srcleft, destleft; + size_t srcleft, destleft, tmpbuf_used; bool ret = TRUE; if (t->cd == (iconv_t)-1) { /* input is already supposed to be UTF-8 */ - if (charset_append_utf8(t, src, *src_size, dest) < 0) - *result = CHARSET_RET_INVALID_INPUT; - else - *result = CHARSET_RET_OK; + *result = charset_utf8_to_utf8(t->normalizer, src, src_size, dest); return TRUE; } destleft = sizeof(tmpbuf); @@ -109,8 +92,9 @@ /* we just converted data to UTF-8. it shouldn't be invalid, but Solaris iconv appears to pass invalid data through sometimes (e.g. 8 bit characters with UTF-7) */ - if (charset_append_utf8(t, tmpbuf, sizeof(tmpbuf) - destleft, - dest) < 0) + tmpbuf_used = sizeof(tmpbuf) - destleft; + if (charset_utf8_to_utf8(t->normalizer, (void *)tmpbuf, + &tmpbuf_used, dest) != CHARSET_RET_OK) *result = CHARSET_RET_INVALID_INPUT; return ret; } diff -r 55184e2a689f -r 7459c0891a85 src/lib-charset/charset-utf8.c --- a/src/lib-charset/charset-utf8.c Thu Jan 08 23:07:54 2015 +0200 +++ b/src/lib-charset/charset-utf8.c Sat Jan 10 04:25:21 2015 +0200 @@ -70,15 +70,31 @@ charset_to_utf8(struct charset_translation *t, const unsigned char *src, size_t *src_size, buffer_t *dest) { - if (t->normalizer != NULL) { - if (t->normalizer(src, *src_size, dest) < 0) + return charset_utf8_to_utf8(t->normalizer, src, src_size, dest); +} + +#endif + +enum charset_result +charset_utf8_to_utf8(normalizer_func_t *normalizer, + const unsigned char *src, size_t *src_size, buffer_t *dest) +{ + enum charset_result res = CHARSET_RET_OK; + size_t pos; + + uni_utf8_partial_strlen_n(src, *src_size, &pos); + if (pos < *src_size) { + *src_size = pos; + res = CHARSET_RET_INCOMPLETE_INPUT; + } + + if (normalizer != NULL) { + if (normalizer(src, *src_size, dest) < 0) return CHARSET_RET_INVALID_INPUT; } else if (!uni_utf8_get_valid_data(src, *src_size, dest)) { return CHARSET_RET_INVALID_INPUT; } else { buffer_append(dest, src, *src_size); } - return CHARSET_RET_OK; + return res; } - -#endif diff -r 55184e2a689f -r 7459c0891a85 src/lib-charset/charset-utf8.h --- a/src/lib-charset/charset-utf8.h Thu Jan 08 23:07:54 2015 +0200 +++ b/src/lib-charset/charset-utf8.h Sat Jan 10 04:25:21 2015 +0200 @@ -32,4 +32,9 @@ const char *input, string_t *output, enum charset_result *result_r) ATTR_NULL(2); +/* INTERNAL: */ +enum charset_result +charset_utf8_to_utf8(normalizer_func_t *normalizer, + const unsigned char *src, size_t *src_size, buffer_t *dest); + #endif From dovecot at dovecot.org Sat Jan 10 02:31:45 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 10 Jan 2015 02:31:45 +0000 Subject: dovecot-2.2: lib: Added uni_utf8_partial_strlen_n() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f191dbcaec5f changeset: 18145:f191dbcaec5f user: Timo Sirainen date: Sat Jan 10 04:30:40 2015 +0200 description: lib: Added uni_utf8_partial_strlen_n() diffstat: src/lib/test-unichar.c | 16 ++++++++++++++++ src/lib/unichar.c | 18 ++++++++++++++---- src/lib/unichar.h | 6 ++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diffs (83 lines): diff -r 7459c0891a85 -r f191dbcaec5f src/lib/test-unichar.c --- a/src/lib/test-unichar.c Sat Jan 10 04:25:21 2015 +0200 +++ b/src/lib/test-unichar.c Sat Jan 10 04:30:40 2015 +0200 @@ -5,6 +5,20 @@ #include "buffer.h" #include "unichar.h" +static void test_unichar_uni_utf8_partial_strlen_n(void) +{ + static const char input[] = "\xC3\xA4\xC3\xA4"; + size_t pos; + + test_begin("uni_utf8_partial_strlen_n()"); + test_assert(uni_utf8_partial_strlen_n(input, 1, &pos) == 0 && pos == 0); + test_assert(uni_utf8_partial_strlen_n(input, 2, &pos) == 1 && pos == 2); + test_assert(uni_utf8_partial_strlen_n(input, 3, &pos) == 1 && pos == 2); + test_assert(uni_utf8_partial_strlen_n(input, 4, &pos) == 2 && pos == 4); + test_assert(uni_utf8_partial_strlen_n(input, (size_t)-1, &pos) == 2 && pos == 4); + test_end(); +} + void test_unichar(void) { static const char overlong_utf8[] = "\xf8\x80\x95\x81\xa1"; @@ -32,4 +46,6 @@ test_assert(!uni_utf8_str_is_valid(overlong_utf8)); test_assert(uni_utf8_get_char(overlong_utf8, &chr2) < 0); test_end(); + + test_unichar_uni_utf8_partial_strlen_n(); } diff -r 7459c0891a85 -r f191dbcaec5f src/lib/unichar.c --- a/src/lib/unichar.c Sat Jan 10 04:25:21 2015 +0200 +++ b/src/lib/unichar.c Sat Jan 10 04:30:40 2015 +0200 @@ -192,18 +192,28 @@ return uni_utf8_strlen_n(input, (size_t)-1); } -unsigned int uni_utf8_strlen_n(const void *_input, size_t size) +unsigned int uni_utf8_strlen_n(const void *input, size_t size) +{ + size_t partial_pos; + + return uni_utf8_partial_strlen_n(input, size, &partial_pos); +} + +unsigned int uni_utf8_partial_strlen_n(const void *_input, size_t size, + size_t *partial_pos_r) { const unsigned char *input = _input; - unsigned int len = 0; + unsigned int count, len = 0; size_t i; for (i = 0; i < size && input[i] != '\0'; ) { - i += uni_utf8_char_bytes(input[i]); - if (i > size) + count = uni_utf8_char_bytes(input[i]); + if (i + count > size) break; + i += count; len++; } + *partial_pos_r = i; return len; } diff -r 7459c0891a85 -r f191dbcaec5f src/lib/unichar.h --- a/src/lib/unichar.h Sat Jan 10 04:25:21 2015 +0200 +++ b/src/lib/unichar.h Sat Jan 10 04:30:40 2015 +0200 @@ -55,6 +55,12 @@ unsigned int uni_utf8_strlen(const char *input) ATTR_PURE; /* Returns UTF-8 string length with maximum input size. */ unsigned int uni_utf8_strlen_n(const void *input, size_t size) ATTR_PURE; +/* Same as uni_utf8_strlen_n(), but if input ends with a partial UTF-8 + character, don't include it in the return value and set partial_pos_r to + where the character begins. Otherwise partial_pos_r is set to the end + of the input. */ +unsigned int uni_utf8_partial_strlen_n(const void *input, size_t size, + size_t *partial_pos_r); /* Returns the number of bytes belonging to this UTF-8 character. The given parameter is the first byte of the UTF-8 sequence. Invalid input is From dovecot at dovecot.org Sat Jan 10 02:33:45 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 10 Jan 2015 02:33:45 +0000 Subject: dovecot-2.2: lib-mail: message-decoder no longer skips lib-chars... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e3640ccaa76d changeset: 18146:e3640ccaa76d user: Timo Sirainen date: Sat Jan 10 04:32:42 2015 +0200 description: lib-mail: message-decoder no longer skips lib-charset for UTF8 -> UTF8 translations. With the previous lib-charset fix this makes message-decoder handle partial UTF-8 text in input blocks correctly. diffstat: src/lib-mail/Makefile.am | 4 +- src/lib-mail/message-decoder.c | 20 +-------------- src/lib-mail/test-message-decoder.c | 47 ++++++++++++++---------------------- 3 files changed, 22 insertions(+), 49 deletions(-) diffs (135 lines): diff -r f191dbcaec5f -r e3640ccaa76d src/lib-mail/Makefile.am --- a/src/lib-mail/Makefile.am Sat Jan 10 04:30:40 2015 +0200 +++ b/src/lib-mail/Makefile.am Sat Jan 10 04:32:42 2015 +0200 @@ -133,8 +133,8 @@ test_message_date_DEPENDENCIES = $(test_deps) test_message_decoder_SOURCES = test-message-decoder.c -test_message_decoder_LDADD = message-decoder.lo rfc822-parser.lo rfc2231-parser.lo $(test_libs) -test_message_decoder_DEPENDENCIES = $(test_deps) +test_message_decoder_LDADD = message-decoder.lo quoted-printable.lo rfc822-parser.lo rfc2231-parser.lo ../lib-charset/libcharset.la $(test_libs) +test_message_decoder_DEPENDENCIES = ../lib-charset/libcharset.la $(test_deps) test_message_header_decode_SOURCES = test-message-header-decode.c test_message_header_decode_LDADD = message-header-decode.lo quoted-printable.lo message-header-encode.lo $(test_libs) diff -r f191dbcaec5f -r e3640ccaa76d src/lib-mail/message-decoder.c --- a/src/lib-mail/message-decoder.c Sat Jan 10 04:30:40 2015 +0200 +++ b/src/lib-mail/message-decoder.c Sat Jan 10 04:32:42 2015 +0200 @@ -38,7 +38,6 @@ char *content_charset; enum message_cte message_cte; - unsigned int charset_utf8:1; unsigned int binary_input:1; }; @@ -142,7 +141,6 @@ for (; *results != NULL; results += 2) { if (strcasecmp(results[0], "charset") == 0) { ctx->content_charset = i_strdup(results[1]); - ctx->charset_utf8 = charset_is_utf8(results[1]); break; } } @@ -243,7 +241,7 @@ (part->flags & (MESSAGE_PART_FLAG_TEXT | MESSAGE_PART_FLAG_MESSAGE_RFC822)) == 0; - if (ctx->charset_utf8 || ctx->binary_input) + if (ctx->binary_input) return; if (ctx->charset_trans != NULL && ctx->content_charset != NULL && @@ -334,21 +332,6 @@ if (ctx->binary_input) { output->data = data; output->size = size; - } else if (ctx->charset_utf8 || ctx->charset_trans == NULL) { - /* handle unknown charsets the same as UTF-8. it might find - usable ASCII text. */ - buffer_set_used_size(ctx->buf2, 0); - if (ctx->normalizer != NULL) { - (void)ctx->normalizer(data, size, ctx->buf2); - output->data = ctx->buf2->data; - output->size = ctx->buf2->used; - } else if (uni_utf8_get_valid_data(data, size, ctx->buf2)) { - output->data = data; - output->size = size; - } else { - output->data = ctx->buf2->data; - output->size = ctx->buf2->used; - } } else { buffer_set_used_size(ctx->buf2, 0); if (ctx->translation_size != 0) @@ -400,6 +383,5 @@ { i_free_and_null(ctx->content_charset); ctx->message_cte = MESSAGE_CTE_78BIT; - ctx->charset_utf8 = TRUE; buffer_set_used_size(ctx->encoding_buf, 0); } diff -r f191dbcaec5f -r e3640ccaa76d src/lib-mail/test-message-decoder.c --- a/src/lib-mail/test-message-decoder.c Sat Jan 10 04:30:40 2015 +0200 +++ b/src/lib-mail/test-message-decoder.c Sat Jan 10 04:32:42 2015 +0200 @@ -16,34 +16,6 @@ buffer_append(dest, data, size); } -int quoted_printable_decode(const unsigned char *src, size_t src_size, - size_t *src_pos_r, buffer_t *dest) -{ - while (src_size > 0 && src[src_size-1] == ' ') - src_size--; - buffer_append(dest, src, src_size); - *src_pos_r = src_size; - return 0; -} - -int charset_to_utf8_begin(const char *charset ATTR_UNUSED, - normalizer_func_t *normalizer ATTR_UNUSED, - struct charset_translation **t_r) -{ - *t_r = NULL; - return 0; -} -void charset_to_utf8_end(struct charset_translation **t ATTR_UNUSED) { } -bool charset_is_utf8(const char *charset ATTR_UNUSED) { return TRUE; } - -enum charset_result -charset_to_utf8(struct charset_translation *t ATTR_UNUSED, - const unsigned char *src, size_t *src_size, buffer_t *dest) -{ - buffer_append(dest, src, *src_size); - return CHARSET_RET_OK; -} - static void test_message_decoder(void) { struct message_decoder_context *ctx; @@ -86,6 +58,25 @@ test_assert(output.size == 14); test_assert(memcmp(output.data, " bar", 14) == 0); + /* partial text - \xC3\xA4 in quoted-printable. we should get a single + UTF-8 letter as result */ + input.data = (const void *)"="; input.size = 1; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 0); + input.data = (const void *)"C"; input.size = 1; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 0); + input.data = (const void *)"3"; input.size = 1; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 0); + input.data = (const void *)"=A"; input.size = 2; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 0); + input.data = (const void *)"4"; input.size = 1; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 2); + test_assert(memcmp(output.data, "\xC3\xA4", 2) == 0); + message_decoder_deinit(&ctx); test_end(); From dovecot at dovecot.org Wed Jan 14 22:12:29 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 22:12:29 +0000 Subject: dovecot-2.2: lib-storage: Added "oldestonly" search arg to stop ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/14bf136959bc changeset: 18147:14bf136959bc user: Timo Sirainen date: Thu Jan 15 00:10:56 2015 +0200 description: lib-storage: Added "oldestonly" search arg to stop searching after the first non-match. This parameter works only for doveadm search queries. It's not fully exact currently, because if mailbox.search_next_update_seq() skips over non-matching messages we don't stop if the next message matches. So this parameter is mainly useful for optimization of commands like: doveadm expunge -u user at domain mailbox inbox savedsince 30d oldestonly Where the timestamps should be ascending all the time anyway and there's no point in continuing to search for more mails after the first timestamp is too high. diffstat: src/lib-storage/index/index-search.c | 12 +++++++++++- src/lib-storage/mail-search-build.c | 3 +-- src/lib-storage/mail-search-build.h | 1 + src/lib-storage/mail-search-register-human.c | 10 +++++++++- src/lib-storage/mail-search.h | 3 +++ 5 files changed, 25 insertions(+), 4 deletions(-) diffs (97 lines): diff -r e3640ccaa76d -r 14bf136959bc src/lib-storage/index/index-search.c --- a/src/lib-storage/index/index-search.c Sat Jan 10 04:32:42 2015 +0200 +++ b/src/lib-storage/index/index-search.c Thu Jan 15 00:10:56 2015 +0200 @@ -1561,6 +1561,12 @@ break; } + /* non-match */ + if (_ctx->args->stop_on_nonmatch) { + ret = -1; + break; + } + cost2 = search_get_cost(mail->transaction); ctx->cost += cost2 - cost1; cost1 = cost2; @@ -1685,10 +1691,14 @@ if (imail->data.search_results == NULL) break; - /* searching wasn't finished yet */ + /* prefetch running - searching wasn't finished yet */ if (search_finish_prefetch(ctx, imail)) break; /* search finished as non-match */ + if (ctx->mail_ctx.args->stop_on_nonmatch) { + ret = -1; + break; + } } return ret; } diff -r e3640ccaa76d -r 14bf136959bc src/lib-storage/mail-search-build.c --- a/src/lib-storage/mail-search-build.c Sat Jan 10 04:32:42 2015 +0200 +++ b/src/lib-storage/mail-search-build.c Thu Jan 15 00:10:56 2015 +0200 @@ -146,9 +146,8 @@ *args_r = NULL; *error_r = NULL; - args = mail_search_build_init(); - memset(&ctx, 0, sizeof(ctx)); + ctx.args = args = mail_search_build_init(); ctx.pool = args->pool; ctx.reg = reg; ctx.parser = parser; diff -r e3640ccaa76d -r 14bf136959bc src/lib-storage/mail-search-build.h --- a/src/lib-storage/mail-search-build.h Sat Jan 10 04:32:42 2015 +0200 +++ b/src/lib-storage/mail-search-build.h Thu Jan 15 00:10:56 2015 +0200 @@ -8,6 +8,7 @@ struct mail_search_build_context { pool_t pool; + struct mail_search_args *args; struct mail_search_register *reg; struct mail_search_parser *parser; const char *charset; diff -r e3640ccaa76d -r 14bf136959bc src/lib-storage/mail-search-register-human.c --- a/src/lib-storage/mail-search-register-human.c Sat Jan 10 04:32:42 2015 +0200 +++ b/src/lib-storage/mail-search-register-human.c Thu Jan 15 00:10:56 2015 +0200 @@ -159,6 +159,13 @@ return mail_search_build_str(ctx, SEARCH_MAILBOX_GUID); } +static struct mail_search_arg * +human_search_oldestonly(struct mail_search_build_context *ctx) +{ + ctx->args->stop_on_nonmatch = TRUE; + return mail_search_build_new(ctx, SEARCH_ALL); +} + static const struct mail_search_register_arg human_register_args[] = { { "OR", human_search_or }, @@ -183,7 +190,8 @@ /* Other Dovecot extensions: */ { "GUID", human_search_guid }, { "MAILBOX", human_search_mailbox }, - { "MAILBOX-GUID", human_search_mailbox_guid } + { "MAILBOX-GUID", human_search_mailbox_guid }, + { "OLDESTONLY", human_search_oldestonly } }; static struct mail_search_register * diff -r e3640ccaa76d -r 14bf136959bc src/lib-storage/mail-search.h --- a/src/lib-storage/mail-search.h Sat Jan 10 04:32:42 2015 +0200 +++ b/src/lib-storage/mail-search.h Thu Jan 15 00:10:56 2015 +0200 @@ -109,6 +109,9 @@ unsigned int simplified:1; unsigned int have_inthreads:1; + /* Stop mail_search_next() when finding a non-matching mail. + (Could be useful when wanting to find only the oldest mails.) */ + unsigned int stop_on_nonmatch:1; }; #define ARG_SET_RESULT(arg, res) \ From dovecot at dovecot.org Wed Jan 14 23:23:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:20 +0000 Subject: dovecot-2.2: lib: Fixed NUL-handling in uni_utf8_*strlen*() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e645ee117fa9 changeset: 18148:e645ee117fa9 user: Timo Sirainen date: Thu Jan 15 01:03:58 2015 +0200 description: lib: Fixed NUL-handling in uni_utf8_*strlen*() uni_utf8_strlen() could have skipped over the ending NUL byte and caused read buffer overflows with invalid input. uni_utf8_strlen_n() and uni_utf8_partial_strlen_n() now allow NUL bytes in the input and they're treated as regular control characters. Previously the size was actually treated as max_size with early NUL byte termination. Technically this is an API change, but I'm not aware of anything using these functions in an incompatible way. diffstat: src/lib/test-unichar.c | 22 ++++++++++++++++++++-- src/lib/unichar.c | 4 ++-- src/lib/unichar.h | 4 ++-- 3 files changed, 24 insertions(+), 6 deletions(-) diffs (83 lines): diff -r 14bf136959bc -r e645ee117fa9 src/lib/test-unichar.c --- a/src/lib/test-unichar.c Thu Jan 15 00:10:56 2015 +0200 +++ b/src/lib/test-unichar.c Thu Jan 15 01:03:58 2015 +0200 @@ -5,9 +5,25 @@ #include "buffer.h" #include "unichar.h" +static void test_unichar_uni_utf8_strlen(void) +{ + static const char input[] = "\xC3\xA4\xC3\xA4\0a"; + + test_begin("uni_utf8_strlen()"); + test_assert(uni_utf8_strlen(input) == 2); + test_end(); + + test_begin("uni_utf8_strlen_n()"); + test_assert(uni_utf8_strlen_n(input, 1) == 0); + test_assert(uni_utf8_strlen_n(input, 2) == 1); + test_assert(uni_utf8_strlen_n(input, 3) == 1); + test_assert(uni_utf8_strlen_n(input, 4) == 2); + test_end(); +} + static void test_unichar_uni_utf8_partial_strlen_n(void) { - static const char input[] = "\xC3\xA4\xC3\xA4"; + static const char input[] = "\xC3\xA4\xC3\xA4\0a"; size_t pos; test_begin("uni_utf8_partial_strlen_n()"); @@ -15,7 +31,8 @@ test_assert(uni_utf8_partial_strlen_n(input, 2, &pos) == 1 && pos == 2); test_assert(uni_utf8_partial_strlen_n(input, 3, &pos) == 1 && pos == 2); test_assert(uni_utf8_partial_strlen_n(input, 4, &pos) == 2 && pos == 4); - test_assert(uni_utf8_partial_strlen_n(input, (size_t)-1, &pos) == 2 && pos == 4); + test_assert(uni_utf8_partial_strlen_n(input, 5, &pos) == 3 && pos == 5); + test_assert(uni_utf8_partial_strlen_n(input, 6, &pos) == 4 && pos == 6); test_end(); } @@ -47,5 +64,6 @@ test_assert(uni_utf8_get_char(overlong_utf8, &chr2) < 0); test_end(); + test_unichar_uni_utf8_strlen(); test_unichar_uni_utf8_partial_strlen_n(); } diff -r 14bf136959bc -r e645ee117fa9 src/lib/unichar.c --- a/src/lib/unichar.c Thu Jan 15 00:10:56 2015 +0200 +++ b/src/lib/unichar.c Thu Jan 15 01:03:58 2015 +0200 @@ -189,7 +189,7 @@ unsigned int uni_utf8_strlen(const char *input) { - return uni_utf8_strlen_n(input, (size_t)-1); + return uni_utf8_strlen_n(input, strlen(input)); } unsigned int uni_utf8_strlen_n(const void *input, size_t size) @@ -206,7 +206,7 @@ unsigned int count, len = 0; size_t i; - for (i = 0; i < size && input[i] != '\0'; ) { + for (i = 0; i < size; ) { count = uni_utf8_char_bytes(input[i]); if (i + count > size) break; diff -r 14bf136959bc -r e645ee117fa9 src/lib/unichar.h --- a/src/lib/unichar.h Thu Jan 15 00:10:56 2015 +0200 +++ b/src/lib/unichar.h Thu Jan 15 01:03:58 2015 +0200 @@ -51,9 +51,9 @@ -1 for invalid input. */ int uni_utf8_get_char(const char *input, unichar_t *chr_r); int uni_utf8_get_char_n(const void *input, size_t max_len, unichar_t *chr_r); -/* Returns UTF-8 string length. */ +/* Returns number of characters in UTF-8 string. */ unsigned int uni_utf8_strlen(const char *input) ATTR_PURE; -/* Returns UTF-8 string length with maximum input size. */ +/* Returns number of characters in UTF-8 input of specified size. */ unsigned int uni_utf8_strlen_n(const void *input, size_t size) ATTR_PURE; /* Same as uni_utf8_strlen_n(), but if input ends with a partial UTF-8 character, don't include it in the return value and set partial_pos_r to From dovecot at dovecot.org Wed Jan 14 23:23:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:20 +0000 Subject: dovecot-2.2: lib-charset: Added charset_utf8_to_utf8_begin() wra... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0e74934072e0 changeset: 18149:0e74934072e0 user: Timo Sirainen date: Thu Jan 15 01:05:13 2015 +0200 description: lib-charset: Added charset_utf8_to_utf8_begin() wrapper function. It's never supposed to fail, so it makes it nicer for the callers who need to use it. diffstat: src/lib-charset/charset-utf8.c | 10 ++++++++++ src/lib-charset/charset-utf8.h | 3 +++ 2 files changed, 13 insertions(+), 0 deletions(-) diffs (33 lines): diff -r e645ee117fa9 -r 0e74934072e0 src/lib-charset/charset-utf8.c --- a/src/lib-charset/charset-utf8.c Thu Jan 15 01:03:58 2015 +0200 +++ b/src/lib-charset/charset-utf8.c Thu Jan 15 01:05:13 2015 +0200 @@ -32,6 +32,16 @@ return 0; } +struct charset_translation * +charset_utf8_to_utf8_begin(normalizer_func_t *normalizer) +{ + struct charset_translation *trans; + + if (charset_to_utf8_begin("UTF-8", normalizer, &trans) < 0) + i_unreached(); + return trans; +} + #ifndef HAVE_ICONV struct charset_translation { diff -r e645ee117fa9 -r 0e74934072e0 src/lib-charset/charset-utf8.h --- a/src/lib-charset/charset-utf8.h Thu Jan 15 01:03:58 2015 +0200 +++ b/src/lib-charset/charset-utf8.h Thu Jan 15 01:05:13 2015 +0200 @@ -15,6 +15,9 @@ int charset_to_utf8_begin(const char *charset, normalizer_func_t *normalizer, struct charset_translation **t_r) ATTR_NULL(2); +/* Translate UTF-8 to UTF-8 while validating the input. */ +struct charset_translation * +charset_utf8_to_utf8_begin(normalizer_func_t *normalizer); void charset_to_utf8_end(struct charset_translation **t); void charset_to_utf8_reset(struct charset_translation *t); From dovecot at dovecot.org Wed Jan 14 23:23:25 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:25 +0000 Subject: dovecot-2.2: lib-charset: Added CHARSET_MAX_PENDING_BUF_SIZE mac... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3d9ec121dc81 changeset: 18150:3d9ec121dc81 user: Timo Sirainen date: Thu Jan 15 01:05:36 2015 +0200 description: lib-charset: Added CHARSET_MAX_PENDING_BUF_SIZE macro and asserts for it. diffstat: src/lib-charset/charset-iconv.c | 1 + src/lib-charset/charset-utf8.c | 1 + src/lib-charset/charset-utf8.h | 12 +++++++++++- 3 files changed, 13 insertions(+), 1 deletions(-) diffs (51 lines): diff -r 0e74934072e0 -r 3d9ec121dc81 src/lib-charset/charset-iconv.c --- a/src/lib-charset/charset-iconv.c Thu Jan 15 01:05:13 2015 +0200 +++ b/src/lib-charset/charset-iconv.c Thu Jan 15 01:05:36 2015 +0200 @@ -129,6 +129,7 @@ if (prev_invalid_pos != (size_t)-1) result = CHARSET_RET_INVALID_INPUT; + i_assert(*src_size - pos <= CHARSET_MAX_PENDING_BUF_SIZE); *src_size = pos; return result; } diff -r 0e74934072e0 -r 3d9ec121dc81 src/lib-charset/charset-utf8.c --- a/src/lib-charset/charset-utf8.c Thu Jan 15 01:05:13 2015 +0200 +++ b/src/lib-charset/charset-utf8.c Thu Jan 15 01:05:36 2015 +0200 @@ -94,6 +94,7 @@ uni_utf8_partial_strlen_n(src, *src_size, &pos); if (pos < *src_size) { + i_assert(*src_size - pos <= CHARSET_MAX_PENDING_BUF_SIZE); *src_size = pos; res = CHARSET_RET_INCOMPLETE_INPUT; } diff -r 0e74934072e0 -r 3d9ec121dc81 src/lib-charset/charset-utf8.h --- a/src/lib-charset/charset-utf8.h Thu Jan 15 01:05:13 2015 +0200 +++ b/src/lib-charset/charset-utf8.h Thu Jan 15 01:05:36 2015 +0200 @@ -3,6 +3,11 @@ #include "unichar.h" +/* Max number of bytes that iconv can require for a single character. + UTF-8 takes max 6 bytes per character. Not sure about others, but I'd think + 10 is more than enough for everyone.. */ +#define CHARSET_MAX_PENDING_BUF_SIZE 10 + struct charset_translation; enum charset_result { @@ -25,7 +30,12 @@ bool charset_is_utf8(const char *charset) ATTR_PURE; /* Translate src to UTF-8. src_size is updated to contain the number of - characters actually translated from src. */ + characters actually translated from src. The src_size should never shrink + more than CHARSET_MAX_PENDING_BUF_SIZE bytes. + + If src contains invalid input, UNICODE_REPLACEMENT_CHAR is placed in such + positions and the invalid input is skipped over. Return value is also + CHARSET_RET_INCOMPLETE_INPUT in that case. */ enum charset_result charset_to_utf8(struct charset_translation *t, const unsigned char *src, size_t *src_size, buffer_t *dest); From dovecot at dovecot.org Wed Jan 14 23:23:30 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:30 +0000 Subject: dovecot-2.2: lib-mail: Replaced MAX_TRANSLATION_BUF_SIZE with th... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e49a2e800650 changeset: 18151:e49a2e800650 user: Timo Sirainen date: Thu Jan 15 01:08:00 2015 +0200 description: lib-mail: Replaced MAX_TRANSLATION_BUF_SIZE with the new CHARSET_MAX_PENDING_BUF_SIZE diffstat: src/lib-mail/message-decoder.c | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-) diffs (41 lines): diff -r 3d9ec121dc81 -r e49a2e800650 src/lib-mail/message-decoder.c --- a/src/lib-mail/message-decoder.c Thu Jan 15 01:05:36 2015 +0200 +++ b/src/lib-mail/message-decoder.c Thu Jan 15 01:08:00 2015 +0200 @@ -16,10 +16,6 @@ /* base64 takes max 4 bytes per character, q-p takes max 3. */ #define MAX_ENCODING_BUF_SIZE 3 -/* UTF-8 takes max 5 bytes per character. Not sure about others, but I'd think - 10 is more than enough for everyone.. */ -#define MAX_TRANSLATION_BUF_SIZE 10 - struct message_decoder_context { enum message_decoder_flags flags; normalizer_func_t *normalizer; @@ -30,7 +26,7 @@ char *charset_trans_charset; struct charset_translation *charset_trans; - char translation_buf[MAX_TRANSLATION_BUF_SIZE]; + char translation_buf[CHARSET_MAX_PENDING_BUF_SIZE]; unsigned int translation_size; buffer_t *encoding_buf; @@ -197,7 +193,7 @@ static void translation_buf_decode(struct message_decoder_context *ctx, const unsigned char **data, size_t *size) { - unsigned char trans_buf[MAX_TRANSLATION_BUF_SIZE+1]; + unsigned char trans_buf[CHARSET_MAX_PENDING_BUF_SIZE+1]; unsigned int data_wanted, skip; size_t trans_size, orig_size; @@ -216,7 +212,7 @@ if (trans_size <= ctx->translation_size) { /* need more data to finish the translation. */ - i_assert(orig_size < MAX_TRANSLATION_BUF_SIZE); + i_assert(orig_size < CHARSET_MAX_PENDING_BUF_SIZE); memcpy(ctx->translation_buf, trans_buf, orig_size); ctx->translation_size = orig_size; *data += *size; From dovecot at dovecot.org Wed Jan 14 23:23:31 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:31 +0000 Subject: dovecot-2.2: lib-mail: Fixed crash in message-decoder with unkno... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/38e807433e2f changeset: 18152:38e807433e2f user: Timo Sirainen date: Thu Jan 15 01:10:11 2015 +0200 description: lib-mail: Fixed crash in message-decoder with unknown charsets. Caused by earlier changes. diffstat: src/lib-mail/message-decoder.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r e49a2e800650 -r 38e807433e2f src/lib-mail/message-decoder.c --- a/src/lib-mail/message-decoder.c Thu Jan 15 01:08:00 2015 +0200 +++ b/src/lib-mail/message-decoder.c Thu Jan 15 01:10:11 2015 +0200 @@ -254,7 +254,7 @@ ctx->content_charset : "UTF-8"); if (charset_to_utf8_begin(ctx->charset_trans_charset, ctx->normalizer, &ctx->charset_trans) < 0) - ctx->charset_trans = NULL; + ctx->charset_trans = charset_utf8_to_utf8_begin(ctx->normalizer); } static bool message_decode_body(struct message_decoder_context *ctx, From dovecot at dovecot.org Wed Jan 14 23:23:31 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:31 +0000 Subject: dovecot-2.2: lib-mail: message-decoder now always sets output->s... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/7250ccf9ab4c changeset: 18153:7250ccf9ab4c user: Timo Sirainen date: Thu Jan 15 01:11:34 2015 +0200 description: lib-mail: message-decoder now always sets output->size=0 when headers are returned. diffstat: src/lib-mail/message-decoder.c | 5 +++-- src/lib-mail/test-message-decoder.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diffs (36 lines): diff -r 38e807433e2f -r 7250ccf9ab4c src/lib-mail/message-decoder.c --- a/src/lib-mail/message-decoder.c Thu Jan 15 01:10:11 2015 +0200 +++ b/src/lib-mail/message-decoder.c Thu Jan 15 01:11:34 2015 +0200 @@ -363,9 +363,10 @@ output->part = input->part; ctx->prev_part = input->part; - if (input->hdr != NULL) + if (input->hdr != NULL) { + output->size = 0; return message_decode_header(ctx, input->hdr, output); - else if (input->size != 0) + } else if (input->size != 0) return message_decode_body(ctx, input, output); else { output->hdr = NULL; diff -r 38e807433e2f -r 7250ccf9ab4c src/lib-mail/test-message-decoder.c --- a/src/lib-mail/test-message-decoder.c Thu Jan 15 01:10:11 2015 +0200 +++ b/src/lib-mail/test-message-decoder.c Thu Jan 15 01:11:34 2015 +0200 @@ -27,7 +27,7 @@ memset(&part, 0, sizeof(part)); memset(&input, 0, sizeof(input)); - memset(&output, 0, sizeof(output)); + memset(&output, 0xff, sizeof(output)); input.part = ∂ ctx = message_decoder_init(NULL, 0); @@ -39,6 +39,7 @@ hdr.full_value_len = strlen((const char *)hdr.full_value); input.hdr = &hdr; test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(output.size == 0); input.hdr = NULL; test_assert(message_decoder_decode_next_block(ctx, &input, &output)); From dovecot at dovecot.org Wed Jan 14 23:23:41 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:23:41 +0000 Subject: dovecot-2.2: lib-mail: Added message_decoder_current_content_type() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/55555824f636 changeset: 18154:55555824f636 user: Timo Sirainen date: Thu Jan 15 01:22:04 2015 +0200 description: lib-mail: Added message_decoder_current_content_type() diffstat: src/lib-mail/message-decoder.c | 15 ++++++- src/lib-mail/test-message-decoder.c | 64 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diffs (132 lines): diff -r 7250ccf9ab4c -r 55555824f636 src/lib-mail/message-decoder.c --- a/src/lib-mail/message-decoder.c Thu Jan 15 01:11:34 2015 +0200 +++ b/src/lib-mail/message-decoder.c Thu Jan 15 01:22:04 2015 +0200 @@ -31,7 +31,7 @@ buffer_t *encoding_buf; - char *content_charset; + char *content_type, *content_charset; enum message_cte message_cte; unsigned int binary_input:1; @@ -69,6 +69,7 @@ buffer_free(&ctx->buf); buffer_free(&ctx->buf2); i_free(ctx->charset_trans_charset); + i_free(ctx->content_type); i_free(ctx->content_charset); i_free(ctx); } @@ -124,14 +125,15 @@ const char *const *results; string_t *str; - if (ctx->content_charset != NULL) + if (ctx->content_type != NULL) return; rfc822_parser_init(&parser, hdr->full_value, hdr->full_value_len, NULL); rfc822_skip_lwsp(&parser); str = t_str_new(64); - if (rfc822_parse_content_type(&parser, str) <= 0) + if (rfc822_parse_content_type(&parser, str) < 0) return; + ctx->content_type = i_strdup(str_c(str)); rfc2231_parse(&parser, &results); for (; *results != NULL; results += 2) { @@ -376,8 +378,15 @@ } } +const char * +message_decoder_current_content_type(struct message_decoder_context *ctx) +{ + return ctx->content_type; +} + void message_decoder_decode_reset(struct message_decoder_context *ctx) { + i_free_and_null(ctx->content_type); i_free_and_null(ctx->content_charset); ctx->message_cte = MESSAGE_CTE_78BIT; buffer_set_used_size(ctx->encoding_buf, 0); diff -r 7250ccf9ab4c -r 55555824f636 src/lib-mail/test-message-decoder.c --- a/src/lib-mail/test-message-decoder.c Thu Jan 15 01:11:34 2015 +0200 +++ b/src/lib-mail/test-message-decoder.c Thu Jan 15 01:22:04 2015 +0200 @@ -83,10 +83,74 @@ test_end(); } +static void test_message_decoder_current_content_type(void) +{ + struct message_decoder_context *ctx; + struct message_part part, part2, part3; + struct message_header_line hdr; + struct message_block input, output; + + test_begin("message_decoder_current_content_type()"); + + memset(&part, 0, sizeof(part)); + part2 = part3 = part; + + memset(&input, 0, sizeof(input)); + memset(&output, 0xff, sizeof(output)); + input.part = ∂ + + ctx = message_decoder_init(NULL, 0); + test_assert(message_decoder_current_content_type(ctx) == NULL); + + /* multipart/mixed */ + memset(&hdr, 0, sizeof(hdr)); + hdr.name = "Content-Type"; + hdr.name_len = strlen(hdr.name); + hdr.full_value = (const void *)"multipart/mixed; boundary=x"; + hdr.full_value_len = strlen((const char *)hdr.full_value); + input.hdr = &hdr; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + + input.hdr = NULL; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(strcmp(message_decoder_current_content_type(ctx), "multipart/mixed") == 0); + + /* child 1 */ + input.part = &part2; + hdr.full_value = (const void *)"text/plain"; + hdr.full_value_len = strlen((const char *)hdr.full_value); + input.hdr = &hdr; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + + input.hdr = NULL; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(strcmp(message_decoder_current_content_type(ctx), "text/plain") == 0); + + /* child 2 */ + input.part = &part3; + hdr.full_value = (const void *)"application/pdf"; + hdr.full_value_len = strlen((const char *)hdr.full_value); + input.hdr = &hdr; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + + input.hdr = NULL; + test_assert(message_decoder_decode_next_block(ctx, &input, &output)); + test_assert(strcmp(message_decoder_current_content_type(ctx), "application/pdf") == 0); + + /* reset */ + message_decoder_decode_reset(ctx); + test_assert(message_decoder_current_content_type(ctx) == NULL); + + message_decoder_deinit(&ctx); + + test_end(); +} + int main(void) { static void (*test_functions[])(void) = { test_message_decoder, + test_message_decoder_current_content_type, NULL }; return test_run(test_functions); From dovecot at dovecot.org Wed Jan 14 23:27:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 14 Jan 2015 23:27:11 +0000 Subject: dovecot-2.2: lib-mail: Forgot to commit .h file for message_deco... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3d612ade5d75 changeset: 18155:3d612ade5d75 user: Timo Sirainen date: Thu Jan 15 01:26:02 2015 +0200 description: lib-mail: Forgot to commit .h file for message_decoder_current_content_type() change. diffstat: src/lib-mail/message-decoder.h | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r 55555824f636 -r 3d612ade5d75 src/lib-mail/message-decoder.h --- a/src/lib-mail/message-decoder.h Thu Jan 15 01:22:04 2015 +0200 +++ b/src/lib-mail/message-decoder.h Thu Jan 15 01:26:02 2015 +0200 @@ -40,6 +40,11 @@ struct message_block *input, struct message_block *output); +/* Returns the parsed Content-Type of the current MIME part. If there is no + explicit Content-Type, returns NULL. */ +const char * +message_decoder_current_content_type(struct message_decoder_context *ctx); + /* Call whenever message changes */ void message_decoder_decode_reset(struct message_decoder_context *ctx); From pigeonhole at rename-it.nl Fri Jan 16 17:26:02 2015 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Fri, 16 Jan 2015 18:26:02 +0100 Subject: dovecot-2.2-pigeonhole: lib-sieve: file storage: Restructured st... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/cd8194a2469e changeset: 1986:cd8194a2469e user: Stephan Bosch date: Fri Jan 16 18:25:51 2015 +0100 description: lib-sieve: file storage: Restructured storage initialization to address backwards compatibility issues. diffstat: src/lib-sieve/storage/file/sieve-file-script.c | 105 +- src/lib-sieve/storage/file/sieve-file-storage-active.c | 9 +- src/lib-sieve/storage/file/sieve-file-storage-list.c | 1 + src/lib-sieve/storage/file/sieve-file-storage-quota.c | 1 + src/lib-sieve/storage/file/sieve-file-storage-save.c | 1 + src/lib-sieve/storage/file/sieve-file-storage.c | 594 +++++++++++----- src/lib-sieve/storage/file/sieve-file-storage.h | 3 + 7 files changed, 459 insertions(+), 255 deletions(-) diffs (truncated from 978 to 300 lines): diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-script.c --- a/src/lib-sieve/storage/file/sieve-file-script.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-script.c Fri Jan 16 18:25:51 2015 +0100 @@ -52,7 +52,7 @@ */ static void sieve_file_script_handle_error -(struct sieve_file_script *fscript, const char *path, +(struct sieve_file_script *fscript, const char *op, const char *path, const char *name, enum sieve_error *error_r) { struct sieve_script *script = &fscript->script; @@ -67,12 +67,14 @@ break; case EACCES: sieve_script_set_critical(script, - "Failed to stat sieve script: %s", eacces_error_get("stat", path)); + "Failed to %s sieve script: %s", + op, eacces_error_get(op, path)); *error_r = SIEVE_ERROR_NO_PERMISSION; break; default: sieve_script_set_critical(script, - "Failed to stat sieve script: stat(%s) failed: %m", path); + "Failed to %s sieve script: %s(%s) failed: %m", + op, op, path); *error_r = SIEVE_ERROR_TEMP_FAILURE; break; } @@ -150,14 +152,15 @@ struct sieve_storage *storage = &fstorage->storage; struct sieve_file_script *fscript; - if (name != NULL) { + if (name != NULL && S_ISDIR(fstorage->st.st_mode)) { return sieve_file_script_init_from_filename (fstorage, sieve_script_file_from_name(name), name); } fscript = sieve_file_script_alloc(); sieve_script_init - (&fscript->script, storage, &sieve_file_script, fstorage->path, NULL); + (&fscript->script, storage, &sieve_file_script, + fstorage->active_path, name); return fscript; } @@ -259,7 +262,7 @@ if ( S_ISLNK(st->st_mode) && stat(path, st) < 0 ) return -1; - return 1; + return 0; } static const char * @@ -289,67 +292,67 @@ pool_t pool = script->pool; const char *filename, *name, *path; const char *dirpath, *basename, *binpath, *binprefix; - struct stat st; - struct stat lnk_st; + struct stat st, lnk_st; bool success = TRUE; - int ret; + int ret = 0; filename = fscript->filename; basename = NULL; name = script->name; - path = fstorage->path; + st = fstorage->st; + lnk_st = fstorage->lnk_st; if (name == NULL) name = storage->script_name; T_BEGIN { - if ( (ret=sieve_file_script_stat(path, &st, &lnk_st)) > 0 ) { - if ( S_ISDIR(st.st_mode) ) { - /* Path is directory */ - if ( (filename == NULL || *filename == '\0') && - name != NULL && *name != '\0' ) { - /* Name is used to find actual filename */ - filename = sieve_script_file_from_name(name); + if ( S_ISDIR(st.st_mode) ) { + /* Storage is a directory */ + path = fstorage->path; + + if ( (filename == NULL || *filename == '\0') && + name != NULL && *name != '\0' ) { + /* Name is used to find actual filename */ + filename = sieve_script_file_from_name(name); + basename = name; + } + if ( filename == NULL || *filename == '\0' ) { + sieve_script_set_critical(script, + "Sieve script file path '%s' is a directory.", path); + *error_r = SIEVE_ERROR_TEMP_FAILURE; + success = FALSE; + } else { + /* Extend storage path with filename */ + if (name == NULL) { + if ( basename == NULL && + (basename=sieve_script_file_get_scriptname(filename)) == NULL ) + basename = filename; + name = basename; + } else if (basename == NULL) { basename = name; } - if ( filename == NULL || *filename == '\0' ) { - sieve_script_set_critical(script, - "Sieve script file path '%s' is a directory.", path); - *error_r = SIEVE_ERROR_TEMP_FAILURE; - success = FALSE; - } else { - /* Extend storage path with filename */ - if (name == NULL) { - if ( basename == NULL && - (basename=sieve_script_file_get_scriptname(filename)) == NULL ) - basename = filename; - name = basename; - } else if (basename == NULL) { - basename = name; - } - dirpath = path; + dirpath = path; - path = sieve_file_storage_path_extend(fstorage, filename); - ret = sieve_file_script_stat(path, &st, &lnk_st); - } + path = sieve_file_storage_path_extend(fstorage, filename); + ret = sieve_file_script_stat(path, &st, &lnk_st); + } - } else { + } else { + /* Storage is a single file */ + path = fstorage->active_path; - /* Extract filename from path */ - filename = path_split_filename(path, &dirpath); + /* Extract filename from path */ + filename = path_split_filename(path, &dirpath); - if ( (basename=sieve_script_file_get_scriptname(filename)) == NULL ) - basename = filename; + if ( (basename=sieve_script_file_get_scriptname(filename)) == NULL ) + basename = filename; - if ( name == NULL ) - name = basename; - } - } else { - basename = name; + if ( name == NULL ) + name = basename; } if ( success ) { - if ( ret <= 0 ) { + if ( ret < 0 ) { /* Make sure we have a script name for the error */ if ( name == NULL ) { if ( basename == NULL ) { @@ -361,7 +364,8 @@ } name = basename; } - sieve_file_script_handle_error(fscript, path, name, error_r); + sieve_file_script_handle_error + (fscript, "stat", path, name, error_r); success = FALSE; } else if ( !S_ISREG(st.st_mode) ) { @@ -431,7 +435,7 @@ if ( (fd=open(fscript->path, O_RDONLY)) < 0 ) { sieve_file_script_handle_error - (fscript, fscript->path, fscript->script.name, error_r); + (fscript, "open", fscript->path, fscript->script.name, error_r); return -1; } @@ -599,6 +603,8 @@ if ( ret <= 0 || strcmp(fscript->filename, afile) != 0 ) activated = 1; + i_assert( fstorage->link_path != NULL ); + /* Check the scriptfile we are trying to activate */ if ( lstat(fscript->path, &st) != 0 ) { sieve_script_set_critical(script, @@ -684,6 +690,7 @@ /* Is the requested script active? */ if ( sieve_script_is_active(script) ) { /* Active; make active link point to the new copy */ + i_assert( fstorage->link_path != NULL ); link_path = t_strconcat ( fstorage->link_path, newfile, NULL ); diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-storage-active.c --- a/src/lib-sieve/storage/file/sieve-file-storage-active.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-storage-active.c Fri Jan 16 18:25:51 2015 +0100 @@ -133,6 +133,7 @@ } /* Check whether the path is any good */ + i_assert( fstorage->link_path != NULL ); if ( _file_path_cmp(scriptpath, fstorage->link_path) != 0 && _file_path_cmp(scriptpath, fstorage->path) != 0 ) { sieve_storage_sys_warning(storage, @@ -284,8 +285,12 @@ return NULL; /* Try to open the active_path as a regular file */ - fscript = sieve_file_script_open_from_path(fstorage, - fstorage->active_path, NULL, NULL); + if ( S_ISDIR(fstorage->st.st_mode) ) { + fscript = sieve_file_script_open_from_path(fstorage, + fstorage->active_path, NULL, NULL); + } else { + fscript = sieve_file_script_open_from_name(fstorage, NULL); + } if ( fscript == NULL ) { if ( storage->error_code != SIEVE_ERROR_NOT_FOUND ) { sieve_storage_set_critical(storage, diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-storage-list.c --- a/src/lib-sieve/storage/file/sieve-file-storage-list.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-storage-list.c Fri Jan 16 18:25:51 2015 +0100 @@ -84,6 +84,7 @@ /* Don't list our active sieve script link if the link * resides in the script dir (generally a bad idea). */ + i_assert( fstorage->link_path != NULL ); if ( *(fstorage->link_path) == '\0' && strcmp(fstorage->active_fname, dp->d_name) == 0 ) continue; diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-storage-quota.c --- a/src/lib-sieve/storage/file/sieve-file-storage-quota.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-storage-quota.c Fri Jan 16 18:25:51 2015 +0100 @@ -60,6 +60,7 @@ /* Don't list our active sieve script link if the link * resides in the script dir (generally a bad idea). */ + i_assert( fstorage->link_path != NULL ); if ( *(fstorage->link_path) == '\0' && strcmp(fstorage->active_fname, dp->d_name) == 0 ) continue; diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-storage-save.c --- a/src/lib-sieve/storage/file/sieve-file-storage-save.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-storage-save.c Fri Jan 16 18:25:51 2015 +0100 @@ -184,6 +184,7 @@ /* Prevent overwriting the active script link when it resides in the * sieve storage directory. */ + i_assert( fstorage->link_path != NULL ); if ( *(fstorage->link_path) == '\0' ) { const char *svext; size_t namelen; diff -r 8f73af8e6c3a -r cd8194a2469e src/lib-sieve/storage/file/sieve-file-storage.c --- a/src/lib-sieve/storage/file/sieve-file-storage.c Fri Jan 16 18:23:49 2015 +0100 +++ b/src/lib-sieve/storage/file/sieve-file-storage.c Fri Jan 16 18:25:51 2015 +0100 @@ -2,6 +2,7 @@ */ #include "lib.h" +#include "abspath.h" #include "home-expand.h" #include "ioloop.h" #include "mkdir-parents.h" @@ -46,6 +47,46 @@ * */ +static int sieve_file_storage_stat +(struct sieve_file_storage *fstorage, const char *path, + enum sieve_error *error_r) +{ + struct sieve_storage *storage = &fstorage->storage; + struct stat st; + + if ( lstat(path, &st) == 0 ) { + fstorage->lnk_st = st; + + if ( !S_ISLNK(st.st_mode) || stat(path, &st) == 0 ) { + fstorage->st = st; + return 0; + } + } + + switch ( errno ) { + case ENOENT: + sieve_storage_sys_debug(storage, + "Storage path `%s' not found", t_abspath(path)); + sieve_storage_set_internal_error(storage); // should be overriden + *error_r = SIEVE_ERROR_NOT_FOUND; + break; + case EACCES: + sieve_storage_set_critical(storage, From pigeonhole at rename-it.nl Fri Jan 16 17:26:02 2015 From: pigeonhole at rename-it.nl (pigeonhole at rename-it.nl) Date: Fri, 16 Jan 2015 18:26:02 +0100 Subject: dovecot-2.2-pigeonhole: lib-sieve: Make sure internal script sto... Message-ID: details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/8f73af8e6c3a changeset: 1985:8f73af8e6c3a user: Stephan Bosch date: Fri Jan 16 18:23:49 2015 +0100 description: lib-sieve: Make sure internal script storage errors clear previous error. diffstat: src/lib-sieve/sieve-script.c | 4 +++- src/lib-sieve/sieve-storage.c | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diffs (53 lines): diff -r efe2a5fdcc25 -r 8f73af8e6c3a src/lib-sieve/sieve-script.c --- a/src/lib-sieve/sieve-script.c Thu Jan 08 02:07:51 2015 +0100 +++ b/src/lib-sieve/sieve-script.c Fri Jan 16 18:23:49 2015 +0100 @@ -571,7 +571,6 @@ va_list va; - sieve_storage_clear_error(storage); if (fmt != NULL) { if ( (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 ) { va_start(va, fmt); @@ -580,7 +579,10 @@ va_end(va); sieve_storage_set_internal_error(storage); + } else { + sieve_storage_clear_error(storage); + /* no user is involved while synchronizing, so do it the normal way */ va_start(va, fmt); diff -r efe2a5fdcc25 -r 8f73af8e6c3a src/lib-sieve/sieve-storage.c --- a/src/lib-sieve/sieve-storage.c Thu Jan 08 02:07:51 2015 +0100 +++ b/src/lib-sieve/sieve-storage.c Fri Jan 16 18:23:49 2015 +0100 @@ -986,6 +986,8 @@ struct tm *tm; char str[256]; + sieve_storage_clear_error(storage); + /* critical errors may contain sensitive data, so let user see only "Internal error" with a timestamp to make it easier to look from log files the actual error message. */ @@ -1003,7 +1005,6 @@ { va_list va; - sieve_storage_clear_error(storage); if (fmt != NULL) { if ( (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0 ) { va_start(va, fmt); @@ -1012,7 +1013,10 @@ va_end(va); sieve_storage_set_internal_error(storage); + } else { + sieve_storage_clear_error(storage); + /* no user is involved while synchronizing, so do it the normal way */ va_start(va, fmt); From dovecot at dovecot.org Fri Jan 16 22:16:56 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 22:16:56 +0000 Subject: dovecot-2.2: lib-mail: Added mail-html2text API Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d59753d9f5e9 changeset: 18156:d59753d9f5e9 user: Timo Sirainen date: Sat Jan 17 00:15:44 2015 +0200 description: lib-mail: Added mail-html2text API What makes it mail-specific is that it allows skipping over data inside
. This code probably doesn't parse HTML perfectly, but hopefully good enough for HTML emails. diffstat: src/lib-mail/Makefile.am | 10 + src/lib-mail/html-entities.h | 253 ++++++++++++++++++++++++++++ src/lib-mail/mail-html2text.c | 323 +++++++++++++++++++++++++++++++++++++ src/lib-mail/mail-html2text.h | 15 + src/lib-mail/test-mail-html2text.c | 80 +++++++++ 5 files changed, 681 insertions(+), 0 deletions(-) diffs (truncated from 735 to 300 lines): diff -r 3d612ade5d75 -r d59753d9f5e9 src/lib-mail/Makefile.am --- a/src/lib-mail/Makefile.am Thu Jan 15 01:26:02 2015 +0200 +++ b/src/lib-mail/Makefile.am Sat Jan 17 00:15:44 2015 +0200 @@ -13,6 +13,7 @@ istream-header-filter.c \ istream-nonuls.c \ istream-qp-decoder.c \ + mail-html2text.c \ mail-user-hash.c \ mbox-from.c \ message-address.c \ @@ -33,6 +34,9 @@ rfc2231-parser.c \ rfc822-parser.c +noinst_HEADERS = \ + html-entities.h + headers = \ istream-attachment-connector.h \ istream-attachment-extractor.h \ @@ -43,6 +47,7 @@ istream-qp.h \ mail-user-hash.h \ mbox-from.h \ + mail-html2text.h \ mail-types.h \ message-address.h \ message-binary-part.h \ @@ -71,6 +76,7 @@ test-istream-binary-converter \ test-istream-header-filter \ test-istream-qp-decoder \ + test-mail-html2text \ test-mbox-from \ test-message-address \ test-message-date \ @@ -160,6 +166,10 @@ test_message_part_LDADD = message-part.lo message-parser.lo message-header-parser.lo message-size.lo rfc822-parser.lo rfc2231-parser.lo $(test_libs) test_message_part_DEPENDENCIES = $(test_deps) +test_mail_html2text_SOURCES = test-mail-html2text.c +test_mail_html2text_LDADD = mail-html2text.lo $(test_libs) +test_mail_html2text_DEPENDENCIES = $(test_deps) + test_ostream_dot_SOURCES = test-ostream-dot.c test_ostream_dot_LDADD = ostream-dot.lo $(test_libs) test_ostream_dot_DEPENDENCIES = $(test_deps) diff -r 3d612ade5d75 -r d59753d9f5e9 src/lib-mail/html-entities.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-mail/html-entities.h Sat Jan 17 00:15:44 2015 +0200 @@ -0,0 +1,253 @@ +{ "quot", 0x0022 }, +{ "amp", 0x0026 }, +{ "apos", 0x0027 }, +{ "lt", 0x003C }, +{ "gt", 0x003E }, +{ "nbsp", 0x00A0 }, +{ "iexcl", 0x00A1 }, +{ "cent", 0x00A2 }, +{ "pound", 0x00A3 }, +{ "curren", 0x00A4 }, +{ "yen", 0x00A5 }, +{ "brvbar", 0x00A6 }, +{ "sect", 0x00A7 }, +{ "uml", 0x00A8 }, +{ "copy", 0x00A9 }, +{ "ordf", 0x00AA }, +{ "laquo", 0x00AB }, +{ "not", 0x00AC }, +{ "shy", 0x00AD }, +{ "reg", 0x00AE }, +{ "macr", 0x00AF }, +{ "deg", 0x00B0 }, +{ "plusmn", 0x00B1 }, +{ "sup2", 0x00B2 }, +{ "sup3", 0x00B3 }, +{ "acute", 0x00B4 }, +{ "micro", 0x00B5 }, +{ "para", 0x00B6 }, +{ "middot", 0x00B7 }, +{ "cedil", 0x00B8 }, +{ "sup1", 0x00B9 }, +{ "ordm", 0x00BA }, +{ "raquo", 0x00BB }, +{ "frac14", 0x00BC }, +{ "frac12", 0x00BD }, +{ "frac34", 0x00BE }, +{ "iquest", 0x00BF }, +{ "Agrave", 0x00C0 }, +{ "Aacute", 0x00C1 }, +{ "Acirc", 0x00C2 }, +{ "Atilde", 0x00C3 }, +{ "Auml", 0x00C4 }, +{ "Aring", 0x00C5 }, +{ "AElig", 0x00C6 }, +{ "Ccedil", 0x00C7 }, +{ "Egrave", 0x00C8 }, +{ "Eacute", 0x00C9 }, +{ "Ecirc", 0x00CA }, +{ "Euml", 0x00CB }, +{ "Igrave", 0x00CC }, +{ "Iacute", 0x00CD }, +{ "Icirc", 0x00CE }, +{ "Iuml", 0x00CF }, +{ "ETH", 0x00D0 }, +{ "Ntilde", 0x00D1 }, +{ "Ograve", 0x00D2 }, +{ "Oacute", 0x00D3 }, +{ "Ocirc", 0x00D4 }, +{ "Otilde", 0x00D5 }, +{ "Ouml", 0x00D6 }, +{ "times", 0x00D7 }, +{ "Oslash", 0x00D8 }, +{ "Ugrave", 0x00D9 }, +{ "Uacute", 0x00DA }, +{ "Ucirc", 0x00DB }, +{ "Uuml", 0x00DC }, +{ "Yacute", 0x00DD }, +{ "THORN", 0x00DE }, +{ "szlig", 0x00DF }, +{ "agrave", 0x00E0 }, +{ "aacute", 0x00E1 }, +{ "acirc", 0x00E2 }, +{ "atilde", 0x00E3 }, +{ "auml", 0x00E4 }, +{ "aring", 0x00E5 }, +{ "aelig", 0x00E6 }, +{ "ccedil", 0x00E7 }, +{ "egrave", 0x00E8 }, +{ "eacute", 0x00E9 }, +{ "ecirc", 0x00EA }, +{ "euml", 0x00EB }, +{ "igrave", 0x00EC }, +{ "iacute", 0x00ED }, +{ "icirc", 0x00EE }, +{ "iuml", 0x00EF }, +{ "eth", 0x00F0 }, +{ "ntilde", 0x00F1 }, +{ "ograve", 0x00F2 }, +{ "oacute", 0x00F3 }, +{ "ocirc", 0x00F4 }, +{ "otilde", 0x00F5 }, +{ "ouml", 0x00F6 }, +{ "divide", 0x00F7 }, +{ "oslash", 0x00F8 }, +{ "ugrave", 0x00F9 }, +{ "uacute", 0x00FA }, +{ "ucirc", 0x00FB }, +{ "uuml", 0x00FC }, +{ "yacute", 0x00FD }, +{ "thorn", 0x00FE }, +{ "yuml", 0x00FF }, +{ "OElig", 0x0152 }, +{ "oelig", 0x0153 }, +{ "Scaron", 0x0160 }, +{ "scaron", 0x0161 }, +{ "Yuml", 0x0178 }, +{ "fnof", 0x0192 }, +{ "circ", 0x02C6 }, +{ "tilde", 0x02DC }, +{ "Alpha", 0x0391 }, +{ "Beta", 0x0392 }, +{ "Gamma", 0x0393 }, +{ "Delta", 0x0394 }, +{ "Epsilon", 0x0395 }, +{ "Zeta", 0x0396 }, +{ "Eta", 0x0397 }, +{ "Theta", 0x0398 }, +{ "Iota", 0x0399 }, +{ "Kappa", 0x039A }, +{ "Lambda", 0x039B }, +{ "Mu", 0x039C }, +{ "Nu", 0x039D }, +{ "Xi", 0x039E }, +{ "Omicron", 0x039F }, +{ "Pi", 0x03A0 }, +{ "Rho", 0x03A1 }, +{ "Sigma", 0x03A3 }, +{ "Tau", 0x03A4 }, +{ "Upsilon", 0x03A5 }, +{ "Phi", 0x03A6 }, +{ "Chi", 0x03A7 }, +{ "Psi", 0x03A8 }, +{ "Omega", 0x03A9 }, +{ "alpha", 0x03B1 }, +{ "beta", 0x03B2 }, +{ "gamma", 0x03B3 }, +{ "delta", 0x03B4 }, +{ "epsilon", 0x03B5 }, +{ "zeta", 0x03B6 }, +{ "eta", 0x03B7 }, +{ "theta", 0x03B8 }, +{ "iota", 0x03B9 }, +{ "kappa", 0x03BA }, +{ "lambda", 0x03BB }, +{ "mu", 0x03BC }, +{ "nu", 0x03BD }, +{ "xi", 0x03BE }, +{ "omicron", 0x03BF }, +{ "pi", 0x03C0 }, +{ "rho", 0x03C1 }, +{ "sigmaf", 0x03C2 }, +{ "sigma", 0x03C3 }, +{ "tau", 0x03C4 }, +{ "upsilon", 0x03C5 }, +{ "phi", 0x03C6 }, +{ "chi", 0x03C7 }, +{ "psi", 0x03C8 }, +{ "omega", 0x03C9 }, +{ "thetasym", 0x03D1 }, +{ "upsih", 0x03D2 }, +{ "piv", 0x03D6 }, +{ "ensp", 0x2002 }, +{ "emsp", 0x2003 }, +{ "thinsp", 0x2009 }, +{ "zwnj", 0x200C }, +{ "zwj", 0x200D }, +{ "lrm", 0x200E }, +{ "rlm", 0x200F }, +{ "ndash", 0x2013 }, +{ "mdash", 0x2014 }, +{ "lsquo", 0x2018 }, +{ "rsquo", 0x2019 }, +{ "sbquo", 0x201A }, +{ "ldquo", 0x201C }, +{ "rdquo", 0x201D }, +{ "bdquo", 0x201E }, +{ "dagger", 0x2020 }, +{ "Dagger", 0x2021 }, +{ "bull", 0x2022 }, +{ "hellip", 0x2026 }, +{ "permil", 0x2030 }, +{ "prime", 0x2032 }, +{ "Prime", 0x2033 }, +{ "lsaquo", 0x2039 }, +{ "rsaquo", 0x203A }, +{ "oline", 0x203E }, +{ "frasl", 0x2044 }, +{ "euro", 0x20AC }, +{ "image", 0x2111 }, +{ "weierp", 0x2118 }, +{ "real", 0x211C }, +{ "trade", 0x2122 }, +{ "alefsym", 0x2135 }, +{ "larr", 0x2190 }, +{ "uarr", 0x2191 }, +{ "rarr", 0x2192 }, +{ "darr", 0x2193 }, +{ "harr", 0x2194 }, +{ "crarr", 0x21B5 }, +{ "lArr", 0x21D0 }, +{ "uArr", 0x21D1 }, +{ "rArr", 0x21D2 }, +{ "dArr", 0x21D3 }, +{ "hArr", 0x21D4 }, +{ "forall", 0x2200 }, +{ "part", 0x2202 }, +{ "exist", 0x2203 }, +{ "empty", 0x2205 }, +{ "nabla", 0x2207 }, +{ "isin", 0x2208 }, +{ "notin", 0x2209 }, +{ "ni", 0x220B }, +{ "prod", 0x220F }, +{ "sum", 0x2211 }, +{ "minus", 0x2212 }, +{ "lowast", 0x2217 }, +{ "radic", 0x221A }, +{ "prop", 0x221D }, +{ "infin", 0x221E }, +{ "ang", 0x2220 }, +{ "and", 0x2227 }, +{ "or", 0x2228 }, +{ "cap", 0x2229 }, +{ "cup", 0x222A }, +{ "int", 0x222B }, +{ "there4", 0x2234 }, +{ "sim", 0x223C }, +{ "cong", 0x2245 }, +{ "asymp", 0x2248 }, +{ "ne", 0x2260 }, +{ "equiv", 0x2261 }, +{ "le", 0x2264 }, +{ "ge", 0x2265 }, +{ "sub", 0x2282 }, +{ "sup", 0x2283 }, +{ "nsub", 0x2284 }, +{ "sube", 0x2286 }, +{ "supe", 0x2287 }, +{ "oplus", 0x2295 }, +{ "otimes", 0x2297 }, +{ "perp", 0x22A5 }, +{ "sdot", 0x22C5 }, +{ "lceil", 0x2308 }, +{ "rceil", 0x2309 }, +{ "lfloor", 0x230A }, +{ "rfloor", 0x230B }, +{ "lang", 0x27E8 }, +{ "rang", 0x27E9 }, From dovecot at dovecot.org Fri Jan 16 22:33:26 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 22:33:26 +0000 Subject: dovecot-2.2: lib-mail: Added message_snippet_generate() to produ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5211234206ea changeset: 18157:5211234206ea user: Timo Sirainen date: Sat Jan 17 00:23:36 2015 +0200 description: lib-mail: Added message_snippet_generate() to produce a short text snippet of a mail. diffstat: src/lib-mail/Makefile.am | 7 + src/lib-mail/message-snippet.c | 136 ++++++++++++++++++++++++++++++++++++ src/lib-mail/message-snippet.h | 14 +++ src/lib-mail/test-message-snippet.c | 80 +++++++++++++++++++++ 4 files changed, 237 insertions(+), 0 deletions(-) diffs (280 lines): diff -r d59753d9f5e9 -r 5211234206ea src/lib-mail/Makefile.am --- a/src/lib-mail/Makefile.am Sat Jan 17 00:15:44 2015 +0200 +++ b/src/lib-mail/Makefile.am Sat Jan 17 00:23:36 2015 +0200 @@ -29,6 +29,7 @@ message-part-serialize.c \ message-search.c \ message-size.c \ + message-snippet.c \ ostream-dot.c \ quoted-printable.c \ rfc2231-parser.c \ @@ -62,6 +63,7 @@ message-part-serialize.h \ message-search.h \ message-size.h \ + message-snippet.h \ ostream-dot.h \ quoted-printable.h \ rfc2231-parser.h \ @@ -87,6 +89,7 @@ test-message-id \ test-message-parser \ test-message-part \ + test-message-snippet \ test-ostream-dot \ test-quoted-printable \ test-rfc2231-parser @@ -166,6 +169,10 @@ test_message_part_LDADD = message-part.lo message-parser.lo message-header-parser.lo message-size.lo rfc822-parser.lo rfc2231-parser.lo $(test_libs) test_message_part_DEPENDENCIES = $(test_deps) +test_message_snippet_SOURCES = test-message-snippet.c +test_message_snippet_LDADD = message-snippet.lo mail-html2text.lo $(test_message_decoder_LDADD) message-parser.lo message-header-parser.lo message-header-decode.lo message-size.lo +test_message_snippet_DEPENDENCIES = $(test_deps) + test_mail_html2text_SOURCES = test-mail-html2text.c test_mail_html2text_LDADD = mail-html2text.lo $(test_libs) test_mail_html2text_DEPENDENCIES = $(test_deps) diff -r d59753d9f5e9 -r 5211234206ea src/lib-mail/message-snippet.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-mail/message-snippet.c Sat Jan 17 00:23:36 2015 +0200 @@ -0,0 +1,136 @@ +/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "buffer.h" +#include "str.h" +#include "istream.h" +#include "mail-html2text.h" +#include "message-parser.h" +#include "message-decoder.h" +#include "message-snippet.h" + +enum snippet_state { + /* beginning of the line */ + SNIPPET_STATE_NEWLINE = 0, + /* within normal text */ + SNIPPET_STATE_NORMAL, + /* within quoted text - skip until EOL */ + SNIPPET_STATE_QUOTED +}; + +struct snippet_context { + string_t *snippet; + unsigned int chars_left; + enum snippet_state state; + bool add_whitespace; + struct mail_html2text *html2text; + buffer_t *plain_output; +}; + +static bool snippet_generate(struct snippet_context *ctx, + const unsigned char *data, size_t size) +{ + unsigned int i, count; + + if (ctx->html2text != NULL) { + buffer_set_used_size(ctx->plain_output, 0); + mail_html2text_more(ctx->html2text, data, size, + ctx->plain_output); + data = ctx->plain_output->data; + size = ctx->plain_output->used; + } + + /* message-decoder should feed us only valid and complete + UTF-8 input */ + for (i = 0; i < size; i += count) { + count = 1; + switch (ctx->state) { + case SNIPPET_STATE_NEWLINE: + if (data[i] == '>' && ctx->html2text == NULL) { + ctx->state = SNIPPET_STATE_QUOTED; + break; + } + ctx->state = SNIPPET_STATE_NORMAL; + /* fallthrough */ + case SNIPPET_STATE_NORMAL: + if (data[i] == '\r' || data[i] == '\n' || + data[i] == '\t' || data[i] == ' ') { + ctx->add_whitespace = TRUE; + if (data[i] == '\n') + ctx->state = SNIPPET_STATE_NEWLINE; + break; + } + if (ctx->add_whitespace) { + str_append_c(ctx->snippet, ' '); + ctx->add_whitespace = FALSE; + if (ctx->chars_left-- == 0) + return FALSE; + } + if (ctx->chars_left-- == 0) + return FALSE; + count = uni_utf8_char_bytes(data[i]); + i_assert(i + count <= size); + str_append_n(ctx->snippet, data + i, count); + break; + case SNIPPET_STATE_QUOTED: + if (data[i] == '\n') + ctx->state = SNIPPET_STATE_NEWLINE; + break; + } + } + return TRUE; +} + +int message_snippet_generate(struct istream *input, + unsigned int max_snippet_chars, + string_t *snippet) +{ + struct message_parser_ctx *parser; + struct message_part *parts; + struct message_decoder_context *decoder; + struct message_block raw_block, block; + struct snippet_context ctx; + pool_t pool; + int ret; + + memset(&ctx, 0, sizeof(ctx)); + pool = pool_alloconly_create("message snippet", 1024); + ctx.snippet = snippet; + ctx.chars_left = max_snippet_chars; + + parser = message_parser_init(pool_datastack_create(), input, 0, 0); + decoder = message_decoder_init(NULL, 0); + while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) { + if (!message_decoder_decode_next_block(decoder, &raw_block, &block)) + continue; + if (block.size == 0) { + const char *ct; + + if (block.hdr != NULL) + continue; + + /* end of headers - verify that we can use this + Content-Type. we get here only once, because we + always handle only one non-multipart MIME part. */ + ct = message_decoder_current_content_type(decoder); + if (ct == NULL) + /* text/plain */ ; + else if (strcasecmp(ct, "text/html") == 0) { + ctx.html2text = mail_html2text_init(MAIL_HTML2TEXT_FLAG_SKIP_QUOTED); + ctx.plain_output = buffer_create_dynamic(pool, 1024); + } else if (strncasecmp(ct, "text/", 5) != 0) + break; + continue; + } + if (!snippet_generate(&ctx, block.data, block.size)) + break; + } + i_assert(ret != 0); + message_decoder_deinit(&decoder); + if (message_parser_deinit(&parser, &parts) < 0) + i_unreached(); + if (ctx.html2text != NULL) + mail_html2text_deinit(&ctx.html2text); + pool_unref(&pool); + return input->stream_errno == 0 ? 0 : -1; +} diff -r d59753d9f5e9 -r 5211234206ea src/lib-mail/message-snippet.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-mail/message-snippet.h Sat Jan 17 00:23:36 2015 +0200 @@ -0,0 +1,14 @@ +#ifndef MESSAGE_SNIPPET_H +#define MESSAGE_SNIPPET_H + +/* Generate UTF-8 text snippet from the beginning of the given mail input + stream. The stream is expected to start at the MIME part's headers whose + snippet is being generated. Returns 0 if ok, -1 if I/O error. + + Currently only Content-Type: text/ is supported, others will result in an + empty string. */ +int message_snippet_generate(struct istream *input, + unsigned int max_snippet_chars, + string_t *snippet); + +#endif diff -r d59753d9f5e9 -r 5211234206ea src/lib-mail/test-message-snippet.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-mail/test-message-snippet.c Sat Jan 17 00:23:36 2015 +0200 @@ -0,0 +1,80 @@ +/* Copyright (c) 2015 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "istream.h" +#include "message-snippet.h" +#include "test-common.h" + +static struct { + const char *input; + unsigned int max_snippet_chars; + const char *output; +} tests[] = { + { "Content-Type: text/plain\n" + "\n" + "1234567890 234567890", + 12, + "1234567890 2" }, + { "Content-Type: text/plain\n" + "\n" + "line1\n>quote2\nline2\n", + 100, + "line1 line2" }, + { "Content-Type: text/plain\n" + "\n" + "line1\n>quote2\n> quote3\n > line4\n\n \t\t \nline5\n \t ", + 100, + "line1 > line4 line5" }, + { "Content-Type: text/plain; charset=utf-8\n" + "\n" + "hyv\xC3\xA4\xC3\xA4 p\xC3\xA4iv\xC3\xA4\xC3\xA4", + 11, + "hyv\xC3\xA4\xC3\xA4 p\xC3\xA4iv\xC3\xA4" }, + { "Content-Type: text/plain; charset=utf-8\n" + "Content-Transfer-Encoding: quoted-printable\n" + "\n" + "hyv=C3=A4=C3=A4 p=C3=A4iv=C3=A4=C3=A4", + 11, + "hyv\xC3\xA4\xC3\xA4 p\xC3\xA4iv\xC3\xA4" }, + + { "Content-Transfer-Encoding: quoted-printable\n" + "Content-Type: text/html;\n" + " charset=utf-8\n" + "\n" + "Hi,

How =\n" + "is it going?
quoted text is ignored
\n" + "> -foo\n" + "

=\n", + 100, + "Hi, How is it going? > -foo" }, +}; + +static void test_message_snippet(void) +{ + string_t *str = t_str_new(128); + struct istream *input; + unsigned int i; + + test_begin("message snippet"); + for (i = 0; i < N_ELEMENTS(tests); i++) { + str_truncate(str, 0); + input = i_stream_create_from_data(tests[i].input, strlen(tests[i].input)); + test_assert_idx(message_snippet_generate(input, tests[i].max_snippet_chars, str) == 0, i); + test_assert_idx(strcmp(tests[i].output, str_c(str)) == 0, i); + i_stream_destroy(&input); + } + test_end(); +} + +int main(void) +{ + static void (*test_functions[])(void) = { + test_message_snippet, + NULL + }; + return test_run(test_functions); +} From dovecot at dovecot.org Fri Jan 16 22:33:32 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 22:33:32 +0000 Subject: dovecot-2.2: fts: Parse HTML MIME parts using lib-mail's mail-ht... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/08afd516a622 changeset: 18158:08afd516a622 user: Timo Sirainen date: Sat Jan 17 00:24:36 2015 +0200 description: fts: Parse HTML MIME parts using lib-mail's mail-html2text. diffstat: src/plugins/fts/Makefile.am | 1 - src/plugins/fts/fts-parser-html.c | 236 +---------------------------------- src/plugins/fts/html-entities.h | 253 -------------------------------------- 3 files changed, 6 insertions(+), 484 deletions(-) diffs (truncated from 543 to 300 lines): diff -r 5211234206ea -r 08afd516a622 src/plugins/fts/Makefile.am --- a/src/plugins/fts/Makefile.am Sat Jan 17 00:23:36 2015 +0200 +++ b/src/plugins/fts/Makefile.am Sat Jan 17 00:24:36 2015 +0200 @@ -42,7 +42,6 @@ noinst_HEADERS = \ doveadm-fts.h \ - html-entities.h \ fts-build-mail.h \ fts-plugin.h \ fts-search-serialize.h \ diff -r 5211234206ea -r 08afd516a622 src/plugins/fts/fts-parser-html.c --- a/src/plugins/fts/fts-parser-html.c Sat Jan 17 00:23:36 2015 +0200 +++ b/src/plugins/fts/fts-parser-html.c Sat Jan 17 00:24:36 2015 +0200 @@ -2,49 +2,14 @@ #include "lib.h" #include "buffer.h" -#include "unichar.h" #include "message-parser.h" +#include "mail-html2text.h" #include "fts-parser.h" -/* Zero-width space (​) apparently also belongs here, but that gets a - bit tricky to handle.. is it actually used anywhere? */ -#define HTML_WHITESPACE(c) \ - ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n') - -enum html_state { - /* regular text */ - HTML_STATE_TEXT, - /* tag outside "quoted string" */ - HTML_STATE_TAG, - /* tag inside "double quoted string" */ - HTML_STATE_TAG_DQUOTED, - /* tag -> "escape\ */ - HTML_STATE_TAG_DQUOTED_ESCAPE, - /* tag inside 'single quoted string' */ - HTML_STATE_TAG_SQUOTED, - /* tag -> 'escape\ */ - HTML_STATE_TAG_SQUOTED_ESCAPE, - /* script/stype content */ - HTML_STATE_IGNORE, - /* comment */ - HTML_STATE_COMMENT, - /* comment is ending, we've seen "--" and now just waiting for ">" */ - HTML_STATE_COMMENT_END -}; - struct html_fts_parser { struct fts_parser parser; - - enum html_state state; - buffer_t *input, *output; - bool ignore_next_text; -}; - -static struct { - const char *name; - unichar_t chr; -} html_entities[] = { -#include "html-entities.h" + struct mail_html2text *html2text; + buffer_t *output; }; static struct fts_parser * @@ -59,207 +24,19 @@ parser = i_new(struct html_fts_parser, 1); parser->parser.v = fts_parser_html; - parser->input = buffer_create_dynamic(default_pool, 512); + parser->html2text = mail_html2text_init(0); parser->output = buffer_create_dynamic(default_pool, 4096); return &parser->parser; } -static size_t -parse_tag_name(struct html_fts_parser *parser, - const unsigned char *data, size_t size) -{ - size_t i; - - if (size >= 3 && memcmp(data, "!--", 3) == 0) { - parser->state = HTML_STATE_COMMENT; - return 3 + 1; - } - - if (size > 5 && i_memcasecmp(data, "style", 5) == 0) { - i = 5; - } else if (size > 6 && i_memcasecmp(data, "script", 6) == 0) { - i = 6; - } else { - if (size <= 6) { - /* can we see the whole tag name? */ - for (i = 0; i < size; i++) { - if (HTML_WHITESPACE(data[i]) || data[i] == '>') - break; - } - if (i == size) { - /* need more data */ - return 0; - } - } - parser->state = HTML_STATE_TAG; - return 1; - } - parser->state = HTML_STATE_TAG; - if (HTML_WHITESPACE(data[i]) || data[i] == '>') - parser->ignore_next_text = TRUE; - return 1; -} - -static bool html_entity_get_unichar(const char *name, unichar_t *chr_r) -{ - unsigned int i; - - for (i = 0; i < N_ELEMENTS(html_entities); i++) { - if (strcasecmp(html_entities[i].name, name) == 0) { - *chr_r = html_entities[i].chr; - return TRUE; - } - } - return FALSE; -} - -static size_t parse_entity(struct html_fts_parser *parser, - const unsigned char *data, size_t size) -{ - char entity[10]; - unichar_t chr; - size_t i; - - for (i = 0; i < size; i++) { - if (HTML_WHITESPACE(data[i]) || i >= sizeof(entity)) { - /* broken entity */ - return 1; - } - if (data[i] == ';') - break; - } - if (i == size) - return 0; - - i_assert(i < sizeof(entity)); - memcpy(entity, data, i); entity[i] = '\0'; - - if (html_entity_get_unichar(entity, &chr)) - uni_ucs4_to_utf8_c(chr, parser->output); - return i + 1; -} - -static void parser_add_space(struct html_fts_parser *parser) -{ - const unsigned char *data = parser->output->data; - - if (parser->output->used > 0 && - data[parser->output->used-1] != ' ') - buffer_append_c(parser->output, ' '); -} - -static size_t -parse_data(struct html_fts_parser *parser, - const unsigned char *data, size_t size) -{ - size_t i, ret; - - for (i = 0; i < size; i++) { - char c = data[i]; - - switch (parser->state) { - case HTML_STATE_TEXT: - if (c == '<') { - ret = parse_tag_name(parser, data+i+1, size-i-1); - if (ret == 0) - return i; - i += ret - 1; - } else if (c == '&') { - ret = parse_entity(parser, data+i+1, size-i-1); - if (ret == 0) - return i; - i += ret - 1; - } else { - buffer_append_c(parser->output, c); - } - break; - case HTML_STATE_TAG: - if (c == '"') - parser->state = HTML_STATE_TAG_DQUOTED; - else if (c == '\'') - parser->state = HTML_STATE_TAG_DQUOTED; - else if (c == '>') { - parser->state = parser->ignore_next_text ? - HTML_STATE_IGNORE : HTML_STATE_TEXT; - parser_add_space(parser); - } - break; - case HTML_STATE_TAG_DQUOTED: - if (c == '"') - parser->state = HTML_STATE_TAG; - else if (c == '\\') - parser->state = HTML_STATE_TAG_DQUOTED_ESCAPE; - break; - case HTML_STATE_TAG_DQUOTED_ESCAPE: - parser->state = HTML_STATE_TAG_DQUOTED; - break; - case HTML_STATE_TAG_SQUOTED: - if (c == '\'') - parser->state = HTML_STATE_TAG; - else if (c == '\\') - parser->state = HTML_STATE_TAG_SQUOTED_ESCAPE; - break; - case HTML_STATE_TAG_SQUOTED_ESCAPE: - parser->state = HTML_STATE_TAG_SQUOTED; - break; - case HTML_STATE_IGNORE: - if (c == '<') { - parser->state = HTML_STATE_TAG; - parser->ignore_next_text = FALSE; - } - break; - case HTML_STATE_COMMENT: - if (c == '-') { - if (i+1 == size) - return i; - if (data[i+1] == '-') { - parser->state = HTML_STATE_COMMENT_END; - i++; - } - } - break; - case HTML_STATE_COMMENT_END: - if (c == '>') - parser->state = HTML_STATE_TEXT; - else if (!HTML_WHITESPACE(c)) - parser->state = HTML_STATE_COMMENT; - break; - } - } - return i; -} - static void fts_parser_html_more(struct fts_parser *_parser, struct message_block *block) { struct html_fts_parser *parser = (struct html_fts_parser *)_parser; - size_t size, buf_orig_size; buffer_set_used_size(parser->output, 0); - - if (parser->input->used > 0) { - /* we didn't get enough input the last time to know - what to do. */ - buf_orig_size = parser->input->used; - - size = I_MIN(block->size, 128); - buffer_append(parser->input, block->data, size); - size = parse_data(parser, parser->input->data, - parser->input->used); - if (size != 0) { - i_assert(size >= buf_orig_size); - block->data += size - buf_orig_size; - block->size -= size - buf_orig_size; - } else if (block->size != 0) { - /* we're slowly parsing forward */ - return; - } else { - /* we're at EOF and can't finish this */ - } - buffer_set_used_size(parser->input, 0); - } - size = parse_data(parser, block->data, block->size); - buffer_append(parser->input, block->data + size, block->size - size); + mail_html2text_more(parser->html2text, block->data, block->size, + parser->output); block->data = parser->output->data; block->size = parser->output->used; @@ -269,7 +46,6 @@ { struct html_fts_parser *parser = (struct html_fts_parser *)_parser; - buffer_free(&parser->input); buffer_free(&parser->output); i_free(parser); } diff -r 5211234206ea -r 08afd516a622 src/plugins/fts/html-entities.h --- a/src/plugins/fts/html-entities.h Sat Jan 17 00:23:36 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,253 +0,0 @@ -{ "quot", 0x0022 }, -{ "amp", 0x0026 }, -{ "apos", 0x0027 }, -{ "lt", 0x003C }, -{ "gt", 0x003E }, -{ "nbsp", 0x00A0 }, -{ "iexcl", 0x00A1 }, -{ "cent", 0x00A2 }, -{ "pound", 0x00A3 }, -{ "curren", 0x00A4 }, From dovecot at dovecot.org Fri Jan 16 22:33:42 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 22:33:42 +0000 Subject: dovecot-2.2: lib-storage: Added MAIL_FETCH_BODY_SNIPPET. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/a76507bc3f36 changeset: 18159:a76507bc3f36 user: Timo Sirainen date: Sat Jan 17 00:31:35 2015 +0200 description: lib-storage: Added MAIL_FETCH_BODY_SNIPPET. diffstat: src/lib-storage/index/index-mail-headers.c | 1 + src/lib-storage/index/index-mail.c | 155 ++++++++++++++++++++++++++++- src/lib-storage/index/index-mail.h | 4 +- src/lib-storage/mail-storage.h | 3 +- 4 files changed, 159 insertions(+), 4 deletions(-) diffs (truncated from 306 to 300 lines): diff -r 08afd516a622 -r a76507bc3f36 src/lib-storage/index/index-mail-headers.c --- a/src/lib-storage/index/index-mail-headers.c Sat Jan 17 00:24:36 2015 +0200 +++ b/src/lib-storage/index/index-mail-headers.c Sat Jan 17 00:31:35 2015 +0200 @@ -383,6 +383,7 @@ mail->data.save_sent_date = TRUE; mail->data.save_bodystructure_header = TRUE; mail->data.save_bodystructure_body = TRUE; + mail->data.save_body_snippet = TRUE; mail->data.tee_stream = tee_i_stream_create(input); input = tee_i_stream_create_child(mail->data.tee_stream); diff -r 08afd516a622 -r a76507bc3f36 src/lib-storage/index/index-mail.c --- a/src/lib-storage/index/index-mail.c Sat Jan 17 00:24:36 2015 +0200 +++ b/src/lib-storage/index/index-mail.c Sat Jan 17 00:31:35 2015 +0200 @@ -9,6 +9,7 @@ #include "message-date.h" #include "message-part-serialize.h" #include "message-parser.h" +#include "message-snippet.h" #include "imap-bodystructure.h" #include "imap-envelope.h" #include "mail-cache.h" @@ -19,6 +20,9 @@ #include +#define BODY_SNIPPET_ALGO_V1 "1" +#define BODY_SNIPPET_MAX_CHARS 100 + struct mail_cache_field global_cache_fields[MAIL_INDEX_CACHE_FIELD_COUNT] = { { .name = "flags", .type = MAIL_CACHE_FIELD_BITMASK, @@ -54,6 +58,8 @@ { .name = "mime.parts", .type = MAIL_CACHE_FIELD_VARIABLE_SIZE }, { .name = "binary.parts", + .type = MAIL_CACHE_FIELD_VARIABLE_SIZE }, + { .name = "body.snippet", .type = MAIL_CACHE_FIELD_VARIABLE_SIZE } }; @@ -766,6 +772,9 @@ case MAIL_CACHE_PHYSICAL_FULL_SIZE: fetch_field = MAIL_FETCH_PHYSICAL_SIZE; break; + case MAIL_CACHE_BODY_SNIPPET: + fetch_field = MAIL_FETCH_BODY_SNIPPET; + break; default: i_unreached(); } @@ -783,6 +792,16 @@ } } +static void index_mail_body_parsed_cache_body_snippet(struct index_mail *mail) +{ + if (mail->data.body_snippet != NULL && + index_mail_want_cache(mail, MAIL_CACHE_BODY_SNIPPET)) { + index_mail_cache_add(mail, MAIL_CACHE_BODY_SNIPPET, + mail->data.body_snippet, + strlen(mail->data.body_snippet)+1); + } +} + static void index_mail_cache_sizes(struct index_mail *mail) { static enum index_cache_field size_fields[] = { @@ -832,6 +851,86 @@ (void)index_mail_cache_sent_date(mail); } +static struct message_part * +index_mail_find_first_text_mime_part(struct message_part *parts) +{ + struct message_part_body_data *body_data = parts->context; + struct message_part *part; + + i_assert(body_data != NULL); + + if (body_data->content_type == NULL || + strcasecmp(body_data->content_type, "\"text\"") == 0) { + /* use any text/ part, even if we don't know what exactly + it is. */ + return parts; + } + if (strcasecmp(body_data->content_type, "\"multipart\"") != 0) { + /* for now we support only text Content-Types */ + return NULL; + } + + if (strcasecmp(body_data->content_subtype, "\"alternative\"") == 0) { + /* text/plain > text/html > text/ */ + struct message_part *html_part = NULL, *text_part = NULL; + + for (part = parts->children; part != NULL; part = part->next) { + struct message_part_body_data *sub_body_data = + part->context; + + i_assert(sub_body_data != NULL); + + if (strcasecmp(sub_body_data->content_type, "\"text\"") == 0) { + if (strcasecmp(sub_body_data->content_subtype, "\"plain\"") == 0) + return part; + if (strcasecmp(sub_body_data->content_subtype, "\"html\"") == 0) + html_part = part; + else + text_part = part; + } + } + return html_part != NULL ? html_part : text_part; + } + /* find the first usable MIME part */ + for (part = parts->children; part != NULL; part = part->next) { + struct message_part *subpart = + index_mail_find_first_text_mime_part(part); + if (subpart != NULL) + return subpart; + } + return NULL; +} + +static int index_mail_write_body_snippet(struct index_mail *mail) +{ + struct message_part *part; + struct istream *input; + string_t *str; + int ret; + + i_assert(mail->data.parsed_bodystructure); + + part = index_mail_find_first_text_mime_part(mail->data.parts); + if (part == NULL) { + mail->data.body_snippet = BODY_SNIPPET_ALGO_V1; + return 0; + } + + if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0) + return -1; + i_stream_seek(input, part->physical_pos); + input = i_stream_create_limit(input, part->header_size.physical_size + + part->body_size.physical_size); + + str = str_new(mail->mail.data_pool, 128); + str_append(str, BODY_SNIPPET_ALGO_V1); + ret = message_snippet_generate(input, BODY_SNIPPET_MAX_CHARS, str); + if (ret == 0) + mail->data.body_snippet = str_c(str); + i_stream_destroy(&input); + return ret; +} + static int index_mail_parse_body_finish(struct index_mail *mail, enum index_cache_field field, bool success) @@ -884,6 +983,11 @@ mail->data.save_bodystructure_body = FALSE; i_assert(mail->data.parts != NULL); } + if (mail->data.save_body_snippet) { + if (index_mail_write_body_snippet(mail) < 0) + return -1; + mail->data.save_body_snippet = FALSE; + } if (mail->data.no_caching) { /* if we're here because we aborted parsing, don't get any @@ -897,6 +1001,7 @@ index_mail_body_parsed_cache_flags(mail); index_mail_body_parsed_cache_message_parts(mail); index_mail_body_parsed_cache_bodystructure(mail, field); + index_mail_body_parsed_cache_body_snippet(mail); index_mail_cache_sizes(mail); index_mail_cache_dates(mail); return 0; @@ -1089,13 +1194,14 @@ struct index_mail_data *data = &mail->data; string_t *str; - if (data->parsed_bodystructure) { + if (data->parsed_bodystructure && field != MAIL_CACHE_BODY_SNIPPET) { /* we have everything parsed already, but just not written to a string */ index_mail_body_parsed_cache_bodystructure(mail, field); } else { if (data->save_bodystructure_header || - !data->save_bodystructure_body) { + !data->save_bodystructure_body || + field == MAIL_CACHE_BODY_SNIPPET) { /* we haven't parsed the header yet */ data->save_bodystructure_header = TRUE; data->save_bodystructure_body = TRUE; @@ -1129,6 +1235,10 @@ data->bodystructure = str_c(str); } break; + case MAIL_CACHE_BODY_SNIPPET: + i_assert(data->body_snippet != NULL && + data->body_snippet[0] != '\0'); + break; default: i_unreached(); } @@ -1146,6 +1256,35 @@ str_append(str, " NIL NIL NIL NIL"); } +static int +index_mail_fetch_body_snippet(struct index_mail *mail, const char **value_r) +{ + const struct mail_cache_field *cache_fields = mail->ibox->cache_fields; + const unsigned int cache_field = + cache_fields[MAIL_CACHE_BODY_SNIPPET].idx; + string_t *str; + + if (mail->data.body_snippet == NULL) { + str = str_new(mail->mail.data_pool, 128); + if (index_mail_cache_lookup_field(mail, str, cache_field) > 0 && + str_len(str) > 0) + mail->data.body_snippet = str_c(str); + } + if (mail->data.body_snippet != NULL) { + *value_r = mail->data.body_snippet; + return 0; + } + + /* reuse the IMAP bodystructure parsing code to get all the useful + headers that we need. */ + mail->data.save_body_snippet = TRUE; + if (index_mail_parse_bodystructure(mail, MAIL_CACHE_BODY_SNIPPET) < 0) + return -1; + i_assert(mail->data.body_snippet != NULL); + *value_r = mail->data.body_snippet; + return 0; +} + int index_mail_get_special(struct mail *_mail, enum mail_fetch_field field, const char **value_r) { @@ -1250,6 +1389,8 @@ *value_r = data->from_envelope != NULL ? data->from_envelope : ""; return 0; + case MAIL_FETCH_BODY_SNIPPET: + return index_mail_fetch_body_snippet(mail, value_r); case MAIL_FETCH_UIDL_FILE_NAME: case MAIL_FETCH_UIDL_BACKEND: case MAIL_FETCH_SEARCH_RELEVANCY: @@ -1520,6 +1661,16 @@ data->save_sent_date = TRUE; } } + if ((data->wanted_fields & MAIL_FETCH_BODY_SNIPPET) != 0) { + const unsigned int cache_field = + cache_fields[MAIL_CACHE_BODY_SNIPPET].idx; + + if (mail_cache_field_exists(cache_view, _mail->seq, + cache_field) <= 0) { + data->access_part |= PARSE_HDR | PARSE_BODY; + data->save_body_snippet = TRUE; + } + } if ((data->wanted_fields & (MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY)) != 0) { if ((data->wanted_fields & MAIL_FETCH_STREAM_HEADER) != 0) diff -r 08afd516a622 -r a76507bc3f36 src/lib-storage/index/index-mail.h --- a/src/lib-storage/index/index-mail.h Sat Jan 17 00:24:36 2015 +0200 +++ b/src/lib-storage/index/index-mail.h Sat Jan 17 00:31:35 2015 +0200 @@ -23,6 +23,7 @@ MAIL_CACHE_GUID, MAIL_CACHE_MESSAGE_PARTS, MAIL_CACHE_BINARY_PARTS, + MAIL_CACHE_BODY_SNIPPET, MAIL_INDEX_CACHE_FIELD_COUNT }; @@ -83,7 +84,7 @@ struct message_part *parts; struct message_binary_part *bin_parts; const char *envelope, *body, *bodystructure, *guid, *filename; - const char *from_envelope; + const char *from_envelope, *body_snippet; struct message_part_envelope_data *envelope_data; uint32_t seq; @@ -114,6 +115,7 @@ unsigned int save_bodystructure_header:1; unsigned int save_bodystructure_body:1; unsigned int save_message_parts:1; + unsigned int save_body_snippet:1; unsigned int stream_has_only_header:1; unsigned int parsed_bodystructure:1; unsigned int hdr_size_set:1; diff -r 08afd516a622 -r a76507bc3f36 src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Sat Jan 17 00:24:36 2015 +0200 +++ b/src/lib-storage/mail-storage.h Sat Jan 17 00:31:35 2015 +0200 @@ -154,7 +154,8 @@ MAIL_FETCH_SEARCH_RELEVANCY = 0x00100000, MAIL_FETCH_GUID = 0x00200000, MAIL_FETCH_POP3_ORDER = 0x00400000, From dovecot at dovecot.org Fri Jan 16 22:33:42 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 22:33:42 +0000 Subject: dovecot-2.2: doveadm fetch: Added body.snippet field. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/48d2bc84e047 changeset: 18160:48d2bc84e047 user: Timo Sirainen date: Sat Jan 17 00:32:10 2015 +0200 description: doveadm fetch: Added body.snippet field. diffstat: src/doveadm/doveadm-mail-fetch.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) diffs (30 lines): diff -r a76507bc3f36 -r 48d2bc84e047 src/doveadm/doveadm-mail-fetch.c --- a/src/doveadm/doveadm-mail-fetch.c Sat Jan 17 00:31:35 2015 +0200 +++ b/src/doveadm/doveadm-mail-fetch.c Sat Jan 17 00:32:10 2015 +0200 @@ -199,6 +199,18 @@ return doveadm_print_istream(input); } +static int fetch_body_snippet(struct fetch_cmd_context *ctx) +{ + const char *value; + + if (mail_get_special(ctx->mail, MAIL_FETCH_BODY_SNIPPET, &value) < 0) + return -1; + /* [0] contains the snippet algorithm, skip over it */ + i_assert(value[0] != '\0'); + doveadm_print(value + 1); + return 0; +} + static int fetch_text(struct fetch_cmd_context *ctx) { struct istream *input; @@ -376,6 +388,7 @@ { "modseq", 0, fetch_modseq }, { "hdr", MAIL_FETCH_STREAM_HEADER, fetch_hdr }, { "body", MAIL_FETCH_STREAM_BODY, fetch_body }, + { "body.snippet", MAIL_FETCH_BODY_SNIPPET, fetch_body_snippet }, { "text", MAIL_FETCH_STREAM_HEADER | MAIL_FETCH_STREAM_BODY, fetch_text }, { "text.utf8", MAIL_FETCH_STREAM_HEADER | From dovecot at dovecot.org Fri Jan 16 23:20:57 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 16 Jan 2015 23:20:57 +0000 Subject: dovecot-2.2: doveadm user: If username is changed by userdb look... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ec0518476003 changeset: 18161:ec0518476003 user: Timo Sirainen date: Sat Jan 17 01:19:42 2015 +0200 description: doveadm user: If username is changed by userdb lookup, return it. diffstat: src/doveadm/doveadm-auth.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diffs (38 lines): diff -r 48d2bc84e047 -r ec0518476003 src/doveadm/doveadm-auth.c --- a/src/doveadm/doveadm-auth.c Sat Jan 17 00:32:10 2015 +0200 +++ b/src/doveadm/doveadm-auth.c Sat Jan 17 01:19:42 2015 +0200 @@ -48,14 +48,14 @@ { const char *lookup_name = userdb ? "userdb lookup" : "passdb lookup"; pool_t pool; - const char *username, *const *fields, *p; + const char *updated_username = NULL, *const *fields, *p; int ret; pool = pool_alloconly_create("auth master lookup", 1024); if (userdb) { ret = auth_master_user_lookup(conn, input->username, &input->info, - pool, &username, &fields); + pool, &updated_username, &fields); } else { ret = auth_master_pass_lookup(conn, input->username, &input->info, pool, &fields); @@ -82,6 +82,8 @@ } else { printf("%s: %s\n", userdb ? "userdb" : "passdb", input->username); + if (updated_username != NULL) + printf(" %-10s: %s\n", "user", updated_username); for (; *fields; fields++) { p = strchr(*fields, '='); if (p == NULL) @@ -388,6 +390,8 @@ return 0; } + if (strcmp(input->username, user->username) != 0) + cmd_user_mail_input_field("user", user->username, show_field); cmd_user_mail_input_field("uid", user->set->mail_uid, show_field); cmd_user_mail_input_field("gid", user->set->mail_gid, show_field); cmd_user_mail_input_field("home", user->set->mail_home, show_field); From dovecot at dovecot.org Sat Jan 17 00:32:38 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 17 Jan 2015 00:32:38 +0000 Subject: dovecot-2.2: lib-storage: Added mail_user_init_fs_settings() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/a6e51d9098bc changeset: 18162:a6e51d9098bc user: Timo Sirainen date: Sat Jan 17 02:31:24 2015 +0200 description: lib-storage: Added mail_user_init_fs_settings() Also changed mailbox_list_init_fs() to use it internally. diffstat: src/lib-storage/mail-user.c | 20 ++++++++++++++++++++ src/lib-storage/mail-user.h | 7 +++++++ src/lib-storage/mailbox-list.c | 12 ++---------- 3 files changed, 29 insertions(+), 10 deletions(-) diffs (80 lines): diff -r ec0518476003 -r a6e51d9098bc src/lib-storage/mail-user.c --- a/src/lib-storage/mail-user.c Sat Jan 17 01:19:42 2015 +0200 +++ b/src/lib-storage/mail-user.c Sat Jan 17 02:31:24 2015 +0200 @@ -11,6 +11,8 @@ #include "strescape.h" #include "var-expand.h" #include "settings-parser.h" +#include "iostream-ssl.h" +#include "fs-api.h" #include "auth-master.h" #include "master-service.h" #include "mountpoint-list.h" @@ -536,3 +538,21 @@ user2->session_id = p_strdup(user2->pool, user->session_id); return user2; } + +void mail_user_init_fs_settings(struct mail_user *user, + struct fs_settings *fs_set, + struct ssl_iostream_settings *ssl_set) +{ + const struct mail_storage_settings *mail_set = + mail_user_set_get_storage_set(user); + + fs_set->username = user->username; + fs_set->session_id = user->session_id; + fs_set->base_dir = user->set->base_dir; + fs_set->temp_dir = user->set->mail_temp_dir; + fs_set->debug = user->mail_debug; + + fs_set->ssl_client_set = ssl_set; + ssl_set->ca_dir = mail_set->ssl_client_ca_dir; + ssl_set->ca_file = mail_set->ssl_client_ca_file; +} diff -r ec0518476003 -r a6e51d9098bc src/lib-storage/mail-user.h --- a/src/lib-storage/mail-user.h Sat Jan 17 01:19:42 2015 +0200 +++ b/src/lib-storage/mail-user.h Sat Jan 17 02:31:24 2015 +0200 @@ -6,6 +6,8 @@ struct module; struct mail_user; +struct fs_settings; +struct ssl_iostream_settings; struct mail_user_vfuncs { void (*deinit)(struct mail_user *user); @@ -159,4 +161,9 @@ struct mail_storage * mail_user_get_storage_class(struct mail_user *user, const char *name); +/* Initialize fs_settings from mail_user settings. */ +void mail_user_init_fs_settings(struct mail_user *user, + struct fs_settings *fs_set, + struct ssl_iostream_settings *ssl_set); + #endif diff -r ec0518476003 -r a6e51d9098bc src/lib-storage/mailbox-list.c --- a/src/lib-storage/mailbox-list.c Sat Jan 17 01:19:42 2015 +0200 +++ b/src/lib-storage/mailbox-list.c Sat Jan 17 02:31:24 2015 +0200 @@ -1830,18 +1830,10 @@ struct ssl_iostream_settings ssl_set; memset(&ssl_set, 0, sizeof(ssl_set)); - ssl_set.ca_dir = list->mail_set->ssl_client_ca_dir; - ssl_set.ca_file = list->mail_set->ssl_client_ca_file; - memset(&fs_set, 0, sizeof(fs_set)); - fs_set.username = list->ns->user->username; - fs_set.session_id = list->ns->user->session_id; + mail_user_init_fs_settings(list->ns->user, &fs_set, &ssl_set); + fs_set.root_path = root_dir; fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(list); - fs_set.base_dir = list->ns->user->set->base_dir; - fs_set.temp_dir = list->ns->user->set->mail_temp_dir; - fs_set.ssl_client_set = &ssl_set; - fs_set.root_path = root_dir; - fs_set.debug = list->ns->user->mail_debug; return fs_init(driver, args, &fs_set, fs_r, error_r); } From dovecot at dovecot.org Sat Jan 17 00:41:24 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 17 Jan 2015 00:41:24 +0000 Subject: dovecot-2.2: auth: Changed passdb { continue-ok } handling for c... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/20acc7cc5b11 changeset: 18163:20acc7cc5b11 user: Timo Sirainen date: Sat Jan 17 02:40:11 2015 +0200 description: auth: Changed passdb { continue-ok } handling for credentials lookups. If the last passdb after it doesn't return credentials, use the first passdb's credentials. This allows implementing plugins that modify the passdb result without actually changing the credentials. diffstat: src/auth/auth-request.c | 19 +++++++++++++++++++ src/auth/auth-request.h | 4 +++- src/auth/passdb.c | 4 ++++ 3 files changed, 26 insertions(+), 1 deletions(-) diffs (61 lines): diff -r a6e51d9098bc -r 20acc7cc5b11 src/auth/auth-request.c --- a/src/auth/auth-request.c Sat Jan 17 02:31:24 2015 +0200 +++ b/src/auth/auth-request.c Sat Jan 17 02:40:11 2015 +0200 @@ -800,10 +800,29 @@ { if (!auth_request_handle_passdb_callback(&result, request)) { /* try next passdb */ + if (request->skip_password_check && + request->delayed_credentials == NULL) { + /* passdb continue* rule after a successful lookup. + remember these credentials and use them later on. */ + unsigned char *dup; + + dup = p_malloc(request->pool, size); + memcpy(dup, credentials, size); + request->delayed_credentials = dup; + request->delayed_credentials_size = size; + } auth_request_lookup_credentials(request, request->credentials_scheme, request->private_callback.lookup_credentials); } else { + if (request->delayed_credentials != NULL && size == 0) { + /* we did multiple passdb lookups, but the last one + didn't provide any credentials (e.g. just wanted to + add some extra fields). so use the first passdb's + credentials instead. */ + credentials = request->delayed_credentials; + size = request->delayed_credentials_size; + } if (request->set->debug_passwords && result == PASSDB_RESULT_OK) { auth_request_log_debug(request, AUTH_SUBSYS_DB, diff -r a6e51d9098bc -r 20acc7cc5b11 src/auth/auth-request.h --- a/src/auth/auth-request.h Sat Jan 17 02:31:24 2015 +0200 +++ b/src/auth/auth-request.h Sat Jan 17 02:40:11 2015 +0200 @@ -89,7 +89,9 @@ set_credentials_callback_t *set_credentials; userdb_callback_t *userdb; } private_callback; - const char *credentials_scheme; + const char *credentials_scheme; + const unsigned char *delayed_credentials; + size_t delayed_credentials_size; void *context; diff -r a6e51d9098bc -r 20acc7cc5b11 src/auth/passdb.c --- a/src/auth/passdb.c Sat Jan 17 02:31:24 2015 +0200 +++ b/src/auth/passdb.c Sat Jan 17 02:40:11 2015 +0200 @@ -155,6 +155,10 @@ } else if (*auth_request->credentials_scheme == '\0') { /* We're doing a passdb lookup (not authenticating). Pass through a NULL password without an error. */ + } else if (auth_request->delayed_credentials != NULL) { + /* We already have valid credentials from an earlier + passdb lookup. auth_request_lookup_credentials_finish() + will use them. */ } else { auth_request_log_info(auth_request, AUTH_SUBSYS_DB, "Requested %s scheme, but we have a NULL password", From dovecot at dovecot.org Sat Jan 17 02:16:10 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 17 Jan 2015 02:16:10 +0000 Subject: dovecot-2.2: lib: Added o_stream_add_destroy_callback() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/4723cecff76c changeset: 18164:4723cecff76c user: Timo Sirainen date: Sat Jan 17 04:13:13 2015 +0200 description: lib: Added o_stream_add_destroy_callback() diffstat: src/lib/iostream-private.h | 4 ++++ src/lib/iostream.c | 28 ++++++++++++++++++++++++++++ src/lib/istream.c | 24 ++++-------------------- src/lib/ostream.c | 15 +++++++++++++++ src/lib/ostream.h | 12 ++++++++++++ 5 files changed, 63 insertions(+), 20 deletions(-) diffs (145 lines): diff -r 20acc7cc5b11 -r 4723cecff76c src/lib/iostream-private.h --- a/src/lib/iostream-private.h Sat Jan 17 02:40:11 2015 +0200 +++ b/src/lib/iostream-private.h Sat Jan 17 04:13:13 2015 +0200 @@ -27,6 +27,10 @@ void io_stream_close(struct iostream_private *stream, bool close_parent); void io_stream_set_max_buffer_size(struct iostream_private *stream, size_t max_size); +void io_stream_add_destroy_callback(struct iostream_private *stream, + void (*callback)(void *), void *context); +void io_stream_remove_destroy_callback(struct iostream_private *stream, + void (*callback)(void *)); /* Set a specific error for the stream. This shouldn't be used for regular syscall errors where stream's errno is enough, since it's used by default. The stream errno must always be set even if the error string is also set. diff -r 20acc7cc5b11 -r 4723cecff76c src/lib/iostream.c --- a/src/lib/iostream.c Sat Jan 17 02:40:11 2015 +0200 +++ b/src/lib/iostream.c Sat Jan 17 04:13:13 2015 +0200 @@ -62,6 +62,34 @@ stream->set_max_buffer_size(stream, max_size); } +void io_stream_add_destroy_callback(struct iostream_private *stream, + void (*callback)(void *), void *context) +{ + struct iostream_destroy_callback *dc; + + if (!array_is_created(&stream->destroy_callbacks)) + i_array_init(&stream->destroy_callbacks, 2); + dc = array_append_space(&stream->destroy_callbacks); + dc->callback = callback; + dc->context = context; +} + +void io_stream_remove_destroy_callback(struct iostream_private *stream, + void (*callback)(void *)) +{ + const struct iostream_destroy_callback *dcs; + unsigned int i, count; + + dcs = array_get(&stream->destroy_callbacks, &count); + for (i = 0; i < count; i++) { + if (dcs[i].callback == callback) { + array_delete(&stream->destroy_callbacks, i, 1); + return; + } + } + i_unreached(); +} + void io_stream_set_error(struct iostream_private *stream, const char *fmt, ...) { diff -r 20acc7cc5b11 -r 4723cecff76c src/lib/istream.c --- a/src/lib/istream.c Sat Jan 17 02:40:11 2015 +0200 +++ b/src/lib/istream.c Sat Jan 17 04:13:13 2015 +0200 @@ -58,31 +58,15 @@ void i_stream_add_destroy_callback(struct istream *stream, istream_callback_t *callback, void *context) { - struct iostream_private *iostream = &stream->real_stream->iostream; - struct iostream_destroy_callback *dc; - - if (!array_is_created(&iostream->destroy_callbacks)) - i_array_init(&iostream->destroy_callbacks, 2); - dc = array_append_space(&iostream->destroy_callbacks); - dc->callback = callback; - dc->context = context; + io_stream_add_destroy_callback(&stream->real_stream->iostream, + callback, context); } void i_stream_remove_destroy_callback(struct istream *stream, void (*callback)()) { - struct iostream_private *iostream = &stream->real_stream->iostream; - const struct iostream_destroy_callback *dcs; - unsigned int i, count; - - dcs = array_get(&iostream->destroy_callbacks, &count); - for (i = 0; i < count; i++) { - if (dcs[i].callback == (istream_callback_t *)callback) { - array_delete(&iostream->destroy_callbacks, i, 1); - return; - } - } - i_unreached(); + io_stream_remove_destroy_callback(&stream->real_stream->iostream, + callback); } int i_stream_get_fd(struct istream *stream) diff -r 20acc7cc5b11 -r 4723cecff76c src/lib/ostream.c --- a/src/lib/ostream.c Sat Jan 17 02:40:11 2015 +0200 +++ b/src/lib/ostream.c Sat Jan 17 04:13:13 2015 +0200 @@ -89,6 +89,21 @@ *_stream = NULL; } +#undef o_stream_add_destroy_callback +void o_stream_add_destroy_callback(struct ostream *stream, + ostream_callback_t *callback, void *context) +{ + io_stream_add_destroy_callback(&stream->real_stream->iostream, + callback, context); +} + +void o_stream_remove_destroy_callback(struct ostream *stream, + void (*callback)()) +{ + io_stream_remove_destroy_callback(&stream->real_stream->iostream, + callback); +} + void o_stream_close(struct ostream *stream) { o_stream_close_full(stream, TRUE); diff -r 20acc7cc5b11 -r 4723cecff76c src/lib/ostream.h --- a/src/lib/ostream.h Sat Jan 17 02:40:11 2015 +0200 +++ b/src/lib/ostream.h Sat Jan 17 04:13:13 2015 +0200 @@ -25,6 +25,7 @@ Pretty much the only real reason to return 0 is if you wish to send more data to client which isn't buffered, eg. o_stream_send_istream(). */ typedef int stream_flush_callback_t(void *context); +typedef void ostream_callback_t(void *context); /* Create new output stream from given file descriptor. If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */ @@ -63,6 +64,17 @@ void o_stream_ref(struct ostream *stream); /* Unreferences the stream and sets stream pointer to NULL. */ void o_stream_unref(struct ostream **stream); +/* Call the given callback function when stream is destroyed. */ +void o_stream_add_destroy_callback(struct ostream *stream, + ostream_callback_t *callback, void *context) + ATTR_NULL(3); +#define o_stream_add_destroy_callback(stream, callback, context) \ + o_stream_add_destroy_callback(stream + \ + CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \ + (ostream_callback_t *)callback, context) +/* Remove the destroy callback. */ +void o_stream_remove_destroy_callback(struct ostream *stream, + void (*callback)()); /* Mark the stream and all of its parent streams closed. Nothing will be sent after this call. */ From dovecot at dovecot.org Sat Jan 17 02:16:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 17 Jan 2015 02:16:11 +0000 Subject: dovecot-2.2: lib: Added o_stream_create_passthrough() for creati... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/071e46b032c8 changeset: 18165:071e46b032c8 user: Timo Sirainen date: Sat Jan 17 04:14:09 2015 +0200 description: lib: Added o_stream_create_passthrough() for creating simple wrapper ostreams diffstat: src/lib/ostream.c | 24 ++++++++++++++++++++++++ src/lib/ostream.h | 3 +++ 2 files changed, 27 insertions(+), 0 deletions(-) diffs (58 lines): diff -r 4723cecff76c -r 071e46b032c8 src/lib/ostream.c --- a/src/lib/ostream.c Sat Jan 17 04:13:13 2015 +0200 +++ b/src/lib/ostream.c Sat Jan 17 04:14:09 2015 +0200 @@ -528,6 +528,20 @@ return -1; } +static ssize_t +o_stream_default_sendv(struct ostream_private *stream, + const struct const_iovec *iov, unsigned int iov_count) +{ + ssize_t ret; + + if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) { + o_stream_copy_error_from_parent(stream); + return -1; + } + stream->ostream.offset += ret; + return ret; +} + static int o_stream_default_write_at(struct ostream_private *_stream, const void *data ATTR_UNUSED, @@ -589,6 +603,8 @@ _stream->get_used_size = o_stream_default_get_used_size; if (_stream->seek == NULL) _stream->seek = o_stream_default_seek; + if (_stream->sendv == NULL) + _stream->sendv = o_stream_default_sendv; if (_stream->write_at == NULL) _stream->write_at = o_stream_default_write_at; if (_stream->send_istream == NULL) @@ -628,3 +644,11 @@ va_end(args); return output; } + +struct ostream *o_stream_create_passthrough(struct ostream *output) +{ + struct ostream_private *stream; + + stream = i_new(struct ostream_private, 1); + return o_stream_create(stream, output, o_stream_get_fd(output)); +} diff -r 4723cecff76c -r 071e46b032c8 src/lib/ostream.h --- a/src/lib/ostream.h Sat Jan 17 04:13:13 2015 +0200 +++ b/src/lib/ostream.h Sat Jan 17 04:14:09 2015 +0200 @@ -45,6 +45,9 @@ struct ostream * o_stream_create_error_str(int stream_errno, const char *fmt, ...) ATTR_FORMAT(2, 3); +/* Create an output stream that simply passes through data. This is mainly + useful as a wrapper when combined with destroy callbacks. */ +struct ostream *o_stream_create_passthrough(struct ostream *output); /* Set name (e.g. path) for output stream. */ void o_stream_set_name(struct ostream *stream, const char *name); From dovecot at dovecot.org Sat Jan 17 02:16:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 17 Jan 2015 02:16:11 +0000 Subject: dovecot-2.2: lib: iostream-rawlog now writes to ostreams instead... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/c02f29ca104d changeset: 18166:c02f29ca104d user: Timo Sirainen date: Sat Jan 17 04:14:58 2015 +0200 description: lib: iostream-rawlog now writes to ostreams instead of directly to fds. diffstat: src/lib/iostream-rawlog-private.h | 3 +- src/lib/iostream-rawlog.c | 150 ++++++++++++++++++++----------------- src/lib/iostream-rawlog.h | 5 + src/lib/istream-rawlog.c | 20 ++++- src/lib/istream-rawlog.h | 4 + src/lib/ostream-rawlog.c | 20 ++++- src/lib/ostream-rawlog.h | 4 + 7 files changed, 127 insertions(+), 79 deletions(-) diffs (truncated from 349 to 300 lines): diff -r 071e46b032c8 -r c02f29ca104d src/lib/iostream-rawlog-private.h --- a/src/lib/iostream-rawlog-private.h Sat Jan 17 04:14:09 2015 +0200 +++ b/src/lib/iostream-rawlog-private.h Sat Jan 17 04:14:58 2015 +0200 @@ -13,8 +13,7 @@ struct iostream_private *iostream; enum iostream_rawlog_flags flags; - char *rawlog_path; - int rawlog_fd; + struct ostream *rawlog_output; buffer_t *buffer; bool input; diff -r 071e46b032c8 -r c02f29ca104d src/lib/iostream-rawlog.c --- a/src/lib/iostream-rawlog.c Sat Jan 17 04:14:09 2015 +0200 +++ b/src/lib/iostream-rawlog.c Sat Jan 17 04:14:58 2015 +0200 @@ -21,29 +21,14 @@ #define RAWLOG_MAX_LINE_LEN 8192 -static int -rawlog_write(struct rawlog_iostream *rstream, const void *data, size_t size) -{ - if (rstream->rawlog_fd == -1) - return -1; - - if (write_full(rstream->rawlog_fd, data, size) < 0) { - i_error("rawlog_istream.write(%s) failed: %m", - rstream->rawlog_path); - iostream_rawlog_close(rstream); - return -1; - } - return 0; -} - -static int +static void rawlog_write_timestamp(struct rawlog_iostream *rstream, bool line_ends) { unsigned char data[MAX_INT_STRLEN + 6 + 1 + 3]; buffer_t buf; if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_TIMESTAMP) == 0) - return 0; + return; buffer_create_from_data(&buf, data, sizeof(data)); str_printfa(&buf, "%lu.%06u ", @@ -54,7 +39,7 @@ str_append_c(&buf, line_ends ? ':' : '>'); str_append_c(&buf, ' '); } - return rawlog_write(rstream, buf.data, buf.used); + o_stream_nsend(rstream->rawlog_output, buf.data, buf.used); } void iostream_rawlog_init(struct rawlog_iostream *rstream, @@ -67,27 +52,60 @@ } static void +iostream_rawlog_write_buffered(struct rawlog_iostream *rstream, + const unsigned char *data, size_t size) +{ + const unsigned char *p; + size_t pos; + bool line_ends; + + while (size > 0) { + p = memchr(data, '\n', size); + if (p != NULL) { + line_ends = TRUE; + pos = p-data + 1; + } else if (rstream->buffer->used + size < RAWLOG_MAX_LINE_LEN) { + buffer_append(rstream->buffer, data, size); + break; + } else { + line_ends = FALSE; + pos = size; + } + + rawlog_write_timestamp(rstream, line_ends); + if (rstream->buffer->used > 0) { + o_stream_nsend(rstream->rawlog_output, + rstream->buffer->data, + rstream->buffer->used); + buffer_set_used_size(rstream->buffer, 0); + } + o_stream_nsend(rstream->rawlog_output, data, pos); + + data += pos; + size -= pos; + } +} + +static void iostream_rawlog_write_unbuffered(struct rawlog_iostream *rstream, const unsigned char *data, size_t size) { size_t i, start; - if (!rstream->line_continued) { - if (rawlog_write_timestamp(rstream, TRUE) < 0) - return; - } + if (!rstream->line_continued) + rawlog_write_timestamp(rstream, TRUE); for (start = 0, i = 1; i < size; i++) { if (data[i-1] == '\n') { - if (rawlog_write(rstream, data + start, i - start) < 0 || - rawlog_write_timestamp(rstream, TRUE) < 0) - return; + o_stream_nsend(rstream->rawlog_output, + data + start, i - start); + rawlog_write_timestamp(rstream, TRUE); start = i; } } if (start != size) { - if (rawlog_write(rstream, data + start, size - start) < 0) - return; + o_stream_nsend(rstream->rawlog_output, + data + start, size - start); } rstream->line_continued = data[size-1] != '\n'; } @@ -95,59 +113,30 @@ void iostream_rawlog_write(struct rawlog_iostream *rstream, const unsigned char *data, size_t size) { - const unsigned char *p; - size_t pos; - bool line_ends; - - if (size == 0) + if (size == 0 || rstream->rawlog_output == NULL) return; io_loop_time_refresh(); - if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) == 0) { + + o_stream_cork(rstream->rawlog_output); + if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0) + iostream_rawlog_write_buffered(rstream, data, size); + else iostream_rawlog_write_unbuffered(rstream, data, size); - return; - } + o_stream_uncork(rstream->rawlog_output); - while (rstream->rawlog_fd != -1 && size > 0) { - p = memchr(data, '\n', size); - if (p != NULL) { - line_ends = TRUE; - pos = p-data + 1; - } else if (rstream->buffer->used + size < RAWLOG_MAX_LINE_LEN) { - buffer_append(rstream->buffer, data, size); - return; - } else { - line_ends = FALSE; - pos = size; - } - - if (rawlog_write_timestamp(rstream, line_ends) < 0) - break; - if (rstream->buffer->used > 0) { - if (rawlog_write(rstream, rstream->buffer->data, - rstream->buffer->used) < 0) - break; - buffer_set_used_size(rstream->buffer, 0); - } - if (rawlog_write(rstream, data, pos) < 0) - break; - - data += pos; - size -= pos; + if (o_stream_nfinish(rstream->rawlog_output) < 0) { + i_error("write(%s) failed: %s", + o_stream_get_name(rstream->rawlog_output), + o_stream_get_error(rstream->rawlog_output)); + iostream_rawlog_close(rstream); } } void iostream_rawlog_close(struct rawlog_iostream *rstream) { - if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0 && - rstream->rawlog_fd != -1) { - if (close(rstream->rawlog_fd) < 0) { - i_error("rawlog_istream.close(%s) failed: %m", - rstream->rawlog_path); - } - } - rstream->rawlog_fd = -1; - i_free_and_null(rstream->rawlog_path); + if (rstream->rawlog_output != NULL) + o_stream_unref(&rstream->rawlog_output); if (rstream->buffer != NULL) buffer_free(&rstream->buffer); } @@ -285,3 +274,24 @@ iostream_rawlog_create_fd(fd, path, input, output); return 0; } + +void iostream_rawlog_create_from_stream(struct ostream *rawlog_output, + struct istream **input, + struct ostream **output) +{ + const enum iostream_rawlog_flags rawlog_flags = + IOSTREAM_RAWLOG_FLAG_BUFFERED | + IOSTREAM_RAWLOG_FLAG_TIMESTAMP; + struct istream *old_input; + struct ostream *old_output; + + old_input = *input; + old_output = *output; + o_stream_ref(rawlog_output); + *input = i_stream_create_rawlog_from_stream(old_input, rawlog_output, + rawlog_flags); + *output = o_stream_create_rawlog_from_stream(old_output, rawlog_output, + rawlog_flags); + i_stream_unref(&old_input); + o_stream_unref(&old_output); +} diff -r 071e46b032c8 -r c02f29ca104d src/lib/iostream-rawlog.h --- a/src/lib/iostream-rawlog.h Sat Jan 17 04:14:09 2015 +0200 +++ b/src/lib/iostream-rawlog.h Sat Jan 17 04:14:58 2015 +0200 @@ -13,5 +13,10 @@ int ATTR_NOWARN_UNUSED_RESULT iostream_rawlog_create_path(const char *path, struct istream **input, struct ostream **output); +/* Create rawlog that appends to the given rawlog_output. + Both input and output are written to the same stream. */ +void iostream_rawlog_create_from_stream(struct ostream *rawlog_output, + struct istream **input, + struct ostream **output); #endif diff -r 071e46b032c8 -r c02f29ca104d src/lib/istream-rawlog.c --- a/src/lib/istream-rawlog.c Sat Jan 17 04:14:09 2015 +0200 +++ b/src/lib/istream-rawlog.c Sat Jan 17 04:14:58 2015 +0200 @@ -1,6 +1,7 @@ /* Copyright (c) 2011-2015 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "ostream.h" #include "iostream-rawlog-private.h" #include "istream-private.h" #include "istream-rawlog.h" @@ -76,17 +77,30 @@ i_stream_create_rawlog(struct istream *input, const char *rawlog_path, int rawlog_fd, enum iostream_rawlog_flags flags) { - struct rawlog_istream *rstream; + struct ostream *rawlog_output; + bool autoclose_fd = (flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0; i_assert(rawlog_path != NULL); i_assert(rawlog_fd != -1); + rawlog_output = o_stream_create_fd(rawlog_fd, 0, autoclose_fd); + o_stream_set_name(rawlog_output, + t_strdup_printf("rawlog(%s)", rawlog_path)); + return i_stream_create_rawlog_from_stream(input, rawlog_output, flags); +} + +struct istream * +i_stream_create_rawlog_from_stream(struct istream *input, + struct ostream *rawlog_output, + enum iostream_rawlog_flags flags) +{ + struct rawlog_istream *rstream; + rstream = i_new(struct rawlog_istream, 1); rstream->istream.max_buffer_size = input->real_stream->max_buffer_size; rstream->istream.stream_size_passthrough = TRUE; - rstream->riostream.rawlog_path = i_strdup(rawlog_path); - rstream->riostream.rawlog_fd = rawlog_fd; + rstream->riostream.rawlog_output = rawlog_output; iostream_rawlog_init(&rstream->riostream, flags, TRUE); rstream->istream.read = i_stream_rawlog_read; diff -r 071e46b032c8 -r c02f29ca104d src/lib/istream-rawlog.h --- a/src/lib/istream-rawlog.h Sat Jan 17 04:14:09 2015 +0200 +++ b/src/lib/istream-rawlog.h Sat Jan 17 04:14:58 2015 +0200 @@ -4,5 +4,9 @@ struct istream * i_stream_create_rawlog(struct istream *input, const char *rawlog_path, int rawlog_fd, enum iostream_rawlog_flags flags); +struct istream * +i_stream_create_rawlog_from_stream(struct istream *input, + struct ostream *rawlog_output, + enum iostream_rawlog_flags flags); #endif diff -r 071e46b032c8 -r c02f29ca104d src/lib/ostream-rawlog.c --- a/src/lib/ostream-rawlog.c Sat Jan 17 04:14:09 2015 +0200 From dovecot at dovecot.org Mon Jan 19 19:12:49 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 19:12:49 +0000 Subject: dovecot-2.2: fts: Fixed assert-crash in HTML parsing, broken by ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/89163656c0f5 changeset: 18167:89163656c0f5 user: Timo Sirainen date: Mon Jan 19 21:11:29 2015 +0200 description: fts: Fixed assert-crash in HTML parsing, broken by the earlier changes. diffstat: src/plugins/fts/fts-parser-html.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diffs (15 lines): diff -r c02f29ca104d -r 89163656c0f5 src/plugins/fts/fts-parser-html.c --- a/src/plugins/fts/fts-parser-html.c Sat Jan 17 04:14:58 2015 +0200 +++ b/src/plugins/fts/fts-parser-html.c Mon Jan 19 21:11:29 2015 +0200 @@ -34,6 +34,11 @@ { struct html_fts_parser *parser = (struct html_fts_parser *)_parser; + if (block->size == 0) { + /* finished */ + return; + } + buffer_set_used_size(parser->output, 0); mail_html2text_more(parser->html2text, block->data, block->size, parser->output); From dovecot at dovecot.org Mon Jan 19 19:59:39 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 19:59:39 +0000 Subject: dovecot-2.2: dbox: Added asserts to make sure the mail body isn'... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/b03b1369410d changeset: 18168:b03b1369410d user: Timo Sirainen date: Mon Jan 19 21:52:21 2015 +0200 description: dbox: Added asserts to make sure the mail body isn't tried to be read too early while saving. If the mail headers are still being written, the opening will just fail thinking the mail is corrupted. diffstat: src/lib-storage/index/dbox-multi/mdbox-save.c | 3 +++ src/lib-storage/index/dbox-single/sdbox-file.h | 1 + src/lib-storage/index/dbox-single/sdbox-save.c | 7 +++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diffs (69 lines): diff -r 89163656c0f5 -r b03b1369410d src/lib-storage/index/dbox-multi/mdbox-save.c --- a/src/lib-storage/index/dbox-multi/mdbox-save.c Mon Jan 19 21:11:29 2015 +0200 +++ b/src/lib-storage/index/dbox-multi/mdbox-save.c Mon Jan 19 21:52:21 2015 +0200 @@ -24,6 +24,7 @@ struct dbox_file_append_context *file_append; uint32_t seq; uint32_t append_offset; + bool written_to_disk; }; struct mdbox_save_context { @@ -85,6 +86,7 @@ } /* saved mail */ + i_assert(mail->written_to_disk); if (dbox_file_append_flush(mail->file_append) < 0) ctx->ctx.failed = TRUE; @@ -183,6 +185,7 @@ dbox_file_set_syscall_error(file, "pwrite()"); return -1; } + mail->written_to_disk = TRUE; return 0; } diff -r 89163656c0f5 -r b03b1369410d src/lib-storage/index/dbox-single/sdbox-file.h --- a/src/lib-storage/index/dbox-single/sdbox-file.h Mon Jan 19 21:11:29 2015 +0200 +++ b/src/lib-storage/index/dbox-single/sdbox-file.h Mon Jan 19 21:52:21 2015 +0200 @@ -13,6 +13,7 @@ /* list of attachment paths while saving/copying message */ pool_t attachment_pool; ARRAY_TYPE(const_string) attachment_paths; + bool written_to_disk; }; struct dbox_file *sdbox_file_init(struct sdbox_mailbox *mbox, uint32_t uid); diff -r 89163656c0f5 -r b03b1369410d src/lib-storage/index/dbox-single/sdbox-save.c --- a/src/lib-storage/index/dbox-single/sdbox-save.c Mon Jan 19 21:11:29 2015 +0200 +++ b/src/lib-storage/index/dbox-single/sdbox-save.c Mon Jan 19 21:52:21 2015 +0200 @@ -38,7 +38,7 @@ { struct sdbox_save_context *ctx = (struct sdbox_save_context *)t->save_ctx; - struct dbox_file *const *files; + struct dbox_file *const *files, *file; unsigned int count; i_assert(seq >= ctx->first_saved_seq); @@ -47,7 +47,9 @@ i_assert(count > 0); i_assert(seq - ctx->first_saved_seq < count); - return files[seq - ctx->first_saved_seq]; + file = files[seq - ctx->first_saved_seq]; + i_assert(((struct sdbox_file *)file)->written_to_disk); + return file; } struct mail_save_context * @@ -144,6 +146,7 @@ dbox_file_set_syscall_error(file, "pwrite()"); return -1; } + sfile->written_to_disk = TRUE; /* remember the attachment paths until commit time */ extrefs_arr = index_attachment_save_get_extrefs(&ctx->ctx); From dovecot at dovecot.org Mon Jan 19 19:59:42 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 19:59:42 +0000 Subject: dovecot-2.2: lib-storage: MAIL_FETCH_BODY_SNIPPET should seek th... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/50514ef4f138 changeset: 18169:50514ef4f138 user: Timo Sirainen date: Mon Jan 19 21:53:00 2015 +0200 description: lib-storage: MAIL_FETCH_BODY_SNIPPET should seek the mail stream back to original position. diffstat: src/lib-storage/index/index-mail.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (28 lines): diff -r b03b1369410d -r 50514ef4f138 src/lib-storage/index/index-mail.c --- a/src/lib-storage/index/index-mail.c Mon Jan 19 21:52:21 2015 +0200 +++ b/src/lib-storage/index/index-mail.c Mon Jan 19 21:53:00 2015 +0200 @@ -905,6 +905,7 @@ { struct message_part *part; struct istream *input; + uoff_t old_offset; string_t *str; int ret; @@ -916,6 +917,7 @@ return 0; } + old_offset = mail->data.stream == NULL ? 0 : mail->data.stream->v_offset; if (mail_get_stream(&mail->mail.mail, NULL, NULL, &input) < 0) return -1; i_stream_seek(input, part->physical_pos); @@ -928,6 +930,8 @@ if (ret == 0) mail->data.body_snippet = str_c(str); i_stream_destroy(&input); + + i_stream_seek(mail->data.stream, old_offset); return ret; } From dovecot at dovecot.org Mon Jan 19 19:59:47 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 19:59:47 +0000 Subject: dovecot-2.2: lib-storage: Removed caching body snippet while mes... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/861c9985e7c2 changeset: 18170:861c9985e7c2 user: Timo Sirainen date: Mon Jan 19 21:58:19 2015 +0200 description: lib-storage: Removed caching body snippet while message is being saved. This broke saving mails with dbox, because it attempts to open the mails too early. Also the generation was a bit costly operation to do if it wasn't actually wanted to be cached. So in future we'd first want to check if body snippet is actually wanted. If it is, then generate the potential snippets while the message is being parsed (always generate the snippet for the best found MIME part, replacing existing snippets when needed). This requires the message_snippet_generate() API to support sending input as partial message_blocks. diffstat: src/lib-storage/index/index-mail-headers.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diffs (11 lines): diff -r 50514ef4f138 -r 861c9985e7c2 src/lib-storage/index/index-mail-headers.c --- a/src/lib-storage/index/index-mail-headers.c Mon Jan 19 21:53:00 2015 +0200 +++ b/src/lib-storage/index/index-mail-headers.c Mon Jan 19 21:58:19 2015 +0200 @@ -383,7 +383,6 @@ mail->data.save_sent_date = TRUE; mail->data.save_bodystructure_header = TRUE; mail->data.save_bodystructure_body = TRUE; - mail->data.save_body_snippet = TRUE; mail->data.tee_stream = tee_i_stream_create(input); input = tee_i_stream_create_child(mail->data.tee_stream); From dovecot at dovecot.org Mon Jan 19 20:26:14 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 20:26:14 +0000 Subject: dovecot-2.2: virtual plugin: If mailbox list iteration fails, lo... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/d4e9c940fb7f changeset: 18171:d4e9c940fb7f user: Timo Sirainen date: Mon Jan 19 22:09:14 2015 +0200 description: virtual plugin: If mailbox list iteration fails, log the error. diffstat: src/plugins/virtual/virtual-config.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-) diffs (40 lines): diff -r 861c9985e7c2 -r d4e9c940fb7f src/plugins/virtual/virtual-config.c --- a/src/plugins/virtual/virtual-config.c Mon Jan 19 21:58:19 2015 +0200 +++ b/src/plugins/virtual/virtual-config.c Mon Jan 19 22:09:14 2015 +0200 @@ -304,7 +304,8 @@ return FALSE; } -static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx) +static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx, + const char **error_r) { const enum mail_namespace_type iter_ns_types = MAIL_NAMESPACE_TYPE_MASK_ALL; @@ -354,7 +355,11 @@ } for (i = 0; i < count; i++) mail_search_args_unref(&wboxes[i]->search_args); - return mailbox_list_iter_deinit(&iter); + if (mailbox_list_iter_deinit(&iter) < 0) { + *error_r = mailbox_list_get_last_error(user->namespaces->list, NULL); + return -1; + } + return 0; } static void virtual_config_search_args_dup(struct virtual_mailbox *mbox) @@ -434,8 +439,11 @@ } virtual_mailbox_get_list_patterns(&ctx); - if (ret == 0 && ctx.have_wildcards) - ret = virtual_config_expand_wildcards(&ctx); + if (ret == 0 && ctx.have_wildcards) { + ret = virtual_config_expand_wildcards(&ctx, &error); + if (ret < 0) + mail_storage_set_critical(storage, "%s: %s", path, error); + } if (ret == 0 && !ctx.have_mailbox_defines) { mail_storage_set_critical(storage, From dovecot at dovecot.org Mon Jan 19 20:26:19 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 20:26:19 +0000 Subject: dovecot-2.2: imap-urlauth: If mailbox list iteration fails, log ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/fb2549cdf316 changeset: 18172:fb2549cdf316 user: Timo Sirainen date: Mon Jan 19 22:10:17 2015 +0200 description: imap-urlauth: If mailbox list iteration fails, log the error. diffstat: src/lib-imap-urlauth/imap-urlauth-backend.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diffs (15 lines): diff -r d4e9c940fb7f -r fb2549cdf316 src/lib-imap-urlauth/imap-urlauth-backend.c --- a/src/lib-imap-urlauth/imap-urlauth-backend.c Mon Jan 19 22:09:14 2015 +0200 +++ b/src/lib-imap-urlauth/imap-urlauth-backend.c Mon Jan 19 22:10:17 2015 +0200 @@ -136,7 +136,10 @@ ret = -1; mailbox_free(&box); } - if (mailbox_list_iter_deinit(&iter) < 0) + if (mailbox_list_iter_deinit(&iter) < 0) { + i_error("urlauth key reset: Couldn't iterate mailboxes: %s", + mailbox_list_get_last_error(user->namespaces->list, NULL)); ret = -1; + } return ret; } From dovecot at dovecot.org Mon Jan 19 20:26:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 20:26:20 +0000 Subject: dovecot-2.2: doveadm: If mailbox list iteration fails, log the e... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/322afa8ca547 changeset: 18173:322afa8ca547 user: Timo Sirainen date: Mon Jan 19 22:11:29 2015 +0200 description: doveadm: If mailbox list iteration fails, log the error reason. diffstat: src/doveadm/doveadm-mail-index.c | 3 ++- src/doveadm/doveadm-mail.c | 3 ++- src/doveadm/doveadm-mailbox-list-iter.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diffs (39 lines): diff -r fb2549cdf316 -r 322afa8ca547 src/doveadm/doveadm-mail-index.c --- a/src/doveadm/doveadm-mail-index.c Mon Jan 19 22:10:17 2015 +0200 +++ b/src/doveadm/doveadm-mail-index.c Mon Jan 19 22:11:29 2015 +0200 @@ -192,7 +192,8 @@ } T_END; } if (mailbox_list_iter_deinit(&iter) < 0) { - i_error("Listing mailboxes failed"); + i_error("Listing mailboxes failed: %s", + mailbox_list_get_last_error(user->namespaces->list, NULL)); doveadm_mail_failed_error(_ctx, MAIL_ERROR_TEMP); ret = -1; } diff -r fb2549cdf316 -r 322afa8ca547 src/doveadm/doveadm-mail.c --- a/src/doveadm/doveadm-mail.c Mon Jan 19 22:10:17 2015 +0200 +++ b/src/doveadm/doveadm-mail.c Mon Jan 19 22:11:29 2015 +0200 @@ -241,7 +241,8 @@ } T_END; } if (mailbox_list_iter_deinit(&iter) < 0) { - i_error("Listing mailboxes failed"); + i_error("Listing mailboxes failed: %s", + mailbox_list_get_last_error(user->namespaces->list, NULL)); ret = -1; } return ret; diff -r fb2549cdf316 -r 322afa8ca547 src/doveadm/doveadm-mailbox-list-iter.c --- a/src/doveadm/doveadm-mailbox-list-iter.c Mon Jan 19 22:10:17 2015 +0200 +++ b/src/doveadm/doveadm-mailbox-list-iter.c Mon Jan 19 22:11:29 2015 +0200 @@ -150,7 +150,8 @@ if (iter->iter == NULL) ret = 0; else if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) { - i_error("Listing mailboxes failed"); + i_error("Listing mailboxes failed: %s", + mailbox_list_get_last_error(iter->user->namespaces->list, NULL)); doveadm_mail_failed_error(iter->ctx, MAIL_ERROR_TEMP); } array_free(&iter->patterns); From dovecot at dovecot.org Mon Jan 19 20:26:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 20:26:20 +0000 Subject: dovecot-2.2: lib-storage: Comment updates to mailbox_list_iter_*() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e6d8d7e56828 changeset: 18174:e6d8d7e56828 user: Timo Sirainen date: Mon Jan 19 22:12:58 2015 +0200 description: lib-storage: Comment updates to mailbox_list_iter_*() diffstat: src/lib-storage/mailbox-list-iter.h | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diffs (23 lines): diff -r 322afa8ca547 -r e6d8d7e56828 src/lib-storage/mailbox-list-iter.h --- a/src/lib-storage/mailbox-list-iter.h Mon Jan 19 22:11:29 2015 +0200 +++ b/src/lib-storage/mailbox-list-iter.h Mon Jan 19 22:12:58 2015 +0200 @@ -65,7 +65,8 @@ const char *const *patterns, enum mailbox_list_iter_flags flags); /* List mailbox_list_iter_init_multiple(), but list mailboxes from all the - specified namespaces. */ + specified namespaces. If it fails, the error message is set to the first + namespaces->list. */ struct mailbox_list_iterate_context * mailbox_list_iter_init_namespaces(struct mail_namespace *namespaces, const char *const *patterns, @@ -75,7 +76,8 @@ const struct mailbox_info * mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx); /* Deinitialize mailbox list request. Returns -1 if some error - occurred while listing. */ + occurred while listing. The error string can be looked up with + mailbox_list_get_last_error(). */ int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **ctx); /* List one mailbox. Returns 1 if info returned, 0 if mailbox doesn't exist, -1 if error. */ From dovecot at dovecot.org Mon Jan 19 20:26:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 20:26:20 +0000 Subject: dovecot-2.2: doveadm: Added missing error handling to various ma... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f2a0dd55ad37 changeset: 18175:f2a0dd55ad37 user: Timo Sirainen date: Mon Jan 19 22:24:42 2015 +0200 description: doveadm: Added missing error handling to various mail commands. This fixes assert-crash that happened when the commands failed, because they hadn't set any exit_code. diffstat: src/doveadm/doveadm-mail-deduplicate.c | 15 +++++++++++---- src/doveadm/doveadm-mail-mailbox-metadata.c | 14 ++++++++++++-- src/doveadm/doveadm-mail.c | 10 ++++++++++ src/doveadm/doveadm-mail.h | 3 +++ src/doveadm/doveadm-mailbox-list-iter.c | 5 +++-- 5 files changed, 39 insertions(+), 8 deletions(-) diffs (189 lines): diff -r e6d8d7e56828 -r f2a0dd55ad37 src/doveadm/doveadm-mail-deduplicate.c --- a/src/doveadm/doveadm-mail-deduplicate.c Mon Jan 19 22:12:58 2015 +0200 +++ b/src/doveadm/doveadm-mail-deduplicate.c Mon Jan 19 22:24:42 2015 +0200 @@ -18,7 +18,8 @@ bool by_msgid; }; -static int cmd_deduplicate_uidlist(struct mailbox *box, struct uidlist *uidlist) +static int cmd_deduplicate_uidlist(struct doveadm_mail_cmd_context *_ctx, + struct mailbox *box, struct uidlist *uidlist) { struct mailbox_transaction_context *trans; struct mail_search_context *search_ctx; @@ -47,10 +48,14 @@ while (mailbox_search_next(search_ctx, &mail)) mail_expunge(mail); - if (mailbox_search_deinit(&search_ctx) < 0) + if (mailbox_search_deinit(&search_ctx) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); ret = -1; - if (mailbox_transaction_commit(&trans) < 0) + } + if (mailbox_transaction_commit(&trans) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); ret = -1; + } return ret; } @@ -85,6 +90,7 @@ continue; i_error("Couldn't lookup Message-ID: for UID=%u: %s", mail->uid, errstr); + doveadm_mail_failed_error(_ctx, error); ret = -1; break; } @@ -95,6 +101,7 @@ continue; i_error("Couldn't lookup GUID: for UID=%u: %s", mail->uid, errstr); + doveadm_mail_failed_error(_ctx, error); ret = -1; break; } @@ -122,7 +129,7 @@ iter = hash_table_iterate_init(hash); while (hash_table_iterate(iter, hash, &key, &value)) { T_BEGIN { - if (cmd_deduplicate_uidlist(box, value) < 0) + if (cmd_deduplicate_uidlist(_ctx, box, value) < 0) ret = -1; } T_END; } diff -r e6d8d7e56828 -r f2a0dd55ad37 src/doveadm/doveadm-mail-mailbox-metadata.c --- a/src/doveadm/doveadm-mail-mailbox-metadata.c Mon Jan 19 22:12:58 2015 +0200 +++ b/src/doveadm/doveadm-mail-mailbox-metadata.c Mon Jan 19 22:24:42 2015 +0200 @@ -32,6 +32,7 @@ if (mailbox_open(box) < 0) { i_error("Failed to open mailbox: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); mailbox_free(&box); return -1; } @@ -43,10 +44,12 @@ if (ret < 0) { i_error("Failed to set attribute: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); mailbox_transaction_rollback(&trans); } else if (mailbox_transaction_commit(&trans) < 0) { i_error("Failed to commit transaction: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); ret = -1; } @@ -145,6 +148,7 @@ if (mailbox_open(box) < 0) { i_error("Failed to open mailbox: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); mailbox_free(&box); return -1; } @@ -154,6 +158,7 @@ if (ret < 0) { i_error("Failed to get attribute: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); } else if (ret == 0) { /* not found, print as empty */ doveadm_print(""); @@ -225,17 +230,22 @@ if (mailbox_open(box) < 0) { i_error("Failed to open mailbox: %s", mailbox_get_last_error(box, NULL)); + doveadm_mail_failed_mailbox(_ctx, box); mailbox_free(&box); return -1; } if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_PRIVATE) { - if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_PRIVATE) < 0) + if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_PRIVATE) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); ret = -1; + } } if (ctx->key == NULL || ctx->key_type == MAIL_ATTRIBUTE_TYPE_SHARED) { - if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_SHARED) < 0) + if (cmd_mailbox_metadata_list_run_iter(ctx, box, MAIL_ATTRIBUTE_TYPE_SHARED) < 0) { + doveadm_mail_failed_mailbox(_ctx, box); ret = -1; + } } mailbox_free(&box); return ret; diff -r e6d8d7e56828 -r f2a0dd55ad37 src/doveadm/doveadm-mail.c --- a/src/doveadm/doveadm-mail.c Mon Jan 19 22:12:58 2015 +0200 +++ b/src/doveadm/doveadm-mail.c Mon Jan 19 22:24:42 2015 +0200 @@ -89,6 +89,15 @@ doveadm_mail_failed_storage(ctx, mailbox_get_storage(box)); } +void doveadm_mail_failed_list(struct doveadm_mail_cmd_context *ctx, + struct mailbox_list *list) +{ + enum mail_error error; + + mailbox_list_get_last_error(list, &error); + doveadm_mail_failed_error(ctx, error); +} + struct doveadm_mail_cmd_context * doveadm_mail_cmd_alloc_size(size_t size) { @@ -243,6 +252,7 @@ if (mailbox_list_iter_deinit(&iter) < 0) { i_error("Listing mailboxes failed: %s", mailbox_list_get_last_error(user->namespaces->list, NULL)); + doveadm_mail_failed_list(ctx, user->namespaces->list); ret = -1; } return ret; diff -r e6d8d7e56828 -r f2a0dd55ad37 src/doveadm/doveadm-mail.h --- a/src/doveadm/doveadm-mail.h Mon Jan 19 22:12:58 2015 +0200 +++ b/src/doveadm/doveadm-mail.h Mon Jan 19 22:24:42 2015 +0200 @@ -9,6 +9,7 @@ #include "mail-storage-service.h" struct mailbox; +struct mailbox_list; struct mail_storage; struct mail_user; struct doveadm_mail_cmd_context; @@ -135,6 +136,8 @@ struct mail_storage *storage); void doveadm_mail_failed_mailbox(struct doveadm_mail_cmd_context *ctx, struct mailbox *box); +void doveadm_mail_failed_list(struct doveadm_mail_cmd_context *ctx, + struct mailbox_list *list); extern struct doveadm_mail_cmd cmd_expunge; extern struct doveadm_mail_cmd cmd_search; diff -r e6d8d7e56828 -r f2a0dd55ad37 src/doveadm/doveadm-mailbox-list-iter.c --- a/src/doveadm/doveadm-mailbox-list-iter.c Mon Jan 19 22:12:58 2015 +0200 +++ b/src/doveadm/doveadm-mailbox-list-iter.c Mon Jan 19 22:24:42 2015 +0200 @@ -143,6 +143,7 @@ int doveadm_mailbox_list_iter_deinit(struct doveadm_mailbox_list_iter **_iter) { struct doveadm_mailbox_list_iter *iter = *_iter; + enum mail_error error; int ret; *_iter = NULL; @@ -151,8 +152,8 @@ ret = 0; else if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) { i_error("Listing mailboxes failed: %s", - mailbox_list_get_last_error(iter->user->namespaces->list, NULL)); - doveadm_mail_failed_error(iter->ctx, MAIL_ERROR_TEMP); + mailbox_list_get_last_error(iter->user->namespaces->list, &error)); + doveadm_mail_failed_error(iter->ctx, error); } array_free(&iter->patterns); i_free(iter); From dovecot at dovecot.org Mon Jan 19 21:59:53 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 21:59:53 +0000 Subject: dovecot-2.2: lib-storage: Added mail_parse_human_timestamp() to ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/b0fb4113fbbe changeset: 18176:b0fb4113fbbe user: Timo Sirainen date: Mon Jan 19 23:40:27 2015 +0200 description: lib-storage: Added mail_parse_human_timestamp() to parse human-writable timestamps. This isn't really the ideal location for the function, but since it uses both lib-settings and lib-imap, there's not any good location for it that I can think of.. diffstat: src/lib-storage/mail-search-register-human.c | 31 +++---------------------- src/lib-storage/mail-storage.c | 34 ++++++++++++++++++++++++++++ src/lib-storage/mail-storage.h | 5 ++++ 3 files changed, 43 insertions(+), 27 deletions(-) diffs (115 lines): diff -r f2a0dd55ad37 -r b0fb4113fbbe src/lib-storage/mail-search-register-human.c --- a/src/lib-storage/mail-search-register-human.c Mon Jan 19 22:24:42 2015 +0200 +++ b/src/lib-storage/mail-search-register-human.c Mon Jan 19 23:40:27 2015 +0200 @@ -6,7 +6,7 @@ #include "str.h" #include "unichar.h" #include "settings-parser.h" -#include "imap-date.h" +#include "mail-storage.h" #include "mail-search-register.h" #include "mail-search-parser.h" #include "mail-search-build.h" @@ -34,38 +34,15 @@ enum mail_search_date_type date_type) { struct mail_search_arg *sarg; - const char *value, *error; - struct tm tm; - unsigned int secs; - unsigned long unixtime; + const char *value; sarg = mail_search_build_new(ctx, type); if (mail_search_parse_string(ctx->parser, &value) < 0) return NULL; - /* a) yyyy-mm-dd - b) imap date - c) unix timestamp - d) interval (e.g. n days) */ - if (i_isdigit(value[0]) && i_isdigit(value[1]) && - i_isdigit(value[2]) && i_isdigit(value[3]) && value[4] == '-' && - i_isdigit(value[5]) && i_isdigit(value[6]) && value[7] == '-' && - i_isdigit(value[8]) && i_isdigit(value[9]) && value[10] == '\0') { - memset(&tm, 0, sizeof(tm)); - tm.tm_year = (value[0]-'0') * 1000 + (value[1]-'0') * 100 + - (value[2]-'0') * 10 + (value[3]-'0') - 1900; - tm.tm_mon = (value[5]-'0') * 10 + (value[6]-'0') - 1; - tm.tm_mday = (value[8]-'0') * 10 + (value[9]-'0'); - sarg->value.time = mktime(&tm); - } else if (imap_parse_date(value, &sarg->value.time)) { - /* imap date */ - } else if (str_to_ulong(value, &unixtime) == 0) { - sarg->value.time = unixtime; - } else if (settings_get_time(value, &secs, &error) == 0) { - sarg->value.time = ioloop_time - secs; - } else { + if (mail_parse_human_timestamp(value, &sarg->value.time) < 0) sarg->value.time = (time_t)-1; - } + sarg->value.search_flags = MAIL_SEARCH_ARG_FLAG_USE_TZ; if (sarg->value.time == (time_t)-1) { diff -r f2a0dd55ad37 -r b0fb4113fbbe src/lib-storage/mail-storage.c --- a/src/lib-storage/mail-storage.c Mon Jan 19 22:24:42 2015 +0200 +++ b/src/lib-storage/mail-storage.c Mon Jan 19 23:40:27 2015 +0200 @@ -12,6 +12,8 @@ #include "time-util.h" #include "var-expand.h" #include "dsasl-client.h" +#include "imap-date.h" +#include "settings-parser.h" #include "mail-index-private.h" #include "mail-index-alloc-cache.h" #include "mailbox-tree.h" @@ -2480,3 +2482,35 @@ index_flags |= MAIL_INDEX_OPEN_FLAG_NFS_FLUSH; return index_flags; } + +int mail_parse_human_timestamp(const char *str, time_t *timestamp_r) +{ + struct tm tm; + unsigned int secs; + const char *error; + + if (i_isdigit(str[0]) && i_isdigit(str[1]) && + i_isdigit(str[2]) && i_isdigit(str[3]) && str[4] == '-' && + i_isdigit(str[5]) && i_isdigit(str[6]) && str[7] == '-' && + i_isdigit(str[8]) && i_isdigit(str[9]) && str[10] == '\0') { + /* yyyy-mm-dd */ + memset(&tm, 0, sizeof(tm)); + tm.tm_year = (str[0]-'0') * 1000 + (str[1]-'0') * 100 + + (str[2]-'0') * 10 + (str[3]-'0') - 1900; + tm.tm_mon = (str[5]-'0') * 10 + (str[6]-'0') - 1; + tm.tm_mday = (str[8]-'0') * 10 + (str[9]-'0'); + *timestamp_r = mktime(&tm); + return 0; + } else if (imap_parse_date(str, timestamp_r)) { + /* imap date */ + return 0; + } else if (str_to_time(str, timestamp_r) == 0) { + /* unix timestamp */ + return 0; + } else if (settings_get_time(str, &secs, &error) == 0) { + *timestamp_r = ioloop_time - secs; + return 0; + } else { + return -1; + } +} diff -r f2a0dd55ad37 -r b0fb4113fbbe src/lib-storage/mail-storage.h --- a/src/lib-storage/mail-storage.h Mon Jan 19 22:24:42 2015 +0200 +++ b/src/lib-storage/mail-storage.h Mon Jan 19 23:40:27 2015 +0200 @@ -948,4 +948,9 @@ 128 bits are returned. */ void mail_generate_guid_128_hash(const char *guid, guid_128_t guid_128_r); +/* Parse a human-writable string into a timestamp. Returns 0 and timestamp on + success, -1 if the string couldn't be parsed. Currently supported string + formats: yyyy-mm-dd, imap date, unix timestamp, interval (e.g. n days). */ +int mail_parse_human_timestamp(const char *str, time_t *timestamp_r); + #endif From dovecot at dovecot.org Mon Jan 19 21:59:53 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 21:59:53 +0000 Subject: dovecot-2.2: dsync: Added -t parameter to save only ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f393f63764e0 changeset: 18177:f393f63764e0 user: Timo Sirainen date: Mon Jan 19 23:43:37 2015 +0200 description: dsync: Added -t parameter to save only mails newer than If one side has old mails that don't exist on the other side, they are ignored (not synced and not deleted). diffstat: src/doveadm/doveadm-dsync.c | 9 ++++++++- src/doveadm/dsync/dsync-brain-mailbox.c | 3 +++ src/doveadm/dsync/dsync-brain-private.h | 1 + src/doveadm/dsync/dsync-brain.c | 3 +++ src/doveadm/dsync/dsync-brain.h | 2 ++ src/doveadm/dsync/dsync-ibc-stream.c | 26 ++++++++++++++++++++++++-- src/doveadm/dsync/dsync-ibc.h | 2 ++ src/doveadm/dsync/dsync-mail.c | 1 + src/doveadm/dsync/dsync-mail.h | 3 +++ src/doveadm/dsync/dsync-mailbox-export.c | 20 +++++++++++++++++++- src/doveadm/dsync/dsync-mailbox-export.h | 3 ++- src/doveadm/dsync/dsync-mailbox-import.c | 25 ++++++++++++++++++++++++- src/doveadm/dsync/dsync-mailbox-import.h | 1 + 13 files changed, 93 insertions(+), 6 deletions(-) diffs (truncated from 375 to 300 lines): diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/doveadm-dsync.c --- a/src/doveadm/doveadm-dsync.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/doveadm-dsync.c Mon Jan 19 23:43:37 2015 +0200 @@ -16,6 +16,7 @@ #include "settings-parser.h" #include "master-service.h" #include "master-service-ssl-settings.h" +#include "mail-storage.h" #include "mail-storage-service.h" #include "mail-user.h" #include "mail-namespace.h" @@ -36,7 +37,7 @@ #include #include -#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:NPr:Rs:Ux:" +#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:NPr:Rs:t:Ux:" #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 /* The broken_char is mainly set to get a proper error message when trying to convert a mailbox with a name that can't be used properly translated between @@ -59,6 +60,7 @@ const char *state_input, *rawlog_path; ARRAY_TYPE(const_string) exclude_mailboxes; ARRAY_TYPE(const_string) namespace_prefixes; + time_t sync_since_timestamp; const char *remote_name; const char *local_location; @@ -539,6 +541,7 @@ set.process_title_prefix = t_strdup_printf( "%s ", net_ip2addr(&_ctx->cur_client_ip)); } + set.sync_since_timestamp = ctx->sync_since_timestamp; 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; @@ -960,6 +963,10 @@ ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_STATE; ctx->state_input = optarg; break; + case 't': + if (mail_parse_human_timestamp(optarg, &ctx->sync_since_timestamp) < 0) + i_fatal("Invalid -t parameter: %s", optarg); + break; case 'U': ctx->replicator_notify = TRUE; break; diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-brain-mailbox.c --- a/src/doveadm/dsync/dsync-brain-mailbox.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-mailbox.c Mon Jan 19 23:43:37 2015 +0200 @@ -220,6 +220,7 @@ remote_dsync_box->first_recent_uid, remote_dsync_box->highest_modseq, remote_dsync_box->highest_pvt_modseq, + brain->sync_since_timestamp, import_flags); } @@ -306,6 +307,8 @@ exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_MAILS_HAVE_GUIDS; if (brain->no_mail_prefetch) exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_MINIMAL_DMAIL_FILL; + if (brain->sync_since_timestamp > 0) + exporter_flags |= DSYNC_MAILBOX_EXPORTER_FLAG_TIMESTAMPS; brain->box_exporter = brain->backup_recv ? NULL : dsync_mailbox_export_init(brain->box, brain->log_scan, diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-brain-private.h --- a/src/doveadm/dsync/dsync-brain-private.h Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-private.h Mon Jan 19 23:43:37 2015 +0200 @@ -55,6 +55,7 @@ guid_128_t sync_box_guid; const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; + time_t sync_since_timestamp; char alt_char; unsigned int lock_timeout; diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-brain.c --- a/src/doveadm/dsync/dsync-brain.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.c Mon Jan 19 23:43:37 2015 +0200 @@ -175,6 +175,7 @@ } brain->alt_char = set->mailbox_alt_char == '\0' ? '_' : set->mailbox_alt_char; + brain->sync_since_timestamp = set->sync_since_timestamp; 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); @@ -207,6 +208,7 @@ NULL : str_c(sync_ns_str); ibc_set.sync_box = set->sync_box; ibc_set.exclude_mailboxes = set->exclude_mailboxes; + ibc_set.sync_since_timestamp = set->sync_since_timestamp; memcpy(ibc_set.sync_box_guid, set->sync_box_guid, sizeof(ibc_set.sync_box_guid)); ibc_set.sync_type = sync_type; @@ -452,6 +454,7 @@ 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); + brain->sync_since_timestamp = ibc_set->sync_since_timestamp; 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 -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-brain.h --- a/src/doveadm/dsync/dsync-brain.h Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.h Mon Jan 19 23:43:37 2015 +0200 @@ -55,6 +55,8 @@ /* Alternative character to use in mailbox names where the original character cannot be used. */ char mailbox_alt_char; + /* Sync only mails with received timestamp at least this high. */ + time_t sync_since_timestamp; /* If non-zero, use dsync lock file for this user */ unsigned int lock_timeout_secs; diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-ibc-stream.c --- a/src/doveadm/dsync/dsync-ibc-stream.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Mon Jan 19 23:43:37 2015 +0200 @@ -73,9 +73,10 @@ .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 " - "no_mail_sync no_backup_overwrite purge_remote" + "no_mail_sync no_backup_overwrite purge_remote " + "sync_since_timestamp" }, { .name = "mailbox_state", .chr = 'S', @@ -649,6 +650,10 @@ dsync_serializer_encode_add(encoder, "lock_timeout", t_strdup_printf("%u", set->lock_timeout)); } + if (set->sync_since_timestamp > 0) { + dsync_serializer_encode_add(encoder, "sync_since_timestamp", + t_strdup_printf("%ld", (long)set->sync_since_timestamp)); + } if ((set->brain_flags & DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS) != 0) dsync_serializer_encode_add(encoder, "send_mail_requests", ""); if ((set->brain_flags & DSYNC_BRAIN_FLAG_BACKUP_SEND) != 0) @@ -741,6 +746,14 @@ return DSYNC_IBC_RECV_RET_TRYAGAIN; } } + if (dsync_deserializer_decode_try(decoder, "sync_since_timestamp", &value)) { + if (str_to_time(value, &set->sync_since_timestamp) < 0 || + set->sync_since_timestamp == 0) { + dsync_ibc_input_error(ibc, decoder, + "Invalid sync_since_timestamp: %s", value); + return DSYNC_IBC_RECV_RET_TRYAGAIN; + } + } if (dsync_deserializer_decode_try(decoder, "send_mail_requests", &value)) set->brain_flags |= DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS; if (dsync_deserializer_decode_try(decoder, "backup_send", &value)) @@ -1539,6 +1552,10 @@ dsync_serializer_encode_add(encoder, "keyword_changes", str_c(kw_str)); } + if (change->received_timestamp > 0) { + dsync_serializer_encode_add(encoder, "received_timestamp", + t_strdup_printf("%lx", (unsigned long)change->received_timestamp)); + } dsync_serializer_encode_finish(&encoder, str); dsync_ibc_stream_send_string(ibc, str); @@ -1619,6 +1636,11 @@ array_append(&change->keyword_changes, &value, 1); } } + if (dsync_deserializer_decode_try(decoder, "received_timestamp", &value) && + str_to_time(value, &change->received_timestamp) < 0) { + dsync_ibc_input_error(ibc, decoder, "Invalid received_timestamp"); + return DSYNC_IBC_RECV_RET_TRYAGAIN; + } *change_r = change; return DSYNC_IBC_RECV_RET_OK; diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-ibc.h --- a/src/doveadm/dsync/dsync-ibc.h Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc.h Mon Jan 19 23:43:37 2015 +0200 @@ -52,6 +52,8 @@ /* Exclude these mailboxes from the sync. They can contain '*' wildcards and be \special-use flags. */ const char *const *exclude_mailboxes; + /* Sync only mails with received timestamp at least this high. */ + time_t sync_since_timestamp; enum dsync_brain_sync_type sync_type; enum dsync_brain_flags brain_flags; diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-mail.c --- a/src/doveadm/dsync/dsync-mail.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mail.c Mon Jan 19 23:43:37 2015 +0200 @@ -156,4 +156,5 @@ dest_r->keywords_reset = src->keywords_reset; const_string_array_dup(pool, &src->keyword_changes, &dest_r->keyword_changes); + dest_r->received_timestamp = src->received_timestamp; } diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-mail.h --- a/src/doveadm/dsync/dsync-mail.h Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mail.h Mon Jan 19 23:43:37 2015 +0200 @@ -77,6 +77,9 @@ bool keywords_reset; /* +add, -remove, =final, &add_and_final. */ ARRAY_TYPE(const_string) keyword_changes; + + /* Received timestamp for saves, if brain.sync_since_timestamp is set */ + time_t received_timestamp; }; struct mailbox_header_lookup_ctx * diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-mailbox-export.c --- a/src/doveadm/dsync/dsync-mailbox-export.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-export.c Mon Jan 19 23:43:37 2015 +0200 @@ -59,6 +59,7 @@ unsigned int mails_have_guids:1; unsigned int minimal_dmail_fill:1; unsigned int return_all_mails:1; + unsigned int export_received_timestamps:1; }; static int dsync_mail_error(struct dsync_mailbox_exporter *exporter, @@ -271,21 +272,36 @@ { struct dsync_mail_change *change; const char *guid, *hdr_hash; + enum mail_fetch_field wanted_fields = MAIL_FETCH_GUID; + time_t received_timestamp = 0; int ret; /* update wanted fields in case we didn't already set them for the search */ - mail_add_temp_wanted_fields(mail, MAIL_FETCH_GUID, + if (exporter->export_received_timestamps) + wanted_fields |= MAIL_FETCH_RECEIVED_DATE; + mail_add_temp_wanted_fields(mail, wanted_fields, exporter->wanted_headers); /* If message is already expunged here, just skip it */ if ((ret = exporter_get_guids(exporter, mail, &guid, &hdr_hash)) <= 0) return ret; + if (exporter->export_received_timestamps) { + if (mail_get_received_date(mail, &received_timestamp) < 0) + return dsync_mail_error(exporter, mail, "received-time"); + if (received_timestamp == 0) { + /* don't allow timestamps to be zero. we want to have + asserts verify that the timestamp is set properly. */ + received_timestamp = 1; + } + } + change = export_save_change_get(exporter, mail->uid); change->guid = *guid == '\0' ? "" : p_strdup(exporter->pool, guid); change->hdr_hash = p_strdup(exporter->pool, hdr_hash); + change->received_timestamp = received_timestamp; search_update_flag_changes(exporter, mail, change); export_add_mail_instance(exporter, change, mail->seq); @@ -478,6 +494,8 @@ (flags & DSYNC_MAILBOX_EXPORTER_FLAG_MAILS_HAVE_GUIDS) != 0; exporter->minimal_dmail_fill = (flags & DSYNC_MAILBOX_EXPORTER_FLAG_MINIMAL_DMAIL_FILL) != 0; + exporter->export_received_timestamps = + (flags & DSYNC_MAILBOX_EXPORTER_FLAG_TIMESTAMPS) != 0; p_array_init(&exporter->requested_uids, pool, 16); p_array_init(&exporter->search_uids, pool, 16); hash_table_create(&exporter->export_guids, pool, 0, str_hash, strcmp); diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-mailbox-export.h --- a/src/doveadm/dsync/dsync-mailbox-export.h Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-export.h Mon Jan 19 23:43:37 2015 +0200 @@ -4,7 +4,8 @@ enum dsync_mailbox_exporter_flags { DSYNC_MAILBOX_EXPORTER_FLAG_AUTO_EXPORT_MAILS = 0x01, DSYNC_MAILBOX_EXPORTER_FLAG_MAILS_HAVE_GUIDS = 0x02, - DSYNC_MAILBOX_EXPORTER_FLAG_MINIMAL_DMAIL_FILL = 0x04 + DSYNC_MAILBOX_EXPORTER_FLAG_MINIMAL_DMAIL_FILL = 0x04, + DSYNC_MAILBOX_EXPORTER_FLAG_TIMESTAMPS = 0x08 }; struct dsync_mailbox_exporter * diff -r b0fb4113fbbe -r f393f63764e0 src/doveadm/dsync/dsync-mailbox-import.c --- a/src/doveadm/dsync/dsync-mailbox-import.c Mon Jan 19 23:40:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Mon Jan 19 23:43:37 2015 +0200 @@ -58,6 +58,7 @@ uint32_t remote_uid_next; uint32_t remote_first_recent_uid; uint64_t remote_highest_modseq, remote_highest_pvt_modseq; + time_t sync_since_timestamp; struct mailbox_transaction_context *trans, *ext_trans; struct mail_search_context *search_ctx; @@ -177,6 +178,7 @@ uint32_t remote_first_recent_uid, From dovecot at dovecot.org Mon Jan 19 22:21:45 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Mon, 19 Jan 2015 22:21:45 +0000 Subject: dovecot-2.2: dsync: Added more debug logging. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/dbf3a0701810 changeset: 18178:dbf3a0701810 user: Timo Sirainen date: Tue Jan 20 00:20:27 2015 +0200 description: dsync: Added more debug logging. diffstat: src/doveadm/dsync/dsync-mailbox-import.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (12 lines): diff -r f393f63764e0 -r dbf3a0701810 src/doveadm/dsync/dsync-mailbox-import.c --- a/src/doveadm/dsync/dsync-mailbox-import.c Mon Jan 19 23:43:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 00:20:27 2015 +0200 @@ -1650,6 +1650,8 @@ new_uid = newmail->link->final_uid; } else { new_uid = common_uid_next++; + imp_debug(importer, "UID %u isn't usable, assigning new UID %u", + newmail->final_uid, new_uid); } newmail->final_uid = new_uid; From dovecot at dovecot.org Tue Jan 20 01:25:05 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 01:25:05 +0000 Subject: dovecot-2.2: virtual plugin: Read virtual index header when open... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e83c50fda315 changeset: 18179:e83c50fda315 user: Timo Sirainen date: Tue Jan 20 03:14:37 2015 +0200 description: virtual plugin: Read virtual index header when opening virtual mailbox. This allows doing some mailbox accessing without actually syncing the mailbox. For example MAIL_FETCH_MAILBOX_NAME can be used without crashing. diffstat: src/plugins/virtual/virtual-mail.c | 2 + src/plugins/virtual/virtual-storage.c | 7 ++++ src/plugins/virtual/virtual-storage.h | 4 ++ src/plugins/virtual/virtual-sync.c | 53 +++++++++++++++++++--------------- 4 files changed, 42 insertions(+), 24 deletions(-) diffs (194 lines): diff -r dbf3a0701810 -r e83c50fda315 src/plugins/virtual/virtual-mail.c --- a/src/plugins/virtual/virtual-mail.c Tue Jan 20 00:20:27 2015 +0200 +++ b/src/plugins/virtual/virtual-mail.c Tue Jan 20 03:14:37 2015 +0200 @@ -106,6 +106,8 @@ } bbox = virtual_backend_box_lookup(mbox, vmail->cur_vrec.mailbox_id); + i_assert(bbox != NULL); + vmail->cur_backend_mail = backend_mail_find(vmail, bbox->box); if (vmail->cur_backend_mail == NULL) { if (!bbox->box->opened && diff -r dbf3a0701810 -r e83c50fda315 src/plugins/virtual/virtual-storage.c --- a/src/plugins/virtual/virtual-storage.c Tue Jan 20 00:20:27 2015 +0200 +++ b/src/plugins/virtual/virtual-storage.c Tue Jan 20 03:14:37 2015 +0200 @@ -420,6 +420,7 @@ static int virtual_mailbox_open(struct mailbox *box) { struct virtual_mailbox *mbox = (struct virtual_mailbox *)box; + bool broken; int ret = 0; if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) { @@ -447,6 +448,12 @@ mail_index_ext_register(mbox->box.index, "virtual", 0, sizeof(struct virtual_mail_index_record), sizeof(uint32_t)); + + if (virtual_mailbox_ext_header_read(mbox, box->view, &broken) < 0) { + virtual_mailbox_close_internal(mbox); + index_storage_mailbox_close(box); + return -1; + } return 0; } diff -r dbf3a0701810 -r e83c50fda315 src/plugins/virtual/virtual-storage.h --- a/src/plugins/virtual/virtual-storage.h Tue Jan 20 00:20:27 2015 +0200 +++ b/src/plugins/virtual/virtual-storage.h Tue Jan 20 03:14:37 2015 +0200 @@ -172,6 +172,10 @@ int virtual_config_read(struct virtual_mailbox *mbox); void virtual_config_free(struct virtual_mailbox *mbox); +int virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox, + struct mail_index_view *view, + bool *broken_r); + struct virtual_backend_box * virtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name); struct virtual_backend_box * diff -r dbf3a0701810 -r e83c50fda315 src/plugins/virtual/virtual-sync.c --- a/src/plugins/virtual/virtual-sync.c Tue Jan 20 00:20:27 2015 +0200 +++ b/src/plugins/virtual/virtual-sync.c Tue Jan 20 03:14:37 2015 +0200 @@ -125,25 +125,27 @@ } static int -virtual_sync_get_backend_box(struct virtual_sync_context *ctx, const char *name, +virtual_sync_get_backend_box(struct virtual_mailbox *mbox, const char *name, struct virtual_backend_box **bbox_r) { - *bbox_r = virtual_backend_box_lookup_name(ctx->mbox, name); - if (*bbox_r != NULL || !ctx->mbox->sync_initialized) + *bbox_r = virtual_backend_box_lookup_name(mbox, name); + if (*bbox_r != NULL || !mbox->sync_initialized) return 0; /* another process just added a new mailbox. we can't handle this currently. */ - ctx->mbox->inconsistent = TRUE; - mail_storage_set_error(ctx->mbox->box.storage, MAIL_ERROR_TEMP, + mbox->inconsistent = TRUE; + mail_storage_set_error(mbox->box.storage, MAIL_ERROR_TEMP, "Backend mailbox added by another session. " "Reopen the virtual mailbox."); return -1; } -static int virtual_sync_ext_header_read(struct virtual_sync_context *ctx) +int virtual_mailbox_ext_header_read(struct virtual_mailbox *mbox, + struct mail_index_view *view, + bool *broken_r) { - const char *box_path = mailbox_get_path(&ctx->mbox->box); + const char *box_path = mailbox_get_path(&mbox->box); const struct virtual_mail_index_header *ext_hdr; const struct mail_index_header *hdr; const struct virtual_mail_index_mailbox_record *mailboxes; @@ -154,26 +156,26 @@ uint32_t prev_mailbox_id; int ret = 1; - hdr = mail_index_get_header(ctx->sync_view); - mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id, + hdr = mail_index_get_header(view); + mail_index_get_header_ext(view, mbox->virtual_ext_id, &ext_data, &ext_size); ext_hdr = ext_data; - if (ctx->mbox->sync_initialized && - ctx->mbox->prev_uid_validity == hdr->uid_validity && + if (mbox->sync_initialized && + mbox->prev_uid_validity == hdr->uid_validity && ext_size >= sizeof(*ext_hdr) && - ctx->mbox->prev_change_counter == ext_hdr->change_counter) { + mbox->prev_change_counter == ext_hdr->change_counter) { /* fully refreshed */ return 1; } - ctx->mbox->prev_uid_validity = hdr->uid_validity; + mbox->prev_uid_validity = hdr->uid_validity; if (ext_hdr == NULL || - ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) { + mbox->search_args_crc32 != ext_hdr->search_args_crc32) { mailboxes = NULL; ext_name_offset = 0; ext_mailbox_count = 0; } else { - ctx->mbox->prev_change_counter = ext_hdr->change_counter; + mbox->prev_change_counter = ext_hdr->change_counter; mailboxes = (const void *)(ext_hdr + 1); ext_name_offset = sizeof(*ext_hdr) + ext_hdr->mailbox_count * sizeof(*mailboxes); @@ -181,7 +183,7 @@ ext_hdr->mailbox_count > INT_MAX/sizeof(*mailboxes)) { i_error("virtual index %s: Broken mailbox_count header", box_path); - ctx->index_broken = TRUE; + *broken_r = TRUE; ext_mailbox_count = 0; ret = 0; } else { @@ -215,7 +217,7 @@ nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset); name = t_strndup(nameptr, mailboxes[i].name_len); - if (virtual_sync_get_backend_box(ctx, name, &bbox) < 0) + if (virtual_sync_get_backend_box(mbox, name, &bbox) < 0) ret = -1; } T_END; @@ -237,23 +239,23 @@ prev_mailbox_id = mailboxes[i].id; } if (i < ext_mailbox_count) { - ctx->index_broken = TRUE; + *broken_r = TRUE; ret = 0; } - ctx->mbox->highest_mailbox_id = ext_hdr == NULL ? 0 : + mbox->highest_mailbox_id = ext_hdr == NULL ? 0 : ext_hdr->highest_mailbox_id; - ctx->mbox->sync_initialized = TRUE; + mbox->sync_initialized = TRUE; /* assign new mailbox IDs if any are missing */ - bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count); + bboxes = array_get_modifiable(&mbox->backend_boxes, &count); for (i = 0; i < count; i++) { if (bboxes[i]->mailbox_id == 0) { - bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id; + bboxes[i]->mailbox_id = ++mbox->highest_mailbox_id; ret = 0; } } /* sort the backend mailboxes by mailbox_id. */ - array_sort(&ctx->mbox->backend_boxes, bbox_mailbox_id_cmp); + array_sort(&mbox->backend_boxes, bbox_mailbox_id_cmp); return ret; } @@ -1628,6 +1630,7 @@ { struct virtual_sync_context *ctx; enum mail_index_sync_flags index_sync_flags; + bool broken; int ret; ctx = i_new(struct virtual_sync_context, 1); @@ -1656,11 +1659,13 @@ return ret; } - ret = virtual_sync_ext_header_read(ctx); + ret = virtual_mailbox_ext_header_read(mbox, ctx->sync_view, &broken); if (ret < 0) return virtual_sync_finish(ctx, FALSE); if (ret == 0) ctx->ext_header_rewrite = TRUE; + if (broken) + ctx->index_broken = TRUE; /* apply changes from virtual index to backend mailboxes */ if (virtual_sync_index_changes(ctx) < 0) return virtual_sync_finish(ctx, FALSE); From dovecot at dovecot.org Tue Jan 20 01:25:05 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 01:25:05 +0000 Subject: dovecot-2.2: dsync: If same GUID already exists in storage, try ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/39d00448490f changeset: 18180:39d00448490f user: Timo Sirainen date: Tue Jan 20 03:23:29 2015 +0200 description: dsync: If same GUID already exists in storage, try to copy it instead of recreating the mail. This way most mailbox backends can reduce disk space by only doing a reference count update. This feature isn't enabled by default. A virtual "All Mails" mailbox needs to be configured using the virtual plugin. Then you need to give this mailbox as -a parameter, e.g.: doveadm sync -a "Virtual/All Mails" ... Currently this is implemented by reading through all the GUIDs in the virtual mailbox. This of course isn't very efficient for things like incremental replication. An upcoming conversation plugin will keep track of all the mails' GUIDs, so in future replication should be able to have this functionality efficiently as well. diffstat: src/doveadm/doveadm-dsync.c | 7 +- src/doveadm/dsync/dsync-brain-mailbox.c | 3 +- src/doveadm/dsync/dsync-brain-private.h | 1 + src/doveadm/dsync/dsync-brain.c | 18 +++ src/doveadm/dsync/dsync-brain.h | 4 + src/doveadm/dsync/dsync-ibc-pipe.c | 1 + src/doveadm/dsync/dsync-ibc-stream.c | 8 +- src/doveadm/dsync/dsync-ibc.h | 3 + src/doveadm/dsync/dsync-mailbox-import.c | 146 +++++++++++++++++++++++++----- src/doveadm/dsync/dsync-mailbox-import.h | 1 + 10 files changed, 165 insertions(+), 27 deletions(-) diffs (truncated from 503 to 300 lines): diff -r e83c50fda315 -r 39d00448490f src/doveadm/doveadm-dsync.c --- a/src/doveadm/doveadm-dsync.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/doveadm-dsync.c Tue Jan 20 03:23:29 2015 +0200 @@ -37,7 +37,7 @@ #include #include -#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:NPr:Rs:t:Ux:" +#define DSYNC_COMMON_GETOPT_ARGS "+1a:dEfg:l:m:n:NPr:Rs:t:Ux:" #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 /* The broken_char is mainly set to get a proper error message when trying to convert a mailbox with a name that can't be used properly translated between @@ -56,6 +56,7 @@ struct doveadm_mail_cmd_context ctx; enum dsync_brain_sync_type sync_type; const char *mailbox; + const char *virtual_all_box; guid_128_t mailbox_guid; const char *state_input, *rawlog_path; ARRAY_TYPE(const_string) exclude_mailboxes; @@ -543,6 +544,7 @@ } set.sync_since_timestamp = ctx->sync_since_timestamp; set.sync_box = ctx->mailbox; + set.virtual_all_box = ctx->virtual_all_box; 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; @@ -909,6 +911,9 @@ ctx->oneway = TRUE; ctx->backup = TRUE; break; + case 'a': + ctx->virtual_all_box = optarg; + break; case 'd': ctx->default_replica_location = TRUE; break; diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-brain-mailbox.c --- a/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 03:23:29 2015 +0200 @@ -213,7 +213,8 @@ import_flags |= DSYNC_MAILBOX_IMPORT_FLAG_MAILS_USE_GUID128; brain->box_importer = brain->backup_send ? NULL : - dsync_mailbox_import_init(brain->box, brain->log_scan, + dsync_mailbox_import_init(brain->box, brain->virtual_all_box, + brain->log_scan, last_common_uid, last_common_modseq, last_common_pvt_modseq, remote_dsync_box->uid_next, diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-brain-private.h --- a/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 03:23:29 2015 +0200 @@ -52,6 +52,7 @@ const char *process_title_prefix; ARRAY(struct mail_namespace *) sync_namespaces; const char *sync_box; + struct mailbox *virtual_all_box; guid_128_t sync_box_guid; const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-brain.c --- a/src/doveadm/dsync/dsync-brain.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.c Tue Jan 20 03:23:29 2015 +0200 @@ -141,6 +141,16 @@ (flags & DSYNC_BRAIN_FLAG_NO_MAIL_PREFETCH) != 0; } +static void +dsync_brain_open_virtual_all_box(struct dsync_brain *brain, + const char *vname) +{ + struct mail_namespace *ns; + + ns = mail_namespace_find(brain->user->namespaces, vname); + brain->virtual_all_box = mailbox_alloc(ns->list, vname, 0); +} + struct dsync_brain * dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc, enum dsync_brain_sync_type sync_type, @@ -185,6 +195,9 @@ brain->master_brain = TRUE; dsync_brain_set_flags(brain, flags); + if (set->virtual_all_box != NULL) + dsync_brain_open_virtual_all_box(brain, set->virtual_all_box); + if (sync_type != DSYNC_BRAIN_SYNC_TYPE_STATE) ; else if (dsync_mailbox_states_import(brain->mailbox_states, brain->pool, @@ -207,6 +220,7 @@ ibc_set.sync_ns_prefixes = sync_ns_str == NULL ? NULL : str_c(sync_ns_str); ibc_set.sync_box = set->sync_box; + ibc_set.virtual_all_box = set->virtual_all_box; ibc_set.exclude_mailboxes = set->exclude_mailboxes; ibc_set.sync_since_timestamp = set->sync_since_timestamp; memcpy(ibc_set.sync_box_guid, set->sync_box_guid, @@ -295,6 +309,8 @@ if (brain->box != NULL) dsync_brain_sync_mailbox_deinit(brain); + if (brain->virtual_all_box != NULL) + mailbox_free(&brain->virtual_all_box); if (brain->local_tree_iter != NULL) dsync_mailbox_tree_iter_deinit(&brain->local_tree_iter); if (brain->local_mailbox_tree != NULL) @@ -465,6 +481,8 @@ brain->purge = (ibc_set->brain_flags & DSYNC_BRAIN_FLAG_PURGE_REMOTE) != 0; + if (ibc_set->virtual_all_box != NULL) + dsync_brain_open_virtual_all_box(brain, ibc_set->virtual_all_box); dsync_brain_mailbox_trees_init(brain); if (brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE) diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-brain.h --- a/src/doveadm/dsync/dsync-brain.h Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.h Tue Jan 20 03:23:29 2015 +0200 @@ -47,6 +47,10 @@ ARRAY(struct mail_namespace *) sync_namespaces; /* Sync only this mailbox name */ const char *sync_box; + /* Use this virtual \All mailbox to be able to copy mails with the same + GUID instead of saving them twice. With most storages this results + in less disk space usage. */ + const char *virtual_all_box; /* Sync only this mailbox GUID */ guid_128_t sync_box_guid; /* Exclude these mailboxes from the sync. They can contain '*' diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-ibc-pipe.c --- a/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 03:23:29 2015 +0200 @@ -167,6 +167,7 @@ item->u.set.sync_ns_prefixes = p_strdup(item->pool, set->sync_ns_prefixes); item->u.set.sync_box = p_strdup(item->pool, set->sync_box); + item->u.set.virtual_all_box = p_strdup(item->pool, set->virtual_all_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, diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-ibc-stream.c --- a/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 03:23:29 2015 +0200 @@ -76,7 +76,7 @@ "debug sync_visible_namespaces exclude_mailboxes " "send_mail_requests backup_send backup_recv lock_timeout " "no_mail_sync no_backup_overwrite purge_remote " - "sync_since_timestamp" + "sync_since_timestamp virtual_all_box" }, { .name = "mailbox_state", .chr = 'S', @@ -613,6 +613,10 @@ } if (set->sync_box != NULL) dsync_serializer_encode_add(encoder, "sync_box", set->sync_box); + if (set->virtual_all_box != NULL) { + dsync_serializer_encode_add(encoder, "virtual_all_box", + set->virtual_all_box); + } if (set->exclude_mailboxes != NULL) { string_t *substr = t_str_new(64); unsigned int i; @@ -710,6 +714,8 @@ set->sync_ns_prefixes = p_strdup(pool, value); if (dsync_deserializer_decode_try(decoder, "sync_box", &value)) set->sync_box = p_strdup(pool, value); + if (dsync_deserializer_decode_try(decoder, "virtual_all_box", &value)) + set->virtual_all_box = p_strdup(pool, value); if (dsync_deserializer_decode_try(decoder, "sync_box_guid", &value) && guid_128_from_string(value, set->sync_box_guid) < 0) { dsync_ibc_input_error(ibc, decoder, diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-ibc.h --- a/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 03:23:29 2015 +0200 @@ -47,6 +47,9 @@ const char *sync_ns_prefixes; /* if non-NULL, sync only this mailbox name */ const char *sync_box; + /* if non-NULL, use this mailbox for finding messages with GUIDs and + copying them instead of saving them again. */ + const char *virtual_all_box; /* if non-empty, sync only this mailbox GUID */ guid_128_t sync_box_guid; /* Exclude these mailboxes from the sync. They can contain '*' diff -r e83c50fda315 -r 39d00448490f src/doveadm/dsync/dsync-mailbox-import.c --- a/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 03:14:37 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 03:23:29 2015 +0200 @@ -36,6 +36,9 @@ uint32_t local_uid; /* the original remote UID, or 0 if exists only remotely */ uint32_t remote_uid; + /* UID for the mail in the virtual \All mailbox */ + uint32_t virtual_all_uid; + unsigned int uid_in_local:1; unsigned int uid_is_usable:1; unsigned int skip:1; @@ -64,6 +67,10 @@ struct mail_search_context *search_ctx; struct mail *mail, *ext_mail; + struct mailbox *virtual_all_box; + struct mailbox_transaction_context *virtual_trans; + struct mail *virtual_mail; + struct mail *cur_mail; const char *cur_guid; const char *cur_hdr_hash; @@ -108,9 +115,10 @@ unsigned int delete_mailbox:1; }; -static void dsync_mailbox_save_newmails(struct dsync_mailbox_importer *importer, +static bool dsync_mailbox_save_newmails(struct dsync_mailbox_importer *importer, const struct dsync_mail *mail, - struct importer_new_mail *all_newmails); + struct importer_new_mail *all_newmails, + bool remote_mail); static int dsync_mailbox_import_commit(struct dsync_mailbox_importer *importer, bool final); @@ -170,6 +178,7 @@ struct dsync_mailbox_importer * dsync_mailbox_import_init(struct mailbox *box, + struct mailbox *virtual_all_box, struct dsync_transaction_log_scan *log_scan, uint32_t last_common_uid, uint64_t last_common_modseq, @@ -190,6 +199,7 @@ importer = p_new(pool, struct dsync_mailbox_importer, 1); importer->pool = pool; importer->box = box; + importer->virtual_all_box = virtual_all_box; importer->last_common_uid = last_common_uid; importer->last_common_modseq = last_common_modseq; importer->last_common_pvt_modseq = last_common_pvt_modseq; @@ -1666,17 +1676,17 @@ static int dsync_mailbox_import_local_uid(struct dsync_mailbox_importer *importer, - uint32_t uid, const char *guid, + struct mail *mail, uint32_t uid, const char *guid, struct dsync_mail *dmail_r) { const char *error_field, *errstr; enum mail_error error; - if (!mail_set_uid(importer->mail, uid)) + if (!mail_set_uid(mail, uid)) return 0; - if (dsync_mail_fill(importer->mail, TRUE, dmail_r, &error_field) < 0) { - errstr = mailbox_get_last_error(importer->mail->box, &error); + if (dsync_mail_fill(mail, TRUE, dmail_r, &error_field) < 0) { + errstr = mailbox_get_last_error(mail->box, &error); if (error == MAIL_ERROR_EXPUNGED) return 0; @@ -1834,13 +1844,32 @@ other instances */ local_n = 0; seq_range_array_iter_init(&local_iter, local_uids); while (seq_range_array_iter_nth(&local_iter, local_n++, &local_uid)) { - if (dsync_mailbox_import_local_uid(importer, local_uid, - all_newmails->guid, + if (dsync_mailbox_import_local_uid(importer, importer->mail, + local_uid, all_newmails->guid, &dmail) > 0) { - dsync_mailbox_save_newmails(importer, &dmail, - all_newmails); + if (dsync_mailbox_save_newmails(importer, &dmail, + all_newmails, FALSE)) + return TRUE; + } + } + return FALSE; +} + +static bool +dsync_mailbox_import_try_virtual_all(struct dsync_mailbox_importer *importer, + struct importer_new_mail *all_newmails) +{ + struct dsync_mail dmail; + + if (all_newmails->virtual_all_uid == 0) + return FALSE; + + if (dsync_mailbox_import_local_uid(importer, importer->virtual_mail, + all_newmails->virtual_all_uid, + all_newmails->guid, &dmail) > 0) { + if (dsync_mailbox_save_newmails(importer, &dmail, + all_newmails, FALSE)) return TRUE; - } } return FALSE; From dovecot at dovecot.org Tue Jan 20 02:31:45 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 02:31:45 +0000 Subject: dovecot-2.2: dsync: Added -F parameter to sync only mails with[o... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/35e4a6ae8d85 changeset: 18181:35e4a6ae8d85 user: Timo Sirainen date: Tue Jan 20 04:07:09 2015 +0200 description: dsync: Added -F parameter to sync only mails with[out] specific flag. diffstat: src/doveadm/doveadm-dsync.c | 17 +++++- src/doveadm/dsync/dsync-brain-mailbox.c | 1 + src/doveadm/dsync/dsync-brain-private.h | 1 + src/doveadm/dsync/dsync-brain.c | 3 + src/doveadm/dsync/dsync-brain.h | 3 + src/doveadm/dsync/dsync-ibc-pipe.c | 2 + src/doveadm/dsync/dsync-ibc-stream.c | 8 ++- src/doveadm/dsync/dsync-ibc.h | 2 + src/doveadm/dsync/dsync-mailbox-import.c | 98 ++++++++++++++++++++++++++----- src/doveadm/dsync/dsync-mailbox-import.h | 2 +- 10 files changed, 118 insertions(+), 19 deletions(-) diffs (truncated from 341 to 300 lines): diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/doveadm-dsync.c --- a/src/doveadm/doveadm-dsync.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/doveadm-dsync.c Tue Jan 20 04:07:09 2015 +0200 @@ -14,6 +14,7 @@ #include "strescape.h" #include "var-expand.h" #include "settings-parser.h" +#include "imap-util.h" #include "master-service.h" #include "master-service-ssl-settings.h" #include "mail-storage.h" @@ -37,7 +38,7 @@ #include #include -#define DSYNC_COMMON_GETOPT_ARGS "+1a:dEfg:l:m:n:NPr:Rs:t:Ux:" +#define DSYNC_COMMON_GETOPT_ARGS "+1a:dEfF:g:l:m:n:NPr:Rs:t:Ux:" #define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30 /* The broken_char is mainly set to get a proper error message when trying to convert a mailbox with a name that can't be used properly translated between @@ -56,6 +57,7 @@ struct doveadm_mail_cmd_context ctx; enum dsync_brain_sync_type sync_type; const char *mailbox; + const char *sync_flags; const char *virtual_all_box; guid_128_t mailbox_guid; const char *state_input, *rawlog_path; @@ -544,6 +546,7 @@ } set.sync_since_timestamp = ctx->sync_since_timestamp; set.sync_box = ctx->mailbox; + set.sync_flag = ctx->sync_flags; set.virtual_all_box = ctx->virtual_all_box; memcpy(set.sync_box_guid, ctx->mailbox_guid, sizeof(set.sync_box_guid)); set.lock_timeout_secs = ctx->lock_timeout; @@ -924,6 +927,18 @@ case 'f': ctx->sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL; break; + case 'F': { + const char *str = optarg; + + if (strchr(str, ' ') != NULL) + i_fatal("-F parameter doesn't support multiple flags currently"); + if (str[0] == '-') + str++; + if (str[0] == '\\' && imap_parse_system_flag(str) == 0) + i_fatal("Invalid system flag given for -F parameter: '%s'", str); + ctx->sync_flags = optarg; + break; + } case 'g': if (optarg[0] == '\0') ctx->no_mail_sync = TRUE; diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-brain-mailbox.c --- a/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-mailbox.c Tue Jan 20 04:07:09 2015 +0200 @@ -222,6 +222,7 @@ remote_dsync_box->highest_modseq, remote_dsync_box->highest_pvt_modseq, brain->sync_since_timestamp, + brain->sync_flag, import_flags); } diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-brain-private.h --- a/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain-private.h Tue Jan 20 04:07:09 2015 +0200 @@ -57,6 +57,7 @@ const char *const *exclude_mailboxes; enum dsync_brain_sync_type sync_type; time_t sync_since_timestamp; + const char *sync_flag; char alt_char; unsigned int lock_timeout; diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-brain.c --- a/src/doveadm/dsync/dsync-brain.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.c Tue Jan 20 04:07:09 2015 +0200 @@ -186,6 +186,7 @@ brain->alt_char = set->mailbox_alt_char == '\0' ? '_' : set->mailbox_alt_char; brain->sync_since_timestamp = set->sync_since_timestamp; + brain->sync_flag = p_strdup(brain->pool, set->sync_flag); 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); @@ -223,6 +224,7 @@ ibc_set.virtual_all_box = set->virtual_all_box; ibc_set.exclude_mailboxes = set->exclude_mailboxes; ibc_set.sync_since_timestamp = set->sync_since_timestamp; + ibc_set.sync_flags = set->sync_flag; memcpy(ibc_set.sync_box_guid, set->sync_box_guid, sizeof(ibc_set.sync_box_guid)); ibc_set.sync_type = sync_type; @@ -471,6 +473,7 @@ brain->exclude_mailboxes = ibc_set->exclude_mailboxes == NULL ? NULL : p_strarray_dup(brain->pool, ibc_set->exclude_mailboxes); brain->sync_since_timestamp = ibc_set->sync_since_timestamp; + brain->sync_flag = p_strdup(brain->pool, ibc_set->sync_flags); 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 -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-brain.h --- a/src/doveadm/dsync/dsync-brain.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-brain.h Tue Jan 20 04:07:09 2015 +0200 @@ -61,6 +61,9 @@ char mailbox_alt_char; /* Sync only mails with received timestamp at least this high. */ time_t sync_since_timestamp; + /* Sync only mails which contains / doesn't contain this flag. + '-' at the beginning means this flag must not exist. */ + const char *sync_flag; /* If non-zero, use dsync lock file for this user */ unsigned int lock_timeout_secs; diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-ibc-pipe.c --- a/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-pipe.c Tue Jan 20 04:07:09 2015 +0200 @@ -172,6 +172,8 @@ 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)); + item->u.set.sync_since_timestamp = set->sync_since_timestamp; + item->u.set.sync_flags = p_strdup(item->pool, set->sync_flags); } static enum dsync_ibc_recv_ret diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-ibc-stream.c --- a/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc-stream.c Tue Jan 20 04:07:09 2015 +0200 @@ -76,7 +76,7 @@ "debug sync_visible_namespaces exclude_mailboxes " "send_mail_requests backup_send backup_recv lock_timeout " "no_mail_sync no_backup_overwrite purge_remote " - "sync_since_timestamp virtual_all_box" + "sync_since_timestamp sync_flags virtual_all_box" }, { .name = "mailbox_state", .chr = 'S', @@ -658,6 +658,10 @@ dsync_serializer_encode_add(encoder, "sync_since_timestamp", t_strdup_printf("%ld", (long)set->sync_since_timestamp)); } + if (set->sync_flags != NULL) { + dsync_serializer_encode_add(encoder, "sync_flags", + set->sync_flags); + } if ((set->brain_flags & DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS) != 0) dsync_serializer_encode_add(encoder, "send_mail_requests", ""); if ((set->brain_flags & DSYNC_BRAIN_FLAG_BACKUP_SEND) != 0) @@ -760,6 +764,8 @@ return DSYNC_IBC_RECV_RET_TRYAGAIN; } } + if (dsync_deserializer_decode_try(decoder, "sync_flags", &value)) + set->sync_flags = p_strdup(pool, value); if (dsync_deserializer_decode_try(decoder, "send_mail_requests", &value)) set->brain_flags |= DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS; if (dsync_deserializer_decode_try(decoder, "backup_send", &value)) diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-ibc.h --- a/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-ibc.h Tue Jan 20 04:07:09 2015 +0200 @@ -57,6 +57,8 @@ const char *const *exclude_mailboxes; /* Sync only mails with received timestamp at least this high. */ time_t sync_since_timestamp; + /* Sync only mails with specified flags. */ + const char *sync_flags; enum dsync_brain_sync_type sync_type; enum dsync_brain_flags brain_flags; diff -r 39d00448490f -r 35e4a6ae8d85 src/doveadm/dsync/dsync-mailbox-import.c --- a/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 03:23:29 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 04:07:09 2015 +0200 @@ -63,6 +63,10 @@ uint64_t remote_highest_modseq, remote_highest_pvt_modseq; time_t sync_since_timestamp; + enum mail_flags sync_flag; + const char *sync_keyword; + bool sync_flag_dontwant; + struct mailbox_transaction_context *trans, *ext_trans; struct mail_search_context *search_ctx; struct mail *mail, *ext_mail; @@ -187,7 +191,7 @@ uint32_t remote_first_recent_uid, uint64_t remote_highest_modseq, uint64_t remote_highest_pvt_modseq, - time_t sync_since_timestamp, + time_t sync_since_timestamp, const char *sync_flag, enum dsync_mailbox_import_flags flags) { struct dsync_mailbox_importer *importer; @@ -211,6 +215,16 @@ importer->remote_highest_pvt_modseq = remote_highest_pvt_modseq; importer->sync_since_timestamp = sync_since_timestamp; importer->stateful_import = importer->last_common_uid_found; + if (sync_flag != NULL) { + if (sync_flag[0] == '-') { + importer->sync_flag_dontwant = TRUE; + sync_flag++; + } + if (sync_flag[0] == '\\') + importer->sync_flag = imap_parse_system_flag(sync_flag); + else + importer->sync_keyword = p_strdup(pool, sync_flag); + } hash_table_create(&importer->import_guids, pool, 0, str_hash, strcmp); hash_table_create_direct(&importer->import_uids, pool, 0); @@ -1226,11 +1240,72 @@ mail_update_pvt_modseq(mail, new_modseq); } +static bool +dsync_mail_change_have_keyword(const struct dsync_mail_change *change, + const char *keyword) +{ + const char *const *strp; + + array_foreach(&change->keyword_changes, strp) { + switch ((*strp)[0]) { + case KEYWORD_CHANGE_FINAL: + case KEYWORD_CHANGE_ADD_AND_FINAL: + if (strcasecmp((*strp)+1, keyword) == 0) + return TRUE; + break; + default: + break; + } + } + return FALSE; +} + +static bool +dsync_mailbox_import_want_change(struct dsync_mailbox_importer *importer, + const struct dsync_mail_change *change, + const char **result_r) +{ + if (importer->sync_since_timestamp > 0) { + i_assert(change->received_timestamp > 0); + if (change->received_timestamp < importer->sync_since_timestamp) { + /* mail has too old timestamp - skip it */ + *result_r = "Ignoring missing local mail with too old timestamp"; + return FALSE; + } + } + if (importer->sync_flag != 0) { + bool have_flag = (change->final_flags & importer->sync_flag) != 0; + + if (have_flag && importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that doesn't have wanted flags"; + return FALSE; + } + if (!have_flag && !importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that has unwanted flags"; + return FALSE; + } + } + if (importer->sync_keyword != NULL) { + bool have_kw = dsync_mail_change_have_keyword(change, importer->sync_keyword); + + if (have_kw && importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that doesn't have wanted keywords"; + return FALSE; + } + if (!have_kw && !importer->sync_flag_dontwant) { + *result_r = "Ignoring missing local mail that has unwanted keywords"; + return FALSE; + } + } + return TRUE; +} + static void dsync_mailbox_import_save(struct dsync_mailbox_importer *importer, const struct dsync_mail_change *change) { struct dsync_mail_change *save; + const char *result; i_assert(change->guid != NULL); @@ -1241,13 +1316,8 @@ dsync_mailbox_import_flag_change(importer, change); return; } - if (importer->sync_since_timestamp > 0) { - i_assert(change->received_timestamp > 0); - if (change->received_timestamp < importer->sync_since_timestamp) { - /* mail has too old timestamp - skip it */ - return; - } - } + if (!dsync_mailbox_import_want_change(importer, change, &result)) + return; From dovecot at dovecot.org Tue Jan 20 02:31:46 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 02:31:46 +0000 Subject: dovecot-2.2: imapc: Added imapc_features=gmail-labels-keyword Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/c18b2ffeb882 changeset: 18182:c18b2ffeb882 user: Timo Sirainen date: Tue Jan 20 04:30:27 2015 +0200 description: imapc: Added imapc_features=gmail-labels-keyword This is a bit kludgy feature mainly intended for migrations from GMail. Unfortunately I couldn't figure out any nicer way to do this for now. GMail's "All Mail" folder contains all messages in all folders, but it also contains some messages that don't exist in other folders. For migrations we want to copy only those messages that don't exist elsewhere. This can now be achieved with something like: doveadm -o imapc_features='gmail-labels-keyword ...' \ backup -F '-$GmailHaveLabels' mdbox:~/mdbox Note that dsync can't handle inserting mails into folders, so if doveadm backup is already run once and one of the existing mails loses all labels, doveadm backup will delete the whole folder and start again. diffstat: src/lib-storage/index/imapc/imapc-mailbox.c | 16 +++++++++++++++- src/lib-storage/index/imapc/imapc-settings.c | 1 + src/lib-storage/index/imapc/imapc-settings.h | 7 ++++--- src/lib-storage/index/imapc/imapc-sync.c | 14 +++++++++++--- 4 files changed, 31 insertions(+), 7 deletions(-) diffs (99 lines): diff -r 35e4a6ae8d85 -r c18b2ffeb882 src/lib-storage/index/imapc/imapc-mailbox.c --- a/src/lib-storage/index/imapc/imapc-mailbox.c Tue Jan 20 04:07:09 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mailbox.c Tue Jan 20 04:30:27 2015 +0200 @@ -263,7 +263,7 @@ uint32_t fetch_uid, uid; unsigned int i, j; ARRAY_TYPE(const_string) keywords = ARRAY_INIT; - bool seen_flags = FALSE; + bool seen_flags = FALSE, have_labels = FALSE; if (mbox == NULL || rseq == 0 || !imap_arg_get_list(reply->args, &list)) return; @@ -293,6 +293,12 @@ array_append(&keywords, &atom, 1); } } + } else if (strcasecmp(atom, "X-GM-LABELS") == 0 && + IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) { + if (!imap_arg_get_list(&list[i+1], &flags_list)) + return; + if (flags_list[0].type != IMAP_ARG_EOL) + have_labels = TRUE; } } /* FIXME: need to do something about recent flags */ @@ -351,6 +357,14 @@ mail_index_lookup_keywords(mbox->delayed_sync_view, lseq, &old_kws); + if (have_labels) { + /* add keyword for mails that have GMail labels. + this can be used for "All Mail" mailbox migrations + with dsync */ + atom = "$GMailHaveLabels"; + array_append(&keywords, &atom, 1); + } + array_append_zero(&keywords); kw = mail_index_keywords_create(mbox->box.index, array_idx(&keywords, 0)); diff -r 35e4a6ae8d85 -r c18b2ffeb882 src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 04:07:09 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 04:30:27 2015 +0200 @@ -80,6 +80,7 @@ { "rfc822.size", IMAPC_FEATURE_RFC822_SIZE }, { "guid-forced", IMAPC_FEATURE_GUID_FORCED }, { "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS }, + { "gmail-labels-keyword", IMAPC_FEATURE_GMAIL_LABELS_KEYWORD }, { NULL, 0 } }; diff -r 35e4a6ae8d85 -r c18b2ffeb882 src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 04:07:09 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 04:30:27 2015 +0200 @@ -3,9 +3,10 @@ /* */ enum imapc_features { - IMAPC_FEATURE_RFC822_SIZE = 0x01, - IMAPC_FEATURE_GUID_FORCED = 0x02, - IMAPC_FEATURE_FETCH_HEADERS = 0x04 + IMAPC_FEATURE_RFC822_SIZE = 0x01, + IMAPC_FEATURE_GUID_FORCED = 0x02, + IMAPC_FEATURE_FETCH_HEADERS = 0x04, + IMAPC_FEATURE_GMAIL_LABELS_KEYWORD = 0x08 }; /* */ diff -r 35e4a6ae8d85 -r c18b2ffeb882 src/lib-storage/index/imapc/imapc-sync.c --- a/src/lib-storage/index/imapc/imapc-sync.c Tue Jan 20 04:07:09 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-sync.c Tue Jan 20 04:30:27 2015 +0200 @@ -316,8 +316,13 @@ /* we'll resync existing messages' flags and add new messages. adding new messages requires sync locking to avoid duplicates. */ - imapc_sync_cmd(ctx, t_strdup_printf( - "UID FETCH %u:* FLAGS", mbox->sync_fetch_first_uid)); + string_t *cmd = t_str_new(64); + + str_printfa(cmd, "UID FETCH %u:* (FLAGS", mbox->sync_fetch_first_uid); + if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) + str_append(cmd, " X-GM-LABELS"); + str_append_c(cmd, ')'); + imapc_sync_cmd(ctx, str_c(cmd)); mbox->sync_fetch_first_uid = 0; } @@ -352,7 +357,10 @@ mbox->sync_next_lseq = 1; mbox->sync_next_rseq = 1; - imapc_sync_cmd(ctx, "UID FETCH 1:* FLAGS"); + if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) + imapc_sync_cmd(ctx, "UID FETCH 1:* FLAGS"); + else + imapc_sync_cmd(ctx, "UID FETCH 1:* (FLAGS X-GM-LABELS)"); } static int From dovecot at dovecot.org Tue Jan 20 02:48:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 02:48:11 +0000 Subject: dovecot-2.2: dsync: Crashfix to -F parameter handling. Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/b505739970e7 changeset: 18183:b505739970e7 user: Timo Sirainen date: Tue Jan 20 04:46:26 2015 +0200 description: dsync: Crashfix to -F parameter handling. diffstat: src/doveadm/dsync/dsync-mailbox-import.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r c18b2ffeb882 -r b505739970e7 src/doveadm/dsync/dsync-mailbox-import.c --- a/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 04:30:27 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-import.c Tue Jan 20 04:46:26 2015 +0200 @@ -1246,6 +1246,9 @@ { const char *const *strp; + if (!array_is_created(&change->keyword_changes)) + return FALSE; + array_foreach(&change->keyword_changes, strp) { switch ((*strp)[0]) { case KEYWORD_CHANGE_FINAL: From dovecot at dovecot.org Tue Jan 20 02:48:11 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 02:48:11 +0000 Subject: dovecot-2.2: dsync: Allow -m parameter to specify \Special-use m... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ba0b94f11cea changeset: 18184:ba0b94f11cea user: Timo Sirainen date: Tue Jan 20 04:46:51 2015 +0200 description: dsync: Allow -m parameter to specify \Special-use mailboxes. Similarly to how -x parameter allows them. diffstat: src/doveadm/dsync/dsync-mailbox-tree-fill.c | 31 ++++++++++++++++++++-------- 1 files changed, 22 insertions(+), 9 deletions(-) diffs (74 lines): diff -r b505739970e7 -r ba0b94f11cea src/doveadm/dsync/dsync-mailbox-tree-fill.c --- a/src/doveadm/dsync/dsync-mailbox-tree-fill.c Tue Jan 20 04:46:26 2015 +0200 +++ b/src/doveadm/dsync/dsync-mailbox-tree-fill.c Tue Jan 20 04:46:51 2015 +0200 @@ -268,17 +268,28 @@ } static bool -dsync_mailbox_info_is_excluded(const struct mailbox_info *info, - const char *const *exclude_mailboxes) +dsync_mailbox_info_is_wanted(const struct mailbox_info *info, + const char *box_name, + const char *const *exclude_mailboxes) { const char *const *info_specialuses; unsigned int i; - if (exclude_mailboxes == NULL) - return FALSE; + if (exclude_mailboxes == NULL && + (box_name == NULL || box_name[0] != '\\')) + return TRUE; info_specialuses = info->special_use == NULL ? NULL : t_strsplit(info->special_use, " "); + /* include */ + if (box_name != NULL && box_name[0] == '\\') { + if (info_specialuses == NULL || + !str_array_icase_find(info_specialuses, box_name)) + return FALSE; + } + /* exclude */ + if (exclude_mailboxes == NULL) + return TRUE; for (i = 0; exclude_mailboxes[i] != NULL; i++) { const char *exclude = exclude_mailboxes[i]; @@ -286,14 +297,14 @@ /* special-use */ if (info_specialuses != NULL && str_array_icase_find(info_specialuses, exclude)) - return TRUE; + return FALSE; } else { /* mailbox with wildcards */ if (wildcard_match(info->vname, exclude)) - return TRUE; + return FALSE; } } - return FALSE; + return TRUE; } int dsync_mailbox_tree_fill(struct dsync_mailbox_tree *tree, @@ -314,7 +325,8 @@ struct mailbox_list_iterate_context *iter; struct dsync_mailbox_node *node, *dup_node1, *dup_node2; const struct mailbox_info *info; - const char *list_pattern = box_name != NULL ? box_name : "*"; + const char *list_pattern = + box_name != NULL && box_name[0] != '\\' ? box_name : "*"; int ret = 0; i_assert(mail_namespace_get_sep(ns) == tree->sep); @@ -331,7 +343,8 @@ /* 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) T_BEGIN { - if (!dsync_mailbox_info_is_excluded(info, exclude_mailboxes)) { + if (dsync_mailbox_info_is_wanted(info, box_name, + exclude_mailboxes)) { if (dsync_mailbox_tree_add(tree, info, box_guid) < 0) ret = -1; } From dovecot at dovecot.org Tue Jan 20 03:42:41 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 03:42:41 +0000 Subject: dovecot-2.2: imapc: Added imapc_features=gmail-pop3-uidl Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/38c70f8ac3dd changeset: 18185:38c70f8ac3dd user: Timo Sirainen date: Tue Jan 20 05:41:23 2015 +0200 description: imapc: Added imapc_features=gmail-pop3-uidl This allows imapc to generate GMail POP3 compatible UIDL so that pop3-migration plugin isn't needed. diffstat: src/lib-storage/index/imapc/imapc-mail.c | 16 ++++++++++++++++ src/lib-storage/index/imapc/imapc-settings.c | 1 + src/lib-storage/index/imapc/imapc-settings.h | 3 ++- 3 files changed, 19 insertions(+), 1 deletions(-) diffs (57 lines): diff -r ba0b94f11cea -r 38c70f8ac3dd src/lib-storage/index/imapc/imapc-mail.c --- a/src/lib-storage/index/imapc/imapc-mail.c Tue Jan 20 04:46:51 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mail.c Tue Jan 20 05:41:23 2015 +0200 @@ -463,6 +463,8 @@ const char **value_r) { struct imapc_mailbox *mbox = (struct imapc_mailbox *)_mail->box; + struct index_mail *imail = (struct index_mail *)_mail; + uint64_t num; switch (field) { case MAIL_FETCH_GUID: @@ -473,6 +475,20 @@ } *value_r = ""; return imapc_mail_get_guid(_mail, value_r); + case MAIL_FETCH_UIDL_BACKEND: + if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3_UIDL)) + break; + if (imapc_mail_get_guid(_mail, value_r) < 0) + return -1; + if (str_to_uint64(*value_r, &num) < 0) { + mail_storage_set_critical(_mail->box->storage, + "X-GM-MSGID not 64bit integer as expected for POP3 UIDL generation: %s", *value_r); + return -1; + } + + *value_r = p_strdup_printf(imail->mail.data_pool, "GmailId%llx", + (unsigned long long)num); + return 0; default: break; } diff -r ba0b94f11cea -r 38c70f8ac3dd src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 04:46:51 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 05:41:23 2015 +0200 @@ -81,6 +81,7 @@ { "guid-forced", IMAPC_FEATURE_GUID_FORCED }, { "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS }, { "gmail-labels-keyword", IMAPC_FEATURE_GMAIL_LABELS_KEYWORD }, + { "gmail-pop3-uidl", IMAPC_FEATURE_GMAIL_POP3_UIDL }, { NULL, 0 } }; diff -r ba0b94f11cea -r 38c70f8ac3dd src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 04:46:51 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 05:41:23 2015 +0200 @@ -6,7 +6,8 @@ IMAPC_FEATURE_RFC822_SIZE = 0x01, IMAPC_FEATURE_GUID_FORCED = 0x02, IMAPC_FEATURE_FETCH_HEADERS = 0x04, - IMAPC_FEATURE_GMAIL_LABELS_KEYWORD = 0x08 + IMAPC_FEATURE_GMAIL_LABELS_KEYWORD = 0x08, + IMAPC_FEATURE_GMAIL_POP3_UIDL = 0x10 }; /* */ From dovecot at dovecot.org Tue Jan 20 19:56:19 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 19:56:19 +0000 Subject: dovecot-2.2: lib-imap-client: Added imapc_command_get_tag() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/034cb24bc590 changeset: 18186:034cb24bc590 user: Timo Sirainen date: Tue Jan 20 21:49:04 2015 +0200 description: lib-imap-client: Added imapc_command_get_tag() diffstat: src/lib-imap-client/imapc-client.h | 1 + src/lib-imap-client/imapc-connection.c | 5 +++++ 2 files changed, 6 insertions(+), 0 deletions(-) diffs (26 lines): diff -r 38c70f8ac3dd -r 034cb24bc590 src/lib-imap-client/imapc-client.h --- a/src/lib-imap-client/imapc-client.h Tue Jan 20 05:41:23 2015 +0200 +++ b/src/lib-imap-client/imapc-client.h Tue Jan 20 21:49:04 2015 +0200 @@ -155,6 +155,7 @@ ATTR_FORMAT(2, 3); void imapc_command_sendvf(struct imapc_command *cmd, const char *cmd_fmt, va_list args) ATTR_FORMAT(2, 0); +const char *imapc_command_get_tag(struct imapc_command *cmd); void imapc_command_abort(struct imapc_command **cmd); void imapc_client_register_untagged(struct imapc_client *client, diff -r 38c70f8ac3dd -r 034cb24bc590 src/lib-imap-client/imapc-connection.c --- a/src/lib-imap-client/imapc-connection.c Tue Jan 20 05:41:23 2015 +0200 +++ b/src/lib-imap-client/imapc-connection.c Tue Jan 20 21:49:04 2015 +0200 @@ -1610,6 +1610,11 @@ pool_unref(&cmd->pool); } +const char *imapc_command_get_tag(struct imapc_command *cmd) +{ + return t_strdup_printf("%u", cmd->tag); +} + void imapc_command_abort(struct imapc_command **_cmd) { struct imapc_command *cmd = *_cmd; From dovecot at dovecot.org Tue Jan 20 19:56:19 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 19:56:19 +0000 Subject: dovecot-2.2: imapc: Implemented imapc_features=gmail-pop3 that a... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/df92d09acc63 changeset: 18187:df92d09acc63 user: Timo Sirainen date: Tue Jan 20 21:54:58 2015 +0200 description: imapc: Implemented imapc_features=gmail-pop3 that also migrates pop3_deleted_flag. This also caused gmail-pop3-uidl feature to be renamed to simply gmail-pop3, which includes both the features. diffstat: src/lib-storage/index/imapc/imapc-mail.c | 2 +- src/lib-storage/index/imapc/imapc-mailbox.c | 76 ++++++++++++++++++++++++++++ src/lib-storage/index/imapc/imapc-settings.c | 8 ++- src/lib-storage/index/imapc/imapc-settings.h | 4 +- src/lib-storage/index/imapc/imapc-storage.h | 1 + src/lib-storage/index/imapc/imapc-sync.c | 45 ++++++++++++---- 6 files changed, 120 insertions(+), 16 deletions(-) diffs (266 lines): diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-mail.c --- a/src/lib-storage/index/imapc/imapc-mail.c Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mail.c Tue Jan 20 21:54:58 2015 +0200 @@ -476,7 +476,7 @@ *value_r = ""; return imapc_mail_get_guid(_mail, value_r); case MAIL_FETCH_UIDL_BACKEND: - if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3_UIDL)) + if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3)) break; if (imapc_mail_get_guid(_mail, value_r) < 0) return -1; diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-mailbox.c --- a/src/lib-storage/index/imapc/imapc-mailbox.c Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mailbox.c Tue Jan 20 21:54:58 2015 +0200 @@ -3,6 +3,7 @@ #include "lib.h" #include "ioloop.h" #include "imap-arg.h" +#include "imap-seqset.h" #include "imap-util.h" #include "imapc-client.h" #include "imapc-mail.h" @@ -422,6 +423,79 @@ } static void +imapc_untagged_esearch_gmail_pop3(const struct imap_arg *args, + struct imapc_mailbox *mbox) +{ + struct imapc_msgmap *msgmap; + const char *atom; + struct seq_range_iter iter; + ARRAY_TYPE(seq_range) rseqs; + unsigned int n; + uint32_t rseq, lseq, uid; + ARRAY_TYPE(keyword_indexes) keywords; + struct mail_keywords *kw; + unsigned int pop3_deleted_kw_idx; + + i_free_and_null(mbox->sync_gmail_pop3_search_tag); + + /* It should contain ALL */ + t_array_init(&rseqs, 64); + if (!imap_arg_atom_equals(&args[0], "ALL") || + !imap_arg_get_atom(&args[1], &atom) || + imap_seq_set_parse(atom, &rseqs) < 0) { + i_error("Invalid gmail-pop3 ESEARCH reply"); + return; + } + + mail_index_keyword_lookup_or_create(mbox->box.index, + mbox->storage->set->pop3_deleted_flag, &pop3_deleted_kw_idx); + + t_array_init(&keywords, 1); + array_append(&keywords, &pop3_deleted_kw_idx, 1); + kw = mail_index_keywords_create_from_indexes(mbox->box.index, &keywords); + + msgmap = imapc_client_mailbox_get_msgmap(mbox->client_box); + seq_range_array_iter_init(&iter, &rseqs); n = 0; + while (seq_range_array_iter_nth(&iter, n++, &rseq)) { + if (rseq > imapc_msgmap_count(msgmap)) { + /* we haven't even seen this message yet */ + break; + } + uid = imapc_msgmap_rseq_to_uid(msgmap, rseq); + if (!mail_index_lookup_seq(mbox->delayed_sync_view, + uid, &lseq)) + continue; + + /* add the pop3_deleted_flag */ + mail_index_update_keywords(mbox->delayed_sync_trans, + lseq, MODIFY_ADD, kw); + } + mail_index_keywords_unref(&kw); +} + +static void imapc_untagged_esearch(const struct imapc_untagged_reply *reply, + struct imapc_mailbox *mbox) +{ + const struct imap_arg *tag_list; + const char *str; + + if (mbox == NULL || !imap_arg_get_list(reply->args, &tag_list)) + return; + + /* ESEARCH begins with (TAG ) */ + if (!imap_arg_atom_equals(&tag_list[0], "TAG") || + !imap_arg_get_string(&tag_list[1], &str) || + tag_list[2].type != IMAP_ARG_EOL) + return; + + /* for now the only ESEARCH reply that we have is for getting GMail's + list of hidden POP3 messages. */ + if (mbox->sync_gmail_pop3_search_tag != NULL && + strcmp(mbox->sync_gmail_pop3_search_tag, str) == 0) + imapc_untagged_esearch_gmail_pop3(reply->args+1, mbox); +} + +static void imapc_resp_text_uidvalidity(const struct imapc_untagged_reply *reply, struct imapc_mailbox *mbox) { @@ -512,6 +586,8 @@ imapc_untagged_fetch); imapc_mailbox_register_untagged(mbox, "EXPUNGE", imapc_untagged_expunge); + imapc_mailbox_register_untagged(mbox, "ESEARCH", + imapc_untagged_esearch); imapc_mailbox_register_resp_text(mbox, "UIDVALIDITY", imapc_resp_text_uidvalidity); imapc_mailbox_register_resp_text(mbox, "UIDNEXT", diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.c Tue Jan 20 21:54:58 2015 +0200 @@ -30,6 +30,8 @@ DEF(SET_STR, imapc_list_prefix), DEF(SET_TIME, imapc_max_idle_time), + DEF(SET_STR, pop3_deleted_flag), + SETTING_DEFINE_LIST_END }; @@ -48,7 +50,9 @@ .imapc_features = "", .imapc_rawlog_dir = "", .imapc_list_prefix = "", - .imapc_max_idle_time = 60*29 + .imapc_max_idle_time = 60*29, + + .pop3_deleted_flag = "" }; static const struct setting_parser_info imapc_setting_parser_info = { @@ -81,7 +85,7 @@ { "guid-forced", IMAPC_FEATURE_GUID_FORCED }, { "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS }, { "gmail-labels-keyword", IMAPC_FEATURE_GMAIL_LABELS_KEYWORD }, - { "gmail-pop3-uidl", IMAPC_FEATURE_GMAIL_POP3_UIDL }, + { "gmail-pop3", IMAPC_FEATURE_GMAIL_POP3 }, { NULL, 0 } }; diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.h Tue Jan 20 21:54:58 2015 +0200 @@ -7,7 +7,7 @@ IMAPC_FEATURE_GUID_FORCED = 0x02, IMAPC_FEATURE_FETCH_HEADERS = 0x04, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD = 0x08, - IMAPC_FEATURE_GMAIL_POP3_UIDL = 0x10 + IMAPC_FEATURE_GMAIL_POP3 = 0x10 }; /* */ @@ -28,6 +28,8 @@ const char *imapc_list_prefix; unsigned int imapc_max_idle_time; + const char *pop3_deleted_flag; + enum imapc_features parsed_features; }; diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-storage.h --- a/src/lib-storage/index/imapc/imapc-storage.h Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.h Tue Jan 20 21:54:58 2015 +0200 @@ -110,6 +110,7 @@ uint32_t sync_next_rseq; uint32_t exists_count; uint32_t min_append_uid; + char *sync_gmail_pop3_search_tag; /* keep the previous fetched message body cached, mainly for partial IMAP fetches */ diff -r 034cb24bc590 -r df92d09acc63 src/lib-storage/index/imapc/imapc-sync.c --- a/src/lib-storage/index/imapc/imapc-sync.c Tue Jan 20 21:49:04 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-sync.c Tue Jan 20 21:54:58 2015 +0200 @@ -38,7 +38,8 @@ imapc_client_stop(ctx->mbox->storage->client->client); } -static void imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str) +static struct imapc_command * +imapc_sync_cmd(struct imapc_sync_context *ctx, const char *cmd_str) { struct imapc_command *cmd; @@ -47,6 +48,7 @@ imapc_sync_callback, ctx); imapc_command_set_flags(cmd, IMAPC_COMMAND_FLAG_RETRIABLE); imapc_command_send(cmd, cmd_str); + return cmd; } static void @@ -273,6 +275,28 @@ } } +static void +imapc_sync_send_commands(struct imapc_sync_context *ctx, uint32_t first_uid) +{ + string_t *cmd = t_str_new(64); + + str_printfa(cmd, "UID FETCH %u:* (FLAGS", first_uid); + if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) + str_append(cmd, " X-GM-LABELS"); + str_append_c(cmd, ')'); + imapc_sync_cmd(ctx, str_c(cmd)); + + if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_POP3) && + ctx->mbox->storage->set->pop3_deleted_flag[0] != '\0') { + struct imapc_command *cmd; + + cmd = imapc_sync_cmd(ctx, "SEARCH RETURN (ALL) X-GM-RAW \"in:^pop\""); + i_free(ctx->mbox->sync_gmail_pop3_search_tag); + ctx->mbox->sync_gmail_pop3_search_tag = + i_strdup(imapc_command_get_tag(cmd)); + } +} + static void imapc_sync_index(struct imapc_sync_context *ctx) { struct imapc_mailbox *mbox = ctx->mbox; @@ -316,13 +340,7 @@ /* we'll resync existing messages' flags and add new messages. adding new messages requires sync locking to avoid duplicates. */ - string_t *cmd = t_str_new(64); - - str_printfa(cmd, "UID FETCH %u:* (FLAGS", mbox->sync_fetch_first_uid); - if (IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) - str_append(cmd, " X-GM-LABELS"); - str_append_c(cmd, ')'); - imapc_sync_cmd(ctx, str_c(cmd)); + imapc_sync_send_commands(ctx, mbox->sync_fetch_first_uid); mbox->sync_fetch_first_uid = 0; } @@ -357,10 +375,7 @@ mbox->sync_next_lseq = 1; mbox->sync_next_rseq = 1; - if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) - imapc_sync_cmd(ctx, "UID FETCH 1:* FLAGS"); - else - imapc_sync_cmd(ctx, "UID FETCH 1:* (FLAGS X-GM-LABELS)"); + imapc_sync_send_commands(ctx, 1); } static int @@ -427,6 +442,12 @@ } else { mail_index_sync_rollback(&ctx->index_sync_ctx); } + if (ctx->mbox->sync_gmail_pop3_search_tag != NULL) { + mail_storage_set_critical(&ctx->mbox->storage->storage, + "gmail-pop3 search not successful"); + i_free_and_null(ctx->mbox->sync_gmail_pop3_search_tag); + ret = -1; + } ctx->mbox->syncing = FALSE; ctx->mbox->sync_ctx = NULL; From dovecot at dovecot.org Tue Jan 20 22:20:35 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 22:20:35 +0000 Subject: dovecot-2.2: master: Fixed a check to see if login directory has... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e9a8fc0e21c9 changeset: 18188:e9a8fc0e21c9 user: Timo Sirainen date: Wed Jan 21 00:19:17 2015 +0200 description: master: Fixed a check to see if login directory has any unix listeners. diffstat: src/master/master-settings.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (21 lines): diff -r df92d09acc63 -r e9a8fc0e21c9 src/master/master-settings.c --- a/src/master/master-settings.c Tue Jan 20 21:54:58 2015 +0200 +++ b/src/master/master-settings.c Wed Jan 21 00:19:17 2015 +0200 @@ -644,6 +644,7 @@ { struct service_settings *const *services; struct file_listener_settings *const *uls; + unsigned int dir_len = strlen(dir); array_foreach(&set->services, services) { struct service_settings *service = *services; @@ -652,7 +653,8 @@ array_foreach(&service->unix_listeners, uls) { struct file_listener_settings *u = *uls; - if (strncmp(u->path, dir, strlen(dir)) == 0) + if (strncmp(u->path, dir, dir_len) == 0 && + u->path[dir_len] == '/') return TRUE; } } From dovecot at dovecot.org Tue Jan 20 23:43:31 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:43:31 +0000 Subject: dovecot-2.2: lib: data-stack - fix pointer arithmetic compiler w... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/3ef7f3d53d17 changeset: 18189:3ef7f3d53d17 user: Phil Carmody date: Wed Jan 21 01:42:01 2015 +0200 description: lib: data-stack - fix pointer arithmetic compiler warning Clang's -fsanitize=unsigned-integer-overflow barfs as follows: data-stack.c:477:29: runtime error: negation of 8 cannot be represented in type 'unsigned long' data-stack.c:495:15: runtime error: negation of 8 cannot be represented in type 'unsigned long' Which is of course complete bollocks. There is no 8, there's only an 8ul, and the negation of 8ul is 0xfffffff8ul (or a wider equivalent). That's the law. However, the pointer arithmetic which follows the negation, whilst almost certainly working in practice, is probably bogus, so just make the thing signed before the negation, and both problems go away. Reported-by: Teemu Huovila Signed-off-by: Phil Carmody diffstat: src/lib/data-stack.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r e9a8fc0e21c9 -r 3ef7f3d53d17 src/lib/data-stack.c --- a/src/lib/data-stack.c Wed Jan 21 00:19:17 2015 +0200 +++ b/src/lib/data-stack.c Wed Jan 21 01:42:01 2015 +0200 @@ -474,7 +474,7 @@ alloc_growth = (new_alloc_size - last_alloc_size); #ifdef DEBUG size_t old_raw_size; /* sorry, non-C99 users - add braces if you need them */ - old_raw_size = *(size_t *)PTR_OFFSET(mem, -MEM_ALIGN(sizeof(size_t))); + old_raw_size = *(size_t *)PTR_OFFSET(mem, -(ptrdiff_t)MEM_ALIGN(sizeof(size_t))); i_assert(ALLOC_SIZE(old_raw_size) == last_alloc_size); /* Only check one byte for over-run, that catches most offenders who are likely to use t_try_realloc() */ @@ -492,7 +492,7 @@ /* All reallocs are permanent by definition However, they don't count as a new allocation */ current_frame_block->alloc_bytes[frame_pos] += alloc_growth; - *(size_t *)PTR_OFFSET(mem, -MEM_ALIGN(sizeof(size_t))) = size; + *(size_t *)PTR_OFFSET(mem, -(ptrdiff_t)MEM_ALIGN(sizeof(size_t))) = size; memset(PTR_OFFSET(mem, size), CLEAR_CHR, new_alloc_size - size - MEM_ALIGN(sizeof(size_t))); #endif From dovecot at dovecot.org Tue Jan 20 23:54:58 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:54:58 +0000 Subject: dovecot-2.2: lib: seq-range-array - add range changes Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/230f3579c9b7 changeset: 18190:230f3579c9b7 user: Phil Carmody date: Wed Jan 21 01:44:31 2015 +0200 description: lib: seq-range-array - add range changes Pull the _add_range() guts into a private helper function, and add a new _add_range_count() helper which also returns the number of SEQs added. Expand the tests to test this new functionality. Signed-off-by: Phil Carmody diffstat: src/lib/seq-range-array.c | 56 ++++++++++++++++++++++++++++++++++++++++- src/lib/seq-range-array.h | 10 ++++++- src/lib/test-seq-range-array.c | 16 ++++++++--- 3 files changed, 74 insertions(+), 8 deletions(-) diffs (143 lines): diff -r 3ef7f3d53d17 -r 230f3579c9b7 src/lib/seq-range-array.c --- a/src/lib/seq-range-array.c Wed Jan 21 01:42:01 2015 +0200 +++ b/src/lib/seq-range-array.c Wed Jan 21 01:44:31 2015 +0200 @@ -110,8 +110,10 @@ seq_range_array_add(array, seq); } -void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array, - uint32_t seq1, uint32_t seq2) +static void +seq_range_array_add_range_internal(ARRAY_TYPE(seq_range) *array, + uint32_t seq1, uint32_t seq2, + unsigned int *r_count) { struct seq_range *data, value; unsigned int idx1, idx2, count; @@ -120,6 +122,43 @@ seq_range_lookup(array, seq2, &idx2); data = array_get_modifiable(array, &count); + if (r_count != NULL) { + /* Find number we're adding by counting the number we're + not adding, and subtracting that from the nominal range. */ + unsigned int added = seq2+1 - seq1; + unsigned int countidx2 = idx2; + unsigned int overcounted = 0u, notadded = 0u; + unsigned int i; + + if (idx1 == count) { + /* not in a range as too far right */ + } else if (seq1 < data[idx1].seq1) { + /* not in a range, to the left of a real range */ + } else { + /* count the whole of this range, which is an overcount */ + overcounted += seq1 - data[idx1].seq1; + /* fencepost check: equality means the whole range is valid, + therefore there's no overcounting. Result = 0 overcount */ + } + if (idx2 == count) { + /* not in a range as too far right */ + } else if (seq2 < data[idx2].seq1) { + /* not in a range, to the left of a real range */ + } else { + /* count the whole of this range, which is an overcount */ + overcounted += data[idx2].seq2 - seq2; + countidx2++; /* may become == count i.e. past the end */ + /* fencepost check: equality means the whole range is valid, + therefore there's no overcounting. Result = 0 overcount. */ + } + /* Now count how many we're not adding */ + for (i = idx1; i < countidx2; i++) + notadded += data[i].seq2+1 - data[i].seq1; + /* Maybe the not added tally included some over-counting too */ + added -= (notadded - overcounted); + *r_count = added; + } + if (idx1 > 0 && data[idx1-1].seq2+1 == seq1) idx1--; @@ -149,6 +188,19 @@ } } +void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array, + uint32_t seq1, uint32_t seq2) +{ + seq_range_array_add_range_internal(array, seq1, seq2, NULL); +} +unsigned int seq_range_array_add_range_count(ARRAY_TYPE(seq_range) *array, + uint32_t seq1, uint32_t seq2) +{ + unsigned int count; + seq_range_array_add_range_internal(array, seq1, seq2, &count); + return count; +} + void seq_range_array_merge(ARRAY_TYPE(seq_range) *dest, const ARRAY_TYPE(seq_range) *src) { diff -r 3ef7f3d53d17 -r 230f3579c9b7 src/lib/seq-range-array.h --- a/src/lib/seq-range-array.h Wed Jan 21 01:42:01 2015 +0200 +++ b/src/lib/seq-range-array.h Wed Jan 21 01:44:31 2015 +0200 @@ -11,7 +11,13 @@ unsigned int prev_n, prev_idx; }; -/* Add sequrence to range. If the array isn't created yet, create it with +static inline uint32_t ATTR_PURE seq_range_length(struct seq_range *range) +{ + i_assert(range->seq2 >= range->seq1); + return range->seq2 - range->seq1 + 1; +} + +/* Add sequence to range. If the array isn't created yet, create it with initial size of init_count. */ bool ATTR_NOWARN_UNUSED_RESULT seq_range_array_add(ARRAY_TYPE(seq_range) *array, uint32_t seq); @@ -21,6 +27,8 @@ unsigned int init_count, uint32_t seq); void seq_range_array_add_range(ARRAY_TYPE(seq_range) *array, uint32_t seq1, uint32_t seq2); +unsigned int seq_range_array_add_range_count(ARRAY_TYPE(seq_range) *array, + uint32_t seq1, uint32_t seq2); void seq_range_array_merge(ARRAY_TYPE(seq_range) *dest, const ARRAY_TYPE(seq_range) *src); /* Remove the given sequrence from range. Returns TRUE if it was found. */ diff -r 3ef7f3d53d17 -r 230f3579c9b7 src/lib/test-seq-range-array.c --- a/src/lib/test-seq-range-array.c Wed Jan 21 01:42:01 2015 +0200 +++ b/src/lib/test-seq-range-array.c Wed Jan 21 01:44:31 2015 +0200 @@ -82,8 +82,8 @@ static void test_seq_range_array_random(void) { -#define SEQ_RANGE_TEST_BUFSIZE 20 -#define SEQ_RANGE_TEST_COUNT 10000 +#define SEQ_RANGE_TEST_BUFSIZE 100 +#define SEQ_RANGE_TEST_COUNT 20000 unsigned char shadowbuf[SEQ_RANGE_TEST_BUFSIZE]; ARRAY_TYPE(seq_range) range; const struct seq_range *seqs; @@ -100,12 +100,18 @@ test = rand() % 4; switch (test) { case 0: - seq_range_array_add(&range, seq1); + ret = seq_range_array_add(&range, seq1) ? 0 : 1; /* FALSE == added */ + ret2 = shadowbuf[seq1] == 0 ? 1 : 0; shadowbuf[seq1] = 1; break; case 1: - seq_range_array_add_range(&range, seq1, seq2); - memset(shadowbuf + seq1, 1, seq2 - seq1 + 1); + ret = seq_range_array_add_range_count(&range, seq1, seq2); + for (ret2 = 0; seq1 <= seq2; seq1++) { + if (shadowbuf[seq1] == 0) { + ret2++; + shadowbuf[seq1] = 1; + } + } break; case 2: ret = seq_range_array_remove(&range, seq1) ? 1 : 0; From dovecot at dovecot.org Tue Jan 20 23:55:04 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:04 +0000 Subject: dovecot-2.2: plugins/fts: expung-log - add the concept of not un... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/2e756ad0ffcf changeset: 18191:2e756ad0ffcf user: Phil Carmody date: Wed Jan 21 01:46:13 2015 +0200 description: plugins/fts: expung-log - add the concept of not unlinking at the end No behavioural differences, the default is to unlink. Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diffs (39 lines): diff -r 230f3579c9b7 -r 2e756ad0ffcf src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:44:31 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:46:13 2015 +0200 @@ -61,6 +61,7 @@ bool failed; bool corrupted; + bool unlink; }; struct fts_expunge_log *fts_expunge_log_init(const char *path) @@ -348,6 +349,7 @@ ctx->failed = TRUE; else if (log->fd != -1) ctx->input = i_stream_create_fd(log->fd, (size_t)-1, FALSE); + ctx->unlink = TRUE; return ctx; } @@ -395,7 +397,8 @@ (void)i_stream_read_data(ctx->input, &data, &size, IO_BLOCK_SIZE); if (size == 0 && ctx->input->stream_errno == 0) { /* expected EOF - mark the file as read by unlinking it */ - if (unlink(ctx->log->path) < 0 && errno != ENOENT) + if (ctx->unlink && + unlink(ctx->log->path) < 0 && errno != ENOENT) i_error("unlink(%s) failed: %m", ctx->log->path); /* try reading again, in case something new was written */ @@ -462,7 +465,8 @@ *_ctx = NULL; if (ctx->corrupted) { - if (unlink(ctx->log->path) < 0 && errno != ENOENT) + if (ctx->unlink && + unlink(ctx->log->path) < 0 && errno != ENOENT) i_error("unlink(%s) failed: %m", ctx->log->path); } From dovecot at dovecot.org Tue Jan 20 23:55:04 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:04 +0000 Subject: dovecot-2.2: plugins/fts: expunge-log - permit append helpers to... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/5091f03d70e1 changeset: 18192:5091f03d70e1 user: Phil Carmody date: Wed Jan 21 01:47:25 2015 +0200 description: plugins/fts: expunge-log - permit append helpers to have no log to write to This is for creating an in-RAM, later queriable, structure which you do not want to be written to backing storage. As when you've finished with one, there's no concept of a "commit", provide an alternative "abort" way out. These are identical apart from the call to the write() routine, so refactor the two. Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 27 +++++++++++++-------------- src/plugins/fts/fts-expunge-log.h | 2 ++ 2 files changed, 15 insertions(+), 14 deletions(-) diffs (75 lines): diff -r 2e756ad0ffcf -r 5091f03d70e1 src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:46:13 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:47:25 2015 +0200 @@ -182,7 +182,7 @@ ctx->pool = pool; hash_table_create(&ctx->mailboxes, pool, 0, guid_128_hash, guid_128_cmp); - if (fts_expunge_log_reopen_if_needed(log, TRUE) < 0) + if (log != NULL && fts_expunge_log_reopen_if_needed(log, TRUE) < 0) ctx->failed = TRUE; return ctx; } @@ -266,6 +266,9 @@ uint32_t expunge_count, *e; int ret; + /* Unbacked expunge logs cannot be written, by definition */ + i_assert(log != NULL); + /* try to append to the latest file */ if (fts_expunge_log_reopen_if_needed(log, TRUE) < 0) return -1; @@ -311,31 +314,27 @@ return ret; } -int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **_ctx) +static int fts_expunge_log_append_finalise(struct fts_expunge_log_append_ctx **_ctx, + bool commit) { struct fts_expunge_log_append_ctx *ctx = *_ctx; int ret = ctx->failed ? -1 : 0; *_ctx = NULL; - if (ret == 0) + if (commit && ret == 0) ret = fts_expunge_log_write(ctx); hash_table_destroy(&ctx->mailboxes); pool_unref(&ctx->pool); return ret; } - -int fts_expunge_log_uid_count(struct fts_expunge_log *log, - unsigned int *expunges_r) +int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **_ctx) { - int ret; - - if ((ret = fts_expunge_log_reopen_if_needed(log, FALSE)) <= 0) { - *expunges_r = 0; - return ret; - } - - return fts_expunge_log_read_expunge_count(log, expunges_r); + return fts_expunge_log_append_finalise(_ctx, TRUE); +} +int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **_ctx) +{ + return fts_expunge_log_append_finalise(_ctx, FALSE); } struct fts_expunge_log_read_ctx * diff -r 2e756ad0ffcf -r 5091f03d70e1 src/plugins/fts/fts-expunge-log.h --- a/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:46:13 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:47:25 2015 +0200 @@ -18,6 +18,8 @@ const guid_128_t mailbox_guid, uint32_t uid); int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **ctx); +/* Do not commit non-backed structures, abort them after use. */ +int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **ctx); int fts_expunge_log_uid_count(struct fts_expunge_log *log, unsigned int *expunges_r); From dovecot at dovecot.org Tue Jan 20 23:55:09 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:09 +0000 Subject: dovecot-2.2: plugins/fts: expunge-log - pull mailbox finding/cre... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/8b4693c01cce changeset: 18193:8b4693c01cce user: Phil Carmody date: Wed Jan 21 01:48:00 2015 +0200 description: plugins/fts: expunge-log - pull mailbox finding/creating into a helper There will be more clients than just this one. Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) diffs (32 lines): diff -r 5091f03d70e1 -r 8b4693c01cce src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:47:25 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:48:00 2015 +0200 @@ -203,9 +203,9 @@ return mailbox; } -void fts_expunge_log_append_next(struct fts_expunge_log_append_ctx *ctx, - const guid_128_t mailbox_guid, - uint32_t uid) +static struct fts_expunge_log_mailbox * +fts_expunge_log_append_mailbox(struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid) { const uint8_t *guid_p = mailbox_guid; struct fts_expunge_log_mailbox *mailbox; @@ -219,6 +219,15 @@ mailbox = fts_expunge_log_mailbox_alloc(ctx, mailbox_guid); ctx->prev_mailbox = mailbox; } + return mailbox; +} +void fts_expunge_log_append_next(struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid, + uint32_t uid) +{ + struct fts_expunge_log_mailbox *mailbox; + + mailbox = fts_expunge_log_append_mailbox(ctx, mailbox_guid); if (!seq_range_array_add(&mailbox->uids, uid)) mailbox->uids_count++; } From dovecot at dovecot.org Tue Jan 20 23:55:14 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:14 +0000 Subject: dovecot-2.2: plugins/fts: expunge-log - create flattened in-RAM ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e1b50803e5d4 changeset: 18194:e1b50803e5d4 user: Phil Carmody date: Wed Jan 21 01:51:46 2015 +0200 description: plugins/fts: expunge-log - create flattened in-RAM log with no backing storage Combine each record in a source expunge log. This source log does not get deleted afterwards. Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 49 +++++++++++++++++++++++++++++++++++++++ src/plugins/fts/fts-expunge-log.h | 9 +++++++ 2 files changed, 58 insertions(+), 0 deletions(-) diffs (87 lines): diff -r 8b4693c01cce -r e1b50803e5d4 src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:48:00 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:51:46 2015 +0200 @@ -231,6 +231,28 @@ if (!seq_range_array_add(&mailbox->uids, uid)) mailbox->uids_count++; } +void fts_expunge_log_append_range(struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid, + const struct seq_range *uids) +{ + struct fts_expunge_log_mailbox *mailbox; + + mailbox = fts_expunge_log_append_mailbox(ctx, mailbox_guid); + mailbox->uids_count += seq_range_array_add_range_count(&mailbox->uids, + uids->seq1, uids->seq2); + /* To be honest, an unbacked log doesn't need to maintain the uids_count, + but we don't know here if we're supporting an unbacked log or not, so we + have to maintain the value, just in case. + At the moment, the only caller of this function is for unbacked logs. */ +} +void fts_expunge_log_append_record(struct fts_expunge_log_append_ctx *ctx, + const struct fts_expunge_log_read_record *record) +{ + const struct seq_range *range; + /* FIXME: Optimise with a merge */ + array_foreach(&record->uids, range) + fts_expunge_log_append_range(ctx, record->mailbox_guid, range); +} static void fts_expunge_log_export(struct fts_expunge_log_append_ctx *ctx, @@ -483,3 +505,30 @@ i_free(ctx); return ret; } + +int fts_expunge_log_flatten(const char *path, + struct fts_expunge_log_append_ctx **flattened_r) +{ + struct fts_expunge_log *read; + struct fts_expunge_log_read_ctx *read_ctx; + const struct fts_expunge_log_read_record *record; + struct fts_expunge_log_append_ctx *append; + int ret; + + i_assert(path != NULL && flattened_r != NULL); + read = fts_expunge_log_init(path); + + read_ctx = fts_expunge_log_read_begin(read); + read_ctx->unlink = FALSE; + + append = fts_expunge_log_append_begin(NULL); + while((record = fts_expunge_log_read_next(read_ctx)) != NULL) { + fts_expunge_log_append_record(append, record); + } + + if ((ret = fts_expunge_log_read_end(&read_ctx)) > 0) + *flattened_r = append; + fts_expunge_log_deinit(&read); + + return ret; +} diff -r 8b4693c01cce -r e1b50803e5d4 src/plugins/fts/fts-expunge-log.h --- a/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:48:00 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:51:46 2015 +0200 @@ -17,6 +17,11 @@ void fts_expunge_log_append_next(struct fts_expunge_log_append_ctx *ctx, const guid_128_t mailbox_guid, uint32_t uid); +void fts_expunge_log_append_range(struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid, + const struct seq_range *uids); +void fts_expunge_log_append_record(struct fts_expunge_log_append_ctx *ctx, + const struct fts_expunge_log_read_record *record); int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **ctx); /* Do not commit non-backed structures, abort them after use. */ int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **ctx); @@ -32,4 +37,8 @@ If end() is called before reading all records, the log isn't unlinked. */ int fts_expunge_log_read_end(struct fts_expunge_log_read_ctx **ctx); +/* Read an entire log file, and flatten it into one hash of arrays. + The struct it returns cannot be written, as it has no backing store */ +int fts_expunge_log_flatten(const char *path, + struct fts_expunge_log_append_ctx **flattened_r); #endif From dovecot at dovecot.org Tue Jan 20 23:55:14 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:14 +0000 Subject: dovecot-2.2: plugins/fts: expunge-log - query function to lookup... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/91b00535e1f9 changeset: 18195:91b00535e1f9 user: Phil Carmody date: Wed Jan 21 01:52:59 2015 +0200 description: plugins/fts: expunge-log - query function to lookup GUID/UID Constant time hash lookup for GUID. Log time lookup in seq_range array. Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 11 +++++++++++ src/plugins/fts/fts-expunge-log.h | 3 +++ 2 files changed, 14 insertions(+), 0 deletions(-) diffs (29 lines): diff -r e1b50803e5d4 -r 91b00535e1f9 src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:51:46 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:52:59 2015 +0200 @@ -532,3 +532,14 @@ return ret; } +bool fts_expunge_log_contains(const struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid, uint32_t uid) +{ + const struct fts_expunge_log_mailbox *mailbox; + const uint8_t *guid_p = mailbox_guid; + + mailbox = hash_table_lookup(ctx->mailboxes, guid_p); + if (mailbox == NULL) + return FALSE; + return seq_range_exists(&mailbox->uids, uid); +} diff -r e1b50803e5d4 -r 91b00535e1f9 src/plugins/fts/fts-expunge-log.h --- a/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:51:46 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.h Wed Jan 21 01:52:59 2015 +0200 @@ -41,4 +41,7 @@ The struct it returns cannot be written, as it has no backing store */ int fts_expunge_log_flatten(const char *path, struct fts_expunge_log_append_ctx **flattened_r); +bool fts_expunge_log_contains(const struct fts_expunge_log_append_ctx *ctx, + const guid_128_t mailbox_guid, uint32_t uid); + #endif From dovecot at dovecot.org Tue Jan 20 23:55:14 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 20 Jan 2015 23:55:14 +0000 Subject: dovecot-2.2: plugins/fts: use common guid_128 helpers Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/991a6b7a9385 changeset: 18196:991a6b7a9385 user: Phil Carmody date: Wed Jan 21 01:53:34 2015 +0200 description: plugins/fts: use common guid_128 helpers Signed-off-by: Phil Carmody diffstat: src/plugins/fts/fts-expunge-log.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (21 lines): diff -r 91b00535e1f9 -r 991a6b7a9385 src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:52:59 2015 +0200 +++ b/src/plugins/fts/fts-expunge-log.c Wed Jan 21 01:53:34 2015 +0200 @@ -195,7 +195,7 @@ struct fts_expunge_log_mailbox *mailbox; mailbox = p_new(ctx->pool, struct fts_expunge_log_mailbox, 1); - memcpy(mailbox->guid, mailbox_guid, sizeof(mailbox->guid)); + guid_128_copy(mailbox->guid, mailbox_guid); p_array_init(&mailbox->uids, ctx->pool, 16); guid_p = mailbox->guid; @@ -211,7 +211,7 @@ struct fts_expunge_log_mailbox *mailbox; if (ctx->prev_mailbox != NULL && - memcmp(mailbox_guid, ctx->prev_mailbox->guid, GUID_128_SIZE) == 0) + guid_128_equals(mailbox_guid, ctx->prev_mailbox->guid)) mailbox = ctx->prev_mailbox; else { mailbox = hash_table_lookup(ctx->mailboxes, guid_p); From dovecot at dovecot.org Wed Jan 21 00:22:54 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Wed, 21 Jan 2015 00:22:54 +0000 Subject: dovecot-2.2: sdbox: Fixed assert-crash when copying mails due to... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/e30e9b2b0e37 changeset: 18197:e30e9b2b0e37 user: Timo Sirainen date: Wed Jan 21 02:21:35 2015 +0200 description: sdbox: Fixed assert-crash when copying mails due to earlier change. diffstat: src/lib-storage/index/dbox-single/sdbox-copy.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (11 lines): diff -r 991a6b7a9385 -r e30e9b2b0e37 src/lib-storage/index/dbox-single/sdbox-copy.c --- a/src/lib-storage/index/dbox-single/sdbox-copy.c Wed Jan 21 01:53:34 2015 +0200 +++ b/src/lib-storage/index/dbox-single/sdbox-copy.c Wed Jan 21 02:21:35 2015 +0200 @@ -135,6 +135,7 @@ dbox_file_unref(&dest_file); return ret; } + ((struct sdbox_file *)dest_file)->written_to_disk = TRUE; dbox_save_add_to_index(ctx); index_copy_cache_fields(_ctx, mail, ctx->seq); From dovecot at dovecot.org Fri Jan 23 23:55:38 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 23 Jan 2015 23:55:38 +0000 Subject: dovecot-2.2: imapc: With gmail-labels-keyword feature add the $G... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/f2fac7c857f2 changeset: 18198:f2fac7c857f2 user: Timo Sirainen date: Fri Jan 23 23:18:01 2015 +0200 description: imapc: With gmail-labels-keyword feature add the $GMailHaveLabels only to \All mailbox This is primarily intended for migration, and with this behavior dsync can be run just once so it's faster. diffstat: src/lib-storage/index/imapc/imapc-sync.c | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diffs (21 lines): diff -r e30e9b2b0e37 -r f2fac7c857f2 src/lib-storage/index/imapc/imapc-sync.c --- a/src/lib-storage/index/imapc/imapc-sync.c Wed Jan 21 02:21:35 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-sync.c Fri Jan 23 23:18:01 2015 +0200 @@ -281,8 +281,15 @@ string_t *cmd = t_str_new(64); str_printfa(cmd, "UID FETCH %u:* (FLAGS", first_uid); - if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) - str_append(cmd, " X-GM-LABELS"); + if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) { + /* do this only for the \All mailbox */ + enum mailbox_info_flags flags; + + if (imapc_list_get_mailbox_flags(ctx->mbox->box.list, + ctx->mbox->box.name, &flags) == 0 && + (flags & MAILBOX_SPECIALUSE_ALL) != 0) + str_append(cmd, " X-GM-LABELS"); + } str_append_c(cmd, ')'); imapc_sync_cmd(ctx, str_c(cmd)); From dovecot at dovecot.org Fri Jan 23 23:55:39 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 23 Jan 2015 23:55:39 +0000 Subject: dovecot-2.2: imapc: Merged gmail-pop3 and gmail-labels-keyword f... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/111dcc2ca272 changeset: 18199:111dcc2ca272 user: Timo Sirainen date: Fri Jan 23 23:19:24 2015 +0200 description: imapc: Merged gmail-pop3 and gmail-labels-keyword features into a single gmail-migration feature There's really no other reason to use them except for migration. diffstat: src/lib-storage/index/imapc/imapc-mail.c | 2 +- src/lib-storage/index/imapc/imapc-mailbox.c | 2 +- src/lib-storage/index/imapc/imapc-settings.c | 3 +-- src/lib-storage/index/imapc/imapc-settings.h | 3 +-- src/lib-storage/index/imapc/imapc-sync.c | 4 ++-- 5 files changed, 6 insertions(+), 8 deletions(-) diffs (71 lines): diff -r f2fac7c857f2 -r 111dcc2ca272 src/lib-storage/index/imapc/imapc-mail.c --- a/src/lib-storage/index/imapc/imapc-mail.c Fri Jan 23 23:18:01 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mail.c Fri Jan 23 23:19:24 2015 +0200 @@ -476,7 +476,7 @@ *value_r = ""; return imapc_mail_get_guid(_mail, value_r); case MAIL_FETCH_UIDL_BACKEND: - if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_POP3)) + if (!IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_MIGRATION)) break; if (imapc_mail_get_guid(_mail, value_r) < 0) return -1; diff -r f2fac7c857f2 -r 111dcc2ca272 src/lib-storage/index/imapc/imapc-mailbox.c --- a/src/lib-storage/index/imapc/imapc-mailbox.c Fri Jan 23 23:18:01 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-mailbox.c Fri Jan 23 23:19:24 2015 +0200 @@ -295,7 +295,7 @@ } } } else if (strcasecmp(atom, "X-GM-LABELS") == 0 && - IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) { + IMAPC_BOX_HAS_FEATURE(mbox, IMAPC_FEATURE_GMAIL_MIGRATION)) { if (!imap_arg_get_list(&list[i+1], &flags_list)) return; if (flags_list[0].type != IMAP_ARG_EOL) diff -r f2fac7c857f2 -r 111dcc2ca272 src/lib-storage/index/imapc/imapc-settings.c --- a/src/lib-storage/index/imapc/imapc-settings.c Fri Jan 23 23:18:01 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.c Fri Jan 23 23:19:24 2015 +0200 @@ -84,8 +84,7 @@ { "rfc822.size", IMAPC_FEATURE_RFC822_SIZE }, { "guid-forced", IMAPC_FEATURE_GUID_FORCED }, { "fetch-headers", IMAPC_FEATURE_FETCH_HEADERS }, - { "gmail-labels-keyword", IMAPC_FEATURE_GMAIL_LABELS_KEYWORD }, - { "gmail-pop3", IMAPC_FEATURE_GMAIL_POP3 }, + { "gmail-migration", IMAPC_FEATURE_GMAIL_MIGRATION }, { NULL, 0 } }; diff -r f2fac7c857f2 -r 111dcc2ca272 src/lib-storage/index/imapc/imapc-settings.h --- a/src/lib-storage/index/imapc/imapc-settings.h Fri Jan 23 23:18:01 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-settings.h Fri Jan 23 23:19:24 2015 +0200 @@ -6,8 +6,7 @@ IMAPC_FEATURE_RFC822_SIZE = 0x01, IMAPC_FEATURE_GUID_FORCED = 0x02, IMAPC_FEATURE_FETCH_HEADERS = 0x04, - IMAPC_FEATURE_GMAIL_LABELS_KEYWORD = 0x08, - IMAPC_FEATURE_GMAIL_POP3 = 0x10 + IMAPC_FEATURE_GMAIL_MIGRATION = 0x08 }; /* */ diff -r f2fac7c857f2 -r 111dcc2ca272 src/lib-storage/index/imapc/imapc-sync.c --- a/src/lib-storage/index/imapc/imapc-sync.c Fri Jan 23 23:18:01 2015 +0200 +++ b/src/lib-storage/index/imapc/imapc-sync.c Fri Jan 23 23:19:24 2015 +0200 @@ -281,7 +281,7 @@ string_t *cmd = t_str_new(64); str_printfa(cmd, "UID FETCH %u:* (FLAGS", first_uid); - if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_LABELS_KEYWORD)) { + if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_MIGRATION)) { /* do this only for the \All mailbox */ enum mailbox_info_flags flags; @@ -293,7 +293,7 @@ str_append_c(cmd, ')'); imapc_sync_cmd(ctx, str_c(cmd)); - if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_POP3) && + if (IMAPC_BOX_HAS_FEATURE(ctx->mbox, IMAPC_FEATURE_GMAIL_MIGRATION) && ctx->mbox->storage->set->pop3_deleted_flag[0] != '\0') { struct imapc_command *cmd; From dovecot at dovecot.org Sat Jan 24 00:18:06 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sat, 24 Jan 2015 00:18:06 +0000 Subject: dovecot-2.2: lib: array - helper to swap array buffer ownership Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/7557234ac0f4 changeset: 18200:7557234ac0f4 user: Phil Carmody date: Sat Jan 24 02:15:45 2015 +0200 description: lib: array - helper to swap array buffer ownership Currently there's no simple way to create a replacement for an array, and then atomically switch in that replacement. With this helper, you can just exchange ownership of the two lists and then free the new list (which now contains the old buffer). Signed-off-by: Phil Carmody diffstat: src/lib/array.h | 16 ++++++++++++++++ src/lib/test-array.c | 23 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 0 deletions(-) diffs (66 lines): diff -r 111dcc2ca272 -r 7557234ac0f4 src/lib/array.h --- a/src/lib/array.h Fri Jan 23 23:19:24 2015 +0200 +++ b/src/lib/array.h Sat Jan 24 02:15:45 2015 +0200 @@ -271,6 +271,22 @@ count * dest->element_size); } +/* Exchange ownership of two arrays, which should have been allocated + from the same pool/context. Useful for updating an array with a + replacement. */ +static inline void +array_swap_i(struct array *array1, struct array *array2) +{ + buffer_t *buffer = array1->buffer; + + i_assert(array1->element_size == array2->element_size); + array1->buffer = array2->buffer; + array2->buffer = buffer; +} +#define array_swap(array1, array2) \ + array_swap_i(&(array1)->arr + ARRAY_TYPES_CHECK(array1, array2), \ + &(array2)->arr) + bool array_cmp_i(const struct array *array1, const struct array *array2) ATTR_PURE; #define array_cmp(array1, array2) \ diff -r 111dcc2ca272 -r 7557234ac0f4 src/lib/test-array.c --- a/src/lib/test-array.c Fri Jan 23 23:19:24 2015 +0200 +++ b/src/lib/test-array.c Sat Jan 24 02:15:45 2015 +0200 @@ -32,6 +32,28 @@ test_end(); } +static void test_array_swap(void) +{ + ARRAY(struct foo) foos[3]; + struct foo nfoo; + int i, j; + + test_begin("array swap"); + for (i = 1; i <= 3; i++) { + t_array_init(&foos[i-1], i); + for (j = 1; j <= 2*i+1; j++) { + nfoo.a = nfoo.b = nfoo.c = j; + array_append(&foos[i-1], &nfoo, 1); + } + } + for (i = 0; i < 1000; i++) + array_swap(&foos[rand()%3], &foos[rand()%3]); + /* Just want size 3, 5, and 7 in any order */ + test_assert(array_count(&foos[0]) * array_count(&foos[1]) * array_count(&foos[2]) == 3*5*7); + test_assert(array_count(&foos[0]) + array_count(&foos[1]) + array_count(&foos[2]) == 3+5+7); + test_end(); +} + static int test_int_compare(const int *key, const int *elem) { return (*key < *elem) ? -1 : @@ -192,6 +214,7 @@ test_array_reverse(); test_array_cmp(); test_array_cmp_str(); + test_array_swap(); } enum fatal_test_state fatal_array(int stage) From dovecot at dovecot.org Sun Jan 25 18:38:53 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Sun, 25 Jan 2015 18:38:53 +0000 Subject: dovecot-2.2: lib-mail: Test program wasn't linked with libiconv,... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/0f337ba2bc08 changeset: 18201:0f337ba2bc08 user: Timo Sirainen date: Sun Jan 25 10:37:35 2015 -0800 description: lib-mail: Test program wasn't linked with libiconv, causing linking failures. diffstat: src/lib-mail/Makefile.am | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 7557234ac0f4 -r 0f337ba2bc08 src/lib-mail/Makefile.am --- a/src/lib-mail/Makefile.am Sat Jan 24 02:15:45 2015 +0200 +++ b/src/lib-mail/Makefile.am Sun Jan 25 10:37:35 2015 -0800 @@ -142,7 +142,7 @@ test_message_date_DEPENDENCIES = $(test_deps) test_message_decoder_SOURCES = test-message-decoder.c -test_message_decoder_LDADD = message-decoder.lo quoted-printable.lo rfc822-parser.lo rfc2231-parser.lo ../lib-charset/libcharset.la $(test_libs) +test_message_decoder_LDADD = message-decoder.lo quoted-printable.lo rfc822-parser.lo rfc2231-parser.lo ../lib-charset/libcharset.la $(test_libs) $(LIBICONV) test_message_decoder_DEPENDENCIES = ../lib-charset/libcharset.la $(test_deps) test_message_header_decode_SOURCES = test-message-header-decode.c From dovecot at dovecot.org Tue Jan 27 00:08:37 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 27 Jan 2015 00:08:37 +0000 Subject: dovecot-2.2: fts: Added back fts_expunge_log_uid_count() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/eaa37c259891 changeset: 18202:eaa37c259891 user: Timo Sirainen date: Tue Jan 27 02:07:10 2015 +0200 description: fts: Added back fts_expunge_log_uid_count() This was accidentally removed by commit 5091f03d70e1 diffstat: src/plugins/fts/fts-expunge-log.c | 15 +++++++++++++++ 1 files changed, 15 insertions(+), 0 deletions(-) diffs (29 lines): diff -r 0f337ba2bc08 -r eaa37c259891 src/plugins/fts/fts-expunge-log.c --- a/src/plugins/fts/fts-expunge-log.c Sun Jan 25 10:37:35 2015 -0800 +++ b/src/plugins/fts/fts-expunge-log.c Tue Jan 27 02:07:10 2015 +0200 @@ -359,10 +359,25 @@ pool_unref(&ctx->pool); return ret; } + +int fts_expunge_log_uid_count(struct fts_expunge_log *log, + unsigned int *expunges_r) +{ + int ret; + + if ((ret = fts_expunge_log_reopen_if_needed(log, FALSE)) <= 0) { + *expunges_r = 0; + return ret; + } + + return fts_expunge_log_read_expunge_count(log, expunges_r); +} + int fts_expunge_log_append_commit(struct fts_expunge_log_append_ctx **_ctx) { return fts_expunge_log_append_finalise(_ctx, TRUE); } + int fts_expunge_log_append_abort(struct fts_expunge_log_append_ctx **_ctx) { return fts_expunge_log_append_finalise(_ctx, FALSE); From dovecot at dovecot.org Tue Jan 27 00:20:25 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Tue, 27 Jan 2015 00:20:25 +0000 Subject: dovecot-2.2: fts: When indexing address headers, don't add MISSI... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/93851d1ca12d changeset: 18203:93851d1ca12d user: Timo Sirainen date: Tue Jan 27 02:19:01 2015 +0200 description: fts: When indexing address headers, don't add MISSING_MAILBOX or MISSING_DOMAIN. diffstat: src/plugins/fts/fts-build-mail.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r eaa37c259891 -r 93851d1ca12d src/plugins/fts/fts-build-mail.c --- a/src/plugins/fts/fts-build-mail.c Tue Jan 27 02:07:10 2015 +0200 +++ b/src/plugins/fts/fts-build-mail.c Tue Jan 27 02:19:01 2015 +0200 @@ -129,7 +129,7 @@ addr = message_address_parse(pool_datastack_create(), hdr->full_value, hdr->full_value_len, - UINT_MAX, TRUE); + UINT_MAX, FALSE); str = t_str_new(hdr->full_value_len); message_address_write(str, addr); From dovecot at dovecot.org Thu Jan 29 16:44:39 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Thu, 29 Jan 2015 16:44:39 +0000 Subject: dovecot-2.2: lib-ssl-iostream: Don't set EPIPE/ECONNRESET error ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/1d1a310bb488 changeset: 18204:1d1a310bb488 user: Timo Sirainen date: Thu Jan 29 18:43:15 2015 +0200 description: lib-ssl-iostream: Don't set EPIPE/ECONNRESET error to istream when connection is closed. Several istream users verify at EOF that stream_errno=0 and fail if it isn't. diffstat: src/lib-ssl-iostream/iostream-openssl.c | 16 +++++++++------- src/lib-ssl-iostream/istream-openssl.c | 3 ++- 2 files changed, 11 insertions(+), 8 deletions(-) diffs (53 lines): diff -r 93851d1ca12d -r 1d1a310bb488 src/lib-ssl-iostream/iostream-openssl.c --- a/src/lib-ssl-iostream/iostream-openssl.c Tue Jan 27 02:19:01 2015 +0200 +++ b/src/lib-ssl-iostream/iostream-openssl.c Thu Jan 29 18:43:15 2015 +0200 @@ -387,11 +387,13 @@ ret = openssl_iostream_read_more(ssl_io, &data, &size); ssl_io->plain_input->real_stream->try_alloc_limit = 0; if (ret == -1 && size == 0 && !bytes_read) { - i_free(ssl_io->plain_stream_errstr); - ssl_io->plain_stream_errstr = - i_strdup(i_stream_get_error(ssl_io->plain_input)); - ssl_io->plain_stream_errno = - ssl_io->plain_input->stream_errno; + if (ssl_io->plain_input->stream_errno != 0) { + i_free(ssl_io->plain_stream_errstr); + ssl_io->plain_stream_errstr = + i_strdup(i_stream_get_error(ssl_io->plain_input)); + ssl_io->plain_stream_errno = + ssl_io->plain_input->stream_errno; + } ssl_io->closed = TRUE; return FALSE; } @@ -504,7 +506,7 @@ errstr = strerror(errno); } else { /* EOF. */ - errno = ECONNRESET; + errno = EPIPE; errstr = "Disconnected"; break; } @@ -513,7 +515,7 @@ break; case SSL_ERROR_ZERO_RETURN: /* clean connection closing */ - errno = ECONNRESET; + errno = EPIPE; i_free_and_null(ssl_io->last_error); return -1; case SSL_ERROR_SSL: diff -r 93851d1ca12d -r 1d1a310bb488 src/lib-ssl-iostream/istream-openssl.c --- a/src/lib-ssl-iostream/istream-openssl.c Tue Jan 27 02:19:01 2015 +0200 +++ b/src/lib-ssl-iostream/istream-openssl.c Thu Jan 29 18:43:15 2015 +0200 @@ -78,7 +78,8 @@ io_stream_set_error(&stream->iostream, "%s", ssl_io->last_error); } - stream->istream.stream_errno = errno; + if (errno != EPIPE) + stream->istream.stream_errno = errno; stream->istream.eof = TRUE; sstream->seen_eof = TRUE; return -1; From dovecot at dovecot.org Fri Jan 30 01:14:07 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 01:14:07 +0000 Subject: dovecot-2.2: replicator: Remember last successful sync and show ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/58466077dff9 changeset: 18205:58466077dff9 user: Timo Sirainen date: Fri Jan 30 03:12:37 2015 +0200 description: replicator: Remember last successful sync and show it in "doveadm replicator status" Patch by Matthew Via / Rackspace diffstat: src/doveadm/doveadm-replicator.c | 7 +++++-- src/replication/replicator/doveadm-connection.c | 5 +++-- src/replication/replicator/replicator-brain.c | 2 ++ src/replication/replicator/replicator-queue.c | 16 +++++++++++++--- src/replication/replicator/replicator-queue.h | 2 +- 5 files changed, 24 insertions(+), 8 deletions(-) diffs (126 lines): diff -r 1d1a310bb488 -r 58466077dff9 src/doveadm/doveadm-replicator.c --- a/src/doveadm/doveadm-replicator.c Thu Jan 29 18:43:15 2015 +0200 +++ b/src/doveadm/doveadm-replicator.c Fri Jan 30 03:12:37 2015 +0200 @@ -141,7 +141,7 @@ { struct replicator_context *ctx; const char *line, *const *args; - time_t last_fast, last_full; + time_t last_fast, last_full, last_success; ctx = cmd_replicator_init(&argc, &argv, "a:", cmd_replicator_status); @@ -156,6 +156,7 @@ doveadm_print_header_simple("priority"); doveadm_print_header_simple("fast sync"); doveadm_print_header_simple("full sync"); + doveadm_print_header_simple("success sync"); doveadm_print_header_simple("failed"); replicator_send(ctx, t_strdup_printf("STATUS\t%s\n", @@ -167,11 +168,13 @@ args = t_strsplit_tab(line); if (str_array_length(args) >= 5 && str_to_time(args[2], &last_fast) == 0 && - str_to_time(args[3], &last_full) == 0) { + str_to_time(args[3], &last_full) == 0 && + str_to_time(args[5], &last_success) == 0) { doveadm_print(args[0]); doveadm_print(args[1]); doveadm_print(time_ago(last_fast)); doveadm_print(time_ago(last_full)); + doveadm_print(time_ago(last_success)); doveadm_print(args[4][0] == '0' ? "-" : "y"); } } T_END; diff -r 1d1a310bb488 -r 58466077dff9 src/replication/replicator/doveadm-connection.c --- a/src/replication/replicator/doveadm-connection.c Thu Jan 29 18:43:15 2015 +0200 +++ b/src/replication/replicator/doveadm-connection.c Fri Jan 30 03:12:37 2015 +0200 @@ -98,10 +98,11 @@ str_append_tabescaped(str, user->username); str_append_c(str, '\t'); str_append(str, replicator_priority_to_str(user->priority)); - str_printfa(str, "\t%lld\t%lld\t%d\n", + str_printfa(str, "\t%lld\t%lld\t%d\t%lld\n", (long long)user->last_fast_sync, (long long)user->last_full_sync, - user->last_sync_failed); + user->last_sync_failed, + (long long)user->last_successful_sync); o_stream_send(client->conn.output, str_data(str), str_len(str)); } replicator_queue_iter_deinit(&iter); diff -r 1d1a310bb488 -r 58466077dff9 src/replication/replicator/replicator-brain.c --- a/src/replication/replicator/replicator-brain.c Thu Jan 29 18:43:15 2015 +0200 +++ b/src/replication/replicator/replicator-brain.c Fri Jan 30 03:12:37 2015 +0200 @@ -116,6 +116,8 @@ i_free(ctx->user->state); ctx->user->state = i_strdup_empty(state); ctx->user->last_sync_failed = reply != DSYNC_REPLY_OK; + if (reply == DSYNC_REPLY_OK) + ctx->user->last_successful_sync = ioloop_time; replicator_queue_push(ctx->brain->queue, ctx->user); } if (!ctx->brain->deinitializing) diff -r 1d1a310bb488 -r 58466077dff9 src/replication/replicator/replicator-queue.c --- a/src/replication/replicator/replicator-queue.c Thu Jan 29 18:43:15 2015 +0200 +++ b/src/replication/replicator/replicator-queue.c Fri Jan 30 03:12:37 2015 +0200 @@ -305,7 +305,7 @@ struct replicator_user *user, tmp_user; /* - */ + */ args = t_strsplit_tabescaped(line); if (str_array_length(args) < 7) return -1; @@ -322,6 +322,14 @@ tmp_user.priority = priority; tmp_user.last_sync_failed = args[5][0] != '0'; + if (str_array_length(args) >= 8) { + if (str_to_time(args[7], &tmp_user.last_successful_sync) < 0) + return -1; + } else { + tmp_user.last_successful_sync = 0; + /* On-disk format didn't have this yet */ + } + user = hash_table_lookup(queue->user_hash, username); if (user != NULL) { if (user->last_update > tmp_user.last_update) { @@ -340,6 +348,7 @@ user->last_update = tmp_user.last_update; user->last_fast_sync = tmp_user.last_fast_sync; user->last_full_sync = tmp_user.last_full_sync; + user->last_successful_sync = tmp_user.last_successful_sync; user->last_sync_failed = tmp_user.last_sync_failed; i_free(user->state); user->state = i_strdup(state); @@ -383,11 +392,12 @@ replicator_queue_export_user(struct replicator_user *user, string_t *str) { str_append_tabescaped(str, user->username); - str_printfa(str, "\t%d\t%lld\t%lld\t%lld\t%d\t", (int)user->priority, + str_printfa(str, "\t%d\t%lld\t%lld\t%lld\t%d\t%lld\t", (int)user->priority, (long long)user->last_update, (long long)user->last_fast_sync, (long long)user->last_full_sync, - user->last_sync_failed); + user->last_sync_failed, + (long long)user->last_successful_sync); if (user->state != NULL) str_append_tabescaped(str, user->state); str_append_c(str, '\n'); diff -r 1d1a310bb488 -r 58466077dff9 src/replication/replicator/replicator-queue.h --- a/src/replication/replicator/replicator-queue.h Thu Jan 29 18:43:15 2015 +0200 +++ b/src/replication/replicator/replicator-queue.h Fri Jan 30 03:12:37 2015 +0200 @@ -13,7 +13,7 @@ /* last time this user's state was updated */ time_t last_update; /* last_fast_sync is always >= last_full_sync. */ - time_t last_fast_sync, last_full_sync; + time_t last_fast_sync, last_full_sync, last_successful_sync; enum replication_priority priority; /* User isn't currently in replication queue */ From dovecot at dovecot.org Fri Jan 30 09:54:57 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 09:54:57 +0000 Subject: dovecot-2.2: lib: Various fixes to str_sanitize*() Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ee12ce691bd3 changeset: 18206:ee12ce691bd3 user: Timo Sirainen date: Fri Jan 30 11:52:33 2015 +0200 description: lib: Various fixes to str_sanitize*() - UTF-8 sequences could have been truncated to become partial sequences - Truncation may not have happened at all to text containing UTF-8 - str_sanitize_append() might have truncated string beyond what we were appending, although that happened only if max_len was very small diffstat: src/lib/str-sanitize.c | 43 +++++++++++++++++++++++++++++++++++-------- src/lib/test-str-sanitize.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 10 deletions(-) diffs (143 lines): diff -r 58466077dff9 -r ee12ce691bd3 src/lib/str-sanitize.c --- a/src/lib/str-sanitize.c Fri Jan 30 03:12:37 2015 +0200 +++ b/src/lib/str-sanitize.c Fri Jan 30 11:52:33 2015 +0200 @@ -11,26 +11,49 @@ unichar_t chr; size_t i; - for (i = 0; i < max_len; ) { + for (i = 0; src[i] != '\0'; ) { len = uni_utf8_char_bytes(src[i]); - if (uni_utf8_get_char(src+i, &chr) <= 0) + if (i + len > max_len || uni_utf8_get_char(src+i, &chr) <= 0) break; if ((unsigned char)src[i] < 32) break; i += len; } + i_assert(i <= max_len); return i; } +static void str_sanitize_truncate_char(string_t *dest, unsigned int initial_pos) +{ + const unsigned char *data = str_data(dest); + unsigned int len = str_len(dest); + + if (len == initial_pos) + return; + if ((data[len-1] & 0x80) == 0) { + str_truncate(dest, len-1); + return; + } + /* truncate UTF-8 sequence. */ + while (len > 0 && (data[len-1] & 0xc0) == 0x80) + len--; + if (len > 0 && (data[len-1] & 0xc0) == 0xc0) + len--; + if (len >= initial_pos) + str_truncate(dest, len); +} + void str_sanitize_append(string_t *dest, const char *src, size_t max_len) { - unsigned int len; + unsigned int len, initial_pos = str_len(dest); unichar_t chr; size_t i; int ret; - for (i = 0; i < max_len && src[i] != '\0'; ) { + for (i = 0; src[i] != '\0'; ) { len = uni_utf8_char_bytes(src[i]); + if (i + len > max_len) + break; ret = uni_utf8_get_char(src+i, &chr); if (ret <= 0) { /* invalid UTF-8 */ @@ -45,12 +68,17 @@ if ((unsigned char)src[i] < 32) str_append_c(dest, '?'); else - str_append_c(dest, src[i]); + str_append_n(dest, src+i, len); i += len; } if (src[i] != '\0') { - str_truncate(dest, str_len(dest) <= 3 ? 0 : str_len(dest)-3); + if (max_len < 3) + str_truncate(dest, initial_pos); + else { + while (str_len(dest) - initial_pos > max_len-3) + str_sanitize_truncate_char(dest, initial_pos); + } str_append(dest, "..."); } } @@ -68,7 +96,6 @@ return src; str = t_str_new(I_MIN(max_len, 256)); - str_append_n(str, src, i); - str_sanitize_append(str, src + i, max_len - i); + str_sanitize_append(str, src, max_len); return str_c(str); } diff -r 58466077dff9 -r ee12ce691bd3 src/lib/test-str-sanitize.c --- a/src/lib/test-str-sanitize.c Fri Jan 30 03:12:37 2015 +0200 +++ b/src/lib/test-str-sanitize.c Fri Jan 30 11:52:33 2015 +0200 @@ -1,6 +1,7 @@ /* Copyright (c) 2007-2015 Dovecot authors, see the included COPYING file */ #include "test-lib.h" +#include "str.h" #include "str-sanitize.h" struct str_sanitize_test { @@ -19,11 +20,21 @@ { "abc", 2, "..." }, { "abcd", 3, "..." }, { "abcde", 4, "a..." }, - { "?", 10, NULL }, - { "?", 1, NULL }, + { "\xD1\x81", 1, "..." }, + { "\xD1\x81", 2, "\xD1\x81" }, + { "\xD1\x81", 3, NULL }, + { "\xC3\xA4\xC3\xA4zyxa", 1, "..." }, + { "\xC3\xA4\xC3\xA4zyxa", 2, "..." }, + { "\xC3\xA4\xC3\xA4zyxa", 3, "..." }, + { "\xC3\xA4\xC3\xA4zyxa", 4, "..." }, + { "\xC3\xA4\xC3\xA4zyxa", 5, "\xC3\xA4..." }, + { "\xC3\xA4\xC3\xA4zyxa", 6, "\xC3\xA4..." }, + { "\xC3\xA4\xC3\xA4zyxa", 7, "\xC3\xA4\xC3\xA4..." }, + { "\xC3\xA4\xC3\xA4zyxa", 8, "\xC3\xA4\xC3\xA4zyxa" }, { "\001x\x1fy\x81", 10, "?x?y?" } }; const char *str; + string_t *str2; unsigned int i; test_begin("str_sanitize"); @@ -35,4 +46,21 @@ test_assert_idx(str == tests[i].str, i); } test_end(); + + test_begin("str_sanitize_append"); + str2 = t_str_new(128); + for (i = 0; i < N_ELEMENTS(tests); i++) { + if (tests[i].str == NULL) + continue; + str_truncate(str2, 0); + str_append(str2, "1234567890"); + str_sanitize_append(str2, tests[i].str, tests[i].max_len); + + test_assert_idx(strncmp(str_c(str2), "1234567890", 10) == 0, i); + if (tests[i].sanitized != NULL) + test_assert_idx(strcmp(str_c(str2)+10, tests[i].sanitized) == 0, i); + else + test_assert_idx(strcmp(str_c(str2)+10, tests[i].str) == 0, i); + } + test_end(); } From dovecot at dovecot.org Fri Jan 30 09:54:57 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 09:54:57 +0000 Subject: dovecot-2.2: lib: str_sanitize*() max_len parameter renamed to m... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/081c7da83d8f changeset: 18207:081c7da83d8f user: Timo Sirainen date: Fri Jan 30 11:53:12 2015 +0200 description: lib: str_sanitize*() max_len parameter renamed to max_bytes to describe it more accurately. diffstat: src/lib/str-sanitize.c | 22 +++++++++++----------- src/lib/str-sanitize.h | 8 +++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diffs (101 lines): diff -r ee12ce691bd3 -r 081c7da83d8f src/lib/str-sanitize.c --- a/src/lib/str-sanitize.c Fri Jan 30 11:52:33 2015 +0200 +++ b/src/lib/str-sanitize.c Fri Jan 30 11:53:12 2015 +0200 @@ -5,7 +5,7 @@ #include "str.h" #include "str-sanitize.h" -static size_t str_sanitize_skip_start(const char *src, size_t max_len) +static size_t str_sanitize_skip_start(const char *src, size_t max_bytes) { unsigned int len; unichar_t chr; @@ -13,13 +13,13 @@ for (i = 0; src[i] != '\0'; ) { len = uni_utf8_char_bytes(src[i]); - if (i + len > max_len || uni_utf8_get_char(src+i, &chr) <= 0) + if (i + len > max_bytes || uni_utf8_get_char(src+i, &chr) <= 0) break; if ((unsigned char)src[i] < 32) break; i += len; } - i_assert(i <= max_len); + i_assert(i <= max_bytes); return i; } @@ -43,7 +43,7 @@ str_truncate(dest, len); } -void str_sanitize_append(string_t *dest, const char *src, size_t max_len) +void str_sanitize_append(string_t *dest, const char *src, size_t max_bytes) { unsigned int len, initial_pos = str_len(dest); unichar_t chr; @@ -52,7 +52,7 @@ for (i = 0; src[i] != '\0'; ) { len = uni_utf8_char_bytes(src[i]); - if (i + len > max_len) + if (i + len > max_bytes) break; ret = uni_utf8_get_char(src+i, &chr); if (ret <= 0) { @@ -73,17 +73,17 @@ } if (src[i] != '\0') { - if (max_len < 3) + if (max_bytes < 3) str_truncate(dest, initial_pos); else { - while (str_len(dest) - initial_pos > max_len-3) + while (str_len(dest) - initial_pos > max_bytes-3) str_sanitize_truncate_char(dest, initial_pos); } str_append(dest, "..."); } } -const char *str_sanitize(const char *src, size_t max_len) +const char *str_sanitize(const char *src, size_t max_bytes) { string_t *str; size_t i; @@ -91,11 +91,11 @@ if (src == NULL) return NULL; - i = str_sanitize_skip_start(src, max_len); + i = str_sanitize_skip_start(src, max_bytes); if (src[i] == '\0') return src; - str = t_str_new(I_MIN(max_len, 256)); - str_sanitize_append(str, src, max_len); + str = t_str_new(I_MIN(max_bytes, 256)); + str_sanitize_append(str, src, max_bytes); return str_c(str); } diff -r ee12ce691bd3 -r 081c7da83d8f src/lib/str-sanitize.h --- a/src/lib/str-sanitize.h Fri Jan 30 11:52:33 2015 +0200 +++ b/src/lib/str-sanitize.h Fri Jan 30 11:53:12 2015 +0200 @@ -2,10 +2,12 @@ #define STR_SANITIZE_H /* All control characters in src will be appended as '?'. If src is longer - than max_len, it's truncated with "..." appended to the end. */ -void str_sanitize_append(string_t *dest, const char *src, size_t max_len); + than max_bytes, it's truncated with "..." appended to the end. Note that + src is treated as UTF-8 input, but max_bytes is in bytes instead of + UTF-8 characters. */ +void str_sanitize_append(string_t *dest, const char *src, size_t max_bytes); /* Return src sanitized. If there are no changes, src pointer is returned. If src is NULL, returns NULL. */ -const char *str_sanitize(const char *src, size_t max_len); +const char *str_sanitize(const char *src, size_t max_bytes); #endif From dovecot at dovecot.org Fri Jan 30 10:21:22 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 10:21:22 +0000 Subject: dovecot-2.2: imap: Dynamic capabilities weren't being added corr... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/2ef1371e0b77 changeset: 18208:2ef1371e0b77 user: Timo Sirainen date: Fri Jan 30 12:19:58 2015 +0200 description: imap: Dynamic capabilities weren't being added correctly when imap_capability setting was used. They were supposed to be added when '+' prefix was used in imap_capability and not added when it wasn't. But the behavior was exactly the opposite. diffstat: src/imap/imap-client.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diffs (17 lines): diff -r 081c7da83d8f -r 2ef1371e0b77 src/imap/imap-client.c --- a/src/imap/imap-client.c Fri Jan 30 11:53:12 2015 +0200 +++ b/src/imap/imap-client.c Fri Jan 30 12:19:58 2015 +0200 @@ -108,10 +108,10 @@ if (*set->imap_capability == '\0') str_append(client->capability_string, CAPABILITY_STRING); - else if (*set->imap_capability != '+') + else if (*set->imap_capability != '+') { + explicit_capability = TRUE; str_append(client->capability_string, set->imap_capability); - else { - explicit_capability = TRUE; + } else { str_append(client->capability_string, CAPABILITY_STRING); str_append_c(client->capability_string, ' '); str_append(client->capability_string, set->imap_capability + 1); From dovecot at dovecot.org Fri Jan 30 10:30:51 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 10:30:51 +0000 Subject: dovecot-2.2: imap: If GETMETADATA fails for some mailbox, don't ... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/6e3b90370ad4 changeset: 18209:6e3b90370ad4 user: Timo Sirainen date: Fri Jan 30 12:29:25 2015 +0200 description: imap: If GETMETADATA fails for some mailbox, don't send the error message mixed in the METADATA reply line. diffstat: src/imap/cmd-getmetadata.c | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diffs (59 lines): diff -r 2ef1371e0b77 -r 6e3b90370ad4 src/imap/cmd-getmetadata.c --- a/src/imap/cmd-getmetadata.c Fri Jan 30 12:19:58 2015 +0200 +++ b/src/imap/cmd-getmetadata.c Fri Jan 30 12:29:25 2015 +0200 @@ -27,6 +27,8 @@ struct imap_metadata_iter *iter; string_t *iter_entry_prefix; + string_t *delayed_errors; + unsigned int entry_idx; bool first_entry_sent; bool failed; @@ -158,8 +160,10 @@ error_string = imap_metadata_transaction_get_last_error( ctx->trans, &error); if (error != MAIL_ERROR_NOTFOUND && error != MAIL_ERROR_PERM) { - client_send_line(client, t_strconcat("* NO ", error_string, NULL)); + str_printfa(ctx->delayed_errors, "* NO %s\r\n", + error_string); ctx->failed = TRUE; + return; } } @@ -265,9 +269,9 @@ /* iteration finished, get to the next entry */ if (imap_metadata_iter_deinit(&ctx->iter) < 0) { enum mail_error error; - client_send_line(client, t_strconcat("* NO ", - imap_metadata_transaction_get_last_error(ctx->trans, &error), - NULL)); + + str_printfa(ctx->delayed_errors, "* NO %s\r\n", + imap_metadata_transaction_get_last_error(ctx->trans, &error)); ctx->failed = TRUE; } return -1; @@ -364,6 +368,13 @@ if (ctx->first_entry_sent) o_stream_nsend_str(cmd->client->output, ")\r\n"); + if (str_len(ctx->delayed_errors) > 0) { + o_stream_nsend(cmd->client->output, + str_data(ctx->delayed_errors), + str_len(ctx->delayed_errors)); + str_truncate(ctx->delayed_errors, 0); + } + cmd_getmetadata_iter_deinit(ctx); if (ctx->list_iter != NULL) return cmd_getmetadata_mailbox_iter_next(ctx); @@ -469,6 +480,7 @@ ctx->cmd = cmd; ctx->maxsize = (uint32_t)-1; ctx->cmd->context = ctx; + ctx->delayed_errors = str_new(cmd->pool, 128); if (imap_arg_get_list(&args[0], &options)) { if (!cmd_getmetadata_parse_options(ctx, options)) From dovecot at dovecot.org Fri Jan 30 23:12:20 2015 From: dovecot at dovecot.org (dovecot at dovecot.org) Date: Fri, 30 Jan 2015 23:12:20 +0000 Subject: dovecot-2.2: replicator: Previous "last successful sync" timesta... Message-ID: details: http://hg.dovecot.org/dovecot-2.2/rev/ad04a5e6a766 changeset: 18210:ad04a5e6a766 user: Timo Sirainen date: Sat Jan 31 01:10:56 2015 +0200 description: replicator: Previous "last successful sync" timestamp change wrote data wrong to replicator.db Patch by Matthew Via / Rackspace diffstat: src/replication/replicator/replicator-queue.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diffs (22 lines): diff -r 6e3b90370ad4 -r ad04a5e6a766 src/replication/replicator/replicator-queue.c --- a/src/replication/replicator/replicator-queue.c Fri Jan 30 12:29:25 2015 +0200 +++ b/src/replication/replicator/replicator-queue.c Sat Jan 31 01:10:56 2015 +0200 @@ -392,15 +392,14 @@ replicator_queue_export_user(struct replicator_user *user, string_t *str) { str_append_tabescaped(str, user->username); - str_printfa(str, "\t%d\t%lld\t%lld\t%lld\t%d\t%lld\t", (int)user->priority, + str_printfa(str, "\t%d\t%lld\t%lld\t%lld\t%d\t", (int)user->priority, (long long)user->last_update, (long long)user->last_fast_sync, (long long)user->last_full_sync, - user->last_sync_failed, - (long long)user->last_successful_sync); + user->last_sync_failed); if (user->state != NULL) str_append_tabescaped(str, user->state); - str_append_c(str, '\n'); + str_printfa(str, "\t%lld\n", (long long)user->last_successful_sync); } int replicator_queue_export(struct replicator_queue *queue, const char *path)