msgengine.c

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

Generated on Fri Apr 11 01:53:47 2008 for gwenhywfar by  doxygen 1.5.5