[git] GpgOL - branch, master, updated. gpgol-1.1.3-56-gc607ce5

by Andre Heinecke cvs at cvs.gnupg.org
Thu Aug 8 16:52:21 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, master has been updated
       via  c607ce5551ec261b0c51daf10c32142cd7c60eb2 (commit)
       via  d7e589d22a2bce76847d7f77ae89b45d7b911eb2 (commit)
       via  08984c034b6e04a5f49c5705eac1499fd94f06ad (commit)
       via  eb4a8b909508994236fcb8e967fe90a1ddbcf8b5 (commit)
       via  02c82f9197d0fa7dabce2e9fda1f8ca6514eec3b (commit)
      from  d1a9b54ba57016d0194ada1778f09126af1e9afd (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 c607ce5551ec261b0c51daf10c32142cd7c60eb2
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Aug 8 14:10:36 2013 +0000

    Add signature support for files and text
    
        For files a detached signature is created and additionally
        attached. This also generalizes the encryptInspector and
        uses it as a more generic interface to the message composer
        context.
    
        * src/common.c, src/common.h (get_pretty_attachment_name): Add
        Parameter to query for the name of a detached signature.
        * src/dialogs.h: Define ID for sign-48.png
        * src/engine-assuan.c, src/engine-assuan.h (op_assuan_sign): Add
        flags parameter to control signature options.
        * src/engine.c (engine_sign_start): Create detached signatures
        by default.
        (engine_sign_opaque_start): New. Creates an opaque signature.
        * src/engine.h (ENGINE_FLAG_DETACHED): New.
        * src/gpgoladdin.cpp (GetIDsOfNames, Invoke, GetCustomUI): Add
        sign Action.
        * src/sign-48.png: New.
        * src/Makefile.am (EXTRA_DIST): Add sing-48.png
        * src/ribbon-callbacks.cpp (copyFileToSink): New. Helper function
        to copy the contents of a file into a sink.
        (attachSignature): New. Helper function to add a detached signature
        of a File to a MailItem.
        (encryptInspector, do_composer_action): Renamed. Actions and data is
        now controled by flags. Added sign action.
        (decryptInspector): Use subject as session title.
        (attachEncryptedFile): New. Attaches an encrypted file. Optionally
        also attaches the signature of that file.
        * src/ribbon-callbacks.h: Update accordingly.
    
    --
      It is not clear how we will handle text sign. For now you can just
      dump opaque signed data in the messagecomposer if you want to.
      Some clients like Kmail handle this gracefully. But we also need
      support for verify in Outlook.

diff --git a/src/Makefile.am b/src/Makefile.am
index 1c01565..c61a5d6 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,7 @@ EXTRA_DIST = \
 	key-manager-64.png \
 	decrypt-16.png decrypt-48.png \
 	encrypt-sign-file-48.png \
+	sign-48.png \
 	logo.bmp README.icons
 
 EXEEXT = .dll
diff --git a/src/common.c b/src/common.c
index 199103f..8473fee 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1056,11 +1056,14 @@ fix_linebreaks (char *str, int *len)
 }
 
 /* Get a pretty name for the file at path path. File extension
-   will be set to work for the protocol as provided in protocol.
+   will be set to work for the protocol as provided in protocol and
+   depends on the signature setting. Set signature to 0 if the
+   extension should not be a signature extension.
    Returns NULL on success.
    Caller must free result. */
 wchar_t *
