doc/
authorMarcus Brinkmann <mb@g10code.com>
Mon, 28 Apr 2003 23:59:03 +0000 (23:59 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Mon, 28 Apr 2003 23:59:03 +0000 (23:59 +0000)
2003-04-28  Marcus Brinkmann  <marcus@g10code.de>

* gpgme.texi (Verify): Rewritten to take into account new and
deprecated functions and data types.

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

* gpgme.h (struct _gpgme_sig_notation): New structure.
(GpgmeSigNotation): New type.
(struct _gpgme_signature): New structure.
(GpgmeSignature): New type.
(struct _gpgme_op_verify_result): New structure.
(GpgmeVerifyResult): New type.
(gpgme_op_verify_result): New prototype.
(gpgme_get_notation): Remove prototype.
* ops.h (_gpgme_op_verify_init_result): New prototype.
(_gpgme_verify_status_handler): Change first argument to void *.
* util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error):
New prototypes.
* conversion.c (_gpgme_decode_percent_string): New function.
(gnupg_errors): New static global.
(_gpgme_map_gnupg_error): New function.
* gpgme.c (gpgme_release): Don't release CTX->notation.
(gpgme_get_notation): Remove function.
* decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call
_gpgme_op_verify_init_result.
* verify.c: Do not include <stdio.h>, <assert.h> and "key.h", but
do include "gpgme.h".
(struct verify_result): Replace with ...
(op_data_t): ... this type.
(release_verify_result): Remove function.
(release_op_data): New function.
(is_token): Remove function.
(skip_token): Remove function.
(copy_token): Remove function.
(gpgme_op_verify_result): New function.
(calc_sig_summary): Rewritten.
(finish_sig): Remove function.
(parse_new_sig): New function.
(parse_valid_sig): New function.
(parse_notation): New function.
(parse_trust): New function.
(parse_error): New function.
(_gpgme_verify_status_handler): Rewritten.  Change first argument
to void *.
(_gpgme_op_verify_start): Rework error handling.  Call
_gpgme_op_verify_init_result.
(gpgme_op_verify): Do not release or clear CTX->notation.
(gpgme_get_sig_status): Rewritten.
(gpgme_get_sig_string_attr): Likewise.
(gpgme_get_sig_ulong_attr): Likewise.
(gpgme_get_sig_key): Likewise.

15 files changed:
NEWS
TODO
doc/ChangeLog
doc/gpgme.texi
gpgme/ChangeLog
gpgme/conversion.c
gpgme/decrypt-verify.c
gpgme/gpgme.c
gpgme/gpgme.h
gpgme/ops.h
gpgme/sign.c
gpgme/util.h
gpgme/verify.c
tests/gpg/t-verify.c
tests/gpgsm/t-verify.c

diff --git a/NEWS b/NEWS
index b6c166f5688974b5b488a144765bce247540ddf7..352380c2cad30512bebec74af54e51dcb1b02b1e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -86,14 +86,17 @@ Noteworthy changes in version 0.4.1 (unreleased)
    information about the result of an encryption operation in
    a GpgmeEncryptResult object.
 
- * The new gpgme_op_encrypt_result function provides detailed
-   information about the result of an encryption operation in
-   a GpgmeEncryptResult object.
-
  * The new gpgme_op_decrypt_result function provides detailed
    information about the result of an encryption operation in
    a GpgmeDecryptResult object.
 
+ * The new gpgme_op_verify_result function provides detailed
+   information about the result of an verify operation in
+   a GpgmeVerifyResult object.  Because of this, the GPGME_SIG_STAT_*
+   values, gpgme_get_sig_status, gpgme_get_sig_ulong_attr,
+   gpgme_get_sig_string_attr and gpgme_get_sig_key are now deprecated,
+   and gpgme_get_notation is removed.
+
  * Interface changes relative to the 0.4.0 release:
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 GpgmeIOCb                      CHANGED: Return type from void to GpgmeError.
@@ -136,6 +139,14 @@ GpgmeEncryptResult         NEW
 gpgme_op_encrypt_result                NEW
 GpgmeDecryptResult             NEW
 gpgme_op_decrypt_result                NEW
+GpgmeVerifyResult              NEW
+gpgme_op_verify_result         NEW
+gpgme_get_notation             REMOVED: Access verify result directly instead.
+gpgme_get_sig_key              DEPRECATED: Use gpgme_get_key with fingerprint.
+gpgme_get_sig_ulong_attr       DEPRECATED: Use verify result directly.
+gpgme_get_sig_string_attr      DEPRECATED: Use verify result directly.
+GPGME_SIG_STAT_*               DEPRECATED: Use error value in sig status.
+gpgme_get_sig_status           DEPRECATED: Use verify result directly.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Noteworthy changes in version 0.4.0 (2002-12-23)
diff --git a/TODO b/TODO
index 00115147d061114ae0f6826c2fa38d8eea241c42..7937e8ea22dd8aeff8a9b608549d88066caa1cf2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,6 +14,13 @@ Hey Emacs, this is -*- outline -*- mode!
 *** GPGME_Busy, GPGME_No_Request
 *** GPGME_No_Passphrase
 *** GPGME_Invalid_Recipient, GPGME_No_Recipients
+*** GPGME_No_Passphrase
+*** gpgme_op_import_ext
+*** gpgme_get_sig_key
+*** gpgme_get_sig_ulong_attr
+*** gpgme_get_sig_string_attr
+*** GPGME_SIG_STAT_*
+*** gpgme_get_sig_status
 
 * Thread support:
 ** Build thread modules for static linking (which just suck in the
index 778625e4375f883f709ae5ca6fd2faa49bd20b38..653c216b3f776cb481f494468534ad5ffb9cd6ff 100644 (file)
@@ -1,5 +1,8 @@
 2003-04-28  Marcus Brinkmann  <marcus@g10code.de>
 
+       * gpgme.texi (Verify): Rewritten to take into account new and
+       deprecated functions and data types.
+
        * gpgme.texi (Decrypt): Descript gpgme_op_decrypt_result and
        GpgmeDecryptResult.
 
index 4e15fa077a79a9abf1da4a14bf3bf880852b20a4..a05a0e6442844cf62db97138fd3e385d87534745 100644 (file)
@@ -2805,56 +2805,6 @@ next operation is started on the context.
 @cindex signature, verification
 @cindex cryptographic operation, verification
 @cindex cryptographic operation, signature check
-@cindex signature, status
-
-@deftp {Data type} {enum GpgmeSigStat}
-@tindex GpgmeSigStat
-The @code{GpgmeSigStat} type holds the result of a signature check, or
-the combined result of all signatures.  The following results are
-possible:
-
-@table @code
-@item GPGME_SIG_STAT_NONE
-This status should not occur in normal operation.
-
-@item GPGME_SIG_STAT_GOOD
-This status indicates that the signature is valid.  For the combined
-result this status means that all signatures are valid.
-
-@item GPGME_SIG_STAT_GOOD_EXP
-This status indicates that the signature is valid but expired.  For
-the combined result this status means that all signatures are valid
-and expired.
-
-@item GPGME_SIG_STAT_GOOD_EXPKEY
-This status indicates that the signature is valid but the key used to
-verify the signature has expired.  For the combined result this status
-means that all signatures are valid and all keys are expired.
-
-@item GPGME_SIG_STAT_BAD
-This status indicates that the signature is invalid.  For the combined
-result this status means that all signatures are invalid.
-
-@item GPGME_SIG_STAT_NOKEY
-This status indicates that the signature could not be verified due to
-a missing key.  For the combined result this status means that all
-signatures could not be checked due to missing keys.
-
-@item GPGME_SIG_STAT_NOSIG
-This status indicates that the signature data provided was not a real
-signature.
-
-@item GPGME_SIG_STAT_ERROR
-This status indicates that there was some other error which prevented
-the signature verification.
-
-@item GPGME_SIG_STAT_DIFF
-For the combined result this status means that at least two signatures
-have a different status.  You can get each key's status with
-@code{gpgme_get_sig_status}.
-@end table
-@end deftp
-
 
 @deftypefun GpgmeError gpgme_op_verify (@w{GpgmeCtx @var{ctx}}, @w{GpgmeData @var{sig}}, @w{GpgmeData @var{signed_text}}, @w{GpgmeData @var{plain}})
 The function @code{gpgme_op_verify} verifies that the signature in the
@@ -2867,7 +2817,7 @@ writable data object that will contain the plaintext after successful
 verification.
 
 The results of the individual signature verifications can be retrieved
-with @code{gpgme_get_sig_status} and @code{gpgme_get_sig_key}.
+with @code{gpgme_op_verify_result}.
 
 The function returns @code{GPGME_No_Error} if the operation could be
 completed successfully, @code{GPGME_Invalid_Value} if @var{ctx},
@@ -2889,76 +2839,41 @@ started successfully, @code{GPGME_Invalid_Value} if @var{ctx},
 data to verify.
 @end deftypefun
 
-@deftypefun {const char *} gpgme_get_sig_status (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeSigStat *@var{r_stat}}, @w{time_t *@var{r_created}})
-The function @code{gpgme_get_sig_status} receives information about a
-signature after the @code{gpgme_op_verify} or
-@code{gpgme_op_verify_decrypt} operation.  A single detached signature
-can contain signatures by more than one key.  The @var{idx} specifies
-which signature's information should be retrieved, starting from
-@var{0}.
-
-The status of the signature will be returned in @var{r_stat} if it is
-not @code{NULL}.  The creation time stamp of the signature will be
-returned in @var{r_created} if it is not @var{NULL}.
-
-The function returns a statically allocated string that contains the
-fingerprint of the key which signed the plaintext, or @code{NULL} if
-@var{ctx} is not a valid pointer, the operation is still pending, or
-no verification could be performed.
-@end deftypefun
-
-@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{what}}, @w{int @var{whatidx}})
-This function is similar to @code{gpgme_get_sig_status} but may be used
-to retrieve more detailed information.  @var{ctx} should be the context
-used for the last signature verification, @var{idx} is used to enumerate
-over all signatures starting with @code{0} and @var{whatidx} should be
-@code{0} unless otherwise stated.
+@deftp {Data type} {GpgmeSigNotation}
+This is a pointer to a structure used to store a part of the result of
+a @code{gpgme_op_verify} operation.  The structure contains the
+following members:
 
-The following values may be used for @var{what}:
 @table @code
-@item GPGME_ATTR_FPR
-Return the fingerprint of the key used to create the signature.
+@item GpgmeSigNotation next
+This is a pointer to the next new signature notation structure in the
+linked list, or @code{NULL} if this is the last element.
 
-@item GPGME_ATTR_ERRTOK
-Return a token with a more detailed error description.  A @var{whatidx}
-of @code{0} returns an error token associated with validity calculation,
-a value of @code{1} return an error token related to the certificate
-checking.
+@item char *name
+The name of the notation field.  If this is @code{NULL}, then the
+member @code{value} will contain a policy URL.
 
+@item char *value
+The value of the notation field.  If @code{name} is @code{NULL}, then
+this is a policy URL.
 @end table
-@end deftypefun
-
-@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{whatidx}})
-This function is similar to @code{gpgme_get_sig_string_attr} but used
-for attributes which can be represented by an @code{unsigned long} data
-type.  @var{ctx} should be the context used for the last signature
-verification, @var{idx} is used to enumerate over all signatures
-starting with @code{0} and @var{whatidx} should be @code{0} unless
-otherwise stated.
-
-The following values may be used for @var{what}:
-@table @code
-@item GPGME_ATTR_CREATED
-Return the creation time of the signature in seconds since Epoch.  This
-is the same value as returned by @code{gpgme_get_sig_status}.
-
-@item GPGME_ATTR_EXPIRE
-Return the expiration time of the signature in seconds since Epoch. 
+@end deftp
 
