changeset: 6423:70b85d8b232b
user:      Peter Wu <[email protected]>
date:      Tue Feb 10 18:29:24 2015 +0100
link:      http://dev.mutt.org/hg/mutt/rev/70b85d8b232b

Fix buffer underread for empty header values. (closes #3736)

When a header has no value (*p == '\0' so l == 0), do not read outside
the buffer but print the newline anyway when a tag is already printed
(col != 0).

Caught by ASAN while opening a draft with no Subject.

changeset: 6424:71f12fef8c6f
user:      Kevin McCarthy <[email protected]>
date:      Thu Feb 19 11:00:32 2015 -0800
link:      http://dev.mutt.org/hg/mutt/rev/71f12fef8c6f

merge stable

diffs (truncated from 4764 to 950 lines):

diff -r 31ce789af3df -r 71f12fef8c6f .hgignore
--- a/.hgignore Wed Dec 31 20:35:38 2014 -0800
+++ b/.hgignore Thu Feb 19 11:00:32 2015 -0800
@@ -37,6 +37,8 @@
 ^doc/manual\.(txt|xml|aux|log|out|tex|pdf)$
 ^doc/mutt\.1$
 ^doc/muttrc\.man$
+^doc/pgpewrap\.1$
+^doc/pgpring\.1$
 ^doc/.*\.html$
 ^doc/stamp-
 ^doc/smime_keys\.1$
@@ -53,6 +55,9 @@
 syntax: glob
 .deps
 Makefile
+GPATH
+GRTAGS
+GTAGS
 TAGS
 cscope.*
 *.swp
diff -r 31ce789af3df -r 71f12fef8c6f INSTALL
--- a/INSTALL   Wed Dec 31 20:35:38 2014 -0800
+++ b/INSTALL   Thu Feb 19 11:00:32 2015 -0800
@@ -280,7 +280,7 @@
        For the real fix, applying Sun patches # 105490-05 (linker
        patch) and # 105210-17 (libc and malloc patch) from
        sunsolve.sun.com has been reported to stop these problems
-       from occuring.
+       from occurring.
 
 Linux
 
diff -r 31ce789af3df -r 71f12fef8c6f Makefile.am
--- a/Makefile.am       Wed Dec 31 20:35:38 2014 -0800
+++ b/Makefile.am       Thu Feb 19 11:00:32 2015 -0800
@@ -1,5 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 ## Use aclocal -I m4; automake --foreign
+include $(top_srcdir)/flymake.am
 
 AUTOMAKE_OPTIONS = 1.6 foreign
 EXTRA_PROGRAMS = mutt_dotlock pgpring pgpewrap mutt_md5
diff -r 31ce789af3df -r 71f12fef8c6f README.SECURITY
--- a/README.SECURITY   Wed Dec 31 20:35:38 2014 -0800
+++ b/README.SECURITY   Thu Feb 19 11:00:32 2015 -0800
@@ -19,7 +19,7 @@
 
 - Backticks are handled specially when preparing % expandos for
   mailcap entries.  This fix will keep the current problem from
-  occuring, but we are sure there are other possible mailcap entries
+  occurring, but we are sure there are other possible mailcap entries
   where this doesn't help.
 
 - We have added a configuration variable named $mailcap_sanitize,
diff -r 31ce789af3df -r 71f12fef8c6f README.SSL
--- a/README.SSL        Wed Dec 31 20:35:38 2014 -0800
+++ b/README.SSL        Thu Feb 19 11:00:32 2015 -0800
@@ -97,7 +97,7 @@
     openssl s_client -host <imap server> -port <port> -verify -debug -no_ssl2
     openssl s_client -host <imap server> -port <port> -verify -debug -no_ssl3
 
-You can also combine the options until you get a successfull connect.  Once
+You can also combine the options until you get a successful connect.  Once
 you know which options do not work, you can set the variables for non-working
 protocols to know.  The variables for the protocols are ssl_use_tlsv1, 
 ssl_use_sslv2, and ssl_use_sslv3.
