Reverting a folder is now possible.
authorWerner Koch <wk@gnupg.org>
Fri, 1 Aug 2008 13:53:15 +0000 (13:53 +0000)
committerWerner Koch <wk@gnupg.org>
Fri, 1 Aug 2008 13:53:15 +0000 (13:53 +0000)
NEWS
src/ChangeLog
src/common.h
src/ext-commands.cpp
src/ext-commands.h
src/mapihelp.cpp
src/mapihelp.h
src/message-events.cpp
src/message.cpp
src/session-events.cpp
src/user-events.cpp

diff --git a/NEWS b/NEWS
index 54d73e6..985a1e7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,9 @@ Noteworthy changes for version 0.10.15
    is useful to make sure that the body will never show up in
    plaintext in the message store.
 
+ * New menu item to remove all GpgOL created flags and attachments
+   from all messages in a folder.
+
 
 Noteworthy changes for version 0.10.14 (2008-05-28)
 ===================================================
index 369cb19..92e4453 100644 (file)
@@ -1,4 +1,16 @@
-2008-07-30  Werner Koch  <wk@g10code.com>
+2008-07-31  Werner Koch  <wk@g10code.com>
+
+       * ext-commands.h (class GpgolExtCommands): Add m_nCmdRevertFolder.
+       * ext-commands.cpp (GpgolExtCommands, InstallCommands): Ditto.
+       (DoCommand): Implement RevertFolder command.
+
+       * common.h (struct): Add variable DISABLE_GPGOL.
+       * session-events.cpp (OnDelivery): Make use of that variable.
+       * message.cpp (message_incoming_handler): Ditto.
+       * user-events.cpp (OnSelectionChange): Ditto
+       * message-events.cpp (OnRead, OnReadComplete, OnWrite) 
+       (OnWriteComplete): Ditto
+       * mapihelp.cpp (mapi_get_int_prop): New.
 
        * olflange.cpp (Install): Improve version check.
 
index 5e92eef..78dea38 100644 (file)
@@ -134,6 +134,11 @@ struct
 
   /* The SVN revision as stored in the registry.  */
   int svn_revision; 
+
+  /* Disable message processing until restart.  This is required to
+     implement message reverting as a perparation to remove GpgOL.  */
+  int disable_gpgol;
+
 } opt;
 
 
index 5368848..f33afd0 100644 (file)
@@ -106,6 +106,7 @@ GpgolExtCommands::GpgolExtCommands (GpgolExt* pParentInterface)
   m_nCmdEncrypt = 0;  
   m_nCmdSign = 0; 
   m_nCmdKeyManager = 0;
+  m_nCmdRevertFolder = 0;
   m_nCmdCryptoState = 0;
   m_nCmdDebug0 = 0;
   m_nCmdDebug1 = 0;
