doc/
authorMarcus Brinkmann <mb@g10code.com>
Wed, 30 Apr 2003 03:02:50 +0000 (03:02 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Wed, 30 Apr 2003 03:02:50 +0000 (03:02 +0000)
2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

* gpgme.texi (Key Listing Mode): Add GPGME_KEYLIST_MODE_SIGS.
(Manipulating Keys): Add obsoleteness note.
(Key Signatures): Likewise.
(Information About Keys): Likewise.
(Key Management): Add new data types GpgmeSubkey, GpgmeKeySig,
GpgmeUserID, and all the information about GpgmeKey.

gpgme/
2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

* gpgme.h (struct _gpgme_key): New structure.
(GpgmeKey): Define using _gpgme_key.
(struct _gpgme_subkey): New structure.
(GpgmeSubKey): New type.
(struct _gpgme_key_sig): New structure.
(GpgmeKeySig): New type.
(struct _gpgme_user_id): New structure.
(GpgmeUserID): New type.
(struct _gpgme_op_keylist_result): New structure.
(GpgmeKeyListResult): New type.
(gpgme_op_keylist_result): New function.
(gpgme_key_get_as_xml): Remove prototype.
* context.h (struct gpgme_context_s): Remove members tmp_key,
tmp_uid, key_cond and key_queue.
(struct key_queue_item_s): Remove structure.
(struct user_id_s): Remove structure.
(struct gpgme_recipients_s): Replace with simple
GpgmeUserID list.
* gpgme.c (gpgme_release): Do not release CTX->tmp_key.
* ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name,
_gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes.
* rungpg.c (command_cb): Return GpgmeError instead int.
New variable ERR.  Use it to hold return value of cmd handler.
(gpg_delete): Access fingerprint of key directly.
(append_args_from_signers): Likewise.
(gpg_edit): Likewise.
(append_args_from_recipients): Use GpgmeUserID for recipient list.
* engine-gpgsm.c: Do not include "key.h".
(gpgsm_delete): Access fingerprint of key directly.
(gpgsm_sign): Likewise.
(set_recipients): Use GpgmeUserID for recipients.  Invert invalid
user ID flag.
* key.h: File removed.
* key.c: Completely reworked to use exposed GpgmeKey data types.
* keylist.c: Likewise.
* recipient.c: Completely reworked to use GpgmeUserID.

tests/
2003-04-30  Marcus Brinkmann  <marcus@g10code.de>

* gpg/t-keylist.c: Rewritten.
* gpgsm/t-keylist.c (main): Rewritten.
* gpg/t-edit.c (main): Do not use gpgme_key_get_as_xml.  Use
gpgme_key_unref instead gpgme_key_release.
* gpg/t-signers.c (main): Use gpgme_key_unref instead
gpgme_key_release.

20 files changed:
NEWS
doc/ChangeLog
doc/gpgme.texi
gpgme/ChangeLog
gpgme/context.h
gpgme/engine-gpgsm.c
gpgme/gpgme.c
gpgme/gpgme.h
gpgme/key.c
gpgme/keylist.c
gpgme/ops.h
gpgme/recipient.c
gpgme/rungpg.c
gpgme/trust-item.c
gpgme/trustlist.c
tests/ChangeLog
tests/gpg/t-edit.c
tests/gpg/t-keylist.c
tests/gpg/t-signers.c
tests/gpgsm/t-keylist.c

diff --git a/NEWS b/NEWS
index 92f3855..98cee17 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ Noteworthy changes in version 0.4.1 (unreleased)
  * GPGME_ATTR_IS_SECRET is not anymore representable as a string.
 
  * gpgme_op_verify and gpgme_op_decrypt_verify don't return a status
-   summary anymore.  Use gpgme_get_sig_status to retrieve the individual stati.
+   summary anymore.  Use gpgme_get_sig_status to retrieve the individual
+   stati.
 
  * GpgmeIOCb changed from a void function to a function returning a
    GpgmeError value.  However, it will always return 0, so you can
@@ -87,7 +88,7 @@ Noteworthy changes in version 0.4.1 (unreleased)
    a GpgmeEncryptResult object.
 
  * The new gpgme_op_decrypt_result function provides detailed
-   information about the result of an encryption operation in
+   information about the result of a decryption operation in
    a GpgmeDecryptResult object.
 
  * The new gpgme_op_verify_result function provides detailed
@@ -106,6 +107,19 @@ Noteworthy changes in version 0.4.1 (unreleased)
  * Keys are not cached internally anymore, so the force_update argument
    to gpgme_get_key has been removed.
 
+ * GpgmeKey objects have now directly accessible data so the
+   gpgme_key_get_string_attr, gpgme_key_get_ulong_attr,
+   gpgme_key_sig_get_string_attr and gpgme_key_sig_get_ulong_attr
+   functions are deprecated.  Also, gpgme_key_release is now
+   deprecated.  The gpgme_key_get_as_xml function has been dropped.
+
+ * Because all interfaces using attributes are deprecated, the
+   GpgmeAttr data type is also deprecated.
+
+ * The new gpgme_op_keylist_result function provides detailed
+   information about the result of a key listing operation in
+   a GpgmeKeyListResult object.
+
  * Interface changes relative to the 0.4.0 release:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 GpgmeIOCb                      CHANGED: Return type from void to GpgmeError.
@@ -163,6 +177,17 @@ gpgme_trust_item_release   DEPRECATED: Use gpgme_trust_item_unref.
 gpgme_trust_item_get_string_attr DEPRECATED
 gpgme_trust_item_get_ulong_attr        DEPRECATED
 gpgme_get_key                  CHANGED: Removed force_update argument.
+GpgmeSubKey                    NEW
+GpgmeKeySig                    NEW
+GpgmeUserID                    NEW
+GpgmeKey                       CHANGED: Now has user accessible data members.
+gpgme_key_get_string_attr      DEPRECATED
+gpgme_key_get_ulong_attr       DEPRECATED
+gpgme_key_sig_get_string_attr  DEPRECATED
+gpgme_key_sig_get_ulong_attr   DEPRECATED
+gpgme_key_get_as_xml           REMOVED
+GpgmeKeyListResult             NEW
+gpgme_op_keylist_result                NEW
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Noteworthy changes in version 0.4.0 (2002-12-23)
index 6d69fa7..94d8f19 100644 (file)
@@ -1,3 +1,12 @@
+2003-04-30  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgme.texi (Key Listing Mode): Add GPGME_KEYLIST_MODE_SIGS.
+       (Manipulating Keys): Add obsoleteness note.
+       (Key Signatures): Likewise.
+       (Information About Keys): Likewise.
+       (Key Management): Add new data types GpgmeSubkey, GpgmeKeySig,
+       GpgmeUserID, and all the information about GpgmeKey.
+
 2003-04-29  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.texi (Listing Keys): Remove force_update argument from
index 6ba9163..2107e84 100644 (file)
@@ -1647,6 +1647,10 @@ source should be should be searched for keys in the keylisting
 operation.  The type of external source is dependant on the crypto
 engine used.  For example, it can be a remote keyserver or LDAP
 certificate server.
+
+@item GPGME_KEYLIST_MODE_SIGS
+The @code{GPGME_KEYLIST_MODE_SIGS} symbol specifies that the key
+signatures should be included in the listed keys.
 @end table
 
 At least one of @code{GPGME_KEYLIST_MODE_LOCAL} and
@@ -1785,11 +1789,230 @@ signers are specified.  This is always done by specifying the
 respective keys that should be used for the operation.  The following
 section describes how such keys can be selected and manipulated.
 
+@deftp {Data type} GpgmeSubkey
+The @code{GpgmeSubKey} type is a pointer to a subkey structure.  Sub
+keys are one component of a @code{GpgmeKey} object.  In fact, subkeys
+are those parts that contains the real information about the
+individual cryptographic keys that belong to the same key object.  One
+@code{GpgmeKey} can contain several subkeys.  The first subkey in the
+linked list is also called the primary key.
+
+The subkey structure has the following members:
+
+@table @code
+@item GpgmeSubkey next
+This is a pointer to the next subkey structure in the linked list, or
+@code{NULL} if this is the last element.
+
+@item unsigned int revoked : 1
+This is true if the subkey is revoked.
+
+@item unsigned int expired : 1
+This is true if the subkey is expired.
+
+@item unsigned int disabled : 1
+This is true if the subkey is disabled.
+
+@item unsigned int invalid : 1
+This is true if the subkey is invalid.
+
+@item unsigned int can_encrypt : 1
+This is true if the subkey can be used for encryption.
+
+@item unsigned int can_sign : 1
+This is true if the subkey can be used for signing.
+
+@item unsigned int can_certify : 1
+This is true if the subkey can be used for certification.
+
+@item unsigned int secret : 1
+This is true if the subkey is a secret key.
+
+@item GpgmePubKeyAlgo pubkey_algo
+This is the public key algorithm supported by this subkey.
+
+@item unsigned int length
+This is the length of the subkey (in bits).
+
+@item char *keyid
+This is the key ID of the subkey in hexadecimal digits.
+
+@item char *fpr
+This is the fingerprint of the subkey in hexadecimal digits, if
+available.  This is usually only available for the primary key.
+
+@item long int timestamp
+This is the creation timestamp of the subkey.  This is -1 if the
+timestamp is invalid, and 0 if it is not available.
+
+@item long int expires
+This is the expiration timestamp of the subkey, or 0 if the subkey
+does not expire.
+@end table
+@end deftp
+
+@deftp {Data type} GpgmeKeySig
+The @code{GpgmeKeySig} type is a pointer to a key signature structure.
+Key signatures are one component of a @code{GpgmeKey} object, and
+validate user IDs on the key.
+
+The signatures on a key are only available if the key was retrieved
+via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
+enabled, because it is expensive to retrieve all signatures of a key.
+
+The key signature structure has the following members:
+
+@table @code
+@item GpgmeKeySig next
+This is a pointer to the next key signature structure in the linked
+list, or @code{NULL} if this is the last element.
+
+@item unsigned int revoked : 1
+This is true if the key signature is a revocation signature.
+
+@item unsigned int expired : 1
+This is true if the key signature is expired.
+
+@item unsigned int invalid : 1
+This is true if the key signature is invalid.
+
+@item unsigned int disabled : 1
+This is true if the key signature is exportable.
+
+@item GpgmePubKeyAlgo pubkey_algo
+This is the public key algorithm used to create the signature.
+
+@item char *keyid
+This is the key ID of the key (in hexadecimal digits) used to create
+the signature.
+
+@item long int timestamp
+This is the creation timestamp of the key signature.  This is -1 if
+the timestamp is invalid, and 0 if it is not available.
+
+@item long int expires
+This is the expiration timestamp of the key signature, or 0 if the key
+signature does not expire.
+
+@item GpgmeError status
+This is the status of the signature and has the same meaning as the
+member of the same name in a @code{GpgmeSignature} object.
+
+@item unsigned int class
+This specifies the signature class of the key signature.  The meaning
+is specific to the crypto engine.
+
+@item char *uid
+This is the main user ID of the key used to create the signature.
+
+@item char *name
+This is the name component of @code{uid}, if available.
+
+@item char *comment
+This is the comment component of @code{uid}, if available.
+
+@item char *email
+This is the email component of @code{uid}, if available.
+@end table
+@end deftp
+
+@deftp {Data type} GpgmeUserID
+A user ID is a component of a @code{GpgmeKey} object.  One key can
+have many user IDs.  The first one in the list is the main (or
+primary) user ID.
+
+The user ID structure has the following members.
+
+@table @code
+@item GpgmeUserID next
+This is a pointer to the next user ID structure in the linked list, or
+@code{NULL} if this is the last element.
+
+@item unsigned int revoked : 1
+This is true if the user ID is revoked.
+
+@item unsigned int invalid : 1
+This is true if the user ID is invalid.
+
+@item GpgmeValidity validity
+This specifies the validity of the user ID.
+
+@item char *uid
+This is the user ID string.
+
+@item char *name
+This is the name component of @code{uid}, if available.
+
+@item char *comment
+This is the comment component of @code{uid}, if available.
+
+@item char *email
+This is the email component of @code{uid}, if available.
+
+@item GpgmeKeySig signatures
+This is a linked list with the signatures on this user ID.
+@end table
+@end deftp
+
 @deftp {Data type} GpgmeKey
-The @code{GpgmeKey} type is a handle for a public or secret key, and
-is used to select the key for operations involving it.
+The @code{GpgmeKey} type is a pointer to a key object.  It has the
+following members:
+
+@table @code
+@item unsigned int revoked : 1
+This is true if the key is revoked.
+
+@item unsigned int expired : 1
+This is true if the key is expired.
+
+@item unsigned int disabled : 1
+This is true if the key is disabled.
+
+@item unsigned int invalid : 1
+This is true if the key is invalid.
+
+@item unsigned int can_encrypt : 1
+This is true if the key (ie one of its subkeys) can be used for
+encryption.
 
-A key can contain several user IDs and sub keys.
+@item unsigned int can_sign : 1
+This is true if the key (ie one of its subkeys) can be used for
+signing.
+
+@item unsigned int can_certify : 1
+This is true if the key (ie one of its subkeys) can be used for
+certification.
+
+@item unsigned int secret : 1
+This is true if the key is a secret key.
+
+@item GpgmeProtocol protocol
+This is the protocol supported by this key.
+
+@item char *issuer_serial
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+issuer serial.
+
+@item char *issuer_name
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+issuer name.
+
+@item char *chain_id
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+chain ID, which can be used to built the certificate chain.
+@item GpgmeValidity owner_trust
+If @code{protocol} is @code{GPGME_PROTOCOL_OpenPGP}, then this is the
+owner trust.
+
+@item GpgmeSubkey subkeys
+This is a linked list with the subkeys of the key.  The first subkey
+in the list is the primary key and usually available.
+
+@item GpgmeUserID uids
+This is a linked list with the user IDs of the key.  The first user ID
+in the list is the main (or primary) user ID.
+@end table
 @end deftp
 
 @menu
@@ -1880,6 +2103,10 @@ there is not enough memory for the operation.
 The function @code{gpgme_op_keylist_next} ends a pending key list
 operation in the context @var{ctx}.
 
+After the operation completed successfully, the result of the key
+listing operation can be retrieved with
+@code{gpgme_op_keylist_result}.
+
 The function returns @code{GPGME_Invalid_Value} if @var{ctx} is not a
 valid pointer, and @code{GPGME_Out_Of_Core} if at some time during the
 operation there was not enough memory available.
@@ -1914,6 +2141,29 @@ if (err)
   @}
 @end example
 
+@deftp {Data type} {GpgmeKeyListResult}
+This is a pointer to a structure used to store the result of a
+@code{gpgme_op_keylist_*} operation.  After successfully ending a key
+listing operation, you can retrieve the pointer to the result with
+@code{gpgme_op_keylist_result}.  The structure contains the following
+member:
+
+@table @code
+@item unsigned int truncated : 1
+This is true if the crypto backend had to truncate the result, and
+less than the desired keys could be listed.
+@end table
+@end deftp
+
+@deftypefun GpgmeKeyListResult gpgme_op_keylist_result (@w{GpgmeCtx @var{ctx}})
+The function @code{gpgme_op_keylist_result} returns a
+@code{GpgmeKeyListResult} pointer to a structure holding the result of
+a @code{gpgme_op_keylist_*} operation.  The pointer is only valid if
+the last operation on the context was a key listing operation, and if
+this operation finished successfully.  The returned pointer is only
+valid until the next operation is started on the context.
+@end deftypefun
+
 In a simple program, for which a blocking operation is acceptable, the
 following function can be used to retrieve a single key.
 
@@ -1939,14 +2189,44 @@ available.
 @cindex key, attributes
 @cindex attributes, of a key
 
-@deftypefun {char *} gpgme_key_get_as_xml (@w{GpgmeKey @var{key}})
-The function @code{gpgme_key_get_as_xml} returns a string in
-@acronym{XML} format describing the key @var{key}.  The user has to
-release the string with @code{free}.
+Please see the beginning of this section for more information about
+@code{GpgmeKey} objects.
 
-The function returns @code{NULL} if @var{key} is not a valid pointer,
-or there is not enough memory available.
-@end deftypefun
+@deftp {Data type} GpgmeValidity
+The @code{GpgmeValidity} type is used to specify the validity of a user ID
+in a key.  The following validities are defined:
+
+@table @code
+@item GPGME_VALIDITY_UNKNOWN
+The user ID is of unknown validity.  The string representation of this
+validity is ``?''.
+
+@item GPGME_VALIDITY_UNDEFINED
+The validity of the user ID is undefined.  The string representation of this
+validity is ``q''.
+
+@item GPGME_VALIDITY_NEVER
+The user ID is never valid.  The string representation of this
+validity is ``n''.
+
+@item GPGME_VALIDITY_MARGINAL
+The user ID is marginally valid.  The string representation of this
+validity is ``m''.
+
+@item GPGME_VALIDITY_FULL
+The user ID is fully valid.  The string representation of this
+validity is ``f''.
+
+@item GPGME_VALIDITY_ULTIMATE
+The user ID is ultimately valid.  The string representation of this
+validity is ``u''.
+@end table
+@end deftp
+
+
+The following interfaces are deprecated and only provided for backward
+compatibility.  Don't use them.  They will be removed in a future
+version of @acronym{GPGME}.
 
 @deftp {Data type} GpgmeAttr
 The @code{GpgmeAttr} type is used to specify a key or trust item
@@ -2080,37 +2360,6 @@ is representable as a string.
 @end table
 @end deftp
 
