Base: http://home.woolridge.ca/mutt/patches/patch-1.5.3.dw.confirm-crypt-hook.1
      http://home.woolridge.ca/mutt/patches/patch-1.5.3.dw.multiple-crypt-hook.1
      http://home.woolridge.ca/mutt/patches/patch-1.5.3.dw.crypt-autoselectkey.1

--- PATCHES	Tue Dec 17 10:47:20 2002
+++ PATCHES	Fri Jan 24 11:27:21 2003
@@ -0,0 +1,3 @@
+patch-1.5.3.dw.crypt-autoselectkey.1
+patch-1.5.3.dw.confirm-crypt-hook.1
+patch-1.5.3.dw.multiple-crypt-hook.1
--- doc/manual.sgml.head	Tue Dec 17 10:36:42 2002
+++ doc/manual.sgml.head	Fri Jan 24 11:26:59 2003
@@ -1423,7 +1423,9 @@
 or because, for some reasons, you need to override the key Mutt would
 normally use.  The crypt-hook command provides a method by which you can
 specify the ID of the public key to be used when encrypting messages to
-a certain recipient.
+a certain recipient.  You may use multiple pgp-hook's with the same
+pattern; multiple matching pgp-hook's result in the use of multiple
+keyids for recipient.
 
 <sect1>Adding key sequences to the keyboard buffer<label id="push">
 <p>
