[git] GpgOL - branch, outlook14, updated. gpgol-1.1.3-9-gd737d16

by Andre Heinecke cvs at cvs.gnupg.org
Tue Jul 9 17:05:12 CEST 2013


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, outlook14 has been updated
       via  d737d168278cfec479cb1bd49b8825d98e7260c0 (commit)
       via  3aae0ada6f19ef45ee2392afbb93df92bb093bf0 (commit)
       via  3fc86e1ca4700c6a91ddab8168fdbe486616e996 (commit)
       via  2dec95936ebfa8e8a8b5f474bfb423b5d18b40bb (commit)
      from  5dd6e2b9a52e05f754109c5858eebc330f6a0176 (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 d737d168278cfec479cb1bd49b8825d98e7260c0
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jul 9 14:40:12 2013 +0000

    Add nohup option to decrypt command
    
        Otherwise Outlook would block until the decryption
        completes.
    
        * src/engine-assuan.c (op_assuan_start_decrypt_files):
        Add --nohup to decrypt files command

diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index 8e0737f..6523e1b 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -2234,7 +2234,7 @@ op_assuan_start_decrypt_files (void *hwnd, char **filenames)
             return err;
           filenames++;
         }
-      err = assuan_transact (ctx, "DECRYPT_FILES",
+      err = assuan_transact (ctx, "DECRYPT_FILES --nohup",
                              NULL, NULL, NULL, NULL, NULL, NULL);
       assuan_release (ctx);
     }

commit 3aae0ada6f19ef45ee2392afbb93df92bb093bf0
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jul 9 14:30:31 2013 +0000

    Add encrypt selection command and improve for OL14
    
        This implements a context menu action to encrypt selected
        text when composing a mail. This also removes a crash
        under some optimization circumstances because it no longer uses
        the RibbonCallback interface directly.
    
        * src/gpgoladdin.cpp, src/gpgoladdin.h (decrypt_attachments):
        Moved into ribbon-callbacks.cpp. Removed usage of
        LPRIBBONCALLBACK as a structure.
        * src/gpgoladdin.cpp (Invoke): Add support for encryptSelection
        * src/gpgoladdin.cpp (GetCustomUI): Add ui prototype for
        encryptSelection
        * src/ribbon-callbacks.cpp, src/ribbon-callbacks.h: New.
        Source files to handle the Ribbon UI actions.
        (encryptSelection): New. Parse an Inspector context to replace
        selected plain text with encrpyted text. Based on mimemaker code.
        * src/Makefile.am: Add ribbon callbacks

diff --git a/src/Makefile.am b/src/Makefile.am
index 3f73dba..4c59507 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,7 +80,8 @@ gpgol_SOURCES = \
 	mailitem.cpp mailitem.h \
 	cmdbarcontrols.cpp cmdbarcontrols.h \
 	w32-gettext.c w32-gettext.h \
-	gpgoladdin.cpp gpgoladdin.h
+	gpgoladdin.cpp gpgoladdin.h \
+	ribbon-callbacks.cpp ribbon-callbacks.h
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/gpgoladdin.cpp b/src/gpgoladdin.cpp
index 40063d0..0a7323d 100644
--- a/src/gpgoladdin.cpp
+++ b/src/gpgoladdin.cpp
@@ -44,16 +44,12 @@
 #include "olflange.h"
 
 #include "gpgol-ids.h"
+#include "ribbon-callbacks.h"
 
 #define TRACEPOINT() do { log_debug ("%s:%s:%d: tracepoint\n", \
                                      SRCNAME, __func__, __LINE__); \
                         } while (0)
 
-/* Id's of our callbacks */
-#define ID_CMD_DECRYPT_VERIFY   1
-#define ID_CMD_DECRYPT          2
-#define ID_CMD_VERIFY           3
-
 ULONG addinLocks = 0;
 
 /* This is the main entry point for the addin
@@ -417,10 +413,17 @@ GpgolRibbonExtender::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames,
          different parameters and just match the name (the first element)
          and we give it one of our own dispIds's that are later handled in
          the invoke part */
-      if (!wcscmp (rgszNames[i], L"AttachmentDecryptCallback"))
+      if (!wcscmp (rgszNames[i], L"attachmentDecryptCallback"))
         {
           found = true;
           rgDispId[i] = ID_CMD_DECRYPT;
+          break;
+        }
+      if (!wcscmp (rgszNames[i], L"encryptSelection"))
+        {
+          found = true;
+          rgDispId[i] = ID_CMD_ENCRYPT_SELECTION;
+          break;
         }
     }
 
