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

Generated on Wed Sep 3 15:21:59 2008 for gwenhywfar by  doxygen 1.5.6