* keyserver.c (keyserver_search_prompt): Make sure the search string is
[gnupg.git] / g10 / misc.c
index 58d6bce..c2dfe35 100644 (file)
@@ -1,5 +1,6 @@
 /* misc.c -  miscellaneous functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
+ *               2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <unistd.h>
 #include <errno.h>
 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
-  #include <asm/sysinfo.h>
-  #include <asm/unistd.h>
+#include <asm/sysinfo.h>
+#include <asm/unistd.h>
 #endif
 #ifdef HAVE_SETRLIMIT
-  #include <time.h>
-  #include <sys/time.h>
-  #include <sys/resource.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #endif
 #include "util.h"
 #include "main.h"
 #include "options.h"
 #include "i18n.h"
 
-
-const char *g10m_revision_string(int);
-const char *g10c_revision_string(int);
-const char *g10u_revision_string(int);
-
-#ifdef __GNUC__
-volatile
-#endif
-        void
-pull_in_libs(void)
-{
-    g10m_revision_string(0);
-    g10c_revision_string(0);
-    g10u_revision_string(0);
-}
-
-
 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
 static int
 setsysinfo(unsigned long op, void *buffer, unsigned long size,
@@ -84,10 +68,10 @@ trap_unaligned(void)
 int
 disable_core_dumps()
 {
- #ifdef HAVE_DOSISH_SYSTEM
+#ifdef HAVE_DOSISH_SYSTEM
     return 0;
- #else
-  #ifdef HAVE_SETRLIMIT
+#else
+#ifdef HAVE_SETRLIMIT
     struct rlimit limit;
 
     limit.rlim_cur = 0;
@@ -96,9 +80,9 @@ disable_core_dumps()
        return 0;
     if( errno != EINVAL && errno != ENOSYS )
        log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
-  #endif
+#endif
     return 1;
- #endif
+#endif
 }
 
 
@@ -179,9 +163,9 @@ print_cipher_algo_note( int algo )
             || algo == CIPHER_ALGO_CAST5
             || algo == CIPHER_ALGO_BLOWFISH
             || algo == CIPHER_ALGO_TWOFISH
-            || algo == CIPHER_ALGO_RIJNDAEL
-            || algo == CIPHER_ALGO_RIJNDAEL192
-            || algo == CIPHER_ALGO_RIJNDAEL256
+            || algo == CIPHER_ALGO_AES
+            || algo == CIPHER_ALGO_AES192
+            || algo == CIPHER_ALGO_AES256
           )
        ;
     else {
@@ -258,7 +242,7 @@ openpgp_pk_algo_usage ( int algo )
     /* they are hardwired in gpg 1.0 */
     switch ( algo ) {    
       case PUBKEY_ALGO_RSA:
-          use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
+          use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH;
           break;
       case PUBKEY_ALGO_RSA_E:
           use = PUBKEY_USAGE_ENC;
@@ -270,10 +254,7 @@ openpgp_pk_algo_usage ( int algo )
           use = PUBKEY_USAGE_ENC;
           break;
       case PUBKEY_ALGO_DSA:  
-          use = PUBKEY_USAGE_SIG;
-          break;
-      case PUBKEY_ALGO_ELGAMAL:
-          use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC;
+          use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
           break;
       default:
           break;
@@ -322,6 +303,8 @@ pct_expando(const char *string,struct expando_args *args)
   if(args->sk)
     keyid_from_sk(args->sk,sk_keyid);
 
+  /* This is used so that %k works in photoid command strings in
+     --list-secret-keys (which of course has a sk, but no pk). */
   if(!args->pk && args->sk)
     keyid_from_sk(args->sk,pk_keyid);
 
@@ -383,16 +366,38 @@ pct_expando(const char *string,struct expando_args *args)
                }
              break;
 