-@item GPGME_ATTR_VALIDITY
-Returns the validity of the key used to create the signature.  This is a
-shortcut function which avoids an extra key lookup.  The value returned
-is one of @code{GPGME_VALIDITY_UNKNOWN}, @code{GPGME_VALIDITY_NEVER},
-@code{GPGME_VALIDITY_MARGINAL} or @code{GPGME_VALIDITY_FULL}.
+@deftp {Data type} {GpgmeSignature}
+This is a pointer to a structure used to store a part of the result of
+a @code{gpgme_op_verify} operation.  The structure contains the
+following members:
 
-@item GPGME_ATTR_SIG_STATUS
-This is the same value as returned by @code{gpgme_get_sig_status}.
+@table @code
+@item GpgmeSignature next
+This is a pointer to the next new signature structure in the linked
+list, or @code{NULL} if this is the last element.
 
-@item GPGME_ATTR_SIG_SUMMARY
-This returns a bit vector giving a summary of the signature status.
-Itprovides an easy interface to a defined semantic of the signature
-status.  Checking just one bit is sufficient to see whether a signature
-is valid without any restrictions.
+@item unsigned int summary;
+This is a bit vector giving a summary of the signature status.  It
+provides an easy interface to a defined semantic of the signature
+status.  Checking just one bit is sufficient to see whether a
+signature is valid without any restrictions.
 
 The defined bits are:
   @table @code
@@ -2999,44 +2914,316 @@ The defined bits are:
 
   @item GPGME_SIGSUM_SYS_ERROR
   A system error occured. 
+  @end table
+
+@item char *fpr
+This is the fingerprint or key ID of the signature.
 
+@item GpgmeError status
+This is the status of the signature.  In particular, the following
+status codes are of interest:
+
+  @table @code
+  @item GPGME_No_Error
+  This status indicates that the signature is valid.  For the combined
+  result this status means that all signatures are valid.
+
+  @item GPGME_Sig_Expired
+  This status indicates that the signature is valid but expired.  For
+  the combined result this status means that all signatures are valid
+  and expired.
+
+  @item GPGME_Key_Expired
+  This status indicates that the signature is valid but the key used to
+  verify the signature has expired.  For the combined result this status
+  means that all signatures are valid and all keys are expired.
+
+  @item GPGME_Bad_Signature
+  This status indicates that the signature is invalid.  For the combined
+  result this status means that all signatures are invalid.
+
+  @item GPGME_No_Public_Key
+  This status indicates that the signature could not be verified due to
+  a missing key.  For the combined result this status means that all
+  signatures could not be checked due to missing keys.
+
+  @item GPGME_General_Error
+  This status indicates that there was some other error which prevented
+  the signature verification.
   @end table
 
+@item GpgmeSigNotation notations
+This is a linked list with the notation data and policy URLs.
+
+@item unsigned long timestamp
+The creation timestamp of this signature.
+
+@item unsigned long exp_timestamp
+The expiration timestamp of this signature, or 0 if the signature does
+not expire.
+
+@item int wrong_key_usage : 1;
+
+@item GpgmeValidity validity
+
+@item GpgmeError validity_reason
 @end table
+@end deftp
+
+@deftp {Data type} {GpgmeVerifyResult}
+This is a pointer to a structure used to store the result of a
+@code{gpgme_op_verify} operation.  After successfully verifying a
+signature, you can retrieve the pointer to the result with
+@code{gpgme_op_verify_result}.  The structure contains the following
+member:
+
+@table @code
+@item GpgmeSignature signatures
+A linked list with information about all signatures for which a
+verification was attempted.
+@end table
+@end deftp
+
+@deftypefun GpgmeSignResult gpgme_op_verify_result (@w{GpgmeCtx @var{ctx}})
+The function @code{gpgme_op_verify_result} returns a
+@code{GpgmeVerifyResult} pointer to a structure holding the result of
+a @code{gpgme_op_verify} operation.  The pointer is only valid if the
+last operation on the context was a @code{gpgme_op_verify} or
+@code{gpgme_op_verify_start} operation, and if this operation finished
+successfully.  The returned pointer is only valid until the next
+operation is started on the context.
 @end deftypefun
 
 
-@deftypefun {const char *} gpgme_get_sig_key (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeKey *@var{r_key}})
-The function @code{gpgme_get_sig_status} receives a @code{GpgmeKey}
-object for the key which was used to verify the signature after the
-@code{gpgme_op_verify} or @code{gpgme_op_verify_decrypt} operation.  A
-single detached signature can contain signatures by more than one key.
-The @var{idx} specifies which signature's information should be
-retrieved, starting from @var{0}.  The key will have on reference for
-the user.
+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 function is a convenient way to retrieve the keys belonging to the
-fingerprints returned by @code{gpgme_get_sig_status}.
+@deftp {Data type} {enum GpgmeSigStat}
+@tindex GpgmeSigStat
+The @code{GpgmeSigStat} type holds the result of a signature check, or
+the combined result of all signatures.  The following results are
+possible:
 
-The function returns @code{GPGME_No_Error} if the key could be
-returned, @code{GPGME_Invalid_Value} if @var{r_key} is not a valid
-pointer, @code{GPGME_Invalid_Key} if the fingerprint is not valid,
-@code{GPGME_EOF} if @var{idx} is too large, or some other error value
-if a problem occurred requesting the key.
+@table @code
+@item GPGME_SIG_STAT_NONE
+This status should not occur in normal operation.
+
+@item GPGME_SIG_STAT_GOOD
+This status indicates that the signature is valid.  For the combined
+result this status means that all signatures are valid.
+
+@item GPGME_SIG_STAT_GOOD_EXP
+This status indicates that the signature is valid but expired.  For
+the combined result this status means that all signatures are valid
+and expired.
+
+@item GPGME_SIG_STAT_GOOD_EXPKEY
+This status indicates that the signature is valid but the key used to
+verify the signature has expired.  For the combined result this status
+means that all signatures are valid and all keys are expired.
+
+@item GPGME_SIG_STAT_BAD
+This status indicates that the signature is invalid.  For the combined
+result this status means that all signatures are invalid.
+
+@item GPGME_SIG_STAT_NOKEY
+This status indicates that the signature could not be verified due to
+a missing key.  For the combined result this status means that all
+signatures could not be checked due to missing keys.
+
+@item GPGME_SIG_STAT_NOSIG
+This status indicates that the signature data provided was not a real
+signature.
+
+@item GPGME_SIG_STAT_ERROR
+This status indicates that there was some other error which prevented
+the signature verification.
+
+@item GPGME_SIG_STAT_DIFF
+For the combined result this status means that at least two signatures
+have a different status.  You can get each key's status with
+@code{gpgme_get_sig_status}.
+@end table
+@end deftp
+
+@deftypefun {const char *} gpgme_get_sig_status (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeSigStat *@var{r_stat}}, @w{time_t *@var{r_created}})
+The function @code{gpgme_get_sig_status} is equivalent to:
+@example
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
+
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
+
+  while (sig && idx)
+    @{
+      sig = sig->next;
+      idx--;
+    @}
+  if (!sig || idx)
+    return NULL;
+
+  if (r_stat)
+    @{
+      switch (sig->status)
+       @{
+       case GPGME_No_Error:
+         *r_stat = GPGME_SIG_STAT_GOOD;
+         break;
+         
+       case GPGME_Bad_Signature:
+         *r_stat = GPGME_SIG_STAT_BAD;
+         break;
+         
+       case GPGME_No_Public_Key:
+         *r_stat = GPGME_SIG_STAT_NOKEY;
+         break;
+         
+       case GPGME_No_Data:
+         *r_stat = GPGME_SIG_STAT_NOSIG;
+         break;
+         
+       case GPGME_Sig_Expired:
+         *r_stat = GPGME_SIG_STAT_GOOD_EXP;
+         break;
+         
+       case GPGME_Key_Expired:
+         *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
+         break;
+         
+       default:
+         *r_stat = GPGME_SIG_STAT_ERROR;
+         break;
+       @}
+    @}
+  if (r_created)
+    *r_created = sig->timestamp;
+  return sig->fpr;
+@end example
+@end deftypefun
+
+@deftypefun {const char *} gpgme_get_sig_string_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{what}}, @w{int @var{whatidx}})
+The function @code{gpgme_get_sig_string_attr} is equivalent to:
+@example
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
+
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
+
+  while (sig && idx)
+    @{
+      sig = sig->next;
+      idx--;
+    @}
+  if (!sig || idx)
+    return NULL;
+
+  switch (what)
+    @{
+    case GPGME_ATTR_FPR:
+      return sig->fpr;
+
+    case GPGME_ATTR_ERRTOK:
+      if (whatidx == 1)
+        return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+      else
+       return "";
+    default:
+      break;
+    @}
+
+  return NULL;
+@end example
+@end deftypefun
+
+@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeAttr @var{waht}}, @w{int @var{whatidx}})
+The function @code{gpgme_get_sig_ulong_attr} is equivalent to:
+@example
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
+
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
+
+  while (sig && idx)
+    @{
+      sig = sig->next;
+      idx--;
+    @}
+  if (!sig || idx)
+    return 0;
+
+  switch (what)
+    @{
+    case GPGME_ATTR_CREATED:
+      return sig->timestamp;
+
+    case GPGME_ATTR_EXPIRE:
+      return sig->exp_timestamp;
+
+    case GPGME_ATTR_VALIDITY:
+      return (unsigned long) sig->validity;
+
+    case GPGME_ATTR_SIG_STATUS:
+      switch (sig->status)
+       @{
+       case GPGME_No_Error:
+         return GPGME_SIG_STAT_GOOD;
+         
+       case GPGME_Bad_Signature:
+         return GPGME_SIG_STAT_BAD;
+         
+       case GPGME_No_Public_Key:
+         return GPGME_SIG_STAT_NOKEY;
+         
+       case GPGME_No_Data:
+         return GPGME_SIG_STAT_NOSIG;
+         
+       case GPGME_Sig_Expired:
+         return GPGME_SIG_STAT_GOOD_EXP;
+         
+       case GPGME_Key_Expired:
+         return GPGME_SIG_STAT_GOOD_EXPKEY;
+         
+       default:
+         return GPGME_SIG_STAT_ERROR;
+       @}
+
+    case GPGME_ATTR_SIG_SUMMARY:
+      return sig->summary;
+
+    default:
+      break;
+    @}
+  return 0;
+@end example
 @end deftypefun
 
-@deftypefun {char *} gpgme_get_notation (@w{GpgmeCtx @var{ctx}})
-The function @code{gpgme_get_notation} can be used to retrieve
-notation data from the last signature check in the context @var{ctx}.
+@deftypefun {const char *} gpgme_get_sig_key (@w{GpgmeCtx @var{ctx}}, @w{int @var{idx}}, @w{GpgmeKey *@var{r_key}})
+The function @code{gpgme_get_sig_key} is equivalent to:
+
+@example
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
+
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
 
-If there is notation data available from the last signature check,
-this function may be used to return this notation data as a string.
-The string is an XML representation of that data embedded in a
-<notation> container.  The user has to release the string with
-@code{free}.
+  while (sig && idx)
+    @{
+      sig = sig->next;
+      idx--;
+    @}
+  if (!sig || idx)
+    return GPGME_EOF;
 
