Because the default changes, this is a slight change of the API
semantics. We consider it to be a bug fix.
+ * Information about the recipients of an encrypted text is now
+ available at decryption time.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_set_engine_info NEW
gpgme_ctx_get_engine_info NEW
gpgme_ctx_set_engine_info NEW
gpgme_set_include_certs CHANGED DEFAULT
GPGME_INCLUDE_CERTS_DEFAULT NEW
+gpgme_recipient_t NEW
+gpgme_decrypt_result_t EXTENDED: New field recipients.
GPGME_STATUS_SIG_SUBPACKET NEW
GPGME_STATUS_NEED_PASSPHRASE_PIN NEW
GPGME_STATUS_SC_OP_FAILURE NEW
+2005-06-03 Marcus Brinkmann <marcus@g10code.de>
+
+ * gpgme.texi (Decrypt): Add gpgme_recipient_t.
+
2005-05-28 Marcus Brinkmann <marcus@g10code.de>
* gpgme.texi (Key Listing Mode): Fix return type of
if @var{cipher} or @var{plain} is not a valid pointer.
@end deftypefun
+@deftp {Data type} {gpgme_recipient_t}
+This is a pointer to a structure used to store information about the
+recipient of an encrypted text which is decrypted in a
+@code{gpgme_op_decrypt} operation. This information (except for the
+status field) is even available before the operation finished
+successfully, for example in a passphrase callback. The structure
+contains the following members:
+
+@table @code
+@item gpgme_recipient_t next
+This is a pointer to the next recipient structure in the linked list,
+or @code{NULL} if this is the last element.
+
+@item gpgme_pubkey_algo_t
+The public key algorithm used in the encryption.
+
+@item unsigned int wrong_key_usage : 1
+This is true if the key was not used according to its policy.
+
+@item char *keyid
+This is the key ID of the key (in hexadecimal digits) used as
+recipient.
+
+@item gpgme_error_t status
+This is an error number with the error code GPG_ERR_NO_SECKEY if the
+secret key for this recipient is not available, and 0 otherwise.
+@end table
+@end deftp
+
@deftp {Data type} {gpgme_decrypt_result_t}
This is a pointer to a structure used to store the result of a
-@code{gpgme_op_decrypt} operation. After successfully encrypting
+@code{gpgme_op_decrypt} operation. After successfully decrypting
data, you can retrieve the pointer to the result with
@code{gpgme_op_decrypt_result}. The structure contains the following
members:
@item unsigned int wrong_key_usage : 1
This is true if the key was not used according to its policy.
+
+@item gpgme_recipient_t recipient
+This is a linked list of recipients to which this message was encrypted.
@end table
@end deftp
2005-06-03 Marcus Brinkmann <marcus@g10code.de>
+ * gpgme.h (struct _gpgme_recipient): New structure.
+ (gpgme_recipient_t): New type.
+ (struct _gpgme_op_decrypt_result): Add member recipients.
+ * decrypt.c (op_data_t): New member last_recipient_p.
+ (_gpgme_op_decrypt_init_result): Initialize last_recipient_p.
+ (parse_enc_to): New function.
+ (_gpgme_decrypt_status_handler): Handle status ENC_TO and
+ NO_SECKEY.
+
* wait-global.c (gpgme_wait): Break out of the fd processing loop
after an error.
Reported by Igor Belyi <gpgme@katehok.ac93.org>.
int okay;
int failed;
+
+ /* A pointer to the next pointer of the last recipient in the list.
+ This makes appending new invalid signers painless while
+ preserving the order. */
+ gpgme_recipient_t *last_recipient_p;
} *op_data_t;
}
\f
+static gpgme_error_t
+parse_enc_to (char *args, gpgme_recipient_t *recp)
+{
+ gpgme_recipient_t rec;
+ char *tail;
+ int i;
+
+ rec = malloc (sizeof (*rec));
+ if (!rec)
+ return gpg_error_from_errno (errno);
+
+ rec->next = NULL;
+ rec->keyid = rec->_keyid;
+ rec->status = 0;
+
+ for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
+ {
+ if (args[i] == '\0' || args[i] == ' ')
+ break;
+
+ rec->_keyid[i] = args[i];
+ }
+ rec->_keyid[i] = '\0';
+
+ args = &args[i];
+ if (*args != '\0' && *args != ' ')
+ {
+ free (rec);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ while (*args == ' ')
+ args++;
+
+ if (*args)
+ {
+ errno = 0;
+ rec->pubkey_algo = strtol (args, &tail, 0);
+ if (errno || args == tail || *tail != ' ')
+ {
+ /* The crypto backend does not behave. */
+ free (rec);
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ }
+
+ /* FIXME: The key length is always 0 right now, so no need to parse
+ it. */
+
+ *recp = rec;
+ return 0;
+}
+
+
gpgme_error_t
_gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
char *args)
}
}
break;
-
+
+ case GPGME_STATUS_ENC_TO:
+ err = parse_enc_to (args, opd->last_recipient_p);
+ if (err)
+ return err;
+
+ opd->last_recipient_p = &(*opd->last_recipient_p)->next;
+ break;
+
+ case GPGME_STATUS_NO_SECKEY:
+ {
+ gpgme_recipient_t rec = opd->result.recipients;
+
+ while (rec)
+ {
+ if (!strcmp (rec->keyid, args))
+ {
+ rec->status = gpg_error (GPG_ERR_NO_SECKEY);
+ break;
+ }
+ }
+ /* FIXME: Is this ok? */
+ if (!rec)
+ return gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ break;
+
default:
break;
}
gpgme_error_t
_gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
{
+ gpgme_error_t err;
void *hook;
op_data_t opd;
- return _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
- sizeof (*opd), release_op_data);
+ err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->last_recipient_p = &opd->result.recipients;
+ return 0;
}
\f
/* Decryption. */
+
+struct _gpgme_recipient
+{
+ struct _gpgme_recipient *next;
+
+ /* The key ID of key for which the text was encrypted. */
+ char *keyid;
+
+ /* Internal to GPGME, do not use. */
+ char _keyid[16 + 1];
+
+ /* The public key algorithm of the recipient key. */
+ gpgme_pubkey_algo_t pubkey_algo;
+
+ /* The status of the recipient. */
+ gpgme_error_t status;
+};
+typedef struct _gpgme_recipient *gpgme_recipient_t;
+
struct _gpgme_op_decrypt_result
{
char *unsupported_algorithm;
/* Internal to GPGME, do not use. */
int _unused : 31;
+
+ gpgme_recipient_t recipients;
};
typedef struct _gpgme_op_decrypt_result *gpgme_decrypt_result_t;