New encrypted message are now viewable in the setn messages folder.
authorWerner Koch <wk@gnupg.org>
Fri, 11 Jan 2008 17:41:55 +0000 (17:41 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 11 Jan 2008 17:41:55 +0000 (17:41 +0000)
12 files changed:
NEWS
src/ChangeLog
src/ext-commands.cpp
src/item-events.cpp
src/mapihelp.cpp
src/mapihelp.h
src/message-events.cpp
src/message.cpp
src/message.h
src/mimemaker.c
src/olflange.cpp
src/olflange.h

diff --git a/NEWS b/NEWS
index b4708ea..af411cc 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Noteworthy changes for version 0.10.4
 
  * Texts with embedded attachments are now concatenated.
 
+ * Encrypted message are now viewable in the sent messages folder.
+
 
 Noteworthy changes for version 0.10.3 (2007-12-10)
 ==================================================
index bbe29ae..b7853ee 100644 (file)
@@ -1,3 +1,28 @@
+2008-01-11  Werner Koch  <wk@g10code.com>
+
+       * mimemaker.c (finalize_message): Add args PROTOCOL and ENCRYPT
+       and use them to set the override message class.
+       (mime_sign, mime_encrypt, mime_sign_encrypt): Pass this info via
+       the new args.
+       * message.cpp (message_decrypt): Add hack fro seldgenerated messages.
+
+2008-01-10  Werner Koch  <wk@g10code.com>
+
+       * mapihelp.cpp (get_gpgolmsgclass_tag, mapi_set_gpgol_msg_class):
+       New.
+       (mapi_change_message_class, mapi_get_message_type): Try override
+       first.
+
+       * message.cpp (message_incoming_handler): Remove arg MSGTYE and
+       let the function retrieve it.  Changed all callers.  Retry after a
+       sucessful message class change.
+       * olflange.cpp (getMsgtype): Remove.  The caching might lead to
+       problems and makes it all more complex.  Changed all callers to
+       use mapi_get_message_type.
+       
+       * mimemaker.c (create_top_encryption_header) <SMIME>: Write empty
+       line after header.
+
 2008-01-09  Werner Koch  <wk@g10code.com>
 
        * mimeparser.c (finish_saved_body): New.
index 119069c..7966783 100644 (file)
@@ -412,18 +412,28 @@ GpgolExtCommands::InstallCommands (
   if (m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
       int need_dvm = 0;
+      LPMDB mdb = NULL;
+      LPMESSAGE message = NULL;
 
-      switch (m_pExchExt->getMsgtype (eecb))
+      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (FAILED(hr))
+        log_debug ("%s:%s: getObject failed: hr=%#lx\n", SRCNAME, __func__, hr);
+      else
         {
-        case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
-        case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
-        case MSGTYPE_GPGOL_PGP_MESSAGE:
-          need_dvm = 1;
-          break;
-        default:
-          break;
+          switch (mapi_get_message_type (message))
+            {
+            case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
+            case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
+            case MSGTYPE_GPGOL_PGP_MESSAGE:
+              need_dvm = 1;
+              break;
+            default:
+              break;
+            }
         }
-
+      ul_release (message, __func__, __LINE__);
+      ul_release (mdb, __func__, __LINE__);
+      
       /* We always enable the verify button as it might be useful on
          an already decrypted message. */
       add_menu (eecb, pnCommandIDBase,
@@ -586,7 +596,7 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
       hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
-          message_decrypt (message, m_pExchExt->getMsgtype (eecb), 1, hwnd);
+          message_decrypt (message, mapi_get_message_type (message), 1, hwnd);
           message_display_handler (eecb, hwnd);
        }
       ul_release (message, __func__, __LINE__);
@@ -599,7 +609,7 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
       hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
-          message_verify (message, m_pExchExt->getMsgtype (eecb), 1, hwnd);
+          message_verify (message, mapi_get_message_type (message), 1, hwnd);
        }
       else
         log_debug_w32 (hr, "%s:%s: CmdCheckSig failed", SRCNAME, __func__);
index 7e83061..806671a 100644 (file)
@@ -106,7 +106,7 @@ GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK eecb)
 
   m_wasencrypted = false;
   eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-  if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb), hwnd))
+  if (message_incoming_handler (message, hwnd))
     m_processed = TRUE;
   ul_release (message);
   ul_release (mdb);
index df8ad04..9b87cf5 100644 (file)
 #include "serpent.h"
 #include "mapihelp.h"
 
+#ifndef CRYPT_E_STREAM_INSUFFICIENT_DATA
+#define CRYPT_E_STREAM_INSUFFICIENT_DATA 0x80091011
+#endif
+#ifndef CRYPT_E_ASN1_BADTAG
+#define CRYPT_E_ASN1_BADTAG 0x8009310B
+#endif
+
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
@@ -120,6 +127,16 @@ create_gpgol_tag (LPMESSAGE message, wchar_t *name, const char *func)
 }
 
 
