summaryrefslogtreecommitdiffstats
path: root/contrib/ffaup/ffaup.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--contrib/ffaup/ffaup.c395
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