aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libucl
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2018-05-05 14:58:37 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2018-05-05 14:58:37 +0100
commita3191bd7b34d3373d151827a6e6592ea82084747 (patch)
treeab4ecb6c138e1a21cb76aeaf4503d04a253568ae /contrib/libucl
parent91154ccc0114f1dca3b803a9c9bcfd065297c329 (diff)
downloadrspamd-a3191bd7b34d3373d151827a6e6592ea82084747.tar.gz
rspamd-a3191bd7b34d3373d151827a6e6592ea82084747.zip
[Feture] Allow external preprocessors in libucl
Diffstat (limited to 'contrib/libucl')
-rw-r--r--contrib/libucl/ucl.h28
-rw-r--r--contrib/libucl/ucl_internal.h10
-rw-r--r--contrib/libucl/ucl_parser.c30
-rw-r--r--contrib/libucl/ucl_util.c32
4 files changed, 93 insertions, 7 deletions
diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h
index 812b89477..f0dbeca84 100644
--- a/contrib/libucl/ucl.h
+++ b/contrib/libucl/ucl.h
@@ -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);
+
/** @} */
/**
diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h
index d60581037..4ddc713b5 100644
--- a/contrib/libucl/ucl_internal.h
+++ b/contrib/libucl/ucl_internal.h
@@ -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_ */
diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c
index 339b93dff..631bc7412 100644
--- a/contrib/libucl/ucl_parser.c
+++ b/contrib/libucl/ucl_parser.c
@@ -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;
diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c
index c6c07ba87..95878109b 100644
--- a/contrib/libucl/ucl_util.c
+++ b/contrib/libucl/ucl_util.c
@@ -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 --;
}