diff options
Diffstat (limited to 'src')
-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> |