Cleanups and played with ietm infos. An ECF file is now required.
authorWerner Koch <wk@gnupg.org>
Fri, 21 Sep 2007 14:02:48 +0000 (14:02 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 21 Sep 2007 14:02:48 +0000 (14:02 +0000)
Extra/Show crypt Info shows the structure of the message.

14 files changed:
src/ChangeLog
src/ext-commands.cpp
src/item-events.cpp
src/item-events.h
src/mapihelp.cpp
src/mapihelp.h
src/message-events.cpp
src/message-events.h
src/message.cpp
src/message.h
src/mimemaker.c
src/mimeparser.c
src/olflange.cpp
src/user-events.cpp

index 542109b..0fd7c5a 100644 (file)
@@ -1,3 +1,15 @@
+2007-09-21  Werner Koch  <wk@g10code.com>
+
+       * mimeparser.c (build_mimeinfo): New.
+       (finish_message): Store the mime structure.
+       * mapihelp.cpp (mapi_get_message_class): New.
+       (mapi_get_sig_status): New.
+       (get_gpgolprotectiv_tag, get_gpgolsigstatus_tag) 
+       (get_gpgolattachtype_tag): Factored code out to ...
+       (create_gpgol_tag): .. New.
+       (get_gpgolmimeinfo_tag): New.
+       (mapi_get_mime_info): New.
+
 2007-09-20  Werner Koch  <wk@g10code.com>
 
        * user-events.cpp, user-events.h:  New.
index 384385a..a86c21a 100644 (file)
@@ -412,8 +412,9 @@ GpgolExtCommands::DoCommand (
   if (FAILED (pEECB->GetWindow (&hWnd)))
     hWnd = NULL;
 
-  log_debug ("%s:%s: commandID=%u (%#x) hwnd=%p\n",
-             SRCNAME, __func__, nCommandID, nCommandID, hWnd);
+  log_debug ("%s:%s: commandID=%u (%#x) context=%s hwnd=%p\n",
+             SRCNAME, __func__, nCommandID, nCommandID, 
+             ext_context_name (m_lContext), hWnd);
 
   if (nCommandID == SC_CLOSE && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
@@ -470,34 +471,37 @@ GpgolExtCommands::DoCommand (
       log_debug ("%s:%s: command Forward called\n", SRCNAME, __func__);
       return S_FALSE; /* Pass it on.  */
     }
-  else if (nCommandID == m_nCmdEncrypt 
+  else if (nCommandID == m_nCmdDecrypt
            && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
       hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
-//           GpgMsg *m = CreateGpgMsg (message);
-//           m->setExchangeCallback ((void*)pEECB);
-//           m->decrypt (hWnd, 0);
-//           delete m;
+          message_decrypt (message, m_pExchExt->getMsgtype (pEECB), 1);
        }
       ul_release (message);
       ul_release (mdb);
     }
-  else if (nCommandID == m_nCmdShowInfo
+  else if (nCommandID == m_nCmdCheckSig
            && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
-      MessageBox (NULL, 
-                  _("Here you should see crypto related info"),
-                  "GpgOL", MB_ICONINFORMATION|MB_OK);
+      hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (SUCCEEDED (hr))
+        {
+          message_verify (message, m_pExchExt->getMsgtype (pEECB), 1);
+       }
+      else
+        log_debug_w32 (hr, "%s:%s: CmdCheckSig failed", SRCNAME, __func__);
+      ul_release (message);
+      ul_release (mdb);
     }
-  else if (nCommandID == m_nCmdCheckSig
+  else if (nCommandID == m_nCmdShowInfo
            && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
       hr = pEECB->GetObject (&mdb, (LPMAPIPROP *)&message);
       if (SUCCEEDED (hr))
         {
-          message_verify (message, m_pExchExt->getMsgtype (pEECB), 1);
+          message_show_info (message, hWnd);
        }
       ul_release (message);
       ul_release (mdb);
index 312db49..38ea22d 100644 (file)
@@ -30,6 +30,9 @@
 #include "common.h"
 #include "olflange-def.h"
 #include "olflange.h"
+#include "message.h"
+#include "mapihelp.h"
+#include "display.h"
 #include "item-events.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                         } while (0)
 
 
+/* Wrapper around UlRelease with error checking. */
+/* FIXME: Duplicated code.  */
+static void 
+ul_release (LPVOID punk)
+{
+  ULONG res;
+  
+  if (!punk)
+    return;
+  res = UlRelease (punk);
+//   log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res);
+}
+
+
+
 
 /* Our constructor.  */
 GpgolItemEvents::GpgolItemEvents (GpgolExt *pParentInterface)
 { 
   m_pExchExt = pParentInterface;
   m_ref = 0;
+  m_processed = false;
+  m_wasencrypted = false;
 }
 
 
@@ -76,9 +96,20 @@ GpgolItemEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
                 displayed.
 */
 STDMETHODIMP 
-GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK peecb)
+GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK eecb)
 {
-  log_debug ("%s:%s: received", SRCNAME, __func__);
+  LPMDB mdb = NULL;
+  LPMESSAGE message = NULL;
+  
+  log_debug ("%s:%s: received\n", SRCNAME, __func__);
+
+  m_wasencrypted = false;
+  eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+  if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb)))
+    m_processed = TRUE;
+  ul_release (message);
+  ul_release (mdb);
+
   return S_FALSE;
 }
 
@@ -99,9 +130,22 @@ GpgolItemEvents::OnOpen (LPEXCHEXTCALLBACK peecb)
     The same return values as for OnOpen may be used..
 */ 
 STDMETHODIMP 
-GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK peecb, ULONG flags)
+GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
 {
   log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags);