-The function returns a string if the notation data is available or
-@code{NULL} if there is no such data available.
+  return gpgme_get_key (ctx, sig->fpr, r_key, 0, 0);
+@end example
 @end deftypefun
 
 
@@ -3204,7 +3391,7 @@ The hash algorithm used to create this signature.
 @item unsigned long class
 The signature class of this signature.
 
-@item long int created
+@item long int timestamp
 The creation timestamp of this signature.
 
 @item char *fpr
index 720dc7b05c9030e0625e0eaa3056e55767a394ce..c371ce3fe051dbb2ebb35ce05e51c7dcb0cfe62b 100644 (file)
@@ -1,5 +1,51 @@
 2003-04-28  Marcus Brinkmann  <marcus@g10code.de>
 
+       * gpgme.h (struct _gpgme_sig_notation): New structure.
+       (GpgmeSigNotation): New type.
+       (struct _gpgme_signature): New structure.
+       (GpgmeSignature): New type.
+       (struct _gpgme_op_verify_result): New structure.
+       (GpgmeVerifyResult): New type.
+       (gpgme_op_verify_result): New prototype.
+       (gpgme_get_notation): Remove prototype.
+       * ops.h (_gpgme_op_verify_init_result): New prototype.
+       (_gpgme_verify_status_handler): Change first argument to void *.
+       * util.h (_gpgme_decode_percent_string, _gpgme_map_gnupg_error):
+       New prototypes.
+       * conversion.c (_gpgme_decode_percent_string): New function.
+       (gnupg_errors): New static global.
+       (_gpgme_map_gnupg_error): New function.
+       * gpgme.c (gpgme_release): Don't release CTX->notation.
+       (gpgme_get_notation): Remove function.
+       * decrypt-verify.c (_gpgme_op_decrypt_verify_start): Call
+       _gpgme_op_verify_init_result.
+       * verify.c: Do not include <stdio.h>, <assert.h> and "key.h", but
+       do include "gpgme.h".
+       (struct verify_result): Replace with ...
+       (op_data_t): ... this type.
+       (release_verify_result): Remove function.
+       (release_op_data): New function.
+       (is_token): Remove function.
+       (skip_token): Remove function.
+       (copy_token): Remove function.
+       (gpgme_op_verify_result): New function.
+       (calc_sig_summary): Rewritten.
+       (finish_sig): Remove function.
+       (parse_new_sig): New function.
+       (parse_valid_sig): New function.
+       (parse_notation): New function.
+       (parse_trust): New function.
+       (parse_error): New function.
+       (_gpgme_verify_status_handler): Rewritten.  Change first argument
+       to void *.
+       (_gpgme_op_verify_start): Rework error handling.  Call
+       _gpgme_op_verify_init_result.
+       (gpgme_op_verify): Do not release or clear CTX->notation.
+       (gpgme_get_sig_status): Rewritten.
+       (gpgme_get_sig_string_attr): Likewise.
+       (gpgme_get_sig_ulong_attr): Likewise.
+       (gpgme_get_sig_key): Likewise.
+
        * gpgme.h (struct _gpgme_op_decrypt_result): New structure.
        (GpgmeDecryptResult): New type.
        (gpgme_op_decrypt_result): New prototype.
index 5b2cb67aea0703327a05c4df89e88b1c77726e6c..57e2f5141114d4b0864f23a359a89c12a0dde061 100644 (file)
@@ -161,6 +161,178 @@ _gpgme_decode_c_string (const char *src, char **destp, int len)
   return 0;
 }
 
+
+/* Decode the percent escaped string SRC and store the result in the
+   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
+   large enough buffer is allocated with malloc and *DESTP is set to
+   the result.  Currently, LEN is only used to specify if allocation
+   is desired or not, the caller is expected to make sure that *DESTP
+   is large enough if LEN is not zero.  */
+GpgmeError
+_gpgme_decode_percent_string (const char *src, char **destp, int len)
+{
+  char *dest;
+
+  /* Set up the destination buffer.  */
+  if (len)
+    {
+      if (len < strlen (src) + 1)
+       return GPGME_General_Error;
+
+      dest = *destp;
+    }
+  else
+    {
+      /* The converted string will never be larger than the original
+        string.  */
+      dest = malloc (strlen (src) + 1);
+      if (!dest)
+       return GPGME_Out_Of_Core;
+
+      *destp = dest;
+    }
+
+  /* Convert the string.  */
+  while (*src)
+    {
+      if (*src != '%')
+       {
+         *(dest++) = *(src++);
+         continue;
+       }
+      else
+       {
+         int val = _gpgme_hextobyte (&src[1]);
+         
+         if (val == -1)
+           {
+             /* Should not happen.  */
+             *(dest++) = *(src++);
+             if (*src)
+               *(dest++) = *(src++);
+             if (*src)
+               *(dest++) = *(src++);
+           }
+         else
+           {
+             if (!val)
+               {
+                 /* A binary zero is not representable in a C
+                    string.  */
+                 *(dest++) = '\\';
+                 *(dest++) = '0'; 
+               }
+             else 
+               *((unsigned char *) dest++) = val;
+             src += 3;
+           }
+       }
+    }
+  *(dest++) = 0;
+
+  return 0;
+}
+
+\f
+static struct
+{
+  char *name;
+  GpgmeError err;
+} gnupg_errors[] =
+  {
+    { "EOF", GPGME_EOF },
+    { "No_Error", GPGME_No_Error },
+    { "General_Error", GPGME_General_Error },
+    { "Out_Of_Core", GPGME_Out_Of_Core },
+    { "Invalid_Value", GPGME_Invalid_Value },
+    { "IO_Error", GPGME_General_Error },
+    { "Resource_Limit", GPGME_General_Error },
+    { "Internal_Error", GPGME_General_Error },
+    { "Bad_Certificate", GPGME_Invalid_Key },
+    { "Bad_Certificate_Chain", GPGME_General_Error },
+    { "Missing_Certificate", GPGME_No_Public_Key },
+    { "No_Data", GPGME_No_Data },
+    { "Bad_Signature", GPGME_Bad_Signature },
+    { "Not_Implemented", GPGME_Not_Implemented },
+    { "Conflict", GPGME_Conflict },
+    { "Bug", GPGME_General_Error },
+    { "Read_Error", GPGME_General_Error },
+    { "Write_Error", GPGME_General_Error },
+    { "Invalid_Line", GPGME_General_Error },
+    { "Incomplete_Line", GPGME_General_Error },
+    { "Invalid_Response", GPGME_General_Error },
+    { "Agent_Error", GPGME_General_Error },
+    { "No_Public_Key", GPGME_No_Public_Key },
+    { "No_Secret_Key", GPGME_No_Secret_Key },
+    { "File_Open_Error", GPGME_General_Error },
+    { "File_Create_Error", GPGME_General_Error },
+    { "File_Error", GPGME_General_Error },
+    { "Not_Supported", GPGME_General_Error },
+    { "Invalid_Data", GPGME_General_Error },
+    { "Assuan_Server_Fault", GPGME_General_Error },
+    { "Assuan_Error", GPGME_General_Error },
+    { "Invalid_Session_Key", GPGME_General_Error },
+    { "Invalid_Sexp", GPGME_General_Error },
+    { "Unsupported_Algorithm", GPGME_Unsupported_Algorithm },
+    { "No_PIN_Entry", GPGME_Invalid_Engine },
+    { "PIN_Entry_Error", GPGME_Invalid_Engine },
+    { "Bad_PIN", GPGME_Bad_Passphrase },
+    { "Bad_Passphrase", GPGME_Bad_Passphrase },
+    { "Invalid_Name", GPGME_General_Error },
+    { "Bad_Public_Key", GPGME_General_Error },
+    { "Bad_Secret_Key", GPGME_General_Error },
+    { "Bad_Data", GPGME_General_Error },
+    { "Invalid_Parameter", GPGME_General_Error },
+    { "Tribute_to_D_A", GPGME_General_Error },
+    { "No_Dirmngr", GPGME_Invalid_Engine },
+    { "Dirmngr_Error", GPGME_General_Error },
+    { "Certificate_Revoked", GPGME_Key_Revoked },
+    { "No_CRL_Known", GPGME_No_CRL_Known },
+    { "CRL_Too_Old", GPGME_CRL_Too_Old },
+    { "Line_Too_Long", GPGME_General_Error },
+    { "Not_Trusted", GPGME_Key_Not_Trusted },
+    { "Canceled", GPGME_Canceled },
+    { "Bad_CA_Certificate", GPGME_General_Error },
+    { "Certificate_Expired", GPGME_Key_Expired },
+    { "Certificate_Too_Young", GPGME_Invalid_Key },
+    { "Unsupported_Certificate", GPGME_General_Error },
+    { "Unknown_Sexp", GPGME_General_Error },
+    { "Unsupported_Protection", GPGME_General_Error },
+    { "Corrupted_Protection", GPGME_General_Error },
+    { "Ambiguous_Name", GPGME_Ambiguous_Specification },
+    { "Card_Error", GPGME_General_Error },
+    { "Card_Reset", GPGME_General_Error },
+    { "Card_Removed", GPGME_General_Error },
+    { "Invalid_Card", GPGME_General_Error },
+    { "Card_Not_Present", GPGME_General_Error },
+    { "No_PKCS15_App", GPGME_General_Error },
+    { "Not_Confirmed", GPGME_General_Error },
+    { "Configuration_Error", GPGME_General_Error },
+    { "No_Policy_Match", GPGME_Policy_Mismatch },
+    { "Invalid_Index", GPGME_General_Error },
+    { "Invalid_Id", GPGME_General_Error },
+    { "No_Scdaemon", GPGME_Invalid_Engine },
+    { "Scdaemon_Error", GPGME_General_Error },
+    { "Unsupported_Protocol", GPGME_General_Error },
+    { "Bad_PIN_Method", GPGME_General_Error },
+    { "Card_Not_Initialized", GPGME_General_Error },
+    { "Unsupported_Operation", GPGME_General_Error },
+    { "Wrong_Key_Usage", GPGME_Wrong_Key_Usage }
+  };
+    
+
+GpgmeError
+_gpgme_map_gnupg_error (char *err)
+{
+  int i;
+
+  for (i = 0; i < DIM (gnupg_errors); i++)
+    if (!strcmp (gnupg_errors[i].name, err))
+      return gnupg_errors[i].err;
+
+  return GPGME_General_Error;
+}
+
 \f
 GpgmeError
 _gpgme_data_append (GpgmeData dh, const char *buffer, size_t length)
index 0a94522a382e2cfd71e20c291f647e61e2be891a..f365b1655525634eb3509970797b555c2b9bdc52 100644 (file)
@@ -48,6 +48,10 @@ _gpgme_op_decrypt_verify_start (GpgmeCtx ctx, int synchronous,
   if (err)
     return err;
 
+  err = _gpgme_op_verify_init_result (ctx);
+  if (err)
+    return err;
+
   if (!cipher)
     return GPGME_No_Data;
   if (!plain)
index 72f502a260246bb947007207b51a05d7d147a68d..dbcd406ffeef31629ac6d51c1d85c99a52cdc8b6 100644 (file)
@@ -68,7 +68,6 @@ gpgme_release (GpgmeCtx ctx)
   _gpgme_fd_table_deinit (&ctx->fdt);
   _gpgme_release_result (ctx);
   gpgme_key_release (ctx->tmp_key);
-  gpgme_data_release (ctx->notation);
   gpgme_signers_clear (ctx);
   if (ctx->signers)
     free (ctx->signers);
@@ -94,26 +93,6 @@ _gpgme_release_result (GpgmeCtx ctx)
 }
 
 