@@ -528,26 +529,29 @@ GpgolExtCommands::InstallCommands (
          an already decrypted message. */
       add_menu (eecb, pnCommandIDBase,
         "@", NULL,
-        _("GpgOL Decrypt/Verify"), &m_nCmdCryptoState,
+        opt.disable_gpgol? "":_("GpgOL Decrypt/Verify"), &m_nCmdCryptoState,
         opt.enable_debug? "GpgOL Debug-0 (display crypto info)":"", 
                 &m_nCmdDebug0,
-        opt.enable_debug? "GpgOL Debug-1 (open_inspector)":"", &m_nCmdDebug1,
-        opt.enable_debug? "GpgOL Debug-2 (change msg class)":"", &m_nCmdDebug2,
+        (opt.enable_debug && !opt.disable_gpgol)?
+                "GpgOL Debug-1 (open_inspector)":"", &m_nCmdDebug1,
+        (opt.enable_debug && !opt.disable_gpgol)? 
+                "GpgOL Debug-2 (change msg class)":"", &m_nCmdDebug2,
         opt.enable_debug? "GpgOL Debug-3 (revert message class)":"",
                 &m_nCmdDebug3,
         NULL);
 
-      add_toolbar (pTBEArray, nTBECnt, 
-                   is_encrypted
-                   ? _("This is an encrypted message.\n"
-                       "Click for more information. ")
-                   : _("This is a signed message.\n"
+      if ( !opt.disable_gpgol)
+        add_toolbar (pTBEArray, nTBECnt, 
+                     is_encrypted
+                     ? _("This is an encrypted message.\n"
+                         "Click for more information. ")
+                     : _("This is a signed message.\n"
                        "Click for more information. "),
-                   IDB_CRYPTO_STATE, m_nCmdCryptoState,
-                   NULL, 0, 0);
+                     IDB_CRYPTO_STATE, m_nCmdCryptoState,
+                     NULL, 0, 0);
 
     }
-  else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE) 
+  else if (m_lContext == EECONTEXT_SENDNOTEMESSAGE && !opt.disable_gpgol
     {
       add_menu (eecb, pnCommandIDBase,
         "@", NULL,
@@ -584,6 +588,7 @@ GpgolExtCommands::InstallCommands (
       add_menu (eecb, pnCommandIDBase, 
         "@", NULL,
         _("GnuPG Certificate &Manager"), &m_nCmdKeyManager,
+        _("Remove GpgOL flags from this folder"), &m_nCmdRevertFolder,
         NULL);
 
       add_toolbar (pTBEArray, nTBECnt, 
@@ -755,6 +760,39 @@ GpgolExtCommands::DoCommand (LPEXCHEXTCALLBACK eecb, UINT nCommandID)
           MessageBox (NULL, _("Could not start certificate manager"),
                       _("GpgOL"), MB_ICONERROR|MB_OK);
     }
+  else if (nCommandID == m_nCmdRevertFolder
+           && m_lContext == EECONTEXT_VIEWER)
+    {
+      log_debug ("%s:%s: command ReverFoldert called\n", SRCNAME, __func__);
+      /* Notify the user that the general GpgOl fucntionaly will be
+         disabled when calling this function the first time.  */
+      if ( opt.disable_gpgol
+           || (MessageBox 
+               (hwnd,
+                _("You are about to start the process of reversing messages "
+                  "created by GpgOL to prepare deinstalling of GpgOL. "
+                  "Running this command will put GpgOL into a disabled state "
+                  "so that messages are not anymore processed by GpgOL.\n"
+                  "\n"
+                  "You should convert all folders one after the other with "
+                  "this command, close Outlook and then deinstall GpgOL.\n"
+                  "\n"
+                  "Note that if you start Outlook again with GpgOL still "
+                  "being installed, GpgOL will again process messages."),
+                _("GpgOL"), MB_ICONWARNING|MB_OKCANCEL) == IDOK))
+        {
+          if ( MessageBox 
+               (hwnd,
+                _("Do you want to revert this folder?"),
+                _("GpgOL"), MB_ICONQUESTION|MB_YESNO) == IDYES )
+            {
+              if (!opt.disable_gpgol)
+                opt.disable_gpgol = 1;
+          
+              gpgol_folder_revert (eecb);
+            }
+        }
+    }
   else if (opt.enable_debug && nCommandID == m_nCmdDebug0
            && m_lContext == EECONTEXT_READNOTEMESSAGE)
     {
index 65ec9bc..8ba7e34 100644 (file)
@@ -46,6 +46,7 @@ private:
   UINT  m_nCmdEncrypt;
   UINT  m_nCmdSign;
   UINT  m_nCmdKeyManager;
+  UINT  m_nCmdRevertFolder;
   UINT  m_nCmdCryptoState;
   UINT  m_nCmdDebug0;
   UINT  m_nCmdDebug1;
index a828a99..3f475a1 100644 (file)
@@ -1367,6 +1367,40 @@ mapi_get_binary_prop (LPMESSAGE message, ULONG proptype, size_t *r_nbytes)
   return data;
 }
 
+/* Return an integer property at R_VALUE.  On error the function
+   returns -1 and sets R_VALUE to 0, on success 0 is returned.  */
+int
+mapi_get_int_prop (LPMAPIPROP object, ULONG proptype, LONG *r_value)
+{
+  int rc = -1;
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+
+  *r_value = 0;
+  hr = HrGetOneProp (object, proptype, &propval);
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: error getting property %#lx: hr=%#lx",
+                 SRCNAME, __func__, proptype, hr);
+      return -1; 
+    }
+  switch ( PROP_TYPE (propval->ulPropTag) )
+    {
+    case PT_LONG:
+      *r_value = propval->Value.l;
+      rc = 0;
+      
+      break;
+      
+    default:
+      log_debug ("%s:%s: requested property %#lx has unknown tag %#lx\n",
+                 SRCNAME, __func__, proptype, propval->ulPropTag);
+      break;
+    }
+  MAPIFreeBuffer (propval);
+  return rc;
+}
+
 
 /* Return the attachment method for attachment OBJ.  In case of error
    we return 0 which happens not to be defined.  */
index 43cdfcb..e76a96f 100644 (file)
@@ -118,6 +118,7 @@ msgtype_t mapi_get_message_type (LPMESSAGE message);
 int mapi_to_mime (LPMESSAGE message, const char *filename);
 
 char *mapi_get_binary_prop (LPMESSAGE message,ULONG proptype,size_t *r_nbytes);
+int  mapi_get_int_prop (LPMAPIPROP object, ULONG proptype, LONG *r_value);
 
 char *mapi_get_from_address (LPMESSAGE message);
 char *mapi_get_subject (LPMESSAGE message);
index 8133d39..7635f2d 100644 (file)
@@ -98,6 +98,75 @@ GpgolMessageEvents::QueryInterface (REFIID riid, LPVOID FAR *ppvObj)
 }
 
 
+#if 0
+#warning  test code
+static void
+show_event_object (LPEXCHEXTCALLBACK eecb)
+{
+  HRESULT hr;
+  LPOUTLOOKEXTCALLBACK outlook_cb;
+  LPUNKNOWN obj;
+  LPDISPATCH disp;
+  LPTYPEINFO tinfo;
+  BSTR bstrname;
+  char *name;
+
+  outlook_cb = NULL;
+  eecb->QueryInterface(IID_IOutlookExtCallback, (void **)&outlook_cb);
+  if (!outlook_cb)
+    {
+      log_debug ("%s%s: no outlook callback found\n", SRCNAME, __func__);
+      return;
+    }
+               
+  obj = NULL;
+  outlook_cb->GetObject (&obj);
+  if (!obj)
+    {
+      log_debug ("%s%s: no object found for event\n", SRCNAME, __func__);
+      outlook_cb->Release ();
+      return;
+    }
+
+  disp = NULL;
+  obj->QueryInterface (IID_IDispatch, (void **)&disp);
+  obj->Release ();
+  obj = NULL;
+  if (!disp)
+    {
+      log_debug ("%s%s: no dispatcher found for event\n", SRCNAME, __func__);
+      outlook_cb->Release ();
+      return;
+    }
+
+  tinfo = NULL;
+  disp->GetTypeInfo (0, 0, &tinfo);
+  if (!tinfo)
+    {
+      log_debug ("%s%s: no dispatcher found for event\n", SRCNAME, __func__);
+      disp->Release ();
+      outlook_cb->Release ();
+      return;
+    }
+
+  name = NULL;
+  hr = tinfo->GetDocumentation (MEMBERID_NIL, &bstrname, 0, 0, 0);
+  if (hr)
+    log_debug ("%s%s: GetDocumentation failed: hr=%#lx\n", 
+               SRCNAME, __func__, hr);
+
+  name = wchar_to_utf8 (bstrname);
+  SysFreeString (bstrname);
+  log_debug ("%s:%s: event fired by item type `%s'\n",
+             SRCNAME, __func__, name);
+  xfree (name);
+
+  disp->Release ();
+  outlook_cb->Release ();
+}
+#endif /* Test code */
+
+
 
 /* Called from Exchange on reading a message.  Returns: S_FALSE to
    signal Exchange to continue calling extensions.  EECB is a pointer
@@ -118,6 +187,8 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
   log_debug ("%s:%s: received (hwnd=%p) %s\n", 
              SRCNAME, __func__, hwnd, m_gotinspector? "got_inspector":"");
 
+//   show_event_object (eecb);
+
   /* Fixme: If preview decryption is not enabled and we have an
      encrypted message, we might want to show a greyed out preview
      window.  There are two ways to clear the preview window: 
@@ -132,7 +203,7 @@ GpgolMessageEvents::OnRead (LPEXCHEXTCALLBACK eecb)
      result that the preview decryption can't be disabled.  */
   m_gotinspector = 1;
   
-  if (m_gotinspector || opt.preview_decrypt)
+  if ( (m_gotinspector || opt.preview_decrypt) && !opt.disable_gpgol )
     {
       eecb->GetObject (&mdb, (LPMAPIPROP *)&message);
       switch (message_incoming_handler (message, hwnd, false))
@@ -167,7 +238,7 @@ GpgolMessageEvents::OnReadComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
 
   /* If the message has been processed by us (i.e. in OnRead), we now
      use our own display code.  */
-  if (!flags && m_processed)
+  if (!flags && m_processed && !opt.disable_gpgol)
     {
       HWND hwnd = NULL;
 
@@ -197,11 +268,11 @@ GpgolMessageEvents::OnWrite (LPEXCHEXTCALLBACK eecb)
   DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
   HWND hWnd = NULL;
 
-
   /* If we are going to encrypt, check that the BodyFormat is
      something we support.  This helps avoiding surprise by sending
      out unencrypted messages. */
-  if (m_pExchExt->m_gpgEncrypt || m_pExchExt->m_gpgSign)
+  if ( (m_pExchExt->m_gpgEncrypt || m_pExchExt->m_gpgSign) 
+       && !opt.disable_gpgol)
     {
       pDisp = find_outlook_property (eecb, "BodyFormat", &dispid);
       if (!pDisp)
@@ -289,6 +360,9 @@ GpgolMessageEvents::OnWriteComplete (LPEXCHEXTCALLBACK eecb, ULONG flags)
   if (flags & (EEME_FAILED|EEME_COMPLETE_FAILED))
     return S_FALSE; /* We don't need to rollback anything in case
                        other extensions flagged a failure. */
+
+  if (opt.disable_gpgol)
+    return S_FALSE;
           
   if (!m_bOnSubmitActive) /* The user is just saving the message. */
     return S_FALSE;
index 2f84d9e..2a149a3 100644 (file)
@@ -80,7 +80,8 @@ message_incoming_handler (LPMESSAGE message, HWND hwnd, bool force)
          been set.  Note that we should have similar code for some
          message classes in GpgolUserEvents:OnSelectionChange; but
          tehre are a couple of problems.  */
-      if (pass == 1 && !force && !mapi_has_sig_status (message))
+      if (pass == 1 && !force && !mapi_has_sig_status (message)
+          && !opt.disable_gpgol)
         {
           log_debug ("%s:%s: message class not yet checked - doing now\n",
                      SRCNAME, __func__);
@@ -89,7 +90,7 @@ message_incoming_handler (LPMESSAGE message, HWND hwnd, bool force)
         }
       break;
     case MSGTYPE_SMIME:
-      if (pass == 1 && !force && opt.enable_smime)
+      if (pass == 1 && !force && opt.enable_smime && !opt.disable_gpgol)
         {
           log_debug ("%s:%s: message class not checked with smime enabled "
                      "- doing now\n", SRCNAME, __func__);
index ca661fd..cab834d 100644 (file)
@@ -103,16 +103,19 @@ GpgolSessionEvents::OnDelivery (LPEXCHEXTCALLBACK pEECB)
   LPMESSAGE pMessage = NULL;
 
   log_debug ("%s:%s: received\n", SRCNAME, __func__);
-  pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
-  log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
-  /* Note, that at this point even an OpenPGP signed message has the
-     message class IPM.Note.SMIME.MultipartSigned.  If we would not
-     change the message class here, OL will change it later (before an
-     OnRead) to IPM.Note. */
-  mapi_change_message_class (pMessage, 0);
-  log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
-  ul_release (pMessage);
-  ul_release (pMDB);
+  if ( !opt.disable_gpgol )
+    {
+      pEECB->GetObject (&pMDB, (LPMAPIPROP *)&pMessage);
+      log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
+      /* Note, that at this point even an OpenPGP signed message has
+         the message class IPM.Note.SMIME.MultipartSigned.  If we
+         would not change the message class here, OL will change it
+         later (before an OnRead) to IPM.Note. */
+      mapi_change_message_class (pMessage, 0);
+      log_mapi_property (pMessage, PR_MESSAGE_CLASS,"PR_MESSAGE_CLASS");
+      ul_release (pMessage);
+      ul_release (pMDB);
+    }
 
   return S_FALSE;
 }
index d00c874..5ad8a79 100644 (file)
@@ -160,7 +160,7 @@ GpgolUserEvents::OnSelectionChange (LPEXCHEXTCALLBACK eecb)
                                        &objtype, (IUnknown**)&message);
                   if (SUCCEEDED (hr)) 
                     {
-                      if (objtype == MAPI_MESSAGE)
+                      if (objtype == MAPI_MESSAGE && !opt.disable_gpgol)
                         {
                           log_debug ("%s:%s: about to change or sync "
                                      "the message class",