aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Brinkmann <[email protected]>2006-02-22 11:02:50 +0000
committerMarcus Brinkmann <[email protected]>2006-02-22 11:02:50 +0000
commit2f4b38533245635ba98f3f115622d5b0c00579bb (patch)
tree4b775526c3d73e5a5a8aacb0722a09480f367e2f
parent2006-02-15 Marcus Brinkmann <[email protected]> (diff)
downloadgpgme-2f4b38533245635ba98f3f115622d5b0c00579bb.tar.gz
gpgme-2f4b38533245635ba98f3f115622d5b0c00579bb.zip
2006-02-22 Marcus Brinkmann <[email protected]>
* rungpg.c (read_colon_line): Invoke colon preprocess handler if it is set. (colon_preprocessor_t): New type. (struct engine_gpg): New member colon.preprocess_fnc. (gpg_keylist_preprocess): New function. * keylist.c (keylist_colon_handler): Allow short key IDs.
Diffstat (limited to '')
-rw-r--r--TODO5
-rw-r--r--gpgme/ChangeLog9
-rw-r--r--gpgme/keylist.c8
-rw-r--r--gpgme/rungpg.c132
4 files changed, 141 insertions, 13 deletions
diff --git a/TODO b/TODO
index e74c5abc..477d868b 100644
--- a/TODO
+++ b/TODO
@@ -5,9 +5,6 @@ Hey Emacs, this is -*- outline -*- mode!
The test is currently disabled there and in gpg/t-import.
** When gpg supports it, write binary subpackets directly,
and parse SUBPACKET status lines.
-** External key listing for OpenPGP.
- This probably requires changes at gpg.
-
* ABI's to break:
** gpgme_edit_cb_t: Add "processed" return argument
@@ -81,7 +78,7 @@ Hey Emacs, this is -*- outline -*- mode!
release everything properly at a reset and at an error. Think hard
about where to guarantee what (ie, what happens if start fails, are
the fds unregistered immediately - i think so?)
-** Optimize the case where a data object has an underlying fd we can pass
+** Optimize the case where a data object has 0an underlying fd we can pass
directly to the engine. This will be automatic with socket I/O and
descriptor passing.
** Move code common to all engines up from gpg to engine.
diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog
index 9e4c831d..29113948 100644
--- a/gpgme/ChangeLog
+++ b/gpgme/ChangeLog
@@ -1,3 +1,12 @@
+2006-02-22 Marcus Brinkmann <[email protected]>
+
+ * rungpg.c (read_colon_line): Invoke colon preprocess handler if
+ it is set.
+ (colon_preprocessor_t): New type.
+ (struct engine_gpg): New member colon.preprocess_fnc.
+ (gpg_keylist_preprocess): New function.
+ * keylist.c (keylist_colon_handler): Allow short key IDs.
+
2006-02-15 Marcus Brinkmann <[email protected]>
* w32-io.c (create_writer): Make C->have_data a manually resetted
diff --git a/gpgme/keylist.c b/gpgme/keylist.c
index 50201773..bf731f0d 100644
--- a/gpgme/keylist.c
+++ b/gpgme/keylist.c
@@ -176,7 +176,8 @@ set_mainkey_trust_info (gpgme_key_t key, const char *src)
case 'd':
/* Note that gpg 1.3 won't print that anymore but only uses
- the capabilities field. */
+ the capabilities field. However, it is still used for
+ external key listings. */
key->disabled = 1;
break;
@@ -493,8 +494,9 @@ keylist_colon_handler (void *priv, char *line)
subkey->pubkey_algo = i;
}
- /* Field 5 has the long keyid. */
- if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
+ /* Field 5 has the long keyid. Allow short key IDs for the
+ output of an external keyserver listing. */
+ if (fields >= 5 && strlen (field[4]) <= DIM(subkey->_keyid) - 1)
strcpy (subkey->_keyid, field[4]);
/* Field 6 has the timestamp (seconds). */
diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c
index 0a3f0bb5..16805f1e 100644
--- a/gpgme/rungpg.c
+++ b/gpgme/rungpg.c
@@ -65,6 +65,8 @@ struct fd_data_map_s
};
+typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
+
struct engine_gpg
{
char *file_name;
@@ -95,6 +97,7 @@ struct engine_gpg
engine_colon_line_handler_t fnc; /* this indicate use of this structrue */
void *fnc_value;
void *tag;
+ colon_preprocessor_t preprocess_fnc;
} colon;
char **argv;
@@ -1013,14 +1016,27 @@ read_colon_line (engine_gpg_t gpg)
{
/* (we require that the last line is terminated by a LF)
and we skip empty lines. Note: we use UTF8 encoding
- and escaping of special characters We require at
+ and escaping of special characters. We require at
least one colon to cope with some other printed
information. */
*p = 0;
if (*buffer && strchr (buffer, ':'))
{
+ char *line = NULL;
+
+ if (gpg->colon.preprocess_fnc)
+ {
+ gpgme_error_t err;
+
+ err = gpg->colon.preprocess_fnc (buffer, &line);
+ if (err)
+ return err;
+ }
+
assert (gpg->colon.fnc);
- gpg->colon.fnc (gpg->colon.fnc_value, buffer);
+ gpg->colon.fnc (gpg->colon.fnc_value, line ? line : buffer);
+ if (line)
+ free (line);
}
/* To reuse the buffer for the next line we have to
@@ -1613,6 +1629,93 @@ gpg_import (void *engine, gpgme_data_t keydata)
}
+/* The output for external keylistings in GnuPG is different from all
+ the other key listings. We catch this here with a special
+ preprocessor that reformats the colon handler lines. */
+static gpgme_error_t
+gpg_keylist_preprocess (char *line, char **r_line)
+{
+ enum
+ {
+ RT_NONE, RT_INFO, RT_PUB, RT_UID
+ }
+ rectype = RT_NONE;
+#define NR_FIELDS 16
+ char *field[NR_FIELDS];
+ int fields = 0;
+
+ *r_line = NULL;
+
+ while (line && fields < NR_FIELDS)
+ {
+ field[fields++] = line;
+ line = strchr (line, ':');
+ if (line)
+ *(line++) = '\0';
+ }
+
+ if (!strcmp (field[0], "info"))
+ rectype = RT_INFO;
+ else if (!strcmp (field[0], "pub"))
+ rectype = RT_PUB;
+ else if (!strcmp (field[0], "uid"))
+ rectype = RT_UID;
+ else
+ rectype = RT_NONE;
+
+ switch (rectype)
+ {
+ case RT_INFO:
+ /* FIXME: Eventually, check the version number at least. */
+ return 0;
+
+ case RT_PUB:
+ if (fields < 7)
+ return 0;
+
+ /* The format is:
+
+ pub:<keyid>:<algo>:<keylen>:<creationdate>:<expirationdate>:<flags>
+
+ as defined in 5.2. Machine Readable Indexes of the OpenPGP
+ HTTP Keyserver Protocol (draft).
+
+ We want:
+ pub:o<flags>:<keylen>:<algo>:<keyid>:<creatdate>:<expdate>::::::::
+ */
+
+ if (asprintf (r_line, "pub:o%s:%s:%s:%s:%s:%s::::::::",
+ field[6], field[3], field[2], field[1],
+ field[4], field[5]) < 0)
+ return gpg_error_from_errno (errno);
+ return 0;
+
+ case RT_UID:
+ /* The format is:
+
+ uid:<escaped uid string>:<creationdate>:<expirationdate>:<flags>
+
+ as defined in 5.2. Machine Readable Indexes of the OpenPGP
+ HTTP Keyserver Protocol (draft).
+
+ We want:
+ uid:o<flags>::::<creatdate>:<expdate>:::<uid>:
+ */
+
+ if (asprintf (r_line, "uid:o%s::::%s:%s:::%s:",
+ field[4], field[2], field[3], field[1]) < 0)
+ return gpg_error_from_errno (errno);
+ return 0;
+
+ case RT_NONE:
+ /* Unknown record. */
+ break;
+ }
+ return 0;
+
+}
+
+
static gpgme_error_t
gpg_keylist (void *engine, const char *pattern, int secret_only,
gpgme_keylist_mode_t mode)
@@ -1620,6 +1723,13 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ {
+ if ((mode & GPGME_KEYLIST_MODE_LOCAL)
+ || secret_only)
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+ }
+
err = add_arg (gpg, "--with-colons");
if (!err)
err = add_arg (gpg, "--fixed-list-mode");
@@ -1635,10 +1745,20 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
}
if (!err)
- err = add_arg (gpg, secret_only ? "--list-secret-keys"
- : ((mode & GPGME_KEYLIST_MODE_SIGS)
- ? "--check-sigs" : "--list-keys"));
-
+ {
+ if (mode & GPGME_KEYLIST_MODE_EXTERN)
+ {
+ err = add_arg (gpg, "--search-keys");
+ gpg->colon.preprocess_fnc = gpg_keylist_preprocess;
+ }
+ else
+ {
+ err = add_arg (gpg, secret_only ? "--list-secret-keys"
+ : ((mode & GPGME_KEYLIST_MODE_SIGS)
+ ? "--check-sigs" : "--list-keys"));
+ }
+ }
+
/* Tell the gpg object about the data. */
if (!err)
err = add_arg (gpg, "--");