-/**
- * gpgme_get_notation:
- * @c: the context
- *
- * If there is notation data available from the last signature check,
- * this function may be used to return this notation data as a string.
- * The string is an XML represantaton of that data embedded in a
- * %&lt;notation&gt; container.
- *
- * Return value: An XML string or NULL if no notation data is available.
- **/
-char *
-gpgme_get_notation (GpgmeCtx ctx)
-{
-  if (!ctx->notation)
-    return NULL;
-  return _gpgme_data_get_as_string (ctx->notation);
-}
-
-
 /**
  * gpgme_get_op_info:
  * @c: the context
index 0071f06bcc0b613433dd16ce447841e4de56c0a0..4ee92121177f18020533bf5222d5c4ad3d218c59 100644 (file)
@@ -188,23 +188,6 @@ typedef enum
   }
 GpgmeSigStat;
 
-/* Flags used with the GPGME_ATTR_SIG_SUMMARY.  */
-enum 
-  {
-    GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid.  */
-    GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good.  */
-    GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad.  */
-    GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked.  */
-    GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired.  */
-    GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired.  */
-    GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing.  */
-    GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */
-    GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */
-    GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */
-    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured.  */
-  };
-
-
 /* The available signature modes.  */
 typedef enum
   {
@@ -406,9 +389,6 @@ GpgmeError gpgme_new (GpgmeCtx *ctx);
 /* Release the context CTX.  */
 void gpgme_release (GpgmeCtx ctx);
 
-/* Retrieve more info about performed signature check.  */
-char *gpgme_get_notation (GpgmeCtx ctx);
-
 /* Set the protocol to be used by CTX to PROTO.  */
 GpgmeError gpgme_set_protocol (GpgmeCtx ctx, GpgmeProtocol proto);
 
@@ -831,7 +811,7 @@ struct _gpgme_new_signature
   GpgmePubKeyAlgo pubkey_algo;
   GpgmeHashAlgo hash_algo;
   unsigned long class;
-  long int created;
+  long int timestamp;
   char *fpr;
 };
 typedef struct _gpgme_new_signature *GpgmeNewSignature;
@@ -856,6 +836,75 @@ GpgmeError gpgme_op_sign (GpgmeCtx ctx,
                          GpgmeSigMode mode);
 
 \f
+/* Verify.  */
+struct _gpgme_sig_notation
+{
+  struct _gpgme_sig_notation *next;
+
+  /* If NAME is a null pointer, then VALUE contains a policy URL
+     rather than a notation.  */
+  char *name;
+  char *value;
+};
+typedef struct _gpgme_sig_notation *GpgmeSigNotation;
+
+/* Flags used for the SUMMARY field in a GpgmeSignature.  */
+enum 
+  {
+    GPGME_SIGSUM_VALID       = 0x0001,  /* The signature is fully valid.  */
+    GPGME_SIGSUM_GREEN       = 0x0002,  /* The signature is good.  */
+    GPGME_SIGSUM_RED         = 0x0004,  /* The signature is bad.  */
+    GPGME_SIGSUM_KEY_REVOKED = 0x0010,  /* One key has been revoked.  */
+    GPGME_SIGSUM_KEY_EXPIRED = 0x0020,  /* One key has expired.  */
+    GPGME_SIGSUM_SIG_EXPIRED = 0x0040,  /* The signature has expired.  */
+    GPGME_SIGSUM_KEY_MISSING = 0x0080,  /* Can't verify: key missing.  */
+    GPGME_SIGSUM_CRL_MISSING = 0x0100,  /* CRL not available.  */
+    GPGME_SIGSUM_CRL_TOO_OLD = 0x0200,  /* Available CRL is too old.  */
+    GPGME_SIGSUM_BAD_POLICY  = 0x0400,  /* A policy was not met.  */
+    GPGME_SIGSUM_SYS_ERROR   = 0x0800   /* A system error occured.  */
+  };
+
+struct _gpgme_signature
+{
+  struct _gpgme_signature *next;
+
+  /* A summary of the signature status.  */
+  unsigned int summary;
+
+  /* The fingerprint or key ID of the signature.  */
+  char *fpr;
+
+  /* The status of the signature.  */
+  GpgmeError status;
+
+  /* Notation data and policy URLs.  */
+  GpgmeSigNotation notations;
+
+  /* Signature creation time.  */
+  unsigned long timestamp;
+
+  /* Signature exipration time or 0.  */
+  unsigned long exp_timestamp;
+
+  int wrong_key_usage : 1;
+
+  /* Internal to GPGME, do not use.  */
+  int _unused : 31;
+
+  GpgmeValidity validity;
+  GpgmeError validity_reason;
+};
+typedef struct _gpgme_signature *GpgmeSignature;
+
+struct _gpgme_op_verify_result
+{
+  GpgmeSignature signatures;
+};
+typedef struct _gpgme_op_verify_result *GpgmeVerifyResult;
+
+/* Retrieve a pointer to the result of the verify operation.  */
+GpgmeVerifyResult gpgme_op_verify_result (GpgmeCtx ctx);
+
 /* Verify within CTX that SIG is a valid signature for TEXT.  */
 GpgmeError gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig,
                                  GpgmeData signed_text, GpgmeData plaintext);
@@ -863,6 +912,7 @@ GpgmeError gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig,
                            GpgmeData signed_text, GpgmeData plaintext);
 
 \f
+/* Import.  */
 enum
   {
     /* The key was new.  */
index 165a51723e1b291919714d84e41b7202870406df..ffc2bdbe89b7213c4dc2c65574e7247480a649a5 100644 (file)
@@ -1,4 +1,4 @@
-/* ops.h - internal operations stuff 
+/* ops.h - Internal operation support.
    Copyright (C) 2000 Werner Koch (dd9jn)
    Copyright (C) 2001, 2002, 2003 g10 Code GmbH
  
@@ -73,8 +73,9 @@ GpgmeError _gpgme_op_reset (GpgmeCtx ctx, int synchronous);
 GpgmeError _gpgme_parse_inv_userid (char *args, GpgmeInvalidUserID *userid);
 
 \f
-/*-- verify.c --*/
-GpgmeError _gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code,
+/* From verify.c.  */
+GpgmeError _gpgme_op_verify_init_result (GpgmeCtx ctx);
+GpgmeError _gpgme_verify_status_handler (void *priv, GpgmeStatusCode code,
                                         char *args);
 
 \f
index 260aa5f7fa3dc9928c2c29f8779b670f8d1679e7..413865dcc0f6a352706352bc34865b5997b38e96 100644 (file)
@@ -149,7 +149,7 @@ parse_sig_created (char *args, GpgmeNewSignature *sigp)
     }
   args = tail;
 
-  sig->created = strtol (args, &tail, 0);
+  sig->timestamp = strtol (args, &tail, 0);
   if (errno || args == tail || *tail != ' ')
     {
       /* The crypto backend does not behave.  */
index 2734115eb9310771969c2b9cb3c0b3f0fdc7e1c8..70b7de9a0a1cf59d8ce9f953d21d3cffa4d1df86 100644 (file)
@@ -74,5 +74,15 @@ int _gpgme_hextobyte (const unsigned char *str);
    is large enough if LEN is not zero.  */
 GpgmeError _gpgme_decode_c_string (const char *src, char **destp, int len);
 
+/* Decode the percent escaped string SRC and store the result in the
+   buffer *DESTP which is LEN bytes long.  If LEN is zero, then a
+   large enough buffer is allocated with malloc and *DESTP is set to
+   the result.  Currently, LEN is only used to specify if allocation
+   is desired or not, the caller is expected to make sure that *DESTP
+   is large enough if LEN is not zero.  */
+GpgmeError _gpgme_decode_percent_string (const char *src, char **destp,
+                                        int len);
+
+GpgmeError _gpgme_map_gnupg_error (char *err);
 
 #endif /* UTIL_H */
index 3b63491f0a9e26f77806c12cacfdeca38012a61b..85854cdb0e107b93b77cc80df360d3b6e6f783b2 100644 (file)
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
+#include <errno.h>
 
+#include "gpgme.h"
 #include "util.h"
 #include "context.h"
 #include "ops.h"
-#include "key.h"
 
-
-struct verify_result
+\f
+typedef struct
 {
-  GpgmeSigStat status;
-  GpgmeSigStat expstatus;      /* Only used by finish_sig.  */
-  GpgmeData notation;          /* We store an XML fragment here.  */
-  int collecting;              /* Private to finish_sig().  */
-  int notation_in_data;                /* Private to add_notation().  */
-  char fpr[41];                        /* Fingerprint of a good signature or keyid of
-                                  a bad one.  */
-  ulong timestamp;             /* Signature creation time.  */
-  ulong exptimestamp;          /* Signature exipration time or 0.  */
-  GpgmeValidity validity;
-  int wrong_key_usage;  
-  char trust_errtok[31];       /* Error token send with the trust status.  */
-};
-typedef struct verify_result *VerifyResult;
+  struct _gpgme_op_verify_result result;
+
+  GpgmeSignature current_sig;
+} *op_data_t;
 
 
 static void
-release_verify_result (void *hook)
+release_op_data (void *hook)
 {
-  VerifyResult result = (VerifyResult) hook;
+  op_data_t opd = (op_data_t) hook;
+  GpgmeSignature sig = opd->result.signatures;
 
-  gpgme_data_release (result->notation);
-}
+  while (sig)
+    {
+      GpgmeSignature next = sig->next;
+      GpgmeSigNotation notation = sig->notations;
 
+      while (notation)
+       {
+         GpgmeSigNotation next_nota = notation->next;
 
-/* Check whether STRING starts with TOKEN and return true in this
-   case.  This is case insensitive.  If NEXT is not NULL return the
-   number of bytes to be added to STRING to get to the next token; a
-   returned value of 0 indicates end of line.  */
-static int 
-is_token (const char *string, const char *token, size_t *next)
-{
-  size_t n = 0;
+         if (notation->name)
+           free (notation->name);
+         if (notation->value)
+           free (notation->value);
+         notation = next_nota;
+       }
 
-  for (;*string && *token && *string == *token; string++, token++, n++)
-    ;
-  if (*token || (*string != ' ' && !*string))
-    return 0;
-  if (next)
-    {
-      for (; *string == ' '; string++, n++)
-        ;
-      *next = n;
+      if (sig->fpr)
+       free (sig->fpr);
+      free (sig);
+      sig = next;
     }
-  return 1;
 }
 
-static int
-skip_token (const char *string, size_t *next)
+
+GpgmeVerifyResult
+gpgme_op_verify_result (GpgmeCtx ctx)
 {
-  size_t n = 0;
+  op_data_t opd;
+  GpgmeError err;
 
-  for (;*string && *string != ' '; string++, n++)
-    ;
-  for (;*string == ' '; string++, n++)
-    ;
-  if (!*string)
-    return 0;
-  if (next)
-    *next = n;
-  return 1;
-}
+  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd, -1, NULL);
+  if (err || !opd)
+    return NULL;
 
+  return &opd->result;
+}
 
-static size_t
-copy_token (const char *string, char *buffer, size_t length)
+\f
+/* Build a summary vector from RESULT. */
+static void
+calc_sig_summary (GpgmeSignature sig)
 {
-  const char *s = string;
-  char *p = buffer;
-  size_t i;
-
-  for (i = 1; i < length && *s && *s != ' ' ; i++)
-    *p++ = *s++;
-  *p = 0;
-  /* continue scanning in case the copy was truncated */
-  while (*s && *s != ' ')
-    s++;
-  return s - string;
-}
+  unsigned long sum = 0;
 
