summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--imap4d/fetch.c14
-rw-r--r--include/mailutils/header.h1
-rw-r--r--include/mailutils/imap.h14
-rw-r--r--include/mailutils/message.h75
-rw-r--r--include/mailutils/mime.h3
-rw-r--r--include/mailutils/sys/message.h2
-rw-r--r--libmailutils/mailbox/Makefile.am2
-rw-r--r--libmailutils/mailbox/bodystruct.c325
-rw-r--r--libmailutils/mailbox/imapenv.c138
-rw-r--r--libmailutils/string/wordsplit.c2
-rw-r--r--libproto/imap/fetch.c498
-rw-r--r--libproto/imap/resplist.c9
-rw-r--r--mu/imap.c168
-rw-r--r--testsuite/Makefile.am1
-rw-r--r--testsuite/bs.c169
15 files changed, 1353 insertions, 68 deletions
diff --git a/imap4d/fetch.c b/imap4d/fetch.c
index fed2e3f21..ad42ff3a9 100644
--- a/imap4d/fetch.c
+++ b/imap4d/fetch.c
@@ -372,8 +372,9 @@ bodystructure (mu_message_t msg, int extension)
if (mu_header_aget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0)
{
struct mu_wordsplit ws;
- char *s, *p;
-
+ char *p;
+ size_t len;
+
ws.ws_delim = " \t\r\n;=";
ws.ws_alloc_die = imap4d_ws_alloc_die;
if (mu_wordsplit (buffer, &ws, IMAP4D_WS_FLAGS))
@@ -383,18 +384,17 @@ bodystructure (mu_message_t msg, int extension)
return RESP_BAD; /* FIXME: a better error handling, maybe? */
}
+ len = strcspn (ws.ws_wordv[0], "/");
if (mu_c_strcasecmp (ws.ws_wordv[0], "MESSAGE/RFC822") == 0)
message_rfc822 = 1;
- else if (mu_c_strcasecmp (ws.ws_wordv[0], "TEXT/PLAIN") == 0)
+ else if (mu_c_strncasecmp (ws.ws_wordv[0], "TEXT", len) == 0)
text_plain = 1;
- s = strchr (ws.ws_wordv[0], '/');
- if (s)
- *s++ = 0;
+ ws.ws_wordv[0][len++] = 0;
p = ws.ws_wordv[0];
io_send_qstring (p);
io_sendf (" ");
- io_send_qstring (s);
+ io_send_qstring (ws.ws_wordv[0] + len);
/* body parameter parenthesized list: Content-type attributes */
if (ws.ws_wordc > 1)
diff --git a/include/mailutils/header.h b/include/mailutils/header.h
index ed13ab31b..4117a2913 100644
--- a/include/mailutils/header.h
+++ b/include/mailutils/header.h
@@ -59,6 +59,7 @@ extern "C" {
#define MU_HEADER_CONTENT_DESCRIPTION "Content-Description"
#define MU_HEADER_CONTENT_DISPOSITION "Content-Disposition"
#define MU_HEADER_CONTENT_MD5 "Content-MD5"
+#define MU_HEADER_CONTENT_LOCATION "Content-Location"
#define MU_HEADER_MIME_VERSION "MIME-Version"
#define MU_HEADER_X_MAILER "X-Mailer"
#define MU_HEADER_X_UIDL "X-UIDL"
diff --git a/include/mailutils/imap.h b/include/mailutils/imap.h
index 63a5eae1b..b6f9e5740 100644
--- a/include/mailutils/imap.h
+++ b/include/mailutils/imap.h
@@ -236,23 +236,13 @@ struct mu_imap_fetch_body
struct mu_imap_fetch_bodystructure
{
int type;
- //FIXME?
+ struct mu_bodystructure *bs;
};
struct mu_imap_fetch_envelope
{
int type;
- struct tm date;
- struct mu_timezone tz;
- char *subject;
- mu_address_t from;
- mu_address_t sender;
- mu_address_t reply_to;
- mu_address_t to;
- mu_address_t cc;
- mu_address_t bcc;
- char *in_reply_to;
- char *message_id;
+ struct mu_imapenvelope *imapenvelope;
};
struct mu_imap_fetch_flags
diff --git a/include/mailutils/message.h b/include/mailutils/message.h
index ced790153..d1a31ecaa 100644
--- a/include/mailutils/message.h
+++ b/include/mailutils/message.h
@@ -20,6 +20,7 @@
#define _MAILUTILS_MESSAGE_H
#include <mailutils/types.h>
+#include <mailutils/datetime.h>
#ifdef __cplusplus
extern "C" {
@@ -28,6 +29,64 @@ extern "C" {
#define MU_SCAN_SEEK 0x01
#define MU_SCAN_SIZE 0x02
+struct mu_imapenvelope
+{
+ struct tm date;
+ struct mu_timezone tz;
+ char *subject;
+ mu_address_t from;
+ mu_address_t sender;
+ mu_address_t reply_to;
+ mu_address_t to;
+ mu_address_t cc;
+ mu_address_t bcc;
+ char *in_reply_to;
+ char *message_id;
+};
+
+enum mu_message_type
+ {
+ mu_message_other,
+ mu_message_text, /* text/plain */
+ mu_message_rfc822, /* message/rfc822 */
+ mu_message_multipart /* multipart/mixed */
+ };
+
+struct mu_bodystructure
+{
+ enum mu_message_type body_message_type;
+ char *body_type;
+ char *body_subtype;
+ mu_assoc_t body_param;
+ char *body_id;
+ char *body_descr;
+ char *body_encoding;
+ size_t body_size;
+ /* Optional */
+ char *body_md5;
+ char *body_disposition;
+ mu_assoc_t body_disp_param;
+ char *body_language;
+ char *body_location;
+ union
+ {
+ struct
+ {
+ size_t body_lines;
+ } text;
+ struct
+ {
+ struct mu_imapenvelope *body_env;
+ struct mu_bodystructure *body_struct;
+ size_t body_lines;
+ } rfc822;
+ struct
+ {
+ mu_list_t body_parts;
+ } multipart;
+ } v;
+};
+
struct mu_message_scan
{
int flags;
@@ -137,6 +196,21 @@ extern int mu_message_set_qid (mu_message_t,
int (*_get_qid) (mu_message_t,
mu_message_qid_t *),
void *owner);
+
+extern int mu_message_get_imapenvelope (mu_message_t, struct mu_imapenvelope **);
+extern void mu_message_imapenvelope_free (struct mu_imapenvelope *);
+extern int mu_message_set_imapenvelope (mu_message_t,
+ int (*_imapenvelope) (mu_message_t, struct mu_imapenvelope **),
+ void *owner);
+
+extern void mu_bodystructure_free (struct mu_bodystructure *);
+extern void mu_list_free_bodystructure (void *item);
+
+extern int mu_message_get_bodystructure (mu_message_t,
+ struct mu_bodystructure **);
+extern int mu_message_set_bodystructure (mu_message_t msg,
+ int (*_bodystructure) (mu_message_t, struct mu_bodystructure **),
+ void *owner);
/* misc functions */
extern int mu_message_create_attachment (const char *content_type,
@@ -190,7 +264,6 @@ extern int mu_message_from_stream_with_envelope (mu_message_t *pmsg,
mu_envelope_t env);
extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/mailutils/mime.h b/include/mailutils/mime.h
index 9c3d473a2..48989f1e1 100644
--- a/include/mailutils/mime.h
+++ b/include/mailutils/mime.h
@@ -66,6 +66,9 @@ int mu_base64_decode (const unsigned char *input, size_t input_len,
unsigned char **output, size_t * output_len);
+int mu_mime_param_assoc_create (mu_assoc_t *passoc);
+int mu_mime_param_assoc_add (mu_assoc_t assoc, const char *name);
+
int mu_mime_header_parse (const char *text, char *charset, char **pvalue,
mu_assoc_t *paramtab);
int mu_mime_header_parse_subset (const char *text, const char *charset,
diff --git a/include/mailutils/sys/message.h b/include/mailutils/sys/message.h
index f538fc9bb..6259dbe89 100644
--- a/include/mailutils/sys/message.h
+++ b/include/mailutils/sys/message.h
@@ -61,6 +61,8 @@ struct _mu_message
int (*_get_qid) (mu_message_t, mu_message_qid_t *);
int (*_get_num_parts) (mu_message_t, size_t *);
int (*_get_part) (mu_message_t, size_t, mu_message_t *);
+ int (*_imapenvelope) (mu_message_t, struct mu_imapenvelope **);
+ int (*_bodystructure) (mu_message_t, struct mu_bodystructure **);
int (*_is_multipart) (mu_message_t, int *);
int (*_lines) (mu_message_t, size_t *, int);
int (*_size) (mu_message_t, size_t *);
diff --git a/libmailutils/mailbox/Makefile.am b/libmailutils/mailbox/Makefile.am
index cb9e775fc..661a92211 100644
--- a/libmailutils/mailbox/Makefile.am
+++ b/libmailutils/mailbox/Makefile.am
@@ -23,12 +23,14 @@ libmailbox_la_SOURCES = \
mbxitr.c\
attribute.c\
body.c\
+ bodystruct.c\
envelope.c\
folder.c\
fsfolder.c\
hdrfirst.c\
hdritr.c\
header.c\
+ imapenv.c\
msgcpy.c\
msgattr.c\
msgbody.c\
diff --git a/libmailutils/mailbox/bodystruct.c b/libmailutils/mailbox/bodystruct.c
new file mode 100644
index 000000000..c99cbbe4a
--- /dev/null
+++ b/libmailutils/mailbox/bodystruct.c
@@ -0,0 +1,325 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/types.h>
+#include <mailutils/assoc.h>
+#include <mailutils/list.h>
+#include <mailutils/message.h>
+#include <mailutils/mime.h>
+#include <mailutils/header.h>
+#include <mailutils/sys/message.h>
+#include <mailutils/errno.h>
+#include <mailutils/debug.h>
+#include <mailutils/nls.h>
+#include <mailutils/cstr.h>
+#include <mailutils/body.h>
+
+void
+mu_list_free_bodystructure (void *item)
+{
+ mu_bodystructure_free (item);
+}
+
+void
+mu_bodystructure_free (struct mu_bodystructure *bs)
+{
+ if (!bs)
+ return;
+ free (bs->body_type);
+ free (bs->body_subtype);
+ mu_assoc_destroy (&bs->body_param);
+ free (bs->body_id);
+ free (bs->body_descr);
+ free (bs->body_encoding);
+ free (bs->body_md5);
+ free (bs->body_disposition);
+ mu_assoc_destroy (&bs->body_disp_param);
+ free (bs->body_language);
+ free (bs->body_location);
+ switch (bs->body_message_type)
+ {
+ case mu_message_other:
+ case mu_message_text:
+ break;
+
+ case mu_message_rfc822:
+ mu_message_imapenvelope_free (bs->v.rfc822.body_env);
+ mu_bodystructure_free (bs->v.rfc822.body_struct);
+ break;
+
+ case mu_message_multipart:
+ mu_list_destroy (&bs->v.multipart.body_parts);
+ }
+
+ free (bs);
+}
+
+static int bodystructure_fill (mu_message_t msg,
+ struct mu_bodystructure *bs);
+
+static int
+bodystructure_init (mu_message_t msg, struct mu_bodystructure **pbs)
+{
+ int rc;
+ struct mu_bodystructure *bs = calloc (1, sizeof (*bs));
+ if (!bs)
+ return ENOMEM;
+ rc = bodystructure_fill (msg, bs);
+ if (rc)
+ mu_bodystructure_free (bs);
+ else
+ *pbs = bs;
+ return rc;
+}
+
+static int
+bodystructure_fill (mu_message_t msg, struct mu_bodystructure *bs)
+{
+ mu_header_t header = NULL;
+ const char *buffer = NULL;
+ mu_body_t body = NULL;
+ int rc;
+ int is_multipart = 0;
+
+ rc = mu_message_get_header (msg, &header);
+ if (rc)
+ return rc;
+
+ if (mu_header_sget_value (header, MU_HEADER_CONTENT_TYPE, &buffer) == 0)
+ {
+ char *value;
+ char *p;
+ size_t len;
+
+ rc = mu_mime_header_parse (buffer, "UTF-8", &value, &bs->body_param);
+ if (rc)
+ return rc;
+
+ len = strcspn (value, "/");
+
+ if (mu_c_strcasecmp (value, "MESSAGE/RFC822") == 0)
+ bs->body_message_type = mu_message_rfc822;
+ else if (mu_c_strncasecmp (value, "TEXT", len) == 0)
+ bs->body_message_type = mu_message_text;
+
+ p = malloc (len + 1);
+ if (!p)
+ return ENOMEM;
+ memcpy (p, value, len);
+ p[len] = 0;
+
+ bs->body_type = p;
+ mu_strupper (bs->body_type);
+ if (value[len])
+ {
+ bs->body_subtype = strdup (value + len + 1);
+ if (!bs->body_subtype)
+ return ENOMEM;
+ mu_strupper (bs->body_subtype);
+ }
+
+ /* body parameter parenthesized list: Content-type attributes */
+
+ rc = mu_message_is_multipart (msg, &is_multipart);
+ if (rc)
+ return rc;
+ if (is_multipart)
+ bs->body_message_type = mu_message_multipart;
+ }
+ else
+ {
+ struct mu_mime_param param;
+
+ /* Default? If Content-Type is not present consider as text/plain. */
+ bs->body_type = strdup ("TEXT");
+ if (!bs->body_type)
+ return ENOMEM;
+ bs->body_subtype = strdup ("PLAIN");
+ if (!bs->body_subtype)
+ return ENOMEM;
+ rc = mu_mime_param_assoc_create (&bs->body_param);
+ if (rc)
+ return rc;
+ memset (&param, 0, sizeof (param));
+ param.value = strdup ("US-ASCII");
+ rc = mu_assoc_install (bs->body_param, "CHARSET", &param);
+ if (rc)
+ {
+ free (param.value);
+ return rc;
+ }
+ bs->body_message_type = mu_message_text;
+ }
+
+ if (is_multipart)
+ {
+ size_t i, nparts;
+
+ rc = mu_message_get_num_parts (msg, &nparts);
+ if (rc)
+ return rc;
+
+ rc = mu_list_create (&bs->v.multipart.body_parts);
+ if (rc)
+ return rc;
+
+ mu_list_set_destroy_item (bs->v.multipart.body_parts,
+ mu_list_free_bodystructure);
+
+ for (i = 1; i <= nparts; i++)
+ {
+ mu_message_t partmsg;
+ struct mu_bodystructure *partbs;
+
+ rc = mu_message_get_part (msg, i, &partmsg);
+ if (rc)
+ return rc;
+
+ rc = bodystructure_init (partmsg, &partbs);
+ if (rc)
+ return rc;
+
+ rc = mu_list_append (bs->v.multipart.body_parts, partbs);
+ if (rc)
+ {
+ mu_bodystructure_free (partbs);
+ return rc;
+ }
+ }
+ }
+ else
+ {
+ /* body id: Content-ID. */
+ rc = mu_header_aget_value_unfold (header, MU_HEADER_CONTENT_ID,
+ &bs->body_id);
+ if (rc && rc != MU_ERR_NOENT)
+ return rc;
+ /* body description: Content-Description. */
+ rc = mu_header_aget_value_unfold (header, MU_HEADER_CONTENT_DESCRIPTION,
+ &bs->body_descr);
+ if (rc && rc != MU_ERR_NOENT)
+ return rc;
+
+ /* body encoding: Content-Transfer-Encoding. */
+ rc = mu_header_aget_value_unfold (header,
+ MU_HEADER_CONTENT_TRANSFER_ENCODING,
+ &bs->body_encoding);
+ if (rc == MU_ERR_NOENT)
+ {
+ bs->body_encoding = strdup ("7BIT");
+ if (!bs->body_encoding)
+ return ENOMEM;
+ }
+ else if (rc)
+ return rc;
+
+ /* body size RFC822 format. */
+ rc = mu_message_get_body (msg, &body);
+ if (rc)
+ return rc;
+ rc = mu_body_size (body, &bs->body_size);
+ if (rc)
+ return rc;
+
+ /* If the mime type was text. */
+ if (bs->body_message_type == mu_message_text)
+ {
+ rc = mu_body_lines (body, &bs->v.text.body_lines);
+ if (rc)
+ return rc;
+ }
+ else if (bs->body_message_type == mu_message_rfc822)
+ {
+ mu_message_t emsg = NULL;
+
+ /* Add envelope structure of the encapsulated message. */
+ rc = mu_message_unencapsulate (msg, &emsg, NULL);
+ if (rc)
+ return rc;
+ rc = mu_message_get_imapenvelope (emsg, &bs->v.rfc822.body_env);
+ if (rc)
+ return rc;
+ /* Add body structure of the encapsulated message. */
+ rc = bodystructure_init (emsg, &bs->v.rfc822.body_struct);
+ if (rc)
+ return rc;
+ /* Size in text lines of the encapsulated message. */
+ rc = mu_message_lines (emsg, &bs->v.rfc822.body_lines);
+ mu_message_destroy (&emsg, NULL);
+ }
+ }
+
+ /* body MD5: Content-MD5. */
+ rc = mu_header_aget_value_unfold (header, MU_HEADER_CONTENT_MD5,
+ &bs->body_md5);
+ if (rc && rc != MU_ERR_NOENT)
+ return rc;
+
+ /* body disposition: Content-Disposition. */
+ rc = mu_header_sget_value (header, MU_HEADER_CONTENT_DISPOSITION,
+ &buffer);
+ if (rc == 0)
+ {
+ rc = mu_mime_header_parse (buffer, "UTF-8", &bs->body_disposition,
+ &bs->body_disp_param);
+ if (rc)
+ return rc;
+ }
+ else if (rc != MU_ERR_NOENT)
+ return rc;
+ /* body language: Content-Language. */
+ rc = mu_header_aget_value_unfold (header, MU_HEADER_CONTENT_LANGUAGE,
+ &bs->body_language);
+ if (rc && rc != MU_ERR_NOENT)
+ return rc;
+ rc = mu_header_aget_value_unfold (header, MU_HEADER_CONTENT_LOCATION,
+ &bs->body_location);
+ if (rc && rc != MU_ERR_NOENT)
+ return rc;
+
+ return 0;
+}
+
+int
+mu_message_get_bodystructure (mu_message_t msg,
+ struct mu_bodystructure **pbs)
+{
+ if (msg == NULL)
+ return EINVAL;
+ if (pbs == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ if (msg->_bodystructure)
+ return msg->_bodystructure (msg, pbs);
+ return bodystructure_init (msg, pbs);
+}
+
+int
+mu_message_set_bodystructure (mu_message_t msg,
+ int (*_bodystructure) (mu_message_t, struct mu_bodystructure **),
+ void *owner)
+{
+ if (msg == NULL)
+ return EINVAL;
+ if (msg->owner != owner)
+ return EACCES;
+ msg->_bodystructure = _bodystructure;
+ return 0;
+}
diff --git a/libmailutils/mailbox/imapenv.c b/libmailutils/mailbox/imapenv.c
new file mode 100644
index 000000000..efd49b9c8
--- /dev/null
+++ b/libmailutils/mailbox/imapenv.c
@@ -0,0 +1,138 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <mailutils/types.h>
+#include <mailutils/header.h>
+#include <mailutils/envelope.h>
+#include <mailutils/address.h>
+#include <mailutils/message.h>
+#include <mailutils/sys/message.h>
+#include <mailutils/errno.h>
+
+void
+mu_message_imapenvelope_free (struct mu_imapenvelope *env)
+{
+ if (!env)
+ return;
+ free (env->subject);
+ mu_address_destroy (&env->from);
+ mu_address_destroy (&env->sender);
+ mu_address_destroy (&env->reply_to);
+ mu_address_destroy (&env->to);
+ mu_address_destroy (&env->cc);
+ mu_address_destroy (&env->bcc);
+ free (env->in_reply_to);
+ free (env->message_id);
+ free (env);
+}
+
+int
+mu_message_get_imapenvelope (mu_message_t msg, struct mu_imapenvelope **pimapenvelope)
+{
+ struct mu_imapenvelope *imapenvelope;
+ int rc;
+
+ if (msg == NULL)
+ return EINVAL;
+ if (imapenvelope == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ if (msg->_imapenvelope)
+ return msg->_imapenvelope (msg, pimapenvelope);
+
+ imapenvelope = calloc (1, sizeof (imapenvelope[0]));
+ if (!imapenvelope)
+ return ENOMEM;
+ do
+ {
+ mu_header_t hdr;
+ mu_envelope_t env;
+ const char *s;
+
+ if ((rc = mu_message_get_envelope (msg, &env)))
+ break;
+ if ((rc = mu_envelope_sget_date (env, &s)))
+ break;
+ if ((rc = mu_scan_datetime (s, MU_DATETIME_FROM,
+ &imapenvelope->date, &imapenvelope->tz,
+ NULL)))
+ break;
+
+ if ((rc = mu_message_get_header (msg, &hdr)))
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_FROM, &imapenvelope->from);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_SENDER, &imapenvelope->sender);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_REPLY_TO, &imapenvelope->reply_to);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_TO, &imapenvelope->to);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_CC, &imapenvelope->cc);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_get_address (hdr, MU_HEADER_BCC, &imapenvelope->bcc);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_aget_value_unfold (hdr, MU_HEADER_SUBJECT,
+ &imapenvelope->subject);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_aget_value_unfold (hdr, MU_HEADER_IN_REPLY_TO,
+ &imapenvelope->in_reply_to);
+ if (rc && rc != MU_ERR_NOENT)
+ break;
+
+ rc = mu_header_aget_value_unfold (hdr, MU_HEADER_MESSAGE_ID,
+ &imapenvelope->message_id);
+ }
+ while (0);
+ if (rc)
+ mu_message_imapenvelope_free (imapenvelope);
+ else
+ *pimapenvelope = imapenvelope;
+ return rc;
+}
+
+int
+mu_message_set_imapenvelope (mu_message_t msg,
+ int (*_imapenvelope) (mu_message_t,
+ struct mu_imapenvelope **),
+ void *owner)
+{
+ if (msg == NULL)
+ return EINVAL;
+ if (msg->owner != owner)
+ return EACCES;
+ msg->_imapenvelope = _imapenvelope;
+ return 0;
+}
diff --git a/libmailutils/string/wordsplit.c b/libmailutils/string/wordsplit.c
index 12af7257e..0acf2a345 100644
--- a/libmailutils/string/wordsplit.c
+++ b/libmailutils/string/wordsplit.c
@@ -184,7 +184,7 @@ alloc_space (struct mu_wordsplit *wsp, size_t count)
else if (wsp->ws_wordn < offs + wsp->ws_wordc + count)
{
newalloc = offs + wsp->ws_wordc +
- count > ALLOC_INCR ? count : ALLOC_INCR;
+ (count > ALLOC_INCR ? count : ALLOC_INCR);
ptr = realloc (wsp->ws_wordv, newalloc * sizeof (ptr[0]));
}
else
diff --git a/libproto/imap/fetch.c b/libproto/imap/fetch.c
index b1994ae48..e44804110 100644
--- a/libproto/imap/fetch.c
+++ b/libproto/imap/fetch.c
@@ -25,6 +25,9 @@
#include <mailutils/address.h>
#include <mailutils/cstr.h>
#include <mailutils/cctype.h>
+#include <mailutils/message.h>
+#include <mailutils/mime.h>
+#include <mailutils/assoc.h>
#include <mailutils/imap.h>
#include <mailutils/sys/imap.h>
@@ -67,19 +70,11 @@ _free_fetch_response (void *ptr)
break;
case MU_IMAP_FETCH_BODYSTRUCTURE:
- /* FIXME */
+ mu_bodystructure_free (resp->bodystructure.bs);
break;
case MU_IMAP_FETCH_ENVELOPE:
- free (resp->envelope.subject);
- mu_address_destroy (&resp->envelope.from);
- mu_address_destroy (&resp->envelope.sender);
- mu_address_destroy (&resp->envelope.reply_to);
- mu_address_destroy (&resp->envelope.to);
- mu_address_destroy (&resp->envelope.cc);
- mu_address_destroy (&resp->envelope.bcc);
- free (resp->envelope.in_reply_to);
- free (resp->envelope.message_id);
+ mu_message_imapenvelope_free (resp->envelope.imapenvelope);
break;
case MU_IMAP_FETCH_FLAGS:
@@ -228,8 +223,9 @@ _body_mapper (union mu_imap_fetch_response *resp,
partv = calloc (partc, sizeof (partv[0]));
for (i = 0, p = section; i < partc; i++)
{
- partv[i] = strtoul (p, &p, 10);
- p++;
+ char *q;
+ partv[i] = strtoul (p, &q, 10);
+ p = q + 1;
}
}
@@ -327,12 +323,438 @@ _date_mapper (union mu_imap_fetch_response *resp,
return 0;
}
-/* FIXME */
-#define _bodystructure_mapper NULL
+static int parse_bodystructure (struct imap_list_element *elt,
+ struct mu_bodystructure **pbs);
+
+struct body_field_map
+{
+ size_t offset; /* Offset of the target member of mu_bodystructure */
+ int (*mapper) (struct imap_list_element *, void *);
+};
+
+static int
+parse_bs_list (struct imap_list_element *elt,
+ struct mu_bodystructure *bs,
+ struct body_field_map *map)
+{
+ int rc;
+ mu_iterator_t itr;
+
+ rc = mu_list_get_iterator (elt->v.list, &itr);
+ if (rc)
+ return rc;
+ for (mu_iterator_first (itr);
+ map->mapper && !mu_iterator_is_done (itr);
+ mu_iterator_next (itr), map++)
+ {
+ struct imap_list_element *tok;
+ mu_iterator_current (itr, (void**)&tok);
+ rc = map->mapper (tok, (char*)bs + map->offset);
+ if (rc)
+ break;
+ }
+ mu_iterator_destroy (&itr);
+ return rc;
+}
+
+static int
+_map_body_param (void **itmv, size_t itmc, void *call_data)
+{
+ mu_assoc_t assoc = call_data;
+ struct mu_mime_param param;
+ struct imap_list_element *key, *val;
+ int rc;
+
+ if (itmc != 2)
+ return MU_ERR_PARSE;
+
+ key = itmv[0];
+ val = itmv[1];
+ if (key->type != imap_eltype_string || val->type != imap_eltype_string)
+ return MU_ERR_PARSE;
+
+ rc = mu_rfc2047_decode_param ("UTF-8", val->v.string, &param);
+ if (rc)
+ {
+ param.lang = param.cset = NULL;
+ param.value = strdup (val->v.string);
+ if (!param.value)
+ return ENOMEM;
+ }
+ return mu_assoc_install (assoc, key->v.string, &param);
+}
+
+static int
+_body_field_text_mapper (struct imap_list_element *tok, void *ptr)
+{
+ char *s;
+
+ if (_mu_imap_list_element_is_nil (tok))
+ s = NULL;
+ else if (tok->type != imap_eltype_string)
+ return MU_ERR_PARSE;
+ else if (!(s = strdup (tok->v.string)))
+ return ENOMEM;
+ *(char**) ptr = s;
+ return 0;
+}
+
+static int
+_body_field_size_mapper (struct imap_list_element *tok, void *ptr)
+{
+ unsigned long n;
+
+ if (_mu_imap_list_element_is_nil (tok))
+ n = 0;
+ else if (tok->type != imap_eltype_string)
+ return MU_ERR_PARSE;
+ else
+ {
+ char *s;
+
+ errno = 0;
+ n = strtoul (tok->v.string, &s, 10);
+ if (*s || errno)
+ return MU_ERR_PARSE;
+ }
+ *(size_t*) ptr = n;
+ return 0;
+}
+
+static int
+_body_field_param_mapper (struct imap_list_element *tok, void *ptr)
+{
+ mu_assoc_t param;
+ int rc = mu_mime_param_assoc_create (&param);
+ if (rc)
+ return rc;
+ *(mu_assoc_t*) ptr = param;
+ if (_mu_imap_list_element_is_nil (tok))
+ return 0;
+ if (tok->type != imap_eltype_list)
+ return MU_ERR_PARSE;
+ return mu_list_gmap (tok->v.list, _map_body_param, 2, param);
+}
+
+static int
+_body_field_disposition_mapper (struct imap_list_element *tok, void *ptr)
+{
+ int rc;
+ struct mu_bodystructure *bs = ptr;
+ struct imap_list_element *elt;
+
+ if (_mu_imap_list_element_is_nil (tok))
+ return 0;
+ if (tok->type != imap_eltype_list)
+ return MU_ERR_PARSE;
+ elt = _mu_imap_list_at (tok->v.list, 0);
+ if (_mu_imap_list_element_is_nil (elt))
+ bs->body_disposition = NULL;
+ else if (elt->type != imap_eltype_string)
+ return MU_ERR_PARSE;
+ else if ((bs->body_disposition = strdup (elt->v.string)) == NULL)
+ return ENOMEM;
+
+ rc = mu_mime_param_assoc_create (&bs->body_disp_param);
+ if (rc)
+ return rc;
+
+ elt = _mu_imap_list_at (tok->v.list, 1);
+ if (_mu_imap_list_element_is_nil (elt))
+ return 0;
+ else if (elt->type != imap_eltype_list)
+ return MU_ERR_PARSE;
+ return mu_list_gmap (elt->v.list, _map_body_param, 2, bs->body_disp_param);
+}
+
+static int parse_envelope (struct imap_list_element *elt,
+ struct mu_imapenvelope **penv);
+
+static int
+_body_field_imapenvelope_mapper (struct imap_list_element *tok, void *ptr)
+{
+ return parse_envelope (tok, ptr);
+}
+
+static int
+_body_field_bodystructure_mapper (struct imap_list_element *tok, void *ptr)
+{
+ return parse_bodystructure (tok, ptr);
+}
+
+/* Simple text or message/rfc822 body.
+
+ Sample TEXT body structure:
+
+ ("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")
+ "<960723163407.20117h@cac.washington.edu>" "Compiler diff"
+ "BASE64" 4554 73)
+
+ Elements:
+
+ 0 "TEXT" body_type
+ 1 "PLAIN" body_subtype
+ 2 (...) body_param
+ 3 "<9607...>" body_id
+ 4 "Compiler diff" body_descr
+ 5 "BASE64" body_encoding
+ 6 4554 body_size
+ 7 73 v.text.body_lines
+ [Optional]
+ 8 body_md5
+ 9 body_disposition;
+ 10 body_language;
+ 11 body_location;
+*/
+
+struct body_field_map base_field_map[] = {
+ { mu_offsetof (struct mu_bodystructure, body_type),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_subtype),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_param),
+ _body_field_param_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_id),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_descr),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_encoding),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_size),
+ _body_field_size_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_md5),
+ _body_field_text_mapper },
+ { 0, _body_field_disposition_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_language),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_location),
+ _body_field_text_mapper },
+ { 0, NULL }
+};
+
+struct body_field_map text_field_map[] = {
+ { mu_offsetof (struct mu_bodystructure, body_type),
+ _body_field_text_mapper },
+ { mu_offsetof (struct mu_bodystructure, body_subtype),
+ _bo