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.

2107 lines
68 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