diff -r 31ce789af3df -r 71f12fef8c6f TODO
--- a/TODO      Wed Dec 31 20:35:38 2014 -0800
+++ b/TODO      Thu Feb 19 11:00:32 2015 -0800
@@ -50,7 +50,7 @@
   Note: This still requires some thought, since we'd have to store
   per-entry data in the menu structure.  As an alternative, we could
   extend the tag method to do something to more general flags. The
-  latter approach would make the implementation of propper
+  latter approach would make the implementation of proper
   tag-prefix behaviour more simple: Functions should only be applied
   when a message is tagged and visible.  Additionally, we must not
   access a menu's max field directly any more: Adding an entry to a
diff -r 31ce789af3df -r 71f12fef8c6f UPDATING
--- a/UPDATING  Wed Dec 31 20:35:38 2014 -0800
+++ b/UPDATING  Thu Feb 19 11:00:32 2015 -0800
@@ -9,6 +9,8 @@
   ! FCC is now preserved when postponing a message.
   ! Mail-Followup-To is now preserved when recalling a postponed message.
   ! Allow filename prompt when saving multiple attachments to a directory.
+  + terminal status-line (TS) support, a.k.a. xterm title. see the
+    following variables: $ts_enabled, $ts_icon_format, $ts_status_format
 
 1.5.22 (2013-10-18):
 
diff -r 31ce789af3df -r 71f12fef8c6f color.c
--- a/color.c   Wed Dec 31 20:35:38 2014 -0800
+++ b/color.c   Thu Feb 19 11:00:32 2015 -0800
@@ -93,6 +93,7 @@
   { "bold",            MT_COLOR_BOLD },
   { "underline",       MT_COLOR_UNDERLINE },
   { "index",           MT_COLOR_INDEX },
+  { "prompt",          MT_COLOR_PROMPT },
   { NULL,              0 }
 };
 
diff -r 31ce789af3df -r 71f12fef8c6f commands.c
--- a/commands.c        Wed Dec 31 20:35:38 2014 -0800
+++ b/commands.c        Thu Feb 19 11:00:32 2015 -0800
@@ -286,7 +286,7 @@
   if (rc || !buf[0])
     return;
 
-  if (!(adr = rfc822_parse_adrlist (adr, buf)))
+  if (!(adr = mutt_parse_adrlist (adr, buf)))
   {
     mutt_error _("Error parsing address!");
     return;
diff -r 31ce789af3df -r 71f12fef8c6f configure.ac
--- a/configure.ac      Wed Dec 31 20:35:38 2014 -0800
+++ b/configure.ac      Thu Feb 19 11:00:32 2015 -0800
@@ -138,6 +138,11 @@
       #needed to get GPGME_LIBS and al correctly
       AM_PATH_GPGME(1.0.0, AC_DEFINE(CRYPT_BACKEND_GPGME, 1,
                     [Define if you use GPGME to support OpenPGP]))
+      dnl AC_CHECK_FUNCS([gpgme_op_export_keys])
+      saved_LIBS="$LIBS"
+      LIBS="$LIBS $GPGME_LIBS"
+      AC_CHECK_FUNCS([gpgme_op_export_keys])
+      LIBS="$saved_LIBS"
       MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS crypt-gpgme.o crypt-mod-pgp-gpgme.o 
crypt-mod-smime-gpgme.o"
    fi
 else
@@ -163,7 +168,7 @@
 ])
  
 if test x$have_smime != xno ; then
-       AC_DEFINE(CRYPT_BACKEND_CLASSIC_SMIME, 1, [Define if you want clasic 
S/MIME support.])
+       AC_DEFINE(CRYPT_BACKEND_CLASSIC_SMIME, 1, [Define if you want classic 
S/MIME support.])
        MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS smime.o crypt-mod-smime-classic.o"
        SMIMEAUX_TARGET="smime_keys"
 fi