+
+  /* If the message has been processed by is (i.e. in OnOpen), we now
+     use our own display code.  */
+  if (!flags && m_processed)
+    {
+      HWND hwnd = NULL;
+
+      if (FAILED (eecb->GetWindow (&hwnd)))
+        hwnd = NULL;
+      if (message_display_handler (eecb, hwnd))
+        m_wasencrypted = true;
+    }
+  
   return S_FALSE;
 }
 
@@ -114,9 +158,10 @@ GpgolItemEvents::OnOpenComplete (LPEXCHEXTCALLBACK peecb, ULONG flags)
       E_ABORT - Abort the close operation and don't dismiss the window.
 */
 STDMETHODIMP 
-GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK peecb, ULONG save_options)
+GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK eecb, ULONG save_options)
 {
   log_debug ("%s:%s: received, options=%#lx", SRCNAME, __func__, save_options);
+
   return S_FALSE;
 }
 
@@ -124,8 +169,61 @@ GpgolItemEvents::OnClose (LPEXCHEXTCALLBACK peecb, ULONG save_options)
 /* This is the corresponding Complete method for OnClose.  See
    OnOpenComplete for a description.  */
 STDMETHODIMP 
-GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK peecb, ULONG flags)
+GpgolItemEvents::OnCloseComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
 {
   log_debug ("%s:%s: received, flags=%#lx", SRCNAME, __func__, flags);
+
+  if (m_wasencrypted)
+    {
+      /* Delete any body parts so that encrypted stuff won't show up
+         in the clear. */
+      HRESULT hr;
+      LPMESSAGE message = NULL;
+      LPMDB mdb = NULL;
+      
+      log_debug ("%s:%s: deleting body properties", SRCNAME, __func__);
+      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (SUCCEEDED (hr))
+        {
+          SPropTagArray proparray;
+          int anyokay = 0;
+          
+          proparray.cValues = 1;
+          proparray.aulPropTag[0] = PR_BODY;
+          hr = message->DeleteProps (&proparray, NULL);
+          if (hr)
+            log_debug_w32 (hr, "%s:%s: deleting PR_BODY failed",
+                           SRCNAME, __func__);
+          else
+            anyokay++;
+     
+          proparray.cValues = 1;
+          proparray.aulPropTag[0] = PR_BODY_HTML;
+          message->DeleteProps (&proparray, NULL);
+          if (hr)
+            log_debug_w32 (hr, "%s:%s: deleting PR_BODY_HTML failed", 
+                           SRCNAME, __func__);
+          else
+            anyokay++;
+
+          if (anyokay)
+            {
+              hr = message->SaveChanges (KEEP_OPEN_READWRITE);
+              if (hr)
+                log_error_w32 (hr, "%s:%s: SaveChanges failed",
+                               SRCNAME, __func__); 
+            }
+
+          m_wasencrypted = false;
+          
+        }  
+      else
+        log_debug_w32 (hr, "%s:%s: error getting message", 
+                       SRCNAME, __func__);
+     
+      ul_release (message);
+      ul_release (mdb);
+    }
+
   return S_FALSE;
 }
index 60b7828..4090728 100644 (file)
@@ -38,6 +38,8 @@ class GpgolItemEvents : public IOutlookExtItemEvents
  private:
   GpgolExt *m_pExchExt;
   ULONG     m_ref;
+  bool    m_processed;       /* The message has been porcessed by us.  */
+  bool    m_wasencrypted;    /* The original message was encrypted.  */
   
  public:
   STDMETHODIMP QueryInterface (REFIID riid, LPVOID FAR *ppvObj);
index 2af0f03..505cd35 100644 (file)
@@ -94,9 +94,9 @@ log_mapi_property (LPMESSAGE message, ULONG prop, const char *propname)
 }
 
 
-/* Return the property tag for GpgOL Attach Type. */
-int 
-get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag)
+/* Helper to create a named property. */
+static ULONG 
+create_gpgol_tag (LPMESSAGE message, wchar_t *name, const char *func)
 {
   HRESULT hr;
   LPSPropTagArray proparr = NULL;
@@ -108,17 +108,28 @@ get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag)
   memset (&mnid, 0, sizeof mnid);
   mnid.lpguid = &guid;
   mnid.ulKind = MNID_STRING;
