changeset 12575:c39557b7662d

Merged fixes from v2.0 tree.
author Timo Sirainen <tss@iki.fi>
date Sat, 01 Jan 2011 15:59:02 +0200
parents 917f3699af5b (current diff) c1e71f579adc (diff)
children 1e425fe18dea
files TODO src/imap/imap-search.c src/lib-storage/index/maildir/maildir-sync.c src/lib-storage/mail-storage.h src/plugins/acl/acl-mailbox-list.c
diffstat 25 files changed, 121 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/auth-request.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/auth/auth-request.c	Sat Jan 01 15:59:02 2011 +0200
@@ -354,6 +354,22 @@
 			  result == PASSDB_RESULT_OK);
 }
 
+static void auth_request_userdb_reply_update_user(struct auth_request *request)
+{
+	const char *str, *p;
+
+	str = t_strdup(auth_stream_reply_export(request->userdb_reply));
+
+	/* reset the reply and add the new username */
+	auth_stream_reply_reset(request->userdb_reply);
+	auth_stream_reply_add(request->userdb_reply, NULL, request->user);
+
+	/* add the rest */
+	p = strchr(str, '\t');
+	if (p != NULL)
+		auth_stream_reply_import(request->userdb_reply, p + 1);
+}
+
 static bool auth_request_master_lookup_finish(struct auth_request *request)
 {
 	struct auth_passdb *passdb;
@@ -368,6 +384,8 @@
 	request->master_user = request->user;
 	request->user = request->requested_login_user;
 	request->requested_login_user = NULL;
+	if (request->userdb_reply != NULL)
+		auth_request_userdb_reply_update_user(request);
 
 	request->skip_password_check = TRUE;
 	request->passdb_password = NULL;
@@ -1079,22 +1097,6 @@
 	auth_stream_reply_add(request->extra_fields, name, value);
 }
 
-static void auth_request_userdb_reply_update_user(struct auth_request *request)
-{
-	const char *str, *p;
-
-	str = t_strdup(auth_stream_reply_export(request->userdb_reply));
-
-	/* reset the reply and add the new username */
-	auth_stream_reply_reset(request->userdb_reply);
-	auth_stream_reply_add(request->userdb_reply, NULL, request->user);
-
-	/* add the rest */
-	p = strchr(str, '\t');
-	if (p != NULL)
-		auth_stream_reply_import(request->userdb_reply, p + 1);
-}
-
 static const char *
 get_updated_username(const char *old_username,
 		     const char *name, const char *value)