@@ -295,6 +300,7 @@
         if test "$ac_cv_func_decl_resizeterm" = yes; then
                 MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS resize.o"
         fi
+        AC_CHECK_FUNCS([use_extended_names])
         LIBS="$old_LIBS"
         ])
 
@@ -706,6 +712,16 @@
       AC_CHECK_DECLS([GNUTLS_VERIFY_DISABLE_TIME_CHECKS], [], [],
                     [[#include <gnutls/x509.h>]])
 
+      LIBS="$LIBS -lgnutls"
+      AC_CHECK_FUNCS(gnutls_priority_set_direct)
+      AC_CHECK_TYPES([gnutls_certificate_credentials_t,
+                      gnutls_certificate_status_t,
+                      gnutls_datum_t,
+                      gnutls_digest_algorithm_t,
+                      gnutls_session_t,
+                      gnutls_transport_ptr_t,
+                      gnutls_x509_crt_t], [], [], [[#include 
<gnutls/gnutls.h>]])
+
       LIBS="$saved_LIBS"
       MUTTLIBS="$MUTTLIBS -lgnutls"
 
diff -r 31ce789af3df -r 71f12fef8c6f contrib/colors.default
--- a/contrib/colors.default    Wed Dec 31 20:35:38 2014 -0800
+++ b/contrib/colors.default    Thu Feb 19 11:00:32 2015 -0800
@@ -6,6 +6,7 @@
 color quoted blue white
 color signature red white
 color attachment red white
+color prompt brightmagenta white
 color message brightred white
 color error brightred white
 color indicator brightyellow red
diff -r 31ce789af3df -r 71f12fef8c6f contrib/colors.linux
--- a/contrib/colors.linux      Wed Dec 31 20:35:38 2014 -0800
+++ b/contrib/colors.linux      Thu Feb 19 11:00:32 2015 -0800
@@ -6,6 +6,7 @@
 color quoted blue black
 color signature blue black
 color attachment red black
+color prompt brightmagenta black
 color message brightred black
 color error brightred black
 color indicator black red
diff -r 31ce789af3df -r 71f12fef8c6f contrib/gpg.rc
--- a/contrib/gpg.rc    Wed Dec 31 20:35:38 2014 -0800
+++ b/contrib/gpg.rc    Thu Feb 19 11:00:32 2015 -0800
@@ -65,10 +65,10 @@
 set pgp_verify_key_command="gpg --verbose --batch --fingerprint --check-sigs 
%r"
 
 # read in the public key ring
-set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons 
--list-keys %r" 
+set pgp_list_pubring_command="gpg --no-verbose --batch --quiet --with-colons 
--with-fingerprint --with-fingerprint --list-keys %r"
 
 # read in the secret key ring
-set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons 
--list-secret-keys %r" 
+set pgp_list_secring_command="gpg --no-verbose --batch --quiet --with-colons 
--with-fingerprint --with-fingerprint --list-secret-keys %r"
 
 # fetch keys
 # set pgp_getkeys_command="pkspxycwrap %r"
diff -r 31ce789af3df -r 71f12fef8c6f contrib/smime.rc
--- a/contrib/smime.rc  Wed Dec 31 20:35:38 2014 -0800
+++ b/contrib/smime.rc  Thu Feb 19 11:00:32 2015 -0800
@@ -59,8 +59,8 @@
 # Sction B: Outgoing messages
 
 # Algorithm to use for encryption.
-# valid choices are rc2-40, rc2-64, rc2-128, des, des3
-set smime_encrypt_with="des3"
+# valid choices are aes128, aes192, aes256, rc2-40, rc2-64, rc2-128, des, des3
+set smime_encrypt_with="aes256"
 
 # Encrypt a message. Input file is a MIME entity.
 set smime_encrypt_command="openssl smime -encrypt -%a -outform DER -in %f %c"
diff -r 31ce789af3df -r 71f12fef8c6f crypt-gpgme.c
--- a/crypt-gpgme.c     Wed Dec 31 20:35:38 2014 -0800
+++ b/crypt-gpgme.c     Thu Feb 19 11:00:32 2015 -0800
@@ -110,6 +110,7 @@
   int idx;             /* and the user ID at this index */
   const char *uid;     /* and for convenience point to this user ID */
   unsigned int flags;  /* global and per uid flags (for convenience)*/
+  gpgme_validity_t validity;  /* uid validity (cached for convenience) */
 } crypt_key_t;
 
 typedef struct crypt_entry
@@ -179,6 +180,34 @@
   return s;
 }
 
+/* Return the long keyID for the key K. */
+static const char *crypt_long_keyid (crypt_key_t *k)
+{
+  const char *s = "????????????????";
+
+  if (k->kobj && k->kobj->subkeys)
+    {
+      s = k->kobj->subkeys->keyid;
+    }
+
+  return s;
+}
+
+/* Return the short keyID for the key K. */
+static const char *crypt_short_keyid (crypt_key_t *k)
+{
+  const char *s = "????????";
+
+  if (k->kobj && k->kobj->subkeys)
+    {
+      s = k->kobj->subkeys->keyid;
+      if (strlen (s) == 16)
+        s += 8;
+    }
+
+  return s;
+}
+
 /* Return the hexstring fingerprint from the key K. */
 static const char *crypt_fpr (crypt_key_t *k)
 {
@@ -240,6 +269,7 @@
   k->idx = key->idx;
   k->uid = key->uid;
   k->flags = key->flags;
+  k->validity = key->validity;
 
   return k;
 }
@@ -248,12 +278,19 @@
    to NULL. */
 static void crypt_free_key (crypt_key_t **keylist)
 {
+  crypt_key_t *k;
+
+  if (!keylist)
+    return;
+
   while (*keylist)
-    {
-      crypt_key_t *k = (*keylist)->next;
-      FREE (&k);
-      *keylist = k;
-    }
+  {
+    k = *keylist;
+    *keylist = (*keylist)->next;
+
+    gpgme_key_unref (k->kobj);
+    FREE (&k);
+  }
 }
 
 /* Return trute when key K is valid. */
@@ -267,21 +304,12 @@
 /* Return true whe validity of KEY is sufficient. */
 static int crypt_id_is_strong (crypt_key_t *key)
 {
-  gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
-  gpgme_user_id_t uid = NULL;
   unsigned int is_strong = 0;
-  unsigned int i = 0;
 
   if ((key->flags & KEYFLAG_ISX509))
     return 1;
 
-  for (i = 0, uid = key->kobj->uids; (i < key->idx) && uid;
-       i++, uid = uid->next)
-    ;
-  if (uid)
-    val = uid->validity;
-
-  switch (val)
+  switch (key->validity)
     {
     case GPGME_VALIDITY_UNKNOWN:
     case GPGME_VALIDITY_UNDEFINED:
@@ -504,21 +532,27 @@
   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;
     }
 
@@ -532,9 +566,9 @@
         {
           if (fwrite (buf, nread, 1, fp) != 1)
             {
-              mutt_perror (tempfile);
+              mutt_perror (tempf);
               safe_fclose (&fp);
-              unlink (tempfile);
+              unlink (tempf);
               return NULL;
             }
         }
@@ -546,13 +580,35 @@
   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)
+    return;
+
+  rset = *p_rset;
+  if (!rset)
+    return;
+
+  while (*rset)
+  {
+    k = *rset;
+    gpgme_key_unref (k);
+    rset++;
+  }
+
+  FREE (p_rset);       /* __FREE_CHECKED__ */
 }
 
 