-  mnid.Kind.lpwstrName = L"GpgOL Attach Type";
+  mnid.Kind.lpwstrName = name;
   pmnid = &mnid;
   hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
-  if (FAILED (hr)) 
+  if (FAILED (hr) || !(proparr->aulPropTag[0] & 0xFFFF0000) 
     {
-      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
-                 SRCNAME, __func__, "GpgOL Attach Type", hr); 
-      return -1;
+      log_error ("%s:%s: can't map GpgOL property: hr=%#lx\n",
+                 SRCNAME, func, hr); 
+      return 0;
     }
     
-  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_LONG);
+  return (proparr->aulPropTag[0] & 0xFFFF0000);
+}
+
+
+
+/* Return the property tag for GpgOL Attach Type. */
+int 
+get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Attach Type", __func__)))
+    return -1;
+  *r_tag |= PT_LONG;
   return 0;
 }
 
@@ -127,27 +138,9 @@ get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag)
 int 
 get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag)
 {
-  HRESULT hr;
-  LPSPropTagArray proparr = NULL;
-  MAPINAMEID mnid, *pmnid;     
-  /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties.  */
-  GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06,
-                                            0x1b, 0x03, 0x10, 0x04}};
-
-  memset (&mnid, 0, sizeof mnid);
-  mnid.lpguid = &guid;
-  mnid.ulKind = MNID_STRING;
-  mnid.Kind.lpwstrName = L"GpgOL Sig Status";
-  pmnid = &mnid;
-  hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
-  if (FAILED (hr)) 
-    {
-      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
-                 SRCNAME, __func__, "GpgOL Sig Status", hr); 
-      return -1;
-    }
-    
-  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_STRING8);
+  if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Sig Status", __func__)))
+    return -1;
+  *r_tag |= PT_STRING8;
   return 0;
 }
 
@@ -156,27 +149,20 @@ get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag)
 int 
 get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag)
 {
-  HRESULT hr;
-  LPSPropTagArray proparr = NULL;
-  MAPINAMEID mnid, *pmnid;     
-  /* {31805ab8-3e92-11dc-879c-00061b031004}: GpgOL custom properties.  */
-  GUID guid = {0x31805ab8, 0x3e92, 0x11dc, {0x87, 0x9c, 0x00, 0x06,
-                                            0x1b, 0x03, 0x10, 0x04}};
+  if (!(*r_tag = create_gpgol_tag (message, L"GpgOL Protect IV", __func__)))
+    return -1;
+  *r_tag |= PT_BINARY;
+  return 0;
+}
 
-  memset (&mnid, 0, sizeof mnid);
-  mnid.lpguid = &guid;
-  mnid.ulKind = MNID_STRING;
-  mnid.Kind.lpwstrName = L"GpgOL Protect IV";
-  pmnid = &mnid;
-  hr = message->GetIDsFromNames (1, &pmnid, MAPI_CREATE, &proparr);
-  if (FAILED (hr)) 
-    {
-      log_error ("%s:%s: can't map %s property: hr=%#lx\n",
-                 SRCNAME, __func__, "GpgOL Protect IV", hr); 
-      return -1;
-    }
-    
-  *r_tag = ((proparr->aulPropTag[0] & 0xFFFF0000) | PT_BINARY);
+
+/* Return the property tag for GpgOL MIME structure. */
+int 
+get_gpgolmimeinfo_tag (LPMESSAGE message, ULONG *r_tag)
+{
+  if (!(*r_tag = create_gpgol_tag (message, L"GpgOL MIME Info", __func__)))
+    return -1;
+  *r_tag |= PT_STRING8;
   return 0;
 }
 
@@ -617,6 +603,40 @@ 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
+   returned string.  */
+char *
+mapi_get_message_class (LPMESSAGE message)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  char *retstr;
+
+  if (!message)
+    return xstrdup ("[No message]");
+  
+  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 xstrdup (hr == MAPI_E_NOT_FOUND?
+                        "[No message class property]":
+                        "[Error getting message class property]");
+    }
+
+  if ( PROP_TYPE (propval->ulPropTag) == PT_STRING8 )
+    retstr = xstrdup (propval->Value.lpszA);
+  else
+    retstr = xstrdup ("[Invalid message class property]");
+    
+  MAPIFreeBuffer (propval);
+  return retstr;
+}
+
+
+
 /* Return the message type.  This function knows only about our own
    message types.  Returns MSGTYPE_UNKNOWN for any MESSAGE we have
    no special support for.  */
@@ -1336,6 +1356,33 @@ mapi_test_sig_status (LPMESSAGE msg)
 }
 
 
