]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Add macro value parsing code.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 16 Aug 2013 16:26:16 +0000 (17:26 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Fri, 16 Aug 2013 16:26:16 +0000 (17:26 +0100)
src/rcl/rcl_parser.c

index 1c13922dd71726f5f7a26a2bed295707b02d83ff..c38edb9432a58405c6c74db20c2f5fd07838c395 100644 (file)
@@ -953,6 +953,92 @@ rspamd_cl_parse_after_value (struct rspamd_cl_parser *parser, struct rspamd_cl_c
        return TRUE;
 }
 
+/**
+ * Handle macro data
+ * @param parser
+ * @param chunk
+ * @param err
+ * @return
+ */
+static gboolean
+rspamd_cl_parse_macro_value (struct rspamd_cl_parser *parser,
+               struct rspamd_cl_chunk *chunk, struct rspamd_cl_macro *macro, GError **err)
+{
+       const guchar *p, *c;
+
+       p = chunk->pos;
+
+       switch (*p) {
+       case '"':
+               /* We have macro value encoded in quotes */
+               c = p;
+               rspamd_cl_chunk_skipc (chunk, *p);
+               p ++;
+               if (!rspamd_cl_lex_json_string (parser, chunk, err)) {
+                       return FALSE;
+               }
+
+               if (!macro->handler (c + 1, chunk->pos - c - 2, macro->ud, err)) {
+                       return FALSE;
+               }
+               p = chunk->pos;
+               break;
+       case '{':
+               /* We got a multiline macro body */
+               rspamd_cl_chunk_skipc (chunk, *p);
+               p ++;
+               /* Skip spaces at the beginning */
+               while (p < chunk->end) {
+                       if (g_ascii_isspace (*p)) {
+                               rspamd_cl_chunk_skipc (chunk, *p);
+                               p ++;
+                       }
+                       else {
+                               break;
+                       }
+               }
+               c = p;
+               while (p < chunk->end) {
+                       if (*p == '}') {
+                               break;
+                       }
+                       rspamd_cl_chunk_skipc (chunk, *p);
+                       p ++;
+               }
+               if (!macro->handler (c, p - c, macro->ud, err)) {
+                       return FALSE;
+               }
+               rspamd_cl_chunk_skipc (chunk, *p);
+               p ++;
+               break;
+       default:
+               /* Macro is not enclosed in quotes or braces */
+               c = p;
+               while (p < chunk->end) {
+                       if (rspamd_cl_lex_is_atom_end (*p)) {
+                               break;
+                       }
+                       rspamd_cl_chunk_skipc (chunk, *p);
+                       p ++;
+               }
+               if (!macro->handler (c, p - c, macro->ud, err)) {
+                       return FALSE;
+               }
+               break;
+       }
+
+       /* We are at the end of a macro */
+       /* Skip ';' and space characters and return to previous state */
+       while (p < chunk->end) {
+               if (!g_ascii_isspace (*p) && *p != ';') {
+                       break;
+               }
+               rspamd_cl_chunk_skipc (chunk, *p);
+               p ++;
+       }
+       return TRUE;
+}
+
 /**
  * Handle the main states of rcl parser
  * @param parser parser structure
@@ -1089,6 +1175,12 @@ rspamd_cl_state_machine (struct rspamd_cl_parser *parser, GError **err)
                        }
                        break;
                case RSPAMD_RCL_STATE_MACRO:
+                       if (!rspamd_cl_parse_macro_value (parser, chunk, macro, err)) {
+                               parser->prev_state = parser->state;
+                               parser->state = RSPAMD_RCL_STATE_ERROR;
+                               return FALSE;
+                       }
+                       parser->state = parser->prev_state;
                        break;
                default:
                        /* TODO: add all states */