From da2cd9aa44fbe2ecdcf0c93d97e6cc5133ea6694 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Wed, 27 Feb 2002 00:59:31 +0000 Subject: [PATCH] doc/ 2002-02-27 Marcus Brinkmann * gpgme.texi (Listing Keys): Document gpgme_op_keylist_ext_start. gpgme/ 2002-02-27 Marcus Brinkmann * rungpg.h (_gpgme_gpg_op_keylist_ext): New prototype. * rungpg.c (_gpgme_gpg_op_keylist_ext): New function. * engine-gpgsm.h (_gpgme_gpgsm_op_keylist_ext): New prototype. * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): New function. * engine.h (_gpgme_engine_op_keylist_ext): New prototype. * engine.c (_gpgme_engine_op_keylist_ext): New function. * keylist.c (gpgme_op_keylist_ext_start): New function. --- NEWS | 15 +++++--- TODO | 10 ++--- doc/ChangeLog | 4 ++ doc/gpgme.texi | 25 ++++++++++++ gpgme/ChangeLog | 10 +++++ gpgme/engine-gpgsm.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ gpgme/engine-gpgsm.h | 4 ++ gpgme/engine.c | 28 +++++++++++++- gpgme/engine.h | 5 +++ gpgme/keylist.c | 67 ++++++++++++++++++++++++++++++++ gpgme/rungpg.c | 33 ++++++++++++++++ gpgme/rungpg.h | 3 ++ 12 files changed, 281 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 8d7a2ba..682f262 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,11 @@ + * gpgme_op_encrypt does now fail with GPGME_Invalid_Recipients if + some recipients have been invalid, whereas earlier versions + succeeded in this case. The plaintext is still encrypted for all valid + recipients, so the application might take this error as a hint that + the ciphertext is not usable for all requested recipients. + Information about invalid recipients is available with gpgme_get_op_info. + * New interfaces gpgme_set_include_certs and gpgme_get_include_certs to set and get the number of certifications to include in S/MIME signed messages. @@ -6,12 +13,7 @@ * New interfaces gpgme_op_encrypt_sign and gpgme_op_encrypt_sign_start to encrypt and sign a message in a combined operation. - * gpgme_op_encrypt does now fail with GPGME_Invalid_Recipients if - some recipients have been invalid, whereas earlier versions - succeeded in this case. The plaintext is still encrypted for all valid - recipients, so the application might take this error as a hint that - the ciphertext is not usable for all requested recipients. - Information about invalid recipients is available with gpgme_get_op_info. + * New interface gpgme_op_keylist_ext_start to search for multiple patterns. * Interface changes relative to the 0.3.3 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -20,6 +22,7 @@ gpgme_set_include_certs NEW gpgme_get_include_certs NEW gpgme_op_encrypt_sign NEW gpgme_op_encrypt_sign_start NEW +gpgme_op_keylist_ext_start NEW ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Noteworthy changes in version 0.3.3 (2002-02-12) diff --git a/TODO b/TODO index 2cf08bc..8970c39 100644 --- a/TODO +++ b/TODO @@ -44,10 +44,10 @@ Hey Emacs, this is -*- outline -*- mode! get GPGME_No_Passphrase." Bug reported by Stephane Corthesy. * Tests - Write a fake gpg-agent so that we can supply known passphrases to - gpgsm and setup the configuration files to use the agent. Without - this we are testing a currently running gpg-agent which is not a - clever idea. +** Write a fake gpg-agent so that we can supply known passphrases to + gpgsm and setup the configuration files to use the agent. Without + this we are testing a currently running gpg-agent which is not a + clever idea. ** t-data *** Test gpgme_data_release_and_get_mem. *** Test gpgme_data_rewind for invalid types. @@ -55,8 +55,6 @@ Hey Emacs, this is -*- outline -*- mode! * Build suite ** Make sure everything is cleaned correctly (esp. test area). -** There is a spurious 4/10 tests failed in some conditions. - Rebuilding from scratch works around that. * Architecture support ** Implement posix-sema.c diff --git a/doc/ChangeLog b/doc/ChangeLog index 8ae8ae2..56be628 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2002-02-27 Marcus Brinkmann + + * gpgme.texi (Listing Keys): Document gpgme_op_keylist_ext_start. + 2002-02-27 Marcus Brinkmann * gpgme.texi (Encrypting a Plaintext): Document diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 5c2a084..a012abb 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -1261,6 +1261,31 @@ valid pointer, and passes through any errors that are reported by the crypto engine support routines. @end deftypefun +@deftypefun GpgmeError gpgme_op_keylist_ext_start (@w{GpgmeCtx @var{ctx}}, @w{const char *@var{pattern}[]}, @w{int @var{secret_only}}, @w{int @var{reserved}}) +The function @code{gpgme_op_keylist_ext_start} initiates an extended +key listing operation inside the context @var{ctx}. It sets +everything up so that subsequent invocations of +@code{gpgme_op_keylist_next} return the keys in the list. + +If @var{pattern} or @var{*pattern} is @code{NULL}, all available keys +are returned. Otherwise, @var{pattern} is a @code{NULL} terminated +array of strings that are used to limit the list to all keys matching +at least one of the patterns verbatim. + +If @var{secret_only} is not @code{0}, the list is restricted to secret +keys only. + +The value of @var{reserved} must be @code{0}. + +The context will be busy until either all keys are received (and +@code{gpgme_op_keylist_next} returns @code{GPGME_EOF}), or +@code{gpgme_op_keylist_end} is called to finish the operation. + +The function returns @code{GPGME_Invalid_Value} if @var{ctx} is not a +valid pointer, and passes through any errors that are reported by the +crypto engine support routines. +@end deftypefun + @deftypefun GpgmeError gpgme_op_keylist_next (@w{GpgmeCtx @var{ctx}}, @w{GpgmeKey *@var{r_key}}) The function @code{gpgme_op_keylist_next} returns the next key in the list created by a previous @code{gpgme_op_keylist_start} operation in diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 55358f7..58f09c6 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,13 @@ +2002-02-27 Marcus Brinkmann + + * rungpg.h (_gpgme_gpg_op_keylist_ext): New prototype. + * rungpg.c (_gpgme_gpg_op_keylist_ext): New function. + * engine-gpgsm.h (_gpgme_gpgsm_op_keylist_ext): New prototype. + * engine-gpgsm.c (_gpgme_gpgsm_op_keylist_ext): New function. + * engine.h (_gpgme_engine_op_keylist_ext): New prototype. + * engine.c (_gpgme_engine_op_keylist_ext): New function. + * keylist.c (gpgme_op_keylist_ext_start): New function. + 2002-02-27 Marcus Brinkmann * gpgme.h: Add new error code GPGME_Invalid_Recipient. diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index a88d638..32ee3a0 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -601,6 +601,97 @@ _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, } +GpgmeError +_gpgme_gpgsm_op_keylist_ext (GpgsmObject gpgsm, const char *pattern[], + int secret_only, int reserved, int keylist_mode) +{ + char *line; + /* Length is "LISTSECRETKEYS " + p + '\0'. */ + int length = 15 + 1; + char *linep; + + if (reserved) + return mk_error (Invalid_Value); + + if (pattern && *pattern) + { + const char **pat = pattern; + + while (*pat) + { + const char *patlet = *pat; + + while (*patlet) + { + length++; + if (*patlet == '%' || *patlet == ' ' || *patlet == '+') + length += 2; + patlet++; + } + pat++; + /* This will allocate one byte more than necessary. */ + length++; + } + } + line = xtrymalloc (length); + if (!line) + return mk_error (Out_Of_Core); + if (secret_only) + { + strcpy (line, "LISTSECRETKEYS "); + linep = &line[15]; + } + else + { + strcpy (line, "LISTKEYS "); + linep = &line[9]; + } + + if (pattern && *pattern) + { + while (*pattern) + { + const char *patlet = *pattern; + + while (*patlet) + { + switch (*patlet) + { + case '%': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '5'; + break; + case ' ': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = '0'; + break; + case '+': + *(linep++) = '%'; + *(linep++) = '2'; + *(linep++) = 'B'; + break; + default: + *(linep++) = *patlet; + break; + } + patlet++; + } + pattern++; + } + } + *linep = '\0'; + + _gpgme_io_close (gpgsm->input_fd); + _gpgme_io_close (gpgsm->output_fd); + _gpgme_io_close (gpgsm->message_fd); + + gpgsm->command = line; + return 0; +} + + GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, diff --git a/gpgme/engine-gpgsm.h b/gpgme/engine-gpgsm.h index b629ed6..ecd80b4 100644 --- a/gpgme/engine-gpgsm.h +++ b/gpgme/engine-gpgsm.h @@ -50,6 +50,10 @@ GpgmeError _gpgme_gpgsm_op_genkey (GpgsmObject gpgsm, GpgmeData help_data, GpgmeError _gpgme_gpgsm_op_import (GpgsmObject gpgsm, GpgmeData keydata); GpgmeError _gpgme_gpgsm_op_keylist (GpgsmObject gpgsm, const char *pattern, int secret_only, int keylist_mode); +GpgmeError _gpgme_gpgsm_op_keylist_ext (GpgsmObject gpgsm, + const char *pattern[], + int secret_only, int reserved, + int keylist_mode); GpgmeError _gpgme_gpgsm_op_sign (GpgsmObject gpgsm, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, diff --git a/gpgme/engine.c b/gpgme/engine.c index 8841b20..c1dd630 100644 --- a/gpgme/engine.c +++ b/gpgme/engine.c @@ -438,9 +438,10 @@ _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata) return 0; } + GpgmeError -_gpgme_engine_op_keylist (EngineObject engine, const char *pattern, int secret_only, - int keylist_mode) +_gpgme_engine_op_keylist (EngineObject engine, const char *pattern, + int secret_only, int keylist_mode) { if (!engine) return mk_error (Invalid_Value); @@ -459,6 +460,29 @@ _gpgme_engine_op_keylist (EngineObject engine, const char *pattern, int secret_o return 0; } + +GpgmeError +_gpgme_engine_op_keylist_ext (EngineObject engine, const char *pattern[], + int secret_only, int reserved, int keylist_mode) +{ + if (!engine) + return mk_error (Invalid_Value); + + switch (engine->protocol) + { + case GPGME_PROTOCOL_OpenPGP: + return _gpgme_gpg_op_keylist_ext (engine->engine.gpg, pattern, + secret_only, reserved, keylist_mode); + case GPGME_PROTOCOL_CMS: + return _gpgme_gpgsm_op_keylist_ext (engine->engine.gpgsm, pattern, + secret_only, reserved, keylist_mode); + default: + break; + } + return 0; +} + + GpgmeError _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, diff --git a/gpgme/engine.h b/gpgme/engine.h index d8881a1..f684021 100644 --- a/gpgme/engine.h +++ b/gpgme/engine.h @@ -60,6 +60,11 @@ GpgmeError _gpgme_engine_op_import (EngineObject engine, GpgmeData keydata); GpgmeError _gpgme_engine_op_keylist (EngineObject engine, const char *pattern, int secret_only, int keylist_mode); +GpgmeError _gpgme_engine_op_keylist_ext (EngineObject engine, + const char *pattern[], + int secret_only, + int reserved, + int keylist_mode); GpgmeError _gpgme_engine_op_sign (EngineObject engine, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, int use_textmode, diff --git a/gpgme/keylist.c b/gpgme/keylist.c index 91bdbc3..55d427d 100644 --- a/gpgme/keylist.c +++ b/gpgme/keylist.c @@ -505,6 +505,73 @@ gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only) } +/** + * gpgme_op_keylist_ext_start: + * @c: context + * @pattern: a NULL terminated array of search patterns + * @secret_only: List only keys where the secret part is available + * @reserved: Should be 0. + * + * Note that this function also cancels a pending key listing + * operaton. To actually retrieve the key, use + * gpgme_op_keylist_next(). + * + * Return value: 0 on success or an errorcode. + **/ +GpgmeError +gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[], + int secret_only, int reserved) +{ + GpgmeError err = 0; + + if (!ctx) + return mk_error (Invalid_Value); + ctx->pending = 1; + + _gpgme_release_result (ctx); + + if (ctx->engine) + { + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + } + gpgme_key_release (ctx->tmp_key); + ctx->tmp_key = NULL; + /* Fixme: Release key_queue. */ + + err = _gpgme_engine_new (ctx->use_cms ? GPGME_PROTOCOL_CMS + : GPGME_PROTOCOL_OpenPGP, &ctx->engine); + if (err) + goto leave; + + _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx); + err = _gpgme_engine_set_colon_line_handler (ctx->engine, + keylist_colon_handler, ctx); + if (err) + goto leave; + + /* We don't want to use the verbose mode as this will also print + the key signatures which is in most cases not needed and furthermore we + just ignore those lines - This should speed up things */ + _gpgme_engine_set_verbosity (ctx->engine, 0); + + err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only, + reserved, ctx->keylist_mode); + + if (!err) /* And kick off the process. */ + err = _gpgme_engine_start (ctx->engine, ctx); + + leave: + if (err) + { + ctx->pending = 0; + _gpgme_engine_release (ctx->engine); + ctx->engine = NULL; + } + return err; +} + + /** * gpgme_op_keylist_next: * @c: Context diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 8738fc3..dc69acb 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -1441,6 +1441,7 @@ _gpgme_gpg_op_import (GpgObject gpg, GpgmeData keydata) return err; } + GpgmeError _gpgme_gpg_op_keylist (GpgObject gpg, const char *pattern, int secret_only, int keylist_mode) @@ -1465,6 +1466,38 @@ _gpgme_gpg_op_keylist (GpgObject gpg, const char *pattern, int secret_only, return err; } + +GpgmeError +_gpgme_gpg_op_keylist_ext (GpgObject gpg, const char *pattern[], + int secret_only, int reserved, int keylist_mode) +{ + GpgmeError err; + + if (reserved) + return mk_error (Invalid_Value); + + err = _gpgme_gpg_add_arg (gpg, "--with-colons"); + if (!err) + err = _gpgme_gpg_add_arg (gpg, "--fixed-list-mode"); + if (!err) + err = _gpgme_gpg_add_arg (gpg, "--with-fingerprint"); + if (!err) + err = _gpgme_gpg_add_arg (gpg, secret_only ? "--list-secret-keys" + : "--list-keys"); + + /* Tell the gpg object about the data */ + if (!err) + err = _gpgme_gpg_add_arg (gpg, "--"); + if (!err && pattern && *pattern) + { + while (*pattern) + err = _gpgme_gpg_add_arg (gpg, *(pattern++)); + } + + return err; +} + + GpgmeError _gpgme_gpg_op_sign (GpgObject gpg, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, diff --git a/gpgme/rungpg.h b/gpgme/rungpg.h index ed65cf1..58afd8a 100644 --- a/gpgme/rungpg.h +++ b/gpgme/rungpg.h @@ -137,6 +137,9 @@ GpgmeError _gpgme_gpg_op_genkey (GpgObject gpg, GpgmeData help_data, GpgmeError _gpgme_gpg_op_import (GpgObject gpg, GpgmeData keydata); GpgmeError _gpgme_gpg_op_keylist (GpgObject gpg, const char *pattern, int secret_only, int keylist_mode); +GpgmeError _gpgme_gpg_op_keylist_ext (GpgObject gpg, const char *pattern[], + int secret_only, int reserved, + int keylist_mode); GpgmeError _gpgme_gpg_op_sign (GpgObject gpg, GpgmeData in, GpgmeData out, GpgmeSigMode mode, int use_armor, int use_textmode, GpgmeCtx ctx /* FIXME */); -- 2.26.2