]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap: Changed imap_arg accessing APIs.
authorTimo Sirainen <tss@iki.fi>
Mon, 5 Apr 2010 04:54:55 +0000 (07:54 +0300)
committerTimo Sirainen <tss@iki.fi>
Mon, 5 Apr 2010 04:54:55 +0000 (07:54 +0300)
The new one is easier for both coders and static analyzers.

--HG--
branch : HEAD

32 files changed:
src/imap-login/client-authenticate.c
src/imap-login/client.c
src/imap/cmd-append.c
src/imap/cmd-cancelupdate.c
src/imap/cmd-enable.c
src/imap/cmd-expunge.c
src/imap/cmd-fetch.c
src/imap/cmd-list.c
src/imap/cmd-search.c
src/imap/cmd-select.c
src/imap/cmd-sort.c
src/imap/cmd-status.c
src/imap/cmd-store.c
src/imap/cmd-thread.c
src/imap/imap-client.c
src/imap/imap-commands-util.c
src/imap/imap-fetch-body.c
src/imap/imap-search-args.c
src/imap/imap-search.c
src/imap/imap-status.c
src/lib-imap/Makefile.am
src/lib-imap/imap-arg.c [new file with mode: 0644]
src/lib-imap/imap-arg.h [new file with mode: 0644]
src/lib-imap/imap-bodystructure.c
src/lib-imap/imap-envelope.c
src/lib-imap/imap-id.c
src/lib-imap/imap-parser.c
src/lib-imap/imap-parser.h
src/lib-imap/imap-util.c
src/lib-storage/mail-search-build.c
src/plugins/imap-quota/imap-quota-plugin.c
src/plugins/imap-zlib/imap-zlib-plugin.c

index 630ceb3f24c0dfc956415e37e2a7cbb8935a2e6c..87ce71957da2b2d1767614fcc0b42fe0849d54af 100644 (file)
@@ -125,22 +125,18 @@ imap_client_auth_begin(struct imap_client *imap_client, const char *mech_name,
 int cmd_authenticate(struct imap_client *imap_client,
                     const struct imap_arg *args)
 {
-       const char *mech_name, *init_resp = NULL;
+       const char *mech_name, *init_resp;
 
-       /* we want only one argument: authentication mechanism name */
-       if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
+       /* <auth mechanism name> [<initial SASL response>] */
+       if (!imap_arg_get_atom(&args[0], &mech_name) || *mech_name == '\0')
                return -1;
-       if (args[1].type != IMAP_ARG_EOL) {
-               /* optional SASL initial response */
-               if (args[1].type != IMAP_ARG_ATOM ||
-                   args[2].type != IMAP_ARG_EOL)
-                       return -1;
-               init_resp = IMAP_ARG_STR(&args[1]);
-       }
-
-       mech_name = IMAP_ARG_STR(&args[0]);
-       if (*mech_name == '\0')
+       if (imap_arg_get_atom(&args[1], &init_resp))
+               args++;
+       else
+               init_resp = NULL;
+       if (!IMAP_ARG_IS_EOL(&args[1]))
                return -1;
+
        return imap_client_auth_begin(imap_client, mech_name, init_resp);
 }
 
@@ -151,15 +147,10 @@ int cmd_login(struct imap_client *imap_client, const struct imap_arg *args)
        string_t *plain_login, *base64;
 
        /* two arguments: username and password */
-       if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING)
+       if (!imap_arg_get_astring(&args[0], &user) ||
+           !imap_arg_get_astring(&args[1], &pass) ||
+           !IMAP_ARG_IS_EOL(&args[2]))
                return -1;
-       if (args[1].type != IMAP_ARG_ATOM && args[1].type != IMAP_ARG_STRING)
-               return -1;
-       if (args[2].type != IMAP_ARG_EOL)
-               return -1;
-
-       user = IMAP_ARG_STR(&args[0]);
-       pass = IMAP_ARG_STR(&args[1]);
 
        if (!client_check_plaintext_auth(client, TRUE))
                return 1;
