[git] GpgOL - branch, master, updated. gpgol-1.4.0-191-ga0326ff

by Andre Heinecke cvs at cvs.gnupg.org
Wed Nov 30 15:55:29 CET 2016


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG extension for MS Outlook".

The branch, master has been updated
       via  a0326ffb755c4a49a259cea3d83831d9ede7d5d9 (commit)
       via  d46db5899b99bae5a82218bfb361b5d8767f380a (commit)
       via  94c354a0845ba4f1e29e4bc8b9d8fc4e3b8081dc (commit)
      from  5b34e853a15baba47a8983e5430069a0a37bcb81 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a0326ffb755c4a49a259cea3d83831d9ede7d5d9
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Wed Nov 30 15:34:11 2016 +0100

    Support sending embedded images(multipart/related)
    
    * src/mimemaker.cpp (add_body_and_attachments): New. Common
    multipart handling for the encrypt / sign functions.
    * src/mimemaker.cpp (mime_encrypt, do_mime_sign):
    Use add_body_and_attachments.
    (is_related): New. Check if we have a multipart/related.
    (write_attachments): Allow to filter out related attachments.
    (write_part): Write Content-ID if there is one.
    * src/mymapitags.h (PR_ATTACH_CONTENT_ID): New.
    
    --
    This enables multipart/related and multipart/mixed with a
    multipart/related subpart.

diff --git a/src/mimemaker.cpp b/src/mimemaker.cpp
index cfc2abb..18bc271 100644
--- a/src/mimemaker.cpp
+++ b/src/mimemaker.cpp
@@ -846,7 +846,8 @@ utf8_to_rfc2047b (const char *input)
    retrieved from the body property.  */
 static int
 write_part (sink_t sink, const char *data, size_t datalen,
-            const char *boundary, const char *filename, int is_mapibody)
+            const char *boundary, const char *filename, int is_mapibody,
+            const char *content_id = NULL)
 {
   int rc;
   const char *ct;
@@ -926,7 +927,14 @@ write_part (sink_t sink, const char *data, size_t datalen,
                                NULL)))
     return rc;
 