+  if (sig->validity == GPGME_VALIDITY_FULL
+      || sig->validity == GPGME_VALIDITY_ULTIMATE)
+    {
+      if (sig->status == GPGME_No_Error
+         || sig->status == GPGME_Sig_Expired
+         || sig->status == GPGME_Key_Expired)
+       sum |= GPGME_SIGSUM_GREEN;
+    }
+  else if (sig->validity == GPGME_VALIDITY_NEVER)
+    {
+      if (sig->status == GPGME_No_Error
+         || sig->status == GPGME_Sig_Expired
+         || sig->status == GPGME_Key_Expired)
+       sum |= GPGME_SIGSUM_RED;
+    }
+  else if (sig->status == GPGME_Bad_Signature)
+    sum |= GPGME_SIGSUM_RED;
+  
+  /* FIXME: handle the case when key and message are expired. */
+  if (sig->status == GPGME_Sig_Expired)
+    sum |= GPGME_SIGSUM_SIG_EXPIRED;
+  else if (sig->status == GPGME_Key_Expired)
+    sum |= GPGME_SIGSUM_KEY_EXPIRED;
+  else if (sig->status == GPGME_No_Public_Key)
+    sum |= GPGME_SIGSUM_KEY_MISSING;
+  else if (sig->status)
+    sum |= GPGME_SIGSUM_SYS_ERROR;
+  
+  if (sig->validity_reason == GPGME_Key_Revoked)
+    sum |= GPGME_SIGSUM_KEY_REVOKED;
+  else if (sig->validity_reason == GPGME_No_CRL_Known)
+    sum |= GPGME_SIGSUM_CRL_MISSING;
+  else if (sig->validity_reason == GPGME_CRL_Too_Old)
+    sum |= GPGME_SIGSUM_CRL_TOO_OLD;
+  else if (sig->validity_reason == GPGME_Policy_Mismatch)
+    sum |= GPGME_SIGSUM_BAD_POLICY;
+  else if (sig->validity_reason)
+    sum |= GPGME_SIGSUM_SYS_ERROR;
+  
+  if (sig->wrong_key_usage)
+    sum |= GPGME_SIGSUM_BAD_POLICY;
+  
+  /* Set the valid flag when the signature is unquestionable
+     valid. */
+  if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
+    sum |= GPGME_SIGSUM_VALID;
+  
+  sig->summary = sum;
+}
+  
 
-/* FIXME: Check that we are adding this to the correct signature.  */
 static GpgmeError
-add_notation (VerifyResult result, GpgmeStatusCode code, const char *notation)
+parse_new_sig (op_data_t opd, GpgmeStatusCode code, char *args)
 {
-  GpgmeData dh = result->notation;
+  GpgmeSignature sig;
+  char *end = strchr (args, ' ');
 
-  if (!dh)
+  if (end)
     {
-      if (gpgme_data_new (&dh))
-       return GPGME_Out_Of_Core;
-      result->notation = dh;
-      _gpgme_data_append_string (dh, "  <notation>\n");
+      *end = '\0';
+      end++;
     }
 
-  if (code == GPGME_STATUS_NOTATION_DATA)
+  sig = calloc (1, sizeof (*sig));
+  if (!sig)
+    return GPGME_Out_Of_Core;
+  if (!opd->result.signatures)
+    opd->result.signatures = sig;
+  if (opd->current_sig)
+    opd->current_sig->next = sig;
+  opd->current_sig = sig;
+
+  switch (code)
     {
-      if (!result->notation_in_data)
-       _gpgme_data_append_string (dh, "  <data>");
-      _gpgme_data_append_percentstring_for_xml (dh, notation);
-      result->notation_in_data = 1;
-      return 0;
+    case GPGME_STATUS_GOODSIG:
+      sig->status = GPGME_No_Error;
+      break;
+
+    case GPGME_STATUS_EXPSIG:
+      sig->status = GPGME_Sig_Expired;
+      break;
+
+    case GPGME_STATUS_EXPKEYSIG:
+      sig->status = GPGME_Key_Expired;
+      break;
+
+    case GPGME_STATUS_BADSIG:
+      sig->status = GPGME_Bad_Signature;
+      break;
+
+    case GPGME_STATUS_ERRSIG:
+      if (end)
+       {
+         int i = 0;
+         /* The return code is the 6th argument, if it is 9, the
+            problem is a missing key.  */
+         while (end && i < 4)
+           end = strchr (end, ' ');
+         if (end && end[0] && (!end[1] || !end[1] == ' '))
+           {
+             switch (end[0])
+               {
+               case '4':
+                 sig->status = GPGME_Unsupported_Algorithm;
+                 break;
+
+               case 9:
+                 sig->status = GPGME_No_Public_Key;
+                 break;
+
+               default:
+                 sig->status = GPGME_General_Error;
+               }
+           }
+       }
+      else
+       sig->status = GPGME_General_Error;
+      break;
+
+    default:
+      return GPGME_General_Error;
     }
 
-  if (result->notation_in_data)
+  if (*args)
     {
-      _gpgme_data_append_string (dh, "</data>\n");
-      result->notation_in_data = 0;
+      sig->fpr = strdup (args);
+      if (!sig->fpr)
+       return GPGME_Out_Of_Core;
     }
+  return 0;
+}
 
-  if (code == GPGME_STATUS_NOTATION_NAME)
+
+static GpgmeError
+parse_valid_sig (GpgmeSignature sig, char *args)
+{
+  char *end = strchr (args, ' ');
+
+  if (end)
     {
-      _gpgme_data_append_string (dh, "  <name>");
-      _gpgme_data_append_percentstring_for_xml (dh, notation);
-      _gpgme_data_append_string (dh, "</name>\n");
+      *end = '\0';
+      end++;
     }
-  else if (code == GPGME_STATUS_POLICY_URL)
+
+  if (!*args)
+    /* We require at least the fingerprint.  */
+    return GPGME_General_Error;
+
+  if (sig->fpr)
+    free (sig->fpr);
+  sig->fpr = strdup (args);
+  if (!sig->fpr)
+    return GPGME_Out_Of_Core;
+
+  end = strchr (end, ' ');
+  if (end)
     {
-      _gpgme_data_append_string (dh, "  <policy>");
-      _gpgme_data_append_percentstring_for_xml (dh, notation);
-      _gpgme_data_append_string (dh, "</policy>\n");
+      char *tail;
+      errno = 0;
+      sig->timestamp = strtol (end, &tail, 0);
+      if (errno || end == tail || (*tail && *tail != ' '))
+       return GPGME_General_Error;
+      end = tail;
+     
+      sig->exp_timestamp = strtol (end, &tail, 0);
+      if (errno || end == tail || (*tail && *tail != ' '))
+       return GPGME_General_Error;
     }
-  else
-    assert (0);
   return 0;
 }
 
 
-/* Finish a pending signature info collection.  */
-static void
-finish_sig (VerifyResult result)
+static GpgmeError
+parse_notation (GpgmeSignature sig, GpgmeStatusCode code, char *args)
 {
-  struct ctx_op_data *op_data;
-
-  /* We intimately know that gpgme_op_data_lookup appends the data to
-     the op_data structure.  We can use this here to change the type
-     knowing only the hook value.  */
-  op_data = (struct ctx_op_data *) ((void *) result
-                                   - sizeof (struct ctx_op_data));
-  op_data->type = OPDATA_VERIFY;
-}
+  GpgmeError err;
+  GpgmeSigNotation *lastp = &sig->notations;
+  GpgmeSigNotation notation = sig->notations;
+  char *end = strchr (args, ' ');
 
+  if (end)
+    *end = '\0';
 
-GpgmeError
-_gpgme_verify_status_handler (GpgmeCtx ctx, GpgmeStatusCode code, char *args)
-{
-  VerifyResult result;
-  GpgmeError err;
-  char *p;
-  size_t n;
-  int i;
+  if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
+    {
+      /* FIXME: We could keep a pointer to the last notation in the list.  */
+      while (notation && notation->value)
+       {
+         lastp = &notation->next;
+         notation = notation->next;
+       }
 
-  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result,
-                              -1, NULL);
-  if (err)
-    return err;
+      if (notation)
+       /* There is another notation name without data for the
+          previous one.  The crypto backend misbehaves.  */
+       return GPGME_General_Error;
+
+      notation = malloc (sizeof (*sig));
+      if (!notation)
+       return GPGME_Out_Of_Core;
+      notation->next = NULL;
 
-  if (code == GPGME_STATUS_GOODSIG || code == GPGME_STATUS_EXPSIG
-      || code == GPGME_STATUS_EXPKEYSIG || code == GPGME_STATUS_BADSIG
-      || code == GPGME_STATUS_ERRSIG)
+      if (code == GPGME_STATUS_NOTATION_NAME)
+       {
+         int len = strlen (args) + 1;
+
+         notation->name = malloc (len);
+         if (!notation->name)
+           {
+             free (notation);
+             return GPGME_Out_Of_Core;
+           }
+         err = _gpgme_decode_percent_string (args, &notation->name, len);
+         if (err)
+           return err;
+
+         notation->value = NULL;
+       }
+      else
+       {
+         int len = strlen (args) + 1;
+
+         notation->name = NULL;
+         notation->value = malloc (len);
+         if (!notation->value)
+           {
+             free (notation);
+             return GPGME_Out_Of_Core;
+           }
+         err = _gpgme_decode_percent_string (args, &notation->value, len);
+         if (err)
+           return err;
+       }
+      *lastp = notation;
+    }
+  else if (code == GPGME_STATUS_NOTATION_DATA)
     {
-      /* A new signature starts.  */
-      if (result)
-       finish_sig (result);
-      err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY_COLLECTING, (void **) &result,
-                                  sizeof (*result), release_verify_result);
+      int len = strlen (args) + 1;
+      char *dest;
+
+      /* FIXME: We could keep a pointer to the last notation in the list.  */
+      while (notation && notation->next)
+       {
+         lastp = &notation->next;
+         notation = notation->next;
+       }
+
+      if (!notation || !notation->name)
+       /* There is notation data without a previous notation
+          name.  The crypto backend misbehaves.  */
+       return GPGME_General_Error;
+      
+      if (!notation->value)
+       {
+         dest = notation->value = malloc (len);
+         if (!dest)
+           return GPGME_Out_Of_Core;
+       }
+      else
+       {
+         int cur_len = strlen (notation->value);
+         dest = realloc (notation->value, len + strlen (notation->value));
+         if (!dest)
+           return GPGME_Out_Of_Core;
+         notation->value = dest;
+         dest += cur_len;
+       }
+      
+      err = _gpgme_decode_percent_string (args, &dest, len);
       if (err)
        return err;
     }
