summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2021-12-01 16:54:35 +0900
committerJinWang An <jinwang.an@samsung.com>2021-12-01 16:54:35 +0900
commitfd5caec0dccd1229c2b9dd5220c8e2b1ef966d0e (patch)
tree9a62094ccb327ef754b15997559dc60fd9b3cc25 /src
parent1c25bd8f2d05ddcc1502bc0d59e23e038dfa6d60 (diff)
downloadgpgme-fd5caec0dccd1229c2b9dd5220c8e2b1ef966d0e.tar.gz
gpgme-fd5caec0dccd1229c2b9dd5220c8e2b1ef966d0e.tar.bz2
gpgme-fd5caec0dccd1229c2b9dd5220c8e2b1ef966d0e.zip
Imported Upstream version 1.6.0upstream/1.6.0
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in4
-rw-r--r--src/context.h7
-rw-r--r--src/debug.c12
-rw-r--r--src/decrypt.c19
-rw-r--r--src/encrypt.c9
-rw-r--r--src/engine-assuan.c10
-rw-r--r--src/engine-backend.h6
-rw-r--r--src/engine-g13.c10
-rw-r--r--src/engine-gpg.c33
-rw-r--r--src/engine-gpgsm.c58
-rw-r--r--src/engine-uiserver.c10
-rw-r--r--src/engine.c10
-rw-r--r--src/engine.h9
-rw-r--r--src/export.c35
-rw-r--r--src/genkey.c26
-rw-r--r--src/gpgme-tool.c35
-rw-r--r--src/gpgme.c65
-rw-r--r--src/gpgme.def6
-rw-r--r--src/gpgme.h.in485
-rw-r--r--src/keylist.c13
-rw-r--r--src/libgpgme.vers6
-rw-r--r--src/op-support.c24
-rw-r--r--src/ops.h4
-rw-r--r--src/passphrase.c43
-rw-r--r--src/passwd.c9
-rw-r--r--src/sign.c15
-rw-r--r--src/status-table.c2
-rw-r--r--src/sys-util.h4
-rw-r--r--src/verify.c9
-rw-r--r--src/versioninfo.rc.in2
-rw-r--r--src/w32-util.c132
31 files changed, 781 insertions, 331 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index bdfcaf2..ec839e4 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -107,8 +107,8 @@ subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(srcdir)/versioninfo.rc.in $(srcdir)/gpgme.h.in \
- $(srcdir)/gpgme-config.in setenv.c funopen.c stpcpy.c \
- vasprintf.c ttyname_r.c $(top_srcdir)/build-aux/depcomp
+ $(srcdir)/gpgme-config.in stpcpy.c funopen.c vasprintf.c \
+ setenv.c ttyname_r.c $(top_srcdir)/build-aux/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
$(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
diff --git a/src/context.h b/src/context.h
index 745ffa8..757d9b4 100644
--- a/src/context.h
+++ b/src/context.h
@@ -98,6 +98,9 @@ struct gpgme_context
/* True if text mode should be used. */
unsigned int use_textmode : 1;
+ /* True if offline mode should be used. */
+ unsigned int offline : 1;
+
/* Flags for keylist mode. */
gpgme_keylist_mode_t keylist_mode;
@@ -132,6 +135,10 @@ struct gpgme_context
gpgme_progress_cb_t progress_cb;
void *progress_cb_value;
+ /* The user provided status callback and its hook value. */
+ gpgme_status_cb_t status_cb;
+ void *status_cb_value;
+
/* A list of file descriptors in active use by the current
operation. */
struct fd_table fdt;
diff --git a/src/debug.c b/src/debug.c
index 292db55..1dd3723 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -46,6 +46,7 @@
#include "util.h"
#include "ath.h"
#include "sema.h"
+#include "sys-util.h"
#include "debug.h"
@@ -207,7 +208,16 @@ debug_init (void)
UNLOCK (debug_lock);
if (debug_level > 0)
- _gpgme_debug (DEBUG_INIT, "gpgme_debug: level=%d\n", debug_level);
+ {
+ _gpgme_debug (DEBUG_INIT, "gpgme_debug: level=%d\n", debug_level);
+#ifdef HAVE_W32_SYSTEM
+ {
+ const char *name = _gpgme_get_inst_dir ();
+ _gpgme_debug (DEBUG_INIT, "gpgme_debug: gpgme='%s'\n",
+ name? name: "?");
+ }
+#endif
+ }
}
diff --git a/src/decrypt.c b/src/decrypt.c
index 4742060..4db68a1 100644
--- a/src/decrypt.c
+++ b/src/decrypt.c
@@ -38,6 +38,9 @@ typedef struct
{
struct _gpgme_op_decrypt_result result;
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
int okay;
int failed;
@@ -192,6 +195,10 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
switch (code)
{
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
/* FIXME: These error values should probably be attributed to
the underlying crypto engine (as error source). */
@@ -199,6 +206,8 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
return gpg_error (GPG_ERR_DECRYPT_FAILED);
else if (!opd->okay)
return gpg_error (GPG_ERR_NO_DATA);
+ else if (opd->failure_code)
+ return opd->failure_code;
break;
case GPGME_STATUS_DECRYPTION_INFO:
@@ -291,6 +300,16 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
err = _gpgme_parse_plaintext (args, &opd->result.file_name);
if (err)
return err;
+ break;
+
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ if (ctx->status_cb)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
+ if (err)
+ return err;
+ }
+ break;
default:
break;
diff --git a/src/encrypt.c b/src/encrypt.c
index 792c25c..9f5134d 100644
--- a/src/encrypt.c
+++ b/src/encrypt.c
@@ -36,6 +36,9 @@ typedef struct
{
struct _gpgme_op_encrypt_result result;
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
/* A pointer to the next pointer of the last invalid recipient in
the list. This makes appending new invalid recipients painless
while preserving the order. */
@@ -114,9 +117,15 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
switch (code)
{
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
if (opd->result.invalid_recipients)
return gpg_error (GPG_ERR_UNUSABLE_PUBKEY);
+ if (opd->failure_code)
+ return opd->failure_code;
break;
case GPGME_STATUS_INV_RECP:
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index 663b2ea..9902467 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -282,12 +282,10 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
char *dft_ttytype = NULL;
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (rc)
- {
- err = gpg_error_from_errno (rc);
- goto leave;
- }
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!rc)
{
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
{
diff --git a/src/engine-backend.h b/src/engine-backend.h
index b3cc412..4f4519c 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -85,10 +85,12 @@ struct engine_ops
gpgme_error_t (*import) (void *engine, gpgme_data_t keydata,
gpgme_key_t *keyarray);
gpgme_error_t (*keylist) (void *engine, const char *pattern,
- int secret_only, gpgme_keylist_mode_t mode);
+ int secret_only, gpgme_keylist_mode_t mode,
+ int engine_flags);
gpgme_error_t (*keylist_ext) (void *engine, const char *pattern[],
int secret_only, int reserved,
- gpgme_keylist_mode_t mode);
+ gpgme_keylist_mode_t mode,
+ int engine_flags);
gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor,
int use_textmode, int include_certs,
diff --git a/src/engine-g13.c b/src/engine-g13.c
index a9717ee..4a7b75c 100644
--- a/src/engine-g13.c
+++ b/src/engine-g13.c
@@ -286,12 +286,10 @@ g13_new (void **engine, const char *file_name, const char *home_dir)
int rc;
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (rc)
- {
- err = gpg_error_from_errno (rc);
- goto leave;
- }
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!rc)
{
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
{
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index e14fd8d..9efced2 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -513,6 +513,8 @@ gpg_new (void **engine, const char *file_name, const char *home_dir)
rc = add_arg (gpg, dft_display);
free (dft_display);
+ if (rc)
+ goto leave;
}
if (isatty (1))
@@ -520,9 +522,10 @@ gpg_new (void **engine, const char *file_name, const char *home_dir)
int err;
err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (err)
- rc = gpg_error_from_errno (err);
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!err)
{
if (*dft_ttyname)
{
@@ -547,9 +550,9 @@ gpg_new (void **engine, const char *file_name, const char *home_dir)
free (dft_ttytype);
}
+ if (rc)
+ goto leave;
}
- if (rc)
- goto leave;
}
leave:
@@ -1456,7 +1459,7 @@ gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
err = add_data (gpg, ciph, -1, 0);
if (!err)
- start (gpg);
+ err = start (gpg);
return err;
}
@@ -1479,7 +1482,7 @@ gpg_delete (void *engine, gpgme_key_t key, int allow_secret)
}
if (!err)
- start (gpg);
+ err = start (gpg);
return err;
}
@@ -1497,7 +1500,7 @@ gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
if (!err)
err = add_arg (gpg, key->subkeys->fpr);
if (!err)
- start (gpg);
+ err = start (gpg);
return err;
}
@@ -1793,7 +1796,8 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
gpgme_error_t err = 0;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
- |GPGME_EXPORT_MODE_MINIMAL)))
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_SECRET)))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
if ((mode & GPGME_EXPORT_MODE_MINIMAL))
@@ -1807,7 +1811,10 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
}
else
{
- err = add_arg (gpg, "--export");
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ err = add_arg (gpg, "--export-secret-keys");
+ else
+ err = add_arg (gpg, "--export");
if (!err && use_armor)
err = add_arg (gpg, "--armor");
if (!err)
@@ -2279,7 +2286,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
static gpgme_error_t
gpg_keylist (void *engine, const char *pattern, int secret_only,
- gpgme_keylist_mode_t mode)
+ gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpg_t gpg = engine;
gpgme_error_t err;
@@ -2298,7 +2305,7 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
static gpgme_error_t
gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
- int reserved, gpgme_keylist_mode_t mode)
+ int reserved, gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpg_t gpg = engine;
gpgme_error_t err;
@@ -2364,7 +2371,7 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
err = add_data (gpg, out, 1, 1);
if (!err)
- start (gpg);
+ err = start (gpg);
return err;
}
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index ac6c5fc..476e9ef 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -408,12 +408,10 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
int rc;
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (rc)
- {
- err = gpg_error_from_errno (rc);
- goto leave;
- }
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!rc)
{
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
{
@@ -1289,17 +1287,23 @@ gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- if (mode)
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
if (!pattern)
pattern = "";
- cmd = malloc (7 + strlen (pattern) + 1);
+ cmd = malloc (7 + 9 + 9 + strlen (pattern) + 1);
if (!cmd)
return gpg_error_from_syserror ();
+
strcpy (cmd, "EXPORT ");
- strcpy (&cmd[7], pattern);
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ strcat (cmd, "--secret ");
+ if ((mode & GPGME_EXPORT_MODE_RAW))
+ strcat (cmd, "--raw ");
+ else if ((mode & GPGME_EXPORT_MODE_PKCS12))
+ strcat (cmd, "--pkcs12 ");
+ }
+ strcat (cmd, pattern);
gpgsm->output_cb.data = keydata;
err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor"
@@ -1323,16 +1327,13 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err = 0;
char *line;
- /* Length is "EXPORT " + p + '\0'. */
- int length = 7 + 1;
+ /* Length is "EXPORT " + "--secret " + "--pkcs12 " + p + '\0'. */
+ int length = 7 + 9 + 9 + 1;
char *linep;
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- if (mode)
- return gpg_error (GPG_ERR_NOT_SUPPORTED);
-
if (pattern && *pattern)
{
const char **pat = pattern;
@@ -1357,7 +1358,15 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
return gpg_error_from_syserror ();
strcpy (line, "EXPORT ");
- linep = &line[7];
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ strcat (line, "--secret ");
+ if ((mode & GPGME_EXPORT_MODE_RAW))
+ strcat (line, "--raw ");
+ else if ((mode & GPGME_EXPORT_MODE_PKCS12))
+ strcat (line, "--pkcs12 ");
+ }
+ linep = &line[strlen (line)];
if (pattern && *pattern)
{
@@ -1542,7 +1551,7 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
static gpgme_error_t
gpgsm_keylist (void *engine, const char *pattern, int secret_only,
- gpgme_keylist_mode_t mode)
+ gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpgsm_t gpgsm = engine;
char *line;
@@ -1599,6 +1608,11 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
+ "OPTION offline=1":
+ "OPTION offline=0" ,
+ NULL, NULL);
/* Length is "LISTSECRETKEYS " + p + '\0'. */
@@ -1629,7 +1643,7 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
static gpgme_error_t
gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
- int reserved, gpgme_keylist_mode_t mode)
+ int reserved, gpgme_keylist_mode_t mode, int engine_flags)
{
engine_gpgsm_t gpgsm = engine;
char *line;
@@ -1669,7 +1683,11 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
-
+ gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ (engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
+ "OPTION offline=1":
+ "OPTION offline=0" ,
+ NULL, NULL);
if (pattern && *pattern)
{
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index a7184b7..e4fd47c 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -326,12 +326,10 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
int rc;
rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
- if (rc)
- {
- err = gpg_error_from_errno (rc);
- goto leave;
- }
- else
+
+ /* Even though isatty() returns 1, ttyname_r() may fail in many
+ ways, e.g., when /dev/pts is not accessible under chroot. */
+ if (!rc)
{
if (asprintf (&optstr, "OPTION ttyname=%s", dft_ttyname) < 0)
{
diff --git a/src/engine.c b/src/engine.c
index ff015c0..8e84da9 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -726,7 +726,8 @@ _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
gpgme_error_t
_gpgme_engine_op_keylist (engine_t engine, const char *pattern,
- int secret_only, gpgme_keylist_mode_t mode)
+ int secret_only, gpgme_keylist_mode_t mode,
+ int engine_flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -734,14 +735,15 @@ _gpgme_engine_op_keylist (engine_t engine, const char *pattern,
if (!engine->ops->keylist)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode);
+ return (*engine->ops->keylist) (engine->engine, pattern, secret_only, mode,
+ engine_flags);
}
gpgme_error_t
_gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
int secret_only, int reserved,
- gpgme_keylist_mode_t mode)
+ gpgme_keylist_mode_t mode, int engine_flags)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -750,7 +752,7 @@ _gpgme_engine_op_keylist_ext (engine_t engine, const char *pattern[],
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->keylist_ext) (engine->engine, pattern, secret_only,
- reserved, mode);
+ reserved, mode, engine_flags);
}
diff --git a/src/engine.h b/src/engine.h
index bbf009d..56fcc42 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -113,12 +113,14 @@ gpgme_error_t _gpgme_engine_op_import (engine_t engine,
gpgme_error_t _gpgme_engine_op_keylist (engine_t engine,
const char *pattern,
int secret_only,
- gpgme_keylist_mode_t mode);
+ gpgme_keylist_mode_t mode,
+ int engine_flags);
gpgme_error_t _gpgme_engine_op_keylist_ext (engine_t engine,
const char *pattern[],
int secret_only,
int reserved,
- gpgme_keylist_mode_t mode);
+ gpgme_keylist_mode_t mode,
+ int engine_flags);
gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in,
gpgme_data_t out, gpgme_sig_mode_t mode,
int use_armor, int use_textmode,
@@ -170,5 +172,8 @@ gpgme_error_t _gpgme_engine_op_spawn (engine_t engine,
gpgme_data_t dataerr,
unsigned int flags);
+/* The available engine option flags. */
+#define GPGME_ENGINE_FLAG_OFFLINE 1
+
#endif /* ENGINE_H */
diff --git a/src/export.c b/src/export.c
index 8930aa6..a29fbde 100644
--- a/src/export.c
+++ b/src/export.c
@@ -120,9 +120,24 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
- |GPGME_EXPORT_MODE_MINIMAL)))
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_RAW
+ |GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ if ((mode & GPGME_EXPORT_MODE_EXTERN))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+ if ((mode & GPGME_EXPORT_MODE_RAW)
+ && (mode & GPGME_EXPORT_MODE_PKCS12))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+
+ if (ctx->protocol != GPGME_PROTOCOL_CMS
+ && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
+ }
if ((mode & GPGME_EXPORT_MODE_EXTERN))
{
@@ -199,9 +214,25 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
op_data_t opd;
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
- |GPGME_EXPORT_MODE_MINIMAL)))
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_RAW
+ |GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
+ if ((mode & GPGME_EXPORT_MODE_SECRET))
+ {
+ if ((mode & GPGME_EXPORT_MODE_EXTERN))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+ if ((mode & GPGME_EXPORT_MODE_RAW)
+ && (mode & GPGME_EXPORT_MODE_PKCS12))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+
+ if (ctx->protocol != GPGME_PROTOCOL_CMS
+ && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
+ }
+
if ((mode & GPGME_EXPORT_MODE_EXTERN))
{
if (keydata)
diff --git a/src/genkey.c b/src/genkey.c
index fd6685e..3afd3b4 100644
--- a/src/genkey.c
+++ b/src/genkey.c
@@ -37,6 +37,9 @@ typedef struct
{
struct _gpgme_op_genkey_result result;
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
/* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter;
} *op_data_t;
@@ -118,10 +121,25 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
}
break;
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
/* FIXME: Should return some more useful error value. */
if (!opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL);
+ else if (opd->failure_code)
+ return opd->failure_code;
+ break;
+
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ if (ctx->status_cb)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
+ if (err)
+ return err;
+ }
break;
default:
@@ -186,6 +204,14 @@ genkey_start (gpgme_ctx_t ctx, int synchronous, const char *parms,
_gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
return _gpgme_engine_op_genkey (ctx->engine, opd->key_parameter,
ctx->use_armor, pubkey, seckey);
}
diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c
index d42179b..e5e5707 100644
--- a/src/gpgme-tool.c
+++ b/src/gpgme-tool.c
@@ -3054,7 +3054,7 @@ cmd_import (assuan_context_t ctx, char *line)
static const char hlp_export[] =
- "EXPORT [--extern] [--minimal] [<pattern>]\n"
+ "EXPORT [--extern] [--minimal] [--secret [--pkcs12] [--raw]] [<pattern>]\n"
"\n"
"Export the keys described by PATTERN. Write the\n"
"the output to the object set by the last OUTPUT command.";
@@ -3082,6 +3082,12 @@ cmd_export (assuan_context_t ctx, char *line)
mode |= GPGME_EXPORT_MODE_EXTERN;
if (has_option (line, "--minimal"))
mode |= GPGME_EXPORT_MODE_MINIMAL;
+ if (has_option (line, "--secret"))
+ mode |= GPGME_EXPORT_MODE_SECRET;
+ if (has_option (line, "--raw"))
+ mode |= GPGME_EXPORT_MODE_RAW;
+ if (has_option (line, "--pkcs12"))
+ mode |= GPGME_EXPORT_MODE_PKCS12;
line = skip_options (line);
@@ -3728,6 +3734,7 @@ static char args_doc[] = "COMMAND [OPTIONS...]";
static struct argp_option options[] = {
{ "server", 's', 0, 0, "Server mode" },
{ "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
+ { "lib-version", 502, 0, 0, "Show library version" },
{ 0 }
};
@@ -3736,7 +3743,7 @@ static struct argp argp = { options, parse_options, args_doc, doc };
struct args
{
- enum { CMD_DEFAULT, CMD_SERVER } cmd;
+ enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd;
const char *gpg_binary;
};
@@ -3762,6 +3769,11 @@ parse_options (int key, char *arg, struct argp_state *state)
case 501:
args->gpg_binary = arg;
break;
+
+ case 502:
+ args->cmd = CMD_LIBVERSION;
+ break;
+
#if 0
case ARGP_KEY_ARG:
if (state->arg_num >= 2)
@@ -3787,6 +3799,7 @@ main (int argc, char *argv[])
struct args args;
struct gpgme_tool gt;
gpg_error_t err;
+ int needgt = 1;
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, "");
@@ -3804,7 +3817,10 @@ main (int argc, char *argv[])
argp_parse (&argp, argc, argv, 0, 0, &args);
log_init ();
- if (args.gpg_binary)
+ if (args.cmd == CMD_LIBVERSION)
+ needgt = 0;
+
+ if (needgt && args.gpg_binary)
{
if (access (args.gpg_binary, X_OK))
err = gpg_error_from_syserror ();
@@ -3816,7 +3832,8 @@ main (int argc, char *argv[])
args.gpg_binary);
}
- gt_init (&gt);
+ if (needgt)
+ gt_init (&gt);
switch (args.cmd)
{
@@ -3824,9 +3841,17 @@ main (int argc, char *argv[])
case CMD_SERVER:
gpgme_server (&gt);
break;
+
+ case CMD_LIBVERSION:
+ printf ("Version from header: %s (0x%06x)\n",
+ GPGME_VERSION, GPGME_VERSION_NUMBER);
+ printf ("Version from binary: %s\n", gpgme_check_version (NULL));
+ printf ("Copyright blurb ...:%s\n", gpgme_check_version ("\x01\x01"));
+ break;
}
- gpgme_release (gt.ctx);
+ if (needgt)
+ gpgme_release (gt.ctx);
#ifdef HAVE_W32CE_SYSTEM
/* Give the buggy ssh server time to flush the output buffers. */
diff --git a/src/gpgme.c b/src/gpgme.c
index 628cdae..0cf999a 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -472,6 +472,30 @@ gpgme_get_textmode (gpgme_ctx_t ctx)
}
+/* Enable offline mode for this context. In offline mode dirmngr
+ will be disabled. */
+void
+gpgme_set_offline (gpgme_ctx_t ctx, int offline)
+{
+ TRACE2 (DEBUG_CTX, "gpgme_set_offline", ctx, "offline=%i (%s)",
+ offline, offline ? "yes" : "no");
+
+ if (!ctx)
+ return;
+
+ ctx->offline = offline;
+}
+
+/* Return the state of the offline flag. */
+int
+gpgme_get_offline (gpgme_ctx_t ctx)
+{
+ TRACE2 (DEBUG_CTX, "gpgme_get_offline", ctx, "ctx->offline=%i (%s)",
+ ctx->offline, ctx->offline ? "yes" : "no");
+ return ctx->offline;
+}
+
+
/* Set the number of certifications to include in an S/MIME message.
The default is GPGME_INCLUDE_CERTS_DEFAULT. -1 means all certs,
and -2 means all certs except the root cert. */
@@ -632,6 +656,47 @@ gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *r_cb,
}
+/* This function sets a callback function to be used as a status
+ message forwarder. */
+void
+gpgme_set_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t cb, void *cb_value)
+{
+ TRACE2 (DEBUG_CTX, "gpgme_set_status_cb", ctx, "status_cb=%p/%p",
+ cb, cb_value);
+
+ if (!ctx)
+ return;
+
+ ctx->status_cb = cb;
+ ctx->status_cb_value = cb_value;
+}
+
+
+/* This function returns the callback function to be used as a
+ status message forwarder. */
+void
+gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *r_cb,
+ void **r_cb_value)
+{
+ TRACE2 (DEBUG_CTX, "gpgme_get_status_cb", ctx, "ctx->status_cb=%p/%p",
+ ctx ? ctx->status_cb : NULL, ctx ? ctx->status_cb_value : NULL);
+
+ if (r_cb)
+ *r_cb = NULL;
+
+ if (r_cb_value)
+ *r_cb_value = NULL;
+
+ if (!ctx || !ctx->status_cb)
+ return;
+
+ if (r_cb)
+ *r_cb = ctx->status_cb;
+ if (r_cb_value)
+ *r_cb_value = ctx->status_cb_value;
+}
+
+
/* Set the I/O callback functions for CTX to IO_CBS. */
void
gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs)
diff --git a/src/gpgme.def b/src/gpgme.def
index dc18948..a3f5fb4 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -217,5 +217,11 @@ EXPORTS
gpgme_op_spawn_start @163
gpgme_op_spawn @164
+
+ gpgme_set_offline @165
+ gpgme_get_offline @166
+
+ gpgme_set_status_cb @167
+ gpgme_get_status_cb @168
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 15ed803..6cea2c7 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1,36 +1,28 @@
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
- Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009
- 2010, 2011, 2012, 2013, 2014 g10 Code GmbH
-
- This file is part of GPGME.
-
- GPGME is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- GPGME is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, see <http://www.gnu.org/licenses/>.
-
- Generated from gpgme.h.in for @GPGME_CONFIG_HOST@. */
+ * Copyright (C) 2000 Werner Koch (dd9jn)
+ * Copyright (C) 2001-2015 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Generated from gpgme.h.in for @GPGME_CONFIG_HOST@.
+ */
#ifndef GPGME_H
#define GPGME_H
-#ifdef __GNUC__
-#define _GPGME_INLINE __inline__
-#elif __STDC_VERSION__ >= 199901L
-#define _GPGME_INLINE inline
-#else
-#define _GPGME_INLINE
-#endif
-
/* Include stdio.h for the FILE type definition. */
#include <stdio.h>
#include <time.h>
@@ -38,29 +30,60 @@
#ifdef __cplusplus
extern "C" {
-#if 0 /* just to make Emacs auto-indent happy */
+#if 0 /*(Make Emacsen's auto-indent happy.)*/
}
#endif
#endif /* __cplusplus */
+
+/* The version of this header should match the one of the library. Do
+ not use this symbol in your application, use gpgme_check_version
+ instead. The purpose of this macro is to let autoconf (using the
+ AM_PATH_GPGME macro) check that this header matches the installed
+ library. */
+#define GPGME_VERSION "@PACKAGE_VERSION@"
+
+/* The version number of this header. It may be used to handle minor
+ API incompatibilities. */
+#define GPGME_VERSION_NUMBER @VERSION_NUMBER@
+
+
+/* System specific typedefs. */
@INSERT__TYPEDEFS_FOR_GPGME_H@
+
-/* Check for compiler features. */
-#if __GNUC__
-#define _GPGME_GCC_VERSION (__GNUC__ * 10000 \
- + __GNUC_MINOR__ * 100 \
- + __GNUC_PATCHLEVEL__)
-
-#if _GPGME_GCC_VERSION > 30100
-#define _GPGME_DEPRECATED __attribute__ ((__deprecated__))
-#endif
+/*
+ * Check for compiler features.
+ */
+#ifdef GPGRT_INLINE
+# define _GPGME_INLINE GPGRT_INLINE
+#elif defined(__GNUC__)
+# define _GPGME_INLINE __inline__
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+# define _GPGME_INLINE inline
+#else
+# define _GPGME_INLINE
#endif
-#ifndef _GPGME_DEPRECATED
-#define _GPGME_DEPRECATED
+
+#ifdef GPGRT_ATTR_DEPRECATED
+# define _GPGME_DEPRECATED GPGRT_ATTR_DEPRECATED
+#elif defined(__GNUC__)
+# define _GPGME_GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+# if _GPGME_GCC_VERSION > 30100
+# define _GPGME_DEPRECATED __attribute__ ((__deprecated__))
+# else
+# define _GPGME_DEPRECATED
+# endif
+#else
+# define _GPGME_DEPRECATED
#endif
+
/* The macro _GPGME_DEPRECATED_OUTSIDE_GPGME suppresses warnings for
fields we must access in GPGME for ABI compatibility. */
#ifdef _GPGME_IN_GPGME
@@ -69,17 +92,6 @@ extern "C" {
#define _GPGME_DEPRECATED_OUTSIDE_GPGME _GPGME_DEPRECATED
#endif
-
-/* The version of this header should match the one of the library. Do
- not use this symbol in your application, use gpgme_check_version
- instead. The purpose of this macro is to let autoconf (using the
- AM_PATH_GPGME macro) check that this header matches the installed
- library. */
-#define GPGME_VERSION "@PACKAGE_VERSION@"
-
-/* The version number of this header. It may be used to handle minor
- API incompatibilities. */
-#define GPGME_VERSION_NUMBER @VERSION_NUMBER@
/* Check for a matching _FILE_OFFSET_BITS definition. */
#if @NEED__FILE_OFFSET_BITS@
@@ -94,7 +106,9 @@ extern "C" {
-/* Some opaque data types used by GPGME. */
+/*
+ * Some opaque data types used by GPGME.
+ */
/* The context holds some global state and configuration options, as
well as the results of a crypto operation. */
@@ -105,8 +119,11 @@ typedef struct gpgme_context *gpgme_ctx_t;
struct gpgme_data;
typedef struct gpgme_data *gpgme_data_t;
+
-/* Wrappers for the libgpg-error library. */
+/*
+ * Wrappers for the libgpg-error library.
+ */
typedef gpg_error_t gpgme_error_t;
typedef gpg_err_code_t gpgme_err_code_t;
@@ -196,7 +213,12 @@ gpgme_error_from_syserror (void)
return gpgme_error (gpgme_err_code_from_syserror ());
}
+
+/*
+ * Various constants and types
+ */
+
/* The possible encoding mode of gpgme_data_t objects. */
typedef enum
{
@@ -210,6 +232,7 @@ typedef enum
}
gpgme_data_encoding_t;
+
/* Known data types. */
typedef enum
{
@@ -226,7 +249,7 @@ typedef enum
}
gpgme_data_type_t;
-
+
/* Public key algorithms. */
typedef enum
{
@@ -264,7 +287,7 @@ typedef enum
}
gpgme_hash_algo_t;
-
+
/* The possible signature stati. Deprecated, use error value in sig
status. */
typedef enum
@@ -292,7 +315,7 @@ typedef enum
}
gpgme_sig_mode_t;
-
+
/* The available key and signature attributes. Deprecated, use the
individual result structures instead. */
typedef enum
@@ -333,7 +356,7 @@ typedef enum
_gpgme_attr_t;
typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED;
-
+
/* The available validities for a trust item or key. */
typedef enum
{
@@ -346,7 +369,7 @@ typedef enum
}
gpgme_validity_t;
-
+
/* The available protocols. */
typedef enum
{
@@ -364,7 +387,7 @@ gpgme_protocol_t;
/* Convenience macro for the surprisingly mixed spelling. */
#define GPGME_PROTOCOL_OPENPGP GPGME_PROTOCOL_OpenPGP
-
+
/* The available keylist mode flags. */
#define GPGME_KEYLIST_MODE_LOCAL 1
#define GPGME_KEYLIST_MODE_EXTERN 2
@@ -376,7 +399,7 @@ gpgme_protocol_t;
typedef unsigned int gpgme_keylist_mode_t;
-
+
/* The pinentry modes. */
typedef enum
{
@@ -388,59 +411,21 @@ typedef enum
}
gpgme_pinentry_mode_t;
-
+
/* The available export mode flags. */
#define GPGME_EXPORT_MODE_EXTERN 2
#define GPGME_EXPORT_MODE_MINIMAL 4
+#define GPGME_EXPORT_MODE_SECRET 16
+#define GPGME_EXPORT_MODE_RAW 32
+#define GPGME_EXPORT_MODE_PKCS12 64
typedef unsigned int gpgme_export_mode_t;
-
+
/* Flags for the audit log functions. */
#define GPGME_AUDITLOG_HTML 1
#define GPGME_AUDITLOG_WITH_HELP 128
-
-/* Signature notations. */
-
-/* The available signature notation flags. */
-#define GPGME_SIG_NOTATION_HUMAN_READABLE 1
-#define GPGME_SIG_NOTATION_CRITICAL 2
-
-typedef unsigned int gpgme_sig_notation_flags_t;
-
-struct _gpgme_sig_notation
-{
- struct _gpgme_sig_notation *next;
-
- /* If NAME is a null pointer, then VALUE contains a policy URL
- rather than a notation. */
- char *name;
-
- /* The value of the notation data. */
- char *value;
-
- /* The length of the name of the notation data. */
- int name_len;
-
- /* The length of the value of the notation data. */
- int value_len;
-
- /* The accumulated flags. */
- gpgme_sig_notation_flags_t flags;
-
- /* Notation data is human-readable. */
- unsigned int human_readable : 1;
-
- /* Notation data is critical. */
- unsigned int critical : 1;
-
- /* Internal to GPGME, do not use. */
- int _unused : 30;
-};
-typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;
-
-
/* The possible stati for the edit operation. */
typedef enum
{
@@ -544,11 +529,56 @@ typedef enum
GPGME_STATUS_PINENTRY_LAUNCHED = 88,
GPGME_STATUS_ATTRIBUTE = 89,
GPGME_STATUS_BEGIN_SIGNING = 90,
- GPGME_STATUS_KEY_NOT_CREATED = 91
+ GPGME_STATUS_KEY_NOT_CREATED = 91,
+ GPGME_STATUS_INQUIRE_MAXLEN = 92,
+ GPGME_STATUS_FAILURE = 93
}
gpgme_status_code_t;
+
+/* The available signature notation flags. */
+#define GPGME_SIG_NOTATION_HUMAN_READABLE 1
+#define GPGME_SIG_NOTATION_CRITICAL 2
+
+typedef unsigned int gpgme_sig_notation_flags_t;
+
+struct _gpgme_sig_notation
+{
+ struct _gpgme_sig_notation *next;
+
+ /* If NAME is a null pointer, then VALUE contains a policy URL
+ rather than a notation. */
+ char *name;
+
+ /* The value of the notation data. */
+ char *value;
+
+ /* The length of the name of the notation data. */
+ int name_len;
+
+ /* The length of the value of the notation data. */
+ int value_len;
+
+ /* The accumulated flags. */
+ gpgme_sig_notation_flags_t flags;
+
+ /* Notation data is human-readable. */
+ unsigned int human_readable : 1;
+
+ /* Notation data is critical. */
+ unsigned int critical : 1;
+
+ /* Internal to GPGME, do not use. */
+ int _unused : 30;
+};
+typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;
+
+
+/*
+ * Public structures.
+ */
+
/* The engine information structure. */
struct _gpgme_engine_info
{
@@ -571,7 +601,7 @@ struct _gpgme_engine_info
};
typedef struct _gpgme_engine_info *gpgme_engine_info_t;
-
+
/* A subkey from a key. */
struct _gpgme_subkey
{
@@ -826,8 +856,20 @@ struct _gpgme_key
typedef struct _gpgme_key *gpgme_key_t;
+/* An invalid key object. */
+struct _gpgme_invalid_key
+{
+ struct _gpgme_invalid_key *next;
+ char *fpr;
+ gpgme_error_t reason;
+};
+typedef struct _gpgme_invalid_key *gpgme_invalid_key_t;
+
+
-/* Types for callback functions. */
+/*
+ * Types for callback functions.
+ */
/* Request a passphrase from the user. */
typedef gpgme_error_t (*gpgme_passphrase_cb_t) (void *hook,
@@ -839,6 +881,11 @@ typedef gpgme_error_t (*gpgme_passphrase_cb_t) (void *hook,
typedef void (*gpgme_progress_cb_t) (void *opaque, const char *what,
int type, int current, int total);
+/* Status messages from gpg. */
+typedef gpgme_error_t (*gpgme_status_cb_t) (void *opaque, const char *keyword,
+ const char *args);
+
+
/* Interact with the user about an edit operation. */
typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
gpgme_status_code_t status,
@@ -847,7 +894,9 @@ typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
-/* Context management functions. */
+/*
+ * Context management functions.
+ */
/* Create a new context and return it in CTX. */
gpgme_error_t gpgme_new (gpgme_ctx_t *ctx);
@@ -887,6 +936,12 @@ void gpgme_set_textmode (gpgme_ctx_t ctx, int yes);
/* Return non-zero if text mode is set in CTX. */
int gpgme_get_textmode (gpgme_ctx_t ctx);
+/* If YES is non-zero, enable offline mode in CTX, disable it otherwise. */
+void gpgme_set_offline (gpgme_ctx_t ctx, int yes);
+
+/* Return non-zero if offline mode is set in CTX. */
+int gpgme_get_offline (gpgme_ctx_t ctx);
+
/* Use whatever the default of the backend crypto engine is. */
#define GPGME_INCLUDE_CERTS_DEFAULT -256
@@ -930,6 +985,16 @@ void gpgme_set_progress_cb (gpgme_ctx_t c, gpgme_progress_cb_t cb,
void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
void **hook_value);
+/* Set the status callback function in CTX to CB. HOOK_VALUE is
+ passed as first argument to thes status callback function. */
+void gpgme_set_status_cb (gpgme_ctx_t c, gpgme_status_cb_t cb,
+ void *hook_value);
+
+/* Get the current status callback function in *CB and the current
+ hook value in *HOOK_VALUE. */
+void gpgme_get_status_cb (gpgme_ctx_t ctx, gpgme_status_cb_t *cb,
+ void **hook_value);
+
/* This function sets the locale for the context CTX, or the default
locale if CTX is a null pointer. */
gpgme_error_t gpgme_set_locale (gpgme_ctx_t ctx, int category,
@@ -947,16 +1012,6 @@ gpgme_error_t gpgme_ctx_set_engine_info (gpgme_ctx_t ctx,
const char *file_name,
const char *home_dir);
-
-/* Return a statically allocated string with the name of the public
- key algorithm ALGO, or NULL if that name is not known. */
-const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo);
-
-/* Return a statically allocated string with the name of the hash
- algorithm ALGO, or NULL if that name is not known. */
-const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo);
-
-
/* Delete all signers from CTX. */
void gpgme_signers_clear (gpgme_ctx_t ctx);
@@ -995,7 +1050,7 @@ const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx,
gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
_GPGME_DEPRECATED;
-
+
/* Clear all notation data from the context. */
void gpgme_sig_notation_clear (gpgme_ctx_t ctx);
@@ -1011,8 +1066,11 @@ gpgme_error_t gpgme_sig_notation_add (gpgme_ctx_t ctx, const char *name,
/* Get the sig notations for this context. */
gpgme_sig_notation_t gpgme_sig_notation_get (gpgme_ctx_t ctx);
+
-/* Run control. */
+/*
+ * Run control.
+ */
/* The type of an I/O callback function. */
typedef gpgme_error_t (*gpgme_io_cb_t) (void *data, int fd);
@@ -1085,8 +1143,17 @@ gpgme_ctx_t gpgme_wait (gpgme_ctx_t ctx, gpgme_error_t *status, int hang);
gpgme_ctx_t gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
gpgme_error_t *op_err, int hang);
+/* Cancel a pending asynchronous operation. */
+gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx);
+
+/* Cancel a pending operation asynchronously. */
+gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx);
+
+
-/* Functions to handle data objects. */
+/*
+ * Functions to handle data objects.
+ */
/* Read up to SIZE bytes into buffer BUFFER from the data object with
the handle HANDLE. Return the number of characters read, 0 on EOF
@@ -1209,14 +1276,20 @@ gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh,
gpgme_data_seek instead. */
gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED;
+
-/* Key and trust functions. */
+/*
+ * Key and trust functions.
+ */
/* Get the key with the fingerprint FPR from the crypto backend. If
SECRET is true, get the secret key. */
gpgme_error_t gpgme_get_key (gpgme_ctx_t ctx, const char *fpr,
gpgme_key_t *r_key, int secret);
+/* Create a dummy key to specify an email address. */
+gpgme_error_t gpgme_key_from_uid (gpgme_key_t *key, const char *name);
+
/* Acquire a reference to KEY. */
void gpgme_key_ref (gpgme_key_t key);
@@ -1259,26 +1332,12 @@ unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx,
const void *reserved, int idx)
_GPGME_DEPRECATED;
-
-/* Crypto Operations. */
-
-/* Cancel a pending asynchronous operation. */
-gpgme_error_t gpgme_cancel (gpgme_ctx_t ctx);
-
-/* Cancel a pending operation asynchronously. */
-gpgme_error_t gpgme_cancel_async (gpgme_ctx_t ctx);
-struct _gpgme_invalid_key
-{
- struct _gpgme_invalid_key *next;
- char *fpr;
- gpgme_error_t reason;
-};
-typedef struct _gpgme_invalid_key *gpgme_invalid_key_t;
+/*
+ * Encryption.
+ */
-
-/* Encryption. */
struct _gpgme_op_encrypt_result
{
/* The list of invalid recipients. */
@@ -1322,7 +1381,9 @@ gpgme_error_t gpgme_op_encrypt_sign (gpgme_ctx_t ctx, gpgme_key_t recp[],
gpgme_data_t plain, gpgme_data_t cipher);
-/* Decryption. */
+/*
+ * Decryption.
+ */
struct _gpgme_recipient
{
@@ -1379,7 +1440,10 @@ gpgme_error_t gpgme_op_decrypt_verify (gpgme_ctx_t ctx, gpgme_data_t cipher,
gpgme_data_t plain);
-/* Signing. */
+/*
+ * Signing.
+ */
+
struct _gpgme_new_signature
{
struct _gpgme_new_signature *next;
@@ -1435,7 +1499,9 @@ gpgme_error_t gpgme_op_sign (gpgme_ctx_t ctx,
gpgme_sig_mode_t mode);
-/* Verify. */
+/*
+ * Verify.
+ */
/* Flags used for the SUMMARY field in a gpgme_signature_t. */
typedef enum
@@ -1524,22 +1590,15 @@ gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t plaintext);
-/* Import. */
-
-/* The key was new. */
-#define GPGME_IMPORT_NEW 1
-
-/* The key contained new user IDs. */
-#define GPGME_IMPORT_UID 2
-
-/* The key contained new signatures. */
-#define GPGME_IMPORT_SIG 4
-
-/* The key contained new sub keys. */
-#define GPGME_IMPORT_SUBKEY 8
+/*
+ * Import/Export
+ */
-/* The key contained a secret key. */
-#define GPGME_IMPORT_SECRET 16
+#define GPGME_IMPORT_NEW 1 /* The key was new. */
+#define GPGME_IMPORT_UID 2 /* The key contained new user IDs. */
+#define GPGME_IMPORT_SIG 4 /* The key contained new signatures. */
+#define GPGME_IMPORT_SUBKEY 8 /* The key contained new sub keys. */
+#define GPGME_IMPORT_SECRET 16 /* The key contained a secret key. */
struct _gpgme_import_status
@@ -1560,7 +1619,7 @@ struct _gpgme_import_status
};
typedef struct _gpgme_import_status *gpgme_import_status_t;
-/* Import. */
+/* Import result object. */
struct _gpgme_op_import_result
{
/* Number of considered keys. */
@@ -1624,7 +1683,6 @@ gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]);
gpgme_error_t gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t keys[]);
-
/* Export the keys found by PATTERN into KEYDATA. */
gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
gpgme_export_mode_t mode,
@@ -1653,7 +1711,10 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx,
-/* Key generation. */
+/*
+ * Key generation.
+ */
+
struct _gpgme_op_genkey_result
{
/* A primary key was generated. */
@@ -1681,7 +1742,7 @@ gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms,
/* Retrieve a pointer to the result of the genkey operation. */
gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx);
-
+
/* Delete KEY from the keyring. If ALLOW_SECRET is non-zero, secret
keys are also deleted. */
gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
@@ -1689,7 +1750,12 @@ gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key,
int allow_secret);
+
+/*
+ * Key Edit interface
+ */
+
/* Edit the key KEY. Send status and command requests to FNC and
output of edit commands to OUT. */
gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
@@ -1709,27 +1775,11 @@ gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_data_t out);
-/* Flags for the spawn operations. */
-#define GPGME_SPAWN_DETACHED 1
-#define GPGME_SPAWN_ALLOW_SET_FG 2
-
-
-/* Run the command FILE with the arguments in ARGV. Connect stdin to
- DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data
- streams is NULL, connect to /dev/null instead. */
-gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t ctx,
- const char *file, const char *argv[],
- gpgme_data_t datain,
- gpgme_data_t dataout, gpgme_data_t dataerr,
- unsigned int flags);
-gpgme_error_t gpgme_op_spawn (gpgme_ctx_t ctx,
- const char *file, const char *argv[],
- gpgme_data_t datain,
- gpgme_data_t dataout, gpgme_data_t dataerr,
- unsigned int flags);
-
-/* Key management functions. */
+/*
+ * Key listing
+ */
+
struct _gpgme_op_keylist_result
{
unsigned int truncated : 1;
@@ -1766,7 +1816,9 @@ gpgme_error_t gpgme_op_passwd (gpgme_ctx_t ctx, gpgme_key_t key,
-/* Trust items and operations. */
+/*
+ * Trust items and operations.
+ */
struct _gpgme_trust_item
{
@@ -1841,7 +1893,12 @@ int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
const void *reserved, int idx)
_GPGME_DEPRECATED;
+
+/*
+ * Audit log
+ */
+
/* Return the auditlog for the current session. This may be called
after a successful or failed operation. If no audit log is
available GPG_ERR_NO_DATA is returned. */
@@ -1852,7 +1909,33 @@ gpgme_error_t gpgme_op_getauditlog (gpgme_ctx_t ctx, gpgme_data_t output,
-/* Low-level Assuan protocol access. */
+/*
+ * Spawn interface
+ */
+
+/* Flags for the spawn operations. */
+#define GPGME_SPAWN_DETACHED 1
+#define GPGME_SPAWN_ALLOW_SET_FG 2
+
+
+/* Run the command FILE with the arguments in ARGV. Connect stdin to
+ DATAIN, stdout to DATAOUT, and STDERR to DATAERR. If one the data
+ streams is NULL, connect to /dev/null instead. */
+gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t ctx,
+ const char *file, const char *argv[],
+ gpgme_data_t datain,
+ gpgme_data_t dataout, gpgme_data_t dataerr,
+ unsigned int flags);
+gpgme_error_t gpgme_op_spawn (gpgme_ctx_t ctx,
+ const char *file, const char *argv[],
+ gpgme_data_t datain,
+ gpgme_data_t dataout, gpgme_data_t dataerr,
+ unsigned int flags);
+
+
+/*
+ * Low-level Assuan protocol access.
+ */
typedef gpgme_error_t (*gpgme_assuan_data_cb_t)
(void *opaque, const void *data, size_t datalen);
@@ -1911,7 +1994,10 @@ gpgme_op_assuan_transact (gpgme_ctx_t ctx,
void *status_cb_value) _GPGME_DEPRECATED;
-/* Crypto container support. */
+/*
+ * Crypto container support.
+ */
+
struct _gpgme_op_vfs_mount_result
{
char *mount_dir;
@@ -1932,7 +2018,9 @@ gpgme_error_t gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
unsigned int flags, gpgme_error_t *op_err);
-/* Interface to gpgconf(1). */
+/*
+ * Interface to gpgconf(1).
+ */
/* The expert level at which a configuration option or group of
options should be displayed. See the gpgconf(1) documentation for
@@ -2096,15 +2184,11 @@ gpgme_error_t gpgme_op_conf_load (gpgme_ctx_t ctx, gpgme_conf_comp_t *conf_p);
follow chained components! */
gpgme_error_t gpgme_op_conf_save (gpgme_ctx_t ctx, gpgme_conf_comp_t comp);
-
-/* UIServer support. */
-
-/* Create a dummy key to specify an email address. */
-gpgme_error_t gpgme_key_from_uid (gpgme_key_t *key, const char *name);
-
-/* Various functions. */
+/*
+ * Various functions.
+ */
/* Set special global flags; consult the manual before use. */
int gpgme_set_global_flag (const char *name, const char *value);
@@ -2139,19 +2223,28 @@ gpgme_error_t gpgme_set_engine_info (gpgme_protocol_t proto,
const char *file_name,
const char *home_dir);
-
-/* Engine support functions. */
-
/* Verify that the engine implementing PROTO is installed and
available. */
gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto);
-
+
+/* Reference counting for result objects. */
void gpgme_result_ref (void *result);
void gpgme_result_unref (void *result);
+/* Return a statically allocated string with the name of the public
+ key algorithm ALGO, or NULL if that name is not known. */
+const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo);
+
+/* Return a statically allocated string with the name of the hash
+ algorithm ALGO, or NULL if that name is not known. */
+const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo);
+
+
-/* Deprecated types. */
+/*
+ * Deprecated types.
+ */
typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED;
typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED;
typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED;
diff --git a/src/keylist.c b/src/keylist.c
index 36ee3ea..fcf574f 100644
--- a/src/keylist.c
+++ b/src/keylist.c
@@ -889,6 +889,7 @@ gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
gpgme_error_t err;
void *hook;
op_data_t opd;
+ int flags = 0;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_start", ctx,
"pattern=%s, secret_only=%i", pattern, secret_only);
@@ -913,8 +914,11 @@ gpgme_op_keylist_start (gpgme_ctx_t ctx, const char *pattern, int secret_only)
if (err)
return TRACE_ERR (err);
+ if (ctx->offline)
+ flags |= GPGME_ENGINE_FLAG_OFFLINE;
+
err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
- ctx->keylist_mode);
+ ctx->keylist_mode, flags);
return TRACE_ERR (err);
}
@@ -929,6 +933,7 @@ gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
gpgme_error_t err;
void *hook;
op_data_t opd;
+ int flags = 0;
TRACE_BEG2 (DEBUG_CTX, "gpgme_op_keylist_ext_start", ctx,
"secret_only=%i, reserved=0x%x", secret_only, reserved);
@@ -952,8 +957,12 @@ gpgme_op_keylist_ext_start (gpgme_ctx_t ctx, const char *pattern[],
if (err)
return TRACE_ERR (err);
+ if (ctx->offline)
+ flags |= GPGME_ENGINE_FLAG_OFFLINE;
+
err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
- reserved, ctx->keylist_mode);
+ reserved, ctx->keylist_mode,
+ flags);
return TRACE_ERR (err);
}
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index 39663c1..6687571 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -92,6 +92,12 @@ GPGME_1.1 {
gpgme_op_spawn_start;
gpgme_op_spawn;
+
+ gpgme_set_offline;
+ gpgme_get_offline;
+
+ gpgme_set_status_cb;
+ gpgme_get_status_cb;
};
diff --git a/src/op-support.c b/src/op-support.c
index 2bcb3a3..02940ef 100644
--- a/src/op-support.c
+++ b/src/op-support.c
@@ -337,3 +337,27 @@ _gpgme_parse_plaintext (char *args, char **filenamep)
}
return 0;
}
+
+
+/* Parse a FAILURE status line and return the error code. ARGS is
+ modified to contain the location part. */
+gpgme_error_t
+_gpgme_parse_failure (char *args)
+{
+ char *where, *which;
+
+ where = strchr (args, ' ');
+ if (!where)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+
+ return atoi (which);
+}
diff --git a/src/ops.h b/src/ops.h
index 782265e..3662d57 100644
--- a/src/ops.h
+++ b/src/ops.h
@@ -65,6 +65,10 @@ gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key);
FILENAMEP. */
gpgme_error_t _gpgme_parse_plaintext (char *args, char **filenamep);
+/* Parse a FAILURE status line and return the error code. ARGS is
+ modified to contain the location part. */
+gpgme_error_t _gpgme_parse_failure (char *args);
+
/* From verify.c. */
diff --git a/src/passphrase.c b/src/passphrase.c
index 00e9d99..c88e57d 100644
--- a/src/passphrase.c
+++ b/src/passphrase.c
@@ -41,6 +41,7 @@ typedef struct
char *uid_hint;
char *passphrase_info;
int bad_passphrase;
+ char *maxlen;
} *op_data_t;
@@ -53,6 +54,7 @@ release_op_data (void *hook)
free (opd->passphrase_info);
if (opd->uid_hint)
free (opd->uid_hint);
+ free (opd->maxlen);
}
@@ -73,6 +75,11 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
switch (code)
{
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ free (opd->maxlen);
+ if (!(opd->maxlen = strdup (args)))
+ return gpg_error_from_syserror ();
+ break;
case GPGME_STATUS_USERID_HINT:
if (opd->uid_hint)
free (opd->uid_hint);
@@ -109,6 +116,31 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
return gpg_error (GPG_ERR_BAD_PASSPHRASE);
break;
+ case GPGME_STATUS_ERROR:
+ /* We abuse this status handler to forward ERROR status codes to
+ the caller. This should better be done in a generic handler,
+ but for now this is sufficient. */
+ if (ctx->status_cb)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "ERROR", args);
+ if (err)
+ return err;
+ }
+ break;
+
+ case GPGME_STATUS_FAILURE:
+ /* We abuse this status handler to forward FAILURE status codes
+ to the caller. This should better be done in a generic
+ handler, but for now this is sufficient. */
+ if (ctx->status_cb)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
+ if (err)
+ return err;
+ }
+ break;
+
+
default:
/* Ignore all other codes. */
break;
@@ -141,9 +173,14 @@ _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
if (processed)
*processed = 1;
- err = ctx->passphrase_cb (ctx->passphrase_cb_value,
- opd->uid_hint, opd->passphrase_info,
- opd->bad_passphrase, fd);
+ if (ctx->status_cb && opd->maxlen)
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN",
+ opd->maxlen);
+
+ if (!err)
+ err = ctx->passphrase_cb (ctx->passphrase_cb_value,
+ opd->uid_hint, opd->passphrase_info,
+ opd->bad_passphrase, fd);
/* Reset bad passphrase flag, in case it is correct now. */
opd->bad_passphrase = 0;
diff --git a/src/passwd.c b/src/passwd.c
index e832026..ff30df0 100644
--- a/src/passwd.c
+++ b/src/passwd.c
@@ -30,6 +30,9 @@
typedef struct
{
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
int success_seen;
int error_seen;
} *op_data_t;
@@ -92,6 +95,10 @@ passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->success_seen = 1;
break;
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
/* In case the OpenPGP engine does not properly implement the
passwd command we won't get a success status back and thus we
@@ -102,6 +109,8 @@ passwd_status_handler (void *priv, gpgme_status_code_t code, char *args)
if (ctx->protocol == GPGME_PROTOCOL_OpenPGP
&& !opd->error_seen && !opd->success_seen)
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ else if (opd->failure_code)
+ err = opd->failure_code;
break;
default:
diff --git a/src/sign.c b/src/sign.c
index ffbde56..6c9fc03 100644
--- a/src/sign.c
+++ b/src/sign.c
@@ -39,6 +39,9 @@ typedef struct
{
struct _gpgme_op_sign_result result;
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
/* A pointer to the next pointer of the last invalid signer in
the list. This makes appending new invalid signers painless
while preserving the order. */
@@ -327,6 +330,10 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->last_signer_p = &(*opd->last_signer_p)->next;
break;
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
/* The UI server does not send information about the created
signature. This is irrelevant for this protocol and thus we
@@ -335,7 +342,12 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
else if (!opd->sig_created_seen
&& ctx->protocol != GPGME_PROTOCOL_UISERVER)
- err = gpg_error (GPG_ERR_GENERAL);
+ err = opd->failure_code? opd->failure_code:gpg_error (GPG_ERR_GENERAL);
+ break;
+
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ if (ctx->status_cb)
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
break;
default:
@@ -369,6 +381,7 @@ sign_init_result (gpgme_ctx_t ctx, int ignore_inv_recp)
opd = hook;
if (err)
return err;
+ opd->failure_code = 0;
opd->last_signer_p = &opd->result.invalid_signers;
opd->last_sig_p = &opd->result.signatures;
opd->ignore_inv_recp = !!ignore_inv_recp;
diff --git a/src/status-table.c b/src/status-table.c
index b936997..6d428d7 100644
--- a/src/status-table.c
+++ b/src/status-table.c
@@ -66,6 +66,7 @@ static struct status_table_s status_table[] =
{ "ERRSIG", GPGME_STATUS_ERRSIG },
{ "EXPKEYSIG", GPGME_STATUS_EXPKEYSIG },
{ "EXPSIG", GPGME_STATUS_EXPSIG },
+ { "FAILURE", GPGME_STATUS_FAILURE },
{ "FILE_DONE", GPGME_STATUS_FILE_DONE },
{ "FILE_ERROR", GPGME_STATUS_FILE_ERROR },
{ "FILE_START", GPGME_STATUS_FILE_START },
@@ -80,6 +81,7 @@ static struct status_table_s status_table[] =
{ "IMPORT_PROBLEM", GPGME_STATUS_IMPORT_PROBLEM },
{ "IMPORT_RES", GPGME_STATUS_IMPORT_RES },
{ "IMPORTED", GPGME_STATUS_IMPORTED },
+ { "INQUIRE_MAXLEN", GPGME_STATUS_INQUIRE_MAXLEN },
{ "INV_RECP", GPGME_STATUS_INV_RECP },
{ "INV_SGNR", GPGME_STATUS_INV_SGNR },
{ "KEY_CREATED", GPGME_STATUS_KEY_CREATED },
diff --git a/src/sys-util.h b/src/sys-util.h
index 7180fca..589634b 100644
--- a/src/sys-util.h
+++ b/src/sys-util.h
@@ -27,4 +27,8 @@ int _gpgme_set_default_gpgconf_name (const char *name);
char *_gpgme_get_gpg_path (void);
char *_gpgme_get_gpgconf_path (void);
+#ifdef HAVE_W32_SYSTEM
+const char *_gpgme_get_inst_dir (void);
+#endif
+
#endif /* SYS_UTIL_H */
diff --git a/src/verify.c b/src/verify.c
index 84487ee..75914e2 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -38,6 +38,9 @@ typedef struct
{
struct _gpgme_op_verify_result result;
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
gpgme_signature_t current_sig;
int did_prepare_new_sig;
int only_newsig_seen;
@@ -769,6 +772,10 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
error code if we are not ready to process this status. */
return parse_error (sig, args, !!sig );
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
case GPGME_STATUS_EOF:
if (sig && !opd->did_prepare_new_sig)
calc_sig_summary (sig);
@@ -795,6 +802,8 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->current_sig = NULL;
}
opd->only_newsig_seen = 0;
+ if (opd->failure_code)
+ return opd->failure_code;
break;
case GPGME_STATUS_PLAINTEXT:
diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in
index a4ab0af..7f19b30 100644
--- a/src/versioninfo.rc.in
+++ b/src/versioninfo.rc.in
@@ -39,7 +39,7 @@ BEGIN
VALUE "FileDescription", "GPGME - GnuPG Made Easy\0"
VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0"
VALUE "InternalName", "gpgme\0"
- VALUE "LegalCopyright", "Copyright © 2001-2013 g10 Code GmbH\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2015 g10 Code GmbH\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "gpgme.dll\0"
VALUE "PrivateBuild", "\0"
diff --git a/src/w32-util.c b/src/w32-util.c
index daf3bd2..9aba26f 100644
--- a/src/w32-util.c
+++ b/src/w32-util.c
@@ -398,40 +398,6 @@ find_program_in_dir (const char *dir, const char *name)
static char *
-find_program_in_inst_dir (const char *inst_dir, const char *name)
-{
- char *result;
- char *dir;
-
- /* If an installation directory has been passed, this overrides a
- location given by the registry. The idea here is that we prefer
- a program installed alongside with gpgme. We don't want the
- registry to override this to have a better isolation of an gpgme
- aware applications for other effects. Note that the "Install
- Directory" registry item has been used for ages in Gpg4win and
- earlier GnuPG windows installers. It is technically not anymore
- required. */
- if (inst_dir)
- {
- result = find_program_in_dir (inst_dir, name);
- if (result)
- return result;
- }
-
- dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
- "Software\\GNU\\GnuPG",
- "Install Directory");
- if (dir)
- {
- result = find_program_in_dir (dir, name);
- free (dir);
- return result;
- }
- return NULL;
-}
-
-
-static char *
find_program_at_standard_place (const char *name)
{
char path[MAX_PATH];
@@ -491,29 +457,50 @@ _gpgme_set_default_gpgconf_name (const char *name)
/* Return the full file name of the GPG binary. This function is used
- if gpgconf was not found and thus it can be assumed that gpg2 is
+ iff gpgconf was not found and thus it can be assumed that gpg2 is
not installed. This function is only called by get_gpgconf_item
and may not be called concurrently. */
char *
_gpgme_get_gpg_path (void)
{
- char *gpg;
- const char *inst_dir, *name;
+ char *gpg = NULL;
+ const char *name, *inst_dir;
+
+ name = default_gpg_name? get_basename (default_gpg_name) : "gpg.exe";
+ /* 1. Try to find gpg.exe in the installation directory of gpgme. */
inst_dir = _gpgme_get_inst_dir ();
- gpg = find_program_in_inst_dir
- (inst_dir,
- default_gpg_name? get_basename (default_gpg_name) : "gpg.exe");
+ if (inst_dir)
+ {
+ gpg = find_program_in_dir (inst_dir, name);
+ }
+
+ /* 2. Try to find gpg.exe using that ancient registry key. */
if (!gpg)
{
- name = (default_gpg_name? default_gpg_name
- /* */ : "GNU\\GnuPG\\gpg.exe");
+ char *dir;
+
+ dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+ "Software\\GNU\\GnuPG",
+ "Install Directory");
+ if (dir)
+ {
+ gpg = find_program_in_dir (dir, name);
+ free (dir);
+ }
+ }
+
+ /* 3. Try to find gpg.exe below CSIDL_PROGRAM_FILES. */
+ if (!gpg)
+ {
+ name = default_gpg_name? default_gpg_name : "GNU\\GnuPG\\gpg.exe";
gpg = find_program_at_standard_place (name);
- if (!gpg)
- _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found",
- name);
}
+ /* 4. Print a debug message if not found. */
+ if (!gpg)
+ _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpg_path: '%s' not found", name);
+
return gpg;
}
@@ -523,22 +510,52 @@ _gpgme_get_gpg_path (void)
char *
_gpgme_get_gpgconf_path (void)
{
- char *gpgconf;
+ char *gpgconf = NULL;
const char *inst_dir, *name;
+ name = default_gpgconf_name? get_basename(default_gpgconf_name):"gpgconf.exe";
+
+ /* 1. Try to find gpgconf.exe in the installation directory of gpgme. */
inst_dir = _gpgme_get_inst_dir ();
- gpgconf = find_program_in_inst_dir
- (inst_dir,
- default_gpgconf_name? get_basename (default_gpgconf_name) : "gpgconf.exe");
+ if (inst_dir)
+ {
+ gpgconf = find_program_in_dir (inst_dir, name);
+ }
+
+ /* 2. Try to find gpgconf.exe from GnuPG >= 2.1 below CSIDL_PROGRAM_FILES. */
+ if (!gpgconf)
+ {
+ const char *name2 = (default_gpgconf_name ? default_gpgconf_name
+ /**/ : "GnuPG\\bin\\gpgconf.exe");
+ gpgconf = find_program_at_standard_place (name2);
+ }
+
+ /* 3. Try to find gpgconf.exe using that ancient registry key. This
+ should eventually be removed. */
+ if (!gpgconf)
+ {
+ char *dir;
+
+ dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+ "Software\\GNU\\GnuPG",
+ "Install Directory");
+ if (dir)
+ {
+ gpgconf = find_program_in_dir (dir, name);
+ free (dir);
+ }
+ }
+
+ /* 4. Try to find gpgconf.exe from Gpg4win below CSIDL_PROGRAM_FILES. */
if (!gpgconf)
{
- name = (default_gpgconf_name? default_gpgconf_name
- /* */ : "GNU\\GnuPG\\gpgconf.exe");
- gpgconf = find_program_at_standard_place (name);
- if (!gpgconf)
- _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",
- name);
+ gpgconf = find_program_at_standard_place ("GNU\\GnuPG\\gpgconf.exe");
}
+
+ /* 5. Print a debug message if not found. */
+ if (!gpgconf)
+ _gpgme_debug (DEBUG_ENGINE, "_gpgme_get_gpgconf_path: '%s' not found",name);
+
return gpgconf;
}
@@ -552,10 +569,7 @@ _gpgme_get_w32spawn_path (void)
inst_dir = _gpgme_get_inst_dir ();
LOCK (get_path_lock);
if (!w32spawn_program)
- w32spawn_program = find_program_in_inst_dir (inst_dir,"gpgme-w32spawn.exe");
- if (!w32spawn_program)
- w32spawn_program
- = find_program_at_standard_place ("GNU\\GnuPG\\gpgme-w32spawn.exe");
+ w32spawn_program = find_program_in_dir (inst_dir, "gpgme-w32spawn.exe");
UNLOCK (get_path_lock);
return w32spawn_program;
}