]> granicus.if.org Git - neomutt/commitdiff
Experimental: New PGP invocation interface. The invocations are done
authorThomas Roessler <roessler@does-not-exist.org>
Thu, 3 Jun 1999 07:27:43 +0000 (07:27 +0000)
committerThomas Roessler <roessler@does-not-exist.org>
Thu, 3 Jun 1999 07:27:43 +0000 (07:27 +0000)
through formats, so all this should fit more cleanly into mutt now.

18 files changed:
Makefile.am
compose.c
configure.in
contrib/gpg.rc [new file with mode: 0644]
contrib/pgp2.rc [new file with mode: 0644]
contrib/pgp5.rc [new file with mode: 0644]
gnupgparse.c
init.c
init.h
mutt.h
pgp.c
pgp.h
pgpewrap [new file with mode: 0755]
pgpinvoke.c
pgpkey.c
pgplib.c [new file with mode: 0644]
pgplib.h [new file with mode: 0644]
pgppubring.c

index e23670d7732abe348702e00b422644bdd2b082e1..a965e33941096d8bb7f8562bc6d9519ffd8c9f1e 100644 (file)
@@ -4,9 +4,9 @@
 ## Use aclocal -I m4; automake --foreign
 
 AUTOMAKE_OPTIONS = foreign
-EXTRA_PROGRAMS = mutt_dotlock
+EXTRA_PROGRAMS = mutt_dotlock pgpring
 
-bin_PROGRAMS = mutt @DOTLOCK_TARGET@
+bin_PROGRAMS = mutt @DOTLOCK_TARGET@ @PGPAUX_TARGET@
 mutt_SOURCES = addrbook.c alias.c attach.c browser.c buffy.c color.c \
        commands.c complete.c compose.c copy.c curs_lib.c curs_main.c date.c \
        edit.c enter.c flags.c init.c filter.c from.c getdomain.c \
@@ -23,12 +23,12 @@ DEFS=-DSHAREDIR=\"$(sharedir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \
        -DBINDIR=\"$(bindir)\" -DHAVE_CONFIG_H=1
 INCLUDES=-I. -I$(includedir)
 
-non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \
+non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \
        gnupgparse.c sha.h sha_locl.h \
        doc/language.txt doc/language50.txt OPS.PGP doc/PGP-Notes \
-       OPS.MIX remailer.c remailer.h
+       OPS.MIX remailer.c remailer.h pgpewrap
 
-EXTRA_mutt_SOURCES = pgp.c pgpinvoke.c pgpkey.c pgppubring.c sha1dgst.c \
+EXTRA_mutt_SOURCES = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \
        gnupgparse.c resize.c dotlock.c pop.c imap.c socket.c
        remailer.c remailer.h browser.h
 
@@ -40,7 +40,7 @@ EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h attach.h \
        reldate.h rfc1524.h rfc2047.h rfc822.h sha.h sha_locl.h \
        sort.h mime.types VERSION prepare _regex.h OPS.MIX      \
        README.SECURITY remailer.c remailer.h browser.h Muttrc.in \
-       lib.h extlib.c
+       lib.h extlib.c pgpewrap
 
 BUILT_SOURCES = mutt_dotlock.c keymap_defs.h
 
@@ -48,6 +48,10 @@ mutt_dotlock_SOURCES = mutt_dotlock.c
 mutt_dotlock_LDADD = @LIBOBJS@
 mutt_dotlock_DEPENDENCIES = @LIBOBJS@
 
+pgpring_SOURCES = pgppubring.c pgplib.c lib.c extlib.c sha1dgst.c
+pgpring_LDADD = @LIBOBJS@
+pgpring_DEPENDENCIES = @LIBOBJS@
+
 mutt_dotlock.c: dotlock.c
        cp $(srcdir)/dotlock.c mutt_dotlock.c
 
