Send the SESSION command to the server.
authorWerner Koch <wk@gnupg.org>
Thu, 5 Jun 2008 10:38:03 +0000 (10:38 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 5 Jun 2008 10:38:03 +0000 (10:38 +0000)
src/ChangeLog
src/engine-assuan.c
src/engine.c
src/engine.h
src/mapihelp.cpp
src/mapihelp.h
src/mimeparser.c

index 165bf2d..c4b4741 100644 (file)
@@ -1,3 +1,20 @@
+2008-06-05  Werner Koch  <wk@g10code.com>
+
+       * mimeparser.c (mime_decrypt): Set session number and title.
+       (mime_verify_opaque, mime_verify): Ditto.
+       * mapihelp.cpp (mapi_get_subject): New.
+       * engine.c (engine_set_session_number, engine_set_session_title) 
+       (engine_set_sender_address): New.
+       (struct engine_filter_s): Add fields session_number, session_title
+       and sender_address.
+       (engine_private_get_session_number): New. 
+       (engine_private_get_session_title): New.
+       (release_filter): Release them.
+       (engine_new_session_number): New.
+       * engine-assuan.c (send_session_info): New
+       (op_assuan_decrypt, op_assuan_verify): Call it.
+       (op_assuan_sign): Use the end-of-option option for the SENDER command.
+
 2008-05-28  Werner Koch  <wk@g10code.com>
 
        * dialogs.h (IDC_BODY_AS_ATTACHMENT): New.
index 3517267..370fe85 100644 (file)
@@ -526,8 +526,22 @@ connect_uiserver (assuan_context_t *r_ctx, pid_t *r_pid, ULONG *r_cmdid,
 }
 
 
+/* end the optiona session information. */
+static void
+send_session_info (assuan_context_t ctx, engine_filter_t filter)
+{
+  char line[1020];
+  unsigned int number = engine_private_get_session_number (filter);
+  const char *title   = engine_private_get_session_title (filter);
+
+  if (title && *title)
+    snprintf (line, sizeof line, "SESSION %u %s", number, title);
+  else
+    snprintf (line, sizeof line, "SESSION %u", number);
+  assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
+}
+
 
-\f
 \f
 static void
 cleanup (void)
@@ -1796,13 +1810,14 @@ op_assuan_sign (protocol_t protocol,
   if (err)
     goto leave;
 
-  /* We always send the SENDER command becuase it allows us to figure
+  /* We always send the SENDER command because it allows us to figure
      out the protocol to use.  In case the UI server faisl to send the
      protocol we fall back to OpenPGP.  */
   suggested_protocol = PROTOCOL_UNKNOWN;
   if (!sender)
     sender = "<kleopatra-does-not-allow-an-empty-arg@example.net>";
-  snprintf (line, sizeof line, "SENDER%s%s", sender? " ":"", sender?sender:"");
+  snprintf (line, sizeof line, "SENDER%s%s",
+            sender? " -- ":"", sender?sender:"");
   err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL,
                          prep_foo_status_cb, &suggested_protocol);
   if (err)
@@ -1915,6 +1930,8 @@ op_assuan_decrypt (protocol_t protocol,
   if (err)
     goto leave;
 
+  send_session_info (ctx, filter);
+
   snprintf (line, sizeof line, "INPUT FD=%ld", (unsigned long int)inpipe[0]);
   err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
   if (err)
@@ -2044,6 +2061,8 @@ op_assuan_verify (gpgme_protocol_t protocol,
   if (err)
     goto leave;
 
+  send_session_info (ctx, filter);
+
   if (!opaque_mode)
     {
       snprintf (line, sizeof line, "MESSAGE FD=%ld",
index f09fc98..b0667cc 100644 (file)
@@ -108,6 +108,13 @@ struct engine_filter_s
 
   /* Counter used to optimize voluntary thread switching. */
   ULONG switch_counter;
+
+  /* Optional data to be passed to the backend to help the server
+     display a useful title and to associate operations with one OL
+     task.  */
+  unsigned int session_number;
+  char *session_title;     /* (malloced) */
+  char *sender_address;    /* (malloced) */
 };
 
 
@@ -196,6 +203,8 @@ release_filter (engine_filter_t filter)
         CloseHandle (filter->in.ready_event);
       gpgme_data_release (filter->indata);
       gpgme_data_release (filter->outdata);
+      xfree (filter->session_title);
+      xfree (filter->sender_address);
       xfree (filter);
     }
 }
@@ -384,6 +393,17 @@ engine_private_finished (engine_filter_t filter, gpg_error_t status)
 }
 
 
+unsigned int
+engine_private_get_session_number (engine_filter_t filter)
+{
+  return filter? filter->session_number : 0;
+}
+
+const char *
+engine_private_get_session_title (engine_filter_t filter)
+{
+  return filter? filter->session_title : NULL;
+}
 
 
 \f
@@ -424,6 +444,21 @@ engine_deinit (void)
   op_gpgme_deinit ();
 }
 
