summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2020-08-07 08:38:21 +0300
committerSergey Poznyakoff <gray@gnu.org>2020-08-07 12:31:19 +0300
commitb3e20c0494abe67760c8bbde251e193d5980d170 (patch)
tree8814b460bb351d86d590e36ca02d20fdd335d21e
parent6b4df0a20f5a18a4be266fade0a4979a4decf23b (diff)
downloadmailutils-b3e20c0494abe67760c8bbde251e193d5980d170.tar.gz
mailutils-b3e20c0494abe67760c8bbde251e193d5980d170.tar.bz2
Bugfixes
* libmailutils/stream/temp_file_stream.c (mu_temp_file_stream_create): Fix return value. * decodemail/decodemail.c (message_decode): Split to two subfunctions to improve error recovery. * include/mailutils/sys/body.h: Fix typo.
-rw-r--r--decodemail/decodemail.c553
-rw-r--r--include/mailutils/sys/body.h2
-rw-r--r--libmailutils/stream/temp_file_stream.c2
3 files changed, 338 insertions, 219 deletions
diff --git a/decodemail/decodemail.c b/decodemail/decodemail.c
index e954eaec0..212b6fcd7 100644
--- a/decodemail/decodemail.c
+++ b/decodemail/decodemail.c
@@ -429,263 +429,382 @@ address_decode (char const *name, char const *value, char const *charset,
* It can modify the coordinate positions starting from dim+1 (inclusive).
*/
static mu_message_t
-message_decode (mu_message_t msg, mu_coord_t *crd, size_t dim)
+message_decode_nomime (mu_message_t msg)
{
mu_message_t newmsg;
- int ismime = 0;
int rc;
-
- set_log_prefix (*crd, dim);
+ mu_stream_t str;
+ mu_body_t body;
+ mu_stream_t bstr;
+ mu_header_t hdr, newhdr;
+ mu_iterator_t itr;
+ size_t i;
+ char *content_type = NULL;
+ mu_stream_stat_buffer stat;
+
+ rc = message_body_stream (msg, from_filter, charset, &str);
+ if (rc)
+ return NULL;
- mu_message_is_multipart (msg, &ismime);
- if (!ismime)
+ rc = mu_message_create (&newmsg, NULL);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_create", NULL, rc);
+ exit (EX_OSERR);
+ }
+
+ rc = mu_message_get_body (newmsg, &body);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_body", NULL, rc);
+ goto end;
+ }
+
+ rc = mu_body_get_streamref (body, &bstr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_body_get_streamref", NULL, rc);
+ goto end;
+ }
+
+ mu_stream_set_stat (bstr,
+ MU_STREAM_STAT_MASK (MU_STREAM_STAT_IN8BIT),
+ stat);
+ rc = mu_stream_copy (bstr, str, 0, NULL);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_copy", NULL, rc);
+ if (mu_stream_err (bstr))
+ {
+ exit (EX_IOERR);
+ }
+ else
+ {
+ mu_stream_printf (bstr,
+ "\n[decodemail: content decoding failed: %s]\n",
+ mu_strerror (rc));
+ }
+ }
+ mu_stream_unref (bstr);
+ mu_stream_unref (str);
+
+ rc = mu_message_get_header (msg, &hdr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", "msg", rc);
+ goto end;
+ }
+
+ rc = mu_message_get_header (newmsg, &newhdr);
+ if (rc)
{
- mu_stream_t str;
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", "newmsg", rc);
+ goto end;
+ }
- rc = message_body_stream (msg, from_filter, charset, &str);
+ rc = mu_header_get_iterator (hdr, &itr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_header_get_iterator", NULL, rc);
+ goto end;
+ }
+
+ for (mu_iterator_first (itr), i = 1; !mu_iterator_is_done (itr);
+ mu_iterator_next (itr), i++)
+ {
+ const char *name;
+ const char *value;
+ char *s;
+
+ rc = mu_iterator_current_kv (itr, (void const **) &name,
+ (void**)&value);
if (rc)
{
- mu_message_ref (msg);
- return msg;
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_iterator_current_kv", NULL, rc);
+ continue;
}
- else
+
+ if (!mu_c_strcasecmp (name, MU_HEADER_CONTENT_TYPE))
{
- mu_body_t body;
- mu_stream_t bstr;
- mu_header_t hdr, newhdr;
- mu_iterator_t itr;
- size_t i;
- char *content_type = NULL;
- mu_stream_stat_buffer stat;
-
- mu_message_create (&newmsg, NULL);
- mu_message_get_body (newmsg, &body);
- mu_body_get_streamref (body, &bstr);
- mu_stream_set_stat (bstr,
- MU_STREAM_STAT_MASK (MU_STREAM_STAT_IN8BIT),
- stat);
- rc = mu_stream_copy (bstr, str, 0, NULL);
- if (rc)
+ if (charset)
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_copy", NULL, rc);
- if (mu_stream_err (bstr))
+ mu_content_type_t ct;
+ struct mu_mime_param **pparam;
+ char *vc = mu_strdup (value);
+ size_t len;
+ mu_string_unfold (vc, &len);
+ rc = mu_content_type_parse_ext (vc, NULL,
+ MU_CONTENT_TYPE_RELAXED |
+ MU_CONTENT_TYPE_PARAM,
+ &ct);
+ if (rc)
{
- exit (EX_IOERR);
+ mu_diag_funcall (MU_DIAG_ERROR,
+ "mu_content_type_parse_ext",
+ vc, rc);
+ free (vc);
+ continue;
}
- else
+ free (vc);
+ rc = mu_assoc_install_ref (ct->param, "charset", &pparam);
+ switch (rc)
{
- mu_stream_printf (bstr,
- "\n[decodemail: content decoding failed: %s]\n",
- mu_strerror (rc));
- }
- }
- mu_stream_unref (bstr);
- mu_stream_unref (str);
+ case 0:
+ *pparam = mu_zalloc (sizeof **pparam);
+ break;
- mu_message_get_header (msg, &hdr);
- mu_message_get_header (newmsg, &newhdr);
- mu_header_get_iterator (hdr, &itr);
-
- for (mu_iterator_first (itr), i = 1; !mu_iterator_is_done (itr);
- mu_iterator_next (itr), i++)
- {
- const char *name;
- const char *value;
- char *s;
-
- rc = mu_iterator_current_kv (itr, (void const **) &name,
- (void**)&value);
+ case MU_ERR_EXISTS:
+ free ((*pparam)->value);
+ break;
- if (!mu_c_strcasecmp (name, MU_HEADER_CONTENT_TYPE))
- {
- if (charset)
- {
- mu_content_type_t ct;
- struct mu_mime_param **pparam;
- char *vc = mu_strdup (value);
- size_t len;
- mu_string_unfold (vc, &len);
- rc = mu_content_type_parse_ext (vc, NULL,
- MU_CONTENT_TYPE_RELAXED |
- MU_CONTENT_TYPE_PARAM,
- &ct);
- if (rc)
- {
- mu_diag_funcall (MU_DIAG_ERROR,
- "mu_content_type_parse_ext",
- vc, rc);
- free (vc);
- continue;
- }
- free (vc);
- rc = mu_assoc_install_ref (ct->param, "charset", &pparam);
- switch (rc)
- {
- case 0:
- *pparam = mu_zalloc (sizeof **pparam);
- break;
-
- case MU_ERR_EXISTS:
- free ((*pparam)->value);
- break;
-
- default:
- mu_diag_funcall (MU_DIAG_ERROR,
- "mu_assoc_install_ref",
- NULL, rc);
- exit (EX_IOERR);
- }
- (*pparam)->value = mu_strdup (charset);
- mu_content_type_format (ct, &content_type);
- mu_content_type_destroy (&ct);
- continue;
- }
- }
- else if (!mu_c_strcasecmp (name,
- MU_HEADER_CONTENT_TRANSFER_ENCODING))
- continue;
- else if (is_address_header (name))
- {
- if (address_decode (name, value, charset, newhdr))
- mu_header_append (newhdr, name, value);
- continue;
- }
-
- rc = mu_rfc2047_decode (charset, value, &s);
- if (rc == 0)
- {
- mu_header_append (newhdr, name, s);
- free (s);
+ default:
+ mu_diag_funcall (MU_DIAG_ERROR,
+ "mu_assoc_install_ref",
+ NULL, rc);
+ exit (EX_IOERR);
}
- else
- mu_header_append (newhdr, name, value);
- }
- mu_iterator_destroy (&itr);
-
- mu_header_set_value (newhdr,
- MU_HEADER_CONTENT_TRANSFER_ENCODING,
- stat[MU_STREAM_STAT_IN8BIT] ? "8bit" : "7bit",
- 1);
- if (charset)
- {
- if (!content_type)
- mu_asprintf (&content_type, "text/plain; charset=%s", charset);
- mu_header_set_value (newhdr,
- MU_HEADER_CONTENT_TYPE,
- content_type,
- 1);
- free (content_type);
+ (*pparam)->value = mu_strdup (charset);
+ mu_content_type_format (ct, &content_type);
+ mu_content_type_destroy (&ct);
+ continue;
}
}
- }
- else
- {
- size_t nparts, i;
- mu_mime_t mime;
- mu_header_t hdr, newhdr;
- mu_iterator_t itr;
- char *s;
- mu_content_type_t ct;
-
- /* FIXME: The following could be simplified if we could obtain
- a mime object from the message */
- mu_message_get_header (msg, &hdr);
- rc = mu_header_aget_value_unfold (hdr, MU_HEADER_CONTENT_TYPE, &s);
- if (rc)
+ else if (!mu_c_strcasecmp (name, MU_HEADER_CONTENT_TRANSFER_ENCODING))
+ continue;
+ else if (is_address_header (name))
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_header_aget_value_unfold",
- MU_HEADER_CONTENT_TYPE, rc);
- mu_message_ref (msg);
- return msg;
+ if (address_decode (name, value, charset, newhdr))
+ mu_header_append (newhdr, name, value);
+ continue;
}
- rc = mu_content_type_parse_ext (s, NULL,
- MU_CONTENT_TYPE_RELAXED |
- MU_CONTENT_TYPE_PARAM, &ct);
- if (rc)
+
+ rc = mu_rfc2047_decode (charset, value, &s);
+ if (rc == 0)
{
- mu_diag_funcall (MU_DIAG_ERROR, "mu_content_type_parse_ext", s, rc);
+ mu_header_append (newhdr, name, s);
free (s);
- mu_message_ref (msg);
- return msg;
}
- free (s);
+ else
+ mu_header_append (newhdr, name, value);
+ }
+ mu_iterator_destroy (&itr);
+ rc = 0;
+
+ mu_header_set_value (newhdr,
+ MU_HEADER_CONTENT_TRANSFER_ENCODING,
+ stat[MU_STREAM_STAT_IN8BIT] ? "8bit" : "7bit",
+ 1);
+ if (charset)
+ {
+ if (!content_type)
+ mu_asprintf (&content_type, "text/plain; charset=%s", charset);
+ mu_header_set_value (newhdr,
+ MU_HEADER_CONTENT_TYPE,
+ content_type,
+ 1);
+ free (content_type);
+ }
+ end:
+ if (rc)
+ {
+ mu_message_unref (newmsg);
+ newmsg = NULL;
+ }
+ return newmsg;
+}
- if (!ct->subtype)
- {
- mu_content_type_destroy (&ct);
- mu_message_ref (msg);
- return msg;
- }
+static mu_message_t
+message_decode_mime (mu_message_t msg, mu_coord_t *crd, size_t dim)
+{
+ int rc;
+ mu_message_t newmsg;
+ size_t nparts, i;
+ mu_mime_t mime;
+ mu_header_t hdr, newhdr;
+ mu_iterator_t itr;
+ char *s;
+ mu_content_type_t ct;
- mu_mime_create_multipart (&mime, ct->subtype, ct->param);
+ /* FIXME: The following could be simplified if we could obtain
+ a mime object from the message */
+ rc = mu_message_get_header (msg, &hdr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", "msg", rc);
+ return NULL;
+ }
+
+ rc = mu_header_aget_value_unfold (hdr, MU_HEADER_CONTENT_TYPE, &s);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_header_aget_value_unfold",
+ MU_HEADER_CONTENT_TYPE, rc);
+ return NULL;
+ }
+
+ rc = mu_content_type_parse_ext (s, NULL,
+ MU_CONTENT_TYPE_RELAXED |
+ MU_CONTENT_TYPE_PARAM, &ct);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_content_type_parse_ext", s, rc);
+ free (s);
+ return NULL;
+ }
+ free (s);
+
+ if (!ct->subtype)
+ {
mu_content_type_destroy (&ct);
- rc = mu_message_get_num_parts (msg, &nparts);
+ return NULL;
+ }
+
+ rc = mu_mime_create_multipart (&mime, ct->subtype, ct->param);
+ mu_content_type_destroy (&ct);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mime_create_multipart", NULL, rc);
+ return NULL;
+ }
+
+ rc = mu_message_get_num_parts (msg, &nparts);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_num_parts",
+ NULL, rc);
+ return NULL;
+ }
+
+ ++dim;
+ if (dim > mu_coord_length (*crd))
+ {
+ rc = mu_coord_realloc (crd, dim);
+ if (rc)
+ mu_alloc_die ();
+ }
+
+ for (i = 1; i <= nparts; i++)
+ {
+ mu_message_t msgpart, msgdec;
+
+ (*crd)[dim] = i;
+ rc = mu_message_get_part (msg, i, &msgpart);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_num_parts",
NULL, rc);
- mu_message_ref (msg);
- return msg;
- }
-
- ++dim;
- if (dim > mu_coord_length (*crd))
- {
- rc = mu_coord_realloc (crd, dim);
- if (rc)
- mu_alloc_die ();
+ mu_mime_unref (mime);
+ goto end;
}
-
- for (i = 1; i <= nparts; i++)
+ msgdec = message_decode (msgpart, crd, dim);
+ rc = mu_mime_add_part (mime, msgdec);
+ mu_message_unref (msgdec);
+ if (rc)
{
- mu_message_t msgpart, msgdec;
-
- (*crd)[dim] = i;
- mu_message_get_part (msg, i, &msgpart);
-
- msgdec = message_decode (msgpart, crd, dim);
- mu_mime_add_part (mime, msgdec);
- mu_message_unref (msgdec);
- }
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mime_add_part", NULL, rc);
+ mu_mime_unref (mime);
+ goto end;
+ }
+ }
- --dim;
+ --dim;
- mu_mime_to_message (mime, &newmsg);
- mu_mime_unref (mime);
+ rc = mu_mime_to_message (mime, &newmsg);
+ mu_mime_unref (mime);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_mime_to_message", NULL, rc);
+ return NULL;
+ }
- /* Copy headers */
- mu_message_get_header (newmsg, &newhdr);
- mu_header_get_iterator (hdr, &itr);
-
- for (mu_iterator_first (itr), i = 1; !mu_iterator_is_done (itr);
- mu_iterator_next (itr), i++)
- {
- const char *name;
- const char *value;
- char *s;
+ /* Copy headers */
+ rc = mu_message_get_header (newmsg, &newhdr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_get_header", "newmsg", rc);
+ goto end;
+ }
+
+ rc = mu_header_get_iterator (hdr, &itr);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_header_get_iterator", NULL, rc);
+ goto end;
+ }
- rc = mu_iterator_current_kv (itr, (void const **) &name,
- (void**)&value);
+ for (mu_iterator_first (itr), i = 1; !mu_iterator_is_done (itr);
+ mu_iterator_next (itr), i++)
+ {
+ const char *name;
+ const char *value;
+ char *s;
+
+ rc = mu_iterator_current_kv (itr, (void const **) &name,
+ (void**)&value);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_iterator_current_kv", NULL, rc);
+ continue;
+ }
- if (mu_c_strcasecmp (name, MU_HEADER_MIME_VERSION) == 0 ||
- mu_c_strcasecmp (name, MU_HEADER_CONTENT_TYPE) == 0)
- continue;
- else if (is_address_header (name))
- {
- if (address_decode (name, value, charset, newhdr))
- mu_header_append (newhdr, name, value);
- continue;
- }
- rc = mu_rfc2047_decode (charset, value, &s);
- if (rc == 0)
- {
- mu_header_append (newhdr, name, s);
- free (s);
- }
- else
+ if (mu_c_strcasecmp (name, MU_HEADER_MIME_VERSION) == 0 ||
+ mu_c_strcasecmp (name, MU_HEADER_CONTENT_TYPE) == 0)
+ continue;
+ else if (is_address_header (name))
+ {
+ if (address_decode (name, value, charset, newhdr))
mu_header_append (newhdr, name, value);
+ continue;
}
- mu_iterator_destroy (&itr);
+ rc = mu_rfc2047_decode (charset, value, &s);
+ if (rc == 0)
+ {
+ mu_header_append (newhdr, name, s);
+ free (s);
+ }
+ else
+ mu_header_append (newhdr, name, value);
+ }
+ mu_iterator_destroy (&itr);
+ rc = 0;
+
+ end:
+ if (rc)
+ {
+ mu_message_unref (newmsg);
+ newmsg = NULL;
+ }
+ return newmsg;
+}
+
+static mu_message_t
+message_decode (mu_message_t msg, mu_coord_t *crd, size_t dim)
+{
+ mu_message_t newmsg;
+ int ismime = 0;
+ int rc;
+
+ set_log_prefix (*crd, dim);
+
+ rc = mu_message_is_multipart (msg, &ismime);
+ if (rc)
+ {
+ mu_diag_funcall (MU_DIAG_ERROR, "mu_message_is_multipart", NULL, rc);
+ newmsg = NULL;
+ }
+ else if (!ismime)
+ {
+ newmsg = message_decode_nomime (msg);
+ }
+ else
+ {
+ newmsg = message_decode_mime (msg, crd, dim);
+ }
+
+ if (!newmsg)
+ {
+ mu_message_ref (msg);
+ return msg;
}
set_log_prefix (*crd, dim);
diff --git a/include/mailutils/sys/body.h b/include/mailutils/sys/body.h
index 8cd67d9ac..a03e84483 100644
--- a/include/mailutils/sys/body.h
+++ b/include/mailutils/sys/body.h
@@ -33,7 +33,7 @@ struct _mu_body
int ref_count; /* Reference counter */
void *owner; /* Owner object pointer */
mu_stream_t data_stream; /* Body content stream */
- mu_stream_t temp_stream; /* RW temporary stream (for writing ro the body) */
+ mu_stream_t temp_stream; /* RW temporary stream (for writing to the body) */
int flags;
int (*_size) (mu_body_t, size_t*);
diff --git a/libmailutils/stream/temp_file_stream.c b/libmailutils/stream/temp_file_stream.c
index d86ef087b..fd1cbab63 100644
--- a/libmailutils/stream/temp_file_stream.c
+++ b/libmailutils/stream/temp_file_stream.c
@@ -100,5 +100,5 @@ mu_temp_file_stream_create (mu_stream_t *pstream,
*pstream = stream;
}
}
- return 0;
+ return rc;
}

Return to:

Send suggestions and report system problems to the System administrator.