]> source.dussan.org Git - rspamd.git/commitdiff
Improve keys parsing.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 7 Aug 2013 16:19:54 +0000 (17:19 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 7 Aug 2013 16:19:54 +0000 (17:19 +0100)
src/rcl/rcl.h
src/rcl/rcl_internal.h
src/rcl/rcl_parser.c
src/rcl/rcl_util.c

index 54c3c81e54971d80a1fc845658e28981361098a8..545dd19f9d73a70cdf110c712699e02d55b81eda 100644 (file)
@@ -281,6 +281,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
index 33256119ddf1e1444225aa4aee62f4544aa657b1..e76c09fd8915acffccac95e2d0daf4516c1763ec 100644 (file)
@@ -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_ */
index f727991de1d13f71bb3a1bfc3fc2cec5c5a3d5ec..1c32bde592ac71011d9949827f670744ea15941b 100644 (file)
@@ -235,96 +235,6 @@ rspamd_cl_lex_json_string (struct rspamd_cl_parser *parser,
        return FALSE;
 }
 
-/**
- * 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
@@ -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;
index 96fc8dda413ee5d52e899222fd0c1e8cfcef89d7..58a6e2cd24bd51a2dbee0b5dacc4280680d091fc 100644 (file)
  * @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++;
+               }
+       }
+}