+/* Return the signature status as an allocated string.  Will never
+   return NULL.  */
+char *
+mapi_get_sig_status (LPMESSAGE msg)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  ULONG tag;
+  char *retstr;
+
+  if (get_gpgolsigstatus_tag (msg, &tag) )
+    return xstrdup ("[Error getting tag for sig status]");
+  hr = HrGetOneProp ((LPMAPIPROP)msg, tag, &propval);
+  if (FAILED (hr))
+    return xstrdup ("");
+  if (PROP_TYPE (propval->ulPropTag) == PT_STRING8)
+    retstr = xstrdup (propval->Value.lpszA);
+  else
+    retstr = xstrdup ("[Sig status has an invalid type]");
+
+  MAPIFreeBuffer (propval);
+  return retstr;
+}
+
+
+
+
 /* Set the signature status property to STATUS_STRING.  There are a
    few special values:
 
@@ -1369,6 +1416,33 @@ mapi_set_sig_status (LPMESSAGE message, const char *status_string)
 }
 
 
+/* Return the MIME info as an allocated string.  Will never return
+   NULL.  */
+char *
+mapi_get_mime_info (LPMESSAGE msg)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  ULONG tag;
+  char *retstr;
+
+  if (get_gpgolmimeinfo_tag (msg, &tag) )
+    return xstrdup ("[Error getting tag for MIME info]");
+  hr = HrGetOneProp ((LPMAPIPROP)msg, tag, &propval);
+  if (FAILED (hr))
+    return xstrdup ("");
+  if (PROP_TYPE (propval->ulPropTag) == PT_STRING8)
+    retstr = xstrdup (propval->Value.lpszA);
+  else
+    retstr = xstrdup ("[MIME info has an invalid type]");
+
+  MAPIFreeBuffer (propval);
+  return retstr;
+}
+
+
+
+
 /* Helper for mapi_get_msg_content_type() */
 static int
 get_message_content_type_cb (void *dummy_arg,
@@ -1531,8 +1605,6 @@ mapi_get_gpgol_body_attachment (LPMESSAGE message, size_t *r_nbytes,
   if (r_protected)
     *r_protected = 0;
 
-  mapi_release_attach_table (mapi_create_attach_table (message, 0));
-
   if (get_gpgolattachtype_tag (message, &moss_tag) )
     return NULL;
 
index e4602cf..3db6621 100644 (file)
@@ -87,10 +87,12 @@ void log_mapi_property (LPMESSAGE message, ULONG prop, const char *propname);
 int get_gpgolattachtype_tag (LPMESSAGE message, ULONG *r_tag);
 int get_gpgolsigstatus_tag (LPMESSAGE message, ULONG *r_tag);
 int get_gpgolprotectiv_tag (LPMESSAGE message, ULONG *r_tag);
+int  get_gpgolmimeinfo_tag (LPMESSAGE message, ULONG *r_tag);
 
 int mapi_set_header (LPMESSAGE msg, const char *name, const char *val);
 
 int mapi_change_message_class (LPMESSAGE message);
+char *mapi_get_message_class (LPMESSAGE message);
 msgtype_t mapi_get_message_type (LPMESSAGE message);
 int mapi_to_mime (LPMESSAGE message, const char *filename);
 
@@ -108,8 +110,12 @@ char *mapi_get_attach (LPMESSAGE message,
 int mapi_mark_moss_attach (LPMESSAGE message, mapi_attach_item_t *item);
 int mapi_has_sig_status (LPMESSAGE msg);
 int mapi_test_sig_status (LPMESSAGE msg);
+char *mapi_get_sig_status (LPMESSAGE msg);
+
 int mapi_set_sig_status (LPMESSAGE message, const char *status_string);
 
+char *mapi_get_mime_info (LPMESSAGE msg);
+
 char *mapi_get_message_content_type (LPMESSAGE message, 
                                      char **r_protocol, char **r_smtype);
 
index b25779e..0640368 100644 (file)
@@ -71,9 +71,10 @@ GpgolMessageEvents::GpgolMessageEvents (GpgolExt *pParentInterface)
 { 
   m_pExchExt = pParentInterface;
   m_lRef = 0; 
-  m_bOnSubmitActive = FALSE;
-  m_want_html = FALSE;
-  m_processed = FALSE;
+  m_bOnSubmitActive = false;
+  m_want_html = false;
+  m_processed = false;
+  m_wasencrypted = false;
 }
 
 
@@ -109,61 +110,17 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
   LPMESSAGE message = NULL;
   
   log_debug ("%s:%s: received\n", SRCNAME, __func__);
-  eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-  switch (m_pExchExt->getMsgtype (eecb))
+
+  m_wasencrypted = false;
+  if (opt.preview_decrypt)
     {
-    case MSGTYPE_UNKNOWN: 
-      break;
-    case MSGTYPE_GPGOL:
-      log_debug ("%s:%s: ignoring unknown message of original SMIME class\n",
-                 SRCNAME, __func__);
-      break;
-    case MSGTYPE_GPGOL_MULTIPART_SIGNED:
-      log_debug ("%s:%s: processing multipart signed message\n", 
-                 SRCNAME, __func__);
-      m_processed = TRUE;
-      message_verify (message, m_pExchExt->getMsgtype (eecb), 0);
-      break;
-    case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
-      log_debug ("%s:%s: processing multipart encrypted message\n",
-                 SRCNAME, __func__);
-      m_processed = TRUE;
-      message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0);
-      /* Hmmm, we might want to abort it and run our own inspector
-         instead.  */
-      break;
-    case MSGTYPE_GPGOL_OPAQUE_SIGNED:
-      log_debug ("%s:%s: processing opaque signed message\n", 
-                 SRCNAME, __func__);
-      m_processed = TRUE;
-      message_verify (message, m_pExchExt->getMsgtype (eecb), 0);
-      break;
-    case MSGTYPE_GPGOL_CLEAR_SIGNED:
-      log_debug ("%s:%s: processing clear signed pgp message\n", 
-                 SRCNAME, __func__);
-      m_processed = TRUE;
-      message_verify (message, m_pExchExt->getMsgtype (eecb), 0);
-      break;
-    case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
-      log_debug ("%s:%s: processing opaque encrypted message\n",
-                 SRCNAME, __func__);
-      m_processed = TRUE;
-      message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0);
-      /* Hmmm, we might want to abort it and run our own inspector
-         instead.  */
-      break;
-    case MSGTYPE_GPGOL_PGP_MESSAGE:
-      log_debug ("%s:%s: processing pgp message\n", SRCNAME, __func__);
-      m_processed = TRUE;
-      message_decrypt (message, m_pExchExt->getMsgtype (eecb), 0);
-      /* Hmmm, we might want to abort it and run our own inspector
-         instead.  */
-      break;
+      eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+      if (message_incoming_handler (message, m_pExchExt->getMsgtype (eecb)))
+        m_processed = true;
+      ul_release (message);
+      ul_release (mdb);
     }
   
-  ul_release (message);
-  ul_release (mdb);
-
   return S_FALSE;
 }
 
