--- PATCHES	Wed Mar 19 22:33:37 2003
+++ PATCHES	Thu Mar 20 21:38:55 2003
@@ -0,0 +1,3 @@
+patch-1.5.4.dw.confirm-crypt-hook.1
+patch-1.5.4.dw.multiple-crypt-hook.2
+patch-1.5.4.dw.crypt-autoselectkey.1
--- doc/manual.sgml.head	Tue Mar  4 08:49:49 2003
+++ doc/manual.sgml.head	Thu Mar 20 21:38:47 2003
@@ -1422,7 +1422,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.
 
 The meaning of "key id" is to be taken broadly in this context:  You
 can either put a numerical key ID here, an e-mail address, or even
--- doc/muttrc.man.head	Sun Dec 22 20:50:22 2002
+++ doc/muttrc.man.head	Thu Mar 20 21:38:47 2003
@@ -286,7 +286,10 @@
 specify the ID of the public key to be used when encrypting messages
 to a certain recipient.  The meaning of "key ID" is to be taken
 broadly: This can be a different e-mail address, a numerical key ID,
-or even just an arbitrary search string.
+or even just an arbitrary search string.  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.
 .TP
 \fBpush\fP \fIstring\fP
 This command adds the named \fIstring\fP to the keyboard buffer.
--- hook.c	Tue Jan 21 13:25:21 2003
+++ hook.c	Thu Mar 20 21:38:47 2003
@@ -117,7 +117,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
@@ -443,9 +447,25 @@
   return _mutt_string_hook (chs, M_ICONVHOOK);
 }
 
-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);
 }
 
 #ifdef USE_SOCKET
--- init.h	Tue Mar  4 10:28:12 2003
+++ init.h	Thu Mar 20 21:38:55 2003
@@ -1192,6 +1192,16 @@
   ** when you are at the end of a message and invoke the \fInext-page\fP
   ** function.
   */
+  
+
+  { "pgp_autoselectkey",	DT_SYN,  R_NONE, UL "crypt_autoselectkey", 0 },
+  { "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.
+  */
   { "pgp_autosign", 	DT_SYN,  R_NONE, UL "crypt_autosign", 0 },
   { "crypt_autosign",	DT_BOOL, R_NONE, OPTCRYPTAUTOSIGN, 0 },
   /*
@@ -1216,6 +1226,15 @@
   ** then OpenSSL is used instead to create S/MIME messages and
   ** settings can be overridden by use of the \fIsmime-menu\fP.
   ** (Crypto only)
+  */
+  { "pgp_confirmhook",		DT_SYN, R_NONE, UL "crypt_confirmhook", 1 },
+  { "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.
   */
   { "pgp_ignore_subkeys", DT_BOOL, R_NONE, OPTPGPIGNORESUB, 1},
   /*
--- mutt.h	Tue Mar  4 08:49:48 2003
+++ mutt.h	Thu Mar 20 21:38:55 2003
@@ -425,6 +425,7 @@
 
   /* PGP options */
   
+  OPTCRYPTAUTOSELECT,
   OPTCRYPTAUTOSIGN,
   OPTCRYPTAUTOENCRYPT,
   OPTCRYPTREPLYENCRYPT,
@@ -434,6 +435,7 @@
   OPTSMIMEISDEFAULT,
   OPTASKCERTLABEL,
   OPTSDEFAULTDECRYPTKEY,
+  OPTCRYPTCONFIRMHOOK,
   OPTPGPIGNORESUB,
   OPTPGPLONGIDS,
   OPTPGPAUTOTRAD,
--- pgp.c	Tue Feb 25 22:28:54 2003
+++ pgp.c	Thu Mar 20 21:40:39 2003
@@ -1014,6 +1014,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;
@@ -1047,70 +1049,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);
--- pgpkey.c	Tue Jan 21 13:25:21 2003
+++ pgpkey.c	Thu Mar 20 21:38:32 2003
@@ -435,8 +435,13 @@
   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)
+				  ADDRESS * p, const char *s)
 {
   int keymax;
   pgp_uid_t **KeyTable;
@@ -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	Thu Mar  6 22:24:46 2003
+++ protos.h	Thu Mar 20 21:38:47 2003
@@ -129,7 +129,7 @@
 char *mutt_get_body_charset (char *, size_t, BODY *);
 const char *mutt_get_name (ADDRESS *);
 char *mutt_get_parameter (const char *, PARAMETER *);
-char *mutt_crypt_hook (ADDRESS *);
+LIST *mutt_crypt_hook (ADDRESS *);
 char *mutt_make_date (char *, size_t);
 
 const char *mutt_make_version (void);