@@ -608,7 +664,9 @@
              {
                mutt_error (_("error adding recipient `%s': %s\n"),
                            buf, gpgme_strerror (err));
-               FREE (&rset);
+               rset[rset_n] = NULL;
+               free_recipient_set (&rset);
+               gpgme_release (context);
                return NULL;
              }
          }
@@ -651,8 +709,8 @@
   err = gpgme_op_keylist_next (listctx, &key2);
   if (!err)
     {
-      gpgme_key_release (key);
-      gpgme_key_release (key2);
+      gpgme_key_unref (key);
+      gpgme_key_unref (key2);
       gpgme_release (listctx);
       mutt_error (_("ambiguous specification of secret key `%s'\n"),
                   signid);
@@ -663,7 +721,7 @@
 
   gpgme_signers_clear (ctx);
   err = gpgme_signers_add (ctx, key);
-  gpgme_key_release (key);
+  gpgme_key_unref (key);
   if (err)
     {
       mutt_error (_("error setting secret key `%s': %s\n"),
@@ -747,7 +805,7 @@
 
   gpgme_release (ctx);
 
-  outfile = data_object_to_tempfile (ciphertext, NULL);
+  outfile = data_object_to_tempfile (ciphertext, NULL, NULL);
   gpgme_data_release (ciphertext);
   return outfile;
 }
@@ -834,6 +892,7 @@
   if (set_signer (ctx, use_smime))
     {
       gpgme_data_release (signature);
+      gpgme_data_release (message);
       gpgme_release (ctx);
       return NULL;
     }
@@ -872,7 +931,7 @@
       return NULL;
   }
 
-  sigfile = data_object_to_tempfile (signature, NULL);
+  sigfile = data_object_to_tempfile (signature, NULL, NULL);
   gpgme_data_release (signature);
   if (!sigfile)
     {
@@ -918,6 +977,7 @@
   else
     {
       t->subtype = safe_strdup ("pgp-signature");
+      mutt_set_parameter ("name", "signature.asc", &t->parameter);
       t->use_disp = 0;
       t->disposition = DISPNONE;
       t->encoding = ENC7BIT;
@@ -961,13 +1021,13 @@
   plaintext = body_to_data_object (a, 0);
   if (!plaintext)
     {
-      FREE (&rset);
+      free_recipient_set (&rset);
       return NULL;
     }
   
   outfile = encrypt_gpgme_object (plaintext, rset, 0, sign);
   gpgme_data_release (plaintext);
-  FREE (&rset);
+  free_recipient_set (&rset);
   if (!outfile)
       return NULL;
 
@@ -1020,13 +1080,13 @@
   plaintext = body_to_data_object (a, 0);
   if (!plaintext)
     {
-      FREE (&rset);
+      free_recipient_set (&rset);
       return NULL;
     }
 
   outfile = encrypt_gpgme_object (plaintext, rset, 1, 0);
   gpgme_data_release (plaintext);
-  FREE (&rset);
+  free_recipient_set (&rset);
   if (!outfile) 
       return NULL;
 
@@ -1342,7 +1402,7 @@
 
       if (signature_key)
        {
-         gpgme_key_release (signature_key);
+         gpgme_key_unref (signature_key);
          signature_key = NULL;
        }
       
@@ -1420,7 +1480,7 @@
       }
 
       if (key != signature_key)
-       gpgme_key_release (key);
+       gpgme_key_unref (key);
     }
 
   return anybad ? 1 : anywarn ? 2 : 0;
@@ -1461,6 +1521,9 @@
   state_attach_puts (_("[-- Begin signature information --]\n"), s);
 
   err = gpgme_op_verify (ctx, signature, message, NULL);
+  gpgme_data_release (message);
+  gpgme_data_release (signature);
+
   mutt_need_hard_redraw ();
   if (err)
     {
@@ -1478,7 +1541,7 @@
 
       if (signature_key)
        {
-         gpgme_key_release (signature_key);
+         gpgme_key_unref (signature_key);
          signature_key = NULL;
        }
 
@@ -1966,7 +2029,7 @@
       subkey = subkey->next;
       more = 1;
     }
-    gpgme_key_release (key);
+    gpgme_key_unref (key);
   }
   if (gpg_err_code (err) != GPG_ERR_EOF)
   {
@@ -2148,7 +2211,7 @@
   char *fname;
   FILE *fp;
 
-  fname = data_object_to_tempfile (data, &fp);
+  fname = data_object_to_tempfile (data, NULL, &fp);
   if (!fname)
     return;
   unlink (fname);
@@ -2341,7 +2404,7 @@
                                            "information --]\n\n"), s);
                     }
 
