Mercurial > dovecot > core-2.2
changeset 11063:dbc864c0cff7 HEAD
lib-imap: Changed imap_arg accessing APIs.
The new one is easier for both coders and static analyzers.
line wrap: on
line diff
--- a/src/imap-login/client-authenticate.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap-login/client-authenticate.c Mon Apr 05 07:54:55 2010 +0300 @@ -125,22 +125,18 @@ 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]); - } + if (imap_arg_get_atom(&args[1], &init_resp)) + args++; + else + init_resp = NULL; + if (!IMAP_ARG_IS_EOL(&args[1])) + return -1; - mech_name = IMAP_ARG_STR(&args[0]); - if (*mech_name == '\0') - return -1; return imap_client_auth_begin(imap_client, mech_name, init_resp); } @@ -151,15 +147,10 @@ string_t *plain_login, *base64; /* two arguments: username and password */ - if (args[0].type != IMAP_ARG_ATOM && args[0].type != IMAP_ARG_STRING) - return -1; - if (args[1].type != IMAP_ARG_ATOM && args[1].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[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;
--- a/src/imap-login/client.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap-login/client.c Mon Apr 05 07:54:55 2010 +0300 @@ -97,14 +97,11 @@ { 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)
--- a/src/imap/cmd-append.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-append.c Mon Apr 05 07:54:55 2010 +0300 @@ -103,29 +103,25 @@ 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 @@ 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;
--- a/src/imap/cmd-cancelupdate.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-cancelupdate.c Mon Apr 05 07:54:55 2010 +0300 @@ -21,23 +21,24 @@ 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;
--- a/src/imap/cmd-enable.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-enable.c Mon Apr 05 07:54:55 2010 +0300 @@ -14,12 +14,12 @@ 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");
--- a/src/imap/cmd-expunge.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-expunge.c Mon Apr 05 07:54:55 2010 +0300 @@ -58,8 +58,7 @@ 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; }
--- a/src/imap/cmd-fetch.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-fetch.c Mon Apr 05 07:54:55 2010 +0300 @@ -30,8 +30,8 @@ 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 @@ *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 @@ 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 @@ { 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 @@ { 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 @@ 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 @@ 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; }
--- a/src/imap/cmd-list.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-list.c Mon Apr 05 07:54:55 2010 +0300 @@ -93,23 +93,21 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } - 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 @@ 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; }
--- a/src/imap/cmd-search.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-search.c Mon Apr 05 07:54:55 2010 +0300 @@ -26,19 +26,14 @@ 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"; }
--- a/src/imap/cmd-select.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-select.c Mon Apr 05 07:54:55 2010 +0300 @@ -65,10 +65,48 @@ } 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,68 +114,44 @@ 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) { + 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); - if (imap_seq_set_parse(IMAP_ARG_STR_NONULL(&args[2]), - &ctx->qresync_known_uids) < 0) { + seq_range_array_add_range(&ctx->qresync_known_uids, + 1, (uint32_t)-1); + } 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-uids"); return FALSE; } - } else { - 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; + args++; + if (imap_arg_get_list(args, &list_args)) { + if (!select_parse_qresync_known_set(ctx, list_args)) + return FALSE; + args++; } - 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) { - client_send_command_error(ctx->cmd, - "Invalid QRESYNC known-uid-set"); - return FALSE; - } - 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, + "Invalid QRESYNC parameters"); + return FALSE; } return TRUE; } @@ -148,13 +162,13 @@ { 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 @@ 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 @@ 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 @@ 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; }
--- a/src/imap/cmd-sort.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-sort.c Mon Apr 05 07:54:55 2010 +0300 @@ -32,20 +32,18 @@ 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 @@ } 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 @@ 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 @@ } /* 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);
--- a/src/imap/cmd-status.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-status.c Mon Apr 05 07:54:55 2010 +0300 @@ -10,7 +10,7 @@ { 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 @@ 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);
--- a/src/imap/cmd-store.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-store.c Mon Apr 05 07:54:55 2010 +0300 @@ -46,20 +46,18 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/imap/cmd-thread.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/cmd-thread.c Mon Apr 05 07:54:55 2010 +0300 @@ -117,26 +117,17 @@ 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 @@ 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; }
--- a/src/imap/imap-client.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-client.c Mon Apr 05 07:54:55 2010 +0300 @@ -383,13 +383,12 @@ 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; }
--- a/src/imap/imap-commands-util.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-commands-util.c Mon Apr 05 07:54:55 2010 +0300 @@ -244,14 +244,13 @@ *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);
--- a/src/imap/imap-fetch-body.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-fetch-body.c Mon Apr 05 07:54:55 2010 +0300 @@ -758,7 +758,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 */
--- a/src/imap/imap-search-args.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-search-args.c Mon Apr 05 07:54:55 2010 +0300 @@ -42,7 +42,7 @@ 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; }
--- a/src/imap/imap-search.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-search.c Mon Apr 05 07:54:55 2010 +0300 @@ -47,13 +47,13 @@ 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 @@ 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 @@ 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 @@ i_array_init(&cmd->client->search_saved_uidset, 128); } - *_args = args; + *_args = args + 2; return 1; }
--- a/src/imap/imap-status.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/imap/imap-status.c Mon Apr 05 07:54:55 2010 +0300 @@ -15,16 +15,15 @@ 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)
--- a/src/lib-imap/Makefile.am Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/Makefile.am Mon Apr 05 07:54:55 2010 +0300 @@ -7,6 +7,7 @@ -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 @@ imap-util.c headers = \ + imap-arg.h \ imap-base-subject.h \ imap-bodystructure.h \ imap-date.h \ @@ -57,16 +59,16 @@ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-imap/imap-arg.c Mon Apr 05 07:54:55 2010 +0300 @@ -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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-imap/imap-arg.h Mon Apr 05 07:54:55 2010 +0300 @@ -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
--- a/src/lib-imap/imap-bodystructure.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-bodystructure.c Mon Apr 05 07:54:55 2010 +0300 @@ -534,47 +534,54 @@ 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 @@ { 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 @@ } /* "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 @@ 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 @@ 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 @@ 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;
--- a/src/lib-imap/imap-envelope.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-envelope.c Mon Apr 05 07:54:55 2010 +0300 @@ -221,22 +221,15 @@ 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 @@ 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_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 @@ 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 &&
--- a/src/lib-imap/imap-id.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-id.c Mon Apr 05 07:54:55 2010 +0300 @@ -55,34 +55,32 @@ 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 @@ string_t *reply; bool log_all; - if (settings == NULL || *settings == '\0' || - args->type != IMAP_ARG_LIST) + if (settings == NULL || *settings == '\0') return NULL; - - args = IMAP_ARG_LIST_ARGS(args); + if (!imap_arg_get_list(args, &args)) + return NULL; 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 @@ } 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) + if (!imap_arg_get_nstring(args, &value)) + value = ""; + else if (value == NULL) value = "NIL"; - else - value = ""; if (str_len(reply) > 0) str_append(reply, ", "); str_append(reply, str_sanitize(key, 30));
--- a/src/lib-imap/imap-parser.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-parser.c Mon Apr 05 07:54:55 2010 +0300 @@ -652,8 +652,7 @@ 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 @@ 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; - } -}
--- a/src/lib-imap/imap-parser.h Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-parser.h Mon Apr 05 07:54:55 2010 +0300 @@ -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 @@ 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 @@ 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
--- a/src/lib-imap/imap-util.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-imap/imap-util.c Mon Apr 05 07:54:55 2010 +0300 @@ -75,10 +75,9 @@ 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 @@ 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 @@ } 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:
--- a/src/lib-storage/mail-search-build.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/lib-storage/mail-search-build.c Mon Apr 05 07:54:55 2010 +0300 @@ -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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ /* <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 @@ 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 @@ } 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 @@ 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 @@ } 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 @@ break; } - data->error = t_strconcat("Unknown argument ", str, NULL); + data->error = t_strconcat("Unknown argument ", key, NULL); return FALSE; } @@ -656,7 +645,7 @@ 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;
--- a/src/plugins/imap-quota/imap-quota-plugin.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/plugins/imap-quota/imap-quota-plugin.c Mon Apr 05 07:54:55 2010 +0300 @@ -158,16 +158,16 @@ 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 @@ 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;
--- a/src/plugins/imap-zlib/imap-zlib-plugin.c Mon Apr 05 05:19:24 2010 +0300 +++ b/src/plugins/imap-zlib/imap-zlib-plugin.c Mon Apr 05 07:54:55 2010 +0300 @@ -76,8 +76,8 @@ 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 @@ 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.");