--- doc/muttrc.man.head	Mon Sep  9 21:28:35 2002
+++ doc/muttrc.man.head	Fri Jan 24 11:26:59 2003
@@ -287 +287,3 @@
-to a certain recipient.
+to a certain recipient.  You may use multiple \fBpgp-hook\fPs with the
+same \fIpattern\fP; multiple matching \fBpgp-hook\fPs result in the use
+of multiple \fIkey-id\fPs for recipient.
--- hook.c	Wed Dec 11 16:13:11 2002
+++ hook.c	Fri Jan 24 11:26:59 2003
@@ -118,7 +118,11 @@
 	ptr->rx.not == not &&
 	!mutt_strcmp (pattern.data, ptr->rx.pattern))
     {
+#ifdef M_CRYPTHOOK
+      if (data & (M_FOLDERHOOK | M_SENDHOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK | M_CRYPTHOOK))
+#else
       if (data & (M_FOLDERHOOK | M_SENDHOOK | M_MESSAGEHOOK | M_ACCOUNTHOOK | M_REPLYHOOK))
+#endif
       {
 	/* these hooks allow multiple commands with the same
 	 * pattern, so if we've already seen this pattern/command pair, just
@@ -445,9 +449,25 @@
 }
 
 #if defined(HAVE_PGP) || defined(HAVE_SMIME)
-char *mutt_crypt_hook (ADDRESS *adr)
+LIST *mutt_crypt_hook (ADDRESS *adr)
 {
-  return _mutt_string_hook (adr->mailbox, M_CRYPTHOOK);
+  HOOK *hook;
+  LIST *key_list = NULL;
+
+  if (!adr && !adr->mailbox)
+    return (NULL);
+
+  for (hook = Hooks; hook; hook = hook->next)
+  {
+    if (!hook->command)
+      continue;
+    if (!(hook->type & M_CRYPTHOOK))
+      continue;
+
+    if ((regexec (hook->rx.rx, adr->mailbox, 0, NULL, 0) == 0) ^ hook->rx.not)
+      key_list = mutt_add_list (key_list, hook->command);
+  }
+  return (key_list);
 }
 #endif /* HAVE_PGP */
 
--- init.h	Mon Dec  9 19:09:21 2002
+++ init.h	Fri Jan 24 11:27:21 2003
@@ -1195,6 +1195,16 @@
 
 #if defined(HAVE_PGP) || defined(HAVE_SMIME)
 # ifdef HAVE_PGP
+  { "pgp_autoselectkey",	DT_SYN,  R_NONE, UL "crypt_autoselectkey", 0 },
+# endif
+  { "crypt_autoselectkey",	DT_BOOL, R_NONE, OPTCRYPTAUTOSELECT, 0 },
+  /*
+  ** .pp
+  ** If set, then a list of keys is not presented for selection when only
+  ** one matching key is available.  This may be useful in conjunction with
+  ** the \fIcrypt-hook\fP command.
+  */
+# ifdef HAVE_PGP
   { "pgp_autosign", 	DT_SYN,  R_NONE, UL "crypt_autosign", 0 },
 # endif  
   { "crypt_autosign",	DT_BOOL, R_NONE, OPTCRYPTAUTOSIGN, 0 },
@@ -1220,6 +1230,17 @@
   ** requested as well.  IF ``$$smime_is_default'' is set, then
   ** OpenSSL is used instead to create S/MIME messages and settings can
   ** be overridden by use of the \fIsmime-menu\fP.
+  */
+# ifdef HAVE_PGP
+  { "pgp_confirmhook",		DT_SYN, R_NONE, UL "crypt_confirmhook", 1 },
+# endif
+  { "crypt_confirmhook",	DT_BOOL, R_NONE, OPTCRYPTCONFIRMHOOK, 1 },
+  /*
+  ** .pp
+  ** If set, then you will be prompted for confirmation of keys when using
+  ** the \fIcrypt-hook\fP command.  If unset, no such confirmation prompt will
+  ** be presented.  This is generally considered unsafe, especially where
+  ** typos are concerned.
   */
 #ifdef HAVE_PGP
   { "pgp_ignore_subkeys", DT_BOOL, R_NONE, OPTPGPIGNORESUB, 1},
--- mutt.h	Fri Dec  6 17:37:21 2002
+++ mutt.h	Fri Jan 24 11:27:21 2003
@@ -431,6 +431,7 @@
   /* PGP options */
   
 #if defined(HAVE_PGP) || defined(HAVE_SMIME)
+  OPTCRYPTAUTOSELECT,
   OPTCRYPTAUTOSIGN,
   OPTCRYPTAUTOENCRYPT,
   OPTCRYPTREPLYENCRYPT,
@@ -442,6 +443,7 @@
   OPTASKCERTLABEL,
   OPTSDEFAULTDECRYPTKEY,
 #endif
+  OPTCRYPTCONFIRMHOOK,
 #ifdef HAVE_PGP
   OPTPGPIGNORESUB,
   OPTPGPLONGIDS,
--- pgp.c	Mon Dec 16 16:27:26 2002
+++ pgp.c	Fri Jan 24 11:27:04 2003
@@ -1051,6 +1051,8 @@
   char *keyID, *keylist = NULL, *t;
   size_t keylist_size = 0;
   size_t keylist_used = 0;
+  LIST *hook_list = NULL;
+  LIST *hook = NULL;
   ADDRESS *tmp = NULL, *addr = NULL;
   ADDRESS **last = &tmp;
   ADDRESS *p, *q;
@@ -1084,70 +1086,97 @@
     char buf[LONG_STRING];
 
     q = p;
-    k_info = NULL;
 
-    if ((keyID = mutt_crypt_hook (p)) != NULL)
+    /*
+     * grab the list of matching hooks (matching on recipient address)
+     * process each entry singly so that auto key selection still works
+     */
+    hook_list = mutt_crypt_hook (p);
+    hook = hook_list;
+    while (1)
     {
       int r;
-      snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
-      if ((r = mutt_yesorno (buf, M_YES)) == M_YES)
+
+      k_info = NULL;
+      key = NULL;
+
+      if (hook)
       {
-	if (is_numerical_keyid (keyID))
+	keyID = (char *)hook->data;
+	snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
+      if (!option(OPTCRYPTCONFIRMHOOK) || (r = mutt_yesorno (buf, M_YES)) == M_YES)
 	{
-	  if (strncmp (keyID, "0x", 2) == 0)
-	    keyID += 2;
-	  goto bypass_selection;		/* you don't see this. */
+	  if (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
+	    k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
 	}
-	
-	/* check for e-mail address */
-	if ((t = strchr (keyID, '@')) && 
-	    (addr = rfc822_parse_adrlist (NULL, keyID)))
+	else if (r == -1)
 	{
-	  if (fqdn) rfc822_qualify (addr, fqdn);
-	  q = addr;
+	  /*
+	   * yes, this implies that if one key fails they all do
+	   */
+	  FREE (&keylist);
+	  rfc822_free_address (&tmp);
+	  rfc822_free_address (&addr);
+	  mutt_free_list (&hook_list);
+	  return NULL;
 	}
-	else
-	  k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
-      }
-      else if (r == -1)
-      {
-	FREE (&keylist);
-	rfc822_free_address (&tmp);
-	rfc822_free_address (&addr);
-	return NULL;
       }
-    }
-
-    if (k_info == NULL)
-      pgp_invoke_getkeys (q);
 
-    if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
-    {
-      snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
+      if (k_info == NULL)
+	pgp_invoke_getkeys (q);
 
-      if ((key = pgp_ask_for_key (buf, q->mailbox,
-				  KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
+      if (k_info == NULL && (k_info = pgp_getkeybyaddr (q, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
       {
-	FREE (&keylist);
-	rfc822_free_address (&tmp);
-	rfc822_free_address (&addr);
-	return NULL;
+	snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), q->mailbox);
+
+	if ((key = pgp_ask_for_key (buf, q->mailbox,
+				    KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
+	{
+	  FREE (&keylist);
+	  rfc822_free_address (&tmp);
+	  rfc822_free_address (&addr);
+	  mutt_free_list (&hook_list);
+	  return NULL;
+	}
       }
-    }
-    else
-      key = k_info;
+      else
+	key = k_info;
 
-    keyID = pgp_keyid (key);
+      keyID = pgp_keyid (key);
     
   bypass_selection:
-    keylist_size += mutt_strlen (keyID) + 4;
-    safe_realloc ((void **)&keylist, keylist_size);
-    sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",	/* __SPRINTF_CHECKED__ */
-	     keyID);
-    keylist_used = mutt_strlen (keylist);
+      keylist_size += mutt_strlen (keyID) + 4;
+      safe_realloc ((void **)&keylist, keylist_size);
+      sprintf (keylist + keylist_used, "%s0x%s", keylist_used ? " " : "",	/* __SPRINTF_CHECKED__ */
+	       keyID);
+      keylist_used = mutt_strlen (keylist);
+
+      pgp_free_key (&key);
+      rfc822_free_address (&addr);
+
+      if (!hook_list)
+	break;
+
+      hook = hook->next;
+      if (!hook)
+	break;
 
-    pgp_free_key (&key);
-    rfc822_free_address (&addr);
+    }
+    mutt_free_list (&hook_list);
 
   }
   rfc822_free_address (&tmp);
diff -ru work.orig/mutt-1.5.3/pgpkey.c work/mutt-1.5.3/pgpkey.c
--- pgpkey.c	Wed Dec 11 12:20:05 2002
+++ pgpkey.c	Fri Jan 24 11:27:21 2003
@@ -435,6 +435,11 @@
   return rv;
 }
 
+
+#define pgp_trusted_id(uid) (!option(OPTPGPCHECKTRUST) \
+			     || (pgp_id_is_valid((uid)) \
+				 && pgp_id_is_strong((uid))))
+
 static pgp_key_t *pgp_select_key (pgp_key_t *keys,
 				  ADDRESS * p, const char *s)
 {
@@ -450,6 +455,7 @@
   pgp_uid_t *a;
   int (*f) (const void *, const void *);
 
+  int keymatch = 0;		/* count matching keys */
   int unusable = 0;
 
   keymax = 0;
@@ -479,6 +485,7 @@
       
       KeyTable[i++] = a;
     }
+    keymatch++;
   }
 
   if (!i && unusable)
@@ -487,6 +494,21 @@
     mutt_sleep (1);
     return NULL;
   }
+  else if (keymatch == 1 && option(OPTCRYPTAUTOSELECT))
+  {
+    /*
+     * Only one matching key...see if there's an id with enough trust to auto-select
+     */
+    kp = KeyTable[0]->parent;
+    for (a = kp->address; a; a = a->next)
+    {
+      if (pgp_trusted_id(a))
+      {
+	safe_free ((void **) &KeyTable);
+	return (kp);
+      }
+    }
+  }
 
   switch (PgpSortKeys & SORT_MASK)
   {
@@ -597,9 +619,7 @@
 	  break;
 	}
       
-      if (option (OPTPGPCHECKTRUST) &&
-	  (!pgp_id_is_valid (KeyTable[menu->current])
-	   || !pgp_id_is_strong (KeyTable[menu->current])))
+      if (!pgp_trusted_id(KeyTable[menu->current]))
       {
 	char *s = "";
 	char buff[LONG_STRING];
--- protos.h	Wed Dec 11 23:31:25 2002
+++ protos.h	Fri Jan 24 11:26:59 2003
@@ -130,7 +130,7 @@
 char *mutt_get_name (ADDRESS *);
 char *mutt_get_parameter (const char *, PARAMETER *);
 #if defined(HAVE_PGP) || defined(HAVE_SMIME)
-char *mutt_crypt_hook (ADDRESS *);
+LIST *mutt_crypt_hook (ADDRESS *);
 #endif /* HAVE_PGP */
 char *mutt_make_date (char *, size_t);
 
