common: New function percent_data_escape.
authorWerner Koch <wk@gnupg.org>
Mon, 2 Jul 2018 18:24:10 +0000 (20:24 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 2 Jul 2018 18:25:30 +0000 (20:25 +0200)
* common/percent.c (percent_data_escape): New.
* common/t-percent.c (test_percent_data_escape): New.

Signed-off-by: Werner Koch <wk@gnupg.org>
common/percent.c
common/t-percent.c
common/util.h

index 569c5fd..eeb026f 100644 (file)
@@ -87,6 +87,50 @@ percent_plus_escape (const char *string)
 }
 
 
+/* Create a newly alloced string from (DATA,DATALEN) with embedded
+ * Nuls quoted as %00.  The standard percent unescaping can be
+ * used to reverse this encoding.   */
+char *
+percent_data_escape (const void *data, size_t datalen)
+{
+  char *buffer, *p;
+  const char *s;
+  size_t n, length;
+
+  for (length=1, s=data, n=datalen; n; s++, n--)
+    {
+      if (!*s || *s == '%')
+        length += 3;
+      else
+        length++;
+    }
+
+  buffer = p = xtrymalloc (length);
+  if (!buffer)
+    return NULL;
+
+  for (s=data, n=datalen; n; s++, n--)
+    {
+      if (!*s)
+        {
+          memcpy (p, "%00", 3);
+          p += 3;
+        }
+      else if (*s == '%')
+        {
+          memcpy (p, "%25", 3);
+          p += 3;
+        }
+      else
+        *p++ = *s;
+    }
+  *p = 0;
+
+  return buffer;
+
+}
+
+
 /* Do the percent and plus/space unescaping from STRING to BUFFER and
    return the length of the valid buffer.  Plus unescaping is only
    done if WITHPLUS is true.  An escaped Nul character will be
index 145a89b..94ece92 100644 (file)
@@ -99,6 +99,55 @@ test_percent_plus_escape (void)
 }
 
 
+static void
+test_percent_data_escape (void)
+{
+  static struct {
+    const char *data;
+    size_t datalen;
+    const char *expect;
+  } tbl[] = {
+    {
+      "", 0,
+      ""
+    }, {
+      "a", 1,
+      "a",
+    }, {
+      "%22", 3,
+      "%2522"
+    }, {
+      "%%", 3,
+      "%25%25%00"
+    }, {
+      "\n \0BC\t", 6,
+      "\n %00BC\t"
+    }, { NULL, 0, NULL }
+  };
+  char *buf;
+  int i;
+  size_t len;
+
+  for (i=0; tbl[i].data; i++)
+    {
+      buf = percent_data_escape (tbl[i].data, tbl[i].datalen);
+      if (!buf)
+        {
+          fprintf (stderr, "out of core: %s\n", strerror (errno));
+          exit (2);
+        }
+      if (strcmp (buf, tbl[i].expect))
+        fail (i);
+      len = percent_plus_unescape_inplace (buf, 0);
+      if (len != tbl[i].datalen)
+        fail (i);
+      else if (memcmp (buf, tbl[i].data, tbl[i].datalen))
+        fail (i);
+      xfree (buf);
+    }
+}
+
+
 
 int
 main (int argc, char **argv)
@@ -109,6 +158,6 @@ main (int argc, char **argv)
   /* FIXME: We escape_unescape is not tested - only
      percent_plus_unescape.  */
   test_percent_plus_escape ();
-
+  test_percent_data_escape ();
   return 0;
 }
index 123d880..682415d 100644 (file)
@@ -201,6 +201,7 @@ char *hex2str_alloc (const char *hexstring, size_t *r_count);
 
 /*-- percent.c --*/
 char *percent_plus_escape (const char *string);
+char *percent_data_escape (const void *data, size_t datalen);
 char *percent_plus_unescape (const char *string, int nulrepl);
 char *percent_unescape (const char *string, int nulrepl);