[gmime] Modified GMimeParser to auto-detect OpenPGP markers



commit e1f9abdff4ca8cb994a6d5879bdf783567c7dd94
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date:   Mon Mar 13 16:09:03 2017 -0400

    Modified GMimeParser to auto-detect OpenPGP markers
    
    If the parser detects OpenPGP markers, it will set
    that state on the GMimePart for easier detection by
    mail clients using GMime w/o the need to manually
    scan for those markers themselves.

 docs/reference/gmime-sections.txt |    3 +
 gmime/gmime-parser.c              |   85 +++++++++++++++++++++++++++----------
 gmime/gmime-part.c                |   35 +++++++++++++++
 gmime/gmime-part.h                |   19 ++++++++
 4 files changed, 120 insertions(+), 22 deletions(-)
---
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index 8ff0a2f..40f06f0 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -713,6 +713,7 @@ GMimeObjectClass
 <SECTION>
 <FILE>gmime-part</FILE>
 GMimePart
+GMimeOpenPGPData
 g_mime_part_new
 g_mime_part_new_with_type
 g_mime_part_is_attachment
@@ -730,6 +731,8 @@ g_mime_part_get_content_encoding
 g_mime_part_get_best_content_encoding
 g_mime_part_set_filename
 g_mime_part_get_filename
+g_mime_part_get_openpgp_data
+g_mime_part_set_openpgp_data
 g_mime_part_get_content
 g_mime_part_set_content
 
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 389fce7..5b485db 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -64,6 +64,18 @@
  * into multiple #GMimeMessage objects.
  **/
 
