diff options
| author | Werner Koch <[email protected]> | 2009-06-16 15:42:37 +0000 | 
|---|---|---|
| committer | Werner Koch <[email protected]> | 2009-06-16 15:42:37 +0000 | 
| commit | bebd9cbe29cf6db15469502b5c6b1f83c93513ef (patch) | |
| tree | f2812ddbb4ddd2f00592b36a6c16cbf494cc7f81 /src | |
| parent | doc/ (diff) | |
| download | gpgme-bebd9cbe29cf6db15469502b5c6b1f83c93513ef.tar.gz gpgme-bebd9cbe29cf6db15469502b5c6b1f83c93513ef.zip | |
Add support for gpg --fetch-keys.
Diffstat (limited to '')
| -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 | 
5 files changed, 150 insertions, 2 deletions
| 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> | 
