[git] GpgOL - branch, master, updated. gpgol-1.4.0-187-g9dde244

by Andre Heinecke cvs at cvs.gnupg.org
Tue Nov 29 18:01:38 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  9dde24462c2ef34b215d0eb8d9ca1cced7cee222 (commit)
       via  4989c5e0aeb2d31576d6df653c2fec2056b3ff32 (commit)
      from  f9efc49ffaf5302b680c17ef0eede636b62319e1 (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 9dde24462c2ef34b215d0eb8d9ca1cced7cee222
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Nov 29 18:01:19 2016 +0100

    Support HTML sending and fix sender updates
    
    * src/mail.cpp (Mail::Mail): Update init.
    (Mail::get_sender): Sender is now a string.
    (Mail::encrypt_sign): Update accordingly.
    (Mail::update_sender): Changed to update_oom_data.
    (Mail::update_oom_data): More generic. Caches BodyFormat,
    HTMLBody and sender. Changed order for sender retrieval
    when composing mails.
    (Mail::update_sigstate): Update accordingly.
    (Mail::is_html_alternative, Mail::get_cached_html_body): New.
    * src/mail.h: Update accordingly.
    * src/mailitem-events.cpp (EVENT_SINK_INVOKE): Update oom data
    on send.
    * src/mimemaker.cpp (create_mapi_attachment): Fix another use
    after free.
    (infer_content_type): is_mapibody now defines text/html or
    text/plain. The naive content deduction is removed.
    (add_body): Handler for the HTML / multipart body.
    (do_mime_sign, mime_encrypt): Use add_body.
    (mime_sign, mime_sign_encrypt): Pass on mail object.
    
    --
    We now send multipart/alternative mails in case HTML or RichText
    is selected as body format. This is the way outlook does it, too.
    
    The sender update fix is a bit mushed in as this is now all
    update_oom_data.

diff --git a/src/mail.cpp b/src/mail.cpp
index b294f16..55800fc 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -76,8 +76,8 @@ Mail::Mail (LPDISPATCH mailitem) :
     m_is_signed(false),
     m_is_valid(false),
     m_close_triggered(false),
+    m_is_html_alternative(false),
     m_moss_position(0),
-    m_sender(NULL),
     m_type(MSGTYPE_UNKNOWN)
 {
   if (get_mail_for_item (mailitem))
@@ -130,7 +130,6 @@ Mail::~Mail()
         }
     }
 
-  xfree (m_sender);
   gpgol_release(m_mailitem);
   if (!m_uuid.empty())
     {
@@ -724,17 +723,17 @@ Mail::encrypt_sign ()
       log_debug ("%s:%s: Sign / Encrypting message",
                  SRCNAME, __func__);
       err = message_sign_encrypt (message, proto,
-                                  NULL, get_sender (), this);
+                                  NULL, get_sender ().c_str (), this);
     }
   else if (flags == 2)
     {
       err = message_sign (message, proto,
-                          NULL, get_sender (), this);
+                          NULL, get_sender ().c_str (), this);
     }
   else if (flags == 1)
     {
       err = message_encrypt (message, proto,
-                             NULL, get_sender (), this);
+                             NULL, get_sender ().c_str (), this);
     }
   else
     {
@@ -790,34 +789,51 @@ Mail::wipe ()
 }
 
 int