index dd7a2b9e43e121f5f5c268706bae8e5b03d5aad0..221f34933d442147e99d004174f4d44f99a4d7d2 100644 (file)
--- a/compose.c
+++ b/compose.c
@@ -132,8 +132,6 @@ static int pgp_send_menu (int bits, int *redraw)
   char input_signas[SHORT_STRING];
   char input_micalg[SHORT_STRING];
 
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_SIGN);
-
   switch (mutt_multi_choice (_("(e)ncrypt, (s)ign, sign (a)s, (b)oth, select (m)ic algorithm, or (f)orget it? "),
                             _("esabmf")))
   {
@@ -149,7 +147,7 @@ static int pgp_send_menu (int bits, int *redraw)
 
     unset_option(OPTPGPCHECKTRUST);
 
-    if (pgp && (p = pgp_ask_for_key (pgp, _("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING)))
+    if ((p = pgp_ask_for_key (_("Sign as: "), NULL, KEYFLAG_CANSIGN, PGP_PUBRING)))
     {
       snprintf (input_signas, sizeof (input_signas), "0x%s", pgp_keyid (p));
       safe_free((void **) &PgpSignAs);             PgpSignAs = safe_strdup (input_signas);
index 300ef9effd6f5af7061c4afc33789bc852844146..a4a14faa6c031614d60b5a744beb91fb5cd1a7ac 100644 (file)
@@ -72,10 +72,11 @@ else
        fi
 
        if test $PGP != no || test $PGPK != no || test $GPG != no ; then
-               MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgppubring.o sha1dgst.o gnupgparse.o"
+               PGPAUX_TARGET="pgpring pgpewrap"
+               MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS pgp.o pgpinvoke.o pgpkey.o pgplib.o gnupgparse.o"
                OPS="$OPS \$(srcdir)/OPS.PGP"
        fi
-       
+
        AC_ARG_WITH(mixmaster, [  --with-mixmaster[=PATH]       include Mixmaster support],
                [if test -x "$withval" ; then
                        MIXMASTER="$withval"
@@ -90,6 +91,8 @@ else
 fi
 AC_SUBST(OPS)
 
+AC_SUBST(PGPAUX_TARGET)
+
 AC_DEFINE_UNQUOTED(SUBVERSION, "$SUBVERSION")
 AC_SUBST(SUBVERSION)
 
diff --git a/contrib/gpg.rc b/contrib/gpg.rc
new file mode 100644 (file)
index 0000000..41799cf
--- /dev/null
@@ -0,0 +1,40 @@
+# -*-muttrc-*-
+#
+# Command formats for gpg.
+#
+# $Id$
+#
+
+# decode application/pgp
+set pgp_decode_command="gpg %?p?--passphrase-fd 0? --no-verbose --batch -o - --decrypt %f"
+
+# verify a pgp/mime signature
+set pgp_verify_command="gpg --no-verbose --batch -o - --verify %s %f"
+
+# decrypt a pgp/mime attachment
+set pgp_decrypt_command="gpg --passphrase-fd 0 --no-verbose --batch -o - --decrypt %f"
+
+# create a pgp/mime signed attachment
+set pgp_sign_command="gpg --no-verbose --batch -o - --passphrase-fd 0 --detach-sign --textmode --armor %?a?-u %a? %f"
+
+# create a pgp/mime encrypted attachment
+set pgp_encrypt_only_command="pgpewrap gpg --no-verbose -v --batch -o - --encrypt --textmode --armor --always-trust -- -r %r
+
+# create a pgp/mime encrypted and signed attachment
+set pgp_encrypt_sign_command="pgpewrap gpg --passphrase-fd 0 --no-verbose -v --batch -o - --encrypt --sign %?a?-u %a? --textmode --armor --always-trust -- -r %r
+
+# import a key into the public key ring
+set pgp_import_command="gpgm --no-verbose --import -v %f"
+
+# export a key from the public key ring
+set pgp_export_command="gpgm --no-verbose --export --armor %r"
+
+# verify a key
+set pgp_verify_key_command="gpgm --no-verbose --batch --fingerprint --check-sigs 
+
+# read in the public key ring
+set pgp_list_pubring_command="gpgm --no-verbose --batch --with-colons --list-keys %r" 
+
+# read in the secret key ring
+set pgp_list_secring_command="gpgm --no-verbose --batch --with-colons --list-secret-keys %r" 
+
diff --git a/contrib/pgp2.rc b/contrib/pgp2.rc
new file mode 100644 (file)
index 0000000..f1a6bd6
--- /dev/null
@@ -0,0 +1,41 @@
+# -*-muttrc-*-
+#
+# PGP command formats for PGP 2.
+#
+# $Id$
+#
+
+# decode application/pgp
+set pgp_decode_command="%?p?PGPPASSFD=0; export PGPPASSFD;? cat %?p?-? %f | pgp +language=mutt +verbose=0 +batchmode -f"
+
+# verify a pgp/mime signature
+set pgp_verify_command="pgp +language=mutt +verbose=0 +batchmode %f %s"
+
+# decrypt a pgp/mime attachment
+set pgp_decrypt_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode -f"
+
+# create a pgp/mime signed attachment
+set pgp_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode -abfst %?a? -u %a?"
+
+# create a pgp/mime encrypted attachment
+set pgp_encrypt_only_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode +aeft %r"
+
+# create a pgp/mime encrypted and signed attachment
+set pgp_encrypt_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgp +language=mutt +verbose=0 +batchmode +aefts %?a?-u %a? %r"
+
+# import a key into the public key ring
+set pgp_import_command="pgp -ka %f +language=mutt"
+
+# export a key from the public key ring
+set pgp_export_command="pgp -kxaf +language=mutt %r"
+
+# verify a key
+set pgp_verify_key_command="pgp -kcc +language=mutt %r"
+
+# read in the public key ring
+set pgp_list_pubring_command="pgpring -k $PGPPATH/pubring.pgp %r"
+
+# read in the secret key ring
+set pgp_list_secring_command="pgpring -k $PGPPATH/secring.pgp %r"
+
+
diff --git a/contrib/pgp5.rc b/contrib/pgp5.rc
new file mode 100644 (file)
index 0000000..0a54f94
--- /dev/null
@@ -0,0 +1,41 @@
+# -*-muttrc-*-
+#
+# PGP command formats for PGP 5.
+#
+# $Id$
+#
+
+# decode application/pgp
+set pgp_decode_command="%?p?PGPPASSFD=0; export PGPPASSFD;? cat %?p?-? %f | pgpv +language=mutt +verbose=0 +batchmode -f --OutputInformationFD=0"
+
+# verify a pgp/mime signature
+set pgp_verify_command="pgpv +language=mutt +verbose=0 +batchmode --OutputInformationFD=1 %f %s"
+
+# decrypt a pgp/mime attachment
+set pgp_decrypt_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpv +language=mutt +verbose=0 +batchmode --OutputInformationFD=2 -f"
+
+# create a pgp/mime signed attachment
+set pgp_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgps +language=mutt +verbose=0 +batchmode -abft %?a? -u %a?"
+
+# create a pgp/mime encrypted attachment
+set pgp_encrypt_only_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpewrap pgpe +language=mutt +verbose=0 +batchmode +nobatchinvalidkeys=off -aft -- -r %r"
+
+# create a pgp/mime encrypted and signed attachment
+set pgp_encrypt_sign_command="PGPPASSFD=0; export PGPPASSFD; cat - %f | pgpewrap pgpe +language=mutt +verbose=0 +batchmode +nobatchinvalidkeys=off -afts %?a? -u %a? -- -r %r"
+
+# import a key into the public key ring
+set pgp_import_command="pgpk -a +language=mutt --OutputInformationFD=1 %f"
+
+# export a key from the public key ring
+set pgp_export_command="pgpk -xa +language=mutt --OutputInformationFD=1 %r"
+
+# verify a key
+set pgp_verify_key_command="pgpk -c +batchmode +language=mutt --OutputInformationFD=1 %r"
+
+# read in the public key ring
+set pgp_list_pubring_command="pgpring -k $PGPPATH/pubring.pkr %r"
+
+# read in the secret key ring
+set pgp_list_secring_command="pgpring -k $PGPPATH/secring.skr %r"
+
+
index 8e44fd609a14e46ce4fb78602047c9c09b47864e..b018035aa94f7e2da19b203b743d84147f8c70b1 100644 (file)
  *     02139, USA.
  */
 
+/*
+ * NOTE
+ * 
+ * This code used to be the parser for GnuPG's output.
+ * 
+ * Nowadays, we are using an external pubring lister with PGP which mimics 
+ * gpg's output format.
+ * 
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
+#include <ctype.h>
 
 #include "mutt.h"
 #include "pgp.h"
+#include "charset.h"
 
+/* for hexval */
+#include "mime.h"
 
 /****************
  * Read the GNUPG keys.  For now we read the complete keyring by
  *   - signature class
  */
 
+/* decode the backslash-escaped user ids. */
+
+static CHARSET *_chs;
+
+static void fix_uid (char *uid)
+{
+  char *s, *d;
+  
+  for (s = d = uid; *s;)
+  {
+    if (*s == '\\' && *(s+1) == 'x' && isxdigit (*(s+2)) && isxdigit (*(s+3)))
+    {
+      *d++ = hexval (*(s+2)) << 4 | hexval (*(s+3));
+      s += 4;
+    }
+    else
+      *d++ = *s++;
+  }
+  *d = '\0';
+  
+  mutt_decode_utf8_string (d, _chs);
+}
+
 static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
 {
   pgp_uid_t *uid = NULL;
@@ -62,6 +98,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
   *is_subkey = 0;
   if (!*buf)
     return NULL;
+  
+  dprint (2, (debugfile, "parse_pub_line: buf = `%s'\n", buf));
+  
   for (p = buf; p; p = pend)
   {
     if ((pend = strchr (p, ':')))
@@ -74,6 +113,8 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
     {
       case 1:                  /* record type */
       {
+       dprint (2, (debugfile, "record type: %s\n", p));
+       
        if (!mutt_strcmp (p, "pub"))
          ;
        else if (!mutt_strcmp (p, "sub"))
@@ -94,6 +135,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
       }
       case 2:                  /* trust info */
       {
+
+       dprint (2, (debugfile, "trust info: %s\n", p));
+       
        switch (*p)
        {                               /* look only at the first letter */
          case 'e':
@@ -102,10 +146,6 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
          case 'r':
            k->flags |= KEYFLAG_REVOKED;
            break;
-         
-         /* produce "undefined trust" as long as gnupg doesn't
-          * have a proper trust model.
-          */
          case 'n':
            trust = 1;
            break;
@@ -123,17 +163,26 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
       }
       case 3:                  /* key length  */
       {
+       
+       dprint (2, (debugfile, "key len: %s\n", p));
+       
        k->keylen = atoi (p);   /* fixme: add validation checks */
        break;
       }
       case 4:                  /* pubkey algo */
       {
+       
+       dprint (2, (debugfile, "pubkey algorithm: %s\n", p));
+       
+       k->numalg = atoi (p);
        k->algorithm = pgp_pkalgbytype (atoi (p));
        k->flags |= pgp_get_abilities (atoi (p));
        break;
       }
       case 5:                  /* 16 hex digits with the long keyid. */
       {
+       dprint (2, (debugfile, "key id: %s\n", p));
+       
        /* We really should do a check here */
        k->keyid = safe_strdup (p);
        break;
@@ -143,6 +192,9 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
       {
        char tstr[11];
        struct tm time;
+       
+       dprint (2, (debugfile, "time stamp: %s\n", p));
+       
        if (!p)
          break;
        time.tm_sec = 0;
@@ -167,7 +219,11 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
       {
        if (!pend || !*p)
          break;                        /* empty field or no trailing colon */
+       
+       dprint (2, (debugfile, "user ID: %s\n", p));
+       
        uid = safe_calloc (sizeof (pgp_uid_t), 1);
+       fix_uid (p);
        uid->addr = safe_strdup (p);
        uid->trust = trust;
        uid->parent = k;
@@ -190,32 +246,7 @@ static pgp_key_t *parse_pub_line (char *buf, int *is_subkey, pgp_key_t *k)
   return k;
 }
 
-static pid_t gpg_invoke_list_keys (struct pgp_vinfo *pgp,
-                             FILE ** pgpin, FILE ** pgpout, FILE ** pgperr,
-                                  int pgpinfd, int pgpoutfd, int pgperrfd,
-                                  pgp_ring_t keyring,
-                                  LIST * hints)
-{
-  char cmd[HUGE_STRING];
-  char tmpcmd[HUGE_STRING];
-
-  /* we use gpgm here */
-  snprintf (cmd, sizeof (cmd),
-           "%sm --no-verbose --batch --with-colons --list-%skeys ",
-           NONULL (*pgp->binary), keyring == PGP_SECRING ? "secret-" : "");
-
-  for (; hints; hints = hints->next)
-  {
-    snprintf (tmpcmd, sizeof (tmpcmd), "%s %s", cmd, (char *) hints->data);
-    strcpy (cmd, tmpcmd);
-  }
-
-  return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
-                               pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pgp_key_t *gpg_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
-                              LIST * hints)
+pgp_key_t *pgp_get_candidates (pgp_ring_t keyring, LIST * hints)
 {
   FILE *fp;
   pid_t thepid;
@@ -227,7 +258,9 @@ pgp_key_t *gpg_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
   if ((devnull = open ("/dev/null", O_RDWR)) == -1)
     return NULL;
 
-  thepid = gpg_invoke_list_keys (pgp, NULL, &fp, NULL, -1, -1, devnull,
+  _chs = mutt_get_charset (Charset);
+  
+  thepid = pgp_invoke_list_keys (NULL, &fp, NULL, -1, -1, devnull,
                                 keyring, hints);
   if (thepid == -1)
   {
diff --git a/init.c b/init.c
index 22436654e396e2728578d208d8c3c4188bea9054..3195581c12effaffd381306856b293b3bcd33b74 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1622,53 +1622,6 @@ void mutt_init (int skip_sys_rc, LIST *commands)
 
   Tempdir = safe_strdup ((p = getenv ("TMPDIR")) ? p : "/tmp");
 
-  
-
-#ifdef _PGPPATH
-#ifdef _PGPV2PATH
-  PgpV2 = safe_strdup (_PGPV2PATH);
-  if ((p = getenv("PGPPATH")) != NULL)
-  {
-    snprintf (buffer, sizeof (buffer), "%s/pubring.pgp", p);
-    PgpV2Pubring = safe_strdup (buffer);
-    snprintf (buffer, sizeof (buffer), "%s/secring.pgp", p); 
-    PgpV2Secring = safe_strdup (buffer);
-  }
-  else
-  {
-    snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pgp", NONULL(Homedir));
-    PgpV2Pubring = safe_strdup (buffer);
-    snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.pgp", NONULL(Homedir));
-    PgpV2Secring = safe_strdup (buffer);
-  }
-#endif
-
-#ifdef _PGPV3PATH
-  PgpV3 = safe_strdup (_PGPV3PATH);
-  if ((p = getenv("PGPPATH")) != NULL)
-  {
-    snprintf (buffer, sizeof (buffer), "%s/pubring.pkr", p);
-    PgpV3Pubring = safe_strdup (buffer);
-    snprintf (buffer, sizeof (buffer), "%s/secring.skr", p); 
-    PgpV3Secring = safe_strdup (buffer);
-  }
-  else
-  {
-    snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pkr", NONULL(Homedir));
-    PgpV3Pubring = safe_strdup (buffer);
-    snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.skr", NONULL(Homedir));
-    PgpV3Secring = safe_strdup (buffer);
-  }
-#endif
-  
-#ifdef _PGPGPGPATH
-  PgpGpg = safe_strdup (_PGPGPGPATH);
-#endif
-
-#endif /* _PGPPATH */
-  
-  
-
 #ifdef USE_POP
   PopUser = safe_strdup (Username);
 #endif
diff --git a/init.h b/init.h
index 47afd71f35bdfb65ecf214a05dd61f579bac8b39..c381bcbe6b974da49061748f376af3f34bba672c 100644 (file)
--- a/init.h
+++ b/init.h
@@ -186,7 +186,11 @@ struct option_t MuttVars[] = {
 
   { "pgp_autosign",    DT_BOOL, R_NONE, OPTPGPAUTOSIGN, 0 },
   { "pgp_autoencrypt", DT_BOOL, R_NONE, OPTPGPAUTOENCRYPT, 0 },
+
+# if 0
   { "pgp_encryptself", DT_BOOL, R_NONE, OPTPGPENCRYPTSELF, 1 },
+# endif
+
   { "pgp_entry_format", DT_STR,  R_NONE, UL &PgpEntryFormat, UL "%4n %t%f %4l/0x%k %-4a %2c %u" },
   { "pgp_long_ids",    DT_BOOL, R_NONE, OPTPGPLONGIDS, 0 },
   { "pgp_replyencrypt",        DT_BOOL, R_NONE, OPTPGPREPLYENCRYPT, 0 },
@@ -199,35 +203,23 @@ struct option_t MuttVars[] = {
   { "pgp_strict_enc",  DT_BOOL, R_NONE, OPTPGPSTRICTENC, 1 },
   { "pgp_timeout",     DT_NUM,  R_NONE, UL &PgpTimeout, 300 },
   { "pgp_verify_sig",  DT_QUAD, R_NONE, OPT_VERIFYSIG, M_YES },
+  { "pgp_sort_keys",   DT_SORT|DT_SORT_KEYS, R_NONE, UL &PgpSortKeys, SORT_ADDRESS },
 
-  { "pgp_v2",          DT_PATH, R_NONE, UL &PgpV2, 0 },
-  { "pgp_v2_language", DT_STR,  R_NONE, UL &PgpV2Language, UL "en" },
-  { "pgp_v2_pubring",  DT_PATH, R_NONE, UL &PgpV2Pubring, 0 },
-  { "pgp_v2_secring",  DT_PATH, R_NONE, UL &PgpV2Secring, 0 },  
-
-  { "pgp_v5",          DT_PATH, R_NONE, UL &PgpV3, 0 },
-  { "pgp_v5_language", DT_STR,  R_NONE, UL &PgpV3Language, 0 },
-  { "pgp_v5_pubring",  DT_PATH, R_NONE, UL &PgpV3Pubring, 0 },
-  { "pgp_v5_secring",  DT_PATH, R_NONE, UL &PgpV3Secring, 0 },
-
-  { "pgp_gpg",         DT_PATH, R_NONE, UL &PgpGpg, 0 },
+  /* XXX Default values! */
   
-# ifdef HAVE_PGP2
-  { "pgp_default_version",     DT_STR, R_NONE, UL &PgpDefaultVersion, UL "pgp2" },
-# else
-#  ifdef HAVE_PGP5
-  { "pgp_default_version",     DT_STR, R_NONE, UL &PgpDefaultVersion, UL "pgp5" },
-#  else
-#   ifdef HAVE_GPG
-  { "pgp_default_version",     DT_STR, R_NONE, UL &PgpDefaultVersion, UL "gpg" },
-#   endif
-#  endif
-# endif
-  { "pgp_receive_version",     DT_STR, R_NONE, UL &PgpReceiveVersion, UL "default" },
-  { "pgp_send_version",                DT_STR, R_NONE, UL &PgpSendVersion, UL "default" },
-  { "pgp_sort_keys",   DT_SORT|DT_SORT_KEYS, R_NONE, UL &PgpSortKeys, SORT_ADDRESS },
-  { "pgp_key_version",         DT_STR, R_NONE, UL &PgpKeyVersion, UL "default" },
+  { "pgp_decode_command",      DT_STR, R_NONE, UL &PgpDecodeCommand, 0},
+  { "pgp_verify_command",      DT_STR, R_NONE, UL &PgpVerifyCommand, 0},
+  { "pgp_decrypt_command",     DT_STR, R_NONE, UL &PgpDecryptCommand, 0},
+  { "pgp_sign_command",                DT_STR, R_NONE, UL &PgpSignCommand, 0},
+  { "pgp_encrypt_sign_command",        DT_STR, R_NONE, UL &PgpEncryptSignCommand, 0},
+  { "pgp_encrypt_only_command", DT_STR, R_NONE, UL &PgpEncryptOnlyCommand, 0},
+  { "pgp_import_command",      DT_STR, R_NONE, UL &PgpImportCommand, 0},
+  { "pgp_export_command",      DT_STR, R_NONE, UL &PgpExportCommand, 0},
+  { "pgp_verify_key_command",  DT_STR, R_NONE, UL &PgpVerifyKeyCommand, 0},
+  { "pgp_list_secring_command",        DT_STR, R_NONE, UL &PgpListSecringCommand, 0},
+  { "pgp_list_pubring_command", DT_STR, R_NONE, UL &PgpListPubringCommand, 0},
 
+    
   { "forward_decrypt", DT_BOOL, R_NONE, OPTFORWDECRYPT, 1 },
   { "forw_decrypt",    DT_SYN,  R_NONE, UL "forward_decrypt", 0 },
 #endif /* _PGPPATH */
diff --git a/mutt.h b/mutt.h
index 38448464b6f571668fe3fe73a0492494e7de8708..e19556f69b2d9c08a465bed4db51d47f06b10936 100644 (file)
--- a/mutt.h
+++ b/mutt.h
@@ -343,7 +343,9 @@ enum
   OPTPGPREPLYENCRYPT,
   OPTPGPREPLYSIGN,
   OPTPGPREPLYSIGNENCRYPTED,
+#if 0
   OPTPGPENCRYPTSELF,
+#endif
   OPTPGPRETAINABLESIG,
   OPTPGPSTRICTENC,
   OPTFORWDECRYPT,
diff --git a/pgp.c b/pgp.c
index e590c3c56d1a1a939ad4e43dcd6edebeb3e6cef0..df1b15fe9a17c773d23ffd32dac4eb62ccc816f4 100644 (file)
--- a/pgp.c
+++ b/pgp.c
 char PgpPass[STRING];
 static time_t PgpExptime = 0; /* when does the cached passphrase expire? */
 
-static struct pgp_vinfo pgp_vinfo[] =
-{
-
-  { PGP_V2,    
-    "pgp2",    
-    &PgpV2,    &PgpV2Pubring,  &PgpV2Secring,  &PgpV2Language, 
-    pgp_get_candidates,
-    pgp_v2_invoke_decode, pgp_v2_invoke_verify, pgp_v2_invoke_decrypt,
-    pgp_v2_invoke_sign, pgp_v2_invoke_encrypt, pgp_v2_invoke_import,
-    pgp_v2_invoke_export, pgp_v2_invoke_verify_key 
-  },
-
-  { PGP_V3,    
-    "pgp3",    
-    &PgpV3,    &PgpV3Pubring,  &PgpV3Secring,  &PgpV3Language, 
-    pgp_get_candidates,
-    pgp_v3_invoke_decode, pgp_v3_invoke_verify, pgp_v3_invoke_decrypt,
-    pgp_v3_invoke_sign, pgp_v3_invoke_encrypt, pgp_v3_invoke_import,
-    pgp_v3_invoke_export, pgp_v3_invoke_verify_key 
-  },
-  
-  { PGP_V3,    
-    "pgp5",    
-    &PgpV3,    &PgpV3Pubring,  &PgpV3Secring,  &PgpV3Language, 
-    pgp_get_candidates,
-    pgp_v3_invoke_decode, pgp_v3_invoke_verify, pgp_v3_invoke_decrypt,
-    pgp_v3_invoke_sign, pgp_v3_invoke_encrypt, pgp_v3_invoke_import,
-    pgp_v3_invoke_export, pgp_v3_invoke_verify_key 
-  },
-  
-  { PGP_GPG,   
-    "gpg",     
-    &PgpGpg,   &PgpGpgDummy,   &PgpGpgDummy, &PgpGpgDummy,
-    gpg_get_candidates,
-    pgp_gpg_invoke_decode, pgp_gpg_invoke_verify, pgp_gpg_invoke_decrypt,
-    pgp_gpg_invoke_sign, pgp_gpg_invoke_encrypt, pgp_gpg_invoke_import,
-    pgp_gpg_invoke_export, pgp_gpg_invoke_verify_key 
-  },
-  
-  { PGP_UNKNOWN,
-    NULL, 
-    NULL, NULL, NULL, NULL,
-    NULL,
-    NULL, NULL, NULL,
-    NULL, NULL, NULL, 
-    NULL, NULL
-  }
-};
-
-static struct
-{
-  enum pgp_ops op;
-  char **str;
-} 
-pgp_opvers[] =
-{
-  { PGP_DECODE,        &PgpReceiveVersion },
-  { PGP_VERIFY,        &PgpReceiveVersion },
-  { PGP_DECRYPT,       &PgpReceiveVersion },
-  { PGP_SIGN,          &PgpSendVersion    },
-  { PGP_ENCRYPT,       &PgpSendVersion   },
-  { PGP_VERIFY_KEY,    &PgpSendVersion   },
-  { PGP_IMPORT,                &PgpKeyVersion    },
-  { PGP_EXPORT,                &PgpKeyVersion    },
-  { PGP_LAST_OP,       NULL              }
-};
-
-
-
 void pgp_void_passphrase (void)
 {
   memset (PgpPass, 0, sizeof (PgpPass));
@@ -147,37 +78,6 @@ void mutt_forget_passphrase (void)
 }
 
 
-struct pgp_vinfo *pgp_get_vinfo(enum pgp_ops op)
-{
-  int i;
-  char *version = "default";
-  char msg[LONG_STRING];
-  
-  for(i = 0; pgp_opvers[i].op != PGP_LAST_OP; i++)
-  {
-    if(pgp_opvers[i].op == op)
-    {
-      version = *pgp_opvers[i].str;
-      break;
-    }
-  }
-  
-  if (!mutt_strcasecmp(version, "default"))
-    version = PgpDefaultVersion;
-  
-  for(i = 0; pgp_vinfo[i].name; i++)
-  {
-    if(!mutt_strcasecmp(pgp_vinfo[i].name, version))
-      return &pgp_vinfo[i];
-  }
-
-  snprintf(msg, sizeof(msg), _("Unknown PGP version \"%s\"."),
-          version);
-  mutt_error(msg);
-
-  return NULL;
-}
-
 char *pgp_keyid(pgp_key_t *k)
 {
   if((k->flags & KEYFLAG_SUBKEY) && k->parent)
@@ -229,11 +129,7 @@ void pgp_application_pgp_handler (BODY *m, STATE *s)
   FILE *pgpout = NULL, *pgpin, *pgperr;
   FILE *tmpfp;
   pid_t thepid;
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_DECODE);
 
-  if(!pgp)
-    return;
-  
   fseek (s->fpin, m->offset, 0);
   last_pos = m->offset;
   
@@ -308,8 +204,7 @@ void pgp_application_pgp_handler (BODY *m, STATE *s)
 
        fclose(tmpfp);
        
-       if ((thepid = pgp->invoke_decode (pgp,
-                                         &pgpin, NULL, 
+       if ((thepid = pgp_invoke_decode (&pgpin, NULL,
                                          &pgperr, -1,
                                          fileno (pgpout), 
                                          -1, tmpfname, 
@@ -622,7 +517,7 @@ static int pgp_write_signed(BODY *a, STATE *s, const char *tempfile)
   return 0;
 }
 
-static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile, struct pgp_vinfo *pgp)
+static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile)
 {
   char sigfile[_POSIX_PATH_MAX], pgperrfile[_POSIX_PATH_MAX];
   FILE *fp, *pgpout, *pgperr;
@@ -650,8 +545,7 @@ static int pgp_verify_one (BODY *sigbdy, STATE *s, const char *tempfile, struct
   
   pgp_current_time (s);
   
-  if((thepid = pgp->invoke_verify (pgp,
-                                  NULL, &pgpout, NULL, 
+  if((thepid = pgp_invoke_verify (NULL, &pgpout, NULL, 
                                   -1, -1, fileno(pgperr),
                                   tempfile, sigfile)) != -1)
   {
@@ -683,16 +577,10 @@ void pgp_signed_handler (BODY *a, STATE *s)
   int protocol_major = TYPEOTHER;
   char *protocol_minor = NULL;
   
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_VERIFY);
-
   BODY **signatures = NULL;
   int sigcnt = 0;
   int i;
 
-  
-  if (!pgp)
-    return;
-
   protocol = mutt_get_parameter ("protocol", a->parameter);
   a = a->parts;
 
@@ -744,7 +632,7 @@ void pgp_signed_handler (BODY *a, STATE *s)
        {
          if (signatures[i]->type == TYPEAPPLICATION 
              && !mutt_strcasecmp(signatures[i]->subtype, "pgp-signature"))
-           pgp_verify_one (signatures[i], s, tempfile, pgp);
+           pgp_verify_one (signatures[i], s, tempfile);
          else
            state_printf (s, _("[-- Warning: We can't verify %s/%s signatures. --]\n\n"),
                          TYPE(signatures[i]), signatures[i]->subtype);
@@ -776,106 +664,95 @@ void pgp_extract_keys_from_messages (HEADER *h)
   int i;
   STATE s;
   char tempfname[_POSIX_PATH_MAX];
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_IMPORT);
-  
-  if(!pgp)
-    return;
-  
-  if(h)
+
+  if (h)
   {
-    mutt_parse_mime_message(Context, h);
-    if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase())
+    mutt_parse_mime_message (Context, h);
+    if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase ())
       return;
   }
 
-  memset(&s, 0, sizeof(STATE));
+  memset (&s, 0, sizeof (STATE));
   
-  mutt_mktemp(tempfname);
-  if(!(s.fpout = safe_fopen(tempfname, "w")))
+  mutt_mktemp (tempfname);
+  if (!(s.fpout = safe_fopen (tempfname, "w")))
   {
-    mutt_perror(tempfname);
+    mutt_perror (tempfname);
     return;
   }
 
-  set_option(OPTDONTHANDLEPGPKEYS);
+  set_option (OPTDONTHANDLEPGPKEYS);
   
-  if(!h)
+  if (!h)
   {
-    for(i = 0; i < Context->vcount; i++)
+    for (i = 0; i < Context->vcount; i++)
     {
-      if(Context->hdrs[Context->v2r[i]]->tagged)
+      if (Context->hdrs[Context->v2r[i]]->tagged)
       {
-       mutt_parse_mime_message(Context, Context->hdrs[Context->v2r[i]]);
-       if(Context->hdrs[Context->v2r[i]]->pgp & PGPENCRYPT
+       mutt_parse_mime_message (Context, Context->hdrs[Context->v2r[i]]);
+       if (Context->hdrs[Context->v2r[i]]->pgp & PGPENCRYPT
           && !pgp_valid_passphrase())
        {
-         fclose(s.fpout);
+         fclose (s.fpout);
          goto bailout;
        }
-       mutt_pipe_message_to_state(Context->hdrs[Context->v2r[i]], &s);
+       mutt_pipe_message_to_state (Context->hdrs[Context->v2r[i]], &s);
       }
     }
   } 
   else
   {
-    mutt_parse_mime_message(Context, h);
-    if(h->pgp & PGPENCRYPT && !pgp_valid_passphrase())
+    mutt_parse_mime_message (Context, h);
+    if (h->pgp & PGPENCRYPT && !pgp_valid_passphrase())
     {
-      fclose(s.fpout);
+      fclose (s.fpout);
       goto bailout;
     }
-    mutt_pipe_message_to_state(h, &s);
+    mutt_pipe_message_to_state (h, &s);
   }
       
-  fclose(s.fpout);
-  endwin();
-  pgp->invoke_import(pgp, tempfname);
-  mutt_any_key_to_continue(NULL);
+  fclose (s.fpout);
+  endwin ();
+  pgp_invoke_import (tempfname);
+  mutt_any_key_to_continue (NULL);
 
   bailout:
   
-  mutt_unlink(tempfname);
-  unset_option(OPTDONTHANDLEPGPKEYS);
+  mutt_unlink (tempfname);
+  unset_option (OPTDONTHANDLEPGPKEYS);
   
 }
 
-static void pgp_extract_keys_from_attachment(struct pgp_vinfo *pgp,
-                                            FILE *fp, BODY *top)
+static void pgp_extract_keys_from_attachment (FILE *fp, BODY *top)
 {
   STATE s;
   FILE *tempfp;
   char tempfname[_POSIX_PATH_MAX];
 
-  mutt_mktemp(tempfname);
-  if(!(tempfp = safe_fopen(tempfname, "w")))
+  mutt_mktemp (tempfname);
+  if (!(tempfp = safe_fopen (tempfname, "w")))
   {
-    mutt_perror(tempfname);
+    mutt_perror (tempfname);
     return;
   }
 
-  memset(&s, 0, sizeof(STATE));
+  memset (&s, 0, sizeof (STATE));
   
   s.fpin = fp;
   s.fpout = tempfp;
   
-  mutt_body_handler(top, &s);
-
-  fclose(tempfp);
+  mutt_body_handler (top, &s);
 
-  pgp->invoke_import(pgp, tempfname);
-  mutt_any_key_to_continue(NULL);
+  fclose (tempfp);
 
-  mutt_unlink(tempfname);
+  pgp_invoke_import (tempfname);
+  mutt_any_key_to_continue (NULL);
 
+  mutt_unlink (tempfname);
 }
 
 void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
 {
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_IMPORT);
-  
-  if(!pgp)
-    return;
-  
   if(!fp)
   {
     mutt_error _("Internal error. Inform <roessler@guug.de>.");
@@ -888,7 +765,7 @@ void pgp_extract_keys_from_attachment_list (FILE *fp, int tag, BODY *top)
   for(; top; top = top->next)
   {
     if(!tag || top->tagged)
-      pgp_extract_keys_from_attachment (pgp, fp, top);
+      pgp_extract_keys_from_attachment (fp, top);
     
     if(!tag)
       break;
@@ -907,10 +784,6 @@ BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout)
   char pgperrfile[_POSIX_PATH_MAX];
   char pgptmpfile[_POSIX_PATH_MAX];
   pid_t thepid;
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_DECRYPT);
-  
-  if(!pgp)
-    return NULL;
   
   mutt_mktemp (pgperrfile);
   if ((pgperr = safe_fopen (pgperrfile, "w+")) == NULL)
@@ -936,7 +809,7 @@ BODY *pgp_decrypt_part (BODY *a, STATE *s, FILE *fpout)
   mutt_copy_bytes (s->fpin, pgptmp, a->length);
   fclose (pgptmp);
 
-  if ((thepid = pgp->invoke_decrypt (pgp, &pgpin, &pgpout, NULL, -1, -1,
+  if ((thepid = pgp_invoke_decrypt (&pgpin, &pgpout, NULL, -1, -1,
                                    fileno (pgperr), pgptmpfile)) == -1)
   {
     fclose (pgperr);
@@ -1119,10 +992,6 @@ static BODY *pgp_sign_message (BODY *a)
   int err = 0;
   int empty = 1;
   pid_t thepid;
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_SIGN);
-  
-  if(!pgp)
-    return NULL;
   
   convert_to_7bit (a); /* Signed data _must_ be in 7-bit format. */
 
@@ -1146,8 +1015,8 @@ static BODY *pgp_sign_message (BODY *a)
   mutt_write_mime_body (a, sfp);
   fclose(sfp);
   
-  if((thepid = pgp->invoke_sign(pgp, &pgpin, &pgpout, &pgperr,
-                              -1, -1, -1, signedfile)) == -1)
+  if ((thepid = pgp_invoke_sign (&pgpin, &pgpout, &pgperr,
+                                -1, -1, -1, signedfile)) == -1)
   {
     mutt_perror _("Can't open PGP subprocess!");
     fclose(fp);
@@ -1241,11 +1110,7 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
   ADDRESS *p;
   int i;
   pgp_key_t *k_info, *key;
-  struct pgp_vinfo *pgp = pgp_get_vinfo (PGP_ENCRYPT);
-  
-  if (!pgp)
-    return NULL;
-  
+
   for (i = 0; i < 3; i++) 
   {
     switch (i)
@@ -1272,14 +1137,14 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc)
     {
       snprintf (buf, sizeof (buf), _("Use keyID = \"%s\" for %s?"), keyID, p->mailbox);
       if (mutt_yesorno (buf, M_YES) == M_YES)
-       k_info = pgp_getkeybystr (pgp, keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
+       k_info = pgp_getkeybystr (keyID, KEYFLAG_CANENCRYPT, PGP_PUBRING);
     }
 
-    if (k_info == NULL && (k_info = pgp_getkeybyaddr (pgp, p, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
+    if (k_info == NULL && (k_info = pgp_getkeybyaddr (p, KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
     {
       snprintf (buf, sizeof (buf), _("Enter keyID for %s: "), p->mailbox);
       
-      if ((key = pgp_ask_for_key (pgp, buf, p->mailbox,
+      if ((key = pgp_ask_for_key (buf, p->mailbox,
                                  KEYFLAG_CANENCRYPT, PGP_PUBRING)) == NULL)
       {
        safe_free ((void **)&keylist);
@@ -1317,10 +1182,6 @@ static BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign)
   int err = 0;
   int empty;
   pid_t thepid;
-  struct pgp_vinfo *pgp = pgp_get_vinfo(PGP_ENCRYPT);
-  
-  if(!pgp)
-    return NULL;
   
   mutt_mktemp (tempfile);
   if ((fpout = safe_fopen (tempfile, "w+")) == NULL)
@@ -1357,9 +1218,9 @@ static BODY *pgp_encrypt_message (BODY *a, char *keylist, int sign)
   mutt_write_mime_body (a, fptmp);
   fclose(fptmp);
   
-  if ((thepid = pgp->invoke_encrypt (pgp, &pgpin, NULL, NULL, -1, 
-                                    fileno (fpout), fileno (pgperr),
-                                    pgpinfile, keylist, sign)) == -1)
+  if ((thepid = pgp_invoke_encrypt (&pgpin, NULL, NULL, -1, 
+                                   fileno (fpout), fileno (pgperr),
+                                   pgpinfile, keylist, sign)) == -1)
   {
     fclose (pgperr);
     unlink(pgpinfile);
diff --git a/pgp.h b/pgp.h
index 8e5580e7163335c3f2ab9b92855a276302ff103c..005e740357c3a21f28ce246fe491c22ee9a76c47 100644 (file)
--- a/pgp.h
+++ b/pgp.h
 
 #ifdef _PGPPATH
 
-#define PGPENCRYPT 1
-#define PGPSIGN    2
-#define PGPKEY     4
+#include "pgplib.h"
 
-#define KEYFLAG_CANSIGN                (1 <<  0)
-#define KEYFLAG_CANENCRYPT             (1 <<  1)
-#define KEYFLAG_EXPIRED                (1 <<  8)
-#define KEYFLAG_REVOKED                (1 <<  9)
-#define KEYFLAG_DISABLED               (1 << 10)
-#define KEYFLAG_SUBKEY                         (1 << 11)
-#define KEYFLAG_CRITICAL               (1 << 12)
-#define KEYFLAG_PREFER_ENCRYPTION      (1 << 13)
-#define KEYFLAG_PREFER_SIGNING                 (1 << 14)
-
-#define KEYFLAG_CANTUSE (KEYFLAG_DISABLED|KEYFLAG_REVOKED|KEYFLAG_EXPIRED)
-#define KEYFLAG_RESTRICTIONS (KEYFLAG_CANTUSE|KEYFLAG_CRITICAL)
-
-#define KEYFLAG_ABILITIES (KEYFLAG_CANSIGN|KEYFLAG_CANENCRYPT|KEYFLAG_PREFER_ENCRYPTION|KEYFLAG_PREFER_SIGNING)
-
-typedef struct pgp_keyinfo
-{
-  char *keyid;
-  struct pgp_uid *address;
-  int flags;
-  short keylen;
-  time_t gen_time;
-  const char *algorithm;
-  struct pgp_keyinfo *parent;
-  struct pgp_keyinfo *next;
-}
-pgp_key_t;
-
-typedef struct pgp_uid
-{
-  char *addr;
-  short trust;
-  struct pgp_keyinfo *parent;
-  struct pgp_uid *next;
-}
-pgp_uid_t;
-
-enum pgp_version
-{
-  PGP_V2,
-  PGP_V3,
-  PGP_GPG,
-  PGP_UNKNOWN
-};
-
-enum pgp_ring
-{
-  PGP_PUBRING,
-  PGP_SECRING
-};
-
-typedef enum pgp_ring pgp_ring_t;
-
-enum pgp_ops
-{
-  PGP_DECODE,                  /* application/pgp */
-  PGP_VERIFY,                  /* PGP/MIME, signed */
-  PGP_DECRYPT,                 /* PGP/MIME, encrypted */
-  PGP_SIGN,                    /* sign data */
-  PGP_ENCRYPT,                 /* encrypt data */
-  PGP_IMPORT,                  /* extract keys from messages */
-  PGP_VERIFY_KEY,              /* verify key when selecting */
-  PGP_EXPORT,                  /* extract keys from key ring */
-  PGP_LAST_OP
-};
-
-struct pgp_vinfo
-{
-
-  /* data */
-
-  enum pgp_version v;
-  char *name;
-  char **binary;
-  char **pubring;
-  char **secring;
-  char **language;
-
-  /* functions */
-
-  pgp_key_t *(*get_candidates) (struct pgp_vinfo *, pgp_ring_t, LIST *);
-  
-  pid_t (*invoke_decode) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                         int, int, int,
-                         const char *, int);
-  
-  pid_t (*invoke_verify) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                         int, int, int,
-                         const char *, const char *);
-  
-  pid_t (*invoke_decrypt) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                          int, int, int,
-                          const char *);
-  
-  pid_t (*invoke_sign) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                       int, int, int,
-                       const char *);
-  
-  pid_t (*invoke_encrypt) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                          int, int, int,
-                          const char *, const char *, int);
-  
-  void (*invoke_import) (struct pgp_vinfo *, const char *);
-  
-  pid_t (*invoke_export) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                         int, int, int,
-                         const char *);
-  
-  pid_t (*invoke_verify_key) (struct pgp_vinfo *, FILE **, FILE **, FILE **,
-                             int, int, int,
-                             const char *);
-  
-};
-
-
-WHERE char *PgpV2;
-WHERE char *PgpV2Language;
-WHERE char *PgpV2Pubring;
-WHERE char *PgpV2Secring;
-
-WHERE char *PgpV3;
-WHERE char *PgpV3Language;
-WHERE char *PgpV3Pubring;
-WHERE char *PgpV3Secring;
+WHERE char *PgpSignAs;
+WHERE char *PgpSignMicalg;
+WHERE short PgpTimeout;
+WHERE char *PgpEntryFormat;
 
-WHERE char *PgpGpg;
-#if 0
-WHERE char *PgpGpgLanguage;
-WHERE char *PgpGpgPubring;
-WHERE char *PgpGpgSecring;
-#else
-WHERE char *PgpGpgDummy;
-#endif
 
-WHERE char *PgpSendVersion;
-WHERE char *PgpReceiveVersion;
-WHERE char *PgpKeyVersion;
-WHERE char *PgpDefaultVersion;
+/* The command formats */
 
-WHERE char *PgpSignAs;
-WHERE char *PgpSignMicalg;
+WHERE char *PgpDecodeCommand;
+WHERE char *PgpVerifyCommand;
+WHERE char *PgpDecryptCommand;
+WHERE char *PgpSignCommand;
+WHERE char *PgpEncryptSignCommand;
+WHERE char *PgpEncryptOnlyCommand;
+WHERE char *PgpImportCommand;
+WHERE char *PgpExportCommand;
+WHERE char *PgpVerifyKeyCommand;
+WHERE char *PgpListSecringCommand;
+WHERE char *PgpListPubringCommand;
 
-WHERE short PgpTimeout;
 
-WHERE char *PgpEntryFormat;
+/* prototypes */
 
 BODY *pgp_decrypt_part (BODY *, STATE *, FILE *);
 BODY *pgp_make_key_attachment (char *);
@@ -175,8 +50,6 @@ BODY *pgp_make_key_attachment (char *);
 char *_pgp_keyid (pgp_key_t *);
 char *pgp_keyid (pgp_key_t *);
 
-const char *pgp_pkalg_to_mic (const char *);
-const char *pgp_pkalgbytype (unsigned char);
 
 int mutt_check_pgp (HEADER * h);
 int mutt_is_application_pgp (BODY *);
@@ -187,203 +60,52 @@ int pgp_decrypt_mime (FILE *, FILE **, BODY *, BODY **);
 int pgp_get_keys (HEADER *, char **);
 int pgp_protect (HEADER *, char *);
 int pgp_query (BODY *);
-int pgp_string_matches_hint (const char *s, LIST * hints);
+/* int pgp_string_matches_hint (const char *s, LIST * hints); */
 int pgp_valid_passphrase (void);
 
-pgp_key_t *gpg_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *);
-pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *, char *, char *, short, pgp_ring_t);
-pgp_key_t *pgp_get_candidates (struct pgp_vinfo *, pgp_ring_t, LIST *);
-pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo *pgp, ADDRESS *, short, pgp_ring_t);
-pgp_key_t *pgp_getkeybystr (struct pgp_vinfo *pgp, char *, short, pgp_ring_t);
-pgp_key_t *pgp_remove_key (pgp_key_t **, pgp_key_t *);
-
-pgp_uid_t *pgp_copy_uids (pgp_uid_t *, pgp_key_t *);
-
-short pgp_canencrypt (unsigned char);
-short pgp_cansign (unsigned char);
-short pgp_get_abilities (unsigned char);
-
-struct pgp_vinfo *pgp_get_vinfo (enum pgp_ops);
+/* 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_getkeybystr (char *, short, pgp_ring_t);
 
 void mutt_forget_passphrase (void);
 void pgp_application_pgp_handler (BODY *, STATE *);
 void pgp_encrypted_handler (BODY *, STATE *);
 void pgp_extract_keys_from_attachment_list (FILE * fp, int tag, BODY * top);
 void pgp_extract_keys_from_messages (HEADER * hdr);
-void pgp_free_key (pgp_key_t **kpp);
 void pgp_signed_handler (BODY *, STATE *);
 void pgp_void_passphrase (void);
 
-#define pgp_secring(a) pgp_getring(a, 0)
-#define pgp_pubring(a) pgp_getring(a, 1)
-
-/* PGP V2 prototypes */
-
-
-pid_t pgp_v2_invoke_decode (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *, int);
-
-pid_t pgp_v2_invoke_verify (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *, const char *);
-
-
-pid_t pgp_v2_invoke_decrypt (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *);
-
-pid_t pgp_v2_invoke_sign (struct pgp_vinfo *,
-                         FILE **, FILE **, FILE **,
-                         int, int, int,
-                         const char *);
-
-pid_t pgp_v2_invoke_encrypt (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *, const char *, int);
-
-void pgp_v2_invoke_import (struct pgp_vinfo *, const char *);
-
-pid_t pgp_v2_invoke_export (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *);
-
-pid_t pgp_v2_invoke_verify_key (struct pgp_vinfo *,
-                               FILE **, FILE **, FILE **,
-                               int, int, int,
-                               const char *);
-
-/* PGP V3 prototypes */
-
-pid_t pgp_v3_invoke_decode (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *, int);
-
-pid_t pgp_v3_invoke_verify (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *, const char *);
-
-
-pid_t pgp_v3_invoke_decrypt (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *);
-
-pid_t pgp_v3_invoke_sign (struct pgp_vinfo *,
-                         FILE **, FILE **, FILE **,
-                         int, int, int,
-                         const char *);
-
-pid_t pgp_v3_invoke_encrypt (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *, const char *, int);
-
-void pgp_v3_invoke_import (struct pgp_vinfo *, const char *);
-
-pid_t pgp_v3_invoke_export (struct pgp_vinfo *,
-                           FILE **, FILE **, FILE **,
-                           int, int, int,
-                           const char *);
-
-pid_t pgp_v3_invoke_verify_key (struct pgp_vinfo *,
-                               FILE **, FILE **, FILE **,
-                               int, int, int,
-                               const char *);
-
-/* GNU Privacy Guard Prototypes */
-
-pid_t pgp_gpg_invoke_decode (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *, int);
-
-pid_t pgp_gpg_invoke_verify (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *, const char *);
-
-
-pid_t pgp_gpg_invoke_decrypt (struct pgp_vinfo *,
-                             FILE **, FILE **, FILE **,
-                             int, int, int,
-                             const char *);
-
-pid_t pgp_gpg_invoke_sign (struct pgp_vinfo *,
-                          FILE **, FILE **, FILE **,
-                          int, int, int,
-                          const char *);
-
-pid_t pgp_gpg_invoke_encrypt (struct pgp_vinfo *,
-                             FILE **, FILE **, FILE **,
-                             int, int, int,
-                             const char *, const char *, int);
-
-void pgp_gpg_invoke_import (struct pgp_vinfo *, const char *);
-
-pid_t pgp_gpg_invoke_export (struct pgp_vinfo *,
-                            FILE **, FILE **, FILE **,
-                            int, int, int,
-                            const char *);
-
-pid_t pgp_gpg_invoke_verify_key (struct pgp_vinfo *,
-                                FILE **, FILE **, FILE **,
-                                int, int, int,
-                                const char *);
-
-
-
-
-#if 0
-
-/* use these as templates for your own prototypes */
-
-
-pid_t pgp_VERSION_invoke_decode (struct pgp_vinfo *,
-                                FILE **, FILE **, FILE **,
-                                int, int, int,
-                                const char *, int);
-
-pid_t pgp_VERSION_invoke_verify (struct pgp_vinfo *,
-                                FILE **, FILE **, FILE **,
-                                int, int, int,
-                                const char *, const char *);
-
-
-pid_t pgp_VERSION_invoke_decrypt (struct pgp_vinfo *,
-                                 FILE **, FILE **, FILE **,
-                                 int, int, int,
-                                 const char *);
-
-pid_t pgp_VERSION_invoke_sign (struct pgp_vinfo *,
-                              FILE **, FILE **, FILE **,
-                              int, int, int,
-                              const char *);
-
-pid_t pgp_VERSION_invoke_encrypt (struct pgp_vinfo *,
-                                 FILE **, FILE **, FILE **,
-                                 int, int, int,
-                                 const char *, const char *, int);
-
-void pgp_VERSION_invoke_import (struct pgp_vinfo *, const char *);
 
-pid_t pgp_VERSION_invoke_export (struct pgp_vinfo *,
-                                FILE **, FILE **, FILE **,
-                                int, int, int,
-                                const char *);
 
-pid_t pgp_VERSION_invoke_verify_key (struct pgp_vinfo *,
-                                    FILE **, FILE **, FILE **,
-                                    int, int, int,
-                                    const char *);
+/* The PGP invocation interface - not really beautiful. */
+
+pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd, 
+                        const char *fname, short need_passphrase);
+pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd, 
+                        const char *fname, const char *sig_fname);
+pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                         int pgpinfd, int pgpoutfd, int pgperrfd, 
+                         const char *fname);
+pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                      int pgpinfd, int pgpoutfd, int pgperrfd, 
+                      const char *fname);
+pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                         int pgpinfd, int pgpoutfd, int pgperrfd,
+                         const char *fname, const char *uids, int sign);
+void pgp_invoke_import (const char *fname);
+pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd, 
+                        const char *uids);
+pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                            int pgpinfd, int pgpoutfd, int pgperrfd, 
+                            const char *uids);
+pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                           int pgpinfd, int pgpoutfd, int pgperrfd, 
+                           pgp_ring_t keyring, LIST *hints);
 
-#endif
 
 #endif /* _PGPPATH */
diff --git a/pgpewrap b/pgpewrap
new file mode 100755 (executable)
index 0000000..2f3a21c
--- /dev/null
+++ b/pgpewrap
@@ -0,0 +1,20 @@
+#!/bin/sh --
+
+cmd=$1
+pfx=""
+
+die() {
+       echo "Command line usage: $0 [flags] -- prefix [recipients]" >& 2
+       exit 1
+}
+
+while shift && test -n "$1" ; do
+       if test "$1" = "--" ; then
+               shift || die
+               pfx="$1"
+               shift || die
+       fi
+       cmd="$cmd $pfx $1"
+done
+
+exec $cmd
index ccc7d4945598ca29058a6bb786e43a394e6f1cd1..4af8b933ef2753885ffcde02d6ca0e985c95a279 100644 (file)
@@ -1,21 +1,28 @@
 /*
  * Copyright (C) 1997-1999 Thomas Roessler <roessler@guug.de>
  * 
- *     This program is free software; you can redistribute it and/or modify
- *     it under the terms of the GNU General Public License as published by
- *     the Free Software Foundation; either version 2 of the License, or
- *     (at your option) any later version.
+ *     This program is free software; you can redistribute it
+ *     and/or modify it under the terms of the GNU General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2 of the License, or (at your option) any later
+ *     version.
  * 
- *     This program is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
+ *     This program is distributed in the hope that it will be
+ *     useful, but WITHOUT ANY WARRANTY; without even the implied
+ *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *     PURPOSE.  See the GNU General Public License for more
+ *     details.
  * 
- *     You should have received a copy of the GNU General Public License
- *     along with this program; if not, write to the Free Software
- *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *     You should have received a copy of the GNU General Public
+ *     License along with this program; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ *     02139, USA.
  */ 
 
+/* This file contains the new pgp invocation code.  Note that this
+ * is almost entirely format based.
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "mutt.h"
 #include "pgp.h"
 
-/*******************************************************************
- * 
- * PGP V2 Invocation stuff
- * 
- *******************************************************************/
-
-pid_t pgp_v2_invoke_decode(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd,
-                          const char *fname, int need_passphrase)
-{
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%scat %s%s | "
-          "%s +language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -f",
-          need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "",
-          need_passphrase ? "- " : "",
-          _fname,
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring));
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_v2_invoke_verify(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd,
-                          const char *signedstuff, const char *sigfile)
-{
-  char _sig[_POSIX_PATH_MAX + SHORT_STRING];
-  char _signed[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_sig, sizeof (_sig), sigfile);
-  mutt_quote_filename (_signed, sizeof (_signed), signedstuff);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), 
-          "%s +language=%s +pubring=%s +secring=%s +batchmode +verbose=0 %s %s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), 
-          NONULL (secring), _sig, _signed);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_v2_invoke_decrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname)
-{
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s +language=%s +pubring=%s +secring=%s "
-          "+verbose=0 +batchmode -f",
-          _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring));
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                           pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_v2_invoke_sign(struct pgp_vinfo *pgp,
-                        FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                        int pgpinfd, int pgpoutfd, int pgperrfd, 
-                        const char *fname)
-{
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "PGPPASSFD=0; export PGPPASSFD; cat - %s | %s "
-          "+language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -abfst %s %s",
-          _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), 
-          PgpSignAs ? "-u" : "",
-          PgpSignAs ? PgpSignAs : "");
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
 
-pid_t pgp_v2_invoke_encrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname, const char *uids, int sign)
+/*
+ * The actual command line formatter.
+ */
+
+struct pgp_command_context {
+  short need_passphrase;       /* %p */
+  const char *fname;           /* %f */
+  const char *sig_fname;       /* %s */
+  const char *signas;          /* %a */
+  const char *ids;             /* %r */
+};
+
+
+const char *_mutt_fmt_pgp_command (char *dest,
+                                  size_t destlen,
+                                  char op,
+                                  const char *src,
+                                  const char *prefix,
+                                  const char *ifstring,
+                                  const char *elsestring,
+                                  unsigned long data,
+                                  format_flag flags)
 {
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "%scat %s%s | %s +language=%s +pubring=%s +secring=%s +verbose=0 %s +batchmode -aeft%s %s%s %s",
-          sign ? "PGPPASSFD=0; export PGPPASSFD; " : "",
-          sign ? "- " : "",
-          _fname,
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), 
-          option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "",
-          sign ? "s" : "",
-          sign && PgpSignAs ? "-u " : "",
-          sign && PgpSignAs ? PgpSignAs : "",
-          uids);
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, 
-                              pgpinfd, pgpoutfd, pgperrfd);
+  char fmt[16];
+  struct pgp_command_context *cctx = (struct pgp_command_context *) data;
+  int optional = (flags & M_FORMAT_OPTIONAL);
+  
+  switch (op)
+  {
+    case 'r':
+    {
+      if (!optional)
+      {
+       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
+       snprintf (dest, destlen, fmt, NONULL (cctx->ids));
+      }
+      else if (!cctx->ids)
+       optional = 0;
+      break;
+    }
+    
+    case 'a':
+    {
+      if (!optional)
+      {
+       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
+       snprintf (dest, destlen, fmt, NONULL (cctx->signas));
+      }
+      else if (!cctx->signas)
+       optional = 0;
+      break;
+    }
+    
+    case 's':
+    {
+      if (!optional)
+      {
+       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
+       snprintf (dest, destlen, fmt, NONULL (cctx->sig_fname));
+      }
+      else if (!cctx->sig_fname)
+       optional = 0;
+      break;
+    }
+    
+    case 'f':
+    {
+      if (!optional)
+      {
+       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
+       snprintf (dest, destlen, fmt, NONULL (cctx->fname));
+      }
+      else if (!cctx->fname)
+       optional = 0;
+      break;
+    }
+    
+    case 'p':
+    {
+      if (!optional)
+      {
+       snprintf (fmt, sizeof (fmt), "%%%ss", prefix);
+       snprintf (dest, destlen, fmt, cctx->need_passphrase ? "PGPPASSFD=0" : "");
+      }
+      else if (!cctx->need_passphrase)
+       optional = 0;
+      break;
+    }
+  }
+  
+  if (optional)
+    mutt_FormatString (dest, destlen, ifstring, mutt_attach_fmt, data, 0);
+  else if (flags & M_FORMAT_OPTIONAL)
+    mutt_FormatString (dest, destlen, elsestring, mutt_attach_fmt, data, 0);
+  
+  return (src);
 }
 
-void pgp_v2_invoke_import(struct pgp_vinfo *pgp, const char *fname)
+void mutt_pgp_command (char *d, size_t dlen, struct pgp_command_context *cctx, const char *fmt)
 {
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%s +language=%s +pubring=%s +secring=%s -ka %s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), 
-          NONULL (secring), _fname);
-  mutt_system(cmd);
+  mutt_FormatString (d, dlen, NONULL (fmt), _mutt_fmt_pgp_command, (unsigned long) cctx, 0);
+  dprint (2, (debugfile, "mutt_pgp_command: %s\n", d));
 }
 
-pid_t pgp_v2_invoke_export(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
+/*
+ * Glue.
+ */
+
+
+static pid_t pgp_invoke (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd,
+                        short need_passphrase,
+                        const char *fname,
+                        const char *sig_fname,
+                        const char *signas,
+                        const char *ids,
+                        const char *format)
 {
+  struct pgp_command_context cctx;
   char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%s -kxaf +language=%s +pubring=%s +secring=%s 0x%8s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id);
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
+  
+  memset (&cctx, 0, sizeof (cctx));
+  
+  cctx.need_passphrase = need_passphrase;
+  cctx.fname          = fname;
+  cctx.sig_fname       = sig_fname;
+  cctx.signas         = signas;
+  cctx.ids            = ids;
+  
+  mutt_pgp_command (cmd, sizeof (cmd), &cctx, format);
+  
+  return mutt_create_filter_fd (cmd, pgpin, pgpout, pgperr,
                               pgpinfd, pgpoutfd, pgperrfd);
 }
 
-pid_t pgp_v2_invoke_verify_key(struct pgp_vinfo *pgp,
-                              FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                              int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
-{
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
 
-  snprintf(cmd, sizeof(cmd), "%s +language=%s +pubring=%s +secring=%s +batchmode -kcc 0x%8s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id);
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-/*******************************************************************
- * 
- * PGP V3 Invocation stuff
+/*
+ * The exported interface.
  * 
- *******************************************************************/
-
-pid_t pgp_v3_invoke_decode(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd,
-                          const char *fname, int need_passphrase)
-{
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%scat %s%s | "
-          "%sv +language=%s +pubring=%s +secring=%s +verbose=0 +batchmode -f "
-          "--OutputInformationFD=2",
-          need_passphrase ? "PGPPASSFD=0; export PGPPASSFD; " : "",
-          need_passphrase ? "- " : "",
-          _fname,
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring));
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_v3_invoke_verify(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd,
-                          const char *signedstuff, const char *sigfile)
-{
-  char _sig[_POSIX_PATH_MAX + SHORT_STRING];
-  char _sign[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_sig, sizeof (_sig), sigfile);
-  mutt_quote_filename (_sign, sizeof (_sign), signedstuff);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "%sv +language=%s +pubring=%s +secring=%s --OutputInformationFD=1 +batchmode +verbose=0 %s %s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), 
-          _sig, _sign);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_v3_invoke_encrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname, const char *uids, int sign)
-{
-  char *cp;
-  char *keylist;
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-  char tmpcmd[HUGE_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "%scat %s%s | %se +language=%s +pubring=%s +secring=%s +verbose=0 %s +batchmode +nobatchinvalidkeys=off -aft%s %s%s",
-          sign ? "PGPPASSFD=0; export PGPPASSFD; " : "",
-          sign ? "- " : "",
-          _fname,
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), 
-          option(OPTPGPENCRYPTSELF) ? "+encrypttoself" : "",
-          sign ? "s" : "",
-          sign && PgpSignAs ? "-u " : "",
-          sign && PgpSignAs ? PgpSignAs : "");
-
-  keylist = safe_strdup(uids);
+ * This is historic and may be removed at some point.
+ *
+ */
 
-  for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " "))
-  {
-    snprintf(tmpcmd, sizeof(tmpcmd), "%s -r %s", 
-            cmd, cp);
-    strcpy(cmd, tmpcmd);
-  }
-  safe_free((void **) &keylist);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, 
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
 
-pid_t pgp_v3_invoke_decrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname)
+pid_t pgp_invoke_decode (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd, 
+                        const char *fname, short need_passphrase)
 {
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "PGPPASSFD=0; export PGPPASSFD; cat - %s | %sv +language=%s +pubring=%s +secring=%s "
-          "+verbose=0 +batchmode -f --OutputInformationFD=2",
-          _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring));
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    need_passphrase, fname, NULL, NULL, NULL, 
+                    PgpDecodeCommand);
 }
 
-pid_t pgp_v3_invoke_sign(struct pgp_vinfo *pgp,
-                        FILE **pgpin, FILE **pgpout, FILE **pgperr,
+pid_t pgp_invoke_verify (FILE **pgpin, FILE **pgpout, FILE **pgperr,
                         int pgpinfd, int pgpoutfd, int pgperrfd, 
-                        const char *fname)
-{
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd),
-          "PGPPASSFD=0; export PGPPASSFD; cat - %s | %ss "
-          "+language=%s +pubring=%s +secring=%s +verbose=0 -abft %s %s",
-          _fname, NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring),
-          PgpSignAs ? "-u" : "",
-          PgpSignAs ? PgpSignAs : "");
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-void pgp_v3_invoke_import(struct pgp_vinfo *pgp, const char *fname)
+                        const char *fname, const char *sig_fname)
 {
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%sk +language=%s +pubring=%s +secring=%s -a --OutputInformationFD=1 %s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), _fname);
-  mutt_system(cmd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    0, fname, sig_fname, NULL, NULL, PgpVerifyCommand);
 }
 
-pid_t pgp_v3_invoke_export(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
+pid_t pgp_invoke_decrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                         int pgpinfd, int pgpoutfd, int pgperrfd, 
+                         const char *fname)
 {
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%sk -xa +language=%s +pubring=%s +secring=%s --OutputInformationFD=1 0x%8s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    1, fname, NULL, NULL, NULL, PgpDecryptCommand);
 }
 
-pid_t pgp_v3_invoke_verify_key(struct pgp_vinfo *pgp,
-                              FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                              int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
+pid_t pgp_invoke_sign (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                      int pgpinfd, int pgpoutfd, int pgperrfd, 
+                      const char *fname)
 {
-  char cmd[HUGE_STRING];
-  char pubring[_POSIX_PATH_MAX + SHORT_STRING];
-  char secring[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (pubring, sizeof (pubring), *pgp->pubring);
-  mutt_quote_filename (secring, sizeof (secring), *pgp->secring); 
-
-  snprintf(cmd, sizeof(cmd), "%sk +language=%s +pubring=%s +secring=%s +batchmode -c --OutputInformationFD=1 0x%8s",
-          NONULL(*pgp->binary), NONULL (*pgp->language), NONULL (pubring), NONULL (secring), id);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    1, fname, NULL, PgpSignAs, NULL, PgpSignCommand);
 }
 
-/*******************************************************************
- * 
- * GNU Privacy Guard invocation stuff
- * 
- * Credits go to Werner Koch for sending me the code on which this 
- * is based.
- * 
- *******************************************************************/
 
-pid_t pgp_gpg_invoke_decode(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname, int need_passphrase)
+pid_t pgp_invoke_encrypt (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                         int pgpinfd, int pgpoutfd, int pgperrfd,
+                         const char *fname, const char *uids, int sign)
 {
-  char cmd[HUGE_STRING];
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-
-  snprintf(cmd, sizeof(cmd),
-          "%s%s --no-verbose --batch  -o - %s",
-          NONULL(*pgp->binary), need_passphrase? " --passphrase-fd 0":"",
-          _fname);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_gpg_invoke_verify(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *signedstuff, const char *sigfile)
-{  
-  char _sig[_POSIX_PATH_MAX + SHORT_STRING];
-  char _sign[_POSIX_PATH_MAX + SHORT_STRING];
-  char cmd[HUGE_STRING];
-
-  mutt_quote_filename (_sig, sizeof (_sig), sigfile);
-  mutt_quote_filename (_sign, sizeof (_sign), signedstuff);
-
-  snprintf(cmd, sizeof(cmd),
-          "%s --no-verbose --batch  -o - "
-          "--verify %s %s",
-          NONULL(*pgp->binary), _sig, _sign);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  if (sign)
+    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                      1, fname, NULL, PgpSignAs, uids, 
+                      PgpEncryptSignCommand);
+  else
+    return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                      0, fname, NULL, NULL, uids, 
+                      PgpEncryptOnlyCommand);
 }
 
-pid_t pgp_gpg_invoke_decrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname)
+void pgp_invoke_import (const char *fname)
 {
   char _fname[_POSIX_PATH_MAX + SHORT_STRING];
   char cmd[HUGE_STRING];
-
+  struct pgp_command_context cctx;
+  
+  memset (&cctx, 0, sizeof (cctx));
+  
   mutt_quote_filename (_fname, sizeof (_fname), fname);
-
-  snprintf(cmd, sizeof(cmd),
-          "%s --passphrase-fd 0 --no-verbose --batch  -o - "
-          "--decrypt %s",
-          NONULL(*pgp->binary), _fname);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  cctx.fname = _fname;
+  
+  mutt_pgp_command (cmd, sizeof (cmd), &cctx, PgpImportCommand);
+  mutt_system (cmd);
 }
 
-static char *gpg_digalg(void)
+pid_t pgp_invoke_export (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                        int pgpinfd, int pgpoutfd, int pgperrfd, 
+                        const char *uids)
 {
-  static char digalg[STRING];
-  if(PgpSignMicalg && !mutt_strncasecmp(PgpSignMicalg, "pgp-", 4))
-    strfcpy(digalg, PgpSignMicalg + 4, sizeof(digalg));
-  else
-  {
-   /* We use md5 here as the default value as it's the good
-    * old default value for PGP and will be used in the
-    * message's headers.
-    */
-
-    strcpy(digalg, "md5");
-  }
-  return digalg;
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    0, NULL, NULL, NULL, uids,
+                    PgpExportCommand);
 }
 
-pid_t pgp_gpg_invoke_sign(struct pgp_vinfo *pgp,
-                        FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                        int pgpinfd, int pgpoutfd, int pgperrfd, 
-                        const char *fname)
+pid_t pgp_invoke_verify_key (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                            int pgpinfd, int pgpoutfd, int pgperrfd, 
+                            const char *uids)
 {
-  char cmd[HUGE_STRING];
-
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-
-  snprintf(cmd, sizeof(cmd),
-          "%s --no-verbose --batch  -o - "
-          "--passphrase-fd 0 --digest-algo %s "
-          "--detach-sign --textmode --armor %s%s %s",
-          NONULL(*pgp->binary),
-          gpg_digalg(),
-          PgpSignAs? "-u " : "",
-          PgpSignAs? PgpSignAs : "", _fname);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    0, NULL, NULL, NULL, uids,
+                    PgpVerifyKeyCommand);
 }
 
