diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-08-07 17:19:54 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-08-07 17:19:54 +0100 |
commit | ef10b8b188fc04082f7e42579a3fd11790b067e5 (patch) | |
tree | eec882b9bf7c55e7304b56d7ad049b467e57ca99 | |
parent | 93f085f6f1893bf075945e23ff3a269dfac2c1cb (diff) | |
download | rspamd-ef10b8b188fc04082f7e42579a3fd11790b067e5.tar.gz rspamd-ef10b8b188fc04082f7e42579a3fd11790b067e5.zip |
Improve keys parsing.
-rw-r--r-- | src/rcl/rcl.h | 6 | ||||
-rw-r--r-- | src/rcl/rcl_internal.h | 6 | ||||
-rw-r--r-- | src/rcl/rcl_parser.c | 105 | ||||
-rw-r--r-- | src/rcl/rcl_util.c | 115 |
4 files changed, 141 insertions, 91 deletions
diff --git a/src/rcl/rcl.h b/src/rcl/rcl.h index 54c3c81e5..545dd19f9 100644 --- a/src/rcl/rcl.h +++ b/src/rcl/rcl.h @@ -282,6 +282,12 @@ rspamd_cl_object_t* rspamd_cl_parser_get_object (struct rspamd_cl_parser *parser void rspamd_cl_parser_free (struct rspamd_cl_parser *parser); /** + * Free cl object + * @param obj cl object to free + */ +void rspamd_cl_obj_free (rspamd_cl_object_t *obj); + +/** * Emit object to a string * @param obj object * @param emit_type if type is RSPAMD_CL_EMIT_JSON then emit json, if type is diff --git a/src/rcl/rcl_internal.h b/src/rcl/rcl_internal.h index 33256119d..e76c09fd8 100644 --- a/src/rcl/rcl_internal.h +++ b/src/rcl/rcl_internal.h @@ -84,4 +84,10 @@ struct rspamd_cl_parser { struct rspamd_cl_chunk *chunks; }; +/** + * Unescape json string inplace + * @param str + */ +void rspamd_cl_unescape_json_string (gchar *str); + #endif /* RCL_INTERNAL_H_ */ diff --git a/src/rcl/rcl_parser.c b/src/rcl/rcl_parser.c index f727991de..1c32bde59 100644 --- a/src/rcl/rcl_parser.c +++ b/src/rcl/rcl_parser.c @@ -236,96 +236,6 @@ rspamd_cl_lex_json_string (struct rspamd_cl_parser *parser, } /** - * Unescape json string inplace - * @param str - */ -static void -rspamd_cl_unescape_json_string (gchar *str) -{ - gchar *t = str, *h = str; - gint i, uval; - - /* t is target (tortoise), h is source (hare) */ - - while (*h != '\0') { - if (*h == '\\') { - h ++; - switch (*h) { - case 'n': - *t++ = '\n'; - break; - case 'r': - *t++ = '\r'; - break; - case 'b': - *t++ = '\b'; - break; - case 't': - *t++ = '\t'; - break; - case 'f': - *t++ = '\f'; - break; - case '\\': - *t++ = '\\'; - break; - case '"': - *t++ = '"'; - break; - case 'u': - /* Unicode escape */ - uval = 0; - for (i = 0; i < 4; i++) { - uval <<= 4; - if (g_ascii_isdigit (h[i])) { - uval += h[i] - '0'; - } - else if (h[i] >= 'a' && h[i] <= 'f') { - uval += h[i] - 'a' + 10; - } - else if (h[i] >= 'A' && h[i] <= 'F') { - uval += h[i] - 'A' + 10; - } - } - /* Encode */ - if(uval < 0x80) { - t[0] = (char)uval; - t ++; - } - else if(uval < 0x800) { - t[0] = 0xC0 + ((uval & 0x7C0) >> 6); - t[1] = 0x80 + ((uval & 0x03F)); - t += 2; - } - else if(uval < 0x10000) { - t[0] = 0xE0 + ((uval & 0xF000) >> 12); - t[1] = 0x80 + ((uval & 0x0FC0) >> 6); - t[2] = 0x80 + ((uval & 0x003F)); - t += 3; - } - else if(uval <= 0x10FFFF) { - t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); - t[1] = 0x80 + ((uval & 0x03F000) >> 12); - t[2] = 0x80 + ((uval & 0x000FC0) >> 6); - t[3] = 0x80 + ((uval & 0x00003F)); - t += 4; - } - else { - *t++ = '?'; - } - break; - default: - *t++ = '?'; - break; - } - } - else { - *t++ = *h++; - } - } -} - -/** * Parse a key in an object * @param parser * @param chunk @@ -338,7 +248,7 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, { const guchar *p, *c = NULL, *end; gboolean got_quote = FALSE, got_eq = FALSE, got_semicolon = FALSE; - rspamd_cl_object_t *nobj; + rspamd_cl_object_t *nobj, *tobj; p = chunk->pos; @@ -442,6 +352,12 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, return FALSE; } } + else if (*p == '/' || *p == '#') { + /* Check for comment */ + if (!rspamd_cl_skip_comments (parser, err)) { + return FALSE; + } + } else { /* Start value */ break; @@ -462,6 +378,13 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser, rspamd_cl_unescape_json_string (nobj->key); } + HASH_FIND_STR (parser->cur_obj->value.ov, nobj->key, tobj); + if (tobj != NULL) { + /* We are going to replace old key with new one */ + HASH_DELETE (hh, parser->cur_obj->value.ov, tobj); + rspamd_cl_obj_free (tobj); + } + HASH_ADD_KEYPTR (hh, parser->cur_obj->value.ov, nobj->key, strlen (nobj->key), nobj); return TRUE; diff --git a/src/rcl/rcl_util.c b/src/rcl/rcl_util.c index 96fc8dda4..58a6e2cd2 100644 --- a/src/rcl/rcl_util.c +++ b/src/rcl/rcl_util.c @@ -29,3 +29,118 @@ * @file rcl_util.c * Utilities for rcl parsing */ + + +void +rspamd_cl_obj_free (rspamd_cl_object_t *obj) +{ + rspamd_cl_object_t *sub, *tmp; + + if (obj->key != NULL) { + g_free (obj->key); + } + + if (obj->type == RSPAMD_CL_STRING) { + g_free (obj->value.sv); + } + else if (obj->type == RSPAMD_CL_ARRAY) { + sub = obj->value.ov; + while (sub != NULL) { + tmp = sub->next; + rspamd_cl_obj_free (sub); + sub = tmp; + } + } + else if (obj->type == RSPAMD_CL_OBJECT) { + HASH_ITER (hh, obj->value.ov, sub, tmp) { + HASH_DELETE (hh, obj->value.ov, sub); + rspamd_cl_obj_free (sub); + } + } +} + +void +rspamd_cl_unescape_json_string (gchar *str) +{ + gchar *t = str, *h = str; + gint i, uval; + + /* t is target (tortoise), h is source (hare) */ + + while (*h != '\0') { + if (*h == '\\') { + h ++; + switch (*h) { + case 'n': + *t++ = '\n'; + break; + case 'r': + *t++ = '\r'; + break; + case 'b': + *t++ = '\b'; + break; + case 't': + *t++ = '\t'; + break; + case 'f': + *t++ = '\f'; + break; + case '\\': + *t++ = '\\'; + break; + case '"': + *t++ = '"'; + break; + case 'u': + /* Unicode escape */ + uval = 0; + for (i = 0; i < 4; i++) { + uval <<= 4; + if (g_ascii_isdigit (h[i])) { + uval += h[i] - '0'; + } + else if (h[i] >= 'a' && h[i] <= 'f') { + uval += h[i] - 'a' + 10; + } + else if (h[i] >= 'A' && h[i] <= 'F') { + uval += h[i] - 'A' + 10; + } + } + /* Encode */ + if(uval < 0x80) { + t[0] = (char)uval; + t ++; + } + else if(uval < 0x800) { + t[0] = 0xC0 + ((uval & 0x7C0) >> 6); + t[1] = 0x80 + ((uval & 0x03F)); + t += 2; + } + else if(uval < 0x10000) { + t[0] = 0xE0 + ((uval & 0xF000) >> 12); + t[1] = 0x80 + ((uval & 0x0FC0) >> 6); + t[2] = 0x80 + ((uval & 0x003F)); + t += 3; + } + else if(uval <= 0x10FFFF) { + t[0] = 0xF0 + ((uval & 0x1C0000) >> 18); + t[1] = 0x80 + ((uval & 0x03F000) >> 12); + t[2] = 0x80 + ((uval & 0x000FC0) >> 6); + t[3] = 0x80 + ((uval & 0x00003F)); + t += 4; + } + else { + *t++ = '?'; + } + break; + default: + *t++ = '?'; + break; + } + } + else { + *t++ = *h++; + } + } +} |