-Mail::update_sender ()
+Mail::update_oom_data ()
 {
   LPDISPATCH sender = NULL;
+  log_debug ("%s:%s", SRCNAME, __func__);
 
-  /* For some reason outlook my store the recipient address
+  /* Update the body format. */
+  m_is_html_alternative = get_oom_int (m_mailitem, "BodyFormat") > 1;
+
+  /* Store the body. It was not obvious for me (aheinecke) how
+     to access this through MAPI. */
+  m_html_body = get_oom_string (m_mailitem, "HTMLBody");
+
+  /* For some reason outlook may store the recipient address
      in the send using account field. If we have SMTP we prefer
      the SenderEmailAddress string. */
-  char *type = get_oom_string (m_mailitem, "SenderEmailType");
-  if (type && !strcmp ("SMTP", type))
+
+  if (is_crypto_mail ())
     {
-      xfree (type);
-      char *senderMail = get_oom_string (m_mailitem, "SenderEmailAddress");
-      if (senderMail)
+      /* This is the case where we are reading a mail and not composing.
+         When composing we need to use the SendUsingAccount because if
+         you send from the folder of userA but change the from to userB
+         outlook will keep the SenderEmailAddress of UserA. This is all
+         so horrible. */
+      char *type = get_oom_string (m_mailitem, "SenderEmailType");
+      if (type && !strcmp ("SMTP", type))
         {
-          xfree (m_sender);
-          m_sender = senderMail;
-          return 0;
+          char *senderMail = get_oom_string (m_mailitem, "SenderEmailAddress");
+          if (senderMail)
+            {
+              m_sender = senderMail;
+              log_debug ("Sender %i is now: %s",__LINE__, m_sender.c_str());
+              xfree (senderMail);
+              xfree (type);
+              return 0;
+            }
         }
+      xfree (type);
     }
-  xfree (type);
-
   sender = get_oom_object (m_mailitem, "SendUsingAccount");
-  xfree (m_sender);
-  m_sender = NULL;
-
   if (sender)
     {
-      m_sender = get_oom_string (sender, "SmtpAddress");
+      char *buf = get_oom_string (sender, "SmtpAddress");
+      m_sender = buf;
+          log_debug ("Sender %i is now: %s",__LINE__, m_sender.c_str());
+      xfree (buf);
       gpgol_release (sender);
       return 0;
     }
@@ -825,7 +841,10 @@ Mail::update_sender ()
   sender = get_oom_object (m_mailitem, "Sender");
   if (sender)
     {
-      m_sender = get_pa_string (sender, PR_SMTP_ADDRESS_DASL);
+      char *buf = get_pa_string (sender, PR_SMTP_ADDRESS_DASL);
+      m_sender = buf;
+          log_debug ("Sender %i is now: %s",__LINE__, m_sender.c_str());
+      xfree (buf);
       gpgol_release (sender);
       return 0;
     }
@@ -834,23 +853,24 @@ Mail::update_sender ()
   sender = get_oom_object (m_mailitem, "Session.CurrentUser");
   if (sender)
     {
-      m_sender = get_pa_string (sender, PR_SMTP_ADDRESS_DASL);
+      char *buf = get_pa_string (sender, PR_SMTP_ADDRESS_DASL);
+      m_sender = buf;
+          log_debug ("Sender %i is now: %s",__LINE__, m_sender.c_str());
+      xfree (buf);
       gpgol_release (sender);
       return 0;
     }
 
-  log_error ("%s:%s: All fallbacks failed.",
+  log_debug ("%s:%s: All fallbacks failed.",
              SRCNAME, __func__);
   return -1;
 }
 
-const char *
+std::string
 Mail::get_sender ()
 {
-  if (!m_sender)
-    {
-      update_sender();
-    }
+  if (m_sender.empty())
+    update_oom_data();
   return m_sender;
 }
 
@@ -1146,9 +1166,9 @@ get_uid_for_sender (const Key k, const char *sender)
 void
 Mail::update_sigstate ()
 {
-  const char *sender = get_sender();
+  std::string sender = get_sender();
 
-  if (!sender)
+  if (sender.empty())
     {
       log_error ("%s:%s:%i", SRCNAME, __func__, __LINE__);
       return;
@@ -1178,7 +1198,7 @@ Mail::update_sigstate ()
           /* For our category we only care about trusted sigs. */
           continue;
         }
-      const auto uid = get_uid_for_sender (sig.key(), sender);
+      const auto uid = get_uid_for_sender (sig.key(), sender.c_str());
       if (sig.validity() == Signature::Validity::Marginal)
         {
           const auto tofu = uid.tofuInfo();
@@ -1429,7 +1449,7 @@ Mail::get_signature_status()
                   + std::string(" ");
         }
 
-      const auto uid = get_uid_for_sender (sig.key(), get_sender());
+      const auto uid = get_uid_for_sender (sig.key(), get_sender().c_str());
       /* Now the key problems */
       if ((sig.summary() & Signature::Summary::KeyMissing))
         {
@@ -1462,7 +1482,7 @@ Mail::get_signature_status()
       else if (uid.isNull())
         {
           gpgrt_asprintf (&buf, _("does not claim the address: \"%s\"."),
-                          get_sender());
+                          get_sender().c_str());
           message += buf;
           xfree (buf);
         }
@@ -1599,3 +1619,15 @@ void Mail::locate_keys()
     }
   xfree (recipients);
 }
