changeset 1168:03f1455664d7 HEAD

Added setting to limit length of custom flag names.
author Timo Sirainen <tss@iki.fi>
date Fri, 14 Feb 2003 10:00:51 +0200
parents 64345e62089c
children 0eaf51e01ccd
files dovecot-example.conf src/imap/client.c src/imap/client.h src/imap/cmd-append.c src/imap/cmd-select.c src/imap/cmd-store.c src/imap/commands-util.c src/imap/commands-util.h src/imap/common.h src/imap/mail-storage-callbacks.c src/imap/main.c src/master/mail-process.c src/master/master-settings.c src/master/master-settings.h
diffstat 14 files changed, 103 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Fri Feb 14 10:00:01 2003 +0200
+++ b/dovecot-example.conf	Fri Feb 14 10:00:51 2003 +0200
@@ -229,6 +229,10 @@
 # or ~user/.
 #mail_full_filesystem_access = no
 
+# Maximum allowed length for custom flag name. It's only forced when trying
+# to create new flags.
+#mail_max_flag_length = 50
+
 # Save mails with CR+LF instead of plain LF. This makes sending those mails
 # take less CPU, especially with sendfile() syscall with Linux and FreeBSD.
 # But it also creates a bit more disk I/O which may just make it slower.
--- a/src/imap/client.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/client.c	Fri Feb 14 10:00:51 2003 +0200
@@ -73,6 +73,8 @@
 					    MAX_IMAP_ARG_ELEMENTS);
         client->last_input = ioloop_time;
 
+	client->mailbox_flags.pool =
+		pool_alloconly_create("mailbox_custom_flags", 512);
 	client->storage = storage;
 	storage->set_callbacks(storage, &mail_storage_callbacks, client);
 
@@ -95,6 +97,7 @@
 	i_stream_unref(client->input);
 	o_stream_unref(client->output);
 
+	pool_unref(client->mailbox_flags.pool);
 	i_free(client);
 
 	/* quit the program */
--- a/src/imap/client.h	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/client.h	Fri Feb 14 10:00:51 2003 +0200
@@ -8,6 +8,13 @@
 
 typedef int client_command_func_t(struct client *client);
 
+struct mailbox_custom_flags {
+	pool_t pool; /* will be p_clear()ed when changed */
+
+	char **custom_flags;
+        unsigned int custom_flags_count;
+};
+
 struct client {
 	int socket;
 	struct io *io;
@@ -16,6 +23,7 @@
 
 	struct mail_storage *storage;
 	struct mailbox *mailbox;
+        struct mailbox_custom_flags mailbox_flags;
 	unsigned int select_counter; /* increased when mailbox is changed */
 
 	time_t last_input;
--- a/src/imap/cmd-append.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/cmd-append.c	Fri Feb 14 10:00:51 2003 +0200
@@ -46,10 +46,12 @@
 int cmd_append(struct client *client)
 {
 	struct mailbox *box;
+	struct mailbox_status status;
 	struct mail_save_context *ctx;
 	struct imap_parser *save_parser;
 	struct imap_arg *args;
 	struct imap_arg_list *flags_list;
+        struct mailbox_custom_flags old_flags;
 	struct mail_full_flags flags;
 	time_t internal_date;
 	const char *mailbox, *internal_date_str, *error;
@@ -71,6 +73,16 @@
 		return TRUE;
 	}
 
+	if (!box->get_status(box, STATUS_CUSTOM_FLAGS, &status)) {
+		client_send_storage_error(client);
+		box->close(box);
+		return TRUE;
+	}
+	memset(&old_flags, 0, sizeof(old_flags));
+        old_flags.pool = data_stack_pool;
+	client_save_custom_flags(&old_flags, status.custom_flags,
+				 status.custom_flags_count);
+
 	ctx = box->save_init(box, TRUE);
 	if (ctx == NULL) {
 		client_send_storage_error(client);
@@ -141,7 +153,7 @@
 
 		if (flags_list != NULL) {
 			if (!client_parse_mail_flags(client, flags_list->args,
-						     &flags))
+						     &old_flags, &flags))
 				break;
 		} else {
 			memset(&flags, 0, sizeof(flags));
--- a/src/imap/cmd-select.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/cmd-select.c	Fri Feb 14 10:00:51 2003 +0200
@@ -34,6 +34,9 @@
 		return TRUE;
 	}
 