-pid_t pgp_gpg_invoke_encrypt(struct pgp_vinfo *pgp,
-                           FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                           int pgpinfd, int pgpoutfd, int pgperrfd,
-                           const char *fname, const char *uids, int sign)
+pid_t pgp_invoke_list_keys (FILE **pgpin, FILE **pgpout, FILE **pgperr,
+                           int pgpinfd, int pgpoutfd, int pgperrfd, 
+                           pgp_ring_t keyring, LIST *hints)
 {
-  char cmd[HUGE_STRING];
-  char tmpcmd[HUGE_STRING];
-  char *cp;
-  char *keylist;
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-
-  snprintf(cmd, sizeof(cmd),
-          "%s%s --no-verbose -v --batch  -o - "
-          "--digest-algo %s "
-          "--encrypt%s --textmode --armor --always-trust %s%s",
-          NONULL(*pgp->binary),
-          sign? " --passphrase-fd 0":"",
-          gpg_digalg(),
-          sign? " --sign":"",
-          PgpSignAs? "-u " : "",
-          PgpSignAs? PgpSignAs : "" );
+  char uids[HUGE_STRING];
+  char tmpuids[HUGE_STRING];
 
-  keylist = safe_strdup(uids);
-  for(cp = strtok(keylist, " "); cp ; cp = strtok(NULL, " "))
+  *uids = '\0';
+  
+  for (; hints; hints = hints->next)
   {
-    snprintf(tmpcmd, sizeof(tmpcmd), "%s -r %s",
-            cmd, cp);
-    strcpy(cmd, tmpcmd);
+    snprintf (tmpuids, sizeof (tmpuids), "%s %s", uids, (char *) hints->data);
+    strcpy (uids, tmpuids);
   }
-  safe_free((void **) &keylist);
-
-  snprintf(tmpcmd, sizeof(tmpcmd), "%s %s", cmd, _fname);
-  strcpy(cmd, tmpcmd);
 
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr, 
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-void pgp_gpg_invoke_import(struct pgp_vinfo *pgp, const char *fname)
-{
-  char cmd[HUGE_STRING];
-  char _fname[_POSIX_PATH_MAX + SHORT_STRING];
-
-  mutt_quote_filename (_fname, sizeof (_fname), fname);
-
-  snprintf(cmd, sizeof(cmd), "%sm --no-verbose --import -v %s",
-          NONULL(*pgp->binary), _fname);
-
-  mutt_system(cmd);
-}
-
-pid_t pgp_gpg_invoke_export(struct pgp_vinfo *pgp,
-                          FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                          int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
-{
-  char cmd[HUGE_STRING];
-
-  snprintf(cmd, sizeof(cmd), "%sm --no-verbose --export --armor 0x%8s",
-          NONULL(*pgp->binary), id);
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
-}
-
-pid_t pgp_gpg_invoke_verify_key(struct pgp_vinfo *pgp,
-                              FILE **pgpin, FILE **pgpout, FILE **pgperr,
-                              int pgpinfd, int pgpoutfd, int pgperrfd, const char *id)
-{
-  char cmd[HUGE_STRING];
-
-  snprintf(cmd, sizeof(cmd),
-          "%sm --no-verbose --batch --fingerprint --check-sigs %s%s",
-          NONULL(*pgp->binary), (mutt_strlen(id)==8 || mutt_strlen(id)==16)? "0x":"", id );
-
-  return mutt_create_filter_fd(cmd, pgpin, pgpout, pgperr,
-                              pgpinfd, pgpoutfd, pgperrfd);
+  return pgp_invoke (pgpin, pgpout, pgperr, pgpinfd, pgpoutfd, pgperrfd,
+                    0, NULL, NULL, NULL, uids,
+                    keyring == PGP_SECRING ? PgpListSecringCommand :
+                    PgpListPubringCommand);
 }
index 869fef00c861a8a32ccbec3f9f1873aeef21c4b1..b1c12a95acd5ee5d9597c392492b498c204741ca 100644 (file)
--- a/pgpkey.c
+++ b/pgpkey.c
@@ -381,15 +381,14 @@ static int pgp_compare_trust (const void *a, const void *b)
                                       : _pgp_compare_trust (a, b));
 }
 
