From 5fe046cff3d3ddb5a76a7781584b61d97402f94a Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 2 May 2010 10:23:14 +0200
Subject: [PATCH] managesieve: updated to changes in Dovecot (IMAP/POP3).

---
 src/managesieve/main.c                 | 56 ++++++++++----------------
 src/managesieve/managesieve-client.c   | 23 +++++++----
 src/managesieve/managesieve-client.h   |  2 +-
 src/managesieve/managesieve-commands.c | 46 +++++++++------------
 4 files changed, 56 insertions(+), 71 deletions(-)

diff --git a/src/managesieve/main.c b/src/managesieve/main.c
index 7282fa7bf..0e6a3227b 100644
--- a/src/managesieve/main.c
+++ b/src/managesieve/main.c
@@ -103,37 +103,18 @@ static void managesieve_die(void)
 static void client_add_input(struct client *client, const buffer_t *buf)
 {
 	struct ostream *output;
-	const char *tag;
-	unsigned int data_pos;
-	bool send_untagged_capability = FALSE;
 
 	if (buf != NULL && buf->used > 0) {
-		tag = t_strndup(buf->data, buf->used);
-		switch (*tag) {
-		case '0':
-			tag++;
-			break;
-		case '1':
-			send_untagged_capability = TRUE;
-			tag++;
-			break;
-		}
-		data_pos = strlen(tag) + 1;
-		if (data_pos > buf->used &&
-		    !i_stream_add_data(client->input,
-				       CONST_PTR_OFFSET(buf->data, data_pos),
-				       buf->used - data_pos))
+		if (!i_stream_add_data(client->input, buf->data, buf->used))
 			i_panic("Couldn't add client input to stream");
 	}
 
 	output = client->output;
 	o_stream_ref(output);
 	o_stream_cork(output);
-
-	client_send_ok(client, "Logged in.");
-
+	if (!IS_STANDALONE())
+		client_send_ok(client, "Logged in.");
   (void)client_input(client);
-
 	o_stream_uncork(output);
 	o_stream_unref(&output);
 }
@@ -164,7 +145,7 @@ client_create_from_input(const struct mail_storage_service_input *input,
 	return 0;
 }
 
-static void main_stdio_run(void)
+static void main_stdio_run(const char *username)
 {
 	struct mail_storage_service_input input;
 	const char *value, *error, *input_base64;
@@ -172,7 +153,7 @@ static void main_stdio_run(void)
 
 	memset(&input, 0, sizeof(input));
 	input.module = input.service = "managesieve";
-	input.username = getenv("USER");
+	input.username =  username != NULL ? username : getenv("USER");
 	if (input.username == NULL && IS_STANDALONE())
 		input.username = getlogin();
 	if (input.username == NULL)
@@ -206,18 +187,13 @@ login_client_connected(const struct master_login_client *client,
 	input.username = username;
 	input.userdb_fields = extra_fields;
 
-	if (input.username == NULL) {
-		i_error("login client: Username missing from auth reply");
-		(void)close(client->fd);
-		return;
-	}
-
 	buffer_create_const_data(&input_buf, client->data,
 				 client->auth_req.data_size);
 	if (client_create_from_input(&input, client->fd, client->fd,
 				     &input_buf, &error) < 0) {
 		i_error("%s", error);
 		(void)close(client->fd);
+		master_service_client_connection_destroyed(master_service);
 	}
 }
 
@@ -250,7 +226,8 @@ int main(int argc, char *argv[])
 	};
 	enum master_service_flags service_flags = 0;
 	enum mail_storage_service_flags storage_service_flags = 0;
-	const char *postlogin_socket_path;
+	const char *postlogin_socket_path, *username = NULL;
+	int c;
 
 	if (IS_STANDALONE() && getuid() == 0 &&
 	    net_getpeername(1, NULL, NULL) == 0) {
@@ -269,9 +246,18 @@ int main(int argc, char *argv[])
 	}
 
 	master_service = master_service_init("managesieve", service_flags,
-					     &argc, &argv, NULL);
-	if (master_getopt(master_service) > 0)
-		return FATAL_DEFAULT;
+					     &argc, &argv, "u:");
+	while ((c = master_getopt(master_service)) > 0) {
+		switch (c) {
+		case 'u':
+			storage_service_flags |=
+				MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;
+			username = optarg;
+			break;
+		default:
+			return FATAL_DEFAULT;
+		}
+	}
 	postlogin_socket_path = argv[1] == NULL ? NULL : t_abspath(argv[1]);
 
 	master_service_init_finish(master_service);
