summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--TODO.org5
-rw-r--r--lib/buffer.c139
-rw-r--r--t/test_umberlog.c30
3 files changed, 166 insertions, 8 deletions
diff --git a/TODO.org b/TODO.org
index 7fa5221..10c9b30 100644
--- a/TODO.org
+++ b/TODO.org
@@ -97,7 +97,10 @@ systems where we would need to copy the thing around.
We need a way to get the post-message key-value pairs some other way,
or with using va_copy() and counting format strings and whatnot.
-* WIP Remove json-c dependency
+* DONE Remove json-c dependency
+CLOSED: [2012-04-13 Fri 13:10]
+- CLOSING NOTE [2012-04-13 Fri 13:10] \\
+ Implemented proper escaping too, and added a test case to verify the behaviour.
- Note taken on [2012-04-13 Fri 12:09] \\
Work in progress: the buffer handling was moved to buffer.c, it does
the heavy lifting and JSON formatting. It does not do escaping yet,
diff --git a/lib/buffer.c b/lib/buffer.c
index d538fda..4c6f0b7 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -33,6 +33,115 @@
#include <stdlib.h>
#include <string.h>
+static const unsigned char json_exceptions[] =
+ {
+ 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+ 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
+ 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
+ 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+ 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
+ 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe,
+ 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+ 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
+ 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+ 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
+ 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6,
+ 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
+ 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+ 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+ 0xff, '\0'
+ };
+
+static inline char *
+_ul_str_escape (const char *str)
+{
+ const unsigned char *p;
+ char *dest;
+ char *q;
+ static unsigned char exmap[256];
+ static int exmap_inited;
+
+ if (!str)
+ return NULL;
+
+ p = (unsigned char *)str;
+ q = dest = malloc (strlen (str) * 6 + 1);
+
+ if (!exmap_inited)
+ {
+ const unsigned char *e = json_exceptions;
+
+ memset (exmap, 0, 256);
+ while (*e)
+ {
+ exmap[*e] = 1;
+ e++;
+ }
+ exmap_inited = 1;
+ }
+
+ while (*p)
+ {
+ if (exmap[*p])
+ *q++ = *p;
+ else
+ {
+ switch (*p)
+ {
+ case '\b':
+ *q++ = '\\';
+ *q++ = 'b';
+ break;
+ case '\f':
+ *q++ = '\\';
+ *q++ = 'f';
+ break;
+ case '\n':
+ *q++ = '\\';
+ *q++ = 'n';
+ break;
+ case '\r':
+ *q++ = '\\';
+ *q++ = 'r';
+ break;
+ case '\t':
+ *q++ = '\\';
+ *q++ = 't';
+ break;
+ case '\\':
+ *q++ = '\\';
+ *q++ = '\\';
+ break;
+ case '"':
+ *q++ = '\\';
+ *q++ = '"';
+ break;
+ default:
+ if ((*p < ' ') || (*p >= 0177))
+ {
+ const char *json_hex_chars = "0123456789abcdef";
+
+ *q++ = '\\';
+ *q++ = 'u';
+ *q++ = '0';
+ *q++ = '0';
+ *q++ = json_hex_chars[(*p) >> 4];
+ *q++ = json_hex_chars[(*p) & 0xf];
+ }
+ else
+ *q++ = *p;
+ break;
+ }
+ }
+ p++;
+ }
+
+ *q = 0;
+ return dest;
+}
+
static inline ul_buffer_t *
_ul_buffer_ensure_size (ul_buffer_t *buffer, size_t size)
{
@@ -58,24 +167,40 @@ ul_buffer_reset (ul_buffer_t *buffer)
ul_buffer_t *
ul_buffer_append (ul_buffer_t *buffer, const char *key, const char *value)
{
+ char *k, *v;
size_t lk, lv;
- lk = strlen (key);
- lv = strlen (value);
+ k = _ul_str_escape (key);
+ if (!k)
+ return NULL;
+ v = _ul_str_escape (value);
+ if (!v)
+ {
+ free (k);
+ return NULL;
+ }
+
+ lk = strlen (k);
+ lv = strlen (v);
buffer = _ul_buffer_ensure_size (buffer, buffer->len + lk + lv + 6);
if (!buffer)
- return NULL;
-
- /* FIXME: Escpae stuff here */
+ {
+ free (k);
+ free (v);
+ return NULL;
+ }
memcpy (buffer->msg + buffer->len, "\"", 1);
- memcpy (buffer->msg + buffer->len + 1, key, lk);
+ memcpy (buffer->msg + buffer->len + 1, k, lk);
memcpy (buffer->msg + buffer->len + 1 + lk, "\":\"", 3);
- memcpy (buffer->msg + buffer->len + 1 + lk + 3, value, lv);
+ memcpy (buffer->msg + buffer->len + 1 + lk + 3, v, lv);
memcpy (buffer->msg + buffer->len + 1 + lk + 3 + lv, "\",", 2);
buffer->len += lk + lv + 6;
+ free (k);
+ free (v);
+
return buffer;
}
diff --git a/t/test_umberlog.c b/t/test_umberlog.c
index f20d28b..26fbadb 100644
--- a/t/test_umberlog.c
+++ b/t/test_umberlog.c
@@ -190,6 +190,35 @@ test_no_timestamp (void)
closelog ();
}
+static void
+test_json_escape (void)
+{
+ char *msg;
+ struct json_object *jo;
+
+ openlog ("umberlog/test_json_escape", LOG_UL_NODISCOVER, LOG_LOCAL0);
+
+ msg = ul_format (LOG_DEBUG, "%s", __FUNCTION__,
+ "quotes", "Hi, \"quoted value\" speaking!",
+ "\"really\"", "yeah",
+ "control", "foo\nbar",
+ "utf8", "Árvíztűrő tükörfúrógép",
+ "junk", "\013foo",
+ NULL);
+ jo = parse_msg (msg);
+ free (msg);
+
+ verify_value (jo, "quotes", "Hi, \"quoted value\" speaking!");
+ verify_value (jo, "\"really\"", "yeah");
+ verify_value (jo, "control", "foo\nbar");
+ verify_value (jo, "utf8", "Árvíztűrő tükörfúrógép");
+ verify_value (jo, "junk", "\013foo");
+
+ json_object_put (jo);
+
+ closelog ();
+}
+
int
main (void)
{
@@ -198,6 +227,7 @@ main (void)
test_additional_fields ();
test_discover_priority ();
test_no_timestamp ();
+ test_json_escape ();
return 0;
}