-static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp,
-                                 pgp_key_t *keys,
+static pgp_key_t *pgp_select_key (pgp_key_t *keys,
                                  ADDRESS * p, const char *s)
 {
   int keymax;
   pgp_uid_t **KeyTable;
   MUTTMENU *menu;
   int i, done = 0;
-  char helpstr[SHORT_STRING], buf[LONG_STRING];
+  char helpstr[SHORT_STRING], buf[LONG_STRING], tmpbuf[STRING];
   char cmd[LONG_STRING], tempfile[_POSIX_PATH_MAX];
   FILE *fp, *devnull;
   pid_t thepid;
@@ -490,9 +489,10 @@ static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp,
 
       mutt_message _("Invoking PGP...");
 
-      if ((thepid = pgp->invoke_verify_key (pgp, NULL, NULL, NULL, -1,
-                   fileno (fp), fileno (devnull),
-                   pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent)))) == -1)
+      snprintf (tmpbuf, sizeof (tmpbuf), "0x%s", pgp_keyid (pgp_principal_key (KeyTable[menu->current]->parent)));
+
+      if ((thepid = pgp_invoke_verify_key (NULL, NULL, NULL, -1,
+                   fileno (fp), fileno (devnull), tmpbuf)) == -1)
       {
        mutt_perror _("Can't create filter");
        unlink (tempfile);
@@ -588,7 +588,7 @@ static pgp_key_t *pgp_select_key (struct pgp_vinfo *pgp,
   return (kp);
 }
 
-pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *pgp, char *tag, char *whatfor,
+pgp_key_t *pgp_ask_for_key (char *tag, char *whatfor,
                            short abilities, pgp_ring_t keyring)
 {
   pgp_key_t *key;
@@ -631,7 +631,7 @@ pgp_key_t *pgp_ask_for_key (struct pgp_vinfo *pgp, char *tag, char *whatfor,
       }
     }
 
-    if ((key = pgp_getkeybystr (pgp, resp, abilities, keyring)))
+    if ((key = pgp_getkeybystr (resp, abilities, keyring)))
       return key;
 
     BEEP ();
@@ -645,25 +645,19 @@ BODY *pgp_make_key_attachment (char *tempf)
 {
   BODY *att;
   char buff[LONG_STRING];
-  char tempfb[_POSIX_PATH_MAX];
-  char *id;
+  char tempfb[_POSIX_PATH_MAX], tmp[STRING];
   FILE *tempfp;
   FILE *devnull;
   struct stat sb;
   pid_t thepid;
   pgp_key_t *key;
-  struct pgp_vinfo *pgp = pgp_get_vinfo (PGP_EXPORT);
-
-  if (!pgp)
-    return NULL;
-
   unset_option (OPTPGPCHECKTRUST);
 
-  key = pgp_ask_for_key (pgp, _("Please enter the key ID: "), NULL, 0, PGP_PUBRING);
+  key = pgp_ask_for_key (_("Please enter the key ID: "), NULL, 0, PGP_PUBRING);
 
   if (!key)    return NULL;
 
-  id = safe_strdup (pgp_keyid (pgp_principal_key(key)));
+  snprintf (tmp, sizeof (tmp), "0x%s", pgp_keyid (pgp_principal_key (key)));
   pgp_free_key (&key);
   
   if (!tempf)
@@ -675,14 +669,12 @@ BODY *pgp_make_key_attachment (char *tempf)
   if ((tempfp = safe_fopen (tempf, tempf == tempfb ? "w" : "a")) == NULL)
   {
     mutt_perror _("Can't create temporary file");
-    safe_free ((void **) &id);
     return NULL;
   }
 
   if ((devnull = fopen ("/dev/null", "w")) == NULL)
   {
     mutt_perror _("Can't open /dev/null");
-    safe_free ((void **) &id);
     fclose (tempfp);
     if (tempf == tempfb)
       unlink (tempf);
@@ -690,16 +682,16 @@ BODY *pgp_make_key_attachment (char *tempf)
   }
 
   mutt_message _("Invoking pgp...");
+
   
   if ((thepid = 
-       pgp->invoke_export (pgp, NULL, NULL, NULL, -1,
-                          fileno (tempfp), fileno (devnull), id)) == -1)
+       pgp_invoke_export (NULL, NULL, NULL, -1,
+                          fileno (tempfp), fileno (devnull), tmp)) == -1)
   {
     mutt_perror _("Can't create filter");
     unlink (tempf);
     fclose (tempfp);
     fclose (devnull);
-    safe_free ((void **) &id);
     return NULL;
   }
 