-           case 'f': /* fingerprint */
+           case 'p': /* primary pk fingerprint of a sk */
+           case 'f': /* pk fingerprint */
+           case 'g': /* sk fingerprint */
              {
                byte array[MAX_FINGERPRINT_LEN];
                size_t len;
                int i;
 
-               if(args->pk)
+               if((*(ch+1))=='p' && args->sk)
+                 {
+                   if(args->sk->is_primary)
+                     fingerprint_from_sk(args->sk,array,&len);
+                   else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
+                     {
+                       PKT_public_key *pk=
+                         m_alloc_clear(sizeof(PKT_public_key));
+
+                       if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
+                         fingerprint_from_pk(pk,array,&len);
+                       else
+                         memset(array,0,(len=MAX_FINGERPRINT_LEN));
+                       free_public_key(pk);
+                     }
+                   else
+                     memset(array,0,(len=MAX_FINGERPRINT_LEN));
+                 }
+               else if((*(ch+1))=='f' && args->pk)
                  fingerprint_from_pk(args->pk,array,&len);
+               else if((*(ch+1))=='g' && args->sk)
+                 fingerprint_from_sk(args->sk,array,&len);
                else
-                 memset(array,0, (len=MAX_FINGERPRINT_LEN));
+                 memset(array,0,(len=MAX_FINGERPRINT_LEN));
 
                if(idx+(len*2)<maxlen)
                  {
@@ -471,31 +476,6 @@ pct_expando(const char *string,struct expando_args *args)
   return NULL;
 }
 
-int
-hextobyte( const char *s )
-{
-    int c;
-
-    if( *s >= '0' && *s <= '9' )
-       c = 16 * (*s - '0');
-    else if( *s >= 'A' && *s <= 'F' )
-       c = 16 * (10 + *s - 'A');
-    else if( *s >= 'a' && *s <= 'f' )
-       c = 16 * (10 + *s - 'a');
-    else
-       return -1;
-    s++;
-    if( *s >= '0' && *s <= '9' )
-       c += *s - '0';
-    else if( *s >= 'A' && *s <= 'F' )
-       c += 10 + *s - 'A';
-    else if( *s >= 'a' && *s <= 'f' )
-       c += 10 + *s - 'a';
-    else
-       return -1;
-    return c;
-}
-
 void
 deprecated_warning(const char *configname,unsigned int configlineno,
                   const char *option,const char *repl1,const char *repl2)
@@ -520,21 +500,27 @@ deprecated_warning(const char *configname,unsigned int configlineno,
 const char *
 compress_algo_to_string(int algo)
 {
-  const char *s="?";
+  const char *s=NULL;
 
   switch(algo)
     {
-    case 0:
-      s="Uncompressed";
+    case COMPRESS_ALGO_NONE:
+      s=_("Uncompressed");
       break;
 
-    case 1:
+    case COMPRESS_ALGO_ZIP:
       s="ZIP";
       break;
 
-    case 2:
+    case COMPRESS_ALGO_ZLIB:
       s="ZLIB";
       break;
+
+#ifdef HAVE_BZIP2
+    case COMPRESS_ALGO_BZIP2:
+      s="BZIP2";
+      break;
+#endif
     }
 
   return s;
@@ -543,18 +529,31 @@ compress_algo_to_string(int algo)
 int
 string_to_compress_algo(const char *string)
 {
-  if(ascii_strcasecmp(string,"uncompressed")==0)
+  /* NOTE TO TRANSLATOR: See doc/TRANSLATE about this string. */
+  if(match_multistr(_("uncompressed|none"),string))
+    return 0;
+  else if(ascii_strcasecmp(string,"uncompressed")==0)
+    return 0;
+  else if(ascii_strcasecmp(string,"none")==0)
     return 0;
   else if(ascii_strcasecmp(string,"zip")==0)
     return 1;
   else if(ascii_strcasecmp(string,"zlib")==0)
     return 2;
+#ifdef HAVE_BZIP2
+  else if(ascii_strcasecmp(string,"bzip2")==0)
+    return 3;
+#endif
   else if(ascii_strcasecmp(string,"z0")==0)
     return 0;
   else if(ascii_strcasecmp(string,"z1")==0)
     return 1;
   else if(ascii_strcasecmp(string,"z2")==0)
     return 2;
+#ifdef HAVE_BZIP2
+  else if(ascii_strcasecmp(string,"z3")==0)
+    return 3;
+#endif
   else
     return -1;
 }
@@ -562,8 +561,13 @@ string_to_compress_algo(const char *string)
 int
 check_compress_algo(int algo)
 {
+#ifdef HAVE_BZIP2
+  if(algo>=0 && algo<=3)
+    return 0;
+#else
   if(algo>=0 && algo<=2)
     return 0;
+#endif
 
   return G10ERR_COMPR_ALGO;
 }
@@ -580,13 +584,13 @@ default_cipher_algo(void)
 }
 
 /* There is no default_digest_algo function, but see
-   sign.c:hash_for */
+   sign.c:hash_for() */
 
 int
 default_compress_algo(void)
 {
-  if(opt.def_compress_algo!=-1)
-    return opt.def_compress_algo;
+  if(opt.compress_algo!=-1)
+    return opt.compress_algo;
   else if(opt.personal_compress_prefs)
     return opt.personal_compress_prefs[0].value;
   else
@@ -639,3 +643,189 @@ compliance_failure(void)
   log_info(_("this message may not be usable by %s\n"),compliance_string());
   opt.compliance=CO_GNUPG;
 }
+
+/* Break a string into successive option pieces.  Accepts single word
+   options and key=value argument options. */
+char *
+optsep(char **stringp)
+{
+  char *tok,*end;
+
+  tok=*stringp;
+  if(tok)
+    {
+      end=strpbrk(tok," ,=");
+      if(end)
+       {
+         int sawequals=0;
+         char *ptr=end;
+
+         /* what we need to do now is scan along starting with *end,
+            If the next character we see (ignoring spaces) is an =
+            sign, then there is an argument. */
+
+         while(*ptr)
+           {
+             if(*ptr=='=')
+               sawequals=1;
+             else if(*ptr!=' ')
+               break;
+             ptr++;
+           }
+
+         /* There is an argument, so grab that too.  At this point,
+            ptr points to the first character of the argument. */
+         if(sawequals)
+           {
+             /* Is it a quoted argument? */
+             if(*ptr=='"')
+               {
+                 ptr++;
+                 end=strchr(ptr,'"');
+                 if(end)
+                   end++;
+               }
+             else
+               end=strpbrk(ptr," ,");
+           }
+
+         if(end && *end)
+           {
+             *end='\0';
+             *stringp=end+1;
+           }
+         else
+           *stringp=NULL;
+       }
+      else
+       *stringp=NULL;
+    }
+
+  return tok;
+}
+
+/* Breaks an option value into key and value.  Returns NULL if there
+   is no value.  Note that "string" is modified to remove the =value
+   part. */
+char *
+argsplit(char *string)
+{
+  char *equals,*arg=NULL;
+
+  equals=strchr(string,'=');
+  if(equals)
+    {
+      char *quote,*space;
+
+      *equals='\0';
+      arg=equals+1;
+
+      /* Quoted arg? */
+      quote=strchr(arg,'"');
+      if(quote)
+       {
+         arg=quote+1;
+
+         quote=strchr(arg,'"');
+         if(quote)
+           *quote='\0';
+       }
+      else
+       {
+         size_t spaces;
+
+         /* Trim leading spaces off of the arg */
+         spaces=strspn(arg," ");
+         arg+=spaces;
+       }
+
+      /* Trim tailing spaces off of the tag */
+      space=strchr(string,' ');
+      if(space)
+       *space='\0';
+    }
+
+  return arg;
+}
+
+/* Return the length of the initial token, leaving off any
+   argument. */
+static size_t
+optlen(const char *s)
+{
+  char *end=strpbrk(s," =");
+
+  if(end)
+    return end-s;
+  else
+    return strlen(s);
+}
+
+int
+parse_options(char *str,unsigned int *options,
+             struct parse_options *opts,int noisy)
+{
+  char *tok;
+
+  while((tok=optsep(&str)))
+    {
+      int i,rev=0;
+      char *otok=tok;
+
+      if(tok[0]=='\0')
+       continue;
+
+      if(ascii_strncasecmp("no-",tok,3)==0)
+       {
+         rev=1;
+         tok+=3;
+       }
+
+      for(i=0;opts[i].name;i++)
+       {
+         size_t toklen=optlen(tok);
+
+         if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
+           {
+             /* We have a match, but it might be incomplete */
+             if(toklen!=strlen(opts[i].name))
+               {
+                 int j;
+
+                 for(j=i+1;opts[j].name;j++)
+                   {
+                     if(ascii_strncasecmp(opts[j].name,tok,toklen)==0)
+                       {
+                         if(noisy)
+                           log_info(_("ambiguous option `%s'\n"),otok);
+                         return 0;
+                       }
+                   }
+               }
+
+             if(rev)
+               {
+                 *options&=~opts[i].bit;
+                 if(opts[i].value)
+                   *opts[i].value=NULL;
+               }
+             else
+               {
+                 *options|=opts[i].bit;
+                 if(opts[i].value)
+                   *opts[i].value=argsplit(tok);
+               }
+             break;
+           }
+       }
+
+      if(!opts[i].name)
+       {
+         if(noisy)
+           log_info(_("unknown option `%s'\n"),otok);
+         return 0;
+       }
+    }
+
+  return 1;
+}