Merge branch 'master' into ben-minor-fixes

This commit is contained in:
Ben McGinnes 2016-08-17 13:14:44 +10:00
commit 14402ece2f
10 changed files with 103 additions and 20 deletions

2
NEWS
View File

@ -7,6 +7,8 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
* Bindings for Python 3 are now included. * Bindings for Python 3 are now included.
* New global flag "require-gnupg" to set a minimal gnupg version.
* Interface changes relative to the 1.6.0 release: * Interface changes relative to the 1.6.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_pubkey_algo_string NEW. gpgme_pubkey_algo_string NEW.

View File

@ -678,12 +678,12 @@ as early as possible --- even before @code{gpgme_check_version}. The
features are identified by the following values for @var{name}: features are identified by the following values for @var{name}:
@table @code @table @code
@item "debug" @item debug
To enable debugging use the string ``debug'' for @var{name} and To enable debugging use the string ``debug'' for @var{name} and
@var{value} identical to the value used with the environment variable @var{value} identical to the value used with the environment variable
@code{GPGME_DEBUG}. @code{GPGME_DEBUG}.
@item "disable-gpgconf" @item disable-gpgconf
Using this feature with any @var{value} disables the detection of the Using this feature with any @var{value} disables the detection of the
gpgconf program and thus forces GPGME to fallback into the simple gpgconf program and thus forces GPGME to fallback into the simple
OpenPGP only mode. It may be used to force the use of GnuPG-1 on OpenPGP only mode. It may be used to force the use of GnuPG-1 on
@ -691,8 +691,8 @@ systems which have both GPG versions installed. Note that in general
the use of @code{gpgme_set_engine_info} is a better way to select a the use of @code{gpgme_set_engine_info} is a better way to select a
specific engine version. specific engine version.
@item "gpgconf-name" @item gpgconf-name
@itemx "gpg-name" @itemx gpg-name
Set the name of the gpgconf respective gpg binary. The defaults are Set the name of the gpgconf respective gpg binary. The defaults are
@code{GNU/GnuPG/gpgconf} and @code{GNU/GnuPG/gpg}. Under Unix the @code{GNU/GnuPG/gpgconf} and @code{GNU/GnuPG/gpg}. Under Unix the
leading directory part is ignored. Under Windows the leading leading directory part is ignored. Under Windows the leading
@ -700,7 +700,13 @@ directory part is used as the default installation directory; the
@code{.exe} suffix is added by GPGME. Use forward slashed even under @code{.exe} suffix is added by GPGME. Use forward slashed even under
Windows. Windows.
@item "w32-inst-dir" @item require-gnupg
Set the mimimum version of the required GnuPG engine. If that version
is not met, GPGME fails early instead of trying to use the existant
version. The given version must be a string with major, minor, and
micro number. Example: "2.1.0".
@item w32-inst-dir
On Windows GPGME needs to know its installation directory to find its On Windows GPGME needs to know its installation directory to find its
spawn helper. This is in general no problem because a DLL has this spawn helper. This is in general no problem because a DLL has this
information. Some applications however link statically to GPGME and information. Some applications however link statically to GPGME and

View File

@ -131,14 +131,14 @@ llass_get_home_dir (void)
static char * static char *
llass_get_version (const char *file_name) llass_get_version (const char *file_name)
{ {
return strdup ("1.0.0"); return NULL;
} }
static const char * static const char *
llass_get_req_version (void) llass_get_req_version (void)
{ {
return "1.0.0"; return NULL;
} }

View File

@ -312,14 +312,14 @@ static char *
engspawn_get_version (const char *file_name) engspawn_get_version (const char *file_name)
{ {
(void)file_name; (void)file_name;
return strdup ("1.0.0"); return NULL;
} }
static const char * static const char *
engspawn_get_req_version (void) engspawn_get_req_version (void)
{ {
return "1.0.0"; return NULL;
} }

View File

