summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/context.h2
-rw-r--r--src/export.c129
2 files changed, 127 insertions, 4 deletions
diff --git a/src/context.h b/src/context.h
index e921436..745ffa8 100644
--- a/src/context.h
+++ b/src/context.h
@@ -38,7 +38,7 @@ typedef enum
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
- OPDATA_PASSWD
+ OPDATA_PASSWD, OPDATA_EXPORT
} ctx_op_data_id_t;
diff --git a/src/export.c b/src/export.c
index 81a23b0..8930aa6 100644
--- a/src/export.c
+++ b/src/export.c
@@ -1,6 +1,6 @@
/* export.c - Export a key.
Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004, 2010 g10 Code GmbH
+ Copyright (C) 2001-2004, 2010, 2014 g10 Code GmbH
This file is part of GPGME.
@@ -31,9 +31,82 @@
#include "ops.h"
+/* Local operation data. */
+typedef struct
+{
+ gpg_error_t err; /* Error encountred during the export. */
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+
+ (void)opd; /* Nothing to release here. */
+}
+
+
+/* Parse an error status line. Return the error location and the
+ error code. The function may modify ARGS. */
+static char *
+parse_error (char *args, gpg_error_t *r_err)
+{
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ {
+ *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ return NULL;
+ }
+
+ *r_err = atoi (which);
+
+ return where;
+}
+
+
static gpgme_error_t
export_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ const char *loc;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_ERROR:
+ loc = parse_error (args, &err);
+ if (!loc)
+ return err;
+ else if (opd->err)
+ ; /* We only want to report the first error. */
+ else if (!strcmp (loc, "keyserver_send"))
+ opd->err = err;
+ break;
+
+ default:
+ break;
+ }
return 0;
}
@@ -43,6 +116,8 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
gpgme_export_mode_t mode, gpgme_data_t keydata)
{
gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL)))
@@ -64,6 +139,12 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
if (err)
return err;
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
_gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
return _gpgme_engine_op_export (ctx->engine, pattern, mode, keydata,
@@ -114,6 +195,8 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
gpgme_export_mode_t mode, gpgme_data_t keydata)
{
gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL)))
@@ -134,6 +217,12 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
if (err)
return err;
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
_gpgme_engine_set_status_handler (ctx->engine, export_status_handler, ctx);
return _gpgme_engine_op_export_ext (ctx->engine, pattern, mode, keydata,
@@ -196,7 +285,24 @@ gpgme_op_export_ext (gpgme_ctx_t ctx, const char *pattern[],
err = export_ext_start (ctx, 1, pattern, mode, keydata);
if (!err)
- err = _gpgme_wait_one (ctx);
+ {
+ err = _gpgme_wait_one (ctx);
+ if (!err)
+ {
+ /* For this synchronous operation we check for operational
+ errors and return them. For asynchronous operations
+ there is currently no way to do this - we need to add a
+ gpgme_op_export_result function to fix that. */
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
+ opd = hook;
+ if (!err)
+ err = opd->err;
+ }
+ }
+
return TRACE_ERR (err);
}
@@ -319,7 +425,24 @@ gpgme_op_export_keys (gpgme_ctx_t ctx,
err = export_keys_start (ctx, 1, keys, mode, keydata);
if (!err)
- err = _gpgme_wait_one (ctx);
+ {
+ err = _gpgme_wait_one (ctx);
+ if (!err)
+ {
+ /* For this synchronous operation we check for operational
+ errors and return them. For asynchronous operations
+ there is currently no way to do this - we need to add a
+ gpgme_op_export_result function to fix that. */
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EXPORT, &hook, -1, NULL);
+ opd = hook;
+ if (!err)
+ err = opd->err;
+ }
+ }
+
return TRACE_ERR (err);
}