summaryrefslogtreecommitdiff
path: root/template.c
diff options
context:
space:
mode:
Diffstat (limited to 'template.c')
-rw-r--r--template.c276
1 files changed, 176 insertions, 100 deletions
diff --git a/template.c b/template.c
index c48bf4b..29c46a2 100644
--- a/template.c
+++ b/template.c
@@ -1,7 +1,7 @@
/* This is the template processing code of rsyslog.
* begun 2004-11-17 rgerhards
*
- * Copyright 2004-2012 Rainer Gerhards and Adiscon
+ * Copyright 2004-2014 Rainer Gerhards and Adiscon
*
* This file is part of rsyslog.
*
@@ -34,7 +34,7 @@
#include <string.h>
#include <ctype.h>
#include <assert.h>
-#include <json/json.h>
+#include <json.h>
#include "stringbuf.h"
#include "syslogd-types.h"
#include "template.h"
@@ -45,6 +45,7 @@
#include "strgen.h"
#include "rsconf.h"
#include "msg.h"
+#include "parserif.h"
#include "unicode-helper.h"
/* static data */
@@ -116,16 +117,16 @@ static int bFirstRegexpErrmsg = 1; /**< did we already do a "can't load regexp"
/* helper to tplToString and strgen's, extends buffer */
#define ALLOC_INC 128
rsRetVal
-ExtendBuf(uchar **pBuf, size_t *pLenBuf, size_t iMinSize)
+ExtendBuf(actWrkrIParams_t *__restrict__ const iparam, const size_t iMinSize)
{
uchar *pNewBuf;
size_t iNewSize;
DEFiRet;
iNewSize = (iMinSize / ALLOC_INC + 1) * ALLOC_INC;
- CHKmalloc(pNewBuf = (uchar*) realloc(*pBuf, iNewSize));
- *pBuf = pNewBuf;
- *pLenBuf = iNewSize;
+ CHKmalloc(pNewBuf = (uchar*) realloc(iparam->param, iNewSize));
+ iparam->param = pNewBuf;
+ iparam->lenBuf = iNewSize;
finalize_it:
RETiRet;
@@ -137,42 +138,39 @@ finalize_it:
* The function takes a pointer to a template and a pointer to a msg object
* as well as a pointer to an output buffer and its size. Note that the output
* buffer pointer may be NULL, size 0, in which case a new one is allocated.
- * The outpub buffer is grown as required. It is the caller's duty to free the
+ * The output buffer is grown as required. It is the caller's duty to free the
* buffer when it is done. Note that it is advisable to reuse memory, as this
* offers big performance improvements.
* rewritten 2009-06-19 rgerhards
*/
rsRetVal
-tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
- struct syslogTime *ttNow)
+tplToString(struct template *__restrict__ const pTpl,
+ msg_t *__restrict__ const pMsg,
+ actWrkrIParams_t *__restrict const iparam,
+ struct syslogTime *const ttNow)
{
DEFiRet;
- struct templateEntry *pTpe;
+ struct templateEntry *__restrict__ pTpe;
size_t iBuf;
unsigned short bMustBeFreed = 0;
uchar *pVal;
rs_size_t iLenVal = 0;
- assert(pTpl != NULL);
- assert(pMsg != NULL);
- assert(ppBuf != NULL);
- assert(pLenBuf != NULL);
-
if(pTpl->pStrgen != NULL) {
- CHKiRet(pTpl->pStrgen(pMsg, ppBuf, pLenBuf));
+ CHKiRet(pTpl->pStrgen(pMsg, iparam));
FINALIZE;
}
- if(pTpl->subtree != NULL) {
+ if(pTpl->bHaveSubtree) {
/* 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);
+ getJSONPropVal(pMsg, &pTpl->subtree, &pVal, &iLenVal, &bMustBeFreed);
+ if(iLenVal >= (rs_size_t)iparam->lenBuf) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(iparam, iLenVal + 1));
+ memcpy(iparam->param, pVal, iLenVal+1);
if(bMustBeFreed)
free(pVal);
FINALIZE;
@@ -193,9 +191,8 @@ tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
iLenVal = pTpe->data.constant.iLenConstant;
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
- pTpe->data.field.propName, &iLenVal,
- &bMustBeFreed, ttNow);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &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,
@@ -212,10 +209,10 @@ tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
/* got source, now copy over */
if(iLenVal > 0) { /* may be zero depending on property */
/* first, make sure buffer fits */
- if(iBuf + iLenVal >= *pLenBuf) /* we reserve one char for the final \0! */
- CHKiRet(ExtendBuf(ppBuf, pLenBuf, iBuf + iLenVal + 1));
+ if(iBuf + iLenVal >= iparam->lenBuf) /* we reserve one char for the final \0! */
+ CHKiRet(ExtendBuf(iparam, iBuf + iLenVal + 1));
- memcpy(*ppBuf + iBuf, pVal, iLenVal);
+ memcpy(iparam->param + iBuf, pVal, iLenVal);
iBuf += iLenVal;
}
@@ -225,15 +222,16 @@ tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *pLenBuf,
pTpe = pTpe->pNext;
}
- if(iBuf == *pLenBuf) {
+ if(iBuf == iparam->lenBuf) {
/* in the weired case of an *empty* template, this can happen.
* it is debatable if we should really fix it here or simply
* forbid that case. However, performance toll is minimal, so
- * I tend to permit it. -- 201011-05 rgerhards
+ * I tend to permit it. -- 2010-11-05 rgerhards
*/
- CHKiRet(ExtendBuf(ppBuf, pLenBuf, iBuf + 1));
+ CHKiRet(ExtendBuf(iparam, iBuf + 1));
}
- (*ppBuf)[iBuf] = '\0';
+ iparam->param[iBuf] = '\0';
+ iparam->lenStr = iBuf;
finalize_it:
RETiRet;
@@ -264,12 +262,12 @@ tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr, struct syslogTime
assert(pMsg != NULL);
assert(ppArr != NULL);
- if(pTpl->subtree) {
+ if(pTpl->bHaveSubtree) {
/* 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);
+ getJSONPropVal(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 {
@@ -290,9 +288,8 @@ tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr, struct syslogTime
if(pTpe->eEntryType == CONSTANT) {
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, ttNow);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &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 {
@@ -326,8 +323,8 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct
rsRetVal localRet;
DEFiRet;
- if(pTpl->subtree != NULL){
- localRet = jsonFind(pMsg, pTpl->subtree, pjson);
+ if(pTpl->bHaveSubtree){
+ localRet = jsonFind(pMsg->json, &pTpl->subtree, pjson);
if(*pjson == NULL) {
/* we need to have a root object! */
*pjson = json_object_new_object();
@@ -345,23 +342,24 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson, struct
jsonf = json_object_new_string((char*) pTpe->data.constant.pConstant);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
} else if(pTpe->eEntryType == FIELD) {
- if(pTpe->data.field.propid == PROP_CEE) {
- localRet = msgGetCEEPropJSON(pMsg, pTpe->data.field.propName, &jsonf);
+ if(pTpe->data.field.msgProp.id == PROP_CEE ||
+ pTpe->data.field.msgProp.id == PROP_LOCAL_VAR ||
+ pTpe->data.field.msgProp.id == PROP_GLOBAL_VAR ) {
+ localRet = msgGetJSONPropJSON(pMsg, &pTpe->data.field.msgProp, &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);
+ DBGPRINTF("tplToJSON: error %d looking up property %s\n",
+ localRet, pTpe->fieldName);
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);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, &pTpe->data.field.msgProp,
+ &propLen, &bMustBeFreed, ttNow);
if(pTpe->data.field.options.bMandatory || propLen > 0) {
- jsonf = json_object_new_string_len((char*)pVal, propLen);
+ jsonf = json_object_new_string_len((char*)pVal, propLen+1);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
}
if(bMustBeFreed) { /* json-c makes its own private copy! */
@@ -477,7 +475,7 @@ doEscape(uchar **pp, rs_size_t *pLen, unsigned short *pbMustBeFreed, int mode)
++p;
}
CHKiRet(cstrFinalize(pStrB));
- CHKiRet(cstrConvSzStrAndDestruct(pStrB, &pszGenerated, 0));
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pszGenerated, 0));
if(*pbMustBeFreed)
free(*pp); /* discard previous value */
@@ -638,7 +636,7 @@ do_Constant(unsigned char **pp, struct template *pTpl, int bDoEscapes)
* 2005-09-09 rgerhards
*/
pTpe->data.constant.iLenConstant = rsCStrLen(pStrB);
- CHKiRet(cstrConvSzStrAndDestruct(pStrB, &pTpe->data.constant.pConstant, 0));
+ CHKiRet(cstrConvSzStrAndDestruct(&pStrB, &pTpe->data.constant.pConstant, 0));
*pp = p;
@@ -646,6 +644,17 @@ finalize_it:
RETiRet;
}
+/* Helper that checks to see if a property already has a format
+ * type defined
+ */
+static int hasFormat(struct templateEntry *pTpe) {
+ return (
+ pTpe->data.field.options.bCSV ||
+ pTpe->data.field.options.bJSON ||
+ pTpe->data.field.options.bJSONf ||
+ pTpe->data.field.options.bJSONr
+ );
+}
/* Helper to do_Parameter(). This parses the formatting options
* specified in a template variable. It returns the passed-in pointer
@@ -695,6 +704,28 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.eDateFormat = tplFmtUnixDate;
} else if(!strcmp((char*)Buf, "date-subseconds")) {
pTpe->data.field.eDateFormat = tplFmtSecFrac;
+ } else if(!strcmp((char*)Buf, "date-wdayname")) {
+ pTpe->data.field.eDateFormat = tplFmtWDayName;
+ } else if(!strcmp((char*)Buf, "date-wday")) {
+ pTpe->data.field.eDateFormat = tplFmtWDay;
+ } else if(!strcmp((char*)Buf, "date-year")) {
+ pTpe->data.field.eDateFormat = tplFmtYear;
+ } else if(!strcmp((char*)Buf, "date-month")) {
+ pTpe->data.field.eDateFormat = tplFmtMonth;
+ } else if(!strcmp((char*)Buf, "date-day")) {
+ pTpe->data.field.eDateFormat = tplFmtDay;
+ } else if(!strcmp((char*)Buf, "date-hour")) {
+ pTpe->data.field.eDateFormat = tplFmtHour;
+ } else if(!strcmp((char*)Buf, "date-minute")) {
+ pTpe->data.field.eDateFormat = tplFmtMinute;
+ } else if(!strcmp((char*)Buf, "date-second")) {
+ pTpe->data.field.eDateFormat = tplFmtSecond;
+ } else if(!strcmp((char*)Buf, "date-tzoffshour")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsHour;
+ } else if(!strcmp((char*)Buf, "date-tzoffsmin")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsMin;
+ } else if(!strcmp((char*)Buf, "date-tzoffsdirection")) {
+ pTpe->data.field.eDateFormat = tplFmtTZOffsDirection;
} else if(!strcmp((char*)Buf, "lowercase")) {
pTpe->data.field.eCaseConv = tplCaseConvLower;
} else if(!strcmp((char*)Buf, "uppercase")) {
@@ -716,26 +747,40 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
} 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) {
+ if(hasFormat(pTpe)) {
errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
- "one option out of (json, jsonf, csv) - csv ignored");
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - csv ignored");
} else {
pTpe->data.field.options.bCSV = 1;
}
} else if(!strcmp((char*)Buf, "json")) {
- if(pTpe->data.field.options.bCSV || pTpe->data.field.options.bJSON) {
+ if(hasFormat(pTpe)) {
errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
- "one option out of (json, jsonf, csv) - json ignored");
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - json ignored");
} else {
pTpe->data.field.options.bJSON = 1;
}
} else if(!strcmp((char*)Buf, "jsonf")) {
- if(pTpe->data.field.options.bCSV || pTpe->data.field.options.bJSON) {
+ if(hasFormat(pTpe)) {
errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
- "one option out of (json, jsonf, csv) - jsonf ignored");
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonf ignored");
} else {
pTpe->data.field.options.bJSONf = 1;
}
+ } else if(!strcmp((char*)Buf, "jsonr")) {
+ if(hasFormat(pTpe)) {
+ errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonr ignored");
+ } else {
+ pTpe->data.field.options.bJSONr = 1;
+ }
+ } else if(!strcmp((char*)Buf, "jsonfr")) {
+ if(hasFormat(pTpe)) {
+ errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, jsonr, jsonfr, csv) - jsonfr ignored");
+ } else {
+ pTpe->data.field.options.bJSONfr = 1;
+ }
} else if(!strcmp((char*)Buf, "mandatory-field")) {
pTpe->data.field.options.bMandatory = 1;
} else {
@@ -747,7 +792,6 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
*pp = p;
}
-
/* helper to tplAddLine. Parses a parameter and generates
* the necessary structure.
*/
@@ -755,7 +799,7 @@ static rsRetVal
do_Parameter(uchar **pp, struct template *pTpl)
{
uchar *p;
- cstr_t *pStrProp;
+ cstr_t *pStrProp = NULL;
cstr_t *pStrField = NULL;
struct templateEntry *pTpe;
int iNum; /* to compute numbers */
@@ -785,19 +829,8 @@ do_Parameter(uchar **pp, struct template *pTpl)
/* got the name */
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);
- 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)+1, cstrLen(pStrProp)-1)) == NULL) {
- cstrDestruct(&pStrProp);
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
- }
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(pStrProp),
+ cstrLen(pStrProp)));
/* Check frompos, if it has an R, then topos should be a regex */
if(*p == ':') {
@@ -921,7 +954,7 @@ do_Parameter(uchar **pp, struct template *pTpl)
if(iNum < 0 || iNum > 255) {
errmsg.LogError(0, NO_ERRCODE, "error: non-USASCII delimiter character value %d in template - using 9 (HT) as substitute", iNum);
pTpe->data.field.field_delim = 9;
- } else {
+ } else {
pTpe->data.field.field_delim = iNum;
# ifdef STRICT_GPLV3
if (*p == '+') {
@@ -935,8 +968,12 @@ do_Parameter(uchar **pp, struct template *pTpl)
while(isdigit((int)*p))
iNum = iNum * 10 + *p++ - '0';
pTpe->data.field.iFromPos = iNum;
+ } else if(*p != ':') {
+ parser_errmsg("error: invalid character '%c' in frompos after \"F,\", property: '%s' "
+ "be sure to use DECIMAL character codes!", *p, (char*) *pp);
+ ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
}
- }
+ }
}
} else {
/* invalid character after F, so we need to reject
@@ -1094,8 +1131,8 @@ do_Parameter(uchar **pp, struct template *pTpl)
/* save field name - if none was given, use the property name instead */
if(pStrField == NULL) {
- if(pTpe->data.field.propid == PROP_CEE) {
- /* in CEE case, we remove "$!" from the fieldname - it's just our indicator */
+ if(pTpe->data.field.msgProp.id == PROP_CEE || pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
+ /* in CEE case, we remove "$!"/"$." from the fieldname - it's just our indicator */
pTpe->fieldName = ustrdup(cstrGetSzStrNoNULL(pStrProp)+2);
pTpe->lenFieldName = cstrLen(pStrProp)-2;
} else {
@@ -1111,10 +1148,11 @@ do_Parameter(uchar **pp, struct template *pTpl)
DBGPRINTF("template/do_Parameter: fieldName is NULL!\n");
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
- cstrDestruct(&pStrProp);
if(*p) ++p; /* eat '%' */
*pp = p;
finalize_it:
+ if(pStrProp != NULL)
+ cstrDestruct(&pStrProp);
RETiRet;
}
@@ -1184,6 +1222,7 @@ struct template *tplAddLine(rsconf_t *conf, char* pName, uchar** ppRestOfConfLin
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) {
@@ -1371,7 +1410,7 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
int bPosRelativeToEnd = 0;
char *re_expr = NULL;
struct cnfparamvals *pvals = NULL;
- enum {F_NONE, F_CSV, F_JSON, F_JSONF} formatType = F_NONE;
+ enum {F_NONE, F_CSV, F_JSON, F_JSONF, F_JSONR, F_JSONFR} formatType = F_NONE;
enum {CC_NONE, CC_ESCAPE, CC_SPACE, CC_DROP} controlchr = CC_NONE;
enum {SP_NONE, SP_DROP, SP_REPLACE} secpath = SP_NONE;
enum tplFormatCaseConvTypes caseconv = tplCaseConvNo;
@@ -1463,6 +1502,10 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
formatType = F_JSON;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonf", sizeof("jsonf")-1)) {
formatType = F_JSONF;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonr", sizeof("jsonr")-1)) {
+ formatType = F_JSONR;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"jsonfr", sizeof("jsonfr")-1)) {
+ formatType = F_JSONFR;
} else {
uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
errmsg.LogError(0, RS_RET_ERR, "invalid format type '%s' for property",
@@ -1526,6 +1569,28 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
datefmt = tplFmtUnixDate;
} else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"subseconds", sizeof("subseconds")-1)) {
datefmt = tplFmtSecFrac;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"wdayname", sizeof("wdayname")-1)) {
+ datefmt = tplFmtWDayName;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"wday", sizeof("wday")-1)) {
+ datefmt = tplFmtWDay;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"year", sizeof("year")-1)) {
+ datefmt = tplFmtYear;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"month", sizeof("month")-1)) {
+ datefmt = tplFmtMonth;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"day", sizeof("day")-1)) {
+ datefmt = tplFmtDay;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"hour", sizeof("hour")-1)) {
+ datefmt = tplFmtHour;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"minute", sizeof("minute")-1)) {
+ datefmt = tplFmtMinute;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"second", sizeof("second")-1)) {
+ datefmt = tplFmtSecond;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffshour", sizeof("tzoffshour")-1)) {
+ datefmt = tplFmtTZOffsHour;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffsmin", sizeof("tzoffsmin")-1)) {
+ datefmt = tplFmtTZOffsMin;
+ } else if(!es_strbufcmp(pvals[i].val.d.estr, (uchar*)"tzoffsdirection", sizeof("tzoffsdirection")-1)) {
+ datefmt = tplFmtTZOffsDirection;
} else {
uchar *typeStr = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
errmsg.LogError(0, RS_RET_ERR, "invalid date format '%s' for property",
@@ -1574,12 +1639,8 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
/* apply */
CHKmalloc(pTpe = tpeConstruct(pTpl));
pTpe->eEntryType = FIELD;
- 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)+1,
- cstrLen(name)-1);
- }
+ CHKiRet(msgPropDescrFill(&pTpe->data.field.msgProp, cstrGetSzStrNoNULL(name),
+ cstrLen(name)));
pTpe->data.field.options.bDropLastLF = droplastlf;
pTpe->data.field.options.bSPIffNo1stSP = spifno1stsp;
pTpe->data.field.options.bMandatory = mandatory;
@@ -1597,6 +1658,12 @@ createPropertyTpe(struct template *pTpl, struct cnfobj *o)
case F_JSONF:
pTpe->data.field.options.bJSONf = 1;
break;
+ case F_JSONR:
+ pTpe->data.field.options.bJSONr = 1;
+ break;
+ case F_JSONFR:
+ pTpe->data.field.options.bJSONfr = 1;
+ break;
}
switch(controlchr) {
case CC_NONE:
@@ -1712,8 +1779,9 @@ tplProcessCnf(struct cnfobj *o)
char *name = NULL;
uchar *tplStr = NULL;
uchar *plugin = NULL;
- es_str_t *subtree = NULL;
uchar *p;
+ msgPropDescr_t subtree;
+ sbool bHaveSubtree = 0;
enum { T_STRING, T_PLUGIN, T_LIST, T_SUBTREE }
tplType = T_STRING; /* init just to keep compiler happy: mandatory parameter */
int i;
@@ -1760,10 +1828,11 @@ tplProcessCnf(struct cnfobj *o)
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);
+ uchar *cstr;
+ cstr = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
+ CHKiRet(msgPropDescrFill(&subtree, cstr, ustrlen(cstr)));
free(cstr);
+ bHaveSubtree = 1;
}
} else if(!strcmp(pblk.descr[i].name, "plugin")) {
plugin = (uchar*) es_str2cstr(pvals[i].val.d.estr, NULL);
@@ -1806,7 +1875,7 @@ tplProcessCnf(struct cnfobj *o)
}
}
- if(subtree == NULL) {
+ if(!bHaveSubtree) {
if(tplType == T_SUBTREE) {
errmsg.LogError(0, RS_RET_ERR, "template '%s' of type subtree needs "
"subtree parameter", name);
@@ -1876,7 +1945,8 @@ tplProcessCnf(struct cnfobj *o)
break;
case T_LIST: createListTpl(pTpl, o);
break;
- case T_SUBTREE: pTpl->subtree = subtree;
+ case T_SUBTREE: memcpy(&pTpl->subtree, &subtree, sizeof(msgPropDescr_t));
+ pTpl->bHaveSubtree = 1;
break;
}
@@ -1968,9 +2038,8 @@ void tplDeleteAll(rsconf_t *conf)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- if(pTpeDel->data.field.propName != NULL)
- es_deleteStr(pTpeDel->data.field.propName);
#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
break;
}
free(pTpeDel->fieldName);
@@ -1980,8 +2049,8 @@ void tplDeleteAll(rsconf_t *conf)
pTplDel = pTpl;
pTpl = pTpl->pNext;
free(pTplDel->pszName);
- if(pTplDel->subtree != NULL)
- es_deleteStr(pTplDel->subtree);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -2028,9 +2097,8 @@ void tplDeleteNew(rsconf_t *conf)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
- if(pTpeDel->data.field.propName != NULL)
- es_deleteStr(pTpeDel->data.field.propName);
#endif
+ msgPropDescrDestruct(&pTpeDel->data.field.msgProp);
break;
}
/*dbgprintf("\n");*/
@@ -2039,8 +2107,8 @@ void tplDeleteNew(rsconf_t *conf)
pTplDel = pTpl;
pTpl = pTpl->pNext;
free(pTplDel->pszName);
- if(pTplDel->subtree != NULL)
- es_deleteStr(pTplDel->subtree);
+ if(pTplDel->bHaveSubtree)
+ msgPropDescrDestruct(&pTplDel->subtree);
free(pTplDel);
}
ENDfunc
@@ -2082,11 +2150,13 @@ void tplPrintList(rsconf_t *conf)
pTpe->data.constant.pConstant);
break;
case FIELD:
- dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.propid);
- if(pTpe->data.field.propid == PROP_CEE) {
- char *cstr = es_str2cstr(pTpe->data.field.propName, NULL);
- dbgprintf("[EE-Property: '%s'] ", cstr);
- free(cstr);
+ dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.msgProp.id);
+ if(pTpe->data.field.msgProp.id == PROP_CEE) {
+ dbgprintf("[EE-Property: '%s'] ", pTpe->data.field.msgProp.name);
+ } else if(pTpe->data.field.msgProp.id == PROP_LOCAL_VAR) {
+ dbgprintf("[Local Var: '%s'] ", pTpe->data.field.msgProp.name);
+ //} else if(pTpe->data.field.propid == PROP_GLOBAL_VAR) {
+ // dbgprintf("[Global Var: '%s'] ", pTpe->data.field.propName);
}
switch(pTpe->data.field.eDateFormat) {
case tplFmtDefault:
@@ -2152,6 +2222,12 @@ void tplPrintList(rsconf_t *conf)
if(pTpe->data.field.options.bJSONf) {
dbgprintf("[format as JSON field] ");
}
+ if(pTpe->data.field.options.bJSONr) {
+ dbgprintf("[format as JSON without re-escaping] ");
+ }
+ if(pTpe->data.field.options.bJSONfr) {
+ dbgprintf("[format as JSON field without re-escaping] ");
+ }
if(pTpe->data.field.options.bMandatory) {
dbgprintf("[mandatory field] ");
}