+	client_save_custom_flags(&client->mailbox_flags, status.custom_flags,
+				 status.custom_flags_count);
+
 	/* set client's mailbox only after getting status to make sure
 	   we're not sending any expunge/exists replies too early to client */
 	client->mailbox = box;
--- a/src/imap/cmd-store.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/cmd-store.c	Fri Feb 14 10:00:51 2003 +0200
@@ -61,10 +61,11 @@
 	if (args[2].type == IMAP_ARG_LIST) {
 		if (!client_parse_mail_flags(client,
 					     IMAP_ARG_LIST(&args[2])->args,
-					     &flags))
+					     &client->mailbox_flags, &flags))
 			return TRUE;
 	} else {
-		if (!client_parse_mail_flags(client, args+2, &flags))
+		if (!client_parse_mail_flags(client, args+2,
+					     &client->mailbox_flags, &flags))
 			return TRUE;
 	}
 
--- a/src/imap/commands-util.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/commands-util.c	Fri Feb 14 10:00:51 2003 +0200
@@ -131,7 +131,32 @@
 			 t_strconcat(syntax ? "* BAD " : "* NO ", error, NULL));
 }
 
+static int is_valid_custom_flag(struct client *client,
+                                const struct mailbox_custom_flags *old_flags,
+				const char *flag)
+{
+	size_t i;
+
+	/* if it already exists, skip validity checks */
+	for (i = 0; i < old_flags->custom_flags_count; i++) {
+		if (old_flags->custom_flags[i] != NULL &&
+		    strcasecmp(old_flags->custom_flags[i], flag) == 0)
+			return TRUE;
+	}
+
+	if (strlen(flag) > max_custom_flag_length) {
+		client_send_tagline(client,
+			t_strdup_printf("BAD Invalid flag name '%s': "
+					"Maximum length is %u characters",
+					flag, max_custom_flag_length));
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 int client_parse_mail_flags(struct client *client, struct imap_arg *args,
+                            const struct mailbox_custom_flags *old_flags,
 			    struct mail_full_flags *flags)
 {
 	/* @UNSAFE */
@@ -187,6 +212,9 @@
 			}
 
 			if (i == flags->custom_flags_count) {
+				if (!is_valid_custom_flag(client, old_flags,
+							  atom))
+					return FALSE;
 				flags->flags |= 1 << (flag_pos +
 						      MAIL_CUSTOM_FLAG_1_BIT);
 				flags->custom_flags[flag_pos++] = atom;
@@ -247,3 +275,19 @@
 				    ")] Flags permitted.", NULL));
 	}
 }
+
+void client_save_custom_flags(struct mailbox_custom_flags *dest,
+			      const char *custom_flags[],
+			      unsigned int custom_flags_count)
+{
+	unsigned int i;
+
+	p_clear(dest->pool);
+
+	dest->custom_flags =
+		p_new(dest->pool, char *, custom_flags_count);
+	dest->custom_flags_count = custom_flags_count;
+
+	for (i = 0; i < custom_flags_count; i++)
+		dest->custom_flags[i] = p_strdup(dest->pool, custom_flags[i]);
+}
--- a/src/imap/commands-util.h	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/commands-util.h	Fri Feb 14 10:00:51 2003 +0200
@@ -33,6 +33,7 @@
 /* Parse flags. Returns TRUE if successful, if not sends an error message to
    client. */
 int client_parse_mail_flags(struct client *client, struct imap_arg *args,
+                            const struct mailbox_custom_flags *old_flags,
 			    struct mail_full_flags *flags);
 
 /* Send FLAGS + PERMANENTFLAGS to client. */
@@ -40,4 +41,9 @@
 			       const char *custom_flags[],
 			       unsigned int custom_flags_count);
 
+/* Copy custom flags into dest. dest must have been initialized. */
+void client_save_custom_flags(struct mailbox_custom_flags *dest,
+			      const char *custom_flags[],
+			      unsigned int custom_flags_count);
+
 #endif