-                  tmpfname = data_object_to_tempfile (plaintext, &pgpout);
+                  tmpfname = data_object_to_tempfile (plaintext, NULL, 
&pgpout);
                   if (!tmpfname)
                     {
                       pgpout = NULL;
@@ -2353,6 +2416,7 @@
                       FREE (&tmpfname);
                     }
                 }
+              gpgme_data_release (plaintext);
               gpgme_release (ctx);
             }
       
@@ -2404,6 +2468,7 @@
                 state_attach_puts (_("[-- END PGP SIGNED MESSAGE --]\n"), s);
             }
           
+          gpgme_data_release (armored_data);
           if (pgpout)
             {
               safe_fclose (&pgpout);
@@ -2769,35 +2834,28 @@
         s = "x";
       else
        {
-         gpgme_user_id_t uid = NULL;
-         unsigned int i = 0;
-
-         for (i = 0, uid = key->kobj->uids; uid && (i < key->idx);
-               i++, uid = uid->next)
-            ;
-         if (uid)
-           switch (uid->validity)
-             {
-             case GPGME_VALIDITY_UNDEFINED:
-               s = "q";
-               break;
-             case GPGME_VALIDITY_NEVER:
-               s = "n";
-               break;
-             case GPGME_VALIDITY_MARGINAL:
-               s = "m";
-               break;
-             case GPGME_VALIDITY_FULL:
-               s = "f";
-               break;
-             case GPGME_VALIDITY_ULTIMATE:
-               s = "u";
-               break;
-             case GPGME_VALIDITY_UNKNOWN:
-             default:
-               s = "?";
-               break;
-             }
+          switch (key->validity)
+            {
+            case GPGME_VALIDITY_UNDEFINED:
+              s = "q";
+              break;
+            case GPGME_VALIDITY_NEVER:
+              s = "n";
+              break;
+            case GPGME_VALIDITY_MARGINAL:
+              s = "m";
+              break;
+            case GPGME_VALIDITY_FULL:
+              s = "f";
+              break;
+            case GPGME_VALIDITY_ULTIMATE:
+              s = "u";
+              break;
+            case GPGME_VALIDITY_UNKNOWN:
+            default:
+              s = "?";
+              break;
+            }
        }
       snprintf (fmt, sizeof (fmt), "%%%sc", prefix);
       snprintf (dest, destlen, fmt, s? *s: 'B');
@@ -2910,10 +2968,8 @@
            - ((*t)->flags & (KEYFLAG_RESTRICTIONS)))))
     return r > 0;
 
