gwenhywfar  4.3.3
msgengine.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Fri Jul 04 2003
00003  copyright   : (C) 2003 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #define DISABLE_DEBUGLOG
00030 
00031 #include <gwenhywfar/gwenhywfarapi.h>
00032 #include <msgengine_p.h>
00033 #include <gwenhywfar/xml.h>
00034 #include <gwenhywfar/text.h>
00035 #include <gwenhywfar/misc.h>
00036 #include <gwenhywfar/path.h>
00037 #include <gwenhywfar/debug.h>
00038 #include <gwenhywfar/buffer.h>
00039 #include <stdlib.h>
00040 #include <assert.h>
00041 #include <string.h>
00042 #include <ctype.h>
00043 
00044 
00045 GWEN_INHERIT_FUNCTIONS(GWEN_MSGENGINE)
00046 
00047 
00048 GWEN_MSGENGINE *GWEN_MsgEngine_new(void){
00049   GWEN_MSGENGINE *e;
00050 
00051   GWEN_NEW_OBJECT(GWEN_MSGENGINE, e);
00052   GWEN_INHERIT_INIT(GWEN_MSGENGINE, e);
00053   e->charsToEscape=strdup(GWEN_MSGENGINE_CHARSTOESCAPE);
00054   e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS);
00055   e->globalValues=GWEN_DB_Group_new("globalvalues");
00056   e->escapeChar='\\';
00057 
00058   e->usage=1;
00059   return e;
00060 }
00061 
00062 
00063 void GWEN_MsgEngine_free(GWEN_MSGENGINE *e){
00064   if (e) {
00065     assert(e->usage);
00066     if (--(e->usage)==0) {
00067       GWEN_INHERIT_FINI(GWEN_MSGENGINE, e);
00068 
00069       if (e->inheritorData && e->freeDataPtr)
00070         e->freeDataPtr(e);
00071       if (e->ownDefs)
00072         GWEN_XMLNode_free(e->defs);
00073       free(e->charsToEscape);
00074       free(e->delimiters);
00075       GWEN_DB_Group_free(e->globalValues);
00076       if (e->trustInfos) {
00077         /* free trustInfos */
00078         GWEN_MSGENGINE_TRUSTEDDATA *td, *tdn;
00079 
00080         td=e->trustInfos;
00081         while(td) {
00082           tdn=td->next;
00083           GWEN_MsgEngine_TrustedData_free(td);
00084           td=tdn;
00085         } /* while */
00086       }
00087       GWEN_FREE_OBJECT(e);
00088     }
00089   }
00090 }
00091 
00092 
00093 
00094 void GWEN_MsgEngine_Attach(GWEN_MSGENGINE *e){
00095   assert(e);
00096   e->usage++;
00097 }
00098 
00099 
00100 void GWEN_MsgEngine_SetEscapeChar(GWEN_MSGENGINE *e, char c){
00101   assert(e);
00102   e->escapeChar=c;
00103 }
00104 
00105 
00106 
00107 char GWEN_MsgEngine_GetEscapeChar(GWEN_MSGENGINE *e){
00108   assert(e);
00109   return e->escapeChar;
00110 }
00111 
00112 
00113 
00114 void GWEN_MsgEngine_SetCharsToEscape(GWEN_MSGENGINE *e, const char *c){
00115   assert(e);
00116   free(e->charsToEscape);
00117   e->charsToEscape=strdup(c);
00118 }
00119 
00120 
00121 
00122 const char *GWEN_MsgEngine_GetCharsToEscape(GWEN_MSGENGINE *e){
00123   assert(e);
00124   return e->charsToEscape;
00125 }
00126 
00127 
00128 
00129 void GWEN_MsgEngine_SetDelimiters(GWEN_MSGENGINE *e, const char *s){
00130   assert(e);
00131   free(e->delimiters);
00132   if (s)
00133     e->delimiters=strdup(s);
00134   else
00135     e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS);
00136 }
00137 
00138 
00139 
00140 const char *GWEN_MsgEngine_GetDelimiters(GWEN_MSGENGINE *e){
00141   assert(e);
00142   return e->delimiters;
00143 }
00144 
00145 
00146 
00147 void GWEN_MsgEngine_SetMode(GWEN_MSGENGINE *e, const char *mode){
00148   GWEN_DB_NODE *db;
00149 
00150   assert(e);
00151   db=GWEN_MsgEngine__GetGlobalValues(e);
00152 
00153   if (mode)
00154     GWEN_DB_SetCharValue(db,
00155                          GWEN_DB_FLAGS_OVERWRITE_VARS,
00156                          "engine/secmode",
00157                          mode);
00158   else
00159     GWEN_DB_DeleteVar(db, "engine/secmode");
00160 }
00161 
00162 
00163 const char *GWEN_MsgEngine_GetMode(GWEN_MSGENGINE *e){
00164   GWEN_DB_NODE *db;
00165 
00166   assert(e);
00167   db=GWEN_MsgEngine__GetGlobalValues(e);
00168   return GWEN_DB_GetCharValue(db, "engine/secmode", 0, 0);
00169 }
00170 
00171 
00172 
00173 GWEN_DB_NODE *GWEN_MsgEngine__GetGlobalValues(GWEN_MSGENGINE *e){
00174   GWEN_DB_NODE *globalValues;
00175 
00176   assert(e);
00177   if (e->getGlobalValuesPtr) {
00178     globalValues=e->getGlobalValuesPtr(e);
00179     if (!globalValues)
00180       globalValues=e->globalValues;
00181   }
00182   else {
00183     globalValues=e->globalValues;
00184   }
00185   assert(globalValues);
00186   return globalValues;
00187 }
00188 
00189 
00190 
00191 unsigned int GWEN_MsgEngine_GetProtocolVersion(GWEN_MSGENGINE *e){
00192   GWEN_DB_NODE *db;
00193 
00194   assert(e);
00195   db=GWEN_MsgEngine__GetGlobalValues(e);
00196   return GWEN_DB_GetIntValue(db, "engine/pversion", 0, 0);
00197 }
00198 
00199 
00200 
00201 void GWEN_MsgEngine_SetProtocolVersion(GWEN_MSGENGINE *e,
00202                                        unsigned int p){
00203   GWEN_DB_NODE *db;
00204 
00205   assert(e);
00206   db=GWEN_MsgEngine__GetGlobalValues(e);
00207 
00208   GWEN_DB_SetIntValue(db,
00209                       GWEN_DB_FLAGS_OVERWRITE_VARS,
00210                       "engine/pversion",
00211                       p);
00212 }
00213 
00214 
00215 
00216 GWEN_XMLNODE *GWEN_MsgEngine_GetDefinitions(GWEN_MSGENGINE *e){
00217   assert(e);
00218   return e->defs;
00219 }
00220 
00221 
00222 void GWEN_MsgEngine_SetDefinitions(GWEN_MSGENGINE *e,
00223                                    GWEN_XMLNODE *n,
00224                                    int take){
00225   assert(e);
00226   if (e->ownDefs)
00227     GWEN_XMLNode_free(e->defs);
00228   e->defs=n;
00229   e->ownDefs=take;
00230 }
00231 
00232 
00233 
00234 void
00235 GWEN_MsgEngine_SetGetGlobalValuesFunction(GWEN_MSGENGINE *e,
00236                                           GWEN_MSGENGINE_GETGLOBALVALUES_PTR p){
00237   assert(e);
00238   e->getGlobalValuesPtr=p;
00239 }
00240 
00241 
00242 
00243 GWEN_MSGENGINE_GETGLOBALVALUES_PTR
00244 GWEN_MsgEngine_GetGetGlobalValuesFunction(GWEN_MSGENGINE *e){
00245   assert(e);
00246   return e->getGlobalValuesPtr;
00247 }
00248 
00249 
00250 
00251 void GWEN_MsgEngine_SetTypeReadFunction(GWEN_MSGENGINE *e,
00252                                         GWEN_MSGENGINE_TYPEREAD_PTR p){
00253   assert(e);
00254   e->typeReadPtr=p;
00255 }
00256 
00257 
00258 
00259 GWEN_MSGENGINE_TYPEREAD_PTR
00260 GWEN_MsgEngine_GetTypeReadFunction(GWEN_MSGENGINE *e){
00261   assert(e);
00262   return e->typeReadPtr;
00263 }
00264 
00265 
00266 
00267 void GWEN_MsgEngine_SetTypeWriteFunction(GWEN_MSGENGINE *e,
00268                                          GWEN_MSGENGINE_TYPEWRITE_PTR p){
00269   assert(e);
00270   e->typeWritePtr=p;
00271 }
00272 
00273 
00274 
00275 GWEN_MSGENGINE_TYPEWRITE_PTR
00276 GWEN_MsgEngine_GetTypeWriteFunction(GWEN_MSGENGINE *e){
00277   assert(e);
00278   return e->typeWritePtr;
00279 }
00280 
00281 
00282 
00283 void GWEN_MsgEngine_SetTypeCheckFunction(GWEN_MSGENGINE *e,
00284                                          GWEN_MSGENGINE_TYPECHECK_PTR p){
00285   assert(e);
00286   e->typeCheckPtr=p;
00287 }
00288 
00289 
00290 
00291 GWEN_MSGENGINE_TYPECHECK_PTR
00292 GWEN_MsgEngine_GetTypeCheckFunction(GWEN_MSGENGINE *e){
00293   assert(e);
00294   return e->typeCheckPtr;
00295 }
00296 
00297 
00298 
00299 
00300 
00301 
00302 void GWEN_MsgEngine_SetBinTypeReadFunction(GWEN_MSGENGINE *e,
00303                                            GWEN_MSGENGINE_BINTYPEREAD_PTR p){
00304   assert(e);
00305   e->binTypeReadPtr=p;
00306 }
00307 
00308 
00309 
00310 GWEN_MSGENGINE_BINTYPEREAD_PTR
00311 GWEN_MsgEngine_GetBinTypeReadFunction(GWEN_MSGENGINE *e){
00312   assert(e);
00313   return e->binTypeReadPtr;
00314 }
00315 
00316 
00317 
00318 void
00319 GWEN_MsgEngine_SetBinTypeWriteFunction(GWEN_MSGENGINE *e,
00320                                        GWEN_MSGENGINE_BINTYPEWRITE_PTR p){
00321   assert(e);
00322   e->binTypeWritePtr=p;
00323 }
00324 
00325 
00326 
00327 GWEN_MSGENGINE_BINTYPEWRITE_PTR
00328 GWEN_MsgEngine_GetBinTypeWriteFunction(GWEN_MSGENGINE *e){
00329   assert(e);
00330   return e->binTypeWritePtr;
00331 }
00332 
00333 
00334 
00335 void
00336 GWEN_MsgEngine_SetGetCharValueFunction(GWEN_MSGENGINE *e,
00337                                        GWEN_MSGENGINE_GETCHARVALUE_PTR p){
00338   assert(e);
00339   e->getCharValuePtr=p;
00340 }
00341 
00342 
00343 
00344 void
00345 GWEN_MsgEngine_SetGetIntValueFunction(GWEN_MSGENGINE *e,
00346                                       GWEN_MSGENGINE_GETINTVALUE_PTR p){
00347   assert(e);
00348   e->getIntValuePtr=p;
00349 }
00350 
00351 
00352 
00353 void
00354 GWEN_MsgEngine_SetFreeDataFunction(GWEN_MSGENGINE *e,
00355                                    GWEN_MSGENGINE_FREEDATA_PTR p){
00356   assert(e);
00357   DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetFreeDataFunction: Deprecated");
00358   e->freeDataPtr=p;
00359 }
00360 
00361 
00362 
00363 void *GWEN_MsgEngine_GetInheritorData(const GWEN_MSGENGINE *e){
00364   assert(e);
00365   return e->inheritorData;
00366 }
00367 
00368 
00369 
00370 void GWEN_MsgEngine_SetInheritorData(GWEN_MSGENGINE *e, void *d){
00371   assert(e);
00372   DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetInheritorData: Deprecated");
00373   if (e->inheritorData && e->freeDataPtr)
00374     e->freeDataPtr(e);
00375   e->inheritorData=d;
00376 }
00377 
00378 
00379 
00380 int GWEN_MsgEngine__WriteValue(GWEN_MSGENGINE *e,
00381                                GWEN_BUFFER *gbuf,
00382                                GWEN_BUFFER *data,
00383                                GWEN_XMLNODE *node) {
00384   unsigned int minsize;
00385   unsigned int maxsize;
00386   unsigned int fixSize;
00387   unsigned int startPos;
00388   int filler;
00389   const char *type;
00390   const char *name;
00391   int rv;
00392 
00393   /* get some sizes */
00394   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
00395   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
00396   fixSize=atoi(GWEN_XMLNode_GetProperty(node, "size","0"));
00397   filler=atoi(GWEN_XMLNode_GetProperty(node, "filler","0"));
00398   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
00399   name=GWEN_XMLNode_GetProperty(node, "name","<unnamed>");
00400   startPos=GWEN_Buffer_GetPos(gbuf);
00401 
00402   /* check sizes */
00403   if (minsize && GWEN_Buffer_GetUsedBytes(data)<minsize) {
00404     DBG_ERROR(GWEN_LOGDOMAIN, "Data too short (minsize is %d)", minsize);
00405     return -1;
00406   }
00407   if (maxsize && GWEN_Buffer_GetUsedBytes(data)>maxsize) {
00408     DBG_ERROR(GWEN_LOGDOMAIN, "Data too long (maxsize is %d)", maxsize);
00409     return -1;
00410   }
00411 
00412   rv=1;
00413   if (e->typeWritePtr) {
00414     rv=e->typeWritePtr(e,
00415                        gbuf,
00416                        data,
00417                        node);
00418   }
00419   if (rv==-1) {
00420     DBG_INFO(GWEN_LOGDOMAIN, "External type writing failed");
00421     return -1;
00422   }
00423   else if (rv==1) {
00424     int i;
00425 
00426     /* type not handled externally, so handle it myself */
00427     if (strcasecmp(type, "bin")==0) {
00428       DBG_DEBUG(GWEN_LOGDOMAIN, "Writing binary data (%d bytes added to %d bytes)",
00429                 GWEN_Buffer_GetUsedBytes(data),
00430                 GWEN_Buffer_GetUsedBytes(gbuf));
00431       if (GWEN_Buffer_AllocRoom(gbuf, 10+GWEN_Buffer_GetUsedBytes(data))) {
00432         DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00433         return -1;
00434       }
00435       sprintf(GWEN_Buffer_GetPosPointer(gbuf),
00436               "@%d@",
00437               GWEN_Buffer_GetUsedBytes(data));
00438 
00439 
00440       i=strlen(GWEN_Buffer_GetPosPointer(gbuf));
00441       GWEN_Buffer_IncrementPos(gbuf, i);
00442       GWEN_Buffer_AdjustUsedBytes(gbuf);
00443       GWEN_Buffer_AppendBuffer(gbuf, data);
00444     } /* if type is "bin" */
00445     else if (strcasecmp(type, "num")==0) {
00446       int num;
00447       unsigned int len;
00448       unsigned int lj;
00449 
00450       num=atoi(GWEN_Buffer_GetPosPointer(data));
00451       len=strlen(GWEN_Buffer_GetPosPointer(data));
00452 
00453       if (atoi(GWEN_XMLNode_GetProperty(node, "leftfill","0"))) {
00454         if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
00455           DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00456           return -1;
00457         }
00458 
00459         /* fill left */
00460         for (lj=0; lj<(maxsize-len); lj++)
00461           GWEN_Buffer_AppendByte(gbuf, '0');
00462 
00463         /* write value */
00464         for (lj=0; lj<len; lj++)
00465           GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data));
00466       }
00467       else if (atoi(GWEN_XMLNode_GetProperty(node, "rightfill","0"))) {
00468         if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
00469           DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00470           return -1;
00471         }
00472 
00473         /* write value */
00474         for (lj=0; lj<len; lj++)
00475           GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data));
00476 
00477         /* fill right */
00478         for (lj=0; lj<(maxsize-len); lj++)
00479           GWEN_Buffer_AppendByte(gbuf, '0');
00480       }
00481       else {
00482         if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
00483           DBG_ERROR(GWEN_LOGDOMAIN, "Maxsize in XML file is higher than the buffer size");
00484           return -1;
00485         }
00486         for (lj=0; lj<len; lj++)
00487           GWEN_Buffer_AppendByte(gbuf, GWEN_Buffer_ReadByte(data));
00488       }
00489     } /* if type is num */
00490     else {
00491       /* TODO: Check for valids */
00492       const char *p;
00493       int lastWasEscape;
00494       unsigned int pcount;
00495 
00496       p=GWEN_Buffer_GetPosPointer(data);
00497       pcount=0;
00498       lastWasEscape=0;
00499       while(*p && pcount<GWEN_Buffer_GetUsedBytes(data)) {
00500         int c;
00501 
00502         c=(unsigned char)*p;
00503         if (lastWasEscape) {
00504           lastWasEscape=0;
00505           switch(c) {
00506           case 'r': c='\r'; break;
00507           case 'n': c='\n'; break;
00508           case 'f': c='\f'; break;
00509           case 't': c='\t'; break;
00510           default: c=(unsigned char)*p;
00511           } /* switch */
00512         }
00513         else {
00514           if (*p=='\\') {
00515             lastWasEscape=1;
00516             c=-1;
00517           }
00518           else
00519             c=(unsigned char)*p;
00520         }
00521         if (c!=-1) {
00522           int needsEscape;
00523 
00524           needsEscape=0;
00525           if (c==e->escapeChar)
00526             needsEscape=1;
00527           else {
00528             if (e->charsToEscape)
00529               if (strchr(e->charsToEscape, c))
00530                 needsEscape=1;
00531           }
00532           if (needsEscape) {
00533             /* write escape char */
00534             if (GWEN_Buffer_AppendByte(gbuf,
00535                                        e->escapeChar)) {
00536               return -1;
00537             }
00538           }
00539           if (GWEN_Buffer_AppendByte(gbuf, c)) {
00540             return -1;
00541           }
00542         }
00543         p++;
00544         pcount++;
00545       } /* while */
00546       if (pcount<GWEN_Buffer_GetUsedBytes(data)) {
00547         DBG_WARN(GWEN_LOGDOMAIN, "Premature end of string (%d<%d)",
00548                  pcount, GWEN_Buffer_GetUsedBytes(data));
00549       }
00550       if (*p) {
00551         DBG_WARN(GWEN_LOGDOMAIN,
00552                  "String for \"%s\" (type %s) is longer than expected "
00553                  "(no #0 at pos=%d)",
00554                  name, type,
00555                  GWEN_Buffer_GetUsedBytes(data)-1);
00556       }
00557     } /* if type is not BIN */
00558   } /* if type not external */
00559   else {
00560     DBG_INFO(GWEN_LOGDOMAIN, "Type \"%s\" (for %s) is external (write)",
00561              type, name);
00562 
00563   } /* if external type */
00564 
00565   /* fill data */
00566   if (fixSize) {
00567     uint32_t bs;
00568     unsigned int j;
00569 
00570     bs=GWEN_Buffer_GetPos(gbuf)-startPos;
00571     if (bs>fixSize) {
00572       DBG_ERROR(GWEN_LOGDOMAIN,
00573                 "Data too long (size is %d, fixed size is %d)",
00574                 bs, fixSize);
00575       return -1;
00576     }
00577 
00578     for (j=bs; j<fixSize; j++)
00579       GWEN_Buffer_AppendByte(gbuf, (unsigned char)filler);
00580   }
00581 
00582   return 0;
00583 }
00584 
00585 
00586 
00587 int GWEN_MsgEngine__IsCharTyp(GWEN_MSGENGINE *e,
00588                               const char *type) {
00589   if (e->typeCheckPtr) {
00590     GWEN_DB_NODE_TYPE vt;
00591 
00592     vt=e->typeCheckPtr(e, type);
00593     if (vt!=GWEN_DB_NodeType_Unknown) {
00594       if (vt==GWEN_DB_NodeType_ValueChar)
00595         return 1;
00596     }
00597   }
00598   return
00599     (strcasecmp(type, "alpha")==0) ||
00600     (strcasecmp(type, "ascii")==0) ||
00601     (strcasecmp(type, "an")==0) ||
00602     (strcasecmp(type, "float")==0);
00603 }
00604 
00605 
00606 
00607 int GWEN_MsgEngine__IsIntTyp(GWEN_MSGENGINE *e,
00608                              const char *type) {
00609   if (e->typeCheckPtr) {
00610     GWEN_DB_NODE_TYPE vt;
00611 
00612     vt=e->typeCheckPtr(e, type);
00613     if (vt!=GWEN_DB_NodeType_Unknown) {
00614       if (vt==GWEN_DB_NodeType_ValueInt)
00615         return 1;
00616     }
00617   }
00618   return
00619     (strcasecmp(type, "num")==0);
00620 }
00621 
00622 
00623 
00624 int GWEN_MsgEngine__IsBinTyp(GWEN_MSGENGINE *e,
00625                              const char *type) {
00626   if (e->typeCheckPtr) {
00627     GWEN_DB_NODE_TYPE vt;
00628 
00629     vt=e->typeCheckPtr(e, type);
00630     if (vt!=GWEN_DB_NodeType_Unknown) {
00631       if (vt==GWEN_DB_NodeType_ValueBin)
00632         return 1;
00633     }
00634   }
00635   return
00636     (strcasecmp(type, "bin")==0);
00637 }
00638 
00639 
00640 
00641 int GWEN_MsgEngine__GetInline(GWEN_MSGENGINE *e,
00642                               GWEN_XMLNODE *node,
00643                               GWEN_BUFFER *mbuf) {
00644   /* get data from within the XML node */
00645   GWEN_XMLNODE *n;
00646   const char *type;
00647 
00648 
00649   type=GWEN_XMLNode_GetProperty(node, "type", "ascii");
00650   DBG_DEBUG(GWEN_LOGDOMAIN,
00651             "Getting data of type \"%s\" from within XML file", type);
00652   n=GWEN_XMLNode_GetFirstData(node);
00653   if (!n) {
00654     DBG_DEBUG(GWEN_LOGDOMAIN, "No child");
00655     return 1;
00656   }
00657 
00658   if (GWEN_MsgEngine__IsBinTyp(e, type)) {
00659     const char *dp;
00660     unsigned int dplen;
00661     const char *stype;
00662 
00663     stype=GWEN_XMLNode_GetProperty(node, "storedAs", type);
00664     if (GWEN_MsgEngine__IsBinTyp(e, stype)) {
00665       dp=GWEN_XMLNode_GetData(n);
00666       dplen=strlen(dp);
00667       if (GWEN_Text_FromHexBuffer(dp, mbuf)) {
00668         DBG_INFO(GWEN_LOGDOMAIN, "here");
00669         return -1;
00670       }
00671     } /* if stored as bin */
00672     else {
00673       /* stored as char */
00674       GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n));
00675     }
00676   } /* if binType */
00677   else {
00678     GWEN_Buffer_AppendString(mbuf, GWEN_XMLNode_GetData(n));
00679   }
00680 
00681   return 0;
00682 }
00683 
00684 
00685 
00686 
00687 
00688 int GWEN_MsgEngine__WriteElement(GWEN_MSGENGINE *e,
00689                                  GWEN_BUFFER *gbuf,
00690                                  GWEN_XMLNODE *node,
00691                                  GWEN_XMLNODE *rnode,
00692                                  GWEN_DB_NODE *gr,
00693                                  int loopNr,
00694                                  int isOptional,
00695                                  GWEN_XMLNODE_PATH *nodePath) {
00696   const char *name;
00697   const char *type;
00698   unsigned int minsize;
00699   unsigned int maxsize;
00700   char numbuffer[256];
00701   const char *pdata;
00702   unsigned int datasize;
00703   GWEN_BUFFER *data;
00704   GWEN_BUFFER *tdata;
00705   int handled;
00706 
00707   pdata=0;
00708   handled=0;
00709   data=0;
00710   tdata=0;
00711 
00712   /* get type */
00713   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
00714   DBG_DEBUG(GWEN_LOGDOMAIN, "Type is \"%s\"", type);
00715   /* get some sizes */
00716   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
00717   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
00718 
00719   if (e->binTypeWritePtr &&
00720       GWEN_MsgEngine__IsBinTyp(e, type) &&
00721       atoi(GWEN_XMLNode_GetProperty(node, "writebin", "1"))) {
00722     int rv;
00723 
00724     data=GWEN_Buffer_new(0,
00725                          64,
00726                          0,
00727                          1);
00728 
00729     rv=e->binTypeWritePtr(e, node, gr, data);
00730     if (rv==-1) {
00731       /* error */
00732       DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00733       return -1;
00734     }
00735     else if (rv==0) {
00736       handled=1;
00737     }
00738     else if (rv==1) {
00739       GWEN_Buffer_free(data);
00740       data=0;
00741     }
00742   }
00743 
00744   if (!handled) {
00745     /* get name */
00746     name=GWEN_XMLNode_GetProperty(node, "name", 0);
00747     if (!name) {
00748       int rv;
00749 
00750       /* get data from within the XML node */
00751       tdata=GWEN_Buffer_new(0, 32, 0, 1);
00752       GWEN_Buffer_SetStep(tdata, 256);
00753       rv=GWEN_MsgEngine__GetInline(e, node, tdata);
00754       if (rv==0) {
00755         pdata=GWEN_Buffer_GetStart(tdata);
00756         datasize=GWEN_Buffer_GetUsedBytes(tdata);
00757       }
00758       else {
00759         GWEN_Buffer_free(tdata);
00760         tdata=0;
00761         pdata="";
00762         datasize=0;
00763       }
00764     } /* if (!name) */
00765     else {
00766       const char *nptr;
00767   
00768       DBG_DEBUG(GWEN_LOGDOMAIN, "Name provided (%s), loop is %d", name, loopNr);
00769       nptr=name;
00770 
00771       if (gr) {
00772         GWEN_DB_NODE_TYPE vt;
00773         int idata;
00774 
00775         /* Variable type of DB takes precedence
00776          */
00777         vt=GWEN_DB_GetValueTypeByPath(gr, nptr, loopNr);
00778         if (vt==GWEN_DB_NodeType_Unknown) {
00779           if (GWEN_MsgEngine__IsCharTyp(e, type))
00780             vt=GWEN_DB_NodeType_ValueChar;
00781           else if (GWEN_MsgEngine__IsIntTyp(e, type))
00782             vt=GWEN_DB_NodeType_ValueInt;
00783           else if (GWEN_MsgEngine__IsBinTyp(e, type))
00784             vt=GWEN_DB_NodeType_ValueBin;
00785           else {
00786             DBG_INFO(GWEN_LOGDOMAIN,
00787                      "Unable to determine parameter "
00788                      "type (%s), assuming \"char\" for this matter", type);
00789             vt=GWEN_DB_NodeType_ValueChar;
00790           }
00791         }
00792   
00793         /* get the value of the given var from the db */
00794         switch(vt) {
00795         case GWEN_DB_NodeType_ValueChar:
00796           DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is char", name);
00797           pdata=GWEN_DB_GetCharValue(gr, nptr, loopNr, 0);
00798           if (pdata) {
00799             DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %s", nptr, pdata);
00800             datasize=strlen(pdata);
00801           }
00802           else
00803             datasize=0;
00804           break;
00805   
00806         case GWEN_DB_NodeType_ValueInt:
00807           DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is int", name);
00808           if (GWEN_DB_ValueExists(gr, nptr, loopNr)) {
00809             idata=GWEN_DB_GetIntValue(gr, nptr, loopNr, 0);
00810             if (-1==GWEN_Text_NumToString(idata, numbuffer,
00811                                           sizeof(numbuffer),0)) {
00812               DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
00813               GWEN_Buffer_free(data);
00814               return -1;
00815             }
00816             DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %d", nptr, idata);
00817             pdata=numbuffer;
00818             datasize=strlen(numbuffer);
00819           }
00820           break;
00821   
00822         case GWEN_DB_NodeType_ValueBin:
00823           DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is bin", name);
00824           pdata=GWEN_DB_GetBinValue(gr, nptr, loopNr, 0, 0, &datasize);
00825           break;
00826 
00827         default:
00828           DBG_WARN(GWEN_LOGDOMAIN, "Unsupported parameter type (%d)", vt);
00829           break;
00830         } /* switch vt */
00831       } /* if gr */
00832   
00833       if (!pdata) {
00834         GWEN_XMLNODE_PATH *copyOfNodePath;
00835   
00836         copyOfNodePath=GWEN_XMLNode_Path_dup(nodePath);
00837   
00838         /* still no data, try to get it from the XML file */
00839         DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\"", name);
00840         pdata=GWEN_MsgEngine__SearchForValue(e,
00841                                              node, copyOfNodePath, nptr,
00842                                              &datasize);
00843         GWEN_XMLNode_Path_free(copyOfNodePath);
00844         if (pdata) {
00845           DBG_DEBUG(GWEN_LOGDOMAIN, "Found value of \"%s\"", name);
00846         }
00847       }
00848 
00849       if (!pdata) {
00850         int rv;
00851   
00852         /* get data from within the XML node */
00853         tdata=GWEN_Buffer_new(0, 32, 0, 1);
00854         GWEN_Buffer_SetStep(tdata, 256);
00855         rv=GWEN_MsgEngine__GetInline(e, node, tdata);
00856         if (rv==0) {
00857           pdata=GWEN_Buffer_GetStart(tdata);
00858           datasize=GWEN_Buffer_GetUsedBytes(tdata);
00859         }
00860         else {
00861           GWEN_Buffer_free(tdata);
00862           tdata=0;
00863         }
00864       }
00865 
00866       if (pdata==0) {
00867         if (isOptional) {
00868           DBG_INFO(GWEN_LOGDOMAIN, "Value not found, omitting element \"%s[%d]\"",
00869                    name, loopNr);
00870           GWEN_Buffer_free(data);
00871           return 1;
00872         }
00873         else {
00874           DBG_ERROR(GWEN_LOGDOMAIN,
00875                     "Value for element \"%s[%d]\" (mode \"%s\") not found",
00876                     name, loopNr,
00877                     GWEN_MsgEngine_GetMode(e));
00878           GWEN_DB_Dump(gr, 4);
00879           GWEN_Buffer_free(data);
00880           return -1;
00881         }
00882       }
00883     }
00884 
00885     if (!data)
00886       data=GWEN_Buffer_new((char*)pdata,
00887                            datasize,
00888                            datasize,
00889                            0 /* dont take ownership*/ );
00890   }
00891 
00892   /* write value */
00893   if (GWEN_MsgEngine__WriteValue(e,
00894                                  gbuf,
00895                                  data,
00896                                  node)!=0) {
00897     DBG_INFO(GWEN_LOGDOMAIN, "Could not write value");
00898     GWEN_Buffer_free(data);
00899     GWEN_Buffer_free(tdata);
00900     return -1;
00901   }
00902   GWEN_Buffer_free(data);
00903   GWEN_Buffer_free(tdata);
00904 
00905   return 0;
00906 }
00907 
00908 
00909 
00910 GWEN_XMLNODE *GWEN_MsgEngine_FindGroupByProperty(GWEN_MSGENGINE *e,
00911                                                  const char *pname,
00912                                                  int version,
00913                                                  const char *pvalue) {
00914   return GWEN_MsgEngine_FindNodeByProperty(e, "GROUP", pname, version, pvalue);
00915 }
00916 
00917 
00918 
00919 GWEN_XMLNODE *GWEN_MsgEngine_FindNodeByProperty(GWEN_MSGENGINE *e,
00920                                                 const char *t,
00921                                                 const char *pname,
00922                                                 int version,
00923                                                 const char *pvalue) {
00924   GWEN_XMLNODE *n;
00925   const char *p;
00926   int i;
00927   const char *mode;
00928   unsigned int proto;
00929   char buffer[256];
00930 
00931   if ((strlen(t)+4)>sizeof(buffer)) {
00932     DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
00933     return 0;
00934   }
00935 
00936   mode=GWEN_MsgEngine_GetMode(e);
00937   proto=GWEN_MsgEngine_GetProtocolVersion(e);
00938   if (!e->defs) {
00939     DBG_INFO(GWEN_LOGDOMAIN, "No definitions available");
00940     return 0;
00941   }
00942   n=e->defs;
00943   n=GWEN_XMLNode_GetChild(n);
00944 
00945   /* find type+"S" */
00946   strcpy(buffer, t);
00947   strcat(buffer,"S");
00948   while(n) {
00949     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
00950       p=GWEN_XMLNode_GetData(n);
00951       assert(p);
00952       if (strcasecmp(p, buffer)==0)
00953         break;
00954     }
00955     n=GWEN_XMLNode_Next(n);
00956   } /* while */
00957 
00958   if (!n) {
00959     DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t);
00960     return 0;
00961   }
00962 
00963   /* find approppriate group definition */
00964   if (!mode)
00965     mode="";
00966   n=GWEN_XMLNode_GetChild(n);
00967   if (!n) {
00968     DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
00969     return 0;
00970   }
00971 
00972   /* find type+"def" */
00973   strcpy(buffer, t);
00974   strcat(buffer,"def");
00975   while(n) {
00976     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
00977       p=GWEN_XMLNode_GetData(n);
00978       assert(p);
00979       if (strcasecmp(p, buffer)==0) {
00980         p=GWEN_XMLNode_GetProperty(n, pname,"");
00981         if (strcasecmp(p, pvalue)==0) {
00982           i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
00983           if (proto==0 || (int)proto==i || i==0) {
00984             i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
00985             if (version==0 || version==i) {
00986               p=GWEN_XMLNode_GetProperty(n, "mode","");
00987               if (strcasecmp(p, mode)==0 || !*p) {
00988                 DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found",
00989                           pname, pvalue);
00990                 return n;
00991               }
00992             }
00993           }
00994         }
00995       }
00996     }
00997     n=GWEN_XMLNode_Next(n);
00998   } /* while */
00999 
01000   DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found",
01001            pname,
01002            pvalue,
01003            version);
01004   return 0;
01005 }
01006 
01007 
01008 
01009 GWEN_XMLNODE *GWEN_MsgEngine_FindNodeByPropertyStrictProto(GWEN_MSGENGINE *e,
01010                                                            const char *t,
01011                                                            const char *pname,
01012                                                            int version,
01013                                                            const char *pvalue) {
01014   GWEN_XMLNODE *n;
01015   const char *p;
01016   int i;
01017   const char *mode;
01018   unsigned int proto;
01019   char buffer[256];
01020 
01021   if ((strlen(t)+4)>sizeof(buffer)) {
01022     DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
01023     return 0;
01024   }
01025 
01026   mode=GWEN_MsgEngine_GetMode(e);
01027   proto=GWEN_MsgEngine_GetProtocolVersion(e);
01028   if (!e->defs) {
01029     DBG_INFO(GWEN_LOGDOMAIN, "No definitions available");
01030     return 0;
01031   }
01032   n=e->defs;
01033   n=GWEN_XMLNode_GetChild(n);
01034 
01035   /* find type+"S" */
01036   strcpy(buffer, t);
01037   strcat(buffer,"S");
01038   while(n) {
01039     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
01040       p=GWEN_XMLNode_GetData(n);
01041       assert(p);
01042       if (strcasecmp(p, buffer)==0)
01043         break;
01044     }
01045     n=GWEN_XMLNode_Next(n);
01046   } /* while */
01047 
01048   if (!n) {
01049     DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t);
01050     return 0;
01051   }
01052 
01053   /* find approppriate group definition */
01054   if (!mode)
01055     mode="";
01056   n=GWEN_XMLNode_GetChild(n);
01057   if (!n) {
01058     DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
01059     return 0;
01060   }
01061 
01062   /* find type+"def" */
01063   strcpy(buffer, t);
01064   strcat(buffer,"def");
01065   while(n) {
01066     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
01067       p=GWEN_XMLNode_GetData(n);
01068       assert(p);
01069       if (strcasecmp(p, buffer)==0) {
01070         p=GWEN_XMLNode_GetProperty(n, pname,"");
01071         if (strcasecmp(p, pvalue)==0) {
01072           i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
01073           if (proto==0 || (int)proto==i) {
01074             i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
01075             if (version==0 || version==i) {
01076               p=GWEN_XMLNode_GetProperty(n, "mode","");
01077               if (strcasecmp(p, mode)==0 || !*p) {
01078                 DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found",
01079                           pname, pvalue);
01080                 return n;
01081               }
01082             }
01083           }
01084         }
01085       }
01086     }
01087     n=GWEN_XMLNode_Next(n);
01088   } /* while */
01089 
01090   DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found",
01091            pname,
01092            pvalue,
01093            version);
01094   return 0;
01095 }
01096 
01097 
01098 
01099 const char *GWEN_MsgEngine__TransformValue(GWEN_MSGENGINE *e,
01100                                            const char *pvalue,
01101                                            GWEN_XMLNODE *node,
01102                                            GWEN_XMLNODE *dnode,
01103                                            unsigned int *datasize) {
01104   const char *p;
01105   static char pbuffer[256];
01106   GWEN_DB_NODE *globalValues;
01107 
01108   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
01109   assert(globalValues);
01110 
01111   if (pvalue) {
01112     DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming value \"%s\"", pvalue);
01113     /* check whether the value is a property */
01114     p=pvalue;
01115     while (*p && isspace((int)*p))
01116       p++;
01117     if (*p=='$' || *p=='+') {
01118       /* global property */
01119       int incr;
01120 
01121       incr=(*p=='+');
01122       p++;
01123 
01124       DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p);
01125       if (incr) {
01126         int z;
01127 
01128         z=GWEN_DB_GetIntValue(globalValues, p, 0, 0);
01129         DBG_DEBUG(GWEN_LOGDOMAIN, "Incrementing global property \"%s\" (%d)",
01130                   p, z);
01131         if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
01132           DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
01133           return 0;
01134         }
01135 
01136         z++;
01137         DBG_DEBUG(GWEN_LOGDOMAIN, "Setting global property \"%s\"=%d", p, z);
01138         GWEN_DB_SetIntValue(globalValues,
01139                             GWEN_DB_FLAGS_DEFAULT |
01140                             GWEN_DB_FLAGS_OVERWRITE_VARS,
01141                             p, z);
01142         pvalue=pbuffer;
01143         *datasize=strlen(pvalue);
01144       }
01145       else {
01146         int z;
01147         GWEN_DB_NODE_TYPE vt;
01148         const char *type = "should_be_known";
01149         /* default value; otherwise the compiler issues a warning */
01150 
01151         DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p);
01152         vt=GWEN_DB_GetVariableType(globalValues, p);
01153         if (vt==GWEN_DB_NodeType_Unknown) {
01154           if (!GWEN_DB_VariableExists(globalValues, p)) {
01155             DBG_ERROR(GWEN_LOGDOMAIN, "Unable to determine type of \"%s\"", p);
01156             return 0;
01157           }
01158           type=GWEN_XMLNode_GetProperty(dnode, "type", "ascii");
01159           if (GWEN_MsgEngine__IsCharTyp(e, type))
01160             vt=GWEN_DB_NodeType_ValueChar;
01161           else if (GWEN_MsgEngine__IsIntTyp(e, type))
01162             vt=GWEN_DB_NodeType_ValueInt;
01163           else if (GWEN_MsgEngine__IsBinTyp(e, type))
01164             vt=GWEN_DB_NodeType_ValueBin;
01165           else {
01166             DBG_ERROR(GWEN_LOGDOMAIN,
01167                       "Unable to determine type of \"%s\" (xml)", p);
01168             return 0;
01169           }
01170         }
01171 
01172         switch(vt) {
01173         case GWEN_DB_NodeType_ValueChar:
01174           pvalue=GWEN_DB_GetCharValue(globalValues, p, 0, "");
01175           *datasize=strlen(pvalue);
01176           break;
01177 
01178         case GWEN_DB_NodeType_ValueInt:
01179           z=GWEN_DB_GetIntValue(globalValues, p, 0, 0);
01180           if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
01181             DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
01182             return 0;
01183           }
01184           pvalue=pbuffer;
01185           *datasize=strlen(pvalue);
01186           break;
01187 
01188         case GWEN_DB_NodeType_ValueBin:
01189           pvalue=GWEN_DB_GetBinValue(globalValues, p, 0,
01190                                      0,0,
01191                                      datasize);
01192           break;
01193 
01194         default:
01195           DBG_ERROR(GWEN_LOGDOMAIN,"Unknown type %s", type);
01196           return 0;
01197         } /* switch */
01198       }
01199       DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed");
01200     }
01201     else if (*p=='%') {
01202       /* local property */
01203       p++;
01204 
01205       DBG_DEBUG(GWEN_LOGDOMAIN, "Getting property \"%s\"", p);
01206       pvalue=GWEN_XMLNode_GetProperty(node, p, 0);
01207       if (pvalue) {
01208         *datasize=strlen(pvalue);
01209         DBG_DEBUG(GWEN_LOGDOMAIN, "Transformed value \"%s\"", pvalue);
01210       }
01211       else
01212         *datasize=0;
01213     }
01214     else if (*p=='?') {
01215       GWEN_DB_NODE_TYPE vt;
01216       int z;
01217       const char *dtype;
01218 
01219       /* get type */
01220       dtype=GWEN_XMLNode_GetProperty(dnode, "type","ASCII");
01221 
01222       /* program variable accessable via callback */
01223       p++;
01224       DBG_DEBUG(GWEN_LOGDOMAIN, "Getting program variable \"%s\"", p);
01225 
01226       pvalue=0;
01227       if (GWEN_MsgEngine__IsCharTyp(e, dtype))
01228         vt=GWEN_DB_NodeType_ValueChar;
01229       else if (GWEN_MsgEngine__IsIntTyp(e, dtype))
01230         vt=GWEN_DB_NodeType_ValueInt;
01231       else {
01232         vt=GWEN_DB_NodeType_ValueChar;
01233       }
01234 
01235       switch(vt) {
01236       case GWEN_DB_NodeType_ValueChar:
01237         if (e->getCharValuePtr) {
01238           pvalue=e->getCharValuePtr(e, p, 0);
01239           if (pvalue)
01240             *datasize=strlen(pvalue);
01241         }
01242         break;
01243 
01244       case GWEN_DB_NodeType_ValueInt:
01245         if (e->getIntValuePtr) {
01246           z=e->getIntValuePtr(e, p, 0);
01247           if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
01248             DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
01249             return 0;
01250           }
01251           pvalue=pbuffer;
01252           *datasize=strlen(pvalue);
01253         }
01254         else {
01255           DBG_NOTICE(GWEN_LOGDOMAIN, "Callback for getIntValue not set");
01256         }
01257         break;
01258 
01259       default:
01260         DBG_ERROR(GWEN_LOGDOMAIN,"Unhandled type %s", dtype);
01261         return 0;
01262       } /* switch */
01263 
01264       DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed");
01265     }
01266     else {
01267       *datasize=strlen(pvalue);
01268     }
01269   }
01270   return pvalue;
01271 }
01272 
01273 
01274 
01275 const char *GWEN_MsgEngine_SearchForProperty(GWEN_XMLNODE *node,
01276                                              GWEN_XMLNODE *refnode,
01277                                              const char *name,
01278                                              int topDown) {
01279   const char *pvalue;
01280   GWEN_XMLNODE *pn;
01281   const char *lastValue;
01282 
01283   DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in properties", name);
01284   lastValue=0;
01285 
01286   pvalue=GWEN_XMLNode_GetProperty(node, name,0);
01287   if (pvalue) {
01288     if (!topDown)
01289       return pvalue;
01290     DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue);
01291     lastValue=pvalue;
01292   }
01293 
01294   pn=refnode;
01295   while(pn) {
01296     pvalue=GWEN_XMLNode_GetProperty(pn, name,0);
01297     if (pvalue) {
01298       if (!topDown)
01299         return pvalue;
01300       DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue);
01301       lastValue=pvalue;
01302     }
01303     pn=GWEN_XMLNode_GetParent(pn);
01304   } /* while */
01305   return lastValue;
01306 }
01307 
01308 
01309 
01310 int GWEN_MsgEngine_GetHighestTrustLevel(GWEN_XMLNODE *node,
01311                                         GWEN_XMLNODE *refnode) {
01312   int value;
01313   GWEN_XMLNODE *pn;
01314   int highestTrust;
01315 
01316   highestTrust=0;
01317 
01318   value=atoi(GWEN_XMLNode_GetProperty(node, "trustlevel","0"));
01319   if (value>highestTrust)
01320     highestTrust=value;
01321 
01322   pn=node;
01323   while(pn) {
01324     value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0"));
01325     if (value>highestTrust)
01326       highestTrust=value;
01327     pn=GWEN_XMLNode_GetParent(pn);
01328   } /* while */
01329 
01330   pn=refnode;
01331   while(pn) {
01332     value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0"));
01333     if (value>highestTrust)
01334       highestTrust=value;
01335     pn=GWEN_XMLNode_GetParent(pn);
01336   } /* while */
01337   return highestTrust;
01338 }
01339 
01340 
01341 
01342 const char *GWEN_MsgEngine__SearchForValue(GWEN_MSGENGINE *e,
01343                                            GWEN_XMLNODE *node,
01344                                            GWEN_XMLNODE_PATH *nodePath,
01345                                            const char *name,
01346                                            unsigned int *datasize) {
01347   const char *pvalue;
01348   GWEN_XMLNODE *pn;
01349   char *bufferPtr;
01350   int topDown;
01351   const char *lastValue;
01352   unsigned int lastDataSize;
01353   unsigned int ldatasize;
01354 
01355   DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in <VALUES>",
01356             name);
01357   if (!node) {
01358     DBG_WARN(GWEN_LOGDOMAIN, "No node !");
01359   }
01360   topDown=atoi(GWEN_XMLNode_GetProperty(node, "topdown", "0"));
01361   lastValue=0;
01362   lastDataSize=0;
01363 
01364   bufferPtr=0;
01365 
01366   /*pn=GWEN_XMLNode_GetParent(node);*/
01367   pn=GWEN_XMLNode_Path_Surface(nodePath);
01368   while(pn) {
01369     const char *ppath;
01370     /*
01371     if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) {
01372       DBG_NOTICE(GWEN_LOGDOMAIN, "Checking node \"%s\"",
01373                  GWEN_XMLNode_GetData(pn));
01374                  }*/
01375     pvalue=GWEN_MsgEngine__findInValues(e, pn, node, name, &ldatasize);
01376     if (pvalue) {
01377       if (!topDown) {
01378         free(bufferPtr);
01379         *datasize=ldatasize;
01380         return pvalue;
01381       }
01382       DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value, but will look further");
01383       lastValue=pvalue;
01384       lastDataSize=ldatasize;
01385     }
01386 
01387     ppath=GWEN_XMLNode_GetProperty(pn, "name", "");
01388 
01389     if (*ppath) {
01390       int i;
01391       char *tmpptr;
01392 
01393       if (bufferPtr) {
01394         i=strlen(bufferPtr)+strlen(ppath)+2;
01395         tmpptr=(char*)malloc(i);
01396         assert(tmpptr);
01397         sprintf(tmpptr, "%s/%s", ppath, bufferPtr);
01398         free(bufferPtr);
01399         bufferPtr=tmpptr;
01400       }
01401       else {
01402         i=strlen(ppath)+strlen(name)+2;
01403         tmpptr=(char*)malloc(i);
01404         assert(tmpptr);
01405         sprintf(tmpptr, "%s/%s", ppath, name);
01406         bufferPtr=tmpptr;
01407       }
01408       name=bufferPtr;
01409     }
01410     pn=GWEN_XMLNode_Path_Surface(nodePath);
01411   } /* while */
01412 
01413   free(bufferPtr);
01414   if (!lastValue)
01415     *datasize=0;
01416   else
01417     *datasize=lastDataSize;
01418   return lastValue;
01419 }
01420 
01421 
01422 
01423 const char *GWEN_MsgEngine__findInValues(GWEN_MSGENGINE *e,
01424                                          GWEN_XMLNODE *node,
01425                                          GWEN_XMLNODE *dnode,
01426                                          const char *name,
01427                                          unsigned int *datasize) {
01428   GWEN_XMLNODE *pn;
01429 
01430   DBG_VERBOUS(GWEN_LOGDOMAIN, "Looking for value of \"%s\" in <VALUES>", name);
01431   pn=GWEN_XMLNode_GetChild(node);
01432 
01433   while(pn) {
01434     if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) {
01435       GWEN_XMLNODE *n;
01436       const char *p;
01437 
01438       p=GWEN_XMLNode_GetData(pn);
01439       assert(p);
01440       DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s", p);
01441       if (strcasecmp(p, "VALUES")==0) {
01442         DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found");
01443         /* <preset> found, check all values */
01444         n=GWEN_XMLNode_GetChild(pn);
01445         while(n) {
01446           if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
01447             p=GWEN_XMLNode_GetData(n);
01448             assert(p);
01449             if (strcasecmp(p, "VALUE")==0) {
01450               const char *pname;
01451               const char *pvalue;
01452 
01453               pname=GWEN_XMLNode_GetProperty(n, "path", 0);
01454               if (pname) {
01455                 DBG_DEBUG(GWEN_LOGDOMAIN, "Comparing against \"%s\"", pname);
01456                 if (strcasecmp(name, pname)==0) {
01457                   GWEN_XMLNODE *dn;
01458 
01459                   dn=GWEN_XMLNode_GetChild(n);
01460                   while (dn) {
01461                     if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) {
01462                       pvalue=GWEN_XMLNode_GetData(dn);
01463                       if (pvalue) {
01464                         DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming \"%s\"", pvalue);
01465                         pvalue=GWEN_MsgEngine__TransformValue(e,
01466                                                               pvalue,
01467                                                               node,
01468                                                               dnode,
01469                                                               datasize);
01470                       }
01471                       if (pvalue)
01472                         return pvalue;
01473                     }
01474                     dn=GWEN_XMLNode_Next(dn);
01475                   } /* while dn */
01476                 } /* if path matches name */
01477               } /* if path given */
01478             } /* if VALUE tag */
01479           } /* if TAG */
01480           n=GWEN_XMLNode_Next(n);
01481         } /* while */
01482         break;           /*  REMOVE this to check multiple groups */
01483       } /* if <preset> found */
01484     } /* if tag */
01485     pn=GWEN_XMLNode_Next(pn);
01486   } /* while node */
01487 
01488   DBG_DEBUG(GWEN_LOGDOMAIN, "No value found for \"%s\" in <VALUES>", name);
01489   return 0;
01490 }
01491 
01492 
01493 
01494 GWEN_XMLNODE *GWEN_MsgEngine__GetGroup(GWEN_MSGENGINE *e,
01495                                        GWEN_XMLNODE *node,
01496                                        const char *t,
01497                                        int version,
01498                                        const char *pvalue) {
01499   GWEN_XMLNODE *n;
01500   const char *p;
01501   int i;
01502   const char *mode;
01503   unsigned int proto;
01504   char buffer[256];
01505 
01506   if ((strlen(t)+4)>sizeof(buffer)) {
01507     DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
01508     return 0;
01509   }
01510 
01511   mode=GWEN_MsgEngine_GetMode(e);
01512   proto=GWEN_MsgEngine_GetProtocolVersion(e);
01513 
01514   /* find type+"S" */
01515   strcpy(buffer, t);
01516   strcat(buffer,"S");
01517   n=GWEN_XMLNode_FindFirstTag(node, buffer, 0, 0);
01518   if (!n) {
01519     DBG_DEBUG(GWEN_LOGDOMAIN,
01520               "No definitions here for type \"%s\"", t);
01521     return 0;
01522   }
01523 
01524   /* find approppriate group definition */
01525   if (!mode)
01526     mode="";
01527   n=GWEN_XMLNode_GetFirstTag(n);
01528   if (!n) {
01529     DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
01530     return 0;
01531   }
01532 
01533   /* find type+"def" */
01534   strcpy(buffer, t);
01535   strcat(buffer, "def");
01536   while(n) {
01537     p=GWEN_XMLNode_GetData(n);
01538     assert(p);
01539     if (strcasecmp(p, buffer)==0 ||
01540         strcasecmp(p, t)==0) {
01541       p=GWEN_XMLNode_GetProperty(n, "id", "");
01542       if (strcasecmp(p, pvalue)!=0)
01543         p=GWEN_XMLNode_GetProperty(n, "name", "");
01544       if (strcasecmp(p, pvalue)==0) {
01545         i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
01546         if (proto==0 || (int)proto==i || i==0) {
01547           i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
01548           if (version==0 || version==i) {
01549             p=GWEN_XMLNode_GetProperty(n, "mode","");
01550             if (strcasecmp(p, mode)==0 || !*p) {
01551               DBG_DEBUG(GWEN_LOGDOMAIN,
01552                         "Group definition for \"%s=%s\" found",
01553                         t, pvalue);
01554               return n;
01555             }
01556           }
01557         }
01558       }
01559     }
01560     n=GWEN_XMLNode_GetNextTag(n);
01561   } /* while */
01562 
01563   DBG_DEBUG(GWEN_LOGDOMAIN,
01564             "Group definition for \"%s=%s\"(%d) not found here",
01565             t,
01566             pvalue,
01567             version);
01568   return 0;
01569 }
01570 
01571 
01572 
01573 GWEN_XMLNODE *GWEN_MsgEngine_GetGroup(GWEN_MSGENGINE *e,
01574                                       GWEN_XMLNODE *node,
01575                                       const GWEN_XMLNODE_PATH *nodePath,
01576                                       const char *t,
01577                                       int version,
01578                                       const char *pvalue) {
01579   GWEN_XMLNODE *n;
01580   GWEN_XMLNODE *nLast = 0;
01581   GWEN_XMLNODE *nRes = 0;
01582   GWEN_XMLNODE_PATH *pathCopy;
01583 
01584   assert(node);
01585   assert(nodePath);
01586   assert(t);
01587   assert(pvalue);
01588 
01589   pathCopy=GWEN_XMLNode_Path_dup(nodePath);
01590   n=GWEN_XMLNode_Path_Surface(pathCopy);
01591   /* first try all nodes along the path */
01592   while(n) {
01593     nLast=n;
01594     nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue);
01595     if (nRes)
01596       break;
01597     n=GWEN_XMLNode_Path_Surface(pathCopy);
01598   }
01599   GWEN_XMLNode_Path_free(pathCopy);
01600   if (nRes) {
01601     /* already found */
01602     if (nRes==node) {
01603       DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected.");
01604       return 0;
01605     }
01606     return nRes;
01607   }
01608 
01609   if (nLast)
01610     n=nLast;
01611   else
01612     n=node;
01613 
01614   if (n) {
01615     n=GWEN_XMLNode_GetParent(n);
01616     while(n) {
01617       nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue);
01618       if (nRes)
01619         break;
01620       n=GWEN_XMLNode_GetParent(n);
01621     }
01622   }
01623 
01624   /* try root as a last resort */
01625   if (!nRes && e->defs)
01626     nRes=GWEN_MsgEngine__GetGroup(e, e->defs, t, version, pvalue);
01627 
01628   if (!nRes) {
01629     DBG_DEBUG(GWEN_LOGDOMAIN,
01630               "Group definition for \"%s=%s\"(%d) not found",
01631               t,
01632               pvalue,
01633               version);
01634     return 0;
01635   }
01636   if (nRes==node) {
01637     DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected.");
01638     return 0;
01639   }
01640   return nRes;
01641 }
01642 
01643 
01644 
01645 int GWEN_MsgEngine__WriteGroup(GWEN_MSGENGINE *e,
01646                                GWEN_BUFFER *gbuf,
01647                                GWEN_XMLNODE *node,
01648                                GWEN_XMLNODE *rnode,
01649                                GWEN_DB_NODE *gr,
01650                                int groupIsOptional,
01651                                GWEN_XMLNODE_PATH *nodePath) {
01652   GWEN_XMLNODE *n;
01653   const char *p;
01654   char delimiter;
01655   char terminator;
01656   int isFirstElement;
01657   int omittedElements;
01658   int hasEntries;
01659 
01660 
01661   /* get some settings */
01662   if (rnode) {
01663     /* get delimiter */
01664     p=GWEN_XMLNode_GetProperty(rnode,
01665                                "delimiter",
01666                                GWEN_XMLNode_GetProperty(node,
01667                                                         "delimiter",
01668                                                         ""));
01669     delimiter=*p;
01670 
01671     /* get terminating char, if any */
01672     p=GWEN_XMLNode_GetProperty(rnode,
01673                                "terminator",
01674                                GWEN_XMLNode_GetProperty(node,
01675                                                         "terminator",
01676                                                         ""));
01677     terminator=*p;
01678   }
01679   else {
01680     /* get delimiter */
01681     p=GWEN_XMLNode_GetProperty(node,
01682                                "delimiter",
01683                                "");
01684     delimiter=*p;
01685 
01686     /* get terminating char, if any */
01687     p=GWEN_XMLNode_GetProperty(node, "terminator","");
01688     terminator=*p;
01689   }
01690 
01691   /* handle all child entries */
01692   n=GWEN_XMLNode_GetChild(node);
01693   isFirstElement=1;
01694   omittedElements=0;
01695   hasEntries=0;
01696   if (!n) {
01697     DBG_INFO(GWEN_LOGDOMAIN, "No subnodes !");
01698   }
01699   while(n) {
01700     int t;
01701     unsigned int minnum;
01702     unsigned int maxnum;
01703     int gversion;
01704     const char *addEmptyMode;
01705     unsigned int loopNr;
01706 
01707     minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
01708     maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
01709     gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
01710     addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one");
01711 
01712     DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements);
01713     t=GWEN_XMLNode_GetType(n);
01714     if (t==GWEN_XMLNodeTypeTag) {
01715       const char *typ;
01716 
01717       typ=GWEN_XMLNode_GetData(n);
01718       if (typ==0) {
01719         DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
01720         return -1;
01721       }
01722       if (strcasecmp(typ, "ELEM")==0) {
01723         /* element tag found */
01724         int j;
01725         int rv;
01726 
01727         DBG_VERBOUS(GWEN_LOGDOMAIN, "Found an element");
01728         /* write element as often as needed */
01729         for (loopNr=0; loopNr<maxnum; loopNr++) {
01730           unsigned int posBeforeElement;
01731 
01732           posBeforeElement=GWEN_Buffer_GetPos(gbuf);
01733 
01734           /* write delimiter, if needed */
01735           if (delimiter) {
01736             DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters",
01737                         omittedElements);
01738             for (j=0; j<omittedElements; j++) {
01739               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01740                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01741                 return -1;
01742               }
01743             }
01744             if (!isFirstElement)
01745               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01746                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01747                 return -1;
01748               }
01749           }
01750 
01751           rv=GWEN_MsgEngine__WriteElement(e,
01752                                           gbuf,
01753                                           n,
01754                                           rnode,
01755                                           gr,
01756                                           loopNr,
01757                                           loopNr>=minnum ||
01758                                           (groupIsOptional && !hasEntries),
01759                                           nodePath);
01760           if (rv==-1) {
01761             DBG_INFO(GWEN_LOGDOMAIN, "Error writing element");
01762             DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
01763             GWEN_XMLNode_Dump(n, 1);
01764             if (gr) {
01765               DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
01766               GWEN_DB_Dump(gr, 1);
01767             }
01768             return -1;
01769           }
01770           else if (rv==0) {
01771             isFirstElement=0;
01772             omittedElements=0;
01773             hasEntries=1;
01774             DBG_DEBUG(GWEN_LOGDOMAIN, "Element written");
01775           }
01776           else {
01777             /* element is optional, not found */
01778             /* restore position */
01779             GWEN_Buffer_SetPos(gbuf, posBeforeElement);
01780             GWEN_Buffer_Crop(gbuf, 0, posBeforeElement);
01781 
01782             if (strcasecmp(addEmptyMode, "max")==0) {
01783               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty");
01784               omittedElements+=(maxnum-loopNr);
01785             }
01786             else if (strcasecmp(addEmptyMode, "min")==0) {
01787               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty");
01788               if (loopNr<minnum)
01789                 omittedElements+=(minnum-loopNr);
01790             }
01791             else if (strcasecmp(addEmptyMode, "one")==0) {
01792               if (loopNr==0)
01793                 omittedElements++;
01794             }
01795             else if (strcasecmp(addEmptyMode, "none")==0) {
01796             }
01797             else {
01798               DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
01799                         addEmptyMode);
01800               return -1;
01801             }
01802             break;
01803           }
01804         } /* for */
01805       }
01806       else if (strcasecmp(typ, "VALUES")==0) {
01807       }
01808       else if (strcasecmp(typ, "DESCR")==0) {
01809       }
01810       else {
01811         /* group tag found */
01812         GWEN_XMLNODE *gn;
01813         GWEN_DB_NODE *gcfg;
01814         const char *gname;
01815         const char *gtype;
01816         unsigned int posBeforeGroup;
01817 
01818         DBG_VERBOUS(GWEN_LOGDOMAIN, "Found a group");
01819 
01820         gcfg=0;
01821         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
01822         if (!gtype) {
01823           /* no "type" property, so use this group directly */
01824           DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
01825           gtype="";
01826           gn=n;
01827         }
01828         else {
01829           DBG_VERBOUS(GWEN_LOGDOMAIN, "<%s> tag is of type \"%s\"", typ, gtype);
01830           gn=GWEN_MsgEngine_GetGroup(e, n, nodePath, typ,
01831                                      gversion, gtype);
01832           if (!gn) {
01833             DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
01834             return -1;
01835           }
01836         }
01837 
01838         gname=NULL;
01839         gcfg=NULL;
01840         if (gr) {
01841           gname=GWEN_XMLNode_GetProperty(n, "name",0);
01842           if (gname) {
01843             DBG_VERBOUS(GWEN_LOGDOMAIN, "Group \"%s\" using special data", gname);
01844             gcfg=GWEN_DB_FindFirstGroup(gr, gname);
01845           }
01846           else {
01847             DBG_DEBUG(GWEN_LOGDOMAIN, "Unnamed group, using basic data");
01848             /* TODO: check for maxnum==1, since only then the following line makes sense */
01849             gcfg=gr;
01850           }
01851         }
01852 
01853         /* write group as often as needed */
01854         for (loopNr=0; loopNr<maxnum; loopNr++) {
01855           int rv;
01856           int groupIsEmpty;
01857 
01858           groupIsEmpty=0;
01859           posBeforeGroup=GWEN_Buffer_GetPos(gbuf);
01860 
01861           /* write delimiter, if needed */
01862           if (delimiter) {
01863             int j;
01864 
01865             DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters",
01866                         omittedElements);
01867             for (j=0; j<omittedElements; j++) {
01868               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01869                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01870                 return -1;
01871               }
01872             }
01873             if (!isFirstElement)
01874               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01875                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01876                 return -1;
01877               }
01878           }
01879 
01880           /* find next matching group */
01881           if (gcfg==0) {
01882             DBG_DEBUG(GWEN_LOGDOMAIN, "No group found");
01883             if (loopNr>=minnum)
01884               groupIsEmpty=1;
01885           }
01886 
01887           if (groupIsEmpty) {
01888             /* empty group, flag as such */
01889             rv=1;
01890           }
01891           else {
01892             int dive;
01893 
01894             /* write group */
01895             if (GWEN_XMLNode_Path_Dive(nodePath, n)) {
01896               DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
01897               return -1;
01898             }
01899             if (n==gn)
01900               dive=1;
01901             else {
01902               if (GWEN_XMLNode_Path_Dive(nodePath, gn)) {
01903                 DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
01904                 return -1;
01905               }
01906               dive=2;
01907             }
01908             rv=GWEN_MsgEngine__WriteGroup(e,
01909                                           gbuf,
01910                                           gn,
01911                                           n,
01912                                           gcfg,
01913                                           loopNr>=minnum || groupIsOptional,
01914                                           nodePath);
01915             GWEN_XMLNode_Path_Surface(nodePath);
01916             if (dive==2)
01917               GWEN_XMLNode_Path_Surface(nodePath);
01918           }
01919 
01920           if (rv==-1) {
01921             DBG_INFO(GWEN_LOGDOMAIN, "Could not write group \"%s\"", gtype);
01922             if (gn) {
01923               DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
01924               GWEN_XMLNode_Dump(gn, 1);
01925             }
01926             if (n) {
01927               DBG_INFO(GWEN_LOGDOMAIN, "Referring node is:");
01928               GWEN_XMLNode_Dump(n, 1);
01929             }
01930             if (gr) {
01931               DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
01932               GWEN_DB_Dump(gr, 1);
01933             }
01934             return -1;
01935           }
01936           else if (rv==0) {
01937             isFirstElement=0;
01938             omittedElements=0;
01939             hasEntries=1;
01940             DBG_DEBUG(GWEN_LOGDOMAIN, "Element written");
01941           }
01942           else {
01943             /* group is optional, not found */
01944             /* restore position */
01945             GWEN_Buffer_SetPos(gbuf, posBeforeGroup);
01946             GWEN_Buffer_Crop(gbuf, 0, posBeforeGroup);
01947 
01948             if (strcasecmp(addEmptyMode, "max")==0) {
01949               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty");
01950               omittedElements+=(maxnum-loopNr);
01951             }
01952             else if (strcasecmp(addEmptyMode, "min")==0) {
01953               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty");
01954               if (loopNr<minnum)
01955                 omittedElements+=(minnum-loopNr);
01956             }
01957             else if (strcasecmp(addEmptyMode, "one")==0) {
01958               if (loopNr==0)
01959                 omittedElements++;
01960             }
01961             else if (strcasecmp(addEmptyMode, "none")==0) {
01962             }
01963             else {
01964               DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
01965                         addEmptyMode);
01966               return -1;
01967             }
01968             break;
01969           }
01970 
01971           /* use next group next time if any */
01972           if (gcfg && gname)
01973             gcfg=GWEN_DB_FindNextGroup(gcfg, gname);
01974         } /* for */
01975       } /* if "GROUP" */
01976     } /* if TAG */
01977     else if (t==GWEN_XMLNodeTypeData) {
01978     }
01979     else {
01980       DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled node type %d", t);
01981     }
01982     n=GWEN_XMLNode_Next(n);
01983   } /* while */
01984 
01985   /* write terminating character, if any */
01986   if (terminator) {
01987     if (GWEN_Buffer_AppendByte(gbuf, terminator)) {
01988       DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01989       return -1;
01990     }
01991   }
01992 
01993   if (!hasEntries) {
01994     DBG_INFO(GWEN_LOGDOMAIN, "No entries in node");
01995   }
01996   return hasEntries?0:1;
01997 }
01998 
01999 
02000 
02001 int GWEN_MsgEngine_CreateMessageFromNode(GWEN_MSGENGINE *e,
02002                                          GWEN_XMLNODE *node,
02003                                          GWEN_BUFFER *gbuf,
02004                                          GWEN_DB_NODE *msgData){
02005   GWEN_XMLNODE_PATH *np;
02006   int rv;
02007 
02008   assert(e);
02009   assert(node);
02010   assert(msgData);
02011 
02012   np=GWEN_XMLNode_Path_new();
02013   GWEN_XMLNode_Path_Dive(np, node);
02014   rv=GWEN_MsgEngine__WriteGroup(e,
02015                                 gbuf,
02016                                 node,
02017                                 0,
02018                                 msgData,
02019                                 0,
02020                                 np);
02021   GWEN_XMLNode_Path_free(np);
02022   if (rv){
02023     const char *p;
02024 
02025     p=GWEN_XMLNode_GetData(node);
02026     if (p) {
02027       DBG_INFO(GWEN_LOGDOMAIN, "Error writing group \"%s\"", p);
02028     }
02029     else {
02030       DBG_INFO(GWEN_LOGDOMAIN, "Error writing group");
02031     }
02032     return -1;
02033   }
02034 
02035   return 0;
02036 }
02037 
02038 
02039 
02040 int GWEN_MsgEngine_CreateMessage(GWEN_MSGENGINE *e,
02041                                  const char *msgName,
02042                                  int msgVersion,
02043                                  GWEN_BUFFER *gbuf,
02044                                  GWEN_DB_NODE *msgData) {
02045   GWEN_XMLNODE *group;
02046 
02047   group=GWEN_MsgEngine_FindGroupByProperty(e, "id", msgVersion, msgName);
02048   if (!group) {
02049     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
02050     return -1;
02051   }
02052   return GWEN_MsgEngine_CreateMessageFromNode(e,
02053                                               group,
02054                                               gbuf,
02055                                               msgData);
02056 }
02057 
02058 
02059 
02060 int GWEN_MsgEngine_AddDefinitions(GWEN_MSGENGINE *e,
02061                                   GWEN_XMLNODE *node) {
02062   GWEN_XMLNODE *nsrc, *ndst;
02063 
02064   assert(e);
02065   assert(node);
02066 
02067   if (!e->defs) {
02068     e->defs=GWEN_XMLNode_dup(node);
02069     e->ownDefs=1;
02070     return 0;
02071   }
02072 
02073   nsrc=GWEN_XMLNode_GetChild(node);
02074   while(nsrc) {
02075     if (GWEN_XMLNode_GetType(nsrc)==GWEN_XMLNodeTypeTag) {
02076       ndst=GWEN_XMLNode_FindNode(e->defs, GWEN_XMLNodeTypeTag,
02077                                  GWEN_XMLNode_GetData(nsrc));
02078       if (ndst) {
02079         GWEN_XMLNODE *n;
02080 
02081         n=GWEN_XMLNode_GetChild(nsrc);
02082         while (n) {
02083           GWEN_XMLNODE *newNode;
02084 
02085           DBG_DEBUG(GWEN_LOGDOMAIN, "Adding node \"%s\"", GWEN_XMLNode_GetData(n));
02086           newNode=GWEN_XMLNode_dup(n);
02087           GWEN_XMLNode_AddChild(ndst, newNode);
02088           n=GWEN_XMLNode_Next(n);
02089         } /* while n */
02090       }
02091       else {
02092         GWEN_XMLNODE *newNode;
02093 
02094         DBG_DEBUG(GWEN_LOGDOMAIN, "Adding branch \"%s\"", GWEN_XMLNode_GetData(nsrc));
02095         newNode=GWEN_XMLNode_dup(nsrc);
02096         GWEN_XMLNode_AddChild(e->defs, newNode);
02097       }
02098     } /* if TAG */
02099     nsrc=GWEN_XMLNode_Next(nsrc);
02100   } /* while */
02101 
02102   return 0;
02103 }
02104 
02105 
02106 
02107 int GWEN_MsgEngine__ShowElement(GWEN_UNUSED GWEN_MSGENGINE *e,
02108                                 const char *path,
02109                                 GWEN_XMLNODE *node,
02110                                 GWEN_STRINGLIST *sl,
02111                                 uint32_t flags) {
02112   const char *name;
02113   const char *type;
02114   const char *npath;
02115   unsigned int minsize;
02116   unsigned int maxsize;
02117   unsigned int minnum;
02118   unsigned int maxnum;
02119   int j;
02120   int isSet;
02121   char nbuffer[256];
02122   GWEN_STRINGLISTENTRY *en;
02123 
02124   /* get type */
02125   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02126 
02127   /* get some sizes */
02128   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
02129   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
02130   minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
02131   maxnum=atoi(GWEN_XMLNode_GetProperty(node, "maxnum","1"));
02132 
02133   npath="";
02134   isSet=0;
02135 
02136   /* get name */
02137   name=GWEN_XMLNode_GetProperty(node, "name", 0);
02138   if (path==0)
02139     path="";
02140 
02141   if (name) {
02142     /* get value of a config variable */
02143     if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
02144       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02145       return -1;
02146     }
02147     if (*path)
02148       sprintf(nbuffer, "%s/%s", path, name);
02149     else
02150       sprintf(nbuffer, "%s", name);
02151     npath=nbuffer;
02152   }
02153 
02154   en=GWEN_StringList_FirstEntry(sl);
02155   while(en) {
02156     if (GWEN_StringListEntry_Data(en))
02157       if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
02158         isSet=1;
02159         break;
02160       }
02161     en=GWEN_StringListEntry_Next(en);
02162   } /* while */
02163 
02164   if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
02165     return 0;
02166 
02167   fprintf(stdout, "  %s",
02168           npath);
02169   j=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(npath);
02170   if (j>0) {
02171     int i;
02172 
02173     for (i=0; i<j; i++)
02174       fprintf(stdout, " ");
02175   }
02176   fprintf(stdout, "| %s", type);
02177   j=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(type);
02178   if (j>0) {
02179     int i;
02180 
02181     for (i=0; i<j; i++)
02182       fprintf(stdout, " ");
02183   }
02184   fprintf(stdout, "| %4d-%4d", minsize, maxsize);
02185   fprintf(stdout," | %3d ", maxnum);
02186   fprintf(stdout," |");
02187   if (minnum==0)
02188     fprintf(stdout," optvar");
02189   if (flags & GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL)
02190     fprintf(stdout," optgrp");
02191 
02192   if (isSet) {
02193     fprintf(stdout," set");
02194   }
02195 
02196   fprintf(stdout,"\n");
02197 
02198   return 0;
02199 }
02200 
02201 
02202 
02203 int GWEN_MsgEngine__ShowGroup(GWEN_MSGENGINE *e,
02204                               const char *path,
02205                               GWEN_XMLNODE *node,
02206                               GWEN_XMLNODE *rnode,
02207                               GWEN_STRINGLIST *sl,
02208                               uint32_t flags) {
02209   GWEN_XMLNODE *n;
02210   int isFirstElement;
02211   int omittedElements;
02212   int rv;
02213 
02214   /* setup data */
02215   n=GWEN_XMLNode_GetChild(node);
02216 
02217   if (path==0)
02218     path="";
02219   if (*path=='/')
02220     path++;
02221 
02222   while(n) {
02223     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02224       const char *p;
02225 
02226       p=GWEN_XMLNode_GetData(n);
02227       assert(p);
02228       DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
02229       if (strcasecmp(p, "VALUES")==0)
02230         break;
02231     } /* if tag */
02232     n=GWEN_XMLNode_Next(n);
02233   } /* while */
02234 
02235   if (n) {
02236     DBG_DEBUG(GWEN_LOGDOMAIN, "<preset> found");
02237     /* <preset> found, handle all values */
02238     n=GWEN_XMLNode_GetChild(n);
02239     while(n) {
02240       if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02241         const char *p;
02242 
02243         p=GWEN_XMLNode_GetData(n);
02244         assert(p);
02245         if (strcasecmp(p, "VALUE")==0) {
02246           const char *pname;
02247           const char *pvalue;
02248 
02249           pname=GWEN_XMLNode_GetProperty(n, "path", 0);
02250           if (pname) {
02251             GWEN_XMLNODE *dn;
02252 
02253             /* path found, find data */
02254             dn=GWEN_XMLNode_GetChild(n);
02255             while (dn) {
02256               if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) {
02257                 pvalue=GWEN_XMLNode_GetData(dn);
02258                 if (pvalue) {
02259                   char pbuffer[256];
02260 
02261                   /* check whether the value is a property */
02262                   p=pvalue;
02263                   while (*p && isspace((int)*p))
02264                     p++;
02265                   if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
02266                     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02267                     return -1;
02268                   }
02269                   if (*path)
02270                     sprintf(pbuffer, "%s/%s", path, pname);
02271                   else
02272                     sprintf(pbuffer, "%s", pname);
02273                   GWEN_StringList_AppendString(sl,
02274                                                pbuffer,
02275                                                0,
02276                                                1);
02277                 }
02278                 break;
02279               }
02280               dn=GWEN_XMLNode_Next(dn);
02281             } /* while dn */
02282           } /* if path given */
02283         } /* if VALUE tag */
02284       } /* if TAG */
02285       n=GWEN_XMLNode_Next(n);
02286     } /* while */
02287   } /* if <preset> found */
02288 
02289   /* now handle all child entries */
02290   n=GWEN_XMLNode_GetChild(node);
02291   isFirstElement=1;
02292   omittedElements=0;
02293   while(n) {
02294     int t;
02295     unsigned int minnum;
02296     unsigned int maxnum;
02297     int gversion;
02298     const char *addEmptyMode;
02299     unsigned int loopNr;
02300     unsigned int lflags;
02301 
02302     minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
02303     maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
02304     gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
02305     addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one");
02306 
02307     lflags=flags;
02308 
02309     DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements);
02310     t=GWEN_XMLNode_GetType(n);
02311     if (t==GWEN_XMLNodeTypeTag) {
02312       const char *typ;
02313 
02314       typ=GWEN_XMLNode_GetData(n);
02315       if (typ==0) {
02316         DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
02317         return -1;
02318       }
02319       if (strcasecmp(typ, "ELEM")==0) {
02320         /* element tag found */
02321 
02322         /* write element as often as needed */
02323         rv=GWEN_MsgEngine__ShowElement(e,
02324                                        path,
02325                                        n,
02326                                        sl,
02327                                        lflags);
02328         if (rv==-1)
02329           return -1;
02330         else {
02331           isFirstElement=0;
02332           omittedElements=0;
02333         }
02334       }
02335       else if (strcasecmp(typ, "VALUES")==0) {
02336       }
02337       else if (strcasecmp(typ, "DESCR")==0) {
02338       }
02339       else {
02340         /* group tag found */
02341         GWEN_XMLNODE *gn;
02342         const char *gname;
02343         const char *gtype;
02344 
02345         if (minnum==0)
02346           lflags|=GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL;
02347 
02348         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
02349         if (!gtype) {
02350           /* no "type" property, so use this group directly */
02351           DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
02352           gtype="";
02353           gn=n;
02354         }
02355         else {
02356           gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
02357           if (!gn) {
02358             DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
02359             return -1;
02360           }
02361         }
02362 
02363         /* write group as often as needed */
02364         for (loopNr=0; loopNr<maxnum; loopNr++) {
02365           /* find group */
02366           char pbuffer[256];
02367           const char *npath;
02368 
02369           /* get configuration */
02370           gname=GWEN_XMLNode_GetProperty(n, "name",0);
02371           if (gname) {
02372             if (loopNr==0) {
02373               if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
02374                 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02375                 return -1;
02376               }
02377               sprintf(pbuffer, "%s/%s", path, gname);
02378               npath=pbuffer;
02379             }
02380             else {
02381               /* this is not the first one, so create new name */
02382               if (strlen(path)+strlen(gname)+10>sizeof(pbuffer)) {
02383                 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02384                 return -1;
02385               }
02386               if (*path)
02387                 sprintf(pbuffer, "%s/%s%d", path, gname, loopNr);
02388               else
02389                 sprintf(pbuffer, "%s%d", gname, loopNr);
02390               /* get the value of the given var */
02391               npath=pbuffer;
02392             }
02393           } /* if name given */
02394           else
02395             npath=path;
02396 
02397           /* write group */
02398           if (GWEN_MsgEngine__ShowGroup(e,
02399                                         npath,
02400                                         gn,
02401                                         n,
02402                                         sl,
02403                                         lflags)) {
02404             DBG_INFO(GWEN_LOGDOMAIN, "Could not show group \"%s\"", gtype);
02405             return -1;
02406           }
02407         } /* for */
02408       }
02409     }
02410     n=GWEN_XMLNode_Next(n);
02411   } /* while */
02412 
02413   return 0;
02414 }
02415 
02416 
02417 
02418 int GWEN_MsgEngine_ShowMessage(GWEN_MSGENGINE *e,
02419                                const char *typ,
02420                                const char *msgName,
02421                                int msgVersion,
02422                                uint32_t flags) {
02423   GWEN_XMLNODE *group;
02424   GWEN_STRINGLIST *sl;
02425   int i, j;
02426   const char *p;
02427 
02428   sl=GWEN_StringList_new();
02429 
02430   fprintf(stdout, "Message \"%s\" version %d\n",
02431           msgName, msgVersion);
02432   for (i=0; i<76; i++)
02433     fprintf(stdout, "=");
02434   fprintf(stdout, "\n");
02435   p="        Variable";
02436   fprintf(stdout, "%s", p);
02437   i=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(p);
02438   for (j=0; j<i; j++)
02439     fprintf(stdout," ");
02440 
02441   fprintf(stdout,"  |");
02442   p=" Type";
02443   fprintf(stdout, "%s", p);
02444   i=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(p);
02445   for (j=0; j<i; j++)
02446     fprintf(stdout," ");
02447 
02448   fprintf(stdout," |   Size    | Num  | Flags\n");
02449   for (i=0; i<76; i++)
02450     fprintf(stdout, "-");
02451   fprintf(stdout, "\n");
02452 
02453   group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
02454   if (!group) {
02455     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
02456     GWEN_StringList_free(sl);
02457     return -1;
02458   }
02459 
02460   if (GWEN_MsgEngine__ShowGroup(e,
02461                                 "",
02462                                 group,
02463                                 0,
02464                                 sl,
02465                                 flags)) {
02466     DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
02467     GWEN_StringList_free(sl);
02468     return -1;
02469   }
02470 
02471   GWEN_StringList_free(sl);
02472 
02473   return 0;
02474 }
02475 
02476 
02477 
02478 int GWEN_MsgEngine__ListElement(GWEN_UNUSED GWEN_MSGENGINE *e,
02479                                 const char *path,
02480                                 GWEN_XMLNODE *node,
02481                                 GWEN_STRINGLIST *sl,
02482                                 GWEN_XMLNODE *listNode,
02483                                 uint32_t flags) {
02484   const char *name;
02485   const char *type;
02486   const char *npath;
02487   int isSet;
02488   char nbuffer[256];
02489   GWEN_STRINGLISTENTRY *en;
02490   GWEN_XMLNODE *nn;
02491 
02492   /* get type */
02493   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02494 
02495   npath="";
02496   isSet=0;
02497 
02498   /* get name */
02499   name=GWEN_XMLNode_GetProperty(node, "name", 0);
02500   if (path==0)
02501     path="";
02502 
02503   if (name) {
02504     /* get value of a config variable */
02505     if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
02506       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02507       return -1;
02508     }
02509     if (*path)
02510       sprintf(nbuffer, "%s/%s", path, name);
02511     else
02512       sprintf(nbuffer, "%s", name);
02513     npath=nbuffer;
02514   }
02515 
02516   en=GWEN_StringList_FirstEntry(sl);
02517   while(en) {
02518     if (GWEN_StringListEntry_Data(en))
02519       if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
02520         isSet=1;
02521         break;
02522       }
02523     en=GWEN_StringListEntry_Next(en);
02524   } /* while */
02525 
02526   if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
02527     return 0;
02528 
02529   nn=GWEN_XMLNode_dup(node);
02530   if (isSet)
02531     GWEN_XMLNode_SetProperty(nn, "GWEN_set", "1");
02532   GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
02533   GWEN_XMLNode_AddChild(listNode, nn);
02534 
02535   return 0;
02536 }
02537 
02538 
02539 
02540 int GWEN_MsgEngine__ListGroup(GWEN_MSGENGINE *e,
02541                               const char *path,
02542                               GWEN_XMLNODE *node,
02543                               GWEN_XMLNODE *rnode,
02544                               GWEN_STRINGLIST *sl,
02545                               GWEN_XMLNODE *listNode,
02546                               uint32_t flags) {
02547   GWEN_XMLNODE *n;
02548   int rv;
02549 
02550   /* setup data */
02551   n=GWEN_XMLNode_GetChild(node);
02552 
02553   if (path==0)
02554     path="";
02555   if (*path=='/')
02556     path++;
02557 
02558   while(n) {
02559     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02560       const char *p;
02561 
02562       p=GWEN_XMLNode_GetData(n);
02563       assert(p);
02564       DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
02565       if (strcasecmp(p, "VALUES")==0)
02566         break;
02567     } /* if tag */
02568     n=GWEN_XMLNode_Next(n);
02569   } /* while */
02570 
02571   if (n) {
02572     DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found");
02573     /* <values> found, handle all values */
02574     n=GWEN_XMLNode_GetChild(n);
02575     while(n) {
02576       if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02577         const char *p;
02578 
02579         p=GWEN_XMLNode_GetData(n);
02580         assert(p);
02581         if (strcasecmp(p, "VALUE")==0) {
02582           const char *pname;
02583           const char *pvalue;
02584 
02585           pname=GWEN_XMLNode_GetProperty(n, "path", 0);
02586           if (pname) {
02587             GWEN_XMLNODE *dn;
02588 
02589             /* path found, find data */
02590             dn=GWEN_XMLNode_GetChild(n);
02591             while (dn) {
02592               if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) {
02593                 pvalue=GWEN_XMLNode_GetData(dn);
02594                 if (pvalue) {
02595                   char pbuffer[256];
02596 
02597                   /* check whether the value is a property */
02598                   p=pvalue;
02599                   while (*p && isspace((int)*p))
02600                     p++;
02601                   if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
02602                     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02603                     return -1;
02604                   }
02605                   if (*path)
02606                     sprintf(pbuffer, "%s/%s", path, pname);
02607                   else
02608                       sprintf(pbuffer, "%s", pname);
02609                   DBG_INFO(GWEN_LOGDOMAIN, "Found preset value for %s", pbuffer);
02610                   GWEN_StringList_AppendString(sl,
02611                                                pbuffer,
02612                                                0,
02613                                                1);
02614                 }
02615                 break;
02616               }
02617               dn=GWEN_XMLNode_Next(dn);
02618             } /* while dn */
02619           } /* if path given */
02620         } /* if VALUE tag */
02621       } /* if TAG */
02622       n=GWEN_XMLNode_Next(n);
02623     } /* while */
02624   } /* if <values> found */
02625 
02626   /* now handle all child entries */
02627   n=GWEN_XMLNode_GetChild(node);
02628   while(n) {
02629     int t;
02630     int gversion;
02631     unsigned int lflags;
02632 
02633     gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
02634     lflags=flags;
02635 
02636     t=GWEN_XMLNode_GetType(n);
02637     if (t==GWEN_XMLNodeTypeTag) {
02638       const char *typ;
02639 
02640       typ=GWEN_XMLNode_GetData(n);
02641       if (typ==0) {
02642         DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
02643         return -1;
02644       }
02645       if (strcasecmp(typ, "ELEM")==0) {
02646         /* element tag found */
02647 
02648         /* list element */
02649         rv=GWEN_MsgEngine__ListElement(e,
02650                                        path,
02651                                        n,
02652                                        sl,
02653                                        listNode,
02654                                        lflags);
02655         if (rv==-1)
02656           return -1;
02657       }
02658       else if (strcasecmp(typ, "VALUES")==0) {
02659       }
02660       else if (strcasecmp(typ, "DESCR")==0) {
02661       }
02662       else {
02663         /* group tag found */
02664         GWEN_XMLNODE *gn;
02665         GWEN_XMLNODE *nn;
02666         const char *gname;
02667         const char *gtype;
02668         char pbuffer[256];
02669         const char *npath;
02670 
02671         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
02672         if (!gtype) {
02673           /* no "type" property, so use this group directly */
02674           DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
02675           gtype="";
02676           gn=n;
02677         }
02678         else {
02679           gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
02680           if (!gn) {
02681             DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
02682             return -1;
02683           }
02684         }
02685 
02686         /* get configuration */
02687         gname=GWEN_XMLNode_GetProperty(n, "name",0);
02688         if (gname) {
02689           if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
02690             DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02691             return -1;
02692           }
02693 
02694           if (*path)
02695             sprintf(pbuffer, "%s/%s", path, gname);
02696           else
02697             sprintf(pbuffer, "%s", gname);
02698           npath=pbuffer;
02699         } /* if name given */
02700         else
02701           npath=path;
02702 
02703         nn=GWEN_XMLNode_dup(n);
02704         if (gn!=n)
02705           GWEN_XMLNode_CopyProperties(nn, gn, 0);
02706         GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
02707         GWEN_XMLNode_AddChild(listNode, nn);
02708 
02709         /* write group */
02710         if (GWEN_MsgEngine__ListGroup(e,
02711                                       npath,
02712                                       gn,
02713                                       n,
02714                                       sl,
02715                                       nn,
02716                                       lflags)) {
02717           DBG_INFO(GWEN_LOGDOMAIN, "Could not list group \"%s\"", gtype);
02718           return -1;
02719         }
02720       }
02721     }
02722     n=GWEN_XMLNode_Next(n);
02723   } /* while */
02724 
02725   return 0;
02726 }
02727 
02728 
02729 
02730 GWEN_XMLNODE *GWEN_MsgEngine_ListMessage(GWEN_MSGENGINE *e,
02731                                          const char *typ,
02732                                          const char *msgName,
02733                                          int msgVersion,
02734                                          uint32_t flags) {
02735   GWEN_XMLNODE *group;
02736   GWEN_STRINGLIST *sl;
02737   GWEN_XMLNODE *listNode;
02738 
02739   group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
02740   if (!group)
02741     group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "code",
02742                                             msgVersion, msgName);
02743   if (!group) {
02744     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" (version %d) not found\n",
02745               msgName, msgVersion);
02746     return 0;
02747   }
02748 
02749   sl=GWEN_StringList_new();
02750   /* copy group, but remove all children (we only want the properties) */
02751   listNode=GWEN_XMLNode_dup(group);
02752   GWEN_XMLNode_RemoveChildren(listNode);
02753 
02754   if (GWEN_MsgEngine__ListGroup(e,
02755                                 "",
02756                                 group,
02757                                 0,
02758                                 sl,
02759                                 listNode,
02760                                 flags)) {
02761     DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
02762     GWEN_StringList_free(sl);
02763     GWEN_XMLNode_free(listNode);
02764     return 0;
02765   }
02766 
02767   GWEN_StringList_free(sl);
02768 
02769   return listNode;
02770 }
02771 
02772 
02773 
02774 
02775 
02776 
02777 
02778 int GWEN_MsgEngine__ReadValue(GWEN_MSGENGINE *e,
02779                               GWEN_BUFFER *msgbuf,
02780                               GWEN_XMLNODE *node,
02781                               GWEN_XMLNODE *rnode,
02782                               GWEN_BUFFER *vbuf,
02783                               const char *delimiters,
02784                               uint32_t flags) {
02785   unsigned int minsize;
02786   unsigned int maxsize;
02787   unsigned int size;
02788   unsigned int minnum;
02789   GWEN_MSGENGINE_TRUSTLEVEL trustLevel;
02790   unsigned int posInMsg;
02791   const char *type;
02792   int rv;
02793   unsigned int realSize;
02794 
02795   /* get some sizes */
02796   posInMsg=GWEN_Buffer_GetPos(msgbuf);
02797   realSize=0;
02798   size=atoi(GWEN_XMLNode_GetProperty(node, "size","0"));
02799   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
02800   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
02801   minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
02802   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02803 
02804   rv=1;
02805   if (e->typeReadPtr) {
02806     rv=e->typeReadPtr(e,
02807                       msgbuf,
02808                       node,
02809                       vbuf,
02810                       e->escapeChar,
02811                       delimiters);
02812   }
02813   if (rv==-1) {
02814     DBG_INFO(GWEN_LOGDOMAIN, "External type reading failed on type \"%s\"", type);
02815     return -1;
02816   }
02817   else if (rv==1) {
02818     if (strcasecmp(type, "bin")==0) {
02819       if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) {
02820         DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (@num@ expected)");
02821         return -1;
02822       }
02823       else {
02824         char lbuffer[16];
02825         int c;
02826         char *p;
02827         int l;
02828 
02829         p=lbuffer;
02830         c=GWEN_Buffer_ReadByte(msgbuf);
02831         if (c!='@') {
02832           DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
02833           return -1;
02834         }
02835 
02836         c=0;
02837         while(GWEN_Buffer_GetBytesLeft(msgbuf)>0) {
02838           c=GWEN_Buffer_ReadByte(msgbuf);
02839           if (c==-1) {
02840             DBG_ERROR(GWEN_LOGDOMAIN, "\"@\" expected");
02841             return -1;
02842           }
02843           if (c=='@')
02844             break;
02845           *p=(char)c;
02846           p++;
02847         } /* while */
02848         *p=0;
02849         if (c!='@') {
02850           DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
02851           return -1;
02852         }
02853         if (sscanf(lbuffer, "%d", &l)!=1) {
02854           DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
02855           return -1;
02856         }
02857         DBG_DEBUG(GWEN_LOGDOMAIN, "Reading binary: %d bytes from pos %d (msgsize=%d)",
02858                  l,
02859                  GWEN_Buffer_GetPos(msgbuf),
02860                  GWEN_Buffer_GetUsedBytes(msgbuf));
02861         if (GWEN_Buffer_GetBytesLeft(msgbuf) < (unsigned) l) {
02862           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
02863           return -1;
02864         }
02865         if (GWEN_Buffer_AppendBytes(vbuf,
02866                                     GWEN_Buffer_GetPosPointer(msgbuf),
02867                                     l)) {
02868           DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
02869           return -1;
02870         }
02871         GWEN_Buffer_IncrementPos(msgbuf,l);
02872       }
02873     } /* if bin */
02874     else {
02875       /* type is not bin */
02876       int lastWasEscape;
02877       int isEscaped;
02878       int br;
02879 
02880       isEscaped=0;
02881       lastWasEscape=0;
02882 
02883       br=0;
02884       while(GWEN_Buffer_GetBytesLeft(msgbuf) &&
02885             (size==0 || br<size)) {
02886         int c;
02887 
02888         c=GWEN_Buffer_ReadByte(msgbuf);
02889         if (lastWasEscape) {
02890           lastWasEscape=0;
02891           isEscaped=1;
02892         }
02893         else {
02894           isEscaped=0;
02895           if (c==e->escapeChar) {
02896             lastWasEscape=1;
02897             c=-1;
02898           }
02899         }
02900         if (c!=-1) {
02901           if (!isEscaped && (c && strchr(delimiters, c)!=0)) {
02902             /* delimiter found, step back */
02903             GWEN_Buffer_DecrementPos(msgbuf,1);
02904             break;
02905           }
02906           else {
02907             if (c=='\\' || iscntrl(c)) {
02908               DBG_WARN(GWEN_LOGDOMAIN,
02909                        "Found a bad character (%02x) in type \"%s\", "
02910                        "converting to SPACE",
02911                        (unsigned int)c,
02912                        type);
02913               c=' ';
02914             }
02915             if (GWEN_Buffer_AppendByte(vbuf, c)) {
02916               DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
02917               return -1;
02918             }
02919             br++;
02920           }
02921         }
02922       } /* while */
02923     } /* if !bin */
02924   } /* if type not external */
02925   else {
02926     DBG_DEBUG(GWEN_LOGDOMAIN, "Type \"%s\" is external (read)", type);
02927   }
02928 
02929   realSize=GWEN_Buffer_GetUsedBytes(vbuf);
02930 
02931   /* check the value */
02932   if (realSize==0) {
02933     DBG_DEBUG(GWEN_LOGDOMAIN, "Datasize is 0");
02934     if (minnum==0) {
02935       DBG_DEBUG(GWEN_LOGDOMAIN, "... but thats ok");
02936       /* value is empty, and that is allowed */
02937       return 1;
02938     }
02939     else {
02940       DBG_ERROR(GWEN_LOGDOMAIN, "Value missing");
02941       GWEN_XMLNode_Dump(node, 1);
02942       return -1;
02943     }
02944   }
02945 
02946   /* check minimum size */
02947   if (minsize!=0 && realSize<minsize) {
02948     DBG_INFO(GWEN_LOGDOMAIN, "Value too short (%d<%d).",
02949              realSize,
02950              minsize);
02951     return -1;
02952   }
02953 
02954   /* check maximum size */
02955   if (maxsize!=0 && realSize>maxsize) {
02956     DBG_INFO(GWEN_LOGDOMAIN, "Value too long (%d>%d).",
02957              realSize, maxsize);
02958     return -1;
02959   }
02960 
02961   if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) {
02962     /* add trust data to msgEngine */
02963     const char *descr;
02964 
02965     trustLevel=GWEN_MsgEngine_GetHighestTrustLevel(node, rnode);
02966     if (trustLevel) {
02967       unsigned int ustart;
02968 
02969       ustart=GWEN_Buffer_GetPos(msgbuf)-realSize;
02970       descr=GWEN_XMLNode_GetProperty(node, "name",0);
02971       if (GWEN_MsgEngine_AddTrustInfo(e,
02972                                       GWEN_Buffer_GetStart(vbuf),
02973                                       realSize,
02974                                       descr,
02975                                       trustLevel,
02976                                       ustart)) {
02977         DBG_INFO(GWEN_LOGDOMAIN, "called from here");
02978         return -1;
02979       }
02980     }
02981   }
02982 
02983   return 0;
02984 }
02985 
02986 
02987 
02988 int GWEN_MsgEngine__ReadGroup(GWEN_MSGENGINE *e,
02989                               GWEN_BUFFER *msgbuf,
02990                               GWEN_XMLNODE *node,
02991                               GWEN_XMLNODE *rnode,
02992                               GWEN_DB_NODE *gr,
02993                               const char *delimiters,
02994                               uint32_t flags) {
02995   unsigned int minsize;
02996   unsigned int maxsize;
02997   unsigned int minnum;
02998   unsigned int maxnum;
02999   const char *name;
03000   const char *p;
03001   char delimiter;
03002   char terminator;
03003   GWEN_XMLNODE *n;
03004   int abortLoop;
03005   GWEN_BUFFER *delimBuffer=0;
03006 
03007   /* get some settings */
03008   if (rnode) {
03009     /* get delimiter */
03010     p=GWEN_XMLNode_GetProperty(rnode,
03011                                "delimiter",
03012                                GWEN_XMLNode_GetProperty(node,
03013                                                         "delimiter",
03014                                                         ""));
03015     delimiter=*p;
03016 
03017     /* get terminating char, if any */
03018     p=GWEN_XMLNode_GetProperty(rnode,
03019                                "terminator",
03020                                GWEN_XMLNode_GetProperty(node,
03021                                                         "terminator",
03022                                                         ""));
03023     terminator=*p;
03024   }
03025   else {
03026     /* get delimiter */
03027     p=GWEN_XMLNode_GetProperty(node,
03028                                "delimiter",
03029                                "");
03030     delimiter=*p;
03031 
03032     /* get terminating char, if any */
03033     p=GWEN_XMLNode_GetProperty(node, "terminator","");
03034     terminator=*p;
03035   }
03036 
03037   delimBuffer=GWEN_Buffer_new(0, strlen(delimiters)+2, 0, 1);
03038   GWEN_Buffer_AppendString(delimBuffer, delimiters);
03039   if (delimiter)
03040     GWEN_Buffer_AppendByte(delimBuffer, delimiter);
03041   if (terminator)
03042     GWEN_Buffer_AppendByte(delimBuffer, terminator);
03043 
03044   DBG_DEBUG(GWEN_LOGDOMAIN, "Delimiters are \"%s\" and \"%c\"",
03045             delimiters, delimiter);
03046 
03047   n=GWEN_XMLNode_GetChild(node);
03048   while (n) {
03049     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
03050       const char *type;
03051 
03052       if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03053         break;
03054 
03055       type=GWEN_XMLNode_GetData(n);
03056 
03057       /*
03058       DBG_NOTICE(GWEN_LOGDOMAIN, "Reading group from here :");
03059       GWEN_Text_DumpString(GWEN_Buffer_GetStart(msgbuf)+
03060                            GWEN_Buffer_GetPos(msgbuf),
03061                            GWEN_Buffer_GetUsedBytes(msgbuf)-
03062                            GWEN_Buffer_GetPos(msgbuf),
03063                            stderr, 3);
03064       */
03065       if (strcasecmp(type, "ELEM")==0) {
03066         unsigned int loopNr;
03067 
03068         /* get some sizes */
03069         minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize","0"));
03070         maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize","0"));
03071         minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
03072         maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
03073         name=GWEN_XMLNode_GetProperty(n, "name", 0);
03074 
03075         loopNr=0;
03076         abortLoop=0;
03077         while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
03078           int c;
03079 
03080           DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %s", name);
03081           if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03082             break;
03083           c=GWEN_Buffer_PeekByte(msgbuf);
03084           if (c==-1) {
03085             DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
03086             GWEN_Buffer_free(delimBuffer);
03087             return -1;
03088           }
03089 
03090           DBG_VERBOUS(GWEN_LOGDOMAIN,
03091                       "Checking delimiter at pos %x "
03092                       "(whether \"%c\" is in \"%s\")",
03093                       GWEN_Buffer_GetPos(msgbuf),
03094                       c, GWEN_Buffer_GetStart(delimBuffer));
03095           if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
03096             abortLoop=1;
03097             DBG_VERBOUS(GWEN_LOGDOMAIN,
03098                         "Found delimiter (\"%c\" is in \"%s\")",
03099                         c, GWEN_Buffer_GetStart(delimBuffer));
03100           } /* if delimiter found */
03101           else {
03102             /* current char is not a delimiter */
03103             if (name==0) {
03104               DBG_VERBOUS(GWEN_LOGDOMAIN, "no name");
03105             }
03106             else {
03107               /* name is given */
03108               int rv;
03109               const char *dtype;
03110               GWEN_BUFFER *vbuf;
03111 
03112               DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading value from pos %x",
03113                           GWEN_Buffer_GetPos(msgbuf));
03114               vbuf=GWEN_Buffer_new(0,
03115                                    GWEN_MSGENGINE_MAX_VALUE_LEN,
03116                                    0,0);
03117               /*
03118               DBG_ERROR(GWEN_LOGDOMAIN, "Reading value from here:\n");
03119               GWEN_Text_DumpString(GWEN_Buffer_GetPosPointer(msgbuf),
03120                                    GWEN_Buffer_GetBytesLeft(msgbuf),
03121                                    stderr, 1);*/
03122 
03123               rv=GWEN_MsgEngine__ReadValue(e,
03124                                            msgbuf,
03125                                            n,
03126                                            rnode,
03127                                            vbuf,
03128                                            GWEN_Buffer_GetStart(delimBuffer),
03129                                            //":+'",
03130                                            flags);
03131               if (rv==1) {
03132                 DBG_INFO(GWEN_LOGDOMAIN, "Empty value");
03133               }
03134               else if (rv==-1) {
03135                 DBG_INFO(GWEN_LOGDOMAIN, "Error parsing node \"%s\" (%s)",
03136                          name,
03137                          type);
03138                 GWEN_Buffer_free(vbuf);
03139                 GWEN_Buffer_free(delimBuffer);
03140                 return -1;
03141               }
03142 
03143               GWEN_Buffer_Rewind(vbuf);
03144 
03145               /* special handling for binary data */
03146               dtype=GWEN_XMLNode_GetProperty(n, "type", "");
03147               if (GWEN_MsgEngine__IsBinTyp(e, dtype)) {
03148                 if (atoi(GWEN_XMLNode_GetProperty(n, "readbin", "1")) &&
03149                     e->binTypeReadPtr) {
03150                   rv=e->binTypeReadPtr(e, n, gr, vbuf);
03151                 }
03152                 else
03153                   rv=1;
03154                 if (rv==-1) {
03155                   DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
03156                   GWEN_Buffer_free(vbuf);
03157                   GWEN_Buffer_free(delimBuffer);
03158                   return -1;
03159                 }
03160                 else if (rv==1) {
03161                   /* bin type not handled, so handle it myself */
03162                   if (GWEN_DB_SetBinValue(gr,
03163                                           GWEN_DB_FLAGS_DEFAULT,
03164                                           name,
03165                                           GWEN_Buffer_GetStart(vbuf),
03166                                           GWEN_Buffer_GetUsedBytes(vbuf))) {
03167                     DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
03168                     GWEN_Buffer_free(vbuf);
03169                     GWEN_Buffer_free(delimBuffer);
03170                     return -1;
03171                   }
03172                 }
03173               } /* if type is bin */
03174               else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) {
03175                 int z;
03176 
03177                 if (1!=sscanf(GWEN_Buffer_GetStart(vbuf), "%d", &z)) {
03178                   DBG_INFO(GWEN_LOGDOMAIN, "Value for \"%s\" is not an integer",
03179                            name);
03180                   GWEN_Buffer_free(delimBuffer);
03181                   return -1;
03182                 }
03183                 if (GWEN_DB_SetIntValue(gr,
03184                                         GWEN_DB_FLAGS_DEFAULT,
03185                                         name, z)) {
03186                   DBG_INFO(GWEN_LOGDOMAIN, "Could not set int value for \"%s\"", name);
03187                   GWEN_Buffer_free(delimBuffer);
03188                   return -1;
03189                 }
03190               } /* if type is int */
03191               else {
03192                 DBG_DEBUG(GWEN_LOGDOMAIN, "Value is \"%s\"",
03193                           GWEN_Buffer_GetStart(vbuf));
03194                 if (GWEN_DB_SetCharValue(gr,
03195                                          GWEN_DB_FLAGS_DEFAULT,
03196                                          name,
03197                                          GWEN_Buffer_GetStart(vbuf))){
03198                   DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
03199                   GWEN_Buffer_free(delimBuffer);
03200                   return -1;
03201                 }
03202               } /* if !bin */
03203 
03204               GWEN_Buffer_free(vbuf);
03205             } /* if name is given */
03206           } /* if current char is not a delimiter */
03207 
03208           if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03209             if (delimiter) {
03210               if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
03211                 GWEN_Buffer_IncrementPos(msgbuf,1);
03212               }
03213             }
03214           }
03215           loopNr++;
03216         } /* while */
03217         if (loopNr<minnum) {
03218           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few ELEM repeats)");
03219           GWEN_XMLNode_Dump(n, 2);
03220           GWEN_Buffer_free(delimBuffer);
03221           return -1;
03222         }
03223         n=GWEN_XMLNode_Next(n);
03224       } /* if ELEM */
03225       else if (strcasecmp(type, "VALUES")==0) {
03226         n=GWEN_XMLNode_Next(n);
03227       }
03228       else if (strcasecmp(type, "DESCR")==0) {
03229         n=GWEN_XMLNode_Next(n);
03230       }
03231       else {
03232         /* group tag found */
03233         GWEN_XMLNODE *gn;
03234         GWEN_DB_NODE *gcfg;
03235         const char *gname;
03236         const char *gtype;
03237         unsigned int gversion;
03238         unsigned int loopNr;
03239 
03240         minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
03241         maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
03242         gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
03243         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
03244         if (!gtype) {
03245           /* no "type" property, so use this group directly */
03246           DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", type);
03247           gtype="";
03248           gn=n;
03249         }
03250         else {
03251           gn=GWEN_MsgEngine_FindNodeByProperty(e, type, "id",
03252                                                gversion, gtype);
03253           if (!gn) {
03254             DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", type);
03255             GWEN_Buffer_free(delimBuffer);
03256             return -1;
03257           }
03258         }
03259 
03260         /* get configuration */
03261         loopNr=0;
03262         abortLoop=0;
03263         while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
03264           int c;
03265 
03266           DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group type %s", gtype);
03267           if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03268             break;
03269           c=GWEN_Buffer_PeekByte(msgbuf);
03270           if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
03271             abortLoop=1;
03272           }
03273           else {
03274             gname=GWEN_XMLNode_GetProperty(n, "name",0);
03275             if (gname) {
03276               DBG_DEBUG(GWEN_LOGDOMAIN, "Creating group \"%s\"", gname);
03277               gcfg=GWEN_DB_GetGroup(gr,
03278                                     GWEN_PATH_FLAGS_CREATE_GROUP,
03279                                     gname);
03280               if (!gcfg) {
03281                 DBG_ERROR(GWEN_LOGDOMAIN, "Could not select group \"%s\"",
03282                           gname);
03283                 GWEN_Buffer_free(delimBuffer);
03284                 return -1;
03285               }
03286               DBG_DEBUG(GWEN_LOGDOMAIN, "Created group \"%s\"", gname);
03287             } /* if name given */
03288             else
03289               gcfg=gr;
03290 
03291             /* read group */
03292             DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group \"%s\"", gname);
03293             if (GWEN_MsgEngine__ReadGroup(e,
03294                                           msgbuf,
03295                                           gn,
03296                                           n,
03297                                           gcfg,
03298                                           GWEN_Buffer_GetStart(delimBuffer),
03299                                           flags)) {
03300               DBG_INFO(GWEN_LOGDOMAIN, "Could not read group \"%s\"", gtype);
03301               GWEN_Buffer_free(delimBuffer);
03302               return -1;
03303             }
03304           }
03305           if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03306             if (delimiter) {
03307               if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
03308                 GWEN_Buffer_IncrementPos(msgbuf, 1);
03309               }
03310             }
03311           }
03312           loopNr++;
03313         } /* while */
03314         if (loopNr<minnum) {
03315           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few group repeats)");
03316           GWEN_Buffer_free(delimBuffer);
03317           return -1;
03318         }
03319         n=GWEN_XMLNode_Next(n);
03320       } /* if GROUP */
03321     } /* if TAG */
03322     else {
03323       n=GWEN_XMLNode_Next(n);
03324     }
03325   } /* while */
03326 
03327   /* check whether there still are nodes which have not been read */
03328   while(n) {
03329     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
03330       if (strcasecmp(GWEN_XMLNode_GetData(n), "ELEM")==0 ||
03331           strcasecmp(GWEN_XMLNode_GetData(n), "GROUP")==0) {
03332         unsigned int i;
03333 
03334         i=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1"));
03335         if (i) {
03336           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (still tags to parse)");
03337           GWEN_XMLNode_Dump(n, 2);
03338           GWEN_Buffer_free(delimBuffer);
03339           return -1;
03340         }
03341       }
03342     }
03343     n=GWEN_XMLNode_Next(n);
03344   }
03345 
03346 
03347   if (terminator) {
03348     /* skip terminator */
03349     if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03350       if (GWEN_Buffer_PeekByte(msgbuf)==terminator) {
03351         GWEN_Buffer_IncrementPos(msgbuf, 1);
03352       }
03353       else {
03354         DBG_ERROR(GWEN_LOGDOMAIN,
03355                   "Terminating character missing (pos=%d [%x]) "
03356                   "expecting \"%c\", got \"%c\")",
03357                   GWEN_Buffer_GetPos(msgbuf),
03358                   GWEN_Buffer_GetPos(msgbuf),
03359                   terminator,
03360                   GWEN_Buffer_PeekByte(msgbuf));
03361         GWEN_XMLNode_Dump(node, 1);
03362         GWEN_Buffer_free(delimBuffer);
03363         return -1;
03364       }
03365     }
03366     else {
03367       DBG_ERROR(GWEN_LOGDOMAIN, "Terminating character missing");
03368       GWEN_Buffer_free(delimBuffer);
03369       return -1;
03370     }
03371   }
03372 
03373   GWEN_Buffer_free(delimBuffer);
03374   return 0;
03375 }
03376 
03377 
03378 
03379 int GWEN_MsgEngine_ParseMessage(GWEN_MSGENGINE *e,
03380                                 GWEN_XMLNODE *group,
03381                                 GWEN_BUFFER *msgbuf,
03382                                 GWEN_DB_NODE *msgData,
03383                                 uint32_t flags){
03384 
03385   if (GWEN_MsgEngine__ReadGroup(e,
03386                                 msgbuf,
03387                                 group,
03388                                 0,
03389                                 msgData,
03390                                 e->delimiters,
03391                                 flags)) {
03392     DBG_INFO(GWEN_LOGDOMAIN, "Error reading group");
03393     return -1;
03394   }
03395 
03396   return 0;
03397 }
03398 
03399 
03400 
03401 int GWEN_MsgEngine_SetValue(GWEN_MSGENGINE *e,
03402                             const char *path,
03403                             const char *value){
03404   GWEN_DB_NODE *globalValues;
03405 
03406   assert(e);
03407   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03408   assert(globalValues);
03409   return GWEN_DB_SetCharValue(globalValues,
03410                               GWEN_DB_FLAGS_DEFAULT |
03411                               GWEN_DB_FLAGS_OVERWRITE_VARS,
03412                               path, value);
03413 }
03414 
03415 
03416 
03417 int GWEN_MsgEngine_SetIntValue(GWEN_MSGENGINE *e,
03418                                const char *path,
03419                                int value){
03420   GWEN_DB_NODE *globalValues;
03421 
03422   assert(e);
03423   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03424   assert(globalValues);
03425   return GWEN_DB_SetIntValue(globalValues,
03426                              GWEN_DB_FLAGS_DEFAULT |
03427                              GWEN_DB_FLAGS_OVERWRITE_VARS,
03428                              path, value);
03429 }
03430 
03431 
03432 
03433 const char *GWEN_MsgEngine_GetValue(GWEN_MSGENGINE *e,
03434                                     const char *path,
03435                                     const char *defValue){
03436   GWEN_DB_NODE *globalValues;
03437 
03438   assert(e);
03439   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03440   assert(globalValues);
03441   return GWEN_DB_GetCharValue(globalValues,
03442                               path, 0, defValue);
03443 }
03444 
03445 
03446 
03447 int GWEN_MsgEngine_GetIntValue(GWEN_MSGENGINE *e,
03448                                const char *path,
03449                                int defValue){
03450   GWEN_DB_NODE *globalValues;
03451 
03452   assert(e);
03453   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03454   assert(globalValues);
03455   return GWEN_DB_GetIntValue(globalValues,
03456                              path, 0, defValue);
03457 }
03458 
03459 
03460 
03461 /* --------------------------------------------------------------- FUNCTION */
03462 int GWEN_MsgEngine_SkipSegment(GWEN_UNUSED GWEN_MSGENGINE *e,
03463                                GWEN_BUFFER *msgbuf,
03464                                unsigned char escapeChar,
03465                                unsigned char delimiter) {
03466   int esc;
03467 
03468   esc=0;
03469   while(GWEN_Buffer_GetBytesLeft(msgbuf)) {
03470     if (esc) {
03471       esc=0;
03472     }
03473     else {
03474       int i;
03475       unsigned char c;
03476 
03477       i=GWEN_Buffer_ReadByte(msgbuf);
03478       if (i==-1) {
03479         DBG_INFO(GWEN_LOGDOMAIN, "called from here");
03480         return 0;
03481       }
03482       c=(unsigned int)i;
03483       if (c==escapeChar) { /* escape */
03484         esc=1;
03485       }
03486       else if (c=='@') {
03487       /* skip binary data */
03488         char lbuffer[16];
03489         char *p;
03490         int l;
03491         int nc;
03492 
03493         p=lbuffer;
03494         while(1) {
03495           nc=GWEN_Buffer_ReadByte(msgbuf);
03496           if (nc==-1) {
03497             DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
03498             return -1;
03499           }
03500           if (nc=='@')
03501             break;
03502           *p=nc;
03503           p++;
03504         } /* while */
03505         *p=0;
03506         if (sscanf(lbuffer, "%d", &l)!=1) {
03507           DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
03508           return -1;
03509         }
03510         if (GWEN_Buffer_GetUsedBytes(msgbuf)-GWEN_Buffer_GetPos(msgbuf) 
03511             < (unsigned) l) {
03512           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
03513           return -1;
03514         }
03515         GWEN_Buffer_IncrementPos(msgbuf, l);
03516       }
03517       else if (c==delimiter) {/* segment-end */
03518         return 0;
03519         break;
03520       }
03521     }
03522   } /* while */
03523 
03524   DBG_ERROR(GWEN_LOGDOMAIN, "End of segment not found");
03525   return -1;
03526 }
03527 
03528 
03529 
03530 /* --------------------------------------------------------------- FUNCTION */
03531 int GWEN_MsgEngine_ReadMessage(GWEN_MSGENGINE *e,
03532                                const char *gtype,
03533                                GWEN_BUFFER *mbuf,
03534                                GWEN_DB_NODE *gr,
03535                                uint32_t flags) {
03536   unsigned int segments;
03537 
03538   segments=0;
03539 
03540   while(GWEN_Buffer_GetBytesLeft(mbuf)) {
03541     GWEN_XMLNODE *node;
03542     unsigned int posBak;
03543     const char *p;
03544     GWEN_DB_NODE *tmpdb;
03545     int segVer;
03546 
03547     /* find head segment description */
03548     tmpdb=GWEN_DB_Group_new("tmpdb");
03549     node=GWEN_MsgEngine_FindGroupByProperty(e,
03550                                             "id",
03551                                             0,
03552                                             "SegHead");
03553     if (node==0) {
03554       DBG_ERROR(GWEN_LOGDOMAIN, "Segment description not found");
03555       GWEN_DB_Group_free(tmpdb);
03556       return -1;
03557     }
03558 
03559     /* parse head segment */
03560     posBak=GWEN_Buffer_GetPos(mbuf);
03561     if (GWEN_MsgEngine_ParseMessage(e,
03562                                     node,
03563                                     mbuf,
03564                                     tmpdb,
03565                                     flags)) {
03566       DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment head");
03567       GWEN_DB_Group_free(tmpdb);
03568       return -1;
03569     }
03570 
03571     /* get segment code */
03572     segVer=GWEN_DB_GetIntValue(tmpdb,
03573                                "version",
03574                                0,
03575                                0);
03576     p=GWEN_DB_GetCharValue(tmpdb,
03577                            "code",
03578                            0,
03579                            0);
03580     if (!p) {
03581       DBG_ERROR(GWEN_LOGDOMAIN, "No segment code for %s ? This seems to be a bad msg...",
03582                 gtype);
03583       GWEN_Buffer_SetPos(mbuf, posBak);
03584       DBG_ERROR(GWEN_LOGDOMAIN, "Full message (pos=%04x)", posBak);
03585       GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf),
03586                            GWEN_Buffer_GetUsedBytes(mbuf),
03587                            1);
03588       GWEN_DB_Dump(tmpdb, 1);
03589       GWEN_DB_Group_free(tmpdb);
03590       return -1;
03591     }
03592 
03593     /* try to find corresponding XML node */
03594     node=GWEN_MsgEngine_FindNodeByProperty(e,
03595                                            gtype,
03596                                            "code",
03597                                            segVer,
03598                                            p);
03599     if (node==0) {
03600       unsigned int ustart;
03601 
03602       ustart=GWEN_Buffer_GetPos(mbuf);
03603       ustart++; /* skip delimiter */
03604 
03605       /* node not found, skip it */
03606       DBG_NOTICE(GWEN_LOGDOMAIN,
03607                  "Unknown segment \"%s\" (Segnum=%d, version=%d, ref=%d)",
03608                  p,
03609                  GWEN_DB_GetIntValue(tmpdb, "seq", 0, -1),
03610                  GWEN_DB_GetIntValue(tmpdb, "version", 0, -1),
03611                  GWEN_DB_GetIntValue(tmpdb, "ref", 0, -1));
03612       if (GWEN_MsgEngine_SkipSegment(e, mbuf, '?', '\'')) {
03613         DBG_ERROR(GWEN_LOGDOMAIN, "Error skipping segment \"%s\"", p);
03614         GWEN_DB_Group_free(tmpdb);
03615         return -1;
03616       }
03617       if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) {
03618         unsigned int usize;
03619 
03620         usize=GWEN_Buffer_GetPos(mbuf)-ustart-1;
03621 #if 0
03622         GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+ustart,
03623                              usize,
03624                              stderr, 1);
03625 #endif
03626         if (GWEN_MsgEngine_AddTrustInfo(e,
03627                                         GWEN_Buffer_GetStart(mbuf)+ustart,
03628                                         usize,
03629                                         p,
03630                                         GWEN_MsgEngineTrustLevelHigh,
03631                                         ustart)) {
03632           DBG_INFO(GWEN_LOGDOMAIN, "called from here");
03633           GWEN_DB_Group_free(tmpdb);
03634           return -1;
03635         }
03636       } /* if trustInfo handling wanted */
03637     }
03638     else {
03639       /* ok, node available, get the corresponding description and parse
03640        * the segment */
03641       const char *id;
03642       GWEN_DB_NODE *storegrp;
03643       unsigned int startPos;
03644 
03645       /* restore start position, since the segment head is part of a full
03646        * description, so we need to restart reading from the very begin */
03647       GWEN_Buffer_SetPos(mbuf, posBak);
03648 
03649       /* create group in DB for this segment */
03650       id=GWEN_XMLNode_GetProperty(node, "id", p);
03651       storegrp=GWEN_DB_GetGroup(gr,
03652                                 GWEN_PATH_FLAGS_CREATE_GROUP,
03653                                 id);
03654       assert(storegrp);
03655 
03656       /* store the start position of this segment within the DB */
03657       startPos=GWEN_Buffer_GetPos(mbuf);
03658       GWEN_DB_SetIntValue(storegrp,
03659                           GWEN_DB_FLAGS_OVERWRITE_VARS,
03660                           "segment/pos",
03661                           startPos);
03662 
03663       /* parse the segment */
03664       if (GWEN_MsgEngine_ParseMessage(e,
03665                                       node,
03666                                       mbuf,
03667                                       storegrp,
03668                                       flags)) {
03669         DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment \"%s\" at %d (%x)",
03670                   p,
03671                   GWEN_Buffer_GetPos(mbuf)-startPos,
03672                   GWEN_Buffer_GetPos(mbuf)-startPos);
03673         GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+startPos,
03674                              GWEN_Buffer_GetUsedBytes(mbuf)-startPos,
03675                              1);
03676         DBG_ERROR(GWEN_LOGDOMAIN, "Stored data so far:");
03677         GWEN_DB_Dump(storegrp, 2);
03678         GWEN_DB_Group_free(tmpdb);
03679         return -1;
03680       }
03681 
03682       /* store segment size within DB */
03683       GWEN_DB_SetIntValue(storegrp,
03684                           GWEN_DB_FLAGS_OVERWRITE_VARS,
03685                           "segment/length",
03686                           GWEN_Buffer_GetPos(mbuf)-startPos);
03687       segments++;
03688     }
03689     GWEN_DB_Group_free(tmpdb);
03690   } /* while */
03691 
03692   /* done */
03693   if (segments) {
03694     DBG_DEBUG(GWEN_LOGDOMAIN, "Parsed %d segments", segments);
03695     return 0;
03696   }
03697   else {
03698     DBG_INFO(GWEN_LOGDOMAIN, "No segments parsed.");
03699     return 1;
03700   }
03701 }
03702 
03703 
03704 
03705 
03706 
03707 
03708 
03709 
03710 GWEN_MSGENGINE_TRUSTEDDATA*
03711 GWEN_MsgEngine_TrustedData_new(const char *data,
03712                                unsigned int size,
03713                                const char *description,
03714                                GWEN_MSGENGINE_TRUSTLEVEL trustLevel){
03715   GWEN_MSGENGINE_TRUSTEDDATA *td;
03716 
03717   assert(data);
03718   assert(size);
03719   GWEN_NEW_OBJECT(GWEN_MSGENGINE_TRUSTEDDATA, td);
03720   td->data=(char*)malloc(size);
03721   assert(td->data);
03722   memmove(td->data, data, size);
03723   if (description)
03724     td->description=strdup(description);
03725   td->trustLevel=trustLevel;
03726   td->size=size;
03727   return td;
03728 }
03729 
03730 
03731 
03732 void GWEN_MsgEngine_TrustedData_free(GWEN_MSGENGINE_TRUSTEDDATA *td){
03733   if (td) {
03734     free(td->data);
03735     free(td->description);
03736     free(td->replacement);
03737     GWEN_FREE_OBJECT(td);
03738   }
03739 }
03740 
03741 
03742 
03743 GWEN_MSGENGINE_TRUSTEDDATA*
03744 GWEN_MsgEngine_TrustedData_GetNext(GWEN_MSGENGINE_TRUSTEDDATA *td){
03745   assert(td);
03746   return td->next;
03747 }
03748 
03749 
03750 
03751 const char*
03752 GWEN_MsgEngine_TrustedData_GetData(GWEN_MSGENGINE_TRUSTEDDATA *td){
03753   assert(td);
03754   return td->data;
03755 }
03756 
03757 
03758 
03759 unsigned int
03760 GWEN_MsgEngine_TrustedData_GetSize(GWEN_MSGENGINE_TRUSTEDDATA *td){
03761   assert(td);
03762   return td->size;
03763 }
03764 
03765 
03766 
03767 const char*
03768 GWEN_MsgEngine_TrustedData_GetDescription(GWEN_MSGENGINE_TRUSTEDDATA *td){
03769   assert(td);
03770   return td->description;
03771 }
03772 
03773 
03774 
03775 GWEN_MSGENGINE_TRUSTLEVEL
03776 GWEN_MsgEngine_TrustedData_GetTrustLevel(GWEN_MSGENGINE_TRUSTEDDATA *td){
03777   assert(td);
03778   return td->trustLevel;
03779 }
03780 
03781 
03782 
03783 const char*
03784 GWEN_MsgEngine_TrustedData_GetReplacement(GWEN_MSGENGINE_TRUSTEDDATA *td){
03785   assert(td);
03786   return td->replacement;
03787 }
03788 
03789 
03790 
03791 int GWEN_MsgEngine_TrustedData_AddPos(GWEN_MSGENGINE_TRUSTEDDATA *td,
03792                                       unsigned int pos){
03793   assert(td);
03794   if (td->posCount>=GWEN_MSGENGINE_TRUSTEDDATA_MAXPOS)
03795     return -1;
03796   td->positions[td->posCount++]=pos;
03797   return 0;
03798 }
03799 
03800 
03801 
03802 int GWEN_MsgEngine_TrustedData_GetFirstPos(GWEN_MSGENGINE_TRUSTEDDATA *td){
03803   assert(td);
03804   td->posPointer=0;
03805   return GWEN_MsgEngine_TrustedData_GetNextPos(td);
03806 }
03807 
03808 
03809 
03810 int GWEN_MsgEngine_TrustedData_GetNextPos(GWEN_MSGENGINE_TRUSTEDDATA *td){
03811   assert(td);
03812   if (td->posPointer>=td->posCount)
03813     return -1;
03814   return td->positions[td->posPointer++];
03815 }
03816 
03817 
03818 
03819 int
03820 GWEN_MsgEngine_TrustedData_CreateReplacements(GWEN_MSGENGINE_TRUSTEDDATA
03821                                               *td){
03822   unsigned int nextNr;
03823   GWEN_MSGENGINE_TRUSTEDDATA *ntd;
03824   unsigned int count;
03825 
03826   assert(td);
03827   count=0;
03828   ntd=td;
03829   while(ntd) {
03830     count++;
03831     ntd=ntd->next;
03832   }
03833 
03834   if (count<0x10)
03835     nextNr=0x01;
03836   else
03837     nextNr=0x11;
03838 
03839   ntd=td;
03840   while(ntd) {
03841     unsigned int i;
03842     char numbuffer[32];
03843     char *rp;
03844     GWEN_MSGENGINE_TRUSTEDDATA *std;
03845     int match;
03846 
03847     /* check whether the same data already exists */
03848     std=td;
03849     match=0;
03850     while(std && std!=ntd) {
03851 
03852       match=1;
03853       if (std->size==ntd->size) {
03854         for (i=0; i<td->size; i++) {
03855           if (std->data[i]!=ntd->data[i]) {
03856             match=0;
03857             break;
03858           }
03859         } /* for */
03860       }
03861       else
03862         match=0;
03863 
03864       if (match)
03865         break;
03866       std=std->next;
03867     } /* while */
03868 
03869     if (match) {
03870       /* copy the found match */
03871       rp=strdup(std->replacement);
03872     }
03873     else {
03874       /* this is a new one */
03875       rp=(char*)malloc(ntd->size+1);
03876       assert(rp);
03877 
03878       if (ntd->size==1) {
03879         if (count>=0x10)
03880           nextNr+=0x10;
03881       }
03882       sprintf(numbuffer, "%02X", nextNr++);
03883       for (i=0; i<ntd->size; i++) {
03884         if (count<0x10)
03885           rp[i]=numbuffer[1];
03886         else
03887           rp[i]=numbuffer[1-(i&1)];
03888       } /* for */
03889       rp[i]=0;
03890     }
03891     /*
03892      DBG_DEBUG(GWEN_LOGDOMAIN, "Replacement: \"%s\" for \"%s\" (%d)", rp,
03893      ntd->description,
03894      ntd->size);
03895      */
03896     free(ntd->replacement);
03897     ntd->replacement=rp;
03898 
03899     ntd=ntd->next;
03900   } /* while */
03901   return 0;
03902 }
03903 
03904 
03905 
03906 GWEN_MSGENGINE_TRUSTEDDATA *GWEN_MsgEngine_TakeTrustInfo(GWEN_MSGENGINE *e){
03907   GWEN_MSGENGINE_TRUSTEDDATA *td;
03908 
03909   assert(e);
03910   td=e->trustInfos;
03911   e->trustInfos=0;
03912   return td;
03913 }
03914 
03915 
03916 
03917 
03918 int GWEN_MsgEngine_AddTrustInfo(GWEN_MSGENGINE *e,
03919                                 const char *data,
03920                                 unsigned int size,
03921                                 const char *description,
03922                                 GWEN_MSGENGINE_TRUSTLEVEL trustLevel,
03923                                 unsigned int pos) {
03924   GWEN_MSGENGINE_TRUSTEDDATA *td;
03925   int match;
03926 
03927   assert(e);
03928   assert(data);
03929   assert(size);
03930 
03931   if (!description)
03932     description="";
03933 
03934   td=e->trustInfos;
03935   while(td) {
03936     unsigned int i;
03937 
03938     /* compare data */
03939     if (td->size==size &&
03940         *description &&
03941         *(td->description) &&
03942         trustLevel==td->trustLevel &&
03943         strcasecmp(description, td->description)==0) {
03944       match=1;
03945       for (i=0; i<td->size; i++) {
03946         if (td->data[i]!=data[i]) {
03947           match=0;
03948           break;
03949         }
03950       } /* for */
03951     }
03952     else
03953       match=0;
03954 
03955     if (match)
03956       break;
03957     td=td->next;
03958   } /* while */
03959 
03960   if (!td) {
03961     DBG_INFO(GWEN_LOGDOMAIN, "Creating new trustInfo for \"%s\" (%d)",
03962              description, size);
03963     td=GWEN_MsgEngine_TrustedData_new(data,
03964                                       size,
03965                                       description,
03966                                       trustLevel);
03967     GWEN_LIST_ADD(GWEN_MSGENGINE_TRUSTEDDATA, td, &(e->trustInfos));
03968   }
03969   else {
03970     DBG_INFO(GWEN_LOGDOMAIN, "Reusing trustInfo for \"%s\" (%d)",
03971              description, size);
03972   }
03973   GWEN_MsgEngine_TrustedData_AddPos(td, pos);
03974   return 0;
03975 }
03976 
03977 
03978