@@ -178,51 +135,17 @@ GpgolMessageEvents::OnReadComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
 
   /* If the message has been processed by is (i.e. in OnRead), we now
      use our own display code.  */
-  if (m_processed)
+  if (!flags && m_processed)
     {
-      HRESULT hr;
       HWND hwnd = NULL;
-      LPMESSAGE message = NULL;
-      LPMDB mdb = NULL;
 
       if (FAILED (eecb->GetWindow (&hwnd)))
         hwnd = NULL;
-      hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
-      if (SUCCEEDED (hr))
-        {
-          int ishtml, wasprotected;
-          char *body;
-
-          /* If the message was protected we don't allow a fallback to
-             the OOM display methods.  */
-          body = mapi_get_gpgol_body_attachment (message, NULL,
-                                                 &ishtml, &wasprotected);
-          if (body)
-            update_display (hwnd, wasprotected? NULL: eecb, ishtml, body);
-          else
-            update_display (hwnd, NULL, 0, 
-                            _("[Crypto operation failed - "
-                              "can't show the body of the message]"));
-          put_outlook_property (eecb, "EncryptedStatus", "MyStatus");
-
-        }
-      ul_release (message);
-      ul_release (mdb);
+      if (message_display_handler (eecb, hwnd))
+        m_wasencrypted = true;
     }
   
 
-#if 1
-    {
-      HWND hWnd = NULL;
-
-      if (FAILED (eecb->GetWindow (&hWnd)))
-        hWnd = NULL;
-      else
-        log_window_hierarchy (hWnd, "%s:%s:%d: Windows hierarchy:",
-                              SRCNAME, __func__, __LINE__);
-    }
-#endif
-
   return S_FALSE;
 }
 
@@ -345,7 +268,7 @@ GpgolMessageEvents::OnWriteComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
   if (FAILED(eecb->GetWindow (&hWnd)))
     hWnd = NULL;
 
-  /* Get the object and call the encryption or signing fucntion.  */
+  /* Get the object and call the encryption or signing function.  */
   HRESULT hr = eecb->GetObject (&pMDB, (LPMAPIPROP *)&msg);
   if (SUCCEEDED (hr))
     {
index 43a4c56..bdcc576 100644 (file)
@@ -40,9 +40,10 @@ class GpgolMessageEvents : public IExchExtMessageEvents
   ULONG   m_lContext;
   BOOL    m_bOnSubmitActive;
   GpgolExt* m_pExchExt;
-  BOOL    m_bWriteFailed;
-  BOOL    m_want_html;       /* Encryption of HTML is desired. */
-  BOOL    m_processed;       /* The message has been porcessed by us.  */
+  bool    m_bWriteFailed;
+  bool    m_want_html;       /* Encryption of HTML is desired. */
+  bool    m_processed;       /* The message has been porcessed by us.  */
+  bool    m_wasencrypted;    /* The original message was encrypted.  */
   
  public:
   STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppvObj);