+/* Helper function to return a new session number.  */
+unsigned int
+engine_new_session_number (void)
+{
+  static ULONG number;
+  ULONG n;
+
+  /* The protocol says the session number is a 32 bit value, thus we
+     make that sure even in the case that ULONG is changed to a 64 bit
+     type (Not an issue under Windows, though). */
+  while (!((n = InterlockedIncrement (&number))&0xffffffff) )
+    ;
+  return n;
+}
+
 
 \f
 /* Filter the INDATA of length INDATA and write the output using
@@ -601,7 +636,7 @@ engine_create_filter (engine_filter_t *r_filter,
 }
 
 
-/* Set the FILTER in a mode which pushes an extra lineffed out.  */
+/* Set the FILTER in a mode which pushes an extra linefeed out.  */
 void
 engine_request_exra_lf (engine_filter_t filter)
 {
@@ -609,6 +644,41 @@ engine_request_exra_lf (engine_filter_t filter)
 }
 
 
+/* Set the session number for FILTER to NUMBER.  */
+void
+engine_set_session_number (engine_filter_t filter, unsigned int value)
+{
+  if (filter)
+    filter->session_number = value;
+}
+
+/* Set the session title for FILTER to TITLE.  */
+void
+engine_set_session_title (engine_filter_t filter, const char *title)
+{
+  if (filter)
+    {
+      xfree (filter->session_title);
+      filter->session_title = title? xstrdup (title) : NULL;
+    }
+}
+
+/* Set the sender address for FILTER to ADDR.  Setting the sender
+   address to NULL is allowed.  This sender address may be used by the
+   server to check whether the used key matches the sender address
+   while verifying a message.  Note that this sender address is not
+   used for selecting a key during encryption or verification. */
+void
+engine_set_sender_address (engine_filter_t filter, const char *addr)
+{
+  if (filter)
+    {
+      xfree (filter->sender_address);
+      filter->sender_address = addr? xstrdup (addr) : NULL;
+    }
+}
+
+
 /* Wait for FILTER to finish.  Returns 0 on success.  FILTER is not
    valid after the function has returned success.  */
 int
@@ -763,7 +833,7 @@ engine_cancel (engine_filter_t filter)
 
 
 
-/* Start an encryption operation to all RECIPEINTS using PROTOCOL
+/* Start an encryption operation to all RECIPIENTS using PROTOCOL
    RECIPIENTS is a NULL terminated array of rfc2822 addresses.  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
index 7f47f57..9aeb0f7 100644 (file)
@@ -50,16 +50,24 @@ typedef struct engine_filter_s *engine_filter_t;
 /*-- engine.c -- */
 int engine_init (void);
 void engine_deinit (void);
+unsigned int engine_new_session_number (void);
 
 void engine_private_set_cancel (engine_filter_t filter, void *cancel_data);
 void engine_private_finished (engine_filter_t filter, gpg_error_t status);
 
+unsigned int engine_private_get_session_number (engine_filter_t filter);
+const char *engine_private_get_session_title (engine_filter_t filter);
+
 int engine_filter (engine_filter_t filter,
                    const void *indata, size_t indatalen);
 int engine_create_filter (engine_filter_t *r_filter,
                           int (*outfnc) (void *, const void *, size_t),
                           void *outfncdata);
 void engine_request_exra_lf (engine_filter_t filter);
+void engine_set_session_number (engine_filter_t filter, unsigned int value);
+void engine_set_session_title (engine_filter_t filter, const char *title);
+void engine_set_sender_address (engine_filter_t filter, const char *addr);
+
 int engine_wait (engine_filter_t filter);
 void engine_cancel (engine_filter_t filter);
 
