The new one is easier for both coders and static analyzers.
--HG--
branch : HEAD
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);
}
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;
{
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)
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;
}
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;
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;
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");
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;
}
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 */
*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;
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);
}
{
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 &&
{
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;
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;
}
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;
}
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 */
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++;
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;
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;
}
}
}
- 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;
}
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;
}
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";
}
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 &
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;
}
{
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)
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;
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;
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;
}
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;
}
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;
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;
}
/* 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);
{
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;
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);
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 {
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 {
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;
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;
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)
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;
}
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;
}
*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);
unsigned int args_count)
{
string_t *str;
- const char **arr;
+ const char **arr, *value;
size_t i;
str = str_new(ctx->cmd->pool, 128);
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");
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]);
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);
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 */
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;
}
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;
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.");
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. */
i_array_init(&cmd->client->search_saved_uidset, 128);
}
- *_args = args;
+ *_args = args + 2;
return 1;
}
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)
-I$(top_srcdir)/src/lib-mail
libimap_la_SOURCES = \
+ imap-arg.c \
imap-base-subject.c \
imap-bodystructure.c \
imap-date.c \
imap-util.c
headers = \
+ imap-arg.h \
imap-base-subject.h \
imap-bodystructure.h \
imap-date.h \
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
+/* 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
+#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
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, ')');
{
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, ')');
}
/* "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]))
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, ' ');
return FALSE;
subargs += 2;
- if (subargs->type == IMAP_ARG_EOL)
+ if (IMAP_ARG_IS_EOL(subargs))
break;
str_append_c(str, ' ');
}
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;
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;
}
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;
}
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
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 &&
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);
}
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
}
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));
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)
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;
- }
-}
#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
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.
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
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
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);
}
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:
#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"
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;
}
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;
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;
}
}
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);
}
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);
/* <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;
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;
}
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;
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;
}
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;
break;
}
- data->error = t_strconcat("Unknown argument ", str, NULL);
+ data->error = t_strconcat("Unknown argument ", key, NULL);
return FALSE;
}
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;
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;
}
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;
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;
}
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.");