--- a/src/auth/passdb-checkpassword.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/auth/passdb-checkpassword.c	Sat Jan 01 15:59:02 2011 +0200
@@ -35,6 +35,9 @@
 				"LF characters in checkpassword reply");
 			result = PASSDB_RESULT_INTERNAL_FAILURE;
 		} else {
+			auth_request_log_debug(request->request,
+					       "checkpassword", "input: %s",
+					       str_c(request->input_buf));
 			auth_request_set_fields(request->request,
 				t_strsplit(str_c(request->input_buf), "\t"),
 				NULL);
--- a/src/auth/passdb-vpopmail.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/auth/passdb-vpopmail.c	Sat Jan 01 15:59:02 2011 +0200
@@ -35,7 +35,7 @@
 	struct vpopmail_passdb_module *module =
 		(struct vpopmail_passdb_module *)_module;
 
-	if (strcmp(request->service, "IMAP") == 0) {
+	if (strcasecmp(request->service, "IMAP") == 0) {
 		if ((vpw->pw_flags & NO_IMAP) != 0) {
 			/* IMAP from webmail IP may still be allowed */
 			if (!net_ip_compare(&module->webmail_ip,
@@ -49,7 +49,7 @@
 		}
 	}
 	if ((vpw->pw_flags & NO_POP) != 0 &&
-	    strcmp(request->service, "POP3") == 0)
+	    strcasecmp(request->service, "POP3") == 0)
 		return TRUE;
 	return FALSE;
 }
@@ -137,8 +137,8 @@
 	}
 
 #ifdef HAVE_VPOPMAIL_OPEN_SMTP_RELAY
-	if (strcmp(request->service, "POP3") == 0 ||
-	    strcmp(request->service, "IMAP") == 0) {
+	if (strcasecmp(request->service, "POP3") == 0 ||
+	    strcasecmp(request->service, "IMAP") == 0) {
 		const char *host = net_ip2addr(&request->remote_ip);
 		if (host != NULL) {
 			/* use putenv() directly rather than env_put() which
--- a/src/doveadm/doveadm-auth.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/doveadm/doveadm-auth.c	Sat Jan 01 15:59:02 2011 +0200
@@ -65,7 +65,7 @@
 		}
 	}
 	auth_master_deinit(&conn);
-	return ret == 0 ? 1 : 0;
+	return ret;
 }
 
 static void
@@ -250,15 +250,23 @@
 		cmd_user_list(auth_socket_path, argv + optind);
 	} else {
 		bool first = TRUE;
+		bool notfound = FALSE;
 
 		while ((input.username = argv[optind++]) != NULL) {
 			if (first)
 				first = FALSE;
 			else
 				putchar('\n');
-			if (cmd_user_input(auth_socket_path, &input) < 0)
+			switch (cmd_user_input(auth_socket_path, &input)) {
+			case -1:
 				exit(1);
+			case 0:
+				notfound = TRUE;
+				break;
+			}
 		}
+		if (notfound)
+			exit(2);
 	}
 }
 
--- a/src/doveadm/doveadm-mail-list-iter.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/doveadm/doveadm-mail-list-iter.c	Sat Jan 01 15:59:02 2011 +0200
@@ -18,7 +18,8 @@
 
 static int
 search_args_get_mailbox_patterns(const struct mail_search_arg *args,
-				 ARRAY_TYPE(const_string) *patterns)
+				 ARRAY_TYPE(const_string) *patterns,
+				 bool *have_guid_r)
 {
 	const struct mail_search_arg *subargs;
 
@@ -30,7 +31,7 @@
 			subargs = args->value.subargs;
 			for (; subargs != NULL; subargs = subargs->next) {
 				if (!search_args_get_mailbox_patterns(subargs,
-								      patterns))
+							patterns, have_guid_r))
 					return 0;
 			}
 			break;
@@ -42,6 +43,9 @@
 			}
 			array_append(patterns, &args->value.str, 1);
 			break;
+		case SEARCH_MAILBOX_GUID:
+			*have_guid_r = TRUE;
+			break;
 		default:
 			break;
 		}
@@ -58,14 +62,18 @@
 	struct doveadm_mail_list_iter *iter;
 	ARRAY_TYPE(const_string) patterns;
 	enum namespace_type ns_mask = NAMESPACE_PRIVATE;
+	bool have_guid = FALSE;
 
 	iter = i_new(struct doveadm_mail_list_iter, 1);
 	iter->search_args = search_args;
 
 	t_array_init(&patterns, 16);
-	search_args_get_mailbox_patterns(search_args->args, &patterns);
+	search_args_get_mailbox_patterns(search_args->args, &patterns,
+					 &have_guid);
 	if (array_count(&patterns) == 0) {
 		iter_flags |= MAILBOX_LIST_ITER_SKIP_ALIASES;
+		if (have_guid)
+			ns_mask |= NAMESPACE_SHARED | NAMESPACE_PUBLIC;
 		array_append(&patterns, &all_pattern, 1);
 	} else {
 		iter_flags |= MAILBOX_LIST_ITER_STAR_WITHIN_NS;
--- a/src/imap/imap-search.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/imap/imap-search.c	Sat Jan 01 15:59:02 2011 +0200
@@ -280,6 +280,7 @@
 	}
 	str_append(str, "\r\n");
 	o_stream_send(client->output, str_data(str), str_len(str));
+	str_free(&str);
 }
 
 static void search_update_mail(struct imap_search_context *ctx)
--- a/src/lda/main.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lda/main.c	Sat Jan 01 15:59:02 2011 +0200
@@ -154,13 +154,6 @@
 	i_free(sender);
 
 	if (input->v_offset == 0) {
-		if (deliver_mail == NULL) {
-			/* no Sieve or any other plugin. this input stream
-			   simply passes to mailbox_save(), so it doesn't need
-			   to be seekable and we can avoid creating temp files
-			   for large mails. */
-			return input;
-		}
 		input2 = input;
 		i_stream_ref(input2);
 	} else {
--- a/src/lib-master/master-interface.h	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-master/master-interface.h	Sat Jan 01 15:59:02 2011 +0200
@@ -68,13 +68,16 @@
 
 /* Shared pipe to master, used to send master_status reports */
 #define MASTER_STATUS_FD 5
+/* Pipe to master, used to detect when it dies. (MASTER_STATUS_FD would have
+   been fine for this, except it's inefficient in Linux) */
+#define MASTER_DEAD_FD 6
 /* First file descriptor where process is expected to be listening.
    The file descriptor count is given in -s parameter, defaulting to 1.
 
    master_status.available_count reports how many accept()s we're still
    accepting. Once no children are listening, master will do it and create
    new child processes when needed. */
-#define MASTER_LISTEN_FD_FIRST 6
+#define MASTER_LISTEN_FD_FIRST 7
 
 /* Timeouts: base everything on how long we can wait for login clients. */
 #define MASTER_LOGIN_TIMEOUT_SECS (3*60)
--- a/src/lib-master/master-login-auth.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-master/master-login-auth.c	Sat Jan 01 15:59:02 2011 +0200
@@ -289,7 +289,7 @@
 			request_internal_failure(request,
 						 "Internal auth failure");
 		} else {
-			i_error("Internal tuah failure: %s "
+			i_error("Internal auth failure: %s "
 				"(client-pid=%u client-id=%u)",
 				error, request->client_pid, request->auth_id);
 			request->callback(NULL, error, request->context);
--- a/src/lib-master/master-service.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-master/master-service.c	Sat Jan 01 15:59:02 2011 +0200
@@ -375,7 +375,7 @@
 			master_service_set_service_count(service, count);
 
 		/* start listening errors for status fd, it means master died */
-		service->io_status_error = io_add(MASTER_STATUS_FD, IO_ERROR,
+		service->io_status_error = io_add(MASTER_DEAD_FD, IO_ERROR,
 						  master_status_error, service);
 	} else {
 		master_service_set_client_limit(service, 1);
--- a/src/lib-storage/index/index-mailbox-check.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/index/index-mailbox-check.c	Sat Jan 01 15:59:02 2011 +0200
@@ -72,6 +72,8 @@
 	struct io *io = NULL;
 	struct index_notify_io *aio;
 
+	i_assert(box->notify_min_interval > 0);
+
 	(void)io_add_notify(path, notify_callback, box, &io);
 	if (io != NULL) {
 		aio = i_new(struct index_notify_io, 1);
--- a/src/lib-storage/index/index-sort.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/index/index-sort.c	Sat Jan 01 15:59:02 2011 +0200
@@ -309,7 +309,7 @@
 	const char *str;
 	int ret;
 
-	if ((ret = mail_get_first_header_utf8(mail, header, &str)) <= 0) {
+	if ((ret = mail_get_first_header(mail, header, &str)) <= 0) {
 		*addr_r = NULL;
 		return ret;
 	}
--- a/src/lib-storage/list/mailbox-list-delete.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-delete.c	Sat Jan 01 15:59:02 2011 +0200
@@ -97,7 +97,7 @@
 		if (trash_dir == trash_dest) {
 			trash_dest = t_strconcat(trash_dir, "/",
 						 unique_fname(), NULL);
-		} else if (unlink_directory(trash_dest, TRUE) < 0 &&
+		} else if (mailbox_list_delete_trash(trash_dest) < 0 &&
 			   (errno != ENOTEMPTY || count >= 5)) {
 			mailbox_list_set_critical(list,
 				"unlink_directory(%s) failed: %m", trash_dest);
@@ -105,7 +105,7 @@
 		}
 	}
 
-	if (unlink_directory(trash_dir, TRUE) < 0 &&
+	if (mailbox_list_delete_trash(trash_dir) < 0 &&
 	    errno != ENOTEMPTY && errno != EBUSY) {
 		mailbox_list_set_critical(list,
 			"unlink_directory(%s) failed: %m", trash_dir);
@@ -189,7 +189,7 @@
 		str_append(full_path, d->d_name);
 
 		if (mailbox_dir) {
-			if (unlink_directory(str_c(full_path), TRUE) < 0) {
+			if (mailbox_list_delete_trash(str_c(full_path)) < 0) {
 				mailbox_list_set_critical(list,
 					"unlink_directory(%s) failed: %m",
 					str_c(full_path));
@@ -297,7 +297,7 @@
 							     rmdir_path) < 0)
 			return;
 	} else {
-		if (unlink_directory(path, TRUE) < 0 &&
+		if (mailbox_list_delete_trash(path) < 0 &&
 		    errno != ENOENT && errno != ENOTEMPTY) {
 			mailbox_list_set_critical(list,
 				"unlink_directory(%s) failed: %m", path);
@@ -314,3 +314,17 @@
 	mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
 	mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
 }
+
+int mailbox_list_delete_trash(const char *path)
+{
+	if (unlink_directory(path, TRUE) < 0) {
+		if (errno == ELOOP) {
+			/* it's a symlink? try just deleting it */
+			if (unlink(path) == 0)
+				return 0;
+			errno = ELOOP;
+			return -1;
+		}
+	}
+	return 0;
+}
--- a/src/lib-storage/list/mailbox-list-delete.h	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-delete.h	Sat Jan 01 15:59:02 2011 +0200
@@ -15,5 +15,6 @@
 
 void mailbox_list_delete_until_root(struct mailbox_list *list, const char *path,
 				    enum mailbox_list_path_type type);
+int mailbox_list_delete_trash(const char *path);
 
 #endif
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c	Sat Jan 01 15:59:02 2011 +0200
@@ -6,6 +6,7 @@
 #include "unlink-directory.h"
 #include "imap-match.h"
 #include "mailbox-tree.h"
+#include "mailbox-list-delete.h"
 #include "mailbox-list-subscriptions.h"
 #include "mailbox-list-maildir.h"
 
@@ -256,7 +257,7 @@
 	path = t_strdup_printf("%s/%s", ctx->dir, fname);
 	if (stat(path, &st) == 0 &&
 	    st.st_mtime < ioloop_time - 3600)
-		(void)unlink_directory(path, TRUE);
+		(void)mailbox_list_delete_trash(path);
 
 	return TRUE;
 }
--- a/src/lib-storage/mail-storage.h	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib-storage/mail-storage.h	Sat Jan 01 15:59:02 2011 +0200
@@ -641,7 +641,11 @@
 int mail_get_first_header(struct mail *mail, const char *field,
 			  const char **value_r);
 /* Like mail_get_first_header(), but decode MIME encoded words to UTF-8.
-   Also multiline headers are returned unfolded. */
+   Also multiline headers are returned unfolded.
+
+   Do not use this function for getting structured fields (e.g. address fields),
+   because decoding may break the structuring. Instead parse them first and
+   only afterwards decode the encoded words. */
 int mail_get_first_header_utf8(struct mail *mail, const char *field,
 			       const char **value_r);
 /* Return a NULL-terminated list of values for each found field.
@@ -649,7 +653,8 @@
 int mail_get_headers(struct mail *mail, const char *field,
 		     const char *const **value_r);
 /* Like mail_get_headers(), but decode MIME encoded words to UTF-8.
-   Also multiline headers are returned unfolded. */
+   Also multiline headers are returned unfolded.
+   Do not use for structured fields (see mail_get_first_header_utf8()). */
 int mail_get_headers_utf8(struct mail *mail, const char *field,
 			  const char *const **value_r);
 /* Returns stream containing specified headers. */
--- a/src/lib/network.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib/network.c	Sat Jan 01 15:59:02 2011 +0200
@@ -371,7 +371,8 @@
 	/* create the socket */
 	fd = socket(so.sin.sin_family, SOCK_STREAM, 0);
 #ifdef HAVE_IPV6
-	if (fd == -1 && (errno == EINVAL || errno == EAFNOSUPPORT)) {
+	if (fd == -1 && my_ip == NULL &&
+	    (errno == EINVAL || errno == EAFNOSUPPORT)) {
 		/* IPv6 is not supported by OS */
 		so.sin.sin_family = AF_INET;
 		so.sin.sin_addr.s_addr = INADDR_ANY;
--- a/src/lib/unlink-directory.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/lib/unlink-directory.c	Sat Jan 01 15:59:02 2011 +0200
@@ -59,7 +59,12 @@
 		return -1;
 
 	if (!S_ISDIR(st.st_mode)) {
-		errno = ENOTDIR;
+		if ((st.st_mode & S_IFMT) != S_IFLNK)
+			errno = ENOTDIR;
+		else {
+			/* be compatible with O_NOFOLLOW */
+			errno = ELOOP;
+		}
 		return -1;
 	}
 
--- a/src/master/common.h	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/master/common.h	Sat Jan 01 15:59:02 2011 +0200
@@ -9,7 +9,7 @@
 extern gid_t master_gid;
 extern bool core_dumps_disabled;
 extern const char *ssl_manual_key_password;
-extern int null_fd;
+extern int null_fd, master_dead_pipe_fd[2];
 extern struct service_list *services;
 
 void process_exec(const char *cmd, const char *extra_args[]) ATTR_NORETURN;
--- a/src/master/main.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/master/main.c	Sat Jan 01 15:59:02 2011 +0200
@@ -42,7 +42,7 @@
 gid_t master_gid;
 bool core_dumps_disabled;
 const char *ssl_manual_key_password;
-int null_fd;
+int null_fd, master_dead_pipe_fd[2];
 struct service_list *services;
 
 static char *pidfile_path;
@@ -412,7 +412,7 @@
         lib_signals_set_handler(SIGUSR1, TRUE, sig_log_reopen, NULL);
         lib_signals_set_handler(SIGCHLD, TRUE, sig_reap_children, NULL);
         lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
-        lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
+	lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
 
 	create_pid_file(pidfile_path);
 	create_config_symlink(set);
@@ -712,6 +712,10 @@
 			i_fatal("Can't open /dev/null: %m");
 		fd_close_on_exec(null_fd, TRUE);
 	} while (null_fd <= STDERR_FILENO);
+	if (pipe(master_dead_pipe_fd) < 0)
+		i_fatal("pipe() failed: %m");
+	fd_close_on_exec(master_dead_pipe_fd[0], TRUE);
+	fd_close_on_exec(master_dead_pipe_fd[1], TRUE);
 
 	set = master_settings_read();
 	if (ask_key_pass) {
--- a/src/master/service-process.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/master/service-process.c	Sat Jan 01 15:59:02 2011 +0200
@@ -116,6 +116,7 @@
 		break;
 	}
 	dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
+	dup2_append(&dups, master_dead_pipe_fd[1], MASTER_DEAD_FD);
 
 	if (service->type == SERVICE_TYPE_LOG) {
 		/* keep stderr as-is. this is especially important when
--- a/src/plugins/acl/acl-mailbox-list.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/plugins/acl/acl-mailbox-list.c	Sat Jan 01 15:59:02 2011 +0200
@@ -487,7 +487,8 @@
 {
 	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
 
-	acl_backend_deinit(&alist->rights.backend);
+	if (alist->rights.backend != NULL)
+		acl_backend_deinit(&alist->rights.backend);
 	alist->module_ctx.super.deinit(list);
 }
 
--- a/src/plugins/quota/doveadm-quota.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/plugins/quota/doveadm-quota.c	Sat Jan 01 15:59:02 2011 +0200
@@ -49,6 +49,9 @@
 	struct quota_user *quser = QUOTA_USER_CONTEXT(user);
 	struct quota_root *const *root;
 
+	if (quser == NULL)
+		i_fatal("Quota not enabled");
+
 	array_foreach(&quser->quota->roots, root)
 		cmd_quota_get_root(*root);
 }
@@ -86,6 +89,9 @@
 	struct quota_root *const *root;
 	struct quota_transaction_context trans;
 
+	if (quser == NULL)
+		i_fatal("Quota not enabled");
+
 	memset(&trans, 0, sizeof(trans));
 	trans.quota = quser->quota;
 	trans.recalculate = TRUE;
--- a/src/plugins/quota/quota.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/plugins/quota/quota.c	Sat Jan 01 15:59:02 2011 +0200
@@ -1092,9 +1092,12 @@
 	if (ctx->failed)
 		ret = -1;
 	else if (ctx->bytes_used != 0 || ctx->count_used != 0 ||
-		 ctx->recalculate) {
+		 ctx->recalculate) T_BEGIN {
+		ARRAY_DEFINE(warn_roots, struct quota_root *);
+
 		mailbox_name = mailbox_get_vname(ctx->box);
 		roots = array_get(&ctx->quota->roots, &count);
+		t_array_init(&warn_roots, count);
 		for (i = 0; i < count; i++) {
 			if (!quota_root_is_visible(roots[i], ctx->box, FALSE))
 				continue;
@@ -1108,13 +1111,15 @@
 
 			if (roots[i]->backend.v.update(roots[i], ctx) < 0)
 				ret = -1;
+			else
+				array_append(&warn_roots, &roots[i], 1);
 		}
 		/* execute quota warnings after all updates. this makes it
 		   work correctly regardless of whether backend.get_resource()
 		   returns updated values before backend.update() or not */
-		for (i = 0; i < count; i++)
-			quota_warnings_execute(ctx, roots[i]);
-	}
+		array_foreach(&warn_roots, roots)
+			quota_warnings_execute(ctx, *roots);
+	} T_END;
 
 	i_free(ctx);
 	return ret;
--- a/src/plugins/snarf/snarf-plugin.c	Sat Jan 01 15:56:37 2011 +0200
+++ b/src/plugins/snarf/snarf-plugin.c	Sat Jan 01 15:59:02 2011 +0200
@@ -37,6 +37,10 @@
 	enum mail_error error;
 	int ret;
 
+	/* make sure the destination mailbox has been opened */
+	if (mailbox_open(destbox) < 0)
+		return -1;
+
 	if (mailbox_sync(srcbox, MAILBOX_SYNC_FLAG_FULL_READ) < 0)
 		return -1;