[gmime] Fixed GMimeParser to handle header names with trailing whitespace
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Fixed GMimeParser to handle header names with trailing whitespace
- Date: Mon, 20 Mar 2017 02:16:47 +0000 (UTC)
commit 7ee0d4263fe54b9c500271cf507a7a898836573a
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Sun Mar 19 22:15:59 2017 -0400
Fixed GMimeParser to handle header names with trailing whitespace
TODO | 2 -
gmime/gmime-header.c | 53 +++++++++++++++++++++++++++++-----------
gmime/gmime-internal.h | 19 ++++++++++----
gmime/gmime-message-partial.c | 5 ++-
gmime/gmime-object.c | 15 +++++++----
gmime/gmime-parser.c | 49 +++++++++++++++++++++++++++-----------
6 files changed, 98 insertions(+), 45 deletions(-)
---
diff --git a/TODO b/TODO
index f9e8922..87537d3 100644
--- a/TODO
+++ b/TODO
@@ -15,8 +15,6 @@ GMime 3.0 Planning:
- Should GMimeHeader->value be decoded by GMime? i.e. work a bit more like
MimeKit.
-- Fix GMimeParser to handle lwsp between header field anme and ':'
-
- Fix GMimeParser to save mbox From markers on the GMimeMessage so
that GMimeMessagePart::write_to_stream() can use it.
diff --git a/gmime/gmime-header.c b/gmime/gmime-header.c
index 3e40917..6c13905 100644
--- a/gmime/gmime-header.c
+++ b/gmime/gmime-header.c
@@ -127,12 +127,13 @@ g_mime_header_finalize (GObject *object)
* Returns: a new #GMimeHeader with the specified values.
**/
static GMimeHeader *
-g_mime_header_new (const char *name, const char *value, const char *raw_value, gint64 offset)
+g_mime_header_new (const char *name, const char *value, const char *raw_name, const char *raw_value, gint64
offset)
{
GMimeHeader *header;
header = g_object_newv (GMIME_TYPE_HEADER, 0, NULL);
header->raw_value = raw_value ? g_strdup (raw_value) : NULL;
+ header->raw_name = g_strdup (raw_name);
header->value = g_strdup (value);
header->name = g_strdup (name);
header->offset = offset;
@@ -205,6 +206,23 @@ g_mime_header_set_value (GMimeHeader *header, const char *value)
/**
+ * g_mime_header_get_raw_name:
+ * @header: a #GMimeHeader
+ *
+ * Gets the header's raw name.
+ *
+ * Returns: the header name.
+ **/
+const char *
+_g_mime_header_get_raw_name (GMimeHeader *header)
+{
+ //g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
+
+ return header->raw_name;
+}
+
+
+/**
* g_mime_header_get_raw_value:
* @header: a #GMimeHeader
*
@@ -215,7 +233,7 @@ g_mime_header_set_value (GMimeHeader *header, const char *value)
const char *
_g_mime_header_get_raw_value (GMimeHeader *header)
{
- g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
+ //g_return_val_if_fail (GMIME_IS_HEADER (header), NULL);
return header->raw_value;
}
@@ -231,11 +249,10 @@ _g_mime_header_get_raw_value (GMimeHeader *header)
void
_g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value)
{
- g_return_if_fail (GMIME_IS_HEADER (header));
- g_return_if_fail (raw_value != NULL);
+ //g_return_if_fail (GMIME_IS_HEADER (header));
+ //g_return_if_fail (raw_value != NULL);
g_free (header->raw_value);
-
header->raw_value = g_strdup (raw_value);
}
@@ -302,7 +319,7 @@ g_mime_header_write_to_stream (GMimeHeaderList *headers, GMimeHeader *header,
g_return_val_if_fail (GMIME_IS_STREAM (stream), -1);
if (header->raw_value) {
- val = g_strdup_printf ("%s:%s", header->name, header->raw_value);
+ val = g_strdup_printf ("%s:%s", header->raw_name, header->raw_value);
nwritten = g_mime_stream_write_string (stream, val);
g_free (val);
@@ -525,14 +542,15 @@ g_mime_header_list_contains (GMimeHeaderList *headers, const char *name)
void
-_g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
GMimeHeaderListChangedEventArgs args;
unsigned char *dest, *src;
GMimeHeader *header;
guint n;
- header = g_mime_header_new (name, value, raw_value, offset);
+ header = g_mime_header_new (name, value, raw_name, raw_value, offset);
g_mime_event_add (header->changed, (GMimeEventCallback) header_changed, headers);
g_hash_table_replace (headers->hash, header->name, header);
@@ -575,17 +593,18 @@ g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const ch
g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
g_return_if_fail (name != NULL);
- _g_mime_header_list_prepend (headers, name, value, NULL, -1);
+ _g_mime_header_list_prepend (headers, name, value, name, NULL, -1);
}
void
-_g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
GMimeHeaderListChangedEventArgs args;
GMimeHeader *header;
- header = g_mime_header_new (name, value, raw_value, offset);
+ header = g_mime_header_new (name, value, raw_name, raw_value, offset);
g_mime_event_add (header->changed, (GMimeEventCallback) header_changed, headers);
g_ptr_array_add (headers->array, header);
@@ -618,7 +637,7 @@ g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const cha
g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
g_return_if_fail (name != NULL);
- _g_mime_header_list_append (headers, name, value, NULL, -1);
+ _g_mime_header_list_append (headers, name, value, name, NULL, -1);
}
@@ -644,7 +663,8 @@ g_mime_header_list_get_header (GMimeHeaderList *headers, const char *name)
void
-_g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
GMimeHeaderListChangedEventArgs args;
GMimeHeader *header, *hdr;
@@ -654,6 +674,9 @@ _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char
g_free (header->raw_value);
header->raw_value = raw_value ? g_strdup (raw_value) : NULL;
+ g_free (header->raw_name);
+ header->raw_name = g_strdup (raw_name);
+
g_free (header->value);
header->value = g_strdup (value);
@@ -678,7 +701,7 @@ _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char
g_mime_event_emit (headers->changed, &args);
} else {
- _g_mime_header_list_append (headers, name, value, raw_value, offset);
+ _g_mime_header_list_append (headers, name, value, raw_name, raw_value, offset);
}
}
@@ -707,7 +730,7 @@ g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *
g_return_if_fail (GMIME_IS_HEADER_LIST (headers));
g_return_if_fail (name != NULL);
- _g_mime_header_list_set (headers, name, value, NULL, -1);
+ _g_mime_header_list_set (headers, name, value, name, NULL, -1);
}
diff --git a/gmime/gmime-internal.h b/gmime/gmime-internal.h
index f5a5afe..67f7a19 100644
--- a/gmime/gmime-internal.h
+++ b/gmime/gmime-internal.h
@@ -53,6 +53,7 @@ G_GNUC_INTERNAL void g_mime_parser_options_shutdown (void);
G_GNUC_INTERNAL GMimeParserOptions *_g_mime_parser_options_clone (GMimeParserOptions *options);
/* GMimeHeader */
+G_GNUC_INTERNAL const char *_g_mime_header_get_raw_name (GMimeHeader *header);
G_GNUC_INTERNAL const char *_g_mime_header_get_raw_value (GMimeHeader *header);
G_GNUC_INTERNAL void _g_mime_header_set_raw_value (GMimeHeader *header, const char *raw_value);
G_GNUC_INTERNAL void _g_mime_header_set_offset (GMimeHeader *header, gint64 offset);
@@ -60,17 +61,23 @@ G_GNUC_INTERNAL void _g_mime_header_set_offset (GMimeHeader *header, gint64 offs
/* GMimeHeaderList */
G_GNUC_INTERNAL GMimeParserOptions *_g_mime_header_list_get_options (GMimeHeaderList *headers);
G_GNUC_INTERNAL void _g_mime_header_list_set_options (GMimeHeaderList *headers, GMimeParserOptions *options);
-G_GNUC_INTERNAL void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char
*value, const char *raw_value, gint64 offset);
-G_GNUC_INTERNAL void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char
*value, const char *raw_value, gint64 offset);
-G_GNUC_INTERNAL void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value,
const char *raw_value, gint64 offset);
+G_GNUC_INTERNAL void _g_mime_header_list_prepend (GMimeHeaderList *headers, const char *name, const char
*value,
+ const char *raw_name, const char *raw_value, gint64 offset);
+G_GNUC_INTERNAL void _g_mime_header_list_append (GMimeHeaderList *headers, const char *name, const char
*value,
+ const char *raw_name, const char *raw_value, gint64 offset);
+G_GNUC_INTERNAL void _g_mime_header_list_set (GMimeHeaderList *headers, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset);
/* GMimeObject */
G_GNUC_INTERNAL void _g_mime_object_block_header_list_changed (GMimeObject *object);
G_GNUC_INTERNAL void _g_mime_object_unblock_header_list_changed (GMimeObject *object);
G_GNUC_INTERNAL void _g_mime_object_set_content_type (GMimeObject *object, GMimeContentType *content_type);
-G_GNUC_INTERNAL void _g_mime_object_prepend_header (GMimeObject *object, const char *header, const char
*value, const char *raw_value, gint64 offset);
-G_GNUC_INTERNAL void _g_mime_object_append_header (GMimeObject *object, const char *header, const char
*value, const char *raw_value, gint64 offset);
-G_GNUC_INTERNAL void _g_mime_object_set_header (GMimeObject *object, const char *header, const char *value,
const char *raw_value, gint64 offset);
+G_GNUC_INTERNAL void _g_mime_object_prepend_header (GMimeObject *object, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64
offset);
+G_GNUC_INTERNAL void _g_mime_object_append_header (GMimeObject *object, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64
offset);
+G_GNUC_INTERNAL void _g_mime_object_set_header (GMimeObject *object, const char *name, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset);
/* utils */
G_GNUC_INTERNAL char *_g_mime_utils_unstructured_header_fold (GMimeParserOptions *options,
GMimeFormatOptions *format,
diff --git a/gmime/gmime-message-partial.c b/gmime/gmime-message-partial.c
index 14e31de..703a971 100644
--- a/gmime/gmime-message-partial.c
+++ b/gmime/gmime-message-partial.c
@@ -321,7 +321,7 @@ g_mime_message_partial_reconstruct_message (GMimeMessagePartial **partials, size
static GMimeMessage *
message_partial_message_new (GMimeMessage *base)
{
- const char *name, *value, *raw_value;
+ const char *name, *value, *raw_name, *raw_value;
GMimeHeaderList *headers;
GMimeMessage *message;
GMimeHeader *header;
@@ -337,11 +337,12 @@ message_partial_message_new (GMimeMessage *base)
for (i = 0; i < count; i++) {
header = g_mime_header_list_get_header_at (headers, i);
raw_value = _g_mime_header_get_raw_value (header);
+ raw_name = _g_mime_header_get_raw_name (header);
offset = g_mime_header_get_offset (header);
value = g_mime_header_get_value (header);
name = g_mime_header_get_name (header);
- _g_mime_object_append_header ((GMimeObject *) message, name, value, raw_value, offset);
+ _g_mime_object_append_header ((GMimeObject *) message, name, value, raw_name, raw_value,
offset);
}
return message;
diff --git a/gmime/gmime-object.c b/gmime/gmime-object.c
index d119f8a..5e94da1 100644
--- a/gmime/gmime-object.c
+++ b/gmime/gmime-object.c
@@ -925,9 +925,10 @@ g_mime_object_get_content_id (GMimeObject *object)
void
-_g_mime_object_prepend_header (GMimeObject *object, const char *header, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_object_prepend_header (GMimeObject *object, const char *header, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
- _g_mime_header_list_prepend (object->headers, header, value, raw_value, offset);
+ _g_mime_header_list_prepend (object->headers, header, value, raw_name, raw_value, offset);
}
@@ -952,9 +953,10 @@ g_mime_object_prepend_header (GMimeObject *object, const char *header, const cha
void
-_g_mime_object_append_header (GMimeObject *object, const char *header, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_object_append_header (GMimeObject *object, const char *header, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
- _g_mime_header_list_append (object->headers, header, value, raw_value, offset);
+ _g_mime_header_list_append (object->headers, header, value, raw_name, raw_value, offset);
}
@@ -979,9 +981,10 @@ g_mime_object_append_header (GMimeObject *object, const char *header, const char
void
-_g_mime_object_set_header (GMimeObject *object, const char *header, const char *value, const char
*raw_value, gint64 offset)
+_g_mime_object_set_header (GMimeObject *object, const char *header, const char *value,
+ const char *raw_name, const char *raw_value, gint64 offset)
{
- _g_mime_header_list_set (object->headers, header, value, raw_value, offset);
+ _g_mime_header_list_set (object->headers, header, value, raw_name, raw_value, offset);
}
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 3da3018..9e4513e 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -103,7 +103,8 @@ typedef struct _boundary_stack {
typedef struct _header_raw {
struct _header_raw *next;
- char *name, *value, *raw_value;
+ char *raw_name, *raw_value;
+ char *name, *value;
gint64 offset;
} HeaderRaw;
@@ -289,7 +290,8 @@ header_raw_clear (HeaderRaw **headers)
next = header->next;
g_free (header->name);
g_free (header->value);
-
+ g_free (header->raw_name);
+ g_free (header->raw_value);
g_slice_free (HeaderRaw, header);
header = next;
@@ -914,10 +916,11 @@ header_parse (GMimeParser *parser, HeaderRaw **tail)
register char *inptr;
HeaderRaw *header;
- *priv->headerptr = '\0';
+ *priv->headerptr = ':';
inptr = priv->headerbuf;
- while (*inptr && *inptr != ':' && !is_type (*inptr, IS_SPACE | IS_CTRL))
+ while (*inptr != ':')
inptr++;
+ *priv->headerptr = '\0';
if (*inptr != ':') {
/* ignore invalid headers */
@@ -937,14 +940,21 @@ header_parse (GMimeParser *parser, HeaderRaw **tail)
header = g_slice_new (HeaderRaw);
header->next = NULL;
- header->name = g_strndup (priv->headerbuf, (size_t) (inptr - priv->headerbuf));
header->value = g_mime_strdup_trim (inptr + 1);
- *priv->rawptr = '\0';
+ /* now walk backwards over lwsp characters */
+ while (inptr > priv->headerbuf && is_blank (inptr[-1]))
+ inptr--;
+
+ header->name = g_strndup (priv->headerbuf, (size_t) (inptr - priv->headerbuf));
+
+ *priv->rawptr = ':';
inptr = priv->rawbuf;
while (*inptr != ':')
inptr++;
+ *priv->rawptr = '\0';
+ header->raw_name = g_strndup (priv->rawbuf, (size_t) (inptr - priv->rawbuf));
header->raw_value = g_strdup (inptr + 1);
header->offset = priv->header_offset;
@@ -1017,6 +1027,7 @@ parser_step_headers (GMimeParser *parser)
struct _GMimeParserPrivate *priv = parser->priv;
gboolean eoln, valid = TRUE, fieldname = TRUE;
gboolean continuation = FALSE;
+ gboolean blank = FALSE;
register char *inptr;
char *start, *inend;
ssize_t left = 0;
@@ -1053,6 +1064,7 @@ parser_step_headers (GMimeParser *parser)
priv->header_offset = parser_offset (priv, inptr);
continuation = FALSE;
fieldname = TRUE;
+ blank = FALSE;
valid = TRUE;
}
@@ -1064,7 +1076,12 @@ parser_step_headers (GMimeParser *parser)
*inend = ':';
while (*inptr != ':') {
- if (is_type (*inptr, IS_SPACE | IS_CTRL)) {
+ /* Note: blank spaces are allowed between the field name
+ * and the ':', but field names themselves are not allowed
+ * to contain spaces. */
+ if (is_blank (*inptr)) {
+ blank = TRUE;
+ } else if (blank || is_ctrl (*inptr)) {
valid = FALSE;
break;
}
@@ -1696,9 +1713,8 @@ parser_scan_message_part (GMimeParser *parser, GMimeParserOptions *options, GMim
header = priv->headers;
while (header) {
if (g_ascii_strncasecmp (header->name, "Content-", 8) != 0) {
- _g_mime_object_append_header ((GMimeObject *) message, header->name,
- header->value, header->raw_value,
- header->offset);
+ _g_mime_object_append_header ((GMimeObject *) message, header->name, header->value,
+ header->raw_name, header->raw_value, header->offset);
}
header = header->next;
@@ -1740,7 +1756,8 @@ parser_construct_leaf_part (GMimeParser *parser, GMimeParserOptions *options, Co
while (header) {
if (!toplevel || !g_ascii_strncasecmp (header->name, "Content-", 8)) {
_g_mime_object_append_header (object, header->name, header->value,
- header->raw_value, header->offset);
+ header->raw_name, header->raw_value,
+ header->offset);
}
header = header->next;
@@ -1883,7 +1900,8 @@ parser_construct_multipart (GMimeParser *parser, GMimeParserOptions *options, Co
while (header) {
if (!toplevel || !g_ascii_strncasecmp (header->name, "Content-", 8)) {
_g_mime_object_append_header (object, header->name, header->value,
- header->raw_value, header->offset);
+ header->raw_name, header->raw_value,
+ header->offset);
}
header = header->next;
@@ -2015,8 +2033,11 @@ parser_construct_message (GMimeParser *parser, GMimeParserOptions *options)
content_length = ULONG_MAX;
}
- if (g_ascii_strncasecmp (header->name, "Content-", 8) != 0)
- _g_mime_object_append_header ((GMimeObject *) message, header->name, header->value,
header->raw_value, header->offset);
+ if (g_ascii_strncasecmp (header->name, "Content-", 8) != 0) {
+ _g_mime_object_append_header ((GMimeObject *) message, header->name, header->value,
+ header->raw_name, header->raw_value, header->offset);
+ }
+
header = header->next;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]