@@ -432,124 +435,6 @@ GpgolRibbonExtender::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames,
   return found ? S_OK : E_NOINTERFACE;
 }
 
-HRESULT
-GpgolRibbonExtender::decryptAttachments(LPRIBBONCONTROL ctrl)
-{
-  BSTR idStr = NULL;
-  LPDISPATCH context = NULL;
-  LPDISPATCH attachmentSelection;
-  int attachmentCount;
-  HRESULT hr = 0;
-  int i = 0;
-  HWND curWindow;
-  LPOLEWINDOW actExplorer;
-  int err;
-
-  /* We got the vtable right so we can save us the invoke and
-     property lookup hassle and call it directly */
-  hr = ctrl->get_Id (&idStr);
-  hr |= ctrl->get_Context (&context);
-
-  if (FAILED(hr))
-    {
-      log_debug ("%s:%s:Context / ID lookup failed. hr: %x",
-                 SRCNAME, __func__, (unsigned int) hr);
-      SysFreeString (idStr);
-      return E_FAIL;
-    }
-  else
-    {
-      log_debug ("%s:%s: contextId: %S, contextObj: %s",
-                 SRCNAME, __func__, idStr, get_object_name (context));
-      SysFreeString (idStr);
-    }
-
-  attachmentSelection = get_oom_object (context, "AttachmentSelection");
-  if (!attachmentSelection)
-    {
-      /* We can be called from a context menu, in that case we
-         directly have an AttachmentSelection context. Otherwise
-         we have an Explorer context with an Attachment Selection property. */
-      attachmentSelection = context;
-    }
-
-  attachmentCount = get_oom_int (attachmentSelection, "Count");
-
-  actExplorer = (LPOLEWINDOW) get_oom_object(attachmentSelection,
-                                             "Application.ActiveExplorer");
-  if (actExplorer)
-    actExplorer->GetWindow (&curWindow);
-  else
-    {
-      log_debug ("%s:%s: Could not find active window",
-                 SRCNAME, __func__);
-      curWindow = NULL;
-    }
-
-  char *filenames[attachmentCount + 1];
-  filenames[attachmentCount] = NULL;
-  /* Yes the items start at 1! */
-  for (i = 1; i <= attachmentCount; i++)
-    {
-      char buf[16];
-      char *filename;
-      wchar_t *wcsOutFilename;
-      DISPPARAMS saveParams;
-      VARIANT aVariant[1];
-      LPDISPATCH attachmentObj;
-      DISPID saveID;
-
-      snprintf (buf, sizeof (buf), "Item(%i)", i);
-      attachmentObj = get_oom_object (attachmentSelection, buf);
-      if (!attachmentObj)
-        {
-          /* Should be impossible */
-          filenames[i-1] = NULL;
-          log_error ("%s:%s: could not find Item %i;",
-                     SRCNAME, __func__, i);
-          break;
-        }
-      filename = get_oom_string (attachmentObj, "FileName");
-
-      saveID = lookup_oom_dispid (attachmentObj, "SaveAsFile");
-
-      saveParams.rgvarg = aVariant;
-      saveParams.rgvarg[0].vt = VT_BSTR;
-      filenames[i-1] = get_save_filename (NULL, filename);
-      xfree (filename);
-
-      wcsOutFilename = utf8_to_wchar2 (filenames[i-1],
-                                       strlen(filenames[i-1]));
-      saveParams.rgvarg[0].bstrVal = SysAllocString (wcsOutFilename);
-      saveParams.cArgs = 1;
-      saveParams.cNamedArgs = 0;
-
-      hr = attachmentObj->Invoke (saveID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
-                                  DISPATCH_METHOD, &saveParams,
-                                  NULL, NULL, NULL);
-      SysFreeString (saveParams.rgvarg[0].bstrVal);
-      if (FAILED(hr))
-        {
-          int j;
-          log_debug ("%s:%s: Saving to file failed. hr: %x",
-                     SRCNAME, __func__, (unsigned int) hr);
-          for (j = 0; j < i; j++)
-            xfree (filenames[j]);
-          return hr;
-        }
-    }
-  err = op_assuan_start_decrypt_files (curWindow, filenames);
-
-  for (i = 0; i < attachmentCount; i++)
-    xfree (filenames[i]);
-
-  log_debug ("%s:%s: Leaving. Err: %i",
-             SRCNAME, __func__, err);
-
-  return S_OK; /* If we return an error outlook will show that our
-                  callback function failed in an ugly window. */
-}
-
 STDMETHODIMP
 GpgolRibbonExtender::Invoke (DISPID dispid, REFIID riid, LCID lcid,
                              WORD flags, DISPPARAMS *parms, VARIANT *result,
@@ -570,8 +455,9 @@ GpgolRibbonExtender::Invoke (DISPID dispid, REFIID riid, LCID lcid,
       case ID_CMD_DECRYPT:
         /* We can assume that this points to an implementation of
            IRibbonControl as we know the callback dispid. */
-        return decryptAttachments ((LPRIBBONCONTROL)
-                                   parms->rgvarg[0].pdispVal);
+        return decryptAttachments (parms->rgvarg[0].pdispVal);
+      case ID_CMD_ENCRYPT_SELECTION:
+        return encryptSelection (parms->rgvarg[0].pdispVal);
     }
 
   log_debug ("%s:%s: leave", SRCNAME, __func__);
@@ -624,15 +510,55 @@ loadXMLResource (int id)
 STDMETHODIMP
 GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
 {
+  /* TODO use callback for label's and Icons, load xml from resource */
   log_debug ("%s:%s: GetCustomUI for id: %S", SRCNAME, __func__, RibbonID);
 
   if (!RibbonXml)
     return E_POINTER;
 
-  /*if (!wcscmp (RibbonID, L"Microsoft.Outlook.Explorer"))
-    {*/
+  if (!wcscmp (RibbonID, L"Microsoft.Outlook.Mail.Compose"))
+    {
+      *RibbonXml = SysAllocString (
+        L"<customUI xmlns=\"http://schemas.microsoft.com/office/2009/07/customui\">"
+        L"<contextMenus>"
+        L"<contextMenu idMso=\"ContextMenuText\">"
+        L" <button id=\"encryptButton\""
+        L"         label=\"Encrypt Text\""
+        L"         onAction=\"encryptSelection\"/>"
+        L" </contextMenu>"
+        L"</contextMenus>"
+        L"</customUI>"
+/*
+        L"<customUI xmlns=\"http://schemas.microsoft.com/office/2009/07/customui\">"
+L"<contextMenus>"
+L"    <contextMenu idMso=\"ContextMenuMailItem\">"
+L"        <button id=\"MyContextMenuMailItem\""
+L"            label=\"Encrypt selection\""
+L"            onAction=\"encryptSelection\"/>"
+L"    </contextMenu>"
+L"</contextMenus>"
+        L"</customUI>"*/
+      );
+    }
+  else if (!wcscmp (RibbonID, L"Microsoft.Outlook.Mail.Read"))
+    {
+      *RibbonXml = SysAllocString (
+        L"<customUI xmlns=\"http://schemas.microsoft.com/office/2009/07/customui\">"
+        L"<contextMenus>"
+        L"<contextMenu idMso=\"ContextMenuText\">"
+        L" <button id=\"encryptButton\""
+        L"         label=\"Encrypt Text\""
+        L"         onAction=\"encryptSelection\"/>"
+        L" </contextMenu>"
+        L"</contextMenus>"
+        L"</customUI>"
+      );
+
+    }
+
+  else /*if (!wcscmp (RibbonID, L"Microsoft.Outlook.Explorer")) */
+    {
      // *RibbonXml = loadXMLResource (IDR_XML_EXPLORER);
-  /* TODO use callback for label's and Icons, load xml from resource */
       *RibbonXml = SysAllocString (
         L"<customUI xmlns=\"http://schemas.microsoft.com/office/2009/07/customui\">"
         L" <ribbon>"
@@ -657,7 +583,7 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
         L"                    size=\"large\""
         L"                    label=\"Save and decrypt\""
         L"                    imageMso=\"HappyFace\""
-        L"                    onAction=\"AttachmentDecryptCallback\" />"
+        L"                    onAction=\"attachmentDecryptCallback\" />"
         L"            </group>"
         L"        </tab>"
         L"    </tabSet>"
@@ -667,12 +593,12 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
         L" <contextMenu idMso=\"ContextMenuAttachments\">"
         L"   <button id=\"gpgol_decrypt\""
         L"    label=\"Save and decrypt\""
-        L"    onAction=\"AttachmentDecryptCallback\"/>"
+        L"    onAction=\"attachmentDecryptCallback\"/>"
         L" </contextMenu>"
         L" </contextMenus>"
         L"</customUI>"
         );
-  /*  } */
+    }
 
   return S_OK;
 }
diff --git a/src/gpgoladdin.h b/src/gpgoladdin.h
index ee4583a..9518d9e 100644
--- a/src/gpgoladdin.h
+++ b/src/gpgoladdin.h
@@ -144,9 +144,6 @@ public:
 private:
   ULONG m_lRef;
 
-  /* Callback implementations */
-  HRESULT decryptAttachments (LPRIBBONCONTROL ctrl);
-
 };
 
 class GpgolAddin : public IDTExtensibility2
diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
new file mode 100644
index 0000000..cf390ec
--- /dev/null
+++ b/src/ribbon-callbacks.cpp
@@ -0,0 +1,417 @@
+/* ribbon-callbacks.h - Callbacks for the ribbon extension interface
+ *    Copyright (C) 2013 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <objidl.h>
+
+#include "ribbon-callbacks.h"
+#include "gpgoladdin.h"
+#include "util.h"
+
+#include "mymapi.h"
+#include "mymapitags.h"
+#include "myexchext.h"
+
+#include "common.h"
+#include "display.h"
+#include "msgcache.h"
+#include "engine.h"
+#include "engine-assuan.h"
+#include "mapihelp.h"
+#include "mimemaker.h"
+
+/* Gets the context of a ribbon control. And prints some
+   useful debug output */
+HRESULT getContext (LPDISPATCH ctrl, LPDISPATCH *context)
+{
+  *context = get_oom_object (ctrl, "get_Context");
+  log_debug ("%s:%s: contextObj: %s",
+             SRCNAME, __func__, get_object_name (*context));
+  return context ? S_OK : E_FAIL;
+}
+
+
+HRESULT
+encryptSelection (LPDISPATCH ctrl)
+{
+  LPDISPATCH context = NULL;
+  LPDISPATCH selection;
+  LPDISPATCH wordEditor;
+  LPDISPATCH application;
+  LPDISPATCH mailItem;
+  LPDISPATCH sender;
+  LPDISPATCH recipients;
+
+  struct sink_s encsinkmem;
+  sink_t encsink = &encsinkmem;
+  struct sink_s sinkmem;
+  sink_t sink = &sinkmem;
+  char* senderAddr = NULL;
+  LPSTREAM tmpstream = NULL;
+  engine_filter_t filter = NULL;
+  char* text = NULL;
+  int rc = 0;
+  HRESULT hr;
+  int recipientsCnt;
+  HWND curWindow;
+  LPOLEWINDOW actExplorer;
+  protocol_t protocol;
+  unsigned int session_number;
+  int i;
+  STATSTG tmpStat;
+
+  hr = getContext (ctrl, &context);
+  if (FAILED(hr))
+      return hr;
+
+  memset (encsink, 0, sizeof *encsink);
+  memset (sink, 0, sizeof *sink);
+
+  actExplorer = (LPOLEWINDOW) get_oom_object(context,
+                                             "Application.ActiveExplorer");
+  if (actExplorer)
+    actExplorer->GetWindow (&curWindow);
+  else
+    {
+      log_debug ("%s:%s: Could not find active window",
+                 SRCNAME, __func__);
+      curWindow = NULL;
+    }
+
+  wordEditor = get_oom_object (context, "WordEditor");
+  application = get_oom_object (wordEditor, "get_Application");
+  selection = get_oom_object (application, "get_Selection");
+  mailItem = get_oom_object (context, "CurrentItem");
+  sender = get_oom_object (mailItem, "Session.CurrentUser");
+  recipients = get_oom_object (mailItem, "Recipients");
+
+  if (!wordEditor || !application || !selection || !mailItem ||
+      !sender || !recipients)
+    {
+      MessageBox (NULL,
+                  _("Internal error in GpgOL.\n"
+                    "Could not find all objects."),
+                  _("GpgOL"),
+                  MB_ICONINFORMATION|MB_OK);
+      log_error ("%s:%s: Could not find all objects.",
+                 SRCNAME, __func__);
+      return S_OK;
+    }
+
+  text = get_oom_string (selection, "Text");
+
+  if (!text || strlen (text) <= 1)
+    {
+      /* TODO more usable if we just use all text in this case? */
+      MessageBox (NULL,
+                  _("Please select some text for encryption."),
+                  _("GpgOL"),
+                  MB_ICONINFORMATION|MB_OK);
+      return S_OK;
+    }
+
+  /* Create a temporary sink to construct the encrypted data.  */
+  hr = OpenStreamOnFile (MAPIAllocateBuffer, MAPIFreeBuffer,
+                         (SOF_UNIQUEFILENAME | STGM_DELETEONRELEASE
+                          | STGM_CREATE | STGM_READWRITE),
+                         NULL, "GPG", &tmpstream);
+
+  if (FAILED (hr))
+    {
+      log_error ("%s:%s: can't create temp file: hr=%#lx\n",
+                 SRCNAME, __func__, hr);
+      rc = -1;
+      goto failure;
+    }
+
+  sink->cb_data = tmpstream;
+  sink->writefnc = sink_std_write;
+
+  senderAddr = get_oom_string (sender, "Address");
+
+  recipientsCnt = get_oom_int (recipients, "Count");
+
+  if (!recipientsCnt)
+    {
+      MessageBox (NULL,
+                  _("Please enter the recipent of the encrypted text first."),
+                  _("GpgOL"),
+                  MB_ICONINFORMATION|MB_OK);
+      return S_OK;
+    }
+
+  {
+    /* Get the recipients */
+    char *recipientAddrs[recipientsCnt + 1];
+    recipientAddrs[recipientsCnt] = NULL;
+    for (i = 1; i <= recipientsCnt; i++)
+      {
+        char buf[16];
+        LPDISPATCH recipient;
+        snprintf (buf, sizeof (buf), "Item(%i)", i);
+        recipient = get_oom_object (recipients, buf);
+        if (!recipient)
+          {
+            /* Should be impossible */
+            recipientAddrs[i-1] = NULL;
+            log_error ("%s:%s: could not find Item %i;",
+                       SRCNAME, __func__, i);
+            break;
+          }
+        recipientAddrs[i-1] = get_oom_string (recipient, "Address");
+      }
+
+    /* Not lets prepare our encryption */
+    session_number = engine_new_session_number ();
+
+    /* Prepare the encryption sink */
+
+    if (engine_create_filter (&filter, write_buffer_for_cb, sink))
+      {
+        for (i = 0; i < recipientsCnt; i++)
+          xfree (recipientAddrs[i]);
+        goto failure;
+      }
+
+    encsink->cb_data = filter;
+    encsink->writefnc = sink_encryption_write;
+
+    engine_set_session_number (filter, session_number);
+      {
+        char *tmp = get_oom_string (mailItem, "Subject");
+        engine_set_session_title (filter, tmp);
+        xfree (tmp);
+      }
+
+    if ((rc=engine_encrypt_prepare (filter, curWindow,
+                                    protocol,
+                                    0 /* ENGINE_FLAG_SIGN_FOLLOWS */,
+                                    senderAddr, recipientAddrs, &protocol)))
+      {
+        for (i = 0; i < recipientsCnt; i++)
+          xfree (recipientAddrs[i]);
+        log_error ("%s:%s: engine encrypt prepare failed : %s",
+                   SRCNAME, __func__, gpg_strerror (rc));
+        goto failure;
+      }
+    for (i = 0; i < recipientsCnt; i++)
+      xfree (recipientAddrs[i]);
+
+    /* lets go */
+
+    if ((rc=engine_encrypt_start (filter, 0)))
+      {
+        log_error ("%s:%s: engine encrypt start failed: %s",
+                   SRCNAME, __func__, gpg_strerror (rc));
+        goto failure;
+      }
+
+    /* Write the text in the encryption sink. */
+    rc = write_buffer (encsink, text, strlen (text));
+
+    if (rc)
+      {
+        log_error ("%s:%s: writing tmpstream to encsink failed: %s",
+                   SRCNAME, __func__, gpg_strerror (rc));
+        goto failure;
+      }
+    /* Flush the encryption sink and wait for the encryption to get
+       ready.  */
+    if ((rc = write_buffer (encsink, NULL, 0)))
+      goto failure;
+    if ((rc = engine_wait (filter)))
+      goto failure;
+    filter = NULL; /* Not valid anymore.  */
+    encsink->cb_data = NULL; /* Not needed anymore.  */
+
+    if (!sink->enc_counter)
+      {
+        log_debug ("%s:%s: nothing received from engine", SRCNAME, __func__);
+        goto failure;
+      }
+  }
+
+  /* Check the size of the encrypted data */
+  tmpstream->Stat (&tmpStat, 0);
+
+  if (tmpStat.cbSize.QuadPart > UINT_MAX)
+    {
+      MessageBox (curWindow, _("GpgOL"),
+                  _("Selected text too long."),
+                  MB_ICONINFORMATION|MB_OK);
+      log_error ("%s:%s: No one should write so large mails.",
+                 SRCNAME, __func__);
+      goto failure;
+    }
+
+  /* Copy the encrypted stream to the message editor.  */
+  {
+    LARGE_INTEGER off;
+    ULONG nread;
+    char buffer[(unsigned int)tmpStat.cbSize.QuadPart];
+
+    off.QuadPart = 0;
+    hr = tmpstream->Seek (off, STREAM_SEEK_SET, NULL);
+    if (hr)
+      {
+        log_error ("%s:%s: seeking back to the begin failed: hr=%#lx",
+                   SRCNAME, __func__, hr);
+        rc = gpg_error (GPG_ERR_EIO);
+        goto failure;
+      }
+    hr = tmpstream->Read (buffer, sizeof buffer, &nread);
+    if (hr)
+      {
+        log_error ("%s:%s: IStream::Read failed: hr=%#lx",
+                   SRCNAME, __func__, hr);
+        rc = gpg_error (GPG_ERR_EIO);
+        goto failure;
+      }
+    if (strlen (buffer) > 1)
+      {
+        /* Now replace the selection with the encrypted text */
+        put_oom_string (selection, "Text", buffer);
+      }
+    else
+      {
+        /* Just to be save not to overwrite the selection with
+           an empty buffer */
+        log_error ("%s:%s: unexpected problem ", SRCNAME, __func__);
+        goto failure;
+      }
+  }
+
+ failure:
+  if (rc)
+    log_debug ("%s:%s: failed rc=%d (%s) <%s>", SRCNAME, __func__, rc,
+               gpg_strerror (rc), gpg_strsource (rc));
+  engine_cancel (filter);
+  if (tmpstream)
+    tmpstream->Release();
+  xfree (senderAddr);
+
+  return S_OK;
+}
+
+HRESULT
+decryptAttachments (LPDISPATCH ctrl)
+{
+  LPDISPATCH context = NULL;
+  LPDISPATCH attachmentSelection;
+  int attachmentCount;
+  HRESULT hr = 0;
+  int i = 0;
+  HWND curWindow;
+  LPOLEWINDOW actExplorer;
+  int err;
+
+  hr = getContext(ctrl, &context);
+
+  attachmentSelection = get_oom_object (context, "AttachmentSelection");
+  if (!attachmentSelection)
+    {
+      /* We can be called from a context menu, in that case we
+         directly have an AttachmentSelection context. Otherwise
+         we have an Explorer context with an Attachment Selection property. */
+      attachmentSelection = context;
+    }
+
+  attachmentCount = get_oom_int (attachmentSelection, "Count");
+
+  actExplorer = (LPOLEWINDOW) get_oom_object(attachmentSelection,
+                                             "Application.ActiveExplorer");
+  if (actExplorer)
+    actExplorer->GetWindow (&curWindow);
+  else
+    {
+      log_debug ("%s:%s: Could not find active window",
+                 SRCNAME, __func__);
+      curWindow = NULL;
+    }
+  {
+    char *filenames[attachmentCount + 1];
+    filenames[attachmentCount] = NULL;
+    /* Yes the items start at 1! */
+    for (i = 1; i <= attachmentCount; i++)
+      {
+        char buf[16];
+        char *filename;
+        wchar_t *wcsOutFilename;
+        DISPPARAMS saveParams;
+        VARIANT aVariant[1];
+        LPDISPATCH attachmentObj;
+        DISPID saveID;
+
+        snprintf (buf, sizeof (buf), "Item(%i)", i);
+        attachmentObj = get_oom_object (attachmentSelection, buf);
+        if (!attachmentObj)
+          {
+            /* Should be impossible */
+            filenames[i-1] = NULL;
+            log_error ("%s:%s: could not find Item %i;",
+                       SRCNAME, __func__, i);
+            break;
+          }
+        filename = get_oom_string (attachmentObj, "FileName");
+
+        saveID = lookup_oom_dispid (attachmentObj, "SaveAsFile");
+
+        saveParams.rgvarg = aVariant;
+        saveParams.rgvarg[0].vt = VT_BSTR;
+        filenames[i-1] = get_save_filename (NULL, filename);
+        xfree (filename);
+
+        wcsOutFilename = utf8_to_wchar2 (filenames[i-1],
+                                         strlen(filenames[i-1]));
+        saveParams.rgvarg[0].bstrVal = SysAllocString (wcsOutFilename);
+        saveParams.cArgs = 1;
+        saveParams.cNamedArgs = 0;
+
+        hr = attachmentObj->Invoke (saveID, IID_NULL, LOCALE_SYSTEM_DEFAULT,
+                                    DISPATCH_METHOD, &saveParams,
+                                    NULL, NULL, NULL);
+        SysFreeString (saveParams.rgvarg[0].bstrVal);
+        if (FAILED(hr))
+          {
+            int j;
+            log_debug ("%s:%s: Saving to file failed. hr: %x",
+                       SRCNAME, __func__, (unsigned int) hr);
+            for (j = 0; j < i; j++)
+              xfree (filenames[j]);
+            return hr;
+          }
+      }
+    err = op_assuan_start_decrypt_files (curWindow, filenames);
+    for (i = 0; i < attachmentCount; i++)
+      xfree (filenames[i]);
+  }
+
+  log_debug ("%s:%s: Leaving. Err: %i",
+             SRCNAME, __func__, err);
+
+  return S_OK; /* If we return an error outlook will show that our
+                  callback function failed in an ugly window. */
+}
diff --git a/src/ribbon-callbacks.h b/src/ribbon-callbacks.h
new file mode 100644
index 0000000..547e17d
--- /dev/null
+++ b/src/ribbon-callbacks.h
@@ -0,0 +1,31 @@
+/* ribbon-callbacks.h - Callbacks for the ribbon extension interface
+ *    Copyright (C) 2013 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RIBBON_CALLBACKS_H
+#define RIBBON_CALLBACKS_H
+
+#include "gpgoladdin.h"
+
+/* Id's of our callbacks */
+#define ID_CMD_DECRYPT           2
+#define ID_CMD_ENCRYPT_SELECTION 3
+
+HRESULT decryptAttachments (LPDISPATCH ctrl);
+HRESULT encryptSelection (LPDISPATCH ctrl);
+#endif

