]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added setting to limit length of custom flag names.
authorTimo Sirainen <tss@iki.fi>
Fri, 14 Feb 2003 08:00:51 +0000 (10:00 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 14 Feb 2003 08:00:51 +0000 (10:00 +0200)
--HG--
branch : HEAD

14 files changed:
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

index 1bbe75d403b8b7bf3b7d45db5844f6a6bb405a68..4c5d9788412d597b4137ed478ad148fea64ad1cd 100644 (file)
@@ -229,6 +229,10 @@ login = pop3
 # 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.
index 33efa83aa33843ea35ebbdb9793e8265ea5168aa..e8693ae991f5218f815af870ed4f19ffd33ca4dd 100644 (file)
@@ -73,6 +73,8 @@ struct client *client_create(int hin, int hout, struct mail_storage *storage)
                                            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 @@ void client_destroy(struct client *client)
        i_stream_unref(client->input);
        o_stream_unref(client->output);
 
+       pool_unref(client->mailbox_flags.pool);
        i_free(client);
 
        /* quit the program */
index 1c0f13420b5c26de2d533f20828dded0f441eb8f..499d8e84b81fc42787fdeb4ddcdfc30a0112f5d9 100644 (file)
@@ -8,6 +8,13 @@ struct imap_arg;
 
 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 client {
 
        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;
index c13cdf4a69062e58221f25ebc491ba95603453d0..ec0837df43ee993b41d6d7f310825b586d60984a 100644 (file)
@@ -46,10 +46,12 @@ static int validate_args(struct imap_arg *args, struct imap_arg_list **flags,
 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 @@ int cmd_append(struct client *client)
                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 @@ int cmd_append(struct client *client)
 
                if (flags_list != NULL) {
                        if (!client_parse_mail_flags(client, flags_list->args,
-                                                    &flags))
+                                                    &old_flags, &flags))
                                break;
                } else {
                        memset(&flags, 0, sizeof(flags));
index 222a3d2e069c2df5dae7efdb6b6620a755201162..5e02521609026faf86f70e24b35f9e1c3bfac806 100644 (file)
@@ -34,6 +34,9 @@ int _cmd_select_full(struct client *client, int readonly)
                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;
index 2a7aede6fb2715c02c7390b13159db7006194757..2b1c6e50f18bfa3d18af22dc774e743e28be2980 100644 (file)
@@ -61,10 +61,11 @@ int cmd_store(struct client *client)
        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;
        }
 
index f030b79abe320903b21fb6ace7d4c3ed66cfcb29..2d09d2576d8ca73449087fc3251d33a66513ed27 100644 (file)
@@ -131,7 +131,32 @@ void client_send_closing_mailbox_error(struct client *client)
                         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 @@ int client_parse_mail_flags(struct client *client, struct imap_arg *args,
                        }
 
                        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 @@ void client_send_mailbox_flags(struct client *client, struct mailbox *box,
                                    ")] 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]);
+}
index 01a847866e48ca6328b6b77046c4a2e77d17c8be..e9ed43cd49225fe0c1dea68d15630850e4fb0104 100644 (file)
@@ -33,6 +33,7 @@ void client_send_closing_mailbox_error(struct client *client);
 /* 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 @@ void client_send_mailbox_flags(struct client *client, struct mailbox *box,
                               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
index ed12ccaf181260f948dc8bde357aaa7228c9f58f..35ef692ac22698dd6305bd3ee7bcaf0215ef4436 100644 (file)
@@ -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
index b8209e6eee78601457ed14cebb2c364456d88171..141711eac3ce31b2791533db215d3c6efc3cfe24 100644 (file)
@@ -95,6 +95,9 @@ static void new_custom_flags(struct mailbox *mailbox,
        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);
 }
index d24036409f49fc83e2d5a1dc8465116c0f6ab1ef..b141edd30eca00fcc260d9c4ae8b38bbf57231bf 100644 (file)
@@ -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 @@ static void main_init(void)
 {
        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 @@ static void main_init(void)
                }
        }
 
+       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()) {
index 3940b958f5a08d052a647aee4f8db9bf73c693f6..405dc10cb2a0f4d0214ee6227d124b2f70c61151 100644 (file)
@@ -162,6 +162,8 @@ int create_mail_process(int socket, struct ip_addr *ip,
                                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");
index ccc176c9ab3d234d197258b474bd580232c12b44..5f13b6687006135f57627903dc58d2976fe6299c 100644 (file)
@@ -56,6 +56,7 @@ static struct setting_def setting_defs[] = {
        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 @@ struct settings default_settings = {
        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,
index bda815bd8afb4c99fc251f6d440d0fd3f7d433ec..c3b98f7992d73f0a9e282504825d7e166df8ab34 100644 (file)
@@ -40,6 +40,7 @@ struct settings {
        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;