auto_mode is used by crypt_opportunistic_encrypt to determine whether
there are valid keys for all recipients of a message, without prompting
the user.

The patch wraps around prompts, and makes getkeybyaddr methods return a
valid key without prompting.

crypt_getkeybyaddr() seems to be a bit different from
pgp_getkeybyaddr().  In my testing, the gpgme method was NOT finding
a single key in cases where the classic pgp method was.  To make
opportunistic_encrypt the most useful, I made both these methods return
a key if they found ANY valid keys.

The patch also enables a call to crypt_is_numerical_keyid() in
find_keys(), so that crypt-hooks can actually be checked without
prompting when gpgme is enabled.  (The addition was patterned off of the
pgp_findKeys() function).


 crypt-gpgme.c |  105 +++++++++++++++++++++++++++++++++++----------------------
 pgp.c         |   42 +++++++++++++---------
 pgp.h         |    2 +-
 pgpkey.c      |   24 ++++++++++--
 smime.c       |    6 ++-
 5 files changed, 114 insertions(+), 65 deletions(-)


# HG changeset patch
# User Kevin McCarthy <ke...@8t8.us>
# Date 1363403034 25200
# Branch HEAD
# Node ID 1e48ca012c852879e46b94bd56d463e3db838831
# Parent  7082744ee06bb5388cb1de22147b20b210d06efc
Implement auto_mode in the find_keys methods.

auto_mode is used by crypt_opportunistic_encrypt to determine whether
there are valid keys for all recipients of a message, without prompting
the user.

The patch wraps around prompts, and makes getkeybyaddr methods return a
valid key without prompting.

crypt_getkeybyaddr() seems to be a bit different from
pgp_getkeybyaddr().  In my testing, the gpgme method was NOT finding
a single key in cases where the classic pgp method was.  To make
opportunistic_encrypt the most useful, I made both these methods return
a key if they found ANY valid keys.

The patch also enables a call to crypt_is_numerical_keyid() in
find_keys(), so that crypt-hooks can actually be checked without
prompting when gpgme is enabled.  (The addition was patterned off of the
pgp_findKeys() function).

