summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/rcl/rcl_parser.c28
-rw-r--r--src/rcl/rcl_util.c54
-rw-r--r--test/rspamd_rcl_test.c11
3 files changed, 76 insertions, 17 deletions
diff --git a/src/rcl/rcl_parser.c b/src/rcl/rcl_parser.c
index cf5ca76b9..16552d325 100644
--- a/src/rcl/rcl_parser.c
+++ b/src/rcl/rcl_parser.c
@@ -232,7 +232,7 @@ rspamd_cl_lex_is_atom_end (const guchar c)
* @return TRUE if a number has been parsed
*/
static gboolean
-rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser,
+rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
struct rspamd_cl_chunk *chunk, rspamd_cl_object_t *obj, GError **err)
{
const guchar *p = chunk->pos, *c = chunk->pos;
@@ -362,10 +362,10 @@ rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser,
p ++;
goto set_obj;
}
- else if (chunk->end - p > 3) {
+ else if (chunk->end - p >= 3) {
if (g_ascii_tolower (p[0]) == 'm' &&
g_ascii_tolower (p[1]) == 'i' &&
- g_ascii_tolower (p[2]) == 'm') {
+ g_ascii_tolower (p[2]) == 'n') {
/* Minutes */
if (!need_double) {
need_double = TRUE;
@@ -413,14 +413,15 @@ rspamd_cl_lex_json_number (struct rspamd_cl_parser *parser,
case 'W':
case 'Y':
case 'y':
- if (p == chunk->end - 1 || rspamd_cl_lex_is_atom_end (*++p)) {
+ if (p == chunk->end - 1 || rspamd_cl_lex_is_atom_end (p[1])) {
if (!need_double) {
need_double = TRUE;
dv = lv;
}
is_date = TRUE;
- rspamd_cl_chunk_skipc (chunk, *p);
dv *= rspamd_cl_lex_time_multiplier (*p);
+ rspamd_cl_chunk_skipc (chunk, *p);
+ p ++;
goto set_obj;
}
break;
@@ -668,12 +669,13 @@ rspamd_cl_parse_key (struct rspamd_cl_parser *parser,
HASH_FIND_STR (container, nobj->key, tobj);
if (tobj != NULL) {
/* Just insert a new object as the next element */
- tobj->next = nobj;
- }
- else {
- HASH_ADD_KEYPTR (hh, container, nobj->key, strlen (nobj->key), nobj);
+ LL_PREPEND (tobj, nobj);
+ HASH_DELETE (hh, container, tobj);
}
+ HASH_ADD_KEYPTR (hh, container, nobj->key, strlen (nobj->key), nobj);
+ parser->stack->obj->value.ov = container;
+
parser->cur_obj = nobj;
return TRUE;
@@ -783,6 +785,8 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err)
if (parser->stack->obj->type == RSPAMD_CL_ARRAY) {
/* Object must be allocated */
obj = rspamd_cl_object_new ();
+ parser->cur_obj = obj;
+ LL_PREPEND (parser->stack->obj->value.ov, parser->cur_obj);
}
else {
/* Object has been already allocated */
@@ -797,8 +801,8 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err)
parser->state = RSPAMD_RCL_STATE_ERROR;
return FALSE;
}
- obj->value.sv = g_malloc (chunk->pos - c);
- rspamd_strlcpy (obj->value.sv, c + 1, chunk->pos - c);
+ obj->value.sv = g_malloc (chunk->pos - c - 1);
+ rspamd_strlcpy (obj->value.sv, c + 1, chunk->pos - c - 1);
rspamd_cl_unescape_json_string (obj->value.sv);
obj->type = RSPAMD_CL_STRING;
parser->state = RSPAMD_RCL_STATE_AFTER_VALUE;
@@ -845,7 +849,7 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err)
}
/* Parse atom */
if (g_ascii_isdigit (*p) || *p == '-') {
- if (!rspamd_cl_lex_json_number (parser, chunk, obj, err)) {
+ if (!rspamd_cl_lex_number (parser, chunk, obj, err)) {
if (parser->state == RSPAMD_RCL_STATE_ERROR) {
return FALSE;
}
diff --git a/src/rcl/rcl_util.c b/src/rcl/rcl_util.c
index 3216a27d8..1c9d6a652 100644
--- a/src/rcl/rcl_util.c
+++ b/src/rcl/rcl_util.c
@@ -31,8 +31,8 @@
*/
-void
-rspamd_cl_obj_free (rspamd_cl_object_t *obj)
+static void
+rspamd_cl_obj_free_internal (rspamd_cl_object_t *obj, gboolean allow_rec)
{
rspamd_cl_object_t *sub, *tmp;
@@ -48,23 +48,33 @@ rspamd_cl_obj_free (rspamd_cl_object_t *obj)
sub = obj->value.ov;
while (sub != NULL) {
tmp = sub->next;
- rspamd_cl_obj_free (sub);
+ rspamd_cl_obj_free_internal (sub, FALSE);
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);
+ rspamd_cl_obj_free_internal (sub, TRUE);
}
}
tmp = obj->next;
g_slice_free1 (sizeof (rspamd_cl_object_t), obj);
obj = tmp;
+
+ if (!allow_rec) {
+ break;
+ }
}
}
void
+rspamd_cl_obj_free (rspamd_cl_object_t *obj)
+{
+ rspamd_cl_obj_free_internal (obj, TRUE);
+}
+
+void
rspamd_cl_unescape_json_string (gchar *str)
{
gchar *t = str, *h = str;
@@ -112,6 +122,7 @@ rspamd_cl_unescape_json_string (gchar *str)
uval += h[i] - 'A' + 10;
}
}
+ h += 3;
/* Encode */
if(uval < 0x80) {
t[0] = (char)uval;
@@ -143,9 +154,44 @@ rspamd_cl_unescape_json_string (gchar *str)
*t++ = '?';
break;
}
+ h ++;
}
else {
*t++ = *h++;
}
}
}
+
+rspamd_cl_object_t*
+rspamd_cl_parser_get_object (struct rspamd_cl_parser *parser, GError **err)
+{
+ if (parser->state != RSPAMD_RCL_STATE_INIT && parser->state != RSPAMD_RCL_STATE_ERROR) {
+ return parser->top_obj;
+ }
+
+ return NULL;
+}
+
+void
+rspamd_cl_parser_free (struct rspamd_cl_parser *parser)
+{
+ struct rspamd_cl_stack *stack, *stmp;
+ struct rspamd_cl_macro *macro, *mtmp;
+ struct rspamd_cl_chunk *chunk, *ctmp;
+
+ if (parser->top_obj != NULL) {
+ rspamd_cl_obj_free (parser->top_obj);
+ }
+
+ LL_FOREACH_SAFE (parser->stack, stack, stmp) {
+ g_slice_free1 (sizeof (struct rspamd_cl_stack), stack);
+ }
+ HASH_ITER (hh, parser->macroes, macro, mtmp) {
+ g_slice_free1 (sizeof (struct rspamd_cl_macro), macro);
+ }
+ LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
+ g_slice_free1 (sizeof (struct rspamd_cl_chunk), chunk);
+ }
+
+ g_slice_free1 (sizeof (struct rspamd_cl_parser), parser);
+}
diff --git a/test/rspamd_rcl_test.c b/test/rspamd_rcl_test.c
index 01b3ba835..695002de5 100644
--- a/test/rspamd_rcl_test.c
+++ b/test/rspamd_rcl_test.c
@@ -23,6 +23,7 @@
#include "../src/config.h"
#include "../src/rcl/rcl.h"
+#include "../src/main.h"
#include "tests.h"
const gchar *rcl_test_valid[] = {
@@ -33,7 +34,7 @@ const gchar *rcl_test_valid[] = {
"\"key1\": \"value;\""
"}\n",
/* Nginx like */
- "section1 { param1 = value; param2 = value, param3 = [\"value1\", 100500]}\n"
+ "section1 { param1 = value; param2 = value, param3 = [\"value1\", value2, 100500]}\n"
"section2 { param1 = {key = value}, param1 = [\"key\"]}",
/* Numbers */
"key = 1s\n"
@@ -57,6 +58,7 @@ rspamd_rcl_test_func (void)
struct rspamd_cl_parser *parser;
rspamd_cl_object_t *obj;
const gchar **cur;
+ guchar *emitted;
GError *err = NULL;
cur = rcl_test_valid;
@@ -65,6 +67,13 @@ rspamd_rcl_test_func (void)
g_assert (parser != NULL);
rspamd_cl_parser_add_chunk (parser, *cur, strlen (*cur), &err);
g_assert_no_error (err);
+ obj = rspamd_cl_parser_get_object (parser, &err);
+ g_assert_no_error (err);
+ emitted = rspamd_cl_object_emit (obj, RSPAMD_CL_EMIT_JSON);
+ g_assert (emitted != NULL);
+ msg_info ("got json output: %s", emitted);
+ g_free (emitted);
+ rspamd_cl_parser_free (parser);
cur ++;
}