+
+bool
+Mail::is_html_alternative () const
+{
+  return m_is_html_alternative;
+}
+
+const std::string &
+Mail::get_cached_html_body () const
+{
+  return m_html_body;
+}
diff --git a/src/mail.h b/src/mail.h
index 3ca144a..7eddf34 100644
--- a/src/mail.h
+++ b/src/mail.h
@@ -162,15 +162,20 @@ public:
    * @returns 0 on success; */
   int revert ();
 
-  /** @brief update the sender address.
+  /** @brief update some data collected from the oom
+   *
+   * This updates cached values from the OOM that are not available
+   * in MAPI events like after Write.
    *
    * For Exchange 2013 at least we don't have any other way to get the
    * senders SMTP address then through the object model. So we have to
    * store the sender address for later events that do not allow us to
    * access the OOM but enable us to work with the underlying MAPI structure.
    *
+   * It also updated the is_html_alternative value.
+   *
    * @returns 0 on success */
-  int update_sender ();
+  int update_oom_data ();
 
   /** @brief get sender SMTP address (UTF-8 encoded).
    *
@@ -178,7 +183,7 @@ public:
    * calls update_sender before returning the sender.
    *
    * @returns A reference to the utf8 sender address. Or NULL. */
-  const char *get_sender ();
+  std::string get_sender ();
 
   /** @brief get the subject string (UTF-8 encoded).
     *
@@ -287,6 +292,13 @@ public:
   /** State variable to check if a close was triggerd by us. */
   void set_close_triggered (bool value);
   bool get_close_triggered () const;
+
+  /** Check if the mail should be sent as html alternative mail.
+    Only valid if update_oom_data was called before. */
+  bool is_html_alternative () const;
+
+  /** Get the html body. It is updated in update_oom_data. */
+  const std::string & get_cached_html_body () const;
 private:
   void update_categories ();
   void update_body ();
@@ -302,9 +314,11 @@ private:
        m_is_smime_checked, /* it was checked if this is an smime mail */
        m_is_signed, /* Mail is signed */
        m_is_valid, /* Mail is valid signed. */
-       m_close_triggered; /* We have programtically triggered a close */
+       m_close_triggered, /* We have programtically triggered a close */
+       m_is_html_alternative; /* Body Format is not plain text */
   int m_moss_position; /* The number of the original message attachment. */
-  char *m_sender;
+  std::string m_sender;
+  std::string m_html_body; /* Cached html body. */
   msgtype_t m_type; /* Our messagetype as set in mapi */
   std::shared_ptr <ParseController> m_parser;
   GpgME::VerificationResult m_verify_result;
diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index ca16bd7..101e2a8 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -306,7 +306,7 @@ EVENT_SINK_INVOKE(MailItemEvents)
                         SRCNAME, __func__);
              break;
            }
-          m_mail->update_sender ();
+          m_mail->update_oom_data ();
           m_send_seen = true;
           invoke_oom_method (m_object, "Save", NULL);
           if (m_mail->crypto_successful ())
diff --git a/src/mimemaker.cpp b/src/mimemaker.cpp
index a9e9aa6..2b98192 100644
--- a/src/mimemaker.cpp
+++ b/src/mimemaker.cpp
@@ -42,6 +42,7 @@
 #include "mimemaker.h"
 #include "oomhelp.h"
 #include "gpgolstr.h"
+#include "mail.h"
 
 static const unsigned char oid_mimetag[] =
     {0x2A, 0x86, 0x48, 0x86, 0xf7, 0x14, 0x03, 0x0a, 0x04};