@ -123,14 +123,15 @@ static void uiserver_io_event (void *engine,
static char * static char *
uiserver_get_version (const char *file_name) uiserver_get_version (const char *file_name)
{ {
return strdup ("1.0.0"); (void)file_name;
return NULL;
} }
static const char * static const char *
uiserver_get_req_version (void) uiserver_get_req_version (void)
{ {
return "1.0.0"; return NULL;
} }

View File

@ -63,6 +63,10 @@ static struct engine_ops *engine_ops[] =
static gpgme_engine_info_t engine_info; static gpgme_engine_info_t engine_info;
DEFINE_STATIC_LOCK (engine_info_lock); DEFINE_STATIC_LOCK (engine_info_lock);
/* If non-NULL, the minimal version required for all engines. */
static char *engine_minimal_version;
/* Get the file name of the engine for PROTOCOL. */ /* Get the file name of the engine for PROTOCOL. */
static const char * static const char *
@ -93,7 +97,8 @@ engine_get_home_dir (gpgme_protocol_t proto)
/* Get a malloced string containing the version number of the engine /* Get a malloced string containing the version number of the engine
for PROTOCOL. */ * for PROTOCOL. If this function returns NULL for a valid protocol,
* it should be assumed that the engine is a pseudo engine. */
static char * static char *
engine_get_version (gpgme_protocol_t proto, const char *file_name) engine_get_version (gpgme_protocol_t proto, const char *file_name)
{ {
@ -107,7 +112,8 @@ engine_get_version (gpgme_protocol_t proto, const char *file_name)
} }
/* Get the required version number of the engine for PROTOCOL. */ /* Get the required version number of the engine for PROTOCOL. This
* may be NULL. */
static const char * static const char *
engine_get_req_version (gpgme_protocol_t proto) engine_get_req_version (gpgme_protocol_t proto)
{ {
@ -164,8 +170,8 @@ _gpgme_engine_info_release (gpgme_engine_info_t info)
{ {
gpgme_engine_info_t next_info = info->next; gpgme_engine_info_t next_info = info->next;
assert (info->file_name); if (info->file_name)
free (info->file_name); free (info->file_name);
if (info->home_dir) if (info->home_dir)
free (info->home_dir); free (info->home_dir);
if (info->version) if (info->version)
@ -176,6 +182,26 @@ _gpgme_engine_info_release (gpgme_engine_info_t info)
} }
/* This is an internal function to set a mimimal required version.
* This function must only be called by gpgme_set_global_flag.
* Returns 0 on success. */
int
_gpgme_set_engine_minimal_version (const char *value)
{
free (engine_minimal_version);
if (value)
{
engine_minimal_version = strdup (value);
return !engine_minimal_version;
}
else
{
engine_minimal_version = NULL;
return 0;
}
}
/* Get the information about the configured and installed engines. A /* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. The is returned in *INFO. If an error occurs, it is returned. The
@ -203,6 +229,7 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
{ {
const char *ofile_name = engine_get_file_name (proto_list[proto]); const char *ofile_name = engine_get_file_name (proto_list[proto]);
const char *ohome_dir = engine_get_home_dir (proto_list[proto]); const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
char *version = engine_get_version (proto_list[proto], NULL);
char *file_name; char *file_name;
char *home_dir; char *home_dir;
@ -222,10 +249,29 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
else else
home_dir = NULL; home_dir = NULL;
*lastp = malloc (sizeof (*engine_info)); *lastp = calloc (1, sizeof (*engine_info));
if (!*lastp && !err) if (!*lastp && !err)
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
/* Check against the optional minimal engine version. */
if (!err && version && engine_minimal_version
&& !_gpgme_compare_versions (version, engine_minimal_version))
{
#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
err = gpg_error (GPG_ERR_NO_ENGINE);
#else
err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
#endif
}
/* Now set the dummy version for pseudo engines. */
if (!err && !version)
{
version = strdup ("1.0.0");
if (!version)
err = gpg_error_from_syserror ();
}
if (err) if (err)
{ {
_gpgme_engine_info_release (engine_info); _gpgme_engine_info_release (engine_info);
@ -235,6 +281,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
free (file_name); free (file_name);
if (home_dir) if (home_dir)
free (home_dir); free (home_dir);
if (version)
free (version);
UNLOCK (engine_info_lock); UNLOCK (engine_info_lock);
return err; return err;
@ -243,8 +291,10 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
(*lastp)->protocol = proto_list[proto]; (*lastp)->protocol = proto_list[proto];
(*lastp)->file_name = file_name; (*lastp)->file_name = file_name;
(*lastp)->home_dir = home_dir; (*lastp)->home_dir = home_dir;
(*lastp)->version = engine_get_version (proto_list[proto], NULL); (*lastp)->version = version;
(*lastp)->req_version = engine_get_req_version (proto_list[proto]); (*lastp)->req_version = engine_get_req_version (proto_list[proto]);
if (!(*lastp)->req_version)
(*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
(*lastp)->next = NULL; (*lastp)->next = NULL;
lastp = &(*lastp)->next; lastp = &(*lastp)->next;
} }
@ -353,6 +403,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
{ {
char *new_file_name; char *new_file_name;
char *new_home_dir; char *new_home_dir;
char *new_version;
/* FIXME: Use some PROTO_MAX definition. */ /* FIXME: Use some PROTO_MAX definition. */
if (proto > DIM (engine_ops)) if (proto > DIM (engine_ops))
@ -401,6 +452,17 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
new_home_dir = NULL; new_home_dir = NULL;
} }
new_version = engine_get_version (proto, new_file_name);
if (!new_version)
{
new_version = strdup ("1.0.0"); /* Fake one for dummy entries. */
if (!new_version)
{
free (new_file_name);
free (new_home_dir);
}
}
/* Remove the old members. */ /* Remove the old members. */
assert (info->file_name); assert (info->file_name);
free (info->file_name); free (info->file_name);
@ -412,7 +474,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
/* Install the new members. */ /* Install the new members. */
info->file_name = new_file_name; info->file_name = new_file_name;
info->home_dir = new_home_dir; info->home_dir = new_home_dir;
info->version = engine_get_version (proto, new_file_name); info->version = new_version;
return 0; return 0;
} }

View File

@ -38,6 +38,8 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv,
typedef gpgme_error_t (*engine_assuan_result_cb_t) (void *priv, typedef gpgme_error_t (*engine_assuan_result_cb_t) (void *priv,
gpgme_error_t result); gpgme_error_t result);
/* Helper for gpgme_set_global_flag. */
int _gpgme_set_engine_minimal_version (const char *value);
/* Get a deep copy of the engine info and return it in INFO. */ /* Get a deep copy of the engine info and return it in INFO. */
gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info); gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);