index c6ba9c8..6e0ecb5 100644 (file)
@@ -31,6 +31,7 @@
 #include "mapihelp.h"
 #include "mimeparser.h"
 #include "mimemaker.h"
+#include "display.h"
 #include "message.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                         } while (0)
 
 
+static void 
+ul_release (LPVOID punk)
+{
+  ULONG res;
+  
+  if (!punk)
+    return;
+  res = UlRelease (punk);
+//   log_debug ("%s UlRelease(%p) had %lu references\n", __func__, punk, res);
+}
+
+
+/* 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)
+{
+  bool retval = false;
+
+  switch (msgtype)
+    {
+    case MSGTYPE_UNKNOWN: 
+      break;
+    case MSGTYPE_GPGOL:
+      log_debug ("%s:%s: ignoring unknown message of original SMIME class\n",
+                 SRCNAME, __func__);
+      break;
+    case MSGTYPE_GPGOL_MULTIPART_SIGNED:
+      log_debug ("%s:%s: processing multipart signed message\n", 
+                 SRCNAME, __func__);
+      retval = true;
+      message_verify (message, msgtype, 0);
+      break;
+    case MSGTYPE_GPGOL_MULTIPART_ENCRYPTED:
+      log_debug ("%s:%s: processing multipart encrypted message\n",
+                 SRCNAME, __func__);
+      retval = true;
+      message_decrypt (message, msgtype, 0);
+      break;
+    case MSGTYPE_GPGOL_OPAQUE_SIGNED:
+      log_debug ("%s:%s: processing opaque signed message\n", 
+                 SRCNAME, __func__);
+      retval = true;
+      message_verify (message, msgtype, 0);
+      break;
+    case MSGTYPE_GPGOL_CLEAR_SIGNED:
+      log_debug ("%s:%s: processing clear signed pgp message\n", 
+                 SRCNAME, __func__);
+      retval = true;
+      message_verify (message, msgtype, 0);
+      break;
+    case MSGTYPE_GPGOL_OPAQUE_ENCRYPTED:
+      log_debug ("%s:%s: processing opaque encrypted message\n",
+                 SRCNAME, __func__);
+      retval = true;
+      message_decrypt (message, msgtype, 0);
+      break;
+    case MSGTYPE_GPGOL_PGP_MESSAGE:
+      log_debug ("%s:%s: processing pgp message\n", SRCNAME, __func__);
+      retval = true;
+      message_decrypt (message, msgtype, 0);
+      break;
+    }
+
+  return retval;
+}
+
+
+/* Common Code ise by OnReadComplete and OnOpenComplete to display a
+   modified message.   Returns true if the message was encrypted.  */
+bool
+message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd)
+{
+  HRESULT hr;
+  LPMESSAGE message = NULL;
+  LPMDB mdb = NULL;
+  int ishtml, wasprotected = false;
+  char *body;
+  
+  hr = eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
+  if (SUCCEEDED (hr))
+    {
+      /* If the message was protected we don't allow a fallback to the
+         OOM display methods.  */
+      body = mapi_get_gpgol_body_attachment (message, NULL, 
+                                             &ishtml, &wasprotected);
+      if (body)
+        update_display (hwnd, wasprotected? NULL: eecb, ishtml, body);
+      else
+        update_display (hwnd, NULL, 0, 
+                        _("[Crypto operation failed - "
+                          "can't show the body of the message]"));
+      xfree (body);
+  
+      /*  put_outlook_property (eecb, "EncryptedStatus", "MyStatus"); */
+    }
+  else
+    log_debug_w32 (hr, "%s:%s: error getting message", SRCNAME, __func__);
+
+  ul_release (message);
+  ul_release (mdb);
+
+  return !!wasprotected;
+}
+
+
+/* Display some information about MESSAGE.  */
+void
+message_show_info (LPMESSAGE message, HWND hwnd)
+{
+  char *msgcls = mapi_get_message_class (message);
+  char *sigstat = mapi_get_sig_status (message);
+  char *mimeinfo = mapi_get_mime_info (message);
+  size_t buflen;
+  char *buffer;
+
+  buflen = strlen (msgcls) + strlen (sigstat) + strlen (mimeinfo) + 200;
+  buffer = (char*)xmalloc (buflen+1);
+  snprintf (buffer, buflen, 
+            _("Message class: %s\n"
+              "Sig Status   : %s\n"
+              "Structure of the message:\n"
+              "%s"), 
+            msgcls,
+            sigstat,
+            mimeinfo);
+  
+  MessageBox (hwnd, buffer, _("GpgOL - Message Information"),
+              MB_ICONINFORMATION|MB_OK);
+  xfree (buffer);
+  xfree (mimeinfo);
+  xfree (sigstat);
+  xfree (msgcls);
+}
+
+
+
+\f
 /* Convert the clear signed message from INPUT into a PS?MIME signed
    message and return it in a new allocated buffer.  OUTPUTLEN
    received the valid length of that buffer; the buffer is guarnateed
index dac0626..d7ff8a8 100644 (file)
 #define MESSAGE_H
 
 
+bool message_incoming_handler (LPMESSAGE message, msgtype_t msgtype);
+bool message_display_handler (LPEXCHEXTCALLBACK eecb, HWND hwnd);
+void message_show_info (LPMESSAGE message, HWND hwnd);
+
+
 int message_verify (LPMESSAGE message, msgtype_t msgtype, int force);
 int message_decrypt (LPMESSAGE message, msgtype_t msgtype, int force);
 
index e9398a7..6ece243 100644 (file)
@@ -1401,7 +1401,6 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
 
   /* Write the top header.  */
   generate_boundary (boundary);
