2002-02-02 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / decrypt.c
index 2fb9052..ff834b5 100644 (file)
 #include "context.h"
 #include "ops.h"
 
+
 struct decrypt_result_s
 {
-  int no_passphrase;
   int okay;
   int failed;
-  void *last_pw_handle;
-  char *userid_hint;
-  char *passphrase_info;
-  int bad_passphrase;
 };
 
+
 void
 _gpgme_release_decrypt_result (DecryptResult result)
 {
   if (!result)
     return;
-  xfree (result->passphrase_info);
-  xfree (result->userid_hint);
   xfree (result);
 }
 
-static GpgmeError
-create_result_struct (GpgmeCtx ctx)
-{
-  assert (!ctx->result.decrypt);
-  ctx->result.decrypt = xtrycalloc (1, sizeof *ctx->result.decrypt);
-  if (!ctx->result.decrypt)
-    return mk_error (Out_Of_Core);
-  return 0;    
-}
-
-static void
-decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
-{
-    if ( ctx->out_of_core )
-        return;
-    if (! ctx->result.decrypt)
-      {
-        if (create_result_struct (ctx))
-         {
-            ctx->out_of_core = 1;
-            return;
-         }
-      }
-
-    switch (code) {
-      case STATUS_EOF:
-        break;
-
-      case STATUS_USERID_HINT:
-        xfree (ctx->result.decrypt->userid_hint);
-        if (!(ctx->result.decrypt->userid_hint = xtrystrdup (args)) )
-            ctx->out_of_core = 1;
-        break;
-
-      case STATUS_BAD_PASSPHRASE:
-        ctx->result.decrypt->bad_passphrase++;
-        break;
-
-      case STATUS_GOOD_PASSPHRASE:
-        ctx->result.decrypt->bad_passphrase = 0;
-        break;
-
-      case STATUS_NEED_PASSPHRASE:
-      case STATUS_NEED_PASSPHRASE_SYM:
-        xfree (ctx->result.decrypt->passphrase_info);
-        if (!(ctx->result.decrypt->passphrase_info = xtrystrdup (args)) )
-            ctx->out_of_core = 1;
-        break;
-
-      case STATUS_MISSING_PASSPHRASE:
-        DEBUG0 ("missing passphrase - stop\n");;
-        ctx->result.decrypt->no_passphrase = 1;
-        break;
-
-      case STATUS_DECRYPTION_OKAY:
-        ctx->result.decrypt->okay = 1;
-        break;
-
-      case STATUS_DECRYPTION_FAILED:
-        ctx->result.decrypt->failed = 1;
-        break;
-        
-
-      default:
-        /* ignore all other codes */
-        break;
-    }
-}
-
 
-static const char *
-command_handler (void *opaque, GpgStatusCode code, const char *key)
+void
+_gpgme_decrypt_status_handler (GpgmeCtx ctx, GpgStatusCode code, char *args)
 {
-    GpgmeCtx c = opaque;
+  _gpgme_passphrase_status_handler (ctx, code, args);
 
-    if (! c->result.decrypt)
-      {
-        if (create_result_struct (c))
-         {
-            c->out_of_core = 1;
-            return NULL;
-         }
-      }
+  if (ctx->error)
+    return;
+  test_and_allocate_result (ctx, decrypt);
 
-    if ( !code ) {
-        /* We have been called for cleanup */
-        if ( c->passphrase_cb ) { 
-            /* Fixme: take the key in account */
-            c->passphrase_cb (c->passphrase_cb_value, NULL, 
-                              &c->result.decrypt->last_pw_handle );
-        }
+  switch (code)
+    {
+    case STATUS_EOF:
+      if (ctx->result.decrypt->failed)
+       ctx->error = mk_error (Decryption_Failed);
+      else if (!ctx->result.decrypt->okay)
+       ctx->error = mk_error (No_Data);
+      break;
+
+    case STATUS_DECRYPTION_OKAY:
+      ctx->result.decrypt->okay = 1;
+      break;
+
+    case STATUS_DECRYPTION_FAILED:
+      ctx->result.decrypt->failed = 1;
+      break;
         
-        return NULL;
-    }
-
-    if ( !key || !c->passphrase_cb )
-        return NULL;
-    
-    if ( code == STATUS_GET_HIDDEN && !strcmp (key, "passphrase.enter") ) {
-        const char *userid_hint = c->result.decrypt->userid_hint;
-        const char *passphrase_info = c->result.decrypt->passphrase_info;
-        int bad_passphrase = c->result.decrypt->bad_passphrase;
-        char *buf;
-        const char *s;
-
-        c->result.decrypt->bad_passphrase = 0;
-        if (!userid_hint)
-            userid_hint = "[User ID hint missing]";
-        if (!passphrase_info)
-            passphrase_info = "[passphrase info missing]";
-        buf = xtrymalloc ( 20 + strlen (userid_hint)
-                           + strlen (passphrase_info) + 3);
-        if (!buf) {
-            c->out_of_core = 1;
-            return NULL;
-        }
-        sprintf (buf, "%s\n%s\n%s",
-                 bad_passphrase? "TRY_AGAIN":"ENTER",
-                 userid_hint, passphrase_info );
-
-        s = c->passphrase_cb (c->passphrase_cb_value,
-                              buf, &c->result.decrypt->last_pw_handle );
-        xfree (buf);
-        return s;
+    default:
+      /* Ignore all other codes.  */
+      break;
     }
-    
-    return NULL;
 }
 
 
 GpgmeError
-gpgme_op_decrypt_start ( GpgmeCtx c, 
-                         GpgmeData ciph, GpgmeData plain   )
+_gpgme_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain,
+                     void *status_handler)
 {
-    int rc = 0;
-    int i;
+  GpgmeError err = 0;
 
-    fail_on_pending_request( c );
-    c->pending = 1;
+  fail_on_pending_request (ctx);
+  ctx->pending = 1;
 
-    _gpgme_release_result (c);
-    c->out_of_core = 0;
+  _gpgme_release_result (ctx);
 
-    /* do some checks */
-    /* create a process object */
-    _gpgme_gpg_release ( c->gpg );
-    rc = _gpgme_gpg_new ( &c->gpg );
-    if (rc)
-        goto leave;
+  /* Create a process object.  */
+  _gpgme_engine_release (ctx->engine);
+  err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS
+                          : GPGME_PROTOCOL_OpenPGP, &ctx->engine);
+  if (err)
+    goto leave;
 