@@ -207,8 +208,9 @@ create_mapi_attachment (LPMESSAGE message, sink_t sink)
   if (!hr)
     {
       prop.ulPropTag = PR_ATTACH_MIME_TAG_A;
-      prop.Value.lpszA = GpgOLStr("multipart/signed");
+      prop.Value.lpszA = strdup("multipart/signed");
       hr = HrSetOneProp ((LPMAPIPROP)att, &prop);
+      xfree (prop.Value.lpszA);
     }
   if (hr)
     {
@@ -558,14 +560,14 @@ write_plain (sink_t sink, const void *data, size_t datalen)
 }
 
 
-/* Infer the conent type from DATA and FILENAME.  The return value is
+/* Infer the conent type from the FILENAME.  The return value is
    a static string there won't be an error return.  In case Bae 64
    encoding is required for the type true will be stored at FORCE_B64;
    however, this is only a shortcut and if that is not set, the caller
-   should infer the encoding by otehr means. */
+   should infer the encoding by other means. */
 static const char *
-infer_content_type (const char *data, size_t datalen, const char *filename,
-                    int is_mapibody, int *force_b64)
+infer_content_type (const char * /*data*/, size_t /*datalen*/,
+                    const char *filename, int is_mapibody, int *force_b64)
 {
   static struct {
     char b64;
@@ -701,15 +703,14 @@ infer_content_type (const char *data, size_t datalen, const char *filename,
 
   /* Not found via filename, look at the content.  */
 
-  if (is_mapibody)
+  if (is_mapibody == 1)
     {
-      /* Fixme:  This is too simple. */
-      if (datalen > 6  && (!memcmp (data, "<html>", 6)
-                           ||!memcmp (data, "<HTML>", 6)))
-        return "text/html";
       return "text/plain";
     }
-
+  else if (is_mapibody == 2)
+    {
+      return "text/html";
+    }
   return "application/octet-stream";
 }
 
@@ -1225,6 +1226,85 @@ create_top_signing_header (char *buffer, size_t buflen, protocol_t protocol,
             micalg, boundary);
 }
 
+/* Add the body, either as multipart/alternative or just as the
+  simple body part. Depending on the format set in outlook. To
+  avoid memory duplication it takes the plain body as parameter.
+
+  Boundary is the potential outer boundary of a multipart/mixed
+  mail. If it is null we assume the multipart/alternative is
+  the only part.
+
+  return is zero on success.
+*/
+static int
+add_body (Mail *mail, const char *boundary, sink_t sink,
+          const char *plain_body)
+{
+  if (!plain_body)
+    {
+      return 0;
+    }
+  bool is_alternative = false;
+  if (mail)
+    {
+      is_alternative = mail->is_html_alternative ();
+    }
+
+  int rc = 0;
+  if (!is_alternative || !plain_body)
+    {
+      if (plain_body)
+        {
+          rc = write_part (sink, plain_body, strlen (plain_body),
+                           *boundary? boundary : NULL, NULL, 1);
+        }
+      /* Just the plain body or no body. We are done. */
+      return rc;
+    }
+
+  /* Now for the multipart/alternative part. We never do HTML only. */
+  char alt_boundary [BOUNDARYSIZE+1];
+  generate_boundary (alt_boundary);
+
+  if ((rc=write_multistring (sink,
+                            "Content-Type: multipart/alternative;\r\n",
+                            "\tboundary=\"", alt_boundary, "\"\r\n",
+                            "\r\n",  /* <-- extra line */
+                            NULL)))
+    {
+      TRACEPOINT;
+      return rc;
+    }
+
+  /* Now the plain body part */
+  if ((rc = write_part (sink, plain_body, strlen (plain_body),
+                       alt_boundary, NULL, 1)))
+    {
+      TRACEPOINT;
+      return rc;
+    }
+
+  /* Now the html body. It is somehow not accessible through PR_HTML,
+     OutlookSpy also shows MAPI Unsported (but shows the data) strange.
+     We just cache it. Memory is cheap :-) */
+  const auto html_body = mail->get_cached_html_body();
+  if (html_body.empty())
+    {
+      log_error ("%s:%s: BUG: Body but no html body in alternative mail?",
+                 SRCNAME, __func__);
+    }
+
+  rc = write_part (sink, html_body.c_str(), html_body.size(),
+                   alt_boundary, NULL, 2);
+  if (rc)
+    {
+      TRACEPOINT;
+      return rc;
+    }
+  /* Finish our multipart */
+  return write_boundary (sink, alt_boundary, 1);
+}
+
 
 /* Main body of mime_sign without the the code to delete the original
    attachments.  On success the function returns the current
@@ -1234,7 +1314,8 @@ create_top_signing_header (char *buffer, size_t buflen, protocol_t protocol,
 static int
 do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
               mapi_attach_item_t **r_att_table, sink_t tmpsink,
-              unsigned int session_number, const char *sender)
+              unsigned int session_number, const char *sender,
+              Mail *mail)
 {
   int result = -1;
   int rc;
@@ -1350,10 +1431,13 @@ do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
                                 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 (body)
-    rc = write_part (hashsink, body, strlen (body),
-                     *inner_boundary? inner_boundary : NULL, NULL, 1);
   if (!rc && n_att_usable)
     rc = write_attachments (hashsink, message, att_table,
                             *inner_boundary? inner_boundary : NULL);
@@ -1497,13 +1581,13 @@ do_mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
    it. */
 int
 mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol,
-           const char *sender, Mail *)
+           const char *sender, Mail *mail)
 {
   int result = -1;
   mapi_attach_item_t *att_table;
 
   result = do_mime_sign (message, hwnd, protocol, &att_table, 0,
-                         engine_new_session_number (), sender);
+                         engine_new_session_number (), sender, mail);
   if (!result)
     {
       if (!finalize_message (message, att_table, protocol, 0))
@@ -1688,7 +1772,7 @@ create_top_encryption_header (sink_t sink, protocol_t protocol, char *boundary)
 int
 mime_encrypt (LPMESSAGE message, HWND hwnd,
               protocol_t protocol, char **recipients,
-              const char *sender, Mail*)
+              const char *sender, Mail* mail)
 {
   int result = -1;
   int rc;
@@ -1782,9 +1866,12 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
   else /* Only one part.  */
     *inner_boundary = 0;
 
-  if (body)
-    rc = write_part (encsink, body, strlen (body),
-                     *inner_boundary? inner_boundary : NULL, NULL, 1);
+  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);
@@ -1841,7 +1928,7 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
 int
 mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
                    protocol_t protocol, char **recipients,
