core: New function gpgme_op_interact, deprecate gpgme_op_edit.

* src/gpgme.h.in (gpgme_interact_cb_t): New.
(GPGME_INTERACT_CARD): New.
(gpgme_op_interact_start, gpgme_op_interact): New.
* src/libgpgme.vers, src/gpgme.def: Add new functions.
* src/edit.c (op_data_t): Rename fnc to fnc_old and change users.  Add
fnc.
(edit_status_handler): Call old or new callback.
(command_handler): Ditto.
(interact_start): New.
(gpgme_op_interact_start, gpgme_op_interact_start): New.
* src/status-table.c (_gpgme_status_to_string): New.

* tests/gpg/t-edit.c (edit_fnc): Rename to interact_fnc and change
type of STATUS.  Use gpgme_io_writen.
(main): s/gpgme_op_edit/gpgme_op_interact/.
--

This change will eventually allow us to remove all those status codes
from gpgme.h.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-09-15 10:45:04 +02:00
parent d2b72d3cc1
commit ed1f2700a7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
9 changed files with 251 additions and 23 deletions

13
NEWS
View File

@ -9,6 +9,9 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
* New global flag "require-gnupg" to set a minimal gnupg version.
* New function gpgme_op_interact to replace the deprecated functions
gpgme_op_edit and gpgme_op_card_edit.
* Interface changes relative to the 1.6.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_pubkey_algo_string NEW.
@ -27,6 +30,15 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
gpgme_op_keysign NEW.
gpgme_op_tofu_policy_start NEW.
gpgme_op_tofu_policy NEW.
gpgme_op_interact_start NEW.
gpgme_op_interact NEW.
gpgme_interact_cb_t NEW.
gpgme_op_edit_start DEPRECATED.
gpgme_op_edit DEPRECATED.
gpgme_op_card_edit_start DEPRECATED.
gpgme_op_card_edit DEPRECATED.
gpgme_edit_cb_t DEPRECATED.
gpgme_status_code_t DEPRECATED.
gpgme_genkey_result_t EXTENDED: New fields pubkey and seckey.
gpgme_signature_t EXTENDED: New field key.
gpgme_key_t EXTENDED: New field fpr.
@ -56,6 +68,7 @@ Noteworthy changes in version 1.7.0 (unreleased) [C25/A14/R_]
GPGME_CREATE_FORCE NEW.
GPGME_KEYSIGN_LOCAL NEW.
GPGME_KEYSIGN_LFSEP NEW.
GPGME_INTERACT_CARD NEW.
Noteworthy changes in version 1.6.0 (2015-08-26) [C25/A14/R0]

View File

