diff options
Diffstat (limited to '')
-rw-r--r-- | contrib/ffaup/ffaup.c | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/contrib/ffaup/ffaup.c b/contrib/ffaup/ffaup.c new file mode 100644 index 0000000..c75ff7b --- /dev/null +++ b/contrib/ffaup/ffaup.c @@ -0,0 +1,395 @@ +/* ffaup.c + * This is a function module for URL parsing. + * + * File begun on 2021/10/23 by TBertin + * + * Copyright 2007-2021 Theo Bertin for Advens + * + * This file is part of rsyslog. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <stddef.h> +#ifndef _AIX +#include <typedefs.h> +#endif +#include <sys/types.h> +#include <string.h> +#include <faup/faup.h> +#include <faup/decode.h> +#include <faup/options.h> +#include <faup/output.h> + +#include "config.h" +#include "rsyslog.h" +#include "parserif.h" +#include "module-template.h" +#include "rainerscript.h" + + + +MODULE_TYPE_FUNCTION +MODULE_TYPE_NOKEEP +DEF_FMOD_STATIC_DATA + +faup_options_t *glbOptions = NULL; + +enum _faup_parse_type_t { + FAUP_PARSE_ALL, + FAUP_PARSE_SCHEME, + FAUP_PARSE_CREDENTIAL, + FAUP_PARSE_SUBDOMAIN, + FAUP_PARSE_DOMAIN, + FAUP_PARSE_DOMAIN_WITHOUT_TLD, + FAUP_PARSE_HOST, + FAUP_PARSE_TLD, + FAUP_PARSE_PORT, + FAUP_PARSE_RESOURCE_PATH, + FAUP_PARSE_QUERY_STRING, + FAUP_PARSE_FRAGMENT +}; +typedef enum _faup_parse_type_t faup_parse_type_t; + + +static inline sbool check_param_count_faup(unsigned short nParams) { + return nParams != 1; +} + + +static void ATTR_NONNULL() +do_faup_parse(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti, const faup_parse_type_t parse_type) { + struct svar srcVal; + int bMustFree; + cnfexprEval(func->expr[0], &srcVal, usrptr, pWti); + char *url = (char*) var2CString(&srcVal, &bMustFree); + + /* + We use the faup_handler_t struct directly instead of calling faup_init to avoid overhead and useless + allocations. Using one handler is not possible as the lib is not thread-safe and thread-locale solutions + still cause some issues. + If the faup_init function changes significantly in the future, it may cause issue. + (Validated with faup v1.5 and faup-master fecf768603e713bc903c56c8df0870fae14e3f93) + */ + faup_handler_t fh = {0}; + fh.options = glbOptions; + + // default, return 0 + ret->datatype = 'N'; + ret->d.n = 0; + + if(!faup_decode(&fh, url, strlen(url))) { + parser_errmsg("faup: could not parse the value\n"); + // No returned error code, so the reason doesn't matter + FINALIZE; + } + + switch(parse_type) { + case FAUP_PARSE_ALL: + ret->datatype = 'J'; + ret->d.json = json_object_new_object(); + json_object_object_add( + ret->d.json, + "scheme", + json_object_new_string_len( + url + faup_get_scheme_pos(&fh), + faup_get_scheme_size(&fh))); + json_object_object_add( + ret->d.json, + "credential", + json_object_new_string_len( + url + faup_get_credential_pos(&fh), + faup_get_credential_size(&fh))); + json_object_object_add( + ret->d.json, + "subdomain", + json_object_new_string_len( + url + faup_get_subdomain_pos(&fh), + faup_get_subdomain_size(&fh))); + json_object_object_add( + ret->d.json, + "domain", + json_object_new_string_len( + url + faup_get_domain_pos(&fh), + faup_get_domain_size(&fh))); + json_object_object_add( + ret->d.json, + "domain_without_tld", + json_object_new_string_len( + url + faup_get_domain_without_tld_pos(&fh), + faup_get_domain_without_tld_size(&fh))); + json_object_object_add( + ret->d.json, + "host", + json_object_new_string_len( + url + faup_get_host_pos(&fh), + faup_get_host_size(&fh))); + json_object_object_add( + ret->d.json, + "tld", + json_object_new_string_len( + url + faup_get_tld_pos(&fh), + faup_get_tld_size(&fh))); + json_object_object_add( + ret->d.json, + "port", + json_object_new_string_len( + url + faup_get_port_pos(&fh), + faup_get_port_size(&fh))); + json_object_object_add( + ret->d.json, + "resource_path", + json_object_new_string_len( + url + faup_get_resource_path_pos(&fh), + faup_get_resource_path_size(&fh))); + json_object_object_add( + ret->d.json, + "query_string", + json_object_new_string_len( + url + faup_get_query_string_pos(&fh), + faup_get_query_string_size(&fh))); + json_object_object_add( + ret->d.json, + "fragment", + json_object_new_string_len( + url + faup_get_fragment_pos(&fh), + faup_get_fragment_size(&fh))); + break; + case FAUP_PARSE_SCHEME: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_scheme_pos(&fh), faup_get_scheme_size(&fh)); + break; + case FAUP_PARSE_CREDENTIAL: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_credential_pos(&fh), faup_get_credential_size(&fh)); + break; + case FAUP_PARSE_SUBDOMAIN: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_subdomain_pos(&fh), faup_get_subdomain_size(&fh)); + break; + case FAUP_PARSE_DOMAIN: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_domain_pos(&fh), faup_get_domain_size(&fh)); + break; + case FAUP_PARSE_DOMAIN_WITHOUT_TLD: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_domain_without_tld_pos(&fh), faup_get_domain_without_tld_size(&fh)); + break; + case FAUP_PARSE_HOST: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_host_pos(&fh), faup_get_host_size(&fh)); + break; + case FAUP_PARSE_TLD: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_tld_pos(&fh), faup_get_tld_size(&fh)); + break; + case FAUP_PARSE_PORT: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_port_pos(&fh), faup_get_port_size(&fh)); + break; + case FAUP_PARSE_RESOURCE_PATH: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_resource_path_pos(&fh), faup_get_resource_path_size(&fh)); + break; + case FAUP_PARSE_QUERY_STRING: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_query_string_pos(&fh), faup_get_query_string_size(&fh)); + break; + case FAUP_PARSE_FRAGMENT: + ret->datatype = 'S'; + ret->d.estr = es_newStrFromCStr( + url + faup_get_fragment_pos(&fh), faup_get_fragment_size(&fh)); + break; + } + +finalize_it: + if(bMustFree) { + free(url); + } + varFreeMembers(&srcVal); +} + + +static void ATTR_NONNULL() +do_faup_parse_full(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_ALL); +} + + +static void ATTR_NONNULL() +do_faup_parse_scheme(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SCHEME); +} + + +static void ATTR_NONNULL() +do_faup_parse_credential(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_CREDENTIAL); +} + + +static void ATTR_NONNULL() +do_faup_parse_subdomain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_SUBDOMAIN); +} + + +static void ATTR_NONNULL() +do_faup_parse_domain(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN); +} + + +static void ATTR_NONNULL() +do_faup_parse_domain_without_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_DOMAIN_WITHOUT_TLD); +} + + +static void ATTR_NONNULL() +do_faup_parse_host(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_HOST); +} + + +static void ATTR_NONNULL() +do_faup_parse_tld(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_TLD); +} + + +static void ATTR_NONNULL() +do_faup_parse_port(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_PORT); +} + + +static void ATTR_NONNULL() +do_faup_parse_resource_path(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_RESOURCE_PATH); +} + + +static void ATTR_NONNULL() +do_faup_parse_query_string(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_QUERY_STRING); +} + + +static void ATTR_NONNULL() +do_faup_parse_fragment(struct cnffunc *__restrict__ const func, struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, wti_t *__restrict__ const pWti) { + do_faup_parse(func, ret, usrptr, pWti, FAUP_PARSE_FRAGMENT); +} + + +static rsRetVal ATTR_NONNULL(1) +initFunc_faup_parse(struct cnffunc *const func) +{ + DEFiRet; + + // Rsyslog cannot free the funcdata object, + // a library-specific freeing function will be used during destruction + func->destructable_funcdata = 0; + if(check_param_count_faup(func->nParams)) { + parser_errmsg("ffaup: ffaup(key) insufficient params.\n"); + ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS); + } + +finalize_it: + RETiRet; +} + + +static struct scriptFunct functions[] = { + {"faup", 1, 1, do_faup_parse_full, initFunc_faup_parse, NULL}, + {"faup_scheme", 1, 1, do_faup_parse_scheme, initFunc_faup_parse, NULL}, + {"faup_credential", 1, 1, do_faup_parse_credential, initFunc_faup_parse, NULL}, + {"faup_subdomain", 1, 1, do_faup_parse_subdomain, initFunc_faup_parse, NULL}, + {"faup_domain", 1, 1, do_faup_parse_domain, initFunc_faup_parse, NULL}, + {"faup_domain_without_tld", 1, 1, do_faup_parse_domain_without_tld, initFunc_faup_parse, NULL}, + {"faup_host", 1, 1, do_faup_parse_host, initFunc_faup_parse, NULL}, + {"faup_tld", 1, 1, do_faup_parse_tld, initFunc_faup_parse, NULL}, + {"faup_port", 1, 1, do_faup_parse_port, initFunc_faup_parse, NULL}, + {"faup_resource_path", 1, 1, do_faup_parse_resource_path, initFunc_faup_parse, NULL}, + {"faup_query_string", 1, 1, do_faup_parse_query_string, initFunc_faup_parse, NULL}, + {"faup_fragment", 1, 1, do_faup_parse_fragment, initFunc_faup_parse, NULL}, + {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array +}; + +BEGINgetFunctArray +CODESTARTgetFunctArray + dbgprintf("Faup: ffaup\n"); + *version = 1; + *functArray = functions; +ENDgetFunctArray + + +BEGINmodExit +CODESTARTmodExit + dbgprintf("ffaup: freeing options\n"); + if(glbOptions){ + faup_options_free(glbOptions); + glbOptions = NULL; + } +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_FMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ + + dbgprintf("ffaup: initializing options\n"); + glbOptions = faup_options_new(); + if(!glbOptions) { + parser_errmsg("ffaup: could not initialize options\n"); + ABORT_FINALIZE(RS_RET_FAUP_INIT_OPTIONS_FAILED); + } + // Don't generate a string output, and don't load LUA modules + // This is useful only for the faup executable + glbOptions->output = FAUP_OUTPUT_NONE; + glbOptions->exec_modules = FAUP_MODULES_NOEXEC; +CODEmodInit_QueryRegCFSLineHdlr + dbgprintf("rsyslog ffaup init called, compiled with version %s\n", VERSION); +ENDmodInit |