--- a/src/imap/common.h	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/common.h	Fri Feb 14 10:00:51 2003 +0200
@@ -8,6 +8,9 @@
    for command from user is around MAX_INBUF_SIZE * MAX_IMAP_ARG_ELEMENTS */
 #define MAX_IMAP_ARG_ELEMENTS 128
 
+#define DEFAULT_MAX_CUSTOM_FLAG_LENGTH 50
+
 extern struct ioloop *ioloop;
+extern unsigned int max_custom_flag_length;
 
 #endif
--- a/src/imap/mail-storage-callbacks.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/mail-storage-callbacks.c	Fri Feb 14 10:00:51 2003 +0200
@@ -95,6 +95,9 @@
 	if (client->mailbox != mailbox)
 		return;
 
+	client_save_custom_flags(&client->mailbox_flags, custom_flags,
+				 custom_flags_count);
+
 	client_send_mailbox_flags(client, mailbox, custom_flags,
 				  custom_flags_count);
 }
--- a/src/imap/main.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/imap/main.c	Fri Feb 14 10:00:51 2003 +0200
@@ -16,6 +16,8 @@
         (getenv("LOGGED_IN") == NULL)
 
 struct ioloop *ioloop;
+unsigned int max_custom_flag_length;
+
 static char log_prefix[128]; /* syslog() needs this to be permanent */
 
 static void sig_quit(int signo __attr_unused__)
@@ -61,7 +63,7 @@
 {
 	struct client *client;
 	struct mail_storage *storage;
-	const char *mail;
+	const char *mail, *str;
 	int hin, hout;
 
 	lib_init_signals(sig_quit);
@@ -100,6 +102,11 @@
 		}
 	}
 
+	str = getenv("MAIL_MAX_FLAG_LENGTH");
+	max_custom_flag_length = str != NULL ?
+		(unsigned int)strtoul(str, NULL, 10) :
+		DEFAULT_MAX_CUSTOM_FLAG_LENGTH;
+
 	client = client_create(hin, hout, storage);
 
 	if (IS_STANDALONE()) {
--- a/src/master/mail-process.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/master/mail-process.c	Fri Feb 14 10:00:51 2003 +0200
@@ -162,6 +162,8 @@
 				set->mailbox_check_interval));
 	env_put(t_strconcat("CLIENT_WORKAROUNDS=",
 			    set->client_workarounds, NULL));
+	env_put(t_strdup_printf("MAIL_MAX_FLAG_LENGTH=%u",
+				set->mail_max_flag_length));
 
 	if (set->mail_save_crlf)
 		env_put("MAIL_SAVE_CRLF=1");
--- a/src/master/master-settings.c	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/master/master-settings.c	Fri Feb 14 10:00:51 2003 +0200
@@ -56,6 +56,7 @@
 	DEF(SET_STR, client_workarounds),
 	DEF(SET_INT, mailbox_check_interval),
 	DEF(SET_BOOL, mail_full_filesystem_access),
+	DEF(SET_INT, mail_max_flag_length),
 	DEF(SET_BOOL, mail_save_crlf),
 	DEF(SET_BOOL, mail_read_mmaped),
 	DEF(SET_BOOL, maildir_copy_with_hardlinks),
@@ -159,6 +160,7 @@
 	MEMBER(client_workarounds) NULL,
 	MEMBER(mailbox_check_interval) 0,
 	MEMBER(mail_full_filesystem_access) FALSE,
+	MEMBER(mail_max_flag_length) 50,
 	MEMBER(mail_save_crlf) FALSE,
 	MEMBER(mail_read_mmaped) FALSE,
 	MEMBER(maildir_copy_with_hardlinks) FALSE,
--- a/src/master/master-settings.h	Fri Feb 14 10:00:01 2003 +0200
+++ b/src/master/master-settings.h	Fri Feb 14 10:00:51 2003 +0200
@@ -40,6 +40,7 @@
 	const char *client_workarounds;
 	unsigned int mailbox_check_interval;
 	int mail_full_filesystem_access;
+	int mail_max_flag_length;
 	int mail_save_crlf;
 	int mail_read_mmaped;
 	int maildir_copy_with_hardlinks;