summaryrefslogtreecommitdiff
path: root/src/json/json.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-11-21 00:53:11 +0100
committerChristian Grothoff <christian@grothoff.org>2021-11-21 00:53:11 +0100
commitae2ce4aaeed35fd077cac016795f069b35189756 (patch)
tree8aac04ba02cc1055f71ff0b2392c6eaec2ed39dc /src/json/json.c
parenta5a3b2ea9ab6fa47d06531b34599237b62742443 (diff)
downloadexchange-ae2ce4aaeed35fd077cac016795f069b35189756.tar.gz
exchange-ae2ce4aaeed35fd077cac016795f069b35189756.tar.bz2
exchange-ae2ce4aaeed35fd077cac016795f069b35189756.zip
trying to fix #7039 insanity for RFC 8785, Dold: please check
Diffstat (limited to 'src/json/json.c')
-rw-r--r--src/json/json.c158
1 files changed, 157 insertions, 1 deletions
diff --git a/src/json/json.c b/src/json/json.c
index 479a0ae96..af2b84e27 100644
--- a/src/json/json.c
+++ b/src/json/json.c
@@ -23,6 +23,7 @@
#include <gnunet/gnunet_util_lib.h>
#include "taler_util.h"
#include "taler_json_lib.h"
+#include <unistr.h>
/**
@@ -61,6 +62,161 @@ contains_real (const json_t *json)
/**
+ * Dump character in the low range into @a buf
+ * following RFC 8785.
+ *
+ * @param[in,out] buf buffer to modify
+ * @param val value to dump
+ */
+static void
+lowdump (struct GNUNET_Buffer *buf,
+ unsigned char val)
+{
+ char scratch[7];
+
+ switch (val)
+ {
+ case 0x8:
+ GNUNET_buffer_write (buf,
+ "\b",
+ 2);
+ break;
+ case 0x9:
+ GNUNET_buffer_write (buf,
+ "\t",
+ 2);
+ break;
+ case 0xA:
+ GNUNET_buffer_write (buf,
+ "\n",
+ 2);
+ break;
+ case 0xC:
+ GNUNET_buffer_write (buf,
+ "\f",
+ 2);
+ break;
+ case 0xD:
+ GNUNET_buffer_write (buf,
+ "\r",
+ 2);
+ break;
+ default:
+ GNUNET_snprintf (scratch,
+ sizeof (scratch),
+ "\\u%04x",
+ (unsigned int) val);
+ GNUNET_buffer_write (buf,
+ scratch,
+ 6);
+ break;
+ }
+}
+
+
+/**
+ * Re-encode string at @a inp to match RFC 8785 (section 3.2.2.2).
+ *
+ * @param[in,out] inp pointer to string to re-encode
+ * @return number of bytes in resulting @a inp
+ */
+static size_t
+rfc8785encode (char **inp)
+{
+ struct GNUNET_Buffer buf = { 0 };
+ size_t left = strlen (*inp) + 1;
+ size_t olen;
+ char *in = *inp;
+ const char *pos = in;
+
+ GNUNET_buffer_prealloc (&buf,
+ left + 40);
+ buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
+ while (1)
+ {
+ int mbl = u8_mblen ((unsigned char *) pos,
+ left);
+ unsigned char val;
+
+ if (0 == mbl)
+ break;
+ val = (unsigned char) *pos;
+ if ( (1 == mbl) &&
+ (val <= 0x1F) )
+ {
+ lowdump (&buf,
+ val);
+ }
+ else if ( (1 == mbl) && ('\\' == *pos) )
+ {
+ switch (*(pos + 1))
+ {
+ case '\\':
+ mbl = 2;
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ break;
+ case 'u':
+ {
+ unsigned int num;
+ uint32_t n32;
+ unsigned char res[8];
+ size_t rlen;
+
+ GNUNET_assert ( (1 ==
+ sscanf (pos + 2,
+ "%4x",
+ &num)) ||
+ (1 ==
+ sscanf (pos + 2,
+ "%4X",
+ &num)) );
+ mbl = 6;
+ n32 = (uint32_t) num;
+ rlen = sizeof (res);
+ u32_to_u8 (&n32,
+ 1,
+ res,
+ &rlen);
+ if ( (1 == rlen) &&
+ (res[0] <= 0x1F) )
+ {
+ lowdump (&buf,
+ res[0]);
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ (const char *) res,
+ rlen);
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ GNUNET_buffer_write (&buf,
+ pos,
+ mbl);
+ }
+ left -= mbl;
+ pos += mbl;
+ }
+
+ /* 0-terminate buffer */
+ GNUNET_buffer_write (&buf,
+ "",
+ 1);
+ GNUNET_free (in);
+ *inp = GNUNET_buffer_reap (&buf,
+ &olen);
+ return olen;
+}
+
+
+/**
* Dump the @a json to a string and hash it.
*
* @param json value to hash
@@ -97,7 +253,7 @@ dump_and_hash (const json_t *json,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- len = strlen (wire_enc) + 1;
+ len = rfc8785encode (&wire_enc);
if (NULL == salt)
{
GNUNET_CRYPTO_hash (wire_enc,