dovecot-2.2: lib-imap: Added support for parsing IMAP BODYSTRUCT...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Sep 15 19:00:53 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/d1f084a39708
changeset: 15057:d1f084a39708
user: Timo Sirainen <tss at iki.fi>
date: Sat Sep 15 18:58:48 2012 +0300
description:
lib-imap: Added support for parsing IMAP BODYSTRUCTURE and writing out a modified version.
diffstat:
src/lib-imap/Makefile.am | 5 +
src/lib-imap/imap-bodystructure.c | 483 +++++++++++++++++++++++++-------
src/lib-imap/imap-bodystructure.h | 28 +
src/lib-imap/test-imap-bodystructure.c | 143 +++++++++
4 files changed, 551 insertions(+), 108 deletions(-)
diffs (truncated from 807 to 300 lines):
diff -r 6acd8b149709 -r d1f084a39708 src/lib-imap/Makefile.am
--- a/src/lib-imap/Makefile.am Sat Sep 15 16:13:02 2012 +0300
+++ b/src/lib-imap/Makefile.am Sat Sep 15 18:58:48 2012 +0300
@@ -41,6 +41,7 @@
pkginc_lib_HEADERS = $(headers)
test_programs = \
+ test-imap-bodystructure \
test-imap-match \
test-imap-parser \
test-imap-url \
@@ -53,6 +54,10 @@
../lib-test/libtest.la \
../lib/liblib.la
+test_imap_bodystructure_SOURCES = test-imap-bodystructure.c
+test_imap_bodystructure_LDADD = imap-bodystructure.lo imap-envelope.lo imap-quote.lo imap-parser.lo imap-arg.lo ../lib-mail/libmail.la $(test_libs)
+test_imap_bodystructure_DEPENDENCIES = imap-bodystructure.lo imap-envelope.lo imap-quote.lo imap-parser.lo imap-arg.lo ../lib-mail/libmail.la $(test_libs)
+
test_imap_match_SOURCES = test-imap-match.c
test_imap_match_LDADD = imap-match.lo $(test_libs)
test_imap_match_DEPENDENCIES = imap-match.lo $(test_libs)
diff -r 6acd8b149709 -r d1f084a39708 src/lib-imap/imap-bodystructure.c
--- a/src/lib-imap/imap-bodystructure.c Sat Sep 15 16:13:02 2012 +0300
+++ b/src/lib-imap/imap-bodystructure.c Sat Sep 15 18:58:48 2012 +0300
@@ -18,21 +18,7 @@
#define EMPTY_BODYSTRUCTURE \
"(\"text\" \"plain\" ("DEFAULT_CHARSET") NIL NIL \"7bit\" 0 0)"
-struct message_part_body_data {
- pool_t pool;
- const char *content_type, *content_subtype;
- const char *content_type_params;
- const char *content_transfer_encoding;
- const char *content_id;
- const char *content_description;
- const char *content_disposition;
- const char *content_disposition_params;
- const char *content_md5;
- const char *content_language;
- const char *content_location;
-
- struct message_part_envelope_data *envelope;
-};
+#define NVL(str, nullstr) ((str) != NULL ? (str) : (nullstr))
static void parse_content_type(struct message_part_body_data *data,
struct message_header_line *hdr)
@@ -290,39 +276,21 @@
}
}
-static void part_write_body_multipart(const struct message_part *part,
- string_t *str, bool extended)
+static void
+imap_bodystructure_write_siblings(const struct message_part *part,
+ string_t *dest, bool extended)
{
- struct message_part_body_data *data = part->context;
+ for (; part != NULL; part = part->next) {
+ str_append_c(dest, '(');
+ imap_bodystructure_write(part, dest, extended);
+ str_append_c(dest, ')');
+ }
+}
- if (part->children != NULL)
- imap_bodystructure_write(part->children, str, extended);
- else {
- /* no parts in multipart message,
- that's not allowed. write a single
- 0-length text/plain structure */
- str_append(str, EMPTY_BODYSTRUCTURE);
- }
-
- str_append_c(str, ' ');
- if (data->content_subtype != NULL)
- str_append(str, data->content_subtype);
- else
- str_append(str, "\"x-unknown\"");
-
- if (!extended)
- return;
-
- /* BODYSTRUCTURE data */
- str_append_c(str, ' ');
- if (data->content_type_params == NULL)
- str_append(str, "NIL");
- else {
- str_append_c(str, '(');
- str_append(str, data->content_type_params);
- str_append_c(str, ')');
- }
-
+static void
+part_write_bodystructure_data_common(struct message_part_body_data *data,
+ string_t *str)
+{
str_append_c(str, ' ');
if (data->content_disposition == NULL)
str_append(str, "NIL");
@@ -351,16 +319,48 @@
}
str_append_c(str, ' ');
- if (data->content_location == NULL)
+ str_append(str, NVL(data->content_location, "NIL"));
+}
+
+static void part_write_body_multipart(const struct message_part *part,
+ string_t *str, bool extended)
+{
+ struct message_part_body_data *data = part->context;
+
+ if (part->children != NULL)
+ imap_bodystructure_write_siblings(part->children, str, extended);
+ else {
+ /* no parts in multipart message,
+ that's not allowed. write a single
+ 0-length text/plain structure */
+ str_append(str, EMPTY_BODYSTRUCTURE);
+ }
+
+ str_append_c(str, ' ');
+ if (data->content_subtype != NULL)
+ str_append(str, data->content_subtype);
+ else
+ str_append(str, "\"x-unknown\"");
+
+ if (!extended)
+ return;
+
+ /* BODYSTRUCTURE data */
+ str_append_c(str, ' ');
+ if (data->content_type_params == NULL)
str_append(str, "NIL");
- else
- str_append(str, data->content_location);
+ else {
+ str_append_c(str, '(');
+ str_append(str, data->content_type_params);
+ str_append_c(str, ')');
+ }
+
+ part_write_bodystructure_data_common(data, str);
}
static void part_write_body(const struct message_part *part,
string_t *str, bool extended)
{
-#define NVL(str, nullstr) ((str) != NULL ? (str) : (nullstr))
struct message_part_body_data *data = part->context;
bool text;
@@ -410,19 +410,20 @@
} else if (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) {
/* message/rfc822 contains envelope + body + line count */
struct message_part_body_data *child_data;
- struct message_part_envelope_data *env_data;
i_assert(part->children != NULL);
i_assert(part->children->next == NULL);
child_data = part->children->context;
- env_data = child_data->envelope;
str_append(str, " (");
- imap_envelope_write_part_data(env_data, str);
+ if (child_data->envelope_str != NULL)
+ str_append(str, child_data->envelope_str);
+ else
+ imap_envelope_write_part_data(child_data->envelope, str);
str_append(str, ") ");
- imap_bodystructure_write(part->children, str, extended);
+ imap_bodystructure_write_siblings(part->children, str, extended);
str_printfa(str, " %u", part->body_size.lines);
}
@@ -435,40 +436,7 @@
("body" "language" "params") "location" */
str_append_c(str, ' ');
str_append(str, NVL(data->content_md5, "NIL"));
-
- str_append_c(str, ' ');
- if (data->content_disposition == NULL)
- str_append(str, "NIL");
- else {
- str_append_c(str, '(');
- str_append(str, data->content_disposition);
- str_append_c(str, ' ');
-
- if (data->content_disposition_params == NULL)
- str_append(str, "NIL");
- else {
- str_append_c(str, '(');
- str_append(str, data->content_disposition_params);
- str_append_c(str, ')');
- }
-
- str_append_c(str, ')');
- }
-
- str_append_c(str, ' ');
- if (data->content_language == NULL)
- str_append(str, "NIL");
- else {
- str_append_c(str, '(');
- str_append(str, data->content_language);
- str_append_c(str, ')');
- }
-
- str_append_c(str, ' ');
- if (data->content_location == NULL)
- str_append(str, "NIL");
- else
- str_append(str, data->content_location);
+ part_write_bodystructure_data_common(data, str);
}
bool imap_bodystructure_is_plain_7bit(const struct message_part *part)
@@ -515,22 +483,10 @@
void imap_bodystructure_write(const struct message_part *part,
string_t *dest, bool extended)
{
- i_assert(part->parent != NULL || part->next == NULL);
-
- while (part != NULL) {
- if (part->parent != NULL)
- str_append_c(dest, '(');
-
- if (part->flags & MESSAGE_PART_FLAG_MULTIPART)
- part_write_body_multipart(part, dest, extended);
- else
- part_write_body(part, dest, extended);
-
- if (part->parent != NULL)
- str_append_c(dest, ')');
-
- part = part->next;
- }
+ if (part->flags & MESSAGE_PART_FLAG_MULTIPART)
+ part_write_body_multipart(part, dest, extended);
+ else
+ part_write_body(part, dest, extended);
}
static bool str_append_nstring(string_t *str, const struct imap_arg *arg)
@@ -566,12 +522,27 @@
return TRUE;
}
+static bool
+get_nstring(const struct imap_arg *arg, pool_t pool, string_t *tmpstr,
+ const char **value_r)
+{
+ if (arg->type == IMAP_ARG_NIL) {
+ *value_r = NULL;
+ return TRUE;
+ }
+
+ str_truncate(tmpstr, 0);
+ if (!str_append_nstring(tmpstr, arg))
+ return FALSE;
+ *value_r = p_strdup(pool, str_c(tmpstr));
+ return TRUE;
+}
+
static void 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 (!IMAP_ARG_IS_EOL(args)) {
if (!str_append_nstring(str, args)) {
if (!imap_arg_get_list(args, &children)) {
@@ -579,14 +550,308 @@
i_unreached();
}
+ str_append_c(str, '(');
imap_write_list(children, str);
+ str_append_c(str, ')');
}
args++;
if (!IMAP_ARG_IS_EOL(args))
str_append_c(str, ' ');
}
- str_append_c(str, ')');
+}
+
+static int imap_write_nstring_list(const struct imap_arg *args, string_t *str)
+{
+ str_truncate(str, 0);
+ while (!IMAP_ARG_IS_EOL(args)) {
+ if (!str_append_nstring(str, &args[0]))
+ return -1;
+ str_append_c(str, ' ');
More information about the dovecot-cvs
mailing list