-@deftp {Data type} GpgmeValidity
-The @code{GpgmeValidity} type is used to specify the validity of a user ID
-in a key.  The following validities are defined:
-
-@table @code
-@item GPGME_VALIDITY_UNKNOWN
-The user ID is of unknown validity.  The string representation of this
-validity is ``?''.
-
-@item GPGME_VALIDITY_UNDEFINED
-The validity of the user ID is undefined.  The string representation of this
-validity is ``q''.
-
-@item GPGME_VALIDITY_NEVER
-The user ID is never valid.  The string representation of this
-validity is ``n''.
-
-@item GPGME_VALIDITY_MARGINAL
-The user ID is marginally valid.  The string representation of this
-validity is ``m''.
-
-@item GPGME_VALIDITY_FULL
-The user ID is fully valid.  The string representation of this
-validity is ``f''.
-
-@item GPGME_VALIDITY_ULTIMATE
-The user ID is ultimately valid.  The string representation of this
-validity is ``u''.
-@end table
-@end deftp
-
 @deftypefun {const char *} gpgme_key_get_string_attr (@w{GpgmeKey @var{key}}, @w{GpgmeAttr @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
 The function @code{gpgme_key_get_string_attr} returns the value of the
 string-representable attribute @var{what} of key @var{key}.  If the
@@ -2145,6 +2394,10 @@ or @var{reserved} not @code{NULL}.
 @cindex key, signatures
 @cindex signatures, on a key
 
+The following interfaces are deprecated and only provided for backward
+compatibility.  Don't use them.  They will be removed in a future
+version of @acronym{GPGME}.
+
 The signatures on a key are only available if the key was retrieved
 via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
 enabled, because it is expensive to retrieve all signatures of a key.
@@ -2253,12 +2506,18 @@ the key @var{key}.
 @end deftypefun
 
 @deftypefun void gpgme_key_unref (@w{GpgmeKey @var{key}})
-@deftypefunx void gpgme_key_release (@w{GpgmeKey @var{key}})
 The function @code{gpgme_key_unref} releases a reference for the key
 @var{key}.  If this was the last reference, the key will be destroyed
 and all resources associated to it will be released.
+@end deftypefun
+
+
+The following interface is deprecated and only provided for backward
+compatibility.  Don't use it.  It will be removed in a future version
+of @acronym{GPGME}.
 
-The function @code{gpgme_key_release} is an alias for
+@deftypefun void gpgme_key_release (@w{GpgmeKey @var{key}})
+The function @code{gpgme_key_release} is equivalent to
 @code{gpgme_key_unref}.
 @end deftypefun
 
@@ -2610,10 +2869,10 @@ value of 2 refers to a user ID.
 @item int level
 This is the trust level.
 
-@item char *otrust
+@item char *owner_trust
 The owner trust if @code{type} is 1.
 
-@item char *val
+@item char *validity
 The calculated validity.
 
 @item char *name
index c9c4770..0d354f2 100644 (file)
@@ -1,3 +1,42 @@
+2003-04-30  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpgme.h (struct _gpgme_key): New structure.
+       (GpgmeKey): Define using _gpgme_key.
+       (struct _gpgme_subkey): New structure.
+       (GpgmeSubKey): New type.
+       (struct _gpgme_key_sig): New structure.
+       (GpgmeKeySig): New type.
+       (struct _gpgme_user_id): New structure.
+       (GpgmeUserID): New type.
+       (struct _gpgme_op_keylist_result): New structure.
+       (GpgmeKeyListResult): New type.
+       (gpgme_op_keylist_result): New function.
+       (gpgme_key_get_as_xml): Remove prototype.
+       * context.h (struct gpgme_context_s): Remove members tmp_key,
+       tmp_uid, key_cond and key_queue.
+       (struct key_queue_item_s): Remove structure.
+       (struct user_id_s): Remove structure.
+       (struct gpgme_recipients_s): Replace with simple
+       GpgmeUserID list.
+       * gpgme.c (gpgme_release): Do not release CTX->tmp_key.
+       * ops.h (_gpgme_key_add_subkey, _gpgme_key_append_name,
+       _gpgme_key_add_sig, _gpgme_trust_item_new): New prototypes.
+       * rungpg.c (command_cb): Return GpgmeError instead int.
+       New variable ERR.  Use it to hold return value of cmd handler.
+       (gpg_delete): Access fingerprint of key directly.
+       (append_args_from_signers): Likewise.
+       (gpg_edit): Likewise.
+       (append_args_from_recipients): Use GpgmeUserID for recipient list.
+       * engine-gpgsm.c: Do not include "key.h".
+       (gpgsm_delete): Access fingerprint of key directly.
+       (gpgsm_sign): Likewise.
+       (set_recipients): Use GpgmeUserID for recipients.  Invert invalid
+       user ID flag.
+       * key.h: File removed.
+       * key.c: Completely reworked to use exposed GpgmeKey data types.
+       * keylist.c: Likewise.
+       * recipient.c: Completely reworked to use GpgmeUserID.
+
 2003-04-29  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpgme.h (gpgme_get_key): Remove force_update argument.
index 43557f7..342b5c3 100644 (file)
@@ -56,15 +56,8 @@ struct ctx_op_data
 };
 
 \f
-struct key_queue_item_s
-{
-  struct key_queue_item_s *next;
-  GpgmeKey key;
-};
-
-
-/* Currently we need it at several places, so we put the definition
-   into this header file.  */
+/* The context defines an environment in which crypto operations can
+   be performed (sequentially).  */
 struct gpgme_context_s
 {
   /* The protocol used by this context.  */
@@ -98,13 +91,6 @@ struct gpgme_context_s
   /* Last operation info.  */
   GpgmeData op_info;
 
-  /* Used by keylist.c.  */
-  GpgmeKey tmp_key;
-  struct user_id_s *tmp_uid;
-  /* Something new is available.  */
-  volatile int key_cond;
-  struct key_queue_item_s *key_queue;
-
   /* The user provided passphrase callback and its hook value.  */
   GpgmePassphraseCb passphrase_cb;
   void *passphrase_cb_value;
@@ -119,31 +105,12 @@ struct gpgme_context_s
   struct GpgmeIOCbs io_cbs;
 };
 
-/* Forward declaration of a structure to store certification
-   signatures.  */
-struct certsig_s;
-
-/* Structure to store user IDs.  */
-struct user_id_s
-{
-  struct user_id_s *next;
-  unsigned int revoked : 1;
-  unsigned int invalid : 1;
-  GpgmeValidity validity; 
-  struct certsig_s *certsigs;
-  struct certsig_s *last_certsig;
-  const char *name_part;       /* All 3 point into strings behind name  */
-  const char *email_part;      /* or to read-only strings.  */
-  const char *comment_part;
-  char name[1];
-};
-
 
+/* A recipient is defined by a user ID, but we define it as an opaque
+   type for the user.  */
 struct gpgme_recipients_s
 {
-  struct user_id_s *list;
-  int checked; /* Whether the recipients are all valid.  */
+  GpgmeUserID list;
 };
 
-
 #endif /* CONTEXT_H */
index a09d234..a5a0b7f 100644 (file)
@@ -35,7 +35,6 @@
 #include "ops.h"
 #include "wait.h"
 #include "io.h"
-#include "key.h"
 #include "sema.h"
 
 #include "assuan.h"
@@ -873,7 +872,7 @@ gpgsm_delete (void *engine, GpgmeKey key, int allow_secret)
 {
   GpgsmObject gpgsm = engine;
   GpgmeError err;
-  char *fpr = (char *) gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
+  char *fpr = key->subkeys ? key->subkeys->fpr : NULL;
   char *linep = fpr;
   char *line;
   int length = 8;      /* "DELKEYS " */
@@ -942,17 +941,17 @@ set_recipients (GpgsmObject gpgsm, GpgmeRecipients recp)
   ASSUAN_CONTEXT ctx = gpgsm->assuan_ctx;
   char *line;
   int linelen;
-  struct user_id_s *r;
-  int valid_recipients = 0;
+  GpgmeUserID uid;
+  int invalid_recipients = 0;
 
   linelen = 10 + 40 + 1;       /* "RECIPIENT " + guess + '\0'.  */
   line = malloc (10 + 40 + 1);
   if (!line)
     return GPGME_Out_Of_Core;
   strcpy (line, "RECIPIENT ");
-  for (r = recp->list; r; r = r->next)
+  for (uid = recp->list; uid; uid = uid->next)
     {
-      int newlen = 11 + strlen (r->name);
+      int newlen = 11 + strlen (uid->uid);
       if (linelen < newlen)
        {
          char *newline = realloc (line, newlen);
@@ -964,22 +963,20 @@ set_recipients (GpgsmObject gpgsm, GpgmeRecipients recp)
          line = newline;
          linelen = newlen;
        }
-      strcpy (&line[10], r->name);
+      strcpy (&line[10], uid->uid);
       
       err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc,
                                         gpgsm->status.fnc_value);
-      if (!err)
-       valid_recipients = 1;
-      else if (err != GPGME_Invalid_Key)
+      if (err == GPGME_Invalid_Key)
+       invalid_recipients = 1;
+      else if (err)
        {
          free (line);
          return err;
        }
     }
   free (line);
-  if (!valid_recipients && gpgsm->status.fnc)
-    gpgsm->status.fnc (gpgsm->status.fnc_value, GPGME_STATUS_NO_RECP, "");
-  return 0;
+  return invalid_recipients ? GPGME_Invalid_UserID : 0;
 }
 
 
@@ -1302,8 +1299,7 @@ gpgsm_sign (void *engine, GpgmeData in, GpgmeData out, GpgmeSigMode mode,
 
   for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
     {
-      const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR,
-                                                NULL, 0);
+      const char *s = key->subkeys ? key->subkeys->fpr : NULL;
       if (s && strlen (s) < 80)
        {
           char buf[100];
index dbcd406..005d137 100644 (file)
@@ -67,11 +67,9 @@ gpgme_release (GpgmeCtx ctx)
   _gpgme_engine_release (ctx->engine);
   _gpgme_fd_table_deinit (&ctx->fdt);
   _gpgme_release_result (ctx);
-  gpgme_key_release (ctx->tmp_key);
   gpgme_signers_clear (ctx);
   if (ctx->signers)
     free (ctx->signers);
-  /* FIXME: Release the key_queue.  */
   free (ctx);
 }
 
index b119360..f9ff990 100644 (file)
@@ -63,10 +63,8 @@ typedef struct gpgme_data_s *GpgmeData;
 struct gpgme_recipients_s;
 typedef struct gpgme_recipients_s *GpgmeRecipients;
 
-/* A key from the keyring.  */
-struct gpgme_key_s;
-typedef struct gpgme_key_s *GpgmeKey;
-
+\f
+/* Public data types provided by GPGME.  */
 
 /* The error numbers used by GPGME.  */
 typedef enum
@@ -343,6 +341,7 @@ typedef enum
   }
 GpgmeStatusCode;
 
+\f
 /* The engine information structure.  */
 struct _gpgme_engine_info
 {
@@ -362,7 +361,221 @@ struct _gpgme_engine_info
 };
 typedef struct _gpgme_engine_info *GpgmeEngineInfo;
 
+\f
+/* A subkey from a key.  */
+struct _gpgme_subkey
+{
+  struct _gpgme_subkey *next;
+
+  /* True if subkey is revoked.  */
+  unsigned int revoked : 1;
+
+  /* True if subkey is expired.  */
+  unsigned int expired : 1;
+
+  /* True if subkey is disabled.  */
+  unsigned int disabled : 1;
+
+  /* True if subkey is invalid.  */
+  unsigned int invalid : 1;
+
+  /* True if subkey can be used for encryption.  */
+  unsigned int can_encrypt : 1;
+
+  /* True if subkey can be used for signing.  */
+  unsigned int can_sign : 1;
+
+  /* True if subkey can be used for certification.  */
+  unsigned int can_certify : 1;
+
+  /* True if subkey is secret.  */
+  unsigned int secret : 1;
 
+  /* Internal to GPGME, do not use.  */
+  unsigned int _unused : 24;
+  
+  /* Public key algorithm supported by this subkey.  */
+  GpgmePubKeyAlgo pubkey_algo;
+
+  /* Length of the subkey.  */
+  unsigned int length;
+
+  /* The key ID of the subkey.  */
+  char *keyid;
+
+  /* Internal to GPGME, do not use.  */
+  char _keyid[16 + 1];
+
+  /* The fingerprint of the subkey in hex digit form.  */
+  char *fpr;
+
+  /* The creation timestamp, -1 if invalid, 0 if not available.  */
+  long int timestamp;
+
+  /* The expiration timestamp, 0 if the subkey does not expire.  */
+  long int expires;
+};
+typedef struct _gpgme_subkey *GpgmeSubkey;
+
+/* A signature on a user ID.  */
+struct _gpgme_key_sig
+{
+  struct _gpgme_key_sig *next;
+
+  /* True if the signature is revoked.  */
+  unsigned int revoked : 1;
+
+  /* True if the signature is expired.  */
+  unsigned int expired : 1;
+
+  /* True if the signature is invalid.  */
+  unsigned int invalid : 1;
+
+  /* True if the signature should be exported.  */
+  unsigned int exportable : 1;
+
+  /* Internal to GPGME, do not use.  */
+  unsigned int _unused : 28;
+
+  /* The public key algorithm used to create the signature.  */
+  GpgmePubKeyAlgo pubkey_algo;
+
+  /* The key ID of key used to create the signature.  */
+  char *keyid;
+
+  /* Internal to GPGME, do not use.  */
+  char _keyid[16 + 1];
+
+  /* The creation timestamp, -1 if invalid, 0 if not available.  */
+  long int timestamp;
+
+  /* The expiration timestamp, 0 if the subkey does not expire.  */
+  long int expires;
+
+  /* Same as in GpgmeSignature.  */
+  GpgmeError status;
+
+  /* Crypto backend specific signature class.  */
+  unsigned int class;
+
+  /* The user ID string.  */
+  char *uid;
+
+  /* The name part of the user ID.  */
+  char *name;
+
+  /* The email part of the user ID.  */
+  char *email;
+
+  /* The comment part of the user ID.  */
+  char *comment;
+};
+typedef struct _gpgme_key_sig *GpgmeKeySig;
+
+/* An user ID from a key.  */
+struct _gpgme_user_id
+{
+  struct _gpgme_user_id *next;
+
+  /* True if the user ID is revoked.  */
+  unsigned int revoked : 1;
+
+  /* True if the user ID is invalid.  */
+  unsigned int invalid : 1;
+
+  /* Internal to GPGME, do not use.  */
+  unsigned int _unused : 30;
+
+  /* The validity of the user ID.  */
+  GpgmeValidity validity; 
+
+  /* The user ID string.  */
+  char *uid;
+
+  /* The name part of the user ID.  */
+  char *name;
+
+  /* The email part of the user ID.  */
+  char *email;
+
+  /* The comment part of the user ID.  */
+  char *comment;
+
+  /* The signatures of the user ID.  */
+  GpgmeKeySig signatures;
+
+  /* Internal to GPGME, do not use.  */
+  GpgmeKeySig _last_keysig;
+};
+typedef struct _gpgme_user_id *GpgmeUserID;
+
+/* A key from the keyring.  */
+struct _gpgme_key
+{
+  /* Internal to GPGME, do not use.  */
+  unsigned int _refs;
+
+  /* True if key is revoked.  */
+  unsigned int revoked : 1;
+
+  /* True if key is expired.  */
+  unsigned int expired : 1;
+
+  /* True if key is disabled.  */
+  unsigned int disabled : 1;
+
+  /* True if key is invalid.  */
+  unsigned int invalid : 1;
+
+  /* True if key can be used for encryption.  */
+  unsigned int can_encrypt : 1;
+
+  /* True if key can be used for signing.  */
+  unsigned int can_sign : 1;
+
+  /* True if key can be used for certification.  */
+  unsigned int can_certify : 1;
+
+  /* True if key is secret.  */
+  unsigned int secret : 1;
+
+  /* Internal to GPGME, do not use.  */
+  unsigned int _unused : 24;
+
+  /* This is the protocol supported by this key.  */
+  GpgmeProtocol protocol;
+
+  /* If protocol is GPGME_PROTOCOL_CMS, this string contains the
+     issuer serial.  */
+  char *issuer_serial;
+
+  /* If protocol is GPGME_PROTOCOL_CMS, this string contains the
+     issuer name.  */
+  char *issuer_name;
+
+  /* If protocol is GPGME_PROTOCOL_CMS, this string contains the chain
+     ID.  */
+  char *chain_id;
+
+  /* If protocol is GPGME_PROTOCOL_OpenPGP, this field contains the
+     owner trust.  */
+  GpgmeValidity owner_trust;
+
+  /* The subkeys of the key.  */
+  GpgmeSubkey subkeys;
+
+  /* The user IDs of the key.  */
+  GpgmeUserID uids;
+
+  /* Internal to GPGME, do not use.  */
+  GpgmeSubkey _last_subkey;
+
+  /* Internal to GPGME, do not use.  */
+  GpgmeUserID _last_uid;
+};
+typedef struct _gpgme_key *GpgmeKey;
+
+\f
 /* Types for callback functions.  */
 
 /* Request a passphrase from the user.  */
@@ -693,10 +906,6 @@ void gpgme_key_ref (GpgmeKey key);
 void gpgme_key_unref (GpgmeKey key);
 void gpgme_key_release (GpgmeKey key);
 
-/* Get the data from key KEY in a XML string, which has to be released
-   with free by the user.  */
-char *gpgme_key_get_as_xml (GpgmeKey key);
-
 /* Return the value of the attribute WHAT of KEY, which has to be
    representable by a string.  IDX specifies the sub key or
    user ID for attributes related to sub keys or user IDs.  */
@@ -1045,7 +1254,19 @@ GpgmeError gpgme_op_edit (GpgmeCtx ctx, GpgmeKey key,
                          GpgmeEditCb fnc, void *fnc_value,
                          GpgmeData out);
 
+\f
 /* Key management functions */
+struct _gpgme_op_keylist_result
+{
+  unsigned int truncated : 1;
+
+  /* Internal to GPGME, do not use.  */
+  unsigned int _unused : 31;
+};
+typedef struct _gpgme_op_keylist_result *GpgmeKeyListResult;
+
+/* Retrieve a pointer to the result of the key listing operation.  */
+GpgmeKeyListResult gpgme_op_keylist_result (GpgmeCtx ctx);
 
 /* Start a keylist operation within CTX, searching for keys which
    match PATTERN.  If SECRET_ONLY is true, only secret keys are
@@ -1082,16 +1303,16 @@ struct _gpgme_trust_item
   int level;
 
   /* The owner trust if TYPE is 1.  */
-  char *otrust;
+  char *owner_trust;
 
   /* Internal to GPGME, do not use.  */
-  char _otrust[2];
+  char _owner_trust[2];
 
   /* The calculated validity.  */
-  char *val;
+  char *validity;
  
   /* Internal to GPGME, do not use.  */
-  char _val[2];
+  char _validity[2];
 
   /* The user name if TYPE is 2.  */
   char *name;
index e6563a8..941c757 100644 (file)
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
-#include <ctype.h>
 
 #include "util.h"
 #include "ops.h"
-#include "key.h"
 #include "sema.h"
 
-
+\f
 /* Protects all reference counters in keys.  All other accesses to a
    key are either read only or happen before the key is entered into
    the cache.  */
 DEFINE_STATIC_LOCK (key_ref_lock);
 