-  TRACEPOINT ();
   if ((rc=write_multistring (sink,
                              "MIME-Version: 1.0\r\n"
                              "Content-Type: multipart/encrypted;\r\n"
@@ -1410,7 +1409,6 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
                              NULL)))
     goto failure;
 
-  TRACEPOINT ();
   /* Write the PGP/MIME encrypted part.  */
   if ((rc = write_boundary (sink, boundary, 0)))
     goto failure;
@@ -1429,11 +1427,9 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
                              "\r\n", NULL)))
     goto failure;
 
-  TRACEPOINT ();
   /* Create a new sink for encrypting the following stuff.  */
   encsink->cb_data = filter;
   encsink->writefnc = sink_encryption_write;
-  TRACEPOINT ();
   
   if ((body && n_att_usable) || n_att_usable > 1)
     {
@@ -1448,8 +1444,6 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
   else /* Only one part.  */
     *inner_boundary = 0;
 
-  TRACEPOINT ();
-
   if (body)
     rc = write_part (encsink, body, strlen (body), 
                      *inner_boundary? inner_boundary : NULL, NULL, 1);
@@ -1458,7 +1452,6 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
                             *inner_boundary? inner_boundary : NULL);
   if (rc)
     goto failure;
-  TRACEPOINT ();
 
   xfree (body);
   body = NULL;
@@ -1476,27 +1469,19 @@ mime_encrypt (LPMESSAGE message, protocol_t protocol, char **recipients)
   filter = NULL; /* Not valid anymore.  */
   encsink->cb_data = NULL; /* Not needed anymore.  */
   
-  TRACEPOINT ();
-
   /* Write the final boundary and finish the attachment.  */
   if ((rc = write_boundary (sink, boundary, 1)))
     goto failure;
 
-  TRACEPOINT ();
-
   if (close_mapi_attachment (&attach, sink))
     goto failure;
 
-  TRACEPOINT ();
-
   if (finalize_message (message, att_table))
     goto failure;
 
   result = 0;  /* Everything is fine, fall through the cleanup now.  */
-  TRACEPOINT ();
 
  failure:
-  TRACEPOINT ();
   engine_cancel (filter);
   cancel_mapi_attachment (&attach, sink);
   xfree (body);
index fbbbb23..8c7f5dc 100644 (file)
@@ -216,7 +216,6 @@ debug_message_event (mime_context_t ctx, rfc822parse_event_t event)
 }
 
 
-
 /* Start a new atatchment.  With IS_BODY set, the attachment is
    actually the body part of the message which is treated in a special
    way. */
@@ -506,9 +505,88 @@ finish_attachment (mime_context_t ctx, int cancel)
 }
 
 
+/* Create the MIME info string.  This is a LF delimited string
+   with one line per MIME part.  Each line is formatted this way:
+   LEVEL:ENCINFO:SIGINFO:CT:CHARSET:FILENAME
+   
+   LEVEL is the nesting level with 0 as the top (rfc822 header)
+   ENCINFO is one of
+      p   PGP/MIME encrypted
+      s   S/MIME encryptyed
+   SIGINFO is one of
+      pX  PGP/MIME signed (also used for clearsigned)
+      sX  S/MIME signed
+      With X being:
+        ?  unklnown status
+        -  Bad signature
+        ~  Good signature but with some problems
+        !  Good signature
+   CT ist the content type of this part
+   CHARSET is the charset used for this part
+   FILENAME is the file name.
+*/
+static char *
+build_mimeinfo (mimestruct_item_t mimestruct)
+{
+  mimestruct_item_t ms;
+  size_t buflen, n;
+  char *buffer, *p;
+  char numbuf[20];
+
+  /* FIXME: We need to escape stuff so that there are no colons.  */
+  for (buflen=0, ms = mimestruct; ms; ms = ms->next)
+    {
+      buflen += sizeof numbuf;
+      buflen += strlen (ms->content_type);
+      buflen += ms->charset? strlen (ms->charset) : 0;
+      buflen += ms->filename? strlen (ms->filename) : 0;
+      buflen += 20;
+    }
+
+  p = buffer = xmalloc (buflen+1);
+  for (ms=mimestruct; ms; ms = ms->next)
+    {
+      snprintf (p, buflen, "%d:::%s:%s:%s:\n",
+                ms->level, ms->content_type,
+                ms->charset? ms->charset : "",
+                ms->filename? ms->filename : "");
+      n = strlen (p);
+      assert (n < buflen);
+      buflen -= n;
+      p += n;
+    }
+
+  return buffer;
+}
+
+
 static int
