Add a couple of new utility functions.
authorWerner Koch <wk@gnupg.org>
Fri, 13 Jun 2014 06:47:49 +0000 (08:47 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 13 Jun 2014 06:47:49 +0000 (08:47 +0200)
* src/logging.c (print_sanitized): New.
(log_printval, log_printkeyval): New.
* src/util.c (keyvalue_remove_nl): New.
(keyvalue_snatch): New.
(parse_www_form_urlencoded): New.

src/logging.c
src/logging.h
src/util.c
src/util.h

index 40d098c..7fd3356 100644 (file)
@@ -878,6 +878,67 @@ log_printhex (const char *text, const void *buffer, size_t length)
 }
 
 
+static void
+print_sanitized (const char *string)
+{
+  const unsigned char *s = string;
+
+  for (; *s; s++)
+    {
+      if (*s < 0x20 || *s == 0x7f || *s == '\\')
+        {
+          if (*s == '\n')
+            log_printf ("\\n");
+          else if (*s == '\r')
+            log_printf ("\\r");
+          else if (*s == '\f')
+            log_printf ("\\f");
+          else if (*s == '\v')
+            log_printf ("\\v");
+          else if (*s == '\b')
+            log_printf ("\\b");
+          else if (!*s)
+            log_printf ("\\0");
+          else
+            log_printf ("\\x%02x", *s);
+        }
+      else
+        log_printf ("%c", *s);
+    }
+}
+
+
+/* Print a key and a value after sanitizing it.  With PREFIX of NULL
+   print just the value, with PREFIX being an empty string, print a
+   trailing linefeed, otherwise print the prefix, the value, abd the
+   LF. */
+void
+log_printval (const char *prefix, const char *value)
+{
+  if (prefix && *prefix)
+    log_info ("%s", prefix);
+  if (value)
+    print_sanitized (value);
+  if (prefix)
+    log_printf ("\n");
+}
+
+
+void
+log_printkeyval (const char *prefix, const char *key, const char *value)
+{
+  if (prefix)
+    log_info ("%s", prefix);
+  if (key)
+    print_sanitized (key);
+  log_printf ("=");
+  if (value)
+    print_sanitized (value);
+  log_printf ("\n");
+}
+
+
+
 /*
 void
 log_printcanon () {}
index 783523a..1c7255b 100644 (file)
@@ -97,6 +97,10 @@ void log_flush (void);
    linefeed, otherwise print an entire debug line with TEXT followed
    by the hexdump and a final LF.  */
 void log_printhex (const char *text, const void *buffer, size_t length);
+void log_printval (const char *prefix, const char *value);
+
+void log_printkeyval (const char *prefix, const char *key, const char *value);
+
 
 void log_clock (const char *string);
 
index d58ca34..8c59ccb 100644 (file)
@@ -305,6 +305,22 @@ keyvalue_append_with_nl (keyvalue_t kv, const char *value)
 }
 
 
+/* Remove all newlines from the value of KV.  This is done in place
+   and and works always.  */
+void
+keyvalue_remove_nl (keyvalue_t kv)
+{
+  char *s, *d;
+
+  if (!kv || !kv->value)
+    return;
+  for (s = d = kv->value; *s; s++)
+    if (*s != '\n')
+      *d++ = *s;
+  *d = 0;
+}
+
+
 gpg_error_t
 keyvalue_put (keyvalue_t *list, const char *key, const char *value)
 {
@@ -396,6 +412,25 @@ keyvalue_get (keyvalue_t list, const char *key)
 }
 
 
+/* Same as keyvalue_get put return the value as a modifiable string
+   and the value in LIST to NULL.  The caller must xfree the
+   result.  */
+char *
+keyvalue_snatch (keyvalue_t list, const char *key)
+{
+  keyvalue_t kv;
+
+  for (kv = list; kv; kv = kv->next)
+    if (!strcmp (kv->name, key))
+      {
+        char *p = kv->value;
+        kv->value = NULL;
+        return p;
+      }
+  return NULL;
+}
+
+
 const char *
 keyvalue_get_string (keyvalue_t list, const char *key)
 {
@@ -413,6 +448,68 @@ keyvalue_get_int (keyvalue_t list, const char *key)
   return atoi (s);
 }
 
+
+\f
+/* Parse the www-form-urlencoded data in STRING into a new dictionary
+   and store that dictionary at R_DICT.  On error store NULL at R_DICT
+   and return an error code.  Note that STRING will be modified on
+   return. */
+gpg_error_t
+parse_www_form_urlencoded (keyvalue_t *r_dict, char *string)
+{
+  gpg_error_t err;
+  char *endp, *name, *value;
+  size_t n;
+  keyvalue_t dict = NULL;
+
+  *r_dict = NULL;
+
+  do
+    {
+      endp = strchr (string, '&');
+      if (endp)
+        *endp = 0;
+
+      name = string;
+      value = strchr (name, '=');
+      if (value)
+        *value++ = 0;
+
+      name[(n=percent_plus_unescape_inplace (name, 0))] = 0;
+      if (!n || strlen (name) != n)
+        {
+          keyvalue_release (dict);
+          return gpg_error (GPG_ERR_INV_VALUE); /* Nul in name or empty.  */
+        }
+
+      if (value)
+        {
+          value[(n=percent_plus_unescape_inplace (value, 0))] = 0;
+          if (strlen (value) != n)
+            {
+              keyvalue_release (dict);
+              return gpg_error (GPG_ERR_INV_VALUE); /* Nul in value.  */
+            }
+        }
+
+      err = keyvalue_put (&dict, name, value? value:"");
+      if (err)
+        {
+          keyvalue_release (dict);
+          return err;
+        }
+
+      if (endp)
+        string = endp + 1;
+    }
+  while (endp);
+
+  *r_dict = dict;
+  return 0;
+}
+
+
+
 \f
 /* Mapping table for zb32.  */
 static char const zb32asc[32] = {'y','b','n','d','r','f','g','8',
index 9ef942f..f369268 100644 (file)
@@ -129,6 +129,7 @@ struct keyvalue_s
 typedef struct keyvalue_s *keyvalue_t;
 
 gpg_error_t keyvalue_append_with_nl (keyvalue_t kv, const char *value);
+void keyvalue_remove_nl (keyvalue_t kv);
 gpg_error_t keyvalue_put (keyvalue_t *list,
                                const char *key, const char *value);
 gpg_error_t keyvalue_del (keyvalue_t list, const char *key);
@@ -137,9 +138,12 @@ gpg_error_t keyvalue_putf (keyvalue_t *list, const char *key,
 void keyvalue_release (keyvalue_t kv);
 keyvalue_t keyvalue_find (keyvalue_t list, const char *key);
 const char *keyvalue_get (keyvalue_t list, const char *key);
+char *keyvalue_snatch (keyvalue_t list, const char *key);
 const char *keyvalue_get_string (keyvalue_t list, const char *key);
 int         keyvalue_get_int (keyvalue_t list, const char *key);
 
+gpg_error_t parse_www_form_urlencoded (keyvalue_t *r_dict, char *string);
+
 int zb32_index (int c);
 char *zb32_encode (const void *data, unsigned int databits);