gwenhywfar  4.3.3
xml.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Sat Jun 28 2003
3  copyright : (C) 2003-2010 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 "xml_p.h"
32 #include "xmlctx_l.h"
33 #include "i18n_l.h"
34 
35 #include <gwenhywfar/debug.h>
36 #include <gwenhywfar/misc.h>
37 #include <gwenhywfar/text.h>
38 #include <gwenhywfar/path.h>
39 #include <gwenhywfar/fastbuffer.h>
40 #include <gwenhywfar/syncio_file.h>
41 #include <gwenhywfar/syncio_memory.h>
42 
43 #include <stdlib.h>
44 #include <assert.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <sys/types.h>
48 #ifdef HAVE_SYS_STAT_H
49 # include <sys/stat.h>
50 #endif
51 #ifdef HAVE_FCNTL_H
52 # include <fcntl.h>
53 #endif
54 #include <errno.h>
55 #ifdef HAVE_UNISTD_H
56 # include <unistd.h>
57 #endif
58 
59 
60 #define GWEN_XML_BUFFERSIZE 512
61 
62 
63 
64 GWEN_LIST_FUNCTIONS(GWEN_XMLNODE, GWEN_XMLNode)
66 
67 GWEN_LIST_FUNCTIONS(GWEN_XMLNODE_NAMESPACE, GWEN_XMLNode_NameSpace)
68 
69 
70 
71 
72 GWEN_XMLPROPERTY *GWEN_XMLProperty_new(const char *name, const char *value){
74 
76  if (name)
77  p->name=GWEN_Memory_strdup(name);
78  if (value)
79  p->value=GWEN_Memory_strdup(value);
80  return p;
81 }
82 
83 
84 
86  if (p) {
87  GWEN_Memory_dealloc(p->name);
88  GWEN_Memory_dealloc(p->value);
89  GWEN_Memory_dealloc(p->nameSpace);
91  }
92 }
93 
94 
95 
97  GWEN_XMLPROPERTY *pp;
98 
99  pp=GWEN_XMLProperty_new(p->name, p->value);
100  if (p->nameSpace)
101  pp->nameSpace=strdup(p->nameSpace);
102 
103  return pp;
104 }
105 
106 
107 
110 }
111 
112 
113 
116 }
117 
118 
121 }
122 
123 
125  while(p) {
126  GWEN_XMLPROPERTY *next;
127 
128  next=p->next;
130  p=next;
131  } /* while */
132 }
133 
134 
135 
136 
138  GWEN_XMLNODE *n;
139 
142  n->type=t;
143  n->children=GWEN_XMLNode_List_new();
144  n->headers=GWEN_XMLNode_List_new();
145  if (data)
146  n->data=GWEN_Memory_strdup(data);
147  n->nameSpaces=GWEN_XMLNode_NameSpace_List_new();
148  return n;
149 }
150 
151 
153  if (n) {
155  GWEN_XMLProperty_freeAll(n->properties);
156  GWEN_Memory_dealloc(n->nameSpace);
157  GWEN_Memory_dealloc(n->data);
158  GWEN_XMLNode_List_free(n->headers);
159  GWEN_XMLNode_List_free(n->children);
160  GWEN_XMLNode_NameSpace_List_free(n->nameSpaces);
161  GWEN_FREE_OBJECT(n);
162  }
163 }
164 
165 
167  while(n) {
168  GWEN_XMLNODE *next;
169 
170  next=GWEN_XMLNode_List_Next(n);
172  n=next;
173  } /* while */
174 }
175 
176 
178  GWEN_XMLNODE *nn, *cn, *ncn;
179  const GWEN_XMLPROPERTY *p;
180  const GWEN_XMLNODE_NAMESPACE *nns;
181 
182  /* duplicate node itself */
183  nn=GWEN_XMLNode_new(n->type, n->data);
184  if (n->nameSpace)
185  nn->nameSpace=strdup(n->nameSpace);
186 
187  /* duplicate properties */
188  p=n->properties;
189  while(p) {
190  GWEN_XMLPROPERTY *np;
191 
192  np=GWEN_XMLProperty_dup(p);
193  GWEN_XMLProperty_add(np, &(nn->properties));
194  p=p->next;
195  } /* while */
196 
197  /* duplicate children */
198  cn=GWEN_XMLNode_List_First(n->children);
199  while(cn) {
200  ncn=GWEN_XMLNode_dup(cn);
201  GWEN_XMLNode_AddChild(nn, ncn);
202  cn=GWEN_XMLNode_Next(cn);
203  } /* while */
204 
205  /* duplicate headers */
206  cn=GWEN_XMLNode_List_First(n->headers);
207  while(cn) {
208  ncn=GWEN_XMLNode_dup(cn);
209  GWEN_XMLNode_AddHeader(nn, ncn);
210  cn=GWEN_XMLNode_Next(cn);
211  } /* while */
212 
213  /* duplicate namespaces */
214  nns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
215  while(nns) {
217 
218  nnns=GWEN_XMLNode_NameSpace_dup(nns);
219  GWEN_XMLNode_NameSpace_List_Add(nnns, nn->nameSpaces);
220  nns=GWEN_XMLNode_NameSpace_List_Next(nns);
221  }
222 
223  return nn;
224 }
225 
226 
227 
228 const char *GWEN_XMLNode_GetProperty(const GWEN_XMLNODE *n, const char *name,
229  const char *defaultValue){
230  GWEN_XMLPROPERTY *p;
231 
232  assert(n);
233  assert(name);
234  p=n->properties;
235  while(p) {
236  assert(p->name);
237  if (strcasecmp(p->name, name)==0)
238  break;
239  p=p->next;
240  } /* while */
241 
242  if (p) {
243  if (p->value)
244  return p->value;
245  }
246  return defaultValue;
247 }
248 
249 
251  const char *name, const char *value,
252  int doInsert){
253  GWEN_XMLPROPERTY *p;
254 
255  p=n->properties;
256  while(p) {
257  assert(p->name);
258  if (strcasecmp(p->name, name)==0)
259  break;
260  p=p->next;
261  } /* while */
262 
263  if (p) {
264  GWEN_Memory_dealloc(p->value);
265  if (value)
266  p->value=GWEN_Memory_strdup(value);
267  else
268  p->value=0;
269  }
270  else {
271  p=GWEN_XMLProperty_new(name, value);
272  if (doInsert)
273  GWEN_XMLProperty_insert(p, &(n->properties));
274  else
275  GWEN_XMLProperty_add(p, &(n->properties));
276  }
277 }
278 
279 
280 
282  const char *name, const char *value){
283  GWEN_XMLNode__SetProperty(n, name, value, 0);
284 }
285 
286 
287 
289  assert(n);
290  n->usage++;
291 }
292 
293 
294 
296  assert(n);
297  if (n->usage==0) {
298  DBG_WARN(GWEN_LOGDOMAIN, "Node usage already is zero");
299  }
300  else
301  n->usage--;
302 }
303 
304 
305 
307  assert(n);
308  return n->usage;
309 }
310 
311 
312 
313 const char *GWEN_XMLNode_GetData(const GWEN_XMLNODE *n){
314  assert(n);
315  return n->data;
316 }
317 
318 
319 void GWEN_XMLNode_SetData(GWEN_XMLNODE *n, const char *data){
320  assert(n);
321  GWEN_Memory_dealloc(n->data);
322  if (data)
323  n->data=GWEN_Memory_strdup(data);
324  else
325  n->data=0;
326 }
327 
328 
329 
331  assert(n);
332  return n->nameSpace;
333 }
334 
335 
336 
337 void GWEN_XMLNode_SetNamespace(GWEN_XMLNODE *n, const char *s) {
338  assert(n);
339  GWEN_Memory_dealloc(n->nameSpace);
340  if (s)
341  n->nameSpace=GWEN_Memory_strdup(s);
342  else
343  n->nameSpace=NULL;
344 }
345 
346 
347 
349  assert(n);
350  return GWEN_XMLNode_List_First(n->children);
351 }
352 
353 
355  assert(n);
356  return n->parent;
357 }
358 
359 
361  assert(n);
362  GWEN_XMLNode_List_Add(child, n->children);
363  child->parent=n;
364 }
365 
366 
367 
369  int copythem){
370  GWEN_XMLNODE *ch;
371 
372  assert(n);
373  assert(nn);
374 
375  ch=GWEN_XMLNode_GetChild(nn);
376  while(ch) {
377  GWEN_XMLNODE *nc;
378 
379  nc=GWEN_XMLNode_Next(ch);
380  if (!copythem) {
381  GWEN_XMLNode_UnlinkChild(nn, ch);
382  GWEN_XMLNode_AddChild(n, ch);
383  }
384  else {
386  }
387  ch=nc;
388  } /* while */
389 }
390 
391 
392 
394  assert(n);
395  return n->type;
396 }
397 
398 
400  assert(n);
401  return GWEN_XMLNode_List_Next(n);
402 }
403 
404 
405 void GWEN_XMLNode_Dump(const GWEN_XMLNODE *n, int ind) {
406  GWEN_XMLPROPERTY *p;
407  GWEN_XMLNODE *c;
408  int i;
409  int simpleTag;
410 
411  assert(n);
412 
413  for(i=0; i<ind; i++)
414  fprintf(stderr, " ");
415 
416  simpleTag=0;
417  if (n->type==GWEN_XMLNodeTypeTag) {
418  if (n->data)
419  fprintf(stderr, "<%s", n->data);
420  else
421  fprintf(stderr, "<UNKNOWN");
422  p=n->properties;
423  while (p) {
424  if (p->value)
425  fprintf(stderr, " %s=\"%s\"", p->name, p->value);
426  else
427  fprintf(stderr, " %s", p->name);
428  p=p->next;
429  }
430 
431  if (n->data) {
432  if (n->data[0]=='?') {
433  simpleTag=1;
434  fprintf(stderr, "?");
435  }
436  else if (n->data[0]=='!') {
437  simpleTag=1;
438  }
439  }
440 
441  fprintf(stderr, ">\n");
442  if (!simpleTag) {
444  while(c) {
445  GWEN_XMLNode_Dump(c, ind+2);
446  c=GWEN_XMLNode_Next(c);
447  }
448  for(i=0; i<ind; i++)
449  fprintf(stderr, " ");
450  if (n->data)
451  fprintf(stderr, "</%s>\n", n->data);
452  else
453  fprintf(stderr, "</UNKNOWN>\n");
454  }
455  }
456  else if (n->type==GWEN_XMLNodeTypeData) {
457  if (n->data) {
458  fprintf(stderr, "%s\n", n->data);
459  }
460  }
461  else if (n->type==GWEN_XMLNodeTypeComment) {
462  fprintf(stderr, "<!--");
463  if (n->data) {
464  fprintf(stderr, "%s", n->data);
465  }
466  fprintf(stderr, "-->\n");
467  }
468  else {
469  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown tag type (%d)", n->type);
470  }
471 }
472 
473 
474 
476  GWEN_XMLNODE_TYPE t, const char *data) {
477  GWEN_XMLNODE *n;
478 
479  assert(node);
480  assert(data);
481 
482  n=GWEN_XMLNode_GetChild(node);
483  while(n) {
484  if (n->type==t)
485  if (n->data)
486  if (strcasecmp(n->data, data)==0)
487  break;
488  n=GWEN_XMLNode_Next(n);
489  } /* while */
490 
491  if (!n) {
492  DBG_DEBUG(GWEN_LOGDOMAIN, "Node %d:\"%s\" not found", t, data);
493  return 0;
494  }
495 
496  return n;
497 }
498 
499 
500 
502  assert(n);
503  assert(child);
504  GWEN_XMLNode_List_Del(child);
505  child->parent=0;
506 }
507 
508 
509 
511  assert(n);
512  GWEN_XMLNode_List_Clear(n->children);
513 }
514 
515 
516 
518  const GWEN_XMLNODE *sn,
519  int overwrite){
520  const GWEN_XMLPROPERTY *sp;
521  GWEN_XMLPROPERTY *tp;
522 
523  assert(tn);
524  assert(sn);
525 
526  sp=sn->properties;
527  while(sp) {
528  GWEN_XMLPROPERTY *np;
529 
530  assert(sp->name);
531  tp=tn->properties;
532  /* lookup property in target */
533  while(tp) {
534 
535  assert(tp->name);
536  if (strcasecmp(tp->name, sp->name)==0) {
537  /* property already exists */
538  if (overwrite) {
539  /* overwrite old property */
540  GWEN_Memory_dealloc(tp->value);
541  tp->value=0;
542  if (sp->value)
543  tp->value=GWEN_Memory_strdup(sp->value);
544  }
545  break;
546  }
547  tp=tp->next;
548  } /* while */
549 
550  if (!tp) {
551  /* property not found, simply copy and add it */
552  np=GWEN_XMLProperty_dup(sp);
553  GWEN_XMLProperty_add(np, &(tn->properties));
554  }
555 
556  sp=sp->next;
557  } /* while */
558 }
559 
560 
561 
564  GWEN_XMLNODE *nn;
565 
566  assert(n);
567  nn=GWEN_XMLNode_GetChild(n);
568  while(nn) {
569  if (nn->type==t)
570  return nn;
571  nn=GWEN_XMLNode_Next(nn);
572  } /* while */
573  return 0;
574 }
575 
576 
577 
580  assert(n);
581  while(n) {
582  if (n->type==t)
583  return (GWEN_XMLNODE *)n;
584  n=GWEN_XMLNode_Next(n);
585  } /* while */
586  return 0;
587 }
588 
589 
590 
593 }
594 
595 
596 
598  GWEN_XMLNODE *next;
599 
600  next=GWEN_XMLNode_Next(n);
601  if (!next)
602  return 0;
604 }
605 
606 
607 
610 }
611 
612 
613 
615  GWEN_XMLNODE *next;
616 
617  next=GWEN_XMLNode_Next(n);
618  if (!next)
619  return 0;
621 }
622 
623 
624 
626  const char *tname,
627  const char *pname,
628  const char *pvalue){
629  while(n) {
630  if (-1!=GWEN_Text_ComparePattern(n->data, tname, 0)) {
631  if (pname) {
632  const char *p;
633 
634  p=GWEN_XMLNode_GetProperty(n, pname, 0);
635  if (p) {
636  if (!pvalue)
637  return (GWEN_XMLNODE*)n;
638  if (-1!=GWEN_Text_ComparePattern(pvalue, p, 0))
639  return (GWEN_XMLNODE*)n;
640  }
641  else {
642  /* return this node if pvalue is 0 an the property does not exist */
643  if (!pvalue)
644  return (GWEN_XMLNODE*)n;
645  }
646  } /* if pname */
647  else
648  return (GWEN_XMLNODE*)n;
649  }
651  } /* while */
652  return 0;
653 }
654 
655 
656 
658  const char *tname,
659  const char *pname,
660  const char *pvalue){
661  GWEN_XMLNODE *nn;
662 
664  if (!nn)
665  return 0;
666  return GWEN_XMLNode_FindTag(nn,
667  tname,
668  pname,
669  pvalue);
670 }
671 
672 
673 
675  const char *tname,
676  const char *pname,
677  const char *pvalue){
678  GWEN_XMLNODE *nn;
679 
681  if (!nn)
682  return 0;
683  return GWEN_XMLNode_FindTag(nn,
684  tname,
685  pname,
686  pvalue);
687 }
688 
689 
690 
692  const char *name,
693  const char *defValue) {
694  GWEN_XMLNODE *nn;
695 
696  nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
697  while(nn) {
698  GWEN_XMLNODE *dn;
699 
701  if (dn) {
702  if (dn->data)
703  return dn->data;
704  }
705  nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
706  }
707 
708  return defValue;
709 }
710 
711 
712 
714  const char *name,
715  const char *defValue) {
716  GWEN_XMLNODE *nn=0;
717  GWEN_STRINGLIST *langl;
718 
720  if (langl) {
722 
723  se=GWEN_StringList_FirstEntry(langl);
724  while(se) {
725  const char *l;
726 
728  DBG_DEBUG(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
729  assert(l);
730  nn=GWEN_XMLNode_FindFirstTag(n, name, "lang", l);
731  while(nn) {
732  GWEN_XMLNODE *dn;
733 
735  if (dn) {
736  if (dn->data && *(dn->data))
737  return dn->data;
738  }
739  nn=GWEN_XMLNode_FindNextTag(nn, name, "lang", l);
740  } /* while nn */
742  } /* while */
743  } /* if language list available */
744 
745  /* otherwise try without locale */
746  nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
747  while(nn) {
748  GWEN_XMLNODE *dn;
749 
751  if (dn) {
752  if (dn->data)
753  return dn->data;
754  }
755  nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
756  }
757 
758  return defValue;
759 }
760 
761 
762 
764  const char *name,
765  const char *value){
766  GWEN_XMLNODE *nn;
767 
769  if (value) {
770  GWEN_XMLNODE *nnn;
771 
773  GWEN_XMLNode_AddChild(nn, nnn);
774  }
775  GWEN_XMLNode_AddChild(n, nn);
776 }
777 
778 
779 
781  const char *name,
782  int defValue) {
783  const char *p;
784  int res;
785 
786  p=GWEN_XMLNode_GetCharValue(n, name, 0);
787  if (!p)
788  return defValue;
789  if (1!=sscanf(p, "%i", &res))
790  return defValue;
791  return res;
792 }
793 
794 
795 
797  const char *name,
798  int value){
799  char numbuf[32];
800 
801  snprintf(numbuf, sizeof(numbuf)-1, "%d", value);
802  numbuf[sizeof(numbuf)-1]=0;
803  GWEN_XMLNode_SetCharValue(n, name, numbuf);
804 }
805 
806 
807 
809  assert(n);
810  return n->properties;
811 }
812 
813 
814 
816  const GWEN_XMLPROPERTY *pr){
817  assert(n);
818  assert(pr);
819  return pr->next;
820 }
821 
822 
823 
825  assert(pr);
826  return pr->name;
827 }
828 
829 
830 
832  assert(pr);
833  return pr->value;
834 }
835 
836 
837 
839  const GWEN_XMLNODE *child) {
840  GWEN_XMLNODE *n;
841 
842  if (!child || !parent || child==parent)
843  return 0;
844  n=child->parent;
845  while(n) {
846  if (n==parent)
847  return 1;
848  n=n->parent;
849  }
850  return 0;
851 }
852 
853 
854 
856  const GWEN_XMLNODE *n2,
857  GWEN_BUFFER *nbuf) {
858  GWEN_BUFFER *lbuf;
859  const GWEN_XMLNODE *ln1;
860  const GWEN_XMLNODE *ln2;
861 
862  if (!n1 && !n2) {
863  DBG_ERROR(GWEN_LOGDOMAIN, "Both nodes are NULL");
864  return -1;
865  }
866 
867  if (!n1) {
868  n1=n2;
869  while(n1->parent)
870  n1=n1->parent;
871  }
872 
873  if (!n2) {
874  n2=n1;
875  while(n2->parent)
876  n2=n2->parent;
877  }
878 
879  if (n2==n1) {
880  GWEN_Buffer_AppendString(nbuf, "here()");
881  return 0;
882  }
883 
884  lbuf=GWEN_Buffer_new(0, 256, 0, 1);
885  GWEN_Buffer_ReserveBytes(lbuf, 128);
886 
887  ln1=n1->parent;
888  if (ln1) {
889  GWEN_Buffer_AppendString(lbuf, "../");
890  while(ln1) {
891  if (ln1==n2) {
892  /* found n2 */
893  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
894  GWEN_Buffer_free(lbuf);
895  return 0;
896  }
897  if (GWEN_XMLNode_IsChildOf(ln1, n2))
898  break;
899  ln1=ln1->parent;
900  GWEN_Buffer_AppendString(lbuf, "../");
901  }
902 
903  if (!ln1) {
904  DBG_ERROR(GWEN_LOGDOMAIN, "Nodes do not share root node");
905  GWEN_Buffer_free(lbuf);
906  return -1;
907  }
908 
909  /* append path to n1 */
910  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
911  }
912  DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
913 
914  /* get path to n2 */
915  GWEN_Buffer_Reset(lbuf);
916 
917  ln2=n2;
918  while(ln2) {
919  GWEN_XMLNODE *tn;
920  int idx;
921  char idxbuf[32];
922 
923  if (ln2->parent==ln1)
924  break;
925 
926  /* count occurences of this tag in this level */
927  idx=1;
928  tn=ln2->parent;
929  if (tn) {
930  tn=GWEN_XMLNode_FindFirstTag(tn, ln2->data, 0, 0);
931 
932  while(tn) {
933  if (tn==ln2)
934  break;
935  idx++;
936  tn=GWEN_XMLNode_FindNextTag(tn, ln2->data, 0, 0);
937  }
938  }
939 
940  snprintf(idxbuf, sizeof(idxbuf), "[%d]", idx);
941  idxbuf[sizeof(idxbuf)-1]=0;
942  GWEN_Buffer_InsertString(lbuf, idxbuf);
944  GWEN_Buffer_InsertByte(lbuf, '/');
945  ln2=ln2->parent;
946  }
947  DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
948  assert(ln2);
949 
950  /* append path to n2 */
951  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
952  GWEN_Buffer_free(lbuf);
953  return 0;
954 }
955 
956 
957 
958 void* GWEN_XMLNode_HandlePath(const char *entry,
959  void *data,
960  int idx,
961  uint32_t flags) {
962  GWEN_XMLNODE *n;
963  GWEN_XMLNODE *nn;
964  int i;
965 
966  n=(GWEN_XMLNODE*)data;
967 
968  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
970  "GWEN_PATH_FLAGS_VARIABLE not allowed for XPATH");
971  return 0;
972  }
973 
974  if (flags & GWEN_PATH_FLAGS_ROOT) {
975  while(n->parent)
976  n=n->parent;
977  if (*entry=='/')
978  entry++;
979  }
980 
981  if (strcasecmp(entry, "..")==0) {
982  return n->parent;
983  }
984  else if (strcasecmp(entry, ".")==0 ||
985  strcasecmp(entry, "here()")==0) {
986  return n;
987  }
988 
989  /* check whether we are allowed to simply create the node */
990  if (
991  ((flags & GWEN_PATH_FLAGS_LAST) &&
992  (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
993  (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
994  (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
995  (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
996  ) ||
997  (
998  !(flags & GWEN_PATH_FLAGS_LAST) &&
999  (flags & GWEN_PATH_FLAGS_PATHCREATE))
1000  ) {
1001  /* simply create the new variable/group */
1002  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
1003  /* not allowed for now */
1004  return 0;
1005  }
1006  else {
1007  if (idx!=0) {
1009  "Can not create tag with index!=1 (%s)", entry);
1010  return 0;
1011  }
1013  "Unconditionally creating tag \"%s\"", entry);
1015  GWEN_XMLNode_AddChild(n, nn);
1016  return nn;
1017  }
1018  }
1019 
1020  /* find the node */
1021  i=idx;
1022  nn=GWEN_XMLNode_FindFirstTag(n, entry, 0, 0);
1023  while(nn && i--) {
1024  nn=GWEN_XMLNode_FindNextTag(nn, entry, 0, 0);
1025  }
1026 
1027  if (!nn) {
1028  /* node not found, check, if we are allowed to create it */
1029  if (
1030  (!(flags & GWEN_PATH_FLAGS_LAST) &&
1031  (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
1033  ) {
1035  "Tag \"%s\" does not exist", entry);
1036  return 0;
1037  }
1038  /* create the new variable/group */
1039  if (idx!=0) {
1041  "Can not create tag with index!=1 (%s)", entry);
1042  return 0;
1043  }
1045  "Tag \"%s\" not found, creating", entry);
1047  GWEN_XMLNode_AddChild(n, nn);
1048  } /* if node not found */
1049  else {
1050  /* node does exist, check whether this is ok */
1051  if (
1052  ((flags & GWEN_PATH_FLAGS_LAST) &&
1053  (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST)) ||
1054  (!(flags & GWEN_PATH_FLAGS_LAST) &&
1056  ) {
1057  DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
1058  return 0;
1059  }
1060  }
1061 
1062  return nn;
1063 }
1064 
1065 
1066 
1068  const char *path,
1069  uint32_t flags){
1070  return (GWEN_XMLNODE*)GWEN_Path_HandleWithIdx(path,
1071  (void*)n,
1072  flags,
1074 }
1075 
1076 
1077 
1079  assert(n);
1080  return GWEN_XMLNode_List_First(n->headers);
1081 }
1082 
1083 
1084 
1086  assert(n);
1087  assert(nh);
1088  GWEN_XMLNode_List_Add(nh, n->headers);
1089 }
1090 
1091 
1092 
1094  assert(n);
1095  assert(nh);
1096  GWEN_XMLNode_List_Del(nh);
1097 }
1098 
1099 
1100 
1102  assert(n);
1103  GWEN_XMLNode_List_Clear(n->headers);
1104 }
1105 
1106 
1107 
1108 GWEN_XMLNODE_NAMESPACE_LIST *GWEN_XMLNode_GetNameSpaces(const GWEN_XMLNODE *n) {
1109  assert(n);
1110  return n->nameSpaces;
1111 }
1112 
1113 
1114 
1116  const char *s) {
1118 
1119  assert(n);
1120  ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
1121  while(ns) {
1122  const char *d;
1123 
1125  if (d && strcasecmp(d, s)==0)
1126  return ns;
1127  ns=GWEN_XMLNode_NameSpace_List_Next(ns);
1128  }
1129 
1130  return NULL;
1131 }
1132 
1133 
1134 
1136  const char *s) {
1138 
1139  assert(n);
1140  ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
1141  while(ns) {
1142  const char *d;
1143 
1145  if (d && strcasecmp(d, s)==0)
1146  return ns;
1147  ns=GWEN_XMLNode_NameSpace_List_Next(ns);
1148  }
1149 
1150  return NULL;
1151 }
1152 
1153 
1154 
1156  assert(n);
1157  assert(ns);
1158  GWEN_XMLNode_NameSpace_List_Add(GWEN_XMLNode_NameSpace_dup(ns), n->nameSpaces);
1159 }
1160 
1161 
1162 
1163 
1164 
1165 
1166 
1167 
1168 
1169 
1170 
1172  const char *prefix,
1173  const char *name){
1174  GWEN_BUFFER *nbuf;
1175  int rv;
1176 
1177  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1178  if (prefix)
1179  GWEN_Buffer_AppendString(nbuf, prefix);
1180  GWEN_Buffer_AppendByte(nbuf, ':');
1181  GWEN_Buffer_AppendString(nbuf, name);
1184  GWEN_Buffer_free(nbuf);
1185  return rv;
1186 }
1187 
1188 
1189 
1191  const char *s){
1193 
1194  it=GWEN_StringList2_First(sl);
1195  if (it) {
1196  const char *t;
1197 
1199  assert(t);
1200  while(t) {
1201  const char *p;
1202 
1203  p=strchr(t, ':');
1204  assert(p);
1205  if ((s==0 && p==t) || (s && strncasecmp(t, s, p-t)==0))
1206  return t;
1208  } /* while */
1210  }
1211  return 0;
1212 }
1213 
1214 
1215 
1217  const char *s){
1219 
1220  it=GWEN_StringList2_First(sl);
1221  if (it) {
1222  const char *t;
1223 
1225  assert(t);
1226  while(t) {
1227  const char *p;
1228 
1229  p=strchr(t, ':');
1230  assert(p);
1231  p++;
1232  if (strcasecmp(p, s)==0) {
1234  return t;
1235  }
1237  } /* while */
1239  }
1240  return 0;
1241 }
1242 
1243 
1244 
1246  const char *prefix,
1247  const char *name){
1248  GWEN_BUFFER *nbuf;
1250 
1251  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1252  if (prefix)
1253  GWEN_Buffer_AppendString(nbuf, prefix);
1254  GWEN_Buffer_AppendByte(nbuf, ':');
1255  GWEN_Buffer_AppendString(nbuf, name);
1256 
1257  it=GWEN_StringList2_First(sl);
1258  if (it) {
1259  const char *t;
1260 
1262  assert(t);
1263  while(t) {
1264  const char *p;
1265 
1266  p=strchr(t, ':');
1267  assert(p);
1268  p++;
1269  if (strcasecmp(p, GWEN_Buffer_GetStart(nbuf))==0) {
1271  GWEN_Buffer_free(nbuf);
1272  return t;
1273  }
1275  } /* while */
1277  }
1278 
1279  GWEN_Buffer_free(nbuf);
1280  return 0;
1281 }
1282 
1283 
1284 
1286  GWEN_STRINGLIST2 *sl,
1287  const char *currentNameSpace) {
1288  GWEN_XMLPROPERTY *pr;
1289  GWEN_XMLNODE *nn;
1290  char *localNameSpace;
1291 
1292  localNameSpace=0;
1293 
1294  /* remove all unnecessary namespace declarations from this node */
1295  pr=n->properties;
1296  while(pr) {
1297  GWEN_XMLPROPERTY *prNext;
1298 
1299  prNext=pr->next;
1300  if (strcasecmp(pr->name, "xmlns")==0) {
1301  /* default namespace changed ? */
1302  if (localNameSpace) {
1303  if (strcasecmp(pr->value, localNameSpace)==0) {
1304  /* already mentioned name space, remove duplicate property */
1305  GWEN_XMLProperty_del(pr, &n->properties);
1307  }
1308  else {
1309  /* current namespace changed */
1310  GWEN_Memory_dealloc(localNameSpace);
1311  localNameSpace=GWEN_Memory_strdup(pr->value);
1312  }
1313  }
1314  else if (currentNameSpace) {
1315  if (strcasecmp(pr->value, currentNameSpace)==0) {
1316  /* already active name space, remove property */
1317  GWEN_XMLProperty_del(pr, &n->properties);
1319  }
1320  else {
1321  /* current namespace changed */
1322  GWEN_Memory_dealloc(localNameSpace);
1323  localNameSpace=GWEN_Memory_strdup(pr->value);
1324  }
1325  }
1326  else {
1327  /* set current namespace */
1328  GWEN_Memory_dealloc(localNameSpace);
1329  localNameSpace=GWEN_Memory_strdup(pr->value);
1330  }
1331  }
1332  else if (strncasecmp(pr->name, "xmlns:", 6)==0) {
1333  const char *prefix;
1334  const char *x;
1335 
1336  prefix=strchr(pr->name, ':');
1337  prefix++;
1338 
1339  /* check for redefinition */
1340  x=GWEN_XML_FindNameSpaceByName(sl, prefix);
1341  if (x) {
1342  const char *p;
1343 
1344  /* prefix already in use, check whether it is the same namespace */
1345  p=strchr(x, ':');
1346  assert(p);
1347  p++;
1348  if (strcasecmp(p, pr->value)!=0) {
1349  GWEN_BUFFER *xpath;
1350 
1351  /* same prefix, different namespace */
1352  xpath=GWEN_Buffer_new(0, 256, 0, 1);
1353  GWEN_XMLNode_GetXPath(0, n, xpath);
1355  "Redefinition of namespace prefix \"%s\" in \"%s\"",
1356  prefix, GWEN_Buffer_GetStart(xpath));
1357  GWEN_Buffer_free(xpath);
1358  return -1;
1359  } /* if different namespace for same prefix */
1360  else {
1361  /* already in list, remove property here */
1362  GWEN_XMLProperty_del(pr, &n->properties);
1364  }
1365  }
1366  else {
1367  GWEN_XML_AddNameSpace(sl, prefix, pr->value);
1368  }
1369  }
1370  pr=prNext;
1371  } /* while */
1372 
1373  /* do the same on all sub nodes */
1375  while(nn) {
1376  int rv;
1377 
1379  localNameSpace?localNameSpace:
1380  currentNameSpace);
1381  if (rv) {
1382  GWEN_Memory_dealloc(localNameSpace);
1383  return rv;
1384  }
1385  nn=GWEN_XMLNode_GetNextTag(nn);
1386  }
1387 
1388  GWEN_Memory_dealloc(localNameSpace);
1389  return 0;
1390 }
1391 
1392 
1393 
1395  const char *prefix,
1396  const char *nspace) {
1397  GWEN_XMLPROPERTY *pr;
1398  const char *p;
1399  int inUse;
1400 
1401  inUse=0;
1402  /* check current tag for prefix */
1403  if (prefix) {
1404  p=strchr(n->data, ':');
1405  if (p) {
1406  if (strncasecmp(n->data, prefix, p-n->data)==0) {
1407  DBG_DEBUG(GWEN_LOGDOMAIN, "Prefix \"%s\" used in tag \"%s\"",
1408  prefix, n->data);
1409  inUse=1;
1410  }
1411  }
1412 
1413  if (!inUse) {
1414  /* check all attributes for prefixes */
1415  pr=n->properties;
1416  while(pr) {
1417  p=strchr(pr->name, ':');
1418  if (p) {
1419  if (strncasecmp(pr->name, prefix, p-pr->name)==0) {
1421  "Prefix \"%s\" used in attribute \"%s\" of tag \"%s\"",
1422  prefix, pr->name, n->data);
1423  inUse=1;
1424  break;
1425  }
1426  else {
1428  "Prefix \"%s\" not used in attribute \"%s\" of tag \"%s\"",
1429  prefix, pr->name, n->data);
1430  }
1431  }
1432  pr=pr->next;
1433  } /* while */
1434  }
1435  } /* if prefix */
1436  else {
1437  /* no prefix, check whether the current element hasn't any */
1438  p=strchr(n->data, ':');
1439  if (!p) {
1440  /* current tag has no prefix, check whether we have a namespace
1441  * declaration here */
1442  if (GWEN_XMLNode_GetProperty(n, "xmlns", 0)==0) {
1443  /* no, so the current namespace from above is used */
1445  "No prefix, current namespace is used");
1446  inUse=1;
1447  }
1448  }
1449  } /* if no prefix */
1450 
1451  if (inUse) {
1452  GWEN_BUFFER *nbuf;
1453 
1454  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1455  GWEN_Buffer_AppendString(nbuf, "xmlns");
1456  if (prefix) {
1457  GWEN_Buffer_AppendByte(nbuf, ':');
1458  GWEN_Buffer_AppendString(nbuf, prefix);
1459  }
1460  GWEN_XMLNode__SetProperty(n, GWEN_Buffer_GetStart(nbuf), nspace, 1);
1461  GWEN_Buffer_free(nbuf);
1462  return 1;
1463  }
1464 
1465  return 0;
1466 }
1467 
1468 
1469 
1471  const char *prefix,
1472  const char *nspace) {
1473  GWEN_XMLNODE *nn;
1474  int rv;
1475 
1476  rv=GWEN_XMLNode__CheckAndSetNameSpace(n, prefix, nspace);
1477  if (rv)
1478  return rv;
1479 
1481  while(nn) {
1482  rv=GWEN_XMLNode__CheckAndSetNameSpace(nn, prefix, nspace);
1483  if (rv==-1)
1484  return rv;
1485  else if (rv==0) {
1486  /* check children */
1487  rv=GWEN_XMLNode__SetNameSpaces(nn, prefix, nspace);
1488  if (rv)
1489  return rv;
1490  }
1491 
1492  nn=GWEN_XMLNode_GetNextTag(nn);
1493  }
1494 
1495  return 0;
1496 }
1497 
1498 
1499 
1501  GWEN_XMLPROPERTY *pr;
1502  GWEN_XMLNODE *nn;
1503  int rv;
1504 
1505  /* move all namespace declarations from this node to the nodes
1506  * of first use */
1507  pr=n->properties;
1508  while(pr) {
1509  GWEN_XMLPROPERTY *prNext;
1510 
1511  prNext=pr->next;
1512  if (strcasecmp(pr->name, "xmlns")==0 ||
1513  strncasecmp(pr->name, "xmlns:", 6)==0) {
1514  const char *prefix;
1515 
1516  prefix=strchr(pr->name, ':');
1517  if (prefix)
1518  prefix++;
1519 
1520  GWEN_XMLProperty_del(pr, &n->properties);
1521  rv=GWEN_XMLNode__SetNameSpaces(n, prefix, pr->value);
1522  DBG_DEBUG(GWEN_LOGDOMAIN, "Removing property \"%s\"",
1523  pr->name);
1525  if (rv==-1)
1526  return rv;
1527  }
1528  pr=prNext;
1529  } /* while */
1530 
1531  /* do the same on all sub nodes */
1533  while(nn) {
1535  if (rv) {
1536  return rv;
1537  }
1538  nn=GWEN_XMLNode_GetNextTag(nn);
1539  }
1540 
1541  return 0;
1542 }
1543 
1544 
1545 
1546 
1548  const char *ns;
1549  int rv;
1550  GWEN_STRINGLIST2 *sl;
1551 
1552  ns=GWEN_XMLNode_GetProperty(n, "xmlns", 0);
1553  sl=GWEN_StringList2_new();
1554  rv=GWEN_XMLNode__CheckNameSpaceDecls1(n, sl, ns);
1556  if (rv) {
1557  DBG_INFO(GWEN_LOGDOMAIN, "here");
1558  return rv;
1559  }
1560 
1561  //rv=GWEN_XMLNode__CheckNameSpaceDecls2(n, ns);
1563  if (rv==-1)
1564  return rv;
1565  return 0;
1566 }
1567 
1568 
1569 
1571  if (n && n->type==GWEN_XMLNodeTypeTag && n->data) {
1572  GWEN_XMLNODE *nn;
1573  GWEN_XMLPROPERTY *pp;
1574 
1575  if (n->nameSpace==0) {
1576  char *p;
1577 
1578  p=strchr(n->data, ':');
1579  if (p) {
1580  int len=p-n->data;
1581  char *s;
1582 
1583  n->nameSpace=(char*)GWEN_Memory_malloc(len);
1584  assert(n->nameSpace);
1585  memmove(n->nameSpace, n->data, len);
1586  n->nameSpace[len-1]=0;
1587  s=GWEN_Memory_strdup(p+1);
1588  free(n->data);
1589  n->data=s;
1590  }
1591  }
1592 
1593  pp=n->properties;
1594  while(pp) {
1595  if (pp->nameSpace==0) {
1596  char *p;
1597 
1598  p=strchr(pp->name, ':');
1599  if (p) {
1600  int len=p-pp->name;
1601  char *s;
1602 
1603  pp->nameSpace=(char*)GWEN_Memory_malloc(len);
1604  assert(pp->nameSpace);
1605  memmove(pp->nameSpace, pp->name, len);
1606  pp->nameSpace[len-1]=0;
1607  s=GWEN_Memory_strdup(p+1);
1608  free(pp->name);
1609  pp->name=s;
1610  }
1611  }
1612 
1613  pp=pp->next;
1614  }
1615 
1616  nn=GWEN_XMLNode_List_First(n->children);
1617  while(nn) {
1618  int rv;
1619 
1621  if (rv<0) {
1622  DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d)", rv);
1623  return rv;
1624  }
1625  nn=GWEN_XMLNode_List_Next(nn);
1626  }
1627  }
1628 
1629  return 0;
1630 }
1631 
1632 
1633 
1634 
1635 
1636 
1637 
1638 
1639 
1641  GWEN_XMLNODE_PATH *p;
1642 
1644  return p;
1645 }
1646 
1647 
1648 
1650  GWEN_XMLNODE_PATH *p;
1651  unsigned int i;
1652 
1654  p->pos=np->pos;
1655  for (i=0; i<np->pos; i++) {
1656  p->nodes[i]=np->nodes[i];
1657  }
1658  return p;
1659 }
1660 
1661 
1662 
1664  GWEN_FREE_OBJECT(np);
1665 }
1666 
1667 
1668 
1670  GWEN_XMLNODE *n){
1671  unsigned int i;
1672 
1673  if (np->pos>=GWEN_XML_MAX_DEPTH) {
1674  DBG_ERROR(GWEN_LOGDOMAIN, "Path too deep");
1675  return 1;
1676  }
1677 
1678  /* check for double entries */
1679  for (i=0; i<np->pos; i++) {
1680  assert(np->nodes[i]!=n);
1681  }
1682  np->nodes[np->pos++]=n;
1683  DBG_DEBUG(GWEN_LOGDOMAIN, "Dived to %d", np->pos);
1684  return 0;
1685 }
1686 
1687 
1688 
1690  if (np->pos==0) {
1691  DBG_DEBUG(GWEN_LOGDOMAIN, "Root reached");
1692  return 0;
1693  }
1694  DBG_DEBUG(GWEN_LOGDOMAIN, "Surfaced to %d", np->pos-1);
1695  return np->nodes[--np->pos];
1696 }
1697 
1698 
1699 
1701  unsigned int i;
1702 
1703  if (np->pos==0) {
1704  DBG_NOTICE(GWEN_LOGDOMAIN, "Empty path");
1705  }
1706  for (i=0; i<np->pos; i++) {
1707  DBG_NOTICE(GWEN_LOGDOMAIN, "Path entry %d:", i);
1708  GWEN_XMLNode_Dump(np->nodes[i], 1);
1709  }
1710 }
1711 
1712 
1713 
1714 
1715 
1716 
1717 
1718 
1719 
1720 
1721 
1723  const char *url) {
1725 
1728 
1729  if (name)
1730  ns->name=GWEN_Memory_strdup(name);
1731  if (url)
1732  ns->url=GWEN_Memory_strdup(url);
1733 
1734  return ns;
1735 }
1736 
1737 
1738 
1740  if (ns) {
1742  free(ns->url);
1743  free(ns->name);
1744  GWEN_FREE_OBJECT(ns);
1745  }
1746 }
1747 
1748 
1749 
1752 
1753  assert(ns);
1754  nns=GWEN_XMLNode_NameSpace_new(ns->name, ns->url);
1755  return nns;
1756 }
1757 
1758 
1759 
1761  assert(ns);
1762  return ns->name;
1763 }
1764 
1765 
1766 
1768  assert(ns);
1769  return ns->url;
1770 }
1771 
1772 
1773 
1774 
1775 
1776 
1777 #include "xmlrw.c"
1778 #include "xmlglobalize.c"
1779 
1780 
1781