-  if ((*s)->kobj->uids)
-    ts = (*s)->kobj->uids->validity;
-  if ((*t)->kobj->uids)
-    tt = (*t)->kobj->uids->validity;
+  ts = (*s)->validity;
+  tt = (*t)->validity;
   if ((r = (tt - ts)))
     return r < 0;
 
@@ -3514,7 +3570,7 @@
     {
       putc ('\n', fp);
       err = gpgme_op_keylist_start (listctx, s, 0);
-      gpgme_key_release (k);
+      gpgme_key_unref (k);
       k = NULL;
       if (!err)
        err = gpgme_op_keylist_next (listctx, &k);
@@ -3537,7 +3593,7 @@
     }
 
  leave:
-  gpgme_key_release (k);
+  gpgme_key_unref (k);
   gpgme_release (listctx);
   safe_fclose (&fp);
   mutt_clear_error ();
@@ -3679,6 +3735,13 @@
          if (key_check_cap (key, KEY_CAP_CAN_SIGN))
             flags |= KEYFLAG_CANSIGN;
 
+          if (key->revoked)
+            flags |= KEYFLAG_REVOKED;
+          if (key->expired)
+            flags |= KEYFLAG_EXPIRED;
+          if (key->disabled)
+            flags |= KEYFLAG_DISABLED;
+
 #if 0 /* DISABLED code */
           if (!flags)
             {
@@ -3705,12 +3768,17 @@
             {
               k = safe_calloc (1, sizeof *k);
               k->kobj = key;
+              gpgme_key_ref (k->kobj);
               k->idx = idx;
               k->uid = uid->uid;
               k->flags = flags;
+              if (uid->revoked)
+                k->flags |= KEYFLAG_REVOKED;
+              k->validity = uid->validity;
               *kend = k;
               kend = &k->next;
             }
+          gpgme_key_unref (key);
         }
       if (gpg_err_code (err) != GPG_ERR_EOF)
         mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror 
