From 0913218bcc1e170c0ad7843a4c93060f6c7422d0 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Fri, 14 Dec 2001 00:49:38 +0000 Subject: [PATCH] gpgme/ 2001-12-14 Marcus Brinkmann * engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic. (_gpgme_gpgsm_new): Initialize some more members. (_gpgme_gpgsm_release): Free the colon line handler's attic line. (gpgsm_status_handler): Rework the inline-data processing. tests/ 2001-12-14 Marcus Brinkmann * gpgsm/t-keylist.c: New file. * gpgsm/Makefile.am (TESTS): Add t-keylist. --- gpgme/ChangeLog | 9 ++- gpgme/engine-gpgsm.c | 96 +++++++++++++++++------- tests/ChangeLog | 5 ++ tests/gpgsm/Makefile.am | 2 +- tests/gpgsm/t-keylist.c | 160 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 243 insertions(+), 29 deletions(-) create mode 100644 tests/gpgsm/t-keylist.c diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 569005f..00449dc 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,10 @@ +2001-12-14 Marcus Brinkmann + + * engine-gpgsm.c (struct gpgsm_object_s): New member colon.attic. + (_gpgme_gpgsm_new): Initialize some more members. + (_gpgme_gpgsm_release): Free the colon line handler's attic line. + (gpgsm_status_handler): Rework the inline-data processing. + 2001-12-13 Marcus Brinkmann * rungpg.c (_gpgme_gpg_spawn): Do not add the fds to the child @@ -130,7 +137,7 @@ * engine-gpgsm.c (_gpgme_gpgsm_op_decrypt): New function. (_gpgme_gpgsm_op_import): Likewise. -2001-11-22 Marcus Brinkmann +2001-11-22 Marcus Brinkmann * engine-gpgsm.c: Shuffle around header inclusion a bit, to still keep them seperate. diff --git a/gpgme/engine-gpgsm.c b/gpgme/engine-gpgsm.c index 887e9ef..456de4f 100644 --- a/gpgme/engine-gpgsm.c +++ b/gpgme/engine-gpgsm.c @@ -83,8 +83,13 @@ struct gpgsm_object_s { GpgColonLineHandler fnc; void *fnc_value; - } colon; - + struct + { + unsigned char *line; + int linesize; + int linelen; + } attic; + } colon; }; const char * @@ -144,6 +149,12 @@ _gpgme_gpgsm_new (GpgsmObject *r_gpgsm) gpgsm->message_fd = -1; gpgsm->message_fd_server = -1; + gpgsm->status.fnc = 0; + gpgsm->colon.fnc = 0; + gpgsm->colon.attic.line = 0; + gpgsm->colon.attic.linesize = 0; + gpgsm->colon.attic.linelen = 0; + if (_gpgme_io_pipe (fds, 0) < 0) { err = mk_error (General_Error); @@ -222,6 +233,7 @@ _gpgme_gpgsm_release (GpgsmObject gpgsm) assuan_pipe_disconnect (gpgsm->assuan_ctx); + xfree (gpgsm->colon.attic.line); xfree (gpgsm->command); xfree (gpgsm); } @@ -529,36 +541,66 @@ gpgsm_status_handler (void *opaque, int pid, int fd) if (linelen > 2 && line[0] == 'D' && line[1] == ' ' - && gpgsm->colon.fnc ) + && gpgsm->colon.fnc) { - unsigned char *s, *d; - - line += 2; - linelen -= 2; - /* Hmmm, we are using the colon handler even for plain - inline data - strange name for that fucntion but for - historic reasons we keep it */ - for (s=d=line; linelen; linelen--) + /* We are using the colon handler even for plain inline data + - strange name for that function but for historic reasons + we keep it. */ + /* FIXME We can't use this for binary data because we + assume this is a string. For the current usage of colon + output it is correct. */ + unsigned char *src = line + 2; + unsigned char *end = line + linelen; + unsigned char *dst; + unsigned char **aline = &gpgsm->colon.attic.line; + int *alinelen = &gpgsm->colon.attic.linelen; + + if (gpgsm->colon.attic.linesize + < *alinelen + linelen + 1) + { + unsigned char *newline = xtryrealloc (*aline, + *alinelen + linelen + 1); + if (!newline) + return mk_error (Out_Of_Core); + *aline = newline; + gpgsm->colon.attic.linesize += linelen + 1; + } + + dst = *aline + *alinelen; + + while (src < end) { - if (*s == '%' && linelen > 2) - { /* handle escaping */ - s++; - *d++ = xtoi_2 (s); - s += 2; - linelen -= 2; + if (*src == '%' && src + 2 < end) + { + /* Handle escaped characters. */ + ++src; + *dst = xtoi_2 (src); + (*alinelen)++; + src += 2; } else - *d++ = *s++; + { + *dst = *src++; + (*alinelen)++; + } + + if (*dst == '\n') + { + /* Terminate the pending line, pass it to the colon + handler and reset it. */ + + if (*alinelen > 1 && *(dst - 1) == '\r') + dst--; + *dst = '\0'; + + /* FIXME How should we handle the return code? */ + gpgsm->colon.fnc (gpgsm->colon.fnc_value, *aline); + dst = *aline; + *alinelen = 0; + } + else + dst++; } - *d = 0; /* add a hidden string terminator */ - - /* fixme: should we handle the return code? */ - /* fixme: Hmmm: we can't use this for binary data because we - assume this is a string. For the current usage of colon - output it is correct */ - /* FIXME: we need extra bufferring to pass colon lines line - by line */ - gpgsm->colon.fnc (gpgsm->colon.fnc_value, line); } else if (linelen > 2 && line[0] == 'S' && line[1] == ' ') diff --git a/tests/ChangeLog b/tests/ChangeLog index 897885a..fa8712a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,8 @@ +2001-12-14 Marcus Brinkmann + + * gpgsm/t-keylist.c: New file. + * gpgsm/Makefile.am (TESTS): Add t-keylist. + 2001-12-13 Marcus Brinkmann * gpgsm/cert_dfn_pca01.der: New file. diff --git a/tests/gpgsm/Makefile.am b/tests/gpgsm/Makefile.am index 89d5467..bf724fb 100644 --- a/tests/gpgsm/Makefile.am +++ b/tests/gpgsm/Makefile.am @@ -22,7 +22,7 @@ TESTS_ENVIRONMENT = GNUPGHOME=. -TESTS = t-import +TESTS = t-import t-keylist EXTRA_DIST = cert_dfn_pca01.der cert_dfn_pca15.der cert_g10code_test1.der diff --git a/tests/gpgsm/t-keylist.c b/tests/gpgsm/t-keylist.c new file mode 100644 index 0000000..9ead110 --- /dev/null +++ b/tests/gpgsm/t-keylist.c @@ -0,0 +1,160 @@ +/* t-keylist.c - regression test + * Copyright (C) 2000 Werner Koch (dd9jn) + * Copyright (C) 2001 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 General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include + +#include + +#define fail_if_err(a) do { if(a) { \ + fprintf (stderr, "%s:%d: GpgmeError %s\n", \ + __FILE__, __LINE__, gpgme_strerror(a)); \ + exit (1); } \ + } while(0) + +static void +doit ( GpgmeCtx ctx, const char *pattern ) +{ + GpgmeError err; + GpgmeKey key; + + err = gpgme_op_keylist_start (ctx, pattern, 0 ); + fail_if_err (err); + + while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) { + char *p; + const char *s; + int i; + + printf ("\n", key ); + p = gpgme_key_get_as_xml ( key ); + if ( p ) { + fputs ( p, stdout ); + free (p); + } + else + fputs("\n", stdout ); + + + for (i=0; ; i++ ) { + s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i ); + if (!s) + break; + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i ); + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i ); + printf ("\n", i, s ); + } + for (i=0; ; i++ ) { + s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i ); + if (!s) + break; + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i ); + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i ); + printf ("\n", i, s ); + } + + fputs ("\n", stdout ); + + printf ("\n", key ); + gpgme_key_release (key); + } + if ( err != GPGME_EOF ) + fail_if_err (err); +} + + +/* + * Check that there are no problems when we are using two context for + * listing keys. + */ +static void +check_two_contexts (void) +{ + GpgmeError err; + GpgmeCtx ctx1, ctx2; + GpgmeKey key; + + err = gpgme_new(&ctx1); fail_if_err (err); + err = gpgme_op_keylist_start(ctx1, "", 1); fail_if_err (err); + err = gpgme_new(&ctx2); fail_if_err (err); + err = gpgme_op_keylist_start(ctx2, "", 1); fail_if_err (err); + + while ( (err=gpgme_op_keylist_next(ctx2, &key)) != GPGME_EOF) { + gpgme_key_release (key); + } + if (err != GPGME_EOF) + fail_if_err (err); + while ( (err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF) { + gpgme_key_release (key); + } + if (err != GPGME_EOF) + fail_if_err (err); +} + +int +main (int argc, char **argv ) +{ + GpgmeCtx ctx; + GpgmeError err; + int loop = 0; + const char *pattern; + + if( argc ) { + argc--; argv++; + } + + if (argc && !strcmp( *argv, "--loop" ) ) { + loop = 1; + argc--; argv++; + } + pattern = argc? *argv : NULL; + + err = gpgme_check_engine(); + fail_if_err (err); + + err = gpgme_new (&ctx); + fail_if_err (err); + gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); + + gpgme_set_keylist_mode (ctx, 1); /* no validity calculation */ + do { + fprintf (stderr, "** pattern=`%s'\n", pattern ); + doit ( ctx, pattern ); + } while ( loop ); + gpgme_release (ctx); + + check_two_contexts (); + + return 0; +} -- 2.26.2