gwenhywfar 4.0.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(){
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 
01736           /*
01737            Replaced the following code because it did not work correctly
01738            with segment HKDAN... (aquamaniac, 2005/07/09)
01739 
01740           if (!isFirstElement && delimiter) {
01741             DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters", omittedElements+1);
01742             for (j=0; j<omittedElements+1; j++) {
01743               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01744                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01745                 return -1;
01746               }
01747             }
01748           }*/
01749 
01750           if (delimiter) {
01751             DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters",
01752                         omittedElements);
01753             for (j=0; j<omittedElements; j++) {
01754               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01755                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01756                 return -1;
01757               }
01758             }
01759             if (!isFirstElement)
01760               if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01761                 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
01762                 return -1;
01763               }
01764           }
01765 
01766           rv=GWEN_MsgEngine__WriteElement(e,
01767                                           gbuf,
01768                                           n,
01769                                           rnode,
01770                                           gr,
01771                                           loopNr,
01772                                           loopNr>=minnum ||
01773                                           (groupIsOptional && !hasEntries),
01774                                           nodePath);
01775           if (rv==-1) {
01776             DBG_INFO(GWEN_LOGDOMAIN, "Error writing element");
01777             DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
01778             GWEN_XMLNode_Dump(n, 1);
01779             if (gr) {
01780               DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
01781               GWEN_DB_Dump(gr, 1);
01782             }
01783             return -1;
01784           }
01785           else if (rv==0) {
01786             isFirstElement=0;
01787             omittedElements=0;
01788             hasEntries=1;
01789             DBG_DEBUG(GWEN_LOGDOMAIN, "Element written");
01790           }
01791           else {
01792             /* element is optional, not found */
01793             /* restore position */
01794             GWEN_Buffer_SetPos(gbuf, posBeforeElement);
01795             GWEN_Buffer_Crop(gbuf, 0, posBeforeElement);
01796 
01797             if (strcasecmp(addEmptyMode, "max")==0) {
01798               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty");
01799               omittedElements+=(maxnum-loopNr);
01800             }
01801             else if (strcasecmp(addEmptyMode, "min")==0) {
01802               DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty");
01803               if (loopNr<minnum)
01804                 omittedElements+=(minnum-loopNr);
01805             }
01806             else if (strcasecmp(addEmptyMode, "one")==0) {
01807               if (loopNr==0)
01808                 omittedElements++;
01809             }
01810             else if (strcasecmp(addEmptyMode, "none")==0) {
01811             }
01812             else {
01813               DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
01814                         addEmptyMode);
01815               return -1;
01816             }
01817             break;
01818           }
01819         } /* for */
01820       }
01821       else if (strcasecmp(typ, "VALUES")==0) {
01822       }
01823       else if (strcasecmp(typ, "DESCR")==0) {
01824       }
01825       else {
01826         /* group tag found */
01827         GWEN_XMLNODE *gn;
01828         GWEN_DB_NODE *gcfg;
01829         const char *gname;
01830         const char *gtype;
01831         unsigned int posBeforeGroup;
01832 
01833         DBG_VERBOUS(GWEN_LOGDOMAIN, "Found a group");
01834 
01835         gcfg=0;
01836         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
01837         if (!gtype) {
01838           /* no "type" property, so use this group directly */
01839           DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
01840           gtype="";
01841           gn=n;
01842         }
01843         else {
01844           DBG_VERBOUS(GWEN_LOGDOMAIN, "<%s> tag is of type \"%s\"", typ, gtype);
01845           gn=GWEN_MsgEngine_GetGroup(e, n, nodePath, typ,
01846                                      gversion, gtype);
01847           if (!gn) {
01848             DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
01849             return -1;
01850           }
01851         }
01852 
01853         gname=0;
01854         gcfg=0;
01855         if (gr) {
01856           gname=GWEN_XMLNode_GetProperty(n, "name",0);
01857           if (gname) {
01858             DBG_VERBOUS(GWEN_LOGDOMAIN, "Group \"%s\" using special data", gname);
01859             gcfg=GWEN_DB_GetFirstGroup(gr);
01860           }
01861           else {
01862             DBG_DEBUG(GWEN_LOGDOMAIN, "Unnamed group, using basic data");
01863             gcfg=gr;
01864           }
01865         }
01866 
01867         /* write group as often as needed */
01868         for (loopNr=0; loopNr<maxnum; loopNr++) {
01869           int rv;
01870           int groupIsEmpty;
01871 
01872           groupIsEmpty=0;
01873           posBeforeGroup=GWEN_Buffer_GetPos(gbuf);
01874 
01875           /* find next matching group */
01876           if (gname) {
01877             DBG_DEBUG(GWEN_LOGDOMAIN, "Finding next group named \"%s\"", gname);
01878             while(gcfg) {
01879               if (strcasecmp(GWEN_DB_GroupName(gcfg), gname)==0)
01880                 break;
01881               gcfg=GWEN_DB_GetNextGroup(gcfg);
01882               if (gcfg==0) {
01883                 DBG_DEBUG(GWEN_LOGDOMAIN, "No group found");
01884                 if (loopNr>=minnum)
01885                   groupIsEmpty=1;
01886               }
01887             } /* while */
01888           }
01889 
01890           if (!groupIsEmpty) {
01891             int dive;
01892 
01893             /* write delimiter, if needed */
01894             if (!isFirstElement && delimiter) {
01895               int j;
01896 
01897               DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters", omittedElements+1);
01898               for (j=0; j<omittedElements+1; j++) {
01899                 if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
01900                   return -1;
01901                 }
01902               }
01903               omittedElements=0;
01904             }
01905             else
01906               isFirstElement=0;
01907 
01908             /* write group */
01909 
01910             if (GWEN_XMLNode_Path_Dive(nodePath, n)) {
01911               DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
01912               return -1;
01913             }
01914             if (n==gn)
01915               dive=1;
01916             else {
01917               if (GWEN_XMLNode_Path_Dive(nodePath, gn)) {
01918                 DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
01919                 return -1;
01920               }
01921               dive=2;
01922             }
01923             rv=GWEN_MsgEngine__WriteGroup(e,
01924                                           gbuf,
01925                                           gn,
01926                                           n,
01927                                           gcfg,
01928                                           loopNr>=minnum || groupIsOptional,
01929                                           nodePath);
01930             GWEN_XMLNode_Path_Surface(nodePath);
01931             if (dive==2)
01932               GWEN_XMLNode_Path_Surface(nodePath);
01933             if (rv==-1){
01934               DBG_INFO(GWEN_LOGDOMAIN, "Could not write group \"%s\"", gtype);
01935               if (gn) {
01936                 DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
01937                 GWEN_XMLNode_Dump(gn, 1);
01938               }
01939               if (n) {
01940                 DBG_INFO(GWEN_LOGDOMAIN, "Referring node is:");
01941                 GWEN_XMLNode_Dump(n, 1);
01942               }
01943               if (gr) {
01944                 DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
01945                 GWEN_DB_Dump(gr, 1);
01946               }
01947               return -1;
01948             }
01949             else if (rv==0) {
01950               hasEntries=1;
01951             }
01952             else
01953               groupIsEmpty=1;
01954           }
01955 
01956           if (groupIsEmpty) {
01957             DBG_DEBUG(GWEN_LOGDOMAIN, "Empty Group");
01958             GWEN_Buffer_SetPos(gbuf, posBeforeGroup);
01959             GWEN_Buffer_Crop(gbuf, 0, posBeforeGroup);
01960 
01961             if (loopNr>=minnum) {
01962               DBG_DEBUG(GWEN_LOGDOMAIN, "No data for group \"%s[%d]\", omitting",
01963                         gname, loopNr);
01964               if (strcasecmp(addEmptyMode, "max")==0) {
01965                 DBG_VERBOUS(GWEN_LOGDOMAIN, "Adding max empty");
01966                 omittedElements+=(maxnum-loopNr);
01967               }
01968               else if (strcasecmp(addEmptyMode, "min")==0) {
01969                 DBG_VERBOUS(GWEN_LOGDOMAIN, "Adding min empty");
01970                 if (loopNr<minnum)
01971                   omittedElements+=(minnum-loopNr);
01972               }
01973               else if (strcasecmp(addEmptyMode, "one")==0) {
01974                 if (loopNr==0)
01975                   omittedElements++;
01976               }
01977               else if (strcasecmp(addEmptyMode, "none")==0) {
01978               }
01979               else {
01980                 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
01981                           addEmptyMode);
01982                 return -1;
01983               }
01984               break;
01985             }
01986             else {
01987               DBG_ERROR(GWEN_LOGDOMAIN, "No data for group \"%s[%d]\"",
01988                         gname, loopNr);
01989               return -1;
01990             }
01991           } /* if empty group */
01992           /* use next group next time if any */
01993           if (gcfg)
01994             gcfg=GWEN_DB_GetNextGroup(gcfg);
01995         } /* for */
01996       }
01997     }
01998     else if (t==GWEN_XMLNodeTypeData) {
01999     }
02000     else {
02001       DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled node type %d", t);
02002     }
02003     n=GWEN_XMLNode_Next(n);
02004   } /* while */
02005 
02006   /* write terminating character, if any */
02007   if (terminator) {
02008     if (GWEN_Buffer_AppendByte(gbuf, terminator)) {
02009       DBG_INFO(GWEN_LOGDOMAIN, "called from here");
02010       return -1;
02011     }
02012   }
02013 
02014   if (!hasEntries) {
02015     DBG_INFO(GWEN_LOGDOMAIN, "No entries in node");
02016   }
02017   return hasEntries?0:1;
02018 }
02019 
02020 
02021 
02022 int GWEN_MsgEngine_CreateMessageFromNode(GWEN_MSGENGINE *e,
02023                                          GWEN_XMLNODE *node,
02024                                          GWEN_BUFFER *gbuf,
02025                                          GWEN_DB_NODE *msgData){
02026   GWEN_XMLNODE_PATH *np;
02027   int rv;
02028 
02029   assert(e);
02030   assert(node);
02031   assert(msgData);
02032 
02033   np=GWEN_XMLNode_Path_new();
02034   GWEN_XMLNode_Path_Dive(np, node);
02035   rv=GWEN_MsgEngine__WriteGroup(e,
02036                                 gbuf,
02037                                 node,
02038                                 0,
02039                                 msgData,
02040                                 0,
02041                                 np);
02042   GWEN_XMLNode_Path_free(np);
02043   if (rv){
02044     const char *p;
02045 
02046     p=GWEN_XMLNode_GetData(node);
02047     if (p) {
02048       DBG_INFO(GWEN_LOGDOMAIN, "Error writing group \"%s\"", p);
02049     }
02050     else {
02051       DBG_INFO(GWEN_LOGDOMAIN, "Error writing group");
02052     }
02053     return -1;
02054   }
02055 
02056   return 0;
02057 }
02058 
02059 
02060 
02061 int GWEN_MsgEngine_CreateMessage(GWEN_MSGENGINE *e,
02062                                  const char *msgName,
02063                                  int msgVersion,
02064                                  GWEN_BUFFER *gbuf,
02065                                  GWEN_DB_NODE *msgData) {
02066   GWEN_XMLNODE *group;
02067 
02068   group=GWEN_MsgEngine_FindGroupByProperty(e, "id", msgVersion, msgName);
02069   if (!group) {
02070     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
02071     return -1;
02072   }
02073   return GWEN_MsgEngine_CreateMessageFromNode(e,
02074                                               group,
02075                                               gbuf,
02076                                               msgData);
02077 }
02078 
02079 
02080 
02081 int GWEN_MsgEngine_AddDefinitions(GWEN_MSGENGINE *e,
02082                                   GWEN_XMLNODE *node) {
02083   GWEN_XMLNODE *nsrc, *ndst;
02084 
02085   assert(e);
02086   assert(node);
02087 
02088   if (!e->defs) {
02089     e->defs=GWEN_XMLNode_dup(node);
02090     e->ownDefs=1;
02091     return 0;
02092   }
02093 
02094   nsrc=GWEN_XMLNode_GetChild(node);
02095   while(nsrc) {
02096     if (GWEN_XMLNode_GetType(nsrc)==GWEN_XMLNodeTypeTag) {
02097       ndst=GWEN_XMLNode_FindNode(e->defs, GWEN_XMLNodeTypeTag,
02098                                  GWEN_XMLNode_GetData(nsrc));
02099       if (ndst) {
02100         GWEN_XMLNODE *n;
02101 
02102         n=GWEN_XMLNode_GetChild(nsrc);
02103         while (n) {
02104           GWEN_XMLNODE *newNode;
02105 
02106           DBG_DEBUG(GWEN_LOGDOMAIN, "Adding node \"%s\"", GWEN_XMLNode_GetData(n));
02107           newNode=GWEN_XMLNode_dup(n);
02108           GWEN_XMLNode_AddChild(ndst, newNode);
02109           n=GWEN_XMLNode_Next(n);
02110         } /* while n */
02111       }
02112       else {
02113         GWEN_XMLNODE *newNode;
02114 
02115         DBG_DEBUG(GWEN_LOGDOMAIN, "Adding branch \"%s\"", GWEN_XMLNode_GetData(nsrc));
02116         newNode=GWEN_XMLNode_dup(nsrc);
02117         GWEN_XMLNode_AddChild(e->defs, newNode);
02118       }
02119     } /* if TAG */
02120     nsrc=GWEN_XMLNode_Next(nsrc);
02121   } /* while */
02122 
02123   return 0;
02124 }
02125 
02126 
02127 
02128 int GWEN_MsgEngine__ShowElement(GWEN_UNUSED GWEN_MSGENGINE *e,
02129                                 const char *path,
02130                                 GWEN_XMLNODE *node,
02131                                 GWEN_STRINGLIST *sl,
02132                                 uint32_t flags) {
02133   const char *name;
02134   const char *type;
02135   const char *npath;
02136   unsigned int minsize;
02137   unsigned int maxsize;
02138   unsigned int minnum;
02139   unsigned int maxnum;
02140   int j;
02141   int isSet;
02142   char nbuffer[256];
02143   GWEN_STRINGLISTENTRY *en;
02144 
02145   /* get type */
02146   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02147 
02148   /* get some sizes */
02149   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
02150   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
02151   minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
02152   maxnum=atoi(GWEN_XMLNode_GetProperty(node, "maxnum","1"));
02153 
02154   npath="";
02155   isSet=0;
02156 
02157   /* get name */
02158   name=GWEN_XMLNode_GetProperty(node, "name", 0);
02159   if (path==0)
02160     path="";
02161 
02162   if (name) {
02163     /* get value of a config variable */
02164     if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
02165       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02166       return -1;
02167     }
02168     if (*path)
02169       sprintf(nbuffer, "%s/%s", path, name);
02170     else
02171       sprintf(nbuffer, "%s", name);
02172     npath=nbuffer;
02173   }
02174 
02175   en=GWEN_StringList_FirstEntry(sl);
02176   while(en) {
02177     if (GWEN_StringListEntry_Data(en))
02178       if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
02179         isSet=1;
02180         break;
02181       }
02182     en=GWEN_StringListEntry_Next(en);
02183   } /* while */
02184 
02185   if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
02186     return 0;
02187 
02188   fprintf(stdout, "  %s",
02189           npath);
02190   j=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(npath);
02191   if (j>0) {
02192     int i;
02193 
02194     for (i=0; i<j; i++)
02195       fprintf(stdout, " ");
02196   }
02197   fprintf(stdout, "| %s", type);
02198   j=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(type);
02199   if (j>0) {
02200     int i;
02201 
02202     for (i=0; i<j; i++)
02203       fprintf(stdout, " ");
02204   }
02205   fprintf(stdout, "| %4d-%4d", minsize, maxsize);
02206   fprintf(stdout," | %3d ", maxnum);
02207   fprintf(stdout," |");
02208   if (minnum==0)
02209     fprintf(stdout," optvar");
02210   if (flags & GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL)
02211     fprintf(stdout," optgrp");
02212 
02213   if (isSet) {
02214     fprintf(stdout," set");
02215   }
02216 
02217   fprintf(stdout,"\n");
02218 
02219   return 0;
02220 }
02221 
02222 
02223 
02224 int GWEN_MsgEngine__ShowGroup(GWEN_MSGENGINE *e,
02225                               const char *path,
02226                               GWEN_XMLNODE *node,
02227                               GWEN_XMLNODE *rnode,
02228                               GWEN_STRINGLIST *sl,
02229                               uint32_t flags) {
02230   GWEN_XMLNODE *n;
02231   int isFirstElement;
02232   int omittedElements;
02233   int rv;
02234 
02235   /* setup data */
02236   n=GWEN_XMLNode_GetChild(node);
02237 
02238   if (path==0)
02239     path="";
02240   if (*path=='/')
02241     path++;
02242 
02243   while(n) {
02244     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02245       const char *p;
02246 
02247       p=GWEN_XMLNode_GetData(n);
02248       assert(p);
02249       DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
02250       if (strcasecmp(p, "VALUES")==0)
02251         break;
02252     } /* if tag */
02253     n=GWEN_XMLNode_Next(n);
02254   } /* while */
02255 
02256   if (n) {
02257     DBG_DEBUG(GWEN_LOGDOMAIN, "<preset> found");
02258     /* <preset> found, handle all values */
02259     n=GWEN_XMLNode_GetChild(n);
02260     while(n) {
02261       if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02262         const char *p;
02263 
02264         p=GWEN_XMLNode_GetData(n);
02265         assert(p);
02266         if (strcasecmp(p, "VALUE")==0) {
02267           const char *pname;
02268           const char *pvalue;
02269 
02270           pname=GWEN_XMLNode_GetProperty(n, "path", 0);
02271           if (pname) {
02272             GWEN_XMLNODE *dn;
02273 
02274             /* path found, find data */
02275             dn=GWEN_XMLNode_GetChild(n);
02276             while (dn) {
02277               if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) {
02278                 pvalue=GWEN_XMLNode_GetData(dn);
02279                 if (pvalue) {
02280                   char pbuffer[256];
02281 
02282                   /* check whether the value is a property */
02283                   p=pvalue;
02284                   while (*p && isspace((int)*p))
02285                     p++;
02286                   if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
02287                     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02288                     return -1;
02289                   }
02290                   if (*path)
02291                     sprintf(pbuffer, "%s/%s", path, pname);
02292                   else
02293                     sprintf(pbuffer, "%s", pname);
02294                   GWEN_StringList_AppendString(sl,
02295                                                pbuffer,
02296                                                0,
02297                                                1);
02298                 }
02299                 break;
02300               }
02301               dn=GWEN_XMLNode_Next(dn);
02302             } /* while dn */
02303           } /* if path given */
02304         } /* if VALUE tag */
02305       } /* if TAG */
02306       n=GWEN_XMLNode_Next(n);
02307     } /* while */
02308   } /* if <preset> found */
02309 
02310   /* now handle all child entries */
02311   n=GWEN_XMLNode_GetChild(node);
02312   isFirstElement=1;
02313   omittedElements=0;
02314   while(n) {
02315     int t;
02316     unsigned int minnum;
02317     unsigned int maxnum;
02318     int gversion;
02319     const char *addEmptyMode;
02320     unsigned int loopNr;
02321     unsigned int lflags;
02322 
02323     minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
02324     maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
02325     gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
02326     addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one");
02327 
02328     lflags=flags;
02329 
02330     DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements);
02331     t=GWEN_XMLNode_GetType(n);
02332     if (t==GWEN_XMLNodeTypeTag) {
02333       const char *typ;
02334 
02335       typ=GWEN_XMLNode_GetData(n);
02336       if (typ==0) {
02337         DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
02338         return -1;
02339       }
02340       if (strcasecmp(typ, "ELEM")==0) {
02341         /* element tag found */
02342 
02343         /* write element as often as needed */
02344         rv=GWEN_MsgEngine__ShowElement(e,
02345                                        path,
02346                                        n,
02347                                        sl,
02348                                        lflags);
02349         if (rv==-1)
02350           return -1;
02351         else {
02352           isFirstElement=0;
02353           omittedElements=0;
02354         }
02355       }
02356       else if (strcasecmp(typ, "VALUES")==0) {
02357       }
02358       else if (strcasecmp(typ, "DESCR")==0) {
02359       }
02360       else {
02361         /* group tag found */
02362         GWEN_XMLNODE *gn;
02363         const char *gname;
02364         const char *gtype;
02365 
02366         if (minnum==0)
02367           lflags|=GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL;
02368 
02369         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
02370         if (!gtype) {
02371           /* no "type" property, so use this group directly */
02372           DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
02373           gtype="";
02374           gn=n;
02375         }
02376         else {
02377           gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
02378           if (!gn) {
02379             DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
02380             return -1;
02381           }
02382         }
02383 
02384         /* write group as often as needed */
02385         for (loopNr=0; loopNr<maxnum; loopNr++) {
02386           /* find group */
02387           char pbuffer[256];
02388           const char *npath;
02389 
02390           /* get configuration */
02391           gname=GWEN_XMLNode_GetProperty(n, "name",0);
02392           if (gname) {
02393             if (loopNr==0) {
02394               if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
02395                 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02396                 return -1;
02397               }
02398               sprintf(pbuffer, "%s/%s", path, gname);
02399               npath=pbuffer;
02400             }
02401             else {
02402               /* this is not the first one, so create new name */
02403               if (strlen(path)+strlen(gname)+10>sizeof(pbuffer)) {
02404                 DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02405                 return -1;
02406               }
02407               if (*path)
02408                 sprintf(pbuffer, "%s/%s%d", path, gname, loopNr);
02409               else
02410                 sprintf(pbuffer, "%s%d", gname, loopNr);
02411               /* get the value of the given var */
02412               npath=pbuffer;
02413             }
02414           } /* if name given */
02415           else
02416             npath=path;
02417 
02418           /* write group */
02419           if (GWEN_MsgEngine__ShowGroup(e,
02420                                         npath,
02421                                         gn,
02422                                         n,
02423                                         sl,
02424                                         lflags)) {
02425             DBG_INFO(GWEN_LOGDOMAIN, "Could not show group \"%s\"", gtype);
02426             return -1;
02427           }
02428         } /* for */
02429       }
02430     }
02431     n=GWEN_XMLNode_Next(n);
02432   } /* while */
02433 
02434   return 0;
02435 }
02436 
02437 
02438 
02439 int GWEN_MsgEngine_ShowMessage(GWEN_MSGENGINE *e,
02440                                const char *typ,
02441                                const char *msgName,
02442                                int msgVersion,
02443                                uint32_t flags) {
02444   GWEN_XMLNODE *group;
02445   GWEN_STRINGLIST *sl;
02446   int i, j;
02447   const char *p;
02448 
02449   sl=GWEN_StringList_new();
02450 
02451   fprintf(stdout, "Message \"%s\" version %d\n",
02452           msgName, msgVersion);
02453   for (i=0; i<76; i++)
02454     fprintf(stdout, "=");
02455   fprintf(stdout, "\n");
02456   p="        Variable";
02457   fprintf(stdout, "%s", p);
02458   i=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(p);
02459   for (j=0; j<i; j++)
02460     fprintf(stdout," ");
02461 
02462   fprintf(stdout,"  |");
02463   p=" Type";
02464   fprintf(stdout, "%s", p);
02465   i=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(p);
02466   for (j=0; j<i; j++)
02467     fprintf(stdout," ");
02468 
02469   fprintf(stdout," |   Size    | Num  | Flags\n");
02470   for (i=0; i<76; i++)
02471     fprintf(stdout, "-");
02472   fprintf(stdout, "\n");
02473 
02474   group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
02475   if (!group) {
02476     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
02477     GWEN_StringList_free(sl);
02478     return -1;
02479   }
02480 
02481   if (GWEN_MsgEngine__ShowGroup(e,
02482                                 "",
02483                                 group,
02484                                 0,
02485                                 sl,
02486                                 flags)) {
02487     DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
02488     GWEN_StringList_free(sl);
02489     return -1;
02490   }
02491 
02492   GWEN_StringList_free(sl);
02493 
02494   return 0;
02495 }
02496 
02497 
02498 
02499 int GWEN_MsgEngine__ListElement(GWEN_UNUSED GWEN_MSGENGINE *e,
02500                                 const char *path,
02501                                 GWEN_XMLNODE *node,
02502                                 GWEN_STRINGLIST *sl,
02503                                 GWEN_XMLNODE *listNode,
02504                                 uint32_t flags) {
02505   const char *name;
02506   const char *type;
02507   const char *npath;
02508   int isSet;
02509   char nbuffer[256];
02510   GWEN_STRINGLISTENTRY *en;
02511   GWEN_XMLNODE *nn;
02512 
02513   /* get type */
02514   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02515 
02516   npath="";
02517   isSet=0;
02518 
02519   /* get name */
02520   name=GWEN_XMLNode_GetProperty(node, "name", 0);
02521   if (path==0)
02522     path="";
02523 
02524   if (name) {
02525     /* get value of a config variable */
02526     if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
02527       DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02528       return -1;
02529     }
02530     if (*path)
02531       sprintf(nbuffer, "%s/%s", path, name);
02532     else
02533       sprintf(nbuffer, "%s", name);
02534     npath=nbuffer;
02535   }
02536 
02537   en=GWEN_StringList_FirstEntry(sl);
02538   while(en) {
02539     if (GWEN_StringListEntry_Data(en))
02540       if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
02541         isSet=1;
02542         break;
02543       }
02544     en=GWEN_StringListEntry_Next(en);
02545   } /* while */
02546 
02547   if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
02548     return 0;
02549 
02550   nn=GWEN_XMLNode_dup(node);
02551   if (isSet)
02552     GWEN_XMLNode_SetProperty(nn, "GWEN_set", "1");
02553   GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
02554   GWEN_XMLNode_AddChild(listNode, nn);
02555 
02556   return 0;
02557 }
02558 
02559 
02560 
02561 int GWEN_MsgEngine__ListGroup(GWEN_MSGENGINE *e,
02562                               const char *path,
02563                               GWEN_XMLNODE *node,
02564                               GWEN_XMLNODE *rnode,
02565                               GWEN_STRINGLIST *sl,
02566                               GWEN_XMLNODE *listNode,
02567                               uint32_t flags) {
02568   GWEN_XMLNODE *n;
02569   int rv;
02570 
02571   /* setup data */
02572   n=GWEN_XMLNode_GetChild(node);
02573 
02574   if (path==0)
02575     path="";
02576   if (*path=='/')
02577     path++;
02578 
02579   while(n) {
02580     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02581       const char *p;
02582 
02583       p=GWEN_XMLNode_GetData(n);
02584       assert(p);
02585       DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
02586       if (strcasecmp(p, "VALUES")==0)
02587         break;
02588     } /* if tag */
02589     n=GWEN_XMLNode_Next(n);
02590   } /* while */
02591 
02592   if (n) {
02593     DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found");
02594     /* <values> found, handle all values */
02595     n=GWEN_XMLNode_GetChild(n);
02596     while(n) {
02597       if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
02598         const char *p;
02599 
02600         p=GWEN_XMLNode_GetData(n);
02601         assert(p);
02602         if (strcasecmp(p, "VALUE")==0) {
02603           const char *pname;
02604           const char *pvalue;
02605 
02606           pname=GWEN_XMLNode_GetProperty(n, "path", 0);
02607           if (pname) {
02608             GWEN_XMLNODE *dn;
02609 
02610             /* path found, find data */
02611             dn=GWEN_XMLNode_GetChild(n);
02612             while (dn) {
02613               if (GWEN_XMLNode_GetType(dn)==GWEN_XMLNodeTypeData) {
02614                 pvalue=GWEN_XMLNode_GetData(dn);
02615                 if (pvalue) {
02616                   char pbuffer[256];
02617 
02618                   /* check whether the value is a property */
02619                   p=pvalue;
02620                   while (*p && isspace((int)*p))
02621                     p++;
02622                   if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
02623                     DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02624                     return -1;
02625                   }
02626                   if (*path)
02627                     sprintf(pbuffer, "%s/%s", path, pname);
02628                   else
02629                       sprintf(pbuffer, "%s", pname);
02630                   DBG_INFO(GWEN_LOGDOMAIN, "Found preset value for %s", pbuffer);
02631                   GWEN_StringList_AppendString(sl,
02632                                                pbuffer,
02633                                                0,
02634                                                1);
02635                 }
02636                 break;
02637               }
02638               dn=GWEN_XMLNode_Next(dn);
02639             } /* while dn */
02640           } /* if path given */
02641         } /* if VALUE tag */
02642       } /* if TAG */
02643       n=GWEN_XMLNode_Next(n);
02644     } /* while */
02645   } /* if <values> found */
02646 
02647   /* now handle all child entries */
02648   n=GWEN_XMLNode_GetChild(node);
02649   while(n) {
02650     int t;
02651     int gversion;
02652     unsigned int lflags;
02653 
02654     gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
02655     lflags=flags;
02656 
02657     t=GWEN_XMLNode_GetType(n);
02658     if (t==GWEN_XMLNodeTypeTag) {
02659       const char *typ;
02660 
02661       typ=GWEN_XMLNode_GetData(n);
02662       if (typ==0) {
02663         DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
02664         return -1;
02665       }
02666       if (strcasecmp(typ, "ELEM")==0) {
02667         /* element tag found */
02668 
02669         /* list element */
02670         rv=GWEN_MsgEngine__ListElement(e,
02671                                        path,
02672                                        n,
02673                                        sl,
02674                                        listNode,
02675                                        lflags);
02676         if (rv==-1)
02677           return -1;
02678       }
02679       else if (strcasecmp(typ, "VALUES")==0) {
02680       }
02681       else if (strcasecmp(typ, "DESCR")==0) {
02682       }
02683       else {
02684         /* group tag found */
02685         GWEN_XMLNODE *gn;
02686         GWEN_XMLNODE *nn;
02687         const char *gname;
02688         const char *gtype;
02689         char pbuffer[256];
02690         const char *npath;
02691 
02692         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
02693         if (!gtype) {
02694           /* no "type" property, so use this group directly */
02695           DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
02696           gtype="";
02697           gn=n;
02698         }
02699         else {
02700           gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
02701           if (!gn) {
02702             DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
02703             return -1;
02704           }
02705         }
02706 
02707         /* get configuration */
02708         gname=GWEN_XMLNode_GetProperty(n, "name",0);
02709         if (gname) {
02710           if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
02711             DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
02712             return -1;
02713           }
02714 
02715           if (*path)
02716             sprintf(pbuffer, "%s/%s", path, gname);
02717           else
02718             sprintf(pbuffer, "%s", gname);
02719           npath=pbuffer;
02720         } /* if name given */
02721         else
02722           npath=path;
02723 
02724         nn=GWEN_XMLNode_dup(n);
02725         if (gn!=n)
02726           GWEN_XMLNode_CopyProperties(nn, gn, 0);
02727         GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
02728         GWEN_XMLNode_AddChild(listNode, nn);
02729 
02730         /* write group */
02731         if (GWEN_MsgEngine__ListGroup(e,
02732                                       npath,
02733                                       gn,
02734                                       n,
02735                                       sl,
02736                                       nn,
02737                                       lflags)) {
02738           DBG_INFO(GWEN_LOGDOMAIN, "Could not list group \"%s\"", gtype);
02739           return -1;
02740         }
02741       }
02742     }
02743     n=GWEN_XMLNode_Next(n);
02744   } /* while */
02745 
02746   return 0;
02747 }
02748 
02749 
02750 
02751 GWEN_XMLNODE *GWEN_MsgEngine_ListMessage(GWEN_MSGENGINE *e,
02752                                          const char *typ,
02753                                          const char *msgName,
02754                                          int msgVersion,
02755                                          uint32_t flags) {
02756   GWEN_XMLNODE *group;
02757   GWEN_STRINGLIST *sl;
02758   GWEN_XMLNODE *listNode;
02759 
02760   group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
02761   if (!group)
02762     group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "code",
02763                                             msgVersion, msgName);
02764   if (!group) {
02765     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" (version %d) not found\n",
02766               msgName, msgVersion);
02767     return 0;
02768   }
02769 
02770   sl=GWEN_StringList_new();
02771   /* copy group, but remove all children (we only want the properties) */
02772   listNode=GWEN_XMLNode_dup(group);
02773   GWEN_XMLNode_RemoveChildren(listNode);
02774 
02775   if (GWEN_MsgEngine__ListGroup(e,
02776                                 "",
02777                                 group,
02778                                 0,
02779                                 sl,
02780                                 listNode,
02781                                 flags)) {
02782     DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
02783     GWEN_StringList_free(sl);
02784     GWEN_XMLNode_free(listNode);
02785     return 0;
02786   }
02787 
02788   GWEN_StringList_free(sl);
02789 
02790   return listNode;
02791 }
02792 
02793 
02794 
02795 
02796 
02797 
02798 
02799 int GWEN_MsgEngine__ReadValue(GWEN_MSGENGINE *e,
02800                               GWEN_BUFFER *msgbuf,
02801                               GWEN_XMLNODE *node,
02802                               GWEN_XMLNODE *rnode,
02803                               GWEN_BUFFER *vbuf,
02804                               const char *delimiters,
02805                               uint32_t flags) {
02806   unsigned int minsize;
02807   unsigned int maxsize;
02808   unsigned int size;
02809   unsigned int minnum;
02810   GWEN_MSGENGINE_TRUSTLEVEL trustLevel;
02811   unsigned int posInMsg;
02812   const char *type;
02813   int rv;
02814   unsigned int realSize;
02815 
02816   /* get some sizes */
02817   posInMsg=GWEN_Buffer_GetPos(msgbuf);
02818   realSize=0;
02819   size=atoi(GWEN_XMLNode_GetProperty(node, "size","0"));
02820   minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
02821   maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
02822   minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
02823   type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
02824 
02825   rv=1;
02826   if (e->typeReadPtr) {
02827     rv=e->typeReadPtr(e,
02828                       msgbuf,
02829                       node,
02830                       vbuf,
02831                       e->escapeChar,
02832                       delimiters);
02833   }
02834   if (rv==-1) {
02835     DBG_INFO(GWEN_LOGDOMAIN, "External type reading failed on type \"%s\"", type);
02836     return -1;
02837   }
02838   else if (rv==1) {
02839     if (strcasecmp(type, "bin")==0) {
02840       if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) {
02841         DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (@num@ expected)");
02842         return -1;
02843       }
02844       else {
02845         char lbuffer[16];
02846         int c;
02847         char *p;
02848         int l;
02849 
02850         p=lbuffer;
02851         c=GWEN_Buffer_ReadByte(msgbuf);
02852         if (c!='@') {
02853           DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
02854           return -1;
02855         }
02856 
02857         c=0;
02858         while(GWEN_Buffer_GetBytesLeft(msgbuf)>0) {
02859           c=GWEN_Buffer_ReadByte(msgbuf);
02860           if (c==-1) {
02861             DBG_ERROR(GWEN_LOGDOMAIN, "\"@\" expected");
02862             return -1;
02863           }
02864           if (c=='@')
02865             break;
02866           *p=(char)c;
02867           p++;
02868         } /* while */
02869         *p=0;
02870         if (c!='@') {
02871           DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
02872           return -1;
02873         }
02874         if (sscanf(lbuffer, "%d", &l)!=1) {
02875           DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
02876           return -1;
02877         }
02878         DBG_DEBUG(GWEN_LOGDOMAIN, "Reading binary: %d bytes from pos %d (msgsize=%d)",
02879                  l,
02880                  GWEN_Buffer_GetPos(msgbuf),
02881                  GWEN_Buffer_GetUsedBytes(msgbuf));
02882         if (GWEN_Buffer_GetBytesLeft(msgbuf) < (unsigned) l) {
02883           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
02884           return -1;
02885         }
02886         if (GWEN_Buffer_AppendBytes(vbuf,
02887                                     GWEN_Buffer_GetPosPointer(msgbuf),
02888                                     l)) {
02889           DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
02890           return -1;
02891         }
02892         GWEN_Buffer_IncrementPos(msgbuf,l);
02893       }
02894     } /* if bin */
02895     else {
02896       /* type is not bin */
02897       int lastWasEscape;
02898       int isEscaped;
02899       int br;
02900 
02901       isEscaped=0;
02902       lastWasEscape=0;
02903 
02904       br=0;
02905       while(GWEN_Buffer_GetBytesLeft(msgbuf) &&
02906             (size==0 || br<size)) {
02907         int c;
02908 
02909         c=GWEN_Buffer_ReadByte(msgbuf);
02910         if (lastWasEscape) {
02911           lastWasEscape=0;
02912           isEscaped=1;
02913         }
02914         else {
02915           isEscaped=0;
02916           if (c==e->escapeChar) {
02917             lastWasEscape=1;
02918             c=-1;
02919           }
02920         }
02921         if (c!=-1) {
02922           if (!isEscaped && (c && strchr(delimiters, c)!=0)) {
02923             /* delimiter found, step back */
02924             GWEN_Buffer_DecrementPos(msgbuf,1);
02925             break;
02926           }
02927           else {
02928             if (c=='\\' || iscntrl(c)) {
02929               DBG_WARN(GWEN_LOGDOMAIN,
02930                        "Found a bad character (%02x) in type \"%s\", "
02931                        "converting to SPACE",
02932                        (unsigned int)c,
02933                        type);
02934               c=' ';
02935             }
02936             if (GWEN_Buffer_AppendByte(vbuf, c)) {
02937               DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
02938               return -1;
02939             }
02940             br++;
02941           }
02942         }
02943       } /* while */
02944     } /* if !bin */
02945   } /* if type not external */
02946   else {
02947     DBG_DEBUG(GWEN_LOGDOMAIN, "Type \"%s\" is external (read)", type);
02948   }
02949 
02950   realSize=GWEN_Buffer_GetUsedBytes(vbuf);
02951 
02952   /* check the value */
02953   if (realSize==0) {
02954     DBG_DEBUG(GWEN_LOGDOMAIN, "Datasize is 0");
02955     if (minnum==0) {
02956       DBG_DEBUG(GWEN_LOGDOMAIN, "... but thats ok");
02957       /* value is empty, and that is allowed */
02958       return 1;
02959     }
02960     else {
02961       DBG_ERROR(GWEN_LOGDOMAIN, "Value missing");
02962       GWEN_XMLNode_Dump(node, 1);
02963       return -1;
02964     }
02965   }
02966 
02967   /* check minimum size */
02968   if (minsize!=0 && realSize<minsize) {
02969     DBG_INFO(GWEN_LOGDOMAIN, "Value too short (%d<%d).",
02970              realSize,
02971              minsize);
02972     return -1;
02973   }
02974 
02975   /* check maximum size */
02976   if (maxsize!=0 && realSize>maxsize) {
02977     DBG_INFO(GWEN_LOGDOMAIN, "Value too long (%d>%d).",
02978              realSize, maxsize);
02979     return -1;
02980   }
02981 
02982   if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) {
02983     /* add trust data to msgEngine */
02984     const char *descr;
02985 
02986     trustLevel=GWEN_MsgEngine_GetHighestTrustLevel(node, rnode);
02987     if (trustLevel) {
02988       unsigned int ustart;
02989 
02990       ustart=GWEN_Buffer_GetPos(msgbuf)-realSize;
02991       descr=GWEN_XMLNode_GetProperty(node, "name",0);
02992       if (GWEN_MsgEngine_AddTrustInfo(e,
02993                                       GWEN_Buffer_GetStart(vbuf),
02994                                       realSize,
02995                                       descr,
02996                                       trustLevel,
02997                                       ustart)) {
02998         DBG_INFO(GWEN_LOGDOMAIN, "called from here");
02999         return -1;
03000       }
03001     }
03002   }
03003 
03004   return 0;
03005 }
03006 
03007 
03008 
03009 int GWEN_MsgEngine__ReadGroup(GWEN_MSGENGINE *e,
03010                               GWEN_BUFFER *msgbuf,
03011                               GWEN_XMLNODE *node,
03012                               GWEN_XMLNODE *rnode,
03013                               GWEN_DB_NODE *gr,
03014                               const char *delimiters,
03015                               uint32_t flags) {
03016   unsigned int minsize;
03017   unsigned int maxsize;
03018   unsigned int minnum;
03019   unsigned int maxnum;
03020   const char *name;
03021   const char *p;
03022   char delimiter;
03023   char terminator;
03024   GWEN_XMLNODE *n;
03025   int abortLoop;
03026   GWEN_BUFFER *delimBuffer=0;
03027 
03028   /* get some settings */
03029   if (rnode) {
03030     /* get delimiter */
03031     p=GWEN_XMLNode_GetProperty(rnode,
03032                                "delimiter",
03033                                GWEN_XMLNode_GetProperty(node,
03034                                                         "delimiter",
03035                                                         ""));
03036     delimiter=*p;
03037 
03038     /* get terminating char, if any */
03039     p=GWEN_XMLNode_GetProperty(rnode,
03040                                "terminator",
03041                                GWEN_XMLNode_GetProperty(node,
03042                                                         "terminator",
03043                                                         ""));
03044     terminator=*p;
03045   }
03046   else {
03047     /* get delimiter */
03048     p=GWEN_XMLNode_GetProperty(node,
03049                                "delimiter",
03050                                "");
03051     delimiter=*p;
03052 
03053     /* get terminating char, if any */
03054     p=GWEN_XMLNode_GetProperty(node, "terminator","");
03055     terminator=*p;
03056   }
03057 
03058   delimBuffer=GWEN_Buffer_new(0, strlen(delimiters)+2, 0, 1);
03059   GWEN_Buffer_AppendString(delimBuffer, delimiters);
03060   if (delimiter)
03061     GWEN_Buffer_AppendByte(delimBuffer, delimiter);
03062   if (terminator)
03063     GWEN_Buffer_AppendByte(delimBuffer, terminator);
03064 
03065   DBG_DEBUG(GWEN_LOGDOMAIN, "Delimiters are \"%s\" and \"%c\"",
03066             delimiters, delimiter);
03067 
03068   n=GWEN_XMLNode_GetChild(node);
03069   while (n) {
03070     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
03071       const char *type;
03072 
03073       if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03074         break;
03075 
03076       type=GWEN_XMLNode_GetData(n);
03077 
03078       /*
03079       DBG_NOTICE(GWEN_LOGDOMAIN, "Reading group from here :");
03080       GWEN_Text_DumpString(GWEN_Buffer_GetStart(msgbuf)+
03081                            GWEN_Buffer_GetPos(msgbuf),
03082                            GWEN_Buffer_GetUsedBytes(msgbuf)-
03083                            GWEN_Buffer_GetPos(msgbuf),
03084                            stderr, 3);
03085       */
03086       if (strcasecmp(type, "ELEM")==0) {
03087         unsigned int loopNr;
03088 
03089         /* get some sizes */
03090         minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize","0"));
03091         maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize","0"));
03092         minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
03093         maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
03094         name=GWEN_XMLNode_GetProperty(n, "name", 0);
03095 
03096         loopNr=0;
03097         abortLoop=0;
03098         while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
03099           int c;
03100 
03101           DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %s", name);
03102           if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03103             break;
03104           c=GWEN_Buffer_PeekByte(msgbuf);
03105           if (c==-1) {
03106             DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
03107             GWEN_Buffer_free(delimBuffer);
03108             return -1;
03109           }
03110 
03111           DBG_VERBOUS(GWEN_LOGDOMAIN,
03112                       "Checking delimiter at pos %x "
03113                       "(whether \"%c\" is in \"%s\")",
03114                       GWEN_Buffer_GetPos(msgbuf),
03115                       c, GWEN_Buffer_GetStart(delimBuffer));
03116           if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
03117             abortLoop=1;
03118             DBG_VERBOUS(GWEN_LOGDOMAIN,
03119                         "Found delimiter (\"%c\" is in \"%s\")",
03120                         c, GWEN_Buffer_GetStart(delimBuffer));
03121           } /* if delimiter found */
03122           else {
03123             /* current char is not a delimiter */
03124             if (name==0) {
03125               DBG_VERBOUS(GWEN_LOGDOMAIN, "no name");
03126             }
03127             else {
03128               /* name is given */
03129               int rv;
03130               const char *dtype;
03131               GWEN_BUFFER *vbuf;
03132 
03133               DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading value from pos %x",
03134                           GWEN_Buffer_GetPos(msgbuf));
03135               vbuf=GWEN_Buffer_new(0,
03136                                    GWEN_MSGENGINE_MAX_VALUE_LEN,
03137                                    0,0);
03138               /*
03139               DBG_ERROR(GWEN_LOGDOMAIN, "Reading value from here:\n");
03140               GWEN_Text_DumpString(GWEN_Buffer_GetPosPointer(msgbuf),
03141                                    GWEN_Buffer_GetBytesLeft(msgbuf),
03142                                    stderr, 1);*/
03143 
03144               rv=GWEN_MsgEngine__ReadValue(e,
03145                                            msgbuf,
03146                                            n,
03147                                            rnode,
03148                                            vbuf,
03149                                            GWEN_Buffer_GetStart(delimBuffer),
03150                                            //":+'",
03151                                            flags);
03152               if (rv==1) {
03153                 DBG_INFO(GWEN_LOGDOMAIN, "Empty value");
03154               }
03155               else if (rv==-1) {
03156                 DBG_INFO(GWEN_LOGDOMAIN, "Error parsing node \"%s\" (%s)",
03157                          name,
03158                          type);
03159                 GWEN_Buffer_free(vbuf);
03160                 GWEN_Buffer_free(delimBuffer);
03161                 return -1;
03162               }
03163 
03164               GWEN_Buffer_Rewind(vbuf);
03165 
03166               /* special handling for binary data */
03167               dtype=GWEN_XMLNode_GetProperty(n, "type", "");
03168               if (GWEN_MsgEngine__IsBinTyp(e, dtype)) {
03169                 if (atoi(GWEN_XMLNode_GetProperty(n, "readbin", "1")) &&
03170                     e->binTypeReadPtr) {
03171                   rv=e->binTypeReadPtr(e, n, gr, vbuf);
03172                 }
03173                 else
03174                   rv=1;
03175                 if (rv==-1) {
03176                   DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
03177                   GWEN_Buffer_free(vbuf);
03178                   GWEN_Buffer_free(delimBuffer);
03179                   return -1;
03180                 }
03181                 else if (rv==1) {
03182                   /* bin type not handled, so handle it myself */
03183                   if (GWEN_DB_SetBinValue(gr,
03184                                           GWEN_DB_FLAGS_DEFAULT,
03185                                           name,
03186                                           GWEN_Buffer_GetStart(vbuf),
03187                                           GWEN_Buffer_GetUsedBytes(vbuf))) {
03188                     DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
03189                     GWEN_Buffer_free(vbuf);
03190                     GWEN_Buffer_free(delimBuffer);
03191                     return -1;
03192                   }
03193                 }
03194               } /* if type is bin */
03195               else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) {
03196                 int z;
03197 
03198                 if (1!=sscanf(GWEN_Buffer_GetStart(vbuf), "%d", &z)) {
03199                   DBG_INFO(GWEN_LOGDOMAIN, "Value for \"%s\" is not an integer",
03200                            name);
03201                   GWEN_Buffer_free(delimBuffer);
03202                   return -1;
03203                 }
03204                 if (GWEN_DB_SetIntValue(gr,
03205                                         GWEN_DB_FLAGS_DEFAULT,
03206                                         name, z)) {
03207                   DBG_INFO(GWEN_LOGDOMAIN, "Could not set int value for \"%s\"", name);
03208                   GWEN_Buffer_free(delimBuffer);
03209                   return -1;
03210                 }
03211               } /* if type is int */
03212               else {
03213                 DBG_DEBUG(GWEN_LOGDOMAIN, "Value is \"%s\"",
03214                           GWEN_Buffer_GetStart(vbuf));
03215                 if (GWEN_DB_SetCharValue(gr,
03216                                          GWEN_DB_FLAGS_DEFAULT,
03217                                          name,
03218                                          GWEN_Buffer_GetStart(vbuf))){
03219                   DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
03220                   GWEN_Buffer_free(delimBuffer);
03221                   return -1;
03222                 }
03223               } /* if !bin */
03224 
03225               GWEN_Buffer_free(vbuf);
03226             } /* if name is given */
03227           } /* if current char is not a delimiter */
03228 
03229           if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03230             if (delimiter) {
03231               if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
03232                 GWEN_Buffer_IncrementPos(msgbuf,1);
03233               }
03234             }
03235           }
03236           loopNr++;
03237         } /* while */
03238         if (loopNr<minnum) {
03239           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few ELEM repeats)");
03240           GWEN_XMLNode_Dump(n, 2);
03241           GWEN_Buffer_free(delimBuffer);
03242           return -1;
03243         }
03244         n=GWEN_XMLNode_Next(n);
03245       } /* if ELEM */
03246       else if (strcasecmp(type, "VALUES")==0) {
03247         n=GWEN_XMLNode_Next(n);
03248       }
03249       else if (strcasecmp(type, "DESCR")==0) {
03250         n=GWEN_XMLNode_Next(n);
03251       }
03252       else {
03253         /* group tag found */
03254         GWEN_XMLNODE *gn;
03255         GWEN_DB_NODE *gcfg;
03256         const char *gname;
03257         const char *gtype;
03258         unsigned int gversion;
03259         unsigned int loopNr;
03260 
03261         minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
03262         maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
03263         gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
03264         gtype=GWEN_XMLNode_GetProperty(n, "type",0);
03265         if (!gtype) {
03266           /* no "type" property, so use this group directly */
03267           DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", type);
03268           gtype="";
03269           gn=n;
03270         }
03271         else {
03272           gn=GWEN_MsgEngine_FindNodeByProperty(e, type, "id",
03273                                                gversion, gtype);
03274           if (!gn) {
03275             DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", type);
03276             GWEN_Buffer_free(delimBuffer);
03277             return -1;
03278           }
03279         }
03280 
03281         /* get configuration */
03282         loopNr=0;
03283         abortLoop=0;
03284         while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
03285           int c;
03286 
03287           DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group type %s", gtype);
03288           if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
03289             break;
03290           c=GWEN_Buffer_PeekByte(msgbuf);
03291           if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
03292             abortLoop=1;
03293           }
03294           else {
03295             gname=GWEN_XMLNode_GetProperty(n, "name",0);
03296             if (gname) {
03297               DBG_DEBUG(GWEN_LOGDOMAIN, "Creating group \"%s\"", gname);
03298               gcfg=GWEN_DB_GetGroup(gr,
03299                                     GWEN_PATH_FLAGS_CREATE_GROUP,
03300                                     gname);
03301               if (!gcfg) {
03302                 DBG_ERROR(GWEN_LOGDOMAIN, "Could not select group \"%s\"",
03303                           gname);
03304                 GWEN_Buffer_free(delimBuffer);
03305                 return -1;
03306               }
03307               DBG_DEBUG(GWEN_LOGDOMAIN, "Created group \"%s\"", gname);
03308             } /* if name given */
03309             else
03310               gcfg=gr;
03311 
03312             /* read group */
03313             DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group \"%s\"", gname);
03314             if (GWEN_MsgEngine__ReadGroup(e,
03315                                           msgbuf,
03316                                           gn,
03317                                           n,
03318                                           gcfg,
03319                                           GWEN_Buffer_GetStart(delimBuffer),
03320                                           flags)) {
03321               DBG_INFO(GWEN_LOGDOMAIN, "Could not read group \"%s\"", gtype);
03322               GWEN_Buffer_free(delimBuffer);
03323               return -1;
03324             }
03325           }
03326           if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03327             if (delimiter) {
03328               if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
03329                 GWEN_Buffer_IncrementPos(msgbuf, 1);
03330               }
03331             }
03332           }
03333           loopNr++;
03334         } /* while */
03335         if (loopNr<minnum) {
03336           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few group repeats)");
03337           GWEN_Buffer_free(delimBuffer);
03338           return -1;
03339         }
03340         n=GWEN_XMLNode_Next(n);
03341       } /* if GROUP */
03342     } /* if TAG */
03343     else {
03344       n=GWEN_XMLNode_Next(n);
03345     }
03346   } /* while */
03347 
03348   /* check whether there still are nodes which have not been read */
03349   while(n) {
03350     if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
03351       if (strcasecmp(GWEN_XMLNode_GetData(n), "ELEM")==0 ||
03352           strcasecmp(GWEN_XMLNode_GetData(n), "GROUP")==0) {
03353         unsigned int i;
03354 
03355         i=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1"));
03356         if (i) {
03357           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (still tags to parse)");
03358           GWEN_XMLNode_Dump(n, 2);
03359           GWEN_Buffer_free(delimBuffer);
03360           return -1;
03361         }
03362       }
03363     }
03364     n=GWEN_XMLNode_Next(n);
03365   }
03366 
03367 
03368   if (terminator) {
03369     /* skip terminator */
03370     if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
03371       if (GWEN_Buffer_PeekByte(msgbuf)==terminator) {
03372         GWEN_Buffer_IncrementPos(msgbuf, 1);
03373       }
03374       else {
03375         DBG_ERROR(GWEN_LOGDOMAIN,
03376                   "Terminating character missing (pos=%d [%x]) "
03377                   "expecting \"%c\", got \"%c\")",
03378                   GWEN_Buffer_GetPos(msgbuf),
03379                   GWEN_Buffer_GetPos(msgbuf),
03380                   terminator,
03381                   GWEN_Buffer_PeekByte(msgbuf));
03382         GWEN_XMLNode_Dump(node, 1);
03383         GWEN_Buffer_free(delimBuffer);
03384         return -1;
03385       }
03386     }
03387     else {
03388       DBG_ERROR(GWEN_LOGDOMAIN, "Terminating character missing");
03389       GWEN_Buffer_free(delimBuffer);
03390       return -1;
03391     }
03392   }
03393 
03394   GWEN_Buffer_free(delimBuffer);
03395   return 0;
03396 }
03397 
03398 
03399 
03400 int GWEN_MsgEngine_ParseMessage(GWEN_MSGENGINE *e,
03401                                 GWEN_XMLNODE *group,
03402                                 GWEN_BUFFER *msgbuf,
03403                                 GWEN_DB_NODE *msgData,
03404                                 uint32_t flags){
03405 
03406   if (GWEN_MsgEngine__ReadGroup(e,
03407                                 msgbuf,
03408                                 group,
03409                                 0,
03410                                 msgData,
03411                                 e->delimiters,
03412                                 flags)) {
03413     DBG_INFO(GWEN_LOGDOMAIN, "Error reading group");
03414     return -1;
03415   }
03416 
03417   return 0;
03418 }
03419 
03420 
03421 
03422 int GWEN_MsgEngine_SetValue(GWEN_MSGENGINE *e,
03423                             const char *path,
03424                             const char *value){
03425   GWEN_DB_NODE *globalValues;
03426 
03427   assert(e);
03428   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03429   assert(globalValues);
03430   return GWEN_DB_SetCharValue(globalValues,
03431                               GWEN_DB_FLAGS_DEFAULT |
03432                               GWEN_DB_FLAGS_OVERWRITE_VARS,
03433                               path, value);
03434 }
03435 
03436 
03437 
03438 int GWEN_MsgEngine_SetIntValue(GWEN_MSGENGINE *e,
03439                                const char *path,
03440                                int value){
03441   GWEN_DB_NODE *globalValues;
03442 
03443   assert(e);
03444   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03445   assert(globalValues);
03446   return GWEN_DB_SetIntValue(globalValues,
03447                              GWEN_DB_FLAGS_DEFAULT |
03448                              GWEN_DB_FLAGS_OVERWRITE_VARS,
03449                              path, value);
03450 }
03451 
03452 
03453 
03454 const char *GWEN_MsgEngine_GetValue(GWEN_MSGENGINE *e,
03455                                     const char *path,
03456                                     const char *defValue){
03457   GWEN_DB_NODE *globalValues;
03458 
03459   assert(e);
03460   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03461   assert(globalValues);
03462   return GWEN_DB_GetCharValue(globalValues,
03463                               path, 0, defValue);
03464 }
03465 
03466 
03467 
03468 int GWEN_MsgEngine_GetIntValue(GWEN_MSGENGINE *e,
03469                                const char *path,
03470                                int defValue){
03471   GWEN_DB_NODE *globalValues;
03472 
03473   assert(e);
03474   globalValues=GWEN_MsgEngine__GetGlobalValues(e);
03475   assert(globalValues);
03476   return GWEN_DB_GetIntValue(globalValues,
03477                              path, 0, defValue);
03478 }
03479 
03480 
03481 
03482 /* --------------------------------------------------------------- FUNCTION */
03483 int GWEN_MsgEngine_SkipSegment(GWEN_UNUSED GWEN_MSGENGINE *e,
03484                                GWEN_BUFFER *msgbuf,
03485                                unsigned char escapeChar,
03486                                unsigned char delimiter) {
03487   int esc;
03488 
03489   esc=0;
03490   while(GWEN_Buffer_GetBytesLeft(msgbuf)) {
03491     if (esc) {
03492       esc=0;
03493     }
03494     else {
03495       int i;
03496       unsigned char c;
03497 
03498       i=GWEN_Buffer_ReadByte(msgbuf);
03499       if (i==-1) {
03500         DBG_INFO(GWEN_LOGDOMAIN, "called from here");
03501         return 0;
03502       }
03503       c=(unsigned int)i;
03504       if (c==escapeChar) { /* escape */
03505         esc=1;
03506       }
03507       else if (c=='@') {
03508       /* skip binary data */
03509         char lbuffer[16];
03510         char *p;
03511         int l;
03512         int nc;
03513 
03514         p=lbuffer;
03515         while(1) {
03516           nc=GWEN_Buffer_ReadByte(msgbuf);
03517           if (nc==-1) {
03518             DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
03519             return -1;
03520           }
03521           if (nc=='@')
03522             break;
03523           *p=nc;
03524           p++;
03525         } /* while */
03526         *p=0;
03527         if (sscanf(lbuffer, "%d", &l)!=1) {
03528           DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
03529           return -1;
03530         }
03531         if (GWEN_Buffer_GetUsedBytes(msgbuf)-GWEN_Buffer_GetPos(msgbuf) 
03532             < (unsigned) l) {
03533           DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
03534           return -1;
03535         }
03536         GWEN_Buffer_IncrementPos(msgbuf, l);
03537       }
03538       else if (c==delimiter) {/* segment-end */
03539         return 0;
03540         break;
03541       }
03542     }
03543   } /* while */
03544 
03545   DBG_ERROR(GWEN_LOGDOMAIN, "End of segment not found");
03546   return -1;
03547 }
03548 
03549 
03550 
03551 /* --------------------------------------------------------------- FUNCTION */
03552 int GWEN_MsgEngine_ReadMessage(GWEN_MSGENGINE *e,
03553                                const char *gtype,
03554                                GWEN_BUFFER *mbuf,
03555                                GWEN_DB_NODE *gr,
03556                                uint32_t flags) {
03557   unsigned int segments;
03558 
03559   segments=0;
03560 
03561   while(GWEN_Buffer_GetBytesLeft(mbuf)) {
03562     GWEN_XMLNODE *node;
03563     unsigned int posBak;
03564     const char *p;
03565     GWEN_DB_NODE *tmpdb;
03566     int segVer;
03567 
03568     /* find head segment description */
03569     tmpdb=GWEN_DB_Group_new("tmpdb");
03570     node=GWEN_MsgEngine_FindGroupByProperty(e,
03571                                             "id",
03572                                             0,
03573                                             "SegHead");
03574     if (node==0) {
03575       DBG_ERROR(GWEN_LOGDOMAIN, "Segment description not found");
03576       GWEN_DB_Group_free(tmpdb);
03577       return -1;
03578     }
03579 
03580     /* parse head segment */
03581     posBak=GWEN_Buffer_GetPos(mbuf);
03582     if (GWEN_MsgEngine_ParseMessage(e,
03583                                     node,
03584                                     mbuf,
03585                                     tmpdb,
03586                                     flags)) {
03587       DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment head");
03588       GWEN_DB_Group_free(tmpdb);
03589       return -1;
03590     }
03591 
03592     /* get segment code */
03593     segVer=GWEN_DB_GetIntValue(tmpdb,
03594                                "version",
03595                                0,
03596                                0);
03597     p=GWEN_DB_GetCharValue(tmpdb,
03598                            "code",
03599                            0,
03600                            0);
03601     if (!p) {
03602       DBG_ERROR(GWEN_LOGDOMAIN, "No segment code for %s ? This seems to be a bad msg...",
03603                 gtype);
03604       GWEN_Buffer_SetPos(mbuf, posBak);
03605       DBG_ERROR(GWEN_LOGDOMAIN, "Full message (pos=%04x)", posBak);
03606       GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf),
03607                            GWEN_Buffer_GetUsedBytes(mbuf),
03608                            1);
03609       GWEN_DB_Dump(tmpdb, 1);
03610       GWEN_DB_Group_free(tmpdb);
03611       return -1;
03612     }
03613 
03614     /* try to find corresponding XML node */
03615     node=GWEN_MsgEngine_FindNodeByProperty(e,
03616                                            gtype,
03617                                            "code",
03618                                            segVer,
03619                                            p);
03620     if (node==0) {
03621       unsigned int ustart;
03622 
03623       ustart=GWEN_Buffer_GetPos(mbuf);
03624       ustart++; /* skip delimiter */
03625 
03626       /* node not found, skip it */
03627       DBG_NOTICE(GWEN_LOGDOMAIN,
03628                  "Unknown segment \"%s\" (Segnum=%d, version=%d, ref=%d)",
03629                  p,
03630                  GWEN_DB_GetIntValue(tmpdb, "seq", 0, -1),
03631                  GWEN_DB_GetIntValue(tmpdb, "version", 0, -1),
03632                  GWEN_DB_GetIntValue(tmpdb, "ref", 0, -1));
03633       if (GWEN_MsgEngine_SkipSegment(e, mbuf, '?', '\'')) {
03634         DBG_ERROR(GWEN_LOGDOMAIN, "Error skipping segment \"%s\"", p);
03635         GWEN_DB_Group_free(tmpdb);
03636         return -1;
03637       }
03638       if (flags & GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO) {
03639         unsigned int usize;
03640 
03641         usize=GWEN_Buffer_GetPos(mbuf)-ustart-1;
03642 #if 0
03643         GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+ustart,
03644                              usize,
03645                              stderr, 1);
03646 #endif
03647         if (GWEN_MsgEngine_AddTrustInfo(e,
03648                                         GWEN_Buffer_GetStart(mbuf)+ustart,
03649                                         usize,
03650                                         p,
03651                                         GWEN_MsgEngineTrustLevelHigh,
03652                                         ustart)) {
03653           DBG_INFO(GWEN_LOGDOMAIN, "called from here");
03654           GWEN_DB_Group_free(tmpdb);
03655           return -1;
03656         }
03657       } /* if trustInfo handling wanted */
03658     }
03659     else {
03660       /* ok, node available, get the corresponding description and parse
03661        * the segment */
03662       const char *id;
03663       GWEN_DB_NODE *storegrp;
03664       unsigned int startPos;
03665 
03666       /* restore start position, since the segment head is part of a full
03667        * description, so we need to restart reading from the very begin */
03668       GWEN_Buffer_SetPos(mbuf, posBak);
03669 
03670       /* create group in DB for this segment */
03671       id=GWEN_XMLNode_GetProperty(node, "id", p);
03672       storegrp=GWEN_DB_GetGroup(gr,
03673                                 GWEN_PATH_FLAGS_CREATE_GROUP,
03674                                 id);
03675       assert(storegrp);
03676 
03677       /* store the start position of this segment within the DB */
03678       startPos=GWEN_Buffer_GetPos(mbuf);
03679       GWEN_DB_SetIntValue(storegrp,
03680                           GWEN_DB_FLAGS_OVERWRITE_VARS,
03681                           "segment/pos",
03682                           startPos);
03683 
03684       /* parse the segment */
03685       if (GWEN_MsgEngine_ParseMessage(e,
03686                                       node,
03687                                       mbuf,
03688                                       storegrp,
03689                                       flags)) {
03690         DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment \"%s\" at %d (%x)",
03691                   p,
03692                   GWEN_Buffer_GetPos(mbuf)-startPos,
03693                   GWEN_Buffer_GetPos(mbuf)-startPos);
03694         GWEN_Text_DumpString(GWEN_Buffer_GetStart(mbuf)+startPos,
03695                              GWEN_Buffer_GetUsedBytes(mbuf)-startPos,
03696                              1);
03697         DBG_ERROR(GWEN_LOGDOMAIN, "Stored data so far:");
03698         GWEN_DB_Dump(storegrp, 2);
03699         GWEN_DB_Group_free(tmpdb);
03700         return -1;
03701       }
03702 
03703       /* store segment size within DB */
03704       GWEN_DB_SetIntValue(storegrp,
03705                           GWEN_DB_FLAGS_OVERWRITE_VARS,
03706                           "segment/length",
03707                           GWEN_Buffer_GetPos(mbuf)-startPos);
03708       segments++;
03709     }
03710     GWEN_DB_Group_free(tmpdb);
03711   } /* while */
03712 
03713   /* done */
03714   if (segments) {
03715     DBG_DEBUG(GWEN_LOGDOMAIN, "Parsed %d segments", segments);
03716     return 0;
03717   }
03718   else {
03719     DBG_INFO(GWEN_LOGDOMAIN, "No segments parsed.");
03720     return 1;
03721   }
03722 }
03723 
03724 
03725 
03726 
03727 
03728 
03729 
03730 
03731 GWEN_MSGENGINE_TRUSTEDDATA*
03732 GWEN_MsgEngine_TrustedData_new(const char *data,
03733                                unsigned int size,
03734                                const char *description,
03735                                GWEN_MSGENGINE_TRUSTLEVEL trustLevel){
03736   GWEN_MSGENGINE_TRUSTEDDATA *td;
03737 
03738   assert(data);
03739   assert(size);
03740   GWEN_NEW_OBJECT(GWEN_MSGENGINE_TRUSTEDDATA, td);
03741   td->data=(char*)malloc(size);
03742   assert(td->data);
03743   memmove(td->data, data, size);
03744   if (description)
03745     td->description=strdup(description);
03746   td->trustLevel=trustLevel;
03747   td->size=size;
03748   return td;
03749 }
03750 
03751 
03752 
03753 void GWEN_MsgEngine_TrustedData_free(GWEN_MSGENGINE_TRUSTEDDATA *td){
03754   if (td) {
03755     free(td->data);
03756     free(td->description);
03757     free(td->replacement);
03758     GWEN_FREE_OBJECT(td);
03759   }
03760 }
03761 
03762 
03763 
03764 GWEN_MSGENGINE_TRUSTEDDATA*
03765 GWEN_MsgEngine_TrustedData_GetNext(GWEN_MSGENGINE_TRUSTEDDATA *td){
03766   assert(td);
03767   return td->next;
03768 }
03769 
03770 
03771 
03772 const char*
03773 GWEN_MsgEngine_TrustedData_GetData(GWEN_MSGENGINE_TRUSTEDDATA *td){
03774   assert(td);
03775   return td->data;
03776 }
03777 
03778 
03779 
03780 unsigned int
03781 GWEN_MsgEngine_TrustedData_GetSize(GWEN_MSGENGINE_TRUSTEDDATA *td){
03782   assert(td);
03783   return td->size;
03784 }
03785 
03786 
03787 
03788 const char*
03789 GWEN_MsgEngine_TrustedData_GetDescription(GWEN_MSGENGINE_TRUSTEDDATA *td){
03790   assert(td);
03791   return td->description;
03792 }
03793 
03794 
03795 
03796 GWEN_MSGENGINE_TRUSTLEVEL
03797 GWEN_MsgEngine_TrustedData_GetTrustLevel(GWEN_MSGENGINE_TRUSTEDDATA *td){
03798   assert(td);
03799   return td->trustLevel;
03800 }
03801 
03802 
03803 
03804 const char*
03805 GWEN_MsgEngine_TrustedData_GetReplacement(GWEN_MSGENGINE_TRUSTEDDATA *td){
03806   assert(td);
03807   return td->replacement;
03808 }
03809 
03810 
03811 
03812 int GWEN_MsgEngine_TrustedData_AddPos(GWEN_MSGENGINE_TRUSTEDDATA *td,
03813                                       unsigned int pos){
03814   assert(td);
03815   if (td->posCount>=GWEN_MSGENGINE_TRUSTEDDATA_MAXPOS)
03816     return -1;
03817   td->positions[td->posCount++]=pos;
03818   return 0;
03819 }
03820 
03821 
03822 
03823 int GWEN_MsgEngine_TrustedData_GetFirstPos(GWEN_MSGENGINE_TRUSTEDDATA *td){
03824   assert(td);
03825   td->posPointer=0;
03826   return GWEN_MsgEngine_TrustedData_GetNextPos(td);
03827 }
03828 
03829 
03830 
03831 int GWEN_MsgEngine_TrustedData_GetNextPos(GWEN_MSGENGINE_TRUSTEDDATA *td){
03832   assert(td);
03833   if (td->posPointer>=td->posCount)
03834     return -1;
03835   return td->positions[td->posPointer++];
03836 }
03837 
03838 
03839 
03840 int
03841 GWEN_MsgEngine_TrustedData_CreateReplacements(GWEN_MSGENGINE_TRUSTEDDATA
03842                                               *td){
03843   unsigned int nextNr;
03844   GWEN_MSGENGINE_TRUSTEDDATA *ntd;
03845   unsigned int count;
03846 
03847   assert(td);
03848   count=0;
03849   ntd=td;
03850   while(ntd) {
03851     count++;
03852     ntd=ntd->next;
03853   }
03854 
03855   if (count<0x10)
03856     nextNr=0x01;
03857   else
03858     nextNr=0x11;
03859 
03860   ntd=td;
03861   while(ntd) {
03862     unsigned int i;
03863     char numbuffer[32];
03864     char *rp;
03865     GWEN_MSGENGINE_TRUSTEDDATA *std;
03866     int match;
03867 
03868     /* check whether the same data already exists */
03869     std=td;
03870     match=0;
03871     while(std && std!=ntd) {
03872 
03873       match=1;
03874       if (std->size==ntd->size) {
03875         for (i=0; i<td->size; i++) {
03876           if (std->data[i]!=ntd->data[i]) {
03877             match=0;
03878             break;
03879           }
03880         } /* for */
03881       }
03882       else
03883         match=0;
03884 
03885       if (match)
03886         break;
03887       std=std->next;
03888     } /* while */
03889 
03890     if (match) {
03891       /* copy the found match */
03892       rp=strdup(std->replacement);
03893     }
03894     else {
03895       /* this is a new one */
03896       rp=(char*)malloc(ntd->size+1);
03897       assert(rp);
03898 
03899       if (ntd->size==1) {
03900         if (count>=0x10)
03901           nextNr+=0x10;
03902       }
03903       sprintf(numbuffer, "%02X", nextNr++);
03904       for (i=0; i<ntd->size; i++) {
03905         if (count<0x10)
03906           rp[i]=numbuffer[1];
03907         else
03908           rp[i]=numbuffer[1-(i&1)];
03909       } /* for */
03910       rp[i]=0;
03911     }
03912     /*
03913      DBG_DEBUG(GWEN_LOGDOMAIN, "Replacement: \"%s\" for \"%s\" (%d)", rp,
03914      ntd->description,
03915      ntd->size);
03916      */
03917     free(ntd->replacement);
03918     ntd->replacement=rp;
03919 
03920     ntd=ntd->next;
03921   } /* while */
03922   return 0;
03923 }
03924 
03925 
03926 
03927 GWEN_MSGENGINE_TRUSTEDDATA *GWEN_MsgEngine_TakeTrustInfo(GWEN_MSGENGINE *e){
03928   GWEN_MSGENGINE_TRUSTEDDATA *td;
03929 
03930   assert(e);
03931   td=e->trustInfos;
03932   e->trustInfos=0;
03933   return td;
03934 }
03935 
03936 
03937 
03938 
03939 int GWEN_MsgEngine_AddTrustInfo(GWEN_MSGENGINE *e,
03940                                 const char *data,
03941                                 unsigned int size,
03942                                 const char *description,
03943                                 GWEN_MSGENGINE_TRUSTLEVEL trustLevel,
03944                                 unsigned int pos) {
03945   GWEN_MSGENGINE_TRUSTEDDATA *td;
03946   int match;
03947 
03948   assert(e);
03949   assert(data);
03950   assert(size);
03951 
03952   if (!description)
03953     description="";
03954 
03955   td=e->trustInfos;
03956   while(td) {
03957     unsigned int i;
03958 
03959     /* compare data */
03960     if (td->size==size &&
03961         *description &&
03962         *(td->description) &&
03963         trustLevel==td->trustLevel &&
03964         strcasecmp(description, td->description)==0) {
03965       match=1;
03966       for (i=0; i<td->size; i++) {
03967         if (td->data[i]!=data[i]) {
03968           match=0;
03969           break;
03970         }
03971       } /* for */
03972     }
03973     else
03974       match=0;
03975 
03976     if (match)
03977       break;
03978     td=td->next;
03979   } /* while */
03980 
03981   if (!td) {
03982     DBG_INFO(GWEN_LOGDOMAIN, "Creating new trustInfo for \"%s\" (%d)",
03983              description, size);
03984     td=GWEN_MsgEngine_TrustedData_new(data,
03985                                       size,
03986                                       description,
03987                                       trustLevel);
03988     GWEN_LIST_ADD(GWEN_MSGENGINE_TRUSTEDDATA, td, &(e->trustInfos));
03989   }
03990   else {
03991     DBG_INFO(GWEN_LOGDOMAIN, "Reusing trustInfo for \"%s\" (%d)",
03992              description, size);
03993   }
03994   GWEN_MsgEngine_TrustedData_AddPos(td, pos);
03995   return 0;
03996 }
03997 
03998 
03999