-get_pretty_attachment_name (wchar_t *path, protocol_t protocol)
+get_pretty_attachment_name (wchar_t *path, protocol_t protocol,
+                            int signature)
 {
   wchar_t* pretty;
   wchar_t* buf;
@@ -1086,20 +1089,39 @@ get_pretty_attachment_name (wchar_t *path, protocol_t protocol)
   wcscpy (pretty, buf);
 
   buf = pretty + wcslen(pretty);
-  if (protocol == PROTOCOL_SMIME)
+  if (signature)
     {
-      *(buf++) = '.';
-      *(buf++) = 'p';
-      *(buf++) = '7';
-      *(buf++) = 'm';
-
+      if (protocol == PROTOCOL_SMIME)
+        {
+          *(buf++) = '.';
+          *(buf++) = 'p';
+          *(buf++) = '7';
+          *(buf++) = 's';
+        }
+      else
+        {
+          *(buf++) = '.';
+          *(buf++) = 's';
+          *(buf++) = 'i';
+          *(buf++) = 'g';
+        }
     }
   else
     {
-      *(buf++) = '.';
-      *(buf++) = 'g';
-      *(buf++) = 'p';
-      *(buf++) = 'g';
+      if (protocol == PROTOCOL_SMIME)
+        {
+          *(buf++) = '.';
+          *(buf++) = 'p';
+          *(buf++) = '7';
+          *(buf++) = 'm';
+        }
+      else
+        {
+          *(buf++) = '.';
+          *(buf++) = 'g';
+          *(buf++) = 'p';
+          *(buf++) = 'g';
+        }
     }
 
   return pretty;
diff --git a/src/common.h b/src/common.h
index a3efad6..c525a17 100644
--- a/src/common.h
+++ b/src/common.h
@@ -193,7 +193,8 @@ size_t b64_decode (b64_state_t *state, char *buffer, size_t length);
 /* Get a temporary filename with and its name */
 wchar_t *get_tmp_outfile (wchar_t *name, HANDLE *outHandle);
 
-wchar_t *get_pretty_attachment_name (wchar_t *path, protocol_t protocol);
+wchar_t *get_pretty_attachment_name (wchar_t *path, protocol_t protocol,
+                                     int signature);
 
 /* The length of the boundary - the buffer needs to be allocated one
    byte larger. */
diff --git a/src/dialogs.h b/src/dialogs.h
index e140507..7da915a 100644
--- a/src/dialogs.h
+++ b/src/dialogs.h
@@ -141,5 +141,6 @@
 #define IDI_DECRYPT_48_PNG              6011
 #define IDI_KEY_MANAGER_64_PNG          6020
 #define IDI_ENCSIGN_FILE_48_PNG         6030
+#define IDI_SIGN_48_PNG                 6040
 
 #endif /*DIALOGS_H*/
diff --git a/src/dialogs.rc b/src/dialogs.rc
index a5ba635..48ab013 100644
--- a/src/dialogs.rc
+++ b/src/dialogs.rc
@@ -34,6 +34,7 @@ IDB_SIGN_16               BITMAP  DISCARDABLE  "sign-16.bmp"
 IDB_SIGN_16M              BITMAP  DISCARDABLE  "sign-16m.bmp"
 IDB_SIGN_32               BITMAP  DISCARDABLE  "sign-32.bmp"
 IDB_SIGN_32M              BITMAP  DISCARDABLE  "sign-32m.bmp"
+IDI_SIGN_48_PNG           RCDATA               "sign-48.png"
 
 IDB_KEY_MANAGER_16        BITMAP  DISCARDABLE  "key-manager-16.bmp"
 IDB_KEY_MANAGER_16M       BITMAP  DISCARDABLE  "key-manager-16m.bmp"
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index 9af3782..c7f3312 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -1805,11 +1805,12 @@ sign_closure (closure_data_t cld)
    called with FILTER as the first argument.  SENDER is the sender's
    mail address (a mailbox).  The used protocol will be stored at
    R_USED_PROTOCOL on return. */
-int 
-op_assuan_sign (protocol_t protocol, 
+int
+op_assuan_sign (protocol_t protocol,
                 gpgme_data_t indata, gpgme_data_t outdata,
                 engine_filter_t filter, void *hwnd,
-                const char *sender, protocol_t *r_used_protocol)
+                const char *sender, protocol_t *r_used_protocol,
+                int flags)
 {
   gpg_error_t err;
   closure_data_t cld;
@@ -1894,8 +1895,11 @@ op_assuan_sign (protocol_t protocol,
   enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, 
                     cmdid, NULL, 1 /* Wait on success */, 0); 
 
-  snprintf (line, sizeof line, "SIGN --protocol=%s --detached",
-            protocol_name);
+  if (flags & ENGINE_FLAG_DETACHED)
+    snprintf (line, sizeof line, "SIGN --protocol=%s --detached",
+              protocol_name);
+  else
+    snprintf (line, sizeof line, "SIGN --protocol=%s", protocol_name);
   err = start_command (ctx, cld, cmdid, line);
   cld = NULL; /* Now owned by start_command.  */
   if (err)
diff --git a/src/engine-assuan.h b/src/engine-assuan.h
index de2a144..237bd85 100644
--- a/src/engine-assuan.h
+++ b/src/engine-assuan.h
@@ -37,7 +37,7 @@ int  op_assuan_init (void);
 void op_assuan_deinit (void);
 void engine_assuan_cancel (void *cancel_data);
 
-int op_assuan_encrypt (protocol_t protocol, 
+int op_assuan_encrypt (protocol_t protocol,
                        gpgme_data_t indata, gpgme_data_t outdata,
                        engine_filter_t notify_data, void *hwnd,
                        unsigned int flags,
@@ -46,15 +46,16 @@ int op_assuan_encrypt (protocol_t protocol,
                        struct engine_assuan_encstate_s **r_encstate);
 int op_assuan_encrypt_bottom (struct engine_assuan_encstate_s *encstate,
                               int cancel);
-int op_assuan_sign (protocol_t protocol, 
+int op_assuan_sign (protocol_t protocol,
                     gpgme_data_t indata, gpgme_data_t outdata,
                     engine_filter_t filter, void *hwnd,
-                    const char *sender, protocol_t *r_used_protocol);
+                    const char *sender, protocol_t *r_used_protocol,
+                    int flags);
 int op_assuan_decrypt (protocol_t protocol,
-                       gpgme_data_t indata, gpgme_data_t outdata, 
+                       gpgme_data_t indata, gpgme_data_t outdata,
                        engine_filter_t filter, void *hwnd,
                        int with_verify, const char *from_address);
-int op_assuan_verify (gpgme_protocol_t protocol, 
+int op_assuan_verify (gpgme_protocol_t protocol,
                       gpgme_data_t data, const char *signature, size_t sig_len,
                       gpgme_data_t outdata,
                       engine_filter_t filter, void *hwnd,
diff --git a/src/engine.c b/src/engine.c
index 04c45ef..1dc471e 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -906,7 +906,8 @@ engine_sign_start (engine_filter_t filter, HWND hwnd, protocol_t protocol,
   if (filter->use_assuan)
     {
       err = op_assuan_sign (protocol, filter->indata, filter->outdata,
-                            filter, hwnd, sender, &used_protocol);
+                            filter, hwnd, sender, &used_protocol,
+                            ENGINE_FLAG_DETACHED);
       if (!err)
         *r_protocol = used_protocol;
     }
@@ -921,6 +922,30 @@ engine_sign_start (engine_filter_t filter, HWND hwnd, protocol_t protocol,
   return err;
 }
 
+/* Start an inline signing operation. Same as engine_sign_start but
+   without the detatched option. */
+int
+engine_sign_opaque_start (engine_filter_t filter, HWND hwnd,
+                          protocol_t protocol, const char *sender,
+                          protocol_t *r_protocol)
+{
+  gpg_error_t err;
+  protocol_t used_protocol;
+
+  if (filter->use_assuan)
+    {
+      err = op_assuan_sign (protocol, filter->indata, filter->outdata,
+                            filter, hwnd, sender, &used_protocol,
+                            0);
+      if (!err)
+        *r_protocol = used_protocol;
+    }
+  else
+    return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+  return err;
+}
+
 
 /* Start an decrypt operation.  FILTER is an object created by
    engine_create_filter.  The caller needs to call engine_wait to
diff --git a/src/engine.h b/src/engine.h
index 0dd07fc..bba50c3 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -47,6 +47,7 @@ typedef struct engine_filter_s *engine_filter_t;
 /* Flag values used by the engine functions.  */
 #define ENGINE_FLAG_SIGN_FOLLOWS  1  /* Expect a sign+encrypt operation.  */
 #define ENGINE_FLAG_BINARY_OUTPUT 2  /* Create binary output */
+#define ENGINE_FLAG_DETACHED      4  /* Create detached signature */
 
 
 
@@ -81,6 +82,9 @@ int engine_encrypt_prepare (engine_filter_t filter, HWND hwnd,
 int engine_encrypt_start (engine_filter_t filter, int cancel);
 int engine_sign_start (engine_filter_t filter, HWND hwnd, protocol_t protocol,
                        const char *sender, protocol_t *r_protocol);
+int engine_sign_opaque_start (engine_filter_t filter, HWND hwnd,
+                              protocol_t protocol, const char *sender,
+                              protocol_t *r_protocol);
 
 int engine_decrypt_start (engine_filter_t filter, HWND hwnd,
                           protocol_t protocol, int with_verify,
diff --git a/src/gpgoladdin.cpp b/src/gpgoladdin.cpp
index 74bafcf..35e1f72 100644
--- a/src/gpgoladdin.cpp
+++ b/src/gpgoladdin.cpp
@@ -451,9 +451,11 @@ GpgolRibbonExtender::GetIDsOfNames (REFIID riid, LPOLESTR *rgszNames,
       ID_MAPPER (L"btnEncrypt", ID_BTN_ENCRYPT)
       ID_MAPPER (L"btnEncryptLarge", ID_BTN_ENCRYPT_LARGE)
       ID_MAPPER (L"btnEncryptFileLarge", ID_BTN_ENCSIGN_LARGE)
+      ID_MAPPER (L"btnSignLarge", ID_BTN_SIGN_LARGE)
       ID_MAPPER (L"encryptBody", ID_CMD_ENCRYPT_BODY)
       ID_MAPPER (L"decryptBody", ID_CMD_DECRYPT_BODY)
       ID_MAPPER (L"addEncSignedAttachment", ID_CMD_ATT_ENCSIGN_FILE)
+      ID_MAPPER (L"signBody", ID_CMD_SIGN_BODY)
     }
 
   if (cNames > 1)
@@ -497,12 +499,15 @@ GpgolRibbonExtender::Invoke (DISPID dispid, REFIID riid, LCID lcid,
         return decryptBody (parms->rgvarg[0].pdispVal);
       case ID_CMD_ATT_ENCSIGN_FILE:
         return addEncSignedAttachment (parms->rgvarg[0].pdispVal);
+      case ID_CMD_SIGN_BODY:
+        return signBody (parms->rgvarg[0].pdispVal);
       case ID_BTN_CERTMANAGER:
       case ID_BTN_ENCRYPT:
       case ID_BTN_DECRYPT:
       case ID_BTN_DECRYPT_LARGE:
       case ID_BTN_ENCRYPT_LARGE:
       case ID_BTN_ENCSIGN_LARGE:
+      case ID_BTN_SIGN_LARGE:
         return getIcon (dispid, result);
     }
 
@@ -560,6 +565,11 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
         L"               size=\"large\""
         L"               label=\"%S\""
         L"               onAction=\"decryptBody\"/>"
+        L"       <button id=\"fullTextSign\""
+        L"               getImage=\"btnSignLarge\""
+        L"               size=\"large\""
+        L"               label=\"%S\""
+        L"               onAction=\"signBody\"/>"
         L"     </group>"
         L"     <group id=\"attachmentGroup\""
         L"            label=\"%S\">"
@@ -589,8 +599,9 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
         _("Textbody"),
         _("Encrypt"),
         _("Decrypt"),
+        _("Sign"),
         _("Attachments"),
-        _("Add Encrypted file"),
+        _("Encrypted file and Signature"),
         _("Encrypt"), _("Decrypt")
         );
     }
diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
index 0143f7c..9ebc1d2 100644
--- a/src/ribbon-callbacks.cpp
+++ b/src/ribbon-callbacks.cpp
@@ -56,17 +56,126 @@ HRESULT getContext (LPDISPATCH ctrl, LPDISPATCH *context)
   return context ? S_OK : E_FAIL;
 }
 
-#define ENCRYPT_INSPECTOR_SELECTION  1
-#define ENCRYPT_INSPECTOR_BODY       2
+#define OP_ENCRYPT     1 /* Encrypt the data */
+#define OP_SIGN        2 /* Sign the data */
+#define DATA_BODY      4 /* Use text body as data */
+#define DATA_SELECTION 8 /* Use selection as data */
+
+/* Read hfile in chunks of 4KB and writes them to the sink */
+static int
+copyFileToSink (HANDLE hFile, sink_t sink)
+{
+  char buf[4096];
+  DWORD bytesRead = 0;
+  do
+    {
+      if (!ReadFile (hFile, buf, sizeof buf, &bytesRead, NULL))
+        {
+          log_error ("%s:%s: Could not read source file.",
+                     SRCNAME, __func__);
+          return -1;
+        }
+      if (write_buffer (sink, bytesRead ? buf : NULL, bytesRead))
+        {
+          log_error ("%s:%s: Could not write out buffer",
+                     SRCNAME, __func__);
+          return -1;
+        }
+    }
+  while (bytesRead);
+  return 0;
+}
+
+static int
+attachSignature (LPDISPATCH mailItem, char *subject, HANDLE hFileToSign,
+                 protocol_t protocol, unsigned int session_number,
+                 HWND curWindow, wchar_t *originalFilename, char *sender)
+{
+  wchar_t *sigName = NULL;
+  wchar_t *sigFileName = NULL;
+  HANDLE hSigFile = NULL;
+  int rc = 0;
+  struct sink_s encsinkmem;
+  sink_t encsink = &encsinkmem;
+  struct sink_s sinkmem;
+  sink_t sink = &sinkmem;
+  engine_filter_t filter = NULL;
+
+  memset (encsink, 0, sizeof *encsink);
+  memset (sink, 0, sizeof *sink);
+
+  /* Prepare a fresh filter */
+  if ((rc = engine_create_filter (&filter, write_buffer_for_cb, sink)))
+    {
+      goto failure;
+    }
+  encsink->cb_data = filter;
+  encsink->writefnc = sink_encryption_write;
+  engine_set_session_number (filter, session_number);
+  engine_set_session_title (filter, subject ? subject :_("GpgOL"));
+
+  if (engine_sign_start (filter, curWindow, protocol, sender, &protocol))
+    goto failure;
+
+  sigName = get_pretty_attachment_name (originalFilename, protocol, 1);
+
+  /* If we are unlucky the number of temporary file artifacts might
+     differ for the signature and the encrypted file but we have
+     to live with that. */
+  sigFileName = get_tmp_outfile (sigName, &hSigFile);
+  sink->cb_data = hSigFile;
+  sink->writefnc = sink_file_write;
+
+  if (!sigFileName)
+    {
+      log_error ("%s:%s: Could not get a decent attachment name",
+                 SRCNAME, __func__);
+      goto failure;
+    }
+
+  /* Reset the file to sign handle to the beginning of the file and
+     copy it to the signature buffer */
+  SetFilePointer (hFileToSign, 0, NULL, 0);
+  if ((rc=copyFileToSink (hFileToSign, encsink)))
+    goto failure;
+
+  /* Lets hope the user did not select a huge file. We are hanging
+     here until encryption is completed.. */
+  if ((rc = engine_wait (filter)))
+    goto failure;
+
+  filter = NULL; /* Not valid anymore.  */
+  encsink->cb_data = NULL; /* Not needed anymore.  */
+
+  if (!sink->enc_counter)
+    {
+      log_error ("%s:%s: nothing received from engine", SRCNAME, __func__);
+      goto failure;
+    }
 
-/* encryptInspector
-   Encrypts text in an IInspector context. Depending on
-   the flags either the active selection or the full body
-   is encrypted.
+  /* Now we have an encrypted file behind encryptedFile. Let's add it */
+  add_oom_attachment (mailItem, sigFileName);
+
+failure:
+  xfree (sigFileName);
+  xfree (sigName);
+  if (hSigFile)
+    {
+      CloseHandle (hSigFile);
+      DeleteFileW (sigFileName);
+    }
+  return rc;
+}
+
+/* do_composer_action
+   Encrypts / Signs text in an IInspector context.
+   Depending on the flags either the
+   active selection or the full body is encrypted.
+   Combine OP_ENCRYPT and OP_SIGN if you want both.
 */
 
 HRESULT
-encryptInspector (LPDISPATCH ctrl, int flags)
+do_composer_action (LPDISPATCH ctrl, int flags)
 {
   LPDISPATCH context = NULL;
   LPDISPATCH selection = NULL;
@@ -124,7 +233,7 @@ encryptInspector (LPDISPATCH ctrl, int flags)
       goto failure;
     }
 
-  if (flags & ENCRYPT_INSPECTOR_SELECTION)
+  if (flags & DATA_SELECTION)
     {
       plaintext = get_oom_string (selection, "Text");
 
@@ -137,7 +246,7 @@ encryptInspector (LPDISPATCH ctrl, int flags)
           goto failure;
         }
     }
-  else if (flags & ENCRYPT_INSPECTOR_BODY)
+  else if (flags & DATA_BODY)
     {
       plaintext = get_oom_string (mailItem, "Body");
       if (!plaintext || strlen (plaintext) <= 1)
@@ -167,19 +276,6 @@ encryptInspector (LPDISPATCH ctrl, int flags)
   sink->cb_data = tmpstream;
   sink->writefnc = sink_std_write;
 
-  senderAddr = get_oom_string (sender, "Address");
-
-  recipientAddrs = get_oom_recipients (recipients);
-
-  if (!recipientAddrs || !(*recipientAddrs))
-    {
-      MessageBox (NULL,
-                  _("Please add at least one recipent."),
-                  _("GpgOL"),
-                  MB_ICONINFORMATION|MB_OK);
-      goto failure;
-    }
-
   /* Now lets prepare our encryption */
   session_number = engine_new_session_number ();
 
@@ -196,23 +292,51 @@ encryptInspector (LPDISPATCH ctrl, int flags)
   engine_set_session_number (filter, session_number);
   engine_set_session_title (filter, _("GpgOL"));
 
-  if ((rc=engine_encrypt_prepare (filter, curWindow,
-                                  PROTOCOL_UNKNOWN,
-                                  0 /* ENGINE_FLAG_SIGN_FOLLOWS */,
-                                  senderAddr, recipientAddrs, &protocol)))
+  senderAddr = get_oom_string (sender, "Address");
+
+  if (flags & OP_ENCRYPT)
     {
-      log_error ("%s:%s: engine encrypt prepare failed : %s",
-                 SRCNAME, __func__, gpg_strerror (rc));
-      goto failure;
-    }
+      recipientAddrs = get_oom_recipients (recipients);
+
+      if (!recipientAddrs || !(*recipientAddrs))
+        {
+          MessageBox (NULL,
+                      _("Please add at least one recipent."),
+                      _("GpgOL"),
+                      MB_ICONINFORMATION|MB_OK);
+          goto failure;
+        }
 
-  /* lets go */
+      if ((rc=engine_encrypt_prepare (filter, curWindow,
+                                      PROTOCOL_UNKNOWN,
+                                      (flags & OP_SIGN) ?
+                                      ENGINE_FLAG_SIGN_FOLLOWS : 0,
+                                      senderAddr, recipientAddrs,
+                                      &protocol)))
+        {
+          log_error ("%s:%s: engine encrypt prepare failed : %s",
+                     SRCNAME, __func__, gpg_strerror (rc));
+          goto failure;
+        }
 
-  if ((rc=engine_encrypt_start (filter, 0)))
+      if ((rc=engine_encrypt_start (filter, 0)))
+        {
+          log_error ("%s:%s: engine encrypt start failed: %s",
+                     SRCNAME, __func__, gpg_strerror (rc));
+          goto failure;
+        }
+    }
+  else
     {
-      log_error ("%s:%s: engine encrypt start failed: %s",
-                 SRCNAME, __func__, gpg_strerror (rc));
-      goto failure;
+      /* We could do some kind of clearsign / sign text as attachment here
+      but it is error prone */
+      if ((rc=engine_sign_opaque_start (filter, curWindow, PROTOCOL_UNKNOWN,
+                                        senderAddr, &protocol)))
+        {
+          log_error ("%s:%s: engine sign start failed: %s",
+                     SRCNAME, __func__, gpg_strerror (rc));
+          goto failure;
+        }
     }
 
   /* Write the text in the encryption sink. */
@@ -286,17 +410,17 @@ encryptInspector (LPDISPATCH ctrl, int flags)
                       "-----BEGIN ENCRYPTED MESSAGE-----\r\n"
                       "%s"
                       "-----END ENCRYPTED MESSAGE-----\r\n", buffer);
-            if (flags & ENCRYPT_INSPECTOR_SELECTION)
+            if (flags & DATA_SELECTION)
               put_oom_string (selection, "Text", enclosedData);
-            else if (flags & ENCRYPT_INSPECTOR_BODY)
+            else if (flags & DATA_BODY)
               put_oom_string (mailItem, "Body", enclosedData);
 
           }
         else
           {
-            if (flags & ENCRYPT_INSPECTOR_SELECTION)
+            if (flags & DATA_SELECTION)
               put_oom_string (selection, "Text", buffer);
-            else if (flags & ENCRYPT_INSPECTOR_BODY)
+            else if (flags & DATA_BODY)
               {
                 put_oom_string (mailItem, "Body", buffer);
               }
@@ -438,7 +562,7 @@ decryptAttachments (LPDISPATCH ctrl)
 
 /* decryptInspector
    decrypts the content of an inspector. Controled by flags
-   similary to the encryptInspector.
+   similary to the do_composer_action.
 */
 
 HRESULT
@@ -459,6 +583,8 @@ decryptInspector (LPDISPATCH ctrl, int flags)
   engine_filter_t filter = NULL;
   HWND curWindow;
   char* encData = NULL;
+  char* senderAddr = NULL;
+  char* subject = NULL;
   int encDataLen = 0;
   int rc = 0;
   unsigned int session_number;
@@ -542,6 +668,9 @@ decryptInspector (LPDISPATCH ctrl, int flags)
 
   fix_linebreaks (encData, &encDataLen);
 
+  subject = get_oom_string (mailItem, "Subject");
+  senderAddr = get_oom_string (mailItem, "SenderEmailAddress");
+
   /* Determine the protocol based on the content */
   protocol = is_cms_data (encData, encDataLen) ? PROTOCOL_SMIME :
     PROTOCOL_OPENPGP;
@@ -570,7 +699,7 @@ decryptInspector (LPDISPATCH ctrl, int flags)
   decsink->writefnc = sink_encryption_write;
 
   engine_set_session_number (filter, session_number);
-  engine_set_session_title (filter, _("GpgOL"));
+  engine_set_session_title (filter, subject ? subject : _("GpgOL"));
 
   if ((rc=engine_decrypt_start (filter, curWindow,
                                 protocol,
@@ -638,7 +767,7 @@ decryptInspector (LPDISPATCH ctrl, int flags)
       {
         /* Now replace the crypto data with the decrypted data or show it
         somehow.*/
-        int err;
+        int err = 0;
         if (flags & DECRYPT_INSPECTOR_SELECTION)
           {
             err = put_oom_string (selection, "Text", buffer);
@@ -674,6 +803,8 @@ decryptInspector (LPDISPATCH ctrl, int flags)
   RELDISP (wordEditor);
   RELDISP (wordApplication);
   xfree (encData);
+  xfree (senderAddr);
+  xfree (subject);
   if (tmpstream)
     tmpstream->Release();
 
@@ -779,48 +910,10 @@ getIcon (int id, VARIANT* result)
   return S_OK;
 }
 
-HRESULT
-startCertManager (LPDISPATCH ctrl)
-{
-  HRESULT hr;
-  LPDISPATCH context;
-  HWND curWindow;
-
-  hr = getContext (ctrl, &context);
-  if (FAILED(hr))
-      return hr;
-
-  curWindow = get_oom_context_window (context);
-
-  engine_start_keymanager (curWindow);
-}
-
-HRESULT
-decryptBody (LPDISPATCH ctrl)
-{
-  return decryptInspector (ctrl, DECRYPT_INSPECTOR_BODY);
-}
-
-HRESULT
-decryptSelection (LPDISPATCH ctrl)
-{
-  return decryptInspector (ctrl, DECRYPT_INSPECTOR_SELECTION);
-}
-
-HRESULT
-encryptBody (LPDISPATCH ctrl)
-{
-  return encryptInspector (ctrl, ENCRYPT_INSPECTOR_BODY);
-}
-
-HRESULT
-encryptSelection (LPDISPATCH ctrl)
-{
-  return encryptInspector (ctrl, ENCRYPT_INSPECTOR_SELECTION);
-}
-
-HRESULT
-addEncSignedAttachment (LPDISPATCH ctrl)
+/* Adds an encrypted attachment if the flag OP_SIGN is set
+   a detached signature of the encrypted file is also added. */
+static HRESULT
+attachEncryptedFile (LPDISPATCH ctrl, int flags)
 {
   LPDISPATCH context = NULL;
   LPDISPATCH mailItem = NULL;
@@ -829,6 +922,7 @@ addEncSignedAttachment (LPDISPATCH ctrl)
   HRESULT hr;
   char* senderAddr = NULL;
   char** recipientAddrs = NULL;
+  char* subject = NULL;
 
   HWND curWindow;
   char *fileToEncrypt = NULL;
@@ -845,10 +939,8 @@ addEncSignedAttachment (LPDISPATCH ctrl)
   sink_t sink = &sinkmem;
   engine_filter_t filter = NULL;
   protocol_t protocol;
-  STATSTG tmpStat;
   int rc = 0;
   int i = 0;
-  LPSTREAM tmpstream = NULL;
 
   memset (encsink, 0, sizeof *encsink);
   memset (sink, 0, sizeof *sink);
@@ -923,8 +1015,12 @@ addEncSignedAttachment (LPDISPATCH ctrl)
 
   senderAddr = get_oom_string (sender, "Address");
 
+  curWindow = get_oom_context_window (context);
+
   session_number = engine_new_session_number ();
 
+  subject = get_oom_string (mailItem, "Subject");
+
   /* Prepare the encryption sink */
   if ((rc = engine_create_filter (&filter, write_buffer_for_cb, sink)))
     {
@@ -935,7 +1031,7 @@ addEncSignedAttachment (LPDISPATCH ctrl)
   encsink->writefnc = sink_encryption_write;
 
   engine_set_session_number (filter, session_number);
-  engine_set_session_title (filter, _("GpgOL"));
+  engine_set_session_title (filter, subject ? subject :_("GpgOL"));
   if ((rc=engine_encrypt_prepare (filter, curWindow,
                                   PROTOCOL_UNKNOWN,
                                   ENGINE_FLAG_BINARY_OUTPUT,
@@ -946,7 +1042,7 @@ addEncSignedAttachment (LPDISPATCH ctrl)
       goto failure;
     }
 
-  attachName = get_pretty_attachment_name (fileToEncryptW, protocol);
+  attachName = get_pretty_attachment_name (fileToEncryptW, protocol, 0);
 
   if (!attachName)
     {
@@ -966,32 +1062,11 @@ addEncSignedAttachment (LPDISPATCH ctrl)
       goto failure;
     }
 
-  /* Read the file in chunks and write them to the encryption
-     buffer */
-  {
-    char buf[4096];
-    DWORD bytesRead = 0;
-    do
-      {
-        if (!ReadFile (hFile, buf, sizeof buf, &bytesRead, NULL))
-          {
-            rc = -1;
-            log_error ("%s:%s: Could not read source file: %s",
-                       SRCNAME, __func__);
-            goto failure;
-          }
-        if ((rc = write_buffer (encsink, bytesRead ? buf : NULL, bytesRead)))
-          {
-            rc = -1;
-            log_error ("%s:%s: Could not wirte out buffer",
-                       SRCNAME, __func__);
-            goto failure;
-          }
-      }
-    while (bytesRead);
-  }
+  if ((rc=copyFileToSink (hFile, encsink)))
+    goto failure;
+
   /* Lets hope the user did not select a huge file. We are hanging
-     here until encryption is completed.. */
+   here until encryption is completed.. */
   if ((rc = engine_wait (filter)))
     goto failure;
 
@@ -1007,6 +1082,12 @@ addEncSignedAttachment (LPDISPATCH ctrl)
   /* Now we have an encrypted file behind encryptedFile. Let's add it */
   add_oom_attachment (mailItem, encryptedFile);
 
+  if (flags & OP_SIGN)
+    {
+      attachSignature (mailItem, subject, hEncFile, protocol, session_number,
+                       curWindow, fileToEncryptW, senderAddr);
+    }
+
 failure:
   if (filter)
     engine_cancel (filter);
@@ -1020,6 +1101,7 @@ failure:
   xfree (encryptedFile);
   xfree (fileToEncryptW);
   xfree (attachName);
+  xfree (subject);
   RELDISP (mailItem);
   RELDISP (sender);
   RELDISP (recipients);
@@ -1035,3 +1117,55 @@ failure:
 
   return S_OK;
 }
+
+HRESULT
+startCertManager (LPDISPATCH ctrl)
+{
+  HRESULT hr;
+  LPDISPATCH context;
+  HWND curWindow;
+
+  hr = getContext (ctrl, &context);
+  if (FAILED(hr))
+      return hr;
+
+  curWindow = get_oom_context_window (context);
+
+  engine_start_keymanager (curWindow);
+  return S_OK;
+}
+
+HRESULT
+decryptBody (LPDISPATCH ctrl)
+{
+  return decryptInspector (ctrl, DECRYPT_INSPECTOR_BODY);
+}
+
+HRESULT
+decryptSelection (LPDISPATCH ctrl)
+{
+  return decryptInspector (ctrl, DECRYPT_INSPECTOR_SELECTION);
+}
+
+HRESULT
+encryptBody (LPDISPATCH ctrl)
+{
+  return do_composer_action (ctrl, OP_ENCRYPT | DATA_BODY);
+}
+
+HRESULT
+encryptSelection (LPDISPATCH ctrl)
+{
+  return do_composer_action (ctrl, OP_ENCRYPT | DATA_SELECTION);
+}
+
+HRESULT
+addEncSignedAttachment (LPDISPATCH ctrl)
+{
+  return attachEncryptedFile (ctrl, OP_SIGN);
+}
+
+HRESULT signBody (LPDISPATCH ctrl)
+{
+  return do_composer_action (ctrl, DATA_BODY | OP_SIGN);
+}
diff --git a/src/ribbon-callbacks.h b/src/ribbon-callbacks.h
index f3b2eb2..fa6d63c 100644
--- a/src/ribbon-callbacks.h
+++ b/src/ribbon-callbacks.h
@@ -33,6 +33,7 @@
 #define ID_CMD_ENCRYPT_BODY      6
 #define ID_CMD_DECRYPT_BODY      8
 #define ID_CMD_ATT_ENCSIGN_FILE  9
+#define ID_CMD_SIGN_BODY        10
 
 #define ID_BTN_CERTMANAGER       IDI_KEY_MANAGER_64_PNG
 #define ID_BTN_DECRYPT           IDI_DECRYPT_16_PNG
@@ -40,6 +41,7 @@
 #define ID_BTN_ENCRYPT           IDI_ENCRYPT_16_PNG
 #define ID_BTN_ENCRYPT_LARGE     IDI_ENCRYPT_48_PNG
 #define ID_BTN_ENCSIGN_LARGE     IDI_ENCSIGN_FILE_48_PNG
+#define ID_BTN_SIGN_LARGE        IDI_SIGN_48_PNG
 
 HRESULT decryptAttachments (LPDISPATCH ctrl);
 HRESULT encryptSelection (LPDISPATCH ctrl);
@@ -49,4 +51,5 @@ HRESULT encryptBody (LPDISPATCH ctrl);
 HRESULT addEncSignedAttachment (LPDISPATCH ctrl);
 HRESULT getIcon (int id, VARIANT* result);
 HRESULT startCertManager (LPDISPATCH ctrl);
+HRESULT signBody (LPDISPATCH ctrl);
 #endif
diff --git a/src/sign-48.png b/src/sign-48.png
new file mode 100644
index 0000000..9d21a57
Binary files /dev/null and b/src/sign-48.png differ

commit d7e589d22a2bce76847d7f77ae89b45d7b911eb2
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Aug 8 14:04:55 2013 +0000

    Add icon for decrypt selection context action
    
        * src/gpgoladdin.cpp (GetCustomUI): Add btnDecrypt to
        decryptSelection action.

diff --git a/src/gpgoladdin.cpp b/src/gpgoladdin.cpp
index 7738c39..74bafcf 100644
--- a/src/gpgoladdin.cpp
+++ b/src/gpgoladdin.cpp
@@ -636,9 +636,10 @@ GpgolRibbonExtender::GetCustomUI (BSTR RibbonID, BSTR * RibbonXml)
         L" </ribbon>"
         L"<contextMenus>"
         L"<contextMenu idMso=\"ContextMenuReadOnlyMailText\">"
-        L" <button id=\"decryptReadButton\""
-        L"         label=\"%S\""
-        L"         onAction=\"decryptSelection\"/>"
+        L"   <button id=\"decryptReadButton\""
+        L"           label=\"%S\""
+        L"           getImage=\"btnDecrypt\""
+        L"           onAction=\"decryptSelection\"/>"
         L" </contextMenu>"
         L" <contextMenu idMso=\"ContextMenuAttachments\">"
         L"   <button id=\"gpgol_decrypt\""

commit 08984c034b6e04a5f49c5705eac1499fd94f06ad
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Aug 8 10:36:08 2013 +0000

    Initialize output buffers for encrypt / decrypt
    
        Fixes the uninialized data seen at the end of those actions
        and makes the lastlinebreak hack uneccessary.
    
        * src/ribbon-callbacks.cpp (decryptInspector, encryptInspector):
        Initialize buffers to make sure they are terminated.

diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
index 966d74f..0143f7c 100644
--- a/src/ribbon-callbacks.cpp
+++ b/src/ribbon-callbacks.cpp
@@ -253,7 +253,10 @@ encryptInspector (LPDISPATCH ctrl, int flags)
   {
     LARGE_INTEGER off;
     ULONG nread;
-    char buffer[(unsigned int)tmpStat.cbSize.QuadPart];
+
+    char buffer[(unsigned int)tmpStat.cbSize.QuadPart + 1];
+
+    memset (buffer, 0, sizeof buffer);
 
     off.QuadPart = 0;
     hr = tmpstream->Seek (off, STREAM_SEEK_SET, NULL);
@@ -264,7 +267,7 @@ encryptInspector (LPDISPATCH ctrl, int flags)
         rc = gpg_error (GPG_ERR_EIO);
         goto failure;
       }
-    hr = tmpstream->Read (buffer, sizeof buffer, &nread);
+    hr = tmpstream->Read (buffer, sizeof (buffer) - 1, &nread);
     if (hr)
       {
         log_error ("%s:%s: IStream::Read failed: hr=%#lx",
@@ -274,14 +277,6 @@ encryptInspector (LPDISPATCH ctrl, int flags)
       }
     if (strlen (buffer) > 1)
       {
-        char* lastlinebreak = strrchr (buffer, '\n');
-        if (lastlinebreak && (lastlinebreak - buffer) > 1)
-          {
-            /*XXX there is some strange data in the buffer
-              after the last linebreak investigate this and
-              fix it! */
-            lastlinebreak[1] = '\0';
-          }
         /* Now replace the selection with the encrypted text */
         if (protocol == PROTOCOL_SMIME)
           {
@@ -618,7 +613,9 @@ decryptInspector (LPDISPATCH ctrl, int flags)
   {
     LARGE_INTEGER off;
     ULONG nread;
-    char buffer[(unsigned int)tmpStat.cbSize.QuadPart];
+    char buffer[(unsigned int)tmpStat.cbSize.QuadPart + 1];
+
+    memset (buffer, 0, sizeof buffer);
 
     off.QuadPart = 0;
     hr = tmpstream->Seek (off, STREAM_SEEK_SET, NULL);
@@ -629,7 +626,7 @@ decryptInspector (LPDISPATCH ctrl, int flags)
         rc = gpg_error (GPG_ERR_EIO);
         goto failure;
       }
-    hr = tmpstream->Read (buffer, sizeof buffer, &nread);
+    hr = tmpstream->Read (buffer, sizeof (buffer) - 1, &nread);
     if (hr)
       {
         log_error ("%s:%s: IStream::Read failed: hr=%#lx",

commit eb4a8b909508994236fcb8e967fe90a1ddbcf8b5
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Aug 8 10:16:17 2013 +0000

    Initialize strings in conflict handler
    
        This fixes the name conflict handling as wcsncpy did not
        terminate the string with \0. Also add the space for
        the terminator in case our strings are MAX_PATH in length.
    
        * src/common.c (get_tmp_outfile): Initialize buffer variables

diff --git a/src/common.c b/src/common.c
index 3d101f5..199103f 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1149,8 +1149,11 @@ get_tmp_outfile (wchar_t *name, HANDLE *outHandle)
                                     FILE_ATTRIBUTE_TEMPORARY,
                                     NULL)) == INVALID_HANDLE_VALUE)
     {
-      wchar_t fnameBuf[MAX_PATH];
-      wchar_t origName[MAX_PATH];
+      wchar_t fnameBuf[MAX_PATH + 1];
+      wchar_t origName[MAX_PATH + 1];
+      memset (fnameBuf, 0, MAX_PATH + 1);
+      memset (origName, 0, MAX_PATH + 1);
+
       snwprintf (origName, MAX_PATH, L"%s%s", tmpPath, name);
       fileExt = wcschr (wcsrchr(origName, '\\'), '.');
       wcsncpy (fnameBuf, origName, fileExt - origName);

commit 02c82f9197d0fa7dabce2e9fda1f8ca6514eec3b
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Wed Aug 7 10:15:47 2013 +0000

    Share encrypted file for reading again.
    
        * src/common.c (get_tmp_outfile): Share for reading
    --
        The share mode and file attribute settings were a last minute
        addition to the previous patch and not properly tested.
        Without the share read setting outlook fails with an undefined
        errorcode on adding the attachment.

diff --git a/src/common.c b/src/common.c
index dd8b2d7..3d101f5 100644
--- a/src/common.c
+++ b/src/common.c
@@ -1143,7 +1143,7 @@ get_tmp_outfile (wchar_t *name, HANDLE *outHandle)
 
   while ((*outHandle = CreateFileW (outName,
                                     GENERIC_WRITE | GENERIC_READ,
-                                    0, /* We do not share this */
+                                    FILE_SHARE_READ,
                                     NULL,
                                     CREATE_NEW,
                                     FILE_ATTRIBUTE_TEMPORARY,

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

Summary of changes:
 src/Makefile.am          |    1 +
 src/common.c             |   55 +++++--
 src/common.h             |    3 +-
 src/dialogs.h            |    1 +
 src/dialogs.rc           |    1 +
 src/engine-assuan.c      |   14 +-
 src/engine-assuan.h      |   11 +-
 src/engine.c             |   27 +++-
 src/engine.h             |    4 +
 src/gpgoladdin.cpp       |   20 ++-
 src/ribbon-callbacks.cpp |  381 +++++++++++++++++++++++++++++++---------------
 src/ribbon-callbacks.h   |    3 +
 src/sign-48.png          |  Bin 0 -> 1531 bytes
 13 files changed, 365 insertions(+), 156 deletions(-)
 create mode 100644 src/sign-48.png


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




More information about the Gnupg-commits mailing list