@@ -713,14 +705,13 @@ BODY *pgp_make_key_attachment (char *tempf)
   att->unlink = 1;
   att->type = TYPEAPPLICATION;
   att->subtype = safe_strdup ("pgp-keys");
-  snprintf (buff, sizeof (buff), _("PGP Key 0x%s."), id);
+  snprintf (buff, sizeof (buff), _("PGP Key %s."), tmp);
   att->description = safe_strdup (buff);
   mutt_update_encoding (att);
 
   stat (tempf, &sb);
   att->length = sb.st_size;
 
-  safe_free ((void **) &id);
   return att;
 }
 
@@ -741,8 +732,7 @@ static LIST *pgp_add_string_to_hints (LIST *hints, const char *str)
 }
 
 
-pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp,
-                         ADDRESS * a, short abilities, pgp_ring_t keyring)
+pgp_key_t *pgp_getkeybyaddr (ADDRESS * a, short abilities, pgp_ring_t keyring)
 {
   ADDRESS *r, *p;
   LIST *hints = NULL;
@@ -760,7 +750,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp,
     hints = pgp_add_string_to_hints (hints, a->personal);
 
   mutt_message (_("Looking for keys matching \"%s\"..."), a->mailbox);
-  keys = pgp->get_candidates (pgp, keyring, hints);
+  keys = pgp_get_candidates (keyring, hints);
 
   mutt_free_list (&hints);
   
@@ -850,7 +840,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp,
     if (matches->next || weak)
     {
       /* query for which key the user wants */
-      k = pgp_select_key (pgp, matches, a, NULL);
+      k = pgp_select_key (matches, a, NULL);
       if (k) 
        pgp_remove_key (&matches, k);
 
@@ -865,8 +855,7 @@ pgp_key_t *pgp_getkeybyaddr (struct pgp_vinfo * pgp,
   return NULL;
 }
 
-pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp,
-                        char *p, short abilities, pgp_ring_t keyring)
+pgp_key_t *pgp_getkeybystr (char *p, short abilities, pgp_ring_t keyring)
 {
   LIST *hints = NULL;
   pgp_key_t *keys;
@@ -879,7 +868,7 @@ pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp,
   mutt_message (_("Looking for keys matching \"%s\"..."), p);
   
   hints = pgp_add_string_to_hints (hints, p);
-  keys = pgp->get_candidates (pgp, keyring, hints);
+  keys = pgp_get_candidates (keyring, hints);
   mutt_free_list (&hints);
 
   if (!keys)
@@ -936,7 +925,7 @@ pgp_key_t *pgp_getkeybystr (struct pgp_vinfo * pgp,
 
   if (matches)
   {
-    k = pgp_select_key (pgp, matches, NULL, p);
+    k = pgp_select_key (matches, NULL, p);
     if (k) 
       pgp_remove_key (&matches, k);
     
diff --git a/pgplib.c b/pgplib.c
new file mode 100644 (file)
index 0000000..40e395e
--- /dev/null
+++ b/pgplib.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 1997-1999 Thomas Roessler <roessler@guug.de>
+ * 
+ *     This program is free software; you can redistribute it
+ *     and/or modify it under the terms of the GNU General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2 of the License, or (at your option) any later
+ *     version.
+ * 
+ *     This program is distributed in the hope that it will be
+ *     useful, but WITHOUT ANY WARRANTY; without even the implied
+ *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *     PURPOSE.  See the GNU General Public License for more
+ *     details.
+ * 
+ *     You should have received a copy of the GNU General Public
+ *     License along with this program; if not, write to the Free
+ *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ *     02139, USA.
+ */
+
+/* Generally useful, pgp-related functions. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "lib.h"
+#include "pgplib.h"
+
+const char *pgp_pkalgbytype (unsigned char type)
+{
+  switch (type)
+  {
+  case 1:
+    return "RSA";
+  case 2:
+    return "RSA";
+  case 3:
+    return "RSA";
+  case 16:
+    return "ElG";
+  case 17:
+    return "DSA";
+  case 20:
+    return "ElG";
+  default:
+    return "unk";
+  }
+}
+
+
+static struct
+{
+  char *pkalg;
+  char *micalg;
+}
+pktomic[] =
+{
+  {
+    "RSA", "pgp-md5"
+  }
+  ,
+  {
+    "ElG", "pgp-rmd160"
+  }
+  ,
+  {
+    "DSA", "pgp-sha1"
+  }
+  ,
+  {
+    NULL, "x-unknown"
+  }
+};
+
+
+const char *pgp_pkalg_to_mic (const char *alg)
+{
+  int i;
+
+  for (i = 0; pktomic[i].pkalg; i++)
+  {
+    if (!mutt_strcasecmp (pktomic[i].pkalg, alg))
+      break;
+  }
+
+  return pktomic[i].micalg;
+}
+
+
+/* unused */
+
+#if 0
+
+static const char *hashalgbytype (unsigned char type)
+{
+  switch (type)
+  {
+  case 1:
+    return "MD5";
+  case 2:
+    return "SHA1";
+  case 3:
+    return "RIPE-MD/160";
+  case 4:
+    return "HAVAL";
+  default:
+    return "unknown";
+  }
+}
+
+#endif
+
+short pgp_canencrypt (unsigned char type)
+{
+  switch (type)
+  {
+  case 1:
+  case 2:
+  case 16:
+  case 20:
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+short pgp_cansign (unsigned char type)
+{
+  switch (type)
+  {
+  case 1:
+  case 3:
+  case 17:
+  case 20:
+    return 1;
+  default:
+    return 0;
+  }
+}
+
+/* return values: 
+
+ * 1 = sign only
+ * 2 = encrypt only
+ * 3 = both
+ */
+
+short pgp_get_abilities (unsigned char type)
+{
+  return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
+}
+
+void pgp_free_uid (pgp_uid_t ** upp)
+{
+  pgp_uid_t *up, *q;
+
+  if (!upp || !*upp)
+    return;
+  for (up = *upp; up; up = q)
+  {
+    q = up->next;
+    safe_free ((void **) &up->addr);
+    safe_free ((void **) &up);
+  }
+
+  *upp = NULL;
+}
+
+pgp_uid_t *pgp_copy_uids (pgp_uid_t *up, pgp_key_t *parent)
+{
+  pgp_uid_t *l = NULL;
+  pgp_uid_t **lp = &l;
+
+  for (; up; up = up->next)
+  {
+    *lp = safe_calloc (1, sizeof (pgp_uid_t));
+    (*lp)->trust  = up->trust;
+    (*lp)->addr   = safe_strdup (up->addr);
+    (*lp)->parent = parent;
+    lp = &(*lp)->next;
+  }
+
+  return l;
+}
+
+static void _pgp_free_key (pgp_key_t ** kpp)
+{
+  pgp_key_t *kp;
+
+  if (!kpp || !*kpp)
+    return;
+
+  kp = *kpp;
+
+  pgp_free_uid (&kp->address);
+  safe_free ((void **) &kp->keyid);
+  safe_free ((void **) kpp);
+}
+
+pgp_key_t *pgp_remove_key (pgp_key_t ** klist, pgp_key_t * key)
+{
+  pgp_key_t **last;
+  pgp_key_t *p, *q, *r;
+
+  if (!klist || !*klist || !key)
+    return NULL;
+
+  if (key->parent && key->parent != key)
+    key = key->parent;
+
+  last = klist;
+  for (p = *klist; p && p != key; p = p->next)
+    last = &p->next;
+
+  if (!p)
+    return NULL;
+
+  for (q = p->next, r = p; q && q->parent == p; q = q->next)
+    r = q;
+
+  if (r)
+    r->next = NULL;
+
+  *last = q;
+  return q;
+}
+
+void pgp_free_key (pgp_key_t ** kpp)
+{
+  pgp_key_t *p, *q, *r;
+
+  if (!kpp || !*kpp)
+    return;
+
+  if ((*kpp)->parent && (*kpp)->parent != *kpp)
+    *kpp = (*kpp)->parent;
+  
+  /* Order is important here:
+   *
+   * - First free all children.
+   * - If we are an orphan (i.e., our parent was not in the key list),
+   *   free our parent.
+   * - free ourselves.
+   */
+
+  for (p = *kpp; p; p = q)
+  {
+    for (q = p->next; q && q->parent == p; q = r)
+    {
+      r = q->next;
+      _pgp_free_key (&q);
+    }
+    if (p->parent)
+      _pgp_free_key (&p->parent);
+
+    _pgp_free_key (&p);
+  }
+
+  *kpp = NULL;
+}
+
diff --git a/pgplib.h b/pgplib.h
new file mode 100644 (file)
index 0000000..2f4c5bf
--- /dev/null
+++ b/pgplib.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 1996,1997 Michael R. Elkins <me@cs.hmc.edu>
+ * Copyright (C) 1999 Thoms Roessler <roessler@guug.de>
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ * 
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ * 
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef _PGPPATH
+
+#define PGPENCRYPT 1
+#define PGPSIGN    2
+#define PGPKEY     4
+
+#define KEYFLAG_CANSIGN                (1 <<  0)
+#define KEYFLAG_CANENCRYPT             (1 <<  1)
+#define KEYFLAG_SECRET                 (1 <<  7)
+#define KEYFLAG_EXPIRED                (1 <<  8)
+#define KEYFLAG_REVOKED                (1 <<  9)
+#define KEYFLAG_DISABLED               (1 << 10)
+#define KEYFLAG_SUBKEY                         (1 << 11)
+#define KEYFLAG_CRITICAL               (1 << 12)
+#define KEYFLAG_PREFER_ENCRYPTION      (1 << 13)
+#define KEYFLAG_PREFER_SIGNING                 (1 << 14)
+
+#define KEYFLAG_CANTUSE (KEYFLAG_DISABLED|KEYFLAG_REVOKED|KEYFLAG_EXPIRED)
+#define KEYFLAG_RESTRICTIONS (KEYFLAG_CANTUSE|KEYFLAG_CRITICAL)
+
+#define KEYFLAG_ABILITIES (KEYFLAG_CANSIGN|KEYFLAG_CANENCRYPT|KEYFLAG_PREFER_ENCRYPTION|KEYFLAG_PREFER_SIGNING)
+
+typedef struct pgp_keyinfo
+{
+  char *keyid;
+  struct pgp_uid *address;
+  int flags;
+  short keylen;
+  time_t gen_time;
+  int numalg;
+  const char *algorithm;
+  struct pgp_keyinfo *parent;
+  struct pgp_keyinfo *next;
+}
+pgp_key_t;
+
+typedef struct pgp_uid
+{
+  char *addr;
+  short trust;
+  struct pgp_keyinfo *parent;
+  struct pgp_uid *next;
+}
+pgp_uid_t;
+
+enum pgp_version
+{
+  PGP_V2,
+  PGP_V3,
+  PGP_GPG,
+  PGP_UNKNOWN
+};
+
+enum pgp_ring
+{
+  PGP_PUBRING,
+  PGP_SECRING
+};
+
+typedef enum pgp_ring pgp_ring_t;
+
+/* prototypes */
+
+const char *pgp_pkalg_to_mic (const char *);
+const char *pgp_pkalgbytype (unsigned char);
+
+pgp_key_t *pgp_remove_key (pgp_key_t **, pgp_key_t *);
+pgp_uid_t *pgp_copy_uids (pgp_uid_t *, pgp_key_t *);
+
+short pgp_canencrypt (unsigned char);
+short pgp_cansign (unsigned char);
+short pgp_get_abilities (unsigned char);
+
+void pgp_free_key (pgp_key_t **kpp);
+
+#define pgp_new_keyinfo() safe_calloc (sizeof (pgp_key_t), 1)
+
+#endif /* _PGPPATH */
index ad001e781bc592d0a44ff24374fdd56a24290880..ff3c27f74040957997d66c9f0a4d675f694afca5 100644 (file)
  *     02139, USA.
  */
 
+/*
+ * This is a "simple" PGP key ring dumper.
+ * 
+ * The output format is supposed to be compatible to the one GnuPG
+ * emits and Mutt expects.
+ * 
+ * Note that the code of this program could be considerably less
+ * complex, but most of it was taken from mutt's second generation
+ * key ring parser.
+ * 
+ * You can actually use this to put together some fairly general
+ * PGP key management applications.
+ *
+ */
+
+
+#include "config.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
 
+#ifdef HAVE_GETOPT_H
+# include <getopt.h>
+#endif
+
 #include "sha.h"
-#include "mutt.h"
-#include "pgp.h"
-#include "charset.h"
+#include "lib.h"
+#include "pgplib.h"
 
 #define CHUNKSIZE 1024
 
 static unsigned char *pbuf = NULL;
 static size_t plen = 0;
 
+static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints);
+static void pgpring_dump_keyblock (pgp_key_t *p);
+
+int main (int argc, char * const argv[])
+{
+  int c;
+  
+  char kring[_POSIX_PATH_MAX];
+  char *pgppath;
+
+  if ((pgppath = getenv ("PGPPATH")))
+    snprintf (kring, sizeof (kring), "%s/%s", pgppath, "pubring.pgp");
+  else
+    *kring = '\0';
+  
+  while ((c = getopt (argc, argv, "k:")) != EOF)
+  {
+    if (c == 'k')
+      strfcpy (kring, optarg, sizeof (kring));
+    else
+    {
+      fprintf (stderr, "usage: %s [-k key ring] [hints]\n",
+              argv[0]);
+      exit (1);
+    }
+  }
+  
+  pgpring_find_candidates (kring, argv + optind, argc - optind);
+    
+  return 0;
+}
+              
+
+
+
 enum packet_tags
 {
   PT_RES0 = 0,                 /* reserved */
@@ -57,151 +112,34 @@ enum packet_tags
   PT_COMMENT                   /* Comment Packet */
 };
 
-/* FIXME I can't find where those strings are displayed! */
-const char *pgp_packet_name[] =
-{
-  N_("reserved"),
-  N_("Encrypted Session Key"),
-  N_("Signature Packet"),
-  N_("Conventionally Encrypted Session Key Packet"),
-  N_("One-Pass Signature Packet"),
-  N_("Secret Key Packet"),
-  N_("Public Key Packet"),
-  N_("Secret Subkey Packet"),
-  N_("Compressed Data Packet"),
-  N_("Symmetrically Encrypted Data Packet"),
-  N_("Marker Packet"),
-  N_("Literal Data Packet"),
-  N_("Trust Packet"),
-  N_("Name Packet"),
-  N_("Subkey Packet"),
-  N_("Reserved"),
-  N_("Comment Packet")
-};
-
-const char *pgp_pkalgbytype (unsigned char type)
-{
-  switch (type)
-  {
-  case 1:
-    return "RSA";
-  case 2:
-    return "RSA";
-  case 3:
-    return "RSA";
-  case 16:
-    return "ElG";
-  case 17:
-    return "DSA";
-  case 20:
-    return "ElG";
-  default:
-    return "unk";
-  }
-}
-
-
-static struct
-{
-  char *pkalg;
-  char *micalg;
-}
-pktomic[] =
-{
-  {
-    "RSA", "pgp-md5"
-  }
-  ,
-  {
-    "ElG", "pgp-rmd160"
-  }
-  ,
-  {
-    "DSA", "pgp-sha1"
-  }
-  ,
-  {
-    NULL, "x-unknown"
-  }
-};
-
-
-const char *pgp_pkalg_to_mic (const char *alg)
-{
-  int i;
-
-  for (i = 0; pktomic[i].pkalg; i++)
-  {
-    if (!mutt_strcasecmp (pktomic[i].pkalg, alg))
-      break;
-  }
-
-  return pktomic[i].micalg;
-}
-
-
-/* unused */
-
-#if 0
-
-static const char *hashalgbytype (unsigned char type)
-{
-  switch (type)
-  {
-  case 1:
-    return "MD5";
-  case 2:
-    return "SHA1";
-  case 3:
-    return "RIPE-MD/160";
-  case 4:
-    return "HAVAL";
-  default:
-    return "unknown";
-  }
-}
-
-#endif
-
-short pgp_canencrypt (unsigned char type)
-{
-  switch (type)
-  {
-  case 1:
-  case 2:
-  case 16:
-  case 20:
-    return 1;
-  default:
-    return 0;
-  }
-}
-
-short pgp_cansign (unsigned char type)
-{
-  switch (type)
-  {
-  case 1:
-  case 3:
-  case 17:
-  case 20:
-    return 1;
-  default:
-    return 0;
-  }
-}
-
-/* return values: 
-
- * 1 = sign only
- * 2 = encrypt only
- * 3 = both
+/* 
+ * These aren't displayed at all currently, but they may come quite
+ * handy for debugging strings.
+ * 
+ * No need to translate them.
+ *
  */
 
-short pgp_get_abilities (unsigned char type)
+const char *pgp_packet_name[] =
 {
-  return (pgp_canencrypt (type) << 1) | pgp_cansign (type);
-}
+  "reserved",
+  "Encrypted Session Key",
+  "Signature Packet",
+  "Conventionally Encrypted Session Key Packet",
+  "One-Pass Signature Packet",
+  "Secret Key Packet",
+  "Public Key Packet",
+  "Secret Subkey Packet",
+  "Compressed Data Packet",
+  "Symmetrically Encrypted Data Packet",
+  "Marker Packet",
+  "Literal Data Packet",
+  "Trust Packet",
+  "Name Packet",
+  "Subkey Packet",
+  "Reserved",
+  "Comment Packet"
+};
 
 static int read_material (size_t material, size_t * used, FILE * fp)
 {
@@ -214,7 +152,7 @@ static int read_material (size_t material, size_t * used, FILE * fp)
 
     if (!(p = realloc (pbuf, nplen)))
     {
-      mutt_perror ("realloc");
+      perror ("realloc");
       return -1;
     }
     plen = nplen;
@@ -223,7 +161,7 @@ static int read_material (size_t material, size_t * used, FILE * fp)
 
   if (fread (pbuf + *used, 1, material, fp) < material)
   {
-    mutt_perror ("fread");
+    perror ("fread");
     return -1;
   }
 
@@ -250,7 +188,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
   if (fread (&ctb, 1, 1, fp) < 1)
   {
     if (!feof (fp))
-      mutt_perror ("fread");
+      perror ("fread");
     goto bail;
   }
 
@@ -269,7 +207,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
     {
       if (fread (&b, 1, 1, fp) < 1)
       {
-       mutt_perror ("fread");
+       perror ("fread");
        goto bail;
       }
 
@@ -284,7 +222,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
        material = (b - 192) * 256;
        if (fread (&b, 1, 1, fp) < 1)
        {
-         mutt_perror ("fread");
+         perror ("fread");
          goto bail;
        }
        material += b + 192;
@@ -303,7 +241,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
        unsigned char buf[4];
        if (fread (buf, 4, 1, fp) < 1)
        {
-         mutt_perror ("fread");
+         perror ("fread");
          goto bail;
        }
        /*assert( sizeof(material) >= 4 ); */
@@ -334,7 +272,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
       {
        if (fread (&b, 1, 1, fp) < 1)
        {
-         mutt_perror ("fread");
+         perror ("fread");
          goto bail;
        }
 
@@ -358,7 +296,7 @@ static unsigned char *pgp_read_packet (FILE * fp, size_t * len)
        {
          if (fread (&b, 1, 1, fp) < 1)
          {
-           mutt_perror ("fread");
+           perror ("fread");
            goto bail;
          }
 
@@ -386,120 +324,6 @@ bail:
   return NULL;
 }
 
-static pgp_key_t *pgp_new_keyinfo (void)
-{
-  return safe_calloc (sizeof (pgp_key_t), 1);
-}
-
-void pgp_free_uid (pgp_uid_t ** upp)
-{
-  pgp_uid_t *up, *q;
-
-  if (!upp || !*upp)
-    return;
-  for (up = *upp; up; up = q)
-  {
-    q = up->next;
-    safe_free ((void **) &up->addr);
-    safe_free ((void **) &up);
-  }
-
-  *upp = NULL;
-}
-
-pgp_uid_t *pgp_copy_uids (pgp_uid_t *up, pgp_key_t *parent)
-{
-  pgp_uid_t *l = NULL;
-  pgp_uid_t **lp = &l;
-
-  for (; up; up = up->next)
-  {
-    *lp = safe_calloc (1, sizeof (pgp_uid_t));
-    (*lp)->trust  = up->trust;
-    (*lp)->addr   = safe_strdup (up->addr);
-    (*lp)->parent = parent;
-    lp = &(*lp)->next;
-  }
-
-  return l;
-}
-
-static void _pgp_free_key (pgp_key_t ** kpp)
-{
-  pgp_key_t *kp;
-
-  if (!kpp || !*kpp)
-    return;
-
-  kp = *kpp;
-
-  pgp_free_uid (&kp->address);
-  safe_free ((void **) &kp->keyid);
-  safe_free ((void **) kpp);
-}
-
-pgp_key_t *pgp_remove_key (pgp_key_t ** klist, pgp_key_t * key)
-{
-  pgp_key_t **last;
-  pgp_key_t *p, *q, *r;
-
-  if (!klist || !*klist || !key)
-    return NULL;
-
-  if (key->parent && key->parent != key)
-    key = key->parent;
-
-  last = klist;
-  for (p = *klist; p && p != key; p = p->next)
-    last = &p->next;
-
-  if (!p)
-    return NULL;
-
-  for (q = p->next, r = p; q && q->parent == p; q = q->next)
-    r = q;
-
-  if (r)
-    r->next = NULL;
-
-  *last = q;
-  return q;
-}
-
-void pgp_free_key (pgp_key_t ** kpp)
-{
-  pgp_key_t *p, *q, *r;
-
-  if (!kpp || !*kpp)
-    return;
-
-  if ((*kpp)->parent && (*kpp)->parent != *kpp)
-    *kpp = (*kpp)->parent;
-  
-  /* Order is important here:
-   *
-   * - First free all children.
-   * - If we are an orphan (i.e., our parent was not in the key list),
-   *   free our parent.
-   * - free ourselves.
-   */
-
-  for (p = *kpp; p; p = q)
-  {
-    for (q = p->next; q && q->parent == p; q = r)
-    {
-      r = q->next;
-      _pgp_free_key (&q);
-    }
-    if (p->parent)
-      _pgp_free_key (&p->parent);
-
-    _pgp_free_key (&p);
-  }
-
-  *kpp = NULL;
-}
-
 static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l)
 {
   pgp_key_t *p;
@@ -515,7 +339,7 @@ static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l)
   if (l < 12)
     return NULL;
 
-  p = pgp_new_keyinfo ();
+  p = pgp_new_keyinfo();
 
   for (i = 0, j = 2; i < 4; i++)
     gen_time = (gen_time << 8) + buff[j++];
@@ -530,6 +354,7 @@ static pgp_key_t *pgp_parse_pgp2_key (unsigned char *buff, size_t l)
 
   alg = buff[j++];
 
+  p->numalg = alg;
   p->algorithm = pgp_pkalgbytype (alg);
   p->flags |= pgp_get_abilities (alg);
 
@@ -628,6 +453,7 @@ static pgp_key_t *pgp_parse_pgp3_key (unsigned char *buff, size_t l)
 
   alg = buff[j++];
 
+  p->numalg = alg;
   p->algorithm = pgp_pkalgbytype (alg);
   p->flags |= pgp_get_abilities (alg);
 
@@ -665,8 +491,6 @@ static pgp_key_t *pgp_parse_keyinfo (unsigned char *buff, size_t l)
   if (!buff || l < 2)
     return NULL;
 
-  dprint (5, (debugfile, " version: %d ", buff[1]));
-
   switch (buff[1])
   {
   case 2:
@@ -876,8 +700,6 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp)
   pgp_uid_t *uid = NULL;
   pgp_uid_t **addr = NULL;
   
-  CHARSET *chs = mutt_get_charset (Charset);
-
   fgetpos (fp, &pos);
   
   while (!err && (buff = pgp_read_packet (fp, &l)) != NULL)
@@ -919,33 +741,32 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp)
            while (*addr) addr = &(*addr)->next;
          }
        }
+       
+       if (pt == PT_SECKEY || pt == PT_SUBSECKEY)
+         p->flags |= KEYFLAG_SECRET;
+
        break;
       }
 
       case PT_SIG:
       {
-       dprint (5, (debugfile, "PT_SIG\n"));
        pgp_parse_sig (buff, l, p);
        break;
       }
 
       case PT_TRUST:
       {
-       dprint (5, (debugfile, "PT_TRUST: "));
        if (p && (last_pt == PT_SECKEY || last_pt == PT_PUBKEY ||
                  last_pt == PT_SUBKEY || last_pt == PT_SUBSECKEY))
        {
          if (buff[1] & 0x20)
          {
-           dprint (5, (debugfile, " disabling %s\n", p->keyid));
            p->flags |= KEYFLAG_DISABLED;
          }
        }
        else if (last_pt == PT_NAME && uid)
        {
          uid->trust = buff[1];
-         dprint (5, (debugfile, " setting trust for \"%s\" to %d.\n",
-                     uid->addr, uid->trust));
        }
        break;
       }
@@ -953,7 +774,6 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp)
       {
        char *chr;
 
-       dprint (5, (debugfile, "PT_NAME: "));
 
        if (!addr)
          break;
@@ -962,9 +782,7 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp)
        memcpy (chr, buff + 1, l - 1);
        chr[l - 1] = '\0';
 
-       dprint (5, (debugfile, "\"%s\"\n", chr));
 
-       mutt_decode_utf8_string (chr, chs);
        *addr = uid = safe_calloc (1, sizeof (pgp_uid_t)); /* XXX */
        uid->addr = chr;
        uid->parent = p;
@@ -993,28 +811,29 @@ static pgp_key_t *pgp_parse_keyblock (FILE * fp)
   return root;  
 }
 
