Changed the way sign+encrypt works.
authorWerner Koch <wk@gnupg.org>
Tue, 11 Mar 2008 10:56:44 +0000 (10:56 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 11 Mar 2008 10:56:44 +0000 (10:56 +0000)
NEWS
configure.ac
po/de.po
po/sv.po
src/ChangeLog
src/engine-assuan.c
src/engine-assuan.h
src/engine.c
src/engine.h
src/mimemaker.c

diff --git a/NEWS b/NEWS
index 56ccf60..abbd8c2 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Noteworthy changes for version 0.10.7
+==================================================
+
+ * Changed the way sign+encrypt works to help the UI-server.
+
+
 Noteworthy changes for version 0.10.6 (2008-03-10)
 ==================================================
 
index f016809..ae3979b 100644 (file)
@@ -16,8 +16,8 @@ min_automake_version="1.9.4"
 # Remember to change the version number immediately *after* a release.
 # Set my_issvn to "yes" for non-released code.  Remember to run an
 # "svn up" and "autogen.sh" right before creating a distribution.
-m4_define([my_version], [0.10.6])
-m4_define([my_issvn], [no])
+m4_define([my_version], [0.10.7])
+m4_define([my_issvn], [yes])
 
 m4_define([svn_revision], m4_esyscmd([echo -n $( (svn info 2>/dev/null \
             || echo 'Revision: 0')|sed -n '/^Revision:/ {s/[^0-9]//gp;q;}')]))
index 51115d9..7f8dd6e 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GpgOL 0.10.0\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2008-03-07 12:10+0100\n"
+"POT-Creation-Date: 2008-03-10 10:02+0100\n"
 "PO-Revision-Date: 2008-03-07 13:31+0100\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: de\n"
@@ -341,7 +341,7 @@ msgstr ""
 "\n"
 "geschrieben."
 
-#: src/mapihelp.cpp:1516
+#: src/mapihelp.cpp:1576
 msgid ""
 "[The content of this message is not visible because it has been decrypted by "
 "another Outlook session.  Use the \"decrypt/verify\" command to make it "
@@ -351,7 +351,7 @@ msgstr ""
 "Outlook Sitzung entschlüsselt wurde.  Verwenden Sie den Menüpunkt "
 "\"entschlüsseln/verifizieren\" um den Inhalt wieder sichtbar zu machen.]"
 
-#: src/mapihelp.cpp:2257
+#: src/mapihelp.cpp:2317
 msgid ""
 "[The content of this message is not visible due to an processing error in "
 "GpgOL.]"
@@ -555,7 +555,9 @@ msgid ""
 msgstr ""
 "Eine neue Version von GpgOL ist installiert worden.\n"
 "\n"
-"Bitte öffnen Sie das Fenster mit den Einstellungen und um zu kontrollieren ob die Einstellungen für Sie noch stimmen.  Sie finden die Einstellungen im Hauptmenu unter:  Extras->Optionen->GpgOL.\n"
+"Bitte öffnen Sie das Fenster mit den Einstellungen und um zu kontrollieren "
+"ob die Einstellungen für Sie noch stimmen.  Sie finden die Einstellungen im "
+"Hauptmenu unter:  Extras->Optionen->GpgOL.\n"
 
 #: src/olflange.cpp:506
 msgid ""
index 6174d52..36e3304 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: GPGol\n"
 "Report-Msgid-Bugs-To: bug-gpgol@g10code.com\n"
-"POT-Creation-Date: 2008-03-07 12:10+0100\n"
+"POT-Creation-Date: 2008-03-10 10:02+0100\n"
 "PO-Revision-Date: 2006-12-12 23:52+0100\n"
 "Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
@@ -339,14 +339,14 @@ msgid ""
 "\"%s\""
 msgstr ""
 
-#: src/mapihelp.cpp:1516
+#: src/mapihelp.cpp:1576
 msgid ""
 "[The content of this message is not visible because it has been decrypted by "
 "another Outlook session.  Use the \"decrypt/verify\" command to make it "
 "visible]"
 msgstr ""
 
-#: src/mapihelp.cpp:2257
+#: src/mapihelp.cpp:2317
 msgid ""
 "[The content of this message is not visible due to an processing error in "
 "GpgOL.]"
index 6a7e0b2..6aacaf3 100644 (file)
@@ -1,3 +1,15 @@
+2008-03-11  Werner Koch  <wk@g10code.com>
+
+       * engine-assuan.c (op_assuan_encrypt): Factor some code out to ..
+       (op_assuan_encrypt_bottom): .. new.
+       (engine_assuan_encstate_s): New.
+       * engine.c (engine_encrypt_start): Split some code into ..
+       (engine_encrypt_prepare): .. new.
+       (engine_cancel): Cancel prepared encryption.
+       * mimemaker.c (mime_encrypt): Use engine_encrypt_prepare and _start.
+       (mime_sign_encrypt): Likewise, but do the _start only after
+       completing the signing.
+
 2008-03-10  Werner Koch  <wk@g10code.com>
 
        * engine.c (FILTER_BUFFER_SIZE): Increase to 4k.
index 0840e5f..4a16686 100644 (file)
@@ -114,6 +114,20 @@ struct work_item_s
 };
 
 
