From 552a2f3af8e8af5cf03e994a060bc46e374f1252 Mon Sep 17 00:00:00 2001 From: Jeffrey Stedfast Date: Wed, 9 Apr 2003 00:09:24 +0000 Subject: Fixes for bug #40778. Probably others as well. 2003-04-08 Jeffrey Stedfast 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. svn path=/trunk/; revision=20773 --- camel/ChangeLog | 12 ++ camel/providers/imap/camel-imap-utils.c | 335 ++++++++++++++++++++------------ 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,3 +1,15 @@ +2003-04-08 Jeffrey Stedfast + + 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 * providers/smtp/camel-smtp-transport.c (smtp_helo): Make sure 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 -- cgit v1.2.3