aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog12
-rw-r--r--camel/providers/imap/camel-imap-utils.c335
2 files changed, 225 insertions, 122 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 02984b4d3b..b089b22def 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,5 +1,17 @@
2003-04-08 Jeffrey Stedfast <fejj@ximian.com>
+ Fixes for bug #40778. Probably others as well.
+
+ * providers/imap/camel-imap-utils.c (parse_params): Return 0 on
+ success, or -1 on fail. The other small utility functions should
+ probably do the same, but I was too lazy to fix them. Setting
+ inptr to NULL is just lame.
+ (imap_body_decode): New function to correctly parse a BODY
+ response.
+ (imap_parse_body): Rewritten to use the above function.
+
+2003-04-08 Jeffrey Stedfast <fejj@ximian.com>
+
* providers/smtp/camel-smtp-transport.c (smtp_helo): Make sure
host->h_name is not an empty string too? Apparently for one user
his resolved hostname is "". Go figure. Probably a broken system,
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index 8a089da7bf..6ca3b5d84a 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -728,7 +728,7 @@ imap_skip_list (const char **str_p)
skip_char (str_p, ')');
}
-static void
+static int
parse_params (const char **parms_p, CamelContentType *type)
{
const char *parms = *parms_p;
@@ -737,13 +737,11 @@ parse_params (const char **parms_p, CamelContentType *type)
if (!strncasecmp (parms, "nil", 3)) {
*parms_p += 3;
- return;
+ return 0;
}
- if (*parms++ != '(') {
- *parms_p = NULL;
- return;
- }
+ if (*parms++ != '(')
+ return -1;
while (parms && *parms != ')') {
name = imap_parse_nstring (&parms, &len);
@@ -759,157 +757,250 @@ parse_params (const char **parms_p, CamelContentType *type)
parms++;
}
- if (!parms || *parms++ != ')') {
- *parms_p = NULL;
- return;
- }
+ if (!parms || *parms++ != ')')
+ return -1;
+
*parms_p = parms;
+
+ return 0;
}
-/**
- * imap_parse_body:
- * @body_p: pointer to the start of an IMAP "body"
- * @folder: an imap folder
- * @ci: a CamelMessageContentInfo to fill in
- *
- * This fills in @ci with data from *@body_p. On success *@body_p
- * will point to the character after the body. On failure, it will be
- * set to %NULL and @ci will be unchanged.
- **/
-void
-imap_parse_body (const char **body_p, CamelFolder *folder,
- CamelMessageContentInfo *ci)
+
+static CamelMessageContentInfo *
+imap_body_decode (const char **in, CamelMessageContentInfo *ci, CamelFolder *folder, GPtrArray *cis)
{
- const char *body = *body_p;
- CamelMessageContentInfo *child;
- CamelContentType *type;
- size_t len;
+ const char *inptr = *in;
+ CamelMessageContentInfo *child = NULL;
+ char *type, *subtype, *id = NULL;
+ CamelContentType *ctype = NULL;
+ char *description = NULL;
+ char *encoding = NULL;
+ unsigned int len;
+ char *p;
+
+ if (*inptr++ != '(')
+ return NULL;
- if (!body || *body++ != '(') {
- *body_p = NULL;
- return;
+ if (ci == NULL) {
+ ci = camel_folder_summary_content_info_new (folder->summary);
+ g_ptr_array_add (cis, ci);
}
- if (*body == '(') {
- /* multipart */
- GPtrArray *children;
- char *subtype;
- int i;
+ if (*inptr == '(') {
+ /* body_type_mpart */
+ CamelMessageContentInfo *tail, *children = NULL;
- /* Parse the child body parts */
- children = g_ptr_array_new ();
- while (body && *body == '(') {
- child = camel_folder_summary_content_info_new (folder->summary);
- g_ptr_array_add (children, child);
- imap_parse_body (&body, folder, child);
- if (!body)
- break;
+ tail = (CamelMessageContentInfo *) &children;
+
+ do {
+ if (!(child = imap_body_decode (&inptr, NULL, folder, cis)))
+ return NULL;
+
child->parent = ci;
- }
- skip_char (&body, ' ');
+ tail->next = child;
+ tail = child;
+ } while (*inptr == '(');
- /* Parse the multipart subtype */
- subtype = imap_parse_string (&body, &len);
+ if (*inptr++ != ' ')
+ return NULL;
- /* If there is a parse error, abort. */
- if (!body) {
- for (i = 0; i < children->len; i++) {
- child = children->pdata[i];
- camel_folder_summary_content_info_free (folder->summary, child);
- }
- g_ptr_array_free (children, TRUE);
- *body_p = NULL;
- return;
+ if (!strncasecmp (inptr, "nil", 3) != 0) {
+ subtype = imap_parse_string (&inptr, &len);
+ } else {
+ subtype = NULL;
+ inptr += 3;
}
- camel_strdown (subtype);
- ci->type = header_content_type_new ("multipart", subtype);
+ ctype = header_content_type_new ("multipart", subtype ? subtype : "mixed");
g_free (subtype);
- /* Chain the children. */
- ci->childs = children->pdata[0];
- ci->size = 0;
- for (i = 0; i < children->len - 1; i++) {
- child = children->pdata[i];
- child->next = children->pdata[i + 1];
- ci->size += child->size;
+ if (*inptr++ != ')') {
+ header_content_type_unref (ctype);
+ return NULL;
}
- g_ptr_array_free (children, TRUE);
+
+ ci->type = ctype;
+ ci->childs = children;
} else {
- /* single part */
- char *main_type, *subtype;
- char *id, *description, *encoding;
- guint32 size = 0;
+ /* body_type_1part */
+ if (strncasecmp (inptr, "nil", 3) != 0) {
+ type = imap_parse_string (&inptr, &len);
+ if (inptr == NULL)
+ return NULL;
+ } else {
+ return NULL;
+ }
- main_type = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- subtype = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- if (!body) {
- g_free (main_type);
- g_free (subtype);
- *body_p = NULL;
- return;
+ if (*inptr++ != ' ') {
+ g_free (type);
+ return NULL;
+ }
+
+ if (strncasecmp (inptr, "nil", 3) != 0) {
+ subtype = imap_parse_string (&inptr, &len);
+ if (inptr == NULL) {
+ g_free (type);
+ return NULL;
+ }
+ } else {
+ if (!strcasecmp (type, "text"))
+ subtype = g_strdup ("plain");
+ else
+ subtype = NULL;
+ inptr += 3;
}
- camel_strdown (main_type);
+ camel_strdown (type);
camel_strdown (subtype);
- type = header_content_type_new (main_type, subtype);
- g_free (main_type);
+ ctype = header_content_type_new (type, subtype);
g_free (subtype);
- parse_params (&body, type);
- skip_char (&body, ' ');
+ g_free (type);
- id = imap_parse_nstring (&body, &len);
- skip_char (&body, ' ');
- description = imap_parse_nstring (&body, &len);
- skip_char (&body, ' ');
- encoding = imap_parse_string (&body, &len);
- skip_char (&body, ' ');
- if (body)
- size = strtoul (body, (char **) &body, 10);
+ if (*inptr++ != ' ')
+ goto exception;
- child = NULL;
- if (header_content_type_is (type, "message", "rfc822")) {
- skip_char (&body, ' ');
- imap_skip_list (&body); /* envelope */
- skip_char (&body, ' ');
- child = camel_folder_summary_content_info_new (folder->summary);
- imap_parse_body (&body, folder, child);
- if (!body)
- camel_folder_summary_content_info_free (folder->summary, child);
- skip_char (&body, ' ');
- if (body)
- strtoul (body, (char **) &body, 10);
- child->parent = ci;
- } else if (header_content_type_is (type, "text", "*")) {
- if (body)
- strtoul (body, (char **) &body, 10);
- }
+ /* content-type params */
+ if (parse_params (&inptr, ctype) == -1)
+ goto exception;
- if (body) {
- ci->type = type;
- ci->id = id;
- ci->description = description;
- ci->encoding = encoding;
- ci->size = size;
- ci->childs = child;
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* content-id */
+ if (strncasecmp (inptr, "nil", 3) != 0) {
+ id = imap_parse_string (&inptr, &len);
+ if (inptr == NULL)
+ goto exception;
+ } else
+ inptr += 3;
+
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* description */
+ if (strncasecmp (inptr, "nil", 3) != 0) {
+ description = imap_parse_string (&inptr, &len);
+ if (inptr == NULL)
+ goto exception;
+ } else
+ inptr += 3;
+
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* encoding */
+ if (strncasecmp (inptr, "nil", 3) != 0) {
+ encoding = imap_parse_string (&inptr, &len);
+ if (inptr == NULL)
+ goto exception;
+ } else
+ inptr += 3;
+
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* size */
+ ci->size = strtoul ((const char *) inptr, &p, 10);
+ inptr = (const unsigned char *) p;
+
+ if (header_content_type_is (ctype, "message", "rfc822")) {
+ /* body_type_msg */
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* envelope */
+ imap_skip_list (&inptr);
+
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* body */
+ if (!(child = imap_body_decode (&inptr, NULL, folder, cis)))
+ goto exception;
+ child->parent = ci;
+
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* lines */
+ strtoul ((const char *) inptr, &p, 10);
+ inptr = (const unsigned char *) p;
+ } else if (header_content_type_is (ctype, "text", "*")) {
+ if (*inptr++ != ' ')
+ goto exception;
+
+ /* lines */
+ strtoul ((const char *) inptr, &p, 10);
+ inptr = (const unsigned char *) p;
} else {
- header_content_type_unref (type);
- g_free (id);
- g_free (description);
- g_free (encoding);
+ /* body_type_basic */
}
+
+ if (*inptr++ != ')')
+ goto exception;
+
+ ci->type = ctype;
+ ci->id = id;
+ ci->description = description;
+ ci->encoding = encoding;
+ ci->childs = child;
}
- if (!body || *body++ != ')') {
+ *in = inptr;
+
+ return ci;
+
+ exception:
+
+ header_content_type_unref (ctype);
+ g_free (id);
+ g_free (description);
+ g_free (encoding);
+
+ return NULL;
+}
+
+
+/**
+ * imap_parse_body:
+ * @body_p: pointer to the start of an IMAP "body"
+ * @folder: an imap folder
+ * @ci: a CamelMessageContentInfo to fill in
+ *
+ * This fills in @ci with data from *@body_p. On success *@body_p
+ * will point to the character after the body. On failure, it will be
+ * set to %NULL and @ci will be unchanged.
+ **/
+void
+imap_parse_body (const char **body_p, CamelFolder *folder,
+ CamelMessageContentInfo *ci)
+{
+ const char *inptr = *body_p;
+ CamelMessageContentInfo *child;
+ GPtrArray *children;
+ int i;
+
+ if (!inptr || *inptr != '(') {
*body_p = NULL;
return;
}
- *body_p = body;
+ children = g_ptr_array_new ();
+
+ if (!(imap_body_decode (&inptr, ci, folder, children))) {
+ for (i = 0; i < children->len; i++) {
+ child = children->pdata[i];
+ camel_folder_summary_content_info_free (folder->summary, child);
+ }
+ *body_p = NULL;
+ } else {
+ *body_p = inptr;
+ }
+
+ g_ptr_array_free (children, TRUE);
}
+
/**
* imap_quote_string:
* @str: the string to quote, which must not contain CR or LF