msgengine.c

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

Generated by  doxygen 1.6.2