index 36cc583..0670b62 100644 (file)
@@ -998,7 +998,7 @@ mapi_get_message_class (LPMESSAGE message)
 
 
 
-/* Return teh sender of the message.  According to the specs this is
+/* Return the sender of the message.  According to the specs this is
    an UTF-8 string; we rely on that the UI server handles
    internationalized domain names.  */ 
 char *
@@ -1055,6 +1055,45 @@ mapi_get_sender (LPMESSAGE message)
   return buf;
 }
 
+/* Return the subject of the message as a malloced UTF-8 string.
+   Returns a replacement string if a subject is missing.  */
+char *
+mapi_get_subject (LPMESSAGE message)
+{
+  HRESULT hr;
+  LPSPropValue propval = NULL;
+  char *buf;
+  
+  if (!message)
+    return xstrdup ("[no message]"); /* Ooops.  */
+
+  hr = HrGetOneProp ((LPMAPIPROP)message, PR_SUBJECT_W, &propval);
+  if (FAILED (hr))
+    {
+      log_debug ("%s:%s: HrGetOneProp failed: hr=%#lx\n",
+                 SRCNAME, __func__, hr);
+      return xstrdup (_("[no subject]"));
+    }
+    
+  if (PROP_TYPE (propval->ulPropTag) != PT_UNICODE) 
+    {
+      log_debug ("%s:%s: HrGetOneProp returns invalid type %lu\n",
+                 SRCNAME, __func__, PROP_TYPE (propval->ulPropTag) );
+      MAPIFreeBuffer (propval);
+      return xstrdup (_("[no subject]"));
+    }
+  
+  buf = wchar_to_utf8 (propval->Value.lpszW);
+  MAPIFreeBuffer (propval);
+  if (!buf)
+    {
+      log_error ("%s:%s: error converting to utf8\n", SRCNAME, __func__);
+      return xstrdup (_("[no subject]"));
+    }
+
+  return buf;
+}
+
 
 
 
index bbcd5e4..90999f4 100644 (file)
@@ -117,6 +117,8 @@ int mapi_to_mime (LPMESSAGE message, const char *filename);
 
 char *mapi_get_binary_prop (LPMESSAGE message,ULONG proptype,size_t *r_nbytes);
 
+char *mapi_get_subject (LPMESSAGE message);
+
 LPSTREAM mapi_get_body_as_stream (LPMESSAGE message);
 char *mapi_get_body (LPMESSAGE message, size_t *r_nbytes);
 
index 2058987..dfe3992 100644 (file)
@@ -1238,6 +1238,12 @@ mime_verify (protocol_t protocol, const char *message, size_t messagelen,
       
       if ((err=engine_create_filter (&filter, NULL, NULL)))
         goto leave;
+      engine_set_session_number (filter, engine_new_session_number ());
+      {
+        char *tmp = mapi_get_subject (mapi_message);
+        engine_set_session_title (filter, tmp);
+        xfree (tmp);
+      }
       if ((err=engine_verify_start (filter, hwnd, signature, sig_len,
                                    ctx->protocol)))
         goto leave;
@@ -1350,6 +1356,12 @@ mime_verify_opaque (protocol_t protocol, LPSTREAM instream,
 
   if ((err=engine_create_filter (&filter, plaintext_handler, ctx)))
     goto leave;
+  engine_set_session_number (filter, engine_new_session_number ());
+  {
+    char *tmp = mapi_get_subject (mapi_message);
+    engine_set_session_title (filter, tmp);
+    xfree (tmp);
+  }
   if ((err=engine_verify_start (filter, hwnd, NULL, 0, protocol)))
     goto leave;
 
@@ -1690,6 +1702,12 @@ mime_decrypt (protocol_t protocol, LPSTREAM instream, LPMESSAGE mapi_message,
     goto leave;
   if (simple_pgp)
     engine_request_exra_lf (filter);
+  engine_set_session_number (filter, engine_new_session_number ());
+  {
+    char *tmp = mapi_get_subject (mapi_message);
+    engine_set_session_title (filter, tmp);
+    xfree (tmp);
+  }
   if ((err=engine_decrypt_start (filter, hwnd, protocol, !preview_mode)))
     goto leave;