-\f
-static const char *
-pkalgo_to_string (int algo)
-{
-  switch (algo)
-    {
-    case 1: 
-    case 2:
-    case 3:
-      return "RSA";
-
-    case 16:
-    case 20:
-      return "ElG";
-
-    case 17:
-      return "DSA";
-
-    default:
-      return "Unknown";
-    }
-}
-
-
-static const char *
-otrust_to_string (int otrust)
-{
-  switch (otrust)
-    {
-    case GPGME_VALIDITY_NEVER:
-      return "n";
-
-    case GPGME_VALIDITY_MARGINAL:
-      return "m";
-
-    case GPGME_VALIDITY_FULL:
-      return "f";
-
-    case GPGME_VALIDITY_ULTIMATE:
-      return "u";
-
-    default:
-      return "?";
-    }
-}
-
-
-static const char *
-validity_to_string (int validity)
-{
-  switch (validity)
-    {
-    case GPGME_VALIDITY_UNDEFINED:
-      return "q";
-
-    case GPGME_VALIDITY_NEVER:
-      return "n";
-
-    case GPGME_VALIDITY_MARGINAL:
-      return "m";
-
-    case GPGME_VALIDITY_FULL:
-      return "f";
-
-    case GPGME_VALIDITY_ULTIMATE:
-      return "u";
 
-    case GPGME_VALIDITY_UNKNOWN:
-    default:
-      return "?";
-    }
-}
-
-
-static GpgmeError
-key_new (GpgmeKey *r_key, int secret)
+/* Create a new key.  */
+GpgmeError
+_gpgme_key_new (GpgmeKey *r_key)
 {
   GpgmeKey key;
 
-  *r_key = NULL;
   key = calloc (1, sizeof *key);
   if (!key)
     return GPGME_Out_Of_Core;
-  key->ref_count = 1;
+  key->_refs = 1;
+
   *r_key = key;
-  if (secret)
-    key->secret = 1;
   return 0;
 }
 
 
 GpgmeError
-_gpgme_key_new (GpgmeKey *r_key)
-{
-  return key_new (r_key, 0);
-}
-
-
-GpgmeError
-_gpgme_key_new_secret (GpgmeKey *r_key)
-{
-  return key_new (r_key, 1);
-}
-
-
-/* Acquire a reference to KEY.  */
-void
-gpgme_key_ref (GpgmeKey key)
-{
-  if (!key)
-    return;
-  LOCK (key_ref_lock);
-  key->ref_count++;
-  UNLOCK (key_ref_lock);
-}
-
-\f
-static struct subkey_s *
-add_subkey (GpgmeKey key, int secret)
+_gpgme_key_add_subkey (GpgmeKey key, GpgmeSubkey *r_subkey)
 {
-  struct subkey_s *k, *kk;
-
-  k = calloc (1, sizeof *k);
-  if (!k)
-    return NULL;
+  GpgmeSubkey subkey;
 
-  if (!(kk = key->keys.next))
-    key->keys.next = k;
-  else
-    {
-      while (kk->next)
-       kk = kk->next;
-      kk->next = k;
-    }
-  if (secret)
-    k->secret = 1;
-  return k;
-}
+  subkey = calloc (1, sizeof *subkey);
+  if (!subkey)
+    return GPGME_Out_Of_Core;
+  subkey->keyid = subkey->_keyid;
+  subkey->_keyid[16] = '\0';
 
+  if (!key->subkeys)
+    key->subkeys = subkey;
+  if (key->_last_subkey)
+    key->_last_subkey->next = subkey;
+  key->_last_subkey = subkey;
 
-struct subkey_s *
-_gpgme_key_add_subkey (GpgmeKey key)
-{
-  return add_subkey (key, 0);
+  *r_subkey = subkey;
+  return 0;
 }
 
 
