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 */

Attachment: signature.asc
Description: PGP signature

Reply via email to