-                   const char *sender, Mail*)
+                   const char *sender, Mail *mail)
 {
   int result = -1;
   int rc = 0;
@@ -1950,7 +2037,7 @@ mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
      the signature.  Note that the protocol to use is taken from the
      encryption operation. */
   if (do_mime_sign (message, hwnd, protocol, &att_table, tmpsink,
-                    session_number, sender))
+                    session_number, sender, mail))
     goto failure;
 
   /* Now send the actual ENCRYPT command.  This split up between

commit 4989c5e0aeb2d31576d6df653c2fec2056b3ff32
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Nov 29 17:51:26 2016 +0100

    Ignore more property changes
    
    * src/mailitem-events.cpp (prop_blacklist): Add OutlookVersion
    and OutlookInternalVersion.
    
    --
    For mails imported from the filesystem outlook changed these
    properties.

diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index 33b48e9..ca16bd7 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -39,6 +39,8 @@ const wchar_t *prop_blacklist[] = {
   L"BCC", /* Ditto */
   L"Categories",
   L"UnRead",
+  L"OutlookVersion",
+  L"OutlookInternalVersion",
   NULL };
 
 typedef enum

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

Summary of changes:
 src/mail.cpp            | 100 +++++++++++++++++++++++-------------
 src/mail.h              |  24 +++++++--
 src/mailitem-events.cpp |   4 +-
 src/mimemaker.cpp       | 133 +++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 198 insertions(+), 63 deletions(-)


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




More information about the Gnupg-commits mailing list