+typedef struct {
+       const char *begin;
+       const char *end;
+       size_t begin_len;
+       size_t end_len;
+} GMimeOpenPGPMarker;
+
+static const GMimeOpenPGPMarker openpgp_markers[] = {
+       { "-----BEGIN PGP MESSAGE-----",        "-----END PGP MESSAGE-----",        27, 25 },
+       { "-----BEGIN PGP SIGNED MESSAGE-----", "-----END PGP SIGNED MESSAGE-----", 34, 32 }
+};
+
 typedef struct _boundary_stack {
        struct _boundary_stack *parent;
        char *boundary;
@@ -109,7 +121,7 @@ static GObjectClass *parent_class = NULL;
 #define HEADER_RAW_INIT_SIZE 1024
 
 
-enum {
+typedef enum {
        GMIME_PARSER_STATE_ERROR = -1,
        GMIME_PARSER_STATE_INIT,
        GMIME_PARSER_STATE_FROM,
@@ -119,7 +131,7 @@ enum {
        GMIME_PARSER_STATE_HEADERS_END,
        GMIME_PARSER_STATE_CONTENT,
        GMIME_PARSER_STATE_COMPLETE,
-};
+} GMimeParserState;
 
 struct _GMimeParserPrivate {
        GMimeStream *stream;
@@ -168,12 +180,14 @@ struct _GMimeParserPrivate {
        
        short int state;
        
-       unsigned short int unused:11;
        unsigned short int midline:1;
        unsigned short int seekable:1;
        unsigned short int have_regex:1;
        unsigned short int persist_stream:1;
        unsigned short int respect_content_length:1;
+       unsigned short int openpgp_begin:2;
+       unsigned short int openpgp_end:2;
+       unsigned short int unused:7;
        
        HeaderRaw *headers;
        
@@ -387,6 +401,9 @@ parser_init (GMimeParser *parser, GMimeStream *stream)
        
        priv->header_offset = -1;
        
+       priv->openpgp_begin = GMIME_OPENPGP_DATA_NONE;
+       priv->openpgp_end = GMIME_OPENPGP_DATA_NONE;
+       
        priv->midline = FALSE;
        priv->seekable = offset != -1;
        
@@ -1393,7 +1410,9 @@ check_boundary (struct _GMimeParserPrivate *priv, const char *start, size_t len)
 {
        gint64 offset = parser_offset (priv, start);
        const char *marker;
+       BoundaryStack *s;
        size_t mlen;
+       guint i;
        
        switch (priv->format) {
        case GMIME_FORMAT_MBOX: marker = MBOX_BOUNDARY; mlen = MBOX_BOUNDARY_LEN; break;
@@ -1404,29 +1423,46 @@ check_boundary (struct _GMimeParserPrivate *priv, const char *start, size_t len)
        if (len > 0 && start[len - 1] == '\r')
                len--;
        
-       if (possible_boundary (marker, mlen, start, len)) {
-               BoundaryStack *s;
+       if (!possible_boundary (marker, mlen, start, len))
+               return FOUND_NOTHING;
+       
+       d(printf ("checking boundary '%.*s'\n", len, start));
+       
+       s = priv->bounds;
+       while (s) {
+               if (offset >= s->content_end &&
+                   is_boundary (priv, start, len, s->boundary, s->boundarylenfinal)) {
+                       d(printf ("found %s\n", s->content_end != -1 && offset >= s->content_end ?
+                                 "end of content" : "end boundary"));
+                       return FOUND_END_BOUNDARY;
+               }
                
-               d(printf ("checking boundary '%.*s'\n", len, start));
+               if (is_boundary (priv, start, len, s->boundary, s->boundarylen)) {
+                       d(printf ("found boundary\n"));
+                       return FOUND_BOUNDARY;
+               }
                
-               s = priv->bounds;
-               while (s) {
-                       if (offset >= s->content_end &&
-                           is_boundary (priv, start, len, s->boundary, s->boundarylenfinal)) {
-                               d(printf ("found %s\n", s->content_end != -1 && offset >= s->content_end ?
-                                         "end of content" : "end boundary"));
-                               return FOUND_END_BOUNDARY;
-                       }
-                       
-                       if (is_boundary (priv, start, len, s->boundary, s->boundarylen)) {
-                               d(printf ("found boundary\n"));
-                               return FOUND_BOUNDARY;
-                       }
+               s = s->parent;
+       }
+       
+       d(printf ("'%.*s' not a boundary\n", len, start));
+       
+       if (!strncmp (start, "--", 2)) {
+               start += 2;
+               len -= 2;
+               
+               /* check for OpenPGP markers... */
+               for (i = 0; i < G_N_ELEMENTS (openpgp_markers); i++) {
+                       size_t begin_len = openpgp_markers[i].begin_len - 2;
+                       const char *begin = openpgp_markers[i].begin + 2;
+                       size_t end_len = openpgp_markers[i].end_len - 2;
+                       const char *end = openpgp_markers[i].end + 2;
                        
-                       s = s->parent;
+                       if (len == begin_len && !strncmp (begin, start, len))
+                               priv->openpgp_begin = (GMimeOpenPGPData) (i + 1);
+                       else if (len == end_len && !strncmp (end, start, len))
+                               priv->openpgp_end = (GMimeOpenPGPData) (i + 1);
                }
-               
-               d(printf ("'%.*s' not a boundary\n", len, start));
        }
        
        return FOUND_NOTHING;
@@ -1476,6 +1512,8 @@ parser_scan_content (GMimeParser *parser, GByteArray *content, guint *crlf)
        
        d(printf ("scan-content\n"));
        
+       priv->openpgp_begin = GMIME_OPENPGP_DATA_NONE;
+       priv->openpgp_end = GMIME_OPENPGP_DATA_NONE;
        priv->midline = FALSE;
        
        g_assert (priv->inptr <= priv->inend);
@@ -1615,6 +1653,9 @@ parser_scan_mime_part_content (GMimeParser *parser, GMimePart *mime_part, int *f
        g_mime_part_set_content (mime_part, wrapper);
        g_object_unref (wrapper);
        g_object_unref (stream);
+       
+       if (priv->openpgp_begin && priv->openpgp_begin == priv->openpgp_end)
+               g_mime_part_set_openpgp_data (mime_part, priv->openpgp_begin);
 }
 
 static void
diff --git a/gmime/gmime-part.c b/gmime/gmime-part.c
index 91dd1a0..ea06c6d 100644
--- a/gmime/gmime-part.c
+++ b/gmime/gmime-part.c
@@ -916,6 +916,41 @@ g_mime_part_get_filename (GMimePart *mime_part)
 }
 
 
+/**
+ * g_mime_part_set_openpgp_data:
+ * @mime_part: a #GMimePart
+ * @data: a #GMimeOpenPGPData
+ *
+ * Sets whether or not (and what type) of OpenPGP data is contained
+ * within the #GMimePart.
+ **/
+void
+g_mime_part_set_openpgp_data (GMimePart *mime_part, GMimeOpenPGPData data)
+{
+       g_return_if_fail (GMIME_IS_PART (mime_part));
+       
+       mime_part->openpgp = data;
+}
+
+
+/**
+ * g_mime_part_get_openpgp_data:
+ * @mime_part: a #GMimePart
+ *
+ * Gets whether or not (and what type) of OpenPGP data is contained
+ * within the #GMimePart.
+ *
+ * Returns: a #GMimeOpenPGPData.
+ **/
+GMimeOpenPGPData
+g_mime_part_get_openpgp_data (GMimePart *mime_part)
+{
+       g_return_val_if_fail (GMIME_IS_PART (mime_part), GMIME_OPENPGP_DATA_NONE);
+       
+       return mime_part->openpgp;
+}
+
+
 static void
 set_content (GMimePart *mime_part, GMimeDataWrapper *content)
 {
diff --git a/gmime/gmime-part.h b/gmime/gmime-part.h
index 0391eef..38a9098 100644
--- a/gmime/gmime-part.h
+++ b/gmime/gmime-part.h
@@ -43,9 +43,24 @@ typedef struct _GMimePart GMimePart;
 typedef struct _GMimePartClass GMimePartClass;
 
 /**
+ * GMimeOpenPGPData:
+ * @GMIME_OPENPGP_DATA_NONE: The #GMimePart does not contain any OpenPGP data.
+ * @GMIME_OPENPGP_DATA_ENCRYPTED: The #GMimePart contains OpenPGP encrypted data.
+ * @GMIME_OPENPGP_DATA_SIGNED: The #GMimePart contains OpenPGP signed data.
+ *
+ * The type of OpenPGP data contained within the content of the #GMimePart, if any.
+ **/
+typedef enum {
+       GMIME_OPENPGP_DATA_NONE,
+       GMIME_OPENPGP_DATA_ENCRYPTED,
+       GMIME_OPENPGP_DATA_SIGNED
+} GMimeOpenPGPData;
+
+/**
  * GMimePart:
  * @parent_object: parent #GMimeObject
  * @encoding: a #GMimeContentEncoding
+ * @openpgp: a #GMimeOpenPGPData
  * @content_description: Content-Description string
  * @content_location: Content-Location string
  * @content_md5: Content-MD5 string
@@ -57,6 +72,7 @@ struct _GMimePart {
        GMimeObject parent_object;
        
        GMimeContentEncoding encoding;
+       GMimeOpenPGPData openpgp;
        char *content_description;
        char *content_location;
        char *content_md5;
@@ -101,6 +117,9 @@ gboolean g_mime_part_is_attachment (GMimePart *mime_part);
 void g_mime_part_set_filename (GMimePart *mime_part, const char *filename);
 const char *g_mime_part_get_filename (GMimePart *mime_part);
 
+void g_mime_part_set_openpgp_data (GMimePart *mime_part, GMimeOpenPGPData data);
+GMimeOpenPGPData g_mime_part_get_openpgp_data (GMimePart *mime_part);
+
 void g_mime_part_set_content (GMimePart *mime_part, GMimeDataWrapper *content);
 GMimeDataWrapper *g_mime_part_get_content (GMimePart *mime_part);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]