@ -15,7 +15,7 @@
@copying
Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2010, 2012, 2013, 2014 g10 Code GmbH.
2008, 2010, 2012, 2013, 2014, 2016 g10 Code GmbH.
@quotation
Permission is granted to copy, distribute and/or modify this document
@ -71,7 +71,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of
@center for version @value{VERSION}
@page
@vskip 0pt plus 1filll
Published by g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
Published by g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
@insertcopying
@end titlepage
@ -4301,7 +4301,79 @@ could not be started.
@subsection Advanced Key Editing
@cindex key, edit
@deftp {Data type} {gpgme_error_t (*gpgme_edit_cb_t) (@w{void *@var{handle}}, @w{gpgme_status_code_t @var{status}}, @w{const char *@var{args}}, @w{int @var{fd}})}
@deftp {Data type} {gpgme_error_t (*gpgme_interact_cb_t) @
(@w{void *@var{handle}}, @
@w{const char *@var{status}}, @
@w{const char *@var{args}}, @
@w{int @var{fd}})}
@tindex gpgme_interact_cb_t
The @code{gpgme_interact_cb_t} type is the type of functions which
@acronym{GPGME} calls if it a key interact operation is on-going. The
status keyword @var{status} and the argument line @var{args} are passed
through by @acronym{GPGME} from the crypto engine. The file
descriptor @var{fd} is -1 for normal status messages. If @var{status}
indicates a command rather than a status message, the response to the
command should be written to @var{fd}. The @var{handle} is provided
by the user at start of operation.
The function should return @code{GPG_ERR_FALSE} if it did not handle
the status code, @code{0} for success, or any other error value.
@end deftp
@deftypefun gpgme_error_t gpgme_op_interact (@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_key_t @var{key}}, @
@w{unsigned int @var{flags}}, @
@w{gpgme_interact_cb_t @var{fnc}}, @
@w{void *@var{handle}}, @
@w{gpgme_data_t @var{out}})
The function @code{gpgme_op_interact} processes the key @var{KEY}
interactively, using the interact callback function @var{FNC} with the
handle @var{HANDLE}. The callback is invoked for every status and
command request from the crypto engine. The output of the crypto
engine is written to the data object @var{out}.
Note that the protocol between the callback function and the crypto
engine is specific to the crypto engine and no further support in
implementing this protocol correctly is provided by @acronym{GPGME}.
@var{flags} modifies the behaviour of the function; the only defined
bit value is:
@table @code
@item GPGME_INTERACT_CARD
This is used for smartcard based keys and uses gpgs
@code{--card-edit} command.
@end table
The function returns @code{0} if the edit operation completes
successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} or @var{key} is
not a valid pointer, and any error returned by the crypto engine or
the edit callback handler.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_interact_start (@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_key_t @var{key}}, @
@w{unsigned int @var{flags}}, @
@w{gpgme_interact_cb_t @var{fnc}}, @
@w{void *@var{handle}}, @
@w{gpgme_data_t @var{out}})
The function @code{gpgme_op_interact_start} initiates a
@code{gpgme_op_interact} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
The function returns @code{0} if the operation was started
successfully, and @code{GPG_ERR_INV_VALUE} if @var{ctx} or @var{key}
is not a valid pointer.
@end deftypefun
@deftp {Data type} {gpgme_error_t (*gpgme_edit_cb_t) @
(@w{void *@var{handle}}, @
@w{gpgme_status_code_t @var{status}}, @
@w{const char *@var{args}}, @
@w{int @var{fd}})}
@tindex gpgme_edit_cb_t
The @code{gpgme_edit_cb_t} type is the type of functions which
@acronym{GPGME} calls if it a key edit operation is on-going. The
@ -4317,6 +4389,9 @@ the status code, @code{0} for success, or any other error value.
@end deftp
@deftypefun gpgme_error_t gpgme_op_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
Note: This function is deprecated, please use
@code{gpgme_op_interact} instead.
The function @code{gpgme_op_edit} processes the key @var{KEY}
interactively, using the edit callback function @var{FNC} with the
handle @var{HANDLE}. The callback is invoked for every status and
@ -4334,6 +4409,9 @@ by the crypto engine or the edit callback handler.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
Note: This function is deprecated, please use
@code{gpgme_op_interact_start} instead.
The function @code{gpgme_op_edit_start} initiates a
@code{gpgme_op_edit} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
@ -4345,11 +4423,17 @@ operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
@deftypefun gpgme_error_t gpgme_op_card_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
Note: This function is deprecated, please use @code{gpgme_op_interact}
with the flag @code{GPGME_INTERACT_CARD} instead.
The function @code{gpgme_op_card_edit} is analogous to
@code{gpgme_op_edit}, but should be used to process the smart card corresponding to the key @var{key}.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_card_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
Note: This function is deprecated, please use @code{gpgme_op_interact_start}
with the flag @code{GPGME_INTERACT_CARD} instead.
The function @code{gpgme_op_card_edit_start} initiates a
@code{gpgme_op_card_edit} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.

View File

