gwenhywfar  4.8.0beta
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 
250 
251 int GWEN_XMLNode_GetIntProperty(const GWEN_XMLNODE *n, const char *name,
252  int defaultValue){
253  GWEN_XMLPROPERTY *p;
254 
255  assert(n);
256  assert(name);
257  p=n->properties;
258  while(p) {
259  assert(p->name);
260  if (strcasecmp(p->name, name)==0)
261  break;
262  p=p->next;
263  } /* while */
264 
265  if (p) {
266  if (p->value) {
267  int i;
268 
269  if (1==sscanf(p->value, "%i", &i))
270  return i;
271  }
272  }
273  return defaultValue;
274 }
275 
276 
278  const char *name, const char *value,
279  int doInsert){
280  GWEN_XMLPROPERTY *p;
281 
282  p=n->properties;
283  while(p) {
284  assert(p->name);
285  if (strcasecmp(p->name, name)==0)
286  break;
287  p=p->next;
288  } /* while */
289 
290  if (p) {
291  GWEN_Memory_dealloc(p->value);
292  if (value)
293  p->value=GWEN_Memory_strdup(value);
294  else
295  p->value=0;
296  }
297  else {
298  p=GWEN_XMLProperty_new(name, value);
299  if (doInsert)
300  GWEN_XMLProperty_insert(p, &(n->properties));
301  else
302  GWEN_XMLProperty_add(p, &(n->properties));
303  }
304 }
305 
306 
307 
309  const char *name, const char *value){
310  GWEN_XMLNode__SetProperty(n, name, value, 0);
311 }
312 
313 
314 
316  const char *name, int value){
317  char numbuf[256];
318 
319  snprintf(numbuf, sizeof(numbuf)-1, "%i", value);
320  numbuf[sizeof(numbuf)-1]=0;
321  GWEN_XMLNode__SetProperty(n, name, numbuf, 0);
322 }
323 
324 
325 
327  assert(n);
328  n->usage++;
329 }
330 
331 
332 
334  assert(n);
335  if (n->usage==0) {
336  DBG_WARN(GWEN_LOGDOMAIN, "Node usage already is zero");
337  }
338  else
339  n->usage--;
340 }
341 
342 
343 
345  assert(n);
346  return n->usage;
347 }
348 
349 
350 
351 const char *GWEN_XMLNode_GetData(const GWEN_XMLNODE *n){
352  assert(n);
353  return n->data;
354 }
355 
356 
357 void GWEN_XMLNode_SetData(GWEN_XMLNODE *n, const char *data){
358  assert(n);
359  GWEN_Memory_dealloc(n->data);
360  if (data)
361  n->data=GWEN_Memory_strdup(data);
362  else
363  n->data=0;
364 }
365 
366 
367 
369  assert(n);
370  return n->nameSpace;
371 }
372 
373 
374 
375 void GWEN_XMLNode_SetNamespace(GWEN_XMLNODE *n, const char *s) {
376  assert(n);
377  GWEN_Memory_dealloc(n->nameSpace);
378  if (s)
379  n->nameSpace=GWEN_Memory_strdup(s);
380  else
381  n->nameSpace=NULL;
382 }
383 
384 
385 
387  assert(n);
388  return GWEN_XMLNode_List_First(n->children);
389 }
390 
391 
393  assert(n);
394  return n->parent;
395 }
396 
397 
399  assert(n);
400  GWEN_XMLNode_List_Add(child, n->children);
401  child->parent=n;
402 }
403 
404 
405 
407  int copythem){
408  GWEN_XMLNODE *ch;
409 
410  assert(n);
411  assert(nn);
412 
413  ch=GWEN_XMLNode_GetChild(nn);
414  while(ch) {
415  GWEN_XMLNODE *nc;
416 
417  nc=GWEN_XMLNode_Next(ch);
418  if (!copythem) {
419  GWEN_XMLNode_UnlinkChild(nn, ch);
420  GWEN_XMLNode_AddChild(n, ch);
421  }
422  else {
424  }
425  ch=nc;
426  } /* while */
427 }
428 
429 
430 
432  assert(n);
433  return n->type;
434 }
435 
436 
438  assert(n);
439  return GWEN_XMLNode_List_Next(n);
440 }
441 
442 
443 void GWEN_XMLNode_Dump(const GWEN_XMLNODE *n, int ind) {
444  GWEN_XMLPROPERTY *p;
445  GWEN_XMLNODE *c;
446  int i;
447  int simpleTag;
448 
449  assert(n);
450 
451  for(i=0; i<ind; i++)
452  fprintf(stderr, " ");
453 
454  simpleTag=0;
455  if (n->type==GWEN_XMLNodeTypeTag) {
456  if (n->data)
457  fprintf(stderr, "<%s", n->data);
458  else
459  fprintf(stderr, "<UNKNOWN");
460  p=n->properties;
461  while (p) {
462  if (p->value)
463  fprintf(stderr, " %s=\"%s\"", p->name, p->value);
464  else
465  fprintf(stderr, " %s", p->name);
466  p=p->next;
467  }
468 
469  if (n->data) {
470  if (n->data[0]=='?') {
471  simpleTag=1;
472  fprintf(stderr, "?");
473  }
474  else if (n->data[0]=='!') {
475  simpleTag=1;
476  }
477  }
478 
479  fprintf(stderr, ">\n");
480  if (!simpleTag) {
482  while(c) {
483  GWEN_XMLNode_Dump(c, ind+2);
484  c=GWEN_XMLNode_Next(c);
485  }
486  for(i=0; i<ind; i++)
487  fprintf(stderr, " ");
488  if (n->data)
489  fprintf(stderr, "</%s>\n", n->data);
490  else
491  fprintf(stderr, "</UNKNOWN>\n");
492  }
493  }
494  else if (n->type==GWEN_XMLNodeTypeData) {
495  if (n->data) {
496  fprintf(stderr, "%s\n", n->data);
497  }
498  }
499  else if (n->type==GWEN_XMLNodeTypeComment) {
500  fprintf(stderr, "<!--");
501  if (n->data) {
502  fprintf(stderr, "%s", n->data);
503  }
504  fprintf(stderr, "-->\n");
505  }
506  else {
507  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown tag type (%d)", n->type);
508  }
509 }
510 
511 
512 
514  GWEN_XMLNODE_TYPE t, const char *data) {
515  GWEN_XMLNODE *n;
516 
517  assert(node);
518  assert(data);
519 
520  n=GWEN_XMLNode_GetChild(node);
521  while(n) {
522  if (n->type==t)
523  if (n->data)
524  if (strcasecmp(n->data, data)==0)
525  break;
526  n=GWEN_XMLNode_Next(n);
527  } /* while */
528 
529  if (!n) {
530  DBG_DEBUG(GWEN_LOGDOMAIN, "Node %d:\"%s\" not found", t, data);
531  return 0;
532  }
533 
534  return n;
535 }
536 
537 
538 
540  assert(n);
541  assert(child);
542  GWEN_XMLNode_List_Del(child);
543  child->parent=0;
544 }
545 
546 
547 
549  assert(n);
550  GWEN_XMLNode_List_Clear(n->children);
551 }
552 
553 
554 
556  const GWEN_XMLNODE *sn,
557  int overwrite){
558  const GWEN_XMLPROPERTY *sp;
559  GWEN_XMLPROPERTY *tp;
560 
561  assert(tn);
562  assert(sn);
563 
564  sp=sn->properties;
565  while(sp) {
566  GWEN_XMLPROPERTY *np;
567 
568  assert(sp->name);
569  tp=tn->properties;
570  /* lookup property in target */
571  while(tp) {
572 
573  assert(tp->name);
574  if (strcasecmp(tp->name, sp->name)==0) {
575  /* property already exists */
576  if (overwrite) {
577  /* overwrite old property */
578  GWEN_Memory_dealloc(tp->value);
579  tp->value=0;
580  if (sp->value)
581  tp->value=GWEN_Memory_strdup(sp->value);
582  }
583  break;
584  }
585  tp=tp->next;
586  } /* while */
587 
588  if (!tp) {
589  /* property not found, simply copy and add it */
590  np=GWEN_XMLProperty_dup(sp);
591  GWEN_XMLProperty_add(np, &(tn->properties));
592  }
593 
594  sp=sp->next;
595  } /* while */
596 }
597 
598 
599 
602  GWEN_XMLNODE *nn;
603 
604  assert(n);
605  nn=GWEN_XMLNode_GetChild(n);
606  while(nn) {
607  if (nn->type==t)
608  return nn;
609  nn=GWEN_XMLNode_Next(nn);
610  } /* while */
611  return 0;
612 }
613 
614 
615 
618  assert(n);
619  while(n) {
620  if (n->type==t)
621  return (GWEN_XMLNODE *)n;
622  n=GWEN_XMLNode_Next(n);
623  } /* while */
624  return 0;
625 }
626 
627 
628 
631 }
632 
633 
634 
636  GWEN_XMLNODE *next;
637 
638  next=GWEN_XMLNode_Next(n);
639  if (!next)
640  return 0;
642 }
643 
644 
645 
648 }
649 
650 
651 
653  GWEN_XMLNODE *next;
654 
655  next=GWEN_XMLNode_Next(n);
656  if (!next)
657  return 0;
659 }
660 
661 
662 
664  const char *tname,
665  const char *pname,
666  const char *pvalue){
667  while(n) {
668  if (-1!=GWEN_Text_ComparePattern(n->data, tname, 0)) {
669  if (pname) {
670  const char *p;
671 
672  p=GWEN_XMLNode_GetProperty(n, pname, 0);
673  if (p) {
674  if (!pvalue)
675  return (GWEN_XMLNODE*)n;
676  if (-1!=GWEN_Text_ComparePattern(pvalue, p, 0))
677  return (GWEN_XMLNODE*)n;
678  }
679  else {
680  /* return this node if pvalue is 0 an the property does not exist */
681  if (!pvalue)
682  return (GWEN_XMLNODE*)n;
683  }
684  } /* if pname */
685  else
686  return (GWEN_XMLNODE*)n;
687  }
689  } /* while */
690  return 0;
691 }
692 
693 
694 
696  const char *tname,
697  const char *pname,
698  const char *pvalue){
699  GWEN_XMLNODE *nn;
700 
702  if (!nn)
703  return 0;
704  return GWEN_XMLNode_FindTag(nn,
705  tname,
706  pname,
707  pvalue);
708 }
709 
710 
711 
713  const char *tname,
714  const char *pname,
715  const char *pvalue){
716  GWEN_XMLNODE *nn;
717 
719  if (!nn)
720  return 0;
721  return GWEN_XMLNode_FindTag(nn,
722  tname,
723  pname,
724  pvalue);
725 }
726 
727 
728 
730  const char *name,
731  const char *defValue) {
732  GWEN_XMLNODE *nn;
733 
734  nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
735  while(nn) {
736  GWEN_XMLNODE *dn;
737 
739  if (dn) {
740  if (dn->data)
741  return dn->data;
742  }
743  nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
744  }
745 
746  return defValue;
747 }
748 
749 
750 
752  const char *name,
753  const char *defValue) {
754  GWEN_XMLNODE *nn=0;
755  GWEN_STRINGLIST *langl;
756 
758  if (langl) {
760 
761  se=GWEN_StringList_FirstEntry(langl);
762  while(se) {
763  const char *l;
764 
766  DBG_DEBUG(GWEN_LOGDOMAIN, "Trying locale \"%s\"", l);
767  assert(l);
768  nn=GWEN_XMLNode_FindFirstTag(n, name, "lang", l);
769  while(nn) {
770  GWEN_XMLNODE *dn;
771 
773  if (dn) {
774  if (dn->data && *(dn->data))
775  return dn->data;
776  }
777  nn=GWEN_XMLNode_FindNextTag(nn, name, "lang", l);
778  } /* while nn */
780  } /* while */
781  } /* if language list available */
782 
783  /* otherwise try without locale */
784  nn=GWEN_XMLNode_FindFirstTag(n, name, 0, 0);
785  while(nn) {
786  GWEN_XMLNODE *dn;
787 
789  if (dn) {
790  if (dn->data)
791  return dn->data;
792  }
793  nn=GWEN_XMLNode_FindNextTag(nn, name, 0, 0);
794  }
795 
796  return defValue;
797 }
798 
799 
800 
802  const char *name,
803  const char *value){
804  GWEN_XMLNODE *nn;
805 
807  if (value) {
808  GWEN_XMLNODE *nnn;
809 
811  GWEN_XMLNode_AddChild(nn, nnn);
812  }
813  GWEN_XMLNode_AddChild(n, nn);
814 }
815 
816 
817 
819  const char *name,
820  int defValue) {
821  const char *p;
822  int res;
823 
824  p=GWEN_XMLNode_GetCharValue(n, name, 0);
825  if (!p)
826  return defValue;
827  if (1!=sscanf(p, "%i", &res))
828  return defValue;
829  return res;
830 }
831 
832 
833 
835  const char *name,
836  int value){
837  char numbuf[32];
838 
839  snprintf(numbuf, sizeof(numbuf)-1, "%d", value);
840  numbuf[sizeof(numbuf)-1]=0;
841  GWEN_XMLNode_SetCharValue(n, name, numbuf);
842 }
843 
844 
845 
847  const char *name,
848  const char *value){
849  GWEN_XMLNODE *nn;
850 
851  nn=GWEN_XMLNode_GetNodeByXPath(n, name, 0);
852  if (nn) {
853  GWEN_XMLNODE *nnn;
854 
855  /* clear current entries */
857  GWEN_XMLNode_List_Clear(nn->children);
858 
859  /* create value node */
861  GWEN_XMLNode_AddChild(nn, nnn);
862 
863  return 0;
864  }
865  else {
866  DBG_ERROR(GWEN_LOGDOMAIN, "Unable to create node [%s]", name);
867  return GWEN_ERROR_INVALID;
868  }
869 }
870 
871 
872 
874  const char *name,
875  const char *defValue){
876  GWEN_XMLNODE *nn;
877 
878  nn=GWEN_XMLNode_GetNodeByXPath(n, name, 0);
879  if (nn) {
880  GWEN_XMLNODE *dn;
881 
883  if (dn) {
884  if (dn->data)
885  return dn->data;
886  }
887  }
888 
889  return defValue;
890 }
891 
892 
893 
895  const char *name,
896  int value){
897  char numbuf[32];
898  int rv;
899 
900  /* create int value */
901  snprintf(numbuf, sizeof(numbuf)-1, "%d", value);
902  numbuf[sizeof(numbuf)-1]=0;
903 
904  rv=GWEN_XMLNode_SetCharValueByPath(n, flags, name, numbuf);
905  if (rv<0) {
906  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
907  return rv;
908  }
909 
910  return rv;
911 }
912 
913 
914 
916  const char *name,
917  int defValue) {
918  const char *p;
919  int res;
920 
922  if (!p)
923  return defValue;
924  if (1!=sscanf(p, "%i", &res))
925  return defValue;
926  return res;
927 }
928 
929 
930 
931 
932 
933 
935  assert(n);
936  return n->properties;
937 }
938 
939 
940 
942  const GWEN_XMLPROPERTY *pr){
943  assert(n);
944  assert(pr);
945  return pr->next;
946 }
947 
948 
949 
951  assert(pr);
952  return pr->name;
953 }
954 
955 
956 
958  assert(pr);
959  return pr->value;
960 }
961 
962 
963 
965  const GWEN_XMLNODE *child) {
966  GWEN_XMLNODE *n;
967 
968  if (!child || !parent || child==parent)
969  return 0;
970  n=child->parent;
971  while(n) {
972  if (n==parent)
973  return 1;
974  n=n->parent;
975  }
976  return 0;
977 }
978 
979 
980 
982  const GWEN_XMLNODE *n2,
983  GWEN_BUFFER *nbuf) {
984  GWEN_BUFFER *lbuf;
985  const GWEN_XMLNODE *ln1;
986  const GWEN_XMLNODE *ln2;
987 
988  if (!n1 && !n2) {
989  DBG_ERROR(GWEN_LOGDOMAIN, "Both nodes are NULL");
990  return -1;
991  }
992 
993  if (!n1) {
994  n1=n2;
995  while(n1->parent)
996  n1=n1->parent;
997  }
998 
999  if (!n2) {
1000  n2=n1;
1001  while(n2->parent)
1002  n2=n2->parent;
1003  }
1004 
1005  if (n2==n1) {
1006  GWEN_Buffer_AppendString(nbuf, "here()");
1007  return 0;
1008  }
1009 
1010  lbuf=GWEN_Buffer_new(0, 256, 0, 1);
1011  GWEN_Buffer_ReserveBytes(lbuf, 128);
1012 
1013  ln1=n1->parent;
1014  if (ln1) {
1015  GWEN_Buffer_AppendString(lbuf, "../");
1016  while(ln1) {
1017  if (ln1==n2) {
1018  /* found n2 */
1019  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
1020  GWEN_Buffer_free(lbuf);
1021  return 0;
1022  }
1023  if (GWEN_XMLNode_IsChildOf(ln1, n2))
1024  break;
1025  ln1=ln1->parent;
1026  GWEN_Buffer_AppendString(lbuf, "../");
1027  }
1028 
1029  if (!ln1) {
1030  DBG_ERROR(GWEN_LOGDOMAIN, "Nodes do not share root node");
1031  GWEN_Buffer_free(lbuf);
1032  return -1;
1033  }
1034 
1035  /* append path to n1 */
1036  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
1037  }
1038  DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
1039 
1040  /* get path to n2 */
1041  GWEN_Buffer_Reset(lbuf);
1042 
1043  ln2=n2;
1044  while(ln2) {
1045  GWEN_XMLNODE *tn;
1046  int idx;
1047  char idxbuf[32];
1048 
1049  if (ln2->parent==ln1)
1050  break;
1051 
1052  /* count occurences of this tag in this level */
1053  idx=1;
1054  tn=ln2->parent;
1055  if (tn) {
1056  tn=GWEN_XMLNode_FindFirstTag(tn, ln2->data, 0, 0);
1057 
1058  while(tn) {
1059  if (tn==ln2)
1060  break;
1061  idx++;
1062  tn=GWEN_XMLNode_FindNextTag(tn, ln2->data, 0, 0);
1063  }
1064  }
1065 
1066  snprintf(idxbuf, sizeof(idxbuf), "[%d]", idx);
1067  idxbuf[sizeof(idxbuf)-1]=0;
1068  GWEN_Buffer_InsertString(lbuf, idxbuf);
1070  GWEN_Buffer_InsertByte(lbuf, '/');
1071  ln2=ln2->parent;
1072  }
1073  DBG_ERROR(GWEN_LOGDOMAIN, "Path so far: %s", GWEN_Buffer_GetStart(lbuf));
1074  assert(ln2);
1075 
1076  /* append path to n2 */
1077  GWEN_Buffer_AppendBuffer(nbuf, lbuf);
1078  GWEN_Buffer_free(lbuf);
1079  return 0;
1080 }
1081 
1082 
1083 
1084 void* GWEN_XMLNode_HandlePath(const char *entry,
1085  void *data,
1086  int idx,
1087  uint32_t flags) {
1088  GWEN_XMLNODE *n;
1089  GWEN_XMLNODE *nn;
1090  int i;
1091 
1092  n=(GWEN_XMLNODE*)data;
1093 
1094  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
1096  "GWEN_PATH_FLAGS_VARIABLE not allowed for XPATH");
1097  return 0;
1098  }
1099 
1100  if (flags & GWEN_PATH_FLAGS_ROOT) {
1101  while(n->parent)
1102  n=n->parent;
1103  if (*entry=='/')
1104  entry++;
1105  }
1106 
1107  if (strcasecmp(entry, "..")==0) {
1108  return n->parent;
1109  }
1110  else if (strcasecmp(entry, ".")==0 ||
1111  strcasecmp(entry, "here()")==0) {
1112  return n;
1113  }
1114 
1115  /* check whether we are allowed to simply create the node */
1116  if (
1117  ((flags & GWEN_PATH_FLAGS_LAST) &&
1118  (((flags & GWEN_PATH_FLAGS_VARIABLE) &&
1119  (flags & GWEN_PATH_FLAGS_CREATE_VAR)) ||
1120  (!(flags & GWEN_PATH_FLAGS_VARIABLE) &&
1121  (flags & GWEN_PATH_FLAGS_CREATE_GROUP)))
1122  ) ||
1123  (
1124  !(flags & GWEN_PATH_FLAGS_LAST) &&
1125  (flags & GWEN_PATH_FLAGS_PATHCREATE))
1126  ) {
1127  /* simply create the new variable/group */
1128  if (flags & GWEN_PATH_FLAGS_VARIABLE) {
1129  /* not allowed for now */
1130  return 0;
1131  }
1132  else {
1133  if (idx!=0) {
1135  "Can not create tag with index!=1 (%s)", entry);
1136  return 0;
1137  }
1139  "Unconditionally creating tag \"%s\"", entry);
1141  GWEN_XMLNode_AddChild(n, nn);
1142  return nn;
1143  }
1144  }
1145 
1146  /* find the node */
1147  i=idx;
1148  nn=GWEN_XMLNode_FindFirstTag(n, entry, 0, 0);
1149  while(nn && i--) {
1150  nn=GWEN_XMLNode_FindNextTag(nn, entry, 0, 0);
1151  }
1152 
1153  if (!nn) {
1154  /* node not found, check, if we are allowed to create it */
1155  if (
1156  (!(flags & GWEN_PATH_FLAGS_LAST) &&
1157  (flags & GWEN_PATH_FLAGS_PATHMUSTEXIST)) ||
1159  ) {
1161  "Tag \"%s\" does not exist", entry);
1162  return 0;
1163  }
1164  /* create the new variable/group */
1165  if (idx!=0) {
1167  "Can not create tag with index!=1 (%s)", entry);
1168  return 0;
1169  }
1171  "Tag \"%s\" not found, creating", entry);
1173  GWEN_XMLNode_AddChild(n, nn);
1174  } /* if node not found */
1175  else {
1176  /* node does exist, check whether this is ok */
1177  if (
1178  ((flags & GWEN_PATH_FLAGS_LAST) &&
1179  (flags & GWEN_PATH_FLAGS_NAMEMUSTNOTEXIST)) ||
1180  (!(flags & GWEN_PATH_FLAGS_LAST) &&
1182  ) {
1183  DBG_VERBOUS(GWEN_LOGDOMAIN, "Entry \"%s\" already exists", entry);
1184  return 0;
1185  }
1186  }
1187 
1188  return nn;
1189 }
1190 
1191 
1192 
1194  const char *path,
1195  uint32_t flags){
1196  return (GWEN_XMLNODE*)GWEN_Path_HandleWithIdx(path,
1197  (void*)n,
1198  flags,
1200 }
1201 
1202 
1203 
1205  assert(n);
1206  return GWEN_XMLNode_List_First(n->headers);
1207 }
1208 
1209 
1210 
1212  assert(n);
1213  assert(nh);
1214  GWEN_XMLNode_List_Add(nh, n->headers);
1215 }
1216 
1217 
1218 
1220  assert(n);
1221  assert(nh);
1222  GWEN_XMLNode_List_Del(nh);
1223 }
1224 
1225 
1226 
1228  assert(n);
1229  GWEN_XMLNode_List_Clear(n->headers);
1230 }
1231 
1232 
1233 
1234 GWEN_XMLNODE_NAMESPACE_LIST *GWEN_XMLNode_GetNameSpaces(const GWEN_XMLNODE *n) {
1235  assert(n);
1236  return n->nameSpaces;
1237 }
1238 
1239 
1240 
1242  const char *s) {
1244 
1245  assert(n);
1246  ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
1247  while(ns) {
1248  const char *d;
1249 
1251  if (d && strcasecmp(d, s)==0)
1252  return ns;
1253  ns=GWEN_XMLNode_NameSpace_List_Next(ns);
1254  }
1255 
1256  return NULL;
1257 }
1258 
1259 
1260 
1262  const char *s) {
1264 
1265  assert(n);
1266  ns=GWEN_XMLNode_NameSpace_List_First(n->nameSpaces);
1267  while(ns) {
1268  const char *d;
1269 
1271  if (d && strcasecmp(d, s)==0)
1272  return ns;
1273  ns=GWEN_XMLNode_NameSpace_List_Next(ns);
1274  }
1275 
1276  return NULL;
1277 }
1278 
1279 
1280 
1282  assert(n);
1283  assert(ns);
1284  GWEN_XMLNode_NameSpace_List_Add(GWEN_XMLNode_NameSpace_dup(ns), n->nameSpaces);
1285 }
1286 
1287 
1288 
1289 
1290 
1291 
1292 
1293 
1294 
1295 
1296 
1298  const char *prefix,
1299  const char *name){
1300  GWEN_BUFFER *nbuf;
1301  int rv;
1302 
1303  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1304  if (prefix)
1305  GWEN_Buffer_AppendString(nbuf, prefix);
1306  GWEN_Buffer_AppendByte(nbuf, ':');
1307  GWEN_Buffer_AppendString(nbuf, name);
1310  GWEN_Buffer_free(nbuf);
1311  return rv;
1312 }
1313 
1314 
1315 
1317  const char *s){
1319 
1320  it=GWEN_StringList2_First(sl);
1321  if (it) {
1322  const char *t;
1323 
1325  assert(t);
1326  while(t) {
1327  const char *p;
1328 
1329  p=strchr(t, ':');
1330  assert(p);
1331  if ((s==0 && p==t) || (s && strncasecmp(t, s, p-t)==0))
1332  return t;
1334  } /* while */
1336  }
1337  return 0;
1338 }
1339 
1340 
1341 
1343  const char *s){
1345 
1346  it=GWEN_StringList2_First(sl);
1347  if (it) {
1348  const char *t;
1349 
1351  assert(t);
1352  while(t) {
1353  const char *p;
1354 
1355  p=strchr(t, ':');
1356  assert(p);
1357  p++;
1358  if (strcasecmp(p, s)==0) {
1360  return t;
1361  }
1363  } /* while */
1365  }
1366  return 0;
1367 }
1368 
1369 
1370 
1372  const char *prefix,
1373  const char *name){
1374  GWEN_BUFFER *nbuf;
1376 
1377  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1378  if (prefix)
1379  GWEN_Buffer_AppendString(nbuf, prefix);
1380  GWEN_Buffer_AppendByte(nbuf, ':');
1381  GWEN_Buffer_AppendString(nbuf, name);
1382 
1383  it=GWEN_StringList2_First(sl);
1384  if (it) {
1385  const char *t;
1386 
1388  assert(t);
1389  while(t) {
1390  const char *p;
1391 
1392  p=strchr(t, ':');
1393  assert(p);
1394  p++;
1395  if (strcasecmp(p, GWEN_Buffer_GetStart(nbuf))==0) {
1397  GWEN_Buffer_free(nbuf);
1398  return t;
1399  }
1401  } /* while */
1403  }
1404 
1405  GWEN_Buffer_free(nbuf);
1406  return 0;
1407 }
1408 
1409 
1410 
1412  GWEN_STRINGLIST2 *sl,
1413  const char *currentNameSpace) {
1414  GWEN_XMLPROPERTY *pr;
1415  GWEN_XMLNODE *nn;
1416  char *localNameSpace;
1417 
1418  localNameSpace=0;
1419 
1420  /* remove all unnecessary namespace declarations from this node */
1421  pr=n->properties;
1422  while(pr) {
1423  GWEN_XMLPROPERTY *prNext;
1424 
1425  prNext=pr->next;
1426  if (strcasecmp(pr->name, "xmlns")==0) {
1427  /* default namespace changed ? */
1428  if (localNameSpace) {
1429  if (strcasecmp(pr->value, localNameSpace)==0) {
1430  /* already mentioned name space, remove duplicate property */
1431  GWEN_XMLProperty_del(pr, &n->properties);
1433  }
1434  else {
1435  /* current namespace changed */
1436  GWEN_Memory_dealloc(localNameSpace);
1437  localNameSpace=GWEN_Memory_strdup(pr->value);
1438  }
1439  }
1440  else if (currentNameSpace) {
1441  if (strcasecmp(pr->value, currentNameSpace)==0) {
1442  /* already active name space, remove property */
1443  GWEN_XMLProperty_del(pr, &n->properties);
1445  }
1446  else {
1447  /* current namespace changed */
1448  GWEN_Memory_dealloc(localNameSpace);
1449  localNameSpace=GWEN_Memory_strdup(pr->value);
1450  }
1451  }
1452  else {
1453  /* set current namespace */
1454  GWEN_Memory_dealloc(localNameSpace);
1455  localNameSpace=GWEN_Memory_strdup(pr->value);
1456  }
1457  }
1458  else if (strncasecmp(pr->name, "xmlns:", 6)==0) {
1459  const char *prefix;
1460  const char *x;
1461 
1462  prefix=strchr(pr->name, ':');
1463  prefix++;
1464 
1465  /* check for redefinition */
1466  x=GWEN_XML_FindNameSpaceByName(sl, prefix);
1467  if (x) {
1468  const char *p;
1469 
1470  /* prefix already in use, check whether it is the same namespace */
1471  p=strchr(x, ':');
1472  assert(p);
1473  p++;
1474  if (strcasecmp(p, pr->value)!=0) {
1475  GWEN_BUFFER *xpath;
1476 
1477  /* same prefix, different namespace */
1478  xpath=GWEN_Buffer_new(0, 256, 0, 1);
1479  GWEN_XMLNode_GetXPath(0, n, xpath);
1481  "Redefinition of namespace prefix \"%s\" in \"%s\"",
1482  prefix, GWEN_Buffer_GetStart(xpath));
1483  GWEN_Buffer_free(xpath);
1484  return -1;
1485  } /* if different namespace for same prefix */
1486  else {
1487  /* already in list, remove property here */
1488  GWEN_XMLProperty_del(pr, &n->properties);
1490  }
1491  }
1492  else {
1493  GWEN_XML_AddNameSpace(sl, prefix, pr->value);
1494  }
1495  }
1496  pr=prNext;
1497  } /* while */
1498 
1499  /* do the same on all sub nodes */
1501  while(nn) {
1502  int rv;
1503 
1505  localNameSpace?localNameSpace:
1506  currentNameSpace);
1507  if (rv) {
1508  GWEN_Memory_dealloc(localNameSpace);
1509  return rv;
1510  }
1511  nn=GWEN_XMLNode_GetNextTag(nn);
1512  }
1513 
1514  GWEN_Memory_dealloc(localNameSpace);
1515  return 0;
1516 }
1517 
1518 
1519 
1521  const char *prefix,
1522  const char *nspace) {
1523  GWEN_XMLPROPERTY *pr;
1524  const char *p;
1525  int inUse;
1526 
1527  inUse=0;
1528  /* check current tag for prefix */
1529  if (prefix) {
1530  p=strchr(n->data, ':');
1531  if (p) {
1532  if (strncasecmp(n->data, prefix, p-n->data)==0) {
1533  DBG_DEBUG(GWEN_LOGDOMAIN, "Prefix \"%s\" used in tag \"%s\"",
1534  prefix, n->data);
1535  inUse=1;
1536  }
1537  }
1538 
1539  if (!inUse) {
1540  /* check all attributes for prefixes */
1541  pr=n->properties;
1542  while(pr) {
1543  p=strchr(pr->name, ':');
1544  if (p) {
1545  if (strncasecmp(pr->name, prefix, p-pr->name)==0) {
1547  "Prefix \"%s\" used in attribute \"%s\" of tag \"%s\"",
1548  prefix, pr->name, n->data);
1549  inUse=1;
1550  break;
1551  }
1552  else {
1554  "Prefix \"%s\" not used in attribute \"%s\" of tag \"%s\"",
1555  prefix, pr->name, n->data);
1556  }
1557  }
1558  pr=pr->next;
1559  } /* while */
1560  }
1561  } /* if prefix */
1562  else {
1563  /* no prefix, check whether the current element hasn't any */
1564  p=strchr(n->data, ':');
1565  if (!p) {
1566  /* current tag has no prefix, check whether we have a namespace
1567  * declaration here */
1568  if (GWEN_XMLNode_GetProperty(n, "xmlns", 0)==0) {
1569  /* no, so the current namespace from above is used */
1571  "No prefix, current namespace is used");
1572  inUse=1;
1573  }
1574  }
1575  } /* if no prefix */
1576 
1577  if (inUse) {
1578  GWEN_BUFFER *nbuf;
1579 
1580  nbuf=GWEN_Buffer_new(0, 32, 0, 1);
1581  GWEN_Buffer_AppendString(nbuf, "xmlns");
1582  if (prefix) {
1583  GWEN_Buffer_AppendByte(nbuf, ':');
1584  GWEN_Buffer_AppendString(nbuf, prefix);
1585  }
1586  GWEN_XMLNode__SetProperty(n, GWEN_Buffer_GetStart(nbuf), nspace, 1);
1587  GWEN_Buffer_free(nbuf);
1588  return 1;
1589  }
1590 
1591  return 0;
1592 }
1593 
1594 
1595 
1597  const char *prefix,
1598  const char *nspace) {
1599  GWEN_XMLNODE *nn;
1600  int rv;
1601 
1602  rv=GWEN_XMLNode__CheckAndSetNameSpace(n, prefix, nspace);
1603  if (rv)
1604  return rv;
1605 
1607  while(nn) {
1608  rv=GWEN_XMLNode__CheckAndSetNameSpace(nn, prefix, nspace);
1609  if (rv==-1)
1610  return rv;
1611  else if (rv==0) {
1612  /* check children */
1613  rv=GWEN_XMLNode__SetNameSpaces(nn, prefix, nspace);
1614  if (rv)
1615  return rv;
1616  }
1617 
1618  nn=GWEN_XMLNode_GetNextTag(nn);
1619  }
1620 
1621  return 0;
1622 }
1623 
1624 
1625 
1627  GWEN_XMLPROPERTY *pr;
1628  GWEN_XMLNODE *nn;
1629  int rv;
1630 
1631  /* move all namespace declarations from this node to the nodes
1632  * of first use */
1633  pr=n->properties;
1634  while(pr) {
1635  GWEN_XMLPROPERTY *prNext;
1636 
1637  prNext=pr->next;
1638  if (strcasecmp(pr->name, "xmlns")==0 ||
1639  strncasecmp(pr->name, "xmlns:", 6)==0) {
1640  const char *prefix;
1641 
1642  prefix=strchr(pr->name, ':');
1643  if (prefix)
1644  prefix++;
1645 
1646  GWEN_XMLProperty_del(pr, &n->properties);
1647  rv=GWEN_XMLNode__SetNameSpaces(n, prefix, pr->value);
1648  DBG_DEBUG(GWEN_LOGDOMAIN, "Removing property \"%s\"",
1649  pr->name);
1651  if (rv==-1)
1652  return rv;
1653  }
1654  pr=prNext;
1655  } /* while */
1656 
1657  /* do the same on all sub nodes */
1659  while(nn) {
1661  if (rv) {
1662  return rv;
1663  }
1664  nn=GWEN_XMLNode_GetNextTag(nn);
1665  }
1666 
1667  return 0;
1668 }
1669 
1670 
1671 
1672 
1674  const char *ns;
1675  int rv;
1676  GWEN_STRINGLIST2 *sl;
1677 
1678  ns=GWEN_XMLNode_GetProperty(n, "xmlns", 0);
1679  sl=GWEN_StringList2_new();
1680  rv=GWEN_XMLNode__CheckNameSpaceDecls1(n, sl, ns);
1682  if (rv) {
1683  DBG_INFO(GWEN_LOGDOMAIN, "here");
1684  return rv;
1685  }
1686 
1687  //rv=GWEN_XMLNode__CheckNameSpaceDecls2(n, ns);
1689  if (rv==-1)
1690  return rv;
1691  return 0;
1692 }
1693 
1694 
1695 
1697  if (n && n->type==GWEN_XMLNodeTypeTag && n->data) {
1698  GWEN_XMLNODE *nn;
1699  GWEN_XMLPROPERTY *pp;
1700 
1701  if (n->nameSpace==0) {
1702  char *p;
1703 
1704  p=strchr(n->data, ':');
1705  if (p) {
1706  int len=p-n->data;
1707  char *s;
1708 
1709  n->nameSpace=(char*)GWEN_Memory_malloc(len);
1710  assert(n->nameSpace);
1711  memmove(n->nameSpace, n->data, len);
1712  n->nameSpace[len-1]=0;
1713  s=GWEN_Memory_strdup(p+1);
1714  free(n->data);
1715  n->data=s;
1716  }
1717  }
1718 
1719  pp=n->properties;
1720  while(pp) {
1721  if (pp->nameSpace==0) {
1722  char *p;
1723 
1724  p=strchr(pp->name, ':');
1725  if (p) {
1726  int len=p-pp->name;
1727  char *s;
1728 
1729  pp->nameSpace=(char*)GWEN_Memory_malloc(len);
1730  assert(pp->nameSpace);
1731  memmove(pp->nameSpace, pp->name, len);
1732  pp->nameSpace[len-1]=0;
1733  s=GWEN_Memory_strdup(p+1);
1734  free(pp->name);
1735  pp->name=s;
1736  }
1737  }
1738 
1739  pp=pp->next;
1740  }
1741 
1742  nn=GWEN_XMLNode_List_First(n->children);
1743  while(nn) {
1744  int rv;
1745 
1747  if (rv<0) {
1748  DBG_DEBUG(GWEN_LOGDOMAIN, "here (%d)", rv);
1749  return rv;
1750  }
1751  nn=GWEN_XMLNode_List_Next(nn);
1752  }
1753  }
1754 
1755  return 0;
1756 }
1757 
1758 
1759 
1760 
1761 
1762 
1763 
1764 
1765 
1767  GWEN_XMLNODE_PATH *p;
1768 
1770  return p;
1771 }
1772 
1773 
1774 
1776  GWEN_XMLNODE_PATH *p;
1777  unsigned int i;
1778 
1780  p->pos=np->pos;
1781  for (i=0; i<np->pos; i++) {
1782  p->nodes[i]=np->nodes[i];
1783  }
1784  return p;
1785 }
1786 
1787 
1788 
1790  GWEN_FREE_OBJECT(np);
1791 }
1792 
1793 
1794 
1796  GWEN_XMLNODE *n){
1797  unsigned int i;
1798 
1799  if (np->pos>=GWEN_XML_MAX_DEPTH) {
1800  DBG_ERROR(GWEN_LOGDOMAIN, "Path too deep");
1801  return 1;
1802  }
1803 
1804  /* check for double entries */
1805  for (i=0; i<np->pos; i++) {
1806  assert(np->nodes[i]!=n);
1807  }
1808  np->nodes[np->pos++]=n;
1809  DBG_DEBUG(GWEN_LOGDOMAIN, "Dived to %d", np->pos);
1810  return 0;
1811 }
1812 
1813 
1814 
1816  if (np->pos==0) {
1817  DBG_DEBUG(GWEN_LOGDOMAIN, "Root reached");
1818  return 0;
1819  }
1820  DBG_DEBUG(GWEN_LOGDOMAIN, "Surfaced to %d", np->pos-1);
1821  return np->nodes[--np->pos];
1822 }
1823 
1824 
1825 
1827  unsigned int i;
1828 
1829  if (np->pos==0) {
1830  DBG_NOTICE(GWEN_LOGDOMAIN, "Empty path");
1831  }
1832  for (i=0; i<np->pos; i++) {
1833  DBG_NOTICE(GWEN_LOGDOMAIN, "Path entry %d:", i);
1834  GWEN_XMLNode_Dump(np->nodes[i], 1);
1835  }
1836 }
1837 
1838 
1839 
1840 
1841 
1842 
1843 
1844 
1845 
1846 
1847 
1849  const char *url) {
1851 
1854 
1855  if (name)
1856  ns->name=GWEN_Memory_strdup(name);
1857  if (url)
1858  ns->url=GWEN_Memory_strdup(url);
1859 
1860  return ns;
1861 }
1862 
1863 
1864 
1866  if (ns) {
1868  free(ns->url);
1869  free(ns->name);
1870  GWEN_FREE_OBJECT(ns);
1871  }
1872 }
1873 
1874 
1875 
1878 
1879  assert(ns);
1880  nns=GWEN_XMLNode_NameSpace_new(ns->name, ns->url);
1881  return nns;
1882 }
1883 
1884 
1885 
1887  assert(ns);
1888  return ns->name;
1889 }
1890 
1891 
1892 
1894  assert(ns);
1895  return ns->url;
1896 }
1897 
1898 
1899 
1900 
1901 
1902 
1903 #include "xmlrw.c"
1904 #include "xmlglobalize.c"
1905 
1906 
1907