diff --git a/crypt-gpgme.c b/crypt-gpgme.c
--- a/crypt-gpgme.c
+++ b/crypt-gpgme.c
@@ -3954,17 +3954,18 @@
   FREE (&key_table);
 
   set_option (OPTNEEDREDRAW);
   
   return k;
 }
 
 static crypt_key_t *crypt_getkeybyaddr (ADDRESS * a, short abilities,
-					unsigned int app, int *forced_valid)
+					unsigned int app, int *forced_valid,
+					int auto_mode)
 {
   ADDRESS *r, *p;
   LIST *hints = NULL;
 
   int weak    = 0;
   int invalid = 0;
   int multi   = 0;
   int this_key_has_strong;
@@ -3979,17 +3980,18 @@
   
   *forced_valid = 0;
 
   if (a && a->mailbox)
     hints = crypt_add_string_to_hints (hints, a->mailbox);
   if (a && a->personal)
     hints = crypt_add_string_to_hints (hints, a->personal);
 
-  mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
+  if (! auto_mode )
+    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
   keys = get_candidates (hints, app, (abilities & KEYFLAG_CANSIGN) );
 
   mutt_free_list (&hints);
   
   if (!keys)
     return NULL;
   
   dprint (5, (debugfile, "crypt_getkeybyaddr: looking for %s <%s>.",
@@ -4054,17 +4056,24 @@
 	  the_valid_key = tmp;
         }
     }
   
   crypt_free_key (&keys);
   
   if (matches)
     {
-      if (the_valid_key && !multi && !weak 
+      if (auto_mode)
+        {
+          if (the_valid_key)
+            k = crypt_copy_key (the_valid_key);
+          else
+            k = NULL;
+        }
+      else if (the_valid_key && !multi && !weak 
           && !(invalid && option (OPTPGPSHOWUNUSABLE)))
         {	
           /* 
            * There was precisely one strong match on a valid ID, there
            * were no valid keys with weak matches, and we aren't
            * interested in seeing invalid keys.
            * 
            * Proceed without asking the user.
@@ -4082,17 +4091,17 @@
     }
   else 
     k = NULL;
   
   return k;
 }
 
 
-static crypt_key_t *crypt_getkeybystr (char *p, short abilities,
+static crypt_key_t *crypt_getkeybystr (const char *p, short abilities,
 				       unsigned int app, int *forced_valid)
 {
   LIST *hints = NULL;
   crypt_key_t *keys;
   crypt_key_t *matches = NULL;
   crypt_key_t **matches_endp = &matches;
   crypt_key_t *k;
 
@@ -4209,52 +4218,64 @@
 }
 
 /* This routine attempts to find the keyids of the recipients of a
    message.  It returns NULL if any of the keys can not be found.
    If auto_mode is true, only keys that can be determined without
    prompting will be used.  */
 static char *find_keys (ADDRESS *adrlist, unsigned int app, int auto_mode)
 {
-  char *keyID, *keylist = NULL, *t;
+  const char *keyID = NULL;
+  char *keylist = NULL, *t;
   size_t keylist_size = 0;
   size_t keylist_used = 0;
   ADDRESS *addr = NULL;
   ADDRESS *p, *q;
-  crypt_key_t *k_info, *key;
+  crypt_key_t *k_info;
   const char *fqdn = mutt_fqdn (1);
 
 #if 0
   *r_application = APPLICATION_PGP|APPLICATION_SMIME;
 #endif
 
   for (p = adrlist; p ; p = p->next)
     {
       char buf[LONG_STRING];
       int forced_valid = 0;
       
       q = p;
       k_info = NULL;
       
       if ((keyID = mutt_crypt_hook (p)) != NULL)
         {
-          int r;
-          snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
-                    keyID, p->mailbox);
-          if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
+          int r = M_NO;
+          if (! auto_mode)
             {
+              snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"),
+                        keyID, p->mailbox);
+              r = mutt_yesorno (buf, M_YES);
+            }
+          if (auto_mode || (r == M_YES))
+            {
+              if (crypt_is_numerical_keyid (keyID))
+                {
+                  if (strncmp (keyID, "0x", 2) == 0)
+                    keyID += 2;
+                  goto bypass_selection;                /* you don't see this. */
+                }
+
               /* check for e-mail address */
               if ((t = strchr (keyID, '@')) && 
                   (addr = rfc822_parse_adrlist (NULL, keyID)))
                 {
                   if (fqdn)
                     rfc822_qualify (addr, fqdn);
                   q = addr;
                 }
-              else
+              else if (! auto_mode)
 		{
 #if 0		  
 		  k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, 
 					      *r_application, &forced_valid);
 #else
 		  k_info = crypt_getkeybystr (keyID, KEYFLAG_CANENCRYPT, 
 					      app, &forced_valid);
 #endif
@@ -4263,58 +4284,62 @@
           else if (r == -1)
             {
               FREE (&keylist);
               rfc822_free_address (&addr);
               return NULL;
             }
         }
 
-      if (k_info == NULL
-          && (k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
-                                           app, &forced_valid)) == NULL)
+      if (k_info == NULL)
+        {
+          k_info = crypt_getkeybyaddr (q, KEYFLAG_CANENCRYPT,
+                                       app, &forced_valid, auto_mode);
+        }
+
+      if ((k_info == NULL) && (! auto_mode))
         {
           snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
           
-          if ((key = crypt_ask_for_key (buf, q->mailbox,
-                                        KEYFLAG_CANENCRYPT,
+          k_info = crypt_ask_for_key (buf, q->mailbox,
+                                      KEYFLAG_CANENCRYPT,
 #if 0
-                                        *r_application,
+                                      *r_application,
 #else
-					app,
+                                      app,
 #endif
-					&forced_valid)) == NULL)
-            {
-              FREE (&keylist);
-              rfc822_free_address (&addr);
-              return NULL;
-            }
+                                      &forced_valid);
         }
-      else
-        key = k_info;
-
-      {
-        const char *s = crypt_fpr (key);
+
+      if (k_info == NULL)
+        {
+          FREE (&keylist);
+          rfc822_free_address (&addr);
+          return NULL;
+        }
+
+
+      keyID = crypt_fpr (k_info);
 
 #if 0
-        if (key->flags & KEYFLAG_ISX509)
-          *r_application &= ~APPLICATION_PGP;
-        if (!(key->flags & KEYFLAG_ISX509))
-          *r_application &= ~APPLICATION_SMIME;
+      if (k_info->flags & KEYFLAG_ISX509)
+        *r_application &= ~APPLICATION_PGP;
+      if (!(k_info->flags & KEYFLAG_ISX509))
+        *r_application &= ~APPLICATION_SMIME;
 #endif
       
-        keylist_size += mutt_strlen (s) + 4 + 1;
-        safe_realloc (&keylist, keylist_size);
-        sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
-                 keylist_used ? " " : "",  s,
-                 forced_valid? "!":"");
-      }
+  bypass_selection:
+      keylist_size += mutt_strlen (keyID) + 4 + 1;
+      safe_realloc (&keylist, keylist_size);
+      sprintf (keylist + keylist_used, "%s0x%s%s", /* __SPRINTF_CHECKED__ */
+               keylist_used ? " " : "",  keyID,
+               forced_valid? "!":"");
       keylist_used = mutt_strlen (keylist);
         
-      crypt_free_key (&key);
+      crypt_free_key (&k_info);
       rfc822_free_address (&addr);
     }
   return (keylist);
 }
 
 char *pgp_gpgme_findkeys (ADDRESS *adrlist, int auto_mode)
 {
   return find_keys (adrlist, APPLICATION_PGP, auto_mode);
diff --git a/pgp.c b/pgp.c
--- a/pgp.c
+++ b/pgp.c
@@ -1139,86 +1139,94 @@
  */
 char *pgp_findKeys (ADDRESS *adrlist, int auto_mode)
 {
   char *keyID, *keylist = NULL;
   size_t keylist_size = 0;
   size_t keylist_used = 0;
   ADDRESS *addr = NULL;
   ADDRESS *p, *q;
-  pgp_key_t k_info = NULL, key = NULL;
+  pgp_key_t k_info = NULL;
 
   const char *fqdn = mutt_fqdn (1);
 
   for (p = adrlist; p ; p = p->next)
   {
     char buf[LONG_STRING];
 
     q = p;
     k_info = NULL;
 
     if ((keyID = mutt_crypt_hook (p)) != NULL)
     {
-      int r;
-      snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
-      if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
+      int r = M_NO;
+      if (! auto_mode)
+      {
+        snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
+        r = mutt_yesorno (buf, M_YES);
+      }
+      if (auto_mode || (r == M_YES))
       {
 	if (crypt_is_numerical_keyid (keyID))
 	{
 	  if (strncmp (keyID, "0x", 2) == 0)
 	    keyID += 2;
 	  goto bypass_selection;		/* you don't see this. */
 	}
 	
 	/* check for e-mail address */
 	if (strchr (keyID, '@') && 
 	    (addr = rfc822_parse_adrlist (NULL, keyID)))
 	{
 	  if (fqdn) rfc822_qualify (addr, fqdn);
 	  q = addr;
 	}
-	else
+	else if (! auto_mode)
+	{
 	  k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
+	}
       }
       else if (r == -1)
       {
 	FREE (&keylist);
 	rfc822_free_address (&addr);
 	return NULL;
       }
     }
 
     if (k_info == NULL)
+    {
       pgp_invoke_getkeys (q);
+      k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING, auto_mode);
+    }
 
-    if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
+    if ((k_info == NULL) && (! auto_mode))
     {
       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
+      k_info = pgp_ask_for_key (buf, q->mailbox,
+                             KEYFLAG_CANENCRYPT, PGP_PUBRING);
+    }
 
-      if ((key = pgp_ask_for_key (buf, q->mailbox,
-				  KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
-      {
-	FREE (&keylist);
-	rfc822_free_address (&addr);
-	return NULL;
-      }
+    if (k_info == NULL)
+    {
+      FREE (&keylist);
+      rfc822_free_address (&addr);
+      return NULL;
     }
-    else
-      key = k_info;
 
-    keyID = pgp_keyid (key);
+    keyID = pgp_keyid (k_info);
     
   bypass_selection:
     keylist_size += mutt_strlen (keyID) + 4;
     safe_realloc (&keylist, keylist_size);
     sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",	/* __SPRINTF_CHECKED__ */
 	     keyID);
     keylist_used = mutt_strlen (keylist);
 
-    pgp_free_key (&key);
+    pgp_free_key (&k_info);
     rfc822_free_address (&addr);
 
   }
   return (keylist);
 }
 
 /* Warning: "a" is no longer freed in this routine, you need
  * to free it later.  This is necessary for $fcc_attach. */
diff --git a/pgp.h b/pgp.h
--- a/pgp.h
+++ b/pgp.h
@@ -41,17 +41,17 @@
 
 int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **);
 
 /* int pgp_string_matches_hint (const char *s, LIST * hints); */
 
 /* pgp_key_t gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *); */
 pgp_key_t pgp_ask_for_key (char *, char *, short, pgp_ring_t);
 pgp_key_t pgp_get_candidates (pgp_ring_t, LIST *);
-pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t);
+pgp_key_t pgp_getkeybyaddr (ADDRESS *, short, pgp_ring_t, int);
 pgp_key_t pgp_getkeybystr (char *, short, pgp_ring_t);
 
 char *pgp_findKeys (ADDRESS *adrlist, int auto_mode);
 
 void pgp_forget_passphrase (void);
 int pgp_application_pgp_handler (BODY *, STATE *);
 int pgp_encrypted_handler (BODY *, STATE *);
 void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top);