@ -27,12 +27,15 @@
#include "debug.h"
#include "context.h"
#include "ops.h"
#include "util.h"
typedef struct
{
/* The user callback function and its hook value. */
gpgme_edit_cb_t fnc;
gpgme_interact_cb_t fnc;
gpgme_edit_cb_t fnc_old;
void *fnc_value;
} *op_data_t;
@ -58,7 +61,11 @@ edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
if (err)
return err;
return (*opd->fnc) (opd->fnc_value, status, args, -1);
if (opd->fnc_old)
return (*opd->fnc_old) (opd->fnc_value, status, args, -1);
return (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
args, -1);
}
@ -90,7 +97,12 @@ command_handler (void *priv, gpgme_status_code_t status, const char *args,
if (err)
return err;
err = (*opd->fnc) (opd->fnc_value, status, args, fd);
if (opd->fnc_old)
err = (*opd->fnc_old) (opd->fnc_value, status, args, fd);
else
err = (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
args, fd);
if (gpg_err_code (err) == GPG_ERR_FALSE)
err = 0;
else
@ -102,6 +114,87 @@ command_handler (void *priv, gpgme_status_code_t status, const char *args,
}
static gpgme_error_t
interact_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
unsigned int flags,
gpgme_interact_cb_t fnc, void *fnc_value, gpgme_data_t out)
{
gpgme_error_t err;
void *hook;
op_data_t opd;
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
if (!fnc || !out)
return gpg_error (GPG_ERR_INV_VALUE);
err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
opd = hook;
if (err)
return err;
opd->fnc = fnc;
opd->fnc_old = NULL;
opd->fnc_value = fnc_value;
err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
ctx, out);
if (err)
return err;
_gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
return _gpgme_engine_op_edit (ctx->engine,
(flags & GPGME_INTERACT_CARD)? 1: 0,
key, out, ctx);
}
gpgme_error_t
gpgme_op_interact_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
gpgme_interact_cb_t fnc, void *fnc_value,
gpgme_data_t out)
{
gpgme_error_t err;
TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact_start", ctx,
"key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
key, flags,fnc, fnc_value, out);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = interact_start (ctx, 0, key, flags, fnc, fnc_value, out);
return err;
}
gpgme_error_t
gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
gpgme_interact_cb_t fnc, void *fnc_value,
gpgme_data_t out)
{
gpgme_error_t err;
TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact", ctx,
"key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
key, flags,fnc, fnc_value, out);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = interact_start (ctx, 1, key, flags, fnc, fnc_value, out);
if (!err)
err = _gpgme_wait_one (ctx);
return err;
}
/* The deprectated interface. */
static gpgme_error_t
edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
@ -122,7 +215,8 @@ edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
if (err)
return err;
opd->fnc = fnc;
opd->fnc = NULL;
opd->fnc_old = fnc;
opd->fnc_value = fnc_value;
err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,

View File

@ -241,6 +241,8 @@ EXPORTS
gpgme_op_keysign @181
gpgme_op_tofu_policy_start @182
gpgme_op_tofu_policy @183
gpgme_op_interact_start @184
gpgme_op_interact @185
; END

View File

