* keyserver.c (keyserver_search_prompt): Make sure the search string is
[gnupg.git] / g10 / misc.c
index 01f34b4..c2dfe35 100644 (file)
@@ -1,5 +1,5 @@
 /* misc.c -  miscellaneous functions
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
  *               2004 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
@@ -476,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)
@@ -669,57 +644,58 @@ compliance_failure(void)
   opt.compliance=CO_GNUPG;
 }
 
+/* Break a string into successive option pieces.  Accepts single word
+   options and key=value argument options. */
 char *
-argsep(char **stringp,char **arg)
+optsep(char **stringp)
 {
-  char *tok,*next;
+  char *tok,*end;
 
   tok=*stringp;
-  *arg=NULL;
-
   if(tok)
     {
-      next=strpbrk(tok," ,=");
-
-      if(next)
+      end=strpbrk(tok," ,=");
+      if(end)
        {
          int sawequals=0;
+         char *ptr=end;
 
-         if(*next=='=')
-           sawequals=1;
-
-         *next++='\0';
-         *stringp=next;
-
-         /* what we need to do now is scan along starting with *next.
-            If the next character we see (ignoring spaces) is a =
+         /* 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(*next)
+         while(*ptr)
            {
-             if(*next=='=')
+             if(*ptr=='=')
                sawequals=1;
-             else if(*next!=' ')
+             else if(*ptr!=' ')
                break;
-             next++;
+             ptr++;
            }
 
-         /* At this point, *next is either an empty string, or the
-            beginning of the next token (which is an argument if
-            sawequals is true). */
-
+         /* There is an argument, so grab that too.  At this point,
+            ptr points to the first character of the argument. */
          if(sawequals)
            {
-             *arg=next;
-             next=strpbrk(*arg," ,");
-             if(next)
+             /* Is it a quoted argument? */
+             if(*ptr=='"')
                {
-                 *next++='\0';
-                 *stringp=next;
+                 ptr++;
+                 end=strchr(ptr,'"');
+                 if(end)
+                   end++;
                }
              else
-               *stringp=NULL;
+               end=strpbrk(ptr," ,");
+           }
+
+         if(end && *end)
+           {
+             *end='\0';
+             *stringp=end+1;
            }
+         else
+           *stringp=NULL;
        }
       else
        *stringp=NULL;
@@ -728,13 +704,70 @@ argsep(char **stringp,char **arg)
   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,*arg;
+  char *tok;
 
-  while((tok=argsep(&str,&arg)))
+  while((tok=optsep(&str)))
     {
       int i,rev=0;
       char *otok=tok;
@@ -750,7 +783,7 @@ parse_options(char *str,unsigned int *options,
 
       for(i=0;opts[i].name;i++)
        {
-         size_t toklen=strlen(tok);
+         size_t toklen=optlen(tok);
 
          if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
            {
@@ -771,11 +804,17 @@ parse_options(char *str,unsigned int *options,
                }
 
              if(rev)
-               *options&=~opts[i].bit;
+               {
+                 *options&=~opts[i].bit;
+                 if(opts[i].value)
+                   *opts[i].value=NULL;
+               }
              else
-               *options|=opts[i].bit;
-             if(opts[i].value)
-               *opts[i].value=arg?m_strdup(arg):NULL;
+               {
+                 *options|=opts[i].bit;
+                 if(opts[i].value)
+                   *opts[i].value=argsplit(tok);
+               }
              break;
            }
        }