diff options
| -rw-r--r-- | NEWS | 3 | ||||
| -rw-r--r-- | doc/ChangeLog | 1 | ||||
| -rw-r--r-- | doc/gpgme.texi | 13 | ||||
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/data.c | 2 | ||||
| -rw-r--r-- | src/engine-gpg.c | 136 | ||||
| -rw-r--r-- | src/gpgme.h.in | 5 | ||||
| -rw-r--r-- | src/version.c | 1 | ||||
| -rw-r--r-- | tests/ChangeLog | 4 | ||||
| -rw-r--r-- | tests/gpg/Makefile.am | 2 | ||||
| -rw-r--r-- | tests/gpg/pgp-export.c | 7 | ||||
| -rw-r--r-- | tests/gpg/pgp-import.c | 129 | ||||
| -rw-r--r-- | tests/gpg/pgp-keylist.c | 61 | ||||
| -rw-r--r-- | tests/gpg/t-support.h | 61 | 
14 files changed, 362 insertions, 71 deletions
| @@ -48,6 +48,9 @@ Noteworthy changes in version 1.2.0 (unreleased)   gpgme_op_export_ext            EXTENDED: Arg RESERVED is now a MODE flag.   gpgme_op_export_keys_start     NEW.   gpgme_op_export_keys           NEW. + GPGME_DATA_ENCODING_URL        NEW. + GPGME_DATA_ENCODING_URL0       NEW. + GPGME_DATA_ENCODING_URLESC     NEW.   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/ChangeLog b/doc/ChangeLog index 6bc623b4..5772e682 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -6,6 +6,7 @@  	* gpgme.texi (Exporting Keys): Document gpgme_op_export_keys.  	(Importing Keys): Document gpgme_op_import_keys. +	(Data Buffer Meta-Data): Document URL encodings.  2009-05-28  Marcus Brinkmann  <[email protected]> diff --git a/doc/gpgme.texi b/doc/gpgme.texi index 8ecb449d..a0bc20e8 100644 --- a/doc/gpgme.texi +++ b/doc/gpgme.texi @@ -1934,6 +1934,19 @@ scheme as used by @acronym{MIME} and other protocols.  @item GPGME_DATA_ENCODING_ARMOR  This specifies that the data is encoded in an armored form as used by  OpenPGP and PEM. + +@item GPGME_DATA_ENCODING_URL +The data is a list of linefeed delimited URLs.  This is only useful with +@code{gpgme_op_import}. + +@item GPGME_DATA_ENCODING_URL0 +The data is a list of binary zero delimited URLs.  This is only useful +with @code{gpgme_op_import}. + +@item GPGME_DATA_ENCODING_URLESC +The data is a list of linefeed delimited URLs with all control and space +characters percent escaped.  This mode is is not yet implemented. +  @end table  @end deftp diff --git a/src/ChangeLog b/src/ChangeLog index 68619136..93108af5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -5,6 +5,14 @@  2009-06-16  Werner Koch  <[email protected]> +	* version.c: Include stdlib.h.  + +	* gpgme.h.in (gpgme_data_encoding_t): Add GPGME_DATA_ENCODING_URL, +	GPGME_DATA_ENCODING_URLESC, GPGME_DATA_ENCODING_URL0. +	* data.c (gpgme_data_set_encoding): Adjust for new values. +	* engine-gpg.c (string_from_data): New. +	(gpg_import): Implement --fetch-key feature. +  	* gpgme.h.in (gpgme_op_export_keys_start, gpgme_op_export_keys): New.  	* gpgme.def, libgpgme.vers: Add them.  	* export.c (gpgme_op_export_keys_start, gpgme_op_export_keys): New. @@ -191,7 +191,7 @@ gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)  	      "encoding=%i", enc);    if (!dh)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); -  if (enc < 0 || enc > GPGME_DATA_ENCODING_ARMOR) +  if (enc < 0 || enc > GPGME_DATA_ENCODING_URL0)      return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));    dh->encoding = enc;    return TRACE_ERR (0); diff --git a/src/engine-gpg.c b/src/engine-gpg.c index 3c06edf8..1012166a 100644 --- a/src/engine-gpg.c +++ b/src/engine-gpg.c @@ -1803,6 +1803,107 @@ gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,    return err;  } +/* Return the next DELIM delimited string from DATA as a C-string. +   The caller needs to provide the address of a pointer variable which +   he has to set to NULL before the first call.  After the last call +   to this function, this function needs to be called once more with +   DATA set to NULL so that the function can release its internal +   state.  After that the pointer variable is free for use again. +   Note that we use a delimiter and thus a trailing delimiter is not +   required.  DELIM may not be changed after the first call. */ +static const char * +string_from_data (gpgme_data_t data, int delim,  +                  void **helpptr, gpgme_error_t *r_err) +{ +#define MYBUFLEN 2000 /* Fixme: We don't support URLs longer than that.  */ +  struct { +    int  eof_seen; +    int  nbytes;      /* Length of the last returned string including +                         the delimiter. */ +    int  buflen;      /* Valid length of BUF.  */ +    char buf[MYBUFLEN+1];  /* Buffer with one byte extra space.  */ +  } *self; +  char *p; +  int nread; + +  *r_err = 0; +  if (!data) +    { +      if (*helpptr) +        { +          free (*helpptr); +          *helpptr = NULL; +        } +      return NULL; +    } + +  if (*helpptr) +    self = *helpptr; +  else +    { +      self = malloc (sizeof *self); +      if (!self) +        { +          *r_err = gpg_error_from_syserror (); +          return NULL; +        } +      *helpptr = self; +      self->eof_seen = 0; +      self->nbytes = 0; +      self->buflen = 0; +    } + +  if (self->eof_seen) +    return NULL; + +  assert (self->nbytes <= self->buflen); +  memmove (self->buf, self->buf + self->nbytes, self->buflen - self->nbytes); +  self->buflen -= self->nbytes; +  self->nbytes = 0; + +  do +    { +      /* Fixme: This is fairly infective scanning because we may scan +         the buffer several times.  */ +      p = memchr (self->buf, delim, self->buflen); +      if (p) +        { +          *p = 0; +          self->nbytes = p - self->buf + 1; +          return self->buf; +        } + +      if ( !(MYBUFLEN - self->buflen) ) +        { +          /* Not enough space - URL too long.  */ +          *r_err = gpg_error (GPG_ERR_TOO_LARGE); +          return NULL; +        } + +      nread = gpgme_data_read (data, self->buf + self->buflen,  +                               MYBUFLEN - self->buflen); +      if (nread < 0) +        { +          *r_err = gpg_error_from_syserror (); +          return NULL; +        } +      self->buflen += nread; +    } +  while (nread); + +  /* EOF reached.  If we have anything in the buffer, append a Nul and +     return it. */ +  self->eof_seen = 1; +  if (self->buflen) +    { +      self->buf[self->buflen] = 0;  /* (we allocated one extra byte)  */ +      return self->buf; +    } +  return NULL; +#undef MYBUFLEN +} + +  static gpgme_error_t  gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray) @@ -1810,10 +1911,13 @@ gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)    engine_gpg_t gpg = engine;    gpgme_error_t err;    int idx; +  gpgme_data_encoding_t dataenc;    if (keydata && keyarray)      gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed.  */ +  dataenc = gpgme_data_get_encoding (keydata); +    if (keyarray)      {        err = add_arg (gpg, "--recv-keys"); @@ -1831,6 +1935,38 @@ gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)              err = add_arg (gpg, keyarray[idx]->subkeys->keyid);          }      } +  else if (dataenc == GPGME_DATA_ENCODING_URL +           || dataenc == GPGME_DATA_ENCODING_URL0) +    { +      void *helpptr; +      const char *string; +      gpgme_error_t xerr; +      int delim = (dataenc == GPGME_DATA_ENCODING_URL)? '\n': 0; + +      /* FIXME: --fetch-keys is probably not correct because it can't +         grok all kinds of URLs.  On Unix it should just work but on +         Windows we will build the command line and that may fail for +         some embedded control characters.  It is anyway limited to +         the maximum size of the command line.  We need another +         command which can take its input from a file.  Maybe we +         should use an option to gpg to modify such commands (ala +         --multifile).  */ +      err = add_arg (gpg, "--fetch-keys"); +      if (!err) +        err = add_arg (gpg, "--"); +      helpptr = NULL; +      while (!err +             && (string = string_from_data (keydata, delim, &helpptr, &xerr))) +        err = add_arg (gpg, string); +      if (!err) +        err = xerr; +      string_from_data (NULL, delim, &helpptr, &xerr); +    } +  else if (dataenc == GPGME_DATA_ENCODING_URLESC) +    { +      /* Already escaped URLs are not yet supported.  */ +      err = gpg_error (GPG_ERR_NOT_IMPLEMENTED); +    }    else      {        err = add_arg (gpg, "--import"); diff --git a/src/gpgme.h.in b/src/gpgme.h.in index ff9bba06..e02a98c3 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -185,7 +185,10 @@ typedef enum      GPGME_DATA_ENCODING_NONE   = 0,	/* Not specified.  */      GPGME_DATA_ENCODING_BINARY = 1,      GPGME_DATA_ENCODING_BASE64 = 2, -    GPGME_DATA_ENCODING_ARMOR  = 3	/* Either PEM or OpenPGP Armor.  */ +    GPGME_DATA_ENCODING_ARMOR  = 3,	/* Either PEM or OpenPGP Armor.  */ +    GPGME_DATA_ENCODING_URL    = 4,     /* LF delimited URL list.        */ +    GPGME_DATA_ENCODING_URLESC = 5,     /* Ditto, but percent escaped.   */ +    GPGME_DATA_ENCODING_URL0   = 6      /* Nul delimited URL list.       */    }  gpgme_data_encoding_t; diff --git a/src/version.c b/src/version.c index f777da44..b2d795ab 100644 --- a/src/version.c +++ b/src/version.c @@ -22,6 +22,7 @@  #if HAVE_CONFIG_H  #include <config.h>  #endif +#include <stdlib.h>  #include <string.h>  #include <limits.h>  #include <ctype.h> diff --git a/tests/ChangeLog b/tests/ChangeLog index c9ab1337..fcdf1565 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,9 @@  2009-06-16  Werner Koch  <[email protected]> +	* gpg/pgp-import.c: New. +	* gpg/t-support.h (print_import_result, nonnull): Factored out +	from other tools. +  	* gpg/pgp-export.c, gpg/pgp-keylist.c: New.  2009-06-09  Werner Koch  <[email protected]> diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am index fdb023c9..441e80ca 100644 --- a/tests/gpg/Makefile.am +++ b/tests/gpg/Makefile.am @@ -51,7 +51,7 @@ t_thread1_LDADD = ../../src/libgpgme-pthread.la  # We don't run t-genkey in the test suite, because it takes too long  # The other programs are used for debugging. -noinst_PROGRAMS = $(TESTS) t-genkey pgp-keylist pgp-export +noinst_PROGRAMS = $(TESTS) t-genkey pgp-keylist pgp-export pgp-import  mkdemodirs: mkdemodirs.in Makefile  	sed -e 's,[@]GPG[@],$(GPG),g' < $(srcdir)/mkdemodirs.in > mkdemodirs diff --git a/tests/gpg/pgp-export.c b/tests/gpg/pgp-export.c index 9911c182..a0b3e8a5 100644 --- a/tests/gpg/pgp-export.c +++ b/tests/gpg/pgp-export.c @@ -37,13 +37,6 @@  static int verbose; -static const char * -nonnull (const char *s) -{ -  return s? s :"[none]"; -} - -  static int  show_usage (int ex)  { diff --git a/tests/gpg/pgp-import.c b/tests/gpg/pgp-import.c new file mode 100644 index 00000000..b9d68608 --- /dev/null +++ b/tests/gpg/pgp-import.c @@ -0,0 +1,129 @@ +/* pgp-import.c  - Helper to run an import command +   Copyright (C) 2008, 2009 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/>. +*/ + +/* We need to include config.h so that we know whether we are building +   with large file system (LFS) support. */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <gpgme.h> + +#define PGM "pgp-import" + +#include "t-support.h" + + +static int verbose; + + +static int +show_usage (int ex) +{ +  fputs ("usage: " PGM " [options] FILENAMEs\n\n" +         "Options:\n" +         "  --verbose        run in verbose mode\n" +         "  --url            import from given URLs\n" +         "  -0               URLs are delimited by a nul\n" +         , stderr); +  exit (ex); +} + +int  +main (int argc, char **argv) +{ +  int last_argc = -1; +  gpgme_error_t err; +  gpgme_ctx_t ctx; +  int url_mode = 0; +  int nul_mode = 0; +  gpgme_import_result_t impres; +  gpgme_data_t data; + +  if (argc) +    { argc--; argv++; } +  while (argc && last_argc != argc ) +    { +      last_argc = argc; +      if (!strcmp (*argv, "--")) +        { +          argc--; argv++; +          break; +        } +      else if (!strcmp (*argv, "--help")) +        show_usage (0); +      else if (!strcmp (*argv, "--verbose")) +        { +          verbose = 1; +          argc--; argv++; +        } +      else if (!strcmp (*argv, "--url")) +        { +          url_mode = 1; +          argc--; argv++; +        } +      else if (!strcmp (*argv, "-0")) +        { +          nul_mode = 1; +          argc--; argv++; +        } +      else if (!strncmp (*argv, "--", 2)) +        show_usage (1); +       +    }           +  +  if (!argc) +    show_usage (1); + +  init_gpgme (GPGME_PROTOCOL_OpenPGP); + +  err = gpgme_new (&ctx); +  fail_if_err (err); +  gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP); + +  for (; argc; argc--, argv++) +    { +      printf ("reading file `%s'\n", *argv); +      err = gpgme_data_new_from_file (&data, *argv, 1); +      fail_if_err (err); + +      if (url_mode) +        gpgme_data_set_encoding (data, (nul_mode? GPGME_DATA_ENCODING_URL0 +                                        : GPGME_DATA_ENCODING_URL)); +       +      err = gpgme_op_import (ctx, data); +      fail_if_err (err); +      impres = gpgme_op_import_result (ctx); +      if (!impres) +        { +          fprintf (stderr, PGM ": no import result returned\n"); +          exit (1); +        } +      print_import_result (impres); +       +      gpgme_data_release (data); +    } + +  gpgme_release (ctx); +  return 0; +} diff --git a/tests/gpg/pgp-keylist.c b/tests/gpg/pgp-keylist.c index 2645f48b..4978b8dd 100644 --- a/tests/gpg/pgp-keylist.c +++ b/tests/gpg/pgp-keylist.c @@ -37,67 +37,6 @@  static int verbose; -static const char * -nonnull (const char *s) -{ -  return s? s :"[none]"; -} - - -static void -print_import_result (gpgme_import_result_t r) -{ -  gpgme_import_status_t st; - -  printf ("key import results:\n" -          "        considered: %d\n" -          "        no user id: %d\n" -          "          imported: %d\n" -          "      imported_rsa: %d\n" -          "         unchanged: %d\n" -          "      new user ids: %d\n" -          "       new subkeys: %d\n" -          "    new signatures: %d\n" -          "   new revocations: %d\n" -          "       secret read: %d\n" -          "   secret imported: %d\n" -          "  secret unchanged: %d\n" -          "  skipped new keys: %d\n" -          "      not imported: %d\n", -          r->considered, -          r->no_user_id, -          r->imported, -          r->imported_rsa, -          r->unchanged, -          r->new_user_ids, -          r->new_sub_keys, -          r->new_signatures, -          r->new_revocations, -          r->secret_read, -          r->secret_imported, -          r->secret_unchanged, -          r->skipped_new_keys, -          r->not_imported); - -  for (st=r->imports; st; st = st->next) -    { -      printf ("  fpr: %s err: %d (%s) status:", nonnull (st->fpr), -              st->result, gpg_strerror (st->result)); -      if (st->status & GPGME_IMPORT_NEW) -        fputs (" new", stdout); -      if (st->status & GPGME_IMPORT_UID) -        fputs (" uid", stdout); -      if (st->status & GPGME_IMPORT_SIG) -        fputs (" sig", stdout); -      if (st->status & GPGME_IMPORT_SUBKEY) -        fputs (" subkey", stdout); -      if (st->status & GPGME_IMPORT_SECRET) -        fputs (" secret", stdout); -      putchar ('\n'); -    } -} - -  static int  show_usage (int ex)  { diff --git a/tests/gpg/t-support.h b/tests/gpg/t-support.h index 362b857a..13475f29 100644 --- a/tests/gpg/t-support.h +++ b/tests/gpg/t-support.h @@ -48,6 +48,13 @@    while (0) +static const char * +nonnull (const char *s) +{ +  return s? s :"[none]"; +} + +  void  print_data (gpgme_data_t dh)  { @@ -113,3 +120,57 @@ init_gpgme (gpgme_protocol_t proto)    err = gpgme_engine_check_version (proto);    fail_if_err (err);  } + + +void +print_import_result (gpgme_import_result_t r) +{ +  gpgme_import_status_t st; + +  for (st=r->imports; st; st = st->next) +    { +      printf ("  fpr: %s err: %d (%s) status:", nonnull (st->fpr), +              st->result, gpg_strerror (st->result)); +      if (st->status & GPGME_IMPORT_NEW) +        fputs (" new", stdout); +      if (st->status & GPGME_IMPORT_UID) +        fputs (" uid", stdout); +      if (st->status & GPGME_IMPORT_SIG) +        fputs (" sig", stdout); +      if (st->status & GPGME_IMPORT_SUBKEY) +        fputs (" subkey", stdout); +      if (st->status & GPGME_IMPORT_SECRET) +        fputs (" secret", stdout); +      putchar ('\n'); +    } +  printf ("key import summary:\n" +          "        considered: %d\n" +          "        no user id: %d\n" +          "          imported: %d\n" +          "      imported_rsa: %d\n" +          "         unchanged: %d\n" +          "      new user ids: %d\n" +          "       new subkeys: %d\n" +          "    new signatures: %d\n" +          "   new revocations: %d\n" +          "       secret read: %d\n" +          "   secret imported: %d\n" +          "  secret unchanged: %d\n" +          "  skipped new keys: %d\n" +          "      not imported: %d\n", +          r->considered, +          r->no_user_id, +          r->imported, +          r->imported_rsa, +          r->unchanged, +          r->new_user_ids, +          r->new_sub_keys, +          r->new_signatures, +          r->new_revocations, +          r->secret_read, +          r->secret_imported, +          r->secret_unchanged, +          r->skipped_new_keys, +          r->not_imported); +} + | 
