diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2014-10-01 17:56:20 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2014-10-01 17:56:20 +0400 |
commit | c046f7bcc92281465917e026f83fd0d38569cb06 (patch) | |
tree | 711f61cf319e171a5f41c469ef30e3298c8917f8 /template.c | |
parent | 17262528e2277c3d069c4a29ed098830d4fdbc08 (diff) | |
parent | 7ec8c6d6f9114765775ea5100af5b0b20af4502e (diff) | |
download | rsyslog-c046f7bcc92281465917e026f83fd0d38569cb06.tar.gz |
Merge branch 'master' of git://anonscm.debian.org/collab-maint/rsyslog
Conflicts:
debian/changelog
debian/patches/series
debian/rules
Diffstat (limited to 'template.c')
-rw-r--r-- | template.c | 276 |
1 files changed, 176 insertions, 100 deletions
@@ -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] "); } |