+  else
+    return GPGME_General_Error;
+  return 0;
+}
+
+
+static GpgmeError
+parse_trust (GpgmeSignature sig, GpgmeStatusCode code, char *args)
+{
+  char *end = strchr (args, ' ');
+
+  if (end)
+    *end = '\0';
 
   switch (code)
     {
-    case GPGME_STATUS_NODATA:
-    case GPGME_STATUS_UNEXPECTED:
-      if (!result)
-       return GPGME_General_Error;
-      result->status = GPGME_SIG_STAT_NOSIG;
+    case GPGME_STATUS_TRUST_UNDEFINED:
+    default:
+      sig->validity = GPGME_VALIDITY_UNKNOWN;
       break;
 
-    case GPGME_STATUS_GOODSIG:
-      if (!result)
-       return GPGME_General_Error;
-      result->expstatus = GPGME_SIG_STAT_GOOD;
+    case GPGME_STATUS_TRUST_NEVER:
+      sig->validity = GPGME_VALIDITY_NEVER;
       break;
 
-    case GPGME_STATUS_EXPSIG:
-      if (!result)
-       return GPGME_General_Error;
-      result->expstatus = GPGME_SIG_STAT_GOOD_EXP;
+    case GPGME_STATUS_TRUST_MARGINAL:
+      sig->validity = GPGME_VALIDITY_MARGINAL;
       break;
 
-    case GPGME_STATUS_EXPKEYSIG:
-      if (!result)
-       return GPGME_General_Error;
-      result->expstatus = GPGME_SIG_STAT_GOOD_EXPKEY;
+    case GPGME_STATUS_TRUST_FULLY:
+    case GPGME_STATUS_TRUST_ULTIMATE:
+      sig->validity = GPGME_VALIDITY_FULL;
       break;
+    }
 
-    case GPGME_STATUS_VALIDSIG:
-      if (!result)
-       return GPGME_General_Error;
-      result->status = GPGME_SIG_STAT_GOOD;
-      i = copy_token (args, result->fpr, DIM (result->fpr));
-      /* Skip the formatted date.  */
-      while (args[i] && args[i] == ' ')
-       i++;
-      while (args[i] && args[i] != ' ')
-       i++;
-      /* And get the timestamp.  */
-      result->timestamp = strtoul (args + i, &p, 10);
-      if (args[i])
-        result->exptimestamp = strtoul (p, NULL, 10);
-      break;
+  if (*args)
+    sig->validity_reason = _gpgme_map_gnupg_error (args);
+
+  return 0;
+}
 
-    case GPGME_STATUS_BADSIG:
-      if (!result)
-       return GPGME_General_Error;
-      result->status = GPGME_SIG_STAT_BAD;
-      /* Store the keyID in the fpr field.  */
-      copy_token (args, result->fpr, DIM (result->fpr));
-      break;
 
+static GpgmeError
+parse_error (GpgmeSignature sig, char *args)
+{
+  GpgmeError err;
+  char *where = strchr (args, ' ');
+  char *which;
+
+  if (where)
+    {
+      *where = '\0';
+      which = where + 1;
+
+      where = strchr (which, ' ');
+      if (where)
+       *where = '\0';
+
+      where = args;      
+    }
+  else
+    return GPGME_General_Error;
+
+  err = _gpgme_map_gnupg_error (which);
+
+  if (!strcmp (where, "verify.findkey"))
+    sig->status = err;
+  else if (!strcmp (where, "verify.keyusage") && err == GPGME_Wrong_Key_Usage)
+    sig->wrong_key_usage = 1;
+
+  return 0;
+}
+
+
+GpgmeError
+_gpgme_verify_status_handler (void *priv, GpgmeStatusCode code, char *args)
+{
+  GpgmeCtx ctx = (GpgmeCtx) priv;
+  GpgmeError err;
+  op_data_t opd;
+  GpgmeSignature sig;
+
+  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd, -1, NULL);
+  if (err)
+    return err;
+
+  sig = opd->current_sig;
+
+  switch (code)
+    {
+    case GPGME_STATUS_GOODSIG:
+    case GPGME_STATUS_EXPSIG:
+    case GPGME_STATUS_EXPKEYSIG:
+    case GPGME_STATUS_BADSIG:
     case GPGME_STATUS_ERRSIG:
-      if (!result)
+      if (sig)
+       calc_sig_summary (sig);
+      return parse_new_sig (opd, code, args);
+
+    case GPGME_STATUS_VALIDSIG:
+      return sig ? parse_valid_sig (sig, args) : GPGME_General_Error;
+
+    case GPGME_STATUS_NODATA:
+    case GPGME_STATUS_UNEXPECTED:
+      if (!sig)
        return GPGME_General_Error;
-      /* The return code is the 6th argument, if it is 9, the problem
-        is a missing key.  Note that this is not emitted by gpgsm */
-      for (p = args, i = 0; p && *p && i < 5; i++)
-        {
-          p = strchr (p, ' ');
-          if (p)
-            while (*p == ' ')
-              p++;
-        }
-      if (p && *(p++) == '9' && (*p == '\0' || *p == ' '))
-       result->status = GPGME_SIG_STAT_NOKEY;
-      else
-       result->status = GPGME_SIG_STAT_ERROR;
-      /* Store the keyID in the fpr field.  */
-      copy_token (args, result->fpr, DIM (result->fpr));
+      sig->status = GPGME_No_Data;
       break;
 
     case GPGME_STATUS_NOTATION_NAME:
     case GPGME_STATUS_NOTATION_DATA:
     case GPGME_STATUS_POLICY_URL:
-      if (!result)
-       return GPGME_General_Error;
-      err = add_notation (result, code, args);
-      if (err)
-       return err;
-      break;
+      return sig ? parse_notation (sig, code, args) : GPGME_General_Error;
 
     case GPGME_STATUS_TRUST_UNDEFINED:
-      if (!result)
-       return GPGME_General_Error;
-      result->validity = GPGME_VALIDITY_UNKNOWN;
-      copy_token (args, result->trust_errtok,
-                  DIM(result->trust_errtok));
-      break;
     case GPGME_STATUS_TRUST_NEVER:
-      if (!result)
-       return GPGME_General_Error;
-      result->validity = GPGME_VALIDITY_NEVER;
-      copy_token (args, result->trust_errtok,
-                  DIM(result->trust_errtok));
-      break;
     case GPGME_STATUS_TRUST_MARGINAL:
-      if (!result)
-       return GPGME_General_Error;
-      if (result->status == GPGME_SIG_STAT_GOOD)
-        result->validity = GPGME_VALIDITY_MARGINAL;
-      copy_token (args, result->trust_errtok,
-                  DIM(result->trust_errtok));
-      break;
     case GPGME_STATUS_TRUST_FULLY:
     case GPGME_STATUS_TRUST_ULTIMATE:
-      if (!result)
-       return GPGME_General_Error;
-      if (result->status == GPGME_SIG_STAT_GOOD)
-        result->validity = GPGME_VALIDITY_FULL;
-      break;
-
-    case GPGME_STATUS_END_STREAM:
-      break;
+      return sig ? parse_trust (sig, code, args) : GPGME_General_Error;
 
     case GPGME_STATUS_ERROR:
-      if (!result)
-       return GPGME_General_Error;
-      /* Generic error, we need this for gpgsm (and maybe for gpg in future)
-         to get error descriptions. */
-      if (is_token (args, "verify.findkey", &n) && n)
-        {
-          args += n;
-          if (is_token (args, "No_Public_Key", NULL))
-            result->status = GPGME_SIG_STAT_NOKEY;
-          else
-            result->status = GPGME_SIG_STAT_ERROR;
-
-        }
-      else if (skip_token (args, &n) && n)
-        {
-          args += n;
-          if (is_token (args, "Wrong_Key_Usage", NULL))
-            result->wrong_key_usage = 1;
-        }
-      break;
+      return sig ? parse_error (sig, args) : GPGME_General_Error;
 
     case GPGME_STATUS_EOF:
-      if (result)
-       {
-         finish_sig (result);
-
-         /* FIXME: Put all notation data into one XML fragment.  */
-         if (result->notation)
-           {
-             GpgmeData dh = result->notation;
-             
-             if (result->notation_in_data)
-               {
-                 _gpgme_data_append_string (dh, "</data>\n");
-                 result->notation_in_data = 0;
-               }
-             _gpgme_data_append_string (dh, "</notation>\n");
-             ctx->notation = dh;
-             result->notation = NULL;
-           }
-       }
+      if (sig)
+       calc_sig_summary (sig);
       break;
+
     default:
-      /* Ignore all other codes.  */
       break;
     }
   return 0;
 }
 
 
+GpgmeError
+_gpgme_op_verify_init_result (GpgmeCtx ctx)
+{  
+  op_data_t opd;
+
+  return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, (void **) &opd,
+                               sizeof (*opd), release_op_data);
+}
+
+
 static GpgmeError
-_gpgme_op_verify_start (GpgmeCtx ctx, int synchronous,
-                       GpgmeData sig, GpgmeData signed_text, GpgmeData plaintext)
+_gpgme_op_verify_start (GpgmeCtx ctx, int synchronous, GpgmeData sig,
+                       GpgmeData signed_text, GpgmeData plaintext)
 {
-  int err = 0;
+  GpgmeError err;
 
   err = _gpgme_op_reset (ctx, synchronous);
   if (err)
-    goto leave;
+    return err;
+
+  err = _gpgme_op_verify_init_result (ctx);
+  if (err)
+    return err;
 
   _gpgme_engine_set_status_handler (ctx->engine, _gpgme_verify_status_handler,
                                    ctx);
 
-  /* Check the supplied data.  */
   if (!sig)
-    {
-      err = GPGME_No_Data;
-      goto leave;
-    }
+    return GPGME_No_Data;
   if (!signed_text && !plaintext)
-    {
-      err = GPGME_Invalid_Value;
-      goto leave;
-    }
-  err = _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
+    return GPGME_Invalid_Value;
 
- leave:
-  if (err)
-    {
-      _gpgme_engine_release (ctx->engine);
-      ctx->engine = NULL;
-    }
-  return err;
+  return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
 }
 
 
+/* Decrypt ciphertext CIPHER and make a signature verification within
+   CTX and store the resulting plaintext in PLAIN.  */
 GpgmeError
 gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,
                       GpgmeData plaintext)
@@ -414,226 +543,166 @@ gpgme_op_verify_start (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,
 }
 
 
-/**
- * gpgme_op_verify:
- * @c: the context
- * @sig: the signature data
- * @text: the signed text
- * 
- * Perform a signature check on the signature given in @sig.  If @text
- * is a new and uninitialized data object, it is assumed that @sig
- * contains a normal or cleartext signature, and the plaintext is
- * returned in @text upon successful verification.
- *
- * If @text is initialized, it is assumed that @sig is a detached
- * signature for the material given in @text.
- *
- * Return value: 0 on success or an errorcode if something not related to
- *               the signature itself did go wrong.
- **/
+/* Decrypt ciphertext CIPHER and make a signature verification within
+   CTX and store the resulting plaintext in PLAIN.  */
 GpgmeError
 gpgme_op_verify (GpgmeCtx ctx, GpgmeData sig, GpgmeData signed_text,
                 GpgmeData plaintext)
 {
   GpgmeError err;
 
-  gpgme_data_release (ctx->notation);
-  ctx->notation = NULL;
-    
   err = _gpgme_op_verify_start (ctx, 1, sig, signed_text, plaintext);
   if (!err)
     err = _gpgme_wait_one (ctx);
   return err;
 }
 
+\f
+/* Compatibility interfaces.  */
 
