* g10.c (main): Use 3DES instead of CAST5 if we don't have CAST5 support.
[gnupg.git] / g10 / g10.c
index 70c609c..3f1126e 100644 (file)
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <assert.h>
 #ifdef HAVE_DOSISH_SYSTEM
   #include <fcntl.h> /* for setmode() */
 #endif
 #ifdef HAVE_DOSISH_SYSTEM
   #include <fcntl.h> /* for setmode() */
 #endif
@@ -64,6 +65,7 @@ enum cmd_and_opt_values { aNull = 0,
     oOutput      = 'o',
     oQuiet       = 'q',
     oRecipient   = 'r',
     oOutput      = 'o',
     oQuiet       = 'q',
     oRecipient   = 'r',
+    oHiddenRecipient = 'R',
     aSign        = 's',
     oTextmodeShort= 't',
     oUser        = 'u',
     aSign        = 's',
     oTextmodeShort= 't',
     oUser        = 'u',
@@ -139,6 +141,7 @@ enum cmd_and_opt_values { aNull = 0,
     oAnswerNo,
     oDefCertCheckLevel,
     oKeyring,
     oAnswerNo,
     oDefCertCheckLevel,
     oKeyring,
+    oPrimaryKeyring,
     oSecretKeyring,
     oShowKeyring,
     oDefaultKey,
     oSecretKeyring,
     oShowKeyring,
     oDefaultKey,
@@ -172,6 +175,8 @@ enum cmd_and_opt_values { aNull = 0,
     oNoPGP6,
     oPGP7,
     oNoPGP7,
     oNoPGP6,
     oPGP7,
     oNoPGP7,
+    oPGP8,
+    oNoPGP8,
     oCipherAlgo,
     oDigestAlgo,
     oCertDigestAlgo,
     oCipherAlgo,
     oDigestAlgo,
     oCertDigestAlgo,
@@ -203,6 +208,8 @@ enum cmd_and_opt_values { aNull = 0,
     oCompressKeys,
     oCompressSigs,
     oAlwaysTrust,
     oCompressKeys,
     oCompressSigs,
     oAlwaysTrust,
+    oTrustModel,
+    oForceOwnertrust,
     oEmuChecksumBug,
     oRunAsShmCP,
     oSetFilename,
     oEmuChecksumBug,
     oRunAsShmCP,
     oSetFilename,
@@ -217,6 +224,7 @@ enum cmd_and_opt_values { aNull = 0,
     oComment,
     oDefaultComment,
     oThrowKeyid,
     oComment,
     oDefaultComment,
     oThrowKeyid,
+    oNoThrowKeyid,
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
     oShowPhotos,
     oNoShowPhotos,
     oPhotoViewer,
@@ -246,6 +254,7 @@ enum cmd_and_opt_values { aNull = 0,
     oTempDir,
     oExecPath,
     oEncryptTo,
     oTempDir,
     oExecPath,
     oEncryptTo,
+    oHiddenEncryptTo,
     oNoEncryptTo,
     oLoggerFD,
 #ifdef __riscos__
     oNoEncryptTo,
     oLoggerFD,
 #ifdef __riscos__
@@ -292,7 +301,6 @@ enum cmd_and_opt_values { aNull = 0,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
     oPersonalCipherPreferences,
     oPersonalDigestPreferences,
     oPersonalCompressPreferences,
-    oEmu3DESS2KBug,  /* will be removed in 1.1 */
     oEmuMDEncodeBug,
     oDisplay,
     oTTYname,
     oEmuMDEncodeBug,
     oDisplay,
     oTTYname,
@@ -300,6 +308,10 @@ enum cmd_and_opt_values { aNull = 0,
     oLCctype,
     oLCmessages,
     oGroup,
     oLCctype,
     oLCmessages,
     oGroup,
+    oStrict,
+    oNoStrict,
+    oMangleDosFilenames,
+    oNoMangleDosFilenames,
 aTest };
 
 
 aTest };
 
 
@@ -370,6 +382,7 @@ static ARGPARSE_OPTS opts[] = {
     { oArmor, "armor",     0, N_("create ascii armored output")},
     { oArmor, "armour",     0, "@" },
     { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
     { oArmor, "armor",     0, N_("create ascii armored output")},
     { oArmor, "armour",     0, "@" },
     { oRecipient, "recipient", 2, N_("|NAME|encrypt for NAME")},
+    { oHiddenRecipient, "hidden-recipient", 2, "@" },
     { oRecipient, "remote-user", 2, "@"},  /* old option name */
     { oDefRecipient, "default-recipient" ,2,
                                  N_("|NAME|use NAME as default recipient")},
     { oRecipient, "remote-user", 2, "@"},  /* old option name */
     { oDefRecipient, "default-recipient" ,2,
                                  N_("|NAME|use NAME as default recipient")},
@@ -379,6 +392,7 @@ static ARGPARSE_OPTS opts[] = {
     { oTempDir, "temp-directory", 2, "@" },
     { oExecPath, "exec-path", 2, "@" },
     { oEncryptTo, "encrypt-to", 2, "@" },
     { oTempDir, "temp-directory", 2, "@" },
     { oExecPath, "exec-path", 2, "@" },
     { oEncryptTo, "encrypt-to", 2, "@" },
+    { oHiddenEncryptTo, "hidden-encrypt-to", 2, "@" },
     { oNoEncryptTo, "no-encrypt-to", 0, "@" },
     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
     { oCompress, NULL,       1, N_("|N|set compress level N (0 disables)") },
     { oNoEncryptTo, "no-encrypt-to", 0, "@" },
     { oUser, "local-user",2, N_("use this user-id to sign or decrypt")},
     { oCompress, NULL,       1, N_("|N|set compress level N (0 disables)") },
@@ -403,7 +417,7 @@ static ARGPARSE_OPTS opts[] = {
     { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") },
     { oNoDisableMDC, "no-disable-mdc", 0, "@" },
     { oDryRun, "dry-run",   0, N_("do not make any changes") },
     { oDisableMDC, "disable-mdc", 0, N_("never use a MDC for encryption") },
     { oNoDisableMDC, "no-disable-mdc", 0, "@" },
     { oDryRun, "dry-run",   0, N_("do not make any changes") },
-  /*{ oInteractive, "interactive", 0, N_("prompt before overwriting") }, */
+    { oInteractive, "interactive", 0, N_("prompt before overwriting") },
     { oUseAgent, "use-agent",0, N_("use the gpg-agent")},
     { oNoUseAgent, "no-use-agent",0, "@"},
     { oGpgAgentInfo, "gpg-agent-info",2, "@"},
     { oUseAgent, "use-agent",0, N_("use the gpg-agent")},
     { oNoUseAgent, "no-use-agent",0, "@"},
     { oGpgAgentInfo, "gpg-agent-info",2, "@"},
@@ -411,6 +425,7 @@ static ARGPARSE_OPTS opts[] = {
     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
     { oAnswerYes, "yes",       0, N_("assume yes on most questions")},
     { oAnswerNo,  "no",        0, N_("assume no on most questions")},
     { oKeyring, "keyring"   ,2, N_("add this keyring to the list of keyrings")},
+    { oPrimaryKeyring, "primary-keyring",2, "@" },
     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
     { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")},
     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
     { oSecretKeyring, "secret-keyring" ,2, N_("add this secret keyring to the list")},
     { oShowKeyring, "show-keyring", 0, N_("show which keyring a listed key is on")},
     { oDefaultKey, "default-key" ,2, N_("|NAME|use NAME as default secret key")},
@@ -447,6 +462,8 @@ static ARGPARSE_OPTS opts[] = {
     { oNoPGP6, "no-pgp6", 0, "@"},
     { oPGP7, "pgp7", 0, "@"},
     { oNoPGP7, "no-pgp7", 0, "@"},
     { oNoPGP6, "no-pgp6", 0, "@"},
     { oPGP7, "pgp7", 0, "@"},
     { oNoPGP7, "no-pgp7", 0, "@"},
+    { oPGP8, "pgp8", 0, "@"},
+    { oNoPGP8, "no-pgp8", 0, "@"},
     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
     { oS2KDigest, "s2k-digest-algo",2,
                N_("|NAME|use message digest algorithm NAME for passphrases")},
     { oS2KMode, "s2k-mode",  1, N_("|N|use passphrase mode N")},
     { oS2KDigest, "s2k-digest-algo",2,
                N_("|NAME|use message digest algorithm NAME for passphrases")},
@@ -456,8 +473,9 @@ static ARGPARSE_OPTS opts[] = {
     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
     { oCertDigestAlgo, "cert-digest-algo", 2 , "@" },
     { oCipherAlgo, "cipher-algo", 2 , N_("|NAME|use cipher algorithm NAME")},
     { oDigestAlgo, "digest-algo", 2 , N_("|NAME|use message digest algorithm NAME")},
     { oCertDigestAlgo, "cert-digest-algo", 2 , "@" },
-    { oCompressAlgo, "compress-algo", 1 , N_("|N|use compress algorithm N")},
+    { oCompressAlgo,"compress-algo",2,N_("|NAME|use compression algorithm NAME")},
     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
     { oThrowKeyid, "throw-keyid", 0, N_("throw keyid field of encrypted packets")},
+    { oNoThrowKeyid, "no-throw-keyid", 0, "@" },
     { oShowPhotos,   "show-photos", 0, N_("Show Photo IDs")},
     { oNoShowPhotos, "no-show-photos", 0, N_("Don't show Photo IDs")},
     { oPhotoViewer,  "photo-viewer", 2, N_("Set command line to view Photo IDs")},
     { oShowPhotos,   "show-photos", 0, N_("Show Photo IDs")},
     { oNoShowPhotos, "no-show-photos", 0, N_("Don't show Photo IDs")},
     { oPhotoViewer,  "photo-viewer", 2, N_("Set command line to view Photo IDs")},
@@ -480,7 +498,8 @@ static ARGPARSE_OPTS opts[] = {
     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
     { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
     { aExportOwnerTrust, "list-ownertrust",0 , "@"},  /* alias */
     { aPrintMDs, "print-mds" , 256, "@"}, /* old */
     { aListTrustDB, "list-trustdb",0 , "@"},
-    { aListTrustPath, "list-trust-path",0, "@"},
+    /* Not yet used */
+    /* { aListTrustPath, "list-trust-path",0, "@"}, */
     { aPipeMode,  "pipemode", 0, "@" },
     { oKOption, NULL,   0, "@"},
     { oPasswdFD, "passphrase-fd",1, "@" },
     { aPipeMode,  "pipemode", 0, "@" },
     { oKOption, NULL,   0, "@"},
     { oPasswdFD, "passphrase-fd",1, "@" },
@@ -514,6 +533,8 @@ static ARGPARSE_OPTS opts[] = {
     { oCompressSigs, "compress-sigs",0, "@"},
     { oDefCertCheckLevel, "default-cert-check-level", 1, "@"},
     { oAlwaysTrust, "always-trust", 0, "@"},
     { oCompressSigs, "compress-sigs",0, "@"},
     { oDefCertCheckLevel, "default-cert-check-level", 1, "@"},
     { oAlwaysTrust, "always-trust", 0, "@"},
+    { oTrustModel, "trust-model", 2, "@"},
+    { oForceOwnertrust, "force-ownertrust", 1, "@"},
     { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
     { oSetFilename, "set-filename", 2, "@" },
     { oEmuChecksumBug, "emulate-checksum-bug", 0, "@"},
     { oRunAsShmCP, "run-as-shm-coprocess", 4, "@" },
     { oSetFilename, "set-filename", 2, "@" },
@@ -581,7 +602,6 @@ static ARGPARSE_OPTS opts[] = {
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
     { oPersonalCipherPreferences,  "personal-cipher-preferences", 2, "@"},
     { oPersonalDigestPreferences,  "personal-digest-preferences", 2, "@"},
     { oPersonalCompressPreferences,  "personal-compress-preferences", 2, "@"},
-    { oEmu3DESS2KBug,  "emulate-3des-s2k-bug", 0, "@"},
     { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
     { oDisplay,    "display",     2, "@" },
     { oTTYname,    "ttyname",     2, "@" },
     { oEmuMDEncodeBug, "emulate-md-encode-bug", 0, "@"},
     { oDisplay,    "display",     2, "@" },
     { oTTYname,    "ttyname",     2, "@" },
@@ -589,6 +609,10 @@ static ARGPARSE_OPTS opts[] = {
     { oLCctype,    "lc-ctype",    2, "@" },
     { oLCmessages, "lc-messages", 2, "@" },
     { oGroup,      "group",       2, "@" },
     { oLCctype,    "lc-ctype",    2, "@" },
     { oLCmessages, "lc-messages", 2, "@" },
     { oGroup,      "group",       2, "@" },
+    { oStrict,     "strict",      0, "@" },
+    { oNoStrict,   "no-strict",   0, "@" },
+    { oMangleDosFilenames, "mangle-dos-filenames", 0, "@" },
+    { oNoMangleDosFilenames, "no-mangle-dos-filenames", 0, "@" },
 {0} };
 
 
 {0} };
 
 
@@ -602,7 +626,6 @@ static char *build_list( const char *text, char letter,
                         const char *(*mapf)(int), int (*chkf)(int) );
 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
                         const char *(*mapf)(int), int (*chkf)(int) );
 static void set_cmd( enum cmd_and_opt_values *ret_cmd,
                        enum cmd_and_opt_values new_cmd );
-static void print_hex( byte *p, size_t n );
 static void print_mds( const char *fname, int algo );
 static void add_notation_data( const char *string, int which );
 static void add_policy_url( const char *string, int which );
 static void print_mds( const char *fname, int algo );
 static void add_notation_data( const char *string, int which );
 static void add_policy_url( const char *string, int which );
@@ -780,6 +803,17 @@ set_debug(void)
 }
 
 
 }
 
 
+/* We need the home directory also in some other directories, so make
+   sure that both variables are always in sync. */
+static void
+set_homedir (char *dir)
+{
+  if (!dir)
+    dir = "";
+  g10_opt_homedir = opt.homedir = dir;
+}
+
+
 static void
 set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
 {
 static void
 set_cmd( enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd )
 {
@@ -816,16 +850,21 @@ static void add_group(char *string)
   STRLIST values=NULL;
 
   /* Break off the group name */
   STRLIST values=NULL;
 
   /* Break off the group name */
-  name=strsep(&string," ");
+  name=strsep(&string,"=");
   if(string==NULL)
     {
   if(string==NULL)
     {
-      log_error(_("no values for group \"%s\"\n"),name);
+      log_error(_("no = sign found in group definition \"%s\"\n"),name);
       return;
     }
 
       return;
     }
 
+  trim_trailing_ws(name,strlen(name));
+
   /* Break apart the values */
   /* Break apart the values */
-  while((value=strsep(&string," ")) && *value!='\0')
-    add_to_strlist2(&values,value,utf8_strings);
+  while ((value= strsep(&string," \t")))
+    {
+      if (*value)
+        add_to_strlist2 (&values,value,utf8_strings);
+    }
 
   item=m_alloc(sizeof(struct groupitem));
   item->name=name;
 
   item=m_alloc(sizeof(struct groupitem));
   item->name=name;
@@ -852,7 +891,7 @@ check_permissions(const char *path,int item)
 {
 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
   static int homedir_cache=-1;
 {
 #if defined(HAVE_STAT) && !defined(HAVE_DOSISH_SYSTEM)
   static int homedir_cache=-1;
-  char *tmppath,*isa,*dir;
+  char *tmppath,*dir;
   struct stat statbuf,dirbuf;
   int homedir=0,ret=0,checkonly=0;
   int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0;
   struct stat statbuf,dirbuf;
   int homedir=0,ret=0,checkonly=0;
   int perm=0,own=0,enc_dir_perm=0,enc_dir_own=0;
@@ -860,6 +899,8 @@ check_permissions(const char *path,int item)
   if(opt.no_perm_warn)
     return 0;
 
   if(opt.no_perm_warn)
     return 0;
 
+  assert(item==0 || item==1 || item==2);
+
   /* extensions may attach a path */
   if(item==2 && path[0]!=DIRSEP_C)
     {
   /* extensions may attach a path */
   if(item==2 && path[0]!=DIRSEP_C)
     {
@@ -876,8 +917,8 @@ check_permissions(const char *path,int item)
      to avoid user confusion with an extra options file warning which
      could be rectified if the homedir itself had proper
      permissions. */
      to avoid user confusion with an extra options file warning which
      could be rectified if the homedir itself had proper
      permissions. */
-  if(item!=0 && homedir_cache>-1 &&
-     ascii_memcasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0)
+  if(item!=0 && homedir_cache>-1
+     && ascii_strncasecmp(opt.homedir,tmppath,strlen(opt.homedir))==0)
     {
       ret=homedir_cache;
       goto end;
     {
       ret=homedir_cache;
       goto end;
@@ -909,8 +950,6 @@ check_permissions(const char *path,int item)
 
   if(item==0)
     {
 
   if(item==0)
     {
-      isa="homedir";
-
       /* The homedir must be x00, a directory, and owned by the user. */
 
       if(S_ISDIR(statbuf.st_mode))
       /* The homedir must be x00, a directory, and owned by the user. */
 
       if(S_ISDIR(statbuf.st_mode))
@@ -930,11 +969,6 @@ check_permissions(const char *path,int item)
     }
   else if(item==1 || item==2)
     {
     }
   else if(item==1 || item==2)
     {
-      if(item==1)
-       isa="configuration file";
-      else
-       isa="extension";
-
       /* The options or extension file.  Okay unless it or its
         containing directory is group or other writable or not owned
         by us or root. */
       /* The options or extension file.  Okay unless it or its
         containing directory is group or other writable or not owned
         by us or root. */
@@ -982,19 +1016,53 @@ check_permissions(const char *path,int item)
   if(!checkonly)
     {
       if(own)
   if(!checkonly)
     {
       if(own)
-       log_info(_("WARNING: unsafe ownership on %s \"%s\"\n"),
-                isa,tmppath);
+       {
+         if(item==0)
+           log_info(_("WARNING: unsafe ownership on "
+                      "homedir \"%s\"\n"),tmppath);
+         else if(item==1)
+           log_info(_("WARNING: unsafe ownership on "
+                      "configuration file \"%s\"\n"),tmppath);
+         else
+           log_info(_("WARNING: unsafe ownership on "
+                      "extension \"%s\"\n"),tmppath);
+       }
       if(perm)
       if(perm)
-       log_info(_("WARNING: unsafe permissions on %s \"%s\"\n"),
-                isa,tmppath);
+       {
+         if(item==0)
+           log_info(_("WARNING: unsafe permissions on "
+                      "homedir \"%s\"\n"),tmppath);
+         else if(item==1)
+           log_info(_("WARNING: unsafe permissions on "
+                      "configuration file \"%s\"\n"),tmppath);
+         else
+           log_info(_("WARNING: unsafe permissions on "
+                      "extension \"%s\"\n"),tmppath);
+       }
       if(enc_dir_own)
       if(enc_dir_own)
-       log_info(_("WARNING: unsafe enclosing directory "
-                  "ownership on %s \"%s\"\n"),
-                isa,tmppath);
+       {
+         if(item==0)
+           log_info(_("WARNING: unsafe enclosing directory ownership on "
+                      "homedir \"%s\"\n"),tmppath);
+         else if(item==1)
+           log_info(_("WARNING: unsafe enclosing directory ownership on "
+                      "configuration file \"%s\"\n"),tmppath);
+         else
+           log_info(_("WARNING: unsafe enclosing directory ownership on "
+                      "extension \"%s\"\n"),tmppath);
+       }
       if(enc_dir_perm)
       if(enc_dir_perm)
-       log_info(_("WARNING: unsafe enclosing directory "
-                  "permissions on %s \"%s\"\n"),
-                isa,tmppath);
+       {
+         if(item==0)
+           log_info(_("WARNING: unsafe enclosing directory permissions on "
+                      "homedir \"%s\"\n"),tmppath);
+         else if(item==1)
+           log_info(_("WARNING: unsafe enclosing directory permissions on "
+                      "configuration file \"%s\"\n"),tmppath);
+         else
+           log_info(_("WARNING: unsafe enclosing directory permissions on "
+                      "extension \"%s\"\n"),tmppath);
+       }
     }
 
  end:
     }
 
  end:
@@ -1038,6 +1106,7 @@ main( int argc, char **argv )
     const char *trustdb_name = NULL;
     char *def_cipher_string = NULL;
     char *def_digest_string = NULL;
     const char *trustdb_name = NULL;
     char *def_cipher_string = NULL;
     char *def_digest_string = NULL;
+    char *def_compress_string = NULL;
     char *cert_digest_string = NULL;
     char *s2k_cipher_string = NULL;
     char *s2k_digest_string = NULL;
     char *cert_digest_string = NULL;
     char *s2k_cipher_string = NULL;
     char *s2k_digest_string = NULL;
@@ -1078,28 +1147,36 @@ main( int argc, char **argv )
     opt.def_compress_algo = -1;
     opt.s2k_mode = 3; /* iterated+salted */
     opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
     opt.def_compress_algo = -1;
     opt.s2k_mode = 3; /* iterated+salted */
     opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
+#ifdef USE_CAST5
     opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
     opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
+#else
+    opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
+#endif
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
     opt.max_cert_depth = 5;
     opt.pgp2_workarounds = 1;
     opt.force_v3_sigs = 1;
     opt.escape_from = 1;
     opt.completes_needed = 1;
     opt.marginals_needed = 3;
     opt.max_cert_depth = 5;
     opt.pgp2_workarounds = 1;
     opt.force_v3_sigs = 1;
     opt.escape_from = 1;
-    opt.import_options=0;
+    opt.import_options=IMPORT_SK2PK;
     opt.export_options=
       EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
     opt.keyserver_options.import_options=IMPORT_REPAIR_HKP_SUBKEY_BUG;
     opt.keyserver_options.export_options=
       EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
     opt.keyserver_options.include_subkeys=1;
     opt.export_options=
       EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
     opt.keyserver_options.import_options=IMPORT_REPAIR_HKP_SUBKEY_BUG;
     opt.keyserver_options.export_options=
       EXPORT_INCLUDE_NON_RFC|EXPORT_INCLUDE_ATTRIBUTES;
     opt.keyserver_options.include_subkeys=1;
-#if defined (__MINGW32__) || defined (__CYGWIN32__)
-    opt.homedir = read_w32_registry_string( NULL, "Software\\GNU\\GnuPG", "HomeDir" );
+    opt.keyserver_options.include_revoked=1;
+    opt.trust_model=TM_OPENPGP;
+    opt.mangle_dos_filenames = 1;
+
+#if defined (__MINGW32__)
+    set_homedir ( read_w32_registry_string( NULL,
+                                    "Software\\GNU\\GnuPG", "HomeDir" ));
 #else
 #else
-    opt.homedir = getenv("GNUPGHOME");
+    set_homedir ( getenv("GNUPGHOME") );
 #endif
 #endif
-    if( !opt.homedir || !*opt.homedir ) {
-       opt.homedir = GNUPG_HOMEDIR;
-    }
+    if( !*opt.homedir )
+       set_homedir ( GNUPG_HOMEDIR );
 
     /* check whether we have a config file on the commandline */
     orig_argc = argc;
 
     /* check whether we have a config file on the commandline */
     orig_argc = argc;
@@ -1119,9 +1196,19 @@ main( int argc, char **argv )
        else if( pargs.r_opt == oNoOptions )
            default_config = 0; /* --no-options */
        else if( pargs.r_opt == oHomedir )
        else if( pargs.r_opt == oNoOptions )
            default_config = 0; /* --no-options */
        else if( pargs.r_opt == oHomedir )
-           opt.homedir = pargs.r.ret_str;
+           set_homedir ( pargs.r.ret_str );
        else if( pargs.r_opt == oNoPermissionWarn )
            opt.no_perm_warn=1;
        else if( pargs.r_opt == oNoPermissionWarn )
            opt.no_perm_warn=1;
+       else if (pargs.r_opt == oStrict )
+         {
+           opt.strict=1;
+           log_set_strict(1);
+         }
+       else if (pargs.r_opt == oNoStrict )
+         {
+           opt.strict=0;
+           log_set_strict(0);
+         }
       #ifdef USE_SHM_COPROCESSING
        else if( pargs.r_opt == oRunAsShmCP ) {
            /* does not make sense in a options file, we do it here,
       #ifdef USE_SHM_COPROCESSING
        else if( pargs.r_opt == oRunAsShmCP ) {
            /* does not make sense in a options file, we do it here,
@@ -1144,7 +1231,7 @@ main( int argc, char **argv )
         for (d=buf,s=opt.homedir; *s; s++)
             *d++ = *s == '\\'? '/': *s;
         *d = 0;
         for (d=buf,s=opt.homedir; *s; s++)
             *d++ = *s == '\\'? '/': *s;
         *d = 0;
-        opt.homedir = buf;
+        set_homedir (buf);
     }
 #endif
 #ifdef USE_SHM_COPROCESSING
     }
 #endif
 #ifdef USE_SHM_COPROCESSING
@@ -1157,6 +1244,8 @@ main( int argc, char **argv )
     maybe_setuid = 0;
     /* Okay, we are now working under our real uid */
 
     maybe_setuid = 0;
     /* Okay, we are now working under our real uid */
 
+    set_native_charset (NULL); /* Try to auto set the character set */
+
     if( default_config )
       {
        configname = make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL );
     if( default_config )
       {
        configname = make_filename(opt.homedir, "gpg" EXTSEP_S "conf", NULL );
@@ -1293,7 +1382,7 @@ main( int argc, char **argv )
             opt.use_agent = 1;
 #else /* __riscos__ */
             opt.use_agent = 0;
             opt.use_agent = 1;
 #else /* __riscos__ */
             opt.use_agent = 0;
-            not_implemented("use-agent");
+            riscos_not_implemented("use-agent");
 #endif /* __riscos__ */
             break;
           case oNoUseAgent: opt.use_agent = 0; break;
 #endif /* __riscos__ */
             break;
           case oNoUseAgent: opt.use_agent = 0; break;
@@ -1301,6 +1390,10 @@ main( int argc, char **argv )
          case oAnswerYes: opt.answer_yes = 1; break;
          case oAnswerNo: opt.answer_no = 1; break;
          case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
          case oAnswerYes: opt.answer_yes = 1; break;
          case oAnswerNo: opt.answer_no = 1; break;
          case oKeyring: append_to_strlist( &nrings, pargs.r.ret_str); break;
+         case oPrimaryKeyring:
+           sl=append_to_strlist( &nrings, pargs.r.ret_str);
+           sl->flags=2;
+           break;
          case oShowKeyring: opt.show_keyring = 1; break;
          case oDebug: opt.debug |= pargs.r.ret_ulong; break;
          case oDebugAll: opt.debug = ~0; break;
          case oShowKeyring: opt.show_keyring = 1; break;
          case oDebug: opt.debug |= pargs.r.ret_ulong; break;
          case oDebugAll: opt.debug = ~0; break;
@@ -1309,7 +1402,7 @@ main( int argc, char **argv )
             break;
 #ifdef __riscos__
          case oStatusFile:
             break;
 #ifdef __riscos__
          case oStatusFile:
-            set_status_fd( iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) );
+            set_status_fd( iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
             break;
 #endif /* __riscos__ */
          case oAttributeFD:
             break;
 #endif /* __riscos__ */
          case oAttributeFD:
@@ -1317,7 +1410,7 @@ main( int argc, char **argv )
             break;
 #ifdef __riscos__
          case oAttributeFile:
             break;
 #ifdef __riscos__
          case oAttributeFile:
-            set_attrib_fd(iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) );
+            set_attrib_fd(iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
             break;
 #endif /* __riscos__ */
          case oLoggerFD:
             break;
 #endif /* __riscos__ */
          case oLoggerFD:
@@ -1327,7 +1420,7 @@ main( int argc, char **argv )
 #ifdef __riscos__
          case oLoggerFile:
             log_set_logfile( NULL,
 #ifdef __riscos__
          case oLoggerFile:
             log_set_logfile( NULL,
-                             iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 1), 1) );
+                             iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 1), 1) );
             break;
 #endif /* __riscos__ */
          case oWithFingerprint:
             break;
 #endif /* __riscos__ */
          case oWithFingerprint:
@@ -1378,13 +1471,34 @@ main( int argc, char **argv )
          case oWithColons: opt.with_colons=':'; break;
 
          case oSkipVerify: opt.skip_verify=1; break;
          case oWithColons: opt.with_colons=':'; break;
 
          case oSkipVerify: opt.skip_verify=1; break;
-         case oCompressAlgo: opt.def_compress_algo = pargs.r.ret_int; break;
          case oCompressKeys: opt.compress_keys = 1; break;
          case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
          case oCompressKeys: opt.compress_keys = 1; break;
          case aListSecretKeys: set_cmd( &cmd, aListSecretKeys); break;
-         case oAlwaysTrust: opt.always_trust = 1; break;
+           /* There are many programs (like mutt) that call gpg with
+              --always-trust so keep this option around for a long
+              time. */
+         case oAlwaysTrust: opt.trust_model=TM_ALWAYS; break;
+         case oTrustModel:
+           if(ascii_strcasecmp(pargs.r.ret_str,"openpgp")==0)
+             opt.trust_model=TM_OPENPGP;
+           else if(ascii_strcasecmp(pargs.r.ret_str,"classic")==0)
+             opt.trust_model=TM_CLASSIC;
+           else if(ascii_strcasecmp(pargs.r.ret_str,"always")==0)
+             opt.trust_model=TM_ALWAYS;
+           else
+             log_error("unknown trust model \"%s\"\n",pargs.r.ret_str);
+           break;
+         case oForceOwnertrust:
+           log_info(_("NOTE: %s is not for normal use!\n"),
+                    "--force-ownertrust");
+           if(pargs.r.ret_int>=TRUST_UNDEFINED
+              && pargs.r.ret_int<=TRUST_ULTIMATE)
+             opt.force_ownertrust=pargs.r.ret_int;
+           else
+             log_error("invalid ownertrust %d\n",pargs.r.ret_int);
+           break;
          case oLoadExtension:
 #ifndef __riscos__
          case oLoadExtension:
 #ifndef __riscos__
-#ifdef USE_DYNAMIC_LINKING
+#if defined(USE_DYNAMIC_LINKING) || defined(__MINGW32__)
            if(check_permissions(pargs.r.ret_str,2))
              log_info(_("cipher extension \"%s\" not loaded due to "
                         "unsafe permissions\n"),pargs.r.ret_str);
            if(check_permissions(pargs.r.ret_str,2))
              log_info(_("cipher extension \"%s\" not loaded due to "
                         "unsafe permissions\n"),pargs.r.ret_str);
@@ -1393,7 +1507,7 @@ main( int argc, char **argv )
                                        pargs.r.ret_str);
 #endif
 #else /* __riscos__ */
                                        pargs.r.ret_str);
 #endif
 #else /* __riscos__ */
-            not_implemented("load-extension");
+            riscos_not_implemented("load-extension");
 #endif /* __riscos__ */
            break;
          case oRFC1991:
 #endif /* __riscos__ */
            break;
          case oRFC1991:
@@ -1420,10 +1534,10 @@ main( int argc, char **argv )
            opt.def_cipher_algo = 0;
            opt.def_digest_algo = 0;
            opt.cert_digest_algo = 0;
            opt.def_cipher_algo = 0;
            opt.def_digest_algo = 0;
            opt.cert_digest_algo = 0;
-           opt.def_compress_algo = 1;
+           opt.def_compress_algo = -1;
             opt.s2k_mode = 3; /* iterated+salted */
            opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
             opt.s2k_mode = 3; /* iterated+salted */
            opt.s2k_digest_algo = DIGEST_ALGO_SHA1;
-           opt.s2k_cipher_algo = CIPHER_ALGO_CAST5;
+           opt.s2k_cipher_algo = CIPHER_ALGO_3DES;
            break;
          case oPGP2: opt.pgp2 = 1; break;
          case oNoPGP2: opt.pgp2 = 0; break;
            break;
          case oPGP2: opt.pgp2 = 1; break;
          case oNoPGP2: opt.pgp2 = 0; break;
@@ -1431,19 +1545,19 @@ main( int argc, char **argv )
          case oNoPGP6: opt.pgp6 = 0; break;
          case oPGP7: opt.pgp7 = 1; break;
          case oNoPGP7: opt.pgp7 = 0; break;
          case oNoPGP6: opt.pgp6 = 0; break;
          case oPGP7: opt.pgp7 = 1; break;
          case oNoPGP7: opt.pgp7 = 0; break;
-         case oEmuChecksumBug: opt.emulate_bugs |= EMUBUG_GPGCHKSUM; break;
-         case oEmu3DESS2KBug:  opt.emulate_bugs |= EMUBUG_3DESS2K; break;
+         case oPGP8: opt.pgp8 = 1; break;
+         case oNoPGP8: opt.pgp8 = 0; break;
          case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
          case oCompressSigs: opt.compress_sigs = 1; break;
          case oRunAsShmCP:
 #ifndef __riscos__
          case oEmuMDEncodeBug: opt.emulate_bugs |= EMUBUG_MDENCODE; break;
          case oCompressSigs: opt.compress_sigs = 1; break;
          case oRunAsShmCP:
 #ifndef __riscos__
-         #ifndef USE_SHM_COPROCESSING
+ifndef USE_SHM_COPROCESSING
            /* not possible in the option file,
             * but we print the warning here anyway */
            log_error("shared memory coprocessing is not available\n");
            /* not possible in the option file,
             * but we print the warning here anyway */
            log_error("shared memory coprocessing is not available\n");
-         #endif
+endif
 #else /* __riscos__ */
 #else /* __riscos__ */
-            not_implemented("run-as-shm-coprocess");
+            riscos_not_implemented("run-as-shm-coprocess");
 #endif /* __riscos__ */
            break;
          case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
 #endif /* __riscos__ */
            break;
          case oSetFilename: opt.set_filename = pargs.r.ret_str; break;
@@ -1461,6 +1575,7 @@ main( int argc, char **argv )
          case oComment: opt.comment_string = pargs.r.ret_str; break;
          case oDefaultComment: opt.comment_string = NULL; break;
          case oThrowKeyid: opt.throw_keyid = 1; break;
          case oComment: opt.comment_string = pargs.r.ret_str; break;
          case oDefaultComment: opt.comment_string = NULL; break;
          case oThrowKeyid: opt.throw_keyid = 1; break;
+         case oNoThrowKeyid: opt.throw_keyid = 0; break;
          case oShowPhotos: opt.show_photos = 1; break;
          case oNoShowPhotos: opt.show_photos = 0; break;
          case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
          case oShowPhotos: opt.show_photos = 1; break;
          case oNoShowPhotos: opt.show_photos = 0; break;
          case oPhotoViewer: opt.photo_viewer = pargs.r.ret_str; break;
@@ -1481,10 +1596,19 @@ main( int argc, char **argv )
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
            sl->flags = 1;
            break;
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
            sl->flags = 1;
            break;
+         case oHiddenEncryptTo: /* store the recipient in the second list */
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = 1|2;
+           break;
          case oRecipient: /* store the recipient */
            add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
             any_explicit_recipient = 1;
            break;
          case oRecipient: /* store the recipient */
            add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
             any_explicit_recipient = 1;
            break;
+         case oHiddenRecipient: /* store the recipient with a flag */
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = 2;
+            any_explicit_recipient = 1;
+           break;
          case oTextmodeShort: opt.textmode = 2; break;
          case oTextmode: opt.textmode=1;  break;
          case oExpert: opt.expert = 1; break;
          case oTextmodeShort: opt.textmode = 2; break;
          case oTextmode: opt.textmode=1;  break;
          case oExpert: opt.expert = 1; break;
@@ -1502,7 +1626,7 @@ main( int argc, char **argv )
             break;
 #ifdef __riscos__
          case oPasswdFile:
             break;
 #ifdef __riscos__
          case oPasswdFile:
-            pwfd = iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 0), 0);
+            pwfd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0);
             break;
 #endif /* __riscos__ */
          case oCommandFD:
             break;
 #endif /* __riscos__ */
          case oCommandFD:
@@ -1510,16 +1634,40 @@ main( int argc, char **argv )
             break;
 #ifdef __riscos__
          case oCommandFile:
             break;
 #ifdef __riscos__
          case oCommandFile:
-            opt.command_fd = iobuf_translate_file_handle ( fdopenfile (pargs.r.ret_str, 0), 0);
+            opt.command_fd = iobuf_translate_file_handle ( riscos_fdopenfile (pargs.r.ret_str, 0), 0);
             break;
 #endif /* __riscos__ */
          case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
          case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
             break;
 #endif /* __riscos__ */
          case oCipherAlgo: def_cipher_string = m_strdup(pargs.r.ret_str); break;
          case oDigestAlgo: def_digest_string = m_strdup(pargs.r.ret_str); break;
+         case oCompressAlgo:
+           /* If it is all digits, stick a Z in front of it for
+              later.  This is for backwards compatibility with
+              versions that took the compress algorithm number. */
+           {
+             char *pt=pargs.r.ret_str;
+             while(*pt)
+               {
+                 if(!isdigit(*pt))
+                   break;
+
+                 pt++;
+               }
+
+             if(*pt=='\0')
+               {
+                 def_compress_string=m_alloc(strlen(pargs.r.ret_str)+2);
+                 strcpy(def_compress_string,"Z");
+                 strcat(def_compress_string,pargs.r.ret_str);
+               }
+             else
+               def_compress_string = m_strdup(pargs.r.ret_str);
+           }
+           break;
          case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break;
          case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
          case oNoPermissionWarn: opt.no_perm_warn=1; break;
          case oNoMDCWarn: opt.no_mdc_warn=1; break;
          case oCertDigestAlgo: cert_digest_string = m_strdup(pargs.r.ret_str); break;
          case oNoSecmemWarn: secmem_set_flags( secmem_get_flags() | 1 ); break;
          case oNoPermissionWarn: opt.no_perm_warn=1; break;
          case oNoMDCWarn: opt.no_mdc_warn=1; break;
-         case oCharset:
+          case oCharset:
            if( set_native_charset( pargs.r.ret_str ) )
                log_error(_("%s is not a valid character set\n"),
                                                    pargs.r.ret_str);
            if( set_native_charset( pargs.r.ret_str ) )
                log_error(_("%s is not a valid character set\n"),
                                                    pargs.r.ret_str);
@@ -1533,7 +1681,7 @@ main( int argc, char **argv )
 #ifndef __riscos__
            opt.lock_once = 0;
 #else /* __riscos__ */
 #ifndef __riscos__
            opt.lock_once = 0;
 #else /* __riscos__ */
-            not_implemented("lock-multiple");
+            riscos_not_implemented("lock-multiple");
 #endif /* __riscos__ */
             break;
          case oKeyServer:
 #endif /* __riscos__ */
             break;
          case oKeyServer:
@@ -1653,6 +1801,12 @@ main( int argc, char **argv )
           case oLCctype: opt.lc_ctype = pargs.r.ret_str; break;
           case oLCmessages: opt.lc_messages = pargs.r.ret_str; break;
          case oGroup: add_group(pargs.r.ret_str); break;
           case oLCctype: opt.lc_ctype = pargs.r.ret_str; break;
           case oLCmessages: opt.lc_messages = pargs.r.ret_str; break;
          case oGroup: add_group(pargs.r.ret_str); break;
+         case oStrict: opt.strict=1; log_set_strict(1); break;
+         case oNoStrict: opt.strict=0; log_set_strict(0); break;
+
+          case oMangleDosFilenames: opt.mangle_dos_filenames = 1; break;
+          case oNoMangleDosFilenames: opt.mangle_dos_filenames = 0; break;
+
          default : pargs.err = configfp? 1:2; break;
        }
     }
          default : pargs.err = configfp? 1:2; break;
        }
     }
@@ -1682,6 +1836,9 @@ main( int argc, char **argv )
     }
   #endif
 
     }
   #endif
 
+    if (opt.verbose > 2)
+        log_info ("using character set `%s'\n", get_native_charset ());
+
     if( may_coredump && !opt.quiet )
        log_info(_("WARNING: program may create a core file!\n"));
 
     if( may_coredump && !opt.quiet )
        log_info(_("WARNING: program may create a core file!\n"));
 
@@ -1712,12 +1869,11 @@ main( int argc, char **argv )
     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
 
     set_debug();
     secmem_set_flags( secmem_get_flags() & ~2 ); /* resume warnings */
 
     set_debug();
-    g10_opt_homedir = opt.homedir;
 
     /* Do these after the switch(), so they can override settings. */
 
     /* Do these after the switch(), so they can override settings. */
-    if(opt.pgp2 && (opt.pgp6 || opt.pgp7))
+    if(opt.pgp2 && (opt.pgp6 || opt.pgp7 || opt.pgp8))
       log_error(_("%s not allowed with %s!\n"),
       log_error(_("%s not allowed with %s!\n"),
-               "--pgp2",opt.pgp6?"--pgp6":"--pgp7");
+               "--pgp2",opt.pgp6?"--pgp6":opt.pgp7?"--pgp7":"--pgp8");
     else
       {
        if(opt.pgp2)
     else
       {
        if(opt.pgp2)
@@ -1758,9 +1914,20 @@ main( int argc, char **argv )
                  }
                else if(cmd==aSym)
                  {
                  }
                else if(cmd==aSym)
                  {
+                   /* This only sets IDEA for symmetric encryption
+                      since it is set via select_algo_from_prefs for
+                      pk encryption. */
                    m_free(def_cipher_string);
                    def_cipher_string = m_strdup("idea");
                  }
                    m_free(def_cipher_string);
                    def_cipher_string = m_strdup("idea");
                  }
+
+               /* PGP2 can't handle the output from the textmode
+                  filter, so we disable it for anything that could
+                  create a literal packet (only encryption and
+                  symmetric encryption, since we disable signing
+                  above). */
+               if(!unusable)
+                 opt.textmode=0;
              }
 
            if(unusable)
              }
 
            if(unusable)
@@ -1787,20 +1954,28 @@ main( int argc, char **argv )
                opt.def_compress_algo = 1;
              }
          }
                opt.def_compress_algo = 1;
              }
          }
-
-       if(opt.pgp6 || opt.pgp7)
+       else if(opt.pgp6)
          {
            opt.sk_comments=0;
            opt.escape_from=1;
            opt.force_v3_sigs=1;
            opt.ask_sig_expire=0;
            opt.def_compress_algo=1;
          {
            opt.sk_comments=0;
            opt.escape_from=1;
            opt.force_v3_sigs=1;
            opt.ask_sig_expire=0;
            opt.def_compress_algo=1;
-
-           if(opt.pgp6) /* pgp7 has MDC */
-             {
-               opt.force_mdc=0;
-               opt.disable_mdc=1;
-             }
+           opt.force_mdc=0;
+           opt.disable_mdc=1;
+         }
+       else if(opt.pgp7)
+         {
+           opt.sk_comments=0;
+           opt.escape_from=1;
+           opt.force_v3_sigs=1;
+           opt.ask_sig_expire=0;
+           opt.def_compress_algo=1;
+         }
+       else if(opt.pgp8)
+         {
+           opt.escape_from=1;
+           opt.def_compress_algo=1;
          }
       }
 
          }
       }
 
@@ -1821,6 +1996,12 @@ main( int argc, char **argv )
        if( check_digest_algo(opt.def_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
        if( check_digest_algo(opt.def_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
+    if( def_compress_string ) {
+       opt.def_compress_algo = string_to_compress_algo(def_compress_string);
+       m_free(def_compress_string); def_compress_string = NULL;
+       if( check_compress_algo(opt.def_compress_algo) )
+           log_error(_("selected compression algorithm is invalid\n"));
+    }
     if( cert_digest_string ) {
        opt.cert_digest_algo = string_to_digest_algo(cert_digest_string);
        m_free(cert_digest_string); cert_digest_string = NULL;
     if( cert_digest_string ) {
        opt.cert_digest_algo = string_to_digest_algo(cert_digest_string);
        m_free(cert_digest_string); cert_digest_string = NULL;
@@ -1839,8 +2020,6 @@ main( int argc, char **argv )
        if( check_digest_algo(opt.s2k_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
        if( check_digest_algo(opt.s2k_digest_algo) )
            log_error(_("selected digest algorithm is invalid\n"));
     }
-    if( opt.def_compress_algo < -1 || opt.def_compress_algo > 2 )
-       log_error(_("compress algorithm must be in range %d..%d\n"), 0, 2);
     if( opt.completes_needed < 1 )
        log_error(_("completes-needed must be greater than 0\n"));
     if( opt.marginals_needed < 2 )
     if( opt.completes_needed < 1 )
        log_error(_("completes-needed must be greater than 0\n"));
     if( opt.marginals_needed < 2 )
@@ -1940,7 +2119,7 @@ main( int argc, char **argv )
        if( !nrings || default_keyring )  /* add default ring */
            keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0);
        for(sl = nrings; sl; sl = sl->next )
        if( !nrings || default_keyring )  /* add default ring */
            keydb_add_resource ("pubring" EXTSEP_S "gpg", 0, 0);
        for(sl = nrings; sl; sl = sl->next )
-           keydb_add_resource ( sl->d, 0, 0 );
+           keydb_add_resource ( sl->d, sl->flags, 0 );
       }
     FREE_STRLIST(nrings);
     FREE_STRLIST(sec_nrings);
       }
     FREE_STRLIST(nrings);
     FREE_STRLIST(sec_nrings);
@@ -1960,13 +2139,6 @@ main( int argc, char **argv )
       case aEnArmor:
       case aFixTrustDB:
        break;
       case aEnArmor:
       case aFixTrustDB:
        break;
-      case aKMode:
-      case aListKeys:
-      case aListSecretKeys:
-      case aCheckKeys:
-       if( opt.with_colons ) /* need this to list the trust */
-           rc = setup_trustdb(1, trustdb_name );
-       break;
       case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
       case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break;
       default: rc = setup_trustdb(1, trustdb_name ); break;
       case aExportOwnerTrust: rc = setup_trustdb( 0, trustdb_name ); break;
       case aListTrustDB: rc = setup_trustdb( argc? 1:0, trustdb_name ); break;
       default: rc = setup_trustdb(1, trustdb_name ); break;
@@ -2209,9 +2381,9 @@ main( int argc, char **argv )
        break;
 
       case aFastImport:
        break;
 
       case aFastImport:
+        opt.import_options |= IMPORT_FAST_IMPORT;
       case aImport:
       case aImport:
-       import_keys( argc? argv:NULL, argc, (cmd == aFastImport),
-                    NULL, opt.import_options );
+       import_keys( argc? argv:NULL, argc, NULL, opt.import_options );
        break;
 
       case aExport:
        break;
 
       case aExport:
@@ -2518,40 +2690,89 @@ g10_exit( int rc )
 }
 
 
 }
 
 
-
-
+/* Pretty-print hex hashes.  This assumes at least an 80-character
+   display, but there are a few other similar assumptions in the
+   display code. */
 static void
 static void
-print_hex( byte *p, size_t n )
+print_hex( MD_HANDLE md, int algo, const char *fname )
 {
 {
-    int i;
+  int i,n,count,indent=0;
+  const byte *p;
 
 
-    if( n == 20 ) {
-       for(i=0; i < n ; i++, i++, p += 2 ) {
-           if( i )
-               putchar(' ');
-           if( i == 10 )
-               putchar(' ');
-           printf("%02X%02X", *p, p[1] );
-       }
+  if(fname)
+    indent=printf("%s: ",fname);
+
+  if(indent>40)
+    {
+      printf("\n");
+      indent=0;
     }
     }
-    else if( n == 24 ) {
-       for(i=0; i < n ; i += 4, p += 4 ) {
-           if( i )
-               putchar(' ');
-           if( i == 12 )
-               putchar(' ');
-           printf("%02X%02X%02X%02X", *p, p[1], p[2], p[3] );
+
+  if(algo==DIGEST_ALGO_RMD160)
+    indent+=printf("RMD160 = ");
+  else if(algo==DIGEST_ALGO_TIGER)
+    indent+=printf(" TIGER = ");
+  else if(algo>0)
+    indent+=printf("%6s = ",digest_algo_to_string(algo));
+  else
+    algo=abs(algo);
+
+  count=indent;
+
+  p = md_read( md, algo );
+  n = md_digest_length(algo);
+
+  count+=printf("%02X",*p++);
+
+  for(i=1;i<n;i++,p++)
+    {
+      if(n==16)
+       {
+         if(count+2>79)
+           {
+             printf("\n%*s",indent," ");
+             count=indent;
+           }
+         else
+           count+=printf(" ");
+
+         if(!(i%8))
+           count+=printf(" ");
        }
        }
-    }
-    else {
-       for(i=0; i < n ; i++, p++ ) {
-           if( i )
-               putchar(' ');
-           if( i && !(i%8) )
-               putchar(' ');
-           printf("%02X", *p );
+      else if (n==20)
+       {
+         if(!(i%2))
+           {
+             if(count+4>79)
+               {
+                 printf("\n%*s",indent," ");
+                 count=indent;
+               }
+             else
+               count+=printf(" ");
+           }
+
+         if(!(i%10))
+           count+=printf(" ");
        }
        }
+      else
+       {
+         if(!(i%4))
+           {
+             if(count+8>79)
+               {
+                 printf("\n%*s",indent," ");
+                 count=indent;
+               }
+             else
+               count+=printf(" ");
+           }
+       }
+
+      count+=printf("%02X",*p);
     }
     }
+
+  printf("\n");
 }
 
 static void
 }
 
 static void
@@ -2585,23 +2806,18 @@ print_mds( const char *fname, int algo )
     char buf[1024];
     size_t n;
     MD_HANDLE md;
     char buf[1024];
     size_t n;
     MD_HANDLE md;
-    char *pname;
 
     if( !fname ) {
        fp = stdin;
       #ifdef HAVE_DOSISH_SYSTEM
        setmode ( fileno(fp) , O_BINARY );
       #endif
 
     if( !fname ) {
        fp = stdin;
       #ifdef HAVE_DOSISH_SYSTEM
        setmode ( fileno(fp) , O_BINARY );
       #endif
-       pname = m_strdup("[stdin]: ");
     }
     else {
     }
     else {
-       pname = m_alloc(strlen(fname)+3);
-       strcpy(stpcpy(pname,fname),": ");
        fp = fopen( fname, "rb" );
     }
     if( !fp ) {
        fp = fopen( fname, "rb" );
     }
     if( !fp ) {
-       log_error("%s%s\n", pname, strerror(errno) );
-       m_free(pname);
+       log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
        return;
     }
 
        return;
     }
 
@@ -2612,14 +2828,22 @@ print_mds( const char *fname, int algo )
        md_enable( md, DIGEST_ALGO_MD5 );
        md_enable( md, DIGEST_ALGO_SHA1 );
        md_enable( md, DIGEST_ALGO_RMD160 );
        md_enable( md, DIGEST_ALGO_MD5 );
        md_enable( md, DIGEST_ALGO_SHA1 );
        md_enable( md, DIGEST_ALGO_RMD160 );
-       if( !check_digest_algo(DIGEST_ALGO_TIGER) )
-           md_enable( md, DIGEST_ALGO_TIGER );
+#ifdef USE_TIGER192
+       md_enable( md, DIGEST_ALGO_TIGER );
+#endif
+#ifdef USE_SHA256
+       md_enable( md, DIGEST_ALGO_SHA256 );
+#endif
+#ifdef USE_SHA512
+       md_enable( md, DIGEST_ALGO_SHA384 );
+       md_enable( md, DIGEST_ALGO_SHA512 );
+#endif
     }
 
     while( (n=fread( buf, 1, DIM(buf), fp )) )
        md_write( md, buf, n );
     if( ferror(fp) )
     }
 
     while( (n=fread( buf, 1, DIM(buf), fp )) )
        md_write( md, buf, n );
     if( ferror(fp) )
-       log_error("%s%s\n", pname, strerror(errno) );
+       log_error("%s: %s\n", fname?fname:"[stdin]", strerror(errno) );
     else {
        md_final(md);
         if ( opt.with_colons ) {
     else {
        md_final(md);
         if ( opt.with_colons ) {
@@ -2629,29 +2853,36 @@ print_mds( const char *fname, int algo )
                 print_hashline( md, DIGEST_ALGO_MD5, fname );
                 print_hashline( md, DIGEST_ALGO_SHA1, fname );
                 print_hashline( md, DIGEST_ALGO_RMD160, fname );
                 print_hashline( md, DIGEST_ALGO_MD5, fname );
                 print_hashline( md, DIGEST_ALGO_SHA1, fname );
                 print_hashline( md, DIGEST_ALGO_RMD160, fname );
-                if( !check_digest_algo(DIGEST_ALGO_TIGER) ) 
-                    print_hashline( md, DIGEST_ALGO_TIGER, fname );
+#ifdef USE_TIGER192
+               print_hashline( md, DIGEST_ALGO_TIGER, fname );
+#endif
+#ifdef USE_SHA256
+                print_hashline( md, DIGEST_ALGO_SHA256, fname );
+#endif
+#ifdef USE_SHA512
+               print_hashline( md, DIGEST_ALGO_SHA384, fname );
+               print_hashline( md, DIGEST_ALGO_SHA512, fname );
+#endif
             }
         }
         else {
             }
         }
         else {
-            if( algo ) {
-                if( fname )
-                    fputs( pname, stdout );
-                print_hex(md_read(md, algo), md_digest_length(algo) );
-            }
+            if( algo )
+              print_hex(md,-algo,fname);
             else {
             else {
-                printf(  "%s   MD5 = ", fname?pname:"" );
-                print_hex(md_read(md, DIGEST_ALGO_MD5), 16 );
-                printf("\n%s  SHA1 = ", fname?pname:""  );
-                print_hex(md_read(md, DIGEST_ALGO_SHA1), 20 );
-                printf("\n%sRMD160 = ", fname?pname:""  );
-                print_hex(md_read(md, DIGEST_ALGO_RMD160), 20 );
-                if( !check_digest_algo(DIGEST_ALGO_TIGER) ) {
-                    printf("\n%s TIGER = ", fname?pname:""  );
-                    print_hex(md_read(md, DIGEST_ALGO_TIGER), 24 );
-                }
+                print_hex( md, DIGEST_ALGO_MD5, fname );
+                print_hex( md, DIGEST_ALGO_SHA1, fname );
+                print_hex( md, DIGEST_ALGO_RMD160, fname );
+#ifdef USE_TIGER192
+               print_hex( md, DIGEST_ALGO_TIGER, fname );
+#endif
+#ifdef USE_SHA256
+                print_hex( md, DIGEST_ALGO_SHA256, fname );
+#endif
+#ifdef USE_SHA512
+               print_hex( md, DIGEST_ALGO_SHA384, fname );
+               print_hex( md, DIGEST_ALGO_SHA512, fname );
+#endif
             }
             }
-            putchar('\n');
         }
     }
     md_close(md);
         }
     }
     md_close(md);
@@ -2673,6 +2904,7 @@ add_notation_data( const char *string, int which )
     STRLIST sl,*notation_data;
     int critical=0;
     int highbit=0;
     STRLIST sl,*notation_data;
     int critical=0;
     int highbit=0;
+    int saw_at=0;
 
     if(which)
       notation_data=&opt.cert_notation_data;
 
     if(which)
       notation_data=&opt.cert_notation_data;
@@ -2684,13 +2916,29 @@ add_notation_data( const char *string, int which )
        string++;
     }
 
        string++;
     }
 
-    for( s=string ; *s != '='; s++ ) {
-       if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) ) {
+    /* If and when the IETF assigns some official name tags, we'll
+       have to add them here. */
+
+    for( s=string ; *s != '='; s++ )
+      {
+       if( *s=='@')
+         saw_at=1;
+
+       if( !*s || (*s & 0x80) || (!isgraph(*s) && !isspace(*s)) )
+         {
            log_error(_("a notation name must have only printable characters "
                        "or spaces, and end with an '='\n") );
            return;
            log_error(_("a notation name must have only printable characters "
                        "or spaces, and end with an '='\n") );
            return;
-       }
-    }
+         }
+      }
+
+    if(!saw_at && !opt.expert)
+      {
+       log_error(
+               _("a user notation name must contain the '@' character\n"));
+       return;
+      }
+
     /* we only support printable text - therefore we enforce the use
      * of only printable characters (an empty value is valid) */
     for( s++; *s ; s++ ) {
     /* we only support printable text - therefore we enforce the use
      * of only printable characters (an empty value is valid) */
     for( s++; *s ; s++ ) {