-    _gpgme_gpg_set_status_handler ( c->gpg, decrypt_status_handler, c );
-    if (c->passphrase_cb) {
-        rc = _gpgme_gpg_set_command_handler ( c->gpg, command_handler, c );
-        if (rc)
-            goto leave;
+  /* Check the supplied data.  */
+  if (!ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE)
+    {
+      err = mk_error (No_Data);
+      goto leave;
     }
+  _gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT);
 
-    /* build the commandline */
-    _gpgme_gpg_add_arg ( c->gpg, "--decrypt" );
-    for ( i=0; i < c->verbosity; i++ )
-        _gpgme_gpg_add_arg ( c->gpg, "--verbose" );
-
-    /* Check the supplied data */
-    if ( !ciph || gpgme_data_get_type (ciph) == GPGME_DATA_TYPE_NONE ) {
-        rc = mk_error (No_Data);
-        goto leave;
+  if (gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE)
+    {
+      err = mk_error (Invalid_Value);
+      goto leave;
     }
-    _gpgme_data_set_mode (ciph, GPGME_DATA_MODE_OUT );
+  _gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN);
 
-    if ( gpgme_data_get_type (plain) != GPGME_DATA_TYPE_NONE ) {
-        rc = mk_error (Invalid_Value);
-        goto leave;
-    }
-    _gpgme_data_set_mode (plain, GPGME_DATA_MODE_IN );
+  err = _gpgme_passphrase_start (ctx);
+  if (err)
+    goto leave;
+
+  _gpgme_engine_set_status_handler (ctx->engine, status_handler, ctx);
+  _gpgme_engine_set_verbosity (ctx->engine, ctx->verbosity);
 
-    /* Tell the gpg object about the data */
-    _gpgme_gpg_add_arg ( c->gpg, "--output" );
-    _gpgme_gpg_add_arg ( c->gpg, "-" );
-    _gpgme_gpg_add_data ( c->gpg, plain, 1 );
-    _gpgme_gpg_add_data ( c->gpg, ciph, 0 );
+  err = _gpgme_engine_op_decrypt (ctx->engine, ciph, plain);
 
-    /* and kick off the process */
-    rc = _gpgme_gpg_spawn ( c->gpg, c );
+  if (!err)    /* And kick off the process.  */
+    err = _gpgme_engine_start (ctx->engine, ctx);
 
  leave:
-    if (rc) {
-        c->pending = 0; 
-        _gpgme_gpg_release ( c->gpg ); c->gpg = NULL;
+  if (err)
+    {
+      ctx->pending = 0; 
+      _gpgme_engine_release (ctx->engine);
+      ctx->engine = NULL;
     }
-    return rc;
+  return err;
+}
+
+
+GpgmeError
+gpgme_op_decrypt_start (GpgmeCtx ctx, GpgmeData ciph, GpgmeData plain)
+{
+  return _gpgme_decrypt_start (ctx, ciph, plain,
+                              _gpgme_decrypt_status_handler);
 }
 
 
 /**
  * gpgme_op_decrypt:
- * @c: The context
+ * @ctx: The context
  * @in: ciphertext input
  * @out: plaintext output
  * 
  * This function decrypts @in to @out.
- * Other parameters are take from the context @c.
+ * Other parameters are take from the context @ctx.
  * The function does wait for the result.
  * 
  * Return value:  0 on success or an errorcode. 
  **/
 GpgmeError
-gpgme_op_decrypt (GpgmeCtx c, GpgmeData in, GpgmeData out)
+gpgme_op_decrypt (GpgmeCtx ctx, GpgmeData in, GpgmeData out)
 {
-  GpgmeError err = gpgme_op_decrypt_start (c, in, out);
+  GpgmeError err = gpgme_op_decrypt_start (ctx, in, out);
   if (!err)
     {
-      gpgme_wait (c, 1);
-      if (!c->result.decrypt)
-       err = mk_error (General_Error);
-      else if (c->out_of_core)
-       err = mk_error (Out_Of_Core);
-      else
-       {
-         if (c->result.decrypt->no_passphrase)
-           err = mk_error (No_Passphrase);
-         else if (c->result.decrypt->failed)
-           err = mk_error (Decryption_Failed);
-         else if (!c->result.decrypt->okay)
-           err = mk_error (No_Data);
-        }
-      c->pending = 0;
+      gpgme_wait (ctx, 1);
+      err = ctx->error;
     }
   return err;
 }