View File

@ -71,6 +71,8 @@ gpgme_set_global_flag (const char *name, const char *value)
_gpgme_dirinfo_disable_gpgconf (); _gpgme_dirinfo_disable_gpgconf ();
return 0; return 0;
} }
else if (!strcmp (name, "require-gnupg"))
return _gpgme_set_engine_minimal_version (value);
else if (!strcmp (name, "gpgconf-name")) else if (!strcmp (name, "gpgconf-name"))
return _gpgme_set_default_gpgconf_name (value); return _gpgme_set_default_gpgconf_name (value);
else if (!strcmp (name, "gpg-name")) else if (!strcmp (name, "gpg-name"))

View File

@ -124,7 +124,7 @@ parse_version_number (const char *str, int *number)
/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for /* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
example, 9.3.2) and return the components in MAJOR, MINOR and MICRO example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
as integers. The function returns the tail of the string that as integers. The function returns the tail of the string that
follows the version number. This might be te empty string if there follows the version number. This might be the empty string if there
is nothing following the version number, or a patchlevel. The is nothing following the version number, or a patchlevel. The
function returns NULL if the version string is not valid. */ function returns NULL if the version string is not valid. */
static const char * static const char *

View File

@ -54,6 +54,7 @@ show_usage (int ex)
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n" " --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
" --import import all keys\n" " --import import all keys\n"
" --offline use offline mode\n" " --offline use offline mode\n"
" --require-gnupg required at least the given GnuPG version\n"
, stderr); , stderr);
exit (ex); exit (ex);
} }
@ -149,9 +150,16 @@ main (int argc, char **argv)
offline = 1; offline = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--require-gnupg"))
{
argc--; argv++;
if (!argc)
show_usage (1);
gpgme_set_global_flag ("require-gnupg", *argv);
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
} }
if (argc > 1) if (argc > 1)