Fix / improve inline PGP decryption
authorAndre Heinecke <aheinecke@intevation.de>
Wed, 14 Dec 2016 16:04:08 +0000 (17:04 +0100)
committerAndre Heinecke <aheinecke@intevation.de>
Wed, 14 Dec 2016 16:05:43 +0000 (17:05 +0100)
* src/mapihelp.cpp (change_message_class_ipm_note): Look for
PGP Lines even without content type.
* src/mimedataprovider.cpp (MimeDataProvider::write): Respect
m_collect_everything.
* src/parsecontroller.cpp (ParseController::ParseController): Don't
expect MIME headers for inline pgp data.
(expect_no_mime): New.

src/mapihelp.cpp
src/mimedataprovider.cpp
src/parsecontroller.cpp

index 92def26..eb23503 100644 (file)
@@ -959,41 +959,37 @@ change_message_class_ipm_note (LPMESSAGE message)
   char *ct, *proto;
 
   ct = mapi_get_message_content_type (message, &proto, NULL);
-  if (ct)
+  log_debug ("%s:%s: content type is '%s'", SRCNAME, __func__,
+             ct ? ct : "null");
+  if (ct && proto)
     {
-      log_debug ("%s:%s: content type is '%s'", SRCNAME, __func__, ct);
-      if (proto)
+      log_debug ("%s:%s:     protocol is '%s'", SRCNAME, __func__, proto);
+
+      if (!strcmp (ct, "multipart/encrypted")
+          && !strcmp (proto, "application/pgp-encrypted"))
         {
-          log_debug ("%s:%s:     protocol is '%s'", SRCNAME, __func__, proto);
-          
-          if (!strcmp (ct, "multipart/encrypted")
-              && !strcmp (proto, "application/pgp-encrypted"))
-            {
-              newvalue = xstrdup ("IPM.Note.GpgOL.MultipartEncrypted");
-            }
-          else if (!strcmp (ct, "multipart/signed")
-                   && !strcmp (proto, "application/pgp-signature"))
-            {
-              /* Sometimes we receive a PGP/MIME signed message with a
-                 class IPM.Note.  */
-              newvalue = xstrdup ("IPM.Note.GpgOL.MultipartSigned");
-            }
-          xfree (proto);
+          newvalue = xstrdup ("IPM.Note.GpgOL.MultipartEncrypted");
         }
-      else if (!strcmp (ct, "text/plain") ||
-               !strcmp (ct, "multipart/mixed") ||
-               !strcmp (ct, "multipart/alternative"))
+      else if (!strcmp (ct, "multipart/signed")
+               && !strcmp (proto, "application/pgp-signature"))
         {
-          /* It is quite common to have a multipart/mixed or alternative
-             mail with separate encrypted PGP parts.  Look at the body to
-             decide.  */
-          newvalue = get_msgcls_from_pgp_lines (message);
+          /* Sometimes we receive a PGP/MIME signed message with a
+             class IPM.Note.  */
+          newvalue = xstrdup ("IPM.Note.GpgOL.MultipartSigned");
         }
-
-      xfree (ct);
+      xfree (proto);
     }
-  else
-    log_debug ("%s:%s: message has no content type", SRCNAME, __func__);
+  else if (!ct || !strcmp (ct, "text/plain") ||
+           !strcmp (ct, "multipart/mixed") ||
+           !strcmp (ct, "multipart/alternative"))
+    {
+      /* It is quite common to have a multipart/mixed or alternative
+         mail with separate encrypted PGP parts.  Look at the body to
+         decide.  */
+      newvalue = get_msgcls_from_pgp_lines (message);
+    }
+
+  xfree (ct);
 
   return newvalue;
 }
index f0273cf..9ae3e2d 100644 (file)
@@ -833,21 +833,30 @@ MimeDataProvider::collect_data(FILE *stream)
 
 ssize_t MimeDataProvider::write(const void *buffer, size_t bufSize)
 {
-    m_rawbuf += std::string ((const char*)buffer, bufSize);
-    size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
-                                            m_rawbuf.size());
-
-    if (not_taken == m_rawbuf.size())
-      {
-        log_error ("%s:%s: Write failed to consume anything.\n"
-                   "Buffer too small? or no newlines in text?",
-                   SRCNAME, __func__);
-        return bufSize;
-      }
-    log_mime_parser ("%s:%s: Write Consumed: " SIZE_T_FORMAT " bytes",
-                     SRCNAME, __func__, m_rawbuf.size() - not_taken);
-    m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
-    return bufSize;
+  if (m_collect_everything)
+    {
+      /* Writing with collect everything one means that we are outputprovider.
+         In this case for inline messages we want to collect everything. */
+      log_mime_parser ("%s:%s: Using complete input as body " SIZE_T_FORMAT " bytes.",
+                       SRCNAME, __func__, bufSize);
+      m_body += std::string ((const char *) buffer, bufSize);
+      return bufSize;
+    }
+  m_rawbuf += std::string ((const char*)buffer, bufSize);
+  size_t not_taken = collect_input_lines (m_rawbuf.c_str(),
+                                          m_rawbuf.size());
+
+  if (not_taken == m_rawbuf.size())
+    {
+      log_error ("%s:%s: Write failed to consume anything.\n"
+                 "Buffer too small? or no newlines in text?",
+                 SRCNAME, __func__);
+      return bufSize;
+    }
+  log_mime_parser ("%s:%s: Write Consumed: " SIZE_T_FORMAT " bytes",
+                   SRCNAME, __func__, m_rawbuf.size() - not_taken);
+  m_rawbuf.erase (0, m_rawbuf.size() - not_taken);
+  return bufSize;
 }
 
 off_t
index f0ddfaa..f053d87 100644 (file)
@@ -64,22 +64,31 @@ expect_no_headers (msgtype_t type)
   return type != MSGTYPE_GPGOL_MULTIPART_SIGNED;
 }
 
+static bool
+expect_no_mime (msgtype_t type)
+{
+  return type == MSGTYPE_GPGOL_PGP_MESSAGE ||
+         type == MSGTYPE_GPGOL_CLEAR_SIGNED;
+}
+
 #ifdef HAVE_W32_SYSTEM
 ParseController::ParseController(LPSTREAM instream, msgtype_t type):
     m_inputprovider  (new MimeDataProvider(instream,
                           expect_no_headers(type))),
-    m_outputprovider (new MimeDataProvider()),
+    m_outputprovider (new MimeDataProvider(expect_no_mime(type))),
     m_type (type)
 {
-  log_mime_parser ("%s:%s: Creating parser for stream: %p of type %i",
-                   SRCNAME, __func__, instream, type);
+  log_mime_parser ("%s:%s: Creating parser for stream: %p of type %i"
+                   " expect headers: %i expect no mime: %i",
+                   SRCNAME, __func__, instream, type,
+                   expect_no_headers (type), expect_no_mime (type));
 }
 #endif
 
 ParseController::ParseController(FILE *instream, msgtype_t type):
     m_inputprovider  (new MimeDataProvider(instream,
                           expect_no_headers(type))),
-    m_outputprovider (new MimeDataProvider()),
+    m_outputprovider (new MimeDataProvider(expect_no_mime(type))),
     m_type (type)
 {
   log_mime_parser ("%s:%s: Creating parser for stream: %p of type %i",