-struct subkey_s *
-_gpgme_key_add_secret_subkey (GpgmeKey key)
-{
-  return add_subkey (key, 1);
-}
-
-\f
 static char *
 set_user_id_part (char *tail, const char *buf, size_t len)
 {
@@ -205,8 +87,8 @@ set_user_id_part (char *tail, const char *buf, size_t len)
 
 
 static void
-parse_user_id (const char *src, const char **name, const char **email,
-                   const char **comment, char *tail)
+parse_user_id (char *src, char **name, char **email,
+              char **comment, char *tail)
 {
   const char *start = NULL;
   int in_name = 0;
@@ -299,8 +181,8 @@ parse_user_id (const char *src, const char **name, const char **email,
 
 
 static void
-parse_x509_user_id (const char *src, const char **name, const char **email,
-                   const char **comment, char *tail)
+parse_x509_user_id (char *src, char **name, char **email,
+                   char **comment, char *tail)
 {
   if (*src == '<' && src[strlen (src) - 1] == '>')
     *email = src;
@@ -315,338 +197,220 @@ parse_x509_user_id (const char *src, const char **name, const char **email,
     *comment = tail;
 }
 
-\f
-struct certsig_s *
-_gpgme_key_add_certsig (GpgmeKey key, char *src)
+
+/* Take a name from the --with-colon listing, remove certain escape
+   sequences sequences and put it into the list of UIDs.  */
+GpgmeError
+_gpgme_key_append_name (GpgmeKey key, char *src)
+{
+  GpgmeUserID uid;
+  char *dst;
+  int src_len = strlen (src);
+
+  assert (key);
+  /* We can malloc a buffer of the same length, because the converted
+     string will never be larger. Actually we allocate it twice the
+     size, so that we are able to store the parsed stuff there too.  */
+  uid = malloc (sizeof (*uid) + 2 * src_len + 3);
+  if (!uid)
+    return GPGME_Out_Of_Core;
+  memset (uid, 0, sizeof *uid);
+
+  uid->uid = ((char *) uid) + sizeof (*uid);
+  dst = uid->uid;
+  _gpgme_decode_c_string (src, &dst, src_len + 1);
+
+  dst += src_len + 1;
+  if (key->protocol == GPGME_PROTOCOL_CMS)
+    parse_x509_user_id (src, &uid->name, &uid->email,
+                       &uid->comment, dst);
+  else
+    parse_user_id (src, &uid->name, &uid->email,
+                  &uid->comment, dst);
+
+  if (!key->uids)
+    key->uids = uid;
+  if (key->_last_uid)
+    key->_last_uid->next = uid;
+  key->_last_uid = uid;
+
+  return 0;
+}
+
+
+GpgmeKeySig
+_gpgme_key_add_sig (GpgmeKey key, char *src)
 {
   int src_len = src ? strlen (src) : 0;
-  struct user_id_s *uid;
-  struct certsig_s *certsig;
+  GpgmeUserID uid;
+  GpgmeKeySig sig;
 
   assert (key);        /* XXX */
 
-  uid = key->last_uid;
+  uid = key->_last_uid;
   assert (uid);        /* XXX */
 
   /* We can malloc a buffer of the same length, because the converted
      string will never be larger. Actually we allocate it twice the
      size, so that we are able to store the parsed stuff there too.  */
-  certsig = calloc (1, sizeof (*certsig) + 2 * src_len + 3);
-  if (!certsig)
+  sig = calloc (1, sizeof (*sig) + 2 * src_len + 3);
+  if (!sig)
     return NULL;
+  sig->keyid = sig->_keyid;
+  sig->_keyid[16] = '\0';
 
   if (src)
     {
-      char *dst = certsig->name;
+      char *dst = sig->uid;
       _gpgme_decode_c_string (src, &dst, src_len + 1);
       dst += src_len + 1;
-      if (key->x509)
-       parse_x509_user_id (src, &certsig->name_part, &certsig->email_part,
-                           &certsig->comment_part, dst);
+      if (key->protocol == GPGME_PROTOCOL_CMS)
+       parse_x509_user_id (src, &sig->name, &sig->email,
+                           &sig->comment, dst);
       else
-       parse_user_id (src, &certsig->name_part, &certsig->email_part,
-                      &certsig->comment_part, dst);
+       parse_user_id (src, &sig->name, &sig->email,
+                      &sig->comment, dst);
     }
 
-  if (!uid->certsigs)
-    uid->certsigs = certsig;
-  if (uid->last_certsig)
-    uid->last_certsig->next = certsig;
-  uid->last_certsig = certsig;
+  if (!uid->signatures)
+    uid->signatures = sig;
+  if (uid->_last_keysig)
+    uid->_last_keysig->next = sig;
+  uid->_last_keysig = sig;
 
-  return certsig;
+  return sig;
 }
 
 \f
-/**
- * gpgme_key_release:
- * @key: Key Object or NULL
- * 
- * Release the key object. Note, that this function may not do an
- * actual release if there are other shallow copies of the objects.
- * You have to call this function for every newly created key object
- * as well as for every gpgme_key_ref() done on the key object.
- **/
+/* Acquire a reference to KEY.  */
 void
-gpgme_key_release (GpgmeKey key)
+gpgme_key_ref (GpgmeKey key)
 {
-  struct certsig_s *c, *c2;
-  struct user_id_s *u, *u2;
-  struct subkey_s *k, *k2;
+  LOCK (key_ref_lock);
+  key->_refs++;
+  UNLOCK (key_ref_lock);
+}
 
-  if (!key)
-    return;
+
+/* gpgme_key_unref releases the key object. Note, that this function
+   may not do an actual release if there are other shallow copies of
+   the objects.  You have to call this function for every newly
+   created key object as well as for every gpgme_key_ref() done on the
+   key object.  */
+void
+gpgme_key_unref (GpgmeKey key)
+{
+  GpgmeUserID uid;
+  GpgmeSubkey subkey;
 
   LOCK (key_ref_lock);
-  assert (key->ref_count);
-  if (--key->ref_count)
+  assert (key->_refs > 0);
+  if (--key->_refs)
     {
       UNLOCK (key_ref_lock);
       return;
     }
   UNLOCK (key_ref_lock);
 
-  free (key->keys.fingerprint);
-  for (k = key->keys.next; k; k = k2)
+  subkey = key->subkeys;
+  while (subkey)
     {
-      k2 = k->next;
-      free (k->fingerprint);
-      free (k);
+      GpgmeSubkey next = subkey->next;
+      if (subkey->fpr)
+       free (subkey->fpr);
+      free (subkey);
+      subkey = next;
     }
-  for (u = key->uids; u; u = u2)
+
+  uid = key->uids;
+  while (uid)
     {
-      u2 = u->next;
-      for (c = u->certsigs; c; c = c2)
-        {
-          c2 = c->next;
-          free (c);
+      GpgmeUserID next_uid = uid->next;
+      GpgmeKeySig keysig = uid->signatures;
+
+      while (keysig)
+       {
+         GpgmeKeySig next = keysig->next;
+          free (keysig);
+         keysig = next;
         }
-      free (u);
+      free (uid);
+      uid = next_uid;
     }
-  free (key->issuer_serial);
-  free (key->issuer_name);
-  free (key->chain_id);
-  free (key);
-}
+  
+  if (key->issuer_serial)
+    free (key->issuer_serial);
+  if (key->issuer_name)
+    free (key->issuer_name);
 
+  if (key->chain_id)
+    free (key->chain_id);
 
-/**
- * gpgme_key_unref:
- * @key: Key Object
- * 
- * This is an alias for gpgme_key_release().
- **/
-void
-gpgme_key_unref (GpgmeKey key)
-{
-  gpgme_key_release (key);
+  free (key);
 }
 
 \f
-/* Take a name from the --with-colon listing, remove certain escape
-   sequences sequences and put it into the list of UIDs.  */
-GpgmeError
-_gpgme_key_append_name (GpgmeKey key, const char *src)
-{
-  struct user_id_s *uid;
-  char *dst;
-  int src_len = strlen (src);
-
-  assert (key);
-  /* We can malloc a buffer of the same length, because the converted
-     string will never be larger. Actually we allocate it twice the
-     size, so that we are able to store the parsed stuff there too.  */
-  uid = malloc (sizeof (*uid) + 2 * src_len + 3);
-  if (!uid)
-    return GPGME_Out_Of_Core;
-  memset (uid, 0, sizeof *uid);
-
-  dst = uid->name;
-  _gpgme_decode_c_string (src, &dst, src_len + 1);
+/* Compatibility interfaces.  */
 
-  dst += src_len + 1;
-  if (key->x509)
-    parse_x509_user_id (src, &uid->name_part, &uid->email_part,
-                       &uid->comment_part, dst);
-  else
-    parse_user_id (src, &uid->name_part, &uid->email_part,
-                  &uid->comment_part, dst);
-
-  if (!key->uids)
-    key->uids = uid;
-  if (key->last_uid)
-    key->last_uid->next = uid;
-  key->last_uid = uid;
-
-  return 0;
-}
-
-
-static void
-add_otag (GpgmeData d, const char *tag)
-{
-  _gpgme_data_append_string (d, "    <");
-  _gpgme_data_append_string (d, tag);
-  _gpgme_data_append_string (d, ">");
-}
-
-
-static void
-add_ctag (GpgmeData d, const char *tag)
+void
+gpgme_key_release (GpgmeKey key)
 {
-  _gpgme_data_append_string (d, "</");
-  _gpgme_data_append_string (d, tag);
-  _gpgme_data_append_string (d, ">\n");
+  gpgme_key_unref (key);
 }
 
 
-static void
-add_tag_and_string (GpgmeData d, const char *tag, const char *string)
+static const char *
+otrust_to_string (int otrust)
 {
-  add_otag (d, tag);
-  _gpgme_data_append_string_for_xml (d, string);
-  add_ctag (d, tag); 
-}
-
+  switch (otrust)
+    {
+    case GPGME_VALIDITY_NEVER:
+      return "n";
 
-static void
-add_tag_and_uint (GpgmeData d, const char *tag, unsigned int val)
-{
-  char buf[30];
-  sprintf (buf, "%u", val);
-  add_tag_and_string (d, tag, buf);
-}
+    case GPGME_VALIDITY_MARGINAL:
+      return "m";
 
+    case GPGME_VALIDITY_FULL:
+      return "f";
 
-static void
-add_tag_and_time (GpgmeData d, const char *tag, time_t val)
-{
-  char buf[30];
+    case GPGME_VALIDITY_ULTIMATE:
+      return "u";
 
-  if (!val || val == (time_t) - 1)
-    return;
-  sprintf (buf, "%lu", (unsigned long) val);
-  add_tag_and_string (d, tag, buf);
+    default:
+      return "?";
+    }
 }
 
 
-static void
-one_certsig_as_xml (GpgmeData data, struct certsig_s *certsig)
+static const char *
+validity_to_string (int validity)
 {
-  _gpgme_data_append_string (data, "    <signature>\n");
-  if (certsig->flags.invalid)
-    _gpgme_data_append_string (data, "      <invalid/>\n");
-  if (certsig->flags.revoked)
-    _gpgme_data_append_string (data, "      <revoked/>\n");
-  if (certsig->flags.expired)
-    _gpgme_data_append_string (data, "      <expired/>\n");
-  add_tag_and_string (data, "keyid", certsig->keyid);
-  add_tag_and_uint (data, "algo", certsig->algo);
-  add_tag_and_time (data, "created", certsig->timestamp);
-  add_tag_and_time (data, "expire", certsig->expires_at);
-  if (*certsig->name)
-    add_tag_and_string (data, "raw", certsig->name);
-  if (*certsig->name_part)
-    add_tag_and_string (data, "name", certsig->name_part);
-  if (*certsig->email_part)
-    add_tag_and_string (data, "email", certsig->email_part);
-  if (*certsig->comment_part)
-    add_tag_and_string (data, "comment", certsig->comment_part);
-  _gpgme_data_append_string (data, "    </signature>\n");
-}
+  switch (validity)
+    {
+    case GPGME_VALIDITY_UNDEFINED:
+      return "q";
 
+    case GPGME_VALIDITY_NEVER:
+      return "n";
 
-static void
-one_uid_as_xml (GpgmeData data, struct user_id_s *uid)
-{
-  struct certsig_s *certsig;
-
-  _gpgme_data_append_string (data, "  <userid>\n");
-  if (uid->invalid)
-    _gpgme_data_append_string (data, "    <invalid/>\n");
-  if (uid->revoked)
-    _gpgme_data_append_string (data, "    <revoked/>\n");
-  add_tag_and_string (data, "raw", uid->name);
-  if (*uid->name_part)
-    add_tag_and_string (data, "name", uid->name_part);
-  if (*uid->email_part)
-    add_tag_and_string (data, "email", uid->email_part);
-  if (*uid->comment_part)
-    add_tag_and_string (data, "comment", uid->comment_part);
-
-  /* Now the signatures.  */
-  for (certsig = uid->certsigs; certsig; certsig = certsig->next)
-    one_certsig_as_xml (data, certsig);
-  _gpgme_data_append_string (data, "  </userid>\n");
-}
+    case GPGME_VALIDITY_MARGINAL:
+      return "m";
 
+    case GPGME_VALIDITY_FULL:
+      return "f";
 
-/**
- * gpgme_key_get_as_xml:
- * @key: Key object
- * 
- * Return the key object as an XML string.  The classer has to free
- * that string.
- * 
- * Return value:  An XML string or NULL in case of a memory problem or
- *                a NULL passed as @key
- **/
-char *
-gpgme_key_get_as_xml (GpgmeKey key)
-{
-  GpgmeData d;
-  struct user_id_s *u;
-  struct subkey_s *k;
-  
-  if (!key)
-    return NULL;
-  
-  if (gpgme_data_new (&d))
-    return NULL;
-  
-  _gpgme_data_append_string (d, "<GnupgKeyblock>\n"
-                            "  <mainkey>\n");
-  if (key->keys.secret)
-    _gpgme_data_append_string (d, "    <secret/>\n");
-  if (key->keys.flags.invalid)
-    _gpgme_data_append_string (d, "    <invalid/>\n");
-  if (key->keys.flags.revoked)
-    _gpgme_data_append_string (d, "    <revoked/>\n");
-  if (key->keys.flags.expired)
-    _gpgme_data_append_string (d, "    <expired/>\n");
-  if (key->keys.flags.disabled)
-    _gpgme_data_append_string (d, "    <disabled/>\n");
-  add_tag_and_string (d, "keyid", key->keys.keyid);
-  if (key->keys.fingerprint)
-    add_tag_and_string (d, "fpr", key->keys.fingerprint);
-  add_tag_and_uint (d, "algo", key->keys.key_algo);
-  add_tag_and_uint (d, "len", key->keys.key_len);
-  add_tag_and_time (d, "created", key->keys.timestamp);
-  add_tag_and_time (d, "expire", key->keys.expires_at);
-  add_tag_and_string (d, "otrust", otrust_to_string (key->otrust));
-  if (key->issuer_serial)
-    add_tag_and_string (d, "serial", key->issuer_serial);
-  if (key->issuer_name)
-    add_tag_and_string (d, "issuer", key->issuer_name);
-  if (key->chain_id)
-    add_tag_and_string (d, "chainid", key->chain_id);
-  _gpgme_data_append_string (d, "  </mainkey>\n");
+    case GPGME_VALIDITY_ULTIMATE:
+      return "u";
 
-  /* Now the user IDs.  */
-  for (u = key->uids; u; u = u->next)
-    one_uid_as_xml (d,u);
-  
-  /* And now the subkeys.  */
-  for (k = key->keys.next; k; k = k->next)
-    {
-      _gpgme_data_append_string (d, "  <subkey>\n");
-      if (k->secret)
-        _gpgme_data_append_string (d, "    <secret/>\n");
-      if (k->flags.invalid)
-        _gpgme_data_append_string (d, "    <invalid/>\n");
-      if (k->flags.revoked)
-        _gpgme_data_append_string (d, "    <revoked/>\n");
-      if (k->flags.expired)
-        _gpgme_data_append_string (d, "    <expired/>\n");
-      if (k->flags.disabled)
-        _gpgme_data_append_string (d, "    <disabled/>\n");
-      add_tag_and_string (d, "keyid", k->keyid);
-      if (k->fingerprint)
-        add_tag_and_string (d, "fpr", k->fingerprint);
-      add_tag_and_uint (d, "algo", k->key_algo);
-      add_tag_and_uint (d, "len", k->key_len);
-      add_tag_and_time (d, "created", k->timestamp);
-      add_tag_and_time (d, "expire", k->expires_at);
-      _gpgme_data_append_string (d, "  </subkey>\n");
+    case GPGME_VALIDITY_UNKNOWN:
+    default:
+      return "?";
     }
-  _gpgme_data_append_string (d, "</GnupgKeyblock>\n");
-  
-  return _gpgme_data_release_and_return_string (d);
 }
 
 
 static const char *
-capabilities_to_string (struct subkey_s *k)
+capabilities_to_string (GpgmeSubkey subkey)
 {
   static const char *const strings[8] =
     {
@@ -659,40 +423,27 @@ capabilities_to_string (struct subkey_s *k)
       "es",
       "esc"
     };
-  return strings[(!!k->flags.can_encrypt << 2)
-                | (!!k->flags.can_sign << 1)
-                | (!!k->flags.can_certify)];
+  return strings[(!!subkey->can_encrypt << 2)
+                | (!!subkey->can_sign << 1)
+                | (!!subkey->can_certify)];
 }
 
 
-/**
- * gpgme_key_get_string_attr:
- * @key: Key Object
- * @what: Attribute specifier
- * @reserved: Must be 0
- * @idx: Index counter
- * 
- * Return a attribute as specified by @what and @idx.  Note that not
- * all attributes can be returned as a string, in which case NULL is
- * returned.  @idx is used to iterate through attributes which do have
- * more than one instance (e.g. user IDs or sub keys).
- * 
- * Return value: NULL or an const string which is only valid as long
- * as the key object itself is valid.
- **/
+/* Return the value of the attribute WHAT of ITEM, which has to be
+   representable by a string.  */
 const char *
 gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
                           const void *reserved, int idx)
 {
-  struct subkey_s *subkey;
-  struct user_id_s *uid;
+  GpgmeSubkey subkey;
+  GpgmeUserID uid;
   int i;
 
   if (!key || reserved || idx < 0)
     return NULL;
 
   /* Select IDXth subkey.  */
-  subkey = &key->keys;
+  subkey = key->subkeys;
   for (i = 0; i < idx; i++)
     {
       subkey = subkey->next;
@@ -715,28 +466,28 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
       return subkey ? subkey->keyid : NULL;
 
     case GPGME_ATTR_FPR:
-      return subkey ? subkey->fingerprint : NULL;
+      return subkey ? subkey->fpr : NULL;
 
     case GPGME_ATTR_ALGO:    
-      return subkey ? pkalgo_to_string (subkey->key_algo) : NULL;
+      return subkey ? gpgme_pubkey_algo_name (subkey->pubkey_algo) : NULL;
 
     case GPGME_ATTR_TYPE:
-      return key->x509 ? "X.509" : "PGP";
+      return key->protocol == GPGME_PROTOCOL_CMS ? "X.509" : "PGP";
 
     case GPGME_ATTR_OTRUST:
-      return otrust_to_string (key->otrust);
+      return otrust_to_string (key->owner_trust);
 
     case GPGME_ATTR_USERID:  
-      return uid ? uid->name : NULL;
+      return uid ? uid->uid : NULL;
 
     case GPGME_ATTR_NAME:   
-      return uid ? uid->name_part : NULL;
+      return uid ? uid->name : NULL;
 
     case GPGME_ATTR_EMAIL:
-      return uid ? uid->email_part : NULL;
+      return uid ? uid->email : NULL;
 
     case GPGME_ATTR_COMMENT:
-      return uid ? uid->comment_part : NULL;
+      return uid ? uid->comment : NULL;
 
     case GPGME_ATTR_VALIDITY:
       return uid ? validity_to_string (uid->validity) : NULL;
@@ -751,7 +502,7 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
       return idx ? NULL : key->issuer_name;
 
     case GPGME_ATTR_CHAINID:
-      return  key->chain_id;
+      return key->chain_id;
 
     default:
       return NULL;
@@ -759,35 +510,19 @@ gpgme_key_get_string_attr (GpgmeKey key, GpgmeAttr what,
 }
 
 
-/**
- * gpgme_key_get_ulong_attr:
- * @key: 
- * @what: 
- * @reserved: 
- * @idx: 
- * 
- * Return a attribute as specified by @what and @idx.  Note that not
- * all attributes can be returned as an integer, in which case 0 is
- * returned.  @idx is used to iterate through attributes which do have
- * more than one instance (e.g. user IDs or sub keys).
- *
- * See gpgme.h for a list of attributes.
- * 
- * Return value: 0 or the requested value.
- **/
 unsigned long
 gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
                          const void *reserved, int idx)
 {
-  struct subkey_s *subkey;
-  struct user_id_s *uid;
+  GpgmeSubkey subkey;
+  GpgmeUserID uid;
   int i;
 
   if (!key || reserved || idx < 0)
     return 0;
 
   /* Select IDXth subkey.  */
-  subkey = &key->keys;
+  subkey = key->subkeys;
   for (i = 0; i < idx; i++)
     {
       subkey = subkey->next;
@@ -807,42 +542,42 @@ gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
   switch (what)
     {
     case GPGME_ATTR_ALGO:
-      return subkey ? (unsigned long) subkey->key_algo : 0;
+      return subkey ? (unsigned long) subkey->pubkey_algo : 0;
 
     case GPGME_ATTR_LEN:
-      return subkey ? (unsigned long) subkey->key_len : 0;
+      return subkey ? (unsigned long) subkey->length : 0;
 
     case GPGME_ATTR_TYPE:
-      return key->x509 ? 1 : 0;
+      return key->protocol == GPGME_PROTOCOL_CMS ? 1 : 0;
 
-    case GPGME_ATTR_CREATED: 
+    case GPGME_ATTR_CREATED:
       return (subkey && subkey->timestamp >= 0)
        ? (unsigned long) subkey->timestamp : 0;
 
     case GPGME_ATTR_EXPIRE: 
-      return (subkey && subkey->expires_at >= 0)
-       ? (unsigned long) subkey->expires_at : 0;
+      return (subkey && subkey->expires >= 0)
+       ? (unsigned long) subkey->expires : 0;
 
     case GPGME_ATTR_VALIDITY:
       return uid ? uid->validity : 0;
 
     case GPGME_ATTR_OTRUST:
-      return key->otrust;
+      return key->owner_trust;
 
     case GPGME_ATTR_IS_SECRET:
       return !!key->secret;
 
     case GPGME_ATTR_KEY_REVOKED:
-      return subkey ? subkey->flags.revoked : 0;
+      return subkey ? subkey->revoked : 0;
 
     case GPGME_ATTR_KEY_INVALID:
-      return subkey ? subkey->flags.invalid : 0;
+      return subkey ? subkey->invalid : 0;
 
     case GPGME_ATTR_KEY_EXPIRED:
-      return subkey ? subkey->flags.expired : 0;
+      return subkey ? subkey->expired : 0;
 
     case GPGME_ATTR_KEY_DISABLED:
-      return subkey ? subkey->flags.disabled : 0;
+      return subkey ? subkey->disabled : 0;
 
     case GPGME_ATTR_UID_REVOKED:
       return uid ? uid->revoked : 0;
@@ -851,13 +586,13 @@ gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
       return uid ? uid->invalid : 0;
 
     case GPGME_ATTR_CAN_ENCRYPT:
-      return key->gloflags.can_encrypt;
+      return key->can_encrypt;
 
     case GPGME_ATTR_CAN_SIGN:
-      return key->gloflags.can_sign;
+      return key->can_sign;
 
     case GPGME_ATTR_CAN_CERTIFY:
-      return key->gloflags.can_certify;
+      return key->can_certify;
 
     default:
       return 0;
@@ -865,11 +600,11 @@ gpgme_key_get_ulong_attr (GpgmeKey key, GpgmeAttr what,
 }
 
 
-static struct certsig_s *
-get_certsig (GpgmeKey key, int uid_idx, int idx)
+static GpgmeKeySig
+get_keysig (GpgmeKey key, int uid_idx, int idx)
 {
-  struct user_id_s *uid;
-  struct certsig_s *certsig;
+  GpgmeUserID uid;
+  GpgmeKeySig sig;
 
   if (!key || uid_idx < 0 || idx < 0)
     return NULL;
@@ -883,13 +618,13 @@ get_certsig (GpgmeKey key, int uid_idx, int idx)
   if (!uid)
     return NULL;
 
-  certsig = uid->certsigs;
-  while (certsig && idx > 0)
+  sig = uid->signatures;
+  while (sig && idx > 0)
     {
-      certsig = certsig->next;
+      sig = sig->next;
       idx--;
     }
-  return certsig;
+  return sig;
 }
 
 
@@ -897,7 +632,7 @@ const char *
 gpgme_key_sig_get_string_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
                               const void *reserved, int idx)
 {
-  struct certsig_s *certsig = get_certsig (key, uid_idx, idx);
+  GpgmeKeySig certsig = get_keysig (key, uid_idx, idx);
 
   if (!certsig || reserved)
     return NULL;
@@ -908,19 +643,19 @@ gpgme_key_sig_get_string_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
       return certsig->keyid;
 
     case GPGME_ATTR_ALGO:    
-      return pkalgo_to_string (certsig->algo);
+      return gpgme_pubkey_algo_name (certsig->pubkey_algo);
 
-    case GPGME_ATTR_USERID:  
-      return certsig->name;
+    case GPGME_ATTR_USERID:
+      return certsig->uid;
 
     case GPGME_ATTR_NAME:   
-      return certsig->name_part;
+      return certsig->name;
 
     case GPGME_ATTR_EMAIL:
-      return certsig->email_part;
+      return certsig->email;
 
     case GPGME_ATTR_COMMENT:
-      return certsig->comment_part;
+      return certsig->comment;
    
     default:
       return NULL;
@@ -932,7 +667,7 @@ unsigned long
 gpgme_key_sig_get_ulong_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
                              const void *reserved, int idx)
 {
-  struct certsig_s *certsig = get_certsig (key, uid_idx, idx);
+  GpgmeKeySig certsig = get_keysig (key, uid_idx, idx);
 
   if (!certsig || reserved)
     return 0;
@@ -940,28 +675,28 @@ gpgme_key_sig_get_ulong_attr (GpgmeKey key, int uid_idx, GpgmeAttr what,
   switch (what)
     {
     case GPGME_ATTR_ALGO:    
-      return (unsigned long) certsig->algo;
+      return (unsigned long) certsig->pubkey_algo;
 
     case GPGME_ATTR_CREATED: 
       return certsig->timestamp < 0 ? 0L : (unsigned long) certsig->timestamp;
 
     case GPGME_ATTR_EXPIRE: 
-      return certsig->expires_at < 0 ? 0L : (unsigned long) certsig->expires_at;
+      return certsig->expires < 0 ? 0L : (unsigned long) certsig->expires;
 
     case GPGME_ATTR_KEY_REVOKED:
-      return certsig->flags.revoked;
+      return certsig->revoked;
 
     case GPGME_ATTR_KEY_INVALID:
-      return certsig->flags.invalid;
+      return certsig->invalid;
 
     case GPGME_ATTR_KEY_EXPIRED:
-      return certsig->flags.expired;
+      return certsig->expired;
 
     case GPGME_ATTR_SIG_CLASS:
-      return certsig->sig_class;
+      return certsig->class;
 
     case GPGME_ATTR_SIG_STATUS:
-      return certsig->sig_stat;
+      return certsig->status;
 
     default:
       return 0;
index 54ce4a9..84ac8e3 100644 (file)
 #include <assert.h>
 #include <ctype.h>
 
+#include "gpgme.h"
 #include "util.h"
 #include "context.h"
 #include "ops.h"
-#include "key.h"
 #include "debug.h"
 
 \f
-struct keylist_result
+struct key_queue_item_s
 {
-  int truncated;
-  GpgmeData xmlinfo;
+  struct key_queue_item_s *next;
+  GpgmeKey key;
 };
-typedef struct keylist_result *KeylistResult;
 
-static void
-release_keylist_result (void *hook)
+typedef struct
 {
-  KeylistResult result = (KeylistResult) hook;
+  struct _gpgme_op_keylist_result result;
 
-  if (result->xmlinfo)
-    gpgme_data_release (result->xmlinfo);
-}
+  GpgmeKey tmp_key;
+  GpgmeUserID tmp_uid;
+  /* Something new is available.  */
+  int key_cond;
+  struct key_queue_item_s *key_queue;
+} *op_data_t;
 
 
-/* Append some XML info.  args is currently ignore but we might want
-   to add more information in the future (like source of the
-   keylisting.  With args of NULL the XML structure is closed.  */
 static void
-append_xml_keylistinfo (GpgmeData *rdh, char *args)
+release_op_data (void *hook)
 {
-  GpgmeData dh;
-
-  if (!*rdh)
-    {
-      if (gpgme_data_new (rdh))
-       return; /* FIXME: We are ignoring out-of-core.  */
-      dh = *rdh;
-      _gpgme_data_append_string (dh, "<GnupgOperationInfo>\n");
-    }
-  else
+  op_data_t opd = (op_data_t) hook;
+  struct key_queue_item_s *key = opd->key_queue;
+
+  if (opd->tmp_key)
+    gpgme_key_unref (opd->tmp_key);
+  if (opd->tmp_uid)
+    free (opd->tmp_uid);
+  while (key)
     {
-      dh = *rdh;
-      _gpgme_data_append_string (dh, "  </keylisting>\n");
-    }
+      struct key_queue_item_s *next = key->next;
 
-  if (!args)
-    {
-      /* Just close the XML containter.  */
-      _gpgme_data_append_string (dh, "</GnupgOperationInfo>\n");
-      return;
+      gpgme_key_unref (key->key);
+      key = next;
     }
-
-  _gpgme_data_append_string (dh, "  <keylisting>\n    <truncated/>\n");
-    
 }
 
 
+GpgmeKeyListResult
+gpgme_op_keylist_result (GpgmeCtx ctx)
+{
+  op_data_t opd;
+  GpgmeError err;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
+  if (err || !opd)
+    return NULL;
+
+  return &opd->result;
+}
+
+\f
 static GpgmeError
-keylist_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
+keylist_status_handler (void *priv, GpgmeStatusCode code, char *args)
 {
+  GpgmeCtx ctx = (GpgmeCtx) priv;
   GpgmeError err;
-  KeylistResult result;
+  op_data_t opd;
 
-  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &result,
-                              sizeof (*result), release_keylist_result);
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
   if (err)
     return err;
 
   switch (code)
     {
     case GPGME_STATUS_TRUNCATED:
-      result->truncated = 1;
-      break;
-
-    case GPGME_STATUS_EOF:
-      if (result->truncated)
-        append_xml_keylistinfo (&result->xmlinfo, "1");
-      if (result->xmlinfo)
-       {
-         append_xml_keylistinfo (&result->xmlinfo, NULL);
-         _gpgme_set_op_info (ctx, result->xmlinfo);
-         result->xmlinfo = NULL;
-        }
+      opd->result.truncated = 1;
       break;
 
     default:
@@ -139,21 +130,21 @@ set_mainkey_trust_info (GpgmeKey key, const char *src)
       switch (*src)
        {
        case 'e':
-         key->keys.flags.expired = 1;
+         key->subkeys->expired = 1;
          break;
 
        case 'r':
-         key->keys.flags.revoked = 1;
+         key->subkeys->revoked = 1;
          break;
 
        case 'd':
           /* Note that gpg 1.3 won't print that anymore but only uses
              the capabilities field. */
-         key->keys.flags.disabled = 1;
+         key->subkeys->disabled = 1;
          break;
 
        case 'i':
-         key->keys.flags.invalid = 1;
+         key->subkeys->invalid = 1;
          break;
         }
       src++;
@@ -164,7 +155,7 @@ set_mainkey_trust_info (GpgmeKey key, const char *src)
 static void
 set_userid_flags (GpgmeKey key, const char *src)
 {
-  struct user_id_s *uid = key->last_uid;
+  GpgmeUserID uid = key->_last_uid;
 
   assert (uid);
   /* Look at letters and stop at the first digit.  */
@@ -202,7 +193,7 @@ set_userid_flags (GpgmeKey key, const char *src)
 
 
 static void
-set_subkey_trust_info (struct subkey_s *subkey, const char *src)
+set_subkey_trust_info (GpgmeSubkey subkey, const char *src)
 {
   /* Look at letters and stop at the first digit.  */
   while (*src && !isdigit (*src))
@@ -210,19 +201,19 @@ set_subkey_trust_info (struct subkey_s *subkey, const char *src)
       switch (*src)
        {
        case 'e':
-         subkey->flags.expired = 1;
+         subkey->expired = 1;
          break;
 
        case 'r':
-         subkey->flags.revoked = 1;
+         subkey->revoked = 1;
          break;
 
        case 'd':
-         subkey->flags.disabled = 1;
+         subkey->disabled = 1;
          break;
 
        case 'i':
-         subkey->flags.invalid = 1;
+         subkey->invalid = 1;
          break;
         }
       src++;
@@ -238,15 +229,15 @@ set_mainkey_capability (GpgmeKey key, const char *src)
       switch (*src)
        {
        case 'e':
-         key->keys.flags.can_encrypt = 1;
+         key->subkeys->can_encrypt = 1;
          break;
 
        case 's':
-         key->keys.flags.can_sign = 1;
+         key->subkeys->can_sign = 1;
          break;
 
        case 'c':
-         key->keys.flags.can_certify = 1;
+         key->subkeys->can_certify = 1;
          break;
 
         case 'd':
@@ -256,19 +247,19 @@ set_mainkey_capability (GpgmeKey key, const char *src)
              and D, so that a future gpg version will be able to
              disable certain subkeys. Currently it is expected that
              gpg sets this for the primary key. */
-                 key->keys.flags.disabled = 1;
+                 key->subkeys->disabled = 1;
           break;
 
        case 'E':
-         key->gloflags.can_encrypt = 1;
+         key->can_encrypt = 1;
          break;
 
        case 'S':
-         key->gloflags.can_sign = 1;
+         key->can_sign = 1;
          break;
 
        case 'C':
-         key->gloflags.can_certify = 1;
+         key->can_certify = 1;
          break;
         }
       src++;
@@ -277,22 +268,22 @@ set_mainkey_capability (GpgmeKey key, const char *src)
 
 
 static void
-set_subkey_capability (struct subkey_s *subkey, const char *src)
+set_subkey_capability (GpgmeSubkey subkey, const char *src)
 {
   while (*src)
     {
       switch (*src)
        {
        case 'e':
-         subkey->flags.can_encrypt = 1;
+         subkey->can_encrypt = 1;
          break;
 
        case 's':
-         subkey->flags.can_sign = 1;
+         subkey->can_sign = 1;
          break;
 
        case 'c':
-         subkey->flags.can_certify = 1;
+         subkey->can_certify = 1;
          break;
         }
       src++;
@@ -308,23 +299,23 @@ set_ownertrust (GpgmeKey key, const char *src)
       switch (*src)
        {
        case 'n':
-         key->otrust = GPGME_VALIDITY_NEVER;
+         key->owner_trust = GPGME_VALIDITY_NEVER;
          break;
 
        case 'm':
-         key->otrust = GPGME_VALIDITY_MARGINAL;
+         key->owner_trust = GPGME_VALIDITY_MARGINAL;
          break;
 
        case 'f':
-         key->otrust = GPGME_VALIDITY_FULL;
+         key->owner_trust = GPGME_VALIDITY_FULL;
          break;
 
        case 'u':
-         key->otrust = GPGME_VALIDITY_ULTIMATE;
+         key->owner_trust = GPGME_VALIDITY_ULTIMATE;
          break;
 
         default:
-         key->otrust = GPGME_VALIDITY_UNKNOWN;
+         key->owner_trust = GPGME_VALIDITY_UNKNOWN;
          break;
         }
       src++;
@@ -332,14 +323,14 @@ set_ownertrust (GpgmeKey key, const char *src)
 }
 
 
-/* We have read an entire key into ctx->tmp_key and should now finish
-   it.  It is assumed that this releases ctx->tmp_key.  */
+/* We have read an entire key into tmp_key and should now finish it.
+   It is assumed that this releases tmp_key.  */
 static void
-finish_key (GpgmeCtx ctx)
+finish_key (GpgmeCtx ctx, op_data_t opd)
 {
-  GpgmeKey key = ctx->tmp_key;
+  GpgmeKey key = opd->tmp_key;
 
-  ctx->tmp_key = NULL;
+  opd->tmp_key = NULL;
 
   if (key)
     _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_KEY, key);
@@ -348,28 +339,37 @@ finish_key (GpgmeCtx ctx)
 
 /* Note: We are allowed to modify LINE.  */
 static GpgmeError
-keylist_colon_handler (GpgmeCtx ctx, char *line)
+keylist_colon_handler (void *priv, char *line)
 {
+  GpgmeCtx ctx = (GpgmeCtx) priv;
   enum
     {
-      RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR, RT_SSB, RT_SEC,
-      RT_CRT, RT_CRS, RT_REV
+      RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
+      RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV
     }
   rectype = RT_NONE;
 #define NR_FIELDS 13
   char *field[NR_FIELDS];
   int fields = 0;
-  GpgmeKey key = ctx->tmp_key;
-  struct subkey_s *subkey = NULL;
-  struct certsig_s *certsig = NULL;
+  op_data_t opd;
+  GpgmeError err;
+  GpgmeKey key;
+  GpgmeSubkey subkey = NULL;
+  GpgmeKeySig keysig = NULL;
 
   DEBUG3 ("keylist_colon_handler ctx = %p, key = %p, line = %s\n",
          ctx, key, line ? line : "(null)");
 
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
+  if (err)
+    return err;
+
+  key = opd->tmp_key;
+
   if (!line)
     {
       /* End Of File.  */
-      finish_key (ctx);
+      finish_key (ctx, opd);
       return 0;
     }
 
@@ -385,67 +385,22 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
     rectype = RT_SIG;
   else if (!strcmp (field[0], "rev"))
     rectype = RT_REV;
-  else if (!strcmp (field[0], "uid") && key)
-    rectype = RT_UID;
-  else if (!strcmp (field[0], "sub") && key)
-    {
-      /* Start a new subkey.  */
-      rectype = RT_SUB; 
-      if (!(subkey = _gpgme_key_add_subkey (key)))
-       return GPGME_Out_Of_Core;
-    }
-  else if (!strcmp (field[0], "ssb") && key)
-    {
-      /* Start a new secret subkey.  */
-      rectype = RT_SSB;
-      if (!(subkey = _gpgme_key_add_secret_subkey (key)))
-       return GPGME_Out_Of_Core;
-    }
   else if (!strcmp (field[0], "pub"))
-    {
-      /* Start a new keyblock.  */
-      if (_gpgme_key_new (&key))
-       /* The only kind of error we can get.  */
-       return GPGME_Out_Of_Core;
-      rectype = RT_PUB;
-      finish_key (ctx);
-      assert (!ctx->tmp_key);
-      ctx->tmp_key = key;
-    }
+    rectype = RT_PUB;
   else if (!strcmp (field[0], "sec"))
-    {
-      /* Start a new keyblock,  */
-      if (_gpgme_key_new_secret (&key))
-       return GPGME_Out_Of_Core;
-      rectype = RT_SEC;
-      finish_key (ctx);
-      assert (!ctx->tmp_key);
-      ctx->tmp_key = key;
-    }
+    rectype = RT_SEC;
   else if (!strcmp (field[0], "crt"))
-    {
-      /* Start a new certificate.  */
-      if (_gpgme_key_new (&key))
-       return GPGME_Out_Of_Core;
-      key->x509 = 1;
-      rectype = RT_CRT;
-      finish_key (ctx);
-      assert (!ctx->tmp_key);
-      ctx->tmp_key = key;
-    }
+    rectype = RT_CRT;
   else if (!strcmp (field[0], "crs"))
-    {
-      /* Start a new certificate.  */
-      if (_gpgme_key_new_secret (&key))
-       return GPGME_Out_Of_Core;
-      key->x509 = 1;
-      rectype = RT_CRS;
-      finish_key (ctx);
-      assert (!ctx->tmp_key);
-      ctx->tmp_key = key;
-    }
+    rectype = RT_CRS;
   else if (!strcmp (field[0], "fpr") && key) 
     rectype = RT_FPR;
+  else if (!strcmp (field[0], "uid") && key)
+    rectype = RT_UID;
+  else if (!strcmp (field[0], "sub") && key)
+    rectype = RT_SUB; 
+  else if (!strcmp (field[0], "ssb") && key)
+    rectype = RT_SSB;
   else 
     rectype = RT_NONE;
 
@@ -453,29 +408,32 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
      this, clear the user ID pointer when encountering anything but a
      signature.  */
   if (rectype != RT_SIG && rectype != RT_REV)
-    ctx->tmp_uid = NULL;
+    opd->tmp_uid = NULL;
 
   switch (rectype)
     {
+    case RT_PUB:
+    case RT_SEC:
     case RT_CRT:
     case RT_CRS:
-      /* Field 8 has the X.509 serial number.  */
-      if (fields >= 8)
+      /* Start a new keyblock.  */
+      err = _gpgme_key_new (&key);
+      if (err)
+       return err;
+      err = _gpgme_key_add_subkey (key, &subkey);
+      if (err)
        {
-         key->issuer_serial = strdup (field[7]);
-         if (!key->issuer_serial)
-           return GPGME_Out_Of_Core;
+         gpgme_key_unref (key);
+         return err;
        }
 
-      /* Field 10 is not used for gpg due to --fixed-list-mode option
-        but GPGSM stores the issuer name.  */
-      if (fields >= 10 && _gpgme_decode_c_string (field[9],
-                                                 &key->issuer_name, 0))
-       return GPGME_Out_Of_Core;
-      /* Fall through!  */
+      if (rectype == RT_SEC || rectype == RT_CRS)
+       key->secret = 1;
+      if (rectype == RT_CRT || rectype == RT_CRS)
+       key->protocol = GPGME_PROTOCOL_CMS;
+      finish_key (ctx, opd);
+      opd->tmp_key = key;
 
-    case RT_PUB:
-    case RT_SEC:
       /* Field 2 has the trust info.  */
       if (fields >= 2)
        set_mainkey_trust_info (key, field[1]);
@@ -486,7 +444,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
          int i = atoi (field[2]);
          /* Ignore invalid values.  */
          if (i > 1)
-           key->keys.key_len = i; 
+           subkey->length = i; 
        }
 
       /* Field 4 has the public key algorithm.  */
@@ -494,25 +452,39 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
        {
          int i = atoi (field[3]);
          if (i >= 1 && i < 128)
-           key->keys.key_algo = i;
+           subkey->pubkey_algo = i;
        }
 
       /* Field 5 has the long keyid.  */
-      if (fields >= 5 && strlen (field[4]) == DIM(key->keys.keyid) - 1)
-       strcpy (key->keys.keyid, field[4]);
+      if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
+       strcpy (subkey->_keyid, field[4]);
 
       /* Field 6 has the timestamp (seconds).  */
       if (fields >= 6)
-       key->keys.timestamp = parse_timestamp (field[5]);
+       subkey->timestamp = parse_timestamp (field[5]);
 
       /* Field 7 has the expiration time (seconds).  */
       if (fields >= 7)
-       key->keys.expires_at = parse_timestamp (field[6]);
+       subkey->expires = parse_timestamp (field[6]);
 
+      /* Field 8 has the X.509 serial number.  */
+      if (fields >= 8 && (rectype == RT_CRT || rectype == RT_CRS))
+       {
+         key->issuer_serial = strdup (field[7]);
+         if (!key->issuer_serial)
+           return GPGME_Out_Of_Core;
+       }
+         
       /* Field 9 has the ownertrust.  */
       if (fields >= 9)
        set_ownertrust (key, field[8]);
 
+      /* Field 10 is not used for gpg due to --fixed-list-mode option
+        but GPGSM stores the issuer name.  */
+      if (fields >= 10 && (rectype == RT_CRT || rectype == RT_CRS))
+       if (_gpgme_decode_c_string (field[9], &key->issuer_name, 0))
+         return GPGME_Out_Of_Core;
+
       /* Field 11 has the signature class.  */
 
       /* Field 12 has the capabilities.  */
@@ -522,6 +494,14 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
 
     case RT_SUB:
     case RT_SSB:
+      /* Start a new subkey.  */
+      err = _gpgme_key_add_subkey (key, &subkey);
+      if (err)
+       return err;
+
+      if (rectype == RT_SSB)
+       subkey->secret = 1;
+
       /* Field 2 has the trust info.  */
       if (fields >= 2)
        set_subkey_trust_info (subkey, field[1]);
@@ -532,7 +512,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
          int i = atoi (field[2]);
          /* Ignore invalid values.  */
          if (i > 1)
-           subkey->key_len = i;
+           subkey->length = i;
        }
 
       /* Field 4 has the public key algorithm.  */
@@ -540,12 +520,12 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
        {
          int i = atoi (field[3]);
          if (i >= 1 && i < 128)
-           subkey->key_algo = i;
+           subkey->pubkey_algo = i;
        }
 
       /* Field 5 has the long keyid.  */
-      if (fields >= 5 && strlen (field[4]) == DIM(subkey->keyid) - 1)
-       strcpy (subkey->keyid, field[4]);
+      if (fields >= 5 && strlen (field[4]) == DIM(subkey->_keyid) - 1)
+       strcpy (subkey->_keyid, field[4]);
 
       /* Field 6 has the timestamp (seconds).  */
       if (fields >= 6)
@@ -553,7 +533,7 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
 
       /* Field 7 has the expiration time (seconds).  */
       if (fields >= 7)
-       subkey->expires_at = parse_timestamp (field[6]);
+       subkey->expires = parse_timestamp (field[6]);
 
       /* Field 8 is reserved (LID).  */
       /* Field 9 has the ownertrust.  */
@@ -576,17 +556,17 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
            {
              if (field[1])
                set_userid_flags (key, field[1]);
-             ctx->tmp_uid = key->last_uid;
+             opd->tmp_uid = key->_last_uid;
            }
        }
       break;
 
     case RT_FPR:
       /* Field 10 has the fingerprint (take only the first one).  */
-      if (fields >= 10 && !key->keys.fingerprint && field[9] && *field[9])
+      if (fields >= 10 && !key->subkeys->fpr && field[9] && *field[9])
        {
-         key->keys.fingerprint = strdup (field[9]);
-         if (!key->keys.fingerprint)
+         key->subkeys->fpr = strdup (field[9]);
+         if (!key->subkeys->fpr)
            return GPGME_Out_Of_Core;
        }
 
@@ -601,13 +581,13 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
 
     case RT_SIG:
     case RT_REV:
-      if (!ctx->tmp_uid)
+      if (!opd->tmp_uid)
        return 0;
 
       /* Start a new (revoked) signature.  */
-      assert (ctx->tmp_uid == key->last_uid);
-      certsig = _gpgme_key_add_certsig (key, (fields >= 10) ? field[9] : NULL);
-      if (!certsig)
+      assert (opd->tmp_uid == key->_last_uid);
+      keysig = _gpgme_key_add_sig (key, (fields >= 10) ? field[9] : NULL);
+      if (!keysig)
        return GPGME_Out_Of_Core;
 
       /* Field 2 has the calculated trust ('!', '-', '?', '%').  */
@@ -615,23 +595,23 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
        switch (field[1][0])
          {
          case '!':
-           certsig->sig_stat = GPGME_SIG_STAT_GOOD;
+           keysig->status = GPGME_No_Error;
            break;
 
          case '-':
-           certsig->sig_stat = GPGME_SIG_STAT_BAD;
+           keysig->status = GPGME_Bad_Signature;
            break;
 
          case '?':
-           certsig->sig_stat = GPGME_SIG_STAT_NOKEY;
+           keysig->status = GPGME_No_Public_Key;
            break;
 
          case '%':
-           certsig->sig_stat = GPGME_SIG_STAT_ERROR;
+           keysig->status = GPGME_General_Error;
            break;
 
          default:
-           certsig->sig_stat = GPGME_SIG_STAT_NONE;
+           keysig->status = GPGME_No_Error;
            break;
          }
 
@@ -640,20 +620,20 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
        {
          int i = atoi (field[3]);
          if (i >= 1 && i < 128)
-           certsig->algo = i;
+           keysig->pubkey_algo = i;
        }
       
       /* Field 5 has the long keyid.  */
-      if (fields >= 5 && strlen (field[4]) == DIM(certsig->keyid) - 1)
-       strcpy (certsig->keyid, field[4]);
+      if (fields >= 5 && strlen (field[4]) == DIM(keysig->_keyid) - 1)
+       strcpy (keysig->_keyid, field[4]);
       
       /* Field 6 has the timestamp (seconds).  */
       if (fields >= 6)
-       certsig->timestamp = parse_timestamp (field[5]);
+       keysig->timestamp = parse_timestamp (field[5]);
 
       /* Field 7 has the expiration time (seconds).  */
       if (fields >= 7)
-       certsig->expires_at = parse_timestamp (field[6]);
+       keysig->expires = parse_timestamp (field[6]);
 
       /* Field 11 has the signature class (eg, 0x30 means revoked).  */
       if (fields >= 11)
@@ -662,12 +642,12 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
            int class = _gpgme_hextobyte (field[10]);
            if (class >= 0)
              {
-               certsig->sig_class = class;
+               keysig->class = class;
                if (class == 0x30)
-                 certsig->flags.revoked = 1;
+                 keysig->revoked = 1;
              }
            if (field[10][2] == 'x')
-             certsig->flags.exportable = 1;
+             keysig->exportable = 1;
          }
       break;
 
@@ -682,162 +662,134 @@ keylist_colon_handler (GpgmeCtx ctx, char *line)
 void
 _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data)
 {
+  GpgmeError err;
   GpgmeCtx ctx = (GpgmeCtx) data;
   GpgmeKey key = (GpgmeKey) type_data;
+  op_data_t opd;
   struct key_queue_item_s *q, *q2;
 
   assert (type == GPGME_EVENT_NEXT_KEY);
 
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
+  if (err)
+    return;
+
   q = malloc (sizeof *q);
   if (!q)
     {
-      gpgme_key_release (key);
+      gpgme_key_unref (key);
       /* FIXME       return GPGME_Out_Of_Core; */
       return;
     }
   q->key = key;
   q->next = NULL;
-  /* FIXME: Lock queue.  Use a tail pointer?  */
-  if (!(q2 = ctx->key_queue))
-    ctx->key_queue = q;
+  /* FIXME: Use a tail pointer?  */
+  if (!(q2 = opd->key_queue))
+    opd->key_queue = q;
   else
     {
       for (; q2->next; q2 = q2->next)
        ;
       q2->next = q;
     }
-  ctx->key_cond = 1;
-  /* FIXME: Unlock queue.  */
+  opd->key_cond = 1;
 }
 
 
-/**
- * gpgme_op_keylist_start:
- * @c: context 
- * @pattern: a GnuPG user ID or NULL for all
- * @secret_only: List only keys where the secret part is available
- * 
- * Note that this function also cancels a pending key listing
- * operaton. To actually retrieve the key, use
- * gpgme_op_keylist_next().
- * 
- * Return value:  0 on success or an errorcode. 
- **/
+/* Start a keylist operation within CTX, searching for keys which
+   match PATTERN.  If SECRET_ONLY is true, only secret keys are
+   returned.  */
 GpgmeError
 gpgme_op_keylist_start (GpgmeCtx ctx, const char *pattern, int secret_only)
 {
-  GpgmeError err = 0;
+  GpgmeError err;
+  op_data_t opd;
 
   err = _gpgme_op_reset (ctx, 2);
   if (err)
-    goto leave;
+    return err;
 
-  gpgme_key_release (ctx->tmp_key);
-  ctx->tmp_key = NULL;
-  /* Fixme: Release key_queue.  */
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd,
+                              sizeof (*opd), release_op_data);
+  if (err)
+    return err;
 
   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
+
   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
                                              keylist_colon_handler, ctx);
   if (err)
-    goto leave;
-
-  err = _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
-                                 ctx->keylist_mode);
+    return err;
 
- leave:
-  if (err)
-    {
-      _gpgme_engine_release (ctx->engine);
-      ctx->engine = NULL;
-    }
-  return err;
+  return _gpgme_engine_op_keylist (ctx->engine, pattern, secret_only,
+                                  ctx->keylist_mode);
 }
 
 
-/**
- * gpgme_op_keylist_ext_start:
- * @c: context 
- * @pattern: a NULL terminated array of search patterns
- * @secret_only: List only keys where the secret part is available
- * @reserved: Should be 0.
- * 
- * Note that this function also cancels a pending key listing
- * operaton. To actually retrieve the key, use
- * gpgme_op_keylist_next().
- * 
- * Return value:  0 on success or an errorcode. 
- **/
+/* Start a keylist operation within CTX, searching for keys which
+   match PATTERN.  If SECRET_ONLY is true, only secret keys are
+   returned.  */
 GpgmeError
 gpgme_op_keylist_ext_start (GpgmeCtx ctx, const char *pattern[],
                            int secret_only, int reserved)
 {
-  GpgmeError err = 0;
+  GpgmeError err;
+  op_data_t opd;
 
   err = _gpgme_op_reset (ctx, 2);
   if (err)
-    goto leave;
+    return err;
 
-  gpgme_key_release (ctx->tmp_key);
-  ctx->tmp_key = NULL;
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd,
+                              sizeof (*opd), release_op_data);
+  if (err)
+    return err;
 
   _gpgme_engine_set_status_handler (ctx->engine, keylist_status_handler, ctx);
   err = _gpgme_engine_set_colon_line_handler (ctx->engine,
                                              keylist_colon_handler, ctx);
   if (err)
-    goto leave;
-
-  err = _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
-                                     reserved, ctx->keylist_mode);
+    return err;
 
- leave:
-  if (err)
-    {
-      _gpgme_engine_release (ctx->engine);
-      ctx->engine = NULL;
-    }
-  return err;
+  return _gpgme_engine_op_keylist_ext (ctx->engine, pattern, secret_only,
+                                      reserved, ctx->keylist_mode);
 }
 
 
-/**
- * gpgme_op_keylist_next:
- * @c: Context
- * @r_key: Returned key object
- * 
- * Return the next key from the key listing started with
- * gpgme_op_keylist_start().  The caller must free the key using
- * gpgme_key_release().  If the last key has already been returned the
- * last time the function was called, %GPGME_EOF is returned and the
- * operation is finished.
- * 
- * Return value: 0 on success, %GPGME_EOF or another error code.
- **/
+/* Return the next key from the keylist in R_KEY.  */
 GpgmeError
 gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
 {
+  GpgmeError err;
   struct key_queue_item_s *queue_item;
+  op_data_t opd;
 
-  if (!r_key)
+  if (!ctx || !r_key)
     return GPGME_Invalid_Value;
   *r_key = NULL;
   if (!ctx)
     return GPGME_Invalid_Value;
 
-  if (!ctx->key_queue)
+  err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, (void **) &opd, -1, NULL);
+  if (err)
+    return err;
+
+  if (!opd->key_queue)
     {
-      GpgmeError err = _gpgme_wait_on_condition (ctx, &ctx->key_cond);
+      err = _gpgme_wait_on_condition (ctx, &opd->key_cond);
       if (err)
        return err;
-      if (!ctx->key_cond)
+
+      if (!opd->key_cond)
        return GPGME_EOF;
-      ctx->key_cond = 0; 
-      assert (ctx->key_queue);
+
+      opd->key_cond = 0; 
+      assert (opd->key_queue);
     }
-  queue_item = ctx->key_queue;
-  ctx->key_queue = queue_item->next;
-  if (!ctx->key_queue)
-    ctx->key_cond = 0;
+  queue_item = opd->key_queue;
+  opd->key_queue = queue_item->next;
+  if (!opd->key_queue)
+    opd->key_cond = 0;
   
   *r_key = queue_item->key;
   free (queue_item);
@@ -845,13 +797,7 @@ gpgme_op_keylist_next (GpgmeCtx ctx, GpgmeKey *r_key)
 }
 
 
-/**
- * gpgme_op_keylist_end:
- * @c: Context
- * 
- * Ends the keylist operation and allows to use the context for some
- * other operation next.
- **/
+/* Terminate a pending keylist operation within CTX.  */
 GpgmeError
 gpgme_op_keylist_end (GpgmeCtx ctx)
 {
index d113160..0159ebc 100644 (file)
@@ -53,10 +53,6 @@ GpgmeError    _gpgme_data_append_percentstring_for_xml ( GpgmeData dh,
 GpgmeError _gpgme_data_inbound_handler (void *opaque, int fd);
 GpgmeError _gpgme_data_outbound_handler (void *opaque, int fd);
 
-/*-- key.c --*/
-GpgmeError _gpgme_key_new ( GpgmeKey *r_key );
-GpgmeError _gpgme_key_new_secret ( GpgmeKey *r_key );
-
 \f
 /* From op-support.c.  */
 
@@ -119,12 +115,27 @@ GpgmeError _gpgme_progress_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
                                           char *args);
 
 \f
-/*-- keylist.c --*/
+/* From key.c.  */
+GpgmeError _gpgme_key_new (GpgmeKey *r_key);
+GpgmeError _gpgme_key_add_subkey (GpgmeKey key, GpgmeSubkey *r_subkey);
+GpgmeError _gpgme_key_append_name (GpgmeKey key, char *src);
+GpgmeKeySig _gpgme_key_add_sig (GpgmeKey key, char *src);
+
+\f
+/* From keylist.c.  */
 void _gpgme_op_keylist_event_cb (void *data, GpgmeEventIO type, void *type_data);
 
-/*-- trustlist.c --*/
+\f
+/* From trust-item.c.  */
+
+/* Create a new trust item.  */
+GpgmeError _gpgme_trust_item_new (GpgmeTrustItem *r_item);
+
+\f
+/* From trustlist.c.  */
 void _gpgme_op_trustlist_event_cb (void *data, GpgmeEventIO type, void *type_data);
 
+\f
 /*-- version.c --*/
 const char *_gpgme_compare_versions (const char *my_version,
                                     const char *req_version);
index 7dbfe3c..693a486 100644 (file)
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 
-#include "util.h"
 #include "context.h"
 
-/**
- * gpgme_recipients_new:
- * @r_rset: Returns the new object.
- * 
- * Create a new uninitialized Reciepient set Object.
- * 
- * Return value: 0 on success or an error code.
- **/
+\f
+/* Create a new uninitialized recipient object and return it in R_RSET.  */
 GpgmeError
 gpgme_recipients_new (GpgmeRecipients *r_rset)
 {
-    GpgmeRecipients rset;
-
-    rset = calloc ( 1, sizeof *rset  );
-    if (!rset)
-        return GPGME_Out_Of_Core;
-    *r_rset = rset;
-    return 0;
+  GpgmeRecipients rset;
+    
+  rset = calloc (1, sizeof *rset);
+  if (!rset)
+    return GPGME_Out_Of_Core;
+  *r_rset = rset;
+  return 0;
 }
 
-/**
- * gpgme_recipients_release:
- * @rset: Recipient Set object
- * 
- * Free the given object.
- **/
+
+/* Release the recipient object RSET.  */
 void
-gpgme_recipients_release ( GpgmeRecipients rset )
+gpgme_recipients_release (GpgmeRecipients rset)
 {
-    if (rset) {
-        struct user_id_s *u, *u2;
+  GpgmeUserID uid = rset->list;
 
-        for (u = rset->list; u; u = u2) {
-            u2 = u->next;
-            free(u);
-        }
+  while (uid)
+    {
+      GpgmeUserID next_uid = uid->next;
+
+      free (uid);
+      uid = next_uid;
     }
-    free ( rset );
+  free (rset);
 }
 
 
-/**
- * gpgme_recipients_add_name:
- * @rset: Recipient Set object 
- * @name: user name or keyID
- * 
- * Add a name to the recipient Set.
- * 
- * Return value: 0 on success or an error code
- **/
+/* Add the name NAME to the recipient set RSET with the given key
+   validity VALIDITY.  */
 GpgmeError
-gpgme_recipients_add_name (GpgmeRecipients rset, const char *name )
+gpgme_recipients_add_name_with_validity (GpgmeRecipients rset,
+                                        const char *name,
+                                         GpgmeValidity validity)
 {
-    return gpgme_recipients_add_name_with_validity (
-        rset, name, GPGME_VALIDITY_UNKNOWN
-        );
+  GpgmeUserID uid;
+
+  if (!name || !rset)
+    return GPGME_Invalid_Value;
+  uid = malloc (sizeof (*uid) + strlen (name));
+  if (!uid)
+    return GPGME_Out_Of_Core;
+  uid->validity = validity;
+  uid->name = "";
+  uid->email = "";
+  uid->comment = "";
+  uid->uid = ((char *) uid) + sizeof (*uid);
+  strcpy (uid->uid, name);
+  uid->next = rset->list;
+  rset->list = uid;
+  return 0;
 }
 
-/**
- * gpgme_recipients_add_name_with_validity:
- * @rset: Recipient Set object
- * @name: user name or keyID
- * @val: Validity value 
- * 
- * Same as gpgme_recipients_add_name() but with explictly given key
- * validity.  Use one of the constants 
- * %GPGME_VALIDITY_UNKNOWN, %GPGME_VALIDITY_UNDEFINED,
- * %GPGME_VALIDITY_NEVER, %GPGME_VALIDITY_MARGINAL,
- * %GPGME_VALIDITY_FULL, %GPGME_VALIDITY_ULTIMATE
- * for the validity.  %GPGME_VALIDITY_UNKNOWN is implicitly used by
- * gpgme_recipients_add_name().
- *
- * Return value: o on success or an error value.
- **/
+
+/* Add the name NAME to the recipient set RSET.  Same as
+   gpgme_recipients_add_name_with_validity with validitiy
+   GPGME_VALIDITY_UNKNOWN.  */
 GpgmeError
-gpgme_recipients_add_name_with_validity (GpgmeRecipients rset,
-                                         const char *name,
-                                         GpgmeValidity val )
+gpgme_recipients_add_name (GpgmeRecipients rset, const char *name)
 {
-    struct user_id_s *r;
-
-    if (!name || !rset )
-        return GPGME_Invalid_Value;
-    r = malloc ( sizeof *r + strlen (name) );
-    if (!r)
-        return GPGME_Out_Of_Core;
-    r->validity = val;
-    r->name_part = "";
-    r->email_part = "";
-    r->comment_part = "";
-    strcpy (r->name, name );
-    r->next = rset->list;
-    rset->list = r;
-    return 0;
+  return gpgme_recipients_add_name_with_validity (rset, name,
+                                                 GPGME_VALIDITY_UNKNOWN);
 }
 
 
-
-/**
- * gpgme_recipients_count:
- * @rset: Recipient Set object
- * 
- * Return value: The number of recipients in the set.
- **/
+/* Return the number of recipients in the set.  */
 unsigned int 
-gpgme_recipients_count ( const GpgmeRecipients rset )
+gpgme_recipients_count (const GpgmeRecipients rset)
 {
-    struct user_id_s *r;
-    unsigned int count = 0;
+  GpgmeUserID uid = rset->list;
+  unsigned int count = 0;
     
-    if ( rset ) {
-        for (r=rset->list ; r; r = r->next )
-            count++;
+  while (uid)
+    {
+      count++;
+      uid = uid->next;
     }
-    return count;
-}
 
+  return count;
+}
 
 
-/**
- * gpgme_recipients_enum_open:
- * @rset: Recipient Set object
- * @ctx: Enumerator
- * 
- * Start an enumeration on the Recipient Set object.  The caller must pass 
- * the address of a void pointer which is used as the enumerator object.
- * 
- * Return value: 0 on success or an error code.
- *
- * See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
- **/
+/* Start an enumeration on the recipient set RSET.  The caller must
+   pass the address of a void pointer which is used as the iterator
+   object.  */
 GpgmeError
-gpgme_recipients_enum_open ( const GpgmeRecipients rset, void **ctx )
+gpgme_recipients_enum_open (const GpgmeRecipients rset, void **iter)
 {
-    if (!rset || !ctx)
-        return GPGME_Invalid_Value;
-
-    *ctx = rset->list;
-    return 0;
+  *iter = rset->list;
+  return 0;
 }
 
-/**
- * gpgme_recipients_enum_read:
- * @rset: Recipient Set object
- * @ctx: Enumerator 
- * 
- * Return the name of the next user name from the given recipient
- * set. This name is valid as along as the @rset is valid and until
- * the next call to this function.
- * 
- * Return value: name or NULL for no more names.
- *
- * See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
- **/
+/* Return the name of the next recipient in the set RSET.  */
 const char *
-gpgme_recipients_enum_read ( const GpgmeRecipients rset, void **ctx )
+gpgme_recipients_enum_read (const GpgmeRecipients rset, void **iter)
 {
-    struct user_id_s *r;
-
-    if (!rset || !ctx)
-        return NULL; /* oops */
-    
-    r = *ctx;
-    if ( r ) {
-        const char *s = r->name;
-        r = r->next;
-        *ctx = r;
-        return s;
-    }
+  GpgmeUserID uid;
 
+  uid = *iter;
+  if (!uid)
     return NULL;
+
+  *iter = uid->next;
+  return uid->name;
 }
 
-/**
- * gpgme_recipients_enum_close:
- * @rset: Recipient Set object
- * @ctx: Enumerator
- * 
- * Release the enumerator @rset for this object.
- * 
- * Return value: 0 on success or %GPGME_Invalid_Value;
- *
- * See also: gpgme_recipients_enum_read(), gpgme_recipients_enum_close().
- **/
+/* Release the iterator for this object.  */
 GpgmeError
-gpgme_recipients_enum_close ( const GpgmeRecipients rset, void **ctx )
+gpgme_recipients_enum_close (const GpgmeRecipients rset, void **iter)
 {
-    if (!rset || !ctx)
-        return GPGME_Invalid_Value;
-    *ctx = NULL;
-    return 0;
+  /* Not really needed, but might catch the occasional mistake.  */
+  *iter = NULL;
+
+  return 0;
 }
 
+
 int
-_gpgme_recipients_all_valid ( const GpgmeRecipients rset )
+_gpgme_recipients_all_valid (const GpgmeRecipients rset)
 {
-    struct user_id_s *r;
-
-    assert (rset);
-    for (r=rset->list ; r; r = r->next ) {
-        if (r->validity != GPGME_VALIDITY_FULL
-            && r->validity != GPGME_VALIDITY_ULTIMATE )
-            return 0; /*no*/
+  GpgmeUserID uid = rset->list;
+
+  while (uid)
+    {
+      if (uid->validity != GPGME_VALIDITY_FULL
+         && uid->validity != GPGME_VALIDITY_ULTIMATE )
+       return 0;
+      uid = uid->next;
     }
-    return 1; /*yes*/
+  return 1;
 }
-
-
-
index e25336a..ab13726 100644 (file)
@@ -437,9 +437,10 @@ gpg_set_colon_line_handler (void *engine, EngineColonLineHandler fnc,
 
 /* Here we handle --command-fd.  This works closely together with the
    status handler.  */
-static int
+static GpgmeError
 command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
 {
+  GpgmeError err;
   GpgObject gpg = opaque;
   const char *value;
   int value_len;
@@ -462,8 +463,11 @@ command_cb (void *opaque, char *buffer, size_t length, size_t *nread)
     }
 
   /* FIXME catch error */
-  gpg->cmd.fnc (gpg->cmd.fnc_value, 
-               gpg->cmd.code, gpg->cmd.keyword, &value);
+  err = gpg->cmd.fnc (gpg->cmd.fnc_value, 
+                     gpg->cmd.code, gpg->cmd.keyword, &value);
+  if (err)
+    return err;
+
   if (!value)
     {
       DEBUG0 ("command_cb: no data from user cb\n");
@@ -1200,11 +1204,10 @@ gpg_delete (void *engine, GpgmeKey key, int allow_secret)
     err = add_arg (gpg, "--");
   if (!err)
     {
-      const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
-      if (!s)
+      if (!key->subkeys || !key->subkeys->fpr)
        err = GPGME_Invalid_Key;
       else
-       err = add_arg (gpg, s);
+       err = add_arg (gpg, key->subkeys->fpr);
     }
 
   if (!err)
@@ -1222,8 +1225,7 @@ append_args_from_signers (GpgObject gpg, GpgmeCtx ctx /* FIXME */)
 
   for (i = 0; (key = gpgme_signers_enum (ctx, i)); i++)
     {
-      const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID,
-                                                NULL, 0);
+      const char *s = key->subkeys ? key->subkeys->keyid : NULL;
       if (s)
        {
          if (!err)
@@ -1255,7 +1257,7 @@ gpg_edit (void *engine, GpgmeKey key, GpgmeData out, GpgmeCtx ctx /* FIXME */)
     err = add_arg (gpg, "--");
   if (!err)
     {
-      const char *s = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0);
+      const char *s = key->subkeys ? key->subkeys->fpr : NULL;
       if (!s)
        err = GPGME_Invalid_Key;
       else
@@ -1272,14 +1274,14 @@ static GpgmeError
 append_args_from_recipients (GpgObject gpg, const GpgmeRecipients rset)
 {
   GpgmeError err = 0;
-  struct user_id_s *r;
+  GpgmeUserID uid;
 
   assert (rset);
-  for (r = rset->list; r; r = r->next)
+  for (uid = rset->list; uid; uid = uid->next)
     {
       err = add_arg (gpg, "-r");
       if (!err)
-       err = add_arg (gpg, r->name);
+       err = add_arg (gpg, uid->uid);
       if (err)
        break;
     }    
index 4fa9753..c30a6dc 100644 (file)
@@ -48,10 +48,10 @@ _gpgme_trust_item_new (GpgmeTrustItem *r_item)
   item->_refs = 1;
   item->keyid = item->_keyid;
   item->_keyid[16] = '\0';
-  item->otrust = item->_otrust;
-  item->_otrust[1] = '\0';
-  item->val = item->_val;
-  item->_val[1] = '\0';
+  item->owner_trust = item->_owner_trust;
+  item->_owner_trust[1] = '\0';
+  item->validity = item->_validity;
+  item->_validity[1] = '\0';
   *r_item = item;
   return 0;
 }
@@ -119,11 +119,11 @@ const char *gpgme_trust_item_get_string_attr (GpgmeTrustItem item,
       break;
 
     case GPGME_ATTR_OTRUST:  
-      val = item->otrust;
+      val = item->owner_trust;
       break;
 
     case GPGME_ATTR_VALIDITY:
-      val = item->val;
+      val = item->validity;
       break;
 
     case GPGME_ATTR_USERID:  
index 4061781..974f6cc 100644 (file)
@@ -99,10 +99,10 @@ trustlist_colon_handler (void *priv, char *line)
          item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
          break;
        case 5: /* owner trust */
-         item->_otrust[0] = *p;
+         item->_owner_trust[0] = *p;
          break;
        case 6: /* validity */
-         item->_val[0] = *p;
+         item->_validity[0] = *p;
          break;
        case 9: /* user ID */
          item->name = strdup (p);
index 04b911a..2a44f23 100644 (file)
@@ -1,3 +1,12 @@
+2003-04-30  Marcus Brinkmann  <marcus@g10code.de>
+
+       * gpg/t-keylist.c: Rewritten.
+       * gpgsm/t-keylist.c (main): Rewritten.
+       * gpg/t-edit.c (main): Do not use gpgme_key_get_as_xml.  Use
+       gpgme_key_unref instead gpgme_key_release.
+       * gpg/t-signers.c (main): Use gpgme_key_unref instead
+       gpgme_key_release.
+
 2003-04-29  Marcus Brinkmann  <marcus@g10code.de>
 
        * gpg/t-trustlist.c: Rewritten.
index b78a7fe..8963832 100644 (file)
@@ -150,13 +150,6 @@ main (int argc, char **argv)
       err = gpgme_op_keylist_end (ctx);
       fail_if_err (err);
 
-      p = gpgme_key_get_as_xml (key);
-      if (p)
-       {
-         fputs (p, stdout);
-         free (p);
-       }
-
       err = gpgme_op_edit (ctx, key, edit_fnc, out, out);
       fail_if_err (err);
 
@@ -164,7 +157,7 @@ main (int argc, char **argv)
       flush_data (out);
 
       gpgme_data_release (out);
-      gpgme_key_release (key);
+      gpgme_key_unref (key);
       gpgme_release (ctx);
     }
   while (argc > 1 && !strcmp( argv[1], "--loop"));
index 24edef5..7084e37 100644 (file)
 /* t-keylist.c  - regression test
- *     Copyright (C) 2000 Werner Koch (dd9jn)
- *      Copyright (C) 2001 g10 Code GmbH
- *
- * This file is part of GPGME.
- *
- * GPGME is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GPGME is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
+   Copyright (C) 2000 Werner Koch (dd9jn)
+   Copyright (C) 2001, 2003 g10 Code GmbH
+
+   This file is part of GPGME.
+   GPGME is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   GPGME is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with GPGME; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include <stdio.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 #include <gpgme.h>
 
-#define fail_if_err(a) do { if(a) {                                       \
-                               fprintf (stderr, "%s:%d: GpgmeError %s\n", \
-                                __FILE__, __LINE__, gpgme_strerror(a));   \
-                                exit (1); }                               \
-                             } while(0)
+\f
+#define fail_if_err(err)                                       \
+  do                                                           \
+    {                                                          \
+      if (err)                                                 \
+        {                                                      \
+          fprintf (stderr, "%s:%d: GpgmeError %s\n",           \
+                   __FILE__, __LINE__, gpgme_strerror (err));   \
+          exit (1);                                            \
+        }                                                      \
+    }                                                          \
+  while (0)
+
+
+struct
+{
+  char *fpr;
+  char *sec_keyid;
+  struct
+  {
+    char *name;
+    char *comment;
+    char *email;
+  } uid[3];
+}
+keys[] =
+  {
+    { "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
+      { { "Alpha Test", "demo key", "alpha@example.net" },
+       { "Alice", "demo key", NULL },
+       { "Alfa Test", "demo key", "alfa@example.net" } } },
+    { "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
+      { { "Charlie Test", "demo key", "charlie@example.net" } } },
+    { "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
+      { { "Echelon", "demo key", NULL },
+       { "Echo Test", "demo key", "echo@example.net" },
+       { "Eve", "demo key", NULL } } },
+    { "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
+      { { "Golf Test", "demo key", "golf@example.net" } } },
+    { "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
+      { { "India Test", "demo key", "india@example.net" } } },
+    { "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
+      { { "Kilo Test", "demo key", "kilo@example.net" } } },
+    { "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
+      { { "Bob", "demo key", NULL },
+       { "Bravo Test", "demo key", "bravo@example.net" } } },
+    { "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
+      { { "Delta Test", "demo key", "delta@example.net" } } },
+    { "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
+      { { "Foxtrot Test", "demo key", "foxtrot@example.net" } } },
+    { "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
+      { { "Hotel Test", "demo key", "hotel@example.net" } } },
+    { "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
+      { { "Juliet Test", "demo key", "juliet@example.net" } } },
+    { "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
+      { { "Lima Test", "demo key", "lima@example.net" } } },
+    { "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
+      { { "Mallory", "demo key", NULL },
+       { "Mike Test", "demo key", "mike@example.net" } } },
+    { "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
+      { { "November Test", "demo key", "november@example.net" } } },
+    { "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
+      { { "Oscar Test", "demo key", "oscar@example.net" } } },
+    { "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
+      { { "Papa test", "demo key", "papa@example.net" } } },
+    { "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
+      { { "Quebec Test", "demo key", "quebec@example.net" } } },
+    { "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
+      { { "Romeo Test", "demo key", "romeo@example.net" } } },
+    { "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
+      { { "Sierra Test", "demo key", "sierra@example.net" } } },
+    { "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
+      { { "Tango Test", "demo key", "tango@example.net" } } },
+    { "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
+      { { "Uniform Test", "demo key", "uniform@example.net" } } },
+    { "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
+      { { "Victor Test", "demo key", "victor@example.org" } } },
+    { "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
+      { { "Whisky Test", "demo key", "whisky@example.net" } } },
+    { "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
+      { { "XRay Test", "demo key", "xray@example.net" } } },
+    { "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
+      { { "Yankee Test", "demo key", "yankee@example.net" } } },
+    { "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
+      { { "Zulu Test", "demo key", "zulu@example.net" } } },
+    { "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", "087DD7E0381701C4",
+      { { "Joe Random Hacker", "test key with passphrase \"x\"",
+         "joe@setq.org" } } },
+    { NULL }
+  };
 
-static void
-doit (GpgmeCtx ctx, const char *pattern)
+int 
+main (int argc, char **argv)
 {
   GpgmeError err;
+  GpgmeCtx ctx;
   GpgmeKey key;
+  GpgmeKeyListResult result;
+  int i = 0;
+
+  err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
+  fail_if_err (err);
+
+  err = gpgme_new (&ctx);
+  fail_if_err (err);
 
-  err = gpgme_op_keylist_start (ctx, pattern, 0);
+  err = gpgme_op_keylist_start (ctx, NULL, 0);
   fail_if_err (err);
     
   while (!(err = gpgme_op_keylist_next (ctx, &key)))
     {
-      char *p;
-      const char *s;
-      int i;
-
-      printf ("<!-- Begin key object (%p) -->\n", key);
-      p = gpgme_key_get_as_xml (key);
-      if (p)
-       {
-         fputs (p, stdout);
-         free (p);
-        }
-      else
-       fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout);
-
-      for (i = 0; ; i++)
-       {
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i);
-         if (!s)
-           break;
-         printf ("<!-- keyid.%d=%s -->\n", i, s);
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i);
-         printf ("<!-- algo.%d=%s -->\n", i, s);
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i);
-         printf ("<!-- caps.%d=%s -->\n", i, s);
-        }
-      for (i = 0; ; i++)
-       {
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i);
-         if (!s)
-           break;
-         printf ("<!-- name.%d=%s -->\n", i, s);
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i);
-         printf ("<!-- email.%d=%s -->\n", i, s);
-         s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i);
-         printf ("<!-- comment.%d=%s -->\n", i, s);
-        }
-      
-      fputs ("<!-- usable for:", stdout);
-      if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_ENCRYPT, NULL, 0))
-       fputs (" encryption", stdout);
-      if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_SIGN, NULL, 0))
-       fputs (" signing", stdout);
-      if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_CERTIFY, NULL, 0))
-       fputs (" certification", stdout);
-      fputs (" -->\n", stdout );
-      
-      printf ("<!-- End key object (%p) -->\n", key);
-      gpgme_key_release (key);
-    }
-  if (err != GPGME_EOF)
-    fail_if_err (err);
-}
+      if (!keys[i].fpr)
+       {
+         fprintf (stderr, "More keys returned than expected\n");
+         exit (1);
+       }
 
+      /* Global key flags.  */
+      if (key->revoked)
+       {
+         fprintf (stderr, "Key unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->expired)
+       {
+         fprintf (stderr, "Key unexpectedly expired\n");
+         exit (1);
+       }
+      if (key->disabled)
+       {
+         fprintf (stderr, "Key unexpectedly disabled\n");
+         exit (1);
+       }
+      if (key->invalid)
+       {
+         fprintf (stderr, "Key unexpectedly invalid\n");
+         exit (1);
+       }
+      if (!key->can_encrypt)
+       {
+         fprintf (stderr, "Key unexpectedly unusable for encryption\n");
+         exit (1);
+       }
+      if (!key->can_sign)
+       {
+         fprintf (stderr, "Key unexpectedly unusable for signing\n");
+         exit (1);
+       }
+      if (!key->can_certify)
+       {
+         fprintf (stderr, "Key unexpectedly unusable for certifications\n");
+         exit (1);
+       }
+      if (key->secret)
+       {
+         fprintf (stderr, "Key unexpectedly secret\n");
+         exit (1);
+       }
+      if (key->protocol != GPGME_PROTOCOL_OpenPGP)
+       {
+         fprintf (stderr, "Key has unexpected protocol: %s\n",
+                  gpgme_get_protocol_name (key->protocol));
+         exit (1);
+       }
+      if (key->issuer_serial)
+       {
+         fprintf (stderr, "Key unexpectedly carries issuer serial: %s\n",
+                  key->issuer_serial);
+         exit (1);
+       }
+      if (key->issuer_name)
+       {
+         fprintf (stderr, "Key unexpectedly carries issuer name: %s\n",
+                  key->issuer_name);
+         exit (1);
+       }
+      if (key->chain_id)
+       {
+         fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
+                  key->chain_id);
+         exit (1);
+       }
+      if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "Key has unexpected owner trust: %i\n",
+                  key->owner_trust);
+         exit (1);
+       }
+      if (!key->subkeys || !key->subkeys->next || key->subkeys->next->next)
+       {
+         fprintf (stderr, "Key has unexpected number of subkeys\n");
+         exit (1);
+       }
 
-/* 
- * Check that there are no problems when we are using two context for
- * listing keys. 
- */
-static void
-check_two_contexts (void)
-{
-  GpgmeError err;
-  GpgmeCtx ctx1, ctx2;
-  GpgmeKey key;
-       
-  err = gpgme_new(&ctx1); fail_if_err (err);
-  err = gpgme_op_keylist_start(ctx1, "", 1);
-  fail_if_err (err);
-  err = gpgme_new(&ctx2); fail_if_err (err);
-  err = gpgme_op_keylist_start(ctx2, "", 1);
-  fail_if_err (err);
-  
-  while ((err = gpgme_op_keylist_next (ctx2, &key)) != GPGME_EOF)
-    gpgme_key_release (key);
+      /* Primary key.  */
+      if (key->subkeys->revoked)
+       {
+         fprintf (stderr, "Primary key unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->subkeys->expired)
+       {
+         fprintf (stderr, "Primary key unexpectedly expired\n");
+         exit (1);
+       }
+      if (key->subkeys->disabled)
+       {
+         fprintf (stderr, "Primary key unexpectedly disabled\n");
+         exit (1);
+       }
+      if (key->subkeys->invalid)
+       {
+         fprintf (stderr, "Primary key unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->subkeys->can_encrypt)
+       {
+         fprintf (stderr, "Primary key unexpectedly usable for encryption\n");
+         exit (1);
+       }
+      if (!key->subkeys->can_sign)
+       {
+         fprintf (stderr, "Primary key unexpectedly unusable for signing\n");
+         exit (1);
+       }
+      if (!key->subkeys->can_certify)
+       {
+         fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
+         exit (1);
+       }
+      if (key->subkeys->secret)
+       {
+         fprintf (stderr, "Primary key unexpectedly secret\n");
+         exit (1);
+       }
+      if (key->subkeys->pubkey_algo != GPGME_PK_DSA)
+       {
+         fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
+                  gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
+         exit (1);
+       }
+      if (key->subkeys->length != 1024)
+       {
+         fprintf (stderr, "Primary key has unexpected length: %i\n",
+                  key->subkeys->length);
+         exit (1);
+       }
+      if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
+       {
+         fprintf (stderr, "Primary key has unexpected key ID: %s\n",
+                  key->subkeys->keyid);
+         exit (1);
+       }
+      if (strcmp (key->subkeys->fpr, keys[i].fpr))
+       {
+         fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
+                  key->subkeys->fpr);
+         exit (1);
+       }
+      if (key->subkeys->expires)
+       {
+         fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
+                  key->subkeys->expires);
+         exit (1);
+       }
 
-  if (err != GPGME_EOF)
-    fail_if_err (err);
-  while ((err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF)
-    gpgme_key_release (key);
+      /* Secondary key.  */
+      if (key->subkeys->next->revoked)
+       {
+         fprintf (stderr, "Secondary key unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->subkeys->next->expired)
+       {
+         fprintf (stderr, "Secondary key unexpectedly expired\n");
+         exit (1);
+       }
+      if (key->subkeys->next->disabled)
+       {
+         fprintf (stderr, "Secondary key unexpectedly disabled\n");
+         exit (1);
+       }
+      if (key->subkeys->next->invalid)
+       {
+         fprintf (stderr, "Secondary key unexpectedly invalid\n");
+         exit (1);
+       }
+      if (!key->subkeys->next->can_encrypt)
+       {
+         fprintf (stderr, "Secondary key unexpectedly unusable for encryption\n");
+         exit (1);
+       }
+      if (key->subkeys->next->can_sign)
+       {
+         fprintf (stderr, "Secondary key unexpectedly usable for signing\n");
+         exit (1);
+       }
+      if (key->subkeys->next->can_certify)
+       {
+         fprintf (stderr, "Secondary key unexpectedly usable for certifications\n");
+         exit (1);
+       }
+      if (key->subkeys->next->secret)
+       {
+         fprintf (stderr, "Secondary key unexpectedly secret\n");
+         exit (1);
+       }
+      if (key->subkeys->next->pubkey_algo != GPGME_PK_ELG_E)
+       {
+         fprintf (stderr, "Secondary key has unexpected public key algo: %s\n",
+                  gpgme_pubkey_algo_name (key->subkeys->next->pubkey_algo));
+         exit (1);
+       }
+      if (key->subkeys->next->length != 1024)
+       {
+         fprintf (stderr, "Secondary key has unexpected length: %i\n",
+                  key->subkeys->next->length);
+         exit (1);
+       }
+      if (strcmp (key->subkeys->next->keyid, keys[i].sec_keyid))
+       {
+         fprintf (stderr, "Secondary key has unexpected key ID: %s\n",
+                  key->subkeys->next->keyid);
+         exit (1);
+       }
+      if (key->subkeys->next->fpr)
+       {
+         fprintf (stderr, "Secondary key has unexpectedly a fingerprint: %s\n",
+                  key->subkeys->next->fpr);
+         exit (1);
+       }
+      if (key->subkeys->next->expires)
+       {
+         fprintf (stderr, "Secondary key unexpectedly expires: %lu\n",
+                  key->subkeys->next->expires);
+         exit (1);
+       }
 
+      /* FIXME: The below test will crash if we want to check for a
+        name, comment or email that doesn't exist in the key's user
+        IDs.  */
+      if (!((!keys[i].uid[0].name && !key->uids)
+           || (keys[i].uid[0].name && !keys[i].uid[1].name
+               && key->uids && !key->uids->next)
+           || (keys[i].uid[0].name && keys[i].uid[1].name
+               && !keys[i].uid[2].name
+               && key->uids && key->uids->next && !key->uids->next->next)
+           || (keys[i].uid[0].name && keys[i].uid[1].name
+               && keys[i].uid[2].name
+               && key->uids && key->uids->next && key->uids->next->next
+               && !key->uids->next->next->next)))
+         {
+           fprintf (stderr, "Key has unexpected number of user IDs\n");
+           exit (1);
+         }
+      if (key->uids && key->uids->revoked)
+       {
+         fprintf (stderr, "First user ID unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->invalid)
+       {
+         fprintf (stderr, "First user ID unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->validity != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "First user ID has unexpectedly validity: %i\n",
+                  key->uids->validity);
+         exit (1);
+       }
+      if (key->uids && key->uids->signatures)
+       {
+         fprintf (stderr, "First user ID unexpectedly signed\n");
+         exit (1);
+       }
+      if (keys[i].uid[0].name
+         && strcmp (keys[i].uid[0].name, key->uids->name))
+       {
+         fprintf (stderr, "Unexpected name in first user ID: %s\n",
+                  key->uids->name);
+         exit (1);
+       }
+      if (keys[i].uid[0].comment
+         && strcmp (keys[i].uid[0].comment, key->uids->comment))
+       {
+         fprintf (stderr, "Unexpected comment in first user ID: %s\n",
+                  key->uids->comment);
+         exit (1);
+       }
+      if (keys[i].uid[0].email
+         && strcmp (keys[i].uid[0].email, key->uids->email))
+       {
+         fprintf (stderr, "Unexpected email in first user ID: %s\n",
+                  key->uids->email);
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->revoked)
+       {
+         fprintf (stderr, "Second user ID unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->invalid)
+       {
+         fprintf (stderr, "Second user ID unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->next
+         && key->uids->next->validity != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "Second user ID has unexpectedly validity: %i\n",
+                  key->uids->next->validity);
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->signatures)
+       {
+         fprintf (stderr, "Second user ID unexpectedly signed\n");
+         exit (1);
+       }
+      if (keys[i].uid[1].name
+         && strcmp (keys[i].uid[1].name, key->uids->next->name))
+       {
+         fprintf (stderr, "Unexpected name in second user ID: %s\n",
+                  key->uids->next->name);
+         exit (1);
+       }
+      if (keys[i].uid[1].comment
+         && strcmp (keys[i].uid[1].comment, key->uids->next->comment))
+       {
+         fprintf (stderr, "Unexpected comment in second user ID: %s\n",
+                  key->uids->next->comment);
+         exit (1);
+       }
+      if (keys[i].uid[1].email
+         && strcmp (keys[i].uid[1].email, key->uids->next->email))
+       {
+         fprintf (stderr, "Unexpected email in second user ID: %s\n",
+                  key->uids->next->email);
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->next
+         && key->uids->next->next->revoked)
+       {
+         fprintf (stderr, "Third user ID unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->next
+         && key->uids->next->next->invalid)
+       {
+         fprintf (stderr, "Third user ID unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->next
+         && key->uids->next->next->validity != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "Third user ID has unexpectedly validity: %i\n",
+                  key->uids->next->next->validity);
+         exit (1);
+       }
+      if (key->uids && key->uids->next && key->uids->next->next
+         && key->uids->next->next->signatures)
+       {
+         fprintf (stderr, "Third user ID unexpectedly signed\n");
+         exit (1);
+       }
+      if (keys[i].uid[2].name
+         && strcmp (keys[i].uid[2].name, key->uids->next->next->name))
+       {
+         fprintf (stderr, "Unexpected name in third user ID: %s\n",
+                  key->uids->next->next->name);
+         exit (1);
+       }
+      if (keys[i].uid[2].comment
+         && strcmp (keys[i].uid[2].comment, key->uids->next->next->comment))
+       {
+         fprintf (stderr, "Unexpected comment in third user ID: %s\n",
+                  key->uids->next->next->comment);
+         exit (1);
+       }
+      if (keys[i].uid[2].email
+         && strcmp (keys[i].uid[2].email, key->uids->next->next->email))
+       {
+         fprintf (stderr, "Unexpected email in third user ID: %s\n",
+                  key->uids->next->next->email);
+         exit (1);
+       }
+
+      gpgme_key_unref (key);
+      i++;
+    }
   if (err != GPGME_EOF)
     fail_if_err (err);
-}
-
+  err = gpgme_op_keylist_end (ctx);
+  fail_if_err (err);
 
-int 
-main (int argc, char **argv)
-{
-  GpgmeCtx ctx;
-  GpgmeError err;
-  int loop = 0;
-  const char *pattern;
-    
-  if (argc)
+  result = gpgme_op_keylist_result (ctx);
+  if (result->truncated)
     {
-      argc--;
-      argv++;
+      fprintf (stderr, "Key listing unexpectedly truncated\n");
+      exit (1);
     }
-    
-  if (argc && !strcmp( *argv, "--loop"))
-    {
-      loop = 1;
-      argc--; argv++;
-    }
-  pattern = argc? *argv : NULL;
 
-  err = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP);
-  fail_if_err (err);
-
-  err = gpgme_new (&ctx);
-  fail_if_err (err);
-  /* No validity calculation.  */
-  gpgme_set_keylist_mode (ctx, 1);
-  do
+  if (keys[i].fpr)
     {
-      fprintf (stderr, "** pattern=`%s'\n", pattern ? pattern : "(null)");
-      doit (ctx, pattern);
+      fprintf (stderr, "Less keys returned than expected\n");
+      exit (1);
     }
-  while (loop);
-  gpgme_release (ctx);
-
-  check_two_contexts ();
 
+  gpgme_release (ctx);
   return 0;
 }
index 145a33e..de492b4 100644 (file)
@@ -197,7 +197,7 @@ main (int argc, char *argv[])
   gpgme_data_release (in);
   gpgme_release (ctx);
 
-  gpgme_key_release (key[0]);
-  gpgme_key_release (key[1]);
+  gpgme_key_unref (key[0]);
+  gpgme_key_unref (key[1]);
   return 0;
 }
index 2307ad6..716e7de 100644 (file)
 /* t-keylist.c  - regression test
- *     Copyright (C) 2000 Werner Koch (dd9jn)
- *      Copyright (C) 2001 g10 Code GmbH
- *
- * This file is part of GPGME.
- *
- * GPGME is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * GPGME is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
+   Copyright (C) 2000 Werner Koch (dd9jn)
+   Copyright (C) 2001, 2003 g10 Code GmbH
+
+   This file is part of GPGME.
+   GPGME is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   GPGME is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with GPGME; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#include <stdio.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 #include <gpgme.h>
 
-#define fail_if_err(a) do { if(a) {                                       \
-                               fprintf (stderr, "%s:%d: GpgmeError %s\n", \
-                                __FILE__, __LINE__, gpgme_strerror(a));   \
-                                exit (1); }                               \
-                             } while(0)
+\f
+#define fail_if_err(err)                                       \
+  do                                                           \
+    {                                                          \
+      if (err)                                                 \
+        {                                                      \
+          fprintf (stderr, "%s:%d: GpgmeError %s\n",           \
+                   __FILE__, __LINE__, gpgme_strerror (err));   \
+          exit (1);                                            \
+        }                                                      \
+    }                                                          \
+  while (0)
 
-static void
-doit ( GpgmeCtx ctx, const char *pattern, int secret )
-{
-    GpgmeError err;
-    GpgmeKey key;
 
-    err = gpgme_op_keylist_start (ctx, pattern, secret );
-    fail_if_err (err);
-    
-    while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
-        char *p;
-        const char *s;
-        int i;
-
-        printf ("<!-- Begin key object (%p) -->\n", key );
-        p = gpgme_key_get_as_xml ( key );
-        if ( p ) {
-            fputs ( p, stdout );
-            free (p);
-        }
-        else
-            fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout );
-
-        
-        for (i=0; ; i++ ) {
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, i );
-            if (!s)
-                break;
-            printf ("<!-- keyid.%d=%s -->\n", i, s );
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, i );
-            printf ("<!-- algo.%d=%s -->\n", i, s );
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEY_CAPS, NULL, i );
-            printf ("<!-- caps.%d=%s -->\n", i, s );
-        }
-        for (i=0; ; i++ ) {
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i );
-            if (!s)
-                break;
-            printf ("<!-- name.%d=%s -->\n", i, s );
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i );
-            printf ("<!-- email.%d=%s -->\n", i, s );
-            s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i );
-            printf ("<!-- comment.%d=%s -->\n", i, s );
-        }
-        
-        fputs ("<!-- usable for:", stdout );
-        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_ENCRYPT, NULL, 0 ))
-            fputs (" encryption", stdout);
-        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_SIGN, NULL, 0 ))
-            fputs (" signing", stdout);
-        if ( gpgme_key_get_ulong_attr (key, GPGME_ATTR_CAN_CERTIFY, NULL, 0 ))
-            fputs (" certification", stdout);
-        fputs (" -->\n", stdout );
-
-        printf ("<!-- End key object (%p) -->\n", key );
-        gpgme_key_release (key);
-    }
-    if ( err != GPGME_EOF )
-        fail_if_err (err);
-
-    {
-      char *p;
-
-      p = gpgme_get_op_info (ctx, 0);
-      if (p)
-        {
-          fputs ("<!-- begin operation info -->\n", stdout);
-          fputs (p, stdout);
-          fputs ("<!-- end operation info -->\n", stdout);
-          free (p);
-        }
-    }
+struct
+{
+  char *fpr;
+  int secret;
+  unsigned long expires;
+  char *issuer_serial;
+  char *issuer_name;
+  char *chain_id;
+  char *uid;
 }
+keys[] =
+  {
+    { "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E", 1, 1038908198, "00",
+      "CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE",
+      NULL,
+      "CN=test cert 1,OU=Aegypten Project,O=g10 Code GmbH,L=D\xc3\xbcsseldorf,C=DE" },
+    { "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD", 0, 1009821790, "01",
+      "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
+      "CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
+      "O=Deutsches Forschungsnetz,C=DE", NULL,
+      "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
+      "CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
+      "O=Deutsches Forschungsnetz,C=DE" },
+    { "2C8F3C356AB761CB3674835B792CDA52937F9285", 0, 1009735200, "15",
+      "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
+      "CN=DFN Top Level Certification Authority,OU=DFN-PCA,"
+      "O=Deutsches Forschungsnetz,C=DE",
+      "DFA56FB5FC41E3A8921F77AD1622EEFD9152A5AD",
+      "1.2.840.113549.1.9.1=#63657274696679407063612E64666E2E6465,"
+      "CN=DFN Server Certification Authority,OU=DFN-PCA,"
+      "O=Deutsches Forschungsnetz,C=DE" },
+    { NULL }
+  };
 
-
-/* 
- * Check that there are no problems when we are using two context for
- * listing keys. 
- */
-static void
-check_two_contexts (void)
+int 
+main (int argc, char **argv)
 {
-    GpgmeError err;
-    GpgmeCtx ctx1, ctx2;
-    GpgmeKey key;
-       
-    err = gpgme_new(&ctx1);
-    fail_if_err (err);
-    gpgme_set_protocol (ctx1, GPGME_PROTOCOL_CMS);
+  GpgmeError err;
+  GpgmeCtx ctx;
+  GpgmeKey key;
+  GpgmeKeyListResult result;
+  int i = 0;
 
-    err = gpgme_op_keylist_start(ctx1, "", 1);
-    fail_if_err (err);
-    err = gpgme_new(&ctx2); fail_if_err (err);
-    gpgme_set_protocol (ctx2, GPGME_PROTOCOL_CMS);
-    err = gpgme_op_keylist_start(ctx2, "", 1);
-    fail_if_err (err);
+  err = gpgme_engine_check_version (GPGME_PROTOCOL_CMS);
+  fail_if_err (err);
 
-    while ( (err=gpgme_op_keylist_next(ctx2, &key)) != GPGME_EOF) {
-        gpgme_key_release (key);
-    }
-    if (err != GPGME_EOF)
-        fail_if_err (err);
-    while ( (err=gpgme_op_keylist_next(ctx1, &key)) != GPGME_EOF) {
-        gpgme_key_release (key);
-    }
-    if (err != GPGME_EOF)
-        fail_if_err (err);
-}
+  err = gpgme_new (&ctx);
+  fail_if_err (err);
+  gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
 
-int 
-main (int argc, char **argv )
-{
-    GpgmeCtx ctx;
-    GpgmeError err;
-    int loop = 0;
-    int secret = 0;
-    const char *pattern;
-
-    if( argc ) {
-        argc--; argv++;
-    }
+  err = gpgme_op_keylist_start (ctx, NULL, 0);
+  fail_if_err (err);
     
-    if (argc && !strcmp( *argv, "--loop" ) ) {
-        loop = 1;
-        argc--; argv++;
-    }
-    if (argc && !strcmp( *argv, "--secret" ) ) {
-        secret = 1;
-        argc--; argv++;
-    }
-    pattern = argc? *argv : NULL;
+  while (!(err = gpgme_op_keylist_next (ctx, &key)))
+    {
+      if (!keys[i].fpr)
+       {
+         fprintf (stderr, "More keys returned than expected\n");
+         exit (1);
+       }
 
-    err = gpgme_engine_check_version (GPGME_PROTOCOL_CMS);
-    fail_if_err (err);
+      /* Global key flags.  */
+      if (key->revoked)
+       {
+         fprintf (stderr, "Key unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->expired)
+       {
+         fprintf (stderr, "Key unexpectedly expired\n");
+         exit (1);
+       }
+      if (key->disabled)
+       {
+         fprintf (stderr, "Key unexpectedly disabled\n");
+         exit (1);
+       }
+      if (key->invalid)
+       {
+         fprintf (stderr, "Key unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->can_encrypt != keys[i].secret)
+       {
+         fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
+                  key->can_encrypt ? "" : " not");
+         exit (1);
+       }
+      if (key->can_sign != keys[i].secret)
+       {
+         fprintf (stderr, "Key unexpectedly%s usable for signing\n",
+                  key->can_sign ? "" : " not");
+         exit (1);
+       }
+      if (!key->can_certify)
+       {
+         fprintf (stderr, "Key unexpectedly unusable for certifications\n");
+         exit (1);
+       }
+      if (key->secret != keys[i].secret)
+       {
+         fprintf (stderr, "Key unexpectedly%s secret\n",
+                  key->secret ? "" : " not");
+         exit (1);
+       }
+      if (key->protocol != GPGME_PROTOCOL_CMS)
+       {
+         fprintf (stderr, "Key has unexpected protocol: %s\n",
+                  gpgme_get_protocol_name (key->protocol));
+         exit (1);
+       }
+      if (!key->issuer_serial)
+       {
+         fprintf (stderr, "Key unexpectedly misses issuer serial\n");
+         exit (1);
+       }
+      if (strcmp (key->issuer_serial, keys[i].issuer_serial))
+       {
+         fprintf (stderr, "Key has unexpected issuer serial: %s\n",
+                  key->issuer_serial);
+         exit (1);
+       }
+      if (!key->issuer_name)
+       {
+         fprintf (stderr, "Key unexpectedly misses issuer name\n");
+         exit (1);
+       }
+      if (strcmp (key->issuer_name, keys[i].issuer_name))
+       {
+         fprintf (stderr, "Key has unexpected issuer name: %s\n",
+                  key->issuer_name);
+         exit (1);
+       }
+      if (key->chain_id && !keys[i].chain_id)
+       {
+         fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
+                  key->chain_id);
+         exit (1);
+       }
+      if (!key->chain_id && keys[i].chain_id)
+       {
+         fprintf (stderr, "Key unexpectedly carries no chain ID\n");
+         exit (1);
+       }
+      if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id))
+       {
+         fprintf (stderr, "Key carries unexpected chain ID: %s\n",
+                  key->chain_id);
+         exit (1);
+       }
+      if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "Key has unexpected owner trust: %i\n",
+                  key->owner_trust);
+         exit (1);
+       }
+      if (!key->subkeys || key->subkeys->next)
+       {
+         fprintf (stderr, "Key has unexpected number of subkeys\n");
+         exit (1);
+       }
+
+      /* Primary key.  */
+      if (key->subkeys->revoked)
+       {
+         fprintf (stderr, "Primary key unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->subkeys->expired)
+       {
+         fprintf (stderr, "Primary key unexpectedly expired\n");
+         exit (1);
+       }
+      if (key->subkeys->disabled)
+       {
+         fprintf (stderr, "Primary key unexpectedly disabled\n");
+         exit (1);
+       }
+      if (key->subkeys->invalid)
+       {
+         fprintf (stderr, "Primary key unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->subkeys->can_encrypt != keys[i].secret)
+       {
+         fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
+                  key->subkeys->can_encrypt ? "" : " not");
+         exit (1);
+       }
+      if (key->subkeys->can_sign != keys[i].secret)
+       {
+         fprintf (stderr, "Key unexpectedly%s usable for signing\n",
+                  key->subkeys->can_sign ? "" : " not");
+         exit (1);
+       }
+      if (!key->subkeys->can_certify)
+       {
+         fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
+         exit (1);
+       }
+      if (key->subkeys->secret)
+       {
+         fprintf (stderr, "Primary key unexpectedly secret\n");
+         exit (1);
+       }
+      if (key->subkeys->pubkey_algo != GPGME_PK_RSA)
+       {
+         fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
+                  gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
+         exit (1);
+       }
+      if (key->subkeys->length != 1024)
+       {
+         fprintf (stderr, "Primary key has unexpected length: %i\n",
+                  key->subkeys->length);
+         exit (1);
+       }
+      if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
+       {
+         fprintf (stderr, "Primary key has unexpected key ID: %s\n",
+                  key->subkeys->keyid);
+         exit (1);
+       }
+      if (strcmp (key->subkeys->fpr, keys[i].fpr))
+       {
+         fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
+                  key->subkeys->fpr);
+         exit (1);
+       }
+      if (key->subkeys->expires != keys[i].expires)
+       {
+         fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
+                  key->subkeys->expires);
+         exit (1);
+       }
 
-    err = gpgme_new (&ctx);
+      if (!key->uids || key->uids->next)
+       {
+         fprintf (stderr, "Key has unexpected number of user IDs\n");
+         exit (1);
+       }
+      if (key->uids->revoked)
+       {
+         fprintf (stderr, "User ID unexpectedly revoked\n");
+         exit (1);
+       }
+      if (key->uids->invalid)
+       {
+         fprintf (stderr, "User ID unexpectedly invalid\n");
+         exit (1);
+       }
+      if (key->uids->validity != GPGME_VALIDITY_UNKNOWN)
+       {
+         fprintf (stderr, "User ID unexpectedly validity: %i\n",
+                  key->uids->validity);
+         exit (1);
+       }
+      if (key->uids->signatures)
+       {
+         fprintf (stderr, "User ID unexpectedly signed\n");
+         exit (1);
+       }
+      if (!key->uids->name || key->uids->name[0])
+       {
+         fprintf (stderr, "Unexpected name in user ID: %s\n",
+                  key->uids->name);
+         exit (1);
+       }
+      if (!key->uids->comment || key->uids->comment[0])
+       {
+         fprintf (stderr, "Unexpected comment in user ID: %s\n",
+                  key->uids->comment);
+         exit (1);
+       }
+      if (!key->uids->email || key->uids->email[0])
+       {
+         fprintf (stderr, "Unexpected email in user ID: %s\n",
+                  key->uids->email);
+         exit (1);
+       }
+      if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid))
+       {
+         fprintf (stderr, "Unexpected uid in user ID: %s\n",
+                  key->uids->uid);
+         exit (1);
+       }
+
+      gpgme_key_unref (key);
+      i++;
+    }
+  if (err != GPGME_EOF)
     fail_if_err (err);
-    gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
+  err = gpgme_op_keylist_end (ctx);
+  fail_if_err (err);
 
-    gpgme_set_keylist_mode (ctx, 1); /* no validity calculation */
-    do {
-        fprintf (stderr, "** pattern=`%s'\n", pattern );
-        doit ( ctx, pattern, secret );
-    } while ( loop );
-    gpgme_release (ctx);
+  result = gpgme_op_keylist_result (ctx);
+  if (result->truncated)
+    {
+      fprintf (stderr, "Key listing unexpectedly truncated\n");
+      exit (1);
+    }
 
-    check_two_contexts ();
+  if (keys[i].fpr)
+    {
+      fprintf (stderr, "Less keys returned than expected\n");
+      exit (1);
+    }
 
-    return 0;
+  gpgme_release (ctx);
+  return 0;
 }