diff --git a/pgpkey.c b/pgpkey.c
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -807,17 +807,18 @@
 {
   for (; p; p = p->next)
     if (!p->next)
       return &p->next;
 
   return NULL;
 }
 
-pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
+pgp_key_t pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring,
+                            int auto_mode)
 {
   ADDRESS *r, *p;
   LIST *hints = NULL;
 
   int multi   = 0;
   int match;
 
   pgp_key_t keys, k, kn;
@@ -826,17 +827,18 @@
   pgp_key_t *last = &matches;
   pgp_uid_t *q;
 
   if (a && a->mailbox)
     hints = pgp_add_string_to_hints (hints, a->mailbox);
   if (a && a->personal)
     hints = pgp_add_string_to_hints (hints, a->personal);
 
-  mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
+  if (! auto_mode )
+    mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
   keys = pgp_get_candidates (keyring, hints);
 
   mutt_free_list (&hints);
 
   if (!keys)
     return NULL;
 
   dprint (5, (debugfile, "pgp_getkeybyaddr: looking for %s <%s>.",
@@ -890,37 +892,49 @@
       last   = pgp_get_lastp (k);
     }
   }
 
   pgp_free_key (&keys);
 
   if (matches)
   {
-    if (the_valid_key && !multi)
+    if (auto_mode)
+    {
+      if (the_valid_key)
+      {
+        pgp_remove_key (&matches, the_valid_key);
+        k = the_valid_key;
+      }
+      else
+      {
+        k = NULL;
+      }
+    }
+    else if (the_valid_key && !multi)
     {
       /*
        * There was precisely one strong match on a valid ID.
        * 
        * Proceed without asking the user.
        */
       pgp_remove_key (&matches, the_valid_key);
-      pgp_free_key (&matches);
       k = the_valid_key;
     }
     else 
     {
       /* 
        * Else: Ask the user.
        */
       if ((k = pgp_select_key (matches, a, NULL)))
 	pgp_remove_key (&matches, k);
-      pgp_free_key (&matches);
     }
 
+    pgp_free_key (&matches);
+
     return k;
   }
 
   return NULL;
 }
 
 pgp_key_t pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
 {
diff --git a/smime.c b/smime.c
--- a/smime.c
+++ b/smime.c
@@ -741,26 +741,28 @@
   ADDRESS *p, *q;
 
   for (p = adrlist; p ; p = p->next)
   {
     char buf[LONG_STRING];
 
     q = p;
 
-    if ((keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1)) == NULL)
+    keyID = smime_get_field_from_db (q->mailbox, NULL, 1, 1);
+    if ((keyID == NULL) && (! auto_mode))
     {
       snprintf(buf, sizeof(buf),
 	       _("Enter keyID for %s: "),
 	       q->mailbox);
       keyID = smime_ask_for_key(buf, q->mailbox, 1);
     }
     if(!keyID)
     {
-      mutt_message (_("No (valid) certificate found for %s."), q->mailbox);
+      if (! auto_mode)
+        mutt_message (_("No (valid) certificate found for %s."), q->mailbox);
       FREE (&keylist);
       return NULL;
     }
     
     keylist_size += mutt_strlen (keyID) + 2;
     safe_realloc (&keylist, keylist_size);
     sprintf (keylist + keylist_used, "%s\n", keyID);	/* __SPRINTF_CHECKED__ */
     keylist_used = mutt_strlen (keylist);

Reply via email to