diff options
| author | Marcus Brinkmann <[email protected]> | 2010-01-07 18:16:54 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2010-01-07 18:16:54 +0000 | 
| commit | 77d8ea8916bb415012f438c253876fa75c0b7864 (patch) | |
| tree | 0cf770e0bba66bdf81ca8cae958db0c59217070c /src | |
| parent | Add an API to change passphrases. Currently only implemented for (diff) | |
| download | gpgme-77d8ea8916bb415012f438c253876fa75c0b7864.tar.gz gpgme-77d8ea8916bb415012f438c253876fa75c0b7864.zip | |
2010-01-07  Marcus Brinkmann  <[email protected]>
	* 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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 16 | ||||
| -rw-r--r-- | src/gpgme-tool.c | 664 | 
2 files changed, 651 insertions, 29 deletions
| diff --git a/src/ChangeLog b/src/ChangeLog index 929bbc5f..aee1be08 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,19 @@ +2010-01-07  Marcus Brinkmann  <[email protected]> + +	* 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  <[email protected]>  	* gpgme-tool.c (gt_passwd, cmd_passwd): New. diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index ad647fc9..be35514c 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -498,6 +498,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 <%s>", +	    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    {      STATUS_PROTOCOL, @@ -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;  } | 