+/* Return the property tag for GpgOL Msg Class. */
+int 
+get_gpgolmsgclass_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Msg Class", __func__)))
+    return -1;
+  *r_tag |= PT_STRING8;
+  return 0;
+}
+
 
 /* Return the property tag for GpgOL Attach Type. */
 int 
@@ -474,6 +491,7 @@ int
 mapi_change_message_class (LPMESSAGE message)
 {
   HRESULT hr;
+  ULONG tag;
   SPropValue prop;
   LPSPropValue propval = NULL;
   char *newvalue = NULL;
@@ -482,13 +500,22 @@ mapi_change_message_class (LPMESSAGE message)
   if (!message)
     return 0; /* No message: Nop. */
 
-  hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
+  if (get_gpgolmsgclass_tag (message, &tag) )
+    return 0; /* Ooops. */
+
+  hr = HrGetOneProp ((LPMAPIPROP)message, tag, &propval);
   if (FAILED (hr))
     {
-      log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
-                 SRCNAME, __func__, hr);
-      return 0;
+      hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
+      if (FAILED (hr))
+        {
+          log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
+                     SRCNAME, __func__, hr);
+          return 0;
+        }
     }
+  else
+    log_debug ("%s:%s: have override message class\n", SRCNAME, __func__);
     
   if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 )
     {
@@ -663,7 +690,7 @@ mapi_change_message_class (LPMESSAGE message)
 
 
 /* Return the message class.  This function will never return NULL so
-   it is onlyuseful for debugging.  Caller needs to releasse the
+   it is only useful for debugging.  Caller needs to release the
    returned string.  */
 char *
 mapi_get_message_class (LPMESSAGE message)
@@ -703,19 +730,31 @@ msgtype_t
 mapi_get_message_type (LPMESSAGE message)
 {
   HRESULT hr;
+  ULONG tag;
   LPSPropValue propval = NULL;
   msgtype_t msgtype = MSGTYPE_UNKNOWN;
 
   if (!message)
     return msgtype; 
 
-  hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
+  if (get_gpgolmsgclass_tag (message, &tag) )
+    return msgtype; /* Ooops */
+
+  hr = HrGetOneProp ((LPMAPIPROP)message, tag, &propval);
   if (FAILED (hr))
     {
-      log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
+      log_error ("%s:%s: HrGetOneProp(GpgOLMsgClass) failed: hr=%#lx\n",
                  SRCNAME, __func__, hr);
-      return msgtype;
+      hr = HrGetOneProp ((LPMAPIPROP)message, PR_MESSAGE_CLASS_A, &propval);
+      if (FAILED (hr))
+        {
+          log_error ("%s:%s: HrGetOneProp() failed: hr=%#lx\n",
+                     SRCNAME, __func__, hr);
+          return msgtype;
+        }
     }
+  else
+    log_debug ("%s:%s: have override message class\n", SRCNAME, __func__);
     
   if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 )
     {
@@ -1477,6 +1516,35 @@ mapi_set_sig_status (LPMESSAGE message, const char *status_string)
 }
 
 
+/* When sending a message we need to fake the message class so that OL
+   processes it according to our needs.  However, if we later try to
+   get the message class from the sent message, OL still has the SMIME
+   message class and tries to hide this by trying to decrypt the
+   message and return the message class from the plaintext.  To
+   mitigate the problem we define our own msg class override
+   property.  */
+int 
+mapi_set_gpgol_msg_class (LPMESSAGE message, const char *name)
+{
+  HRESULT hr;
+  SPropValue prop;
+
+  if (get_gpgolmsgclass_tag (message, &prop.ulPropTag) )
+    return -1;
+  prop.Value.lpszA = xstrdup (name);
+  hr = HrSetOneProp (message, &prop);  
+  xfree (prop.Value.lpszA);
+  if (hr)
+    {
+      log_error ("%s:%s: can't set %s property: hr=%#lx\n",
+                 SRCNAME, __func__, "GpgOL Msg Class", hr); 
+      return -1;
+    }
+
+  return 0;
+}
+
+
 /* Return the MIME info as an allocated string.  Will never return
    NULL.  */
 char *
index abf6789..23a5232 100644 (file)
@@ -114,6 +114,8 @@ char *mapi_get_sig_status (LPMESSAGE msg);
 
 int mapi_set_sig_status (LPMESSAGE message, const char *status_string);
 
+int mapi_set_gpgol_msg_class (LPMESSAGE message, const char *name);
+
 char *mapi_get_mime_info (LPMESSAGE msg);
 
 char *mapi_get_message_content_type (LPMESSAGE message, 
index 69f7d10..63e3504 100644 (file)
@@ -116,8 +116,7 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
       if (FAILED (eecb->GetWindow (&hwnd)))
         hwnd = NULL;
       eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-      if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb),
-                                    hwnd))
+      if (message_incoming_handler (message, hwnd))
         m_processed = true;
       ul_release (message, __func__, __LINE__);
       ul_release (mdb, __func__, __LINE__);