(err));
@@ -3746,12 +3814,15 @@
             {
               k = safe_calloc (1, sizeof *k);
               k->kobj = key;
+              gpgme_key_ref (k->kobj);
               k->idx = idx;
               k->uid = uid->uid;
               k->flags = flags;
+              k->validity = uid->validity;
               *kend = k;
               kend = &k->next;
             }
+          gpgme_key_unref (key);
         }
       if (gpg_err_code (err) != GPG_ERR_EOF)
         mutt_error (_("gpgme_op_keylist_next failed: %s"), gpgme_strerror 
(err));
@@ -3927,23 +3998,11 @@
               char buff[LONG_STRING];
               
               if (key_table[menu->current]->flags & KEYFLAG_CANTUSE)
-                s = N_("ID is expired/disabled/revoked.");
+                warn_s = N_("ID is expired/disabled/revoked.");
               else 
                 {
-                 gpgme_validity_t val = GPGME_VALIDITY_UNKNOWN;
-                 gpgme_user_id_t uid = NULL;
-                 unsigned int j = 0;
-
                   warn_s = "??";
-
-                 uid = key_table[menu->current]->kobj->uids;
-                 for (j = 0; (j < key_table[menu->current]->idx) && uid;
-                       j++, uid = uid->next)
-                    ;
-                 if (uid)
-                   val = uid->validity;
-
-                  switch (val)
+                  switch (key_table[menu->current]->validity)
                     {
                     case GPGME_VALIDITY_UNKNOWN:   
                     case GPGME_VALIDITY_UNDEFINED: 
@@ -3959,18 +4018,18 @@
                     case GPGME_VALIDITY_ULTIMATE:  
                       break;
                     }
-
-                  snprintf (buff, sizeof (buff),
-                            _("%s Do you really want to use the key?"),
-                            _(warn_s));
-                 
-                  if (mutt_yesorno (buff, 0) != 1)
-                    {
-                      mutt_clear_error ();
-                      break;
-                    }
-                  *forced_valid = 1;
                 }
+
+              snprintf (buff, sizeof (buff),
+                        _("%s Do you really want to use the key?"),
+                        _(warn_s));
+              
+              if (mutt_yesorno (buff, 0) != 1)
+                {
+                  mutt_clear_error ();
+                  break;
+                }
+              *forced_valid = 1;
             }  
 
           k = crypt_copy_key (key_table[menu->current]);
@@ -4129,33 +4188,35 @@
   crypt_key_t *matches = NULL;
   crypt_key_t **matches_endp = &matches;
   crypt_key_t *k;
