]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Feture] Allow external preprocessors in libucl
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 5 May 2018 13:58:37 +0000 (14:58 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Sat, 5 May 2018 13:58:37 +0000 (14:58 +0100)
contrib/libucl/ucl.h
contrib/libucl/ucl_internal.h
contrib/libucl/ucl_parser.c
contrib/libucl/ucl_util.c

index 812b89477864ec1fb54edff0c260bae3e81f4091..f0dbeca8470c63fe0e2d46cd36bc5bd453fc0abc 100644 (file)
@@ -1278,6 +1278,34 @@ UCL_EXTERN bool ucl_parser_pubkey_add (struct ucl_parser *parser,
 UCL_EXTERN bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename,
                bool need_expand);
 
+/**
+ * Defines special handler for certain types of data (identified by magic)
+ */
+typedef bool (*ucl_parser_special_handler_t) (struct ucl_parser *parser,
+               const unsigned char *source, size_t source_len,
+               unsigned char **destination, size_t *dest_len,
+               void *user_data);
+
+/**
+ * Special handler structure
+ */
+struct ucl_parser_special_handler {
+       unsigned char *magic;
+       size_t magic_len;
+       ucl_parser_special_handler_t handler;
+       void (*free_function) (unsigned char *data, size_t len, void *user_data);
+       void *user_data;
+       struct ucl_parser_special_handler *next; /* Used internally */
+};
+
+/**
+ * Add special handler for a parser
+ * @param parser parser structure
+ * @param handler handler structure
+ */
+UCL_EXTERN void ucl_parser_add_special_handler (struct ucl_parser *parser,
+               struct ucl_parser_special_handler *handler);
+
 /** @} */
 
 /**
index d6058103783f08882da78723aa81a68d8e6547ff..4ddc713b55b217e86c865c6977edddaecdd32ca7 100644 (file)
@@ -176,7 +176,7 @@ enum ucl_character_type {
 
 struct ucl_macro {
        char *name;
-       union {
+       union _ucl_macro {
                ucl_macro_handler handler;
                ucl_context_macro_handler context_handler;
        } h;
@@ -201,6 +201,7 @@ struct ucl_chunk {
        unsigned priority;
        enum ucl_duplicate_strategy strategy;
        enum ucl_parse_type parse_type;
+       struct ucl_parser_special_handler *special_handler;
        struct ucl_chunk *next;
 };
 
@@ -239,6 +240,7 @@ struct ucl_parser {
        struct ucl_stack *stack;
        struct ucl_chunk *chunks;
        struct ucl_pubkey *keys;
+    struct ucl_parser_special_handler *special_handlers;
        struct ucl_variable *variables;
        ucl_variable_handler var_handler;
        void *var_data;
@@ -619,4 +621,10 @@ bool ucl_parse_msgpack (struct ucl_parser *parser);
 
 bool ucl_parse_csexp (struct ucl_parser *parser);
 
+/**
+ * Free ucl chunk
+ * @param chunk
+ */
+void ucl_chunk_free (struct ucl_chunk *chunk);
+
 #endif /* UCL_INTERNAL_H_ */
index 339b93dffdfe2550bc3e7b38d463aa4720ffb8ae..631bc7412ebd0cf908c2bae3eeeb2d7eb9330dda 100644 (file)
@@ -2726,6 +2726,7 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
                enum ucl_parse_type parse_type)
 {
        struct ucl_chunk *chunk;
+       struct ucl_parser_special_handler *special_handler;
 
        if (parser == NULL) {
                return false;
@@ -2743,6 +2744,28 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
                        return false;
                }
 
+               memset (chunk, 0, sizeof (*chunk));
+
+               LL_FOREACH (parser->special_handlers, special_handler) {
+                       if (len >= special_handler->magic_len &&
+                                       memcmp (data, special_handler->magic, special_handler->magic_len) == 0) {
+                               unsigned char *ndata = NULL;
+                               size_t nlen = 0;
+
+                               if (!special_handler->handler (parser, data, len, &ndata, &nlen,
+                                               special_handler->user_data)) {
+                                       ucl_create_err (&parser->err, "call for external handler failed");
+                                       return false;
+                               }
+
+                               data = ndata;
+                               len = nlen;
+                               chunk->special_handler = special_handler;
+
+                               break;
+                       }
+               }
+
                if (parse_type == UCL_PARSE_AUTO && len > 0) {
                        /* We need to detect parse type by the first symbol */
                        if ((*data & 0x80) == 0x80 && (*data >= 0xdc && *data <= 0xdf)) {
@@ -2832,7 +2855,7 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
 
 bool
 ucl_parser_insert_chunk (struct ucl_parser *parser, const unsigned char *data,
-                size_t len)
+               size_t len)
 {
        if (parser == NULL || parser->top_obj == NULL) {
                return false;
@@ -2854,7 +2877,7 @@ ucl_parser_insert_chunk (struct ucl_parser *parser, const unsigned char *data,
        chunk = parser->chunks;
        if (chunk != NULL) {
                parser->chunks = chunk->next;
-               UCL_FREE (sizeof (struct ucl_chunk), chunk);
+               ucl_chunk_free (chunk);
                parser->recursion --;
        }
 
@@ -2936,7 +2959,8 @@ bool ucl_parser_chunk_skip (struct ucl_parser *parser)
        return false;
 }
 
-ucl_object_t* ucl_parser_get_current_stack_object (struct ucl_parser *parser, unsigned int depth)
+ucl_object_t*
+ucl_parser_get_current_stack_object (struct ucl_parser *parser, unsigned int depth)
 {
        ucl_object_t *obj;
 
index c6c07ba87a06114728140986db53562e8ecd4e0e..95878109b6364425baece253c4ac086002828667 100644 (file)
@@ -516,6 +516,26 @@ ucl_copy_key_trash (const ucl_object_t *obj)
        return obj->trash_stack[UCL_TRASH_KEY];
 }
 
+void
+ucl_chunk_free (struct ucl_chunk *chunk)
+{
+       if (chunk) {
+               if (chunk->special_handler) {
+                       if (chunk->special_handler->free_function) {
+                               chunk->special_handler->free_function (
+                                               (unsigned char *) chunk->begin,
+                                               chunk->end - chunk->begin,
+                                               chunk->special_handler->user_data);
+                       } else {
+                               UCL_FREE (chunk->end - chunk->begin,
+                                               (unsigned char *) chunk->begin);
+                       }
+               }
+
+               UCL_FREE (sizeof (*chunk), chunk);
+       }
+}
+
 char *
 ucl_copy_value_trash (const ucl_object_t *obj)
 {
@@ -601,7 +621,7 @@ ucl_parser_free (struct ucl_parser *parser)
                UCL_FREE (sizeof (struct ucl_macro), macro);
        }
        LL_FOREACH_SAFE (parser->chunks, chunk, ctmp) {
-               UCL_FREE (sizeof (struct ucl_chunk), chunk);
+               ucl_chunk_free (chunk);
        }
        LL_FOREACH_SAFE (parser->keys, key, ktmp) {
                UCL_FREE (sizeof (struct ucl_pubkey), key);
@@ -718,6 +738,12 @@ ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len)
        return true;
 }
 
+void ucl_parser_add_special_handler (struct ucl_parser *parser,
+               struct ucl_parser_special_handler *handler)
+{
+       LL_APPEND (parser->special_handlers, handler);
+}
+
 #ifdef CURL_FOUND
 struct ucl_curl_cbdata {
        unsigned char *buf;
@@ -1017,7 +1043,7 @@ ucl_include_url (const unsigned char *data, size_t len,
                chunk = parser->chunks;
                if (chunk != NULL) {
                        parser->chunks = chunk->next;
-                       UCL_FREE (sizeof (struct ucl_chunk), chunk);
+                       ucl_chunk_free (chunk);
                }
        }
 
@@ -1319,7 +1345,7 @@ ucl_include_file_single (const unsigned char *data, size_t len,
        chunk = parser->chunks;
        if (chunk != NULL) {
                parser->chunks = chunk->next;
-               UCL_FREE (sizeof (struct ucl_chunk), chunk);
+               ucl_chunk_free (chunk);
                parser->recursion --;
        }