index f136d98..610d44e 100644 (file)
@@ -1,5 +1,5 @@
 /* message.cpp - Functions for message handling
- *     Copyright (C) 2006, 2007 g10 Code GmbH
+ *     Copyright (C) 2006, 2007, 2008 g10 Code GmbH
  * 
  * This file is part of GpgOL.
  * 
@@ -53,10 +53,15 @@ ul_release (LPVOID punk, const char *func)
 /* A helper function used by OnRead and OnOpen to dispatch the
    message.  Returns true if the message has been processed.  */
 bool
-message_incoming_handler (LPMESSAGE message,msgtype_t msgtype, HWND hwnd)
+message_incoming_handler (LPMESSAGE message, HWND hwnd)
 {
   bool retval = false;
+  msgtype_t msgtype;
+  int pass = 0;
 
+ retry:
+  pass++;
+  msgtype = mapi_get_message_type (message);
   switch (msgtype)
     {
     case MSGTYPE_UNKNOWN: 
@@ -68,19 +73,21 @@ message_incoming_handler (LPMESSAGE message,msgtype_t msgtype, HWND hwnd)
          been set.  Note that we should have similar code for some
          message classes in GpgolUserEvents:OnSelectionChange; but
          tehre are a couiple of problems.  */
-      if (!mapi_has_sig_status (message))
+      if (pass == 1 && !mapi_has_sig_status (message))
         {
           log_debug ("%s:%s: message class not yet checked - doing now\n",
                      SRCNAME, __func__);
-          mapi_change_message_class (message);
+          if (mapi_change_message_class (message))
+            goto retry;
         }
       break;
     case MSGTYPE_SMIME:
-      if (opt.enable_smime)
+      if (pass == 1 && opt.enable_smime)
         {
           log_debug ("%s:%s: message class not checked with smime enabled "
                      "- doing now\n", SRCNAME, __func__);
-          mapi_change_message_class (message);
+          if (mapi_change_message_class (message))
+            goto retry;
         }
       break;
     case MSGTYPE_GPGOL:
@@ -634,7 +641,17 @@ message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force, HWND hwnd)
              identify it by its order.  */
           part2_idx = -1;
           for (tblidx=0; !table[tblidx].end_of_table; tblidx++)
-            if (table[tblidx].attach_type == ATTACHTYPE_MOSS)
+            if (table[tblidx].attach_type == ATTACHTYPE_MOSSTEMPL)
+              {
+                /* This attachment has been generated by us in the
+                   course of sendeing a new message.  The content will
+                   be multipart/signed because we used this to trick
+                   out OL.  We stop here and use this part for further
+                   processing.  */
+                part2_idx = tblidx;
+                break;
+              }
+            else if (table[tblidx].attach_type == ATTACHTYPE_MOSS)
               {
                 if (part2_idx == -1 && table[tblidx].content_type 
                     && (!strcmp (table[tblidx].content_type,
index a4f482d..f0b6e87 100644 (file)
@@ -21,8 +21,7 @@
 #define MESSAGE_H
 
 
-bool message_incoming_handler (LPMESSAGE message, msgtype_t msgtype,
-                               HWND hwnd);
+bool message_incoming_handler (LPMESSAGE message, HWND hwnd);
 bool message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd);
 void message_wipe_body_cruft (LPEXCHEXTCALLBACK eecb);
 void message_show_info (LPMESSAGE message, HWND hwnd);
index 44afcec..0c268af 100644 (file)
@@ -1013,7 +1013,8 @@ cancel_mapi_attachment (LPATTACH *attach, sink_t sink)
 
 /* Do the final processing for a message. */
 static int
-finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table)
+finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table,
+                  protocol_t protocol, int encrypt)
 {
   HRESULT hr;
   SPropValue prop;
@@ -1034,6 +1035,17 @@ finalize_message (LPMESSAGE message, mapi_attach_item_t *att_table)
   if (mapi_set_sig_status (message, "@"))
     return -1;
 
+  /* We also need to set the message class into our custom
+     property. This override is at leas required for encrypted
+     messages.  */
+  if (mapi_set_gpgol_msg_class (message,
+                                (encrypt? 
+                                 (protocol == PROTOCOL_SMIME? 
+                                  "IPM.Note.GpgOL.OpaqueEncrypted" :
+                                  "IPM.Note.GpgOL.MultipartEncrypted") :
+                                 "IPM.Note.GpgOL.MultipartSigned")))
+    return -1;
+
   /* Now delete all parts of the MAPI message except for the one
      attachment we just created.  */
   if (delete_all_attachments (message, att_table))
@@ -1365,7 +1377,7 @@ mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol)
 
   if (!do_mime_sign (message, hwnd, protocol, &att_table, 0))
     {
-      if (!finalize_message (message, att_table))
+      if (!finalize_message (message, att_table, protocol, 0))
         result = 0;
     }
 
@@ -1503,7 +1515,8 @@ create_top_encryption_header (sink_t sink, protocol_t protocol, char *boundary)
                               "Content-Type: application/pkcs7-mime;\r\n"
                               "\tsmime-type=enveloped-data;\r\n"
                               "\tname=\"smime.p7m\"\r\n"
-                              "Content-Transfer-Encoding: base64\r\n",
+                              "Content-Transfer-Encoding: base64\r\n"
+                              "\r\n",
                               NULL);
     }
   else