+  const char *ps, *pl, *pfcopy, *phint;
 
   mutt_message (_("Looking for keys matching \"%s\"..."), p);
 
   *forced_valid = 0;
 
-  hints = crypt_add_string_to_hints (hints, p);
+  pfcopy = crypt_get_fingerprint_or_id (p, &phint, &pl, &ps);
+  hints = crypt_add_string_to_hints (hints, phint);
   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN));
   mutt_free_list (&hints);
 
   if (!keys)
+  {
+    FREE (&pfcopy);
     return NULL;
-  
+  }
+
   for (k = keys; k; k = k->next)
     {
       if (abilities && !(k->flags & abilities))
         continue;
 
       dprint (5, (debugfile, "crypt_getkeybystr: matching \"%s\" against "
-                  "key %s, \"%s\": ",  p, crypt_keyid (k), k->uid));
+                  "key %s, \"%s\": ",  p, crypt_long_keyid (k), k->uid));
 
       if (!*p
-          || !mutt_strcasecmp (p, crypt_keyid (k))
-          || (!mutt_strncasecmp (p, "0x", 2)
-              && !mutt_strcasecmp (p + 2, crypt_keyid (k)))
-          || (option (OPTPGPLONGIDS)
-              && !mutt_strncasecmp (p, "0x", 2) 
-              && !mutt_strcasecmp (p + 2, crypt_keyid (k) + 8))
+          || (pfcopy && mutt_strcasecmp (pfcopy, crypt_fpr (k)) == 0)
+          || (pl && mutt_strcasecmp (pl, crypt_long_keyid (k)) == 0)
+          || (ps && mutt_strcasecmp (ps, crypt_short_keyid (k)) == 0)
           || mutt_stristr (k->uid, p))
         {
           crypt_key_t *tmp;
@@ -4167,6 +4228,7 @@
         }
     }
   
+  FREE (&pfcopy);
   crypt_free_key (&keys);
   
   if (matches)
@@ -4383,6 +4445,65 @@
   return find_keys (to, cc, bcc, APPLICATION_SMIME);
 }
 
+#ifdef HAVE_GPGME_OP_EXPORT_KEYS
+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;
+}
+#endif
+
 /*
  * Implementation of `init'.
  */
@@ -4405,27 +4526,36 @@
   }
 }
 
-/* Initialization.  */
-static void init_gpgme (void)
+static void init_pgp (void)
 {
-  /* Make sure that gpg-agent is running.  */
-  if (! getenv ("GPG_AGENT_INFO"))
-    {
-      mutt_error (_("\nUsing GPGME backend, although no gpg-agent is 
running"));
-      if (mutt_any_key_to_continue (NULL) == -1)
-       mutt_exit(1);
-    }
+  if (gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP) != GPG_ERR_NO_ERROR)
+  {
+    mutt_error (_("GPGME: OpenPGP protocol not available"));
+    if (mutt_any_key_to_continue (NULL) == -1)
+      mutt_exit(1);
+  }
+}
+
+static void init_smime (void)
+{
+  if (gpgme_engine_check_version (GPGME_PROTOCOL_CMS) != GPG_ERR_NO_ERROR)
+  {
+    mutt_error (_("GPGME: CMS protocol not available"));
+    if (mutt_any_key_to_continue (NULL) == -1)
+      mutt_exit(1);
+  }
 }
 
 void pgp_gpgme_init (void)
 {
-  init_common();
-  init_gpgme ();
+  init_common ();
+  init_pgp ();
 }
 
 void smime_gpgme_init (void)
 {
-  init_common();
+  init_common ();
+  init_smime ();
 }
 
 static int gpgme_send_menu (HEADER *msg, int *redraw, int is_smime)
@@ -4595,7 +4725,7 @@
 
   if (signature_key)
   {
-    gpgme_key_release (signature_key);
+    gpgme_key_unref (signature_key);
     signature_key = NULL;

Reply via email to