[svn] GpgOL - r232 - in trunk: . po src

svn author wk cvs at cvs.gnupg.org
Tue Mar 11 11:56:45 CET 2008


Author: wk
Date: 2008-03-11 11:56:44 +0100 (Tue, 11 Mar 2008)
New Revision: 232

Modified:
   trunk/NEWS
   trunk/configure.ac
   trunk/po/de.po
   trunk/po/sv.po
   trunk/src/ChangeLog
   trunk/src/engine-assuan.c
   trunk/src/engine-assuan.h
   trunk/src/engine.c
   trunk/src/engine.h
   trunk/src/mimemaker.c
Log:
Changed the way sign+encrypt works.


Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/ChangeLog	2008-03-11 10:56:44 UTC (rev 232)
@@ -1,3 +1,15 @@
+2008-03-11  Werner Koch  <wk at 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 at g10code.com>
 
 	* engine.c (FILTER_BUFFER_SIZE): Increase to 4k.

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/NEWS	2008-03-11 10:56:44 UTC (rev 232)
@@ -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)
 ==================================================
 

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/configure.ac	2008-03-11 10:56:44 UTC (rev 232)
@@ -16,8 +16,8 @@
 # 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;}')]))

Modified: trunk/po/de.po  [not shown]
Modified: trunk/po/sv.po  [not shown]
Modified: trunk/src/engine-assuan.c
===================================================================
--- trunk/src/engine-assuan.c	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/engine-assuan.c	2008-03-11 10:56:44 UTC (rev 232)
@@ -114,6 +114,20 @@
 };
 
 
+/* 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 @@
    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 @@
   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 @@
                     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,7 +1510,44 @@
   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;
+}
+
+
+
 
 /* Note that this closure is called in the context of the
    async_worker_thread.  */

Modified: trunk/src/engine-assuan.h
===================================================================
--- trunk/src/engine-assuan.h	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/engine-assuan.h	2008-03-11 10:56:44 UTC (rev 232)
@@ -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 @@
 
 #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 @@
 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,

Modified: trunk/src/engine.c
===================================================================
--- trunk/src/engine.c	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/engine.c	2008-03-11 10:56:44 UTC (rev 232)
@@ -101,6 +101,10 @@
   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 @@
   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 @@
    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 @@
   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,7 +748,24 @@
   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
    finish the operation.  A filter object may not be reused after

Modified: trunk/src/engine.h
===================================================================
--- trunk/src/engine.h	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/engine.h	2008-03-11 10:56:44 UTC (rev 232)
@@ -63,9 +63,10 @@
 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);
 

Modified: trunk/src/mimemaker.c
===================================================================
--- trunk/src/mimemaker.c	2008-03-10 09:25:51 UTC (rev 231)
+++ trunk/src/mimemaker.c	2008-03-11 10:56:44 UTC (rev 232)
@@ -1593,8 +1593,10 @@
      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);
   if (protocol == PROTOCOL_UNKNOWN)
@@ -1730,13 +1732,13 @@
 
 
   /* 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 @@
   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)




More information about the Gnupg-commits mailing list