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

3889 lines
133 KiB

# --- SDE-COPYRIGHT-NOTE-BEGIN ---
# This copyright note is auto-generated by ./scripts/Create-CopyPatch.
#
# Filename: package/.../dovecot/dovecot-2.2.1-0000-upstream-fixes.patch
# Copyright (C) 2013 The OpenSDE Project
#
# More information can be found in the files COPYING and README.
#
# This patch file is dual-licensed. It is available under the license the
# patched project is licensed under, as long as it is an OpenSource license
# as defined at http://www.opensource.org/ (e.g. BSD, X11) or under the terms
# of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
# --- SDE-COPYRIGHT-NOTE-END ---
From a69bfa0e486d70db4ee6e7553bd7235d9707ff58 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Fri, 19 Apr 2013 14:29:23 +0300
Subject: [PATCH] Compiling fix for Sun compilers. I wish gcc/clang warned
about these as well, as sometimes they indicate bugs.
diff --git a/src/imap-urlauth/imap-urlauth-worker.c b/src/imap-urlauth/imap-urlauth-worker.c
index ad02c81..6d94a8f 100644
--- a/src/imap-urlauth/imap-urlauth-worker.c
+++ b/src/imap-urlauth/imap-urlauth-worker.c
@@ -941,7 +941,7 @@ static void main_stdio_run(const char *access_user,
{
bool debug;
- debug = getenv("DEBUG");
+ debug = getenv("DEBUG") != NULL;
access_user = access_user != NULL ? access_user : getenv("USER");
if (access_user == NULL && IS_STANDALONE())
access_user = getlogin();
diff --git a/src/lib/ioloop.c b/src/lib/ioloop.c
index b89adcf..179507c 100644
--- a/src/lib/ioloop.c
+++ b/src/lib/ioloop.c
@@ -663,7 +663,7 @@ struct timeout *io_loop_move_timeout(struct timeout **_timeout)
bool io_loop_have_ios(struct ioloop *ioloop)
{
- return ioloop->io_files;
+ return ioloop->io_files != NULL;
}
bool io_loop_have_immediate_timeouts(struct ioloop *ioloop)
--
1.7.10.2
From d70baed80e47be3a7587901278dc74811f0a4873 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Sat, 20 Apr 2013 20:58:06 +0300
Subject: [PATCH] stats plugin: Fixed memory leak.
diff --git a/src/plugins/stats/stats-plugin.c b/src/plugins/stats/stats-plugin.c
index 27dae5b..ee4e9af 100644
--- a/src/plugins/stats/stats-plugin.c
+++ b/src/plugins/stats/stats-plugin.c
@@ -388,6 +388,7 @@ static void stats_transaction_free(struct stats_user *suser,
trans_stats_add(&suser->session_stats.trans_stats,
&strans->trans->stats);
+ i_free(strans);
}
static int
--
1.7.10.2
From ce10df9f5cc0dc658ece187606f403a814872696 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Sat, 20 Apr 2013 21:02:30 +0300
Subject: [PATCH] Fixed a memory leak.
diff --git a/src/lib-mail/istream-attachment-connector.c b/src/lib-mail/istream-attachment-connector.c
index 4fa6ebf..0cbedb2 100644
--- a/src/lib-mail/istream-attachment-connector.c
+++ b/src/lib-mail/istream-attachment-connector.c
@@ -88,6 +88,20 @@ int istream_attachment_connector_add(struct istream_attachment_connector *conn,
return 0;
}
+static void
+istream_attachment_connector_free(struct istream_attachment_connector *conn)
+{
+ struct istream *const *streamp, *stream;
+
+ array_foreach(&conn->streams, streamp) {
+ stream = *streamp;
+ if (stream != NULL)
+ i_stream_unref(&stream);
+ }
+ i_stream_unref(&conn->base_input);
+ pool_unref(&conn->pool);
+}
+
struct istream *
istream_attachment_connector_finish(struct istream_attachment_connector **_conn)
{
@@ -111,8 +125,7 @@ istream_attachment_connector_finish(struct istream_attachment_connector **_conn)
inputs = array_idx_modifiable(&conn->streams, 0);
input = i_stream_create_concat(inputs);
- i_stream_unref(&conn->base_input);
- pool_unref(&conn->pool);
+ istream_attachment_connector_free(conn);
return input;
}
@@ -122,6 +135,5 @@ void istream_attachment_connector_abort(struct istream_attachment_connector **_c
*_conn = NULL;
- i_stream_unref(&conn->base_input);
- pool_unref(&conn->pool);
+ istream_attachment_connector_free(conn);
}
--
1.7.10.2
From eada33e3bff7e25a7b952ebb08244aba86754e92 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Sat, 20 Apr 2013 21:57:47 +0300
Subject: [PATCH] lib-storage: Avoid wasting data stack during searches.
diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c
index 0077115..9278b6d 100644
--- a/src/lib-storage/index/index-search.c
+++ b/src/lib-storage/index/index-search.c
@@ -1377,7 +1377,9 @@ static int search_match_next(struct index_search_context *ctx)
}
for (i = 0; i < n && ret < 0; i++) {
ctx->cur_mail->lookup_abort = cache_lookups[i];
- ret = search_match_once(ctx);
+ T_BEGIN {
+ ret = search_match_once(ctx);
+ } T_END;
}
ctx->cur_mail->lookup_abort = MAIL_LOOKUP_ABORT_NEVER;
search_match_finish(ctx, ret);
@@ -1556,7 +1558,9 @@ static int search_more_with_prefetching(struct index_search_context *ctx,
int ret = 0;
while ((mail = index_search_get_mail(ctx)) != NULL) {
- ret = search_more_with_mail(ctx, mail);
+ T_BEGIN {
+ ret = search_more_with_mail(ctx, mail);
+ } T_END;
if (ret <= 0)
break;
@@ -1612,8 +1616,10 @@ static bool search_finish_prefetch(struct index_search_context *ctx,
mail_search_args_result_deserialize(ctx->mail_ctx.args,
imail->data.search_results->data,
imail->data.search_results->used);
- ret = search_match_once(ctx);
- search_match_finish(ctx, ret);
+ T_BEGIN {
+ ret = search_match_once(ctx);
+ search_match_finish(ctx, ret);
+ } T_END;
ctx->cur_mail = NULL;
return ret > 0;
}
--
1.7.10.2
From 7276e7875fca54d44fcccb7a371951ac9639d09b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 22 Apr 2013 18:45:04 +0300
Subject: [PATCH] zlib: Keep the last read mail cached uncompressed in a temp
file. This fixes performance problems with partial IMAP
FETCH commands.
diff --git a/src/plugins/zlib/zlib-plugin.c b/src/plugins/zlib/zlib-plugin.c
index d54ea54..5076702 100644
--- a/src/plugins/zlib/zlib-plugin.c
+++ b/src/plugins/zlib/zlib-plugin.c
@@ -3,7 +3,9 @@
#include "lib.h"
#include "array.h"
#include "istream.h"
+#include "istream-seekable.h"
#include "ostream.h"
+#include "str.h"
#include "mail-user.h"
#include "dbox-single/sdbox-storage.h"
#include "dbox-multi/mdbox-storage.h"
@@ -26,6 +28,7 @@
MODULE_CONTEXT(obj, zlib_user_module)
#define MAX_INBUF_SIZE (1024*1024)
+#define ZLIB_MAIL_CACHE_EXPIRE_MSECS (60*1000)
struct zlib_transaction_context {
union mailbox_transaction_module_context module_ctx;
@@ -33,9 +36,19 @@ struct zlib_transaction_context {
struct mail *tmp_mail;
};
+struct zlib_mail_cache {
+ struct timeout *to;
+ struct mailbox *box;
+ uint32_t uid;
+
+ struct istream *input;
+};
+
struct zlib_user {
union mail_user_module_context module_ctx;
+ struct zlib_mail_cache cache;
+
const struct compression_handler *save_handler;
unsigned int save_level;
};
@@ -48,9 +61,58 @@ static MODULE_CONTEXT_DEFINE_INIT(zlib_storage_module,
&mail_storage_module_register);
static MODULE_CONTEXT_DEFINE_INIT(zlib_mail_module, &mail_module_register);
+static void zlib_mail_cache_close(struct zlib_user *zuser)
+{
+ struct zlib_mail_cache *cache = &zuser->cache;
+
+ if (cache->to != NULL)
+ timeout_remove(&cache->to);
+ if (cache->input != NULL)
+ i_stream_unref(&cache->input);
+ memset(cache, 0, sizeof(*cache));
+}
+
+static struct istream *
+zlib_mail_cache_open(struct zlib_user *zuser, struct mail *mail,
+ struct istream *input)
+{
+ struct zlib_mail_cache *cache = &zuser->cache;
+ struct istream *inputs[2];
+ string_t *temp_prefix = t_str_new(128);
+
+ zlib_mail_cache_close(zuser);
+
+ /* zlib istream is seekable, but very slow. create a seekable istream
+ which we can use to quickly seek around in the stream that's been
+ read so far. usually the partial IMAP FETCHes continue from where
+ the previous left off, so this isn't strictly necessary, but with
+ the way lib-imap-storage's CRLF-cache works it has to seek backwards
+ somewhat, which causes a zlib stream reset. And the CRLF-cache isn't
+ easy to fix.. */
+ input->seekable = FALSE;
+ inputs[0] = input;
+ inputs[1] = NULL;
+ mail_user_set_get_temp_prefix(temp_prefix, mail->box->storage->user->set);
+ input = i_stream_create_seekable_path(inputs,
+ i_stream_get_max_buffer_size(inputs[0]),
+ str_c(temp_prefix));
+ i_stream_unref(&inputs[0]);
+
+ cache->to = timeout_add(ZLIB_MAIL_CACHE_EXPIRE_MSECS,
+ zlib_mail_cache_close, zuser);
+ cache->box = mail->box;
+ cache->uid = mail->uid;
+ cache->input = input;
+
+ /* index-mail wants the stream to be destroyed at close, so create
+ a new stream instead of just increasing reference. */
+ return i_stream_create_limit(cache->input, (uoff_t)-1);
+}
+
static int zlib_istream_opened(struct mail *_mail, struct istream **stream)
{
struct zlib_user *zuser = ZLIB_USER_CONTEXT(_mail->box->storage->user);
+ struct zlib_mail_cache *cache = &zuser->cache;
struct mail_private *mail = (struct mail_private *)_mail;
union mail_module_context *zmail = ZLIB_MAIL_CONTEXT(mail);
struct istream *input;
@@ -63,6 +125,15 @@ static int zlib_istream_opened(struct mail *_mail, struct istream **stream)
if (_mail->saving && zuser->save_handler == NULL)
return zmail->super.istream_opened(_mail, stream);
+ if (cache->uid == _mail->uid && cache->box == _mail->box) {
+ /* use the cached stream. when doing partial reads it should
+ already be seeked into the wanted offset. */
+ i_stream_unref(stream);
+ i_stream_seek(cache->input, 0);
+ *stream = i_stream_create_limit(cache->input, (uoff_t)-1);
+ return zmail->super.istream_opened(_mail, stream);
+ }
+
handler = compression_detect_handler(*stream);
if (handler != NULL) {
if (handler->create_istream == NULL) {
@@ -75,6 +146,8 @@ static int zlib_istream_opened(struct mail *_mail, struct istream **stream)
input = *stream;
*stream = handler->create_istream(input, TRUE);
i_stream_unref(&input);
+
+ *stream = zlib_mail_cache_open(zuser, _mail, *stream);
}
return zmail->super.istream_opened(_mail, stream);
}
@@ -265,6 +338,16 @@ static int zlib_mailbox_open(struct mailbox *box)
return zbox->super.open(box);
}
+static void zlib_mailbox_close(struct mailbox *box)
+{
+ union mailbox_module_context *zbox = ZLIB_CONTEXT(box);
+ struct zlib_user *zuser = ZLIB_USER_CONTEXT(box->storage->user);
+
+ if (zuser->cache.box == box)
+ zlib_mail_cache_close(zuser);
+ zbox->super.close(box);
+}
+
static void zlib_mailbox_allocated(struct mailbox *box)
{
struct mailbox_vfuncs *v = box->vlast;
@@ -274,6 +357,7 @@ static void zlib_mailbox_allocated(struct mailbox *box)
zbox->super = *v;
box->vlast = &zbox->super;
v->open = zlib_mailbox_open;
+ v->close = zlib_mailbox_close;
MODULE_CONTEXT_SET_SELF(box, zlib_storage_module, zbox);
@@ -283,12 +367,24 @@ static void zlib_mailbox_allocated(struct mailbox *box)
zlib_permail_alloc_init(box, v);
}
+static void zlib_mail_user_deinit(struct mail_user *user)
+{
+ struct zlib_user *zuser = ZLIB_USER_CONTEXT(user);
+
+ zlib_mail_cache_close(zuser);
+ zuser->module_ctx.super.deinit(user);
+}
+
static void zlib_mail_user_created(struct mail_user *user)
{
+ struct mail_user_vfuncs *v = user->vlast;
struct zlib_user *zuser;
const char *name;
zuser = p_new(user->pool, struct zlib_user, 1);
+ zuser->module_ctx.super = *v;
+ user->vlast = &zuser->module_ctx.super;
+ v->deinit = zlib_mail_user_deinit;
name = mail_user_plugin_getenv(user, "zlib_save");
if (name != NULL && *name != '\0') {
--
1.7.10.2
From f7c17f745db01d854f315ddcbc9955125b4161ef Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 22 Apr 2013 21:51:01 +0300
Subject: [PATCH] stats plugin: Use nonblocking open() for stats fifo. This
fixes hangs in it. Alternative would be to use alarm().
diff --git a/src/plugins/stats/stats-connection.c b/src/plugins/stats/stats-connection.c
index b98e864..da07e9b 100644
--- a/src/plugins/stats/stats-connection.c
+++ b/src/plugins/stats/stats-connection.c
@@ -23,7 +23,7 @@ static bool stats_connection_open(struct stats_connection *conn)
if (conn->open_failed)
return FALSE;
- conn->fd = open(conn->path, O_WRONLY);
+ conn->fd = open(conn->path, O_WRONLY | O_NONBLOCK);
if (conn->fd == -1) {
i_error("stats: open(%s) failed: %m", conn->path);
conn->open_failed = TRUE;
--
1.7.10.2
From 43afe64ef8b8d2af9576b9e5a60feb0ef62223f9 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 13:28:17 +0300
Subject: [PATCH] OpenBSD compile fix: include sys/socket.h when checking for
struct sockpeercred.
diff --git a/configure.ac b/configure.ac
index f06095f..a67d511 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,7 +433,7 @@ AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize madvise \
walkcontext dirfd clearenv malloc_usable_size glob fallocate \
posix_fadvise getpeereid getpeerucred)
-AC_CHECK_TYPES([struct sockpeercred])
+AC_CHECK_TYPES([struct sockpeercred],,,[#include <sys/socket.h>])
AC_SEARCH_LIBS(clock_gettime, rt, [
AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function)
--
1.7.10.2
From 4288a8d102d241c32c5d53609f9242cd13263077 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 13:33:12 +0300
Subject: [PATCH] master: Fixed warning log message.
diff --git a/src/master/master-settings.c b/src/master/master-settings.c
index 29edf86..45e56ac 100644
--- a/src/master/master-settings.c
+++ b/src/master/master-settings.c
@@ -417,7 +417,7 @@ master_settings_verify(void *_set, pool_t pool, const char **error_r)
const struct service_settings *default_service;
#else
rlim_t fd_limit;
- const char *max_client_limit_source = "default_client_count";
+ const char *max_client_limit_source = "default_client_limit";
unsigned int max_client_limit = set->default_client_limit;
#endif
--
1.7.10.2
From 212c975ce882bcaebd49ff7d7ea8e1f109a25101 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 13:47:46 +0300
Subject: [PATCH] fts-solr: Don't crash if fts_solr setting is invalid.
diff --git a/src/plugins/fts-solr/fts-backend-solr-old.c b/src/plugins/fts-solr/fts-backend-solr-old.c
index 9fd8094..1845849 100644
--- a/src/plugins/fts-solr/fts-backend-solr-old.c
+++ b/src/plugins/fts-solr/fts-backend-solr-old.c
@@ -229,11 +229,14 @@ fts_backend_solr_init(struct fts_backend *_backend, const char **error_r)
{
struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user);
- const struct fts_solr_settings *set = &fuser->set;
const char *str;
+ if (fuser == NULL) {
+ *error_r = "Invalid fts_solr setting";
+ return -1;
+ }
if (solr_conn == NULL) {
- if (solr_connection_init(set->url, set->debug,
+ if (solr_connection_init(fuser->set.url, fuser->set.debug,
&solr_conn, error_r) < 0)
return -1;
}
diff --git a/src/plugins/fts-solr/fts-backend-solr.c b/src/plugins/fts-solr/fts-backend-solr.c
index f7b335f..8af1707 100644
--- a/src/plugins/fts-solr/fts-backend-solr.c
+++ b/src/plugins/fts-solr/fts-backend-solr.c
@@ -158,10 +158,13 @@ static int
fts_backend_solr_init(struct fts_backend *_backend, const char **error_r)
{
struct fts_solr_user *fuser = FTS_SOLR_USER_CONTEXT(_backend->ns->user);
- const struct fts_solr_settings *set = &fuser->set;
+ if (fuser == NULL) {
+ *error_r = "Invalid fts_solr setting";
+ return -1;
+ }
if (solr_conn == NULL) {
- if (solr_connection_init(set->url, set->debug,
+ if (solr_connection_init(fuser->set.url, fuser->set.debug,
&solr_conn, error_r) < 0)
return -1;
}
--
1.7.10.2
From efe39df75481a8c4579b70f24987eea075d0eeb8 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 16:20:48 +0300
Subject: [PATCH] lib-http: Makefile fix
diff --git a/src/lib-http/Makefile.am b/src/lib-http/Makefile.am
index 5c19c58..4127a14 100644
--- a/src/lib-http/Makefile.am
+++ b/src/lib-http/Makefile.am
@@ -50,7 +50,7 @@ test_libs = \
$(MODULE_LIBS)
test_deps = \
- $(noinst_LTLIBRARIES)
+ $(noinst_LTLIBRARIES) \
../lib-test/libtest.la \
../lib/liblib.la
--
1.7.10.2
From 7c55c5055f78c849716efce14072a652157f3200 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 17:21:46 +0300
Subject: [PATCH] istream-seekable: Don't crash when seeking forwards past the
data we haven't read yet.
diff --git a/src/lib/istream-seekable.c b/src/lib/istream-seekable.c
index a9c5d81..cf59138 100644
--- a/src/lib/istream-seekable.c
+++ b/src/lib/istream-seekable.c
@@ -345,6 +345,20 @@ i_stream_seekable_stat(struct istream_private *stream, bool exact)
return 0;
}
+static void i_stream_seekable_seek(struct istream_private *stream,
+ uoff_t v_offset, bool mark)
+{
+ if (v_offset <= stream->istream.v_offset) {
+ /* seeking backwards */
+ stream->istream.v_offset = v_offset;
+ stream->skip = stream->pos = 0;
+ } else {
+ /* we can't skip over data we haven't yet read and written to
+ our buffer/temp file */
+ i_stream_default_seek_nonseekable(stream, v_offset, mark);
+ }
+}
+
struct istream *
i_streams_merge(struct istream *input[], size_t max_buffer_size,
int (*fd_callback)(const char **path_r, void *context),
@@ -388,6 +402,7 @@ i_streams_merge(struct istream *input[], size_t max_buffer_size,
sstream->istream.read = i_stream_seekable_read;
sstream->istream.stat = i_stream_seekable_stat;
+ sstream->istream.seek = i_stream_seekable_seek;
sstream->istream.istream.readable_fd = FALSE;
sstream->istream.istream.blocking = blocking;
--
1.7.10.2
From bd6b8ffcd0aef00aaa5b640d8e425fdcd0075993 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 20:51:34 +0300
Subject: [PATCH] dbox: Close file's fd only after its istream is destroyed.
For example zlib plugin keeps the stream open as a cache
even after the dbox_file has been destroyed.
diff --git a/src/lib-storage/index/dbox-common/dbox-file.c b/src/lib-storage/index/dbox-common/dbox-file.c
index 2b36013..c714487 100644
--- a/src/lib-storage/index/dbox-common/dbox-file.c
+++ b/src/lib-storage/index/dbox-common/dbox-file.c
@@ -215,7 +215,7 @@ static int dbox_file_open_full(struct dbox_file *file, bool try_altpath,
}
}
- file->input = i_stream_create_fd(file->fd, DBOX_READ_BLOCK_SIZE, FALSE);
+ file->input = i_stream_create_fd(file->fd, DBOX_READ_BLOCK_SIZE, TRUE);
i_stream_set_name(file->input, file->cur_path);
i_stream_set_init_buffer_size(file->input, DBOX_READ_BLOCK_SIZE);
return dbox_file_read_header(file);
@@ -286,9 +286,12 @@ int dbox_file_header_write(struct dbox_file *file, struct ostream *output)
void dbox_file_close(struct dbox_file *file)
{
dbox_file_unlock(file);
- if (file->input != NULL)
+ if (file->input != NULL) {
+ /* stream autocloses the fd when it gets destroyed. note that
+ the stream may outlive the struct dbox_file. */
i_stream_unref(&file->input);
- if (file->fd != -1) {
+ file->fd = -1;
+ } else if (file->fd != -1) {
if (close(file->fd) < 0)
dbox_file_set_syscall_error(file, "close()");
file->fd = -1;
--
1.7.10.2
From 7e2d3faf969bcb9f65ae8a7860f4dfff28dd8f95 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 20:53:53 +0300
Subject: [PATCH] istream-[b]zlib: Don't break if parent stream gets seeked in
the middle of reads.
diff --git a/src/lib-compression/istream-bzlib.c b/src/lib-compression/istream-bzlib.c
index 2ad33dc..3937cb1 100644
--- a/src/lib-compression/istream-bzlib.c
+++ b/src/lib-compression/istream-bzlib.c
@@ -15,7 +15,7 @@ struct bzlib_istream {
bz_stream zs;
uoff_t eof_offset, stream_size;
- size_t prev_size, high_pos;
+ size_t high_pos;
struct stat last_parent_statbuf;
unsigned int log_errors:1;
@@ -49,7 +49,7 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
struct bzlib_istream *zstream = (struct bzlib_istream *)stream;
const unsigned char *data;
uoff_t high_offset;
- size_t size;
+ size_t size, out_size;
int ret;
high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
@@ -98,42 +98,36 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
}
}
- if (zstream->zs.avail_in == 0) {
- /* need to read more data. try to read a full CHUNK_SIZE */
- i_stream_skip(stream->parent, zstream->prev_size);
- if (i_stream_read_data(stream->parent, &data, &size,
- CHUNK_SIZE-1) == -1 && size == 0) {
- if (stream->parent->stream_errno != 0) {
- stream->istream.stream_errno =
- stream->parent->stream_errno;
- } else {
- i_assert(stream->parent->eof);
- if (zstream->log_errors) {
- bzlib_read_error(zstream,
- "unexpected EOF");
- }
- stream->istream.stream_errno = EINVAL;
- }
- return -1;
+ if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) {
+ if (stream->parent->stream_errno != 0) {
+ stream->istream.stream_errno =
+ stream->parent->stream_errno;
+ } else {
+ i_assert(stream->parent->eof);
+ if (zstream->log_errors)
+ bzlib_read_error(zstream, "unexpected EOF");
+ stream->istream.stream_errno = EINVAL;
}
- zstream->prev_size = size;
- if (size == 0) {
- /* no more input */
- i_assert(!stream->istream.blocking);
- return 0;
- }
-
- zstream->zs.next_in = (char *)data;
- zstream->zs.avail_in = size;
+ return -1;
+ }
+ if (size == 0) {
+ /* no more input */
+ i_assert(!stream->istream.blocking);
+ return 0;
}
- size = stream->buffer_size - stream->pos;
+ zstream->zs.next_in = (char *)data;
+ zstream->zs.avail_in = size;
+
+ out_size = stream->buffer_size - stream->pos;
zstream->zs.next_out = (char *)stream->w_buffer + stream->pos;
- zstream->zs.avail_out = size;
+ zstream->zs.avail_out = out_size;
ret = BZ2_bzDecompress(&zstream->zs);
- size -= zstream->zs.avail_out;
- stream->pos += size;
+ out_size -= zstream->zs.avail_out;
+ stream->pos += out_size;
+
+ i_stream_skip(stream->parent, size - zstream->zs.avail_in);
switch (ret) {
case BZ_OK:
@@ -159,7 +153,7 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
zstream->eof_offset = stream->istream.v_offset +
(stream->pos - stream->skip);
zstream->stream_size = zstream->eof_offset;
- if (size == 0) {
+ if (out_size == 0) {
stream->istream.eof = TRUE;
return -1;
}
@@ -167,11 +161,11 @@ static ssize_t i_stream_bzlib_read(struct istream_private *stream)
default:
i_fatal("BZ2_bzDecompress() failed with %d", ret);
}
- if (size == 0) {
+ if (out_size == 0) {
/* read more input */
return i_stream_bzlib_read(stream);
}
- return size;
+ return out_size;
}
static void i_stream_bzlib_init(struct bzlib_istream *zstream)
@@ -206,7 +200,6 @@ static void i_stream_bzlib_reset(struct bzlib_istream *zstream)
stream->skip = stream->pos = 0;
stream->istream.v_offset = 0;
zstream->high_pos = 0;
- zstream->prev_size = 0;
(void)BZ2_bzDecompressEnd(&zstream->zs);
i_stream_bzlib_init(zstream);
diff --git a/src/lib-compression/istream-zlib.c b/src/lib-compression/istream-zlib.c
index 021bfe0..c7ac2c4 100644
--- a/src/lib-compression/istream-zlib.c
+++ b/src/lib-compression/istream-zlib.c
@@ -122,6 +122,7 @@ static int i_stream_zlib_read_header(struct istream_private *stream)
pos += 2;
}
i_stream_skip(stream->parent, pos);
+ zstream->prev_size = 0;
return 1;
}
@@ -172,7 +173,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
struct zlib_istream *zstream = (struct zlib_istream *)stream;
const unsigned char *data;
uoff_t high_offset;
- size_t size;
+ size_t size, out_size;
int ret;
high_offset = stream->istream.v_offset + (stream->pos - stream->skip);
@@ -208,7 +209,6 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
if (ret <= 0)
return ret;
zstream->header_read = TRUE;
- zstream->prev_size = 0;
}
if (stream->pos < zstream->high_pos) {
@@ -248,44 +248,39 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
}
}
- if (zstream->zs.avail_in == 0) {
- /* need to read more data. try to read a full CHUNK_SIZE */
- i_stream_skip(stream->parent, zstream->prev_size);
- if (i_stream_read_data(stream->parent, &data, &size,
- CHUNK_SIZE-1) == -1 && size == 0) {
- if (stream->parent->stream_errno != 0) {
- stream->istream.stream_errno =
- stream->parent->stream_errno;
- } else {
- i_assert(stream->parent->eof);
- if (zstream->log_errors) {
- zlib_read_error(zstream,
- "unexpected EOF");
- }
- stream->istream.stream_errno = EPIPE;
- }
- return -1;
- }
- zstream->prev_size = size;
- if (size == 0) {
- /* no more input */
- i_assert(!stream->istream.blocking);
- return 0;
+ if (i_stream_read_data(stream->parent, &data, &size, 0) < 0) {
+ if (stream->parent->stream_errno != 0) {
+ stream->istream.stream_errno =
+ stream->parent->stream_errno;
+ } else {
+ i_assert(stream->parent->eof);
+ if (zstream->log_errors)
+ zlib_read_error(zstream, "unexpected EOF");
+ stream->istream.stream_errno = EPIPE;
}
-
- zstream->zs.next_in = (void *)data;
- zstream->zs.avail_in = size;
+ return -1;
+ }
+ if (size == 0) {
+ /* no more input */
+ i_assert(!stream->istream.blocking);
+ return 0;
}
- size = stream->buffer_size - stream->pos;
+ zstream->zs.next_in = (void *)data;
+ zstream->zs.avail_in = size;
+
+ out_size = stream->buffer_size - stream->pos;
zstream->zs.next_out = stream->w_buffer + stream->pos;
- zstream->zs.avail_out = size;
+ zstream->zs.avail_out = out_size;
ret = inflate(&zstream->zs, Z_SYNC_FLUSH);
- size -= zstream->zs.avail_out;
+ out_size -= zstream->zs.avail_out;
zstream->crc32 = crc32_data_more(zstream->crc32,
- stream->w_buffer + stream->pos, size);
- stream->pos += size;
+ stream->w_buffer + stream->pos,
+ out_size);
+ stream->pos += out_size;
+
+ i_stream_skip(stream->parent, size - zstream->zs.avail_in);
switch (ret) {
case Z_OK:
@@ -307,10 +302,7 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
zstream->eof_offset = stream->istream.v_offset +
(stream->pos - stream->skip);
zstream->stream_size = zstream->eof_offset;
- i_stream_skip(stream->parent,
- zstream->prev_size - zstream->zs.avail_in);
zstream->zs.avail_in = 0;
- zstream->prev_size = 0;
if (!zstream->trailer_read) {
/* try to read and verify the trailer, we might not
@@ -322,11 +314,11 @@ static ssize_t i_stream_zlib_read(struct istream_private *stream)
default:
i_fatal("inflate() failed with %d", ret);
}
- if (size == 0) {
+ if (out_size == 0) {
/* read more input */
return i_stream_zlib_read(stream);
}
- return size;
+ return out_size;
}
static void i_stream_zlib_init(struct zlib_istream *zstream)
--
1.7.10.2
From 7e2ef0020ae79382577f9610d6ab3135bb604b56 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 21:06:00 +0300
Subject: [PATCH] lib-storage: Fixed crash with mailbox_list_index=yes after
re-reading index.
diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c
index 1f2dbed..61391ea 100644
--- a/src/lib-storage/list/mailbox-list-index.c
+++ b/src/lib-storage/list/mailbox-list-index.c
@@ -27,8 +27,8 @@ void mailbox_list_index_reset(struct mailbox_list_index *ilist)
{
i_assert(ilist->iter_refcount == 0);
- hash_table_clear(ilist->mailbox_names, FALSE);
- hash_table_clear(ilist->mailbox_hash, FALSE);
+ hash_table_clear(ilist->mailbox_names, TRUE);
+ hash_table_clear(ilist->mailbox_hash, TRUE);
p_clear(ilist->mailbox_pool);
ilist->mailbox_tree = NULL;
ilist->highest_name_id = 0;
--
1.7.10.2
From 249fc7092cf438ee9ca7e2f5cdeb4bd8ff5409e6 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 21:06:34 +0300
Subject: [PATCH] maildir: Crashfix after dovecot-keywords file was re-read.
diff --git a/src/lib-storage/index/maildir/maildir-keywords.c b/src/lib-storage/index/maildir/maildir-keywords.c
index b45db1c..0a32c45 100644
--- a/src/lib-storage/index/maildir/maildir-keywords.c
+++ b/src/lib-storage/index/maildir/maildir-keywords.c
@@ -104,7 +104,7 @@ void maildir_keywords_deinit(struct maildir_keywords **_mk)
static void maildir_keywords_clear(struct maildir_keywords *mk)
{
array_clear(&mk->list);
- hash_table_clear(mk->hash, FALSE);
+ hash_table_clear(mk->hash, TRUE);
p_clear(mk->pool);
}
--
1.7.10.2
From c3df0aec4b12a7aea7fc0a1ec5ca58833862cbb0 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 21:08:31 +0300
Subject: [PATCH] hash_table_clear(): Added a comment about API usage.
diff --git a/src/lib/hash.h b/src/lib/hash.h
index f0ccb67..ead59a1 100644
--- a/src/lib/hash.h
+++ b/src/lib/hash.h
@@ -68,8 +68,8 @@ void hash_table_destroy(struct hash_table **table);
#define hash_table_destroy(table) \
hash_table_destroy(&(*table)._table)
/* Remove all nodes from hash table. If free_collisions is TRUE, the
- memory allocated from node_pool is freed, or discarded with
- alloconly pools. */
+ memory allocated from node_pool is freed, or discarded with alloconly pools.
+ WARNING: If you p_clear() the node_pool, the free_collisions must be TRUE. */
void hash_table_clear(struct hash_table *table, bool free_collisions);
#define hash_table_clear(table, free_collisions) \
hash_table_clear((table)._table, free_collisions)
--
1.7.10.2
From ffdf174645c18d779de5d503df0d7269be42317f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 21:31:52 +0300
Subject: [PATCH] lib-master: Added master_service_is_master_stopped()
diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c
index 378bc63..a06b6e8 100644
--- a/src/lib-master/master-service.c
+++ b/src/lib-master/master-service.c
@@ -600,6 +600,11 @@ bool master_service_is_killed(struct master_service *service)
return service->killed;
}
+bool master_service_is_master_stopped(struct master_service *service)
+{
+ return service->io_status_error == NULL;
+}
+
void master_service_anvil_send(struct master_service *service, const char *cmd)
{
ssize_t ret;
diff --git a/src/lib-master/master-service.h b/src/lib-master/master-service.h
index b975895..0ca002b 100644
--- a/src/lib-master/master-service.h
+++ b/src/lib-master/master-service.h
@@ -141,6 +141,9 @@ void master_service_stop(struct master_service *service);
void master_service_stop_new_connections(struct master_service *service);
/* Returns TRUE if we've received a SIGINT/SIGTERM and we've decided to stop. */
bool master_service_is_killed(struct master_service *service);
+/* Returns TRUE if our master process is already stopped. This process may or
+ may not be dying itself. */
+bool master_service_is_master_stopped(struct master_service *service);
/* Send command to anvil process, if we have fd to it. */
void master_service_anvil_send(struct master_service *service, const char *cmd);
--
1.7.10.2
From 2598176e416438cbaccd65de471d229651786aec Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 23 Apr 2013 21:32:24 +0300
Subject: [PATCH] stats plugin: Don't try to send notifications to already
dead stats process.
diff --git a/src/plugins/stats/Makefile.am b/src/plugins/stats/Makefile.am
index e7a46d5..a88fc3b 100644
--- a/src/plugins/stats/Makefile.am
+++ b/src/plugins/stats/Makefile.am
@@ -2,6 +2,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib-settings \
-I$(top_srcdir)/src/lib-mail \
+ -I$(top_srcdir)/src/lib-master \
-I$(top_srcdir)/src/lib-index \
-I$(top_srcdir)/src/lib-storage
diff --git a/src/plugins/stats/stats-connection.c b/src/plugins/stats/stats-connection.c
index da07e9b..9560cc4 100644
--- a/src/plugins/stats/stats-connection.c
+++ b/src/plugins/stats/stats-connection.c
@@ -5,6 +5,7 @@
#include "net.h"
#include "str.h"
#include "strescape.h"
+#include "master-service.h"
#include "mail-storage.h"
#include "stats-plugin.h"
#include "stats-connection.h"
@@ -71,6 +72,12 @@ void stats_connection_send(struct stats_connection *conn, const string_t *str)
static bool pipe_warned = FALSE;
ssize_t ret;
+ /* if master process has been stopped (and restarted), don't even try
+ to notify the stats process anymore. even if one exists, it doesn't
+ know about us. */
+ if (master_service_is_master_stopped(master_service))
+ return;
+
if (conn->fd == -1) {
if (!stats_connection_open(conn))
return;
--
1.7.10.2
From ebc36aca877984a309ee676da1f88d0d9a87e0c2 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Thu, 2 May 2013 16:20:02 +0300
Subject: [PATCH] example-config: Typofix
diff --git a/doc/example-config/dovecot.conf b/doc/example-config/dovecot.conf
index 16b0b0b..5697661 100644
--- a/doc/example-config/dovecot.conf
+++ b/doc/example-config/dovecot.conf
@@ -47,7 +47,7 @@
# these networks. Typically you'd specify your IMAP proxy servers here.
#login_trusted_networks =
-# Sepace separated list of login access check sockets (e.g. tcpwrap)
+# Space separated list of login access check sockets (e.g. tcpwrap)
#login_access_sockets =
# With proxy_maybe=yes if proxy destination matches any of these IPs, don't do
--
1.7.10.2
From d47967d36496b7e75f3152f917b8e51ef88affd7 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Thu, 2 May 2013 18:11:56 +0300
Subject: [PATCH] imap: Fixed using literals for URLs in CATENATE.
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index 9153e52..b825692 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -349,6 +349,30 @@ static void cmd_append_finish_catenate(struct client_command_context *cmd)
}
}
+static bool catenate_args_can_stop(struct cmd_append_context *ctx,
+ const struct imap_arg *args)
+{
+ /* eat away literal_sizes from URLs */
+ while (args->type != IMAP_ARG_EOL) {
+ if (imap_arg_atom_equals(args, "TEXT"))
+ return TRUE;
+ if (!imap_arg_atom_equals(args, "URL")) {
+ /* error - handle it later */
+ return TRUE;
+ }
+ args++;
+ if (args->type == IMAP_ARG_LITERAL_SIZE ||
+ args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC) {
+ if (args->type == IMAP_ARG_LITERAL_SIZE)
+ cmd_append_send_literal_continue(ctx->client);
+ imap_parser_read_last_literal(ctx->save_parser);
+ return FALSE;
+ }
+ args++;
+ }
+ return TRUE;
+}
+
static bool cmd_append_continue_catenate(struct client_command_context *cmd)
{
struct client *client = cmd->client;
@@ -368,10 +392,12 @@ static bool cmd_append_continue_catenate(struct client_command_context *cmd)
it's fine that this would need to fully fit into input buffer
(although clients attempting to DoS could simply insert an extra
{1+} between the URLs) */
- ret = imap_parser_read_args(ctx->save_parser, 0,
- IMAP_PARSE_FLAG_LITERAL_SIZE |
- IMAP_PARSE_FLAG_LITERAL8 |
- IMAP_PARSE_FLAG_INSIDE_LIST, &args);
+ do {
+ ret = imap_parser_read_args(ctx->save_parser, 0,
+ IMAP_PARSE_FLAG_LITERAL_SIZE |
+ IMAP_PARSE_FLAG_LITERAL8 |
+ IMAP_PARSE_FLAG_INSIDE_LIST, &args);
+ } while (ret > 0 && !catenate_args_can_stop(ctx, args));
if (ret == -1) {
msg = imap_parser_get_error(ctx->save_parser, &fatal);
if (fatal)
@@ -630,8 +656,11 @@ static bool cmd_append_finish_parsing(struct client_command_context *cmd)
return cmd_sync(cmd, sync_flags, imap_flags, str_c(msg));
}
-static bool cmd_append_args_can_stop(const struct imap_arg *args)
+static bool cmd_append_args_can_stop(struct cmd_append_context *ctx,
+ const struct imap_arg *args)
{
+ const struct imap_arg *cat_list;
+
if (args->type == IMAP_ARG_EOL)
return TRUE;
@@ -645,8 +674,8 @@ static bool cmd_append_args_can_stop(const struct imap_arg *args)
args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC)
return TRUE;
if (imap_arg_atom_equals(args, "CATENATE") &&
- args[1].type == IMAP_ARG_LIST)
- return TRUE;
+ imap_arg_get_list(&args[1], &cat_list))
+ return catenate_args_can_stop(ctx, cat_list);
return FALSE;
}
@@ -680,7 +709,7 @@ static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
ret = imap_parser_read_args(ctx->save_parser, arg_min_count++,
IMAP_PARSE_FLAG_LITERAL_SIZE |
IMAP_PARSE_FLAG_LITERAL8, &args);
- } while (ret > 0 && !cmd_append_args_can_stop(args));
+ } while (ret > 0 && !cmd_append_args_can_stop(ctx, args));
if (ret == -1) {
if (!ctx->failed) {
msg = imap_parser_get_error(ctx->save_parser, &fatal);
--
1.7.10.2
From a2a529c6dbe1fc2b4e71e456c7cd3fc53b18bee7 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Thu, 2 May 2013 18:18:26 +0300
Subject: [PATCH] imap: Don't allow empty CATENATE () list.
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index b825692..a7e2b31 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -586,6 +586,10 @@ cmd_append_handle_args(struct client_command_context *cmd,
if (cat_list == NULL) {
/* normal APPEND */
return 1;
+ } else if (cat_list->type == IMAP_ARG_EOL) {
+ /* zero parts */
+ client_send_command_error(cmd, "Empty CATENATE list.");
+ return -1;
} else if ((ret = cmd_append_catenate(cmd, cat_list, nonsync_r)) < 0) {
/* invalid parameters, abort immediately */
return -1;
@@ -734,6 +738,8 @@ static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
ret = cmd_append_handle_args(cmd, args, &nonsync);
if (ret < 0) {
/* invalid parameters, abort immediately */
+ if (ctx->catenate)
+ client->input_skip_line = TRUE;
cmd_append_finish(ctx);
return TRUE;
}
--
1.7.10.2
From b422c981522d9adda053424a5b837b1c5f06a991 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Thu, 2 May 2013 18:29:50 +0300
Subject: [PATCH] imap-urlauth-worker: Fixed a crash (by removing unnecessary
code)
diff --git a/src/imap-urlauth/imap-urlauth-worker.c b/src/imap-urlauth/imap-urlauth-worker.c
index 6d94a8f..49a3d59 100644
--- a/src/imap-urlauth/imap-urlauth-worker.c
+++ b/src/imap-urlauth/imap-urlauth-worker.c
@@ -54,7 +54,7 @@ struct client {
struct io *io, *ctrl_io;
struct istream *input, *ctrl_input;
struct ostream *output, *ctrl_output;
- struct timeout *to_idle, *to_delay;
+ struct timeout *to_idle;
char *access_user;
ARRAY_TYPE(string) access_apps;
@@ -245,8 +245,6 @@ static void client_destroy(struct client *client)
io_remove(&client->ctrl_io);
if (client->to_idle != NULL)
timeout_remove(&client->to_idle);
- if (client->to_delay != NULL)
- timeout_remove(&client->to_delay);
if (client->input != NULL)
i_stream_destroy(&client->input);
@@ -605,7 +603,6 @@ client_handle_user_command(struct client *client, const char *cmd,
i_debug("User %s doesn't exist", input.username);
client_send_line(client, "NO");
- timeout_remove(&client->to_delay);
return 1;
}
@@ -669,7 +666,7 @@ static bool client_handle_input(struct client *client)
const char *line, *cmd, *error;
int ret;
- if (client->url != NULL || client->to_delay != NULL) {
+ if (client->url != NULL) {
/* we're still processing a URL. wait until it's
finished. */
io_remove(&client->io);
--
1.7.10.2
From c35d09cecd4de0fa69514814d26ead0cd8776972 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Thu, 2 May 2013 18:32:47 +0300
Subject: [PATCH] lib-imap-urlauth: Don't try to access garbage memory on
error handling path.
diff --git a/src/lib-imap-urlauth/imap-urlauth.c b/src/lib-imap-urlauth/imap-urlauth.c
index 2a557a2..0019f0e 100644
--- a/src/lib-imap-urlauth/imap-urlauth.c
+++ b/src/lib-imap-urlauth/imap-urlauth.c
@@ -362,6 +362,7 @@ int imap_urlauth_fetch_parsed(struct imap_urlauth_context *uctx,
unsigned char mailbox_key[IMAP_URLAUTH_KEY_LEN];
int ret;
+ *mpurl_r = NULL;
*error_r = NULL;
*error_code_r = MAIL_ERROR_NONE;
--
1.7.10.2
From 769728fec2c3a87695f3c26e5fc3773cb5618a9f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Fri, 3 May 2013 17:17:15 +0300
Subject: [PATCH] quota-status: Return 554 instead of 552 on quota failures.
This is because RFC 5321/2821 recommends that 552 is
treated the same as 452.
diff --git a/src/plugins/quota/quota-status.c b/src/plugins/quota/quota-status.c
index 23a0070..bfac5e7 100644
--- a/src/plugins/quota/quota-status.c
+++ b/src/plugins/quota/quota-status.c
@@ -107,7 +107,7 @@ static void client_handle_request(struct quota_client *client)
/* over quota */
value = mail_user_plugin_getenv(user, "quota_status_overquota");
if (value == NULL)
- value = t_strdup_printf("552 5.2.2 %s\n\n", error);
+ value = t_strdup_printf("554 5.2.2 %s\n\n", error);
}
mail_user_unref(&user);
mail_storage_service_user_free(&service_user);
--
1.7.10.2
From c366e44efb27db7c57dde1b4f3580b879a65a761 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 14:58:55 +0300
Subject: [PATCH] acl: Mailbox creation ignored ACLs (due to API changes in
v2.2). The created mailbox couldn't have been accessed
however.
diff --git a/src/plugins/acl/acl-mailbox.c b/src/plugins/acl/acl-mailbox.c
index 6ed4bc9..1630af5 100644
--- a/src/plugins/acl/acl-mailbox.c
+++ b/src/plugins/acl/acl-mailbox.c
@@ -118,8 +118,23 @@ acl_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
struct acl_mailbox *abox = ACL_CONTEXT(box);
int ret;
- /* we already checked permissions in list.mailbox_create_dir().
- ignore ACLs in this mailbox until creation is complete, because
+ /* we're looking up CREATE permission from our parent's rights */
+ ret = acl_mailbox_list_have_right(box->list, box->name, TRUE,
+ ACL_STORAGE_RIGHT_CREATE, NULL);
+ if (ret <= 0) {
+ if (ret < 0) {
+ mail_storage_set_internal_error(box->storage);
+ return -1;
+ }
+ /* Note that if user didn't have LOOKUP permission to parent
+ mailbox, this may reveal the mailbox's existence to user.
+ Can't help it. */
+ mail_storage_set_error(box->storage, MAIL_ERROR_PERM,
+ MAIL_ERRSTR_NO_PERMISSION);
+ return -1;
+ }
+
+ /* ignore ACLs in this mailbox until creation is complete, because
super.create() may call e.g. mailbox_open() which will fail since
we haven't yet copied ACLs to this mailbox. */
abox->skip_acl_checks = TRUE;
--
1.7.10.2
From 31e39a37524bd48fea0af0dc8169a7eb46231a29 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 14:59:27 +0300
Subject: [PATCH] acl: Optionally get default ACL's for private/shared
namespaces from user's INBOX. This probably should be the
default always, but better not break anyone's existing
setup until v2.3.0. So for now there's a setting for this:
plugin { acl_defaults_from_inbox = yes }
diff --git a/src/plugins/acl/acl-api-private.h b/src/plugins/acl/acl-api-private.h
index 90a83eb..852dc31 100644
--- a/src/plugins/acl/acl-api-private.h
+++ b/src/plugins/acl/acl-api-private.h
@@ -81,6 +81,7 @@ extern const char *const all_mailbox_rights[];
const char *const *
acl_backend_mask_get_names(struct acl_backend *backend,
const struct acl_mask *mask, pool_t pool);
+struct acl_object *acl_backend_get_default_object(struct acl_backend *backend);
int acl_backend_get_default_rights(struct acl_backend *backend,
const struct acl_mask **mask_r);
void acl_rights_write_id(string_t *dest, const struct acl_rights *right);
diff --git a/src/plugins/acl/acl-backend-vfile.c b/src/plugins/acl/acl-backend-vfile.c
index ccf1655..ce8f2ae 100644
--- a/src/plugins/acl/acl-backend-vfile.c
+++ b/src/plugins/acl/acl-backend-vfile.c
@@ -284,7 +284,7 @@ acl_backend_vfile_object_init_parent(struct acl_backend *backend,
}
if (parent == NULL) {
/* use the root */
- parent = "";
+ parent = acl_backend_get_default_object(backend)->name;
}
return acl_backend_vfile_object_init(backend, parent);
}
diff --git a/src/plugins/acl/acl-backend.c b/src/plugins/acl/acl-backend.c
index c1b4451..3e562a6 100644
--- a/src/plugins/acl/acl-backend.c
+++ b/src/plugins/acl/acl-backend.c
@@ -4,6 +4,7 @@
#include "hash.h"
#include "mail-storage-settings.h"
#include "mailbox-list.h"
+#include "mail-namespace.h"
#include "mail-user.h"
#include "acl-cache.h"
#include "acl-api-private.h"
@@ -157,17 +158,35 @@ unsigned int acl_backend_lookup_right(struct acl_backend *backend,
return acl_cache_right_lookup(backend->cache, right);
}
+struct acl_object *acl_backend_get_default_object(struct acl_backend *backend)
+{
+ struct mail_user *user = mailbox_list_get_user(backend->list);
+ struct mail_namespace *ns = mailbox_list_get_namespace(backend->list);
+ const char *default_name = "";
+
+ if (backend->default_aclobj != NULL)
+ return backend->default_aclobj;
+
+ /* FIXME: this should probably be made default in v2.3 */
+ if (mail_user_plugin_getenv(user, "acl_defaults_from_inbox") != NULL) {
+ if (ns->type == MAIL_NAMESPACE_TYPE_PRIVATE ||
+ ns->type == MAIL_NAMESPACE_TYPE_SHARED)
+ default_name = "INBOX";
+ }
+ backend->default_aclobj =
+ acl_object_init_from_name(backend, default_name);
+ return backend->default_aclobj;
+}
+
int acl_backend_get_default_rights(struct acl_backend *backend,
const struct acl_mask **mask_r)
{
- if (backend->default_aclobj == NULL) {
- backend->default_aclobj =
- acl_object_init_from_name(backend, "");
- }
- if (backend->v.object_refresh_cache(backend->default_aclobj) < 0)
+ struct acl_object *aclobj = acl_backend_get_default_object(backend);
+
+ if (backend->v.object_refresh_cache(aclobj) < 0)
return -1;
- *mask_r = acl_cache_get_my_rights(backend->cache, "");
+ *mask_r = acl_cache_get_my_rights(backend->cache, aclobj->name);
if (*mask_r == NULL)
*mask_r = backend->default_aclmask;
return 0;
--
1.7.10.2
From 0ee2c2bc34bee983d109094fe19dc6ac23b5660f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 15:04:57 +0300
Subject: [PATCH] namespace { prefix="" list=no } should never be listed.
diff --git a/src/lib-storage/list/mailbox-list-iter.c b/src/lib-storage/list/mailbox-list-iter.c
index 6abba65..da95178 100644
--- a/src/lib-storage/list/mailbox-list-iter.c
+++ b/src/lib-storage/list/mailbox-list-iter.c
@@ -256,6 +256,9 @@ static bool ns_match_next(struct ns_list_iterate_context *ctx,
/* non-listable namespace matches only with exact prefix */
if (strncmp(ns->prefix, pattern, ns->prefix_len) != 0)
return FALSE;
+ /* prefix="" list=no is never listed */
+ if (ns->prefix_len == 0)
+ return FALSE;
}
prefix_without_sep = t_strndup(ns->prefix, len);
--
1.7.10.2
From dba8e2552b0e4fba4c41b99c7cc2e54bfe2cf492 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 15:17:49 +0300
Subject: [PATCH] maildir++: Fixed mail_shared_explicit_inbox=no
diff --git a/src/lib-storage/list/mailbox-list-maildir-iter.c b/src/lib-storage/list/mailbox-list-maildir-iter.c
index 6e2df66..30506a0 100644
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c
@@ -372,6 +372,7 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
struct mail_namespace *ns = list->ns;
DIR *dirp;
struct dirent *d;
+ const char *vname;
int ret = 0;
dirp = opendir(ctx->dir);
@@ -409,8 +410,8 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
return maildir_fill_inbox(ctx, glob, "INBOX", update_only);
} else if ((ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0) {
/* show shared INBOX. */
- return maildir_fill_inbox(ctx, glob,
- t_strconcat(ns->prefix, "INBOX", NULL), update_only);
+ vname = mailbox_list_get_vname(ns->list, "INBOX");
+ return maildir_fill_inbox(ctx, glob, vname, update_only);
} else {
return 0;
}
--
1.7.10.2
From bbdd76d381da01400db1879fd7fa2e2cb8e5e38a Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 16:43:29 +0300
Subject: [PATCH] lib-index: The previous assert-crashfix didn't actually fix
the problem.
diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c
index 852fe08..707ad6b 100644
--- a/src/lib-index/mail-transaction-log-view.c
+++ b/src/lib-index/mail-transaction-log-view.c
@@ -95,24 +95,18 @@ int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
}
for (file = view->log->files; file != NULL; file = file->next) {
- if (file->hdr.prev_file_seq == min_file_seq)
+ if (file->hdr.prev_file_seq == max_file_seq)
break;
}
- if (file != NULL && min_file_offset == file->hdr.prev_file_offset) {
+ if (file != NULL && max_file_offset == file->hdr.prev_file_offset) {
/* we can skip to the next file. we've delayed checking for
min_file_seq <= max_file_seq until now, because it's not
really an error to specify the same position twice (even if
in "wrong" order) */
i_assert(min_file_seq <= max_file_seq ||
- file->hdr.file_seq <= max_file_seq);
- min_file_seq = file->hdr.file_seq;
- min_file_offset = 0;
-
- if (min_file_seq > max_file_seq) {
- /* empty view */
- max_file_seq = min_file_seq;
- max_file_offset = min_file_offset;
- }
+ min_file_seq <= file->hdr.file_seq);
+ max_file_seq = file->hdr.file_seq;
+ max_file_offset = file->hdr.hdr_size;
} else {
i_assert(min_file_seq <= max_file_seq);
}
@@ -126,16 +120,6 @@ int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
return -1;
}
- if (min_file_offset > 0 && file != NULL &&
- min_file_offset < file->hdr.hdr_size) {
- /* log file offset is probably corrupted in the index file. */
- mail_transaction_log_view_set_corrupted(view,
- "file_seq=%u, min_file_offset (%"PRIuUOFF_T
- ") < hdr_size (%u)",
- min_file_seq, min_file_offset, file->hdr.hdr_size);
- return -1;
- }
-
view->tail = view->head = file = NULL;
for (seq = min_file_seq; seq <= max_file_seq; seq++) {
if (file == NULL || file->hdr.file_seq != seq) {
@@ -200,7 +184,23 @@ int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
max_file_offset = min_file_offset;
}
}
- i_assert(min_file_offset >= view->tail->hdr.hdr_size);
+
+ if (min_file_offset < view->tail->hdr.hdr_size) {
+ /* log file offset is probably corrupted in the index file. */
+ mail_transaction_log_view_set_corrupted(view,
+ "file_seq=%u, min_file_offset (%"PRIuUOFF_T
+ ") < hdr_size (%u)",
+ min_file_seq, min_file_offset, view->tail->hdr.hdr_size);
+ return -1;
+ }
+ if (max_file_offset < view->head->hdr.hdr_size) {
+ /* log file offset is probably corrupted in the index file. */
+ mail_transaction_log_view_set_corrupted(view,
+ "file_seq=%u, min_file_offset (%"PRIuUOFF_T
+ ") < hdr_size (%u)",
+ max_file_seq, max_file_offset, view->head->hdr.hdr_size);
+ return -1;
+ }
/* we have all of them. update refcounts. */
mail_transaction_log_view_unref_all(view);
--
1.7.10.2
From cabf0e30e0a51e54566c3229826ae6478744b103 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 17:27:36 +0300
Subject: [PATCH] doveadm_mail_iter_init(): Removed unnecessarily returning
transaction. If it's needed in future just add a new
doveadm_mail_iter_get_transaction().
diff --git a/src/doveadm/doveadm-mail-altmove.c b/src/doveadm/doveadm-mail-altmove.c
index f9fc505..a7d9843 100644
--- a/src/doveadm/doveadm-mail-altmove.c
+++ b/src/doveadm/doveadm-mail-altmove.c
@@ -20,13 +20,12 @@ cmd_altmove_box(struct doveadm_mail_cmd_context *ctx,
struct mail_search_args *search_args, bool reverse)
{
struct doveadm_mail_iter *iter;
- struct mailbox_transaction_context *trans;
struct mail *mail;
enum modify_type modify_type =
!reverse ? MODIFY_ADD : MODIFY_REMOVE;
if (doveadm_mail_iter_init(ctx, info, search_args, 0, NULL,
- &trans, &iter) < 0)
+ &iter) < 0)
return -1;
while (doveadm_mail_iter_next(iter, &mail)) {
diff --git a/src/doveadm/doveadm-mail-copymove.c b/src/doveadm/doveadm-mail-copymove.c
index 3eb16cc..3be9904 100644
--- a/src/doveadm/doveadm-mail-copymove.c
+++ b/src/doveadm/doveadm-mail-copymove.c
@@ -25,14 +25,13 @@ cmd_copy_box(struct copy_cmd_context *ctx, struct mailbox *destbox,
const struct mailbox_info *info)
{
struct doveadm_mail_iter *iter;
- struct mailbox_transaction_context *trans;
struct mailbox_transaction_context *desttrans;
struct mail_save_context *save_ctx;
struct mail *mail;
int ret = 0;
if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args, 0,
- NULL, &trans, &iter) < 0)
+ NULL, &iter) < 0)
return -1;
/* use a separately committed transaction for each mailbox.
diff --git a/src/doveadm/doveadm-mail-expunge.c b/src/doveadm/doveadm-mail-expunge.c
index 452d3de..8aca907 100644
--- a/src/doveadm/doveadm-mail-expunge.c
+++ b/src/doveadm/doveadm-mail-expunge.c
@@ -22,13 +22,12 @@ cmd_expunge_box(struct doveadm_mail_cmd_context *_ctx,
struct expunge_cmd_context *ctx = (struct expunge_cmd_context *)_ctx;
struct doveadm_mail_iter *iter;
struct mailbox *box;
- struct mailbox_transaction_context *trans;
struct mail *mail;
enum mail_error error;
int ret = 0;
if (doveadm_mail_iter_init(_ctx, info, search_args, 0, NULL,
- &trans, &iter) < 0)
+ &iter) < 0)
return -1;
while (doveadm_mail_iter_next(iter, &mail)) {
diff --git a/src/doveadm/doveadm-mail-fetch.c b/src/doveadm/doveadm-mail-fetch.c
index c918e39..3ade84d 100644
--- a/src/doveadm/doveadm-mail-fetch.c
+++ b/src/doveadm/doveadm-mail-fetch.c
@@ -507,13 +507,12 @@ static int
cmd_fetch_box(struct fetch_cmd_context *ctx, const struct mailbox_info *info)
{
struct doveadm_mail_iter *iter;
- struct mailbox_transaction_context *trans;
int ret = 0;
if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
ctx->wanted_fields,
array_idx(&ctx->header_fields, 0),
- &trans, &iter) < 0)
+ &iter) < 0)
return -1;
while (doveadm_mail_iter_next(iter, &ctx->mail)) {
diff --git a/src/doveadm/doveadm-mail-import.c b/src/doveadm/doveadm-mail-import.c
index a7727a2..59c79d8 100644
--- a/src/doveadm/doveadm-mail-import.c
+++ b/src/doveadm/doveadm-mail-import.c
@@ -103,13 +103,12 @@ cmd_import_box(struct import_cmd_context *ctx, struct mail_user *dest_user,
struct mail_search_args *search_args)
{
struct doveadm_mail_iter *iter;
- struct mailbox_transaction_context *trans;
struct mailbox *box;
struct mail *mail;
int ret = 0;
if (doveadm_mail_iter_init(&ctx->ctx, info, search_args, 0, NULL,
- &trans, &iter) < 0)
+ &iter) < 0)
return -1;
if (doveadm_mail_iter_next(iter, &mail)) {
diff --git a/src/doveadm/doveadm-mail-iter.c b/src/doveadm/doveadm-mail-iter.c
index e97c8a8..52470b4 100644
--- a/src/doveadm/doveadm-mail-iter.c
+++ b/src/doveadm/doveadm-mail-iter.c
@@ -21,7 +21,6 @@ int doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
struct mail_search_args *search_args,
enum mail_fetch_field wanted_fields,
const char *const *wanted_headers,
- struct mailbox_transaction_context **trans_r,
struct doveadm_mail_iter **iter_r)
{
struct doveadm_mail_iter *iter;
@@ -49,8 +48,6 @@ int doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
iter->t = mailbox_transaction_begin(iter->box, 0);
iter->search_ctx = mailbox_search_init(iter->t, search_args, NULL,
wanted_fields, headers_ctx);
-
- *trans_r = iter->t;
*iter_r = iter;
return 0;
}
@@ -128,3 +125,8 @@ bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter,
{
return mailbox_search_next(iter->search_ctx, mail_r);
}
+
+struct mailbox *doveadm_mail_iter_get_mailbox(struct doveadm_mail_iter *iter)
+{
+ return iter->box;
+}
diff --git a/src/doveadm/doveadm-mail-iter.h b/src/doveadm/doveadm-mail-iter.h
index f311fa8..fa33782 100644
--- a/src/doveadm/doveadm-mail-iter.h
+++ b/src/doveadm/doveadm-mail-iter.h
@@ -11,13 +11,13 @@ int doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
struct mail_search_args *search_args,
enum mail_fetch_field wanted_fields,
const char *const *wanted_headers,
- struct mailbox_transaction_context **trans_r,
struct doveadm_mail_iter **iter_r) ATTR_NULL(5);
int doveadm_mail_iter_deinit(struct doveadm_mail_iter **iter);
int doveadm_mail_iter_deinit_sync(struct doveadm_mail_iter **iter);
int doveadm_mail_iter_deinit_keep_box(struct doveadm_mail_iter **iter,
struct mailbox **box_r);
void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **iter);
+struct mailbox *doveadm_mail_iter_get_mailbox(struct doveadm_mail_iter *iter);
bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter,
struct mail **mail_r);
diff --git a/src/doveadm/doveadm-mail-search.c b/src/doveadm/doveadm-mail-search.c
index b6d7331..97a6933 100644
--- a/src/doveadm/doveadm-mail-search.c
+++ b/src/doveadm/doveadm-mail-search.c
@@ -15,16 +15,15 @@ cmd_search_box(struct doveadm_mail_cmd_context *ctx,
{
struct doveadm_mail_iter *iter;
struct mailbox *box;
- struct mailbox_transaction_context *trans;
struct mail *mail;
struct mailbox_metadata metadata;
const char *guid_str;
int ret = 0;
if (doveadm_mail_iter_init(ctx, info, ctx->search_args, 0, NULL,
- &trans, &iter) < 0)
+ &iter) < 0)
return -1;
- box = mailbox_transaction_get_mailbox(trans);
+ box = doveadm_mail_iter_get_mailbox(iter);
if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
ret = -1;
--
1.7.10.2
From f6b7f1619435fc5aec8a689ca67058dff94288fa Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 17:30:07 +0300
Subject: [PATCH] doveadm: If search query attempts to access nonexistent
mailbox, just ignore it. Most importantly running a query
for multiple users wouldn't be an error if the mailbox
existed only for some users. It's probably cleaner to then
always just ignore the nonexistent mailboxes.
diff --git a/src/doveadm/doveadm-mail-iter.c b/src/doveadm/doveadm-mail-iter.c
index 52470b4..e3fc33f 100644
--- a/src/doveadm/doveadm-mail-iter.c
+++ b/src/doveadm/doveadm-mail-iter.c
@@ -25,6 +25,8 @@ int doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
{
struct doveadm_mail_iter *iter;
struct mailbox_header_lookup_ctx *headers_ctx;
+ const char *errstr;
+ enum mail_error error;
iter = i_new(struct doveadm_mail_iter, 1);
iter->ctx = ctx;
@@ -33,8 +35,13 @@ int doveadm_mail_iter_init(struct doveadm_mail_cmd_context *ctx,
iter->search_args = search_args;
if (mailbox_sync(iter->box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
- i_error("Syncing mailbox %s failed: %s", info->vname,
- mailbox_get_last_error(iter->box, NULL));
+ errstr = mailbox_get_last_error(iter->box, &error);
+ if (error == MAIL_ERROR_NOTFOUND) {
+ /* just ignore this mailbox */
+ *iter_r = iter;
+ return 0;
+ }
+ i_error("Syncing mailbox %s failed: %s", info->vname, errstr);
doveadm_mail_failed_mailbox(ctx, iter->box);
mailbox_free(&iter->box);
i_free(iter);
@@ -58,13 +65,17 @@ doveadm_mail_iter_deinit_transaction(struct doveadm_mail_iter *iter,
{
int ret = 0;
- if (mailbox_search_deinit(&iter->search_ctx) < 0) {
- i_error("Searching mailbox %s failed: %s",
- mailbox_get_vname(iter->box),
- mailbox_get_last_error(iter->box, NULL));
- ret = -1;
+ if (iter->search_ctx != NULL) {
+ if (mailbox_search_deinit(&iter->search_ctx) < 0) {
+ i_error("Searching mailbox %s failed: %s",
+ mailbox_get_vname(iter->box),
+ mailbox_get_last_error(iter->box, NULL));
+ ret = -1;
+ }
}
- if (commit) {
+ if (iter->t == NULL)
+ ;
+ else if (commit) {
if (mailbox_transaction_commit(&iter->t) < 0) {
i_error("Committing mailbox %s failed: %s",
mailbox_get_vname(iter->box),
@@ -123,6 +134,8 @@ void doveadm_mail_iter_deinit_rollback(struct doveadm_mail_iter **_iter)
bool doveadm_mail_iter_next(struct doveadm_mail_iter *iter,
struct mail **mail_r)
{
+ if (iter->search_ctx == NULL)
+ return FALSE;
return mailbox_search_next(iter->search_ctx, mail_r);
}
--
1.7.10.2
From 9943d869c5c9796ec8cbdc05adf14a52ca58d8de Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 18:35:36 +0300
Subject: [PATCH] lib-imap-urlauth: Don't try to access garbage memory on
error handling paths.
diff --git a/src/lib-imap-urlauth/imap-urlauth-fetch.c b/src/lib-imap-urlauth/imap-urlauth-fetch.c
index 8cee33d..9801822 100644
--- a/src/lib-imap-urlauth/imap-urlauth-fetch.c
+++ b/src/lib-imap-urlauth/imap-urlauth-fetch.c
@@ -150,7 +150,7 @@ imap_urlauth_fetch_local(struct imap_urlauth_fetch *ufetch, const char *url,
const char *error, *errormsg = NULL, *bpstruct = NULL;
bool debug = ufetch->uctx->user->mail_debug, success;
enum mail_error error_code;
- struct imap_msgpart_url *mpurl;
+ struct imap_msgpart_url *mpurl = NULL;
int ret;
ufetch->pending_requests--;
diff --git a/src/lib-imap-urlauth/imap-urlauth.c b/src/lib-imap-urlauth/imap-urlauth.c
index 0019f0e..d4ef76c 100644
--- a/src/lib-imap-urlauth/imap-urlauth.c
+++ b/src/lib-imap-urlauth/imap-urlauth.c
@@ -227,7 +227,7 @@ int imap_urlauth_generate(struct imap_urlauth_context *uctx,
enum imap_url_parse_flags url_flags =
IMAP_URL_PARSE_ALLOW_URLAUTH;
struct imap_url *url;
- struct imap_msgpart_url *mpurl;
+ struct imap_msgpart_url *mpurl = NULL;
struct mailbox *box;
const char *error;
enum mail_error error_code;
@@ -284,7 +284,8 @@ int imap_urlauth_generate(struct imap_urlauth_context *uctx,
if ((ret = imap_msgpart_url_create(user, url, &mpurl, &error)) < 0 ||
imap_msgpart_url_verify(mpurl, &error) <= 0) {
*error_r = t_strdup_printf("Invalid URL: %s", error);
- imap_msgpart_url_free(&mpurl);
+ if (mpurl != NULL)
+ imap_msgpart_url_free(&mpurl);
return ret;
}
box = imap_msgpart_url_get_mailbox(mpurl);
--
1.7.10.2
From 57fb26d8580d1856a9347425f40a8dda03cb0a79 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 19:48:32 +0300
Subject: [PATCH] lib-imap: imap_parser_read_args() shouldn't append multiple
EOLs when calling multiple times.
diff --git a/src/lib-imap/imap-parser.c b/src/lib-imap/imap-parser.c
index 33fcf90..0c48da8 100644
--- a/src/lib-imap/imap-parser.c
+++ b/src/lib-imap/imap-parser.c
@@ -711,11 +711,7 @@ static int finish_line(struct imap_parser *parser, unsigned int count,
arg = array_append_space(&parser->root_list);
arg->type = IMAP_ARG_EOL;
-
- if (!parser->eol)
- parser->args_added_extra_eol = TRUE;
- else
- i_assert(!parser->literal_size_return);
+ parser->args_added_extra_eol = TRUE;
*args_r = array_get(&parser->root_list, &count);
return ret;
--
1.7.10.2
From 72f915906b61b0e82624d9f604adc4688db2f640 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 19:49:18 +0300
Subject: [PATCH] imap: Don't hang in APPEND when giving it invalid
parameters.
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index a7e2b31..91376c1 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -708,12 +708,13 @@ static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
/* parse the entire line up to the first message literal, or in case
the input buffer is full of MULTIAPPEND CATENATE URLs, parse at
least until the beginning of the next message */
- arg_min_count = 1;
+ arg_min_count = 0;
do {
- ret = imap_parser_read_args(ctx->save_parser, arg_min_count++,
+ ret = imap_parser_read_args(ctx->save_parser, ++arg_min_count,
IMAP_PARSE_FLAG_LITERAL_SIZE |
IMAP_PARSE_FLAG_LITERAL8, &args);
- } while (ret > 0 && !cmd_append_args_can_stop(ctx, args));
+ } while (ret >= (int)arg_min_count &&
+ !cmd_append_args_can_stop(ctx, args));
if (ret == -1) {
if (!ctx->failed) {
msg = imap_parser_get_error(ctx->save_parser, &fatal);
--
1.7.10.2
From 40309d92b95e9824170fc51a1160ada8cdec8fdb Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 19:49:55 +0300
Subject: [PATCH] imap: Fixed assert-crash on invalid APPEND parameters.
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index 91376c1..947b959 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -501,9 +501,8 @@ cmd_append_handle_args(struct client_command_context *cmd,
ctx->binary_input = args->literal8;
valid = TRUE;
}
- /* we parsed the args only up to here. */
- i_assert(IMAP_ARG_IS_EOL(&args[1]));
-
+ if (!IMAP_ARG_IS_EOL(&args[1]))
+ valid = FALSE;
if (!valid) {
client->input_skip_line = TRUE;
if (!ctx->failed)
--
1.7.10.2
From 14508b41d6ece32d3fa835f368011b97374e7cf7 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 19:51:07 +0300
Subject: [PATCH] imap: Don't eat away the next command if CATENATE fails.
diff --git a/src/imap/cmd-append.c b/src/imap/cmd-append.c
index 947b959..bc13535 100644
--- a/src/imap/cmd-append.c
+++ b/src/imap/cmd-append.c
@@ -324,7 +324,6 @@ cmd_append_catenate(struct client_command_context *cmd,
}
if (!ctx->failed)
client_send_command_error(cmd, "Invalid arguments.");
- cmd->client->input_skip_line = TRUE;
return -1;
}
@@ -431,9 +430,6 @@ static bool cmd_append_continue_catenate(struct client_command_context *cmd)
/* TEXT <literal> */
- /* after literal comes CRLF, if we fail make sure we eat it away */
- client->input_skip_line = TRUE;
-
if (!nonsync) {
if (ctx->failed) {
/* tagline was already sent, we can abort here */
@@ -738,8 +734,6 @@ static bool cmd_append_parse_new_msg(struct client_command_context *cmd)
ret = cmd_append_handle_args(cmd, args, &nonsync);
if (ret < 0) {
/* invalid parameters, abort immediately */
- if (ctx->catenate)
- client->input_skip_line = TRUE;
cmd_append_finish(ctx);
return TRUE;
}
--
1.7.10.2
From 9a9ed402e6f5e0110f28cb2dff5db78682826479 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 20:15:58 +0300
Subject: [PATCH] imap: Fixed URLFETCH assert-crashes due to output_cmd_lock
not being cleared.
diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c
index 86f1d05..d8c2e7f 100644
--- a/src/imap/cmd-urlfetch.c
+++ b/src/imap/cmd-urlfetch.c
@@ -43,7 +43,14 @@ static void cmd_urlfetch_finish(struct client_command_context *cmd)
imap_urlauth_fetch_deinit(&ctx->ufetch);
if (ctx->failed) {
- client_send_internal_error(cmd);
+ if (cmd->client->output_cmd_lock == cmd) {
+ /* failed in the middle of a literal.
+ we need to disconnect. */
+ cmd->client->output_cmd_lock = NULL;
+ client_disconnect(cmd->client, "URLFETCH failed");
+ } else {
+ client_send_internal_error(cmd);
+ }
return;
}
@@ -147,12 +154,12 @@ static bool cmd_urlfetch_continue(struct client_command_context *cmd)
client_send_line(client, ")");
else
client_send_line(client, "");
+ client->output_cmd_lock = NULL;
if (imap_urlauth_fetch_continue(ctx->ufetch)) {
/* waiting for imap urlauth service */
cmd->state = CLIENT_COMMAND_STATE_WAIT_EXTERNAL;
cmd->func = cmd_urlfetch_cancel;
- client->output_cmd_lock = NULL;
/* retrieve next url */
return FALSE;
--
1.7.10.2
From 9bb3ca1fe8560d8cee51f64097324a9d0935626f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 20:20:43 +0300
Subject: [PATCH] imap: URLFETCH leaked istream on failures.
diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c
index d8c2e7f..92f17b9 100644
--- a/src/imap/cmd-urlfetch.c
+++ b/src/imap/cmd-urlfetch.c
@@ -39,6 +39,8 @@ static void cmd_urlfetch_finish(struct client_command_context *cmd)
return;
ctx->finished = TRUE;
+ if (ctx->input != NULL)
+ i_stream_unref(&ctx->input);
if (ctx->ufetch != NULL)
imap_urlauth_fetch_deinit(&ctx->ufetch);
@@ -225,7 +227,7 @@ static int cmd_urlfetch_url_sucess(struct client_command_context *cmd,
if (reply->input != NULL) {
ctx->input = reply->input;
ctx->size = reply->size;
- i_stream_ref(reply->input);
+ i_stream_ref(ctx->input);
ret = cmd_urlfetch_transfer_literal(cmd);
if (ret < 0) {
--
1.7.10.2
From e37d7cac7729284fb791b4c0016899f52929e157 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 20:21:27 +0300
Subject: [PATCH] imap: URLFETCH sometimes failed thinking it didn't receive
all of the message data.
diff --git a/src/imap/cmd-urlfetch.c b/src/imap/cmd-urlfetch.c
index 92f17b9..5ddfb5f 100644
--- a/src/imap/cmd-urlfetch.c
+++ b/src/imap/cmd-urlfetch.c
@@ -116,7 +116,7 @@ static int cmd_urlfetch_transfer_literal(struct client_command_context *cmd)
client_disconnect(client, "URLFETCH failed");
return -1;
}
- if (!ctx->input->eof) {
+ if (i_stream_have_bytes_left(ctx->input)) {
o_stream_set_flush_pending(client->output, TRUE);
return 0;
}
--
1.7.10.2
From 0c4653587c1d4cfcd212379c154e82af7be8ad00 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Mon, 6 May 2013 23:59:41 +0300
Subject: [PATCH] lib-index: Previous commit sometimes broke scanning
transaction log view. If min_file_seq+offset pointed to the
end of the previous file that no longer existed, we didn't
just skip over it.
diff --git a/src/lib-index/mail-transaction-log-view.c b/src/lib-index/mail-transaction-log-view.c
index 707ad6b..ca51aea 100644
--- a/src/lib-index/mail-transaction-log-view.c
+++ b/src/lib-index/mail-transaction-log-view.c
@@ -95,6 +95,17 @@ int mail_transaction_log_view_set(struct mail_transaction_log_view *view,
}
for (file = view->log->files; file != NULL; file = file->next) {
+ if (file->hdr.prev_file_seq == min_file_seq)
+ break;
+ }
+
+ if (file != NULL && min_file_offset == file->hdr.prev_file_offset) {
+ /* we can (and sometimes must) skip to the next file */
+ min_file_seq = file->hdr.file_seq;
+ min_file_offset = file->hdr.hdr_size;
+ }
+
+ for (file = view->log->files; file != NULL; file = file->next) {
if (file->hdr.prev_file_seq == max_file_seq)
break;
}
--
1.7.10.2
From 67b54367fff8348b1108391baa349a0230c3a839 Mon Sep 17 00:00:00 2001
From: Dennis Schridde <devurandom@gmx.net>
Date: Mon, 13 May 2013 23:06:31 +0200
Subject: [PATCH] Fix out of source build of manpages
diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am
index 4db8cfd..c18e6c3 100644
--- a/doc/man/Makefile.am
+++ b/doc/man/Makefile.am
@@ -85,4 +85,4 @@ CLEANFILES = $(nodist_man1_MANS)
.1.in.1: $(man_includefiles) Makefile
$(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \
- < $(srcdir)/$< > $@
+ < $< > $@
--
1.7.10.2
From 2c4e0324c5aabbcfab02c3b0589d26c24650c535 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 14:00:21 +0300
Subject: [PATCH] login-proxy: Don't crash if connect() succeeds but login
fails with timeout.
diff --git a/src/login-common/login-proxy-state.h b/src/login-common/login-proxy-state.h
index 65e8fbb..eb08e6b 100644
--- a/src/login-common/login-proxy-state.h
+++ b/src/login-common/login-proxy-state.h
@@ -6,8 +6,9 @@
struct login_proxy_record {
struct ip_addr ip;
unsigned int port;
- unsigned int num_waiting_connections;
+ /* these are tracking connect()s, not necessarily logins: */
+ unsigned int num_waiting_connections;
struct timeval last_failure;
struct timeval last_success;
};
diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c
index 9290883..1fdb2cf 100644
--- a/src/login-common/login-proxy.c
+++ b/src/login-common/login-proxy.c
@@ -254,7 +254,8 @@ static void proxy_connect_timeout(struct login_proxy *proxy)
{
errno = ETIMEDOUT;
proxy_log_connect_error(proxy);
- proxy_fail_connect(proxy);
+ if (!proxy->connected)
+ proxy_fail_connect(proxy);
login_proxy_free(&proxy);
}
--
1.7.10.2
From 110d79c741c2173cd187cb0e47c1c56fbbb3fe0b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 14:02:36 +0300
Subject: [PATCH] login-proxy: If login fails with timeout, log what the
proxying state was.
diff --git a/src/login-common/login-proxy.c b/src/login-common/login-proxy.c
index 1fdb2cf..d2833e2 100644
--- a/src/login-common/login-proxy.c
+++ b/src/login-common/login-proxy.c
@@ -208,8 +208,9 @@ proxy_log_connect_error(struct login_proxy *proxy)
str_printfa(str, "connect(%s, %u) failed: %m",
proxy->host, proxy->port);
} else {
- str_printfa(str, "Login for %s:%u timed out",
- proxy->host, proxy->port);
+ str_printfa(str, "Login for %s:%u timed out in state=%u",
+ proxy->host, proxy->port,
+ proxy->client->proxy_state);
}
str_printfa(str, " (after %u secs",
(unsigned int)(ioloop_time - proxy->created.tv_sec));
--
1.7.10.2
From 942e14b174ea3e1a7b00e945c918c8ed936336fa Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 14:14:16 +0300
Subject: [PATCH] configure: Fixed checking for struct sockpeercred with
OpenBSD <5.3
diff --git a/configure.ac b/configure.ac
index a67d511..b9c1ce5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,7 +433,10 @@ AC_CHECK_FUNCS(fcntl flock lockf inet_aton sigaction getpagesize madvise \
walkcontext dirfd clearenv malloc_usable_size glob fallocate \
posix_fadvise getpeereid getpeerucred)
-AC_CHECK_TYPES([struct sockpeercred],,,[#include <sys/socket.h>])
+AC_CHECK_TYPES([struct sockpeercred],,,[
+#include <sys/types.h>
+#include <sys/socket.h>
+])
AC_SEARCH_LIBS(clock_gettime, rt, [
AC_DEFINE(HAVE_CLOCK_GETTIME,, Define if you have the clock_gettime function)
--
1.7.10.2
From eb3938ec8bf9db181964917253eae94477cac2a7 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 16:32:30 +0300
Subject: [PATCH] pop3: Added pop3_deleted_flag setting.
diff --git a/doc/example-config/conf.d/20-pop3.conf b/doc/example-config/conf.d/20-pop3.conf
index be64c2c..ded9fa9 100644
--- a/doc/example-config/conf.d/20-pop3.conf
+++ b/doc/example-config/conf.d/20-pop3.conf
@@ -59,6 +59,13 @@ protocol pop3 {
# rename: Append a temporary -2, -3, etc. counter after the UIDL.
#pop3_uidl_duplicates = allow
+ # This option changes POP3 behavior so that it's not possible to actually
+ # delete mails via POP3, only hide them from future POP3 sessions. The mails
+ # will still be counted towards user's quota until actually deleted via IMAP.
+ # Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword).
+ # Make sure you can legally archive mails before enabling this setting.
+ #pop3_deleted_flag =
+
# POP3 logout format string:
# %i - total number of bytes read from client
# %o - total number of bytes sent to client
diff --git a/src/pop3/pop3-client.c b/src/pop3/pop3-client.c
index e99f7bd..6de571c 100644
--- a/src/pop3/pop3-client.c
+++ b/src/pop3/pop3-client.c
@@ -141,6 +141,7 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r)
struct mailbox_status status;
struct mailbox_transaction_context *t;
struct mail_search_args *search_args;
+ struct mail_search_arg *sarg;
struct mail_search_context *ctx;
struct mail *mail;
uoff_t size;
@@ -158,7 +159,17 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r)
t = mailbox_transaction_begin(client->mailbox, 0);
search_args = mail_search_build_init();
- mail_search_build_add_all(search_args);
+ if (client->deleted_kw != NULL) {
+ sarg = mail_search_build_add(search_args, SEARCH_KEYWORDS);
+ sarg->match_not = TRUE;
+ sarg->value.str = p_strdup(search_args->pool,
+ client->set->pop3_deleted_flag);
+ i_array_init(&client->all_seqs, 32);
+ } else {
+ mail_search_build_add_all(search_args);
+ }
+ mail_search_args_init(search_args, client->mailbox, TRUE, NULL);
+
ctx = mailbox_search_init(t, search_args, pop3_sort_program,
client->set->pop3_fast_size_lookups ? 0 :
MAIL_FETCH_VIRTUAL_SIZE, NULL);
@@ -175,6 +186,8 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r)
*failed_uid_r = mail->uid;
break;
}
+ if (array_is_created(&client->all_seqs))
+ seq_range_array_add(&client->all_seqs, mail->seq);
msgnum_to_seq_map_add(&msgnum_to_seq_map, client, mail, msgnum);
if ((mail_get_flags(mail) & MAIL_SEEN) != 0)
@@ -197,7 +210,13 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r)
array_free(&msgnum_to_seq_map);
return ret;
}
- i_assert(msgnum == client->messages_count);
+ i_assert(msgnum <= client->messages_count);
+ client->messages_count = msgnum;
+
+ if (!array_is_created(&client->all_seqs)) {
+ i_array_init(&client->all_seqs, 1);
+ seq_range_array_add_range(&client->all_seqs, 1, msgnum);
+ }
client->trans = t;
client->message_sizes =
@@ -211,6 +230,26 @@ static int read_mailbox(struct client *client, uint32_t *failed_uid_r)
return 1;
}
+static int init_pop3_deleted_flag(struct client *client, const char **error_r)
+{
+ const char *deleted_keywords[2];
+
+ if (client->set->pop3_deleted_flag[0] == '\0')
+ return 0;
+
+ deleted_keywords[0] = client->set->pop3_deleted_flag;
+ deleted_keywords[1] = NULL;
+ if (mailbox_keywords_create(client->mailbox, deleted_keywords,
+ &client->deleted_kw) < 0) {
+ *error_r = t_strdup_printf(
+ "pop3_deleted_flags: Invalid keyword '%s': %s",
+ client->set->pop3_deleted_flag,
+ mailbox_get_last_error(client->mailbox, NULL));
+ return -1;
+ }
+ return 0;
+}
+
static int init_mailbox(struct client *client, const char **error_r)
{
uint32_t failed_uid = 0, last_failed_uid = 0;
@@ -392,7 +431,8 @@ int client_create(int fd_in, int fd_out, const char *session_id,
}
client->mail_set = mail_storage_get_settings(storage);
- if (init_mailbox(client, &errmsg) < 0) {
+ if (init_pop3_deleted_flag(client, &errmsg) < 0 ||
+ init_mailbox(client, &errmsg) < 0) {
i_error("Couldn't init INBOX: %s", errmsg);
client_destroy(client, "Mailbox init failed");
return -1;
@@ -553,6 +593,9 @@ static void client_default_destroy(struct client *client, const char *reason)
message sizes. */
(void)mailbox_transaction_commit(&client->trans);
}
+ array_free(&client->all_seqs);
+ if (client->deleted_kw != NULL)
+ mailbox_keywords_unref(&client->deleted_kw);
if (client->mailbox != NULL)
mailbox_free(&client->mailbox);
if (client->anvil_sent) {
diff --git a/src/pop3/pop3-client.h b/src/pop3/pop3-client.h
index 5c3bfe5..f8e6c35 100644
--- a/src/pop3/pop3-client.h
+++ b/src/pop3/pop3-client.h
@@ -1,6 +1,8 @@
#ifndef POP3_CLIENT_H
#define POP3_CLIENT_H
+#include "seq-range-array.h"
+
struct client;
struct mail_storage;
@@ -48,6 +50,7 @@ struct client {
struct mail_namespace *inbox_ns;
struct mailbox *mailbox;
struct mailbox_transaction_context *trans;
+ struct mail_keywords *deleted_kw;
struct timeout *to_session_dotlock_refresh;
struct dotlock *session_dotlock;
@@ -63,6 +66,9 @@ struct client {
uoff_t deleted_size;
uint32_t last_seen_pop3_msn, lowest_retr_pop3_msn;
+ /* All sequences currently visible in the mailbox. */
+ ARRAY_TYPE(seq_range) all_seqs;
+
/* [msgnum] contains mail seq. anything after it has seq = msgnum+1 */
uint32_t *msgnum_to_seq_map;
uint32_t msgnum_to_seq_map_count;
diff --git a/src/pop3/pop3-commands.c b/src/pop3/pop3-commands.c
index a617f94..29e1d44 100644
--- a/src/pop3/pop3-commands.c
+++ b/src/pop3/pop3-commands.c
@@ -196,11 +196,12 @@ static struct mail_search_args *
pop3_search_build(struct client *client, uint32_t seq)
{
struct mail_search_args *search_args;
+ struct mail_search_arg *sarg;
search_args = mail_search_build_init();
if (seq == 0) {
- mail_search_build_add_seqset(search_args,
- 1, client->messages_count);
+ sarg = mail_search_build_add(search_args, SEARCH_SEQSET);
+ sarg->value.seqset = client->all_seqs;
} else {
mail_search_build_add_seqset(search_args, seq, seq);
}
@@ -222,6 +223,15 @@ static int client_verify_ordering(struct client *client,
return 0;
}
+static void client_expunge(struct client *client, struct mail *mail)
+{
+ if (client->deleted_kw != NULL)
+ mail_update_keywords(mail, MODIFY_ADD, client->deleted_kw);
+ else
+ mail_expunge(mail);
+ client->expunged_count++;
+}
+
bool client_update_mails(struct client *client)
{
struct mail_search_args *search_args;
@@ -250,8 +260,7 @@ bool client_update_mails(struct client *client)
bit = 1 << (msgnum % CHAR_BIT);
if (client->deleted_bitmask != NULL &&
(client->deleted_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
- mail_expunge(mail);
- client->expunged_count++;
+ client_expunge(client, mail);
} else if (client->seen_bitmask != NULL &&
(client->seen_bitmask[msgnum / CHAR_BIT] & bit) != 0) {
mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
diff --git a/src/pop3/pop3-settings.c b/src/pop3/pop3-settings.c
index 2f3fbff..d9dc69a 100644
--- a/src/pop3/pop3-settings.c
+++ b/src/pop3/pop3-settings.c
@@ -71,6 +71,7 @@ static const struct setting_define pop3_setting_defines[] = {
DEF(SET_STR, pop3_client_workarounds),
DEF(SET_STR, pop3_logout_format),
DEF(SET_ENUM, pop3_uidl_duplicates),
+ DEF(SET_STR, pop3_deleted_flag),
SETTING_DEFINE_LIST_END
};
@@ -86,7 +87,8 @@ static const struct pop3_settings pop3_default_settings = {
.pop3_fast_size_lookups = FALSE,
.pop3_client_workarounds = "",
.pop3_logout_format = "top=%t/%p, retr=%r/%b, del=%d/%m, size=%s",
- .pop3_uidl_duplicates = "allow:rename"
+ .pop3_uidl_duplicates = "allow:rename",
+ .pop3_deleted_flag = ""
};
static const struct setting_parser_info *pop3_setting_dependencies[] = {
diff --git a/src/pop3/pop3-settings.h b/src/pop3/pop3-settings.h
index e9bd2ba..90cbf77 100644
--- a/src/pop3/pop3-settings.h
+++ b/src/pop3/pop3-settings.h
@@ -23,6 +23,7 @@ struct pop3_settings {
const char *pop3_client_workarounds;
const char *pop3_logout_format;
const char *pop3_uidl_duplicates;
+ const char *pop3_deleted_flag;
enum pop3_client_workarounds parsed_workarounds;
};
--
1.7.10.2
From 14aacf975309dc3be388fd067e652a8ec1efc4a3 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 16:46:08 +0300
Subject: [PATCH] example-config: Moved imap_* and pop3_* settings outside
protocol section. There's no need to keep them inside
protocol {}, and in case of pop3_uidl_format=%m setting
it's actually harmful.
diff --git a/doc/example-config/conf.d/20-imap.conf b/doc/example-config/conf.d/20-imap.conf
index 9de1318..689b0ea 100644
--- a/doc/example-config/conf.d/20-imap.conf
+++ b/doc/example-config/conf.d/20-imap.conf
@@ -2,60 +2,60 @@
## IMAP specific settings
##
-protocol imap {
- # Maximum IMAP command line length. Some clients generate very long command
- # lines with huge mailboxes, so you may need to raise this if you get
- # "Too long argument" or "IMAP command line too large" errors often.
- #imap_max_line_length = 64k
+# Maximum IMAP command line length. Some clients generate very long command
+# lines with huge mailboxes, so you may need to raise this if you get
+# "Too long argument" or "IMAP command line too large" errors often.
+#imap_max_line_length = 64k
+
+# IMAP logout format string:
+# %i - total number of bytes read from client
+# %o - total number of bytes sent to client
+#imap_logout_format = in=%i out=%o
+
+# Override the IMAP CAPABILITY response. If the value begins with '+',
+# add the given capabilities on top of the defaults (e.g. +XFOO XBAR).
+#imap_capability =
+
+# How long to wait between "OK Still here" notifications when client is
+# IDLEing.
+#imap_idle_notify_interval = 2 mins
+
+# ID field names and values to send to clients. Using * as the value makes
+# Dovecot use the default value. The following fields have default values
+# currently: name, version, os, os-version, support-url, support-email.
+#imap_id_send =
+
+# ID fields sent by client to log. * means everything.
+#imap_id_log =
+
+# Workarounds for various client bugs:
+# delay-newmail:
+# Send EXISTS/RECENT new mail notifications only when replying to NOOP
+# and CHECK commands. Some clients ignore them otherwise, for example OSX
+# Mail (<v2.1). Outlook Express breaks more badly though, without this it
+# may show user "Message no longer in server" errors. Note that OE6 still
+# breaks even with this workaround if synchronization is set to
+# "Headers Only".
+# tb-extra-mailbox-sep:
+# Thunderbird gets somehow confused with LAYOUT=fs (mbox and dbox) and
+# adds extra '/' suffixes to mailbox names. This option causes Dovecot to
+# ignore the extra '/' instead of treating it as invalid mailbox name.
+# tb-lsub-flags:
+# Show \Noselect flags for LSUB replies with LAYOUT=fs (e.g. mbox).
+# This makes Thunderbird realize they aren't selectable and show them
+# greyed out, instead of only later giving "not selectable" popup error.
+#
+# The list is space-separated.
+#imap_client_workarounds =
- # Maximum number of IMAP connections allowed for a user from each IP address.
- # NOTE: The username is compared case-sensitively.
- #mail_max_userip_connections = 10
+# Host allowed in URLAUTH URLs sent by client. "*" allows all.
+#imap_urlauth_host =
+protocol imap {
# Space separated list of plugins to load (default is global mail_plugins).
#mail_plugins = $mail_plugins
- # IMAP logout format string:
- # %i - total number of bytes read from client
- # %o - total number of bytes sent to client
- #imap_logout_format = in=%i out=%o
-
- # Override the IMAP CAPABILITY response. If the value begins with '+',
- # add the given capabilities on top of the defaults (e.g. +XFOO XBAR).
- #imap_capability =
-
- # How long to wait between "OK Still here" notifications when client is
- # IDLEing.
- #imap_idle_notify_interval = 2 mins
-
- # ID field names and values to send to clients. Using * as the value makes
- # Dovecot use the default value. The following fields have default values
- # currently: name, version, os, os-version, support-url, support-email.
- #imap_id_send =
-
- # ID fields sent by client to log. * means everything.
- #imap_id_log =
-
- # Workarounds for various client bugs:
- # delay-newmail:
- # Send EXISTS/RECENT new mail notifications only when replying to NOOP
- # and CHECK commands. Some clients ignore them otherwise, for example OSX
- # Mail (<v2.1). Outlook Express breaks more badly though, without this it
- # may show user "Message no longer in server" errors. Note that OE6 still
- # breaks even with this workaround if synchronization is set to
- # "Headers Only".
- # tb-extra-mailbox-sep:
- # Thunderbird gets somehow confused with LAYOUT=fs (mbox and dbox) and
- # adds extra '/' suffixes to mailbox names. This option causes Dovecot to
- # ignore the extra '/' instead of treating it as invalid mailbox name.
- # tb-lsub-flags:
- # Show \Noselect flags for LSUB replies with LAYOUT=fs (e.g. mbox).
- # This makes Thunderbird realize they aren't selectable and show them
- # greyed out, instead of only later giving "not selectable" popup error.
- #
- # The list is space-separated.
- #imap_client_workarounds =
+ # Maximum number of IMAP connections allowed for a user from each IP address.
+ # NOTE: The username is compared case-sensitively.
+ #mail_max_userip_connections = 10
}
-
-# Host allowed in URLAUTH URLs sent by client. "*" allows all.
-#imap_urlauth_host =
diff --git a/doc/example-config/conf.d/20-pop3.conf b/doc/example-config/conf.d/20-pop3.conf
index ded9fa9..50470e9 100644
--- a/doc/example-config/conf.d/20-pop3.conf
+++ b/doc/example-config/conf.d/20-pop3.conf
@@ -2,97 +2,97 @@
## POP3 specific settings
##
-protocol pop3 {
- # Don't try to set mails non-recent or seen with POP3 sessions. This is
- # mostly intended to reduce disk I/O. With maildir it doesn't move files
- # from new/ to cur/, with mbox it doesn't write Status-header.
- #pop3_no_flag_updates = no
+# Don't try to set mails non-recent or seen with POP3 sessions. This is
+# mostly intended to reduce disk I/O. With maildir it doesn't move files
+# from new/ to cur/, with mbox it doesn't write Status-header.
+#pop3_no_flag_updates = no
- # Support LAST command which exists in old POP3 specs, but has been removed
- # from new ones. Some clients still wish to use this though. Enabling this
- # makes RSET command clear all \Seen flags from messages.
- #pop3_enable_last = no
+# Support LAST command which exists in old POP3 specs, but has been removed
+# from new ones. Some clients still wish to use this though. Enabling this
+# makes RSET command clear all \Seen flags from messages.
+#pop3_enable_last = no
- # If mail has X-UIDL header, use it as the mail's UIDL.
- #pop3_reuse_xuidl = no
+# If mail has X-UIDL header, use it as the mail's UIDL.
+#pop3_reuse_xuidl = no
- # Allow only one POP3 session to run simultaneously for the same user.
- #pop3_lock_session = no
+# Allow only one POP3 session to run simultaneously for the same user.
+#pop3_lock_session = no
- # POP3 requires message sizes to be listed as if they had CR+LF linefeeds.
- # Many POP3 servers violate this by returning the sizes with LF linefeeds,
- # because it's faster to get. When this setting is enabled, Dovecot still
- # tries to do the right thing first, but if that requires opening the
- # message, it fallbacks to the easier (but incorrect) size.
- #pop3_fast_size_lookups = no
+# POP3 requires message sizes to be listed as if they had CR+LF linefeeds.
+# Many POP3 servers violate this by returning the sizes with LF linefeeds,
+# because it's faster to get. When this setting is enabled, Dovecot still
+# tries to do the right thing first, but if that requires opening the
+# message, it fallbacks to the easier (but incorrect) size.
+#pop3_fast_size_lookups = no
- # POP3 UIDL (unique mail identifier) format to use. You can use following
- # variables, along with the variable modifiers described in
- # doc/wiki/Variables.txt (e.g. %Uf for the filename in uppercase)
- #
- # %v - Mailbox's IMAP UIDVALIDITY
- # %u - Mail's IMAP UID
- # %m - MD5 sum of the mailbox headers in hex (mbox only)
- # %f - filename (maildir only)
- # %g - Mail's GUID
- #
- # If you want UIDL compatibility with other POP3 servers, use:
- # UW's ipop3d : %08Xv%08Xu
- # Courier : %f or %v-%u (both might be used simultaneosly)
- # Cyrus (<= 2.1.3) : %u
- # Cyrus (>= 2.1.4) : %v.%u
- # Dovecot v0.99.x : %v.%u
- # tpop3d : %Mf
- #
- # Note that Outlook 2003 seems to have problems with %v.%u format which was
- # Dovecot's default, so if you're building a new server it would be a good
- # idea to change this. %08Xu%08Xv should be pretty fail-safe.
- #
- #pop3_uidl_format = %08Xu%08Xv
+# POP3 UIDL (unique mail identifier) format to use. You can use following
+# variables, along with the variable modifiers described in
+# doc/wiki/Variables.txt (e.g. %Uf for the filename in uppercase)
+#
+# %v - Mailbox's IMAP UIDVALIDITY
+# %u - Mail's IMAP UID
+# %m - MD5 sum of the mailbox headers in hex (mbox only)
+# %f - filename (maildir only)
+# %g - Mail's GUID
+#
+# If you want UIDL compatibility with other POP3 servers, use:
+# UW's ipop3d : %08Xv%08Xu
+# Courier : %f or %v-%u (both might be used simultaneosly)
+# Cyrus (<= 2.1.3) : %u
+# Cyrus (>= 2.1.4) : %v.%u
+# Dovecot v0.99.x : %v.%u
+# tpop3d : %Mf
+#
+# Note that Outlook 2003 seems to have problems with %v.%u format which was
+# Dovecot's default, so if you're building a new server it would be a good
+# idea to change this. %08Xu%08Xv should be pretty fail-safe.
+#
+#pop3_uidl_format = %08Xu%08Xv
- # Permanently save UIDLs sent to POP3 clients, so pop3_uidl_format changes
- # won't change those UIDLs. Currently this works only with Maildir.
- #pop3_save_uidl = no
+# Permanently save UIDLs sent to POP3 clients, so pop3_uidl_format changes
+# won't change those UIDLs. Currently this works only with Maildir.
+#pop3_save_uidl = no
- # What to do about duplicate UIDLs if they exist?
- # allow: Show duplicates to clients.
- # rename: Append a temporary -2, -3, etc. counter after the UIDL.
- #pop3_uidl_duplicates = allow
+# What to do about duplicate UIDLs if they exist?
+# allow: Show duplicates to clients.
+# rename: Append a temporary -2, -3, etc. counter after the UIDL.
+#pop3_uidl_duplicates = allow
- # This option changes POP3 behavior so that it's not possible to actually
- # delete mails via POP3, only hide them from future POP3 sessions. The mails
- # will still be counted towards user's quota until actually deleted via IMAP.
- # Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword).
- # Make sure you can legally archive mails before enabling this setting.
- #pop3_deleted_flag =
+# This option changes POP3 behavior so that it's not possible to actually
+# delete mails via POP3, only hide them from future POP3 sessions. The mails
+# will still be counted towards user's quota until actually deleted via IMAP.
+# Use e.g. "$POP3Deleted" as the value (it will be visible as IMAP keyword).
+# Make sure you can legally archive mails before enabling this setting.
+#pop3_deleted_flag =
- # POP3 logout format string:
- # %i - total number of bytes read from client
- # %o - total number of bytes sent to client
- # %t - number of TOP commands
- # %p - number of bytes sent to client as a result of TOP command
- # %r - number of RETR commands
- # %b - number of bytes sent to client as a result of RETR command
- # %d - number of deleted messages
- # %m - number of messages (before deletion)
- # %s - mailbox size in bytes (before deletion)
- # %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
- #pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
+# POP3 logout format string:
+# %i - total number of bytes read from client
+# %o - total number of bytes sent to client
+# %t - number of TOP commands
+# %p - number of bytes sent to client as a result of TOP command
+# %r - number of RETR commands
+# %b - number of bytes sent to client as a result of RETR command
+# %d - number of deleted messages
+# %m - number of messages (before deletion)
+# %s - mailbox size in bytes (before deletion)
+# %u - old/new UIDL hash. may help finding out if UIDLs changed unexpectedly
+#pop3_logout_format = top=%t/%p, retr=%r/%b, del=%d/%m, size=%s
- # Maximum number of POP3 connections allowed for a user from each IP address.
- # NOTE: The username is compared case-sensitively.
- #mail_max_userip_connections = 10
+# Workarounds for various client bugs:
+# outlook-no-nuls:
+# Outlook and Outlook Express hang if mails contain NUL characters.
+# This setting replaces them with 0x80 character.
+# oe-ns-eoh:
+# Outlook Express and Netscape Mail breaks if end of headers-line is
+# missing. This option simply sends it if it's missing.
+# The list is space-separated.
+#pop3_client_workarounds =
+protocol pop3 {
# Space separated list of plugins to load (default is global mail_plugins).
#mail_plugins = $mail_plugins
- # Workarounds for various client bugs:
- # outlook-no-nuls:
- # Outlook and Outlook Express hang if mails contain NUL characters.
- # This setting replaces them with 0x80 character.
- # oe-ns-eoh:
- # Outlook Express and Netscape Mail breaks if end of headers-line is
- # missing. This option simply sends it if it's missing.
- # The list is space-separated.
- #pop3_client_workarounds =
+ # Maximum number of POP3 connections allowed for a user from each IP address.
+ # NOTE: The username is compared case-sensitively.
+ #mail_max_userip_connections = 10
}
--
1.7.10.2
From 2aa4f8006da495916ccea58bf7e2339dd486508b Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 22:23:27 +0300
Subject: [PATCH] Avoid strict aliasing warnings.
diff --git a/src/lib/hash.h b/src/lib/hash.h
index ead59a1..44c172a 100644
--- a/src/lib/hash.h
+++ b/src/lib/hash.h
@@ -82,13 +82,20 @@ void *hash_table_lookup(const struct hash_table *table, const void *key) ATTR_PU
bool hash_table_lookup_full(const struct hash_table *table,
const void *lookup_key,
void **orig_key_r, void **value_r);
-#define hash_table_lookup_full(table, lookup_key, orig_key_r, value_r) \
+#ifndef __cplusplus
+# define hash_table_lookup_full(table, lookup_key, orig_key_r, value_r) \
hash_table_lookup_full((table)._table, \
(void *)((const char *)(lookup_key) + COMPILE_ERROR_IF_TYPES2_NOT_COMPATIBLE((table)._const_key, (table)._key, lookup_key)), \
- (void **)(void *)((orig_key_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._keyp, orig_key_r) + \
+ (void *)((orig_key_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._keyp, orig_key_r) + \
COMPILE_ERROR_IF_TRUE(sizeof(*orig_key_r) != sizeof(void *))), \
- (void **)(void *)((value_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._valuep, value_r) + \
+ (void *)((value_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._valuep, value_r) + \
COMPILE_ERROR_IF_TRUE(sizeof(*value_r) != sizeof(void *))))
+#else
+/* C++ requires (void **) casting, but that's not possible with strict
+ aliasing, so .. we'll just disable the type checks */
+# define hash_table_lookup_full(table, lookup_key, orig_key_r, value_r) \
+ hash_table_lookup_full((table)._table, lookup_key, orig_key_r, value_r)
+#endif
/* Insert/update node in hash table. The difference is that hash_table_insert()
replaces the key in table to given one, while hash_table_update() doesnt. */
@@ -119,12 +126,20 @@ struct hash_iterate_context *hash_table_iterate_init(struct hash_table *table);
hash_table_iterate_init((table)._table)
bool hash_table_iterate(struct hash_iterate_context *ctx,
void **key_r, void **value_r);
-#define hash_table_iterate(ctx, table, key_r, value_r) \
+#ifndef __cplusplus
+# define hash_table_iterate(ctx, table, key_r, value_r) \
hash_table_iterate(ctx, \
- (void **)(void *)((key_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._keyp, key_r) + \
+ (void *)((key_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._keyp, key_r) + \
COMPILE_ERROR_IF_TRUE(sizeof(*key_r) != sizeof(void *)) + \
COMPILE_ERROR_IF_TRUE(sizeof(*value_r) != sizeof(void *))), \
- (void **)(void *)((value_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._valuep, value_r)))
+ (void *)((value_r) + COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE((table)._valuep, value_r)))
+#else
+/* C++ requires (void **) casting, but that's not possible with strict
+ aliasing, so .. we'll just disable the type checks */
+# define hash_table_iterate(ctx, table, key_r, value_r) \
+ hash_table_iterate(ctx, key_r, value_r)
+#endif
+
void hash_table_iterate_deinit(struct hash_iterate_context **ctx);
/* Hash table isn't resized, and removed nodes aren't removed from
diff --git a/src/plugins/fts-lucene/lucene-wrapper.cc b/src/plugins/fts-lucene/lucene-wrapper.cc
index 1597e03..c57b676 100644
--- a/src/plugins/fts-lucene/lucene-wrapper.cc
+++ b/src/plugins/fts-lucene/lucene-wrapper.cc
@@ -1322,11 +1322,10 @@ lucene_index_search_multi(struct lucene_index *index,
BooleanQuery mailbox_query;
struct hash_iterate_context *iter;
- wchar_t *key;
- struct fts_result *value;
+ void *key, *value;
iter = hash_table_iterate_init(guids);
while (hash_table_iterate(iter, guids, &key, &value)) {
- Term *term = _CLNEW Term(_T("box"), key);
+ Term *term = _CLNEW Term(_T("box"), (wchar_t *)key);
TermQuery *q = _CLNEW TermQuery(term);
mailbox_query.add(q, true, BooleanClause::SHOULD);
}
--
1.7.10.2
From 13bcdd36670bd342e9f56ae303bcefa0484aff6c Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Tue, 14 May 2013 23:34:38 +0300
Subject: [PATCH] auth passwd-file: If we fail to open passwd-file, log a
request error directly. Instead of one error message and
another info message.
diff --git a/src/auth/db-passwd-file.c b/src/auth/db-passwd-file.c
index c43a4e0..eeda7bc 100644
--- a/src/auth/db-passwd-file.c
+++ b/src/auth/db-passwd-file.c
@@ -164,7 +164,8 @@ passwd_file_new(struct db_passwd_file *db, const char *expanded_path)
return pw;
}
-static bool passwd_file_open(struct passwd_file *pw, bool startup)
+static int passwd_file_open(struct passwd_file *pw, bool startup,
+ const char **error_r)
{
const char *no_args = NULL;
struct istream *input;
@@ -176,20 +177,20 @@ static bool passwd_file_open(struct passwd_file *pw, bool startup)
fd = open(pw->path, O_RDONLY);
if (fd == -1) {
- if (errno == EACCES) {
- i_error("passwd-file %s: %s", pw->path,
- eacces_error_get("open", pw->path));
- } else {
- i_error("passwd-file %s: Can't open file: %m",
- pw->path);
+ if (errno == EACCES)
+ *error_r = eacces_error_get("open", pw->path);
+ else {
+ *error_r = t_strdup_printf("open(%s) failed: %m",
+ pw->path);
}
- return FALSE;
+ return -1;
}
if (fstat(fd, &st) != 0) {
- i_error("passwd-file %s: fstat() failed: %m", pw->path);
+ *error_r = t_strdup_printf("fstat(%s) failed: %m",
+ pw->path);
i_close_fd(&fd);
- return FALSE;
+ return -1;
}
pw->fd = fd;
@@ -229,7 +230,7 @@ static bool passwd_file_open(struct passwd_file *pw, bool startup)
i_debug("passwd-file %s: Read %u users in %u secs",
pw->path, hash_table_count(pw->users), time_secs);
}
- return TRUE;
+ return 0;
}
static void passwd_file_close(struct passwd_file *pw)
@@ -256,30 +257,37 @@ static void passwd_file_free(struct passwd_file *pw)
i_free(pw);
}
-static bool passwd_file_sync(struct passwd_file *pw)
+static int passwd_file_sync(struct auth_request *request,
+ struct passwd_file *pw)
{
struct stat st;
+ const char *error;
if (stat(pw->path, &st) < 0) {
/* with variables don't give hard errors, or errors about
nonexistent files */
if (errno == EACCES) {
- i_error("passwd-file %s: %s", pw->path,
- eacces_error_get("stat", pw->path));
- } else if (errno != ENOENT) {
- i_error("passwd-file %s: stat() failed: %m", pw->path);
+ auth_request_log_error(request, "passwd-file",
+ "%s", eacces_error_get("stat", pw->path));
+ } else {
+ auth_request_log_error(request, "passwd-file",
+ "stat(%s) failed: %m", pw->path);
}
if (pw->db->default_file != pw)
passwd_file_free(pw);
- return FALSE;
+ return -1;
}
if (st.st_mtime != pw->stamp || st.st_size != pw->size) {
passwd_file_close(pw);
- return passwd_file_open(pw, FALSE);
+ if (passwd_file_open(pw, FALSE, &error) < 0) {
+ auth_request_log_error(request, "passwd-file",
+ "%s", error);
+ return -1;
+ }
}
- return TRUE;
+ return 0;
}
static struct db_passwd_file *db_passwd_file_find(const char *path)
@@ -359,9 +367,12 @@ db_passwd_file_init(const char *path, bool userdb, bool debug)
void db_passwd_file_parse(struct db_passwd_file *db)
{
+ const char *error;
+
if (db->default_file != NULL && db->default_file->stamp == 0) {
/* no variables, open the file immediately */
- (void)passwd_file_open(db->default_file, TRUE);
+ if (passwd_file_open(db->default_file, TRUE, &error) < 0)
+ i_error("passwd-file: %s", error);
}
}
@@ -421,7 +432,6 @@ db_passwd_file_lookup(struct db_passwd_file *db, struct auth_request *request,
struct passwd_user *pu;
const struct var_expand_table *table;
string_t *username, *dest;
- const char *path;
if (!db->vars)
pw = db->default_file;
@@ -437,11 +447,8 @@ db_passwd_file_lookup(struct db_passwd_file *db, struct auth_request *request,
}
}
- path = t_strdup(pw->path);
- if (!passwd_file_sync(pw)) {
+ if (passwd_file_sync(request, pw) < 0) {
/* pw may be freed now */
- auth_request_log_info(request, "passwd-file",
- "no passwd file: %s", path);
return NULL;
}
--
1.7.10.2
From 3098ef40cba6126700c24074a24eaa9dfd8252b2 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 12:48:21 +0300
Subject: [PATCH] example-config: auth-*.conf.ext should say they're included
by 10-auth.conf
diff --git a/doc/example-config/conf.d/auth-checkpassword.conf.ext b/doc/example-config/conf.d/auth-checkpassword.conf.ext
index 02efae3..b2fb13a 100644
--- a/doc/example-config/conf.d/auth-checkpassword.conf.ext
+++ b/doc/example-config/conf.d/auth-checkpassword.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for checkpassword users. Included from auth.conf.
+# Authentication for checkpassword users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.CheckPassword.txt>
diff --git a/doc/example-config/conf.d/auth-deny.conf.ext b/doc/example-config/conf.d/auth-deny.conf.ext
index f2d897d..ce3f1cf 100644
--- a/doc/example-config/conf.d/auth-deny.conf.ext
+++ b/doc/example-config/conf.d/auth-deny.conf.ext
@@ -1,4 +1,4 @@
-# Deny access for users. Included from auth.conf.
+# Deny access for users. Included from 10-auth.conf.
# Users can be (temporarily) disabled by adding a passdb with deny=yes.
# If the user is found from that database, authentication will fail.
diff --git a/doc/example-config/conf.d/auth-ldap.conf.ext b/doc/example-config/conf.d/auth-ldap.conf.ext
index 3e5c51f..5db32fa 100644
--- a/doc/example-config/conf.d/auth-ldap.conf.ext
+++ b/doc/example-config/conf.d/auth-ldap.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for LDAP users. Included from auth.conf.
+# Authentication for LDAP users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.LDAP.txt>
diff --git a/doc/example-config/conf.d/auth-master.conf.ext b/doc/example-config/conf.d/auth-master.conf.ext
index 8e5107f..2cf128f 100644
--- a/doc/example-config/conf.d/auth-master.conf.ext
+++ b/doc/example-config/conf.d/auth-master.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for master users. Included from auth.conf.
+# Authentication for master users. Included from 10-auth.conf.
# By adding master=yes setting inside a passdb you make the passdb a list
# of "master users", who can log in as anyone else.
diff --git a/doc/example-config/conf.d/auth-passwdfile.conf.ext b/doc/example-config/conf.d/auth-passwdfile.conf.ext
index 5554957..c89d28c 100644
--- a/doc/example-config/conf.d/auth-passwdfile.conf.ext
+++ b/doc/example-config/conf.d/auth-passwdfile.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for passwd-file users. Included from auth.conf.
+# Authentication for passwd-file users. Included from 10-auth.conf.
#
# passwd-like file with specified location.
# <doc/wiki/AuthDatabase.PasswdFile.txt>
diff --git a/doc/example-config/conf.d/auth-sql.conf.ext b/doc/example-config/conf.d/auth-sql.conf.ext
index 9ba585b..ccbea86 100644
--- a/doc/example-config/conf.d/auth-sql.conf.ext
+++ b/doc/example-config/conf.d/auth-sql.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for SQL users. Included from auth.conf.
+# Authentication for SQL users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.SQL.txt>
diff --git a/doc/example-config/conf.d/auth-static.conf.ext b/doc/example-config/conf.d/auth-static.conf.ext
index 238d517..90890c5 100644
--- a/doc/example-config/conf.d/auth-static.conf.ext
+++ b/doc/example-config/conf.d/auth-static.conf.ext
@@ -1,4 +1,4 @@
-# Static passdb. Included from auth.conf.
+# Static passdb. Included from 10-auth.conf.
# This can be used for situations where Dovecot doesn't need to verify the
# username or the password, or if there is a single password for all users:
diff --git a/doc/example-config/conf.d/auth-system.conf.ext b/doc/example-config/conf.d/auth-system.conf.ext
index 260c080..23f943c 100644
--- a/doc/example-config/conf.d/auth-system.conf.ext
+++ b/doc/example-config/conf.d/auth-system.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for system users. Included from auth.conf.
+# Authentication for system users. Included from 10-auth.conf.
#
# <doc/wiki/PasswordDatabase.txt>
# <doc/wiki/UserDatabase.txt>
diff --git a/doc/example-config/conf.d/auth-vpopmail.conf.ext b/doc/example-config/conf.d/auth-vpopmail.conf.ext
index 355237d..f2da976 100644
--- a/doc/example-config/conf.d/auth-vpopmail.conf.ext
+++ b/doc/example-config/conf.d/auth-vpopmail.conf.ext
@@ -1,4 +1,4 @@
-# Authentication for vpopmail users. Included from auth.conf.
+# Authentication for vpopmail users. Included from 10-auth.conf.
#
# <doc/wiki/AuthDatabase.VPopMail.txt>
--
1.7.10.2
From 68f86f89ba6ade74b215a65cc35dc0877241ccd8 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 12:50:03 +0300
Subject: [PATCH] example-config: Removed dovecot-db.conf.ext since Berkeley
DB support is never built in.
diff --git a/doc/example-config/dovecot-db.conf.ext b/doc/example-config/dovecot-db.conf.ext
deleted file mode 100644
index 165dc13..0000000
--- a/doc/example-config/dovecot-db.conf.ext
+++ /dev/null
@@ -1,11 +0,0 @@
-# Example DB_CONFIG for Berkeley DB. Typically dict_db_config setting is used
-# to point to this file.
-# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/env/db_config.html
-
-# Maximum number of simultaneous transactions.
-set_tx_max 1000
-
-# http://www.oracle.com/technology/documentation/berkeley-db/db/ref/lock/max.html
-#set_lk_max_locks 1000
-#set_lk_max_lockers 1000
-#set_lk_max_objects 1000
--
1.7.10.2
From 43e1226ce6ef93aaaf1fb51789949ec6464eee13 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 12:50:29 +0300
Subject: [PATCH] Makefile: Removed dovecot-db.conf.ext
diff --git a/doc/example-config/Makefile.am b/doc/example-config/Makefile.am
index d609f06..5a2dd8b 100644
--- a/doc/example-config/Makefile.am
+++ b/doc/example-config/Makefile.am
@@ -12,7 +12,6 @@ README: README.in Makefile
exampledir = $(docdir)/example-config
example_DATA = \
dovecot.conf \
- dovecot-db.conf.ext \
dovecot-dict-auth.conf.ext \
dovecot-dict-sql.conf.ext \
dovecot-ldap.conf.ext \
--
1.7.10.2
From 2dcba78690d3e7282afdf0012c98ea08924c49da Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 12:52:29 +0300
Subject: [PATCH] example-config: Added comment how all *.conf.ext files are
accessed typically.
diff --git a/doc/example-config/dovecot-dict-auth.conf.ext b/doc/example-config/dovecot-dict-auth.conf.ext
index 7e79d3c..50617bb 100644
--- a/doc/example-config/dovecot-dict-auth.conf.ext
+++ b/doc/example-config/dovecot-dict-auth.conf.ext
@@ -1,3 +1,5 @@
+# This file is commonly accessed via dict {} section in dovecot.conf
+
# Dictionary URI
#uri =
diff --git a/doc/example-config/dovecot-dict-sql.conf.ext b/doc/example-config/dovecot-dict-sql.conf.ext
index 674a25f..a9a903f 100644
--- a/doc/example-config/dovecot-dict-sql.conf.ext
+++ b/doc/example-config/dovecot-dict-sql.conf.ext
@@ -1,3 +1,5 @@
+# This file is commonly accessed via dict {} section in dovecot.conf
+
#connect = host=localhost dbname=mails user=testuser password=pass
# CREATE TABLE quota (
diff --git a/doc/example-config/dovecot-ldap.conf.ext b/doc/example-config/dovecot-ldap.conf.ext
index 7dcc748..1ca6733 100644
--- a/doc/example-config/dovecot-ldap.conf.ext
+++ b/doc/example-config/dovecot-ldap.conf.ext
@@ -1,3 +1,6 @@
+# This file is commonly accessed via passdb {} or userdb {} section in
+# conf.d/auth-ldap.conf.ext
+
# This file is opened as root, so it should be owned by root and mode 0600.
#
# http://wiki2.dovecot.org/AuthDatabase/LDAP
diff --git a/doc/example-config/dovecot-sql.conf.ext b/doc/example-config/dovecot-sql.conf.ext
index b650c57..77e8187 100644
--- a/doc/example-config/dovecot-sql.conf.ext
+++ b/doc/example-config/dovecot-sql.conf.ext
@@ -1,3 +1,6 @@
+# This file is commonly accessed via passdb {} or userdb {} section in
+# conf.d/auth-sql.conf.ext
+
# This file is opened as root, so it should be owned by root and mode 0600.
#
# http://wiki2.dovecot.org/AuthDatabase/SQL
--
1.7.10.2
From 36faafec8112b7f76ec89597510925ca85873acd Mon Sep 17 00:00:00 2001
From: Florian Zeitz <florob@babelmonkeys.de>
Date: Sat, 11 May 2013 17:08:12 +0200
Subject: [PATCH] liblib: Fix Unicode decomposition
diff --git a/src/lib/test-unichar.c b/src/lib/test-unichar.c
index abb6357..b7bb258 100644
--- a/src/lib/test-unichar.c
+++ b/src/lib/test-unichar.c
@@ -2,11 +2,15 @@
#include "test-lib.h"
#include "str.h"
+#include "buffer.h"
#include "unichar.h"
void test_unichar(void)
{
- static const char *overlong_utf8 = "\xf8\x80\x95\x81\xa1";
+ static const char overlong_utf8[] = "\xf8\x80\x95\x81\xa1";
+ static const char collate_in[] = "\xc3\xbc \xc2\xb3";
+ static const char collate_exp[] = "U\xcc\x88 3";
+ buffer_t *collate_out;
unichar_t chr, chr2;
string_t *str = t_str_new(16);
@@ -18,6 +22,13 @@ void test_unichar(void)
test_assert(uni_utf8_get_char(str_c(str), &chr2) > 0);
test_assert(chr2 == chr);
}
+
+ collate_out = buffer_create_dynamic(default_pool, 32);
+ uni_utf8_to_decomposed_titlecase(collate_in, sizeof(collate_in),
+ collate_out);
+ test_assert(!strcmp(collate_out->data, collate_exp));
+ buffer_free(&collate_out);
+
test_assert(!uni_utf8_str_is_valid(overlong_utf8));
test_assert(uni_utf8_get_char(overlong_utf8, &chr2) < 0);
test_end();
diff --git a/src/lib/unichar.c b/src/lib/unichar.c
index b0c50f5..97b0aaf 100644
--- a/src/lib/unichar.c
+++ b/src/lib/unichar.c
@@ -287,7 +287,7 @@ static void uni_ucs4_decompose_hangul_utf8(unichar_t chr, buffer_t *output)
static bool uni_ucs4_decompose_multi_utf8(unichar_t chr, buffer_t *output)
{
- const uint16_t *value;
+ const uint32_t *value;
unsigned int idx;
if (chr < multidecomp_keys[0] || chr > 0xffff)
diff --git a/src/lib/unicodemap.pl b/src/lib/unicodemap.pl
index c18c273..2c1bf7a 100755
--- a/src/lib/unicodemap.pl
+++ b/src/lib/unicodemap.pl
@@ -30,14 +30,14 @@ while (<>) {
push @titlecase32_keys, $code;
push @titlecase32_values, $value;
}
- } elsif ($decomp =~ /\<[^>]*> (.+)/) {
+ } elsif ($decomp =~ /(?:\<[^>]*> )?(.+)/) {
# decompositions
my $decomp_codes = $1;
if ($decomp_codes =~ /^([0-9A-Z]*)$/i) {
# unicharacter decomposition. use separate lists for this
my $value = eval("0x$1");
- if ($value > 0xffff) {
- print STDERR "Error: We've assumed decomposition codes are max. 16bit\n";
+ if ($value > 0xffffffff) {
+ print STDERR "Error: We've assumed decomposition codes are max. 32bit\n";
exit 1;
}
if ($code <= 0xff) {
@@ -61,8 +61,8 @@ while (<>) {
foreach my $dcode (split(" ", $decomp_codes)) {
my $value = eval("0x$dcode");
- if ($value > 0xffff) {
- print STDERR "Error: We've assumed decomposition codes are max. 16bit\n";
+ if ($value > 0xffffffff) {
+ print STDERR "Error: We've assumed decomposition codes are max. 32bit\n";
exit 1;
}
push @multidecomp_values, $value;
@@ -78,7 +78,7 @@ sub print_list {
my $last = $#list;
my $n = 0;
foreach my $key (@list) {
- printf("0x%04x", $key);
+ printf("0x%05x", $key);
last if ($n == $last);
print ",";
@@ -137,7 +137,7 @@ print "static const uint16_t uni16_decomp_keys[] = {\n\t";
print_list(\@uni16_decomp_keys);
print "\n};\n";
-print "static const uint16_t uni16_decomp_values[] = {\n\t";
+print "static const uint32_t uni16_decomp_values[] = {\n\t";
print_list(\@uni16_decomp_values);
print "\n};\n";
@@ -145,7 +145,7 @@ print "static const uint32_t uni32_decomp_keys[] = {\n\t";
print_list(\@uni32_decomp_keys);
print "\n};\n";
-print "static const uint16_t uni32_decomp_values[] = {\n\t";
+print "static const uint32_t uni32_decomp_values[] = {\n\t";
print_list(\@uni32_decomp_values);
print "\n};\n";
@@ -157,6 +157,6 @@ print "static const uint16_t multidecomp_offsets[] = {\n\t";
print_list(\@multidecomp_offsets);
print "\n};\n";
-print "static const uint16_t multidecomp_values[] = {\n\t";
+print "static const uint32_t multidecomp_values[] = {\n\t";
print_list(\@multidecomp_values);
print "\n};\n";
--
1.7.10.2
From b92f8fd079ad5aae050cc1e560d1f3bf0a4fd14f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 13:20:43 +0300
Subject: [PATCH] lib-storage: Added mail_always_cache_fields setting.
diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c
index a4c1061..c5c1380 100644
--- a/src/lib-storage/index/index-storage.c
+++ b/src/lib-storage/index/index-storage.c
@@ -65,6 +65,10 @@ static void index_cache_register_defaults(struct mailbox *box)
set_cache_decisions("mail_cache_fields",
set->mail_cache_fields,
MAIL_CACHE_DECISION_TEMP);
+ set_cache_decisions("mail_always_cache_fields",
+ set->mail_always_cache_fields,
+ MAIL_CACHE_DECISION_YES |
+ MAIL_CACHE_DECISION_FORCED);
set_cache_decisions("mail_never_cache_fields",
set->mail_never_cache_fields,
MAIL_CACHE_DECISION_NO |
diff --git a/src/lib-storage/mail-storage-settings.c b/src/lib-storage/mail-storage-settings.c
index 3eb3aa5..67f724d 100644
--- a/src/lib-storage/mail-storage-settings.c
+++ b/src/lib-storage/mail-storage-settings.c
@@ -33,6 +33,7 @@ static const struct setting_define mail_storage_setting_defines[] = {
DEF(SET_STR_VARS, mail_attribute_dict),
DEF(SET_UINT, mail_prefetch_count),
DEF(SET_STR, mail_cache_fields),
+ DEF(SET_STR, mail_always_cache_fields),
DEF(SET_STR, mail_never_cache_fields),
DEF(SET_UINT, mail_cache_min_mail_count),
DEF(SET_TIME, mailbox_idle_check_interval),
@@ -69,6 +70,7 @@ const struct mail_storage_settings mail_storage_default_settings = {
.mail_attribute_dict = "",
.mail_prefetch_count = 0,
.mail_cache_fields = "flags",
+ .mail_always_cache_fields = "",
.mail_never_cache_fields = "imap.envelope",
.mail_cache_min_mail_count = 0,
.mailbox_idle_check_interval = 30,
diff --git a/src/lib-storage/mail-storage-settings.h b/src/lib-storage/mail-storage-settings.h
index aa599f6..aeeadc8 100644
--- a/src/lib-storage/mail-storage-settings.h
+++ b/src/lib-storage/mail-storage-settings.h
@@ -18,6 +18,7 @@ struct mail_storage_settings {
const char *mail_attribute_dict;
unsigned int mail_prefetch_count;
const char *mail_cache_fields;
+ const char *mail_always_cache_fields;
const char *mail_never_cache_fields;
unsigned int mail_cache_min_mail_count;
unsigned int mailbox_idle_check_interval;
--
1.7.10.2
From 20bd7d25419ab4e4bca7d7eef0ba11f50110cb71 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 13:34:59 +0300
Subject: [PATCH] lib-index: Fixed mail_cache_register_fields() decision
updates. Normally this shouldn't matter, except when
mail_*cache_fields settings have been used.
diff --git a/src/lib-index/mail-cache-fields.c b/src/lib-index/mail-cache-fields.c
index 347486e..3cbfc4a 100644
--- a/src/lib-index/mail-cache-fields.c
+++ b/src/lib-index/mail-cache-fields.c
@@ -74,8 +74,8 @@ mail_cache_field_update(struct mail_cache *cache,
i_assert(newfield->type < MAIL_CACHE_FIELD_COUNT);
orig = &cache->fields[newfield->idx];
- if (newfield->decision != MAIL_CACHE_DECISION_NO &&
- orig->field.decision != newfield->decision) {
+ if ((newfield->decision & MAIL_CACHE_DECISION_FORCED) != 0 ||
+ newfield->decision > orig->field.decision) {
orig->field.decision = newfield->decision;
orig->decision_dirty = TRUE;
}
--
1.7.10.2
From 22531ca1ad97537cf96085fe9aac0ba19d7e55aa Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 13:36:43 +0300
Subject: [PATCH] lib-index: Don't mark field decisions dirty when registering
initial cache fields.
diff --git a/src/lib-index/mail-cache-fields.c b/src/lib-index/mail-cache-fields.c
index 3cbfc4a..084331e 100644
--- a/src/lib-index/mail-cache-fields.c
+++ b/src/lib-index/mail-cache-fields.c
@@ -70,18 +70,26 @@ mail_cache_field_update(struct mail_cache *cache,
const struct mail_cache_field *newfield)
{
struct mail_cache_field_private *orig;
+ bool initial_registering;
i_assert(newfield->type < MAIL_CACHE_FIELD_COUNT);
+ /* are we still doing the initial cache field registering for
+ internal fields and for mail_*cache_fields settings? */
+ initial_registering = cache->file_fields_count == 0;
+
orig = &cache->fields[newfield->idx];
if ((newfield->decision & MAIL_CACHE_DECISION_FORCED) != 0 ||
- newfield->decision > orig->field.decision) {
+ ((orig->field.decision & MAIL_CACHE_DECISION_FORCED) == 0 &&
+ newfield->decision > orig->field.decision)) {
orig->field.decision = newfield->decision;
- orig->decision_dirty = TRUE;
+ if (!initial_registering)
+ orig->decision_dirty = TRUE;
}
if (orig->field.last_used < newfield->last_used) {
orig->field.last_used = newfield->last_used;
- orig->decision_dirty = TRUE;
+ if (!initial_registering)
+ orig->decision_dirty = TRUE;
}
if (orig->decision_dirty)
cache->field_header_write_pending = TRUE;
--
1.7.10.2
From 8449d1499abda0d5e0667a2a95298d4863a45265 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 13:44:01 +0300
Subject: [PATCH] lib-storage: Allow mail_*cache_fields settings to specify
any hdr.* fields. Also the fields were previously set only
once globally, so if the process served multiple users, it
wouldn't have been possible to use per-user values for
these fields.
diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c
index c5c1380..727767f 100644
--- a/src/lib-storage/index/index-storage.c
+++ b/src/lib-storage/index/index-storage.c
@@ -28,27 +28,35 @@
struct index_storage_module index_storage_module =
MODULE_CONTEXT_INIT(&mail_storage_module_register);
-static void set_cache_decisions(const char *set, const char *fields,
+static void set_cache_decisions(struct mail_cache *cache,
+ const char *set, const char *fields,
enum mail_cache_decision_type dec)
{
+ struct mail_cache_field field;
const char *const *arr;
- int i;
+ unsigned int idx;
if (fields == NULL || *fields == '\0')
return;
for (arr = t_strsplit_spaces(fields, " ,"); *arr != NULL; arr++) {
- for (i = 0; i < MAIL_INDEX_CACHE_FIELD_COUNT; i++) {
- if (strcasecmp(global_cache_fields[i].name,
- *arr) == 0) {
- global_cache_fields[i].decision = dec;
- break;
- }
- }
- if (i == MAIL_INDEX_CACHE_FIELD_COUNT) {
- i_error("%s: Invalid cache field name '%s', ignoring ",
+ const char *name = *arr;
+
+ idx = mail_cache_register_lookup(cache, name);
+ if (idx != UINT_MAX) {
+ field = *mail_cache_register_get_field(cache, idx);
+ } else if (strncasecmp(name, "hdr.", 4) == 0) {
+ memset(&field, 0, sizeof(field));
+ field.name = name;
+ field.type = MAIL_CACHE_FIELD_HEADER;
+ } else {
+ i_error("%s: Unknown cache field name '%s', ignoring",
set, *arr);
+ continue;
}
+
+ field.decision = dec;
+ mail_cache_register_fields(cache, &field, 1);
}
}
@@ -56,30 +64,24 @@ static void index_cache_register_defaults(struct mailbox *box)
{
struct index_mailbox_context *ibox = INDEX_STORAGE_CONTEXT(box);
const struct mail_storage_settings *set = box->storage->set;
- static bool initialized = FALSE;
struct mail_cache *cache = box->cache;
- if (!initialized) {
- initialized = TRUE;
-
- set_cache_decisions("mail_cache_fields",
- set->mail_cache_fields,
- MAIL_CACHE_DECISION_TEMP);
- set_cache_decisions("mail_always_cache_fields",
- set->mail_always_cache_fields,
- MAIL_CACHE_DECISION_YES |
- MAIL_CACHE_DECISION_FORCED);
- set_cache_decisions("mail_never_cache_fields",
- set->mail_never_cache_fields,
- MAIL_CACHE_DECISION_NO |
- MAIL_CACHE_DECISION_FORCED);
- }
-
ibox->cache_fields = i_malloc(sizeof(global_cache_fields));
memcpy(ibox->cache_fields, global_cache_fields,
sizeof(global_cache_fields));
mail_cache_register_fields(cache, ibox->cache_fields,
MAIL_INDEX_CACHE_FIELD_COUNT);
+ set_cache_decisions(cache, "mail_cache_fields",
+ set->mail_cache_fields,
+ MAIL_CACHE_DECISION_TEMP);
+ set_cache_decisions(cache, "mail_always_cache_fields",
+ set->mail_always_cache_fields,
+ MAIL_CACHE_DECISION_YES |
+ MAIL_CACHE_DECISION_FORCED);
+ set_cache_decisions(cache, "mail_never_cache_fields",
+ set->mail_never_cache_fields,
+ MAIL_CACHE_DECISION_NO |
+ MAIL_CACHE_DECISION_FORCED);
}
void index_storage_lock_notify(struct mailbox *box,
--
1.7.10.2
From e73e2223cf1a42d87c1fcd8ede02998a69036415 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 14:28:04 +0300
Subject: [PATCH] quota-status: If quota_status_* settings are set, don't free
them before using.
diff --git a/src/plugins/quota/quota-status.c b/src/plugins/quota/quota-status.c
index bfac5e7..bff7540 100644
--- a/src/plugins/quota/quota-status.c
+++ b/src/plugins/quota/quota-status.c
@@ -109,6 +109,7 @@ static void client_handle_request(struct quota_client *client)
if (value == NULL)
value = t_strdup_printf("554 5.2.2 %s\n\n", error);
}
+ value = t_strdup(value); /* user's pool is being freed */
mail_user_unref(&user);
mail_storage_service_user_free(&service_user);
}
--
1.7.10.2
From eee84842f41ed4e0753fb49199ea930f9e2b613a Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 15:06:24 +0300
Subject: [PATCH] Added asserts to binary searches to make sure we don't go to
infinite loop. Using idx=left+(right-left)/2 would have
worked also to allow 4GB sizes, but since none of the
places in the code are likely to reach 2GB we might as well
just add an assert. (Also if they do reach 2GB, it could be
possible that they could reach also above 4GB and cause
problems. Better to see an early error.)
diff --git a/src/lib-index/mail-index-map.c b/src/lib-index/mail-index-map.c
index e1275dc..a735c3c 100644
--- a/src/lib-index/mail-index-map.c
+++ b/src/lib-index/mail-index-map.c
@@ -514,6 +514,7 @@ static uint32_t mail_index_bsearch_uid(struct mail_index_map *map,
idx = left_idx;
right_idx = I_MIN(map->hdr.messages_count, uid);
+ i_assert(right_idx < INT_MAX);
while (left_idx < right_idx) {
idx = (left_idx + right_idx) / 2;
diff --git a/src/lib-index/mail-index-transaction-update.c b/src/lib-index/mail-index-transaction-update.c
index f7887bf..aae27e2 100644
--- a/src/lib-index/mail-index-transaction-update.c
+++ b/src/lib-index/mail-index-transaction-update.c
@@ -402,6 +402,7 @@ mail_index_transaction_get_flag_update_pos(struct mail_index_transaction *t,
updates = array_get(&t->updates, &count);
i_assert(left_idx <= right_idx && right_idx <= count);
+ i_assert(count < INT_MAX);
/* find the first update with either overlapping range,
or the update which will come after our insert */
diff --git a/src/lib-storage/index/index-sort-string.c b/src/lib-storage/index/index-sort-string.c
index 0f1f486..17270d3 100644
--- a/src/lib-storage/index/index-sort-string.c
+++ b/src/lib-storage/index/index-sort-string.c
@@ -382,6 +382,7 @@ index_sort_bsearch(struct sort_string_context *ctx, const char *key,
int ret;
nodes = array_get_modifiable(&ctx->nonzero_nodes, &right_idx);
+ i_assert(right_idx < INT_MAX);
idx = left_idx = start_idx;
while (left_idx < right_idx) {
idx = (left_idx + right_idx) / 2;
diff --git a/src/lib/bsearch-insert-pos.c b/src/lib/bsearch-insert-pos.c
index 7bb9e53..d9feebf 100644
--- a/src/lib/bsearch-insert-pos.c
+++ b/src/lib/bsearch-insert-pos.c
@@ -13,6 +13,8 @@ bool bsearch_insert_pos(const void *key, const void *base, unsigned int nmemb,
unsigned int idx, left_idx, right_idx;
int ret;
+ i_assert(nmemb < INT_MAX);
+
idx = 0; left_idx = 0; right_idx = nmemb;
while (left_idx < right_idx) {
idx = (left_idx + right_idx) / 2;
diff --git a/src/lib/bsearch-insert-pos.h b/src/lib/bsearch-insert-pos.h
index 64b547b..52552d0 100644
--- a/src/lib/bsearch-insert-pos.h
+++ b/src/lib/bsearch-insert-pos.h
@@ -5,6 +5,7 @@
#define BINARY_NUMBER_SEARCH(data, count, value, idx_r) \
unsigned int idx, left_idx, right_idx; \
\
+ i_assert((count) < INT_MAX); \
idx = 0; left_idx = 0; right_idx = (count); \
while (left_idx < right_idx) { \
idx = (left_idx + right_idx) / 2; \
diff --git a/src/lib/seq-range-array.c b/src/lib/seq-range-array.c
index 132fc22..c1a1af9 100644
--- a/src/lib/seq-range-array.c
+++ b/src/lib/seq-range-array.c
@@ -12,6 +12,7 @@ seq_range_lookup(const ARRAY_TYPE(seq_range) *array,
unsigned int idx, left_idx, right_idx, count;
data = array_get(array, &count);
+ i_assert(count < INT_MAX);
idx = 0; left_idx = 0; right_idx = count;
while (left_idx < right_idx) {
@@ -198,6 +199,7 @@ bool seq_range_array_remove(ARRAY_TYPE(seq_range) *array, uint32_t seq)
/* somewhere in the middle, array is sorted so find it with
binary search */
+ i_assert(count < INT_MAX);
left_idx = 0; right_idx = count;
while (left_idx < right_idx) {
idx = (left_idx + right_idx) / 2;
--
1.7.10.2
From f8034a3a01bb4ad01255fa9f059422dc9381b2d1 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 15:26:47 +0300
Subject: [PATCH] maildir: Fixed handling over 26 keywords in a mailbox.
diff --git a/src/lib-storage/index/maildir/maildir-sync-index.c b/src/lib-storage/index/maildir/maildir-sync-index.c
index 6869489..299da72 100644
--- a/src/lib-storage/index/maildir/maildir-sync-index.c
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c
@@ -390,10 +390,11 @@ maildir_sync_mail_keywords(struct maildir_index_sync_context *ctx, uint32_t seq)
old_indexes = array_get(&ctx->idx_keywords, &old_count);
have_indexonly_keywords = FALSE;
for (i = old_count; i > 0; i--) {
- if (old_indexes[i-1] < MAILDIR_MAX_KEYWORDS)
- break;
- have_indexonly_keywords = TRUE;
- array_delete(&ctx->idx_keywords, i-1, 1);
+ if (maildir_keywords_idx_char(ctx->keywords_sync_ctx,
+ old_indexes[i-1]) == '\0') {
+ have_indexonly_keywords = TRUE;
+ array_delete(&ctx->idx_keywords, i-1, 1);
+ }
}
if (!have_indexonly_keywords) {
--
1.7.10.2
From 8db81610a50c448d483fb4bf6f4d1ee25ebeb797 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 15:35:10 +0300
Subject: [PATCH] imap: Return how long SELECT or EXAMINE command took to
answer. Could be useful to know sometimes if there's a
large maildir where a lot files need to be rename()d.
diff --git a/src/imap/cmd-select.c b/src/imap/cmd-select.c
index 46d07b9..966ed2f 100644
--- a/src/imap/cmd-select.c
+++ b/src/imap/cmd-select.c
@@ -2,6 +2,7 @@
#include "imap-common.h"
#include "seq-range-array.h"
+#include "time-util.h"
#include "imap-commands.h"
#include "mail-search-build.h"
#include "imap-search-args.h"
@@ -16,6 +17,7 @@ struct imap_select_context {
struct mail_namespace *ns;
struct mailbox *box;
+ struct timeval start_time;
struct imap_fetch_context *fetch_ctx;
uint32_t qresync_uid_validity;
@@ -198,14 +200,24 @@ static void select_context_free(struct imap_select_context *ctx)
static void cmd_select_finish(struct imap_select_context *ctx, int ret)
{
+ const char *resp_code;
+ struct timeval end_time;
+ int time_msecs;
+
if (ret < 0) {
if (ctx->box != NULL)
mailbox_free(&ctx->box);
ctx->cmd->client->mailbox = NULL;
} else {
- client_send_tagline(ctx->cmd, mailbox_is_readonly(ctx->box) ?
- "OK [READ-ONLY] Select completed." :
- "OK [READ-WRITE] Select completed.");
+ resp_code = mailbox_is_readonly(ctx->box) ?
+ "READ-ONLY" : "READ-WRITE";
+ if (gettimeofday(&end_time, NULL) < 0)
+ memset(&end_time, 0, sizeof(end_time));
+ time_msecs = timeval_diff_msecs(&end_time, &ctx->start_time);
+ client_send_tagline(ctx->cmd, t_strdup_printf(
+ "OK [%s] %s completed (%d.%03d secs).", resp_code,
+ ctx->cmd->client->mailbox_examined ? "Examine" : "Select",
+ time_msecs/1000, time_msecs%1000));
}
select_context_free(ctx);
}
@@ -398,6 +410,7 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
ctx = p_new(cmd->pool, struct imap_select_context, 1);
ctx->cmd = cmd;
ctx->ns = client_find_namespace(cmd, &mailbox);
+ (void)gettimeofday(&ctx->start_time, NULL);
if (ctx->ns == NULL) {
close_selected_mailbox(client);
return TRUE;
--
1.7.10.2
From 62c9b86b3a5eef87c553cbbee4769fda183f730f Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 16:10:48 +0300
Subject: [PATCH] lib-storage: Don't lose INBOX's \Subscribed flag when
returning it is delayed.
diff --git a/src/lib-storage/list/mailbox-list-iter.c b/src/lib-storage/list/mailbox-list-iter.c
index da95178..9d2b8a9 100644
--- a/src/lib-storage/list/mailbox-list-iter.c
+++ b/src/lib-storage/list/mailbox-list-iter.c
@@ -597,9 +597,12 @@ mailbox_list_ns_iter_try_next(struct mailbox_list_iterate_context *_ctx,
if (info != NULL) {
if (strcasecmp(info->vname, "INBOX") == 0 && ctx->inbox_list) {
/* delay sending INBOX reply. we already saved its
- flags at init stage, except for \Noinferiors */
+ flags at init stage, except for \Noinferiors
+ and subscription states */
ctx->inbox_info.flags |=
- (info->flags & MAILBOX_NOINFERIORS);
+ (info->flags & (MAILBOX_NOINFERIORS |
+ MAILBOX_SUBSCRIBED |
+ MAILBOX_CHILD_SUBSCRIBED));
return FALSE;
}
if (strncasecmp(info->vname, "INBOX", 5) == 0 &&
--
1.7.10.2
From efef70a8310a915cdc7e896106159f1923574055 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 17:09:36 +0300
Subject: [PATCH] layout=fs: Always return INBOX uppercased when listing
mailboxes.
diff --git a/src/lib-storage/list/mailbox-list-fs-iter.c b/src/lib-storage/list/mailbox-list-fs-iter.c
index 9aabf0a..1688264 100644
--- a/src/lib-storage/list/mailbox-list-fs-iter.c
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c
@@ -682,6 +682,7 @@ fs_list_entry(struct fs_list_iterate_context *ctx,
return 0;
}
inbox_flags_set(ctx, child_dir_match);
+ ctx->info.vname = "INBOX"; /* always return uppercased */
ctx->inbox_found = TRUE;
} else if (strcmp(storage_name, "INBOX") == 0 &&
(ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
--
1.7.10.2
From 8a37bc920230ceac1f72d0628e7aa05e5ae0431a Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 17:10:28 +0300
Subject: [PATCH] mbox: If save's input stream fails, fail saving instead of
ignoring the error.
diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c
index 9880083..ff84725 100644
--- a/src/lib-storage/index/mbox/mbox-save.c
+++ b/src/lib-storage/index/mbox/mbox-save.c
@@ -635,6 +635,11 @@ int mbox_save_continue(struct mail_save_context *_ctx)
}
if (ret == 0)
return 0;
+ if (ctx->input->stream_errno != 0) {
+ i_error("read(%s) failed: %m", i_stream_get_name(ctx->input));
+ ctx->failed = TRUE;
+ return -1;
+ }
i_assert(ctx->last_char == '\n');
--
1.7.10.2
From e6237e5511e0dc0a5ab2c3aaaa4ec43968a9c345 Mon Sep 17 00:00:00 2001
From: Timo Sirainen <tss@iki.fi>
Date: Wed, 15 May 2013 17:18:29 +0300
Subject: [PATCH] mbox: Fixed committing transaction after a previous save had
failed.
diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c
index ff84725..218f290 100644
--- a/src/lib-storage/index/mbox/mbox-save.c
+++ b/src/lib-storage/index/mbox/mbox-save.c
@@ -715,6 +715,13 @@ int mbox_save_finish(struct mail_save_context *_ctx)
ctx->mail_offset = (uoff_t)-1;
}
+ if (ctx->seq != 0) {
+ mail_index_expunge(ctx->trans, ctx->seq);
+ /* currently we can't just drop pending cache updates for this
+ one specific record, so we'll reset the whole cache
+ transaction. */
+ mail_cache_transaction_reset(ctx->ctx.transaction->cache_trans);
+ }
index_save_context_free(_ctx);
return ctx->failed ? -1 : 0;
}
--
1.7.10.2