-/**
- * gpgme_get_sig_status:
- * @c: Context
- * @idx: Index of the signature starting at 0
- * @r_stat: Returns the status
- * @r_created: Returns the creation timestamp
- * 
- * Return information about an already verified signatures. 
- *
- * The result of this operation is returned in @r_stat which can take these
- * values:
- *  GPGME_SIG_STAT_NONE:  No status - should not happen
- *  GPGME_SIG_STAT_GOOD:  The signature is valid 
- *  GPGME_SIG_STAT_BAD:   The signature is not valid
- *  GPGME_SIG_STAT_NOKEY: The signature could not be checked due to a
- *                        missing key
- *  GPGME_SIG_STAT_NOSIG: This is not a signature
- *  GPGME_SIG_STAT_ERROR: Due to some other error the check could not be done.
- *  GPGME_SIG_STAT_DIFF:  There is more than 1 signature and they have not
- *                        the same status.
- *  GPGME_SIG_STAT_GOOD_EXP:  The signature is good but has expired.
- *  GPGME_SIG_STAT_GOOD_KEYEXP:  The signature is good but the key has expired.
- *
- * 
- * Return value: The fingerprint or NULL in case of an problem or
- *               when there are no more signatures.
- **/
-const char *
-gpgme_get_sig_status (GpgmeCtx ctx, int idx,
-                      GpgmeSigStat *r_stat, time_t *r_created)
+/* Get the key used to create signature IDX in CTX and return it in
+   R_KEY.  */
+GpgmeError
+gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key)
 {
-  struct ctx_op_data *op_data;
-  VerifyResult result;
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
 
-  if (!ctx)
-    return NULL;       /* No results yet or verification error.  */
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
 
-  op_data = ctx->op_data;
-  while (op_data)
-    {
-      while (op_data && op_data->type != OPDATA_VERIFY)
-       op_data = op_data->next;
-      if (idx-- == 0)
-       break;
-      op_data = op_data->next; 
-    }
-  if (!op_data)
-    return NULL;       /* No more signatures.  */
-
-  result = (VerifyResult) op_data->hook;
-  if (r_stat)
-    *r_stat = result->status;
-  if (r_created)
-    *r_created = result->timestamp;
-  return result->fpr;
-}
-
-
-/* Build a summary vector from RESULT. */
-static unsigned long
-calc_sig_summary (VerifyResult result)
-{
-  unsigned long sum = 0;
-
-  if (result->validity == GPGME_VALIDITY_FULL
-     || result->validity == GPGME_VALIDITY_ULTIMATE)
-    {
-      if (result->status == GPGME_SIG_STAT_GOOD
-          || result->status == GPGME_SIG_STAT_GOOD_EXP
-          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
-        sum |= GPGME_SIGSUM_GREEN;
-    }
-  else if (result->validity == GPGME_VALIDITY_NEVER)
+  while (sig && idx)
     {
-      if (result->status == GPGME_SIG_STAT_GOOD
-          || result->status == GPGME_SIG_STAT_GOOD_EXP
-          || result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
-        sum |= GPGME_SIGSUM_RED;
+      sig = sig->next;
+      idx--;
     }
-  else if (result->status == GPGME_SIG_STAT_BAD)
-    sum |= GPGME_SIGSUM_RED;
-
-  /* fixme: handle the case when key and message are expired. */
-  if (result->status == GPGME_SIG_STAT_GOOD_EXP)
-    sum |= GPGME_SIGSUM_SIG_EXPIRED;
-  else if (result->status == GPGME_SIG_STAT_GOOD_EXPKEY)
-    sum |= GPGME_SIGSUM_KEY_EXPIRED;
-  else if (result->status == GPGME_SIG_STAT_NOKEY)
-    sum |= GPGME_SIGSUM_KEY_MISSING;
-  else if (result->status == GPGME_SIG_STAT_ERROR)
-    sum |= GPGME_SIGSUM_SYS_ERROR;
-
-  if ( !strcmp (result->trust_errtok, "Certificate_Revoked"))
-    sum |= GPGME_SIGSUM_KEY_REVOKED;
-  else if ( !strcmp (result->trust_errtok, "No_CRL_Known"))
-    sum |= GPGME_SIGSUM_CRL_MISSING;
-  else if ( !strcmp (result->trust_errtok, "CRL_Too_Old"))
-    sum |= GPGME_SIGSUM_CRL_TOO_OLD;
-  else if ( !strcmp (result->trust_errtok, "No_Policy_Match"))
-    sum |= GPGME_SIGSUM_BAD_POLICY;
-  else if (*result->trust_errtok)
-    sum |= GPGME_SIGSUM_SYS_ERROR;
-
-  if (result->wrong_key_usage)
-    sum |= GPGME_SIGSUM_BAD_POLICY;
-
-  /* Set the valid flag when the signature is unquestionable
-     valid. */
-  if ((sum & GPGME_SIGSUM_GREEN) && !(sum & ~GPGME_SIGSUM_GREEN))
-    sum |= GPGME_SIGSUM_VALID;
+  if (!sig || idx)
+    return GPGME_EOF;
 
-  return sum;
+  return gpgme_get_key (ctx, sig->fpr, r_key, 0, 0);
 }
 
 
-const char *
-gpgme_get_sig_string_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int whatidx)
+/* Retrieve the signature status of signature IDX in CTX after a
+   successful verify operation in R_STAT (if non-null).  The creation
+   time stamp of the signature is returned in R_CREATED (if non-null).
+   The function returns a string containing the fingerprint.  */
+const char *gpgme_get_sig_status (GpgmeCtx ctx, int idx,
+                                  GpgmeSigStat *r_stat, time_t *r_created)
 {
-  struct ctx_op_data *op_data;
-  VerifyResult result;
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
 
-  if (!ctx)
-    return NULL;       /* No results yet or verification error.  */
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
 
-  op_data = ctx->op_data;
-  while (op_data)
+  while (sig && idx)
     {
-      while (op_data && op_data->type != OPDATA_VERIFY)
-       op_data = op_data->next;
-      if (idx-- == 0)
-       break;
-      op_data = op_data->next; 
+      sig = sig->next;
+      idx--;
     }
-  if (!op_data)
-    return NULL;       /* No more signatures.  */
+  if (!sig || idx)
+    return NULL;
 
-  result = (VerifyResult) op_data->hook;
-  switch (what)
+  if (r_stat)
     {
-    case GPGME_ATTR_FPR:
-      return result->fpr;
-    case GPGME_ATTR_ERRTOK:
-      if (whatidx == 1)
-        return result->wrong_key_usage? "Wrong_Key_Usage":"";
-      else
-        return result->trust_errtok;
-    default:
-      break;
+      switch (sig->status)
+       {
+       case GPGME_No_Error:
+         *r_stat = GPGME_SIG_STAT_GOOD;
+         break;
+         
+       case GPGME_Bad_Signature:
+         *r_stat = GPGME_SIG_STAT_BAD;
+         break;
+         
+       case GPGME_No_Public_Key:
+         *r_stat = GPGME_SIG_STAT_NOKEY;
+         break;
+         
+       case GPGME_No_Data:
+         *r_stat = GPGME_SIG_STAT_NOSIG;
+         break;
+         
+       case GPGME_Sig_Expired:
+         *r_stat = GPGME_SIG_STAT_GOOD_EXP;
+         break;
+         
+       case GPGME_Key_Expired:
+         *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
+         break;
+         
+       default:
+         *r_stat = GPGME_SIG_STAT_ERROR;
+         break;
+       }
     }
-  return NULL;
+  if (r_created)
+    *r_created = sig->timestamp;
+  return sig->fpr;
 }
 
 
-unsigned long
-gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int reserved)
+/* Retrieve certain attributes of a signature.  IDX is the index
+   number of the signature after a successful verify operation.  WHAT
+   is an attribute where GPGME_ATTR_EXPIRE is probably the most useful
+   one.  WHATIDX is to be passed as 0 for most attributes . */
+unsigned long gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx,
+                                        GpgmeAttr what, int whatidx)
 {
-  struct ctx_op_data *op_data;
-  VerifyResult result;
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
 
-  if (!ctx)
-    return 0;  /* No results yet or verification error.  */
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
 
-  op_data = ctx->op_data;
-  while (op_data)
+  while (sig && idx)
     {
-      while (op_data && op_data->type != OPDATA_VERIFY)
-       op_data = op_data->next;
-      if (idx-- == 0)
-       break;
-      op_data = op_data->next; 
+      sig = sig->next;
+      idx--;
     }
-  if (!op_data)
-    return 0;  /* No more signatures.  */
+  if (!sig || idx)
+    return 0;
 
-  result = (VerifyResult) op_data->hook;
   switch (what)
     {
     case GPGME_ATTR_CREATED:
-      return result->timestamp;
+      return sig->timestamp;
+
     case GPGME_ATTR_EXPIRE:
-      return result->exptimestamp;
+      return sig->exp_timestamp;
+
     case GPGME_ATTR_VALIDITY:
-      return (unsigned long) result->validity;
+      return (unsigned long) sig->validity;
+
     case GPGME_ATTR_SIG_STATUS:
-      return (unsigned long) result->status;
+      switch (sig->status)
+       {
+       case GPGME_No_Error:
+         return GPGME_SIG_STAT_GOOD;
+         
+       case GPGME_Bad_Signature:
+         return GPGME_SIG_STAT_BAD;
+         
+       case GPGME_No_Public_Key:
+         return GPGME_SIG_STAT_NOKEY;
+         
+       case GPGME_No_Data:
+         return GPGME_SIG_STAT_NOSIG;
+         
+       case GPGME_Sig_Expired:
+         return GPGME_SIG_STAT_GOOD_EXP;
+         
+       case GPGME_Key_Expired:
+         return GPGME_SIG_STAT_GOOD_EXPKEY;
+         
+       default:
+         return GPGME_SIG_STAT_ERROR;
+       }
+
     case GPGME_ATTR_SIG_SUMMARY:
-      return calc_sig_summary (result);
+      return sig->summary;
+
     default:
       break;
     }
@@ -641,39 +710,36 @@ gpgme_get_sig_ulong_attr (GpgmeCtx ctx, int idx, GpgmeAttr what, int reserved)
 }
 
 
-/**
- * gpgme_get_sig_key:
- * @c: context
- * @idx: Index of the signature starting at 0
- * @r_key: Returns the key object
- * 
- * Return a key object which was used to check the signature. 
- * 
- * Return value: An Errorcode or 0 for success. GPGME_EOF is returned to
- *               indicate that there are no more signatures. 
- **/
-GpgmeError
-gpgme_get_sig_key (GpgmeCtx ctx, int idx, GpgmeKey *r_key)
+const char *gpgme_get_sig_string_attr (GpgmeCtx ctx, int idx,
+                                      GpgmeAttr what, int whatidx)
 {
-  struct ctx_op_data *op_data;
-  VerifyResult result;
+  GpgmeVerifyResult result;
+  GpgmeSignature sig;
 
-  if (!ctx || !r_key)
-    return GPGME_Invalid_Value;
+  result = gpgme_op_verify_result (ctx);
+  sig = result->signatures;
 
-  op_data = ctx->op_data;
-  while (op_data)
+  while (sig && idx)
     {
-      while (op_data && op_data->type != OPDATA_VERIFY)
-       op_data = op_data->next;
-      if (idx-- == 0)
-       break;
-      op_data = op_data->next; 
+      sig = sig->next;
+      idx--;
     }
-  if (!op_data)
-    return GPGME_EOF;
+  if (!sig || idx)
+    return NULL;
+
+  switch (what)
+    {
+    case GPGME_ATTR_FPR:
+      return sig->fpr;
 
-  result = (VerifyResult) op_data->hook;
+    case GPGME_ATTR_ERRTOK:
+      if (whatidx == 1)
+        return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+      else
+       return "";
+    default:
+      break;
+    }
 
-  return gpgme_get_key (ctx, result->fpr, r_key, 0, 0);
+  return NULL;
 }
index 1dcca5dbf92f030e86c6073eeef7e31dd8fb4ff9..7b5bc36e8706e1863bc96fcc7db0a8404e09502f 100644 (file)
@@ -112,6 +112,7 @@ status_string (GpgmeSigStat status)
     return s;
 }
 
