summaryrefslogtreecommitdiffstats
path: root/template.c
diff options
context:
space:
mode:
Diffstat (limited to 'template.c')
-rw-r--r--template.c157
1 files changed, 111 insertions, 46 deletions
diff --git a/template.c b/template.c
index 23251c0e..a80ac6fb 100644
--- a/template.c
+++ b/template.c
@@ -42,6 +42,7 @@
#include "obj.h"
#include "errmsg.h"
#include "strgen.h"
+#include "rsconf.h"
#include "unicode-helper.h"
/* static data */
@@ -54,17 +55,6 @@ DEFobjCurrIf(regexp)
static int bFirstRegexpErrmsg = 1; /**< did we already do a "can't load regexp" error message? */
#endif
-static struct template *tplRoot = NULL; /* the root of the template list */
-static struct template *tplLast = NULL; /* points to the last element of the template list */
-static struct template *tplLastStatic = NULL; /* last static element of the template list */
-
-enum {
- NO_ESCAPE = 0,
- SQL_ESCAPE,
- STDSQL_ESCAPE,
- JSON_ESCAPE,
-};
-
/* helper to tplToString and strgen's, extends buffer */
#define ALLOC_INC 128
rsRetVal
@@ -126,7 +116,8 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
iLenVal = pTpe->data.constant.iLenConstant;
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
- pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid, &iLenVal, &bMustBeFreed);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
+ pTpe->data.field.propName, &iLenVal, &bMustBeFreed);
/* 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,
@@ -207,7 +198,8 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
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, &propLen, &bMustBeFreed);
+ pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
+ pTpe->data.field.propName, &propLen, &bMustBeFreed);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[iArr] = pVal; /* ... so we can use it! */
} else {
@@ -377,7 +369,8 @@ struct templateEntry* tpeConstruct(struct template *pTpl)
/* Constructs a template list object. Returns pointer to it
* or NULL (if it fails).
*/
-struct template* tplConstruct(void)
+static struct template*
+tplConstruct(rsconf_t *conf)
{
struct template *pTpl;
if((pTpl = calloc(1, sizeof(struct template))) == NULL)
@@ -386,12 +379,12 @@ struct template* tplConstruct(void)
/* basic initialisation is done via calloc() - need to
* initialize only values != 0. */
- if(tplLast == NULL) {
+ if(conf->templates.last == NULL) {
/* we are the first element! */
- tplRoot = tplLast = pTpl;
+ conf->templates.root = conf->templates.last = pTpl;
} else {
- tplLast->pNext = pTpl;
- tplLast = pTpl;
+ conf->templates.last->pNext = pTpl;
+ conf->templates.last = pTpl;
}
return(pTpl);
@@ -505,18 +498,18 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
p = *pp;
- while(*p && *p != '%') {
+ while(*p && *p != '%' && *p != ':') {
/* outer loop - until end of options */
i = 0;
while((i < sizeof(Buf) / sizeof(char)) &&
- *p && *p != '%' && *p != ',') {
+ *p && *p != '%' && *p != ':' && *p != ',') {
/* inner loop - until end of ONE option */
Buf[i++] = tolower((int)*p);
++p;
}
Buf[i] = '\0'; /* terminate */
/* check if we need to skip oversize option */
- while(*p && *p != '%' && *p != ',')
+ while(*p && *p != '%' && *p != ':' && *p != ',')
++p; /* just skip */
if(*p == ',')
++p; /* eat ',' */
@@ -533,6 +526,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
pTpe->data.field.eDateFormat = tplFmtRFC3164BuggyDate;
} else if(!strcmp((char*)Buf, "date-rfc3339")) {
pTpe->data.field.eDateFormat = tplFmtRFC3339Date;
+ } else if(!strcmp((char*)Buf, "date-unixtimestamp")) {
+ pTpe->data.field.eDateFormat = tplFmtUnixDate;
} else if(!strcmp((char*)Buf, "date-subseconds")) {
pTpe->data.field.eDateFormat = tplFmtSecFrac;
} else if(!strcmp((char*)Buf, "lowercase")) {
@@ -554,7 +549,26 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
} else if(!strcmp((char*)Buf, "secpath-replace")) {
pTpe->data.field.options.bSecPathReplace = 1;
} else if(!strcmp((char*)Buf, "csv")) {
- pTpe->data.field.options.bCSV = 1;
+ if(pTpe->data.field.options.bJSON || pTpe->data.field.options.bJSONf) {
+ errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, 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) {
+ errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, 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) {
+ errmsg.LogError(0, NO_ERRCODE, "error: can only specify "
+ "one option out of (json, jsonf, csv) - jsonf ignored");
+ } else {
+ pTpe->data.field.options.bJSONf = 1;
+ }
} else {
dbgprintf("Invalid field option '%s' specified - ignored.\n", Buf);
}
@@ -571,7 +585,8 @@ static void doOptions(unsigned char **pp, struct templateEntry *pTpe)
static int do_Parameter(unsigned char **pp, struct template *pTpl)
{
unsigned char *p;
- cstr_t *pStrB;
+ cstr_t *pStrProp;
+ cstr_t *pStrField = NULL;
struct templateEntry *pTpe;
int iNum; /* to compute numbers */
#ifdef FEATURE_REGEXP
@@ -588,7 +603,7 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
p = (unsigned char*) *pp;
- if(cstrConstruct(&pStrB) != RS_RET_OK)
+ if(cstrConstruct(&pStrProp) != RS_RET_OK)
return 1;
if((pTpe = tpeConstruct(pTpl)) == NULL) {
@@ -599,18 +614,24 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
pTpe->eEntryType = FIELD;
while(*p && *p != '%' && *p != ':') {
- cstrAppendChar(pStrB, tolower(*p));
+ cstrAppendChar(pStrProp, tolower(*p));
++p; /* do NOT do this in tolower()! */
}
/* got the name */
- cstrFinalize(pStrB);
+ cstrFinalize(pStrProp);
- if(propNameToID(pStrB, &pTpe->data.field.propid) != RS_RET_OK) {
- cstrDestruct(&pStrB);
+ if(propNameToID(pStrProp, &pTpe->data.field.propid) != RS_RET_OK) {
+ cstrDestruct(&pStrProp);
return 1;
}
- cstrDestruct(&pStrB); /* no longer needed, now use ID */
+ 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) {
+ cstrDestruct(&pStrProp);
+ return 1;
+ }
+ }
/* Check frompos, if it has an R, then topos should be a regex */
if(*p == ':') {
@@ -889,6 +910,34 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
doOptions(&p, pTpe);
}
+ /* check field name */
+ if(*p == ':') {
+ ++p; /* eat ':' */
+ if(cstrConstruct(&pStrField) != RS_RET_OK)
+ return 1;
+ while(*p != ':' && *p != '%' && *p != '\0') {
+ cstrAppendChar(pStrField, *p);
+ ++p;
+ }
+ cstrFinalize(pStrField);
+ }
+
+ /* save field name - if none was given, use the property name instead */
+ if(pStrField == NULL) {
+ if((pTpe->data.field.fieldName =
+ es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrProp), cstrLen(pStrProp))) == NULL) {
+ return 1;
+ }
+ } else {
+ if((pTpe->data.field.fieldName =
+ es_newStrFromCStr((char*)cstrGetSzStrNoNULL(pStrField), cstrLen(pStrField))) == NULL) {
+ return 1;
+ }
+ cstrDestruct(&pStrField);
+ }
+
+ cstrDestruct(&pStrProp);
+
if(*p) ++p; /* eat '%' */
*pp = p;
@@ -903,14 +952,13 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
static rsRetVal
tplAddTplMod(struct template *pTpl, uchar** ppRestOfConfLine)
{
- uchar *pSrc, *pDst;
+ uchar *pSrc;
uchar szMod[2048];
unsigned lenMod;
strgen_t *pStrgen;
DEFiRet;
pSrc = *ppRestOfConfLine;
- pDst = szMod;
lenMod = 0;
while(*pSrc && !isspace(*pSrc) && lenMod < sizeof(szMod) - 1) {
szMod[lenMod] = *pSrc++;
@@ -948,7 +996,7 @@ finalize_it:
/* Add a new template line
* returns pointer to new object if it succeeds, NULL otherwise.
*/
-struct template *tplAddLine(char* pName, uchar** ppRestOfConfLine)
+struct template *tplAddLine(rsconf_t *conf, char* pName, uchar** ppRestOfConfLine)
{
struct template *pTpl;
unsigned char *p;
@@ -960,7 +1008,7 @@ struct template *tplAddLine(char* pName, uchar** ppRestOfConfLine)
assert(pName != NULL);
assert(ppRestOfConfLine != NULL);
- if((pTpl = tplConstruct()) == NULL)
+ if((pTpl = tplConstruct(conf)) == NULL)
return NULL;
pTpl->iLenName = strlen(pName);
@@ -1089,13 +1137,13 @@ struct template *tplAddLine(char* pName, uchar** ppRestOfConfLine)
* NULL otherwise.
* rgerhards 2004-11-17
*/
-struct template *tplFind(char *pName, int iLenName)
+struct template *tplFind(rsconf_t *conf, char *pName, int iLenName)
{
struct template *pTpl;
assert(pName != NULL);
- pTpl = tplRoot;
+ pTpl = conf->templates.root;
while(pTpl != NULL &&
!(pTpl->iLenName == iLenName &&
!strcmp(pTpl->pszName, pName)
@@ -1113,13 +1161,13 @@ struct template *tplFind(char *pName, int iLenName)
* "normal" debugging. Uncomment them, if they are needed.
* rgerhards, 2007-07-05
*/
-void tplDeleteAll(void)
+void tplDeleteAll(rsconf_t *conf)
{
struct template *pTpl, *pTplDel;
struct templateEntry *pTpe, *pTpeDel;
BEGINfunc
- pTpl = tplRoot;
+ pTpl = conf->templates.root;
while(pTpl != NULL) {
/* dbgprintf("Delete Template: Name='%s'\n ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);*/
pTpe = pTpl->pEntryRoot;
@@ -1144,6 +1192,10 @@ void tplDeleteAll(void)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
+ if(pTpeDel->data.field.propName != NULL)
+ es_deleteStr(pTpeDel->data.field.propName);
+ if(pTpeDel->data.field.fieldName != NULL)
+ es_deleteStr(pTpeDel->data.field.fieldName);
#endif
break;
}
@@ -1163,19 +1215,19 @@ void tplDeleteAll(void)
/* Destroy all templates obtained from conf file
* preserving hardcoded ones. This is called from init().
*/
-void tplDeleteNew(void)
+void tplDeleteNew(rsconf_t *conf)
{
struct template *pTpl, *pTplDel;
struct templateEntry *pTpe, *pTpeDel;
BEGINfunc
- if(tplRoot == NULL || tplLastStatic == NULL)
+ if(conf->templates.root == NULL || conf->templates.lastStatic == NULL)
return;
- pTpl = tplLastStatic->pNext;
- tplLastStatic->pNext = NULL;
- tplLast = tplLastStatic;
+ pTpl = conf->templates.lastStatic->pNext;
+ conf->templates.lastStatic->pNext = NULL;
+ conf->templates.last = conf->templates.lastStatic;
while(pTpl != NULL) {
/* dbgprintf("Delete Template: Name='%s'\n ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);*/
pTpe = pTpl->pEntryRoot;
@@ -1200,6 +1252,8 @@ void tplDeleteNew(void)
regexp.regfree(&(pTpeDel->data.field.re));
}
}
+ if(pTpeDel->data.field.propName != NULL)
+ es_deleteStr(pTpeDel->data.field.propName);
#endif
break;
}
@@ -1216,20 +1270,20 @@ void tplDeleteNew(void)
}
/* Store the pointer to the last hardcoded teplate */
-void tplLastStaticInit(struct template *tpl)
+void tplLastStaticInit(rsconf_t *conf, struct template *tpl)
{
- tplLastStatic = tpl;
+ conf->templates.lastStatic = tpl;
}
/* Print the template structure. This is more or less a
* debug or test aid, but anyhow I think it's worth it...
*/
-void tplPrintList(void)
+void tplPrintList(rsconf_t *conf)
{
struct template *pTpl;
struct templateEntry *pTpe;
- pTpl = tplRoot;
+ pTpl = conf->templates.root;
while(pTpl != NULL) {
dbgprintf("Template: Name='%s' ", pTpl->pszName == NULL? "NULL" : pTpl->pszName);
if(pTpl->optFormatEscape == SQL_ESCAPE)
@@ -1252,6 +1306,11 @@ void tplPrintList(void)
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);
+ }
switch(pTpe->data.field.eDateFormat) {
case tplFmtDefault:
break;
@@ -1267,6 +1326,9 @@ void tplPrintList(void)
case tplFmtRFC3339Date:
dbgprintf("[Format as RFC3339-Date] ");
break;
+ case tplFmtUnixDate:
+ dbgprintf("[Format as Unix timestamp] ");
+ break;
default:
dbgprintf("[INVALID eDateFormat %d] ", pTpe->data.field.eDateFormat);
}
@@ -1301,6 +1363,9 @@ void tplPrintList(void)
if(pTpe->data.field.options.bCSV) {
dbgprintf("[format as CSV (RFC4180)]");
}
+ if(pTpe->data.field.options.bJSON) {
+ dbgprintf("[format as JSON");
+ }
if(pTpe->data.field.options.bDropLastLF) {
dbgprintf("[drop last LF in msg] ");
}