/*************************************************************************** $RCSfile: msgengine.c,v $ ------------------- cvs : $Id: msgengine.c,v 1.74 2005/03/25 17:35:28 aquamaniac Exp $ begin : Fri Jul 04 2003 copyright : (C) 2003 by Martin Preuss email : martin@libchipcard.de *************************************************************************** * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * * MA 02111-1307 USA * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #define DISABLE_DEBUGLOG #include #include #include #include #include #include #include #include #include #include #include #include GWEN_INHERIT_FUNCTIONS(GWEN_MSGENGINE) GWEN_MSGENGINE *GWEN_MsgEngine_new(){ GWEN_MSGENGINE *e; GWEN_NEW_OBJECT(GWEN_MSGENGINE, e); GWEN_INHERIT_INIT(GWEN_MSGENGINE, e); e->charsToEscape=strdup(GWEN_MSGENGINE_CHARSTOESCAPE); e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS); e->globalValues=GWEN_DB_Group_new("globalvalues"); e->escapeChar='\\'; e->usage=1; return e; } void GWEN_MsgEngine_free(GWEN_MSGENGINE *e){ if (e) { assert(e->usage); if (--(e->usage)==0) { GWEN_INHERIT_FINI(GWEN_MSGENGINE, e); if (e->inheritorData && e->freeDataPtr) e->freeDataPtr(e); if (e->ownDefs) GWEN_XMLNode_free(e->defs); free(e->charsToEscape); free(e->delimiters); GWEN_DB_Group_free(e->globalValues); if (e->trustInfos) { /* free trustInfos */ GWEN_MSGENGINE_TRUSTEDDATA *td, *tdn; td=e->trustInfos; while(td) { tdn=td->next; GWEN_MsgEngine_TrustedData_free(td); td=tdn; } /* while */ } GWEN_FREE_OBJECT(e); } } } void GWEN_MsgEngine_Attach(GWEN_MSGENGINE *e){ assert(e); e->usage++; } void GWEN_MsgEngine_SetEscapeChar(GWEN_MSGENGINE *e, char c){ assert(e); e->escapeChar=c; } char GWEN_MsgEngine_GetEscapeChar(GWEN_MSGENGINE *e){ assert(e); return e->escapeChar; } void GWEN_MsgEngine_SetCharsToEscape(GWEN_MSGENGINE *e, const char *c){ assert(e); free(e->charsToEscape); e->charsToEscape=strdup(c); } const char *GWEN_MsgEngine_GetCharsToEscape(GWEN_MSGENGINE *e){ assert(e); return e->charsToEscape; } void GWEN_MsgEngine_SetDelimiters(GWEN_MSGENGINE *e, const char *s){ assert(e); free(e->delimiters); if (s) e->delimiters=strdup(s); else e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS); } const char *GWEN_MsgEngine_GetDelimiters(GWEN_MSGENGINE *e){ assert(e); return e->delimiters; } void GWEN_MsgEngine_SetMode(GWEN_MSGENGINE *e, const char *mode){ GWEN_DB_NODE *db; assert(e); db=GWEN_MsgEngine__GetGlobalValues(e); if (mode) GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "engine/secmode", mode); else GWEN_DB_DeleteVar(db, "engine/secmode"); } const char *GWEN_MsgEngine_GetMode(GWEN_MSGENGINE *e){ GWEN_DB_NODE *db; assert(e); db=GWEN_MsgEngine__GetGlobalValues(e); return GWEN_DB_GetCharValue(db, "engine/secmode", 0, 0); } GWEN_DB_NODE *GWEN_MsgEngine__GetGlobalValues(GWEN_MSGENGINE *e){ GWEN_DB_NODE *globalValues; assert(e); if (e->getGlobalValuesPtr) { globalValues=e->getGlobalValuesPtr(e); if (!globalValues) globalValues=e->globalValues; } else { globalValues=e->globalValues; } assert(globalValues); return globalValues; } unsigned int GWEN_MsgEngine_GetProtocolVersion(GWEN_MSGENGINE *e){ GWEN_DB_NODE *db; assert(e); db=GWEN_MsgEngine__GetGlobalValues(e); return GWEN_DB_GetIntValue(db, "engine/pversion", 0, 0); } void GWEN_MsgEngine_SetProtocolVersion(GWEN_MSGENGINE *e, unsigned int p){ GWEN_DB_NODE *db; assert(e); db=GWEN_MsgEngine__GetGlobalValues(e); GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "engine/pversion", p); } GWEN_XMLNODE *GWEN_MsgEngine_GetDefinitions(GWEN_MSGENGINE *e){ assert(e); return e->defs; } void GWEN_MsgEngine_SetDefinitions(GWEN_MSGENGINE *e, GWEN_XMLNODE *n, int take){ assert(e); if (e->ownDefs) GWEN_XMLNode_free(e->defs); e->defs=n; e->ownDefs=take; } void GWEN_MsgEngine_SetGetGlobalValuesFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_GETGLOBALVALUES_PTR p){ assert(e); e->getGlobalValuesPtr=p; } GWEN_MSGENGINE_GETGLOBALVALUES_PTR GWEN_MsgEngine_GetGetGlobalValuesFunction(GWEN_MSGENGINE *e){ assert(e); return e->getGlobalValuesPtr; } void GWEN_MsgEngine_SetTypeReadFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_TYPEREAD_PTR p){ assert(e); e->typeReadPtr=p; } GWEN_MSGENGINE_TYPEREAD_PTR GWEN_MsgEngine_GetTypeReadFunction(GWEN_MSGENGINE *e){ assert(e); return e->typeReadPtr; } void GWEN_MsgEngine_SetTypeWriteFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_TYPEWRITE_PTR p){ assert(e); e->typeWritePtr=p; } GWEN_MSGENGINE_TYPEWRITE_PTR GWEN_MsgEngine_GetTypeWriteFunction(GWEN_MSGENGINE *e){ assert(e); return e->typeWritePtr; } void GWEN_MsgEngine_SetTypeCheckFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_TYPECHECK_PTR p){ assert(e); e->typeCheckPtr=p; } GWEN_MSGENGINE_TYPECHECK_PTR GWEN_MsgEngine_GetTypeCheckFunction(GWEN_MSGENGINE *e){ assert(e); return e->typeCheckPtr; } void GWEN_MsgEngine_SetBinTypeReadFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_BINTYPEREAD_PTR p){ assert(e); e->binTypeReadPtr=p; } GWEN_MSGENGINE_BINTYPEREAD_PTR GWEN_MsgEngine_GetBinTypeReadFunction(GWEN_MSGENGINE *e){ assert(e); return e->binTypeReadPtr; } void GWEN_MsgEngine_SetBinTypeWriteFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_BINTYPEWRITE_PTR p){ assert(e); e->binTypeWritePtr=p; } GWEN_MSGENGINE_BINTYPEWRITE_PTR GWEN_MsgEngine_GetBinTypeWriteFunction(GWEN_MSGENGINE *e){ assert(e); return e->binTypeWritePtr; } void GWEN_MsgEngine_SetGetCharValueFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_GETCHARVALUE_PTR p){ assert(e); e->getCharValuePtr=p; } void GWEN_MsgEngine_SetGetIntValueFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_GETINTVALUE_PTR p){ assert(e); e->getIntValuePtr=p; } void GWEN_MsgEngine_SetFreeDataFunction(GWEN_MSGENGINE *e, GWEN_MSGENGINE_FREEDATA_PTR p){ assert(e); DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetFreeDataFunction: Deprecated"); e->freeDataPtr=p; } void *GWEN_MsgEngine_GetInheritorData(const GWEN_MSGENGINE *e){ assert(e); return e->inheritorData; } void GWEN_MsgEngine_SetInheritorData(GWEN_MSGENGINE *e, void *d){ assert(e); DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetInheritorData: Deprecated"); if (e->inheritorData && e->freeDataPtr) e->freeDataPtr(e); e->inheritorData=d; } int GWEN_MsgEngine__WriteValue(GWEN_MSGENGINE *e, GWEN_BUFFER *gbuf, GWEN_BUFFER *data, GWEN_XMLNODE *node) { unsigned int minsize; unsigned int maxsize; unsigned int fixSize; unsigned int startPos; int filler; const char *type; const char *name; int rv; /* get some sizes */ minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); fixSize=atoi(GWEN_XMLNode_GetProperty(node, "size","0")); filler=atoi(GWEN_XMLNode_GetProperty(node, "filler","0")); type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); name=GWEN_XMLNode_GetProperty(node, "name",""); startPos=GWEN_Buffer_GetPos(gbuf); /* check sizes */ if (minsize && GWEN_Buffer_GetUsedBytes(data)maxsize) { DBG_ERROR(GWEN_LOGDOMAIN, "Data too long (maxsize is %d)", maxsize); return -1; } rv=1; if (e->typeWritePtr) { rv=e->typeWritePtr(e, gbuf, data, node); } if (rv==-1) { DBG_INFO(GWEN_LOGDOMAIN, "External type writing failed"); return -1; } else if (rv==1) { int i; /* type not handled externally, so handle it myself */ if (strcasecmp(type, "bin")==0) { DBG_DEBUG(GWEN_LOGDOMAIN, "Writing binary data (%d bytes added to %d bytes)", GWEN_Buffer_GetUsedBytes(data), GWEN_Buffer_GetUsedBytes(gbuf)); if (GWEN_Buffer_AllocRoom(gbuf, 10+GWEN_Buffer_GetUsedBytes(data))) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } sprintf(GWEN_Buffer_GetPosPointer(gbuf), "@%d@", GWEN_Buffer_GetUsedBytes(data)); i=strlen(GWEN_Buffer_GetPosPointer(gbuf)); GWEN_Buffer_IncrementPos(gbuf, i); GWEN_Buffer_AdjustUsedBytes(gbuf); GWEN_Buffer_AppendBuffer(gbuf, data); } /* if type is "bin" */ else if (strcasecmp(type, "num")==0) { int num; unsigned int len; unsigned int lj; num=atoi(GWEN_Buffer_GetPosPointer(data)); len=strlen(GWEN_Buffer_GetPosPointer(data)); if (atoi(GWEN_XMLNode_GetProperty(node, "leftfill","0"))) { if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } /* fill left */ for (lj=0; lj<(maxsize-len); lj++) GWEN_Buffer_AppendByte(gbuf, '0'); /* write value */ for (lj=0; ljescapeChar) needsEscape=1; else { if (e->charsToEscape) if (strchr(e->charsToEscape, c)) needsEscape=1; } if (needsEscape) { /* write escape char */ if (GWEN_Buffer_AppendByte(gbuf, e->escapeChar)) { return -1; } } if (GWEN_Buffer_AppendByte(gbuf, c)) { return -1; } } p++; pcount++; } /* while */ if (pcountfixSize) { DBG_ERROR(GWEN_LOGDOMAIN, "Data too long (size is %d, fixed size is %d)", bs, fixSize); return -1; } for (j=bs; jtypeCheckPtr) { GWEN_DB_VALUETYPE vt; vt=e->typeCheckPtr(e, type); if (vt!=GWEN_DB_VALUETYPE_UNKNOWN) { if (vt==GWEN_DB_VALUETYPE_CHAR) return 1; } } return (strcasecmp(type, "alpha")==0) || (strcasecmp(type, "ascii")==0) || (strcasecmp(type, "an")==0) || (strcasecmp(type, "float")==0); } int GWEN_MsgEngine__IsIntTyp(GWEN_MSGENGINE *e, const char *type) { if (e->typeCheckPtr) { GWEN_DB_VALUETYPE vt; vt=e->typeCheckPtr(e, type); if (vt!=GWEN_DB_VALUETYPE_UNKNOWN) { if (vt==GWEN_DB_VALUETYPE_INT) return 1; } } return (strcasecmp(type, "num")==0); } int GWEN_MsgEngine__IsBinTyp(GWEN_MSGENGINE *e, const char *type) { if (e->typeCheckPtr) { GWEN_DB_VALUETYPE vt; vt=e->typeCheckPtr(e, type); if (vt!=GWEN_DB_VALUETYPE_UNKNOWN) { if (vt==GWEN_DB_VALUETYPE_BIN) return 1; } } return (strcasecmp(type, "bin")==0); } int GWEN_MsgEngine__GetInline(GWEN_MSGENGINE *e, GWEN_XMLNODE *node, GWEN_BUFFER *mbuf) { /* get data from within the XML node */ GWEN_XMLNODE *n; const char *type; type=GWEN_XMLNode_GetProperty(node, "type", "ascii"); DBG_DEBUG(GWEN_LOGDOMAIN, "Getting data of type \"%s\" from within XML file", type); n=GWEN_XMLNode_GetFirstData(node); if (!n) { DBG_DEBUG(GWEN_LOGDOMAIN, "No child"); return 1; } if (GWEN_MsgEngine__IsBinTyp(e, type)) { const char *dp; unsigned int dplen; const char *stype; stype=GWEN_XMLNode_GetProperty(node, "storedAs", type); if (GWEN_MsgEngine__IsBinTyp(e, stype)) { dp=GWEN_XMLNode_GetData(n); dplen=strlen(dp); if (GWEN_Text_FromHexBuffer(dp, mbuf)) { DBG_INFO(GWEN_LOGDOMAIN, "here"); return -1; } } /* if stored as bin */ else { /* stored as char */ GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n)); } } /* if binType */ else { GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n)); } return 0; } int GWEN_MsgEngine__WriteElement(GWEN_MSGENGINE *e, GWEN_BUFFER *gbuf, GWEN_XMLNODE *node, GWEN_XMLNODE *rnode, GWEN_DB_NODE *gr, int loopNr, int isOptional, GWEN_XMLNODE_PATH *nodePath) { const char *name; const char *type; unsigned int minsize; unsigned int maxsize; char numbuffer[256]; const char *pdata; unsigned int datasize; GWEN_BUFFER *data; GWEN_BUFFER *tdata; int handled; pdata=0; handled=0; data=0; tdata=0; /* get type */ type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); DBG_DEBUG(GWEN_LOGDOMAIN, "Type is \"%s\"", type); /* get some sizes */ minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); if (e->binTypeWritePtr && GWEN_MsgEngine__IsBinTyp(e, type) && atoi(GWEN_XMLNode_GetProperty(node, "writebin", "1"))) { int rv; data=GWEN_Buffer_new(0, 64, 0, 1); rv=e->binTypeWritePtr(e, node, gr, data); if (rv==-1) { /* error */ DBG_INFO(GWEN_LOGDOMAIN, "called from here"); return -1; } else if (rv==0) { handled=1; } else if (rv==1) { GWEN_Buffer_free(data); data=0; } } if (!handled) { /* get name */ name=GWEN_XMLNode_GetProperty(node, "name", 0); if (!name) { int rv; /* get data from within the XML node */ tdata=GWEN_Buffer_new(0, 32, 0, 1); GWEN_Buffer_SetStep(tdata, 256); rv=GWEN_MsgEngine__GetInline(e, node, tdata); if (rv==0) { pdata=GWEN_Buffer_GetStart(tdata); datasize=GWEN_Buffer_GetUsedBytes(tdata); } else { GWEN_Buffer_free(tdata); tdata=0; pdata=""; datasize=0; } } /* if (!name) */ else { const char *nptr; DBG_DEBUG(GWEN_LOGDOMAIN, "Name provided (%s), loop is %d", name, loopNr); nptr=name; if (gr) { GWEN_DB_VALUETYPE vt; int idata; /* Variable type of DB takes precedence */ vt=GWEN_DB_GetValueTypeByPath(gr, nptr, loopNr); if (vt==GWEN_DB_VALUETYPE_UNKNOWN) { if (GWEN_MsgEngine__IsCharTyp(e, type)) vt=GWEN_DB_VALUETYPE_CHAR; else if (GWEN_MsgEngine__IsIntTyp(e, type)) vt=GWEN_DB_VALUETYPE_INT; else if (GWEN_MsgEngine__IsBinTyp(e, type)) vt=GWEN_DB_VALUETYPE_BIN; else { DBG_INFO(GWEN_LOGDOMAIN, "Unable to determine parameter " "type (%s), assuming \"char\" for this matter", type); vt=GWEN_DB_VALUETYPE_CHAR; } } /* get the value of the given var from the db */ switch(vt) { case GWEN_DB_VALUETYPE_CHAR: DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is char", name); pdata=GWEN_DB_GetCharValue(gr, nptr, loopNr, 0); if (pdata) { DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %s", nptr, pdata); datasize=strlen(pdata); } else datasize=0; break; case GWEN_DB_VALUETYPE_INT: DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is int", name); if (GWEN_DB_ValueExists(gr, nptr, loopNr)) { idata=GWEN_DB_GetIntValue(gr, nptr, loopNr, 0); if (-1==GWEN_Text_NumToString(idata, numbuffer, sizeof(numbuffer),0)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); GWEN_Buffer_free(data); return -1; } DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %d", nptr, idata); pdata=numbuffer; datasize=strlen(numbuffer); } break; case GWEN_DB_VALUETYPE_BIN: DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is bin", name); pdata=GWEN_DB_GetBinValue(gr, nptr, loopNr, 0, 0, &datasize); break; default: DBG_WARN(GWEN_LOGDOMAIN, "Unsupported parameter type (%d)", vt); break; } /* switch vt */ } /* if gr */ if (!pdata) { GWEN_XMLNODE_PATH *copyOfNodePath; copyOfNodePath=GWEN_XMLNode_Path_dup(nodePath); /* still no data, try to get it from the XML file */ DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\"", name); pdata=GWEN_MsgEngine__SearchForValue(e, node, copyOfNodePath, nptr, &datasize); GWEN_XMLNode_Path_free(copyOfNodePath); if (pdata) { DBG_DEBUG(GWEN_LOGDOMAIN, "Found value of \"%s\"", name); } } if (!pdata) { int rv; /* get data from within the XML node */ tdata=GWEN_Buffer_new(0, 32, 0, 1); GWEN_Buffer_SetStep(tdata, 256); rv=GWEN_MsgEngine__GetInline(e, node, tdata); if (rv==0) { pdata=GWEN_Buffer_GetStart(tdata); datasize=GWEN_Buffer_GetUsedBytes(tdata); } else { GWEN_Buffer_free(tdata); tdata=0; } } if (pdata==0) { if (isOptional) { DBG_INFO(GWEN_LOGDOMAIN, "Value not found, omitting element \"%s[%d]\"", name, loopNr); GWEN_Buffer_free(data); return 1; } else { DBG_ERROR(GWEN_LOGDOMAIN, "Value for element \"%s[%d]\" (mode \"%s\") not found", name, loopNr, GWEN_MsgEngine_GetMode(e)); GWEN_DB_Dump(gr, stderr, 4); GWEN_Buffer_free(data); return -1; } } } if (!data) data=GWEN_Buffer_new((char*)pdata, datasize, datasize, 0 /* dont take ownership*/ ); } /* write value */ if (GWEN_MsgEngine__WriteValue(e, gbuf, data, node)!=0) { DBG_INFO(GWEN_LOGDOMAIN, "Could not write value"); GWEN_Buffer_free(data); GWEN_Buffer_free(tdata); return -1; } GWEN_Buffer_free(data); GWEN_Buffer_free(tdata); return 0; } GWEN_XMLNODE *GWEN_MsgEngine_FindGroupByProperty(GWEN_MSGENGINE *e, const char *pname, int version, const char *pvalue) { return GWEN_MsgEngine_FindNodeByProperty(e, "GROUP", pname, version, pvalue); } GWEN_XMLNODE *GWEN_MsgEngine_FindNodeByProperty(GWEN_MSGENGINE *e, const char *t, const char *pname, int version, const char *pvalue) { GWEN_XMLNODE *n; const char *p; int i; const char *mode; unsigned int proto; char buffer[256]; if ((strlen(t)+4)>sizeof(buffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long."); return 0; } mode=GWEN_MsgEngine_GetMode(e); proto=GWEN_MsgEngine_GetProtocolVersion(e); if (!e->defs) { DBG_INFO(GWEN_LOGDOMAIN, "No definitions available"); return 0; } n=e->defs; n=GWEN_XMLNode_GetChild(n); /* find type+"S" */ strcpy(buffer, t); strcat(buffer,"S"); while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, buffer)==0) break; } n=GWEN_XMLNode_Next(n); } /* while */ if (!n) { DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t); return 0; } /* find approppriate group definition */ if (!mode) mode=""; n=GWEN_XMLNode_GetChild(n); if (!n) { DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer); return 0; } /* find type+"def" */ strcpy(buffer, t); strcat(buffer,"def"); while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, buffer)==0) { p=GWEN_XMLNode_GetProperty(n, pname,""); if (strcasecmp(p, pvalue)==0) { i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0")); if (proto==0 || (int)proto==i || i==0) { i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0")); if (version==0 || version==i) { p=GWEN_XMLNode_GetProperty(n, "mode",""); if (strcasecmp(p, mode)==0 || !*p) { DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found", pname, pvalue); return n; } } } } } } n=GWEN_XMLNode_Next(n); } /* while */ DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found", pname, pvalue, version); return 0; } const char *GWEN_MsgEngine__TransformValue(GWEN_MSGENGINE *e, const char *pvalue, GWEN_XMLNODE *node, GWEN_XMLNODE *dnode, unsigned int *datasize) { const char *p; static char pbuffer[256]; GWEN_DB_NODE *globalValues; globalValues=GWEN_MsgEngine__GetGlobalValues(e); assert(globalValues); if (pvalue) { DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming value \"%s\"", pvalue); /* check whether the value is a property */ p=pvalue; while (*p && isspace((int)*p)) p++; if (*p=='$' || *p=='+') { /* global property */ int incr; incr=(*p=='+'); p++; DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p); if (incr) { int z; z=GWEN_DB_GetIntValue(globalValues, p, 0, 0); DBG_DEBUG(GWEN_LOGDOMAIN, "Incrementing global property \"%s\" (%d)", p, z); if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); return 0; } z++; DBG_DEBUG(GWEN_LOGDOMAIN, "Setting global property \"%s\"=%d", p, z); GWEN_DB_SetIntValue(globalValues, GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_OVERWRITE_VARS, p, z); pvalue=pbuffer; *datasize=strlen(pvalue); } else { int z; GWEN_DB_VALUETYPE vt; const char *type = "should_be_known"; /* default value; otherwise the compiler issues a warning */ DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p); vt=GWEN_DB_GetVariableType(globalValues, p); if (vt==GWEN_DB_VALUETYPE_UNKNOWN) { if (!GWEN_DB_VariableExists(globalValues, p)) { DBG_ERROR(GWEN_LOGDOMAIN, "Unable to determine type of \"%s\"", p); return 0; } type=GWEN_XMLNode_GetProperty(dnode, "type", "ascii"); if (GWEN_MsgEngine__IsCharTyp(e, type)) vt=GWEN_DB_VALUETYPE_CHAR; else if (GWEN_MsgEngine__IsIntTyp(e, type)) vt=GWEN_DB_VALUETYPE_INT; else if (GWEN_MsgEngine__IsBinTyp(e, type)) vt=GWEN_DB_VALUETYPE_BIN; else { DBG_ERROR(GWEN_LOGDOMAIN, "Unable to determine type of \"%s\" (xml)", p); return 0; } } switch(vt) { case GWEN_DB_VALUETYPE_CHAR: pvalue=GWEN_DB_GetCharValue(globalValues, p, 0, ""); *datasize=strlen(pvalue); break; case GWEN_DB_VALUETYPE_INT: z=GWEN_DB_GetIntValue(globalValues, p, 0, 0); if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); return 0; } pvalue=pbuffer; *datasize=strlen(pvalue); break; case GWEN_DB_VALUETYPE_BIN: pvalue=GWEN_DB_GetBinValue(globalValues, p, 0, 0,0, datasize); break; default: DBG_ERROR(GWEN_LOGDOMAIN,"Unknown type %s", type); return 0; } /* switch */ } DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed"); } else if (*p=='%') { /* local property */ p++; DBG_DEBUG(GWEN_LOGDOMAIN, "Getting property \"%s\"", p); pvalue=GWEN_XMLNode_GetProperty(node, p, 0); if (pvalue) { *datasize=strlen(pvalue); DBG_DEBUG(GWEN_LOGDOMAIN, "Transformed value \"%s\"", pvalue); } else *datasize=0; } else if (*p=='?') { GWEN_DB_VALUETYPE vt; int z; const char *dtype; /* get type */ dtype=GWEN_XMLNode_GetProperty(dnode, "type","ASCII"); /* program variable accessable via callback */ p++; DBG_DEBUG(GWEN_LOGDOMAIN, "Getting program variable \"%s\"", p); pvalue=0; if (GWEN_MsgEngine__IsCharTyp(e, dtype)) vt=GWEN_DB_VALUETYPE_CHAR; else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) vt=GWEN_DB_VALUETYPE_INT; else { vt=GWEN_DB_VALUETYPE_CHAR; } switch(vt) { case GWEN_DB_VALUETYPE_CHAR: if (e->getCharValuePtr) { pvalue=e->getCharValuePtr(e, p, 0); if (pvalue) *datasize=strlen(pvalue); } break; case GWEN_DB_VALUETYPE_INT: if (e->getIntValuePtr) { z=e->getIntValuePtr(e, p, 0); if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) { DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string"); return 0; } pvalue=pbuffer; *datasize=strlen(pvalue); } else { DBG_NOTICE(GWEN_LOGDOMAIN, "Callback for getIntValue not set"); } break; default: DBG_ERROR(GWEN_LOGDOMAIN,"Unhandled type %s", dtype); return 0; } /* switch */ DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed"); } else { *datasize=strlen(pvalue); } } return pvalue; } const char *GWEN_MsgEngine_SearchForProperty(GWEN_XMLNODE *node, GWEN_XMLNODE *refnode, const char *name, int topDown) { const char *pvalue; GWEN_XMLNODE *pn; const char *lastValue; DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in properties", name); lastValue=0; pvalue=GWEN_XMLNode_GetProperty(node, name,0); if (pvalue) { if (!topDown) return pvalue; DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue); lastValue=pvalue; } pn=refnode; while(pn) { pvalue=GWEN_XMLNode_GetProperty(pn, name,0); if (pvalue) { if (!topDown) return pvalue; DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue); lastValue=pvalue; } pn=GWEN_XMLNode_GetParent(pn); } /* while */ return lastValue; } int GWEN_MsgEngine_GetHighestTrustLevel(GWEN_XMLNODE *node, GWEN_XMLNODE *refnode) { int value; GWEN_XMLNODE *pn; int highestTrust; highestTrust=0; value=atoi(GWEN_XMLNode_GetProperty(node, "trustlevel","0")); if (value>highestTrust) highestTrust=value; pn=node; while(pn) { value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0")); if (value>highestTrust) highestTrust=value; pn=GWEN_XMLNode_GetParent(pn); } /* while */ pn=refnode; while(pn) { value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0")); if (value>highestTrust) highestTrust=value; pn=GWEN_XMLNode_GetParent(pn); } /* while */ return highestTrust; } const char *GWEN_MsgEngine__SearchForValue(GWEN_MSGENGINE *e, GWEN_XMLNODE *node, GWEN_XMLNODE_PATH *nodePath, const char *name, unsigned int *datasize) { const char *pvalue; GWEN_XMLNODE *pn; char *bufferPtr; int topDown; const char *lastValue; unsigned int lastDataSize; unsigned int ldatasize; DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in ", name); if (!node) { DBG_WARN(GWEN_LOGDOMAIN, "No node !"); } topDown=atoi(GWEN_XMLNode_GetProperty(node, "topdown", "0")); lastValue=0; lastDataSize=0; bufferPtr=0; /*pn=GWEN_XMLNode_GetParent(node);*/ pn=GWEN_XMLNode_Path_Surface(nodePath); while(pn) { const char *ppath; /* if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) { DBG_NOTICE(GWEN_LOGDOMAIN, "Checking node \"%s\"", GWEN_XMLNode_GetData(pn)); }*/ pvalue=GWEN_MsgEngine__findInValues(e, pn, node, name, &ldatasize); if (pvalue) { if (!topDown) { free(bufferPtr); *datasize=ldatasize; return pvalue; } DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value, but will look further"); lastValue=pvalue; lastDataSize=ldatasize; } ppath=GWEN_XMLNode_GetProperty(pn, "name", ""); if (*ppath) { int i; char *tmpptr; if (bufferPtr) { i=strlen(bufferPtr)+strlen(ppath)+2; tmpptr=(char*)malloc(i); assert(tmpptr); sprintf(tmpptr, "%s/%s", ppath, bufferPtr); free(bufferPtr); bufferPtr=tmpptr; } else { i=strlen(ppath)+strlen(name)+2; tmpptr=(char*)malloc(i); assert(tmpptr); sprintf(tmpptr, "%s/%s", ppath, name); bufferPtr=tmpptr; } name=bufferPtr; } pn=GWEN_XMLNode_Path_Surface(nodePath); } /* while */ free(bufferPtr); if (!lastValue) *datasize=0; else *datasize=lastDataSize; return lastValue; } const char *GWEN_MsgEngine__findInValues(GWEN_MSGENGINE *e, GWEN_XMLNODE *node, GWEN_XMLNODE *dnode, const char *name, unsigned int *datasize) { GWEN_XMLNODE *pn; DBG_VERBOUS(GWEN_LOGDOMAIN, "Looking for value of \"%s\" in ", name); pn=GWEN_XMLNode_GetChild(node); while(pn) { if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) { GWEN_XMLNODE *n; const char *p; p=GWEN_XMLNode_GetData(pn); assert(p); DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s", p); if (strcasecmp(p, "VALUES")==0) { DBG_DEBUG(GWEN_LOGDOMAIN, " found"); /* found, check all values */ n=GWEN_XMLNode_GetChild(pn); while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { const char *p; p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, "VALUE")==0) { const char *pname; const char *pvalue; pname=GWEN_XMLNode_GetProperty(n, "path", 0); if (pname) { DBG_DEBUG(GWEN_LOGDOMAIN, "Comparing against \"%s\"", pname); if (strcasecmp(name, pname)==0) { GWEN_XMLNODE *dn; dn=GWEN_XMLNode_GetChild(n); while (dn) { if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { pvalue=GWEN_XMLNode_GetData(dn); if (pvalue) { DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming \"%s\"", pvalue); pvalue=GWEN_MsgEngine__TransformValue(e, pvalue, node, dnode, datasize); } if (pvalue) return pvalue; } dn=GWEN_XMLNode_Next(dn); } /* while dn */ } /* if path matches name */ } /* if path given */ } /* if VALUE tag */ } /* if TAG */ n=GWEN_XMLNode_Next(n); } /* while */ break; /* REMOVE this to check multiple groups */ } /* if found */ } /* if tag */ pn=GWEN_XMLNode_Next(pn); } /* while node */ DBG_DEBUG(GWEN_LOGDOMAIN, "No value found for \"%s\" in ", name); return 0; } GWEN_XMLNODE *GWEN_MsgEngine__GetGroup(GWEN_MSGENGINE *e, GWEN_XMLNODE *node, const char *t, int version, const char *pvalue) { GWEN_XMLNODE *n; const char *p; int i; const char *mode; unsigned int proto; char buffer[256]; if ((strlen(t)+4)>sizeof(buffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long."); return 0; } mode=GWEN_MsgEngine_GetMode(e); proto=GWEN_MsgEngine_GetProtocolVersion(e); /* find type+"S" */ strcpy(buffer, t); strcat(buffer,"S"); n=GWEN_XMLNode_FindFirstTag(node, buffer, 0, 0); if (!n) { DBG_DEBUG(GWEN_LOGDOMAIN, "No definitions here for type \"%s\"", t); return 0; } /* find approppriate group definition */ if (!mode) mode=""; n=GWEN_XMLNode_GetFirstTag(n); if (!n) { DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer); return 0; } /* find type+"def" */ strcpy(buffer, t); strcat(buffer, "def"); while(n) { p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, buffer)==0 || strcasecmp(p, t)==0) { p=GWEN_XMLNode_GetProperty(n, "id", ""); if (strcasecmp(p, pvalue)!=0) p=GWEN_XMLNode_GetProperty(n, "name", ""); if (strcasecmp(p, pvalue)==0) { i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0")); if (proto==0 || (int)proto==i || i==0) { i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0")); if (version==0 || version==i) { p=GWEN_XMLNode_GetProperty(n, "mode",""); if (strcasecmp(p, mode)==0 || !*p) { DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found", t, pvalue); return n; } } } } } n=GWEN_XMLNode_GetNextTag(n); } /* while */ DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found here", t, pvalue, version); return 0; } GWEN_XMLNODE *GWEN_MsgEngine_GetGroup(GWEN_MSGENGINE *e, GWEN_XMLNODE *node, const GWEN_XMLNODE_PATH *nodePath, const char *t, int version, const char *pvalue) { GWEN_XMLNODE *n; GWEN_XMLNODE *nLast = 0; GWEN_XMLNODE *nRes = 0; GWEN_XMLNODE_PATH *pathCopy; assert(node); assert(nodePath); assert(t); assert(pvalue); pathCopy=GWEN_XMLNode_Path_dup(nodePath); n=GWEN_XMLNode_Path_Surface(pathCopy); /* first try all nodes along the path */ while(n) { nLast=n; nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue); if (nRes) break; n=GWEN_XMLNode_Path_Surface(pathCopy); } GWEN_XMLNode_Path_free(pathCopy); if (nRes) { /* already found */ if (nRes==node) { DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected."); return 0; } return nRes; } if (nLast) n=nLast; else n=node; if (n) { n=GWEN_XMLNode_GetParent(n); while(n) { nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue); if (nRes) break; n=GWEN_XMLNode_GetParent(n); } } /* try root as a last resort */ if (!nRes && e->defs) nRes=GWEN_MsgEngine__GetGroup(e, e->defs, t, version, pvalue); if (!nRes) { DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found", t, pvalue, version); return 0; } if (nRes==node) { DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected."); return 0; } return nRes; } int GWEN_MsgEngine__WriteGroup(GWEN_MSGENGINE *e, GWEN_BUFFER *gbuf, GWEN_XMLNODE *node, GWEN_XMLNODE *rnode, GWEN_DB_NODE *gr, int groupIsOptional, GWEN_XMLNODE_PATH *nodePath) { GWEN_XMLNODE *n; const char *p; char delimiter; char terminator; int isFirstElement; int omittedElements; int hasEntries; /* get some settings */ if (rnode) { /* get delimiter */ p=GWEN_XMLNode_GetProperty(rnode, "delimiter", GWEN_XMLNode_GetProperty(node, "delimiter", "")); delimiter=*p; /* get terminating char, if any */ p=GWEN_XMLNode_GetProperty(rnode, "terminator", GWEN_XMLNode_GetProperty(node, "terminator", "")); terminator=*p; } else { /* get delimiter */ p=GWEN_XMLNode_GetProperty(node, "delimiter", ""); delimiter=*p; /* get terminating char, if any */ p=GWEN_XMLNode_GetProperty(node, "terminator",""); terminator=*p; } /* handle all child entries */ n=GWEN_XMLNode_GetChild(node); isFirstElement=1; omittedElements=0; hasEntries=0; if (!n) { DBG_INFO(GWEN_LOGDOMAIN, "No subnodes !"); } while(n) { int t; unsigned int minnum; unsigned int maxnum; int gversion; const char *addEmptyMode; unsigned int loopNr; minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one"); DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements); t=GWEN_XMLNode_GetType(n); if (t==GWEN_XMLNodeTypeTag) { const char *typ; typ=GWEN_XMLNode_GetData(n); if (typ==0) { DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); return -1; } if (strcasecmp(typ, "ELEM")==0) { /* element tag found */ int j; int rv; DBG_VERBOUS(GWEN_LOGDOMAIN, "Found an element"); /* write element as often as needed */ for (loopNr=0; loopNr=minnum || (groupIsOptional && !hasEntries), nodePath); if (rv==-1) { DBG_INFO(GWEN_LOGDOMAIN, "Error writing element"); DBG_INFO(GWEN_LOGDOMAIN, "Node is:"); GWEN_XMLNode_Dump(n, stderr, 1); if (gr) { DBG_INFO(GWEN_LOGDOMAIN, "Data is:"); GWEN_DB_Dump(gr, stderr, 1); } return -1; } else if (rv==0) { isFirstElement=0; omittedElements=0; hasEntries=1; DBG_DEBUG(GWEN_LOGDOMAIN, "Element written"); } else { /* element is optional, not found */ /* restore position */ GWEN_Buffer_SetPos(gbuf, posBeforeElement); GWEN_Buffer_Crop(gbuf, 0, posBeforeElement); if (strcasecmp(addEmptyMode, "max")==0) { DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty"); omittedElements+=(maxnum-loopNr); } else if (strcasecmp(addEmptyMode, "min")==0) { DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty"); if (loopNr tag has no \"type\" property", typ); gtype=""; gn=n; } else { DBG_VERBOUS(GWEN_LOGDOMAIN, "<%s> tag is of type \"%s\"", typ, gtype); gn=GWEN_MsgEngine_GetGroup(e, n, nodePath, typ, gversion, gtype); if (!gn) { DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); return -1; } } gname=0; gcfg=0; if (gr) { gname=GWEN_XMLNode_GetProperty(n, "name",0); if (gname) { DBG_VERBOUS(GWEN_LOGDOMAIN, "Group \"%s\" using special data", gname); gcfg=GWEN_DB_GetFirstGroup(gr); } else { DBG_DEBUG(GWEN_LOGDOMAIN, "Unnamed group, using basic data"); gcfg=gr; } } /* write group as often as needed */ for (loopNr=0; loopNr=minnum) groupIsEmpty=1; } } /* while */ } if (!groupIsEmpty) { int dive; /* write delimiter, if needed */ if (!isFirstElement && delimiter) { int j; DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters", omittedElements+1); for (j=0; j=minnum || groupIsOptional, nodePath); GWEN_XMLNode_Path_Surface(nodePath); if (dive==2) GWEN_XMLNode_Path_Surface(nodePath); if (rv==-1){ DBG_INFO(GWEN_LOGDOMAIN, "Could not write group \"%s\"", gtype); if (gn) { DBG_INFO(GWEN_LOGDOMAIN, "Node is:"); GWEN_XMLNode_Dump(gn, stderr, 1); } if (n) { DBG_INFO(GWEN_LOGDOMAIN, "Referring node is:"); GWEN_XMLNode_Dump(n, stderr, 1); } if (gr) { DBG_INFO(GWEN_LOGDOMAIN, "Data is:"); GWEN_DB_Dump(gr, stderr, 1); } return -1; } else if (rv==0) { hasEntries=1; } else groupIsEmpty=1; } if (groupIsEmpty) { DBG_DEBUG(GWEN_LOGDOMAIN, "Empty Group"); GWEN_Buffer_SetPos(gbuf, posBeforeGroup); GWEN_Buffer_Crop(gbuf, 0, posBeforeGroup); if (loopNr>=minnum) { DBG_DEBUG(GWEN_LOGDOMAIN, "No data for group \"%s[%d]\", omitting", gname, loopNr); if (strcasecmp(addEmptyMode, "max")==0) { DBG_VERBOUS(GWEN_LOGDOMAIN, "Adding max empty"); omittedElements+=(maxnum-loopNr); } else if (strcasecmp(addEmptyMode, "min")==0) { DBG_VERBOUS(GWEN_LOGDOMAIN, "Adding min empty"); if (loopNrdefs) { e->defs=GWEN_XMLNode_dup(node); e->ownDefs=1; return 0; } nsrc=GWEN_XMLNode_GetChild(node); while(nsrc) { if (GWEN_XMLNode_GetType(nsrc)==GWEN_XMLNodeTypeTag) { ndst=GWEN_XMLNode_FindNode(e->defs, GWEN_XMLNodeTypeTag, GWEN_XMLNode_GetData(nsrc)); if (ndst) { GWEN_XMLNODE *n; n=GWEN_XMLNode_GetChild(nsrc); while (n) { GWEN_XMLNODE *newNode; DBG_DEBUG(GWEN_LOGDOMAIN, "Adding node \"%s\"", GWEN_XMLNode_GetData(n)); newNode=GWEN_XMLNode_dup(n); GWEN_XMLNode_AddChild(ndst, newNode); n=GWEN_XMLNode_Next(n); } /* while n */ } else { GWEN_XMLNODE *newNode; DBG_DEBUG(GWEN_LOGDOMAIN, "Adding branch \"%s\"", GWEN_XMLNode_GetData(nsrc)); newNode=GWEN_XMLNode_dup(nsrc); GWEN_XMLNode_AddChild(e->defs, newNode); } } /* if TAG */ nsrc=GWEN_XMLNode_Next(nsrc); } /* while */ return 0; } int GWEN_MsgEngine__ShowElement(GWEN_MSGENGINE *e, const char *path, GWEN_XMLNODE *node, GWEN_STRINGLIST *sl, GWEN_TYPE_UINT32 flags) { const char *name; const char *type; const char *npath; unsigned int minsize; unsigned int maxsize; unsigned int minnum; unsigned int maxnum; int j; int isSet; char nbuffer[256]; GWEN_STRINGLISTENTRY *en; /* get type */ type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); /* get some sizes */ minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1")); maxnum=atoi(GWEN_XMLNode_GetProperty(node, "maxnum","1")); npath=""; isSet=0; /* get name */ name=GWEN_XMLNode_GetProperty(node, "name", 0); if (path==0) path=""; if (name) { /* get value of a config variable */ if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(nbuffer, "%s/%s", path, name); else sprintf(nbuffer, "%s", name); npath=nbuffer; } en=GWEN_StringList_FirstEntry(sl); while(en) { if (GWEN_StringListEntry_Data(en)) if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) { isSet=1; break; } en=GWEN_StringListEntry_Next(en); } /* while */ if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET)) return 0; fprintf(stdout, " %s", npath); j=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(npath); if (j>0) { int i; for (i=0; i0) { int i; for (i=0; i found"); /* found, handle all values */ n=GWEN_XMLNode_GetChild(n); while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { const char *p; p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, "VALUE")==0) { const char *pname; const char *pvalue; pname=GWEN_XMLNode_GetProperty(n, "path", 0); if (pname) { GWEN_XMLNODE *dn; /* path found, find data */ dn=GWEN_XMLNode_GetChild(n); while (dn) { if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { pvalue=GWEN_XMLNode_GetData(dn); if (pvalue) { char pbuffer[256]; /* check whether the value is a property */ p=pvalue; while (*p && isspace((int)*p)) p++; if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(pbuffer, "%s/%s", path, pname); else sprintf(pbuffer, "%s", pname); GWEN_StringList_AppendString(sl, pbuffer, 0, 1); } break; } dn=GWEN_XMLNode_Next(dn); } /* while dn */ } /* if path given */ } /* if VALUE tag */ } /* if TAG */ n=GWEN_XMLNode_Next(n); } /* while */ } /* if found */ /* now handle all child entries */ n=GWEN_XMLNode_GetChild(node); isFirstElement=1; omittedElements=0; while(n) { int t; unsigned int minnum; unsigned int maxnum; int gversion; const char *addEmptyMode; unsigned int loopNr; unsigned int lflags; minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one"); lflags=flags; DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements); t=GWEN_XMLNode_GetType(n); if (t==GWEN_XMLNodeTypeTag) { const char *typ; typ=GWEN_XMLNode_GetData(n); if (typ==0) { DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); return -1; } if (strcasecmp(typ, "ELEM")==0) { /* element tag found */ /* write element as often as needed */ rv=GWEN_MsgEngine__ShowElement(e, path, n, sl, lflags); if (rv==-1) return -1; else { isFirstElement=0; omittedElements=0; } } else if (strcasecmp(typ, "VALUES")==0) { } else if (strcasecmp(typ, "DESCR")==0) { } else { /* group tag found */ GWEN_XMLNODE *gn; const char *gname; const char *gtype; if (minnum==0) lflags|=GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL; gtype=GWEN_XMLNode_GetProperty(n, "type",0); if (!gtype) { /* no "type" property, so use this group directly */ DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ); gtype=""; gn=n; } else { gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype); if (!gn) { DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); return -1; } } /* write group as often as needed */ for (loopNr=0; loopNrsizeof(pbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } sprintf(pbuffer, "%s/%s", path, gname); npath=pbuffer; } else { /* this is not the first one, so create new name */ if (strlen(path)+strlen(gname)+10>sizeof(pbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(pbuffer, "%s/%s%d", path, gname, loopNr); else sprintf(pbuffer, "%s%d", gname, loopNr); /* get the value of the given var */ npath=pbuffer; } } /* if name given */ else npath=path; /* write group */ if (GWEN_MsgEngine__ShowGroup(e, npath, gn, n, sl, lflags)) { DBG_INFO(GWEN_LOGDOMAIN, "Could not show group \"%s\"", gtype); return -1; } } /* for */ } } n=GWEN_XMLNode_Next(n); } /* while */ return 0; } int GWEN_MsgEngine_ShowMessage(GWEN_MSGENGINE *e, const char *typ, const char *msgName, int msgVersion, GWEN_TYPE_UINT32 flags) { GWEN_XMLNODE *group; GWEN_STRINGLIST *sl; int i, j; const char *p; sl=GWEN_StringList_new(); fprintf(stdout, "Message \"%s\" version %d\n", msgName, msgVersion); for (i=0; i<76; i++) fprintf(stdout, "="); fprintf(stdout, "\n"); p=" Variable"; fprintf(stdout, "%s", p); i=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(p); for (j=0; j=sizeof(nbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(nbuffer, "%s/%s", path, name); else sprintf(nbuffer, "%s", name); npath=nbuffer; } en=GWEN_StringList_FirstEntry(sl); while(en) { if (GWEN_StringListEntry_Data(en)) if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) { isSet=1; break; } en=GWEN_StringListEntry_Next(en); } /* while */ if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET)) return 0; nn=GWEN_XMLNode_dup(node); if (isSet) GWEN_XMLNode_SetProperty(nn, "GWEN_set", "1"); GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath); GWEN_XMLNode_AddChild(listNode, nn); return 0; } int GWEN_MsgEngine__ListGroup(GWEN_MSGENGINE *e, const char *path, GWEN_XMLNODE *node, GWEN_XMLNODE *rnode, GWEN_STRINGLIST *sl, GWEN_XMLNODE *listNode, GWEN_TYPE_UINT32 flags) { GWEN_XMLNODE *n; int rv; /* setup data */ n=GWEN_XMLNode_GetChild(node); if (path==0) path=""; if (*path=='/') path++; while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { const char *p; p=GWEN_XMLNode_GetData(n); assert(p); DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p); if (strcasecmp(p, "VALUES")==0) break; } /* if tag */ n=GWEN_XMLNode_Next(n); } /* while */ if (n) { DBG_DEBUG(GWEN_LOGDOMAIN, " found"); /* found, handle all values */ n=GWEN_XMLNode_GetChild(n); while(n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { const char *p; p=GWEN_XMLNode_GetData(n); assert(p); if (strcasecmp(p, "VALUE")==0) { const char *pname; const char *pvalue; pname=GWEN_XMLNode_GetProperty(n, "path", 0); if (pname) { GWEN_XMLNODE *dn; /* path found, find data */ dn=GWEN_XMLNode_GetChild(n); while (dn) { if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) { pvalue=GWEN_XMLNode_GetData(dn); if (pvalue) { char pbuffer[256]; /* check whether the value is a property */ p=pvalue; while (*p && isspace((int)*p)) p++; if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(pbuffer, "%s/%s", path, pname); else sprintf(pbuffer, "%s", pname); DBG_INFO(GWEN_LOGDOMAIN, "Found preset value for %s", pbuffer); GWEN_StringList_AppendString(sl, pbuffer, 0, 1); } break; } dn=GWEN_XMLNode_Next(dn); } /* while dn */ } /* if path given */ } /* if VALUE tag */ } /* if TAG */ n=GWEN_XMLNode_Next(n); } /* while */ } /* if found */ /* now handle all child entries */ n=GWEN_XMLNode_GetChild(node); while(n) { int t; int gversion; unsigned int lflags; gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0")); lflags=flags; t=GWEN_XMLNode_GetType(n); if (t==GWEN_XMLNodeTypeTag) { const char *typ; typ=GWEN_XMLNode_GetData(n); if (typ==0) { DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)"); return -1; } if (strcasecmp(typ, "ELEM")==0) { /* element tag found */ /* list element */ rv=GWEN_MsgEngine__ListElement(e, path, n, sl, listNode, lflags); if (rv==-1) return -1; } else if (strcasecmp(typ, "VALUES")==0) { } else if (strcasecmp(typ, "DESCR")==0) { } else { /* group tag found */ GWEN_XMLNODE *gn; GWEN_XMLNODE *nn; const char *gname; const char *gtype; char pbuffer[256]; const char *npath; gtype=GWEN_XMLNode_GetProperty(n, "type",0); if (!gtype) { /* no "type" property, so use this group directly */ DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ); gtype=""; gn=n; } else { gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype); if (!gn) { DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ); return -1; } } /* get configuration */ gname=GWEN_XMLNode_GetProperty(n, "name",0); if (gname) { if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) { DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small"); return -1; } if (*path) sprintf(pbuffer, "%s/%s", path, gname); else sprintf(pbuffer, "%s", gname); npath=pbuffer; } /* if name given */ else npath=path; nn=GWEN_XMLNode_dup(n); if (gn!=n) GWEN_XMLNode_CopyProperties(nn, gn, 0); GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath); GWEN_XMLNode_AddChild(listNode, nn); /* write group */ if (GWEN_MsgEngine__ListGroup(e, npath, gn, n, sl, nn, lflags)) { DBG_INFO(GWEN_LOGDOMAIN, "Could not list group \"%s\"", gtype); return -1; } } } n=GWEN_XMLNode_Next(n); } /* while */ return 0; } GWEN_XMLNODE *GWEN_MsgEngine_ListMessage(GWEN_MSGENGINE *e, const char *typ, const char *msgName, int msgVersion, GWEN_TYPE_UINT32 flags) { GWEN_XMLNODE *group; GWEN_STRINGLIST *sl; GWEN_XMLNODE *listNode; group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName); if (!group) group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "code", msgVersion, msgName); if (!group) { DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" (version %d) not found\n", msgName, msgVersion); return 0; } sl=GWEN_StringList_new(); /* copy group, but remove all children (we only want the properties) */ listNode=GWEN_XMLNode_dup(group); GWEN_XMLNode_RemoveChildren(listNode); if (GWEN_MsgEngine__ListGroup(e, "", group, 0, sl, listNode, flags)) { DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName); GWEN_StringList_free(sl); GWEN_XMLNode_free(listNode); return 0; } GWEN_StringList_free(sl); return listNode; } int GWEN_MsgEngine__ReadValue(GWEN_MSGENGINE *e, GWEN_BUFFER *msgbuf, GWEN_XMLNODE *node, GWEN_XMLNODE *rnode, GWEN_BUFFER *vbuf, const char *delimiters, GWEN_TYPE_UINT32 flags) { unsigned int minsize; unsigned int maxsize; unsigned int minnum; GWEN_MSGENGINE_TRUSTLEVEL trustLevel; unsigned int posInMsg; const char *type; int rv; unsigned int realSize; /* get some sizes */ posInMsg=GWEN_Buffer_GetPos(msgbuf); realSize=0; minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0")); maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0")); minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1")); type=GWEN_XMLNode_GetProperty(node, "type","ASCII"); rv=1; if (e->typeReadPtr) { rv=e->typeReadPtr(e, msgbuf, node, vbuf, e->escapeChar, delimiters); } if (rv==-1) { DBG_INFO(GWEN_LOGDOMAIN, "External type reading failed on type \"%s\"", type); return -1; } else if (rv==1) { if (strcasecmp(type, "bin")==0) { if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) { DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (@num@ expected)"); return -1; } else { char lbuffer[16]; int c; char *p; int l; p=lbuffer; c=GWEN_Buffer_ReadByte(msgbuf); if (c!='@') { DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); return -1; } c=0; while(GWEN_Buffer_GetBytesLeft(msgbuf)>0) { c=GWEN_Buffer_ReadByte(msgbuf); if (c==-1) { DBG_ERROR(GWEN_LOGDOMAIN, "\"@\" expected"); return -1; } if (c=='@') break; *p=(char)c; p++; } /* while */ *p=0; if (c!='@') { DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); return -1; } if (sscanf(lbuffer, "%d", &l)!=1) { DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format"); return -1; } DBG_DEBUG(GWEN_LOGDOMAIN, "Reading binary: %d bytes from pos %d (msgsize=%d)", l, GWEN_Buffer_GetPos(msgbuf), GWEN_Buffer_GetUsedBytes(msgbuf)); if (GWEN_Buffer_GetBytesLeft(msgbuf) < (unsigned) l) { DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)"); return -1; } if (GWEN_Buffer_AppendBytes(vbuf, GWEN_Buffer_GetPosPointer(msgbuf), l)) { DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here"); return -1; } GWEN_Buffer_IncrementPos(msgbuf,l); } } /* if bin */ else { /* type is not bin */ int lastWasEscape; int isEscaped; isEscaped=0; lastWasEscape=0; while(GWEN_Buffer_GetBytesLeft(msgbuf)) { int c; c=GWEN_Buffer_ReadByte(msgbuf); if (lastWasEscape) { lastWasEscape=0; isEscaped=1; } else { isEscaped=0; if (c==e->escapeChar) { lastWasEscape=1; c=-1; } } if (c!=-1) { if (!isEscaped && (c && strchr(delimiters, c)!=0)) { /* delimiter found, step back */ GWEN_Buffer_DecrementPos(msgbuf,1); break; } else { if (c=='\\' || iscntrl(c)) { DBG_WARN(GWEN_LOGDOMAIN, "Found a bad character (%02x) in type \"%s\", " "converting to SPACE", (unsigned int)c, type); c=' '; } if (GWEN_Buffer_AppendByte(vbuf, c)) { DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here"); return -1; } } } } /* while */ } /* if !bin */ } /* if type not external */ else { DBG_DEBUG(GWEN_LOGDOMAIN, "Type \"%s\" is external (read)", type); } realSize=GWEN_Buffer_GetUsedBytes(vbuf); /* check the value */ if (realSize==0) { DBG_DEBUG(GWEN_LOGDOMAIN, "Datasize is 0"); if (minnum==0) { DBG_DEBUG(GWEN_LOGDOMAIN, "... but thats ok"); /* value is empty, and that is allowed */ return 1; } else { DBG_ERROR(GWEN_LOGDOMAIN, "Value missing"); GWEN_XMLNode_Dump(node, stderr, 1); return -1; } } /* check minimum size */ if (minsize!=0 && realSizemaxsize) { DBG_INFO(GWEN_LOGDOMAIN, "Value too long (%d>%d).", realSize, maxsize); return -1; } if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) { /* add trust data to msgEngine */ const char *descr; trustLevel=GWEN_MsgEngine_GetHighestTrustLevel(node, rnode); if (trustLevel) { unsigned int ustart; ustart=GWEN_Buffer_GetPos(msgbuf)-realSize; descr=GWEN_XMLNode_GetProperty(node, "name",0); if (GWEN_MsgEngine_AddTrustInfo(e, GWEN_Buffer_GetStart(vbuf), realSize, descr, trustLevel, ustart)) { DBG_INFO(GWEN_LOGDOMAIN, "called from here"); return -1; } } } return 0; } int GWEN_MsgEngine__ReadGroup(GWEN_MSGENGINE *e, GWEN_BUFFER *msgbuf, GWEN_XMLNODE *node, GWEN_XMLNODE *rnode, GWEN_DB_NODE *gr, const char *delimiters, GWEN_TYPE_UINT32 flags) { unsigned int minsize; unsigned int maxsize; unsigned int minnum; unsigned int maxnum; const char *name; const char *p; char delimiter; char terminator; GWEN_XMLNODE *n; int abortLoop; GWEN_BUFFER *delimBuffer=0; /* get some settings */ if (rnode) { /* get delimiter */ p=GWEN_XMLNode_GetProperty(rnode, "delimiter", GWEN_XMLNode_GetProperty(node, "delimiter", "")); delimiter=*p; /* get terminating char, if any */ p=GWEN_XMLNode_GetProperty(rnode, "terminator", GWEN_XMLNode_GetProperty(node, "terminator", "")); terminator=*p; } else { /* get delimiter */ p=GWEN_XMLNode_GetProperty(node, "delimiter", ""); delimiter=*p; /* get terminating char, if any */ p=GWEN_XMLNode_GetProperty(node, "terminator",""); terminator=*p; } delimBuffer=GWEN_Buffer_new(0, strlen(delimiters)+2, 0, 1); GWEN_Buffer_AppendString(delimBuffer, delimiters); if (delimiter) GWEN_Buffer_AppendByte(delimBuffer, delimiter); if (terminator) GWEN_Buffer_AppendByte(delimBuffer, terminator); DBG_DEBUG(GWEN_LOGDOMAIN, "Delimiters are \"%s\" and \"%c\"", delimiters, delimiter); n=GWEN_XMLNode_GetChild(node); while (n) { if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) { const char *type; if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) break; type=GWEN_XMLNode_GetData(n); /* DBG_NOTICE(GWEN_LOGDOMAIN, "Reading group from here :"); GWEN_Text_DumpString(GWEN_Buffer_GetStart(msgbuf)+ GWEN_Buffer_GetPos(msgbuf), GWEN_Buffer_GetUsedBytes(msgbuf)- GWEN_Buffer_GetPos(msgbuf), stderr, 3); */ if (strcasecmp(type, "ELEM")==0) { unsigned int loopNr; /* get some sizes */ minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize","0")); maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize","0")); minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1")); maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1")); name=GWEN_XMLNode_GetProperty(n, "name", 0); loopNr=0; abortLoop=0; while((maxnum==0 || loopNrbinTypeReadPtr) { rv=e->binTypeReadPtr(e, n, gr, vbuf); } else rv=1; if (rv==-1) { DBG_INFO(GWEN_LOGDOMAIN, "Called from here"); GWEN_Buffer_free(vbuf); GWEN_Buffer_free(delimBuffer); return -1; } else if (rv==1) { /* bin type not handled, so handle it myself */ if (GWEN_DB_SetBinValue(gr, GWEN_DB_FLAGS_DEFAULT, name, GWEN_Buffer_GetStart(vbuf), GWEN_Buffer_GetUsedBytes(vbuf))) { DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name); GWEN_Buffer_free(vbuf); GWEN_Buffer_free(delimBuffer); return -1; } } } /* if type is bin */ else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) { int z; if (1!=sscanf(GWEN_Buffer_GetStart(vbuf), "%d", &z)) { DBG_INFO(GWEN_LOGDOMAIN, "Value for \"%s\" is not an integer", name); GWEN_Buffer_free(delimBuffer); return -1; } if (GWEN_DB_SetIntValue(gr, GWEN_DB_FLAGS_DEFAULT, name, z)) { DBG_INFO(GWEN_LOGDOMAIN, "Could not set int value for \"%s\"", name); GWEN_Buffer_free(delimBuffer); return -1; } } /* if type is int */ else { DBG_DEBUG(GWEN_LOGDOMAIN, "Value is \"%s\"", GWEN_Buffer_GetStart(vbuf)); if (GWEN_DB_SetCharValue(gr, GWEN_DB_FLAGS_DEFAULT, name, GWEN_Buffer_GetStart(vbuf))){ DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name); GWEN_Buffer_free(delimBuffer); return -1; } } /* if !bin */ GWEN_Buffer_free(vbuf); } /* if name is given */ } /* if current char is not a delimiter */ if (GWEN_Buffer_GetBytesLeft(msgbuf)) { if (delimiter) { if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) { GWEN_Buffer_IncrementPos(msgbuf,1); } } } loopNr++; } /* while */ if (loopNr tag has no \"type\" property", type); gtype=""; gn=n; } else { gn=GWEN_MsgEngine_FindNodeByProperty(e, type, "id", gversion, gtype); if (!gn) { DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", type); GWEN_Buffer_free(delimBuffer); return -1; } } /* get configuration */ loopNr=0; abortLoop=0; while((maxnum==0 || loopNrdelimiters, flags)) { DBG_INFO(GWEN_LOGDOMAIN, "Error reading group"); return -1; } return 0; } int GWEN_MsgEngine_SetValue(GWEN_MSGENGINE *e, const char *path, const char *value){ GWEN_DB_NODE *globalValues; assert(e); globalValues=GWEN_MsgEngine__GetGlobalValues(e); assert(globalValues); return GWEN_DB_SetCharValue(globalValues, GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_OVERWRITE_VARS, path, value); } int GWEN_MsgEngine_SetIntValue(GWEN_MSGENGINE *e, const char *path, int value){ GWEN_DB_NODE *globalValues; assert(e); globalValues=GWEN_MsgEngine__GetGlobalValues(e); assert(globalValues); return GWEN_DB_SetIntValue(globalValues, GWEN_DB_FLAGS_DEFAULT | GWEN_DB_FLAGS_OVERWRITE_VARS, path, value); } const char *GWEN_MsgEngine_GetValue(GWEN_MSGENGINE *e, const char *path, const char *defValue){ GWEN_DB_NODE *globalValues; assert(e); globalValues=GWEN_MsgEngine__GetGlobalValues(e); assert(globalValues); return GWEN_DB_GetCharValue(globalValues, path, 0, defValue); } int GWEN_MsgEngine_GetIntValue(GWEN_MSGENGINE *e, const char *path, int defValue){ GWEN_DB_NODE *globalValues; assert(e); globalValues=GWEN_MsgEngine__GetGlobalValues(e); assert(globalValues); return GWEN_DB_GetIntValue(globalValues, path, 0, defValue); } /* --------------------------------------------------------------- FUNCTION */ int GWEN_MsgEngine_SkipSegment(GWEN_MSGENGINE *e, GWEN_BUFFER *msgbuf, unsigned char escapeChar, unsigned char delimiter) { int esc; esc=0; while(GWEN_Buffer_GetBytesLeft(msgbuf)) { if (esc) { esc=0; } else { int i; unsigned char c; i=GWEN_Buffer_ReadByte(msgbuf); if (i==-1) { DBG_INFO(GWEN_LOGDOMAIN, "called from here"); return 0; } c=(unsigned int)i; if (c==escapeChar) { /* escape */ esc=1; } else if (c=='@') { /* skip binary data */ char lbuffer[16]; char *p; int l; int nc; p=lbuffer; while(1) { nc=GWEN_Buffer_ReadByte(msgbuf); if (nc==-1) { DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected"); return -1; } if (nc=='@') break; *p=nc; p++; } /* while */ *p=0; if (sscanf(lbuffer, "%d", &l)!=1) { DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format"); return -1; } if (GWEN_Buffer_GetUsedBytes(msgbuf)-GWEN_Buffer_GetPos(msgbuf) < (unsigned) l) { DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)"); return -1; } GWEN_Buffer_IncrementPos(msgbuf, l); } else if (c==delimiter) {/* segment-end */ return 0; break; } } } /* while */ DBG_ERROR(GWEN_LOGDOMAIN, "End of segment not found"); return -1; } /* --------------------------------------------------------------- FUNCTION */ int GWEN_MsgEngine_ReadMessage(GWEN_MSGENGINE *e, const char *gtype, GWEN_BUFFER *mbuf, GWEN_DB_NODE *gr, GWEN_TYPE_UINT32 flags) { unsigned int segments; segments=0; while(GWEN_Buffer_GetBytesLeft(mbuf)) { GWEN_XMLNODE *node; unsigned int posBak; const char *p; GWEN_DB_NODE *tmpdb; int segVer; /* find head segment description */ tmpdb=GWEN_DB_Group_new("tmpdb"); node=GWEN_MsgEngine_FindGroupByProperty(e, "id", 0, "SegHead"); if (node==0) { DBG_ERROR(GWEN_LOGDOMAIN, "Segment description not found"); GWEN_DB_Group_free(tmpdb); return -1; } /* parse head segment */ posBak=GWEN_Buffer_GetPos(mbuf); if (GWEN_MsgEngine_ParseMessage(e, node, mbuf, tmpdb, flags)) { DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment head"); GWEN_DB_Group_free(tmpdb); return -1; } /* get segment code */ segVer=GWEN_DB_GetIntValue(tmpdb, "version", 0, 0); p=GWEN_DB_GetCharValue(tmpdb, "code", 0, 0); if (!p) { DBG_ERROR(GWEN_LOGDOMAIN, "No segment code for %s ? This seems to be a bad msg...", gtype); GWEN_Buffer_SetPos(mbuf, posBak); DBG_ERROR(GWEN_LOGDOMAIN, "Full message (pos=%04x)", posBak); GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf), stderr, 1); GWEN_DB_Dump(tmpdb, stderr, 1); GWEN_DB_Group_free(tmpdb); return -1; } /* try to find corresponding XML node */ node=GWEN_MsgEngine_FindNodeByProperty(e, gtype, "code", segVer, p); if (node==0) { unsigned int ustart; ustart=GWEN_Buffer_GetPos(mbuf); ustart++; /* skip delimiter */ /* node not found, skip it */ DBG_NOTICE(GWEN_LOGDOMAIN, "Unknown segment \"%s\" (Segnum=%d, version=%d, ref=%d)", p, GWEN_DB_GetIntValue(tmpdb, "seq", 0, -1), GWEN_DB_GetIntValue(tmpdb, "version", 0, -1), GWEN_DB_GetIntValue(tmpdb, "ref", 0, -1)); if (GWEN_MsgEngine_SkipSegment(e, mbuf, '?', '\'')) { DBG_ERROR(GWEN_LOGDOMAIN, "Error skipping segment \"%s\"", p); GWEN_DB_Group_free(tmpdb); return -1; } if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) { unsigned int usize; usize=GWEN_Buffer_GetPos(mbuf)-ustart-1; GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+ustart, usize, stderr, 1); if (GWEN_MsgEngine_AddTrustInfo(e, GWEN_Buffer_GetStart(mbuf)+ustart, usize, p, GWEN_MsgEngineTrustLevelHigh, ustart)) { DBG_INFO(GWEN_LOGDOMAIN, "called from here"); GWEN_DB_Group_free(tmpdb); return -1; } } /* if trustInfo handling wanted */ } else { /* ok, node available, get the corresponding description and parse * the segment */ const char *id; GWEN_DB_NODE *storegrp; unsigned int startPos; /* restore start position, since the segment head is part of a full * description, so we need to restart reading from the very begin */ GWEN_Buffer_SetPos(mbuf, posBak); /* create group in DB for this segment */ id=GWEN_XMLNode_GetProperty(node, "id", p); storegrp=GWEN_DB_GetGroup(gr, GWEN_PATH_FLAGS_CREATE_GROUP, id); assert(storegrp); /* store the start position of this segment within the DB */ startPos=GWEN_Buffer_GetPos(mbuf); GWEN_DB_SetIntValue(storegrp, GWEN_DB_FLAGS_OVERWRITE_VARS, "segment/pos", startPos); /* parse the segment */ if (GWEN_MsgEngine_ParseMessage(e, node, mbuf, storegrp, flags)) { DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment \"%s\" at %d (%x)", p, GWEN_Buffer_GetPos(mbuf)-startPos, GWEN_Buffer_GetPos(mbuf)-startPos); GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+startPos, GWEN_Buffer_GetUsedBytes(mbuf)-startPos, stderr, 1); DBG_ERROR(GWEN_LOGDOMAIN, "Stored data so far:"); GWEN_DB_Dump(storegrp, stderr, 2); GWEN_DB_Group_free(tmpdb); return -1; } /* store segment size within DB */ GWEN_DB_SetIntValue(storegrp, GWEN_DB_FLAGS_OVERWRITE_VARS, "segment/length", GWEN_Buffer_GetPos(mbuf)-startPos); segments++; } GWEN_DB_Group_free(tmpdb); } /* while */ /* done */ if (segments) { DBG_DEBUG(GWEN_LOGDOMAIN, "Parsed %d segments", segments); return 0; } else { DBG_INFO(GWEN_LOGDOMAIN, "No segments parsed."); return 1; } } GWEN_MSGENGINE_TRUSTEDDATA* GWEN_MsgEngine_TrustedData_new(const char *data, unsigned int size, const char *description, GWEN_MSGENGINE_TRUSTLEVEL trustLevel){ GWEN_MSGENGINE_TRUSTEDDATA *td; assert(data); assert(size); GWEN_NEW_OBJECT(GWEN_MSGENGINE_TRUSTEDDATA, td); td->data=(char*)malloc(size); assert(td->data); memmove(td->data, data, size); if (description) td->description=strdup(description); td->trustLevel=trustLevel; td->size=size; return td; } void GWEN_MsgEngine_TrustedData_free(GWEN_MSGENGINE_TRUSTEDDATA *td){ if (td) { free(td->data); free(td->description); free(td->replacement); free(td); } } GWEN_MSGENGINE_TRUSTEDDATA* GWEN_MsgEngine_TrustedData_GetNext(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->next; } const char* GWEN_MsgEngine_TrustedData_GetData(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->data; } unsigned int GWEN_MsgEngine_TrustedData_GetSize(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->size; } const char* GWEN_MsgEngine_TrustedData_GetDescription(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->description; } GWEN_MSGENGINE_TRUSTLEVEL GWEN_MsgEngine_TrustedData_GetTrustLevel(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->trustLevel; } const char* GWEN_MsgEngine_TrustedData_GetReplacement(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); return td->replacement; } int GWEN_MsgEngine_TrustedData_AddPos(GWEN_MSGENGINE_TRUSTEDDATA *td, unsigned int pos){ assert(td); if (td->posCount>=GWEN_MSGENGINE_TRUSTEDDATA_MAXPOS) return -1; td->positions[td->posCount++]=pos; return 0; } int GWEN_MsgEngine_TrustedData_GetFirstPos(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); td->posPointer=0; return GWEN_MsgEngine_TrustedData_GetNextPos(td); } int GWEN_MsgEngine_TrustedData_GetNextPos(GWEN_MSGENGINE_TRUSTEDDATA *td){ assert(td); if (td->posPointer>=td->posCount) return -1; return td->positions[td->posPointer++]; } int GWEN_MsgEngine_TrustedData_CreateReplacements(GWEN_MSGENGINE_TRUSTEDDATA *td){ unsigned int nextNr; GWEN_MSGENGINE_TRUSTEDDATA *ntd; unsigned int count; assert(td); count=0; ntd=td; while(ntd) { count++; ntd=ntd->next; } if (count<0x10) nextNr=0x01; else nextNr=0x11; ntd=td; while(ntd) { unsigned int i; char numbuffer[32]; char *rp; GWEN_MSGENGINE_TRUSTEDDATA *std; int match; /* check whether the same data already exists */ std=td; match=0; while(std && std!=ntd) { match=1; if (std->size==ntd->size) { unsigned int i; for (i=0; isize; i++) { if (std->data[i]!=ntd->data[i]) { match=0; break; } } /* for */ } else match=0; if (match) break; std=std->next; } /* while */ if (match) { /* copy the found match */ rp=strdup(std->replacement); } else { /* this is a new one */ rp=(char*)malloc(ntd->size+1); assert(rp); if (ntd->size==1) { if (count>=0x10) nextNr+=0x10; } sprintf(numbuffer, "%02X", nextNr++); for (i=0; isize; i++) { if (count<0x10) rp[i]=numbuffer[1]; else rp[i]=numbuffer[1-(i&1)]; } /* for */ rp[i]=0; } /* DBG_DEBUG(GWEN_LOGDOMAIN, "Replacement: \"%s\" for \"%s\" (%d)", rp, ntd->description, ntd->size); */ free(ntd->replacement); ntd->replacement=rp; ntd=ntd->next; } /* while */ return 0; } GWEN_MSGENGINE_TRUSTEDDATA *GWEN_MsgEngine_TakeTrustInfo(GWEN_MSGENGINE *e){ GWEN_MSGENGINE_TRUSTEDDATA *td; assert(e); td=e->trustInfos; e->trustInfos=0; return td; } int GWEN_MsgEngine_AddTrustInfo(GWEN_MSGENGINE *e, const char *data, unsigned int size, const char *description, GWEN_MSGENGINE_TRUSTLEVEL trustLevel, unsigned int pos) { GWEN_MSGENGINE_TRUSTEDDATA *td; int match; assert(e); assert(data); assert(size); if (!description) description=""; td=e->trustInfos; while(td) { unsigned int i; /* compare data */ if (td->size==size && *description && *(td->description) && trustLevel==td->trustLevel && strcasecmp(description, td->description)==0) { match=1; for (i=0; isize; i++) { if (td->data[i]!=data[i]) { match=0; break; } } /* for */ } else match=0; if (match) break; td=td->next; } /* while */ if (!td) { DBG_INFO(GWEN_LOGDOMAIN, "Creating new trustInfo for \"%s\" (%d)", description, size); td=GWEN_MsgEngine_TrustedData_new(data, size, description, trustLevel); GWEN_LIST_ADD(GWEN_MSGENGINE_TRUSTEDDATA, td, &(e->trustInfos)); } else { DBG_INFO(GWEN_LOGDOMAIN, "Reusing trustInfo for \"%s\" (%d)", description, size); } GWEN_MsgEngine_TrustedData_AddPos(td, pos); return 0; }