commit 3fc86e1ca4700c6a91ddab8168fdbe486616e996
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jul 9 14:25:15 2013 +0000

    Excpose sink functions and structures
    
        * src/mimemaker.c (write_buffer, sink_std_write),
        (write_buffer_for_cb, sink_encryption_write): Remove staticness.
        * src/mimemaker.h (write_buffer, sink_std_write),
        (write_buffer_for_cb, sink_encryption_write): Add prototypes.
        * src/mimemaker.c, src/mimemaker.h (sink_s, sink_t): Move
        declaration into header.
    
    --
        Those will be used in the ribbon callbacks

diff --git a/src/mimemaker.c b/src/mimemaker.c
index 8f25171..6a358a4 100644
--- a/src/mimemaker.c
+++ b/src/mimemaker.c
@@ -53,24 +53,6 @@ static unsigned char bintoasc[64+1] = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                        "abcdefghijklmnopqrstuvwxyz"
                                        "0123456789+/");
 
-/* The object we use instead of IStream.  It allows us to have a
-   callback method for output and thus for processing stuff
-   recursively.  */
-struct sink_s;
-typedef struct sink_s *sink_t;
-struct sink_s
-{
-  void *cb_data;
-  sink_t extrasink;
-  int (*writefnc)(sink_t sink, const void *data, size_t datalen);
-  unsigned long enc_counter; /* Used by write_buffer_for_cb.  */
-/*   struct { */
-/*     int idx; */
-/*     unsigned char inbuf[4]; */
-/*     int quads; */
-/*   } b64; */
-};
-
 
 /* Object used to collect data in a memory buffer.  */
 struct databuf_s
