2010-01-07 Marcus Brinkmann <marcus@g10code.de>

* gpgme-tool.c (result_xml_write_cb_t, struct result_xml_state):
	New types.
	(MAX_TAGS): New macro.
	(result_init, result_xml_indent, result_xml_tag_start)
	(result_xml_tag_data, result_xml_tag_end, result_add_error)
	(result_add_pubkey_algo, result_add_hash_algo, result_add_keyid)
	(result_add_fpr, result_add_timestamp, result_add_sig_mode)
	(result_add_value, result_add_string, result_encrypt_to_xml)
	(result_decrypt_to_xml, result_sign_to_xml)
	(result_verify_to_xml, result_import_to_xml)
	(result_genkey_to_xml, result_keylist_to_xml)
	(result_vfs_mount_to_xml): New functions.
	(gt_result): Rewritten.
This commit is contained in:
Marcus Brinkmann 2010-01-07 18:16:54 +00:00
parent 97c5d4d312
commit 77d8ea8916
2 changed files with 651 additions and 29 deletions

View File

@ -1,3 +1,19 @@
2010-01-07 Marcus Brinkmann <marcus@g10code.de>
* gpgme-tool.c (result_xml_write_cb_t, struct result_xml_state):
New types.
(MAX_TAGS): New macro.
(result_init, result_xml_indent, result_xml_tag_start)
(result_xml_tag_data, result_xml_tag_end, result_add_error)
(result_add_pubkey_algo, result_add_hash_algo, result_add_keyid)
(result_add_fpr, result_add_timestamp, result_add_sig_mode)
(result_add_value, result_add_string, result_encrypt_to_xml)
(result_decrypt_to_xml, result_sign_to_xml)
(result_verify_to_xml, result_import_to_xml)
(result_genkey_to_xml, result_keylist_to_xml)
(result_vfs_mount_to_xml): New functions.
(gt_result): Rewritten.
2010-01-05 Werner Koch <wk@g10code.com>
* gpgme-tool.c (gt_passwd, cmd_passwd): New.

View File