+/* A helper context used to convey information from op_assuan_encrypt
+   to op_assuan_encrypt_bottom.  */
+struct engine_assuan_encstate_s
+{
+  engine_filter_t filter;
+  const char *protocol_name;
+  HANDLE inpipe[2];
+  HANDLE outpipe[2];
+  closure_data_t cld;
+  assuan_context_t ctx;
+  ULONG cmdid;
+};
+
+
 /* The queue of all outstandig I/O operations.  Protected by the
    work_queue_lock.  */
 static work_item_t work_queue;
@@ -1372,12 +1386,15 @@ encrypt_closure (closure_data_t cld)
    the window handle of the current window and used to maintain the
    correct relationship between a popups and the active window.  If
    this function returns success, the data objects may only be
-   destroyed after an engine_wait or engine_cancel.  */
+   destroyed after an engine_wait or engine_cancel.  On success the
+   fucntion returns a pojunter to the encryption state and thus
+   requires that op_assuan_encrypt_bottom will be run later. */
 int
 op_assuan_encrypt (protocol_t protocol, 
                    gpgme_data_t indata, gpgme_data_t outdata,
                    engine_filter_t filter, void *hwnd,
-                   char **recipients, protocol_t *r_used_protocol)
+                   char **recipients, protocol_t *r_used_protocol,
+                   struct engine_assuan_encstate_s **r_encstate)
 {
   gpg_error_t err;
   closure_data_t cld;
@@ -1390,9 +1407,12 @@ op_assuan_encrypt (protocol_t protocol,
   char *p;
   int detect_protocol;
   const char *protocol_name;
+  struct engine_assuan_encstate_s *encstate;
+
+  *r_encstate = NULL;
 
   detect_protocol = !(protocol_name = get_protocol_name (protocol));
-  
+
   err = connect_uiserver (&ctx, &pid, &cmdid, hwnd);
   if (err)
     return err;
@@ -1462,12 +1482,19 @@ op_assuan_encrypt (protocol_t protocol,
                     cmdid, NULL, 0); 
   enqueue_callback ("output", ctx, outdata, outpipe[0], 0, finalize_handler, 
                     cmdid, NULL, 1 /* Wait on success */); 
-  snprintf (line, sizeof line, "ENCRYPT --protocol=%s", protocol_name);
-  err = start_command (ctx, cld, cmdid, line);
-  cld = NULL; /* Now owned by start_command.  */
-  if (err)
-    goto leave;
 
+  encstate = xcalloc (1, sizeof *encstate);
+  encstate->filter = filter;
+  encstate->protocol_name = protocol_name;
+  encstate->inpipe[0] = inpipe[0];
+  encstate->inpipe[1] = inpipe[1];
+  encstate->outpipe[0] = outpipe[0];
+  encstate->outpipe[1] = outpipe[1];
+  encstate->cld = cld;
+  encstate->ctx = ctx;
+  encstate->cmdid = cmdid;
+  *r_encstate = encstate;
+  return 0;
 
  leave:
   if (err)
@@ -1483,6 +1510,43 @@ op_assuan_encrypt (protocol_t protocol,
   return err;
 }
 
+/* Continue and actually start the encryption or cancel it with CANCEL
+   set to TRUE.  The fucntion takes ownvership of ENCSTATE.  */
+int
+op_assuan_encrypt_bottom (struct engine_assuan_encstate_s *encstate,
+                          int cancel)
+{
+  char line[1024];
+  gpg_error_t err;
+
+  if (!encstate)
+    return 0;
+  if (cancel)
+    err = gpg_error (GPG_ERR_CANCELED);
+  else
+    {
+      snprintf (line, sizeof line, "ENCRYPT --protocol=%s",
+                encstate->protocol_name);
+      err = start_command (encstate->ctx, encstate->cld, 
+                           encstate->cmdid, line);
+      encstate->cld = NULL; /* Now owned by start_command.  */
+    }
+
+  if (err)
+    {
+      /* Fixme: Cancel stuff in the work_queue. */
+      close_pipe (encstate->inpipe);
+      close_pipe (encstate->outpipe);
+      xfree (encstate->cld);
+      assuan_disconnect (encstate->ctx);
+    }
+  else
+    engine_private_set_cancel (encstate->filter, encstate->ctx);
+  xfree (encstate);
+  return err;
+}
+
+
 
 \f
 /* Note that this closure is called in the context of the
index 4493396..eff568f 100644 (file)
@@ -1,5 +1,5 @@
 /* engine-assuan.h - Assuan server based crypto engine
- *     Copyright (C) 2007 g10 Code GmbH
+ *     Copyright (C) 2007, 2008 g10 Code GmbH
  *
  * This file is part of GpgOL.
  *
@@ -31,6 +31,8 @@ extern "C" {
 
 #include "engine.h"
 
+struct engine_assuan_encstate_s;
+
 int  op_assuan_init (void);
 void op_assuan_deinit (void);
 void engine_assuan_cancel (void *cancel_data);
@@ -38,7 +40,10 @@ void engine_assuan_cancel (void *cancel_data);
 int op_assuan_encrypt (protocol_t protocol, 
                        gpgme_data_t indata, gpgme_data_t outdata,
                        engine_filter_t notify_data, void *hwnd,
-                       char **recipients, protocol_t *r_used_protocol);
+                       char **recipients, protocol_t *r_used_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, 
                     gpgme_data_t indata, gpgme_data_t outdata,
                     engine_filter_t filter, void *hwnd,
index 478ff06..373a906 100644 (file)
@@ -101,6 +101,10 @@ struct engine_filter_s
   gpgme_data_t indata;               /* Input data.  */
   gpgme_data_t outdata;              /* Output data.  */
   void *cancel_data;                 /* Used by engine_cancel.  */
+
+  /* A pointer used convey information from engine_encrypt_prepare to
+     engine_encrypt_start.  */
+  struct engine_assuan_encstate_s *encstate;
 };
 
 
@@ -680,6 +684,9 @@ engine_cancel (engine_filter_t filter)
   if (!filter)
     return;
   
+  /* First we need to cancel a possible prepared encrypt operation. */
+  engine_encrypt_start (filter, 1);
+
   take_in_lock (filter, __func__);
   cancel_data = filter->cancel_data;
   filter->cancel_data = NULL;
@@ -713,11 +720,14 @@ engine_cancel (engine_filter_t filter)
    be reused after having been used through this function.  However,
    the lifetime of the filter object lasts until the final engine_wait
    or engine_cancel.  On return the protocol to be used is stored at
-   R_PROTOCOL. */
+   R_PROTOCOL.  This is a two part fucntion.  engine_encrypt_prepare
+   needs to be called first followed by engine_encrypt_start.  The
+   latter command has just one argument CANCEL which can be set to
+   true to cancel the prepared command.  */
 int
-engine_encrypt_start (engine_filter_t filter, HWND hwnd,
-                      protocol_t req_protocol, char **recipients,
-                      protocol_t *r_protocol)
+engine_encrypt_prepare (engine_filter_t filter, HWND hwnd,
+                        protocol_t req_protocol, char **recipients,
+                        protocol_t *r_protocol)
 {
   gpg_error_t err;
   protocol_t used_protocol;
@@ -726,7 +736,8 @@ engine_encrypt_start (engine_filter_t filter, HWND hwnd,
   if (filter->use_assuan)
     {
       err = op_assuan_encrypt (req_protocol, filter->indata, filter->outdata,
-                               filter, hwnd, recipients, &used_protocol);
+                               filter, hwnd, recipients, &used_protocol,
+                               &filter->encstate);
       if (!err)
         *r_protocol = used_protocol;
     }
@@ -737,6 +748,23 @@ engine_encrypt_start (engine_filter_t filter, HWND hwnd,
   return err;
 }
 
+/* See engine_encrypt_prepare.  */
+int
+engine_encrypt_start (engine_filter_t filter, int cancel)
+{
+  gpg_error_t err;
+
+  if (filter->use_assuan)
+    {
+      err = op_assuan_encrypt_bottom (filter->encstate, cancel);
+      filter->encstate = NULL;
+    }
+  else
+    err = 0; /* This is a dummy here.  */
+      
+  return err;
+}
+
 
 /* Start an detached signing operation.  FILTER is an object created
    by engine_create_filter.  The caller needs to call engine_wait to
index ee8f99f..7f47f57 100644 (file)
@@ -63,9 +63,10 @@ void engine_request_exra_lf (engine_filter_t filter);
 int engine_wait (engine_filter_t filter);
 void engine_cancel (engine_filter_t filter);
 
-int engine_encrypt_start (engine_filter_t filter, HWND hwnd,
-                          protocol_t req_protocol, char **recipients,
-                          protocol_t *r_protocol);
+int engine_encrypt_prepare (engine_filter_t filter, HWND hwnd,
+                            protocol_t req_protocol, char **recipients,
+                            protocol_t *r_protocol);
+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);
 
index 43f62aa..7100fe6 100644 (file)
@@ -1593,7 +1593,9 @@ mime_encrypt (LPMESSAGE message, HWND hwnd,
      will fail early. */
   if (engine_create_filter (&filter, write_buffer_for_cb, sink))
     goto failure;
-  if (engine_encrypt_start (filter, hwnd, protocol, recipients, &protocol))
+  if (engine_encrypt_prepare (filter, hwnd, protocol, recipients, &protocol))
+    goto failure;
+  if (engine_encrypt_start (filter, 0))
     goto failure;
 
   protocol = check_protocol (protocol);
@@ -1730,13 +1732,13 @@ mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
 
 
   /* Prepare the encryption.  We do this early as it is quite common
-     that some recipients are not be available and thus the encryption
+     that some recipients are not available and thus the encryption
      will fail early.  This is also required to allow the UIserver to
      figure out the protocol to use if we have not forced one.  */
   if (engine_create_filter (&filter, write_buffer_for_cb, sink))
     goto failure;
-  if ((rc=engine_encrypt_start (filter, hwnd, 
-                                protocol, recipients, &protocol)))
+  if ((rc=engine_encrypt_prepare (filter, hwnd, 
+                                  protocol, recipients, &protocol)))
     goto failure;
 
   protocol = check_protocol (protocol);
@@ -1752,6 +1754,18 @@ mime_sign_encrypt (LPMESSAGE message, HWND hwnd,
   if (do_mime_sign (message, hwnd, protocol, &att_table, tmpsink))
     goto failure;
 
+  /* Now send the actual ENCRYPT command.  This split up between
+     prepare and start is necessary to help with the implementarion of
+     the UI-server.  If we would send the ENCRYPT command immediately
+     the UI-server might block while reading from the input stream
+     because we are first going to do a sign operation which in trun
+     needs the attention of the UI server.  A more robust but
+     complicated approach to the UI-server would be to delay the
+     reading (and thus the start of the underlying encrypt operation)
+     until the first byte has been received. */
+  if ((rc=engine_encrypt_start (filter, 0)))
+    goto failure;
+
   /* Write the top header.  */
   rc = create_top_encryption_header (sink, protocol, boundary);
   if (rc)