diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 94e407fc..1abc055a 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,5 +1,8 @@ 2004-04-15 Werner Koch + * verify.c (prepare_new_sig, _gpgme_verify_status_handler): Remove + unused result.signatures items. + * keylist.c (gpgme_get_key): Return an error if FPR is NULL. 2004-04-08 Werner Koch diff --git a/gpgme/verify.c b/gpgme/verify.c index a63a564f..c695b9e0 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -38,6 +38,7 @@ typedef struct gpgme_signature_t current_sig; int did_prepare_new_sig; + int only_newsig_seen; } *op_data_t; @@ -151,16 +152,29 @@ static gpgme_error_t prepare_new_sig (op_data_t opd) { gpgme_signature_t sig; - - sig = calloc (1, sizeof (*sig)); - if (!sig) - return gpg_error_from_errno (errno); - if (!opd->result.signatures) - opd->result.signatures = sig; - if (opd->current_sig) - opd->current_sig->next = sig; - opd->current_sig = sig; + + if (opd->only_newsig_seen && opd->current_sig) + { + /* We have only seen the NEWSIG status and nothing else - we + better skip this signature therefore and reuse it for the + next possible signature. */ + sig = opd->current_sig; + memset (sig, 0, sizeof *sig); + assert (opd->result.signatures == sig); + } + else + { + sig = calloc (1, sizeof (*sig)); + if (!sig) + return gpg_error_from_errno (errno); + if (!opd->result.signatures) + opd->result.signatures = sig; + if (opd->current_sig) + opd->current_sig->next = sig; + opd->current_sig = sig; + } opd->did_prepare_new_sig = 1; + opd->only_newsig_seen = 0; return 0; } @@ -508,7 +522,9 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_NEWSIG: if (sig) calc_sig_summary (sig); - return prepare_new_sig (opd); + err = prepare_new_sig (opd); + opd->only_newsig_seen = 1; + return err; case GPGME_STATUS_GOODSIG: case GPGME_STATUS_EXPSIG: @@ -517,19 +533,23 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_ERRSIG: if (sig && !opd->did_prepare_new_sig) calc_sig_summary (sig); + opd->only_newsig_seen = 0; return parse_new_sig (opd, code, args); case GPGME_STATUS_VALIDSIG: + opd->only_newsig_seen = 0; return sig ? parse_valid_sig (sig, args) : gpg_error (GPG_ERR_INV_ENGINE); case GPGME_STATUS_NODATA: + opd->only_newsig_seen = 0; if (!sig) return gpg_error (GPG_ERR_NO_DATA); sig->status = gpg_error (GPG_ERR_NO_DATA); break; case GPGME_STATUS_UNEXPECTED: + opd->only_newsig_seen = 0; if (!sig) return gpg_error (GPG_ERR_GENERAL); sig->status = gpg_error (GPG_ERR_NO_DATA); @@ -538,6 +558,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_NOTATION_NAME: case GPGME_STATUS_NOTATION_DATA: case GPGME_STATUS_POLICY_URL: + opd->only_newsig_seen = 0; return sig ? parse_notation (sig, code, args) : gpg_error (GPG_ERR_INV_ENGINE); @@ -546,10 +567,12 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_TRUST_MARGINAL: case GPGME_STATUS_TRUST_FULLY: case GPGME_STATUS_TRUST_ULTIMATE: + opd->only_newsig_seen = 0; return sig ? parse_trust (sig, code, args) : gpg_error (GPG_ERR_INV_ENGINE); case GPGME_STATUS_ERROR: + opd->only_newsig_seen = 0; /* The error status is informational, so we don't return an error code if we are not ready to process this status. */ return sig ? parse_error (sig, args) : 0; @@ -557,6 +580,29 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args) case GPGME_STATUS_EOF: if (sig && !opd->did_prepare_new_sig) calc_sig_summary (sig); + if (opd->only_newsig_seen && sig) + { + gpgme_signature_t sig2; + /* The last signature has no valid information - remove it + from the list. */ + assert (!sig->next); + if (sig == opd->result.signatures) + opd->result.signatures = NULL; + else + { + for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next) + if (sig2->next == sig) + { + sig2->next = NULL; + break; + } + } + /* Note that there is no need to release the members of SIG + because we won't be here if they have been set. */ + free (sig); + opd->current_sig = NULL; + } + opd->only_newsig_seen = 0; break; default: