[gmime] Added new GMimeFilterOpenPGP filter
- From: Jeffrey Stedfast <fejj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gmime] Added new GMimeFilterOpenPGP filter
- Date: Wed, 20 Dec 2017 17:09:16 +0000 (UTC)
commit 61271a33efe33ca7d0cd29d889da662b2dbaeb99
Author: Jeffrey Stedfast <jestedfa microsoft com>
Date: Tue Dec 12 17:30:45 2017 -0500
Added new GMimeFilterOpenPGP filter
docs/reference/gmime-docs.sgml | 2 +
docs/reference/gmime-sections.txt | 25 +++-
docs/reference/gmime.hierarchy | 1 +
gmime/Makefile.am | 2 +
gmime/gmime-filter-openpgp.c | 412 +++++++++++++++++++++++++++++++++++++
gmime/gmime-filter-openpgp.h | 130 ++++++++++++
gmime/gmime-parser.c | 56 ++---
gmime/gmime-part.h | 15 +--
gmime/gmime.h | 1 +
tests/test-pgp.c | 59 ++++++
10 files changed, 655 insertions(+), 48 deletions(-)
---
diff --git a/docs/reference/gmime-docs.sgml b/docs/reference/gmime-docs.sgml
index 890d68e..8626d9f 100644
--- a/docs/reference/gmime-docs.sgml
+++ b/docs/reference/gmime-docs.sgml
@@ -52,6 +52,7 @@
<!ENTITY GMimeFilterFrom SYSTEM "xml/gmime-filter-from.xml">
<!ENTITY GMimeFilterGZip SYSTEM "xml/gmime-filter-gzip.xml">
<!ENTITY GMimeFilterHTML SYSTEM "xml/gmime-filter-html.xml">
+<!ENTITY GMimeFilterOpenPGP SYSTEM "xml/gmime-filter-openpgp.xml">
<!ENTITY GMimeFilterSmtpData SYSTEM "xml/gmime-filter-smtp-data.xml">
<!ENTITY GMimeFilterStrip SYSTEM "xml/gmime-filter-strip.xml">
<!ENTITY GMimeFilterUnix2Dos SYSTEM "xml/gmime-filter-unix2dos.xml">
@@ -218,6 +219,7 @@ string utilities, file utilities, a main loop abstraction, and so on.
&GMimeFilterFrom;
&GMimeFilterGZip;
&GMimeFilterHTML;
+ &GMimeFilterOpenPGP;
&GMimeFilterSmtpData;
&GMimeFilterStrip;
&GMimeFilterUnix2Dos;
diff --git a/docs/reference/gmime-sections.txt b/docs/reference/gmime-sections.txt
index 796dff8..acffe1d 100644
--- a/docs/reference/gmime-sections.txt
+++ b/docs/reference/gmime-sections.txt
@@ -492,6 +492,30 @@ GMIME_FILTER_CHECKSUM_GET_CLASS
</SECTION>
<SECTION>
+<FILE>gmime-filter-openpgp</FILE>
+GMimeOpenPGPData
+GMimeOpenPGPState
+GMimeOpenPGPMarker
+GMimeFilterOpenPGP
+g_mime_filter_openpgp_new
+g_mime_filter_openpgp_get_data_type
+g_mime_filter_openpgp_get_begin_offset
+g_mime_filter_openpgp_get_enbd_offset
+
+<SUBSECTION Private>
+g_mime_filter_openpgp_get_type
+
+<SUBSECTION Standard>
+GMimeFilterOpenPGPClass
+GMIME_TYPE_FILTER_OPENPGP
+GMIME_FILTER_OPENPGP
+GMIME_IS_FILTER_OPENPGP
+GMIME_FILTER_OPENPGP_CLASS
+GMIME_IS_FILTER_OPENPGP_CLASS
+GMIME_FILTER_OPENPGP_GET_CLASS
+</SECTION>
+
+<SECTION>
<FILE>gmime-filter-strip</FILE>
GMimeFilterStrip
g_mime_filter_strip_new
@@ -811,7 +835,6 @@ GMimeObjectClass
<SECTION>
<FILE>gmime-part</FILE>
GMimePart
-GMimeOpenPGPData
g_mime_part_new
g_mime_part_new_with_type
g_mime_part_is_attachment
diff --git a/docs/reference/gmime.hierarchy b/docs/reference/gmime.hierarchy
index e29d056..9aea60b 100644
--- a/docs/reference/gmime.hierarchy
+++ b/docs/reference/gmime.hierarchy
@@ -38,6 +38,7 @@ GObject
GMimeFilterFrom
GMimeFilterGZip
GMimeFilterHTML
+ GMimeFilterOpenPGP
GMimeFilterSmtpData
GMimeFilterStrip
GMimeFilterUnix2Dos
diff --git a/gmime/Makefile.am b/gmime/Makefile.am
index 10fa06d..b90dc4b 100644
--- a/gmime/Makefile.am
+++ b/gmime/Makefile.am
@@ -42,6 +42,7 @@ libgmime_3_0_la_SOURCES = \
gmime-filter-from.c \
gmime-filter-gzip.c \
gmime-filter-html.c \
+ gmime-filter-openpgp.c \
gmime-filter-smtp-data.c \
gmime-filter-strip.c \
gmime-filter-unix2dos.c \
@@ -106,6 +107,7 @@ gmimeinclude_HEADERS = \
gmime-filter-from.h \
gmime-filter-gzip.h \
gmime-filter-html.h \
+ gmime-filter-openpgp.h \
gmime-filter-smtp-data.h \
gmime-filter-strip.h \
gmime-filter-unix2dos.h \
diff --git a/gmime/gmime-filter-openpgp.c b/gmime/gmime-filter-openpgp.c
new file mode 100644
index 0000000..d335bcc
--- /dev/null
+++ b/gmime/gmime-filter-openpgp.c
@@ -0,0 +1,412 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* GMime
+ * Copyright (C) 2000-2017 Jeffrey Stedfast
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gmime-filter-openpgp.h"
+
+
+/**
+ * SECTION: gmime-filter-openpgp
+ * @title: GMimeFilterOpenPGP
+ * @short_description: Detect OpenPGP markers.
+ *
+ * A #GMimeFilter for detecting OpenPGP markers and filtering out any content outside the bounds of said
markers.
+ **/
+
+/* Note: if you add/remove markers, update GMimeParser as well */
+const GMimeOpenPGPMarker g_mime_openpgp_markers[9] = {
+ { "-----BEGIN PGP MESSAGE-----", 27, GMIME_OPENPGP_NONE,
GMIME_OPENPGP_BEGIN_PGP_MESSAGE, FALSE },
+ { "-----END PGP MESSAGE-----", 25, GMIME_OPENPGP_BEGIN_PGP_MESSAGE,
GMIME_OPENPGP_END_PGP_MESSAGE, TRUE },
+ { "-----BEGIN PGP SIGNED MESSAGE-----", 34, GMIME_OPENPGP_NONE,
GMIME_OPENPGP_BEGIN_PGP_SIGNED_MESSAGE, FALSE },
+ { "-----BEGIN PGP SIGNATURE-----", 29, GMIME_OPENPGP_BEGIN_PGP_SIGNED_MESSAGE,
GMIME_OPENPGP_BEGIN_PGP_SIGNATURE, FALSE },
+ { "-----END PGP SIGNATURE-----", 27, GMIME_OPENPGP_BEGIN_PGP_SIGNATURE,
GMIME_OPENPGP_END_PGP_SIGNATURE, TRUE },
+ { "-----BEGIN PGP PUBLIC KEY BLOCK-----", 36, GMIME_OPENPGP_NONE,
GMIME_OPENPGP_BEGIN_PGP_PUBLIC_KEY_BLOCK, FALSE },
+ { "-----END PGP PUBLIC KEY BLOCK-----", 34, GMIME_OPENPGP_BEGIN_PGP_PUBLIC_KEY_BLOCK,
GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK, TRUE },
+ { "-----BEGIN PGP PRIVATE KEY BLOCK-----", 37, GMIME_OPENPGP_NONE,
GMIME_OPENPGP_BEGIN_PGP_PRIVATE_KEY_BLOCK, FALSE },
+ { "-----END PGP PRIVATE KEY BLOCK-----", 35, GMIME_OPENPGP_BEGIN_PGP_PRIVATE_KEY_BLOCK,
GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK, TRUE }
+};
+
+static void g_mime_filter_openpgp_class_init (GMimeFilterOpenPGPClass *klass);
+static void g_mime_filter_openpgp_init (GMimeFilterOpenPGP *filter, GMimeFilterOpenPGPClass *klass);
+
+static GMimeFilter *filter_copy (GMimeFilter *filter);
+static void filter_filter (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace);
+static void filter_complete (GMimeFilter *filter, char *in, size_t len, size_t prespace,
+ char **out, size_t *outlen, size_t *outprespace);
+static void filter_reset (GMimeFilter *filter);
+
+
+static GMimeFilterClass *parent_class = NULL;
+
+
+GType
+g_mime_filter_openpgp_get_type (void)
+{
+ static GType type = 0;
+
+ if (!type) {
+ static const GTypeInfo info = {
+ sizeof (GMimeFilterOpenPGPClass),
+ NULL, /* base_class_init */
+ NULL, /* base_class_finalize */
+ (GClassInitFunc) g_mime_filter_openpgp_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GMimeFilterOpenPGP),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) g_mime_filter_openpgp_init,
+ };
+
+ type = g_type_register_static (GMIME_TYPE_FILTER, "GMimeFilterOpenPGP", &info, 0);
+ }
+
+ return type;
+}
+
+
+static void
+g_mime_filter_openpgp_class_init (GMimeFilterOpenPGPClass *klass)
+{
+ GMimeFilterClass *filter_class = GMIME_FILTER_CLASS (klass);
+
+ parent_class = g_type_class_ref (GMIME_TYPE_FILTER);
+
+ filter_class->copy = filter_copy;
+ filter_class->filter = filter_filter;
+ filter_class->complete = filter_complete;
+ filter_class->reset = filter_reset;
+}
+
+static void
+g_mime_filter_openpgp_init (GMimeFilterOpenPGP *filter, GMimeFilterOpenPGPClass *klass)
+{
+ filter->state = GMIME_OPENPGP_NONE;
+ filter->seen_end_marker = FALSE;
+ filter->midline = FALSE;
+ filter->begin_offset = -1;
+ filter->end_offset = -1;
+ filter->position = 0;
+ filter->next = 0;
+}
+
+
+static GMimeFilter *
+filter_copy (GMimeFilter *filter)
+{
+ return g_mime_filter_openpgp_new ();
+}
+
+static gboolean
+is_marker (const char *input, const char *inend, const GMimeOpenPGPMarker *marker, gboolean *cr)
+{
+ const char *markerend = marker->marker + marker->len;
+ const char *markerptr = marker->marker;
+ const char *inptr = input;
+
+ *cr = FALSE;
+
+ while (inptr < inend && markerptr < markerend) {
+ if (*inptr != *markerptr)
+ return FALSE;
+
+ markerptr++;
+ inptr++;
+ }
+
+ if (markerptr < markerend)
+ return FALSE;
+
+ if (inptr < inend && *inptr == '\r') {
+ *cr = TRUE;
+ inptr++;
+ }
+
+ return *inptr == '\n';
+}
+
+static gboolean
+is_partial_match (const char *input, const char *inend, const GMimeOpenPGPMarker *marker)
+{
+ const char *markerend = marker->marker + marker->len;
+ const char *markerptr = marker->marker;
+ const char *inptr = input;
+
+ while (inptr < inend && markerptr < markerend) {
+ if (*inptr != *markerptr)
+ return FALSE;
+
+ markerptr++;
+ inptr++;
+ }
+
+ if (markerptr < markerend)
+ return FALSE;
+
+ if (inptr < inend && *inptr == '\r')
+ inptr++;
+
+ return inptr == inend;
+}
+
+static void
+set_position (GMimeFilterOpenPGP *openpgp, gint64 offset, guint marker, gboolean cr)
+{
+ size_t length = g_mime_openpgp_markers[marker].len + (cr ? 2 : 1);
+
+ switch (openpgp->state) {
+ case GMIME_OPENPGP_BEGIN_PGP_PRIVATE_KEY_BLOCK: openpgp->begin_offset = openpgp->position + offset;
break;
+ case GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK: openpgp->end_offset = openpgp->position + offset +
length; break;
+ case GMIME_OPENPGP_BEGIN_PGP_PUBLIC_KEY_BLOCK: openpgp->begin_offset = openpgp->position + offset;
break;
+ case GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK: openpgp->end_offset = openpgp->position + offset +
length; break;
+ case GMIME_OPENPGP_BEGIN_PGP_SIGNED_MESSAGE: openpgp->begin_offset = openpgp->position + offset;
break;
+ case GMIME_OPENPGP_END_PGP_SIGNATURE: openpgp->end_offset = openpgp->position + offset + length;
break;
+ case GMIME_OPENPGP_BEGIN_PGP_MESSAGE: openpgp->begin_offset = openpgp->position + offset; break;
+ case GMIME_OPENPGP_END_PGP_MESSAGE: openpgp->end_offset = openpgp->position + offset + length; break;
+ default: break;
+ }
+}
+
+static void
+scan (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
+ char **outbuf, size_t *outlen, size_t *outprespace, gboolean flush)
+{
+ GMimeFilterOpenPGP *openpgp = (GMimeFilterOpenPGP *) filter;
+ const char *inend = inbuf + inlen;
+ const char *inptr = inbuf;
+ gboolean cr;
+ guint i;
+
+ *outprespace = prespace;
+ *outbuf = inbuf;
+ *outlen = 0;
+
+ if (openpgp->seen_end_marker || inlen == 0)
+ return;
+
+ if (openpgp->midline) {
+ while (inptr < inend && *inptr != '\n')
+ inptr++;
+
+ if (inptr == inend) {
+ if (openpgp->state != GMIME_OPENPGP_NONE)
+ *outlen = inlen;
+
+ openpgp->position += inlen;
+ return;
+ }
+
+ openpgp->midline = FALSE;
+ }
+
+ if (openpgp->state == GMIME_OPENPGP_NONE) {
+ do {
+ const char *lineptr = inptr;
+
+ while (inptr < inend && *inptr != '\n')
+ inptr++;
+
+ if (inptr == inend) {
+ gboolean partial = FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (g_mime_openpgp_markers); i++) {
+ if (g_mime_openpgp_markers[i].before == openpgp->state &&
is_partial_match (lineptr, inend, &g_mime_openpgp_markers[i])) {
+ partial = TRUE;
+ break;
+ }
+ }
+
+ if (partial) {
+ g_mime_filter_backup (filter, lineptr, inptr - lineptr);
+ openpgp->position += lineptr - inbuf;
+ } else {
+ openpgp->position += inptr - lineptr;
+ openpgp->midline = TRUE;
+ }
+
+ return;
+ }
+
+ inptr++;
+
+ for (i = 0; i < G_N_ELEMENTS (g_mime_openpgp_markers); i++) {
+ if (g_mime_openpgp_markers[i].before == openpgp->state && is_marker (lineptr,
inend, &g_mime_openpgp_markers[i], &cr)) {
+ openpgp->state = g_mime_openpgp_markers[i].after;
+ set_position (openpgp, lineptr - inbuf, i, cr);
+ *outbuf = (char *) lineptr;
+ *outlen = inptr - lineptr;
+ openpgp->next = i + 1;
+ break;
+ }
+ }
+ } while (inptr < inend && openpgp->state == GMIME_OPENPGP_NONE);
+
+ if (inptr == inend) {
+ openpgp->position += inptr - inbuf;
+ return;
+ }
+ }
+
+ do {
+ const char *lineptr = inptr;
+
+ while (inptr < inend && *inptr != '\n')
+ inptr++;
+
+ if (inptr == inend) {
+ if (!flush) {
+ if (is_partial_match (lineptr, inend,
&g_mime_openpgp_markers[openpgp->next])) {
+ g_mime_filter_backup (filter, lineptr, inptr - lineptr);
+ openpgp->position += lineptr - inbuf;
+ *outlen = lineptr - *outbuf;
+ } else {
+ openpgp->position += inptr - inbuf;
+ *outlen = inptr - *outbuf;
+ openpgp->midline = TRUE;
+ }
+
+ return;
+ }
+
+ openpgp->position += inptr - inbuf;
+ *outlen = inptr - *outbuf;
+
+ return;
+ }
+
+ inptr++;
+
+ if (is_marker (lineptr, inend, &g_mime_openpgp_markers[openpgp->next], &cr)) {
+ openpgp->seen_end_marker = g_mime_openpgp_markers[openpgp->next].is_end_marker;
+ openpgp->state = g_mime_openpgp_markers[openpgp->next].after;
+ set_position (openpgp, lineptr - inbuf, openpgp->next, cr);
+ openpgp->next++;
+
+ if (openpgp->seen_end_marker)
+ break;
+ }
+ } while (inptr < inend);
+
+ openpgp->position += inptr - inbuf;
+ *outlen = inptr - *outbuf;
+}
+
+static void
+filter_filter (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
+ char **outbuf, size_t *outlen, size_t *outprespace)
+{
+ scan (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace, FALSE);
+}
+
+static void
+filter_complete (GMimeFilter *filter, char *inbuf, size_t inlen, size_t prespace,
+ char **outbuf, size_t *outlen, size_t *outprespace)
+{
+ scan (filter, inbuf, inlen, prespace, outbuf, outlen, outprespace, TRUE);
+}
+
+static void
+filter_reset (GMimeFilter *filter)
+{
+ GMimeFilterOpenPGP *openpgp = (GMimeFilterOpenPGP *) filter;
+
+ openpgp->state = GMIME_OPENPGP_NONE;
+ openpgp->seen_end_marker = FALSE;
+ openpgp->midline = FALSE;
+ openpgp->begin_offset = -1;
+ openpgp->end_offset = -1;
+ openpgp->position = 0;
+ openpgp->next = 0;
+}
+
+
+/**
+ * g_mime_filter_openpgp_new:
+ *
+ * Creates a new #GMimeFilterOpenPGP filter.
+ *
+ * Returns: a new #GMimeFilterOpenPGP filter.
+ **/
+GMimeFilter *
+g_mime_filter_openpgp_new (void)
+{
+ return (GMimeFilter *) g_object_new (GMIME_TYPE_FILTER_OPENPGP, NULL);
+}
+
+
+/**
+ * g_mime_filter_openpgp_get_data_type:
+ * @openpgp: A #GMimeFilterOpenPGP filter
+ *
+ * Gets the type of OpenPGP data that has been detected.
+ *
+ * Returns: a #GMimeOpenPGPData value.
+ **/
+GMimeOpenPGPData
+g_mime_filter_openpgp_get_data_type (GMimeFilterOpenPGP *openpgp)
+{
+ g_return_val_if_fail (GMIME_IS_FILTER_OPENPGP (openpgp), GMIME_OPENPGP_DATA_NONE);
+
+ switch (openpgp->state) {
+ case GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK: return GMIME_OPENPGP_DATA_PRIVATE_KEY;
+ case GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK: return GMIME_OPENPGP_DATA_PUBLIC_KEY;
+ case GMIME_OPENPGP_END_PGP_SIGNATURE: return GMIME_OPENPGP_DATA_SIGNED;
+ case GMIME_OPENPGP_END_PGP_MESSAGE: return GMIME_OPENPGP_DATA_ENCRYPTED;
+ default: return GMIME_OPENPGP_DATA_NONE;
+ }
+}
+
+
+/**
+ * g_mime_filter_openpgp_get_begin_offset:
+ * @openpgp: A #GMimeFilterOpenPGP filter
+ *
+ * Gets the stream offset of the beginning of the OpenPGP data block, if any have been found.
+ *
+ * Returns: The stream offset or %-1 if no OpenPGP block was found.
+ **/
+gint64
+g_mime_filter_openpgp_get_begin_offset (GMimeFilterOpenPGP *openpgp)
+{
+ g_return_val_if_fail (GMIME_IS_FILTER_OPENPGP (openpgp), -1);
+
+ return openpgp->begin_offset;
+}
+
+
+/**
+ * g_mime_filter_openpgp_get_end_offset:
+ * @openpgp: A #GMimeFilterOpenPGP filter
+ *
+ * Gets the stream offset of the end of the OpenPGP data block, if any have been found.
+ *
+ * Returns: The stream offset or %-1 if no OpenPGP block was found.
+ **/
+gint64
+g_mime_filter_openpgp_get_end_offset (GMimeFilterOpenPGP *openpgp)
+{
+ g_return_val_if_fail (GMIME_IS_FILTER_OPENPGP (openpgp), -1);
+
+ return openpgp->end_offset;
+}
diff --git a/gmime/gmime-filter-openpgp.h b/gmime/gmime-filter-openpgp.h
new file mode 100644
index 0000000..accdac2
--- /dev/null
+++ b/gmime/gmime-filter-openpgp.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* GMime
+ * Copyright (C) 2000-2017 Jeffrey Stedfast
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+
+#ifndef __GMIME_FILTER_OPENPGP_H__
+#define __GMIME_FILTER_OPENPGP_H__
+
+#include <gmime/gmime-filter.h>
+
+G_BEGIN_DECLS
+
+#define GMIME_TYPE_FILTER_OPENPGP (g_mime_filter_openpgp_get_type ())
+#define GMIME_FILTER_OPENPGP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMIME_TYPE_FILTER_OPENPGP,
GMimeFilterOpenPGP))
+#define GMIME_FILTER_OPENPGP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMIME_TYPE_FILTER_OPENPGP,
GMimeFilterOpenPGPClass))
+#define GMIME_IS_FILTER_OPENPGP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMIME_TYPE_FILTER_OPENPGP))
+#define GMIME_IS_FILTER_OPENPGP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMIME_TYPE_FILTER_OPENPGP))
+#define GMIME_FILTER_OPENPGP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMIME_TYPE_FILTER_OPENPGP,
GMimeFilterOpenPGPClass))
+
+typedef struct _GMimeFilterOpenPGP GMimeFilterOpenPGP;
+typedef struct _GMimeFilterOpenPGPClass GMimeFilterOpenPGPClass;
+
+
+/**
+ * GMimeOpenPGPData:
+ * @GMIME_OPENPGP_DATA_NONE: No OpenPGP data found.
+ * @GMIME_OPENPGP_DATA_ENCRYPTED: The content contains OpenPGP encrypted data.
+ * @GMIME_OPENPGP_DATA_SIGNED: The content contains OpenPGP signed data.
+ * @GMIME_OPENPGP_DATA_PUBLIC_KEY: The content contains OpenPGP public key data.
+ * @GMIME_OPENPGP_DATA_PRIVATE_KEY: The content contains OpenPGP private key data.
+ *
+ * The type of OpenPGP data found, if any.
+ **/
+typedef enum {
+ GMIME_OPENPGP_DATA_NONE,
+ GMIME_OPENPGP_DATA_ENCRYPTED,
+ GMIME_OPENPGP_DATA_SIGNED,
+ GMIME_OPENPGP_DATA_PUBLIC_KEY,
+ GMIME_OPENPGP_DATA_PRIVATE_KEY
+} GMimeOpenPGPData;
+
+
+/**
+ * GMimeOpenPGPState:
+ * @GMIME_OPENPGP_NONE: No OpenPGP markers have been found (yet).
+ * @GMIME_OPENPGP_BEGIN_PGP_MESSAGE: The "-----BEGIN PGP MESSAGE-----" marker has been found.
+ * @GMIME_OPENPGP_END_PGP_MESSAGE: The "-----END PGP MESSAGE-----" marker has been found.
+ * @GMIME_OPENPGP_BEGIN_PGP_SIGNED_MESSAGE: The "-----BEGIN PGP SIGNED MESSAGE-----" marker has been found.
+ * @GMIME_OPENPGP_BEGIN_PGP_SIGNATURE: The "-----BEGIN PGP SIGNATURE-----" marker has been found.
+ * @GMIME_OPENPGP_END_PGP_SIGNATURE: The "-----END PGP SIGNATURE-----" marker has been found.
+ * @GMIME_OPENPGP_BEGIN_PGP_PUBLIC_KEY_BLOCK: The "-----BEGIN PGP PUBLIC KEY BLOCK-----" marker has been
found.
+ * @GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK: The "-----END PGP PUBLIC KEY BLOCK-----" marker has been found.
+ * @GMIME_OPENPGP_BEGIN_PGP_PRIVATE_KEY_BLOCK: The "-----BEGIN PGP PRIVATE KEY BLOCK-----" marker has been
found.
+ * @GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK: The "-----END PGP PRIVATE KEY BLOCK-----" marker has been found.
+ *
+ * The current state of the #GMimeFilterOpenPGP filter.
+ **/
+typedef enum {
+ GMIME_OPENPGP_NONE = 0,
+ GMIME_OPENPGP_BEGIN_PGP_MESSAGE = (1 << 0),
+ GMIME_OPENPGP_END_PGP_MESSAGE = (1 << 1) | (1 << 0),
+ GMIME_OPENPGP_BEGIN_PGP_SIGNED_MESSAGE = (1 << 2),
+ GMIME_OPENPGP_BEGIN_PGP_SIGNATURE = (1 << 3) | (1 << 2),
+ GMIME_OPENPGP_END_PGP_SIGNATURE = (1 << 4) | (1 << 3) | (1 << 2),
+ GMIME_OPENPGP_BEGIN_PGP_PUBLIC_KEY_BLOCK = (1 << 5),
+ GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK = (1 << 6) | (1 << 5),
+ GMIME_OPENPGP_BEGIN_PGP_PRIVATE_KEY_BLOCK = (1 << 7),
+ GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK = (1 << 8) | (1 << 7)
+} GMimeOpenPGPState;
+
+typedef struct {
+ const char *marker;
+ size_t len;
+ GMimeOpenPGPState before;
+ GMimeOpenPGPState after;
+ gboolean is_end_marker;
+} GMimeOpenPGPMarker;
+
+/**
+ * GMimeFilterOpenPGP:
+ * @parent_object: parent #GMimeFilter
+ *
+ * A filter to detect OpenPGP markers.
+ **/
+struct _GMimeFilterOpenPGP {
+ GMimeFilter parent_object;
+
+ /* < private > */
+ GMimeOpenPGPState state;
+ gboolean seen_end_marker;
+ gboolean midline;
+ gint64 begin_offset;
+ gint64 end_offset;
+ gint64 position;
+ guint next;
+};
+
+struct _GMimeFilterOpenPGPClass {
+ GMimeFilterClass parent_class;
+
+};
+
+
+GType g_mime_filter_openpgp_get_type (void);
+
+GMimeFilter *g_mime_filter_openpgp_new (void);
+
+GMimeOpenPGPData g_mime_filter_openpgp_get_data_type (GMimeFilterOpenPGP *openpgp);
+gint64 g_mime_filter_openpgp_get_begin_offset (GMimeFilterOpenPGP *openpgp);
+gint64 g_mime_filter_openpgp_get_end_offset (GMimeFilterOpenPGP *openpgp);
+
+G_END_DECLS
+
+#endif /* __GMIME_FILTER_OPENPGP_H__ */
diff --git a/gmime/gmime-parser.c b/gmime/gmime-parser.c
index 3cde304..7dbb0c1 100644
--- a/gmime/gmime-parser.c
+++ b/gmime/gmime-parser.c
@@ -59,29 +59,7 @@
* into multiple #GMimeMessage objects.
**/
-typedef enum {
- OPENPGP_NONE = 0,
- OPENPGP_BEGIN_PGP_MESSAGE = (1 << 0),
- OPENPGP_END_PGP_MESSAGE = (1 << 1) | (1 << 0),
- OPENPGP_BEGIN_PGP_SIGNED_MESSAGE = (1 << 2),
- OPENPGP_BEGIN_PGP_SIGNATURE = (1 << 3) | (1 << 2),
- OPENPGP_END_PGP_SIGNATURE = (1 << 4) | (1 << 3) | (1 << 2)
-} openpgp_state_t;
-
-typedef struct {
- const char *marker;
- size_t len;
- openpgp_state_t before;
- openpgp_state_t after;
-} GMimeOpenPGPMarker;
-
-static const GMimeOpenPGPMarker openpgp_markers[] = {
- { "-----BEGIN PGP MESSAGE-----", 27, OPENPGP_NONE,
OPENPGP_BEGIN_PGP_MESSAGE },
- { "-----END PGP MESSAGE-----", 25, OPENPGP_BEGIN_PGP_MESSAGE, OPENPGP_END_PGP_MESSAGE
},
- { "-----BEGIN PGP SIGNED MESSAGE-----", 34, OPENPGP_NONE,
OPENPGP_BEGIN_PGP_SIGNED_MESSAGE },
- { "-----BEGIN PGP SIGNATURE-----", 29, OPENPGP_BEGIN_PGP_SIGNED_MESSAGE,
OPENPGP_BEGIN_PGP_SIGNATURE },
- { "-----END PGP SIGNATURE-----", 27, OPENPGP_BEGIN_PGP_SIGNATURE,
OPENPGP_END_PGP_SIGNATURE }
-};
+extern const GMimeOpenPGPMarker g_mime_openpgp_markers[9];
typedef enum {
BOUNDARY_NONE,
@@ -188,7 +166,7 @@ struct _GMimeParserPrivate {
BoundaryStack *bounds;
- openpgp_state_t openpgp;
+ GMimeOpenPGPState openpgp;
short int state;
unsigned short int midline:1;
@@ -403,7 +381,7 @@ parser_init (GMimeParser *parser, GMimeStream *stream)
priv->header_offset = -1;
- priv->openpgp = OPENPGP_NONE;
+ priv->openpgp = GMIME_OPENPGP_NONE;
priv->midline = FALSE;
priv->seekable = offset != -1;
@@ -1414,13 +1392,13 @@ check_boundary (struct _GMimeParserPrivate *priv, const char *start, size_t len)
len -= 2;
/* check for OpenPGP markers... */
- for (i = 0; i < G_N_ELEMENTS (openpgp_markers); i++) {
- const char *pgp_marker = openpgp_markers[i].marker + 2;
- openpgp_state_t state = openpgp_markers[i].before;
- size_t n = openpgp_markers[i].len - 2;
+ for (i = 0; i < G_N_ELEMENTS (g_mime_openpgp_markers); i++) {
+ const char *pgp_marker = g_mime_openpgp_markers[i].marker + 2;
+ GMimeOpenPGPState state = g_mime_openpgp_markers[i].before;
+ size_t n = g_mime_openpgp_markers[i].len - 2;
if (len == n && priv->openpgp == state && !strncmp (pgp_marker, start, len))
- priv->openpgp = openpgp_markers[i].after;
+ priv->openpgp = g_mime_openpgp_markers[i].after;
}
}
@@ -1473,7 +1451,7 @@ parser_scan_content (GMimeParser *parser, GMimeStream *content, gboolean *empty)
d(printf ("scan-content\n"));
- priv->openpgp = OPENPGP_NONE;
+ priv->openpgp = GMIME_OPENPGP_NONE;
priv->midline = FALSE;
g_assert (priv->inptr <= priv->inend);
@@ -1619,10 +1597,22 @@ parser_scan_mime_part_content (GMimeParser *parser, GMimePart *mime_part, Bounda
g_mime_part_set_content (mime_part, content);
g_object_unref (content);
- if (priv->openpgp == OPENPGP_END_PGP_SIGNATURE)
+ switch (priv->openpgp) {
+ case GMIME_OPENPGP_END_PGP_SIGNATURE:
g_mime_part_set_openpgp_data (mime_part, GMIME_OPENPGP_DATA_SIGNED);
- else if (priv->openpgp == OPENPGP_END_PGP_MESSAGE)
+ break;
+ case GMIME_OPENPGP_END_PGP_MESSAGE:
g_mime_part_set_openpgp_data (mime_part, GMIME_OPENPGP_DATA_ENCRYPTED);
+ break;
+ case GMIME_OPENPGP_END_PGP_PUBLIC_KEY_BLOCK:
+ g_mime_part_set_openpgp_data (mime_part, GMIME_OPENPGP_DATA_PUBLIC_KEY);
+ break;
+ case GMIME_OPENPGP_END_PGP_PRIVATE_KEY_BLOCK:
+ g_mime_part_set_openpgp_data (mime_part, GMIME_OPENPGP_DATA_PRIVATE_KEY);
+ break;
+ default:
+ break;
+ }
}
static void
diff --git a/gmime/gmime-part.h b/gmime/gmime-part.h
index d2f720d..c5c1dfa 100644
--- a/gmime/gmime-part.h
+++ b/gmime/gmime-part.h
@@ -28,6 +28,7 @@
#include <gmime/gmime-object.h>
#include <gmime/gmime-encodings.h>
#include <gmime/gmime-filter-best.h>
+#include <gmime/gmime-filter-openpgp.h>
#include <gmime/gmime-data-wrapper.h>
#include <gmime/gmime-crypto-context.h>
@@ -44,20 +45,6 @@ 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
diff --git a/gmime/gmime.h b/gmime/gmime.h
index 9c524e0..6c20968 100644
--- a/gmime/gmime.h
+++ b/gmime/gmime.h
@@ -71,6 +71,7 @@
#include <gmime/gmime-filter-from.h>
#include <gmime/gmime-filter-gzip.h>
#include <gmime/gmime-filter-html.h>
+#include <gmime/gmime-filter-openpgp.h>
#include <gmime/gmime-filter-smtp-data.h>
#include <gmime/gmime-filter-strip.h>
#include <gmime/gmime-filter-unix2dos.h>
diff --git a/tests/test-pgp.c b/tests/test-pgp.c
index b3f7c2d..3f7811c 100644
--- a/tests/test-pgp.c
+++ b/tests/test-pgp.c
@@ -329,12 +329,29 @@ import_key (GMimeCryptoContext *ctx, const char *path)
}
}
+static void
+pump_data_through_filter (GMimeFilter *filter, const char *path)
+{
+ GMimeStream *filtered, *stream;
+
+ stream = g_mime_stream_null_new ();
+ filtered = g_mime_stream_filter_new (stream);
+ g_object_unref (stream);
+
+ g_mime_stream_filter_add ((GMimeStreamFilter *) filtered, filter);
+
+ stream = g_mime_stream_fs_open (path, O_RDONLY, 0644, NULL);
+ g_mime_stream_write_to_stream (stream, filtered);
+ g_object_unref (filtered);
+ g_object_unref (stream);
+}
int main (int argc, char **argv)
{
#ifdef ENABLE_CRYPTO
const char *datadir = "data/pgp";
GMimeStream *istream, *ostream;
+ GMimeFilterOpenPGP *filter;
GMimeCryptoContext *ctx;
const char *what;
char *gpg, *key;
@@ -482,6 +499,48 @@ int main (int argc, char **argv)
g_object_unref (ostream);
g_object_unref (ctx);
+ what = "GMimeFilterOpenPGP";
+ testsuite_check ("%s", what);
+ try {
+ gint64 offset;
+
+ filter = (GMimeFilterOpenPGP *) g_mime_filter_openpgp_new ();
+
+ key = g_build_filename (datadir, "gmime.gpg.pub", NULL);
+ pump_data_through_filter ((GMimeFilter *) filter, key);
+ g_free (key);
+
+ if (g_mime_filter_openpgp_get_data_type (filter) != GMIME_OPENPGP_DATA_PUBLIC_KEY)
+ throw (exception_new ("Failed to detect public key block"));
+
+ if ((offset = g_mime_filter_openpgp_get_begin_offset (filter)) != 0)
+ throw (exception_new ("Incorrect public key block begin offset: %ld", (long) offset));
+
+ if ((offset = g_mime_filter_openpgp_get_end_offset (filter)) != 1690)
+ throw (exception_new ("Incorrect public key block end offset: %ld", (long) offset));
+
+ g_mime_filter_reset ((GMimeFilter *) filter);
+
+ key = g_build_filename (datadir, "gmime.gpg.sec", NULL);
+ pump_data_through_filter ((GMimeFilter *) filter, key);
+ g_free (key);
+
+ if (g_mime_filter_openpgp_get_data_type (filter) != GMIME_OPENPGP_DATA_PRIVATE_KEY)
+ throw (exception_new ("Failed to detect private key block"));
+
+ if ((offset = g_mime_filter_openpgp_get_begin_offset (filter)) != 0)
+ throw (exception_new ("Incorrect private key block begin offset: %ld", (long)
offset));
+
+ if ((offset = g_mime_filter_openpgp_get_end_offset (filter)) != 1895)
+ throw (exception_new ("Incorrect private key block end offset: %ld", (long) offset));
+
+ testsuite_check_passed ();
+ } catch (ex) {
+ testsuite_check_failed ("%s failed: %s", what, ex->message);
+ } finally;
+
+ g_object_unref (filter);
+
testsuite_end ();
g_mime_shutdown ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]