@ -444,7 +444,9 @@ typedef unsigned int gpgme_export_mode_t;
#define GPGME_AUDITLOG_HTML 1
#define GPGME_AUDITLOG_WITH_HELP 128
/* The possible stati for the edit operation. */
/* The possible stati for gpgme_op_edit. The use of that function and
* these status codes are deprecated in favor of gpgme_op_interact. */
typedef enum
{
GPGME_STATUS_EOF = 0,
@ -967,8 +969,13 @@ typedef void (*gpgme_progress_cb_t) (void *opaque, const char *what,
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_interact_cb_t) (void *opaque,
const char *keyword,
const char *args, int fd);
/* The callback type used by the deprecated functions gpgme_op_card
* and gpgme_of_card_edit. */
typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
gpgme_status_code_t status,
const char *args, int fd);
@ -1217,7 +1224,7 @@ void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
/* Wrappers around the internal I/O functions for use with
gpgme_passphrase_cb_t and gpgme_edit_cb_t. */
gpgme_passphrase_cb_t and gpgme_interact_cb_t. */
@API__SSIZE_T@ gpgme_io_read (int fd, void *buffer, size_t count);
@API__SSIZE_T@ gpgme_io_write (int fd, const void *buffer, size_t count);
int gpgme_io_writen (int fd, const void *buffer, size_t count);
@ -1949,23 +1956,36 @@ gpgme_error_t gpgme_op_keysign (gpgme_ctx_t ctx,
* Key edit interface
*/
/* Edit the key KEY. Send status and command requests to FNC and
/* Flags to select the mode of the interact. */
#define GPGME_INTERACT_CARD (1 << 0) /* Use --card-edit mode. */
/* Edit the KEY. Send status and command requests to FNC and
output of edit commands to OUT. */
gpgme_error_t gpgme_op_interact_start (gpgme_ctx_t ctx,
gpgme_key_t key,
unsigned int flags,
gpgme_interact_cb_t fnc,
void *fnc_value,
gpgme_data_t out);
gpgme_error_t gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key,
unsigned int flags,
gpgme_interact_cb_t fnc,
void *fnc_value,
gpgme_data_t out);
gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
gpgme_data_t out);
gpgme_data_t out) _GPGME_DEPRECATED;
gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
gpgme_data_t out);
/* Edit the card for the key KEY. Send status and command requests to
FNC and output of edit commands to OUT. */
gpgme_data_t out) _GPGME_DEPRECATED;
gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
gpgme_data_t out);
gpgme_data_t out) _GPGME_DEPRECATED;
gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
gpgme_data_t out);
gpgme_data_t out) _GPGME_DEPRECATED;
/* Set the Tofu policy of KEY to POLCIY. */

View File

@ -115,6 +115,8 @@ GPGME_1.1 {
gpgme_op_keysign;
gpgme_op_tofu_policy_start;
gpgme_op_tofu_policy;
gpgme_op_interact_start;
gpgme_op_interact;
};

View File

@ -169,3 +169,15 @@ _gpgme_parse_status (const char *name)
sizeof t, status_cmp);
return r ? r->code : -1;
}
const char *
_gpgme_status_to_string (gpgme_status_code_t code)
{
int i;
for (i=0; i < DIM(status_table); i++)
if (status_table[i].code == code)
return status_table[i].name;
return "status_code_lost";
}

View File

@ -185,6 +185,7 @@ gpgme_error_t _gpgme_getenv (const char *name, char **value);
/* Convert a status string to a status code. */
void _gpgme_status_init (void);
gpgme_status_code_t _gpgme_parse_status (const char *name);
const char *_gpgme_status_to_string (gpgme_status_code_t code);
#ifdef HAVE_W32_SYSTEM

View File

@ -55,7 +55,7 @@ flush_data (gpgme_data_t dh)
gpgme_error_t
edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd)
interact_fnc (void *opaque, const char *status, const char *args, int fd)
{
const char *result = NULL;
gpgme_data_t out = (gpgme_data_t) opaque;
@ -63,7 +63,7 @@ edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd)
fputs ("[-- Response --]\n", stdout);
flush_data (out);
fprintf (stdout, "[-- Code: %i, %s --]\n", status, args);
fprintf (stdout, "[-- Code: %s, %s --]\n", status, args);
if (fd >= 0)
{
@ -103,8 +103,8 @@ edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd)
if (result)
{
gpgme_io_write (fd, result, strlen (result));
gpgme_io_write (fd, "\n", 1);
gpgme_io_writen (fd, result, strlen (result));
gpgme_io_writen (fd, "\n", 1);
}
return 0;
}
@ -141,7 +141,7 @@ main (int argc, char **argv)
err = gpgme_op_keylist_end (ctx);
fail_if_err (err);
err = gpgme_op_edit (ctx, key, edit_fnc, out, out);
err = gpgme_op_interact (ctx, key, 0, interact_fnc, out, out);
fail_if_err (err);
fputs ("[-- Last response --]\n", stdout);