summaryrefslogtreecommitdiffstats
path: root/template.c
diff options
context:
space:
mode:
Diffstat (limited to 'template.c')
-rw-r--r--template.c328
1 files changed, 238 insertions, 90 deletions
diff --git a/template.c b/template.c
index 68c4f539..b6752551 100644
--- a/template.c
+++ b/template.c
@@ -44,6 +44,7 @@
#include "errmsg.h"
#include "strgen.h"
#include "rsconf.h"
+#include "msg.h"
#include "unicode-helper.h"
/* static data */
@@ -54,9 +55,10 @@ DEFobjCurrIf(strgen)
/* tables for interfacing with the v6 config system */
static struct cnfparamdescr cnfparamdescr[] = {
{ "name", eCmdHdlrString, 1 },
- { "type", eCmdHdlrString, 0 },
+ { "type", eCmdHdlrString, 1 },
{ "string", eCmdHdlrString, 0 },
{ "plugin", eCmdHdlrString, 0 },
+ { "subtree", eCmdHdlrString, 0 },
{ "option.stdsql", eCmdHdlrBinary, 0 },
{ "option.sql", eCmdHdlrBinary, 0 },
{ "option.json", eCmdHdlrBinary, 0 }
@@ -77,6 +79,7 @@ static struct cnfparamdescr cnfparamdescrProperty[] = {
{ "format", eCmdHdlrString, 0 },
{ "position.from", eCmdHdlrInt, 0 },
{ "position.to", eCmdHdlrInt, 0 },
+ { "position.relativetoend", eCmdHdlrBinary, 0 },
{ "field.number", eCmdHdlrInt, 0 },
{ "field.delimiter", eCmdHdlrInt, 0 },
{ "regex.expression", eCmdHdlrString, 0 },
@@ -139,14 +142,16 @@ finalize_it:
* offers big performance improvements.
* rewritten 2009-06-19 rgerhards
*/
-rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf)
+rsRetVal
+tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
+ struct syslogTime *ttNow)
{
DEFiRet;
struct templateEntry *pTpe;
size_t iBuf;
unsigned short bMustBeFreed = 0;
uchar *pVal;
- size_t iLenVal = 0;
+ rs_size_t iLenVal = 0;
assert(pTpl != NULL);
assert(pMsg != NULL);
@@ -158,6 +163,23 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
FINALIZE;
}
+ if(pTpl->subtree != NULL) {
+ /* only a single CEE subtree must be provided */
+ /* note: we could optimize the code below, however, this is
+ * not worth the effort, as this passing mode is not expected
+ * in subtree mode and so most probably only used for debug & test.
+ */
+ getCEEPropVal(pMsg, pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed);
+ if(iLenVal >= (rs_size_t)*pLenBuf) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(ppBuf, pLenBuf, iLenVal + 1));
+ memcpy(*ppBuf, pVal, iLenVal+1);
+ if(bMustBeFreed)
+ free(pVal);
+ FINALIZE;
+ }
+
+ /* we have a "regular" template with template entries */
+
/* loop through the template. We obtain one value
* and copy it over to our dynamic string buffer. Then, we
* free the obtained value (if requested). We continue this
@@ -172,7 +194,8 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &iLenVal, &bMustBeFreed);
+ pTpe->data.field.propName, &iLenVal,
+ &bMustBeFreed, ttNow);
/* we now need to check if we should use SQL option. In this case,
* we must go over the generated string and escape '\'' characters.
* rgerhards, 2005-09-22: the option values below look somewhat misplaced,
@@ -226,13 +249,14 @@ finalize_it:
* is indicated by a NULL pointer.
* rgerhards, 2009-04-03
*/
-rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
+rsRetVal
+tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr, struct syslogTime *ttNow)
{
DEFiRet;
struct templateEntry *pTpe;
uchar **pArr;
int iArr;
- size_t propLen;
+ rs_size_t propLen;
unsigned short bMustBeFreed;
uchar *pVal;
@@ -240,11 +264,24 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
assert(pMsg != NULL);
assert(ppArr != NULL);
+ if(pTpl->subtree) {
+ /* Note: this mode is untested, as there is no official plugin
+ * using array passing, so I simply could not test it.
+ */
+ CHKmalloc(pArr = calloc(2, sizeof(uchar*)));
+ getCEEPropVal(pMsg, pTpl->subtree, &pVal, &propLen, &bMustBeFreed);
+ if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
+ pArr[0] = pVal; /* ... so we can use it! */
+ } else {
+ CHKmalloc(pArr[0] = (uchar*)strdup((char*) pVal));
+ }
+ FINALIZE;
+ }
+
/* loop through the template. We obtain one value, create a
* private copy (if necessary), add it to the string array
* and then on to the next until we have processed everything.
*/
-
CHKmalloc(pArr = calloc(pTpl->tpenElements + 1, sizeof(uchar*)));
iArr = 0;
@@ -254,7 +291,8 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant));
} else if(pTpe->eEntryType == FIELD) {
pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &propLen, &bMustBeFreed);
+ pTpe->data.field.propName, &propLen,
+ &bMustBeFreed, ttNow);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[iArr] = pVal; /* ... so we can use it! */
} else {
@@ -277,15 +315,28 @@ finalize_it:
* tpltoString().
* rgerhards, 2012-08-29
*/
-rsRetVal tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson)
+rsRetVal
+tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct syslogTime *ttNow)
{
struct templateEntry *pTpe;
- size_t propLen;
+ rs_size_t propLen;
unsigned short bMustBeFreed;
uchar *pVal;
struct json_object *json, *jsonf;
+ rsRetVal localRet;
DEFiRet;
+ if(pTpl->subtree != NULL){
+ localRet = jsonFind(pMsg, pTpl->subtree, pjson);
+ if(*pjson == NULL) {
+ /* we need to have a root object! */
+ *pjson = json_object_new_object();
+ } else {
+ json_object_get(*pjson); /* inc refcount */
+ }
+ FINALIZE;
+ }
+
json = json_object_new_object();
for(pTpe = pTpl->pEntryRoot ; pTpe != NULL ; pTpe = pTpe->pNext) {
if(pTpe->eEntryType == CONSTANT) {
@@ -294,19 +345,34 @@ rsRetVal tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjso
jsonf = json_object_new_string((char*) pTpe->data.constant.pConstant);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &propLen, &bMustBeFreed);
- if(pTpe->data.field.options.bMandatory || propLen > 0) {
- jsonf = json_object_new_string_len((char*)pVal, propLen);
- json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
- }
- if(bMustBeFreed) { /* json-c makes its own private copy! */
- free(pVal);
+ if(pTpe->data.field.propid == PROP_CEE) {
+ localRet = msgGetCEEPropJSON(pMsg, pTpe->data.field.propName, &jsonf);
+ if(localRet == RS_RET_OK) {
+ json_object_object_add(json, (char*)pTpe->fieldName, json_object_get(jsonf));
+ } else {
+ DBGPRINTF("tplToJSON: error %d looking up property\n",
+ localRet);
+ if(pTpe->data.field.options.bMandatory) {
+ json_object_object_add(json, (char*)pTpe->fieldName, NULL);
+ }
+ }
+ } else {
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
+ pTpe->data.field.propName, &propLen,
+ &bMustBeFreed, ttNow);
+ if(pTpe->data.field.options.bMandatory || propLen > 0) {
+ jsonf = json_object_new_string_len((char*)pVal, propLen);
+ json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
+ }
+ if(bMustBeFreed) { /* json-c makes its own private copy! */
+ free(pVal);
+ }
}
}
}
-
*pjson = (iRet == RS_RET_OK) ? json : NULL;
+
+finalize_it:
RETiRet;
}
@@ -364,7 +430,7 @@ static void doEmergencyEscape(register uchar *p, int mode)
* 2005-09-22 rgerhards
*/
rsRetVal
-doEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int mode)
+doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int mode)
{
DEFiRet;
uchar *p = NULL;
@@ -487,14 +553,20 @@ tplConstruct(rsconf_t *conf)
/* helper to tplAddLine. Parses a constant and generates
* the necessary structure.
- * returns: 0 - ok, 1 - failure
+ * Paramter "bDoEscapes" is to support legacy vs. v6+ config system. In
+ * legacy, we must do escapes ourselves, whereas v6+ passes in already
+ * escaped strings (which we are NOT permitted to further escape, this would
+ * cause invalid result strings!). Note: if escapes are not permitted,
+ * quotes (") are just a regular character and do NOT terminate the constant!
*/
-static int do_Constant(unsigned char **pp, struct template *pTpl)
+static rsRetVal
+do_Constant(unsigned char **pp, struct template *pTpl, int bDoEscapes)
{
register unsigned char *p;
cstr_t *pStrB;
struct templateEntry *pTpe;
int i;
+ DEFiRet;
assert(pp != NULL);
assert(*pp != NULL);
@@ -502,13 +574,12 @@ static int do_Constant(unsigned char **pp, struct template *pTpl)
p = *pp;
- if(cstrConstruct(&pStrB) != RS_RET_OK)
- return 1;
+ CHKiRet(cstrConstruct(&pStrB));
/* process the message and expand escapes
* (additional escapes can be added here if needed)
*/
- while(*p && *p != '%' && *p != '\"') {
- if(*p == '\\') {
+ while(*p && *p != '%' && !(bDoEscapes && *p == '\"')) {
+ if(bDoEscapes && *p == '\\') {
switch(*++p) {
case '\0':
/* the best we can do - it's invalid anyhow... */
@@ -557,7 +628,7 @@ static int do_Constant(unsigned char **pp, struct template *pTpl)
if((pTpe = tpeConstruct(pTpl)) == NULL) {
rsCStrDestruct(&pStrB);
- return 1;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
pTpe->eEntryType = CONSTANT;
cstrFinalize(pStrB);
@@ -567,12 +638,12 @@ static int do_Constant(unsigned char **pp, struct template *pTpl)
* 2005-09-09 rgerhards
*/
pTpe->data.constant.iLenConstant = rsCStrLen(pStrB);
- if(cstrConvSzStrAndDestruct(pStrB, &pTpe->data.constant.pConstant, 0) != RS_RET_OK)
- return 1;
+ CHKiRet(cstrConvSzStrAndDestruct(pStrB, &pTpe->data.constant.pConstant, 0));
*pp = p;
- return 0;
+finalize_it:
+ RETiRet;
}
@@ -642,6 +713,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.options.bSecPathDrop = 1;
} else if(!strcmp((char*)Buf, "secpath-replace")) {
pTpe->data.field.options.bSecPathReplace = 1;
+ } else if(!strcmp((char*)Buf, "pos-end-relative")) {
+ pTpe->data.field.options.bFromPosEndRelative = 1;
} else if(!strcmp((char*)Buf, "csv")) {
if(pTpe->data.field.options.bJSON || pTpe->data.field.options.bJSONf) {
errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
@@ -677,11 +750,11 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
/* helper to tplAddLine. Parses a parameter and generates
* the necessary structure.
- * returns: 0 - ok, 1 - failure
*/
-static int do_Parameter(unsigned char **pp, struct template *pTpl)
+static rsRetVal
+do_Parameter(uchar **pp, struct template *pTpl)
{
- unsigned char *p;
+ uchar *p;
cstr_t *pStrProp;
cstr_t *pStrField = NULL;
struct templateEntry *pTpe;
@@ -693,21 +766,15 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
unsigned char *regex_char;
unsigned char *regex_end;
#endif
+ DEFiRet;
assert(pp != NULL);
assert(*pp != NULL);
assert(pTpl != NULL);
- p = (unsigned char*) *pp;
-
- if(cstrConstruct(&pStrProp) != RS_RET_OK)
- return 1;
-
- if((pTpe = tpeConstruct(pTpl)) == NULL) {
- /* TODO: add handler */
- dbgprintf("Could not allocate memory for template parameter!\n");
- return 1;
- }
+ p = (uchar*) *pp;
+ CHKiRet(cstrConstruct(&pStrProp));
+ CHKmalloc(pTpe = tpeConstruct(pTpl));
pTpe->eEntryType = FIELD;
while(*p && *p != '%' && *p != ':') {
@@ -719,19 +786,22 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
cstrFinalize(pStrProp);
if(propNameToID(pStrProp, &pTpe->data.field.propid) != RS_RET_OK) {
+ errmsg.LogError(0, RS_RET_TPL_INVLD_PROP, "template '%s': invalid parameter '%s'",
+ pTpl->pszName, cstrGetSzStrNoNULL(pStrProp));
cstrDestruct(&pStrProp);
- return 1;
+ ABORT_FINALIZE(RS_RET_TPL_INVLD_PROP);
}
if(pTpe->data.field.propid == PROP_CEE) {
/* in CEE case, we need to preserve the actual property name */
- if((pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrProp)+2, cstrLen(pStrProp)-2)) == NULL) {
+ if((pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrProp)+1, cstrLen(pStrProp)-1)) == NULL) {
cstrDestruct(&pStrProp);
- return 1;
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
}
/* Check frompos, if it has an R, then topos should be a regex */
if(*p == ':') {
+ pTpe->bComplexProcessing = 1;
++p; /* eat ':' */
#ifdef FEATURE_REGEXP
if(*p == 'R') {
@@ -791,8 +861,8 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
* comma itself is already part of the next field.
*/
} else {
- errmsg.LogError(0, NO_ERRCODE, "error: invalid regular expression type, rest of line %s",
- (char*) p);
+ errmsg.LogError(0, NO_ERRCODE, "template %s error: invalid regular expression type, rest of line %s",
+ pTpl->pszName, (char*) p);
}
}
@@ -898,9 +968,7 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
#ifdef FEATURE_REGEXP
if (pTpe->data.field.has_regex) {
-
dbgprintf("debug: has regex \n");
-
/* APR 2005-09 I need the string that represent the regex */
/* The regex end is: "--end" */
/* TODO : this is hardcoded and cant be escaped, please change */
@@ -916,16 +984,13 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
if(regex_char == NULL) {
dbgprintf("Could not allocate memory for template parameter!\n");
pTpe->data.field.has_regex = 0;
- return 1;
- /* TODO: RGer: check if we can recover better... (probably not) */
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
/* Get the regex string for compiling later */
memcpy(regex_char, p, longitud);
regex_char[longitud] = '\0';
-
dbgprintf("debug: regex detected: '%s'\n", regex_char);
-
/* Now i compile the regex */
/* Remember that the re is an attribute of the Template entry */
if((iRetLocal = objUse(regexp, LM_REGEXP_FILENAME)) == RS_RET_OK) {
@@ -995,23 +1060,31 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
#endif /* #ifdef FEATURE_REGEXP */
}
- if(pTpe->data.field.iToPos < pTpe->data.field.iFromPos) {
- iNum = pTpe->data.field.iToPos;
- pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
- pTpe->data.field.iFromPos = iNum;
- }
-
/* check options */
if(*p == ':') {
++p; /* eat ':' */
doOptions(&p, pTpe);
}
+ if(pTpe->data.field.options.bFromPosEndRelative) {
+ if(pTpe->data.field.iToPos > pTpe->data.field.iFromPos) {
+ iNum = pTpe->data.field.iToPos;
+ pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
+ pTpe->data.field.iFromPos = iNum;
+ }
+ } else {
+ if(pTpe->data.field.iToPos < pTpe->data.field.iFromPos) {
+ iNum = pTpe->data.field.iToPos;
+ pTpe->data.field.iToPos = pTpe->data.field.iFromPos;
+ pTpe->data.field.iFromPos = iNum;
+ }
+ }
+
+
/* check field name */
if(*p == ':') {
++p; /* eat ':' */
- if(cstrConstruct(&pStrField) != RS_RET_OK)
- return 1;
+ CHKiRet(cstrConstruct(&pStrField));
while(*p != ':' && *p != '%' && *p != '\0') {
cstrAppendChar(pStrField, *p);
++p;
@@ -1031,18 +1104,18 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
}
} else {
pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrField));
- pTpe->lenFieldName = cstrLen(pStrProp);
+ pTpe->lenFieldName = ustrlen(pTpe->fieldName);
cstrDestruct(&pStrField);
}
- if(pTpe->fieldName == NULL)
- return 1;
-
+ if(pTpe->fieldName == NULL) {
+ DBGPRINTF("template/do_Parameter: fieldName is NULL!\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
cstrDestruct(&pStrProp);
-
if(*p) ++p; /* eat '%' */
-
*pp = p;
- return 0;
+finalize_it:
+ RETiRet;
}
@@ -1108,10 +1181,10 @@ struct template *tplAddLine(rsconf_t *conf, char* pName, uchar** ppRestOfConfLin
assert(pName != NULL);
assert(ppRestOfConfLine != NULL);
-
if((pTpl = tplConstruct(conf)) == NULL)
return NULL;
+ DBGPRINTF("tplAddLine processing template '%s'\n", pName);
pTpl->iLenName = strlen(pName);
pTpl->pszName = (char*) MALLOC(sizeof(char) * (pTpl->iLenName + 1));
if(pTpl->pszName == NULL) {
@@ -1171,10 +1244,13 @@ struct template *tplAddLine(rsconf_t *conf, char* pName, uchar** ppRestOfConfLin
break;
case '%': /* parameter */
++p; /* eat '%' */
- do_Parameter(&p, pTpl);
+ if(do_Parameter(&p, pTpl) != RS_RET_OK) {
+ dbgprintf("tplAddLine error: parameter invalid");
+ return NULL;
+ };
break;
default: /* constant */
- do_Constant(&p, pTpl);
+ do_Constant(&p, pTpl, 1);
break;
}
if(*p == '"') {/* end of template string? */
@@ -1235,7 +1311,7 @@ static rsRetVal
createConstantTpe(struct template *pTpl, struct cnfobj *o)
{
struct templateEntry *pTpe;
- es_str_t *value;
+ es_str_t *value = NULL; /* init just to keep compiler happy - mandatory parameter */
int i;
struct cnfparamvals *pvals = NULL;
uchar *outname = NULL;
@@ -1292,6 +1368,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
int fielddelim = 9; /* default is HT (USACSII 9) */
int re_matchToUse = 0;
int re_submatchToUse = 0;
+ int bComplexProcessing = 0;
+ int bPosRelativeToEnd = 0;
char *re_expr = NULL;
struct cnfparamvals *pvals = NULL;
enum {F_NONE, F_CSV, F_JSON, F_JSONF} formatType = F_NONE;
@@ -1317,23 +1395,33 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
free(tmpstr);
} else if(!strcmp(pblkProperty.descr[i].name, "droplastlf")) {
droplastlf = pvals[i].val.d.n;
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "mandatory")) {
mandatory = pvals[i].val.d.n;
} else if(!strcmp(pblkProperty.descr[i].name, "spifno1stsp")) {
spifno1stsp = pvals[i].val.d.n;
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "outname")) {
outname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(pblkProperty.descr[i].name, "position.from")) {
frompos = pvals[i].val.d.n;
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "position.to")) {
topos = pvals[i].val.d.n;
+ bComplexProcessing = 1;
+ } else if(!strcmp(pblkProperty.descr[i].name, "position.relativetoend")) {
+ bPosRelativeToEnd = pvals[i].val.d.n;
} else if(!strcmp(pblkProperty.descr[i].name, "field.number")) {
fieldnum = pvals[i].val.d.n;
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "field.delimiter")) {
fielddelim = pvals[i].val.d.n;
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "regex.expression")) {
re_expr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ bComplexProcessing = 1;
} else if(!strcmp(pblkProperty.descr[i].name, "regex.type")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"BRE", sizeof("BRE")-1)) {
re_type = TPL_REGEX_BRE;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"ERE", sizeof("ERE")-1)) {
@@ -1346,6 +1434,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
ABORT_FINALIZE(RS_RET_ERR);
}
} else if(!strcmp(pblkProperty.descr[i].name, "regex.nomatchmode")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"DFLT", sizeof("DFLT")-1)) {
re_nomatchType = TPL_REGEX_NOMATCH_USE_DFLTSTR;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"BLANK", sizeof("BLANK")-1)) {
@@ -1362,10 +1451,13 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
ABORT_FINALIZE(RS_RET_ERR);
}
} else if(!strcmp(pblkProperty.descr[i].name, "regex.match")) {
+ bComplexProcessing = 1;
re_matchToUse = pvals[i].val.d.n;
} else if(!strcmp(pblkProperty.descr[i].name, "regex.submatch")) {
+ bComplexProcessing = 1;
re_submatchToUse = pvals[i].val.d.n;
} else if(!strcmp(pblkProperty.descr[i].name, "format")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"csv", sizeof("csv")-1)) {
formatType = F_CSV;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"json", sizeof("json")-1)) {
@@ -1380,6 +1472,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
ABORT_FINALIZE(RS_RET_ERR);
}
} else if(!strcmp(pblkProperty.descr[i].name, "controlcharacters")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"escape", sizeof("escape")-1)) {
controlchr = CC_ESCAPE;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"space", sizeof("space")-1)) {
@@ -1394,6 +1487,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
ABORT_FINALIZE(RS_RET_ERR);
}
} else if(!strcmp(pblkProperty.descr[i].name, "securepath")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"drop", sizeof("drop")-1)) {
secpath = SP_DROP;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"replace", sizeof("replace")-1)) {
@@ -1406,6 +1500,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
ABORT_FINALIZE(RS_RET_ERR);
}
} else if(!strcmp(pblkProperty.descr[i].name, "caseconversion")) {
+ bComplexProcessing = 1;
if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"lower", sizeof("lower")-1)) {
caseconv = tplCaseConvLower;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"upper", sizeof("upper")-1)) {
@@ -1458,10 +1553,18 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
topos = 2000000000; /* large enough ;) */
if(frompos == -1 && topos != -1)
frompos = 0;
- if(topos < frompos) {
- errmsg.LogError(0, RS_RET_ERR, "position.to=%d is lower than postion.from=%d\n",
- topos, frompos);
- ABORT_FINALIZE(RS_RET_ERR);
+ if(bPosRelativeToEnd) {
+ if(topos > frompos) {
+ errmsg.LogError(0, RS_RET_ERR, "position.to=%d is higher than postion.from=%d in 'relativeToEnd' mode\n",
+ topos, frompos);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(topos < frompos) {
+ errmsg.LogError(0, RS_RET_ERR, "position.to=%d is lower than postion.from=%d\n",
+ topos, frompos);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
}
if(fieldnum != -1 && re_expr != NULL) {
errmsg.LogError(0, RS_RET_ERR, "both field extraction and regex extraction "
@@ -1475,8 +1578,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
CHKiRet(propNameToID(name, &pTpe->data.field.propid));
if(pTpe->data.field.propid == PROP_CEE) {
/* in CEE case, we need to preserve the actual property name */
- pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(name)+2,
- cstrLen(name)-2);
+ pTpe->data.field.propName = es_newStrFromCStr((char*)cstrGetSzStrNoNULL(name)+1,
+ cstrLen(name)-1);
}
pTpe->data.field.options.bDropLastLF = droplastlf;
pTpe->data.field.options.bSPIffNo1stSP = spifno1stsp;
@@ -1524,6 +1627,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
pTpe->fieldName = outname;
if(outname != NULL)
pTpe->lenFieldName = ustrlen(outname);
+ pTpe->bComplexProcessing = bComplexProcessing;
pTpe->data.field.eDateFormat = datefmt;
if(fieldnum != -1) {
pTpe->data.field.has_fields = 1;
@@ -1533,6 +1637,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
if(frompos != -1) {
pTpe->data.field.iFromPos = frompos;
pTpe->data.field.iToPos = topos;
+ pTpe->data.field.options.bFromPosEndRelative = bPosRelativeToEnd;
}
if(re_expr != NULL) {
rsRetVal iRetLocal;
@@ -1604,12 +1709,14 @@ tplProcessCnf(struct cnfobj *o)
{
struct template *pTpl = NULL;
struct cnfparamvals *pvals = NULL;
- int lenName;
+ int lenName = 0; /* init just to keep compiler happy: mandatory parameter */
char *name = NULL;
uchar *tplStr = NULL;
uchar *plugin = NULL;
+ es_str_t *subtree = NULL;
uchar *p;
- enum { T_STRING, T_PLUGIN, T_LIST } tplType;
+ enum { T_STRING, T_PLUGIN, T_LIST, T_SUBTREE }
+ tplType = T_STRING; /* init just to keep compiler happy: mandatory parameter */
int i;
int o_sql=0, o_stdsql=0, o_json=0; /* options */
int numopts;
@@ -1632,6 +1739,8 @@ tplProcessCnf(struct cnfobj *o)
tplType = T_PLUGIN;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"list", sizeof("list")-1)) {
tplType = T_LIST;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"subtree", sizeof("subtree")-1)) {
+ tplType = T_SUBTREE;
} else {
uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
errmsg.LogError(0, RS_RET_ERR, "invalid template type '%s'",
@@ -1641,6 +1750,22 @@ tplProcessCnf(struct cnfobj *o)
}
} else if(!strcmp(pblk.descr[i].name, "string")) {
tplStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
+ } else if(!strcmp(pblk.descr[i].name, "subtree")) {
+ uchar *st_str = es_getBufAddr(pvals[i].val.d.estr);
+ if(st_str[0] != '$' || st_str[1] != '!') {
+ char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ errmsg.LogError(0, RS_RET_ERR, "invalid subtree "
+ "parameter, variable must start with '$!' but "
+ "var name is '%s'", cstr);
+ free(cstr);
+ free(name); /* overall assigned */
+ ABORT_FINALIZE(RS_RET_ERR);
+ } else {
+ /* TODO: unify strings! */
+ char *cstr = es_str2cstr(pvals[i].val.d.estr, NULL);
+ subtree = es_newStrFromBuf(cstr+1, es_strlen(pvals[i].val.d.estr)-1);
+ free(cstr);
+ }
} else if(!strcmp(pblk.descr[i].name, "plugin")) {
plugin = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(pblk.descr[i].name, "option.stdsql")) {
@@ -1682,6 +1807,19 @@ tplProcessCnf(struct cnfobj *o)
}
}
+ if(subtree == NULL) {
+ if(tplType == T_SUBTREE) {
+ errmsg.LogError(0, RS_RET_ERR, "template '%s' of type subtree needs "
+ "subtree parameter", name);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ } else {
+ if(tplType != T_SUBTREE) {
+ errmsg.LogError(0, RS_RET_ERR, "template '%s' is not a subtree "
+ "template but has a subtree specified - ignored", name);
+ }
+ }
+
if(o->subobjs == NULL) {
if(tplType == T_LIST) {
errmsg.LogError(0, RS_RET_ERR, "template '%s' of type list has "
@@ -1719,10 +1857,10 @@ tplProcessCnf(struct cnfobj *o)
switch(*p) {
case '%': /* parameter */
++p; /* eat '%' */
- do_Parameter(&p, pTpl);
+ CHKiRet(do_Parameter(&p, pTpl));
break;
default: /* constant */
- do_Constant(&p, pTpl);
+ do_Constant(&p, pTpl, 0);
break;
}
}
@@ -1739,6 +1877,8 @@ tplProcessCnf(struct cnfobj *o)
break;
case T_LIST: createListTpl(pTpl, o);
break;
+ case T_SUBTREE: pTpl->subtree = subtree;
+ break;
}
pTpl->optFormatEscape = NO_ESCAPE;
@@ -1840,8 +1980,9 @@ void tplDeleteAll(rsconf_t *conf)
}
pTplDel = pTpl;
pTpl = pTpl->pNext;
- if(pTplDel->pszName != NULL)
- free(pTplDel->pszName);
+ free(pTplDel->pszName);
+ if(pTplDel->subtree != NULL)
+ es_deleteStr(pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -1898,8 +2039,9 @@ void tplDeleteNew(rsconf_t *conf)
}
pTplDel = pTpl;
pTpl = pTpl->pNext;
- if(pTplDel->pszName != NULL)
- free(pTplDel->pszName);
+ free(pTplDel->pszName);
+ if(pTplDel->subtree != NULL)
+ es_deleteStr(pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -1965,8 +2107,14 @@ void tplPrintList(rsconf_t *conf)
case tplFmtUnixDate:
dbgprintf("[Format as Unix timestamp] ");
break;
+ case tplFmtSecFrac:
+ dbgprintf("[fractional seconds, only] ");
+ break;
+ case tplFmtRFC3164BuggyDate:
+ dbgprintf("[Format as buggy RFC3164-Date] ");
+ break;
default:
- dbgprintf("[INVALID eDateFormat %d] ", pTpe->data.field.eDateFormat);
+ dbgprintf("[UNKNOWN eDateFormat %d] ", pTpe->data.field.eDateFormat);
}
switch(pTpe->data.field.eCaseConv) {
case tplCaseConvNo:
@@ -2022,6 +2170,8 @@ void tplPrintList(rsconf_t *conf)
}
break;
}
+ if(pTpe->bComplexProcessing)
+ dbgprintf("[COMPLEX]");
dbgprintf("\n");
pTpe = pTpe->pNext;
}
@@ -2035,8 +2185,6 @@ int tplGetEntryCount(struct template *pTpl)
return(pTpl->tpenElements);
}
-/* our init function. TODO: remove once converted to a class
- */
rsRetVal templateInit()
{
DEFiRet;