@@ -1649,7 +1662,7 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
   if (close_mapi_attachment (&attach, sink))
     goto failure;
 
-  if (finalize_message (message, att_table))
+  if (finalize_message (message, att_table, protocol, 1))
     goto failure;
 
   result = 0;  /* Everything is fine, fall through the cleanup now.  */
@@ -1795,7 +1808,7 @@ mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
   if (close_mapi_attachment (&attach, sink))
     goto failure;
 
-  if (finalize_message (message, att_table))
+  if (finalize_message (message, att_table, protocol, 1))
     goto failure;
 
   result = 0;  /* Everything is fine, fall through the cleanup now.  */
index 1dc952c..691ded2 100644 (file)
@@ -95,17 +95,17 @@ ext_context_name (unsigned long no)
 
 
 /* Wrapper around UlRelease with error checking. */
-static void 
-ul_release (LPVOID punk, const char *func)
-{
-  ULONG res;
+// static void 
+// ul_release (LPVOID punk, const char *func)
+// {
+//   ULONG res;
   
-  if (!punk)
-    return;
-  res = UlRelease (punk);
-  log_debug ("%s:%s: UlRelease(%p) had %lu references\n", 
-             SRCNAME, func, punk, res);
-}
+//   if (!punk)
+//     return;
+//   res = UlRelease (punk);
+//   log_debug ("%s:%s: UlRelease(%p) had %lu references\n", 
+//              SRCNAME, func, punk, res);
+// }
 
 
 \f
@@ -290,8 +290,6 @@ GpgolExt::GpgolExt (void)
   m_protoSelection = PROTOCOL_UNKNOWN;
   m_gpgEncrypt = FALSE;
   m_gpgSign = FALSE;
-  msgtype = MSGTYPE_UNKNOWN;
-  msgtype_valid = FALSE;
 
   m_pExchExtCommands           = new GpgolExtCommands (this);
   m_pExchExtUserEvents         = new GpgolUserEvents (this);
@@ -511,34 +509,3 @@ GpgolExt::Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags)
   log_debug ("%s:%s: can't handle this context\n", SRCNAME, __func__);
   return S_FALSE;
 }
-
-
-/* Return the message type for the current message.  EECB needs to be
-   passed to allow access to the message object.  The function caches
-   the message class so there is no overhead in calling this
-   method. */
-msgtype_t 
-GpgolExt::getMsgtype (LPEXCHEXTCALLBACK eecb)
-{
-  LPMDB mdb = NULL;
-  LPMESSAGE message = NULL;
-
-  if (msgtype_valid)
-    return msgtype;
-  if (!eecb)
-    {
-      log_error ("%s:%s: eecp not passed", SRCNAME, __func__);
-      return MSGTYPE_UNKNOWN;
-    }
-      
-  eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-  msgtype = mapi_get_message_type (message);
-  log_debug ("%s:%s: found msgtype %d\n", SRCNAME, __func__, msgtype);
-  msgtype_valid = TRUE;
-
-  ul_release (message, __func__);
-  ul_release (mdb, __func__);
-
-  return msgtype;
-}
-
index 4e0eed8..1cd922b 100644 (file)
@@ -47,10 +47,6 @@ private:
   ULONG m_lRef;
   ULONG m_lContext;
   
-  /* Information pertaining to the current message.  */
-  msgtype_t msgtype;    /* Type of the current message.  */
-  BOOL msgtype_valid;   /* Indicates that MSGTYPE is valid.  */
-
   /* Pointer to the other extension objects.  */
   GpgolExtCommands        *m_pExchExtCommands;
   GpgolUserEvents         *m_pExchExtUserEvents;
@@ -71,7 +67,6 @@ public:
       return lCount;   
     };
   STDMETHODIMP Install(LPEXCHEXTCALLBACK pEECB, ULONG lContext, ULONG lFlags);
-  msgtype_t getMsgtype (LPEXCHEXTCALLBACK eecb);
 };