[gmime: 12/14] Save (munged) From lines at the start of message/rfc822 parts
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime: 12/14] Save (munged) From lines at the start of message/rfc822 parts
- Date: Fri, 31 Mar 2017 17:07:37 +0000 (UTC)
commit c763403773035b56bb1f32bfc5dc9bf56b0af580
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Fri Mar 31 08:53:24 2017 -0400
Save (munged) From lines at the start of message/rfc822 parts
gmime/gmime-message-part.c | 39 +++++++++++++++++++++++++++++++--
gmime/gmime-message.c | 1 +
gmime/gmime-message.h | 1 +
gmime/gmime-parser.c | 50 ++++++++++++++++++++++++++++++++++++++-----
4 files changed, 82 insertions(+), 9 deletions(-)
---
diff --git a/gmime/gmime-message-part.c b/gmime/gmime-message-part.c
index 53a5fa2..38ce5b7 100644
--- a/gmime/gmime-message-part.c
+++ b/gmime/gmime-message-part.c
@@ -113,7 +113,13 @@ static ssize_t
message_part_write_to_stream (GMimeObject *object, GMimeFormatOptions *options, gboolean content_only,
GMimeStream *stream)
{
GMimeMessagePart *part = (GMimeMessagePart *) object;
+ GMimeMessage *message = part->message;
ssize_t nwritten, total = 0;
+ const char *newline, *eoln;
+ gboolean match;
+ size_t len;
+
+ newline = g_mime_format_options_get_newline (options);
if (!content_only) {
/* write the content headers */
@@ -123,15 +129,42 @@ message_part_write_to_stream (GMimeObject *object, GMimeFormatOptions *options,
total += nwritten;
/* terminate the headers */
- if ((nwritten = g_mime_stream_write (stream, "\n", 1)) == -1)
+ if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1)
return -1;
total += nwritten;
}
/* write the message */
- if (part->message) {
- if ((nwritten = g_mime_object_write_to_stream ((GMimeObject *) part->message, options,
stream)) == -1)
+ if (message) {
+ if (message->marker && (len = strlen (message->marker)) > 0) {
+ if (*(eoln = message->marker + (len - 1)) == '\n') {
+ if (eoln > message->marker && eoln[-1] == '\r')
+ eoln--;
+
+ /* check if newline sequences match... */
+ if (!(match = !strcmp (eoln, newline))) {
+ /* they don't match... trim off the eoln sequence */
+ len = (size_t) (eoln - message->marker);
+ }
+ } else {
+ match = FALSE;
+ }
+
+ if ((nwritten = g_mime_stream_write (stream, message->marker, len)) == -1)
+ return -1;
+
+ total += nwritten;
+
+ if (!match) {
+ if ((nwritten = g_mime_stream_write_string (stream, newline)) == -1)
+ return -1;
+
+ total += nwritten;
+ }
+ }
+
+ if ((nwritten = g_mime_object_write_to_stream ((GMimeObject *) message, options, stream)) ==
-1)
return -1;
total += nwritten;
diff --git a/gmime/gmime-message.c b/gmime/gmime-message.c
index 1e035d7..639f4fe 100644
--- a/gmime/gmime-message.c
+++ b/gmime/gmime-message.c
@@ -221,6 +221,7 @@ g_mime_message_finalize (GObject *object)
g_free (message->addrlists);
g_free (message->message_id);
g_free (message->subject);
+ g_free (message->marker);
if (message->date)
g_date_time_unref (message->date);
diff --git a/gmime/gmime-message.h b/gmime/gmime-message.h
index f1ab970..5a2a918 100644
--- a/gmime/gmime-message.h
+++ b/gmime/gmime-message.h
@@ -87,6 +87,7 @@ struct _GMimeMessage {
/* < private > */
GMimeRfcComplianceMode compliance;
+ char *marker;
};
struct _GMimeMessageClass {
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 66e5548..2313cc2 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -166,6 +166,8 @@ struct _GMimeParserPrivate {
GByteArray *marker;
gint64 marker_offset;
+ char *preheader;
+
/* current message headerblock offsets */
gint64 message_headers_begin;
gint64 message_headers_end;
@@ -282,6 +284,9 @@ parser_free_headers (struct _GMimeParserPrivate *priv)
Header *header;
guint i;
+ g_free (priv->preheader);
+ priv->preheader = NULL;
+
for (i = 0; i < priv->headers->len; i++) {
header = priv->headers->pdata[i];
@@ -382,6 +387,8 @@ parser_init (GMimeParser *parser, GMimeStream *stream)
priv->marker = g_byte_array_new ();
priv->marker_offset = -1;
+ priv->preheader = NULL;
+
priv->headers = g_ptr_array_new ();
priv->headerbuf = g_malloc (HEADER_INIT_SIZE);
@@ -751,6 +758,17 @@ g_mime_parser_eos (GMimeParser *parser)
return g_mime_stream_eos (priv->stream) && priv->inptr == priv->inend;
}
+static gboolean
+is_mbox_marker (const char *inptr, size_t len, gboolean allow_munged)
+{
+ if (allow_munged && *inptr == '>') {
+ inptr++;
+ len--;
+ }
+
+ return len >= 5 && !strncmp ("From ", inptr, 5);
+}
+
static int
parser_step_marker (GMimeParser *parser, const char *marker, size_t marker_len)
{
@@ -855,13 +873,27 @@ static void
header_parse (GMimeParser *parser)
{
struct _GMimeParserPrivate *priv = parser->priv;
+ gboolean valid = TRUE, blank = FALSE;
register char *inptr;
Header *header;
*priv->headerptr = ':';
inptr = priv->headerbuf;
- while (*inptr != ':')
+
+ while (*inptr != ':') {
+ /* Note: blank spaces are allowed between the field name
+ * and the ':', but field names themselves are not allowed
+ * to contain spaces (or control characters). */
+ if (is_blank (*inptr)) {
+ blank = TRUE;
+ } else if (blank || is_ctrl (*inptr)) {
+ valid = FALSE;
+ break;
+ }
+
inptr++;
+ }
+
*priv->headerptr = '\0';
if (*inptr != ':') {
@@ -870,6 +902,9 @@ header_parse (GMimeParser *parser)
(long long) priv->header_offset,
priv->headerbuf));
+ if (priv->preheader == NULL)
+ priv->preheader = g_strdup (priv->headerbuf);
+
priv->headerleft += priv->headerptr - priv->headerbuf;
priv->headerptr = priv->headerbuf;
return;
@@ -1000,7 +1035,7 @@ parser_step_headers (GMimeParser *parser)
while (*inptr != ':') {
/* Note: blank spaces are allowed between the field name
* and the ':', but field names themselves are not allowed
- * to contain spaces. */
+ * to contain spaces (or control characters). */
if (is_blank (*inptr)) {
blank = TRUE;
} else if (blank || is_ctrl (*inptr)) {
@@ -1025,8 +1060,8 @@ parser_step_headers (GMimeParser *parser)
}
if (!valid) {
- if (priv->format == GMIME_FORMAT_MBOX && (inptr - start) >= 5
- && !strncmp (start, "From ", 5))
+ if (priv->format == GMIME_FORMAT_MBOX &&
+ is_mbox_marker (start, (size_t) (inptr - start), FALSE))
goto next_message;
if (priv->headers->len > 0) {
@@ -1045,8 +1080,9 @@ parser_step_headers (GMimeParser *parser)
}
} else if (priv->state == GMIME_PARSER_STATE_MESSAGE_HEADERS) {
/* Be a little more strict when scanning toplevel message
- * headers, but remain lenient with From-lines. */
- if ((inptr - start) < 5 || strncmp (start, "From ", 5) != 0) {
+ * headers, but remain lenient with lines starting with
+ * "From " or ">From ". */
+ if (!is_mbox_marker (start, (size_t) (inptr - start), TRUE)) {
priv->state = GMIME_PARSER_STATE_ERROR;
return -1;
}
@@ -1628,6 +1664,8 @@ parser_scan_message_part (GMimeParser *parser, GMimeParserOptions *options, GMim
message = g_mime_message_new (FALSE);
message->compliance = GMIME_RFC_COMPLIANCE_LOOSE;
+ message->marker = priv->preheader;
+ priv->preheader = NULL;
for (i = 0; i < priv->headers->len; i++) {
header = priv->headers->pdata[i];
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]