+
 static const char *
 validity_string (GpgmeValidity val)
 {
@@ -132,138 +133,181 @@ validity_string (GpgmeValidity val)
 
 
 static void
-print_sig_stat ( GpgmeCtx ctx, GpgmeSigStat status )
+print_sig_stat (GpgmeCtx ctx, GpgmeSigStat status)
 {
-    const char *s;
-    time_t created;
-    int idx;
-    GpgmeKey key;
+  const char *s;
+  time_t created;
+  int idx;
+  GpgmeKey key;
 
-    printf ("Verification Status: %s\n", status_string (status));
+  printf ("Verification Status: %s\n", status_string (status));
     
-    for(idx=0; (s=gpgme_get_sig_status (ctx, idx, &status, &created)); idx++ ) {
-        printf ("sig %d: created: %lu expires: %lu status: %s\n",
-                idx, (unsigned long)created, 
-                gpgme_get_sig_ulong_attr (ctx, idx, GPGME_ATTR_EXPIRE, 0),
-                status_string(status) );
-        printf ("sig %d: fpr/keyid: `%s' validity: %s\n",
-                idx, s,
-                validity_string (gpgme_get_sig_ulong_attr
-                                 (ctx, idx, GPGME_ATTR_VALIDITY, 0)) );
-        if ( !gpgme_get_sig_key (ctx, idx, &key) ) {
-            char *p = gpgme_key_get_as_xml ( key );
-            printf ("sig %d: key object:\n%s\n", idx, p );
-            free (p);
-            gpgme_key_release (key);
+  for (idx = 0; (s = gpgme_get_sig_status (ctx, idx, &status, &created)); idx++)
+    {
+      printf ("sig %d: created: %lu expires: %lu status: %s\n",
+             idx, (unsigned long) created, 
+             gpgme_get_sig_ulong_attr (ctx, idx, GPGME_ATTR_EXPIRE, 0),
+             status_string (status));
+      printf ("sig %d: fpr/keyid: `%s' validity: %s\n",
+             idx, s,
+             validity_string (gpgme_get_sig_ulong_attr
+                              (ctx, idx, GPGME_ATTR_VALIDITY, 0)));
+      if (!gpgme_get_sig_key (ctx, idx, &key))
+       {
+         char *p = gpgme_key_get_as_xml (key);
+         printf ("sig %d: key object:\n%s\n", idx, p);
+         free (p);
+         gpgme_key_release (key);
         }
     }
 }
 
 int 
-main (int argc, char **argv )
+main (int argc, char *argv[])
 {
-    GpgmeCtx ctx;
-    GpgmeError err;
-    GpgmeData sig, text;
-    GpgmeSigStat status;
-    char *nota;
-    int n = 0;
-    size_t len;
-    int j;
-
-    err = gpgme_new (&ctx);
-    fail_if_err (err);
+  GpgmeCtx ctx;
+  GpgmeError err;
+  GpgmeData sig, text;
+  GpgmeSigStat status;
+  GpgmeVerifyResult result;
+  GpgmeSigNotation notation;
+  char *nota;
+  int n = 0;
+  size_t len;
+  int j;
 
-  do {
-    err = gpgme_data_new_from_mem ( &text,
-                                    test_text1, strlen (test_text1), 0 );
-    fail_if_err (err);
-  #if 1
-    err = gpgme_data_new_from_mem ( &sig,
-                                    test_sig1, strlen (test_sig1), 0 );
-  #else
-    err = gpgme_data_new_from_file ( &sig, "xx1", 1 );
-  #endif
-    fail_if_err (err);
+  err = gpgme_new (&ctx);
+  fail_if_err (err);
 
-    puts ("checking a valid message:\n");
-    err = gpgme_op_verify (ctx, sig, text, NULL);
-    fail_if_err (err);
-    if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
-      {
-       fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
-       exit (1);
-      }
-    print_sig_stat (ctx, status);
-    if (status != GPGME_SIG_STAT_GOOD)
-      {
-       fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
-       exit (1);
-      }
-
-    if ((nota = gpgme_get_notation (ctx)))
-        printf ("---Begin Notation---\n%s---End Notation---\n", nota );
-
-    puts ("checking a manipulated message:\n");
-    gpgme_data_release (text);
-    err = gpgme_data_new_from_mem (&text,
-                                  test_text1f, strlen (test_text1f), 0);
-    fail_if_err (err);
-    gpgme_data_rewind (sig);
-    err = gpgme_op_verify (ctx, sig, text, NULL);
-    fail_if_err (err);
-    if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
-      {
-       fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
-       exit (1);
-      }
-    print_sig_stat (ctx, status);
-    if (status != GPGME_SIG_STAT_BAD)
-      {
-       fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
-       exit (1);
-      }
-    if ((nota = gpgme_get_notation (ctx)))
-        printf ("---Begin Notation---\n%s---End Notation---\n", nota );
+  do
+    {
+      err = gpgme_data_new_from_mem (&text,
+                                    test_text1, strlen (test_text1), 0);
+      fail_if_err (err);
+#if 1
+      err = gpgme_data_new_from_mem (&sig,
+                                    test_sig1, strlen (test_sig1), 0);
+#else
+      err = gpgme_data_new_from_file (&sig, "xx1", 1);
+#endif
+      fail_if_err (err);
 
-    puts ("checking a normal signature:");
-    gpgme_data_release (sig);
-    gpgme_data_release (text);
-    err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0);
-    fail_if_err (err);
-    err = gpgme_data_new (&text);
-    fail_if_err (err);
-    err = gpgme_op_verify (ctx, sig, NULL, text);
-    fail_if_err (err);
-    if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
-      {
-       fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
-       exit (1);
-      }
+      puts ("checking a valid message:\n");
+      err = gpgme_op_verify (ctx, sig, text, NULL);
+      fail_if_err (err);
+      if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
+       {
+         fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      print_sig_stat (ctx, status);
+      if (status != GPGME_SIG_STAT_GOOD)
+       {
+         fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
+         exit (1);
+       }
 
-    nota = gpgme_data_release_and_get_mem (text, &len);
-    for (j = 0; j < len; j++)
+      result = gpgme_op_verify_result (ctx);
+      notation = result->signatures->notations;
+      if (notation)
+       {
+         printf ("---Begin Notation---\n");
+         while (notation)
+           {
+             if (notation->name)
+               printf ("%s: %s\n", notation->name, notation->value);
+             else
+               printf ("Policy URL: %s\n", notation->value);
+             notation = notation->next;
+           }
+         printf ("---End Notation---\n");
+       }
+      
+      puts ("checking a manipulated message:\n");
+      gpgme_data_release (text);
+      err = gpgme_data_new_from_mem (&text,
+                                    test_text1f, strlen (test_text1f), 0);
+      fail_if_err (err);
+      gpgme_data_rewind (sig);
+      err = gpgme_op_verify (ctx, sig, text, NULL);
+      fail_if_err (err);
+      if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
+       {
+         fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      print_sig_stat (ctx, status);
+      if (status != GPGME_SIG_STAT_BAD)
+       {
+         fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      result = gpgme_op_verify_result (ctx);
+      notation = result->signatures->notations;
+      if (notation)
+       {
+         printf ("---Begin Notation---\n");
+         while (notation)
+           {
+             if (notation->name)
+               printf ("%s: %s\n", notation->name, notation->value);
+             else
+               printf ("Policy URL: %s\n", notation->value);
+             notation = notation->next;
+           }
+         printf ("---End Notation---\n");
+       }
+      
+      puts ("checking a normal signature:");
+      gpgme_data_release (sig);
+      gpgme_data_release (text);
+      err = gpgme_data_new_from_mem (&sig, test_sig2, strlen (test_sig2), 0);
+      fail_if_err (err);
+      err = gpgme_data_new (&text);
+      fail_if_err (err);
+      err = gpgme_op_verify (ctx, sig, NULL, text);
+      fail_if_err (err);
+      if (!gpgme_get_sig_status (ctx, 0, &status, NULL))
+       {
+         fprintf (stderr, "%s:%d: No signature\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      
+      nota = gpgme_data_release_and_get_mem (text, &len);
+      for (j = 0; j < len; j++)
       putchar (nota[j]);
-    if (strncmp (nota, test_text1, strlen (test_text1)))
-      {
-       fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__);
-       exit (1);
-      }
-   
-    print_sig_stat (ctx, status);
-    if (status != GPGME_SIG_STAT_GOOD)
-      {
-       fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
-       exit (1);
-      }
-
-    if ((nota = gpgme_get_notation (ctx)))
-      printf ("---Begin Notation---\n%s---End Notation---\n", nota);
+      if (strncmp (nota, test_text1, strlen (test_text1)))
+       {
+         fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      
+      print_sig_stat (ctx, status);
+      if (status != GPGME_SIG_STAT_GOOD)
+       {
+         fprintf (stderr, "%s:%d: Wrong sig stat\n", __FILE__, __LINE__);
+         exit (1);
+       }
+      result = gpgme_op_verify_result (ctx);
+      notation = result->signatures->notations;
+      if (notation)
+       {
+         printf ("---Begin Notation---\n");
+         while (notation)
+           {
+             if (notation->name)
+               printf ("%s: %s\n", notation->name, notation->value);
+             else
+               printf ("Policy URL: %s\n", notation->value);
+             notation = notation->next;
+           }
+         printf ("---End Notation---\n");
+       }
+      
+      gpgme_data_release (sig);      
+    }
+  while (argc > 1 && !strcmp (argv[1], "--loop") && ++n < 20);
 
-    gpgme_data_release (sig);
-} while ( argc > 1 && !strcmp( argv[1], "--loop" ) && ++n < 20 );
-      gpgme_release (ctx);
-    
-    return 0;
+  gpgme_release (ctx);
+  return 0;
 }
index 0a48b3cb1034fd722eb59ad16d4a17c68766e35f..282cf2b89b4b29ade5c34c704ccdde1a62ca2ea3 100644 (file)
@@ -169,6 +169,8 @@ main (int argc, char **argv )
     GpgmeError err;
     GpgmeData sig, text;
     GpgmeSigStat status;
+    GpgmeVerifyResult result;
+    GpgmeSigNotation notation;
     char *nota;
     int n = 0;
 
@@ -194,8 +196,21 @@ main (int argc, char **argv )
       }
     print_sig_stat (ctx, status);
 
-    if ( (nota=gpgme_get_notation (ctx)) )
-        printf ("---Begin Notation---\n%s---End Notation---\n", nota);
+    result = gpgme_op_verify_result (ctx);
+    notation = result->signatures->notations;
+    if (notation)
+      {
+       printf ("---Begin Notation---\n");
+       while (notation)
+         {
+           if (notation->name)
+             printf ("%s: %s\n", notation->name, notation->value);
+           else
+             printf ("Policy URL: %s\n", notation->value);
+           notation = notation->next;
+         }
+       printf ("---End Notation---\n");
+      }      
 
     puts ("checking a manipulated message:\n");
     gpgme_data_release (text);
@@ -212,8 +227,21 @@ main (int argc, char **argv )
       }
     print_sig_stat (ctx, status);
 
-    if ((nota=gpgme_get_notation (ctx)))
-        printf ("---Begin Notation---\n%s---End Notation---\n", nota);
+    result = gpgme_op_verify_result (ctx);
+    notation = result->signatures->notations;
+    if (notation)
+      {
+       printf ("---Begin Notation---\n");
+       while (notation)
+         {
+           if (notation->name)
+             printf ("%s: %s\n", notation->name, notation->value);
+           else
+             printf ("Policy URL: %s\n", notation->value);
+           notation = notation->next;
+         }
+       printf ("---End Notation---\n");
+      }
 
     gpgme_data_release (sig);
     gpgme_data_release (text);