1 /***************************************************************************
2     begin       : Sat Apr 18 2018
3     copyright   : (C) 2020 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 
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29 
30 
31 
32 #include "xmlcmd_gxml_fromdb.h"
33 #include "xmlcmd_gxml.h"
34 
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/text.h>
37 #include <gwenhywfar/gwendate.h>
38 
39 
40 #include <ctype.h>
41 
42 
43 
44 
45 /* ------------------------------------------------------------------------------------------------
46  * forward declarations
47  * ------------------------------------------------------------------------------------------------
48  */
49 
50 static int _handleChildren_fromDb(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
51 
52 static int _dbEnter(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
53 static int _dbForEvery(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
54 static int _xmlCreateAndEnterElement(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
55 static int _xmlSetCharValue(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
56 static int _dbIfCharDataMatches(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
57 static int _dbIfNotCharDataMatches(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
58 static int _dbIfHasCharData(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
59 static int _dbIfNotHasCharData(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
60 static int _dbIfPathExists(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
61 static int _dbIfNotPathExists(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode);
62 
63 static int _setCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *value);
64 static int _convertAndSetCharValue(GWEN_XMLNODE *xmlDocNode, GWEN_XMLNODE *xmlSchemaNode, const char *value);
65 
66 
67 
68 
69 
70 /* ------------------------------------------------------------------------------------------------
71  * implementations
72  * ------------------------------------------------------------------------------------------------
73  */
74 
75 
GWEN_XmlCommanderGwenXml_fromDb_new(GWEN_XMLNODE * xmlNodeDestination,GWEN_DB_NODE * dbSource)76 GWEN_XMLCOMMANDER *GWEN_XmlCommanderGwenXml_fromDb_new(GWEN_XMLNODE *xmlNodeDestination,GWEN_DB_NODE *dbSource)
77 {
78   GWEN_XMLCOMMANDER *cmd;
79 
80   cmd=GWEN_XmlCommanderGwenXml_new(xmlNodeDestination, dbSource);
81   GWEN_XmlCommander_SetHandleChildrenFn(cmd, _handleChildren_fromDb);
82 
83   return cmd;
84 }
85 
86 
87 
88 
_handleChildren_fromDb(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)89 int _handleChildren_fromDb(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
90 {
91   GWEN_XMLNODE *n;
92 
93   n=GWEN_XMLNode_GetFirstTag(xmlNode);
94   while (n) {
95     const char *name;
96 
97     name=GWEN_XMLNode_GetData(n);
98     if (name && *name) {
99       int rv;
100 
101       DBG_INFO(GWEN_LOGDOMAIN, "Handling element \"%s\"", name);
102       if (strcasecmp(name, "DbEnter")==0)
103         rv=_dbEnter(cmd, n);
104       else if (strcasecmp(name, "DbForEvery")==0)
105         rv=_dbForEvery(cmd, n);
106       else if (strcasecmp(name, "XmlCreateAndEnterElement")==0)
107         rv=_xmlCreateAndEnterElement(cmd, n);
108       else if (strcasecmp(name, "XmlSetCharValue")==0)
109         rv=_xmlSetCharValue(cmd, n);
110       else if (strcasecmp(name, "DbIfCharDataMatches")==0)
111         rv=_dbIfCharDataMatches(cmd, n);
112       else if (strcasecmp(name, "DbIfNotCharDataMatches")==0)
113         rv=_dbIfNotCharDataMatches(cmd, n);
114       else if (strcasecmp(name, "DbIfHasCharData")==0)
115         rv=_dbIfHasCharData(cmd, n);
116       else if (strcasecmp(name, "DbIfNotHasCharData")==0)
117         rv=_dbIfNotHasCharData(cmd, n);
118       else if (strcasecmp(name, "DbIfPathExists")==0)
119         rv=_dbIfPathExists(cmd, n);
120       else if (strcasecmp(name, "DbIfNotPathExists")==0)
121         rv=_dbIfNotPathExists(cmd, n);
122       else {
123         DBG_ERROR(GWEN_LOGDOMAIN, "Unknown element \"%s\", aborting", name);
124         return GWEN_ERROR_INVALID;
125       }
126       if (rv<0) {
127         DBG_ERROR(GWEN_LOGDOMAIN, "Error in element \"%s\", aborting", name);
128         return rv;
129       }
130     }
131 
132     n=GWEN_XMLNode_GetNextTag(n);
133   }
134 
135   return 0;
136 }
137 
138 
139 
_dbIfPathExists(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)140 int _dbIfPathExists(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
141 {
142   const char *name;
143   GWEN_DB_NODE *dbNew;
144   int rv;
145 
146   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
147   if (!(name && *name)) {
148     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"DbIfPathExists\"");
149     return GWEN_ERROR_INVALID;
150   }
151 
152   dbNew=GWEN_DB_GetGroup(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), GWEN_PATH_FLAGS_NAMEMUSTEXIST, name);
153   if (dbNew) {
154     /* handle children (nothing special here) */
155     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
156 
157     if (rv<0) {
158       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
159       return rv;
160     }
161   }
162 
163   return 0;
164 }
165 
166 
167 
_dbIfNotPathExists(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)168 int _dbIfNotPathExists(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
169 {
170   const char *name;
171   GWEN_DB_NODE *dbNew;
172   int rv;
173 
174   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
175   if (!(name && *name)) {
176     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"DbIfPathExists\"");
177     return GWEN_ERROR_INVALID;
178   }
179 
180   dbNew=GWEN_DB_GetGroup(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), GWEN_PATH_FLAGS_NAMEMUSTEXIST, name);
181   if (dbNew==NULL) {
182     /* handle children (nothing special here) */
183     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
184 
185     if (rv<0) {
186       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
187       return rv;
188     }
189   }
190 
191   return 0;
192 }
193 
194 
195 
_dbEnter(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)196 int _dbEnter(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
197 {
198   const char *name;
199   GWEN_DB_NODE *dbLast;
200   GWEN_DB_NODE *dbNew;
201   int rv;
202 
203   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
204   if (!(name && *name)) {
205     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"DbEnter\"");
206     return GWEN_ERROR_INVALID;
207   }
208 
209   /* save group */
210   dbLast=GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd);
211 
212   dbNew=GWEN_DB_GetGroup(dbLast, GWEN_PATH_FLAGS_NAMEMUSTEXIST, name);
213   if (dbNew) {
214     /* push group */
215     GWEN_XmlCommanderGwenXml_SetCurrentDbGroup(cmd, dbNew);
216 
217     /* handle children (nothing special here) */
218     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
219 
220     /* pop group */
221     GWEN_XmlCommanderGwenXml_SetCurrentDbGroup(cmd, dbLast);
222 
223     if (rv<0) {
224       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
225       return rv;
226     }
227   }
228   else {
229     DBG_ERROR(GWEN_LOGDOMAIN, "Group \"%s\" does not exist", name);
230     return GWEN_ERROR_INVALID;
231   }
232 
233   return 0;
234 }
235 
236 
237 
_dbForEvery(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)238 int _dbForEvery(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
239 {
240   const char *name;
241   GWEN_DB_NODE *dbLast;
242   GWEN_DB_NODE *dbNew;
243   int rv;
244 
245   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
246   if (!(name && *name)) {
247     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"DbEnter\"");
248     return GWEN_ERROR_INVALID;
249   }
250 
251   /* save group */
252   dbLast=GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd);
253 
254   dbNew=GWEN_DB_FindFirstGroup(dbLast, name);
255   while (dbNew) {
256     /* push group */
257     GWEN_XmlCommanderGwenXml_SetCurrentDbGroup(cmd, dbNew);
258 
259     /* handle children (nothing special here) */
260     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
261 
262     /* pop group */
263     GWEN_XmlCommanderGwenXml_SetCurrentDbGroup(cmd, dbLast);
264 
265     if (rv<0) {
266       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
267       return rv;
268     }
269     dbNew=GWEN_DB_FindNextGroup(dbNew, name);
270   }
271 
272   return 0;
273 }
274 
275 
276 
_dbIfCharDataMatches(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)277 int _dbIfCharDataMatches(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
278 {
279   const char *name;
280   const char *pattern;
281   const char *val;
282 
283   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
284   if (!(name && *name)) {
285     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"dbIfCharDataMatches\"");
286     return GWEN_ERROR_INVALID;
287   }
288 
289   pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
290   if (!(pattern && *pattern)) {
291     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"dbIfCharDataMatches\"");
292     return GWEN_ERROR_INVALID;
293   }
294 
295   val=GWEN_DB_GetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), name, 0, NULL);
296   if (val && -1!=GWEN_Text_ComparePattern(val, pattern, 0)) {
297     int rv;
298 
299     /* pattern matches, handle children  */
300     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
301     if (rv<0) {
302       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
303       return rv;
304     }
305   }
306 
307   return 0;
308 }
309 
310 
311 
_dbIfNotCharDataMatches(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)312 int _dbIfNotCharDataMatches(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
313 {
314   const char *name;
315   const char *pattern;
316   const char *val;
317 
318   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
319   if (!(name && *name)) {
320     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"dbIfCharDataMatches\"");
321     return GWEN_ERROR_INVALID;
322   }
323 
324   pattern=GWEN_XMLNode_GetProperty(xmlNode, "pattern", NULL);
325   if (!(pattern && *pattern)) {
326     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty pattern in \"dbIfCharDataMatches\"");
327     return GWEN_ERROR_INVALID;
328   }
329 
330   val=GWEN_DB_GetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), name, 0, NULL);
331   if (val==NULL || -1==GWEN_Text_ComparePattern(val, pattern, 0)) {
332     int rv;
333 
334     /* pattern matches, handle children  */
335     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
336     if (rv<0) {
337       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
338       return rv;
339     }
340   }
341 
342   return 0;
343 }
344 
345 
346 
_dbIfHasCharData(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)347 int _dbIfHasCharData(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
348 {
349   const char *name;
350   const char *val;
351 
352   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
353   if (!(name && *name)) {
354     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"dbIfHasCharData\"");
355     return GWEN_ERROR_INVALID;
356   }
357 
358   val=GWEN_DB_GetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), name, 0, NULL);
359   if (val && *val) {
360     int rv;
361 
362     /* pattern matches, handle children  */
363     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
364     if (rv<0) {
365       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
366       return rv;
367     }
368   }
369 
370   return 0;
371 }
372 
373 
374 
_dbIfNotHasCharData(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)375 int _dbIfNotHasCharData(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
376 {
377   const char *name;
378   const char *val;
379 
380   name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
381   if (!(name && *name)) {
382     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty name in \"dbIfNotHasCharData\"");
383     return GWEN_ERROR_INVALID;
384   }
385 
386   val=GWEN_DB_GetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), name, 0, NULL);
387   if (val==NULL || *val==0) {
388     int rv;
389 
390     /* pattern matches, handle children  */
391     rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
392     if (rv<0) {
393       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
394       return rv;
395     }
396   }
397 
398   return 0;
399 }
400 
401 
402 
_xmlCreateAndEnterElement(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)403 int _xmlCreateAndEnterElement(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
404 {
405   const char *path;
406   GWEN_XMLNODE *n;
407   int rv;
408 
409   path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
410   if (path==NULL) {
411     DBG_ERROR(GWEN_LOGDOMAIN, "Missing path in \"XmlCreateAndEnterElement\"");
412     return GWEN_ERROR_INVALID;
413   }
414 
415   n=GWEN_XMLNode_GetNodeByXPath(GWEN_XmlCommanderGwenXml_GetCurrentDocNode(cmd),
416                                 path, GWEN_PATH_FLAGS_CREATE_GROUP | GWEN_PATH_FLAGS_CREATE_VAR);
417   if (n==NULL) {
418     DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" does not exist", path);
419     return GWEN_ERROR_INVALID;
420   }
421 
422   /* enter given document node */
423   GWEN_XmlCommanderGwenXml_EnterDocNode(cmd, n);
424 
425   rv=GWEN_XmlCommander_HandleChildren(cmd, xmlNode);
426   if (rv<0) {
427     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
428     return rv;
429   }
430 
431   /* leave given document node, re-select previously active one, thus restoring status from the beginning */
432   GWEN_XmlCommanderGwenXml_LeaveDocNode(cmd);
433   return 0;
434 }
435 
436 
437 
_xmlSetCharValue(GWEN_XMLCOMMANDER * cmd,GWEN_XMLNODE * xmlNode)438 int _xmlSetCharValue(GWEN_XMLCOMMANDER *cmd, GWEN_XMLNODE *xmlNode)
439 {
440   const char *path;
441   const char *value;
442 
443   path=GWEN_XMLNode_GetProperty(xmlNode, "path", NULL);
444   if (!(path && *path)) {
445     DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"XmlSetCharValue\"");
446     return GWEN_ERROR_INVALID;
447   }
448 
449   value=GWEN_XMLNode_GetProperty(xmlNode, "value", NULL);
450   if (value) {
451     GWEN_BUFFER *dbuf;
452     int rv;
453 
454     dbuf=GWEN_Buffer_new(0, 256, 0, 1);
455     rv=GWEN_DB_ReplaceVars(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), value, dbuf);
456     if (rv<0) {
457       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
458       GWEN_Buffer_free(dbuf);
459       return rv;
460     }
461     _convertAndSetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDocNode(cmd), xmlNode, GWEN_Buffer_GetStart(dbuf));
462     GWEN_Buffer_free(dbuf);
463   }
464   else {
465     const char *name;
466 
467     name=GWEN_XMLNode_GetProperty(xmlNode, "name", NULL);
468     if (!(name && *name)) {
469       DBG_ERROR(GWEN_LOGDOMAIN, "Missing or name path in \"XmlSetCharValue\"");
470       return GWEN_ERROR_INVALID;
471     }
472 
473     value=GWEN_DB_GetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDbGroup(cmd), name, 0, NULL);
474     if (value && *value) {
475       _convertAndSetCharValue(GWEN_XmlCommanderGwenXml_GetCurrentDocNode(cmd), xmlNode, value);
476     }
477 #if 0
478     else {
479       GWEN_BUFFER *tbuf;
480 
481       tbuf=GWEN_Buffer_new(0, 256, 0, 1);
482 
483       GWEN_XMLNode_GetXPath(NULL, GWEN_XmlCommanderGwenXml_GetCurrentDocNode(cmd), tbuf);
484 
485       DBG_ERROR(GWEN_LOGDOMAIN, "No value in path \"%s\" (%s)", path, GWEN_Buffer_GetStart(tbuf));
486       GWEN_Buffer_free(tbuf);
487 
488       /* GWEN_XMLNode_Dump(GWEN_XmlCommanderGwenXml_GetCurrentDocNode(cmd), 2); */
489       return GWEN_ERROR_INVALID;
490     }
491 #endif
492   }
493 
494   return 0;
495 }
496 
497 
498 
_setCharValueByPath(GWEN_XMLNODE * xmlNode,const char * path,const char * value)499 int _setCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *value)
500 {
501   const char *s;
502 
503   s=strchr(path, '@');
504   if (s) {
505     int idx;
506     char *cpyOfPath;
507     char *property;
508     GWEN_XMLNODE *n;
509 
510 
511     idx=s-path;
512     cpyOfPath=strdup(path);
513     assert(cpyOfPath);
514     cpyOfPath[idx]=0;
515     property=cpyOfPath+idx+1;
516 
517     if (*cpyOfPath) {
518       n=GWEN_XMLNode_GetNodeByXPath(xmlNode, cpyOfPath, 0);
519     }
520     else
521       n=xmlNode;
522 
523     if (n) {
524       GWEN_XMLNode_SetProperty(n, property, value);
525       free(cpyOfPath);
526       return 0;
527     }
528     else {
529       DBG_ERROR(GWEN_LOGDOMAIN, "Path \"%s\" could not be created", path);
530       free(cpyOfPath);
531       return GWEN_ERROR_GENERIC;
532     }
533   }
534   else {
535     int rv;
536 
537     rv=GWEN_XMLNode_SetCharValueByPath(xmlNode, 0, path, value);
538     if (rv<0) {
539       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
540       return rv;
541     }
542     return 0;
543   }
544 }
545 
546 
547 
_convertAndSetCharValue(GWEN_XMLNODE * xmlDocNode,GWEN_XMLNODE * xmlSchemaNode,const char * value)548 int _convertAndSetCharValue(GWEN_XMLNODE *xmlDocNode, GWEN_XMLNODE *xmlSchemaNode, const char *value)
549 {
550   if (value && *value) {
551     const char *name;
552     const char *typ;
553     int doTrim=0;
554     GWEN_BUFFER *resultBuf;
555     int rv;
556 
557     doTrim=GWEN_XMLNode_GetIntProperty(xmlSchemaNode, "trim", 0);
558     resultBuf=GWEN_Buffer_new(0, 256, 0, 1);
559 
560     name=GWEN_XMLNode_GetProperty(xmlSchemaNode, "path", NULL);
561     if (!(name && *name)) {
562       DBG_ERROR(GWEN_LOGDOMAIN, "Missing or empty path in \"XmlSetCharValue\"");
563       GWEN_Buffer_free(resultBuf);
564       return GWEN_ERROR_INVALID;
565     }
566 
567     typ=GWEN_XMLNode_GetProperty(xmlSchemaNode, "type", "string");
568     if (!(typ && *typ)) {
569       DBG_ERROR(GWEN_LOGDOMAIN, "Empty type in \"XmlSetCharValue\"");
570       GWEN_Buffer_free(resultBuf);
571       return GWEN_ERROR_INVALID;
572     }
573 
574     if (strcasecmp(typ, "string")==0) {
575       /* escape */
576       GWEN_Text_EscapeXmlToBuffer(value, resultBuf);
577       if (doTrim)
578         GWEN_Text_CondenseBuffer(resultBuf);
579     }
580     else if (strcasecmp(typ, "date")==0) {
581       const char *tmpl;
582       GWEN_DATE *dt=NULL;
583 
584       tmpl=GWEN_XMLNode_GetProperty(xmlSchemaNode, "template", "YYYYMMDD");
585       if (!(tmpl && *tmpl)) {
586         DBG_ERROR(GWEN_LOGDOMAIN, "Empty template in \"SetCharValue\"");
587         GWEN_Buffer_free(resultBuf);
588         return GWEN_ERROR_INVALID;
589       }
590 
591       dt=GWEN_Date_fromString(value);
592       if (dt) {
593         GWEN_Date_toStringWithTemplate(dt, tmpl, resultBuf);
594         GWEN_Date_free(dt);
595       }
596       else {
597         DBG_ERROR(GWEN_LOGDOMAIN, "Invalid date string for [%s] (value=[%s], tmpl=[%s])", name, value, tmpl);
598       }
599     }
600 
601     if (GWEN_Buffer_GetUsedBytes(resultBuf)) {
602       DBG_INFO(GWEN_LOGDOMAIN, "Setting value: %s = %s", name, GWEN_Buffer_GetStart(resultBuf));
603 
604       rv=_setCharValueByPath(xmlDocNode, name, GWEN_Buffer_GetStart(resultBuf));
605       if (rv<0) {
606         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
607         GWEN_Buffer_free(resultBuf);
608         return rv;
609       }
610     }
611     else {
612       DBG_INFO(GWEN_LOGDOMAIN, "Not setting empty value for [%s]", name);
613     }
614     GWEN_Buffer_free(resultBuf);
615   }
616   return 0;
617 }
618 
619 
620 
621 
622