-  if (encoded_filename)
+  if (content_id)
+    {
+      if ((rc=write_multistring (sink,
+                                 "Content-ID: <", content_id, ">\r\n",
+                                 NULL)))
+        return rc;
+    }
+  else if (encoded_filename)
     if ((rc=write_multistring (sink,
                                "Content-Disposition: attachment;\r\n"
                                "\tfilename=\"", encoded_filename, "\"\r\n",
@@ -967,11 +975,13 @@ count_usable_attachments (mapi_attach_item_t *table)
 }
 
 /* Write out all attachments from TABLE separated by BOUNDARY to SINK.
-   This function needs to be syncronized with count_usable_attachments.  */
+   This function needs to be syncronized with count_usable_attachments.
+   If only_related is 1 only include attachments for multipart/related they
+   are excluded otherwise. */
 static int
 write_attachments (sink_t sink,
                    LPMESSAGE message, mapi_attach_item_t *table,
-                   const char *boundary)
+                   const char *boundary, int only_related)
 {
   int idx, rc;
   char *buffer;
@@ -982,6 +992,14 @@ write_attachments (sink_t sink,
       if (table[idx].attach_type == ATTACHTYPE_UNKNOWN
           && table[idx].method == ATTACH_BY_VALUE)
         {
+          if (only_related && !table[idx].content_id)
+            {
+              continue;
+            }
+          else if (!only_related && table[idx].content_id)
+            {
+              continue;
+            }
           buffer = mapi_get_attach (message, 0, table+idx, &buflen);
           if (!buffer)
             log_debug ("Attachment at index %d not found\n", idx);
@@ -990,7 +1008,7 @@ write_attachments (sink_t sink,
           if (!buffer)
             return -1;
           rc = write_part (sink, buffer, buflen, boundary,
-                           table[idx].filename, 0);
+                           table[idx].filename, 0, table[idx].content_id);
           if (rc)
             {
               log_error ("Write part returned err: %i", rc);
@@ -1000,6 +1018,31 @@ write_attachments (sink_t sink,
   return 0;
 }
 
+/* Returns 1 if all attachments are related. 2 if there is a
+   related and a mixed attachment. 0 if there are no other parts*/
+static int
+is_related (Mail *mail, mapi_attach_item_t *table)
+{
+  if (!mail || !mail->is_html_alternative () || !table)
+    {
+      return 0;
+    }
+
+  int related = 0;
+  int mixed = 0;
+  for (int idx = 0; !table[idx].end_of_table; idx++)
+    {
+      if (table[idx].content_id)
+        {
+          related = 1;
+        }
+      else
+        {
+          mixed = 1;
+        }
+    }
+  return mixed + related;
+}
 
 
 /* Delete all attachments from TABLE except for the one we just created */
@@ -1313,6 +1356,98 @@ add_body (Mail *mail, const char *boundary, sink_t sink,
   return write_boundary (sink, alt_boundary, 1);
 }
 
+/* Add the body and attachments. Does multipart handling. */
+static int
+add_body_and_attachments (sink_t sink, LPMESSAGE message,
+                          mapi_attach_item_t *att_table, Mail *mail,
+                          const char *body, int n_att_usable)
+{
+  int related = is_related (mail, att_table);
+  int rc = 0;
+  char inner_boundary[BOUNDARYSIZE+1];
+  char outer_boundary[BOUNDARYSIZE+1];
+
+  if (((body && n_att_usable) || n_att_usable > 1) && related == 1)
+    {
+      /* A body and at least one attachment or more than one attachment  */
+      generate_boundary (outer_boundary);
+      if ((rc=write_multistring (sink,
+                                 "Content-Type: multipart/related;\r\n",
+                                 "\tboundary=\"", outer_boundary, "\"\r\n",
+                                 NULL)))
+        return rc;
+    }
+  else if ((body && n_att_usable) || n_att_usable > 1)
+    {
+      generate_boundary (outer_boundary);
+      if ((rc=write_multistring (sink,
+                                 "Content-Type: multipart/mixed;\r\n",
+                                 "\tboundary=\"", outer_boundary, "\"\r\n",
+                                 NULL)))
+        return rc;
+    }
+  else
+  /* Only one part.  */
+    *outer_boundary = 0;
+
+  if (*outer_boundary && related == 2)
+    {
+      /* We have attachments that are related to the body and unrelated
+         attachments. So we need another part. */
+      if ((rc=write_boundary (sink, outer_boundary, 0)))
+        {
+          return rc;
+        }
+      generate_boundary (inner_boundary);
+      if ((rc=write_multistring (sink,
+                                 "Content-Type: multipart/related;\r\n",
+                                 "\tboundary=\"", inner_boundary, "\"\r\n",
+                                 NULL)))
+        {
+          return rc;
+        }
+    }
+  else
+    {
+      *inner_boundary = 0;
+    }
+
+
+  if ((rc=add_body (mail, *inner_boundary ? inner_boundary : outer_boundary,
+                    sink, body)))
+    {
+      log_error ("%s:%s: Adding the body failed.",
+                 SRCNAME, __func__);
+      return rc;
+    }
+  if (!rc && n_att_usable && related)
+    {
+      /* Write the related attachments. */
+      rc = write_attachments (sink, message, att_table,
+                              *inner_boundary? inner_boundary :
+                              *outer_boundary? outer_boundary : NULL, 1);
+      if (rc)
+        {
+          return rc;
+        }
+      /* Close the related part if neccessary.*/
+      if (*inner_boundary && (rc=write_boundary (sink, inner_boundary, 1)))
+        {
+          return rc;
+        }
+    }
+
+  /* Now write the other attachments */
+  if (!rc && n_att_usable)
+    rc = write_attachments (sink, message, att_table,
+                            *outer_boundary? outer_boundary : NULL, 0);
+
+  /* Finish the possible multipart/mixed. */
+  if (*outer_boundary && (rc = write_boundary (sink, outer_boundary, 1)))
+    return rc;
+
+  return rc;
+}
 
 /* Main body of mime_sign without the the code to delete the original
    attachments.  On success the function returns the current
@@ -1333,7 +1468,6 @@ do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
   struct sink_s hashsinkmem;
   sink_t hashsink = &hashsinkmem;
   char boundary[BOUNDARYSIZE+1];
-  char inner_boundary[BOUNDARYSIZE+1];
   mapi_attach_item_t *att_table = NULL;
   char *body = NULL;
   int n_att_usable;
@@ -1412,13 +1546,6 @@ do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
   if ((rc = write_string (sink, top_header)))
     goto failure;
 
-  /* Create the inner boundary if we have a body and at least one
-     attachment or more than one attachment.  */
-  if ((body && n_att_usable) || n_att_usable > 1)
-    generate_boundary (inner_boundary);
-  else
-    *inner_boundary = 0;
-
   /* Write the boundary so that it is not included in the hashing.  */
   if ((rc = write_boundary (sink, boundary, 0)))
     goto failure;
@@ -1428,37 +1555,14 @@ do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
   hashsink->extrasink = sink;
   hashsink->writefnc = sink_hashing_write;
 
-  /* Note that OL2003 will add an extra line after the multipart
-     header, thus we do the same to avoid running all through an
-     IConverterSession first. */
-  if (*inner_boundary
-      && (rc=write_multistring (hashsink,
-                                "Content-Type: multipart/mixed;\r\n",
-                                "\tboundary=\"", inner_boundary, "\"\r\n",
-                                "\r\n",  /* <-- extra line */
-                                NULL)))
-        goto failure;
-
-  if ((rc=add_body (mail, inner_boundary, hashsink, body)))
-    {
-      log_error ("%s:%s: Adding the body failed.",
-                 SRCNAME, __func__);
-      goto failure;
-    }
-
-  if (!rc && n_att_usable)
-    rc = write_attachments (hashsink, message, att_table,
-                            *inner_boundary? inner_boundary : NULL);
-  if (rc)
+  /* Add the plaintext */
+  if (add_body_and_attachments (hashsink, message, att_table, mail,
+                                body, n_att_usable))
     goto failure;
 
   xfree (body);
   body = NULL;
 
-  /* Finish the possible multipart/mixed. */
-  if (*inner_boundary && (rc = write_boundary (hashsink, inner_boundary, 1)))
-    goto failure;
-
   /* Here we are ready with the hashing.  Flush the filter and wait
      for the signing process to finish.  */
   if ((rc = write_buffer (hashsink, NULL, 0)))
@@ -1790,7 +1894,6 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
   struct sink_s encsinkmem;
   sink_t encsink = &encsinkmem;
   char boundary[BOUNDARYSIZE+1];
-  char inner_boundary[BOUNDARYSIZE+1];
   mapi_attach_item_t *att_table = NULL;
   char *body = NULL;
   int n_att_usable;
@@ -1861,38 +1964,14 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
   encsink->cb_data = filter;
   encsink->writefnc = sink_encryption_write;
 
-  if ((body && n_att_usable) || n_att_usable > 1)
-    {
-      /* A body and at least one attachment or more than one attachment  */
-      generate_boundary (inner_boundary);
-      if ((rc=write_multistring (encsink,
-                                 "Content-Type: multipart/mixed;\r\n",
-                                 "\tboundary=\"", inner_boundary, "\"\r\n",
-                                 NULL)))
-        goto failure;
-    }
-  else /* Only one part.  */
-    *inner_boundary = 0;
-
-  if ((rc=add_body (mail, inner_boundary, encsink, body)))
-    {
-      log_error ("%s:%s: Adding the body failed.",
-                 SRCNAME, __func__);
-      goto failure;
-    }
-  if (!rc && n_att_usable)
-    rc = write_attachments (encsink, message, att_table,
-                            *inner_boundary? inner_boundary : NULL);
-  if (rc)
+  /* Add the plaintext */
+  if (add_body_and_attachments (encsink, message, att_table, mail,
+                                body, n_att_usable))
     goto failure;
 
   xfree (body);
   body = NULL;
 
-  /* Finish the possible multipart/mixed. */
-  if (*inner_boundary && (rc = write_boundary (encsink, inner_boundary, 1)))
-    goto failure;
-
   /* Flush the encryption sink and wait for the encryption to get
      ready.  */
   if ((rc = write_buffer (encsink, NULL, 0)))
diff --git a/src/mymapitags.h b/src/mymapitags.h
index c2d6e4f..9232c37 100644
--- a/src/mymapitags.h
+++ b/src/mymapitags.h
@@ -513,6 +513,7 @@
 #define PR_ATTACH_MIME_TAG_W                    PROP_TAG( PT_UNICODE,   0x370E)
 #define PR_ATTACH_MIME_TAG_A                    PROP_TAG( PT_STRING8,   0x370E)
 #define PR_ATTACH_ADDITIONAL_INFO               PROP_TAG( PT_BINARY,    0x370F)
+#define PR_ATTACH_CONTENT_ID                    PROP_TAG( PT_UNICODE,   0x3712)
 #define PR_DISPLAY_TYPE                         PROP_TAG( PT_LONG,      0x3900)
 #define PR_TEMPLATEID                           PROP_TAG( PT_BINARY,    0x3902)
 #define PR_PRIMARY_CAPABILITY                   PROP_TAG( PT_BINARY,    0x3904)

commit d46db5899b99bae5a82218bfb361b5d8767f380a
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Wed Nov 30 15:30:55 2016 +0100

    Add content_id to our attach table
    
    * src/common_indep.h (mapi_attach_item_t): Extend with
    content_id.
    * src/mapihelp.cpp (get_attach_content_id): New.
    (mapi_create_attach_table): Use it.
    (mapi_release_attach_table): Free it.

diff --git a/src/common_indep.h b/src/common_indep.h
index ec7f026..a5c04f3 100644
--- a/src/common_indep.h
+++ b/src/common_indep.h
@@ -141,6 +141,9 @@ struct mapi_attach_item_s
   /* If not NULL the parameters of the content_type. */
   const char *content_type_parms;
 
+  /* If not NULL the content_id */
+  char *content_id;
+
   /* The attachment type from Property GpgOL Attach Type.  */
   attachtype_t attach_type;
 };
diff --git a/src/mapihelp.cpp b/src/mapihelp.cpp
index 2ebe333..de325c5 100644
--- a/src/mapihelp.cpp
+++ b/src/mapihelp.cpp
@@ -1996,6 +1996,44 @@ get_attach_filename (LPATTACH obj)
   return name;
 }
 
+/* Return the content-id of the attachment OBJ or NULL if it does
+   not exists.  Caller must free. */
+static char *
+get_attach_content_id (LPATTACH obj)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  char *name;
+
+  hr = HrGetOneProp ((LPMAPIPROP)obj, PR_ATTACH_CONTENT_ID, &propval);
+  if (FAILED (hr))
+    {
+      if (hr != MAPI_E_NOT_FOUND)
+        log_error ("%s:%s: error getting attachment's MIME tag: hr=%#lx",
+                   SRCNAME, __func__, hr);
+      return NULL;
+    }
+  switch ( PROP_TYPE (propval->ulPropTag) )
+    {
+    case PT_UNICODE:
+      name = wchar_to_utf8 (propval->Value.lpszW);
+      if (!name)
+        log_debug ("%s:%s: error converting to utf8\n", SRCNAME, __func__);
+      break;
+
+    case PT_STRING8:
+      name = xstrdup (propval->Value.lpszA);
+      break;
+
+    default:
+      log_debug ("%s:%s: proptag=%#lx not supported\n",
+                 SRCNAME, __func__, propval->ulPropTag);
+      name = NULL;
+      break;
+    }
+  MAPIFreeBuffer (propval);
+  return name;
+}
 
 /* Return the content-type of the attachment OBJ or NULL if it does
    not exists.  Caller must free. */
@@ -2140,6 +2178,7 @@ mapi_create_attach_table (LPMESSAGE message, int fast)
       table[pos].method = get_attach_method (att);
       table[pos].filename = fast? NULL : get_attach_filename (att);
       table[pos].content_type = fast? NULL : get_attach_mime_tag (att);
+      table[pos].content_id = fast? NULL : get_attach_content_id (att);
       if (table[pos].content_type)
         {
           char *p = strchr (table[pos].content_type, ';');
@@ -2200,6 +2239,7 @@ mapi_release_attach_table (mapi_attach_item_t *table)
     {
       xfree (table[pos].filename);
       xfree (table[pos].content_type);
+      xfree (table[pos].content_id);
     }
   xfree (table);
 }

commit 94c354a0845ba4f1e29e4bc8b9d8fc4e3b8081dc
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Wed Nov 30 15:29:19 2016 +0100

    Fix content type detection
    
    * src/mimemaker.cpp (infer_content_type): Fix it.
    
    --
    This never worked because the tolower did not increase the
    suffix pointer and just filled the buffer with the first letter
    of the suffix.
    
    Now we have c++ we can simplify the tolower.

diff --git a/src/mimemaker.cpp b/src/mimemaker.cpp
index b7bd1e5..cfc2abb 100644
--- a/src/mimemaker.cpp
+++ b/src/mimemaker.cpp
@@ -681,24 +681,25 @@ infer_content_type (const char * /*data*/, size_t /*datalen*/,
       { 0, NULL, NULL }
     };
   int i;
-  char suffix_buffer[12+1];
-  const char *suffix;
+  std::string suffix;
 
   *force_b64 = 0;
-  suffix = filename? strrchr (filename, '.') : NULL;
-  if (suffix && strlen (suffix) < sizeof suffix_buffer -1 )
+  if (filename)
+    suffix = strrchr (filename, '.');
+
+  if (!suffix.empty())
     {
-      suffix++;
-      for (i=0; i < sizeof suffix_buffer - 1; i++)
-        suffix_buffer[i] = tolower (*(const unsigned char*)suffix);
-      suffix_buffer[i] = 0;
+      suffix.erase(0, 1);
+      std::transform(suffix.begin(), suffix.end(), suffix.begin(), ::tolower);
       for (i=0; suffix_table[i].suffix; i++)
-        if (!strcmp (suffix_table[i].suffix, suffix_buffer))
-          {
-            if (suffix_table[i].b64)
-              *force_b64 = 1;
-            return suffix_table[i].ct;
-          }
+        {
+          if (!strcmp (suffix_table[i].suffix, suffix.c_str()))
+            {
+              if (suffix_table[i].b64)
+                *force_b64 = 1;
+              return suffix_table[i].ct;
+            }
+        }
     }
 
   /* Not found via filename, look at the content.  */

-----------------------------------------------------------------------

Summary of changes:
 src/common_indep.h |   3 +
 src/mapihelp.cpp   |  40 +++++++++
 src/mimemaker.cpp  | 242 +++++++++++++++++++++++++++++++++++------------------
 src/mymapitags.h   |   1 +
 4 files changed, 205 insertions(+), 81 deletions(-)


hooks/post-receive
-- 
GnuPG extension for MS Outlook
http://git.gnupg.org




More information about the Gnupg-commits mailing list