index ce71f1de7eaa397be77fd69d5fb07ec0c4a33ddb..daaa21ba870d4c0000931b5d1415a1aeefd964c4 100644 (file)
@@ -97,14 +97,11 @@ client_update_info(struct imap_client *client, const struct imap_arg *args)
 {
        const char *key, *value;
 
-       if (args->type != IMAP_ARG_LIST)
+       if (!imap_arg_get_list(args, &args))
                return;
-       args = IMAP_ARG_LIST_ARGS(args);
 
-       while (args->type == IMAP_ARG_STRING &&
-              args[1].type == IMAP_ARG_STRING) {
-               key = IMAP_ARG_STR_NONULL(&args[0]);
-               value = IMAP_ARG_STR_NONULL(&args[1]);
+       while (imap_arg_get_string(&args[0], &key) &&
+              imap_arg_get_nstring(&args[1], &value)) {
                if (strcasecmp(key, "x-originating-ip") == 0)
                        (void)net_addr2ip(value, &client->common.ip);
                else if (strcasecmp(key, "x-originating-port") == 0)
index a500fae7a46c363f7740daa5270e5dc87da9a775..7e6b9a1ba8bd94edaa6f96a2afa4a33e183c11c8 100644 (file)
@@ -103,29 +103,25 @@ static int validate_args(const struct imap_arg *args,
                         bool *nonsync_r)
 {
        /* [<flags>] */
-       if (args->type != IMAP_ARG_LIST)
+       if (!imap_arg_get_list(args, flags_r))
                *flags_r = NULL;
-       else {
-               *flags_r = IMAP_ARG_LIST_ARGS(args);
+       else
                args++;
-       }
 
        /* [<internal date>] */
        if (args->type != IMAP_ARG_STRING)
                *internal_date_r = NULL;
        else {
-               *internal_date_r = IMAP_ARG_STR(args);
+               *internal_date_r = imap_arg_as_astring(args);
                args++;
        }
 
-       if (args->type != IMAP_ARG_LITERAL_SIZE &&
-           args->type != IMAP_ARG_LITERAL_SIZE_NONSYNC) {
+       if (!imap_arg_get_literal_size(args, msg_size_r)) {
                *nonsync_r = FALSE;
                return FALSE;
        }
 
        *nonsync_r = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
-       *msg_size_r = IMAP_ARG_LITERAL_SIZE(args);
        return TRUE;
 }
 
@@ -241,7 +237,7 @@ static bool cmd_append_continue_parsing(struct client_command_context *cmd)
                return FALSE;
        }
 
-       if (args->type == IMAP_ARG_EOL) {
+       if (IMAP_ARG_IS_EOL(args)) {
                /* last message */
                enum mailbox_sync_flags sync_flags;
                enum imap_sync_flags imap_flags;
index d2e93cfa431b1735c142a43d8a15f826d11b4ea1..731c564d658423ae80cd105a4a0125af649e7eef 100644 (file)
@@ -21,23 +21,24 @@ static bool client_search_update_cancel(struct client *client, const char *tag)
 bool cmd_cancelupdate(struct client_command_context *cmd)
 {
        const struct imap_arg *args;
-       const char *str;
+       const char *tag;
        unsigned int i;
 
        if (!client_read_args(cmd, 0, 0, &args))
                return FALSE;
 
        for (i = 0; args[i].type == IMAP_ARG_STRING; i++) ;
-       if (args[i].type != IMAP_ARG_EOL || i == 0) {
+       if (!IMAP_ARG_IS_EOL(&args[i]) || i == 0) {
                client_send_tagline(cmd, "BAD Invalid parameters.");
                return TRUE;
        }
-       for (i = 0; args[i].type == IMAP_ARG_STRING; i++) {
-               str = IMAP_ARG_STR_NONULL(&args[i]);
-               if (!client_search_update_cancel(cmd->client, str)) {
+
+       while (imap_arg_get_quoted(args, &tag)) {
+               if (!client_search_update_cancel(cmd->client, tag)) {
                        client_send_tagline(cmd, "BAD Unknown tag.");
                        return TRUE;
                }
+               args++;
        }
        client_send_tagline(cmd, "OK Updates cancelled.");
        return TRUE;
index 140057b69b508fe5eee20989fb027d9c9d8578a2..778a6e96ce4cc4285dfa4ab8ab6830955aca7f31 100644 (file)
@@ -14,12 +14,12 @@ bool cmd_enable(struct client_command_context *cmd)
 
        reply = t_str_new(64);
        str_append(reply, "* ENABLED");
-       for (; args->type != IMAP_ARG_EOL; args++) {
-               if (args->type != IMAP_ARG_ATOM) {
+       for (; !IMAP_ARG_IS_EOL(args); args++) {
+               if (!imap_arg_get_atom(args, &str)) {
                        client_send_command_error(cmd, "Invalid arguments.");
                        return TRUE;
                }
-               str = t_str_ucase(IMAP_ARG_STR(args));
+               str = t_str_ucase(str);
                if (strcmp(str, "CONDSTORE") == 0) {
                        client_enable(cmd->client, MAILBOX_FEATURE_CONDSTORE);
                        str_append(reply, " CONDSTORE");
index 924ffb2e3556d80e31684f5cf99936608347dc9e..ce0fce21a47b983de588a47c047f9105d2f8a61f 100644 (file)
@@ -58,8 +58,7 @@ bool cmd_uid_expunge(struct client_command_context *cmd)
        if (!client_verify_open_mailbox(cmd))
                return TRUE;
 
-       uidset = imap_arg_string(&args[0]);
-       if (uidset == NULL) {
+       if (!imap_arg_get_astring(&args[0], &uidset)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
index 988e4d2f24ee65e5ed175b5f0a04778b72ed7c23..e30a190c766164f2eec3743db850b956a1d39b63 100644 (file)
@@ -30,8 +30,8 @@ fetch_parse_args(struct imap_fetch_context *ctx, const struct imap_arg *arg,
                if (!imap_fetch_init_handler(ctx, "UID", &arg))
                        return FALSE;
        }
-       if (arg->type == IMAP_ARG_ATOM) {
-               str = t_str_ucase(IMAP_ARG_STR(arg));
+       if (imap_arg_get_atom(arg, &str)) {
+               str = t_str_ucase(str);
                arg++;
 
                /* handle macros first */
@@ -56,14 +56,14 @@ fetch_parse_args(struct imap_fetch_context *ctx, const struct imap_arg *arg,
                *next_arg_r = arg;
        } else {
                *next_arg_r = arg + 1;
-               arg = IMAP_ARG_LIST_ARGS(arg);
-               while (arg->type == IMAP_ARG_ATOM) {
-                       str = t_str_ucase(IMAP_ARG_STR(arg));
+               arg = imap_arg_as_list(arg);
+               while (imap_arg_get_atom(arg, &str)) {
+                       str = t_str_ucase(str);
                        arg++;
                        if (!imap_fetch_init_handler(ctx, str, &arg))
                                return FALSE;
                }
-               if (arg->type != IMAP_ARG_EOL) {
+               if (!IMAP_ARG_IS_EOL(arg)) {
                        client_send_command_error(ctx->cmd,
                                "FETCH list contains non-atoms.");
                        return FALSE;
@@ -76,15 +76,16 @@ static bool
 fetch_parse_modifier(struct imap_fetch_context *ctx,
                     const char *name, const struct imap_arg **args)
 {
+       const char *str;
        unsigned long long num;
 
        if (strcmp(name, "CHANGEDSINCE") == 0) {
-               if ((*args)->type != IMAP_ARG_ATOM) {
+               if (!imap_arg_get_atom(*args, &str)) {
                        client_send_command_error(ctx->cmd,
                                "Invalid CHANGEDSINCE modseq.");
                        return FALSE;
                }
-               num = strtoull(imap_arg_string(*args), NULL, 10);
+               num = strtoull(str, NULL, 10);
                *args += 1;
                return imap_fetch_add_changed_since(ctx, num);
        }
@@ -109,15 +110,14 @@ fetch_parse_modifiers(struct imap_fetch_context *ctx,
 {
        const char *name;
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &name)) {
                        client_send_command_error(ctx->cmd,
                                "FETCH modifiers contain non-atoms.");
                        return FALSE;
                }
-               name = t_str_ucase(IMAP_ARG_STR(args));
                args++;
-               if (!fetch_parse_modifier(ctx, name, &args))
+               if (!fetch_parse_modifier(ctx, t_str_ucase(name), &args))
                        return FALSE;
        }
        if (ctx->send_vanished &&
@@ -184,7 +184,7 @@ bool cmd_fetch(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
        struct imap_fetch_context *ctx;
-       const struct imap_arg *args, *next_arg;
+       const struct imap_arg *args, *next_arg, *list_arg;
        struct mail_search_args *search_args;
        const char *messageset;
        int ret;
@@ -196,10 +196,9 @@ bool cmd_fetch(struct client_command_context *cmd)
                return TRUE;
 
        /* <messageset> <field(s)> [(modifiers)] */
-       messageset = imap_arg_string(&args[0]);
-       if (messageset == NULL ||
+       if (!imap_arg_get_atom(&args[0], &messageset) ||
            (args[1].type != IMAP_ARG_LIST && args[1].type != IMAP_ARG_ATOM) ||
-           (args[2].type != IMAP_ARG_EOL && args[2].type != IMAP_ARG_LIST)) {
+           (!IMAP_ARG_IS_EOL(&args[2]) && args[2].type != IMAP_ARG_LIST)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
@@ -218,8 +217,8 @@ bool cmd_fetch(struct client_command_context *cmd)
        ctx->search_args = search_args;
 
        if (!fetch_parse_args(ctx, &args[1], &next_arg) ||
-           (next_arg->type == IMAP_ARG_LIST &&
-            !fetch_parse_modifiers(ctx, IMAP_ARG_LIST_ARGS(next_arg)))) {
+           (imap_arg_get_list(next_arg, &list_arg) &&
+            !fetch_parse_modifiers(ctx, list_arg))) {
                imap_fetch_deinit(ctx);
                return TRUE;
        }
index 39ef8c023ce36fe3cd23f473161e1da85399b003..92650c995f8f7806617707f93544fb5efb5856e9 100644 (file)
@@ -93,23 +93,21 @@ static bool
 parse_select_flags(struct cmd_list_context *ctx, const struct imap_arg *args)
 {
        enum mailbox_list_iter_flags list_flags = 0;
-       const char *atom;
+       const char *str;
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &str)) {
                        client_send_command_error(ctx->cmd,
                                "List options contains non-atoms.");
                        return FALSE;
                }
 
-               atom = IMAP_ARG_STR(args);
-
-               if (strcasecmp(atom, "SUBSCRIBED") == 0) {
+               if (strcasecmp(str, "SUBSCRIBED") == 0) {
                        list_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
                                MAILBOX_LIST_ITER_RETURN_SUBSCRIBED;
-               } else if (strcasecmp(atom, "RECURSIVEMATCH") == 0)
+               } else if (strcasecmp(str, "RECURSIVEMATCH") == 0)
                        list_flags |= MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH;
-               else if (strcasecmp(atom, "REMOTE") == 0) {
+               else if (strcasecmp(str, "REMOTE") == 0) {
                        /* not supported, ignore */
                } else {
                        /* skip also optional list value */
@@ -135,26 +133,24 @@ static bool
 parse_return_flags(struct cmd_list_context *ctx, const struct imap_arg *args)
 {
        enum mailbox_list_iter_flags list_flags = 0;
-       const char *atom;
+       const struct imap_arg *list_args;
+       const char *str;
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &str)) {
                        client_send_command_error(ctx->cmd,
                                "List options contains non-atoms.");
                        return FALSE;
                }
 
-               atom = IMAP_ARG_STR(args);
-
-               if (strcasecmp(atom, "SUBSCRIBED") == 0)
+               if (strcasecmp(str, "SUBSCRIBED") == 0)
                        list_flags |= MAILBOX_LIST_ITER_RETURN_SUBSCRIBED;
-               else if (strcasecmp(atom, "CHILDREN") == 0)
+               else if (strcasecmp(str, "CHILDREN") == 0)
                        list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN;
-               else if (strcasecmp(atom, "STATUS") == 0 &&
-                        args[1].type == IMAP_ARG_LIST) {
-                       if (imap_status_parse_items(ctx->cmd,
-                                               IMAP_ARG_LIST_ARGS(&args[1]),
-                                               &ctx->status_items) < 0)
+               else if (strcasecmp(str, "STATUS") == 0 &&
+                        imap_arg_get_list(&args[1], &list_args)) {
+                       if (imap_status_parse_items(ctx->cmd, list_args,
+                                                   &ctx->status_items) < 0)
                                return FALSE;
                        ctx->used_status = TRUE;
                        args++;
@@ -837,7 +833,8 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
 bool cmd_list_full(struct client_command_context *cmd, bool lsub)
 {
        struct client *client = cmd->client;
-       const struct imap_arg *args, *arg;
+       const struct imap_arg *args, *list_args;
+       unsigned int arg_count;
         struct cmd_list_context *ctx;
        ARRAY_DEFINE(patterns, const char *) = ARRAY_INIT;
        const char *pattern, *const *patterns_strarr;
@@ -854,40 +851,33 @@ bool cmd_list_full(struct client_command_context *cmd, bool lsub)
 
        cmd->context = ctx;
 
-       if (args[0].type == IMAP_ARG_LIST && !lsub) {
+       if (!lsub && imap_arg_get_list(&args[0], &list_args)) {
                /* LIST-EXTENDED selection options */
                ctx->used_listext = TRUE;
-               if (!parse_select_flags(ctx, IMAP_ARG_LIST_ARGS(&args[0])))
+               if (!parse_select_flags(ctx, list_args))
                        return TRUE;
                args++;
        }
 
-       ctx->ref = imap_arg_string(&args[0]);
-       if (ctx->ref == NULL) {
-               /* broken */
+       if (!imap_arg_get_astring(&args[0], &ctx->ref)) {
                client_send_command_error(cmd, "Invalid reference.");
                return TRUE;
        }
-       if (args[1].type == IMAP_ARG_LIST) {
+       if (imap_arg_get_list_full(&args[1], &list_args, &arg_count)) {
                ctx->used_listext = TRUE;
                /* convert pattern list to string array */
-               p_array_init(&patterns, cmd->pool,
-                            IMAP_ARG_LIST_COUNT(&args[1]));
-               arg = IMAP_ARG_LIST_ARGS(&args[1]);
-               for (; arg->type != IMAP_ARG_EOL; arg++) {
-                       if (!IMAP_ARG_TYPE_IS_STRING(arg->type)) {
-                               /* broken */
+               p_array_init(&patterns, cmd->pool, arg_count);
+               for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
+                       if (!imap_arg_get_astring(list_args, &pattern)) {
                                client_send_command_error(cmd,
                                        "Invalid pattern list.");
                                return TRUE;
                        }
-                       pattern = imap_arg_string(arg);
                        array_append(&patterns, &pattern, 1);
                }
                args += 2;
        } else {
-               pattern = imap_arg_string(&args[1]);
-               if (pattern == NULL) {
+               if (!imap_arg_get_astring(&args[1], &pattern)) {
                        client_send_command_error(cmd, "Invalid pattern.");
                        return TRUE;
                }
@@ -903,11 +893,11 @@ bool cmd_list_full(struct client_command_context *cmd, bool lsub)
                }
        }
 
-       if (args[0].type == IMAP_ARG_ATOM && args[1].type == IMAP_ARG_LIST &&
-           strcasecmp(imap_arg_string(&args[0]), "RETURN") == 0) {
+       if (imap_arg_atom_equals(&args[0], "RETURN") &&
+           imap_arg_get_list(&args[1], &list_args)) {
                /* LIST-EXTENDED return options */
                ctx->used_listext = TRUE;
-               if (!parse_return_flags(ctx, IMAP_ARG_LIST_ARGS(&args[1])))
+               if (!parse_return_flags(ctx, list_args))
                        return TRUE;
                args += 2;
        }
@@ -923,7 +913,7 @@ bool cmd_list_full(struct client_command_context *cmd, bool lsub)
                ctx->list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN;
        }
 
-       if (args[0].type != IMAP_ARG_EOL) {
+       if (!IMAP_ARG_IS_EOL(args)) {
                client_send_command_error(cmd, "Extra arguments.");
                return TRUE;
        }
index 0f4ce4d5439b8e87862da16213d32fa4749ee985..44a2a4ec0c09b5d90ed694d8612df3633d7926e1 100644 (file)
@@ -26,19 +26,14 @@ bool cmd_search(struct client_command_context *cmd)
                return ret < 0;
        }
 
-       if (args->type == IMAP_ARG_ATOM &&
-           strcasecmp(IMAP_ARG_STR_NONULL(args), "CHARSET") == 0) {
+       if (imap_arg_atom_equals(args, "CHARSET")) {
                /* CHARSET specified */
-               args++;
-               if (args->type != IMAP_ARG_ATOM &&
-                   args->type != IMAP_ARG_STRING) {
+               if (!imap_arg_get_astring(&args[1], &charset)) {
                        client_send_command_error(cmd,
-                                                 "Invalid charset argument.");
+                               "Invalid charset argument.");
                        return TRUE;
                }
-
-               charset = IMAP_ARG_STR(args);
-               args++;
+               args += 2;
        } else {
                charset = "UTF-8";
        }
index de1d4d41ad835733d283e1c89160e389090d684a..3b7bb38da2c9c71ba49c775cfb56e37639a35675 100644 (file)
@@ -64,11 +64,49 @@ static int select_qresync_get_uids(struct imap_select_context *ctx,
        return 0;
 }
 
+static bool
+select_parse_qresync_known_set(struct imap_select_context *ctx,
+                              const struct imap_arg *args)
+{
+       ARRAY_TYPE(seq_range) seqset, uidset;
+       const char *str;
+
+       t_array_init(&seqset, 32);
+       if (!imap_arg_get_atom(args, &str) ||
+           imap_seq_set_parse(str, &seqset) < 0) {
+               client_send_command_error(ctx->cmd,
+                       "Invalid QRESYNC known-sequence-set");
+               return FALSE;
+       }
+       args++;
+
+       t_array_init(&uidset, 32);
+       if (!imap_arg_get_atom(args, &str) ||
+           imap_seq_set_parse(str, &uidset) < 0) {
+               client_send_command_error(ctx->cmd,
+                       "Invalid QRESYNC known-uid-set");
+               return FALSE;
+       }
+       args++;
+
+       if (select_qresync_get_uids(ctx, &seqset, &uidset) < 0) {
+               client_send_command_error(ctx->cmd, "Invalid QRESYNC sets");
+               return FALSE;
+       }
+       if (!IMAP_ARG_IS_EOL(args)) {
+               client_send_command_error(ctx->cmd,
+                       "Too many parameters to QRESYNC known set");
+               return FALSE;
+       }
+       return TRUE;
+}
+
 static bool
 select_parse_qresync(struct imap_select_context *ctx,
                     const struct imap_arg *args)
 {
-       ARRAY_TYPE(seq_range) seqset, uidset;
+       const struct imap_arg *list_args;
+       const char *arg1, *arg2;
        unsigned int count;
 
        if ((ctx->cmd->client->enabled_features &
@@ -76,69 +114,45 @@ select_parse_qresync(struct imap_select_context *ctx,
                client_send_command_error(ctx->cmd, "QRESYNC not enabled");
                return FALSE;
        }
-       if (args->type != IMAP_ARG_LIST) {
+       if (!imap_arg_get_list_full(args, &args, &count)) {
                client_send_command_error(ctx->cmd,
                                          "QRESYNC parameters missing");
                return FALSE;
        }
-       args = IMAP_ARG_LIST_ARGS(args);
-       for (count = 0; args[count].type != IMAP_ARG_EOL; count++) ;
-
-       if (count < 2 || count > 4 ||
-           args[0].type != IMAP_ARG_ATOM ||
-           args[1].type != IMAP_ARG_ATOM ||
-           (count > 2 && args[2].type != IMAP_ARG_ATOM) ||
-           (count > 3 && args[3].type != IMAP_ARG_LIST)) {
+
+       if (!imap_arg_get_atom(&args[0], &arg1) ||
+           !imap_arg_get_atom(&args[1], &arg2)) {
                client_send_command_error(ctx->cmd,
                                          "Invalid QRESYNC parameters");
                return FALSE;
        }
-       ctx->qresync_uid_validity =
-               strtoul(IMAP_ARG_STR_NONULL(&args[0]), NULL, 10);
-       ctx->qresync_modseq =
-               strtoull(IMAP_ARG_STR_NONULL(&args[1]), NULL, 10);
-       if (count > 2) {
-               i_array_init(&ctx->qresync_known_uids, 64);
-               if (imap_seq_set_parse(IMAP_ARG_STR_NONULL(&args[2]),
-                                      &ctx->qresync_known_uids) < 0) {
-                       client_send_command_error(ctx->cmd,
-                                                 "Invalid QRESYNC known-uids");
-                       return FALSE;
-               }
-       } else {
+       args += 2;
+       ctx->qresync_uid_validity = strtoul(arg1, NULL, 10);
+       ctx->qresync_modseq = strtoull(arg2, NULL, 10);
+
+       if (!imap_arg_get_atom(args, &arg1)) {
                i_array_init(&ctx->qresync_known_uids, 64);
                seq_range_array_add_range(&ctx->qresync_known_uids,
                                          1, (uint32_t)-1);
-       }
-       if (count > 3) {
-               args = IMAP_ARG_LIST_ARGS(&args[3]);
-               if (args[0].type != IMAP_ARG_ATOM ||
-                   args[1].type != IMAP_ARG_ATOM ||
-                   args[2].type != IMAP_ARG_EOL) {
-                       client_send_command_error(ctx->cmd,
-                               "Invalid QRESYNC known set parameters");
-                       return FALSE;
-               }
-               t_array_init(&seqset, 32);
-               if (imap_seq_set_parse(IMAP_ARG_STR_NONULL(&args[0]),
-                                      &seqset) < 0) {
-                       client_send_command_error(ctx->cmd,
-                               "Invalid QRESYNC known-sequence-set");
-                       return FALSE;
-               }
-               t_array_init(&uidset, 32);
-               if (imap_seq_set_parse(IMAP_ARG_STR_NONULL(&args[1]),
-                                      &uidset) < 0) {
+       } else {
+               i_array_init(&ctx->qresync_known_uids, 64);
+               if (imap_seq_set_parse(arg1, &ctx->qresync_known_uids) < 0) {
                        client_send_command_error(ctx->cmd,
-                               "Invalid QRESYNC known-uid-set");
+                                                 "Invalid QRESYNC known-uids");
                        return FALSE;
                }
-               if (select_qresync_get_uids(ctx, &seqset, &uidset) < 0) {
-                       client_send_command_error(ctx->cmd,
-                               "Invalid QRESYNC sets");
-                       return FALSE;
+               args++;
+               if (imap_arg_get_list(args, &list_args)) {
+                       if (!select_parse_qresync_known_set(ctx, list_args))
+                               return FALSE;
+                       args++;
                }
        }
+       if (!IMAP_ARG_IS_EOL(args)) {
+               client_send_command_error(ctx->cmd,
+                                         "Invalid QRESYNC parameters");
+               return FALSE;
+       }
        return TRUE;
 }
 
@@ -148,13 +162,13 @@ select_parse_options(struct imap_select_context *ctx,
 {
        const char *name;
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &name)) {
                        client_send_command_error(ctx->cmd,
                                "SELECT options contain non-atoms.");
                        return FALSE;
                }
-               name = t_str_ucase(IMAP_ARG_STR(args));
+               name = t_str_ucase(name);
                args++;
 
                if (strcmp(name, "CONDSTORE") == 0)
@@ -340,7 +354,7 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
        struct client *client = cmd->client;
        struct mailbox *box;
        struct imap_select_context *ctx;
-       const struct imap_arg *args;
+       const struct imap_arg *args, *list_args;
        enum mailbox_name_status status;
        const char *mailbox, *storage_name;
        int ret;
@@ -349,11 +363,10 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
        if (!client_read_args(cmd, 0, 0, &args))
                return FALSE;
 
-       if (!IMAP_ARG_TYPE_IS_STRING(args[0].type)) {
+       if (!imap_arg_get_astring(args, &mailbox)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return FALSE;
        }
-       mailbox = IMAP_ARG_STR(&args[0]);
 
        ctx = p_new(cmd->pool, struct imap_select_context, 1);
        ctx->cmd = cmd;
@@ -373,8 +386,8 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
                return TRUE;
        }
 
-       if (args[1].type == IMAP_ARG_LIST) {
-               if (!select_parse_options(ctx, IMAP_ARG_LIST_ARGS(&args[1]))) {
+       if (imap_arg_get_list(&args[1], &list_args)) {
+               if (!select_parse_options(ctx, list_args)) {
                        select_context_free(ctx);
                        return TRUE;
                }
index af77dcdbb900176560b59941bbf06440ae3d0cc0..a789dbecfd3cbcaaa6f372669692f52ec30ed6ee 100644 (file)
@@ -32,20 +32,18 @@ get_sort_program(struct client_command_context *cmd,
                 enum mail_sort_type program[MAX_SORT_PROGRAM_SIZE])
 {
        enum mail_sort_type mask = 0;
+       const char *arg;
        unsigned int i, pos;
        bool reverse, last_reverse;
 
-       if (args->type == IMAP_ARG_EOL) {
+       if (IMAP_ARG_IS_EOL(args)) {
                /* empyty list */
                client_send_command_error(cmd, "Empty sort program.");
                return -1;
        }
 
        pos = 0; reverse = last_reverse = FALSE;
-       for (; args->type == IMAP_ARG_ATOM || args->type == IMAP_ARG_STRING;
-            args++) {
-               const char *arg = IMAP_ARG_STR(args);
-
+       for (; imap_arg_get_astring(args, &arg); args++) {
                last_reverse = strcasecmp(arg, "reverse") == 0;
                if (last_reverse) {
                        reverse = !reverse;
@@ -80,7 +78,7 @@ get_sort_program(struct client_command_context *cmd,
        }
        program[pos] = MAIL_SORT_END;
 
-       if (args->type != IMAP_ARG_EOL) {
+       if (!IMAP_ARG_IS_EOL(args)) {
                client_send_command_error(cmd,
                                          "Invalid sort list argument.");
                return -1;
@@ -94,7 +92,7 @@ bool cmd_sort(struct client_command_context *cmd)
        struct imap_search_context *ctx;
        struct mail_search_args *sargs;
        enum mail_sort_type sort_program[MAX_SORT_PROGRAM_SIZE];
-       const struct imap_arg *args;
+       const struct imap_arg *args, *list_args;
        const char *charset;
        int ret;
 
@@ -113,22 +111,20 @@ bool cmd_sort(struct client_command_context *cmd)
        }
 
        /* sort program */
-       if (args->type != IMAP_ARG_LIST) {
+       if (!imap_arg_get_list(args, &list_args)) {
                client_send_command_error(cmd, "Invalid sort argument.");
                return TRUE;
        }
 
-       if (get_sort_program(cmd, IMAP_ARG_LIST_ARGS(args), sort_program) < 0)
+       if (get_sort_program(cmd, list_args, sort_program) < 0)
                return TRUE;
        args++;
 
        /* charset */
-       if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) {
-               client_send_command_error(cmd,
-                                         "Invalid charset argument.");
+       if (!imap_arg_get_astring(args, &charset)) {
+               client_send_command_error(cmd, "Invalid charset argument.");
                return TRUE;
        }
-       charset = IMAP_ARG_STR(args);
        args++;
 
        ret = imap_search_args_build(cmd, args, charset, &sargs);
index 43cc8ecf3657c1eb1c02603994d18a9ba28feab7..b4d6959c6781a6df62ad44a1a5333a5d7bc3734c 100644 (file)
@@ -10,7 +10,7 @@ bool cmd_status(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
        enum mailbox_name_status status;
-       const struct imap_arg *args;
+       const struct imap_arg *args, *list_args;
        struct imap_status_items items;
        struct imap_status_result result;
        struct mail_namespace *ns;
@@ -21,15 +21,14 @@ bool cmd_status(struct client_command_context *cmd)
        if (!client_read_args(cmd, 2, 0, &args))
                return FALSE;
 
-       mailbox = imap_arg_string(&args[0]);
-       if (mailbox == NULL || args[1].type != IMAP_ARG_LIST) {
-               client_send_command_error(cmd, "Status items must be list.");
+       if (!imap_arg_get_astring(&args[0], &mailbox) ||
+           !imap_arg_get_list(&args[1], &list_args)) {
+               client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
 
        /* get the items client wants */
-       if (imap_status_parse_items(cmd, IMAP_ARG_LIST_ARGS(&args[1]),
-                                   &items) < 0)
+       if (imap_status_parse_items(cmd, list_args, &items) < 0)
                return TRUE;
 
        ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
index 30361916af98ff26367cdc907123190aae7e75a0..51dd1b1273b317cb0ff0c01f129b73a87bd5f315 100644 (file)
@@ -46,20 +46,18 @@ static bool
 store_parse_modifiers(struct imap_store_context *ctx,
                      const struct imap_arg *args)
 {
-       const char *name;
+       const char *name, *value;
 
-       for (; args->type != IMAP_ARG_EOL; args++) {
-               if (args->type != IMAP_ARG_ATOM ||
-                   args[1].type != IMAP_ARG_ATOM) {
+       for (; !IMAP_ARG_IS_EOL(args); args += 2) {
+               if (!imap_arg_get_atom(&args[0], &name) ||
+                   !imap_arg_get_atom(&args[1], &value)) {
                        client_send_command_error(ctx->cmd,
-                               "STORE modifiers contain non-atoms.");
+                               "Invalid STORE modifiers.");
                        return FALSE;
                }
-               name = IMAP_ARG_STR(args);
+
                if (strcasecmp(name, "UNCHANGEDSINCE") == 0) {
-                       args++;
-                       ctx->max_modseq =
-                               strtoull(imap_arg_string(args), NULL, 10);
+                       ctx->max_modseq = strtoull(value, NULL, 10);
                        client_enable(ctx->cmd->client,
                                      MAILBOX_FEATURE_CONDSTORE);
                } else {
@@ -75,24 +73,26 @@ static bool
 store_parse_args(struct imap_store_context *ctx, const struct imap_arg *args)
 {
        struct client_command_context *cmd = ctx->cmd;
+       const struct imap_arg *list_args;
        const char *type;
        const char *const *keywords_list = NULL;
 
        ctx->max_modseq = (uint64_t)-1;
-       if (args->type == IMAP_ARG_LIST) {
-               if (!store_parse_modifiers(ctx, IMAP_ARG_LIST_ARGS(args)))
+       if (imap_arg_get_list(args, &list_args)) {
+               if (!store_parse_modifiers(ctx, list_args))
                        return FALSE;
                args++;
        }
 
-       type = imap_arg_string(args++);
-       if (type == NULL || !get_modify_type(ctx, type)) {
+       if (!imap_arg_get_astring(args, &type) ||
+           !get_modify_type(ctx, type)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return FALSE;
        }
+       args++;
 
-       if (args->type == IMAP_ARG_LIST) {
-               if (!client_parse_mail_flags(cmd, IMAP_ARG_LIST_ARGS(args),
+       if (imap_arg_get_list(args, &list_args)) {
+               if (!client_parse_mail_flags(cmd, list_args,
                                             &ctx->flags, &keywords_list))
                        return FALSE;
        } else {
@@ -125,7 +125,7 @@ bool cmd_store(struct client_command_context *cmd)
        ARRAY_TYPE(seq_range) modified_set, uids;
        enum mailbox_transaction_flags flags = 0;
        enum imap_sync_flags imap_sync_flags = 0;
-       const char *reply, *tagged_reply;
+       const char *set, *reply, *tagged_reply;
        string_t *str;
        int ret;
 
@@ -135,12 +135,11 @@ bool cmd_store(struct client_command_context *cmd)
        if (!client_verify_open_mailbox(cmd))
                return TRUE;
 
-       if (args->type != IMAP_ARG_ATOM) {
+       if (!imap_arg_get_atom(args, &set)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
-       ret = imap_search_get_seqset(cmd, IMAP_ARG_STR_NONULL(args),
-                                    cmd->uid, &search_args);
+       ret = imap_search_get_seqset(cmd, set, cmd->uid, &search_args);
        if (ret <= 0)
                return ret < 0;
 
index 70f2f7e2e204fe71a2439e4b0e609bd13011649c..54c8905ab02ba02f04732d066b4605907551f83c 100644 (file)
@@ -117,26 +117,17 @@ bool cmd_thread(struct client_command_context *cmd)
        if (!client_verify_open_mailbox(cmd))
                return TRUE;
 
-       if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) {
-               client_send_command_error(cmd,
-                                         "Invalid thread algorithm argument.");
+       if (!imap_arg_get_astring(&args[0], &str) ||
+           !imap_arg_get_astring(&args[1], &charset)) {
+               client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
+       args += 2;
 
-       str = IMAP_ARG_STR(args);
        if (!mail_thread_type_parse(str, &thread_type)) {
                client_send_command_error(cmd, "Unknown thread algorithm.");
                return TRUE;
        }
-       args++;
-
-       /* charset */
-       if (args->type != IMAP_ARG_ATOM && args->type != IMAP_ARG_STRING) {
-               client_send_command_error(cmd, "Invalid charset argument.");
-               return TRUE;
-       }
-       charset = IMAP_ARG_STR(args);
-       args++;
 
        ret = imap_search_args_build(cmd, args, charset, &sargs);
        if (ret <= 0)
@@ -146,7 +137,7 @@ bool cmd_thread(struct client_command_context *cmd)
        mail_search_args_unref(&sargs);
        if (ret < 0) {
                client_send_storage_error(cmd,
-                                         mailbox_get_storage(client->mailbox));
+                       mailbox_get_storage(client->mailbox));
                return TRUE;
        }
 
index 3256b1461f1cddcf856dd7cfe5fe028104f71bc7..df8f08d7fec3c3a9cbc2b4247d7f0b052cfe837a 100644 (file)
@@ -383,13 +383,12 @@ bool client_read_string_args(struct client_command_context *cmd,
        for (i = 0; i < count; i++) {
                const char **ret = va_arg(va, const char **);
 
-               if (imap_args[i].type == IMAP_ARG_EOL) {
+               if (IMAP_ARG_IS_EOL(&imap_args[i])) {
                        client_send_command_error(cmd, "Missing arguments.");
                        break;
                }
 
-               str = imap_arg_string(&imap_args[i]);
-               if (str == NULL) {
+               if (!imap_arg_get_astring(&imap_args[i], &str)) {
                        client_send_command_error(cmd, "Invalid arguments.");
                        break;
                }
index 5a68867de59d428370a31a5ff220693514889b22..cb1234894f071ed919793ad566b584b535e7f53e 100644 (file)
@@ -244,14 +244,13 @@ bool client_parse_mail_flags(struct client_command_context *cmd,
        *keywords_r = NULL;
        p_array_init(&keywords, cmd->pool, 16);
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &atom)) {
                        client_send_command_error(cmd,
                                "Flags list contains non-atoms.");
                        return FALSE;
                }
 
-               atom = IMAP_ARG_STR(args);
                if (*atom == '\\') {
                        /* system flag */
                        atom = t_str_ucase(atom);
index af70876e1cfc3bd733aa16090c58ea51aafb58f6..7c158bb172ed3185219fa911a77db4ee631bcbd4 100644 (file)
@@ -758,7 +758,7 @@ static bool body_section_build(struct imap_fetch_context *ctx,
                               unsigned int args_count)
 {
        string_t *str;
-       const char **arr;
+       const char **arr, *value;
        size_t i;
 
        str = str_new(ctx->cmd->pool, 128);
@@ -769,8 +769,7 @@ static bool body_section_build(struct imap_fetch_context *ctx,
        arr = p_new(ctx->cmd->pool, const char *, args_count + 1);
 
        for (i = 0; i < args_count; i++) {
-               if (args[i].type != IMAP_ARG_ATOM &&
-                   args[i].type != IMAP_ARG_STRING) {
+               if (!imap_arg_get_astring(&args[i], &value)) {
                        client_send_command_error(ctx->cmd,
                                "Invalid BODY[..] parameter: "
                                "Header list contains non-strings");
@@ -779,7 +778,7 @@ static bool body_section_build(struct imap_fetch_context *ctx,
 
                if (i != 0)
                        str_append_c(str, ' ');
-               arr[i] = t_str_ucase(IMAP_ARG_STR(&args[i]));
+               arr[i] = t_str_ucase(value);
 
                if (args[i].type == IMAP_ARG_ATOM)
                        str_append(str, arr[i]);
@@ -802,7 +801,9 @@ bool fetch_body_section_init(struct imap_fetch_context *ctx, const char *name,
                             const struct imap_arg **args)
 {
        struct imap_fetch_body_data *body;
-       const char *partial;
+       const struct imap_arg *list_args;
+       unsigned int list_count;
+       const char *partial, *str;
        const char *p = name + 4;
 
        body = p_new(ctx->cmd->pool, struct imap_fetch_body_data, 1);
@@ -821,19 +822,17 @@ bool fetch_body_section_init(struct imap_fetch_context *ctx, const char *name,
                return FALSE;
        }
 
-       if ((*args)[0].type == IMAP_ARG_LIST) {
+       if (imap_arg_get_list_full(&(*args)[0], &list_args, &list_count)) {
                /* BODY[HEADER.FIELDS.. (headers list)] */
-               if ((*args)[1].type != IMAP_ARG_ATOM ||
-                   IMAP_ARG_STR(&(*args)[1])[0] != ']') {
+               if (!imap_arg_get_atom(&(*args)[1], &str) ||
+                   str[0] != ']') {
                        client_send_command_error(ctx->cmd,
                                "Invalid BODY[..] parameter: Missing ']'");
                        return FALSE;
                }
-               if (!body_section_build(ctx, body, p+1,
-                                       IMAP_ARG_LIST_ARGS(&(*args)[0]),
-                                       IMAP_ARG_LIST_COUNT(&(*args)[0])))
+               if (!body_section_build(ctx, body, p+1, list_args, list_count))
                        return FALSE;
-               p = IMAP_ARG_STR(&(*args)[1]);
+               p = str;
                *args += 2;
        } else {
                /* no headers list */
index 7eda0b7686aa467669ddc7ec7b28bfcb200804bd..74326a80b2ddf095f6cecd2829ad4fccb6c2a4a1 100644 (file)
@@ -42,7 +42,7 @@ int imap_search_args_build(struct client_command_context *cmd,
        struct mail_search_args *sargs;
        const char *error;
 
-       if (args->type == IMAP_ARG_EOL) {
+       if (IMAP_ARG_IS_EOL(args)) {
                client_send_command_error(cmd, "Missing search parameters");
                return -1;
        }
index b510d212f57a79559895d1d7f5d08552abc085f6..6c6b842fe50288d640dd9730fa0e7a99a9996e10 100644 (file)
@@ -47,13 +47,13 @@ search_parse_return_options(struct imap_search_context *ctx,
        const char *name, *str;
        unsigned int idx;
 
-       while (args->type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_ATOM) {
+       while (!IMAP_ARG_IS_EOL(args)) {
+               if (!imap_arg_get_atom(args, &name)) {
                        client_send_command_error(cmd,
                                "SEARCH return options contain non-atoms.");
                        return FALSE;
                }
-               name = t_str_ucase(IMAP_ARG_STR_NONULL(args));
+               name = t_str_ucase(name);
                args++;
                if (strcmp(name, "MIN") == 0)
                        ctx->return_options |= SEARCH_RETURN_MIN;
@@ -74,12 +74,11 @@ search_parse_return_options(struct imap_search_context *ctx,
                                return FALSE;
                        }
                        ctx->return_options |= SEARCH_RETURN_PARTIAL;
-                       if (args->type != IMAP_ARG_ATOM) {
+                       if (!imap_arg_get_atom(args, &str)) {
                                client_send_command_error(cmd,
                                        "PARTIAL range missing.");
                                return FALSE;
                        }
-                       str = IMAP_ARG_STR_NONULL(args);
                        if (imap_partial_range_parse(ctx, str) < 0) {
                                client_send_command_error(cmd,
                                        "PARTIAL range broken.");
@@ -445,19 +444,17 @@ static void cmd_search_more_callback(struct client_command_context *cmd)
 int cmd_search_parse_return_if_found(struct imap_search_context *ctx,
                                     const struct imap_arg **_args)
 {
-       const struct imap_arg *args = *_args;
+       const struct imap_arg *list_args, *args = *_args;
        struct client_command_context *cmd = ctx->cmd;
 
-       if (!(args->type == IMAP_ARG_ATOM && args[1].type == IMAP_ARG_LIST &&
-             strcasecmp(IMAP_ARG_STR_NONULL(args), "RETURN") == 0)) {
+       if (!imap_arg_atom_equals(&args[0], "RETURN") ||
+           !imap_arg_get_list(&args[1], &list_args)) {
                ctx->return_options = SEARCH_RETURN_ALL;
                return 1;
        }
 
-       args++;
-       if (!search_parse_return_options(ctx, IMAP_ARG_LIST_ARGS(args)))
+       if (!search_parse_return_options(ctx, list_args))
                return -1;
-       args++;
 
        if ((ctx->return_options & SEARCH_RETURN_SAVE) != 0) {
                /* wait if there is another SEARCH SAVE command running. */
@@ -472,7 +469,7 @@ int cmd_search_parse_return_if_found(struct imap_search_context *ctx,
                        i_array_init(&cmd->client->search_saved_uidset, 128);
        }
 
-       *_args = args;
+       *_args = args + 2;
        return 1;
 }
 
index 3f41623868251dfc81f56fb27ef43f6d83c25a3e..be950778afac96998fbaca3d246b0f08f2f18ffd 100644 (file)
@@ -15,16 +15,15 @@ int imap_status_parse_items(struct client_command_context *cmd,
 
        memset(items_r, 0, sizeof(*items_r));
        items = 0;
-       for (; args->type != IMAP_ARG_EOL; args++) {
-               if (args->type != IMAP_ARG_ATOM) {
+       for (; !IMAP_ARG_IS_EOL(args); args++) {
+               if (!imap_arg_get_atom(args, &item)) {
                        /* list may contain only atoms */
                        client_send_command_error(cmd,
                                "Status list contains non-atoms.");
                        return -1;
                }
 
-               item = t_str_ucase(IMAP_ARG_STR(args));
-
+               item = t_str_ucase(item);
                if (strcmp(item, "MESSAGES") == 0)
                        items |= STATUS_MESSAGES;
                else if (strcmp(item, "RECENT") == 0)
index 1e1d5f21543bc20e4fe5280ea1619f1017f375eb..65f9e05e3e96fbd9abe081358c351bd97adf63eb 100644 (file)
@@ -7,6 +7,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib-mail
 
 libimap_la_SOURCES = \
+       imap-arg.c \
        imap-base-subject.c \
        imap-bodystructure.c \
        imap-date.c \
@@ -20,6 +21,7 @@ libimap_la_SOURCES = \
        imap-util.c
 
 headers = \
+       imap-arg.h \
        imap-base-subject.h \
        imap-bodystructure.h \
        imap-date.h \
@@ -57,16 +59,16 @@ test_imap_match_LDADD = imap-match.lo $(test_libs)
 test_imap_match_DEPENDENCIES = imap-match.lo $(test_libs)
 
 test_imap_parser_SOURCES = test-imap-parser.c
-test_imap_parser_LDADD = imap-parser.lo $(test_libs)
-test_imap_parser_DEPENDENCIES = imap-parser.lo $(test_libs)
+test_imap_parser_LDADD = imap-parser.lo imap-arg.lo $(test_libs)
+test_imap_parser_DEPENDENCIES = imap-parser.lo imap-arg.lo $(test_libs)
 
 test_imap_utf7_SOURCES = test-imap-utf7.c
 test_imap_utf7_LDADD = imap-utf7.lo $(test_libs)
 test_imap_utf7_DEPENDENCIES = imap-utf7.lo $(test_libs)
 
 test_imap_util_SOURCES = test-imap-util.c
-test_imap_util_LDADD = imap-util.lo $(test_libs)
-test_imap_util_DEPENDENCIES = imap-util.lo $(test_libs)
+test_imap_util_LDADD = imap-util.lo imap-arg.lo $(test_libs)
+test_imap_util_DEPENDENCIES = imap-util.lo imap-arg.lo $(test_libs)
 
 check: check-am check-test
 check-test: all-am
diff --git a/src/lib-imap/imap-arg.c b/src/lib-imap/imap-arg.c
new file mode 100644 (file)
index 0000000..0a1674c
--- /dev/null
@@ -0,0 +1,130 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "imap-arg.h"
+
+bool imap_arg_get_atom(const struct imap_arg *arg, const char **str_r)
+{
+       if (arg->type != IMAP_ARG_ATOM)
+               return FALSE;
+
+       *str_r = arg->_data.str;
+       return TRUE;
+}
+
+bool imap_arg_get_quoted(const struct imap_arg *arg, const char **str_r)
+{
+       if (arg->type != IMAP_ARG_STRING)
+               return FALSE;
+
+       *str_r = arg->_data.str;
+       return TRUE;
+}
+
+bool imap_arg_get_string(const struct imap_arg *arg, const char **str_r)
+{
+       if (arg->type != IMAP_ARG_STRING && arg->type != IMAP_ARG_LITERAL)
+               return FALSE;
+
+       *str_r = arg->_data.str;
+       return TRUE;
+}
+
+bool imap_arg_get_astring(const struct imap_arg *arg, const char **str_r)
+{
+       if (!IMAP_ARG_IS_ASTRING(arg))
+               return FALSE;
+
+       *str_r = arg->_data.str;
+       return TRUE;
+}
+
+bool imap_arg_get_nstring(const struct imap_arg *arg, const char **str_r)
+{
+       if (arg->type == IMAP_ARG_NIL) {
+               *str_r = NULL;
+               return TRUE;
+       }
+       return imap_arg_get_astring(arg, str_r);
+}
+
+bool imap_arg_get_literal_size(const struct imap_arg *arg, uoff_t *size_r)
+{
+       if (arg->type != IMAP_ARG_LITERAL_SIZE &&
+           arg->type != IMAP_ARG_LITERAL_SIZE_NONSYNC)
+               return FALSE;
+
+       *size_r = arg->_data.literal_size;
+       return TRUE;
+}
+
+bool imap_arg_get_list(const struct imap_arg *arg,
+                      const struct imap_arg **list_r)
+{
+       unsigned int count;
+
+       return imap_arg_get_list_full(arg, list_r, &count);
+}
+
+bool imap_arg_get_list_full(const struct imap_arg *arg,
+                           const struct imap_arg **list_r,
+                           unsigned int *list_count_r)
+{
+       unsigned int count;
+
+       if (arg->type != IMAP_ARG_LIST)
+               return FALSE;
+
+       *list_r = array_get(&arg->_data.list, &count);
+
+       /* drop IMAP_ARG_EOL from list size */
+       i_assert(count > 0);
+       *list_count_r = count - 1;
+       return TRUE;
+}
+
+const char *imap_arg_as_astring(const struct imap_arg *arg)
+{
+       const char *str;
+
+       if (!imap_arg_get_astring(arg, &str))
+               i_unreached();
+       return str;
+}
+
+const char *imap_arg_as_nstring(const struct imap_arg *arg)
+{
+       const char *str;
+
+       if (!imap_arg_get_nstring(arg, &str))
+               i_unreached();
+       return str;
+}
+
+uoff_t imap_arg_as_literal_size(const struct imap_arg *arg)
+{
+       uoff_t size;
+
+       if (!imap_arg_get_literal_size(arg, &size))
+               i_unreached();
+       return size;
+}
+
+const struct imap_arg *
+imap_arg_as_list(const struct imap_arg *arg)
+{
+       const struct imap_arg *ret;
+
+       if (!imap_arg_get_list(arg, &ret))
+               i_unreached();
+       return ret;
+}
+
+bool imap_arg_atom_equals(const struct imap_arg *arg, const char *str)
+{
+       const char *value;
+
+       if (!imap_arg_get_atom(arg, &value))
+               return FALSE;
+       return strcasecmp(value, str) == 0;
+}
diff --git a/src/lib-imap/imap-arg.h b/src/lib-imap/imap-arg.h
new file mode 100644 (file)
index 0000000..d42be4e
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef IMAP_ARG_H
+#define IMAP_ARG_H
+
+#include "array.h"
+
+/* We use this macro to read atoms from input. It should probably contain
+   everything some day, but for now we can't handle some input otherwise:
+
+   ']' is required for parsing section (FETCH BODY[])
+   '%', '*' and ']' are valid list-chars for LIST patterns
+   '\' is used in flags */
+#define IS_ATOM_SPECIAL_INPUT(c) \
+       ((c) == '(' || (c) == ')' || (c) == '{' || \
+        (c) == '"' || (c) <= 32 || (c) == 0x7f)
+
+#define IS_ATOM_SPECIAL(c) \
+       (IS_ATOM_SPECIAL_INPUT(c) || \
+        (c) == ']' || (c) == '%' || (c) == '*' || (c) == '\\')
+
+enum imap_arg_type {
+       IMAP_ARG_NIL = 0,
+       IMAP_ARG_ATOM,
+       IMAP_ARG_STRING,
+       IMAP_ARG_LIST,
+
+       /* literals are returned as IMAP_ARG_STRING by default */
+       IMAP_ARG_LITERAL,
+       IMAP_ARG_LITERAL_SIZE,
+       IMAP_ARG_LITERAL_SIZE_NONSYNC,
+
+       IMAP_ARG_EOL /* end of argument list */
+};
+
+ARRAY_DEFINE_TYPE(imap_arg_list, struct imap_arg);
+struct imap_arg {
+       enum imap_arg_type type;
+        struct imap_arg *parent; /* always of type IMAP_ARG_LIST */
+
+       union {
+               const char *str;
+               uoff_t literal_size;
+               ARRAY_TYPE(imap_arg_list) list;
+       } _data;
+};
+
+/* RFC 3501's astring type */
+#define IMAP_ARG_TYPE_IS_ASTRING(type) \
+       ((type) == IMAP_ARG_ATOM || \
+        (type) == IMAP_ARG_STRING || \
+        (type) == IMAP_ARG_LITERAL)
+#define IMAP_ARG_IS_ASTRING(arg) \
+       IMAP_ARG_TYPE_IS_ASTRING((arg)->type)
+#define IMAP_ARG_IS_EOL(arg) \
+       ((arg)->type == IMAP_ARG_EOL)
+
+bool imap_arg_get_atom(const struct imap_arg *arg, const char **str_r)
+       ATTR_WARN_UNUSED_RESULT;
+bool imap_arg_get_quoted(const struct imap_arg *arg, const char **str_r)
+       ATTR_WARN_UNUSED_RESULT;
+bool imap_arg_get_string(const struct imap_arg *arg, const char **str_r)
+       ATTR_WARN_UNUSED_RESULT;
+bool imap_arg_get_astring(const struct imap_arg *arg, const char **str_r)
+       ATTR_WARN_UNUSED_RESULT;
+/* str is set to NULL for NIL. */
+bool imap_arg_get_nstring(const struct imap_arg *arg, const char **str_r)
+       ATTR_WARN_UNUSED_RESULT;
+
+bool imap_arg_get_literal_size(const struct imap_arg *arg, uoff_t *size_r)
+       ATTR_WARN_UNUSED_RESULT;
+
+bool imap_arg_get_list(const struct imap_arg *arg,
+                      const struct imap_arg **list_r)
+       ATTR_WARN_UNUSED_RESULT;
+bool imap_arg_get_list_full(const struct imap_arg *arg,
+                           const struct imap_arg **list_r,
+                           unsigned int *list_count_r) ATTR_WARN_UNUSED_RESULT;
+
+/* Similar to above, but assumes that arg is already of correct type. */
+const char *imap_arg_as_astring(const struct imap_arg *arg);
+const char *imap_arg_as_nstring(const struct imap_arg *arg);
+uoff_t imap_arg_as_literal_size(const struct imap_arg *arg);
+const struct imap_arg *imap_arg_as_list(const struct imap_arg *arg);
+
+/* Returns TRUE if arg is atom and case-insensitively matches str */
+bool imap_arg_atom_equals(const struct imap_arg *arg, const char *str);
+
+#endif
index 589063edec098bf72b0e054b1763f98875aeab05..edebef42fcff0e07e68d81f0ac7ce4b99ba683a6 100644 (file)
@@ -534,47 +534,54 @@ void imap_bodystructure_write(const struct message_part *part,
 
 static bool str_append_imap_arg(string_t *str, const struct imap_arg *arg)
 {
+       const char *cstr;
+
+       if (!imap_arg_get_nstring(arg, &cstr))
+               return FALSE;
+
        switch (arg->type) {
        case IMAP_ARG_NIL:
                str_append(str, "NIL");
                break;
        case IMAP_ARG_ATOM:
-               str_append(str, IMAP_ARG_STR(arg));
+               str_append(str, cstr);
                break;
        case IMAP_ARG_STRING:
                str_append_c(str, '"');
-               str_append(str, IMAP_ARG_STR(arg));
+               /* NOTE: we're parsing with no-unescape flag,
+                  so don't double-escape it here */
+               str_append(str, cstr);
                str_append_c(str, '"');
                break;
        case IMAP_ARG_LITERAL: {
-               const char *argstr = IMAP_ARG_STR(arg);
-
-               str_printfa(str, "{%"PRIuSIZE_T"}\r\n", strlen(argstr));
-               str_append(str, argstr);
+               str_printfa(str, "{%"PRIuSIZE_T"}\r\n", strlen(cstr));
+               str_append(str, cstr);
                break;
        }
        default:
+               i_unreached();
                return FALSE;
        }
-
        return TRUE;
 }
 
 static bool imap_write_list(const struct imap_arg *args, string_t *str)
 {
+       const struct imap_arg *children;
+
        /* don't do any typechecking, just write it out */
        str_append_c(str, '(');
-       while (args->type != IMAP_ARG_EOL) {
+       while (!IMAP_ARG_IS_EOL(args)) {
                if (!str_append_imap_arg(str, args)) {
-                       if (args->type != IMAP_ARG_LIST)
+                       if (!imap_arg_get_list(args, &children))
                                return FALSE;
 
-                       if (!imap_write_list(IMAP_ARG_LIST_ARGS(args), str))
+                       if (!imap_write_list(children, str))
                                return FALSE;
                }
                args++;
 
-               if (args->type != IMAP_ARG_EOL)
+               if (!IMAP_ARG_IS_EOL(args))
                        str_append_c(str, ' ');
        }
        str_append_c(str, ')');
@@ -586,13 +593,14 @@ static bool imap_parse_bodystructure_args(const struct imap_arg *args,
 {
        const struct imap_arg *subargs;
        const struct imap_arg *list_args;
+       const char *value, *content_type, *subtype;
        bool multipart, text, message_rfc822;
        int i;
 
        multipart = FALSE;
        while (args->type == IMAP_ARG_LIST) {
                str_append_c(str, '(');
-               list_args = IMAP_ARG_LIST_ARGS(args);
+               list_args = imap_arg_as_list(args);
                if (!imap_parse_bodystructure_args(list_args, str))
                        return FALSE;
                str_append_c(str, ')');
@@ -608,7 +616,8 @@ static bool imap_parse_bodystructure_args(const struct imap_arg *args,
        }
 
        /* "content type" "subtype" */
-       if (args[0].type == IMAP_ARG_NIL || args[1].type == IMAP_ARG_NIL)
+       if (!imap_arg_get_astring(&args[0], &content_type) ||
+           !imap_arg_get_astring(&args[1], &subtype))
                return FALSE;
 
        if (!str_append_imap_arg(str, &args[0]))
@@ -617,18 +626,16 @@ static bool imap_parse_bodystructure_args(const struct imap_arg *args,
        if (!str_append_imap_arg(str, &args[1]))
                return FALSE;
 
-       text = strcasecmp(IMAP_ARG_STR_NONULL(&args[0]), "text") == 0;
-       message_rfc822 =
-               strcasecmp(IMAP_ARG_STR_NONULL(&args[0]), "message") == 0 &&
-               strcasecmp(IMAP_ARG_STR_NONULL(&args[1]), "rfc822") == 0;
+       text = strcasecmp(content_type, "text") == 0;
+       message_rfc822 = strcasecmp(content_type, "message") == 0 &&
+               strcasecmp(subtype, "rfc822") == 0;
 
        args += 2;
 
        /* ("content type param key" "value" ...) | NIL */
-       if (args->type == IMAP_ARG_LIST) {
+       if (imap_arg_get_list(args, &subargs)) {
                str_append(str, " (");
-                subargs = IMAP_ARG_LIST_ARGS(args);
-               for (; subargs->type != IMAP_ARG_EOL; ) {
+               while (!IMAP_ARG_IS_EOL(subargs)) {
                        if (!str_append_imap_arg(str, &subargs[0]))
                                return FALSE;
                        str_append_c(str, ' ');
@@ -636,7 +643,7 @@ static bool imap_parse_bodystructure_args(const struct imap_arg *args,
                                return FALSE;
 
                        subargs += 2;
-                       if (subargs->type == IMAP_ARG_EOL)
+                       if (IMAP_ARG_IS_EOL(subargs))
                                break;
                        str_append_c(str, ' ');
                }
@@ -658,32 +665,31 @@ static bool imap_parse_bodystructure_args(const struct imap_arg *args,
 
        if (text) {
                /* text/xxx - text lines */
-               if (args->type != IMAP_ARG_ATOM)
+               if (!imap_arg_get_atom(args, &value))
                        return FALSE;
 
                str_append_c(str, ' ');
-               str_append(str, IMAP_ARG_STR(args));
+               str_append(str, value);
        } else if (message_rfc822) {
                /* message/rfc822 - envelope + bodystructure + text lines */
-               if (args[0].type != IMAP_ARG_LIST ||
-                   args[1].type != IMAP_ARG_LIST ||
-                   args[2].type != IMAP_ARG_ATOM)
-                       return FALSE;
-
                str_append_c(str, ' ');
 
-               list_args = IMAP_ARG_LIST_ARGS(&args[0]);
+               if (!imap_arg_get_list(&args[0], &list_args))
+                       return FALSE;
                if (!imap_write_list(list_args, str))
                        return FALSE;
 
                str_append(str, " (");
 
-               list_args = IMAP_ARG_LIST_ARGS(&args[1]);
+               if (!imap_arg_get_list(&args[1], &list_args))
+                       return FALSE;
                if (!imap_parse_bodystructure_args(list_args, str))
                        return FALSE;
 
                str_append(str, ") ");
-               str_append(str, IMAP_ARG_STR(&args[2]));
+               if (!imap_arg_get_atom(&args[2], &value))
+                       return FALSE;
+               str_append(str, value);
        }
 
        return TRUE;
index 8b6f7f2bc45ae448800869cbcac9fcea2e69851a..b070b6402206fb5630d96d66054a9c3d66a0f254 100644 (file)
@@ -221,22 +221,15 @@ static bool imap_address_arg_append(const struct imap_arg *arg, string_t *str,
        const char *args[4];
        int i;
 
-       if (arg->type != IMAP_ARG_LIST)
+       if (!imap_arg_get_list_full(arg, &list_args, &list_count))
                return FALSE;
-       list_args = IMAP_ARG_LIST_ARGS(arg);
-       list_count = IMAP_ARG_LIST_COUNT(arg);
 
        /* we require 4 arguments, strings or NILs */
        if (list_count < 4)
                return FALSE;
 
        for (i = 0; i < 4; i++) {
-               if (list_args[i].type == IMAP_ARG_NIL)
-                       args[i] = NULL;
-               else if (list_args[i].type == IMAP_ARG_STRING ||
-                        list_args[i].type == IMAP_ARG_ATOM)
-                       args[i] = IMAP_ARG_STR(&list_args[i]);
-               else
+               if (!imap_arg_get_nstring(&list_args[i], &args[i]))
                        return FALSE;
        }
 
@@ -298,14 +291,13 @@ static const char *imap_envelope_parse_address(const struct imap_arg *arg)
        string_t *str;
        bool in_group;
 
-       if (arg->type != IMAP_ARG_LIST)
+       if (!imap_arg_get_list(arg, &list_args))
                return NULL;
 
        in_group = FALSE;
        str = t_str_new(128);
 
-       list_args = IMAP_ARG_LIST_ARGS(arg);
-       for (; list_args->type != IMAP_ARG_EOL; list_args++) {
+       for (; !IMAP_ARG_IS_EOL(list_args); list_args++) {
                if (!imap_address_arg_append(list_args, str, &in_group))
                        return NULL;
        }
@@ -316,21 +308,22 @@ static const char *imap_envelope_parse_address(const struct imap_arg *arg)
 static const char *imap_envelope_parse_first_mailbox(const struct imap_arg *arg)
 {
        const struct imap_arg *list_args;
+       const char *str;
+       unsigned int list_count;
 
        /* ((...)(...) ...) */
-       if (arg->type != IMAP_ARG_LIST)
+       if (!imap_arg_get_list(arg, &list_args))
                return NULL;
-
-       list_args = IMAP_ARG_LIST_ARGS(arg);
-       if (list_args->type == IMAP_ARG_EOL)
+       if (IMAP_ARG_IS_EOL(list_args))
                return "";
 
        /* (name route mailbox domain) */
-       if (IMAP_ARG_LIST_COUNT(list_args) != 4)
+       if (!imap_arg_get_list_full(arg, &list_args, &list_count) ||
+           list_count != 4)
                return NULL;
-
-       list_args = IMAP_ARG_LIST_ARGS(list_args);
-       return t_strdup(imap_arg_string(&list_args[2]));
+       if (!imap_arg_get_nstring(&list_args[2], &str))
+               return NULL;
+       return t_strdup(str);
 }
 
 static bool
@@ -351,8 +344,10 @@ imap_envelope_parse_arg(const struct imap_arg *arg,
        case IMAP_ENVELOPE_RESULT_TYPE_STRING:
                if (field >= IMAP_ENVELOPE_FROM && field <= IMAP_ENVELOPE_BCC)
                        value = imap_envelope_parse_address(arg);
-               else
-                       value = t_strdup(imap_arg_string(arg));
+               else {
+                       if (imap_arg_get_nstring(arg, &value))
+                               value = t_strdup(value);
+               }
                break;
        case IMAP_ENVELOPE_RESULT_TYPE_FIRST_MAILBOX:
                i_assert(field >= IMAP_ENVELOPE_FROM &&
index 6395e5100b97ead389eeec2751ee0498d4e4c2d3..4268280b642d8360e11cb6dc904325b9631a83e8 100644 (file)
@@ -55,34 +55,32 @@ imap_id_reply_generate_from_imap_args(const struct imap_arg *args)
        string_t *str;
        const char *key, *value;
 
-       if (args->type == IMAP_ARG_EOL)
+       if (IMAP_ARG_IS_EOL(args))
                return "NIL";
 
        str = t_str_new(256);
        str_append_c(str, '(');
-       for (; args->type != IMAP_ARG_EOL; args++) {
-               if (!IMAP_ARG_TYPE_IS_STRING(args->type)) {
+       for (; !IMAP_ARG_IS_EOL(args); args++) {
+               if (!imap_arg_get_astring(args, &key)) {
                        /* broken input */
-                       if (args[1].type == IMAP_ARG_EOL)
+                       if (IMAP_ARG_IS_EOL(&args[1]))
                                break;
                        args++;
                } else {
                        /* key */
                        if (str_len(str) > 1)
                                str_append_c(str, ' ');
-                       key = IMAP_ARG_STR_NONULL(args);
                        imap_dquote_append(str, key);
                        str_append_c(str, ' ');
                        /* value */
-                       if (args[1].type == IMAP_ARG_EOL) {
+                       if (IMAP_ARG_IS_EOL(&args[1])) {
                                str_append(str, "NIL");
                                break;
                        }
                        args++;
-                       if (!IMAP_ARG_TYPE_IS_STRING(args->type))
+                       if (!imap_arg_get_astring(args, &value))
                                value = NULL;
                        else {
-                               value = IMAP_ARG_STR_NONULL(args);
                                if (strcmp(value, "*") == 0)
                                        value = imap_id_get_default(key);
                        }
@@ -132,22 +130,21 @@ const char *imap_id_args_get_log_reply(const struct imap_arg *args,
        string_t *reply;
        bool log_all;
 
-       if (settings == NULL || *settings == '\0' ||
-           args->type != IMAP_ARG_LIST)
+       if (settings == NULL || *settings == '\0')
+               return NULL;
+       if (!imap_arg_get_list(args, &args))
                return NULL;
-
-       args = IMAP_ARG_LIST_ARGS(args);
 
        log_all = strcmp(settings, "*") == 0;
        reply = t_str_new(256);
        keys = t_strsplit_spaces(settings, " ");
-       while (args->type != IMAP_ARG_EOL && args[1].type != IMAP_ARG_EOL) {
-               if (args->type != IMAP_ARG_STRING) {
+       while (!IMAP_ARG_IS_EOL(&args[0]) &&
+              !IMAP_ARG_IS_EOL(&args[1])) {
+               if (!imap_arg_get_string(args, &key)) {
                        /* broken input */
                        args += 2;
                        continue;
                }
-               key = IMAP_ARG_STR_NONULL(args);
                args++;
                if (strlen(key) > 30) {
                        /* broken: ID spec requires fields to be max. 30
@@ -157,12 +154,10 @@ const char *imap_id_args_get_log_reply(const struct imap_arg *args,
                }
 
                if (log_all || str_array_icase_find(keys, key)) {
-                       if (IMAP_ARG_TYPE_IS_STRING(args->type))
-                               value = IMAP_ARG_STR_NONULL(args);
-                       else if (args->type == IMAP_ARG_NIL)
-                               value = "NIL";
-                       else
+                       if (!imap_arg_get_nstring(args, &value))
                                value = "";
+                       else if (value == NULL)
+                               value = "NIL";
                        if (str_len(reply) > 0)
                                str_append(reply, ", ");
                        str_append(reply, str_sanitize(key, 30));
index a0e03b49addac7fcb59b4fb72384586cf0ad5e65..1f76d38cd3b240a93f91dcdf8f58536680877762 100644 (file)
@@ -652,8 +652,7 @@ bool imap_parser_get_literal_size(struct imap_parser *parser, uoff_t *size_r)
        if (last_arg == NULL)
                return FALSE;
 
-       *size_r = IMAP_ARG_LITERAL_SIZE(last_arg);
-       return TRUE;
+       return imap_arg_get_literal_size(last_arg, size_r);
 }
 
 void imap_parser_read_last_literal(struct imap_parser *parser)
@@ -717,19 +716,3 @@ const char *imap_parser_read_word(struct imap_parser *parser)
                return NULL;
        }
 }
-
-const char *imap_arg_string(const struct imap_arg *arg)
-{
-       switch (arg->type) {
-       case IMAP_ARG_NIL:
-               return "";
-
-       case IMAP_ARG_ATOM:
-       case IMAP_ARG_STRING:
-       case IMAP_ARG_LITERAL:
-               return arg->_data.str;
-
-       default:
-               return NULL;
-       }
-}
index 7fb28a329d78f8486996576466ae6e247aa6156f..76f1dd58ee8317b1ee7bfc43d43410bda0a31a0f 100644 (file)
@@ -1,21 +1,7 @@
 #ifndef IMAP_PARSER_H
 #define IMAP_PARSER_H
 
-#include "array.h"
-
-/* We use this macro to read atoms from input. It should probably contain
-   everything some day, but for now we can't handle some input otherwise:
-
-   ']' is required for parsing section (FETCH BODY[])
-   '%', '*' and ']' are valid list-chars for LIST patterns
-   '\' is used in flags */
-#define IS_ATOM_SPECIAL_INPUT(c) \
-       ((c) == '(' || (c) == ')' || (c) == '{' || \
-        (c) == '"' || (c) <= 32 || (c) == 0x7f)
-
-#define IS_ATOM_SPECIAL(c) \
-       (IS_ATOM_SPECIAL_INPUT(c) || \
-        (c) == ']' || (c) == '%' || (c) == '*' || (c) == '\\')
+#include "imap-arg.h"
 
 enum imap_parser_flags {
        /* Set this flag if you wish to read only size of literal argument
@@ -33,61 +19,8 @@ enum imap_parser_flags {
        IMAP_PARSE_FLAG_MULTILINE_STR   = 0x10
 };
 
-enum imap_arg_type {
-       IMAP_ARG_NIL = 0,
-       IMAP_ARG_ATOM,
-       IMAP_ARG_STRING,
-       IMAP_ARG_LIST,
-
-       /* literals are returned as IMAP_ARG_STRING by default */
-       IMAP_ARG_LITERAL,
-       IMAP_ARG_LITERAL_SIZE,
-       IMAP_ARG_LITERAL_SIZE_NONSYNC,
-
-       IMAP_ARG_EOL /* end of argument list */
-};
-
 struct imap_parser;
 
-ARRAY_DEFINE_TYPE(imap_arg_list, struct imap_arg);
-struct imap_arg {
-       enum imap_arg_type type;
-        struct imap_arg *parent; /* always of type IMAP_ARG_LIST */
-
-       union {
-               const char *str;
-               uoff_t literal_size;
-               ARRAY_TYPE(imap_arg_list) list;
-       } _data;
-};
-
-#define IMAP_ARG_TYPE_IS_STRING(type) \
-       ((type) == IMAP_ARG_ATOM || (type) == IMAP_ARG_STRING || \
-        (type) == IMAP_ARG_LITERAL)
-
-#define IMAP_ARG_STR(arg) \
-       ((arg)->type == IMAP_ARG_NIL ? NULL : \
-        IMAP_ARG_TYPE_IS_STRING((arg)->type) ? \
-        (arg)->_data.str : imap_arg_str_error())
-
-#define IMAP_ARG_STR_NONULL(arg) \
-       ((arg)->type == IMAP_ARG_ATOM || (arg)->type == IMAP_ARG_STRING || \
-        (arg)->type == IMAP_ARG_LITERAL ? \
-        (arg)->_data.str : imap_arg_str_error())
-
-#define IMAP_ARG_LITERAL_SIZE(arg) \
-       (((arg)->type == IMAP_ARG_LITERAL_SIZE || \
-        (arg)->type == IMAP_ARG_LITERAL_SIZE_NONSYNC) ? \
-        (arg)->_data.literal_size : imap_arg_literal_size_error())
-
-#define IMAP_ARG_LIST(arg) \
-       ((arg)->type == IMAP_ARG_LIST ? \
-        &(arg)->_data.list : imap_arg_list_error())
-#define IMAP_ARG_LIST_ARGS(arg) \
-       array_idx(IMAP_ARG_LIST(arg), 0)
-#define IMAP_ARG_LIST_COUNT(arg) \
-       (array_count(IMAP_ARG_LIST(arg)) - 1)
-
 /* Create new IMAP argument parser. output is used for sending command
    continuation requests for literals.
 
@@ -144,35 +77,4 @@ int imap_parser_finish_line(struct imap_parser *parser, unsigned int count,
    Returns NULL if more data is needed. */
 const char *imap_parser_read_word(struct imap_parser *parser);
 
-/* Returns the imap argument as string. NIL returns "" and list returns NULL. */
-const char *imap_arg_string(const struct imap_arg *arg);
-
-/* Error functions */
-static inline char * ATTR_NORETURN
-imap_arg_str_error(void)
-{
-       i_unreached();
-#ifndef ATTRS_DEFINED
-       return NULL;
-#endif
-}
-
-static inline uoff_t ATTR_NORETURN
-imap_arg_literal_size_error(void)
-{
-       i_unreached();
-#ifndef ATTRS_DEFINED
-       return 0;
-#endif
-}
-
-static inline ARRAY_TYPE(imap_arg_list) * ATTR_NORETURN
-imap_arg_list_error(void)
-{
-       i_unreached();
-#ifndef ATTRS_DEFINED
-       return NULL;
-#endif
-}
-
 #endif
index 17a45a6975b1b10f8450fb2433c101c267e09b0c..17119bca7ae153e0008f99b71b6f4c0e35c87718 100644 (file)
@@ -75,10 +75,9 @@ void imap_write_seq_range(string_t *dest, const ARRAY_TYPE(seq_range) *array)
 
 void imap_write_args(string_t *dest, const struct imap_arg *args)
 {
-       const ARRAY_TYPE(imap_arg_list) *list;
        bool first = TRUE;
 
-       for (; args->type != IMAP_ARG_EOL; args++) {
+       for (; !IMAP_ARG_IS_EOL(args); args++) {
                if (first)
                        first = FALSE;
                else
@@ -89,15 +88,15 @@ void imap_write_args(string_t *dest, const struct imap_arg *args)
                        str_append(dest, "NIL");
                        break;
                case IMAP_ARG_ATOM:
-                       str_append(dest, IMAP_ARG_STR(args));
+                       str_append(dest, imap_arg_as_astring(args));
                        break;
                case IMAP_ARG_STRING:
                        str_append_c(dest, '"');
-                       str_append(dest, str_escape(IMAP_ARG_STR(args)));
+                       str_append(dest, str_escape(imap_arg_as_astring(args)));
                        str_append_c(dest, '"');
                        break;
                case IMAP_ARG_LITERAL: {
-                       const char *strarg = IMAP_ARG_STR(args);
+                       const char *strarg = imap_arg_as_astring(args);
                        str_printfa(dest, "{%"PRIuSIZE_T"}\r\n",
                                    strlen(strarg));
                        str_append(dest, strarg);
@@ -105,14 +104,13 @@ void imap_write_args(string_t *dest, const struct imap_arg *args)
                }
                case IMAP_ARG_LIST:
                        str_append_c(dest, '(');
-                       list = IMAP_ARG_LIST(args);
-                       imap_write_args(dest, array_idx(list, 0));
+                       imap_write_args(dest, imap_arg_as_list(args));
                        str_append_c(dest, ')');
                        break;
                case IMAP_ARG_LITERAL_SIZE:
                case IMAP_ARG_LITERAL_SIZE_NONSYNC:
                        str_printfa(dest, "{%"PRIuUOFF_T"}\r\n",
-                                   IMAP_ARG_LITERAL_SIZE(args));
+                                   imap_arg_as_literal_size(args));
                        str_append(dest, "<too large>");
                        break;
                case IMAP_ARG_EOL:
index 7ad1d28225421477aa94b885f8d54d9ea4226013..777bd67f9563979635739e30e73e8dbbe3af1a31 100644 (file)
@@ -3,7 +3,7 @@
 #include "lib.h"
 #include "ioloop.h"
 #include "imap-date.h"
-#include "imap-parser.h"
+#include "imap-arg.h"
 #include "imap-seqset.h"
 #include "mail-search-build.h"
 #include "mail-storage.h"
@@ -30,17 +30,15 @@ static bool
 arg_get_next(struct search_build_data *data, const struct imap_arg **args,
             const char **value_r)
 {
-       if ((*args)->type == IMAP_ARG_EOL) {
+       if (IMAP_ARG_IS_EOL(*args)) {
                data->error = "Missing parameter for argument";
                return FALSE;
        }
-       if ((*args)->type != IMAP_ARG_ATOM &&
-           (*args)->type != IMAP_ARG_STRING) {
+       if (!imap_arg_get_astring(*args, value_r)) {
                data->error = "Invalid parameter for argument";
                return FALSE;
        }
 
-       *value_r = IMAP_ARG_STR(*args);
        *args += 1;
        return TRUE;
 }
@@ -266,33 +264,30 @@ static bool search_arg_build(struct search_build_data *data,
                             struct mail_search_arg **next_sarg)
 {
        struct mail_search_arg **subargs, *sarg;
-       const struct imap_arg *arg;
-       const char *str;
+       const struct imap_arg *arg, *listargs;
+       const char *key, *value;
 
-       if ((*args)->type == IMAP_ARG_EOL) {
+       if (IMAP_ARG_IS_EOL(*args)) {
                data->error = "Missing argument";
                return FALSE;
        }
 
        arg = *args;
-
        if (arg->type == IMAP_ARG_NIL) {
                /* NIL not allowed */
                data->error = "NIL not allowed";
                return FALSE;
        }
 
-       if (arg->type == IMAP_ARG_LIST) {
-               const struct imap_arg *listargs = IMAP_ARG_LIST_ARGS(arg);
-
-               if (listargs->type == IMAP_ARG_EOL) {
+       if (imap_arg_get_list(arg, &listargs)) {
+               if (IMAP_ARG_IS_EOL(listargs)) {
                        data->error = "Empty list not allowed";
                        return FALSE;
                }
 
                *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
                subargs = &(*next_sarg)->value.subargs;
-               while (listargs->type != IMAP_ARG_EOL) {
+               while (IMAP_ARG_IS_EOL(listargs)) {
                        if (!search_arg_build(data, &listargs, subargs))
                                return FALSE;
                        subargs = &(*subargs)->next;
@@ -302,91 +297,84 @@ static bool search_arg_build(struct search_build_data *data,
                return TRUE;
        }
 
-       i_assert(arg->type == IMAP_ARG_ATOM ||
-                arg->type == IMAP_ARG_STRING);
-
        /* string argument - get the name and jump to next */
-       str = IMAP_ARG_STR(arg);
+       key = imap_arg_as_astring(arg);
        *args += 1;
-       str = t_str_ucase(str);
+       key = t_str_ucase(key);
 
-       switch (*str) {
+       switch (*key) {
        case 'A':
-               if (strcmp(str, "ANSWERED") == 0)
+               if (strcmp(key, "ANSWERED") == 0)
                        return ARG_NEW_FLAGS(MAIL_ANSWERED);
-               else if (strcmp(str, "ALL") == 0)
+               else if (strcmp(key, "ALL") == 0)
                        return ARG_NEW_SINGLE(SEARCH_ALL);
                break;
        case 'B':
-               if (strcmp(str, "BODY") == 0) {
+               if (strcmp(key, "BODY") == 0) {
                        /* <string> */
-                       if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
-                           *IMAP_ARG_STR(*args) == '\0') {
+                       if (imap_arg_get_astring(*args, &value) &&
+                           *value == '\0') {
+                               /* optimization: BODY "" matches everything */
                                *args += 1;
                                return ARG_NEW_SINGLE(SEARCH_ALL);
                        }
                        return ARG_NEW_STR(SEARCH_BODY);
-               } else if (strcmp(str, "BEFORE") == 0) {
+               } else if (strcmp(key, "BEFORE") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_BEFORE);
-               } else if (strcmp(str, "BCC") == 0) {
+               } else if (strcmp(key, "BCC") == 0) {
                        /* <string> */
-                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
+                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, key);
                }
                break;
        case 'C':
-               if (strcmp(str, "CC") == 0) {
+               if (strcmp(key, "CC") == 0) {
                        /* <string> */
-                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
+                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, key);
                }
                break;
        case 'D':
-               if (strcmp(str, "DELETED") == 0)
+               if (strcmp(key, "DELETED") == 0)
                        return ARG_NEW_FLAGS(MAIL_DELETED);
-               else if (strcmp(str, "DRAFT") == 0)
+               else if (strcmp(key, "DRAFT") == 0)
                        return ARG_NEW_FLAGS(MAIL_DRAFT);
                break;
        case 'F':
-               if (strcmp(str, "FLAGGED") == 0)
+               if (strcmp(key, "FLAGGED") == 0)
                        return ARG_NEW_FLAGS(MAIL_FLAGGED);
-               else if (strcmp(str, "FROM") == 0) {
+               else if (strcmp(key, "FROM") == 0) {
                        /* <string> */
-                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
+                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, key);
                }
                break;
        case 'H':
-               if (strcmp(str, "HEADER") == 0) {
+               if (strcmp(key, "HEADER") == 0) {
                        /* <field-name> <string> */
-                       const char *key;
-
-                       if ((*args)->type == IMAP_ARG_EOL) {
+                       if (IMAP_ARG_IS_EOL(*args)) {
                                data->error = "Missing parameter for HEADER";
                                return FALSE;
                        }
-                       if ((*args)->type != IMAP_ARG_ATOM &&
-                           (*args)->type != IMAP_ARG_STRING) {
+                       if (!imap_arg_get_astring(*args, &value)) {
                                data->error = "Invalid parameter for HEADER";
                                return FALSE;
                        }
 
-                       key = t_str_ucase(IMAP_ARG_STR(*args));
                        *args += 1;
-                       return ARG_NEW_HEADER(SEARCH_HEADER, key);
+                       return ARG_NEW_HEADER(SEARCH_HEADER,
+                                             t_str_ucase(value));
                }
                break;
        case 'I':
-               if (strcmp(str, "INTHREAD") == 0) {
+               if (strcmp(key, "INTHREAD") == 0) {
                        /* <algorithm> <search key> */
                        enum mail_thread_type thread_type;
-                       const char *str;
 
-                       if ((*args)->type != IMAP_ARG_ATOM) {
+                       if (!imap_arg_get_atom(*args, &value)) {
                                data->error = "Invalid parameter for INTHREAD";
                                return FALSE;
                        }
 
-                       str = IMAP_ARG_STR_NONULL(*args);
-                       if (!mail_thread_type_parse(str, &thread_type)) {
+                       if (!mail_thread_type_parse(value, &thread_type)) {
                                data->error = "Unknown thread algorithm";
                                return FALSE;
                        }
@@ -400,29 +388,29 @@ static bool search_arg_build(struct search_build_data *data,
                }
                break;
        case 'K':
-               if (strcmp(str, "KEYWORD") == 0) {
+               if (strcmp(key, "KEYWORD") == 0) {
                        return ARG_NEW_STR(SEARCH_KEYWORDS);
                }
                break;
        case 'L':
-               if (strcmp(str, "LARGER") == 0) {
+               if (strcmp(key, "LARGER") == 0) {
                        /* <n> */
                        return ARG_NEW_SIZE(SEARCH_LARGER);
                }
                break;
        case 'M':
-               if (strcmp(str, "MODSEQ") == 0) {
+               if (strcmp(key, "MODSEQ") == 0) {
                        /* [<name> <type>] <n> */
                        return ARG_NEW_MODSEQ();
                }
                break;
        case 'N':
-               if (strcmp(str, "NOT") == 0) {
+               if (strcmp(key, "NOT") == 0) {
                        if (!search_arg_build(data, args, next_sarg))
                                return FALSE;
                        (*next_sarg)->not = !(*next_sarg)->not;
                        return TRUE;
-               } else if (strcmp(str, "NEW") == 0) {
+               } else if (strcmp(key, "NEW") == 0) {
                        /* NEW == (RECENT UNSEEN) */
                        *next_sarg = search_arg_new(data->pool, SEARCH_SUB);
 
@@ -437,7 +425,7 @@ static bool search_arg_build(struct search_build_data *data,
                }
                break;
        case 'O':
-               if (strcmp(str, "OR") == 0) {
+               if (strcmp(key, "OR") == 0) {
                        /* <search-key1> <search-key2> */
                        *next_sarg = search_arg_new(data->pool, SEARCH_OR);
 
@@ -450,12 +438,8 @@ static bool search_arg_build(struct search_build_data *data,
 
                                /* <key> OR <key> OR ... <key> - put them all
                                   under one SEARCH_OR list. */
-                               if ((*args)->type == IMAP_ARG_EOL)
-                                       break;
-
-                               if ((*args)->type != IMAP_ARG_ATOM ||
-                                   strcasecmp(IMAP_ARG_STR_NONULL(*args),
-                                              "OR") != 0)
+                               if (!imap_arg_get_atom(*args, &value) ||
+                                   strcasecmp(value, "OR") != 0)
                                        break;
 
                                *args += 1;
@@ -464,17 +448,17 @@ static bool search_arg_build(struct search_build_data *data,
                        if (!search_arg_build(data, args, subargs))
                                return FALSE;
                        return TRUE;
-               } if (strcmp(str, "ON") == 0) {
+               } if (strcmp(key, "ON") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_ON);
-               } if (strcmp(str, "OLD") == 0) {
+               } if (strcmp(key, "OLD") == 0) {
                        /* OLD == NOT RECENT */
                        if (!ARG_NEW_FLAGS(MAIL_RECENT))
                                return FALSE;
 
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } if (strcmp(str, "OLDER") == 0) {
+               } if (strcmp(key, "OLDER") == 0) {
                        /* <interval> - WITHIN extension */
                        if (!ARG_NEW_INTERVAL(SEARCH_BEFORE))
                                return FALSE;
@@ -486,48 +470,49 @@ static bool search_arg_build(struct search_build_data *data,
                }
                break;
        case 'R':
-               if (strcmp(str, "RECENT") == 0)
+               if (strcmp(key, "RECENT") == 0)
                        return ARG_NEW_FLAGS(MAIL_RECENT);
                break;
        case 'S':
-               if (strcmp(str, "SEEN") == 0)
+               if (strcmp(key, "SEEN") == 0)
                        return ARG_NEW_FLAGS(MAIL_SEEN);
-               else if (strcmp(str, "SUBJECT") == 0) {
+               else if (strcmp(key, "SUBJECT") == 0) {
                        /* <string> */
-                       return ARG_NEW_HEADER(SEARCH_HEADER_COMPRESS_LWSP, str);
-               } else if (strcmp(str, "SENTBEFORE") == 0) {
+                       return ARG_NEW_HEADER(SEARCH_HEADER_COMPRESS_LWSP, key);
+               } else if (strcmp(key, "SENTBEFORE") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_SENTBEFORE);
-               } else if (strcmp(str, "SENTON") == 0) {
+               } else if (strcmp(key, "SENTON") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_SENTON);
-               } else if (strcmp(str, "SENTSINCE") == 0) {
+               } else if (strcmp(key, "SENTSINCE") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_SENTSINCE);
-               } else if (strcmp(str, "SINCE") == 0) {
+               } else if (strcmp(key, "SINCE") == 0) {
                        /* <date> */
                        return ARG_NEW_DATE(SEARCH_SINCE);
-               } else if (strcmp(str, "SMALLER") == 0) {
+               } else if (strcmp(key, "SMALLER") == 0) {
                        /* <n> */
                        return ARG_NEW_SIZE(SEARCH_SMALLER);
                }
                break;
        case 'T':
-               if (strcmp(str, "TEXT") == 0) {
+               if (strcmp(key, "TEXT") == 0) {
                        /* <string> */
-                       if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
-                           *IMAP_ARG_STR(*args) == '\0') {
+                       if (imap_arg_get_astring(*args, &value) &&
+                           *value == '\0') {
+                               /* optimization: TEXT "" matches everything */
                                *args += 1;
                                return ARG_NEW_SINGLE(SEARCH_ALL);
                        }
                        return ARG_NEW_STR(SEARCH_TEXT);
-               } else if (strcmp(str, "TO") == 0) {
+               } else if (strcmp(key, "TO") == 0) {
                        /* <string> */
-                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, str);
+                       return ARG_NEW_HEADER(SEARCH_HEADER_ADDRESS, key);
                }
                break;
        case 'U':
-               if (strcmp(str, "UID") == 0) {
+               if (strcmp(key, "UID") == 0) {
                        /* <message set> */
                        if (!ARG_NEW_STR(SEARCH_UIDSET))
                                return FALSE;
@@ -544,32 +529,32 @@ static bool search_arg_build(struct search_build_data *data,
                                return FALSE;
                        }
                        return TRUE;
-               } else if (strcmp(str, "UNANSWERED") == 0) {
+               } else if (strcmp(key, "UNANSWERED") == 0) {
                        if (!ARG_NEW_FLAGS(MAIL_ANSWERED))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } else if (strcmp(str, "UNDELETED") == 0) {
+               } else if (strcmp(key, "UNDELETED") == 0) {
                        if (!ARG_NEW_FLAGS(MAIL_DELETED))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } else if (strcmp(str, "UNDRAFT") == 0) {
+               } else if (strcmp(key, "UNDRAFT") == 0) {
                        if (!ARG_NEW_FLAGS(MAIL_DRAFT))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } else if (strcmp(str, "UNFLAGGED") == 0) {
+               } else if (strcmp(key, "UNFLAGGED") == 0) {
                        if (!ARG_NEW_FLAGS(MAIL_FLAGGED))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } else if (strcmp(str, "UNKEYWORD") == 0) {
+               } else if (strcmp(key, "UNKEYWORD") == 0) {
                        if (!ARG_NEW_STR(SEARCH_KEYWORDS))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
                        return TRUE;
-               } else if (strcmp(str, "UNSEEN") == 0) {
+               } else if (strcmp(key, "UNSEEN") == 0) {
                        if (!ARG_NEW_FLAGS(MAIL_SEEN))
                                return FALSE;
                        (*next_sarg)->not = TRUE;
@@ -577,50 +562,54 @@ static bool search_arg_build(struct search_build_data *data,
                }
                break;
        case 'Y':
-               if (strcmp(str, "YOUNGER") == 0) {
+               if (strcmp(key, "YOUNGER") == 0) {
                        /* <interval> - WITHIN extension */
                        return ARG_NEW_INTERVAL(SEARCH_SINCE);
                }
                break;
        case 'X':
-               if (strcmp(str, "X-BODY-FAST") == 0) {
+               if (strcmp(key, "X-BODY-FAST") == 0) {
                        /* <string> */
-                       if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
-                           *IMAP_ARG_STR(*args) == '\0') {
+                       if (imap_arg_get_astring(*args, &value) &&
+                           *value == '\0') {
+                               /* optimization: X-BODY-FAST "" matches
+                                  everything */
                                *args += 1;
                                return ARG_NEW_SINGLE(SEARCH_ALL);
                        }
                        return ARG_NEW_STR(SEARCH_BODY_FAST);
-               } else if (strcmp(str, "X-TEXT-FAST") == 0) {
+               } else if (strcmp(key, "X-TEXT-FAST") == 0) {
                        /* <string> */
-                       if (IMAP_ARG_TYPE_IS_STRING((*args)->type) &&
-                           *IMAP_ARG_STR(*args) == '\0') {
+                       if (imap_arg_get_astring(*args, &value) &&
+                           *value == '\0') {
+                               /* optimization: X-TEXT-FAST "" matches
+                                  everything */
                                *args += 1;
                                return ARG_NEW_SINGLE(SEARCH_ALL);
                        }
                        return ARG_NEW_STR(SEARCH_TEXT_FAST);
-               } else if (strcmp(str, "X-GUID") == 0) {
+               } else if (strcmp(key, "X-GUID") == 0) {
                        /* <string> */
                        return ARG_NEW_STR(SEARCH_GUID);
-               } else if (strcmp(str, "X-MAILBOX") == 0) {
+               } else if (strcmp(key, "X-MAILBOX") == 0) {
                        /* <string> */
                        return ARG_NEW_STR(SEARCH_MAILBOX);
                }
                break;
        default:
-               if (*str == '*' || (*str >= '0' && *str <= '9')) {
+               if (*key == '*' || (*key >= '0' && *key <= '9')) {
                        /* <message-set> */
                        if (!ARG_NEW_SINGLE(SEARCH_SEQSET))
                                return FALSE;
 
                        p_array_init(&(*next_sarg)->value.seqset,
                                     data->pool, 16);
-                       if (imap_seq_set_parse(str, &(*next_sarg)->value.seqset) < 0) {
+                       if (imap_seq_set_parse(key, &(*next_sarg)->value.seqset) < 0) {
                                data->error = "Invalid messageset";
                                return FALSE;
                        }
                        return TRUE;
-               } else if (strcmp(str, "$") == 0) {
+               } else if (strcmp(key, "$") == 0) {
                        /* SEARCHRES: delay initialization */
                        if (!ARG_NEW_SINGLE(SEARCH_UIDSET))
                                return FALSE;
@@ -633,7 +622,7 @@ static bool search_arg_build(struct search_build_data *data,
                break;
        }
 
-       data->error = t_strconcat("Unknown argument ", str, NULL);
+       data->error = t_strconcat("Unknown argument ", key, NULL);
        return FALSE;
 }
 
@@ -656,7 +645,7 @@ int mail_search_build_from_imap_args(const struct imap_arg *imap_args,
        data.error = NULL;
 
        sargs = &args->args;
-       while (imap_args->type != IMAP_ARG_EOL) {
+       while (!IMAP_ARG_IS_EOL(imap_args)) {
                if (!search_arg_build(&data, &imap_args, sargs)) {
                        pool_unref(&args->pool);
                        *error_r = data.error;
index 6f85c6dd34b4887f31089f2b904c9220071bdb65..517e3850a73b8ce5a449d08967efd21e52e90b7a 100644 (file)
@@ -158,16 +158,16 @@ static bool cmd_getquota(struct client_command_context *cmd)
 static bool cmd_setquota(struct client_command_context *cmd)
 {
        struct quota_root *root;
-        const struct imap_arg *args, *arg;
-       const char *root_name, *name, *error;
+        const struct imap_arg *args, *list_args;
+       const char *root_name, *name, *value_str, *error;
        uint64_t value;
 
        /* <quota root> <resource limits> */
        if (!client_read_args(cmd, 2, 0, &args))
                return FALSE;
 
-       root_name = imap_arg_string(&args[0]);
-       if (args[1].type != IMAP_ARG_LIST || root_name == NULL) {
+       if (!imap_arg_get_astring(&args[0], &root_name) ||
+           !imap_arg_get_list(&args[1], &list_args)) {
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
@@ -178,16 +178,15 @@ static bool cmd_setquota(struct client_command_context *cmd)
                return TRUE;
        }
 
-        arg = IMAP_ARG_LIST_ARGS(&args[1]);
-       for (; arg->type != IMAP_ARG_EOL; arg += 2) {
-               name = imap_arg_string(arg);
-               if (name == NULL || arg[1].type != IMAP_ARG_ATOM ||
-                   !is_numeric(IMAP_ARG_STR(&arg[1]), '\0')) {
+       for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
+               if (!imap_arg_get_atom(&list_args[0], &name) ||
+                   !imap_arg_get_atom(&list_args[1], &value_str) ||
+                   !is_numeric(value_str, '\0')) {
                        client_send_command_error(cmd, "Invalid arguments.");
                        return TRUE;
                }
 
-                value = strtoull(IMAP_ARG_STR_NONULL(&arg[1]), NULL, 10);
+                value = strtoull(value_str, NULL, 10);
                if (quota_set_resource(root, name, value, &error) < 0) {
                        client_send_command_error(cmd, error);
                        return TRUE;
index 00a8ec04748d105e3300ecbd4b621dc2fc5b0305..52cf04b3211286100054c0ad2749d8a1f8d605cd 100644 (file)
@@ -76,8 +76,8 @@ static bool cmd_compress(struct client_command_context *cmd)
        if (!client_read_args(cmd, 0, 0, &args))
                return FALSE;
 
-       mechanism = imap_arg_string(&args[0]);
-       if (mechanism == NULL || args[1].type != IMAP_ARG_EOL) {
+       if (!imap_arg_get_atom(args, &mechanism) ||
+           !IMAP_ARG_IS_EOL(&args[1])) {
                client_send_command_error(cmd, "Invalid arguments.");
                return TRUE;
        }
@@ -93,7 +93,6 @@ static bool cmd_compress(struct client_command_context *cmd)
                return TRUE;
        }
 
-
        handler = zlib_find_zlib_handler(t_str_lcase(mechanism));
        if (handler == NULL || handler->create_istream == NULL) {
                client_send_tagline(cmd, "NO Unknown compression mechanism.");