-int pgp_string_matches_hint (const char *s, LIST * hints)
+static int pgpring_string_matches_hint (const char *s, const char *hints[], int nhints)
 {
-  if (!hints)
+  int i;
+
+  if (!hints || !nhints)
     return 1;
 
-  for (; hints; hints = hints->next)
+  for (i = 0; i < nhints; i++)
   {
-    if (mutt_stristr (s, (char *) hints->data) != NULL)
+    if (mutt_stristr (s, hints[i]) != NULL)
       return 1;
   }
 
   return 0;
 }
 
-/* Go through the key ring file and look for keys with
+/* 
+ * Go through the key ring file and look for keys with
  * matching IDs.
  */
 
-pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
-                              LIST * hints)
+static void pgpring_find_candidates (char *ringfile, const char *hints[], int nhints)
 {
-  char *ringfile;
   FILE *rfp;
   fpos_t pos, keypos;
 
@@ -1022,28 +841,12 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
   unsigned char pt = 0;
   size_t l = 0;
 
-  CHARSET *chs = mutt_get_charset (Charset);
-
-  pgp_key_t *keys = NULL;
-  pgp_key_t **last = &keys;
   short err = 0;
-
-  switch (keyring)
-  {
-    case PGP_PUBRING:
-      ringfile = *pgp->pubring;
-      break;
-    case PGP_SECRING:
-      ringfile = *pgp->secring;
-      break;
-    default:
-      return NULL;
-  }
-
+  
   if ((rfp = fopen (ringfile, "r")) == NULL)
   {
-    mutt_perror ("fopen");
-    return NULL;
+    perror ("fopen");
+    return;
   }
 
   fgetpos (rfp, &pos);
@@ -1066,9 +869,10 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
 
       memcpy (tmp, buff + 1, l - 1);
       tmp[l - 1] = '\0';
-      mutt_decode_utf8_string (tmp, chs);
 
-      if (pgp_string_matches_hint (tmp, hints))
+      /* mutt_decode_utf8_string (tmp, chs); */
+
+      if (pgpring_string_matches_hint (tmp, hints, nhints))
       {
        pgp_key_t *p;
 
@@ -1076,11 +880,11 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
 
        /* Not bailing out here would lead us into an endless loop. */
 
-       if ((*last = pgp_parse_keyblock (rfp)) == NULL)
+       if ((p = pgp_parse_keyblock (rfp)) == NULL)
          err = 1;
-
-       for (p = *last; p; p = p->next)
-         last = &p->next;
+       
+       pgpring_dump_keyblock (p);
+       pgp_free_key (&p);
       }
 
       safe_free ((void **) &tmp);
@@ -1091,5 +895,86 @@ pgp_key_t *pgp_get_candidates (struct pgp_vinfo * pgp, pgp_ring_t keyring,
 
   fclose (rfp);
 
-  return keys;
 }
+
+static void print_userid (const char *id)
+{
+  for (; id && *id; id++)
+  {
+    if (*id >= ' ' && *id <= 'z' && *id != ':')
+      putchar (*id);
+    else
+      printf ("\\x%02x", *id);
+  }
+}
+
+static char gnupg_trustletter (int t)
+{
+  switch (t)
+  {
+    case 1: return 'n';
+    case 2: return 'm';
+    case 3: return 'f';
+  }
+  return 'q';
+}
+
+static void pgpring_dump_keyblock (pgp_key_t *p)
+{
+  pgp_uid_t *uid;
+  short first;
+  struct tm *tp;
+  time_t t;
+  
+  for (; p; p = p->next)
+  {
+    first = 1;
+
+    if (p->flags & KEYFLAG_SECRET)
+    {
+      if (p->flags & KEYFLAG_SUBKEY)
+       printf ("ssb:");
+      else
+       printf ("sec:");
+    }
+    else 
+    {
+      if (p->flags & KEYFLAG_SUBKEY)
+       printf ("sub:");
+      else
+       printf ("pub:");
+    }
+    
+    if (p->flags & KEYFLAG_REVOKED)
+      putchar ('r');
+    if (p->flags & KEYFLAG_EXPIRED)
+      putchar ('e');
+    
+    for (uid = p->address; uid; uid = uid->next, first = 0)
+    {
+      if (!first)
+      {
+       printf ("uid:%c::::::::", gnupg_trustletter (uid->trust));
+       print_userid (uid->addr);
+       printf (":\n");
+      }
+      else
+      {
+       if (p->flags & KEYFLAG_SECRET)
+         putchar ('u');
+       else
+         putchar (gnupg_trustletter (uid->trust));
+
+       t = p->gen_time;
+       tp = gmtime (&t);
+
+       printf (":%d:%d:%s:%04d-%02d-%02d::::", p->keylen, p->numalg, p->keyid,
+               1900 + tp->tm_year, tp->tm_mon + 1, tp->tm_mday);
+       
+       print_userid (uid->addr);
+       printf (":\n");
+      }
+    }
+  }
+}
+