@ -497,6 +497,605 @@ log_error (int status, gpg_error_t errnum, const char *fmt, ...)
}
typedef gpg_error_t (*result_xml_write_cb_t) (void *hook, const void *buf,
size_t len);
struct result_xml_state
{
int indent;
result_xml_write_cb_t cb;
void *hook;
#define MAX_TAGS 20
int next_tag;
char *tag[MAX_TAGS];
int had_data[MAX_TAGS];
};
void
result_init (struct result_xml_state *state, int indent,
result_xml_write_cb_t cb, void *hook)
{
memset (state, '\0', sizeof (*state));
state->indent = indent;
state->cb = cb;
state->hook = hook;
}
gpg_error_t
result_xml_indent (struct result_xml_state *state)
{
char spaces[state->indent + 1];
int i;
for (i = 0; i < state->indent; i++)
spaces[i] = ' ';
spaces[i] = '\0';
return (*state->cb) (state->hook, spaces, i);
}
gpg_error_t
result_xml_tag_start (struct result_xml_state *state, char *name, ...)
{
result_xml_write_cb_t cb = state->cb;
void *hook = state->hook;
va_list ap;
char *attr;
char *attr_val;
va_start (ap, name);
if (state->next_tag > 0)
{
if (! state->had_data[state->next_tag - 1])
{
(*cb) (hook, ">\n", 2);
(*cb) (hook, NULL, 0);
}
state->had_data[state->next_tag - 1] = 1;
}
result_xml_indent (state);
(*cb) (hook, "<", 1);
(*cb) (hook, name, strlen (name));
state->tag[state->next_tag] = name;
state->had_data[state->next_tag] = 0;
state->indent += 2;
state->next_tag++;
while (1)
{
attr = va_arg (ap, char *);
if (attr == NULL)
break;
attr_val = va_arg (ap, char *);
if (attr_val == NULL)
attr_val = "(null)";
(*cb) (hook, " ", 1);
(*cb) (hook, attr, strlen (attr));
(*cb) (hook, "=\"", 2);
(*cb) (hook, attr_val, strlen (attr_val));
(*cb) (hook, "\"", 1);
}
va_end (ap);
return 0;
}
gpg_error_t
result_xml_tag_data (struct result_xml_state *state, char *data)
{
result_xml_write_cb_t cb = state->cb;
void *hook = state->hook;
if (state->had_data[state->next_tag - 1])
{
(*cb) (hook, "\n", 2);
(*cb) (hook, NULL, 0);
result_xml_indent (state);
}
else
(*cb) (hook, ">", 1);
state->had_data[state->next_tag - 1] = 2;
(*cb) (hook, data, strlen (data));
return 0;
}
gpg_error_t
result_xml_tag_end (struct result_xml_state *state)
{
result_xml_write_cb_t cb = state->cb;
void *hook = state->hook;
state->next_tag--;
state->indent -= 2;
if (state->had_data[state->next_tag])
{
if (state->had_data[state->next_tag] == 1)
result_xml_indent (state);
(*cb) (hook, "</", 2);
(*cb) (hook, state->tag[state->next_tag],
strlen (state->tag[state->next_tag]));
(*cb) (hook, ">\n", 2);
(*cb) (hook, NULL, 0);
}
else
{
(*cb) (hook, " />\n", 4);
(*cb) (hook, NULL, 0);
}
return 0;
}
gpg_error_t
result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
{
char code[20];
char msg[1024];
snprintf (code, sizeof (code) - 1, "0x%x", err);
snprintf (msg, sizeof (msg) - 1, "%s &lt;%s&gt;",
gpg_strerror (err), gpg_strsource (err));
result_xml_tag_start (state, name, "value", code, NULL);
result_xml_tag_data (state, msg);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_pubkey_algo (struct result_xml_state *state,
char *name, gpgme_pubkey_algo_t algo)
{
char code[20];
char msg[80];
snprintf (code, sizeof (code) - 1, "0x%x", algo);
snprintf (msg, sizeof (msg) - 1, "%s",
gpgme_pubkey_algo_name (algo));
result_xml_tag_start (state, name, "value", code, NULL);
result_xml_tag_data (state, msg);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_hash_algo (struct result_xml_state *state,
char *name, gpgme_hash_algo_t algo)
{
char code[20];
char msg[80];
snprintf (code, sizeof (code) - 1, "0x%x", algo);
snprintf (msg, sizeof (msg) - 1, "%s",
gpgme_hash_algo_name (algo));
result_xml_tag_start (state, name, "value", code, NULL);
result_xml_tag_data (state, msg);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
{
result_xml_tag_start (state, name, NULL);
result_xml_tag_data (state, keyid);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
{
result_xml_tag_start (state, name, NULL);
result_xml_tag_data (state, fpr);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_timestamp (struct result_xml_state *state, char *name,
unsigned int timestamp)
{
char code[20];
snprintf (code, sizeof (code) - 1, "%ui", timestamp);
result_xml_tag_start (state, name, "unix", code);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_sig_mode (struct result_xml_state *state, char *name,
gpgme_sig_mode_t sig_mode)
{
char *mode;
char code[20];
snprintf (code, sizeof (code) - 1, "%i", sig_mode);
switch (sig_mode)
{
case GPGME_SIG_MODE_NORMAL:
mode = "normal";
break;
case GPGME_SIG_MODE_DETACH:
mode = "detach";
break;
case GPGME_SIG_MODE_CLEAR:
mode = "clear";
break;
default:
mode = "unknown";
}
result_xml_tag_start (state, name, "type", mode, "value", code, NULL);
result_xml_tag_data (state, mode);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_value (struct result_xml_state *state,
char *name, unsigned int val)
{
char code[20];
snprintf (code, sizeof (code) - 1, "0x%x", val);
result_xml_tag_start (state, name, "value", code, NULL);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_add_string (struct result_xml_state *state,
char *name, char *str)
{
result_xml_tag_start (state, name, NULL);
result_xml_tag_data (state, str);
result_xml_tag_end (state);
return 0;
}
gpg_error_t
result_encrypt_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_encrypt_result_t res = gpgme_op_encrypt_result (ctx);
gpgme_invalid_key_t inv_recp;
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "encrypt-result", NULL);
inv_recp = res->invalid_recipients;
if (inv_recp)
{
result_xml_tag_start (&state, "invalid-recipients", NULL);
while (inv_recp)
{
result_xml_tag_start (&state, "invalid-key", NULL);
result_add_fpr (&state, "fpr", inv_recp->fpr);
result_add_error (&state, "reason", inv_recp->reason);
result_xml_tag_end (&state);
inv_recp = inv_recp->next;
}
result_xml_tag_end (&state);
}
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_decrypt_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_decrypt_result_t res = gpgme_op_decrypt_result (ctx);
gpgme_recipient_t recp;
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "decrypt-result", NULL);
if (res->file_name)
{
result_xml_tag_start (&state, "file-name", NULL);
result_xml_tag_data (&state, res->file_name);
result_xml_tag_end (&state);
}
if (res->unsupported_algorithm)
{
result_xml_tag_start (&state, "unsupported-alogorithm", NULL);
result_xml_tag_data (&state, res->unsupported_algorithm);
result_xml_tag_end (&state);
}
if (res->wrong_key_usage)
{
result_xml_tag_start (&state, "wrong-key-usage", NULL);
result_xml_tag_end (&state);
}
recp = res->recipients;
if (recp)
{
result_xml_tag_start (&state, "recipients", NULL);
while (recp)
{
result_xml_tag_start (&state, "recipient", NULL);
result_add_keyid (&state, "keyid", recp->keyid);
result_add_pubkey_algo (&state, "pubkey-algo", recp->pubkey_algo);
result_add_error (&state, "status", recp->status);
result_xml_tag_end (&state);
recp = recp->next;
}
result_xml_tag_end (&state);
}
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_sign_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_sign_result_t res = gpgme_op_sign_result (ctx);
gpgme_invalid_key_t inv_key;
gpgme_new_signature_t new_sig;
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "sign-result", NULL);
inv_key = res->invalid_signers;
if (inv_key)
{
result_xml_tag_start (&state, "invalid-signers", NULL);
while (inv_key)
{
result_xml_tag_start (&state, "invalid-key", NULL);
result_add_fpr (&state, "fpr", inv_key->fpr);
result_add_error (&state, "reason", inv_key->reason);
result_xml_tag_end (&state);
inv_key = inv_key->next;
}
result_xml_tag_end (&state);
}
new_sig = res->signatures;
if (new_sig)
{
result_xml_tag_start (&state, "signatures", NULL);
while (new_sig)
{
result_xml_tag_start (&state, "new-signature", NULL);
result_add_sig_mode (&state, "type", new_sig->type);
result_add_pubkey_algo (&state, "pubkey-algo", new_sig->pubkey_algo);
result_add_hash_algo (&state, "hash-algo", new_sig->hash_algo);
result_add_timestamp (&state, "timestamp", new_sig->timestamp);
result_add_fpr (&state, "fpr", new_sig->fpr);
result_add_value (&state, "sig-class", new_sig->sig_class);
result_xml_tag_end (&state);
new_sig = new_sig->next;
}
result_xml_tag_end (&state);
}
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_verify_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_verify_result_t res = gpgme_op_verify_result (ctx);
gpgme_signature_t sig;
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "verify-result", NULL);
if (res->file_name)
{
result_xml_tag_start (&state, "file-name", NULL);
result_xml_tag_data (&state, res->file_name);
result_xml_tag_end (&state);
}
sig = res->signatures;
if (sig)
{
result_xml_tag_start (&state, "signatures", NULL);
while (sig)
{
result_xml_tag_start (&state, "signature", NULL);
// FIXME: Could be done better.
result_add_value (&state, "summary", sig->summary);
result_add_fpr (&state, "fpr", sig->fpr);
result_add_error (&state, "status", sig->status);
// FIXME: notations
result_add_timestamp (&state, "timestamp", sig->timestamp);
result_add_timestamp (&state, "exp-timestamp", sig->exp_timestamp);
result_add_value (&state, "wrong-key-usage", sig->wrong_key_usage);
result_add_value (&state, "pka-trust", sig->pka_trust);
result_add_value (&state, "chain-model", sig->chain_model);
result_add_value (&state, "validity", sig->validity);
result_add_error (&state, "validity-reason", sig->validity_reason);
result_add_pubkey_algo (&state, "pubkey-algo", sig->pubkey_algo);
result_add_hash_algo (&state, "hash-algo", sig->hash_algo);
if (sig->pka_address)
result_add_string (&state, "pka_address", sig->pka_address);
result_xml_tag_end (&state);
sig = sig->next;
}
result_xml_tag_end (&state);
}
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_import_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_import_result_t res = gpgme_op_import_result (ctx);
gpgme_import_status_t stat;
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "import-result", NULL);
result_add_value (&state, "considered", res->considered);
result_add_value (&state, "no-user-id", res->no_user_id);
result_add_value (&state, "imported", res->imported);
result_add_value (&state, "imported-rsa", res->imported_rsa);
result_add_value (&state, "unchanged", res->unchanged);
result_add_value (&state, "new-user-ids", res->new_user_ids);
result_add_value (&state, "new-sub-keys", res->new_sub_keys);
result_add_value (&state, "new-signatures", res->new_signatures);
result_add_value (&state, "new-revocations", res->new_revocations);
result_add_value (&state, "secret-read", res->secret_read);
result_add_value (&state, "secret-imported", res->secret_imported);
result_add_value (&state, "secret-unchanged", res->secret_unchanged);
result_add_value (&state, "skipped-new-keys", res->skipped_new_keys);
result_add_value (&state, "not-imported", res->not_imported);
stat = res->imports;
if (stat)
{
result_xml_tag_start (&state, "imports", NULL);
while (stat)
{
result_xml_tag_start (&state, "import-status", NULL);
result_add_fpr (&state, "fpr", stat->fpr);
result_add_error (&state, "result", stat->result);
// FIXME: Could be done better.
result_add_value (&state, "status", stat->status);
result_xml_tag_end (&state);
stat = stat->next;
}
result_xml_tag_end (&state);
}
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_genkey_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_genkey_result_t res = gpgme_op_genkey_result (ctx);
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "genkey-result", NULL);
result_add_value (&state, "primary", res->primary);
result_add_value (&state, "sub", res->sub);
result_add_fpr (&state, "fpr", res->fpr);
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_keylist_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_keylist_result_t res = gpgme_op_keylist_result (ctx);
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "keylist-result", NULL);
result_add_value (&state, "truncated", res->truncated);
result_xml_tag_end (&state);
return 0;
}
gpg_error_t
result_vfs_mount_to_xml (gpgme_ctx_t ctx, int indent,
result_xml_write_cb_t cb, void *hook)
{
struct result_xml_state state;
gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (ctx);
if (! res)
return 0;
result_init (&state, indent, cb, hook);
result_xml_tag_start (&state, "vfs-mount-result", NULL);
result_add_string (&state, "mount-dir", res->mount_dir);
result_xml_tag_end (&state);
return 0;
}
typedef enum status
{
@ -769,7 +1368,7 @@ gt_write_status (gpgme_tool_t gt, status_t status, ...)
gpg_error_t
gt_write_data (gpgme_tool_t gt, void *buf, size_t len)
gt_write_data (gpgme_tool_t gt, const void *buf, size_t len)
{
return gt->write_data (gt->write_data_hook, buf, len);
}
@ -968,9 +1567,9 @@ gt_sign_encrypt (gpgme_tool_t gt, gpgme_encrypt_flags_t flags,
gpg_error_t err;
if (sign)
err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
else
err = gpgme_op_encrypt_sign (gt->ctx, gt->recipients, flags, plain, cipher);
else
err = gpgme_op_encrypt (gt->ctx, gt->recipients, flags, plain, cipher);
gt_recipients_clear (gt);
@ -1138,9 +1737,6 @@ gt_passwd (gpgme_tool_t gt, char *fpr)
}
/* TODO */
#define GT_RESULT_ENCRYPT 0x1
#define GT_RESULT_DECRYPT 0x2
#define GT_RESULT_SIGN 0x4
@ -1154,31 +1750,41 @@ 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[] = "<?xml version=\"1.0\" "
"encoding=\"UTF-8\" standalone=\"yes\"?>\n";
static const char xml_preamble2[] = "<gpgme>\n";
static const char xml_end[] = "</gpgme>\n";
int indent = 2;
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);
if (flags & GT_RESULT_ENCRYPT)
{
gpgme_encrypt_result_t res = gpgme_op_encrypt_result (gt->ctx);
if (res)
{
gpgme_invalid_key_t invrec = res->invalid_recipients;
while (invrec)
{
gt_write_status (gt, STATUS_ENCRYPT_RESULT, "invalid_recipient",
invrec->fpr, invrec->reason, NULL);
invrec = invrec->next;
}
}
}
result_encrypt_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_DECRYPT)
result_decrypt_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_SIGN)
result_sign_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_VERIFY)
result_verify_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_IMPORT)
result_import_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_GENKEY)
result_genkey_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_KEYLIST)
result_keylist_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
if (flags & GT_RESULT_VFS_MOUNT)
{
gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result (gt->ctx);
if (res)
{
gt_write_data (gt, "vfs_mount\n", 10);
gt_write_data (gt, "mount_dir:", 10);
gt_write_data (gt, res->mount_dir, strlen (res->mount_dir));
gt_write_data (gt, "\n", 1);
}
}
result_vfs_mount_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
gt_write_data (gt, xml_end, sizeof (xml_end));
return 0;
}