-finish_message (LPMESSAGE message)
+finish_message (LPMESSAGE message, gpg_error_t err, 
+                mimestruct_item_t mimestruct)
 {
+  HRESULT hr;
+  SPropValue prop;
+
+  if (get_gpgolmimeinfo_tag (message, &prop.ulPropTag) )
+    return -1;
+  prop.Value.lpszA = build_mimeinfo (mimestruct);
+  hr = IMessage_SetProps (message, 1, &prop, NULL);
+  xfree (prop.Value.lpszA);
+  if (hr)
+    {
+      log_error_w32 (hr, "%s:%s: error setting the mime info",
+                     SRCNAME, __func__);
+      return -1;
+    }
+
+  hr = IMessage_SaveChanges (message, KEEP_OPEN_READWRITE|FORCE_SAVE);
+  if (hr)
+    {
+      log_error_w32 (hr, "%s:%s: SaveChanges to the message failed",
+                     SRCNAME, __func__); 
+      return -1;
+    }
+
   return 0;
 }
 
@@ -888,21 +966,6 @@ plaintext_handler (void *handle, const void *buffer, size_t size)
 
 
 
-static void 
-show_mimestruct (mimestruct_item_t mimestruct)
-{
-  mimestruct_item_t ms;
-
-  for (ms = mimestruct; ms; ms = ms->next)
-    log_debug ("MIMESTRUCT: %*s%s  cs=%s  fn=%s\n",
-               ms->level*2, "", ms->content_type,
-               ms->charset? ms->charset : "[none]",
-               ms->filename? ms->filename : "[none]");
-}
-
-
-
-
 int
 mime_verify (protocol_t protocol, const char *message, size_t messagelen, 
              LPMESSAGE mapi_message, HWND hwnd, int preview_mode)
@@ -988,7 +1051,6 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
             }
           else if (nread)
             {
-              TRACEPOINT();
               err = engine_filter (filter, buffer, nread);
             }
           else
@@ -1008,7 +1070,6 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
 
 
  leave:
-  TRACEPOINT();
   gpgme_free (signature);
   engine_cancel (filter);
   if (ctx)
@@ -1018,7 +1079,7 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
       rfc822parse_close (ctx->msg);
       gpgme_data_release (ctx->signed_data);
       gpgme_data_release (ctx->sig_data);
-      show_mimestruct (ctx->mimestruct);
+      finish_message (mapi_message, err, ctx->mimestruct);
       while (ctx->mimestruct)
         {
           mimestruct_item_t tmp = ctx->mimestruct->next;
@@ -1029,8 +1090,6 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
         }
       symenc_close (ctx->symenc);
       xfree (ctx);
-      if (!err)
-        finish_message (mapi_message);
     }
   return err;
 }
@@ -1136,7 +1195,7 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
         gpgme_data_release (ctx->signed_data);
       if (ctx->sig_data)
         gpgme_data_release (ctx->sig_data);
-      show_mimestruct (ctx->mimestruct);
+      finish_message (mapi_message, err, ctx->mimestruct);
       while (ctx->mimestruct)
         {
           mimestruct_item_t tmp = ctx->mimestruct->next;
@@ -1147,8 +1206,6 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
         }
       symenc_close (ctx->symenc);
       xfree (ctx);
-      if (!err)
-        finish_message (mapi_message);
     }
   return err;
 }
index a74c38f..712112b 100644 (file)
@@ -204,7 +204,7 @@ DllRegisterServer (void)
       return E_ACCESSDENIED;
     }
 
-  strcpy (szEntry, "GPGol - The GPG Outlook Plugin");
+  strcpy (szEntry, "GpgOL - The GnuPG Outlook Plugin");
   dwTemp = strlen (szEntry) + 1;
   RegSetValueEx (hkey, NULL, 0, REG_SZ, (BYTE*)szEntry, dwTemp);
 
index 4371bfb..258bb96 100644 (file)
@@ -115,6 +115,7 @@ GpgolUserEvents::OnSelectionChange (LPEXCHEXTCALLBACK eecb)
             SRCNAME, __func__, msgclass);
         }
     }
+
 }
 
 /* I assume this is called from Outlook for all object changes.