This patch implements mail-key, Esc-K, for gpgme. If anyone wants to try it out and give feedback, please go ahead. I'll push it up to the repository in a few days.
Thanks, -Kevin
# HG changeset patch # User Kevin McCarthy <[email protected]> # Date 1421957871 28800 # Thu Jan 22 12:17:51 2015 -0800 # Node ID 73f20978ef5673261bd0440cddcce9940e1c54f3 # Parent b39219ffe75bd255ec7673e950a4d53ffdd73a83 Implement make-key-attachment for gpgme. (closes #3488) This patch implements the make-key-attachment for gpgme, modeled after the pgp version. It adds an optional tempf parameter to data_object_to_tempfile() so the function can be reused. diff --git a/crypt-gpgme.c b/crypt-gpgme.c --- a/crypt-gpgme.c +++ b/crypt-gpgme.c @@ -534,65 +534,71 @@ if (nread == -1) { mutt_error (_("error reading data object: %s\n"), strerror (errno)); return -1; } return 0; } -/* Copy a data object to a newly created temporay file and return that - filename. Caller must free. With RET_FP not NULL, don't close the - stream but return it there. */ -static char *data_object_to_tempfile (gpgme_data_t data, FILE **ret_fp) +/* Copy a data object to a temporary file. + * The tempfile name may be optionally passed in. + * If ret_fp is passed in, the file will be rewound, left open, and returned + * via that parameter. + * The tempfile name is returned, and must be freed. + */ +static char *data_object_to_tempfile (gpgme_data_t data, char *tempf, FILE **ret_fp) { int err; - char tempfile[_POSIX_PATH_MAX]; + char tempfb[_POSIX_PATH_MAX]; FILE *fp; size_t nread = 0; - mutt_mktemp (tempfile, sizeof (tempfile)); - fp = safe_fopen (tempfile, "w+"); - if (!fp) + if (!tempf) { - mutt_perror (tempfile); + mutt_mktemp (tempfb, sizeof (tempfb)); + tempf = tempfb; + } + if ((fp = safe_fopen (tempf, tempf == tempfb ? "w+" : "a+")) == NULL) + { + mutt_perror _("Can't create temporary file"); return NULL; } err = ((gpgme_data_seek (data, 0, SEEK_SET) == -1) ? gpgme_error_from_errno (errno) : 0); if (!err) { char buf[4096]; while ((nread = gpgme_data_read (data, buf, sizeof (buf)))) { if (fwrite (buf, nread, 1, fp) != 1) { - mutt_perror (tempfile); + mutt_perror (tempf); safe_fclose (&fp); - unlink (tempfile); + unlink (tempf); return NULL; } } } if (ret_fp) rewind (fp); else safe_fclose (&fp); if (nread == -1) { mutt_error (_("error reading data object: %s\n"), gpgme_strerror (err)); - unlink (tempfile); + unlink (tempf); safe_fclose (&fp); return NULL; } if (ret_fp) *ret_fp = fp; - return safe_strdup (tempfile); + return safe_strdup (tempf); } static void free_recipient_set (gpgme_key_t **p_rset) { gpgme_key_t *rset, k; if (!p_rset) @@ -801,17 +807,17 @@ mutt_error (_("error encrypting data: %s\n"), gpgme_strerror (err)); gpgme_data_release (ciphertext); gpgme_release (ctx); return NULL; } gpgme_release (ctx); - outfile = data_object_to_tempfile (ciphertext, NULL); + outfile = data_object_to_tempfile (ciphertext, NULL, NULL); gpgme_data_release (ciphertext); return outfile; } /* Find the "micalg" parameter from the last Gpgme operation on context CTX. It is expected that this operation was a sign operation. Return the algorithm name as a C string in buffer BUF which must have been allocated by the caller with size BUFLEN. @@ -927,17 +933,17 @@ if (!sigres->signatures) { gpgme_data_release (signature); gpgme_release (ctx); mutt_error (_("$pgp_sign_as unset and no default key specified in ~/.gnupg/gpg.conf")); return NULL; } - sigfile = data_object_to_tempfile (signature, NULL); + sigfile = data_object_to_tempfile (signature, NULL, NULL); gpgme_data_release (signature); if (!sigfile) { gpgme_release (ctx); return NULL; } t = mutt_new_body (); @@ -2207,17 +2213,17 @@ static void copy_clearsigned (gpgme_data_t data, STATE *s, char *charset) { char buf[HUGE_STRING]; short complete, armor_header; FGETCONV *fc; char *fname; FILE *fp; - fname = data_object_to_tempfile (data, &fp); + fname = data_object_to_tempfile (data, NULL, &fp); if (!fname) return; unlink (fname); FREE (&fname); /* fromcode comes from the MIME Content-Type charset label. It might * be a wrong label, so we want the ability to do corrections via * charset-hooks. Therefore we set flags to M_ICONV_HOOK_FROM. @@ -2400,17 +2406,17 @@ } if (!anybad && idx) maybe_goodsig = 1; state_attach_puts (_("[-- End signature " "information --]\n\n"), s); } - tmpfname = data_object_to_tempfile (plaintext, &pgpout); + tmpfname = data_object_to_tempfile (plaintext, NULL, &pgpout); if (!tmpfname) { pgpout = NULL; state_attach_puts (_("Error: copy data failed\n"), s); } else { unlink (tmpfname); @@ -4458,16 +4464,73 @@ return find_keys (to, cc, bcc, APPLICATION_PGP); } char *smime_gpgme_findkeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) { return find_keys (to, cc, bcc, APPLICATION_SMIME); } +BODY *pgp_gpgme_make_key_attachment (char *tempf) +{ + crypt_key_t *key = NULL; + gpgme_ctx_t context = NULL; + gpgme_key_t export_keys[2]; + gpgme_data_t keydata = NULL; + gpgme_error_t err; + BODY *att = NULL; + char buff[LONG_STRING]; + struct stat sb; + + unset_option (OPTPGPCHECKTRUST); + + key = crypt_ask_for_key (_("Please enter the key ID: "), NULL, 0, + APPLICATION_PGP, NULL); + if (!key) + goto bail; + export_keys[0] = key->kobj; + export_keys[1] = NULL; + + context = create_gpgme_context (0); + gpgme_set_armor (context, 1); + keydata = create_gpgme_data (); + err = gpgme_op_export_keys (context, export_keys, 0, keydata); + if (err != GPG_ERR_NO_ERROR) + { + mutt_error (_("Error exporting key: %s\n"), gpgme_strerror (err)); + mutt_sleep (1); + goto bail; + } + + tempf = data_object_to_tempfile (keydata, tempf, NULL); + if (!tempf) + goto bail; + + att = mutt_new_body (); + /* tempf is a newly allocated string, so this is correct: */ + att->filename = tempf; + att->unlink = 1; + att->use_disp = 0; + att->type = TYPEAPPLICATION; + att->subtype = safe_strdup ("pgp-keys"); + snprintf (buff, sizeof (buff), _("PGP Key 0x%s."), crypt_keyid (key)); + att->description = safe_strdup (buff); + mutt_update_encoding (att); + + stat (tempf, &sb); + att->length = sb.st_size; + +bail: + crypt_free_key (&key); + gpgme_data_release (keydata); + gpgme_release (context); + + return att; +} + /* * Implementation of `init'. */ /* This function contains common code needed to be executed for both the pgp * and smime support of gpgme. */ static void init_common(void) { diff --git a/crypt-mod-pgp-gpgme.c b/crypt-mod-pgp-gpgme.c --- a/crypt-mod-pgp-gpgme.c +++ b/crypt-mod-pgp-gpgme.c @@ -90,16 +90,21 @@ return pgp_gpgme_send_menu (msg, redraw); } static BODY *crypt_mod_pgp_encrypt_message (BODY *a, char *keylist, int sign) { return pgp_gpgme_encrypt_message (a, keylist, sign); } +static BODY *crypt_mod_pgp_make_key_attachment (char *tempf) +{ + return pgp_gpgme_make_key_attachment (tempf); +} + static void crypt_mod_pgp_set_sender (const char *sender) { gpgme_set_sender (sender); } struct crypt_module_specs crypt_mod_pgp_gpgme = { APPLICATION_PGP, { @@ -113,17 +118,17 @@ crypt_mod_pgp_findkeys, crypt_mod_pgp_sign_message, crypt_mod_pgp_verify_one, crypt_mod_pgp_send_menu, crypt_mod_pgp_set_sender, /* PGP specific. */ crypt_mod_pgp_encrypt_message, - NULL, /* pgp_make_key_attachment, */ + crypt_mod_pgp_make_key_attachment, crypt_mod_pgp_check_traditional, NULL, /* pgp_traditional_encryptsign */ NULL, /* pgp_invoke_getkeys */ crypt_mod_pgp_invoke_import, NULL, /* pgp_extract_keys_from_attachment_list */ NULL, /* smime_getkeys */ NULL, /* smime_verify_sender */
signature.asc
Description: PGP signature
