[dovecot-cvs] dovecot/src/imap cmd-fetch.c, 1.23,
1.24 imap-fetch-body.c, 1.12, 1.13 imap-fetch.c, 1.26,
1.27 imap-fetch.h, 1.9, 1.10
cras at dovecot.org
cras at dovecot.org
Tue Sep 28 13:55:39 EEST 2004
Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv1148/imap
Modified Files:
cmd-fetch.c imap-fetch-body.c imap-fetch.c imap-fetch.h
Log Message:
BODY.PEEK[HEADER.FIELDS (...)] list is allowed to contain strings and
literals. We didn't handle them correctly before.
Index: cmd-fetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-fetch.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- cmd-fetch.c 19 Sep 2004 23:23:08 -0000 1.23
+++ cmd-fetch.c 28 Sep 2004 10:55:36 -0000 1.24
@@ -6,45 +6,52 @@
#include "imap-search.h"
#include "mail-search.h"
+const char *all_macro[] = {
+ "FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", NULL
+};
+const char *fast_macro[] = {
+ "FLAGS", "INTERNALDATE", "RFC822.SIZE", NULL
+};
+const char *full_macro[] = {
+ "FLAGS", "INTERNALDATE", "RFC822.SIZE", "ENVELOPE", "BODY", NULL
+};
+
static int
fetch_parse_args(struct client *client, struct imap_fetch_context *ctx,
struct imap_arg *arg)
{
- const char *str;
+ const char *str, *const *macro;
if (arg->type == IMAP_ARG_ATOM) {
str = str_ucase(IMAP_ARG_STR(arg));
+ arg++;
/* handle macros first */
- if (strcmp(str, "ALL") == 0) {
- if (!imap_fetch_init_handler(ctx, "FLAGS") ||
- !imap_fetch_init_handler(ctx, "INTERNALDATE") ||
- !imap_fetch_init_handler(ctx, "RFC822.SIZE") ||
- !imap_fetch_init_handler(ctx, "ENVELOPE"))
- return FALSE;
- } else if (strcmp(str, "FAST") == 0) {
- if (!imap_fetch_init_handler(ctx, "FLAGS") ||
- !imap_fetch_init_handler(ctx, "INTERNALDATE") ||
- !imap_fetch_init_handler(ctx, "RFC822.SIZE"))
- return FALSE;
- } else if (strcmp(str, "FULL") == 0) {
- if (!imap_fetch_init_handler(ctx, "FLAGS") ||
- !imap_fetch_init_handler(ctx, "INTERNALDATE") ||
- !imap_fetch_init_handler(ctx, "RFC822.SIZE") ||
- !imap_fetch_init_handler(ctx, "ENVELOPE") ||
- !imap_fetch_init_handler(ctx, "BODY"))
- return FALSE;
- } else {
- if (!imap_fetch_init_handler(ctx, str))
+ if (strcmp(str, "ALL") == 0)
+ macro = all_macro;
+ else if (strcmp(str, "FAST") == 0)
+ macro = fast_macro;
+ else if (strcmp(str, "FULL") == 0)
+ macro = full_macro;
+ else {
+ macro = NULL;
+ if (!imap_fetch_init_handler(ctx, str, &arg))
return FALSE;
}
+ if (macro != NULL) {
+ while (*macro != NULL) {
+ if (!imap_fetch_init_handler(ctx, *macro, &arg))
+ return FALSE;
+ macro++;
+ }
+ }
} else {
arg = IMAP_ARG_LIST(arg)->args;
while (arg->type == IMAP_ARG_ATOM) {
str = str_ucase(IMAP_ARG_STR(arg));
- if (!imap_fetch_init_handler(ctx, str))
- return FALSE;
arg++;
+ if (!imap_fetch_init_handler(ctx, str, &arg))
+ return FALSE;
}
if (arg->type != IMAP_ARG_EOL) {
client_send_command_error(client,
@@ -54,7 +61,7 @@
}
if (client->cmd_uid) {
- if (!imap_fetch_init_handler(ctx, "UID"))
+ if (!imap_fetch_init_handler(ctx, "UID", &arg))
return FALSE;
}
@@ -122,7 +129,7 @@
const char *messageset;
int ret;
- if (!client_read_args(client, 2, 0, &args))
+ if (!client_read_args(client, 0, 0, &args))
return FALSE;
if (!client_verify_open_mailbox(client))
Index: imap-fetch-body.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch-body.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- imap-fetch-body.c 23 Sep 2004 09:18:39 -0000 1.12
+++ imap-fetch-body.c 28 Sep 2004 10:55:36 -0000 1.13
@@ -3,12 +3,14 @@
#include "common.h"
#include "buffer.h"
#include "str.h"
+#include "strescape.h"
#include "istream.h"
#include "ostream.h"
#include "istream-header-filter.h"
#include "message-parser.h"
#include "message-send.h"
#include "mail-storage.h"
+#include "imap-parser.h"
#include "imap-fetch.h"
#include <stdlib.h>
@@ -22,6 +24,10 @@
const char *section; /* NOTE: always uppercased */
uoff_t skip, max_size; /* if you don't want max_size,
set it to (uoff_t)-1 */
+
+ const char *const *fields;
+ size_t fields_count;
+
unsigned int skip_set:1;
unsigned int peek:1;
};
@@ -37,24 +43,6 @@
static struct partial_cache partial = { 0, 0, 0, 0, { 0, 0, 0 } };
-static const char *const *
-imap_fetch_get_body_fields(const char *fields, size_t *count_r)
-{
- const char **arr, **p;
- size_t count;
-
- i_assert(*fields == '(');
-
- arr = t_strsplit_spaces(t_strcut(fields+1, ')'), " ");
- for (count = 0, p = arr; *p != NULL; p++)
- count++;
-
- qsort(arr, count, sizeof(*arr), strcasecmp_p);
-
- *count_r = count;
- return arr;
-}
-
static int seek_partial(unsigned int select_counter, unsigned int uid,
struct partial_cache *partial, struct istream *stream,
uoff_t virtual_skip)
@@ -376,27 +364,23 @@
const struct imap_fetch_body_data *body,
const char *header_section)
{
- const char *const *fields;
struct message_size msg_size;
struct istream *input;
- size_t fields_count;
/* MIME, HEADER.FIELDS (list), HEADER.FIELDS.NOT (list) */
ctx->cur_have_eoh = FALSE;
if (strncmp(header_section, "HEADER.FIELDS ", 14) == 0) {
- fields = imap_fetch_get_body_fields(header_section + 14,
- &fields_count);
input = i_stream_create_header_filter(ctx->cur_input,
HEADER_FILTER_INCLUDE,
- fields, fields_count,
+ body->fields,
+ body->fields_count,
header_filter_eoh, ctx);
} else if (strncmp(header_section, "HEADER.FIELDS.NOT ", 18) == 0) {
- fields = imap_fetch_get_body_fields(header_section + 18,
- &fields_count);
input = i_stream_create_header_filter(ctx->cur_input,
HEADER_FILTER_EXCLUDE,
- fields, fields_count,
+ body->fields,
+ body->fields_count,
header_filter_eoh, ctx);
} else if (strcmp(header_section, "MIME") == 0) {
/* Mime-Version + Content-* fields */
@@ -589,8 +573,7 @@
struct imap_fetch_body_data *body,
const char *section)
{
- const char *const *headers, *const *arr;
- size_t count;
+ const char *const *arr;
if (!fetch_body_header_fields_check(section))
return FALSE;
@@ -604,14 +587,13 @@
}
t_push();
- headers = imap_fetch_get_body_fields(section, &count);
- for (arr = headers; *arr != NULL; arr++) {
+ for (arr = body->fields; *arr != NULL; arr++) {
char *hdr = p_strdup(ctx->client->cmd_pool, *arr);
buffer_append(ctx->all_headers_buf, &hdr, sizeof(hdr));
}
- body->header_ctx = mailbox_header_lookup_init(ctx->box, headers);
+ body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields);
imap_fetch_add_handler(ctx, fetch_body_header_fields, body);
t_pop();
return TRUE;
@@ -698,11 +680,58 @@
return TRUE;
}
-int fetch_body_section_init(struct imap_fetch_context *ctx, const char *arg)
+static int body_section_build(struct imap_fetch_context *ctx,
+ struct imap_fetch_body_data *body,
+ const char *prefix,
+ const struct imap_arg_list *list)
+{
+ string_t *str;
+ const char **arr;
+ size_t i;
+
+ str = str_new(ctx->client->cmd_pool, 128);
+ str_append(str, prefix);
+ str_append(str, " (");
+
+ /* @UNSAFE: NULL-terminated list of headers */
+ arr = p_new(ctx->client->cmd_pool, const char *, list->size + 1);
+
+ for (i = 0; i < list->size; i++) {
+ if (list->args[i].type != IMAP_ARG_ATOM &&
+ list->args[i].type != IMAP_ARG_STRING) {
+ client_send_command_error(ctx->client,
+ "Invalid BODY[..] parameter: "
+ "Header list contains non-strings");
+ return FALSE;
+ }
+
+ if (i != 0)
+ str_append_c(str, ' ');
+ arr[i] = str_ucase(IMAP_ARG_STR(&list->args[i]));
+
+ if (list->args[i].type == IMAP_ARG_ATOM)
+ str_append(str, arr[i]);
+ else {
+ str_append_c(str, '"');
+ str_append(str, str_escape(arr[i]));
+ str_append_c(str, '"');
+ }
+ }
+ str_append_c(str, ')');
+
+ qsort(arr, list->size, sizeof(*arr), strcasecmp_p);
+ body->fields = arr;
+ body->fields_count = list->size;
+ body->section = str_c(str);
+ return TRUE;
+}
+
+int fetch_body_section_init(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args)
{
struct imap_fetch_body_data *body;
const char *partial;
- const char *p = arg + 4;
+ const char *p = name + 4;
body = p_new(ctx->client->cmd_pool, struct imap_fetch_body_data, 1);
body->max_size = (uoff_t)-1;
@@ -720,14 +749,31 @@
return FALSE;
}
- body->section = p+1;
- p = strchr(body->section, ']');
- if (p == NULL) {
- client_send_command_error(ctx->client,
- "Invalid BODY[..] parameter: Missing ']'");
- return FALSE;
+ if ((*args)[0].type == IMAP_ARG_LIST) {
+ /* BODY[HEADER.FIELDS.. (headers list)] */
+ if ((*args)[1].type != IMAP_ARG_ATOM ||
+ IMAP_ARG_STR(&(*args)[1])[0] != ']') {
+ client_send_command_error(ctx->client,
+ "Invalid BODY[..] parameter: Missing ']'");
+ return FALSE;
+ }
+ if (!body_section_build(ctx, body, p+1,
+ IMAP_ARG_LIST(&(*args)[0])))
+ return FALSE;
+ p = IMAP_ARG_STR(&(*args)[1]);
+ *args += 2;
+ } else {
+ /* no headers list */
+ body->section = p+1;
+ p = strchr(body->section, ']');
+ if (p == NULL) {
+ client_send_command_error(ctx->client,
+ "Invalid BODY[..] parameter: Missing ']'");
+ return FALSE;
+ }
+ body->section = p_strdup_until(ctx->client->cmd_pool,
+ body->section, p);
}
- body->section = p_strdup_until(ctx->client->cmd_pool, body->section, p);
if (*++p == '<') {
/* <start.end> */
@@ -860,9 +906,10 @@
return fetch_stream(ctx, &body_size);
}
-int fetch_rfc822_init(struct imap_fetch_context *ctx, const char *arg)
+int fetch_rfc822_init(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args __attr_unused__)
{
- if (arg[6] == '\0') {
+ if (name[6] == '\0') {
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
MAIL_FETCH_STREAM_BODY;
ctx->flags_update_seen = TRUE;
@@ -870,17 +917,17 @@
return TRUE;
}
- if (strcmp(arg+6, ".SIZE") == 0) {
+ if (strcmp(name+6, ".SIZE") == 0) {
ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE;
imap_fetch_add_handler(ctx, fetch_rfc822_size, NULL);
return TRUE;
}
- if (strcmp(arg+6, ".HEADER") == 0) {
+ if (strcmp(name+6, ".HEADER") == 0) {
ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
imap_fetch_add_handler(ctx, fetch_rfc822_header, NULL);
return TRUE;
}
- if (strcmp(arg+6, ".TEXT") == 0) {
+ if (strcmp(name+6, ".TEXT") == 0) {
ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
ctx->flags_update_seen = TRUE;
imap_fetch_add_handler(ctx, fetch_rfc822_text, NULL);
@@ -888,6 +935,6 @@
}
client_send_command_error(ctx->client, t_strconcat(
- "Unknown parameter ", arg, NULL));
+ "Unknown parameter ", name, NULL));
return FALSE;
}
Index: imap-fetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- imap-fetch.c 19 Sep 2004 23:23:08 -0000 1.26
+++ imap-fetch.c 28 Sep 2004 10:55:36 -0000 1.27
@@ -58,22 +58,23 @@
return name[i] < 'A' || name[i] >= 'Z' ? 0 : -1;
}
-int imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *arg)
+int imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args)
{
const struct imap_fetch_handler *handler;
- handler = bsearch(arg, fetch_handlers->data,
+ handler = bsearch(name, fetch_handlers->data,
fetch_handlers->used /
sizeof(struct imap_fetch_handler),
sizeof(struct imap_fetch_handler),
imap_fetch_handler_bsearch);
if (handler == NULL) {
client_send_command_error(ctx->client,
- t_strconcat("Unknown command ", arg, NULL));
+ t_strconcat("Unknown command ", name, NULL));
return FALSE;
}
- return handler->init(ctx, arg);
+ return handler->init(ctx, name, args);
}
struct imap_fetch_context *imap_fetch_init(struct client *client)
@@ -136,7 +137,7 @@
ctx->flags_update_seen = FALSE;
else if (!ctx->flags_have_handler) {
ctx->flags_show_only_seen_changes = TRUE;
- (void)imap_fetch_init_handler(ctx, "FLAGS");
+ (void)imap_fetch_init_handler(ctx, "FLAGS", NULL);
}
}
@@ -290,14 +291,15 @@
return 1;
}
-static int fetch_body_init(struct imap_fetch_context *ctx, const char *arg)
+static int fetch_body_init(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args)
{
- if (arg[4] == '\0') {
+ if (name[4] == '\0') {
ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
imap_fetch_add_handler(ctx, fetch_body, NULL);
return TRUE;
}
- return fetch_body_section_init(ctx, arg);
+ return fetch_body_section_init(ctx, name, args);
}
static int fetch_bodystructure(struct imap_fetch_context *ctx,
@@ -325,7 +327,8 @@
}
static int fetch_bodystructure_init(struct imap_fetch_context *ctx,
- const char *arg __attr_unused__)
+ const char *name __attr_unused__,
+ struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
imap_fetch_add_handler(ctx, fetch_bodystructure, NULL);
@@ -356,7 +359,8 @@
}
static int fetch_envelope_init(struct imap_fetch_context *ctx,
- const char *arg __attr_unused__)
+ const char *name __attr_unused__,
+ struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
imap_fetch_add_handler(ctx, fetch_envelope, NULL);
@@ -392,7 +396,8 @@
}
static int fetch_flags_init(struct imap_fetch_context *ctx,
- const char *arg __attr_unused__)
+ const char *name __attr_unused__,
+ struct imap_arg **args __attr_unused__)
{
ctx->flags_have_handler = TRUE;
ctx->fetch_data |= MAIL_FETCH_FLAGS;
@@ -416,7 +421,8 @@
static int fetch_internaldate_init(struct imap_fetch_context *ctx,
- const char *arg __attr_unused__)
+ const char *name __attr_unused__,
+ struct imap_arg **args __attr_unused__)
{
ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
imap_fetch_add_handler(ctx, fetch_internaldate, NULL);
@@ -431,7 +437,8 @@
}
static int fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__,
- const char *arg __attr_unused__)
+ const char *name __attr_unused__,
+ struct imap_arg **args __attr_unused__)
{
imap_fetch_add_handler(ctx, fetch_uid, NULL);
return TRUE;
Index: imap-fetch.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- imap-fetch.h 22 Aug 2004 09:52:11 -0000 1.9
+++ imap-fetch.h 28 Sep 2004 10:55:37 -0000 1.10
@@ -12,7 +12,8 @@
const char *name;
/* Returns FALSE if arg is invalid. */
- int (*init)(struct imap_fetch_context *ctx, const char *arg);
+ int (*init)(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args);
};
struct imap_fetch_context_handler {
@@ -63,13 +64,16 @@
struct imap_fetch_context *imap_fetch_init(struct client *client);
int imap_fetch_deinit(struct imap_fetch_context *ctx);
-int imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *arg);
+int imap_fetch_init_handler(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args);
void imap_fetch_begin(struct imap_fetch_context *ctx,
struct mail_search_arg *search_arg);
int imap_fetch(struct imap_fetch_context *ctx);
-int fetch_body_section_init(struct imap_fetch_context *ctx, const char *arg);
-int fetch_rfc822_init(struct imap_fetch_context *ctx, const char *arg);
+int fetch_body_section_init(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args);
+int fetch_rfc822_init(struct imap_fetch_context *ctx, const char *name,
+ struct imap_arg **args);
#endif
More information about the dovecot-cvs
mailing list