@@ -90,7 +72,7 @@ static int write_multistring (sink_t sink, const char *text1,
 
 

 /* Standard write method used with a sink_t object.  */
-static int
+int
 sink_std_write (sink_t sink, const void *data, size_t datalen)
 {
   HRESULT hr;
@@ -233,7 +215,7 @@ create_mapi_attachment (LPMESSAGE message, sink_t sink)
 
 
 /* Write data to a sink_t.  */
-static int
+int
 write_buffer (sink_t sink, const void *data, size_t datalen)
 {
   if (!sink || !sink->writefnc)
@@ -247,7 +229,7 @@ write_buffer (sink_t sink, const void *data, size_t datalen)
 /* Same as above but used for passing as callback function.  This
    fucntion does not return an error code but the number of bytes
    written.  */
-static int
+int
 write_buffer_for_cb (void *opaque, const void *data, size_t datalen)
 {
   sink_t sink = opaque;
@@ -1430,7 +1412,7 @@ mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol)
 
 

 /* Sink write method used by mime_encrypt.  */
-static int
+int
 sink_encryption_write (sink_t encsink, const void *data, size_t datalen)
 {
   engine_filter_t filter = encsink->cb_data;
diff --git a/src/mimemaker.h b/src/mimemaker.h
index 3c79e5a..0c804b3 100644
--- a/src/mimemaker.h
+++ b/src/mimemaker.h
@@ -26,12 +26,33 @@ extern "C" {
 #endif
 #endif
 
+/* The object we use instead of IStream.  It allows us to have a
+   callback method for output and thus for processing stuff
+   recursively.  */
+struct sink_s;
+typedef struct sink_s *sink_t;
+struct sink_s
+{
+  void *cb_data;
+  sink_t extrasink;
+  int (*writefnc)(sink_t sink, const void *data, size_t datalen);
+  unsigned long enc_counter; /* Used by write_buffer_for_cb.  */
+/*   struct { */
+/*     int idx; */
+/*     unsigned char inbuf[4]; */
+/*     int quads; */
+/*   } b64; */
+};
+
 int mime_sign (LPMESSAGE message, HWND hwnd, protocol_t protocol);
 int mime_encrypt (LPMESSAGE message, HWND hwnd,
                   protocol_t protocol, char **recipients);
 int mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
                        protocol_t protocol, char **recipients);
-
+int sink_std_write (sink_t sink, const void *data, size_t datalen);
+int sink_encryption_write (sink_t encsink, const void *data, size_t datalen);
+int write_buffer_for_cb (void *opaque, const void *data, size_t datalen);
+int write_buffer (sink_t sink, const void *data, size_t datalen);
 
 #ifdef __cplusplus
 }

commit 2dec95936ebfa8e8a8b5f474bfb423b5d18b40bb
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Jul 9 14:21:41 2013 +0000

    Improve debug output in get_oom_object
    
        Sometimes there is some additional information hidden
        in the execpinfo structure. So print it in case of an error.
    
        * src/oomhelp.cpp (dump_excepinfo): New. Dumps an excepinfo
        structure to log_debug.
        (get_oom_object): Use exceptinfo from Invoke call.

diff --git a/src/oomhelp.cpp b/src/oomhelp.cpp
index 7ee9108..c660629 100644
--- a/src/oomhelp.cpp
+++ b/src/oomhelp.cpp
@@ -105,6 +105,26 @@ lookup_oom_dispid (LPDISPATCH pDisp, const char *name)
   return dispid;
 }
 
+void
+dump_excepinfo (EXCEPINFO err)
+{
+  log_debug ("%s:%s: Dumping exception: \n"
+             "              wCode: 0x%x\n"
+             "              wReserved: 0x%x\n"
+             "              desc: %S\n"
+             "              help: %S\n"
+             "              helpCtx: 0x%x\n"
+             "              deferredFill: 0x%x\n"
+             "              scode: 0x%x\n"
+             "%s:%s: Dump done." ,
+             SRCNAME, __func__, (unsigned int) err.wCode,
+             (unsigned int) err.wReserved,
+             err.bstrSource, err.bstrDescription, err.bstrHelpFile,
+             (unsigned int) err.dwHelpContext,
+             (unsigned int) err.pfnDeferredFillIn,
+             (unsigned int) err.scode,
+             SRCNAME, __func__);
+}
 
 /* Return the OOM object's IDispatch interface described by FULLNAME.
    Returns NULL if not found.  PSTART is the object where the search
@@ -135,6 +155,8 @@ get_oom_object (LPDISPATCH pStart, const char *fullname)
       DISPID dispid;
       char *p, *pend;
       int dispmethod;
+      unsigned int argErr = 0;
+      EXCEPINFO execpinfo;
 
       if (pDisp)
         {
@@ -257,14 +279,16 @@ get_oom_object (LPDISPATCH pStart, const char *fullname)
       VariantInit (&vtResult);
       hr = pDisp->Invoke (dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
                           dispmethod, &dispparams,
-                          &vtResult, NULL, NULL);
+                          &vtResult, &execpinfo, &argErr);
       if (parmstr)
         SysFreeString (parmstr);
       if (hr != S_OK || vtResult.vt != VT_DISPATCH)
         {
-          log_debug ("%s:%s:       error: '%s' p=%p vt=%d hr=0x%x",
+          log_debug ("%s:%s:       error: '%s' p=%p vt=%d hr=0x%x argErr=0x%x",
                      SRCNAME, __func__,
-                     name, vtResult.pdispVal, vtResult.vt, (unsigned int)hr);
+                     name, vtResult.pdispVal, vtResult.vt, (unsigned int)hr,
+                     (unsigned int)argErr);
+          dump_excepinfo (execpinfo);
           VariantClear (&vtResult);
           if (parmstr)
             SysFreeString (parmstr);

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

Summary of changes:
 src/Makefile.am                       |    3 +-
 src/engine-assuan.c                   |    2 +-
 src/gpgoladdin.cpp                    |  190 +++++-----------
 src/gpgoladdin.h                      |    3 -
 src/mimemaker.c                       |   26 +--
 src/mimemaker.h                       |   23 ++-
 src/oomhelp.cpp                       |   30 +++-
 src/ribbon-callbacks.cpp              |  417 +++++++++++++++++++++++++++++++++
 src/{xmalloc.h => ribbon-callbacks.h} |   37 +--
 9 files changed, 544 insertions(+), 187 deletions(-)
 create mode 100644 src/ribbon-callbacks.cpp
 copy src/{xmalloc.h => ribbon-callbacks.h} (62%)


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




More information about the Gnupg-commits mailing list