summaryrefslogtreecommitdiffstats
path: root/template.c
diff options
context:
space:
mode:
Diffstat (limited to 'template.c')
-rw-r--r--template.c142
1 files changed, 119 insertions, 23 deletions
diff --git a/template.c b/template.c
index f62e8453..2fc85e55 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 */
@@ -57,6 +58,7 @@ static struct cnfparamdescr cnfparamdescr[] = {
{ "type", eCmdHdlrString, 0 },
{ "string", eCmdHdlrString, 0 },
{ "plugin", eCmdHdlrString, 0 },
+ { "subtree", eCmdHdlrString, 0 },
{ "option.stdsql", eCmdHdlrBinary, 0 },
{ "option.sql", eCmdHdlrBinary, 0 },
{ "option.json", eCmdHdlrBinary, 0 }
@@ -146,7 +148,7 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
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 +160,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
@@ -232,7 +251,7 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
struct templateEntry *pTpe;
uchar **pArr;
int iArr;
- size_t propLen;
+ rs_size_t propLen;
unsigned short bMustBeFreed;
uchar *pVal;
@@ -240,11 +259,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;
@@ -277,15 +309,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 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 +339,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);
+ 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 +424,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;
@@ -723,7 +783,7 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl)
}
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;
}
@@ -1474,8 +1534,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;
@@ -1607,8 +1667,9 @@ tplProcessCnf(struct cnfobj *o)
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;
int i;
int o_sql=0, o_stdsql=0, o_json=0; /* options */
int numopts;
@@ -1631,6 +1692,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'",
@@ -1640,6 +1703,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")) {
@@ -1681,6 +1760,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 "
@@ -1738,6 +1830,8 @@ tplProcessCnf(struct cnfobj *o)
break;
case T_LIST: createListTpl(pTpl, o);
break;
+ case T_SUBTREE: pTpl->subtree = subtree;
+ break;
}
pTpl->optFormatEscape = NO_ESCAPE;
@@ -1839,8 +1933,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
@@ -1897,8 +1992,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