From 3d69b51f7f083193db28f364da4590c33b5e44e6 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 28 Sep 2012 08:31:13 +0200 Subject: [PATCH] gpgme-tool: Return more detailed XML from KEYLIST src/gpgme-tool.c (cmd_keylist): Convert output from a list of to more detailed XML. (xml_preamble1, xml_preamble2, xml_end): Make global. (result_add_protocol, result_add_validity): New functions for generating XML from GPGME types. (result_add_string): Treat NULL strings as "". (result_xml_tag_data): Make 'data' a 'const char' so we can use the value returned by gpgme_get_protocol_name directly. -- This is a first pass at returning most of the gpgme_key_t data from the KEYLIST call. Signed-off-by: W. Trevor King --- src/gpgme-tool.c | 134 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 14 deletions(-) diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index 19dedb6..23122e8 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -565,6 +565,12 @@ skip_options (char *line) typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf, size_t len); +static char xml_preamble1[] = "\n"; +static const char xml_preamble2[] = "\n"; +static const char xml_end[] = "\n"; + + struct result_xml_state { int indent; @@ -653,7 +659,7 @@ result_xml_tag_start (struct result_xml_state *state, char *name, ...) gpg_error_t -result_xml_tag_data (struct result_xml_state *state, char *data) +result_xml_tag_data (struct result_xml_state *state, const char *data) { result_xml_write_cb_t cb = state->cb; void *hook = state->hook; @@ -812,6 +818,60 @@ result_add_sig_mode (struct result_xml_state *state, char *name, } +gpg_error_t +result_add_protocol (struct result_xml_state *state, char *name, + gpgme_protocol_t protocol) +{ + const char *str; + char code[20]; + + snprintf (code, sizeof (code) - 1, "%i", protocol); + str = gpgme_get_protocol_name(protocol); + if (!str) + str = "invalid"; + result_xml_tag_start (state, name, "value", code, NULL); + result_xml_tag_data (state, str); + result_xml_tag_end (state); + return 0; +} + + +gpg_error_t +result_add_validity (struct result_xml_state *state, char *name, + gpgme_validity_t validity) +{ + const char *str; + char code[20]; + + snprintf (code, sizeof (code) - 1, "%i", validity); + switch (validity) + { + case GPGME_VALIDITY_UNDEFINED: + str ="undefined"; + break; + case GPGME_VALIDITY_NEVER: + str ="never"; + break; + case GPGME_VALIDITY_MARGINAL: + str ="marginal"; + break; + case GPGME_VALIDITY_FULL: + str ="full"; + break; + case GPGME_VALIDITY_ULTIMATE: + str ="ultimate"; + break; + default: + str ="unknown"; + } + + result_xml_tag_start (state, name, "value", code, NULL); + result_xml_tag_data (state, str); + result_xml_tag_end (state); + return 0; +} + + gpg_error_t result_add_value (struct result_xml_state *state, char *name, unsigned int val) @@ -829,6 +889,8 @@ gpg_error_t result_add_string (struct result_xml_state *state, char *name, char *str) { + if (!str) + str = ""; result_xml_tag_start (state, name, NULL); result_xml_tag_data (state, str); result_xml_tag_end (state); @@ -1820,10 +1882,6 @@ gt_passwd (gpgme_tool_t gt, char *fpr) gpg_error_t gt_result (gpgme_tool_t gt, unsigned int flags) { - static const char xml_preamble1[] = "\n"; - static const char xml_preamble2[] = "\n"; - static const char xml_end[] = "\n"; int indent = 2; gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1)); @@ -2840,9 +2898,11 @@ cmd_keylist (assuan_context_t ctx, char *line) { #define MAX_CMD_KEYLIST_PATTERN 20 struct server *server = assuan_get_pointer (ctx); + gpgme_tool_t gt = server->gt; + struct result_xml_state state; gpg_error_t err; int secret_only = 0; - int idx; + int idx, indent=2; const char *pattern[MAX_CMD_KEYLIST_PATTERN+1]; const char optstr[] = "--secret-only"; char *p; @@ -2872,10 +2932,19 @@ cmd_keylist (assuan_context_t ctx, char *line) } pattern[idx] = NULL; + gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1)); + gt_write_data (gt, NULL, 0); + gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2)); + gt_write_data (gt, NULL, 0); + result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt); + result_xml_tag_start (&state, "keylist", NULL); + err = gt_keylist_start (server->gt, pattern, secret_only); while (! err) { gpgme_key_t key; + gpgme_subkey_t subkey; + gpgme_user_id_t uid; err = gt_keylist_next (server->gt, &key); if (gpg_err_code (err) == GPG_ERR_EOF) @@ -2885,18 +2954,55 @@ cmd_keylist (assuan_context_t ctx, char *line) } else if (! err) { - char buf[100]; - /* FIXME: More data. */ - snprintf (buf, sizeof (buf), "key:%s\n", key->subkeys->fpr); - /* Write data and flush so that we see one D line for each - key. This does not change the semantics but is easier to - read by organic eyes. */ - if (!assuan_send_data (ctx, buf, strlen (buf))) - assuan_send_data (ctx, NULL, 0); + result_xml_tag_start (&state, "key", NULL); + result_add_value (&state, "revoked", key->revoked); + result_add_value (&state, "expired", key->expired); + result_add_value (&state, "disabled", key->disabled); + result_add_value (&state, "invalid", key->invalid); + result_add_value (&state, "can-encrypt", key->can_encrypt); + result_add_value (&state, "can-sign", key->can_sign); + result_add_value (&state, "can-certify", key->can_certify); + result_add_value (&state, "can-authenticate", key->can_authenticate); + result_add_value (&state, "is-qualified", key->is_qualified); + result_add_value (&state, "secret", key->secret); + result_add_protocol (&state, "protocol", key->protocol); + result_xml_tag_start (&state, "issuer", NULL); + result_add_string (&state, "serial", key->issuer_serial); + result_add_string (&state, "name", key->issuer_name); + result_xml_tag_end (&state); /* issuer */ + result_add_string (&state, "chain_id", key->chain_id); + result_add_validity (&state, "owner-trust", key->owner_trust); + result_xml_tag_start (&state, "subkeys", NULL); + subkey = key->subkeys; + while (subkey) { + result_xml_tag_start (&state, "subkey", NULL); + /* FIXME: more data */ + result_add_fpr (&state, "fpr", subkey->fpr); + result_xml_tag_end (&state); /* subkey */ + subkey = subkey->next; + } + result_xml_tag_end (&state); /* subkeys */ + result_xml_tag_start (&state, "uids", NULL); + uid = key->uids; + while (uid) { + result_xml_tag_start (&state, "uid", NULL); + /* FIXME: more data */ + result_add_string (&state, "uid", uid->uid); + result_add_string (&state, "name", uid->name); + result_add_string (&state, "email", uid->email); + result_add_string (&state, "comment", uid->comment); + result_xml_tag_end (&state); /* uid */ + uid = uid->next; + } + result_xml_tag_end (&state); /* uids */ + result_xml_tag_end (&state); /* key */ gpgme_key_unref (key); } } + result_xml_tag_end (&state); /* keylist */ + gt_write_data (gt, xml_end, sizeof (xml_end)); + server_reset_fds (server); return err; -- 2.26.2