gwenhywfar  4.6.0beta
msgengine.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Fri Jul 04 2003
3  copyright : (C) 2003 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 #include <gwenhywfar/gwenhywfarapi.h>
32 #include <msgengine_p.h>
33 #include <gwenhywfar/xml.h>
34 #include <gwenhywfar/text.h>
35 #include <gwenhywfar/misc.h>
36 #include <gwenhywfar/path.h>
37 #include <gwenhywfar/debug.h>
38 #include <gwenhywfar/buffer.h>
39 #include <stdlib.h>
40 #include <assert.h>
41 #include <string.h>
42 #include <ctype.h>
43 
44 
46 
47 
49  GWEN_MSGENGINE *e;
50 
53  e->charsToEscape=strdup(GWEN_MSGENGINE_CHARSTOESCAPE);
54  e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS);
55  e->globalValues=GWEN_DB_Group_new("globalvalues");
56  e->escapeChar='\\';
57 
58  e->usage=1;
59  return e;
60 }
61 
62 
64  if (e) {
65  assert(e->usage);
66  if (--(e->usage)==0) {
68 
69  if (e->inheritorData && e->freeDataPtr)
70  e->freeDataPtr(e);
71  if (e->ownDefs)
72  GWEN_XMLNode_free(e->defs);
73  free(e->charsToEscape);
74  free(e->delimiters);
75  GWEN_DB_Group_free(e->globalValues);
76  if (e->trustInfos) {
77  /* free trustInfos */
79 
80  td=e->trustInfos;
81  while(td) {
82  tdn=td->next;
84  td=tdn;
85  } /* while */
86  }
88  }
89  }
90 }
91 
92 
93 
95  assert(e);
96  e->usage++;
97 }
98 
99 
101  assert(e);
102  e->escapeChar=c;
103 }
104 
105 
106 
108  assert(e);
109  return e->escapeChar;
110 }
111 
112 
113 
115  assert(e);
116  free(e->charsToEscape);
117  e->charsToEscape=strdup(c);
118 }
119 
120 
121 
123  assert(e);
124  return e->charsToEscape;
125 }
126 
127 
128 
130  assert(e);
131  free(e->delimiters);
132  if (s)
133  e->delimiters=strdup(s);
134  else
135  e->delimiters=strdup(GWEN_MSGENGINE_DEFAULT_DELIMITERS);
136 }
137 
138 
139 
141  assert(e);
142  return e->delimiters;
143 }
144 
145 
146 
147 void GWEN_MsgEngine_SetMode(GWEN_MSGENGINE *e, const char *mode){
148  GWEN_DB_NODE *db;
149 
150  assert(e);
152 
153  if (mode)
156  "engine/secmode",
157  mode);
158  else
159  GWEN_DB_DeleteVar(db, "engine/secmode");
160 }
161 
162 
164  GWEN_DB_NODE *db;
165 
166  assert(e);
168  return GWEN_DB_GetCharValue(db, "engine/secmode", 0, 0);
169 }
170 
171 
172 
174  GWEN_DB_NODE *globalValues;
175 
176  assert(e);
177  if (e->getGlobalValuesPtr) {
178  globalValues=e->getGlobalValuesPtr(e);
179  if (!globalValues)
180  globalValues=e->globalValues;
181  }
182  else {
183  globalValues=e->globalValues;
184  }
185  assert(globalValues);
186  return globalValues;
187 }
188 
189 
190 
192  GWEN_DB_NODE *db;
193 
194  assert(e);
196  return GWEN_DB_GetIntValue(db, "engine/pversion", 0, 0);
197 }
198 
199 
200 
202  unsigned int p){
203  GWEN_DB_NODE *db;
204 
205  assert(e);
207 
210  "engine/pversion",
211  p);
212 }
213 
214 
215 
217  assert(e);
218  return e->defs;
219 }
220 
221 
223  GWEN_XMLNODE *n,
224  int take){
225  assert(e);
226  if (e->ownDefs)
227  GWEN_XMLNode_free(e->defs);
228  e->defs=n;
229  e->ownDefs=take;
230 }
231 
232 
233 
234 void
237  assert(e);
238  e->getGlobalValuesPtr=p;
239 }
240 
241 
242 
245  assert(e);
246  return e->getGlobalValuesPtr;
247 }
248 
249 
250 
253  assert(e);
254  e->typeReadPtr=p;
255 }
256 
257 
258 
261  assert(e);
262  return e->typeReadPtr;
263 }
264 
265 
266 
269  assert(e);
270  e->typeWritePtr=p;
271 }
272 
273 
274 
277  assert(e);
278  return e->typeWritePtr;
279 }
280 
281 
282 
285  assert(e);
286  e->typeCheckPtr=p;
287 }
288 
289 
290 
293  assert(e);
294  return e->typeCheckPtr;
295 }
296 
297 
298 
299 
300 
301 
304  assert(e);
305  e->binTypeReadPtr=p;
306 }
307 
308 
309 
312  assert(e);
313  return e->binTypeReadPtr;
314 }
315 
316 
317 
318 void
321  assert(e);
322  e->binTypeWritePtr=p;
323 }
324 
325 
326 
329  assert(e);
330  return e->binTypeWritePtr;
331 }
332 
333 
334 
335 void
338  assert(e);
339  e->getCharValuePtr=p;
340 }
341 
342 
343 
344 void
347  assert(e);
348  e->getIntValuePtr=p;
349 }
350 
351 
352 
353 void
356  assert(e);
357  DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetFreeDataFunction: Deprecated");
358  e->freeDataPtr=p;
359 }
360 
361 
362 
364  assert(e);
365  return e->inheritorData;
366 }
367 
368 
369 
371  assert(e);
372  DBG_WARN(GWEN_LOGDOMAIN, "GWEN_MsgEngine_SetInheritorData: Deprecated");
373  if (e->inheritorData && e->freeDataPtr)
374  e->freeDataPtr(e);
375  e->inheritorData=d;
376 }
377 
378 
379 
381  GWEN_BUFFER *gbuf,
382  GWEN_BUFFER *data,
383  GWEN_XMLNODE *node) {
384  unsigned int minsize;
385  unsigned int maxsize;
386  unsigned int fixSize;
387  unsigned int startPos;
388  int filler;
389  const char *type;
390  const char *name;
391  int rv;
392 
393  /* get some sizes */
394  minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
395  maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
396  fixSize=atoi(GWEN_XMLNode_GetProperty(node, "size","0"));
397  filler=atoi(GWEN_XMLNode_GetProperty(node, "filler","0"));
398  type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
399  name=GWEN_XMLNode_GetProperty(node, "name","<unnamed>");
400  startPos=GWEN_Buffer_GetPos(gbuf);
401 
402  /* check sizes */
403  if (minsize && GWEN_Buffer_GetUsedBytes(data)<minsize) {
404  DBG_ERROR(GWEN_LOGDOMAIN, "Data too short (minsize is %d)", minsize);
405  return -1;
406  }
407  if (maxsize && GWEN_Buffer_GetUsedBytes(data)>maxsize) {
408  DBG_ERROR(GWEN_LOGDOMAIN, "Data too long (maxsize is %d)", maxsize);
409  return -1;
410  }
411 
412  rv=1;
413  if (e->typeWritePtr) {
414  rv=e->typeWritePtr(e,
415  gbuf,
416  data,
417  node);
418  }
419  if (rv==-1) {
420  DBG_INFO(GWEN_LOGDOMAIN, "External type writing failed");
421  return -1;
422  }
423  else if (rv==1) {
424  int i;
425 
426  /* type not handled externally, so handle it myself */
427  if (strcasecmp(type, "bin")==0) {
428  DBG_DEBUG(GWEN_LOGDOMAIN, "Writing binary data (%d bytes added to %d bytes)",
431  if (GWEN_Buffer_AllocRoom(gbuf, 10+GWEN_Buffer_GetUsedBytes(data))) {
432  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
433  return -1;
434  }
435  sprintf(GWEN_Buffer_GetPosPointer(gbuf),
436  "@%d@",
438 
439 
440  i=strlen(GWEN_Buffer_GetPosPointer(gbuf));
441  GWEN_Buffer_IncrementPos(gbuf, i);
443  GWEN_Buffer_AppendBuffer(gbuf, data);
444  } /* if type is "bin" */
445  else if (strcasecmp(type, "num")==0) {
446  int num;
447  unsigned int len;
448  unsigned int lj;
449 
450  num=atoi(GWEN_Buffer_GetPosPointer(data));
451  len=strlen(GWEN_Buffer_GetPosPointer(data));
452 
453  if (atoi(GWEN_XMLNode_GetProperty(node, "leftfill","0"))) {
454  if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
455  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
456  return -1;
457  }
458 
459  /* fill left */
460  for (lj=0; lj<(maxsize-len); lj++)
461  GWEN_Buffer_AppendByte(gbuf, '0');
462 
463  /* write value */
464  for (lj=0; lj<len; lj++)
466  }
467  else if (atoi(GWEN_XMLNode_GetProperty(node, "rightfill","0"))) {
468  if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
469  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
470  return -1;
471  }
472 
473  /* write value */
474  for (lj=0; lj<len; lj++)
476 
477  /* fill right */
478  for (lj=0; lj<(maxsize-len); lj++)
479  GWEN_Buffer_AppendByte(gbuf, '0');
480  }
481  else {
482  if (GWEN_Buffer_AllocRoom(gbuf, maxsize+1)) {
483  DBG_ERROR(GWEN_LOGDOMAIN, "Maxsize in XML file is higher than the buffer size");
484  return -1;
485  }
486  for (lj=0; lj<len; lj++)
488  }
489  } /* if type is num */
490  else {
491  /* TODO: Check for valids */
492  const char *p;
493  int lastWasEscape;
494  unsigned int pcount;
495 
497  pcount=0;
498  lastWasEscape=0;
499  while(*p && pcount<GWEN_Buffer_GetUsedBytes(data)) {
500  int c;
501 
502  c=(unsigned char)*p;
503  if (lastWasEscape) {
504  lastWasEscape=0;
505  switch(c) {
506  case 'r': c='\r'; break;
507  case 'n': c='\n'; break;
508  case 'f': c='\f'; break;
509  case 't': c='\t'; break;
510  default: c=(unsigned char)*p;
511  } /* switch */
512  }
513  else {
514  if (*p=='\\') {
515  lastWasEscape=1;
516  c=-1;
517  }
518  else
519  c=(unsigned char)*p;
520  }
521  if (c!=-1) {
522  int needsEscape;
523 
524  needsEscape=0;
525  if (c==e->escapeChar)
526  needsEscape=1;
527  else {
528  if (e->charsToEscape)
529  if (strchr(e->charsToEscape, c))
530  needsEscape=1;
531  }
532  if (needsEscape) {
533  /* write escape char */
534  if (GWEN_Buffer_AppendByte(gbuf,
535  e->escapeChar)) {
536  return -1;
537  }
538  }
539  if (GWEN_Buffer_AppendByte(gbuf, c)) {
540  return -1;
541  }
542  }
543  p++;
544  pcount++;
545  } /* while */
546  if (pcount<GWEN_Buffer_GetUsedBytes(data)) {
547  DBG_WARN(GWEN_LOGDOMAIN, "Premature end of string (%d<%d)",
548  pcount, GWEN_Buffer_GetUsedBytes(data));
549  }
550  if (*p) {
552  "String for \"%s\" (type %s) is longer than expected "
553  "(no #0 at pos=%d)",
554  name, type,
555  GWEN_Buffer_GetUsedBytes(data)-1);
556  }
557  } /* if type is not BIN */
558  } /* if type not external */
559  else {
560  DBG_INFO(GWEN_LOGDOMAIN, "Type \"%s\" (for %s) is external (write)",
561  type, name);
562 
563  } /* if external type */
564 
565  /* fill data */
566  if (fixSize) {
567  uint32_t bs;
568  unsigned int j;
569 
570  bs=GWEN_Buffer_GetPos(gbuf)-startPos;
571  if (bs>fixSize) {
573  "Data too long (size is %d, fixed size is %d)",
574  bs, fixSize);
575  return -1;
576  }
577 
578  for (j=bs; j<fixSize; j++)
579  GWEN_Buffer_AppendByte(gbuf, (unsigned char)filler);
580  }
581 
582  return 0;
583 }
584 
585 
586 
588  const char *type) {
589  if (e->typeCheckPtr) {
591 
592  vt=e->typeCheckPtr(e, type);
593  if (vt!=GWEN_DB_NodeType_Unknown) {
595  return 1;
596  }
597  }
598  return
599  (strcasecmp(type, "alpha")==0) ||
600  (strcasecmp(type, "ascii")==0) ||
601  (strcasecmp(type, "an")==0) ||
602  (strcasecmp(type, "float")==0);
603 }
604 
605 
606 
608  const char *type) {
609  if (e->typeCheckPtr) {
611 
612  vt=e->typeCheckPtr(e, type);
613  if (vt!=GWEN_DB_NodeType_Unknown) {
615  return 1;
616  }
617  }
618  return
619  (strcasecmp(type, "num")==0);
620 }
621 
622 
623 
625  const char *type) {
626  if (e->typeCheckPtr) {
628 
629  vt=e->typeCheckPtr(e, type);
630  if (vt!=GWEN_DB_NodeType_Unknown) {
632  return 1;
633  }
634  }
635  return
636  (strcasecmp(type, "bin")==0);
637 }
638 
639 
640 
642  GWEN_XMLNODE *node,
643  GWEN_BUFFER *mbuf) {
644  /* get data from within the XML node */
645  GWEN_XMLNODE *n;
646  const char *type;
647 
648 
649  type=GWEN_XMLNode_GetProperty(node, "type", "ascii");
651  "Getting data of type \"%s\" from within XML file", type);
653  if (!n) {
654  DBG_DEBUG(GWEN_LOGDOMAIN, "No child");
655  return 1;
656  }
657 
658  if (GWEN_MsgEngine__IsBinTyp(e, type)) {
659  const char *dp;
660  unsigned int dplen;
661  const char *stype;
662 
663  stype=GWEN_XMLNode_GetProperty(node, "storedAs", type);
664  if (GWEN_MsgEngine__IsBinTyp(e, stype)) {
665  dp=GWEN_XMLNode_GetData(n);
666  dplen=strlen(dp);
667  if (GWEN_Text_FromHexBuffer(dp, mbuf)) {
668  DBG_INFO(GWEN_LOGDOMAIN, "here");
669  return -1;
670  }
671  } /* if stored as bin */
672  else {
673  /* stored as char */
675  }
676  } /* if binType */
677  else {
679  }
680 
681  return 0;
682 }
683 
684 
685 
686 
687 
689  GWEN_BUFFER *gbuf,
690  GWEN_XMLNODE *node,
691  GWEN_XMLNODE *rnode,
692  GWEN_DB_NODE *gr,
693  int loopNr,
694  int isOptional,
695  GWEN_XMLNODE_PATH *nodePath) {
696  const char *name;
697  const char *type;
698  unsigned int minsize;
699  unsigned int maxsize;
700  char numbuffer[256];
701  const char *pdata;
702  unsigned int datasize;
703  GWEN_BUFFER *data;
704  GWEN_BUFFER *tdata;
705  int handled;
706 
707  pdata=0;
708  handled=0;
709  data=0;
710  tdata=0;
711 
712  /* get type */
713  type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
714  DBG_DEBUG(GWEN_LOGDOMAIN, "Type is \"%s\"", type);
715  /* get some sizes */
716  minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
717  maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
718 
719  if (e->binTypeWritePtr &&
720  GWEN_MsgEngine__IsBinTyp(e, type) &&
721  atoi(GWEN_XMLNode_GetProperty(node, "writebin", "1"))) {
722  int rv;
723 
724  data=GWEN_Buffer_new(0,
725  64,
726  0,
727  1);
728 
729  rv=e->binTypeWritePtr(e, node, gr, data);
730  if (rv==-1) {
731  /* error */
732  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
733  return -1;
734  }
735  else if (rv==0) {
736  handled=1;
737  }
738  else if (rv==1) {
739  GWEN_Buffer_free(data);
740  data=0;
741  }
742  }
743 
744  if (!handled) {
745  /* get name */
746  name=GWEN_XMLNode_GetProperty(node, "name", 0);
747  if (!name) {
748  int rv;
749 
750  /* get data from within the XML node */
751  tdata=GWEN_Buffer_new(0, 32, 0, 1);
752  GWEN_Buffer_SetStep(tdata, 256);
753  rv=GWEN_MsgEngine__GetInline(e, node, tdata);
754  if (rv==0) {
755  pdata=GWEN_Buffer_GetStart(tdata);
756  datasize=GWEN_Buffer_GetUsedBytes(tdata);
757  }
758  else {
759  GWEN_Buffer_free(tdata);
760  tdata=0;
761  pdata="";
762  datasize=0;
763  }
764  } /* if (!name) */
765  else {
766  const char *nptr;
767 
768  DBG_DEBUG(GWEN_LOGDOMAIN, "Name provided (%s), loop is %d", name, loopNr);
769  nptr=name;
770 
771  if (gr) {
773  int idata;
774 
775  /* Variable type of DB takes precedence
776  */
777  vt=GWEN_DB_GetValueTypeByPath(gr, nptr, loopNr);
778  if (vt==GWEN_DB_NodeType_Unknown) {
779  if (GWEN_MsgEngine__IsCharTyp(e, type))
781  else if (GWEN_MsgEngine__IsIntTyp(e, type))
783  else if (GWEN_MsgEngine__IsBinTyp(e, type))
785  else {
787  "Unable to determine parameter "
788  "type (%s), assuming \"char\" for this matter", type);
790  }
791  }
792 
793  /* get the value of the given var from the db */
794  switch(vt) {
796  DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is char", name);
797  pdata=GWEN_DB_GetCharValue(gr, nptr, loopNr, 0);
798  if (pdata) {
799  DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %s", nptr, pdata);
800  datasize=strlen(pdata);
801  }
802  else
803  datasize=0;
804  break;
805 
807  DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is int", name);
808  if (GWEN_DB_ValueExists(gr, nptr, loopNr)) {
809  idata=GWEN_DB_GetIntValue(gr, nptr, loopNr, 0);
810  if (-1==GWEN_Text_NumToString(idata, numbuffer,
811  sizeof(numbuffer),0)) {
812  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
813  GWEN_Buffer_free(data);
814  return -1;
815  }
816  DBG_DEBUG(GWEN_LOGDOMAIN, "Value of \"%s\" is %d", nptr, idata);
817  pdata=numbuffer;
818  datasize=strlen(numbuffer);
819  }
820  break;
821 
823  DBG_DEBUG(GWEN_LOGDOMAIN, "Type of \"%s\" is bin", name);
824  pdata=GWEN_DB_GetBinValue(gr, nptr, loopNr, 0, 0, &datasize);
825  break;
826 
827  default:
828  DBG_WARN(GWEN_LOGDOMAIN, "Unsupported parameter type (%d)", vt);
829  break;
830  } /* switch vt */
831  } /* if gr */
832 
833  if (!pdata) {
834  GWEN_XMLNODE_PATH *copyOfNodePath;
835 
836  copyOfNodePath=GWEN_XMLNode_Path_dup(nodePath);
837 
838  /* still no data, try to get it from the XML file */
839  DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\"", name);
841  node, copyOfNodePath, nptr,
842  &datasize);
843  GWEN_XMLNode_Path_free(copyOfNodePath);
844  if (pdata) {
845  DBG_DEBUG(GWEN_LOGDOMAIN, "Found value of \"%s\"", name);
846  }
847  }
848 
849  if (!pdata) {
850  int rv;
851 
852  /* get data from within the XML node */
853  tdata=GWEN_Buffer_new(0, 32, 0, 1);
854  GWEN_Buffer_SetStep(tdata, 256);
855  rv=GWEN_MsgEngine__GetInline(e, node, tdata);
856  if (rv==0) {
857  pdata=GWEN_Buffer_GetStart(tdata);
858  datasize=GWEN_Buffer_GetUsedBytes(tdata);
859  }
860  else {
861  GWEN_Buffer_free(tdata);
862  tdata=0;
863  }
864  }
865 
866  if (pdata==0) {
867  if (isOptional) {
868  DBG_INFO(GWEN_LOGDOMAIN, "Value not found, omitting element \"%s[%d]\"",
869  name, loopNr);
870  GWEN_Buffer_free(data);
871  return 1;
872  }
873  else {
875  "Value for element \"%s[%d]\" (mode \"%s\") not found",
876  name, loopNr,
878  GWEN_DB_Dump(gr, 4);
879  GWEN_Buffer_free(data);
880  return -1;
881  }
882  }
883  }
884 
885  if (!data)
886  data=GWEN_Buffer_new((char*)pdata,
887  datasize,
888  datasize,
889  0 /* dont take ownership*/ );
890  }
891 
892  /* write value */
894  gbuf,
895  data,
896  node)!=0) {
897  DBG_INFO(GWEN_LOGDOMAIN, "Could not write value");
898  GWEN_Buffer_free(data);
899  GWEN_Buffer_free(tdata);
900  return -1;
901  }
902  GWEN_Buffer_free(data);
903  GWEN_Buffer_free(tdata);
904 
905  return 0;
906 }
907 
908 
909 
911  const char *pname,
912  int version,
913  const char *pvalue) {
914  return GWEN_MsgEngine_FindNodeByProperty(e, "GROUP", pname, version, pvalue);
915 }
916 
917 
918 
920  const char *t,
921  const char *pname,
922  int version,
923  const char *pvalue) {
924  GWEN_XMLNODE *n;
925  const char *p;
926  int i;
927  const char *mode;
928  unsigned int proto;
929  char buffer[256];
930 
931  if ((strlen(t)+4)>sizeof(buffer)) {
932  DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
933  return 0;
934  }
935 
936  mode=GWEN_MsgEngine_GetMode(e);
938  if (!e->defs) {
939  DBG_INFO(GWEN_LOGDOMAIN, "No definitions available");
940  return 0;
941  }
942  n=e->defs;
944 
945  /* find type+"S" */
946  strcpy(buffer, t);
947  strcat(buffer,"S");
948  while(n) {
951  assert(p);
952  if (strcasecmp(p, buffer)==0)
953  break;
954  }
955  n=GWEN_XMLNode_Next(n);
956  } /* while */
957 
958  if (!n) {
959  DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t);
960  return 0;
961  }
962 
963  /* find approppriate group definition */
964  if (!mode)
965  mode="";
967  if (!n) {
968  DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
969  return 0;
970  }
971 
972  /* find type+"def" */
973  strcpy(buffer, t);
974  strcat(buffer,"def");
975  while(n) {
978  assert(p);
979  if (strcasecmp(p, buffer)==0) {
980  p=GWEN_XMLNode_GetProperty(n, pname,"");
981  if (strcasecmp(p, pvalue)==0) {
982  i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
983  if (proto==0 || (int)proto==i || i==0) {
984  i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
985  if (version==0 || version==i) {
986  p=GWEN_XMLNode_GetProperty(n, "mode","");
987  if (strcasecmp(p, mode)==0 || !*p) {
988  DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found",
989  pname, pvalue);
990  return n;
991  }
992  }
993  }
994  }
995  }
996  }
997  n=GWEN_XMLNode_Next(n);
998  } /* while */
999 
1000  DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found",
1001  pname,
1002  pvalue,
1003  version);
1004  return 0;
1005 }
1006 
1007 
1008 
1010  const char *t,
1011  const char *pname,
1012  int version,
1013  const char *pvalue) {
1014  GWEN_XMLNODE *n;
1015  const char *p;
1016  int i;
1017  const char *mode;
1018  unsigned int proto;
1019  char buffer[256];
1020 
1021  if ((strlen(t)+4)>sizeof(buffer)) {
1022  DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
1023  return 0;
1024  }
1025 
1026  mode=GWEN_MsgEngine_GetMode(e);
1028  if (!e->defs) {
1029  DBG_INFO(GWEN_LOGDOMAIN, "No definitions available");
1030  return 0;
1031  }
1032  n=e->defs;
1033  n=GWEN_XMLNode_GetChild(n);
1034 
1035  /* find type+"S" */
1036  strcpy(buffer, t);
1037  strcat(buffer,"S");
1038  while(n) {
1040  p=GWEN_XMLNode_GetData(n);
1041  assert(p);
1042  if (strcasecmp(p, buffer)==0)
1043  break;
1044  }
1045  n=GWEN_XMLNode_Next(n);
1046  } /* while */
1047 
1048  if (!n) {
1049  DBG_INFO(GWEN_LOGDOMAIN, "No definitions available for type \"%s\"", t);
1050  return 0;
1051  }
1052 
1053  /* find approppriate group definition */
1054  if (!mode)
1055  mode="";
1056  n=GWEN_XMLNode_GetChild(n);
1057  if (!n) {
1058  DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
1059  return 0;
1060  }
1061 
1062  /* find type+"def" */
1063  strcpy(buffer, t);
1064  strcat(buffer,"def");
1065  while(n) {
1067  p=GWEN_XMLNode_GetData(n);
1068  assert(p);
1069  if (strcasecmp(p, buffer)==0) {
1070  p=GWEN_XMLNode_GetProperty(n, pname,"");
1071  if (strcasecmp(p, pvalue)==0) {
1072  i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
1073  if (proto==0 || (int)proto==i) {
1074  i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
1075  if (version==0 || version==i) {
1076  p=GWEN_XMLNode_GetProperty(n, "mode","");
1077  if (strcasecmp(p, mode)==0 || !*p) {
1078  DBG_DEBUG(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\" found",
1079  pname, pvalue);
1080  return n;
1081  }
1082  }
1083  }
1084  }
1085  }
1086  }
1087  n=GWEN_XMLNode_Next(n);
1088  } /* while */
1089 
1090  DBG_INFO(GWEN_LOGDOMAIN, "Group definition for \"%s=%s\"(%d) not found",
1091  pname,
1092  pvalue,
1093  version);
1094  return 0;
1095 }
1096 
1097 
1098 
1100  const char *pvalue,
1101  GWEN_XMLNODE *node,
1102  GWEN_XMLNODE *dnode,
1103  unsigned int *datasize) {
1104  const char *p;
1105  static char pbuffer[256];
1106  GWEN_DB_NODE *globalValues;
1107 
1108  globalValues=GWEN_MsgEngine__GetGlobalValues(e);
1109  assert(globalValues);
1110 
1111  if (pvalue) {
1112  DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming value \"%s\"", pvalue);
1113  /* check whether the value is a property */
1114  p=pvalue;
1115  while (*p && isspace((int)*p))
1116  p++;
1117  if (*p=='$' || *p=='+') {
1118  /* global property */
1119  int incr;
1120 
1121  incr=(*p=='+');
1122  p++;
1123 
1124  DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p);
1125  if (incr) {
1126  int z;
1127 
1128  z=GWEN_DB_GetIntValue(globalValues, p, 0, 0);
1129  DBG_DEBUG(GWEN_LOGDOMAIN, "Incrementing global property \"%s\" (%d)",
1130  p, z);
1131  if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
1132  DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
1133  return 0;
1134  }
1135 
1136  z++;
1137  DBG_DEBUG(GWEN_LOGDOMAIN, "Setting global property \"%s\"=%d", p, z);
1138  GWEN_DB_SetIntValue(globalValues,
1141  p, z);
1142  pvalue=pbuffer;
1143  *datasize=strlen(pvalue);
1144  }
1145  else {
1146  int z;
1147  GWEN_DB_NODE_TYPE vt;
1148  const char *type = "should_be_known";
1149  /* default value; otherwise the compiler issues a warning */
1150 
1151  DBG_DEBUG(GWEN_LOGDOMAIN, "Getting global property \"%s\"", p);
1152  vt=GWEN_DB_GetVariableType(globalValues, p);
1153  if (vt==GWEN_DB_NodeType_Unknown) {
1154  if (!GWEN_DB_VariableExists(globalValues, p)) {
1155  DBG_ERROR(GWEN_LOGDOMAIN, "Unable to determine type of \"%s\"", p);
1156  return 0;
1157  }
1158  type=GWEN_XMLNode_GetProperty(dnode, "type", "ascii");
1159  if (GWEN_MsgEngine__IsCharTyp(e, type))
1161  else if (GWEN_MsgEngine__IsIntTyp(e, type))
1163  else if (GWEN_MsgEngine__IsBinTyp(e, type))
1165  else {
1167  "Unable to determine type of \"%s\" (xml)", p);
1168  return 0;
1169  }
1170  }
1171 
1172  switch(vt) {
1174  pvalue=GWEN_DB_GetCharValue(globalValues, p, 0, "");
1175  *datasize=strlen(pvalue);
1176  break;
1177 
1179  z=GWEN_DB_GetIntValue(globalValues, p, 0, 0);
1180  if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
1181  DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
1182  return 0;
1183  }
1184  pvalue=pbuffer;
1185  *datasize=strlen(pvalue);
1186  break;
1187 
1189  pvalue=GWEN_DB_GetBinValue(globalValues, p, 0,
1190  0,0,
1191  datasize);
1192  break;
1193 
1194  default:
1195  DBG_ERROR(GWEN_LOGDOMAIN,"Unknown type %s", type);
1196  return 0;
1197  } /* switch */
1198  }
1199  DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed");
1200  }
1201  else if (*p=='%') {
1202  /* local property */
1203  p++;
1204 
1205  DBG_DEBUG(GWEN_LOGDOMAIN, "Getting property \"%s\"", p);
1206  pvalue=GWEN_XMLNode_GetProperty(node, p, 0);
1207  if (pvalue) {
1208  *datasize=strlen(pvalue);
1209  DBG_DEBUG(GWEN_LOGDOMAIN, "Transformed value \"%s\"", pvalue);
1210  }
1211  else
1212  *datasize=0;
1213  }
1214  else if (*p=='?') {
1215  GWEN_DB_NODE_TYPE vt;
1216  int z;
1217  const char *dtype;
1218 
1219  /* get type */
1220  dtype=GWEN_XMLNode_GetProperty(dnode, "type","ASCII");
1221 
1222  /* program variable accessable via callback */
1223  p++;
1224  DBG_DEBUG(GWEN_LOGDOMAIN, "Getting program variable \"%s\"", p);
1225 
1226  pvalue=0;
1227  if (GWEN_MsgEngine__IsCharTyp(e, dtype))
1229  else if (GWEN_MsgEngine__IsIntTyp(e, dtype))
1231  else {
1233  }
1234 
1235  switch(vt) {
1237  if (e->getCharValuePtr) {
1238  pvalue=e->getCharValuePtr(e, p, 0);
1239  if (pvalue)
1240  *datasize=strlen(pvalue);
1241  }
1242  break;
1243 
1245  if (e->getIntValuePtr) {
1246  z=e->getIntValuePtr(e, p, 0);
1247  if (GWEN_Text_NumToString(z, pbuffer, sizeof(pbuffer),0)<1) {
1248  DBG_ERROR(GWEN_LOGDOMAIN, "Error converting num to string");
1249  return 0;
1250  }
1251  pvalue=pbuffer;
1252  *datasize=strlen(pvalue);
1253  }
1254  else {
1255  DBG_NOTICE(GWEN_LOGDOMAIN, "Callback for getIntValue not set");
1256  }
1257  break;
1258 
1259  default:
1260  DBG_ERROR(GWEN_LOGDOMAIN,"Unhandled type %s", dtype);
1261  return 0;
1262  } /* switch */
1263 
1264  DBG_DEBUG(GWEN_LOGDOMAIN, "Value transformed");
1265  }
1266  else {
1267  *datasize=strlen(pvalue);
1268  }
1269  }
1270  return pvalue;
1271 }
1272 
1273 
1274 
1276  GWEN_XMLNODE *refnode,
1277  const char *name,
1278  int topDown) {
1279  const char *pvalue;
1280  GWEN_XMLNODE *pn;
1281  const char *lastValue;
1282 
1283  DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in properties", name);
1284  lastValue=0;
1285 
1286  pvalue=GWEN_XMLNode_GetProperty(node, name,0);
1287  if (pvalue) {
1288  if (!topDown)
1289  return pvalue;
1290  DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue);
1291  lastValue=pvalue;
1292  }
1293 
1294  pn=refnode;
1295  while(pn) {
1296  pvalue=GWEN_XMLNode_GetProperty(pn, name,0);
1297  if (pvalue) {
1298  if (!topDown)
1299  return pvalue;
1300  DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value (%s), but will look further", pvalue);
1301  lastValue=pvalue;
1302  }
1303  pn=GWEN_XMLNode_GetParent(pn);
1304  } /* while */
1305  return lastValue;
1306 }
1307 
1308 
1309 
1311  GWEN_XMLNODE *refnode) {
1312  int value;
1313  GWEN_XMLNODE *pn;
1314  int highestTrust;
1315 
1316  highestTrust=0;
1317 
1318  value=atoi(GWEN_XMLNode_GetProperty(node, "trustlevel","0"));
1319  if (value>highestTrust)
1320  highestTrust=value;
1321 
1322  pn=node;
1323  while(pn) {
1324  value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0"));
1325  if (value>highestTrust)
1326  highestTrust=value;
1327  pn=GWEN_XMLNode_GetParent(pn);
1328  } /* while */
1329 
1330  pn=refnode;
1331  while(pn) {
1332  value=atoi(GWEN_XMLNode_GetProperty(pn, "trustlevel","0"));
1333  if (value>highestTrust)
1334  highestTrust=value;
1335  pn=GWEN_XMLNode_GetParent(pn);
1336  } /* while */
1337  return highestTrust;
1338 }
1339 
1340 
1341 
1343  GWEN_XMLNODE *node,
1344  GWEN_XMLNODE_PATH *nodePath,
1345  const char *name,
1346  unsigned int *datasize) {
1347  const char *pvalue;
1348  GWEN_XMLNODE *pn;
1349  char *bufferPtr;
1350  int topDown;
1351  const char *lastValue;
1352  unsigned int lastDataSize;
1353  unsigned int ldatasize;
1354 
1355  DBG_DEBUG(GWEN_LOGDOMAIN, "Searching for value of \"%s\" in <VALUES>",
1356  name);
1357  if (!node) {
1358  DBG_WARN(GWEN_LOGDOMAIN, "No node !");
1359  }
1360  topDown=atoi(GWEN_XMLNode_GetProperty(node, "topdown", "0"));
1361  lastValue=0;
1362  lastDataSize=0;
1363 
1364  bufferPtr=0;
1365 
1366  /*pn=GWEN_XMLNode_GetParent(node);*/
1367  pn=GWEN_XMLNode_Path_Surface(nodePath);
1368  while(pn) {
1369  const char *ppath;
1370  /*
1371  if (GWEN_XMLNode_GetType(pn)==GWEN_XMLNodeTypeTag) {
1372  DBG_NOTICE(GWEN_LOGDOMAIN, "Checking node \"%s\"",
1373  GWEN_XMLNode_GetData(pn));
1374  }*/
1375  pvalue=GWEN_MsgEngine__findInValues(e, pn, node, name, &ldatasize);
1376  if (pvalue) {
1377  if (!topDown) {
1378  free(bufferPtr);
1379  *datasize=ldatasize;
1380  return pvalue;
1381  }
1382  DBG_DEBUG(GWEN_LOGDOMAIN, "Found a value, but will look further");
1383  lastValue=pvalue;
1384  lastDataSize=ldatasize;
1385  }
1386 
1387  ppath=GWEN_XMLNode_GetProperty(pn, "name", "");
1388 
1389  if (*ppath) {
1390  int i;
1391  char *tmpptr;
1392 
1393  if (bufferPtr) {
1394  i=strlen(bufferPtr)+strlen(ppath)+2;
1395  tmpptr=(char*)malloc(i);
1396  assert(tmpptr);
1397  sprintf(tmpptr, "%s/%s", ppath, bufferPtr);
1398  free(bufferPtr);
1399  bufferPtr=tmpptr;
1400  }
1401  else {
1402  i=strlen(ppath)+strlen(name)+2;
1403  tmpptr=(char*)malloc(i);
1404  assert(tmpptr);
1405  sprintf(tmpptr, "%s/%s", ppath, name);
1406  bufferPtr=tmpptr;
1407  }
1408  name=bufferPtr;
1409  }
1410  pn=GWEN_XMLNode_Path_Surface(nodePath);
1411  } /* while */
1412 
1413  free(bufferPtr);
1414  if (!lastValue)
1415  *datasize=0;
1416  else
1417  *datasize=lastDataSize;
1418  return lastValue;
1419 }
1420 
1421 
1422 
1424  GWEN_XMLNODE *node,
1425  GWEN_XMLNODE *dnode,
1426  const char *name,
1427  unsigned int *datasize) {
1428  GWEN_XMLNODE *pn;
1429 
1430  DBG_VERBOUS(GWEN_LOGDOMAIN, "Looking for value of \"%s\" in <VALUES>", name);
1431  pn=GWEN_XMLNode_GetChild(node);
1432 
1433  while(pn) {
1435  GWEN_XMLNODE *n;
1436  const char *p;
1437 
1438  p=GWEN_XMLNode_GetData(pn);
1439  assert(p);
1440  DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s", p);
1441  if (strcasecmp(p, "VALUES")==0) {
1442  DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found");
1443  /* <preset> found, check all values */
1444  n=GWEN_XMLNode_GetChild(pn);
1445  while(n) {
1447  p=GWEN_XMLNode_GetData(n);
1448  assert(p);
1449  if (strcasecmp(p, "VALUE")==0) {
1450  const char *pname;
1451  const char *pvalue;
1452 
1453  pname=GWEN_XMLNode_GetProperty(n, "path", 0);
1454  if (pname) {
1455  DBG_DEBUG(GWEN_LOGDOMAIN, "Comparing against \"%s\"", pname);
1456  if (strcasecmp(name, pname)==0) {
1457  GWEN_XMLNODE *dn;
1458 
1459  dn=GWEN_XMLNode_GetChild(n);
1460  while (dn) {
1462  pvalue=GWEN_XMLNode_GetData(dn);
1463  if (pvalue) {
1464  DBG_DEBUG(GWEN_LOGDOMAIN, "Transforming \"%s\"", pvalue);
1466  pvalue,
1467  node,
1468  dnode,
1469  datasize);
1470  }
1471  if (pvalue)
1472  return pvalue;
1473  }
1474  dn=GWEN_XMLNode_Next(dn);
1475  } /* while dn */
1476  } /* if path matches name */
1477  } /* if path given */
1478  } /* if VALUE tag */
1479  } /* if TAG */
1480  n=GWEN_XMLNode_Next(n);
1481  } /* while */
1482  break; /* REMOVE this to check multiple groups */
1483  } /* if <preset> found */
1484  } /* if tag */
1485  pn=GWEN_XMLNode_Next(pn);
1486  } /* while node */
1487 
1488  DBG_DEBUG(GWEN_LOGDOMAIN, "No value found for \"%s\" in <VALUES>", name);
1489  return 0;
1490 }
1491 
1492 
1493 
1495  GWEN_XMLNODE *node,
1496  const char *t,
1497  int version,
1498  const char *pvalue) {
1499  GWEN_XMLNODE *n;
1500  const char *p;
1501  int i;
1502  const char *mode;
1503  unsigned int proto;
1504  char buffer[256];
1505 
1506  if ((strlen(t)+4)>sizeof(buffer)) {
1507  DBG_ERROR(GWEN_LOGDOMAIN, "Type name too long.");
1508  return 0;
1509  }
1510 
1511  mode=GWEN_MsgEngine_GetMode(e);
1513 
1514  /* find type+"S" */
1515  strcpy(buffer, t);
1516  strcat(buffer,"S");
1517  n=GWEN_XMLNode_FindFirstTag(node, buffer, 0, 0);
1518  if (!n) {
1520  "No definitions here for type \"%s\"", t);
1521  return 0;
1522  }
1523 
1524  /* find approppriate group definition */
1525  if (!mode)
1526  mode="";
1528  if (!n) {
1529  DBG_INFO(GWEN_LOGDOMAIN, "No definitions inside \"%s\"", buffer);
1530  return 0;
1531  }
1532 
1533  /* find type+"def" */
1534  strcpy(buffer, t);
1535  strcat(buffer, "def");
1536  while(n) {
1537  p=GWEN_XMLNode_GetData(n);
1538  assert(p);
1539  if (strcasecmp(p, buffer)==0 ||
1540  strcasecmp(p, t)==0) {
1541  p=GWEN_XMLNode_GetProperty(n, "id", "");
1542  if (strcasecmp(p, pvalue)!=0)
1543  p=GWEN_XMLNode_GetProperty(n, "name", "");
1544  if (strcasecmp(p, pvalue)==0) {
1545  i=atoi(GWEN_XMLNode_GetProperty(n, "pversion" ,"0"));
1546  if (proto==0 || (int)proto==i || i==0) {
1547  i=atoi(GWEN_XMLNode_GetProperty(n, "version" ,"0"));
1548  if (version==0 || version==i) {
1549  p=GWEN_XMLNode_GetProperty(n, "mode","");
1550  if (strcasecmp(p, mode)==0 || !*p) {
1552  "Group definition for \"%s=%s\" found",
1553  t, pvalue);
1554  return n;
1555  }
1556  }
1557  }
1558  }
1559  }
1561  } /* while */
1562 
1564  "Group definition for \"%s=%s\"(%d) not found here",
1565  t,
1566  pvalue,
1567  version);
1568  return 0;
1569 }
1570 
1571 
1572 
1574  GWEN_XMLNODE *node,
1575  const GWEN_XMLNODE_PATH *nodePath,
1576  const char *t,
1577  int version,
1578  const char *pvalue) {
1579  GWEN_XMLNODE *n;
1580  GWEN_XMLNODE *nLast = 0;
1581  GWEN_XMLNODE *nRes = 0;
1582  GWEN_XMLNODE_PATH *pathCopy;
1583 
1584  assert(node);
1585  assert(nodePath);
1586  assert(t);
1587  assert(pvalue);
1588 
1589  pathCopy=GWEN_XMLNode_Path_dup(nodePath);
1590  n=GWEN_XMLNode_Path_Surface(pathCopy);
1591  /* first try all nodes along the path */
1592  while(n) {
1593  nLast=n;
1594  nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue);
1595  if (nRes)
1596  break;
1597  n=GWEN_XMLNode_Path_Surface(pathCopy);
1598  }
1599  GWEN_XMLNode_Path_free(pathCopy);
1600  if (nRes) {
1601  /* already found */
1602  if (nRes==node) {
1603  DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected.");
1604  return 0;
1605  }
1606  return nRes;
1607  }
1608 
1609  if (nLast)
1610  n=nLast;
1611  else
1612  n=node;
1613 
1614  if (n) {
1616  while(n) {
1617  nRes=GWEN_MsgEngine__GetGroup(e, n, t, version, pvalue);
1618  if (nRes)
1619  break;
1621  }
1622  }
1623 
1624  /* try root as a last resort */
1625  if (!nRes && e->defs)
1626  nRes=GWEN_MsgEngine__GetGroup(e, e->defs, t, version, pvalue);
1627 
1628  if (!nRes) {
1630  "Group definition for \"%s=%s\"(%d) not found",
1631  t,
1632  pvalue,
1633  version);
1634  return 0;
1635  }
1636  if (nRes==node) {
1637  DBG_ERROR(GWEN_LOGDOMAIN, "Loop detected.");
1638  return 0;
1639  }
1640  return nRes;
1641 }
1642 
1643 
1644 
1646  GWEN_BUFFER *gbuf,
1647  GWEN_XMLNODE *node,
1648  GWEN_XMLNODE *rnode,
1649  GWEN_DB_NODE *gr,
1650  int groupIsOptional,
1651  GWEN_XMLNODE_PATH *nodePath) {
1652  GWEN_XMLNODE *n;
1653  const char *p;
1654  char delimiter;
1655  char terminator;
1656  int isFirstElement;
1657  int omittedElements;
1658  int hasEntries;
1659 
1660 
1661  /* get some settings */
1662  if (rnode) {
1663  /* get delimiter */
1664  p=GWEN_XMLNode_GetProperty(rnode,
1665  "delimiter",
1667  "delimiter",
1668  ""));
1669  delimiter=*p;
1670 
1671  /* get terminating char, if any */
1672  p=GWEN_XMLNode_GetProperty(rnode,
1673  "terminator",
1675  "terminator",
1676  ""));
1677  terminator=*p;
1678  }
1679  else {
1680  /* get delimiter */
1681  p=GWEN_XMLNode_GetProperty(node,
1682  "delimiter",
1683  "");
1684  delimiter=*p;
1685 
1686  /* get terminating char, if any */
1687  p=GWEN_XMLNode_GetProperty(node, "terminator","");
1688  terminator=*p;
1689  }
1690 
1691  /* handle all child entries */
1692  n=GWEN_XMLNode_GetChild(node);
1693  isFirstElement=1;
1694  omittedElements=0;
1695  hasEntries=0;
1696  if (!n) {
1697  DBG_INFO(GWEN_LOGDOMAIN, "No subnodes !");
1698  }
1699  while(n) {
1700  int t;
1701  unsigned int minnum;
1702  unsigned int maxnum;
1703  int gversion;
1704  const char *addEmptyMode;
1705  unsigned int loopNr;
1706 
1707  minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
1708  maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
1709  gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
1710  addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one");
1711 
1712  DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements);
1713  t=GWEN_XMLNode_GetType(n);
1714  if (t==GWEN_XMLNodeTypeTag) {
1715  const char *typ;
1716 
1717  typ=GWEN_XMLNode_GetData(n);
1718  if (typ==0) {
1719  DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
1720  return -1;
1721  }
1722  if (strcasecmp(typ, "ELEM")==0) {
1723  /* element tag found */
1724  int j;
1725  int rv;
1726 
1727  DBG_VERBOUS(GWEN_LOGDOMAIN, "Found an element");
1728  /* write element as often as needed */
1729  for (loopNr=0; loopNr<maxnum; loopNr++) {
1730  unsigned int posBeforeElement;
1731 
1732  posBeforeElement=GWEN_Buffer_GetPos(gbuf);
1733 
1734  /* write delimiter, if needed */
1735  if (delimiter) {
1736  DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters",
1737  omittedElements);
1738  for (j=0; j<omittedElements; j++) {
1739  if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
1740  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
1741  return -1;
1742  }
1743  }
1744  if (!isFirstElement)
1745  if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
1746  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
1747  return -1;
1748  }
1749  }
1750 
1752  gbuf,
1753  n,
1754  rnode,
1755  gr,
1756  loopNr,
1757  loopNr>=minnum ||
1758  (groupIsOptional && !hasEntries),
1759  nodePath);
1760  if (rv==-1) {
1761  DBG_INFO(GWEN_LOGDOMAIN, "Error writing element");
1762  DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
1763  GWEN_XMLNode_Dump(n, 1);
1764  if (gr) {
1765  DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
1766  GWEN_DB_Dump(gr, 1);
1767  }
1768  return -1;
1769  }
1770  else if (rv==0) {
1771  isFirstElement=0;
1772  omittedElements=0;
1773  hasEntries=1;
1774  DBG_DEBUG(GWEN_LOGDOMAIN, "Element written");
1775  }
1776  else {
1777  /* element is optional, not found */
1778  /* restore position */
1779  GWEN_Buffer_SetPos(gbuf, posBeforeElement);
1780  GWEN_Buffer_Crop(gbuf, 0, posBeforeElement);
1781 
1782  if (strcasecmp(addEmptyMode, "max")==0) {
1783  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty");
1784  omittedElements+=(maxnum-loopNr);
1785  }
1786  else if (strcasecmp(addEmptyMode, "min")==0) {
1787  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty");
1788  if (loopNr<minnum)
1789  omittedElements+=(minnum-loopNr);
1790  }
1791  else if (strcasecmp(addEmptyMode, "one")==0) {
1792  if (loopNr==0)
1793  omittedElements++;
1794  }
1795  else if (strcasecmp(addEmptyMode, "none")==0) {
1796  }
1797  else {
1798  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
1799  addEmptyMode);
1800  return -1;
1801  }
1802  break;
1803  }
1804  } /* for */
1805  }
1806  else if (strcasecmp(typ, "VALUES")==0) {
1807  }
1808  else if (strcasecmp(typ, "DESCR")==0) {
1809  }
1810  else {
1811  /* group tag found */
1812  GWEN_XMLNODE *gn;
1813  GWEN_DB_NODE *gcfg;
1814  const char *gname;
1815  const char *gtype;
1816  unsigned int posBeforeGroup;
1817 
1818  DBG_VERBOUS(GWEN_LOGDOMAIN, "Found a group");
1819 
1820  gcfg=0;
1821  gtype=GWEN_XMLNode_GetProperty(n, "type",0);
1822  if (!gtype) {
1823  /* no "type" property, so use this group directly */
1824  DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
1825  gtype="";
1826  gn=n;
1827  }
1828  else {
1829  DBG_VERBOUS(GWEN_LOGDOMAIN, "<%s> tag is of type \"%s\"", typ, gtype);
1830  gn=GWEN_MsgEngine_GetGroup(e, n, nodePath, typ,
1831  gversion, gtype);
1832  if (!gn) {
1833  DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
1834  return -1;
1835  }
1836  }
1837 
1838  gname=NULL;
1839  gcfg=NULL;
1840  if (gr) {
1841  gname=GWEN_XMLNode_GetProperty(n, "name",0);
1842  if (gname) {
1843  DBG_VERBOUS(GWEN_LOGDOMAIN, "Group \"%s\" using special data", gname);
1844  gcfg=GWEN_DB_FindFirstGroup(gr, gname);
1845  }
1846  else {
1847  DBG_DEBUG(GWEN_LOGDOMAIN, "Unnamed group, using basic data");
1848  /* TODO: check for maxnum==1, since only then the following line makes sense */
1849  gcfg=gr;
1850  }
1851  }
1852 
1853  /* write group as often as needed */
1854  for (loopNr=0; loopNr<maxnum; loopNr++) {
1855  int rv;
1856  int groupIsEmpty;
1857 
1858  groupIsEmpty=0;
1859  posBeforeGroup=GWEN_Buffer_GetPos(gbuf);
1860 
1861  /* write delimiter, if needed */
1862  if (delimiter) {
1863  int j;
1864 
1865  DBG_VERBOUS(GWEN_LOGDOMAIN, "Appending %d delimiters",
1866  omittedElements);
1867  for (j=0; j<omittedElements; j++) {
1868  if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
1869  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
1870  return -1;
1871  }
1872  }
1873  if (!isFirstElement)
1874  if (GWEN_Buffer_AppendByte(gbuf, delimiter)) {
1875  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
1876  return -1;
1877  }
1878  }
1879 
1880  /* find next matching group */
1881  if (gcfg==0) {
1882  DBG_DEBUG(GWEN_LOGDOMAIN, "No group found");
1883  if (loopNr>=minnum)
1884  groupIsEmpty=1;
1885  }
1886 
1887  if (groupIsEmpty) {
1888  /* empty group, flag as such */
1889  rv=1;
1890  }
1891  else {
1892  int dive;
1893 
1894  /* write group */
1895  if (GWEN_XMLNode_Path_Dive(nodePath, n)) {
1896  DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
1897  return -1;
1898  }
1899  if (n==gn)
1900  dive=1;
1901  else {
1902  if (GWEN_XMLNode_Path_Dive(nodePath, gn)) {
1903  DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
1904  return -1;
1905  }
1906  dive=2;
1907  }
1909  gbuf,
1910  gn,
1911  n,
1912  gcfg,
1913  loopNr>=minnum || groupIsOptional,
1914  nodePath);
1915  GWEN_XMLNode_Path_Surface(nodePath);
1916  if (dive==2)
1917  GWEN_XMLNode_Path_Surface(nodePath);
1918  }
1919 
1920  if (rv==-1) {
1921  DBG_INFO(GWEN_LOGDOMAIN, "Could not write group \"%s\"", gtype);
1922  if (gn) {
1923  DBG_INFO(GWEN_LOGDOMAIN, "Node is:");
1924  GWEN_XMLNode_Dump(gn, 1);
1925  }
1926  if (n) {
1927  DBG_INFO(GWEN_LOGDOMAIN, "Referring node is:");
1928  GWEN_XMLNode_Dump(n, 1);
1929  }
1930  if (gr) {
1931  DBG_INFO(GWEN_LOGDOMAIN, "Data is:");
1932  GWEN_DB_Dump(gr, 1);
1933  }
1934  return -1;
1935  }
1936  else if (rv==0) {
1937  isFirstElement=0;
1938  omittedElements=0;
1939  hasEntries=1;
1940  DBG_DEBUG(GWEN_LOGDOMAIN, "Element written");
1941  }
1942  else {
1943  /* group is optional, not found */
1944  /* restore position */
1945  GWEN_Buffer_SetPos(gbuf, posBeforeGroup);
1946  GWEN_Buffer_Crop(gbuf, 0, posBeforeGroup);
1947 
1948  if (strcasecmp(addEmptyMode, "max")==0) {
1949  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding max empty");
1950  omittedElements+=(maxnum-loopNr);
1951  }
1952  else if (strcasecmp(addEmptyMode, "min")==0) {
1953  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding min empty");
1954  if (loopNr<minnum)
1955  omittedElements+=(minnum-loopNr);
1956  }
1957  else if (strcasecmp(addEmptyMode, "one")==0) {
1958  if (loopNr==0)
1959  omittedElements++;
1960  }
1961  else if (strcasecmp(addEmptyMode, "none")==0) {
1962  }
1963  else {
1964  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown addemptymode \"%s\"",
1965  addEmptyMode);
1966  return -1;
1967  }
1968  break;
1969  }
1970 
1971  /* use next group next time if any */
1972  if (gcfg && gname)
1973  gcfg=GWEN_DB_FindNextGroup(gcfg, gname);
1974  } /* for */
1975  } /* if "GROUP" */
1976  } /* if TAG */
1977  else if (t==GWEN_XMLNodeTypeData) {
1978  }
1979  else {
1980  DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled node type %d", t);
1981  }
1982  n=GWEN_XMLNode_Next(n);
1983  } /* while */
1984 
1985  /* write terminating character, if any */
1986  if (terminator) {
1987  if (GWEN_Buffer_AppendByte(gbuf, terminator)) {
1988  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
1989  return -1;
1990  }
1991  }
1992 
1993  if (!hasEntries) {
1994  DBG_INFO(GWEN_LOGDOMAIN, "No entries in node");
1995  }
1996  return hasEntries?0:1;
1997 }
1998 
1999 
2000 
2002  GWEN_XMLNODE *node,
2003  GWEN_BUFFER *gbuf,
2004  GWEN_DB_NODE *msgData){
2005  GWEN_XMLNODE_PATH *np;
2006  int rv;
2007 
2008  assert(e);
2009  assert(node);
2010  assert(msgData);
2011 
2012  np=GWEN_XMLNode_Path_new();
2013  GWEN_XMLNode_Path_Dive(np, node);
2015  gbuf,
2016  node,
2017  0,
2018  msgData,
2019  0,
2020  np);
2022  if (rv){
2023  const char *p;
2024 
2025  p=GWEN_XMLNode_GetData(node);
2026  if (p) {
2027  DBG_INFO(GWEN_LOGDOMAIN, "Error writing group \"%s\"", p);
2028  }
2029  else {
2030  DBG_INFO(GWEN_LOGDOMAIN, "Error writing group");
2031  }
2032  return -1;
2033  }
2034 
2035  return 0;
2036 }
2037 
2038 
2039 
2041  const char *msgName,
2042  int msgVersion,
2043  GWEN_BUFFER *gbuf,
2044  GWEN_DB_NODE *msgData) {
2045  GWEN_XMLNODE *group;
2046 
2047  group=GWEN_MsgEngine_FindGroupByProperty(e, "id", msgVersion, msgName);
2048  if (!group) {
2049  DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
2050  return -1;
2051  }
2053  group,
2054  gbuf,
2055  msgData);
2056 }
2057 
2058 
2059 
2061  GWEN_XMLNODE *node) {
2062  GWEN_XMLNODE *nsrc, *ndst;
2063 
2064  assert(e);
2065  assert(node);
2066 
2067  if (!e->defs) {
2068  e->defs=GWEN_XMLNode_dup(node);
2069  e->ownDefs=1;
2070  return 0;
2071  }
2072 
2073  nsrc=GWEN_XMLNode_GetChild(node);
2074  while(nsrc) {
2077  GWEN_XMLNode_GetData(nsrc));
2078  if (ndst) {
2079  GWEN_XMLNODE *n;
2080 
2081  n=GWEN_XMLNode_GetChild(nsrc);
2082  while (n) {
2083  GWEN_XMLNODE *newNode;
2084 
2085  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding node \"%s\"", GWEN_XMLNode_GetData(n));
2086  newNode=GWEN_XMLNode_dup(n);
2087  GWEN_XMLNode_AddChild(ndst, newNode);
2088  n=GWEN_XMLNode_Next(n);
2089  } /* while n */
2090  }
2091  else {
2092  GWEN_XMLNODE *newNode;
2093 
2094  DBG_DEBUG(GWEN_LOGDOMAIN, "Adding branch \"%s\"", GWEN_XMLNode_GetData(nsrc));
2095  newNode=GWEN_XMLNode_dup(nsrc);
2096  GWEN_XMLNode_AddChild(e->defs, newNode);
2097  }
2098  } /* if TAG */
2099  nsrc=GWEN_XMLNode_Next(nsrc);
2100  } /* while */
2101 
2102  return 0;
2103 }
2104 
2105 
2106 
2108  const char *path,
2109  GWEN_XMLNODE *node,
2110  GWEN_STRINGLIST *sl,
2111  uint32_t flags) {
2112  const char *name;
2113  const char *type;
2114  const char *npath;
2115  unsigned int minsize;
2116  unsigned int maxsize;
2117  unsigned int minnum;
2118  unsigned int maxnum;
2119  int j;
2120  int isSet;
2121  char nbuffer[256];
2123 
2124  /* get type */
2125  type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
2126 
2127  /* get some sizes */
2128  minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
2129  maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
2130  minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
2131  maxnum=atoi(GWEN_XMLNode_GetProperty(node, "maxnum","1"));
2132 
2133  npath="";
2134  isSet=0;
2135 
2136  /* get name */
2137  name=GWEN_XMLNode_GetProperty(node, "name", 0);
2138  if (path==0)
2139  path="";
2140 
2141  if (name) {
2142  /* get value of a config variable */
2143  if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
2144  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2145  return -1;
2146  }
2147  if (*path)
2148  sprintf(nbuffer, "%s/%s", path, name);
2149  else
2150  sprintf(nbuffer, "%s", name);
2151  npath=nbuffer;
2152  }
2153 
2155  while(en) {
2156  if (GWEN_StringListEntry_Data(en))
2157  if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
2158  isSet=1;
2159  break;
2160  }
2162  } /* while */
2163 
2164  if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
2165  return 0;
2166 
2167  fprintf(stdout, " %s",
2168  npath);
2169  j=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(npath);
2170  if (j>0) {
2171  int i;
2172 
2173  for (i=0; i<j; i++)
2174  fprintf(stdout, " ");
2175  }
2176  fprintf(stdout, "| %s", type);
2177  j=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(type);
2178  if (j>0) {
2179  int i;
2180 
2181  for (i=0; i<j; i++)
2182  fprintf(stdout, " ");
2183  }
2184  fprintf(stdout, "| %4d-%4d", minsize, maxsize);
2185  fprintf(stdout," | %3d ", maxnum);
2186  fprintf(stdout," |");
2187  if (minnum==0)
2188  fprintf(stdout," optvar");
2189  if (flags & GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL)
2190  fprintf(stdout," optgrp");
2191 
2192  if (isSet) {
2193  fprintf(stdout," set");
2194  }
2195 
2196  fprintf(stdout,"\n");
2197 
2198  return 0;
2199 }
2200 
2201 
2202 
2204  const char *path,
2205  GWEN_XMLNODE *node,
2206  GWEN_XMLNODE *rnode,
2207  GWEN_STRINGLIST *sl,
2208  uint32_t flags) {
2209  GWEN_XMLNODE *n;
2210  int isFirstElement;
2211  int omittedElements;
2212  int rv;
2213 
2214  /* setup data */
2215  n=GWEN_XMLNode_GetChild(node);
2216 
2217  if (path==0)
2218  path="";
2219  if (*path=='/')
2220  path++;
2221 
2222  while(n) {
2224  const char *p;
2225 
2226  p=GWEN_XMLNode_GetData(n);
2227  assert(p);
2228  DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
2229  if (strcasecmp(p, "VALUES")==0)
2230  break;
2231  } /* if tag */
2232  n=GWEN_XMLNode_Next(n);
2233  } /* while */
2234 
2235  if (n) {
2236  DBG_DEBUG(GWEN_LOGDOMAIN, "<preset> found");
2237  /* <preset> found, handle all values */
2238  n=GWEN_XMLNode_GetChild(n);
2239  while(n) {
2241  const char *p;
2242 
2243  p=GWEN_XMLNode_GetData(n);
2244  assert(p);
2245  if (strcasecmp(p, "VALUE")==0) {
2246  const char *pname;
2247  const char *pvalue;
2248 
2249  pname=GWEN_XMLNode_GetProperty(n, "path", 0);
2250  if (pname) {
2251  GWEN_XMLNODE *dn;
2252 
2253  /* path found, find data */
2254  dn=GWEN_XMLNode_GetChild(n);
2255  while (dn) {
2257  pvalue=GWEN_XMLNode_GetData(dn);
2258  if (pvalue) {
2259  char pbuffer[256];
2260 
2261  /* check whether the value is a property */
2262  p=pvalue;
2263  while (*p && isspace((int)*p))
2264  p++;
2265  if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
2266  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2267  return -1;
2268  }
2269  if (*path)
2270  sprintf(pbuffer, "%s/%s", path, pname);
2271  else
2272  sprintf(pbuffer, "%s", pname);
2274  pbuffer,
2275  0,
2276  1);
2277  }
2278  break;
2279  }
2280  dn=GWEN_XMLNode_Next(dn);
2281  } /* while dn */
2282  } /* if path given */
2283  } /* if VALUE tag */
2284  } /* if TAG */
2285  n=GWEN_XMLNode_Next(n);
2286  } /* while */
2287  } /* if <preset> found */
2288 
2289  /* now handle all child entries */
2290  n=GWEN_XMLNode_GetChild(node);
2291  isFirstElement=1;
2292  omittedElements=0;
2293  while(n) {
2294  int t;
2295  unsigned int minnum;
2296  unsigned int maxnum;
2297  int gversion;
2298  const char *addEmptyMode;
2299  unsigned int loopNr;
2300  unsigned int lflags;
2301 
2302  minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
2303  maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
2304  gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
2305  addEmptyMode=GWEN_XMLNode_GetProperty(n, "addemptymode","one");
2306 
2307  lflags=flags;
2308 
2309  DBG_DEBUG(GWEN_LOGDOMAIN, "Omitted elements: %d", omittedElements);
2310  t=GWEN_XMLNode_GetType(n);
2311  if (t==GWEN_XMLNodeTypeTag) {
2312  const char *typ;
2313 
2314  typ=GWEN_XMLNode_GetData(n);
2315  if (typ==0) {
2316  DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
2317  return -1;
2318  }
2319  if (strcasecmp(typ, "ELEM")==0) {
2320  /* element tag found */
2321 
2322  /* write element as often as needed */
2324  path,
2325  n,
2326  sl,
2327  lflags);
2328  if (rv==-1)
2329  return -1;
2330  else {
2331  isFirstElement=0;
2332  omittedElements=0;
2333  }
2334  }
2335  else if (strcasecmp(typ, "VALUES")==0) {
2336  }
2337  else if (strcasecmp(typ, "DESCR")==0) {
2338  }
2339  else {
2340  /* group tag found */
2341  GWEN_XMLNODE *gn;
2342  const char *gname;
2343  const char *gtype;
2344 
2345  if (minnum==0)
2346  lflags|=GWEN_MSGENGINE_SHOW_FLAGS_OPTIONAL;
2347 
2348  gtype=GWEN_XMLNode_GetProperty(n, "type",0);
2349  if (!gtype) {
2350  /* no "type" property, so use this group directly */
2351  DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
2352  gtype="";
2353  gn=n;
2354  }
2355  else {
2356  gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
2357  if (!gn) {
2358  DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
2359  return -1;
2360  }
2361  }
2362 
2363  /* write group as often as needed */
2364  for (loopNr=0; loopNr<maxnum; loopNr++) {
2365  /* find group */
2366  char pbuffer[256];
2367  const char *npath;
2368 
2369  /* get configuration */
2370  gname=GWEN_XMLNode_GetProperty(n, "name",0);
2371  if (gname) {
2372  if (loopNr==0) {
2373  if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
2374  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2375  return -1;
2376  }
2377  sprintf(pbuffer, "%s/%s", path, gname);
2378  npath=pbuffer;
2379  }
2380  else {
2381  /* this is not the first one, so create new name */
2382  if (strlen(path)+strlen(gname)+10>sizeof(pbuffer)) {
2383  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2384  return -1;
2385  }
2386  if (*path)
2387  sprintf(pbuffer, "%s/%s%d", path, gname, loopNr);
2388  else
2389  sprintf(pbuffer, "%s%d", gname, loopNr);
2390  /* get the value of the given var */
2391  npath=pbuffer;
2392  }
2393  } /* if name given */
2394  else
2395  npath=path;
2396 
2397  /* write group */
2399  npath,
2400  gn,
2401  n,
2402  sl,
2403  lflags)) {
2404  DBG_INFO(GWEN_LOGDOMAIN, "Could not show group \"%s\"", gtype);
2405  return -1;
2406  }
2407  } /* for */
2408  }
2409  }
2410  n=GWEN_XMLNode_Next(n);
2411  } /* while */
2412 
2413  return 0;
2414 }
2415 
2416 
2417 
2419  const char *typ,
2420  const char *msgName,
2421  int msgVersion,
2422  uint32_t flags) {
2423  GWEN_XMLNODE *group;
2424  GWEN_STRINGLIST *sl;
2425  int i, j;
2426  const char *p;
2427 
2428  sl=GWEN_StringList_new();
2429 
2430  fprintf(stdout, "Message \"%s\" version %d\n",
2431  msgName, msgVersion);
2432  for (i=0; i<76; i++)
2433  fprintf(stdout, "=");
2434  fprintf(stdout, "\n");
2435  p=" Variable";
2436  fprintf(stdout, "%s", p);
2437  i=GWEN_MSGENGINE_VARNAME_WIDTH-strlen(p);
2438  for (j=0; j<i; j++)
2439  fprintf(stdout," ");
2440 
2441  fprintf(stdout," |");
2442  p=" Type";
2443  fprintf(stdout, "%s", p);
2444  i=GWEN_MSGENGINE_TYPENAME_WIDTH-strlen(p);
2445  for (j=0; j<i; j++)
2446  fprintf(stdout," ");
2447 
2448  fprintf(stdout," | Size | Num | Flags\n");
2449  for (i=0; i<76; i++)
2450  fprintf(stdout, "-");
2451  fprintf(stdout, "\n");
2452 
2453  group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
2454  if (!group) {
2455  DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" not found\n", msgName);
2457  return -1;
2458  }
2459 
2461  "",
2462  group,
2463  0,
2464  sl,
2465  flags)) {
2466  DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
2468  return -1;
2469  }
2470 
2472 
2473  return 0;
2474 }
2475 
2476 
2477 
2479  const char *path,
2480  GWEN_XMLNODE *node,
2481  GWEN_STRINGLIST *sl,
2482  GWEN_XMLNODE *listNode,
2483  uint32_t flags) {
2484  const char *name;
2485  const char *type;
2486  const char *npath;
2487  int isSet;
2488  char nbuffer[256];
2490  GWEN_XMLNODE *nn;
2491 
2492  /* get type */
2493  type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
2494 
2495  npath="";
2496  isSet=0;
2497 
2498  /* get name */
2499  name=GWEN_XMLNode_GetProperty(node, "name", 0);
2500  if (path==0)
2501  path="";
2502 
2503  if (name) {
2504  /* get value of a config variable */
2505  if (strlen(path)+strlen(name)+10>=sizeof(nbuffer)) {
2506  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2507  return -1;
2508  }
2509  if (*path)
2510  sprintf(nbuffer, "%s/%s", path, name);
2511  else
2512  sprintf(nbuffer, "%s", name);
2513  npath=nbuffer;
2514  }
2515 
2517  while(en) {
2518  if (GWEN_StringListEntry_Data(en))
2519  if (strcasecmp(GWEN_StringListEntry_Data(en), npath)==0) {
2520  isSet=1;
2521  break;
2522  }
2524  } /* while */
2525 
2526  if (isSet && (flags & GWEN_MSGENGINE_SHOW_FLAGS_NOSET))
2527  return 0;
2528 
2529  nn=GWEN_XMLNode_dup(node);
2530  if (isSet)
2531  GWEN_XMLNode_SetProperty(nn, "GWEN_set", "1");
2532  GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
2533  GWEN_XMLNode_AddChild(listNode, nn);
2534 
2535  return 0;
2536 }
2537 
2538 
2539 
2541  const char *path,
2542  GWEN_XMLNODE *node,
2543  GWEN_XMLNODE *rnode,
2544  GWEN_STRINGLIST *sl,
2545  GWEN_XMLNODE *listNode,
2546  uint32_t flags) {
2547  GWEN_XMLNODE *n;
2548  int rv;
2549 
2550  /* setup data */
2551  n=GWEN_XMLNode_GetChild(node);
2552 
2553  if (path==0)
2554  path="";
2555  if (*path=='/')
2556  path++;
2557 
2558  while(n) {
2560  const char *p;
2561 
2562  p=GWEN_XMLNode_GetData(n);
2563  assert(p);
2564  DBG_DEBUG(GWEN_LOGDOMAIN, "Checking %s",p);
2565  if (strcasecmp(p, "VALUES")==0)
2566  break;
2567  } /* if tag */
2568  n=GWEN_XMLNode_Next(n);
2569  } /* while */
2570 
2571  if (n) {
2572  DBG_DEBUG(GWEN_LOGDOMAIN, "<values> found");
2573  /* <values> found, handle all values */
2574  n=GWEN_XMLNode_GetChild(n);
2575  while(n) {
2577  const char *p;
2578 
2579  p=GWEN_XMLNode_GetData(n);
2580  assert(p);
2581  if (strcasecmp(p, "VALUE")==0) {
2582  const char *pname;
2583  const char *pvalue;
2584 
2585  pname=GWEN_XMLNode_GetProperty(n, "path", 0);
2586  if (pname) {
2587  GWEN_XMLNODE *dn;
2588 
2589  /* path found, find data */
2590  dn=GWEN_XMLNode_GetChild(n);
2591  while (dn) {
2593  pvalue=GWEN_XMLNode_GetData(dn);
2594  if (pvalue) {
2595  char pbuffer[256];
2596 
2597  /* check whether the value is a property */
2598  p=pvalue;
2599  while (*p && isspace((int)*p))
2600  p++;
2601  if (strlen(path)+strlen(pname)+2>sizeof(pbuffer)) {
2602  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2603  return -1;
2604  }
2605  if (*path)
2606  sprintf(pbuffer, "%s/%s", path, pname);
2607  else
2608  sprintf(pbuffer, "%s", pname);
2609  DBG_INFO(GWEN_LOGDOMAIN, "Found preset value for %s", pbuffer);
2611  pbuffer,
2612  0,
2613  1);
2614  }
2615  break;
2616  }
2617  dn=GWEN_XMLNode_Next(dn);
2618  } /* while dn */
2619  } /* if path given */
2620  } /* if VALUE tag */
2621  } /* if TAG */
2622  n=GWEN_XMLNode_Next(n);
2623  } /* while */
2624  } /* if <values> found */
2625 
2626  /* now handle all child entries */
2627  n=GWEN_XMLNode_GetChild(node);
2628  while(n) {
2629  int t;
2630  int gversion;
2631  unsigned int lflags;
2632 
2633  gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
2634  lflags=flags;
2635 
2636  t=GWEN_XMLNode_GetType(n);
2637  if (t==GWEN_XMLNodeTypeTag) {
2638  const char *typ;
2639 
2640  typ=GWEN_XMLNode_GetData(n);
2641  if (typ==0) {
2642  DBG_ERROR(GWEN_LOGDOMAIN, "Unnamed tag found (internal error?)");
2643  return -1;
2644  }
2645  if (strcasecmp(typ, "ELEM")==0) {
2646  /* element tag found */
2647 
2648  /* list element */
2650  path,
2651  n,
2652  sl,
2653  listNode,
2654  lflags);
2655  if (rv==-1)
2656  return -1;
2657  }
2658  else if (strcasecmp(typ, "VALUES")==0) {
2659  }
2660  else if (strcasecmp(typ, "DESCR")==0) {
2661  }
2662  else {
2663  /* group tag found */
2664  GWEN_XMLNODE *gn;
2665  GWEN_XMLNODE *nn;
2666  const char *gname;
2667  const char *gtype;
2668  char pbuffer[256];
2669  const char *npath;
2670 
2671  gtype=GWEN_XMLNode_GetProperty(n, "type",0);
2672  if (!gtype) {
2673  /* no "type" property, so use this group directly */
2674  DBG_DEBUG(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", typ);
2675  gtype="";
2676  gn=n;
2677  }
2678  else {
2679  gn=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", gversion, gtype);
2680  if (!gn) {
2681  DBG_DEBUG(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", typ);
2682  return -1;
2683  }
2684  }
2685 
2686  /* get configuration */
2687  gname=GWEN_XMLNode_GetProperty(n, "name",0);
2688  if (gname) {
2689  if (strlen(path)+strlen(gname)+1>sizeof(pbuffer)) {
2690  DBG_ERROR(GWEN_LOGDOMAIN, "Buffer too small");
2691  return -1;
2692  }
2693 
2694  if (*path)
2695  sprintf(pbuffer, "%s/%s", path, gname);
2696  else
2697  sprintf(pbuffer, "%s", gname);
2698  npath=pbuffer;
2699  } /* if name given */
2700  else
2701  npath=path;
2702 
2703  nn=GWEN_XMLNode_dup(n);
2704  if (gn!=n)
2705  GWEN_XMLNode_CopyProperties(nn, gn, 0);
2706  GWEN_XMLNode_SetProperty(nn, "GWEN_path", npath);
2707  GWEN_XMLNode_AddChild(listNode, nn);
2708 
2709  /* write group */
2711  npath,
2712  gn,
2713  n,
2714  sl,
2715  nn,
2716  lflags)) {
2717  DBG_INFO(GWEN_LOGDOMAIN, "Could not list group \"%s\"", gtype);
2718  return -1;
2719  }
2720  }
2721  }
2722  n=GWEN_XMLNode_Next(n);
2723  } /* while */
2724 
2725  return 0;
2726 }
2727 
2728 
2729 
2731  const char *typ,
2732  const char *msgName,
2733  int msgVersion,
2734  uint32_t flags) {
2735  GWEN_XMLNODE *group;
2736  GWEN_STRINGLIST *sl;
2737  GWEN_XMLNODE *listNode;
2738 
2739  group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "id", msgVersion, msgName);
2740  if (!group)
2741  group=GWEN_MsgEngine_FindNodeByProperty(e, typ, "code",
2742  msgVersion, msgName);
2743  if (!group) {
2744  DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" (version %d) not found\n",
2745  msgName, msgVersion);
2746  return 0;
2747  }
2748 
2749  sl=GWEN_StringList_new();
2750  /* copy group, but remove all children (we only want the properties) */
2751  listNode=GWEN_XMLNode_dup(group);
2752  GWEN_XMLNode_RemoveChildren(listNode);
2753 
2755  "",
2756  group,
2757  0,
2758  sl,
2759  listNode,
2760  flags)) {
2761  DBG_INFO(GWEN_LOGDOMAIN, "Error showing group \"%s\"", msgName);
2763  GWEN_XMLNode_free(listNode);
2764  return 0;
2765  }
2766 
2768 
2769  return listNode;
2770 }
2771 
2772 
2773 
2774 
2775 
2776 
2777 
2779  GWEN_BUFFER *msgbuf,
2780  GWEN_XMLNODE *node,
2781  GWEN_XMLNODE *rnode,
2782  GWEN_BUFFER *vbuf,
2783  const char *delimiters,
2784  uint32_t flags) {
2785  unsigned int minsize;
2786  unsigned int maxsize;
2787  unsigned int size;
2788  unsigned int minnum;
2789  GWEN_MSGENGINE_TRUSTLEVEL trustLevel;
2790  unsigned int posInMsg;
2791  const char *type;
2792  int rv;
2793  unsigned int realSize;
2794 
2795  /* get some sizes */
2796  posInMsg=GWEN_Buffer_GetPos(msgbuf);
2797  realSize=0;
2798  size=atoi(GWEN_XMLNode_GetProperty(node, "size","0"));
2799  minsize=atoi(GWEN_XMLNode_GetProperty(node, "minsize","0"));
2800  maxsize=atoi(GWEN_XMLNode_GetProperty(node, "maxsize","0"));
2801  minnum=atoi(GWEN_XMLNode_GetProperty(node, "minnum","1"));
2802  type=GWEN_XMLNode_GetProperty(node, "type","ASCII");
2803 
2804  rv=1;
2805  if (e->typeReadPtr) {
2806  rv=e->typeReadPtr(e,
2807  msgbuf,
2808  node,
2809  vbuf,
2810  e->escapeChar,
2811  delimiters);
2812  }
2813  if (rv==-1) {
2814  DBG_INFO(GWEN_LOGDOMAIN, "External type reading failed on type \"%s\"", type);
2815  return -1;
2816  }
2817  else if (rv==1) {
2818  if (strcasecmp(type, "bin")==0) {
2819  if (GWEN_Buffer_GetBytesLeft(msgbuf)==0) {
2820  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (@num@ expected)");
2821  return -1;
2822  }
2823  else {
2824  char lbuffer[16];
2825  int c;
2826  char *p;
2827  int l;
2828 
2829  p=lbuffer;
2830  c=GWEN_Buffer_ReadByte(msgbuf);
2831  if (c!='@') {
2832  DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
2833  return -1;
2834  }
2835 
2836  c=0;
2837  while(GWEN_Buffer_GetBytesLeft(msgbuf)>0) {
2838  c=GWEN_Buffer_ReadByte(msgbuf);
2839  if (c==-1) {
2840  DBG_ERROR(GWEN_LOGDOMAIN, "\"@\" expected");
2841  return -1;
2842  }
2843  if (c=='@')
2844  break;
2845  *p=(char)c;
2846  p++;
2847  } /* while */
2848  *p=0;
2849  if (c!='@') {
2850  DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
2851  return -1;
2852  }
2853  if (sscanf(lbuffer, "%d", &l)!=1) {
2854  DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
2855  return -1;
2856  }
2857  DBG_DEBUG(GWEN_LOGDOMAIN, "Reading binary: %d bytes from pos %d (msgsize=%d)",
2858  l,
2859  GWEN_Buffer_GetPos(msgbuf),
2860  GWEN_Buffer_GetUsedBytes(msgbuf));
2861  if (GWEN_Buffer_GetBytesLeft(msgbuf) < (unsigned) l) {
2862  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
2863  return -1;
2864  }
2865  if (GWEN_Buffer_AppendBytes(vbuf,
2866  GWEN_Buffer_GetPosPointer(msgbuf),
2867  l)) {
2868  DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
2869  return -1;
2870  }
2871  GWEN_Buffer_IncrementPos(msgbuf,l);
2872  }
2873  } /* if bin */
2874  else {
2875  /* type is not bin */
2876  int lastWasEscape;
2877  int isEscaped;
2878  int br;
2879 
2880  isEscaped=0;
2881  lastWasEscape=0;
2882 
2883  br=0;
2884  while(GWEN_Buffer_GetBytesLeft(msgbuf) &&
2885  (size==0 || br<size)) {
2886  int c;
2887 
2888  c=GWEN_Buffer_ReadByte(msgbuf);
2889  if (lastWasEscape) {
2890  lastWasEscape=0;
2891  isEscaped=1;
2892  }
2893  else {
2894  isEscaped=0;
2895  if (c==e->escapeChar) {
2896  lastWasEscape=1;
2897  c=-1;
2898  }
2899  }
2900  if (c!=-1) {
2901  if (!isEscaped && (c && strchr(delimiters, c)!=0)) {
2902  /* delimiter found, step back */
2903  GWEN_Buffer_DecrementPos(msgbuf,1);
2904  break;
2905  }
2906  else {
2907  if (c=='\\' || iscntrl(c)) {
2909  "Found a bad character (%02x) in type \"%s\", "
2910  "converting to SPACE",
2911  (unsigned int)c,
2912  type);
2913  c=' ';
2914  }
2915  if (GWEN_Buffer_AppendByte(vbuf, c)) {
2916  DBG_DEBUG(GWEN_LOGDOMAIN, "Called from here");
2917  return -1;
2918  }
2919  br++;
2920  }
2921  }
2922  } /* while */
2923  } /* if !bin */
2924  } /* if type not external */
2925  else {
2926  DBG_DEBUG(GWEN_LOGDOMAIN, "Type \"%s\" is external (read)", type);
2927  }
2928 
2929  realSize=GWEN_Buffer_GetUsedBytes(vbuf);
2930 
2931  /* check the value */
2932  if (realSize==0) {
2933  DBG_DEBUG(GWEN_LOGDOMAIN, "Datasize is 0");
2934  if (minnum==0) {
2935  DBG_DEBUG(GWEN_LOGDOMAIN, "... but thats ok");
2936  /* value is empty, and that is allowed */
2937  return 1;
2938  }
2939  else {
2940  DBG_ERROR(GWEN_LOGDOMAIN, "Value missing");
2941  GWEN_XMLNode_Dump(node, 1);
2942  return -1;
2943  }
2944  }
2945 
2946  /* check minimum size */
2947  if (minsize!=0 && realSize<minsize) {
2948  DBG_INFO(GWEN_LOGDOMAIN, "Value too short (%d<%d).",
2949  realSize,
2950  minsize);
2951  return -1;
2952  }
2953 
2954  /* check maximum size */
2955  if (maxsize!=0 && realSize>maxsize) {
2956  DBG_INFO(GWEN_LOGDOMAIN, "Value too long (%d>%d).",
2957  realSize, maxsize);
2958  return -1;
2959  }
2960 
2962  /* add trust data to msgEngine */
2963  const char *descr;
2964 
2965  trustLevel=GWEN_MsgEngine_GetHighestTrustLevel(node, rnode);
2966  if (trustLevel) {
2967  unsigned int ustart;
2968 
2969  ustart=GWEN_Buffer_GetPos(msgbuf)-realSize;
2970  descr=GWEN_XMLNode_GetProperty(node, "name",0);
2972  GWEN_Buffer_GetStart(vbuf),
2973  realSize,
2974  descr,
2975  trustLevel,
2976  ustart)) {
2977  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
2978  return -1;
2979  }
2980  }
2981  }
2982 
2983  return 0;
2984 }
2985 
2986 
2987 
2989  GWEN_BUFFER *msgbuf,
2990  GWEN_XMLNODE *node,
2991  GWEN_XMLNODE *rnode,
2992  GWEN_DB_NODE *gr,
2993  const char *delimiters,
2994  uint32_t flags) {
2995  unsigned int minsize;
2996  unsigned int maxsize;
2997  unsigned int minnum;
2998  unsigned int maxnum;
2999  const char *name;
3000  const char *p;
3001  char delimiter;
3002  char terminator;
3003  GWEN_XMLNODE *n;
3004  int abortLoop;
3005  GWEN_BUFFER *delimBuffer=0;
3006 
3007  /* get some settings */
3008  if (rnode) {
3009  /* get delimiter */
3010  p=GWEN_XMLNode_GetProperty(rnode,
3011  "delimiter",
3013  "delimiter",
3014  ""));
3015  delimiter=*p;
3016 
3017  /* get terminating char, if any */
3018  p=GWEN_XMLNode_GetProperty(rnode,
3019  "terminator",
3021  "terminator",
3022  ""));
3023  terminator=*p;
3024  }
3025  else {
3026  /* get delimiter */
3027  p=GWEN_XMLNode_GetProperty(node,
3028  "delimiter",
3029  "");
3030  delimiter=*p;
3031 
3032  /* get terminating char, if any */
3033  p=GWEN_XMLNode_GetProperty(node, "terminator","");
3034  terminator=*p;
3035  }
3036 
3037  delimBuffer=GWEN_Buffer_new(0, strlen(delimiters)+2, 0, 1);
3038  GWEN_Buffer_AppendString(delimBuffer, delimiters);
3039  if (delimiter)
3040  GWEN_Buffer_AppendByte(delimBuffer, delimiter);
3041  if (terminator)
3042  GWEN_Buffer_AppendByte(delimBuffer, terminator);
3043 
3044  DBG_DEBUG(GWEN_LOGDOMAIN, "Delimiters are \"%s\" and \"%c\"",
3045  delimiters, delimiter);
3046 
3047  n=GWEN_XMLNode_GetChild(node);
3048  while (n) {
3050  const char *type;
3051 
3052  if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
3053  break;
3054 
3055  type=GWEN_XMLNode_GetData(n);
3056 
3057  /*
3058  DBG_NOTICE(GWEN_LOGDOMAIN, "Reading group from here :");
3059  GWEN_Text_DumpString(GWEN_Buffer_GetStart(msgbuf)+
3060  GWEN_Buffer_GetPos(msgbuf),
3061  GWEN_Buffer_GetUsedBytes(msgbuf)-
3062  GWEN_Buffer_GetPos(msgbuf),
3063  stderr, 3);
3064  */
3065  if (strcasecmp(type, "ELEM")==0) {
3066  unsigned int loopNr;
3067 
3068  /* get some sizes */
3069  minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize","0"));
3070  maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize","0"));
3071  minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
3072  maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
3073  name=GWEN_XMLNode_GetProperty(n, "name", 0);
3074 
3075  loopNr=0;
3076  abortLoop=0;
3077  while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
3078  int c;
3079 
3080  DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %s", name);
3081  if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
3082  break;
3083  c=GWEN_Buffer_PeekByte(msgbuf);
3084  if (c==-1) {
3085  DBG_DEBUG(GWEN_LOGDOMAIN, "called from here");
3086  GWEN_Buffer_free(delimBuffer);
3087  return -1;
3088  }
3089 
3091  "Checking delimiter at pos %x "
3092  "(whether \"%c\" is in \"%s\")",
3093  GWEN_Buffer_GetPos(msgbuf),
3094  c, GWEN_Buffer_GetStart(delimBuffer));
3095  if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
3096  abortLoop=1;
3098  "Found delimiter (\"%c\" is in \"%s\")",
3099  c, GWEN_Buffer_GetStart(delimBuffer));
3100  } /* if delimiter found */
3101  else {
3102  /* current char is not a delimiter */
3103  if (name==0) {
3104  DBG_VERBOUS(GWEN_LOGDOMAIN, "no name");
3105  }
3106  else {
3107  /* name is given */
3108  int rv;
3109  const char *dtype;
3110  GWEN_BUFFER *vbuf;
3111 
3112  DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading value from pos %x",
3113  GWEN_Buffer_GetPos(msgbuf));
3114  vbuf=GWEN_Buffer_new(0,
3116  0,0);
3117  /*
3118  DBG_ERROR(GWEN_LOGDOMAIN, "Reading value from here:\n");
3119  GWEN_Text_DumpString(GWEN_Buffer_GetPosPointer(msgbuf),
3120  GWEN_Buffer_GetBytesLeft(msgbuf),
3121  stderr, 1);*/
3122 
3124  msgbuf,
3125  n,
3126  rnode,
3127  vbuf,
3128  GWEN_Buffer_GetStart(delimBuffer),
3129  //":+'",
3130  flags);
3131  if (rv==1) {
3132  DBG_INFO(GWEN_LOGDOMAIN, "Empty value");
3133  }
3134  else if (rv==-1) {
3135  DBG_INFO(GWEN_LOGDOMAIN, "Error parsing node \"%s\" (%s)",
3136  name,
3137  type);
3138  GWEN_Buffer_free(vbuf);
3139  GWEN_Buffer_free(delimBuffer);
3140  return -1;
3141  }
3142 
3143  GWEN_Buffer_Rewind(vbuf);
3144 
3145  /* special handling for binary data */
3146  dtype=GWEN_XMLNode_GetProperty(n, "type", "");
3147  if (GWEN_MsgEngine__IsBinTyp(e, dtype)) {
3148  if (atoi(GWEN_XMLNode_GetProperty(n, "readbin", "1")) &&
3149  e->binTypeReadPtr) {
3150  rv=e->binTypeReadPtr(e, n, gr, vbuf);
3151  }
3152  else
3153  rv=1;
3154  if (rv==-1) {
3155  DBG_INFO(GWEN_LOGDOMAIN, "Called from here");
3156  GWEN_Buffer_free(vbuf);
3157  GWEN_Buffer_free(delimBuffer);
3158  return -1;
3159  }
3160  else if (rv==1) {
3161  /* bin type not handled, so handle it myself */
3162  if (GWEN_DB_SetBinValue(gr,
3164  name,
3165  GWEN_Buffer_GetStart(vbuf),
3166  GWEN_Buffer_GetUsedBytes(vbuf))) {
3167  DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
3168  GWEN_Buffer_free(vbuf);
3169  GWEN_Buffer_free(delimBuffer);
3170  return -1;
3171  }
3172  }
3173  } /* if type is bin */
3174  else if (GWEN_MsgEngine__IsIntTyp(e, dtype)) {
3175  int z;
3176 
3177  if (1!=sscanf(GWEN_Buffer_GetStart(vbuf), "%d", &z)) {
3178  DBG_INFO(GWEN_LOGDOMAIN, "Value for \"%s\" is not an integer",
3179  name);
3180  GWEN_Buffer_free(delimBuffer);
3181  return -1;
3182  }
3183  if (GWEN_DB_SetIntValue(gr,
3185  name, z)) {
3186  DBG_INFO(GWEN_LOGDOMAIN, "Could not set int value for \"%s\"", name);
3187  GWEN_Buffer_free(delimBuffer);
3188  return -1;
3189  }
3190  } /* if type is int */
3191  else {
3192  DBG_DEBUG(GWEN_LOGDOMAIN, "Value is \"%s\"",
3193  GWEN_Buffer_GetStart(vbuf));
3194  if (GWEN_DB_SetCharValue(gr,
3196  name,
3197  GWEN_Buffer_GetStart(vbuf))){
3198  DBG_INFO(GWEN_LOGDOMAIN, "Could not set value for \"%s\"", name);
3199  GWEN_Buffer_free(delimBuffer);
3200  return -1;
3201  }
3202  } /* if !bin */
3203 
3204  GWEN_Buffer_free(vbuf);
3205  } /* if name is given */
3206  } /* if current char is not a delimiter */
3207 
3208  if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
3209  if (delimiter) {
3210  if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
3211  GWEN_Buffer_IncrementPos(msgbuf,1);
3212  }
3213  }
3214  }
3215  loopNr++;
3216  } /* while */
3217  if (loopNr<minnum) {
3218  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few ELEM repeats)");
3219  GWEN_XMLNode_Dump(n, 2);
3220  GWEN_Buffer_free(delimBuffer);
3221  return -1;
3222  }
3223  n=GWEN_XMLNode_Next(n);
3224  } /* if ELEM */
3225  else if (strcasecmp(type, "VALUES")==0) {
3226  n=GWEN_XMLNode_Next(n);
3227  }
3228  else if (strcasecmp(type, "DESCR")==0) {
3229  n=GWEN_XMLNode_Next(n);
3230  }
3231  else {
3232  /* group tag found */
3233  GWEN_XMLNODE *gn;
3234  GWEN_DB_NODE *gcfg;
3235  const char *gname;
3236  const char *gtype;
3237  unsigned int gversion;
3238  unsigned int loopNr;
3239 
3240  minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum","1"));
3241  maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum","1"));
3242  gversion=atoi(GWEN_XMLNode_GetProperty(n, "version","0"));
3243  gtype=GWEN_XMLNode_GetProperty(n, "type",0);
3244  if (!gtype) {
3245  /* no "type" property, so use this group directly */
3246  DBG_INFO(GWEN_LOGDOMAIN, "<%s> tag has no \"type\" property", type);
3247  gtype="";
3248  gn=n;
3249  }
3250  else {
3251  gn=GWEN_MsgEngine_FindNodeByProperty(e, type, "id",
3252  gversion, gtype);
3253  if (!gn) {
3254  DBG_INFO(GWEN_LOGDOMAIN, "Definition for type \"%s\" not found", type);
3255  GWEN_Buffer_free(delimBuffer);
3256  return -1;
3257  }
3258  }
3259 
3260  /* get configuration */
3261  loopNr=0;
3262  abortLoop=0;
3263  while((maxnum==0 || loopNr<maxnum) && !abortLoop) {
3264  int c;
3265 
3266  DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group type %s", gtype);
3267  if (GWEN_Buffer_GetBytesLeft(msgbuf)==0)
3268  break;
3269  c=GWEN_Buffer_PeekByte(msgbuf);
3270  if (c && strchr(GWEN_Buffer_GetStart(delimBuffer), c)) {
3271  abortLoop=1;
3272  }
3273  else {
3274  gname=GWEN_XMLNode_GetProperty(n, "name",0);
3275  if (gname) {
3276  DBG_DEBUG(GWEN_LOGDOMAIN, "Creating group \"%s\"", gname);
3277  gcfg=GWEN_DB_GetGroup(gr,
3279  gname);
3280  if (!gcfg) {
3281  DBG_ERROR(GWEN_LOGDOMAIN, "Could not select group \"%s\"",
3282  gname);
3283  GWEN_Buffer_free(delimBuffer);
3284  return -1;
3285  }
3286  DBG_DEBUG(GWEN_LOGDOMAIN, "Created group \"%s\"", gname);
3287  } /* if name given */
3288  else
3289  gcfg=gr;
3290 
3291  /* read group */
3292  DBG_DEBUG(GWEN_LOGDOMAIN, "Reading group \"%s\"", gname);
3294  msgbuf,
3295  gn,
3296  n,
3297  gcfg,
3298  GWEN_Buffer_GetStart(delimBuffer),
3299  flags)) {
3300  DBG_INFO(GWEN_LOGDOMAIN, "Could not read group \"%s\"", gtype);
3301  GWEN_Buffer_free(delimBuffer);
3302  return -1;
3303  }
3304  }
3305  if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
3306  if (delimiter) {
3307  if (GWEN_Buffer_PeekByte(msgbuf)==delimiter) {
3308  GWEN_Buffer_IncrementPos(msgbuf, 1);
3309  }
3310  }
3311  }
3312  loopNr++;
3313  } /* while */
3314  if (loopNr<minnum) {
3315  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (too few group repeats)");
3316  GWEN_Buffer_free(delimBuffer);
3317  return -1;
3318  }
3319  n=GWEN_XMLNode_Next(n);
3320  } /* if GROUP */
3321  } /* if TAG */
3322  else {
3323  n=GWEN_XMLNode_Next(n);
3324  }
3325  } /* while */
3326 
3327  /* check whether there still are nodes which have not been read */
3328  while(n) {
3330  if (strcasecmp(GWEN_XMLNode_GetData(n), "ELEM")==0 ||
3331  strcasecmp(GWEN_XMLNode_GetData(n), "GROUP")==0) {
3332  unsigned int i;
3333 
3334  i=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1"));
3335  if (i) {
3336  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (still tags to parse)");
3337  GWEN_XMLNode_Dump(n, 2);
3338  GWEN_Buffer_free(delimBuffer);
3339  return -1;
3340  }
3341  }
3342  }
3343  n=GWEN_XMLNode_Next(n);
3344  }
3345 
3346 
3347  if (terminator) {
3348  /* skip terminator */
3349  if (GWEN_Buffer_GetBytesLeft(msgbuf)) {
3350  if (GWEN_Buffer_PeekByte(msgbuf)==terminator) {
3351  GWEN_Buffer_IncrementPos(msgbuf, 1);
3352  }
3353  else {
3355  "Terminating character missing (pos=%d [%x]) "
3356  "expecting \"%c\", got \"%c\")",
3357  GWEN_Buffer_GetPos(msgbuf),
3358  GWEN_Buffer_GetPos(msgbuf),
3359  terminator,
3360  GWEN_Buffer_PeekByte(msgbuf));
3361  GWEN_XMLNode_Dump(node, 1);
3362  GWEN_Buffer_free(delimBuffer);
3363  return -1;
3364  }
3365  }
3366  else {
3367  DBG_ERROR(GWEN_LOGDOMAIN, "Terminating character missing");
3368  GWEN_Buffer_free(delimBuffer);
3369  return -1;
3370  }
3371  }
3372 
3373  GWEN_Buffer_free(delimBuffer);
3374  return 0;
3375 }
3376 
3377 
3378 
3380  GWEN_XMLNODE *group,
3381  GWEN_BUFFER *msgbuf,
3382  GWEN_DB_NODE *msgData,
3383  uint32_t flags){
3384 
3386  msgbuf,
3387  group,
3388  0,
3389  msgData,
3390  e->delimiters,
3391  flags)) {
3392  DBG_INFO(GWEN_LOGDOMAIN, "Error reading group");
3393  return -1;
3394  }
3395 
3396  return 0;
3397 }
3398 
3399 
3400 
3402  const char *path,
3403  const char *value){
3404  GWEN_DB_NODE *globalValues;
3405 
3406  assert(e);
3407  globalValues=GWEN_MsgEngine__GetGlobalValues(e);
3408  assert(globalValues);
3409  return GWEN_DB_SetCharValue(globalValues,
3412  path, value);
3413 }
3414 
3415 
3416 
3418  const char *path,
3419  int value){
3420  GWEN_DB_NODE *globalValues;
3421 
3422  assert(e);
3423  globalValues=GWEN_MsgEngine__GetGlobalValues(e);
3424  assert(globalValues);
3425  return GWEN_DB_SetIntValue(globalValues,
3428  path, value);
3429 }
3430 
3431 
3432 
3434  const char *path,
3435  const char *defValue){
3436  GWEN_DB_NODE *globalValues;
3437 
3438  assert(e);
3439  globalValues=GWEN_MsgEngine__GetGlobalValues(e);
3440  assert(globalValues);
3441  return GWEN_DB_GetCharValue(globalValues,
3442  path, 0, defValue);
3443 }
3444 
3445 
3446 
3448  const char *path,
3449  int defValue){
3450  GWEN_DB_NODE *globalValues;
3451 
3452  assert(e);
3453  globalValues=GWEN_MsgEngine__GetGlobalValues(e);
3454  assert(globalValues);
3455  return GWEN_DB_GetIntValue(globalValues,
3456  path, 0, defValue);
3457 }
3458 
3459 
3460 
3461 /* --------------------------------------------------------------- FUNCTION */
3463  GWEN_BUFFER *msgbuf,
3464  unsigned char escapeChar,
3465  unsigned char delimiter) {
3466  int esc;
3467 
3468  esc=0;
3469  while(GWEN_Buffer_GetBytesLeft(msgbuf)) {
3470  if (esc) {
3471  esc=0;
3472  }
3473  else {
3474  int i;
3475  unsigned char c;
3476 
3477  i=GWEN_Buffer_ReadByte(msgbuf);
3478  if (i==-1) {
3479  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
3480  return 0;
3481  }
3482  c=(unsigned int)i;
3483  if (c==escapeChar) { /* escape */
3484  esc=1;
3485  }
3486  else if (c=='@') {
3487  /* skip binary data */
3488  char lbuffer[16];
3489  char *p;
3490  int l;
3491  int nc;
3492 
3493  p=lbuffer;
3494  while(1) {
3495  nc=GWEN_Buffer_ReadByte(msgbuf);
3496  if (nc==-1) {
3497  DBG_ERROR(GWEN_LOGDOMAIN, "\"@num@\" expected");
3498  return -1;
3499  }
3500  if (nc=='@')
3501  break;
3502  *p=nc;
3503  p++;
3504  } /* while */
3505  *p=0;
3506  if (sscanf(lbuffer, "%d", &l)!=1) {
3507  DBG_ERROR(GWEN_LOGDOMAIN, "Bad number format");
3508  return -1;
3509  }
3510  if (GWEN_Buffer_GetUsedBytes(msgbuf)-GWEN_Buffer_GetPos(msgbuf)
3511  < (unsigned) l) {
3512  DBG_ERROR(GWEN_LOGDOMAIN, "Premature end of message (binary beyond end)");
3513  return -1;
3514  }
3515  GWEN_Buffer_IncrementPos(msgbuf, l);
3516  }
3517  else if (c==delimiter) {/* segment-end */
3518  return 0;
3519  break;
3520  }
3521  }
3522  } /* while */
3523 
3524  DBG_ERROR(GWEN_LOGDOMAIN, "End of segment not found");
3525  return -1;
3526 }
3527 
3528 
3529 
3530 /* --------------------------------------------------------------- FUNCTION */
3532  const char *gtype,
3533  GWEN_BUFFER *mbuf,
3534  GWEN_DB_NODE *gr,
3535  uint32_t flags) {
3536  unsigned int segments;
3537 
3538  segments=0;
3539 
3540  while(GWEN_Buffer_GetBytesLeft(mbuf)) {
3541  GWEN_XMLNODE *node;
3542  unsigned int posBak;
3543  const char *p;
3544  GWEN_DB_NODE *tmpdb;
3545  int segVer;
3546 
3547  /* find head segment description */
3548  tmpdb=GWEN_DB_Group_new("tmpdb");
3550  "id",
3551  0,
3552  "SegHead");
3553  if (node==0) {
3554  DBG_ERROR(GWEN_LOGDOMAIN, "Segment description not found");
3555  GWEN_DB_Group_free(tmpdb);
3556  return -1;
3557  }
3558 
3559  /* parse head segment */
3560  posBak=GWEN_Buffer_GetPos(mbuf);
3562  node,
3563  mbuf,
3564  tmpdb,
3565  flags)) {
3566  DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment head");
3567  GWEN_DB_Group_free(tmpdb);
3568  return -1;
3569  }
3570 
3571  /* get segment code */
3572  segVer=GWEN_DB_GetIntValue(tmpdb,
3573  "version",
3574  0,
3575  0);
3576  p=GWEN_DB_GetCharValue(tmpdb,
3577  "code",
3578  0,
3579  0);
3580  if (!p) {
3581  DBG_ERROR(GWEN_LOGDOMAIN, "No segment code for %s ? This seems to be a bad msg...",
3582  gtype);
3583  GWEN_Buffer_SetPos(mbuf, posBak);
3584  DBG_ERROR(GWEN_LOGDOMAIN, "Full message (pos=%04x)", posBak);
3587  1);
3588  GWEN_DB_Dump(tmpdb, 1);
3589  GWEN_DB_Group_free(tmpdb);
3590  return -1;
3591  }
3592 
3593  /* try to find corresponding XML node */
3595  gtype,
3596  "code",
3597  segVer,
3598  p);
3599  if (node==0) {
3600  unsigned int ustart;
3601 
3602  ustart=GWEN_Buffer_GetPos(mbuf);
3603  ustart++; /* skip delimiter */
3604 
3605  /* node not found, skip it */
3607  "Unknown segment \"%s\" (Segnum=%d, version=%d, ref=%d)",
3608  p,
3609  GWEN_DB_GetIntValue(tmpdb, "seq", 0, -1),
3610  GWEN_DB_GetIntValue(tmpdb, "version", 0, -1),
3611  GWEN_DB_GetIntValue(tmpdb, "ref", 0, -1));
3612  if (GWEN_MsgEngine_SkipSegment(e, mbuf, '?', '\'')) {
3613  DBG_ERROR(GWEN_LOGDOMAIN, "Error skipping segment \"%s\"", p);
3614  GWEN_DB_Group_free(tmpdb);
3615  return -1;
3616  }
3618  unsigned int usize;
3619 
3620  usize=GWEN_Buffer_GetPos(mbuf)-ustart-1;
3621 #if 0
3623  usize,
3624  stderr, 1);
3625 #endif
3627  GWEN_Buffer_GetStart(mbuf)+ustart,
3628  usize,
3629  p,
3631  ustart)) {
3632  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
3633  GWEN_DB_Group_free(tmpdb);
3634  return -1;
3635  }
3636  } /* if trustInfo handling wanted */
3637  }
3638  else {
3639  /* ok, node available, get the corresponding description and parse
3640  * the segment */
3641  const char *id;
3642  GWEN_DB_NODE *storegrp;
3643  unsigned int startPos;
3644 
3645  /* restore start position, since the segment head is part of a full
3646  * description, so we need to restart reading from the very begin */
3647  GWEN_Buffer_SetPos(mbuf, posBak);
3648 
3649  /* create group in DB for this segment */
3650  id=GWEN_XMLNode_GetProperty(node, "id", p);
3651  storegrp=GWEN_DB_GetGroup(gr,
3653  id);
3654  assert(storegrp);
3655 
3656  /* store the start position of this segment within the DB */
3657  startPos=GWEN_Buffer_GetPos(mbuf);
3658  GWEN_DB_SetIntValue(storegrp,
3660  "segment/pos",
3661  startPos);
3662 
3663  /* parse the segment */
3665  node,
3666  mbuf,
3667  storegrp,
3668  flags)) {
3669  DBG_ERROR(GWEN_LOGDOMAIN, "Error parsing segment \"%s\" at %d (%x)",
3670  p,
3671  GWEN_Buffer_GetPos(mbuf)-startPos,
3672  GWEN_Buffer_GetPos(mbuf)-startPos);
3674  GWEN_Buffer_GetUsedBytes(mbuf)-startPos,
3675  1);
3676  DBG_ERROR(GWEN_LOGDOMAIN, "Stored data so far:");
3677  GWEN_DB_Dump(storegrp, 2);
3678  GWEN_DB_Group_free(tmpdb);
3679  return -1;
3680  }
3681 
3682  /* store segment size within DB */
3683  GWEN_DB_SetIntValue(storegrp,
3685  "segment/length",
3686  GWEN_Buffer_GetPos(mbuf)-startPos);
3687  segments++;
3688  }
3689  GWEN_DB_Group_free(tmpdb);
3690  } /* while */
3691 
3692  /* done */
3693  if (segments) {
3694  DBG_DEBUG(GWEN_LOGDOMAIN, "Parsed %d segments", segments);
3695  return 0;
3696  }
3697  else {
3698  DBG_INFO(GWEN_LOGDOMAIN, "No segments parsed.");
3699  return 1;
3700  }
3701 }
3702 
3703 
3704 
3705 
3706 
3707 
3708 
3709 
3712  unsigned int size,
3713  const char *description,
3714  GWEN_MSGENGINE_TRUSTLEVEL trustLevel){
3716 
3717  assert(data);
3718  assert(size);
3720  td->data=(char*)malloc(size);
3721  assert(td->data);
3722  memmove(td->data, data, size);
3723  if (description)
3724  td->description=strdup(description);
3725  td->trustLevel=trustLevel;
3726  td->size=size;
3727  return td;
3728 }
3729 
3730 
3731 
3733  if (td) {
3734  free(td->data);
3735  free(td->description);
3736  free(td->replacement);
3737  GWEN_FREE_OBJECT(td);
3738  }
3739 }
3740 
3741 
3742 
3745  assert(td);
3746  return td->next;
3747 }
3748 
3749 
3750 
3751 const char*
3753  assert(td);
3754  return td->data;
3755 }
3756 
3757 
3758 
3759 unsigned int
3761  assert(td);
3762  return td->size;
3763 }
3764 
3765 
3766 
3767 const char*
3769  assert(td);
3770  return td->description;
3771 }
3772 
3773 
3774 
3777  assert(td);
3778  return td->trustLevel;
3779 }
3780 
3781 
3782 
3783 const char*
3785  assert(td);
3786  return td->replacement;
3787 }
3788 
3789 
3790 
3792  unsigned int pos){
3793  assert(td);
3794  if (td->posCount>=GWEN_MSGENGINE_TRUSTEDDATA_MAXPOS)
3795  return -1;
3796  td->positions[td->posCount++]=pos;
3797  return 0;
3798 }
3799 
3800 
3801 
3803  assert(td);
3804  td->posPointer=0;
3806 }
3807 
3808 
3809 
3811  assert(td);
3812  if (td->posPointer>=td->posCount)
3813  return -1;
3814  return td->positions[td->posPointer++];
3815 }
3816 
3817 
3818 
3819 int
3821  *td){
3822  unsigned int nextNr;
3824  unsigned int count;
3825 
3826  assert(td);
3827  count=0;
3828  ntd=td;
3829  while(ntd) {
3830  count++;
3831  ntd=ntd->next;
3832  }
3833 
3834  if (count<0x10)
3835  nextNr=0x01;
3836  else
3837  nextNr=0x11;
3838 
3839  ntd=td;
3840  while(ntd) {
3841  unsigned int i;
3842  char numbuffer[32];
3843  char *rp;
3845  int match;
3846 
3847  /* check whether the same data already exists */
3848  std=td;
3849  match=0;
3850  while(std && std!=ntd) {
3851 
3852  match=1;
3853  if (std->size==ntd->size) {
3854  for (i=0; i<td->size; i++) {
3855  if (std->data[i]!=ntd->data[i]) {
3856  match=0;
3857  break;
3858  }
3859  } /* for */
3860  }
3861  else
3862  match=0;
3863 
3864  if (match)
3865  break;
3866  std=std->next;
3867  } /* while */
3868 
3869  if (match) {
3870  /* copy the found match */
3871  rp=strdup(std->replacement);
3872  }
3873  else {
3874  /* this is a new one */
3875  rp=(char*)malloc(ntd->size+1);
3876  assert(rp);
3877 
3878  if (ntd->size==1) {
3879  if (count>=0x10)
3880  nextNr+=0x10;
3881  }
3882  sprintf(numbuffer, "%02X", nextNr++);
3883  for (i=0; i<ntd->size; i++) {
3884  if (count<0x10)
3885  rp[i]=numbuffer[1];
3886  else
3887  rp[i]=numbuffer[1-(i&1)];
3888  } /* for */
3889  rp[i]=0;
3890  }
3891  /*
3892  DBG_DEBUG(GWEN_LOGDOMAIN, "Replacement: \"%s\" for \"%s\" (%d)", rp,
3893  ntd->description,
3894  ntd->size);
3895  */
3896  free(ntd->replacement);
3897  ntd->replacement=rp;
3898 
3899  ntd=ntd->next;
3900  } /* while */
3901  return 0;
3902 }
3903 
3904 
3905 
3908 
3909  assert(e);
3910  td=e->trustInfos;
3911  e->trustInfos=0;
3912  return td;
3913 }
3914 
3915 
3916 
3917 
3919  const char *data,
3920  unsigned int size,
3921  const char *description,
3922  GWEN_MSGENGINE_TRUSTLEVEL trustLevel,
3923  unsigned int pos) {
3925  int match;
3926 
3927  assert(e);
3928  assert(data);
3929  assert(size);
3930 
3931  if (!description)
3932  description="";
3933 
3934  td=e->trustInfos;
3935  while(td) {
3936  unsigned int i;
3937 
3938  /* compare data */
3939  if (td->size==size &&
3940  *description &&
3941  *(td->description) &&
3942  trustLevel==td->trustLevel &&
3943  strcasecmp(description, td->description)==0) {
3944  match=1;
3945  for (i=0; i<td->size; i++) {
3946  if (td->data[i]!=data[i]) {
3947  match=0;
3948  break;
3949  }
3950  } /* for */
3951  }
3952  else
3953  match=0;
3954 
3955  if (match)
3956  break;
3957  td=td->next;
3958  } /* while */
3959 
3960  if (!td) {
3961  DBG_INFO(GWEN_LOGDOMAIN, "Creating new trustInfo for \"%s\" (%d)",
3962  description, size);
3964  size,
3965  description,
3966  trustLevel);
3967  GWEN_LIST_ADD(GWEN_MSGENGINE_TRUSTEDDATA, td, &(e->trustInfos));
3968  }
3969  else {
3970  DBG_INFO(GWEN_LOGDOMAIN, "Reusing trustInfo for \"%s\" (%d)",
3971  description, size);
3972  }
3974  return 0;
3975 }
3976 
3977 
3978