@@ -290,7 +276,7 @@ int main(int argc, char *argv[])
 
 	if (IS_STANDALONE()) {
 		T_BEGIN {
-			main_stdio_run();
+			main_stdio_run(username);
 		} T_END;
 	} else {
 		master_login = master_login_init(master_service, "auth-master",
diff --git a/src/managesieve/managesieve-client.c b/src/managesieve/managesieve-client.c
index 5b1f38ef3..53941cf3b 100644
--- a/src/managesieve/managesieve-client.c
+++ b/src/managesieve/managesieve-client.c
@@ -67,8 +67,13 @@ static const struct sieve_environment managesieve_sieve_env = {
 
 static void client_idle_timeout(struct client *client)
 {
-	client_send_bye(client, "Disconnected for inactivity.");
-	client_destroy(client, "Disconnected for inactivity");
+	if (client->cmd.func != NULL) {
+		client_destroy(client,
+			"Disconnected for inactivity in reading our output");
+	} else {
+		client_send_bye(client, "Disconnected for inactivity");
+		client_destroy(client, "Disconnected for inactivity");
+	}
 }
 
 static struct sieve_storage *client_get_storage
@@ -192,7 +197,8 @@ static const char *client_stats(struct client *client)
 
 static const char *client_get_disconnect_reason(struct client *client)
 {
-	errno = client->input->stream_errno != 0 ?		client->input->stream_errno :
+	errno = client->input->stream_errno != 0 ?
+		client->input->stream_errno :
 		client->output->stream_errno;
 	return errno == 0 || errno == EPIPE ? "Connection closed" :
 		t_strdup_printf("Connection closed: %m");
@@ -406,22 +412,22 @@ void client_send_storage_error(struct client *client,
 }
 
 bool client_read_args(struct client_command_context *cmd, unsigned int count,
-		      unsigned int flags, struct managesieve_arg **args)
+		      unsigned int flags, struct managesieve_arg **args_r)
 {
 	int ret;
 
 	i_assert(count <= INT_MAX);
 
-	ret = managesieve_parser_read_args(cmd->client->parser, count, flags, args);
+	ret = managesieve_parser_read_args(cmd->client->parser, count, flags, args_r);
 	if (ret >= (int)count) {
 		/* all parameters read successfully */
 		return TRUE;
 	} else if (ret == -2) {
 		/* need more data */
 		if (cmd->client->input->closed) {
-            /* disconnected */
-            cmd->param_error = TRUE;
-        }
+			/* disconnected */
+ 			cmd->param_error = TRUE;
+		}
 		return FALSE;
 	} else {
 		/* error, or missing arguments */
@@ -565,6 +571,7 @@ static bool client_handle_input(struct client_command_context *cmd)
 		if (cmd->name == NULL)
 			return FALSE; /* need more data */
 		cmd->name = p_strdup(cmd->pool, cmd->name);
+		managesieve_refresh_proctitle();
 	}
 
 	if (cmd->name == '\0') {
diff --git a/src/managesieve/managesieve-client.h b/src/managesieve/managesieve-client.h
index d1daa466e..fd904d08c 100644
--- a/src/managesieve/managesieve-client.h
+++ b/src/managesieve/managesieve-client.h
@@ -112,7 +112,7 @@ void client_send_storage_error(struct client *client,
 /* Read a number of arguments. Returns TRUE if everything was read or
    FALSE if either needs more data or error occurred. */
 bool client_read_args(struct client_command_context *cmd, unsigned int count,
-		      unsigned int flags, struct managesieve_arg **args);
+		      unsigned int flags, struct managesieve_arg **args_r);
 /* Reads a number of string arguments. ... is a list of pointers where to
    store the arguments. */
 bool client_read_string_args(struct client_command_context *cmd,
diff --git a/src/managesieve/managesieve-commands.c b/src/managesieve/managesieve-commands.c
index 4657627c8..585f899a1 100644
--- a/src/managesieve/managesieve-commands.c
+++ b/src/managesieve/managesieve-commands.c
@@ -13,7 +13,7 @@
  * to avoid duplicate code 
  */
 
-const struct command managesieve_commands[] = {
+static const struct command managesieve_base_commands[] = {
 	{ "CAPABILITY", cmd_capability },
 	{ "LOGOUT", cmd_logout },
 	{ "PUTSCRIPT", cmd_putscript },
@@ -27,18 +27,19 @@ const struct command managesieve_commands[] = {
 	{ "NOOP", cmd_noop }
 };
 
-#define MANAGESIEVE_COMMANDS_COUNT N_ELEMENTS(managesieve_commands) 
+#define MANAGESIEVE_COMMANDS_COUNT N_ELEMENTS(managesieve_base_commands) 
 
-static ARRAY_DEFINE(commands, struct command);
+static ARRAY_DEFINE(managesieve_commands, struct command);
 static bool commands_unsorted;
 
 void command_register(const char *name, command_func_t *func)
 {
 	struct command cmd;
 
+	memset(&cmd, 0, sizeof(cmd));
 	cmd.name = name;
 	cmd.func = func;
-	array_append(&commands, &cmd, 1);
+	array_append(&managesieve_commands, &cmd, 1);
 
 	commands_unsorted = TRUE;
 }
@@ -48,10 +49,10 @@ void command_unregister(const char *name)
 	const struct command *cmd;
 	unsigned int i, count;
 
-	cmd = array_get(&commands, &count);
+	cmd = array_get(&managesieve_commands, &count);
 	for (i = 0; i < count; i++) {
 		if (strcasecmp(cmd[i].name, name) == 0) {
-			array_delete(&commands, i, 1);
+			array_delete(&managesieve_commands, i, 1);
 			return;
 		}
 	}
@@ -62,7 +63,7 @@ void command_unregister(const char *name)
 void command_register_array(const struct command *cmdarr, unsigned int count)
 {
 	commands_unsorted = TRUE;
-	array_append(&commands, cmdarr, count);
+	array_append(&managesieve_commands, cmdarr, count);
 }
 
 void command_unregister_array(const struct command *cmdarr, unsigned int count)
@@ -73,45 +74,36 @@ void command_unregister_array(const struct command *cmdarr, unsigned int count)
 	}
 }
 
-static int command_cmp(const void *p1, const void *p2)
+static int command_cmp(const struct command *c1, const struct command *c2)
 {
-	const struct command *c1 = p1, *c2 = p2;
-
 	return strcasecmp(c1->name, c2->name);
 }
 
-static int command_bsearch(const void *name, const void *cmd_p)
+static int command_bsearch(const char *name, const struct command *cmd)
 {
-	const struct command *cmd = cmd_p;
-
 	return strcasecmp(name, cmd->name);
 }
 
 struct command *command_find(const char *name)
 {
-    void *base;
-    unsigned int count;
-
-    base = array_get_modifiable(&commands, &count);
-    if (commands_unsorted) {
-        qsort(base, count, sizeof(struct command), command_cmp);
-                commands_unsorted = FALSE;
-    }
+	if (commands_unsorted) {
+		array_sort(&managesieve_commands, command_cmp);
+		commands_unsorted = FALSE;
+	}
 
-    return bsearch(name, base, count, sizeof(struct command),
-               command_bsearch);
+	return array_bsearch(&managesieve_commands, name, command_bsearch);
 }
 
 void commands_init(void)
 {
-	i_array_init(&commands, 16);
+	i_array_init(&managesieve_commands, 16);
 	commands_unsorted = FALSE;
 	
-	command_register_array(managesieve_commands, MANAGESIEVE_COMMANDS_COUNT);
+	command_register_array(managesieve_base_commands, MANAGESIEVE_COMMANDS_COUNT);
 }
 
 void commands_deinit(void)
 {
-	command_unregister_array(managesieve_commands, MANAGESIEVE_COMMANDS_COUNT);
-	array_free(&commands);
+	command_unregister_array(managesieve_base_commands, MANAGESIEVE_COMMANDS_COUNT);
+	array_free(&managesieve_commands);
 }
-- 
GitLab