1/*
2	dom.c[pp]
3
4	gSOAP DOM implementation
5
6gSOAP XML Web services tools
7Copyright (C) 2000-2008, Robert van Engelen, Genivia, Inc. All Rights Reserved.
8This part of the software is released under ONE of the following licenses:
9GPL, the gSOAP public license, OR Genivia's license for commercial use.
10--------------------------------------------------------------------------------
11gSOAP public license.
12
13The contents of this file are subject to the gSOAP Public License Version 1.3
14(the "License"); you may not use this file except in compliance with the
15License. You may obtain a copy of the License at
16http://www.cs.fsu.edu/~engelen/soaplicense.html
17Software distributed under the License is distributed on an "AS IS" basis,
18WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
19for the specific language governing rights and limitations under the License.
20
21The Initial Developer of the Original Code is Robert A. van Engelen.
22Copyright (C) 2000-2008 Robert A. van Engelen, Genivia inc. All Rights Reserved.
23--------------------------------------------------------------------------------
24GPL license.
25
26This program is free software; you can redistribute it and/or modify it under
27the terms of the GNU General Public License as published by the Free Software
28Foundation; either version 2 of the License, or (at your option) any later
29version.
30
31This program is distributed in the hope that it will be useful, but WITHOUT ANY
32WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
33PARTICULAR PURPOSE. See the GNU General Public License for more details.
34
35You should have received a copy of the GNU General Public License along with
36this program; if not, write to the Free Software Foundation, Inc., 59 Temple
37Place, Suite 330, Boston, MA 02111-1307 USA
38
39Author contact information:
40engelen@genivia.com / engelen@acm.org
41
42This program is released under the GPL with the additional exemption that
43compiling, linking, and/or using OpenSSL is allowed.
44--------------------------------------------------------------------------------
45A commercial use license is available from Genivia, Inc., contact@genivia.com
46--------------------------------------------------------------------------------
47*/
48
49#include "stdsoap2.h"
50
51SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_xsd__anyType(struct soap*, struct soap_dom_element const*);
52SOAP_FMAC1 void SOAP_FMAC2 soap_default_xsd__anyType(struct soap*, struct soap_dom_element *);
53SOAP_FMAC3 int SOAP_FMAC4 soap_put_xsd__anyType(struct soap*, const struct soap_dom_element *, const char*, const char*);
54SOAP_FMAC1 int SOAP_FMAC2 soap_out_xsd__anyType(struct soap*, const char*, int, const struct soap_dom_element *, const char*);
55SOAP_FMAC3 struct soap_dom_element * SOAP_FMAC4 soap_get_xsd__anyType(struct soap*, struct soap_dom_element *, const char*, const char*);
56SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_in_xsd__anyType(struct soap*, const char*, struct soap_dom_element *, const char*);
57
58SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_xsd__anyAttribute(struct soap*, struct soap_dom_attribute const*);
59SOAP_FMAC1 void SOAP_FMAC2 soap_default_xsd__anyAttribute(struct soap*, struct soap_dom_attribute *);
60SOAP_FMAC3 int SOAP_FMAC4 soap_put_xsd__anyAttribute(struct soap*, const struct soap_dom_attribute *, const char*, const char*);
61SOAP_FMAC1 int SOAP_FMAC2 soap_out_xsd__anyAttribute(struct soap*, const char*, int, const struct soap_dom_attribute *, const char*);
62SOAP_FMAC3 struct soap_dom_attribute * SOAP_FMAC4 soap_get_xsd__anyAttribute(struct soap*, struct soap_dom_attribute *, const char*, const char*);
63SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_in_xsd__anyAttribute(struct soap*, const char*, struct soap_dom_attribute *, const char*);
64
65#ifdef __cplusplus
66extern "C" {
67#endif
68SOAP_FMAC1 void SOAP_FMAC2 soap_markelement(struct soap*, const void*, int);
69SOAP_FMAC1 int SOAP_FMAC2 soap_putelement(struct soap*, const void*, const char*, int, int);
70SOAP_FMAC1 void *SOAP_FMAC2 soap_getelement(struct soap*, int*);
71#ifdef __cplusplus
72}
73#endif
74
75/* format string for generating DOM namespace prefixes (<= 16 chars total) */
76#define SOAP_DOMID_FORMAT "dom%d"
77
78/* namespace name (URI) lookup and store routines */
79static struct soap_ilist *soap_lookup_ns_prefix(struct soap*, const char*);
80static struct soap_ilist *soap_enter_ns_prefix(struct soap*, const char*, const char*);
81
82static int out_element(struct soap *soap, const struct soap_dom_element *node, const char *prefix, const char *name, const char *nstr);
83static int out_attribute(struct soap *soap, const char *prefix, const char *name, const char *data, const wchar_t *wide, int flag);
84
85/******************************************************************************\
86 *
87 *	DOM custom (de)serializers
88 *
89\******************************************************************************/
90
91SOAP_FMAC1
92void
93SOAP_FMAC2
94soap_serialize_xsd__anyType(struct soap *soap, const struct soap_dom_element *node)
95{ if (node)
96  { if (node->type && node->node)
97      soap_markelement(soap, node->node, node->type);
98    else
99    { const struct soap_dom_element *elt;
100      for (elt = node->elts; elt; elt = elt->next)
101        soap_serialize_xsd__anyType(soap, elt);
102    }
103  }
104}
105
106/******************************************************************************/
107
108SOAP_FMAC1
109void
110SOAP_FMAC2
111soap_serialize_xsd__anyAttribute(struct soap *soap, const struct soap_dom_attribute *node)
112{
113}
114
115/******************************************************************************/
116
117SOAP_FMAC1
118void
119SOAP_FMAC2
120soap_default_xsd__anyType(struct soap *soap, struct soap_dom_element *node)
121{ node->next = NULL;
122  node->prnt = NULL;
123  node->elts = NULL;
124  node->atts = NULL;
125  node->nstr = NULL;
126  node->name = NULL;
127  node->data = NULL;
128  node->wide = NULL;
129  node->node = NULL;
130  node->type = 0;
131  node->head = NULL;
132  node->tail = NULL;
133  node->soap = soap;
134}
135
136/******************************************************************************/
137
138SOAP_FMAC1
139void
140SOAP_FMAC2
141soap_default_xsd__anyAttribute(struct soap *soap, struct soap_dom_attribute *node)
142{ node->next = NULL;
143  node->nstr = NULL;
144  node->name = NULL;
145  node->data = NULL;
146  node->wide = NULL;
147  node->soap = soap;
148}
149
150/******************************************************************************/
151
152static int
153out_element(struct soap *soap, const struct soap_dom_element *node, const char *prefix, const char *name, const char *nstr)
154{ if (node->head && soap_send(soap, node->head))
155    return soap->error;
156  if (node->type && node->node)
157  { if (prefix)
158    { char *s = (char*)SOAP_MALLOC(soap, strlen(prefix) + strlen(name) + 2);
159      if (!s)
160        return soap->error = SOAP_EOM;
161      sprintf(s, "%s:%s", prefix, name);
162      soap_putelement(soap, node->node, s, 0, node->type);
163      SOAP_FREE(soap, s);
164    }
165    else
166      return soap_putelement(soap, node->node, name, 0, node->type);
167  }
168  else if (prefix)
169  { char *s;
170    if (strlen(prefix) + strlen(name) < sizeof(soap->msgbuf))
171      s = soap->msgbuf;
172    else
173    { s = (char*)SOAP_MALLOC(soap, strlen(prefix) + strlen(name) + 2);
174      if (!s)
175        return soap->error = SOAP_EOM;
176    }
177    sprintf(s, "%s:%s", prefix, name);
178    if (soap_element(soap, s, 0, NULL)) /* element() */
179      return soap->error;
180    if (nstr)
181    { sprintf(s, "xmlns:%s", prefix);
182      soap_attribute(soap, s, nstr);
183    }
184    if (s != soap->msgbuf)
185      SOAP_FREE(soap, s);
186  }
187  else
188    return soap_element(soap, name, 0, NULL); /* element() */
189  return soap->error;
190}
191
192/******************************************************************************/
193
194static int
195out_attribute(struct soap *soap, const char *prefix, const char *name, const char *data, const wchar_t *wide, int flag)
196{ char *s;
197  const char *t;
198  int err;
199  if (wide)
200    data = soap_wchar2s(soap, wide);
201  if (!prefix)
202  { if (flag)
203      return soap_set_attr(soap, name, data);
204    return soap_attribute(soap, name, data);
205  }
206  t = strchr(name, ':');
207  if (t)
208    t++;
209  else
210    t = name;
211  if (strlen(prefix) + strlen(t) < sizeof(soap->msgbuf))
212    s = soap->msgbuf;
213  else
214  { s = (char*)SOAP_MALLOC(soap, strlen(prefix) + strlen(t) + 2);
215    if (!s)
216      return soap->error = SOAP_EOM;
217  }
218  sprintf(s, "%s:%s", prefix, t);
219  if (flag)
220    err = soap_set_attr(soap, s, data);
221  else
222    err = soap_attribute(soap, s, data);
223  if (s != soap->msgbuf)
224    SOAP_FREE(soap, s);
225  return err;
226}
227
228/******************************************************************************/
229
230SOAP_FMAC1
231int
232SOAP_FMAC2
233soap_out_xsd__anyType(struct soap *soap, const char *tag, int id, const struct soap_dom_element *node, const char *type)
234{ if (node)
235  { register struct soap_ilist *p = NULL;
236    const char *prefix;		/* namespace prefix, if namespace is present */
237    size_t colon;
238    if (!(soap->mode & SOAP_DOM_ASIS))
239    { struct soap_dom_attribute *att;
240      for (att = node->atts; att; att = att->next)
241      { if (att->name && att->data && !strncmp(att->name, "xmlns:", 6))
242	{ if (!(soap_enter_ns_prefix(soap, att->name + 6, att->data)))
243            return soap->error = SOAP_EOM;
244	}
245        else if (att->name && att->nstr)
246        { if ((prefix = strchr(att->name, ':')))
247          { colon = prefix - att->name + 1;
248            if (colon > sizeof(soap->tag))
249              colon = sizeof(soap->tag);
250	    strncpy(soap->tag, att->name, colon - 1);
251            soap->tag[colon - 1] = '\0';
252            if (!(soap_enter_ns_prefix(soap, soap->tag, att->nstr)))
253              return soap->error = SOAP_EOM;
254          }
255        }
256      }
257    }
258    if (node->name)
259      tag = node->name;
260    else if (!tag)
261      tag = "-";
262    if ((prefix = strchr(tag, ':')))
263    { colon = prefix - tag + 1;
264      if (colon > sizeof(soap->tag))
265        colon = sizeof(soap->tag);
266    }
267    else
268      colon = 0;
269    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node '%s'\n", tag));
270    prefix = NULL;
271    if (node->nstr && *node->nstr && !(soap->mode & SOAP_DOM_ASIS))
272    { if (colon)
273      { strncpy(soap->tag, tag, colon - 1);
274        soap->tag[colon - 1] = '\0';
275        if (!(p = soap_enter_ns_prefix(soap, soap->tag, node->nstr)))
276          return soap->error = SOAP_EOM;
277        prefix = p->id;
278        if (out_element(soap, node, prefix, tag + colon, node->nstr))
279          return soap->error;
280      }
281      else
282      { /* This code removed to remove assumption that nstable was emitted in the root
283        struct Namespace *ns;
284        for (ns = soap->local_namespaces; ns && ns->id; ns++)
285        { if (ns->ns == node->nstr || !strcmp(ns->ns, node->nstr))
286          { prefix = ns->id;
287            if (out_element(soap, node, ns->id, tag + colon, NULL))
288              return soap->error;
289            break;
290          }
291	}
292        if (!ns || !ns->id)
293	{
294	*/
295        if ((p = soap_lookup_ns_prefix(soap, node->nstr)))
296        { prefix = p->id;
297          p = NULL;
298          if (out_element(soap, node, prefix, tag + colon, NULL))
299            return soap->error;
300        }
301        else
302        { struct Namespace *ns;
303          for (ns = soap->local_namespaces; ns && ns->id; ns++)
304          { if (ns->ns == node->nstr || !strcmp(ns->ns, node->nstr))
305            { prefix = ns->id;
306              break;
307            }
308          }
309          if (!prefix)
310          { sprintf(soap->tag, SOAP_DOMID_FORMAT, soap->idnum++);
311            prefix = soap->tag;
312          }
313          if (!(p = soap_enter_ns_prefix(soap, prefix, node->nstr)))
314            return soap->error = SOAP_EOM;
315          if (out_element(soap, node, prefix, tag + colon, node->nstr))
316            return soap->error;
317        }
318        /* } */
319      }
320    }
321    else
322    { colon = 0;
323      if (out_element(soap, node, NULL, tag, NULL))
324        return soap->error;
325    }
326    if (!node->type || !node->node)
327    { struct soap_dom_attribute *att;
328      struct soap_dom_element *elt;
329      for (att = node->atts; att; att = att->next)
330      { if (att->name)
331        { if (att->nstr && !(soap->mode & SOAP_DOM_ASIS))
332          { register struct soap_ilist *q;
333            if ((att->nstr == node->nstr || (node->nstr && !strcmp(att->nstr, node->nstr))) && prefix)
334	    { if (out_attribute(soap, prefix, att->name, att->data, att->wide, 0))
335	        return soap->error;
336	    }
337	    else if ((q = soap_lookup_ns_prefix(soap, att->nstr)))
338	    { if (out_attribute(soap, q->id, att->name, att->data, att->wide, 0))
339	        return soap->error;
340	    }
341	    else
342            { /* This code removed to remove assumption that nstable was emitted in the root
343	      struct Namespace *ns;
344	      for (ns = soap->local_namespaces; ns && ns->id; ns++)
345              { if (ns->ns == att->nstr || !strcmp(ns->ns, att->nstr))
346	        { if (out_attribute(soap, strncmp(att->name, "xml", 3) ? ns->id : NULL, att->name, att->data, att->wide, 0))
347	            return soap->error;
348	          break;
349	        }
350	      }
351	      if (!ns || !ns->id)
352	      {
353	      */
354	      if (!strncmp(att->name, "xml", 3))
355	      { if (out_attribute(soap, NULL, att->name, att->data, att->wide, 0))
356                  return soap->error;
357	      }
358	      else
359              { sprintf(soap->msgbuf, "xmlns:"SOAP_DOMID_FORMAT, soap->idnum++);
360	        if (soap_attribute(soap, soap->msgbuf, att->nstr))
361	          return soap->error;
362	        if (!(soap_enter_ns_prefix(soap, soap->msgbuf + 6, att->nstr)))
363                  return soap->error = SOAP_EOM;
364	        strcat(soap->msgbuf, ":");
365	        strcat(soap->msgbuf, att->name);
366	        if (soap_attribute(soap, soap->msgbuf + 6, att->wide ? soap_wchar2s(soap, att->wide) : att->data))
367	          return soap->error;
368              }
369	    /* } */
370            }
371          }
372	  else if (soap_attribute(soap, att->name, att->wide ? soap_wchar2s(soap, att->wide) : att->data))
373            return soap->error;
374        }
375      }
376      if (soap_element_start_end_out(soap, NULL))
377        return soap->error;
378      if (node->data)
379      { if (soap_string_out(soap, node->data, 0))
380          return soap->error;
381      }
382      else if (node->wide)
383      { if (soap_wstring_out(soap, node->wide, 0))
384          return soap->error;
385      }
386      for (elt = node->elts; elt; elt = elt->next)
387      { if (soap_out_xsd__anyType(soap, tag, 0, elt, NULL))
388          return soap->error;
389      }
390      if (node->tail && soap_send(soap, node->tail))
391        return soap->error;
392      if (!prefix)
393      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of DOM node '%s'\n", tag + colon));
394        if (soap_element_end_out(soap, tag + colon))
395          return soap->error;
396      }
397      else
398      { char *s;
399        if (strlen(prefix) + strlen(tag + colon) < sizeof(soap->msgbuf))
400	  s = soap->msgbuf;
401	else
402	{ s = (char*)SOAP_MALLOC(soap, strlen(prefix) + strlen(tag + colon) + 2);
403          if (!s)
404            return soap->error = SOAP_EOM;
405	}
406	sprintf(s, "%s:%s", prefix, tag + colon);
407        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of DOM node '%s'\n", s));
408        if (soap_element_end_out(soap, s))
409          return soap->error;
410        if (s != soap->msgbuf)
411	  SOAP_FREE(soap, s);
412      }
413      if (p)
414        p->level = 0; /* xmlns binding is out of scope */
415    }
416  }
417  return SOAP_OK;
418}
419
420/******************************************************************************/
421
422SOAP_FMAC1
423int
424SOAP_FMAC2
425soap_out_xsd__anyAttribute(struct soap *soap, const char *tag, int id, const struct soap_dom_attribute *node, const char *type)
426{ if (!(soap->mode & SOAP_DOM_ASIS))
427  { const struct soap_dom_attribute *att;
428    for (att = node; att; att = att->next)
429    { if (att->name && att->data && !strncmp(att->name, "xmlns:", 6))
430      { if (!(soap_enter_ns_prefix(soap, att->name + 6, att->data)))
431          return soap->error = SOAP_EOM;
432      }
433      else if (att->name && att->nstr)
434      { const char *prefix;
435        if ((prefix = strchr(att->name, ':')))
436        { size_t colon = prefix - att->name + 1;
437          if (colon > sizeof(soap->tag))
438            colon = sizeof(soap->tag);
439          strncpy(soap->tag, att->name, colon - 1);
440          soap->tag[colon - 1] = '\0';
441          if (!(soap_enter_ns_prefix(soap, soap->tag, att->nstr)))
442            return soap->error = SOAP_EOM;
443        }
444      }
445    }
446  }
447  while (node)
448  { if (node->name)
449    { if (node->nstr && !(soap->mode & SOAP_DOM_ASIS) && !strchr(node->name, ':'))
450      { struct soap_ilist *q;
451        if ((q = soap_lookup_ns_prefix(soap, node->nstr)))
452        { if (out_attribute(soap, q->id, node->name, node->data, node->wide, 1))
453            return soap->error;
454        }
455        else
456        { struct Namespace *ns;
457          for (ns = soap->local_namespaces; ns && ns->id; ns++)
458          { if (ns->ns == node->nstr || !strcmp(ns->ns, node->nstr))
459            { if (out_attribute(soap, strncmp(node->name, "xml", 3) ? ns->id : NULL, node->name, node->data, node->wide, 1))
460                return soap->error;
461              break;
462            }
463          }
464          if (!ns || !ns->id)
465	  { if (!strncmp(node->name, "xml", 3))
466            { if (node->name && node->data && !strncmp(node->name, "xmlns:", 6))
467	      { if (!(soap_enter_ns_prefix(soap, node->name + 6, node->data)))
468                  return soap->error = SOAP_EOM;
469	      }
470              if (out_attribute(soap, NULL, node->name, node->data, node->wide, 1))
471                  return soap->error;
472	    }
473	    else
474            { struct Namespace *ns;
475              for (ns = soap->local_namespaces; ns && ns->id; ns++)
476              { if (ns->ns == node->nstr || !strcmp(ns->ns, node->nstr))
477                { if (out_attribute(soap, ns->id, node->name, node->data, node->wide, 1))
478                    return soap->error;
479                  break;
480                }
481	      }
482	      if (!ns || !ns->id)
483              { sprintf(soap->msgbuf, "xmlns:"SOAP_DOMID_FORMAT, soap->idnum++);
484                if (soap_set_attr(soap, soap->msgbuf, node->nstr))
485                  return soap->error;
486	        if (!(soap_enter_ns_prefix(soap, soap->msgbuf + 6, node->nstr)))
487                  return soap->error = SOAP_EOM;
488                strcat(soap->msgbuf, ":");
489                strcat(soap->msgbuf, node->name);
490                if (out_attribute(soap, NULL, soap->msgbuf + 6, node->data, node->wide, 1))
491                  return soap->error;
492	      }
493            }
494          }
495        }
496      }
497      else
498      { out_attribute(soap, NULL, node->name, node->data, node->wide, 1);
499      }
500    }
501    node = node->next;
502  }
503  return SOAP_OK;
504}
505
506/******************************************************************************/
507
508SOAP_FMAC1
509struct soap_dom_element *
510SOAP_FMAC2
511soap_in_xsd__anyType(struct soap *soap, const char *tag, struct soap_dom_element *node, const char *type)
512{ register struct soap_attribute *tp;
513  register struct soap_dom_attribute **att;
514  if (soap_peek_element(soap))
515    return NULL;
516  if (!node)
517  { if (!(node = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element))))
518    { soap->error = SOAP_EOM;
519      return NULL;
520    }
521  }
522  soap_default_xsd__anyType(soap, node);
523  node->nstr = soap_current_namespace(soap, soap->tag);
524  if ((soap->mode & SOAP_DOM_ASIS))
525    node->name = soap_strdup(soap, soap->tag);
526  else
527  { char *s = strchr(soap->tag, ':');
528    if (s)
529      node->name = soap_strdup(soap, s+1);
530    else
531      node->name = soap_strdup(soap, soap->tag);
532  }
533  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node %s in namespace %s\n", node->name, node->nstr?node->nstr:""));
534  if ((soap->mode & SOAP_DOM_NODE) || (!(soap->mode & SOAP_DOM_TREE) && *soap->id))
535  { if ((node->node = soap_getelement(soap, &node->type)))
536    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node contains type %d from xsi:type\n", node->type));
537      return node;
538    }
539    if (soap->error == SOAP_TAG_MISMATCH)
540      soap->error = SOAP_OK;
541    else
542      return NULL;
543  }
544  att = &node->atts;
545  for (tp = soap->attributes; tp; tp = tp->next)
546  { if (tp->visible)
547    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node attribute='%s'\n", tp->name));
548      *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
549      if (!*att)
550      { soap->error = SOAP_EOM;
551        return NULL;
552      }
553      (*att)->next = NULL;
554      (*att)->nstr = soap_current_namespace(soap, tp->name);
555      if ((soap->mode & SOAP_DOM_ASIS) || !strncmp(tp->name, "xml", 3))
556        (*att)->name = soap_strdup(soap, tp->name);
557      else
558      { char *s = strchr(tp->name, ':');
559        if (s)
560          (*att)->name = soap_strdup(soap, s+1);
561        else
562          (*att)->name = soap_strdup(soap, tp->name);
563      }
564      if (tp->visible == 2)
565        (*att)->data = soap_strdup(soap, tp->value);
566      else
567        (*att)->data = NULL;
568      (*att)->wide = NULL;
569      (*att)->soap = soap;
570      att = &(*att)->next;
571      tp->visible = 0;
572    }
573  }
574  soap_element_begin_in(soap, NULL, 1, NULL);
575  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node '%s' pulled\n", node->name));
576  if (soap->body)
577  { if (!soap_peek_element(soap))
578    { struct soap_dom_element **elt;
579      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node '%s' has subelements\n", node->name));
580      elt = &node->elts;
581      for (;;)
582      { if (!(*elt = soap_in_xsd__anyType(soap, NULL, NULL, NULL)))
583        { if (soap->error == SOAP_NO_TAG)
584            soap->error = SOAP_OK;
585          else
586            return NULL;
587          break;
588        }
589	(*elt)->prnt = node;
590        elt = &(*elt)->next;
591      }
592    }
593    else if (soap->error == SOAP_NO_TAG)
594    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node '%s' has cdata\n", node->name));
595      if ((soap->mode & SOAP_C_UTFSTRING) || (soap->mode & SOAP_C_MBSTRING))
596      { if (!(node->data = soap_string_in(soap, 1, -1, -1)))
597          return NULL;
598      }
599      else if (!(node->wide = soap_wstring_in(soap, 1, -1, -1)))
600        return NULL;
601    }
602    else
603      return NULL;
604    if (soap_element_end_in(soap, node->name))
605      return NULL;
606    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of DOM node '%s'\n", node->name));
607  }
608  return node;
609}
610
611/******************************************************************************/
612
613SOAP_FMAC1
614struct soap_dom_attribute *
615SOAP_FMAC2
616soap_in_xsd__anyAttribute(struct soap *soap, const char *tag, struct soap_dom_attribute *node, const char *type)
617{ register struct soap_attribute *tp;
618  struct soap_dom_attribute *tmp = node;
619  struct soap_dom_attribute *att = node;
620  for (tp = soap->attributes; tp; tp = tp->next)
621  { if (tp->visible)
622    { if (!att)
623      { att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
624        if (tmp)
625	  tmp->next = att;
626	else
627	  node = att;
628        tmp = att;
629      }
630      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DOM node attribute='%s'\n", tp->name));
631      if (!att)
632      { soap->error = SOAP_EOM;
633        return NULL;
634      }
635      att->next = NULL;
636      att->nstr = soap_current_namespace(soap, tp->name);
637      if ((soap->mode & SOAP_DOM_ASIS) || !strncmp(tp->name, "xml", 3))
638        att->name = soap_strdup(soap, tp->name);
639      else
640      { char *s = strchr(tp->name, ':');
641        if (s)
642          att->name = soap_strdup(soap, s+1);
643	else
644          att->name = soap_strdup(soap, tp->name);
645      }
646      if (tp->visible == 2)
647        att->data = soap_strdup(soap, tp->value);
648      else
649        att->data = NULL;
650      att->wide = NULL;
651      att->soap = soap;
652      att = NULL;
653    }
654  }
655  return node;
656}
657
658/******************************************************************************\
659 *
660 *	DOM traversing
661 *
662\******************************************************************************/
663
664SOAP_FMAC1
665struct soap_dom_element *
666SOAP_FMAC2
667soap_dom_next_element(struct soap_dom_element *elt)
668{ if (elt->elts)
669    return elt->elts;
670  if (elt->next)
671    return elt->next;
672  do elt = elt->prnt;
673  while (elt && !elt->next);
674  if (elt)
675    elt = elt->next;
676  return elt;
677}
678
679/******************************************************************************/
680
681struct soap_dom_attribute *
682soap_dom_next_attribute(struct soap_dom_attribute *att)
683{ return att->next;
684}
685
686/******************************************************************************\
687 *
688 *	Namespace prefix lookup/store
689 *
690\******************************************************************************/
691
692static struct soap_ilist *
693soap_lookup_ns_prefix(struct soap *soap, const char *nstr)
694{ register struct soap_ilist *ip;
695  for (ip = soap->iht[soap_hash(nstr)]; ip; ip = ip->next)
696    if (!strcmp((char*)ip->ptr, nstr) && ip->level)
697      return ip;
698  return NULL;
699}
700
701/******************************************************************************/
702
703static struct soap_ilist *
704soap_enter_ns_prefix(struct soap *soap, const char *prefix, const char *nstr)
705{ size_t h;
706  register struct soap_ilist *ip;
707  for (ip = soap->iht[soap_hash(nstr)]; ip; ip = ip->next)
708  { if (!strcmp((char*)ip->ptr, nstr) && !ip->level)
709    { strcpy(ip->id, prefix);
710      ip->level = 1;
711      return ip;
712    }
713  }
714  ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(nstr) + SOAP_TAGLEN);
715  if (ip)
716  { h = soap_hash(nstr);
717    strcpy(ip->id, prefix);
718    ip->ptr = ip->id + SOAP_TAGLEN;
719    strcpy((char*)ip->ptr, nstr);
720    ip->next = soap->iht[h];
721    soap->iht[h] = ip;
722    ip->flist = NULL;
723    ip->copy = NULL;
724    ip->level = 1;
725    return ip;
726  }
727  return NULL;
728}
729
730#ifdef __cplusplus
731
732/******************************************************************************\
733 *
734 *	soap_dom_element class
735 *
736\******************************************************************************/
737
738soap_dom_element::soap_dom_element()
739{ soap_default_xsd__anyType(NULL, this);
740}
741
742/******************************************************************************/
743
744soap_dom_element::soap_dom_element(struct soap *soap)
745{ soap_default_xsd__anyType(soap, this);
746}
747
748/******************************************************************************/
749
750soap_dom_element::soap_dom_element(struct soap *soap, const char *nstr, const char *name)
751{ soap_default_xsd__anyType(soap, this);
752  this->nstr = soap_strdup(soap, nstr);
753  this->name = soap_strdup(soap, name);
754}
755
756/******************************************************************************/
757
758soap_dom_element::soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data)
759{ soap_default_xsd__anyType(soap, this);
760  this->nstr = soap_strdup(soap, nstr);
761  this->name = soap_strdup(soap, name);
762  this->data = soap_strdup(soap, data);
763}
764
765/******************************************************************************/
766
767soap_dom_element::soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type)
768{ soap_default_xsd__anyType(soap, this);
769  this->nstr = soap_strdup(soap, nstr);
770  this->name = soap_strdup(soap, name);
771  this->node = node;
772  this->type = type;
773}
774
775/******************************************************************************/
776
777soap_dom_element::~soap_dom_element()
778{ }
779
780/******************************************************************************/
781
782soap_dom_element &soap_dom_element::set(const char *nstr, const char *name)
783{ this->nstr = soap_strdup(soap, nstr);
784  this->name = soap_strdup(soap, name);
785  return *this;
786}
787
788/******************************************************************************/
789
790soap_dom_element &soap_dom_element::set(const char *data)
791{ this->data = soap_strdup(soap, data);
792  return *this;
793}
794
795/******************************************************************************/
796
797soap_dom_element &soap_dom_element::set(void *node, int type)
798{ this->node = node;
799  this->type = type;
800  return *this;
801}
802
803/******************************************************************************/
804
805soap_dom_element &soap_dom_element::add(struct soap_dom_element *elt)
806{ elt->prnt = this;
807  for (struct soap_dom_element *e = elts; e; e = e->next)
808  { if (!e->next)
809    { e->next = elt;
810      return *this;
811    }
812  }
813  elts = elt;
814  return *this;
815}
816
817/******************************************************************************/
818
819soap_dom_element &soap_dom_element::add(struct soap_dom_element &elt)
820{ return add(&elt);
821}
822
823/******************************************************************************/
824
825soap_dom_element &soap_dom_element::add(struct soap_dom_attribute *att)
826{ for (struct soap_dom_attribute *a = atts; a; a = a->next)
827  { if (!a->next)
828    { a->next = att;
829      return *this;
830    }
831  }
832  atts = att;
833  return *this;
834}
835
836/******************************************************************************/
837
838soap_dom_element &soap_dom_element::add(struct soap_dom_attribute &att)
839{ return add(&att);
840}
841
842/******************************************************************************/
843
844soap_dom_element_iterator soap_dom_element::begin()
845{ soap_dom_element_iterator iter(this);
846  return iter;
847}
848
849/******************************************************************************/
850
851soap_dom_element_iterator soap_dom_element::end()
852{ soap_dom_element_iterator iter(NULL);
853  return iter;
854}
855
856/******************************************************************************/
857
858soap_dom_element_iterator soap_dom_element::find(const char *nstr, const char *name)
859{ soap_dom_element_iterator iter(this);
860  iter.nstr = nstr;
861  iter.name = name;
862  if (name && soap_tag_cmp(this->name, name))
863    return ++iter;
864  if (nstr && this->nstr && soap_tag_cmp(this->nstr, nstr))
865    return ++iter;
866  return iter;
867}
868
869/******************************************************************************/
870
871soap_dom_element_iterator soap_dom_element::find(int type)
872{ soap_dom_element_iterator iter(this);
873  iter.type = type;
874  if (this->type != type)
875    return ++iter;
876  return iter;
877}
878
879/******************************************************************************/
880
881void soap_dom_element::unlink()
882{ soap_unlink(soap, this);
883  soap_unlink(soap, nstr);
884  soap_unlink(soap, name);
885  soap_unlink(soap, data);
886  soap_unlink(soap, wide);
887  if (elts)
888    elts->unlink();
889  if (atts)
890    elts->unlink();
891  if (next)
892    next->unlink();
893  node = NULL;
894  type = 0;
895}
896
897/******************************************************************************\
898 *
899 *	soap_dom_attribute class
900 *
901\******************************************************************************/
902
903soap_dom_attribute::soap_dom_attribute()
904{ this->soap = NULL;
905  this->next = NULL;
906  this->nstr = NULL;
907  this->name = NULL;
908  this->data = NULL;
909  this->wide = NULL;
910}
911
912/******************************************************************************/
913
914soap_dom_attribute::soap_dom_attribute(struct soap *soap)
915{ this->soap = soap;
916  this->next = NULL;
917  this->nstr = NULL;
918  this->name = NULL;
919  this->data = NULL;
920  this->wide = NULL;
921}
922
923/******************************************************************************/
924
925soap_dom_attribute::soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data)
926{ this->soap = soap;
927  this->next = NULL;
928  this->nstr = soap_strdup(soap, nstr);
929  this->name = soap_strdup(soap, name);
930  this->data = soap_strdup(soap, data);
931  this->wide = NULL;
932}
933
934/******************************************************************************/
935
936soap_dom_attribute::~soap_dom_attribute()
937{ }
938
939/******************************************************************************/
940
941soap_dom_attribute_iterator soap_dom_attribute::begin()
942{ soap_dom_attribute_iterator iter(this);
943  return iter;
944}
945
946/******************************************************************************/
947
948soap_dom_attribute_iterator soap_dom_attribute::end()
949{ soap_dom_attribute_iterator iter(NULL);
950  return iter;
951}
952
953/******************************************************************************/
954
955soap_dom_attribute_iterator soap_dom_attribute::find(const char *nstr, const char *name)
956{ soap_dom_attribute_iterator iter(this);
957  iter.nstr = nstr;
958  iter.name = name;
959  if (name && soap_tag_cmp(this->name, name))
960    return ++iter;
961  if (nstr && this->nstr && soap_tag_cmp(this->nstr, nstr))
962    return ++iter;
963  return iter;
964}
965
966/******************************************************************************/
967
968void soap_dom_attribute::unlink()
969{ soap_unlink(soap, this);
970  soap_unlink(soap, nstr);
971  soap_unlink(soap, name);
972  soap_unlink(soap, data);
973  soap_unlink(soap, wide);
974  if (next)
975    next->unlink();
976}
977
978/******************************************************************************\
979 *
980 *	soap_dom_element_iterator class
981 *
982\******************************************************************************/
983
984soap_dom_element_iterator::soap_dom_element_iterator()
985{ elt = NULL;
986  nstr = NULL;
987  name = NULL;
988  type = 0;
989}
990
991/******************************************************************************/
992
993soap_dom_element_iterator::soap_dom_element_iterator(struct soap_dom_element *elt)
994{ this->elt = elt;
995  nstr = NULL;
996  name = NULL;
997  type = 0;
998}
999
1000/******************************************************************************/
1001
1002soap_dom_element_iterator::~soap_dom_element_iterator()
1003{ }
1004
1005/******************************************************************************/
1006
1007bool soap_dom_element_iterator::operator==(const soap_dom_element_iterator &iter) const
1008{ return this->elt == iter.elt;
1009}
1010
1011/******************************************************************************/
1012
1013bool soap_dom_element_iterator::operator!=(const soap_dom_element_iterator &iter) const
1014{ return this->elt != iter.elt;
1015}
1016
1017/******************************************************************************/
1018
1019struct soap_dom_element &soap_dom_element_iterator::operator*() const
1020{ return *this->elt;
1021}
1022
1023/******************************************************************************/
1024
1025soap_dom_element_iterator &soap_dom_element_iterator::operator++()
1026{ while (elt)
1027  { elt = soap_dom_next_element(elt);
1028    if (!elt)
1029      break;
1030    if (name && elt->name)
1031    { if (!soap_tag_cmp(elt->name, name))
1032      { if (nstr && elt->nstr)
1033        { if (!soap_tag_cmp(elt->nstr, nstr))
1034	    break;
1035        }
1036        else
1037          break;
1038      }
1039    }
1040    else if (type)
1041    { if (elt->type == type)
1042        break;
1043    }
1044    else
1045      break;
1046  }
1047  return *this;
1048}
1049
1050/******************************************************************************\
1051 *
1052 *	soap_dom_attribute_iterator class
1053 *
1054\******************************************************************************/
1055
1056soap_dom_attribute_iterator::soap_dom_attribute_iterator()
1057{ att = NULL;
1058  nstr = NULL;
1059  name = NULL;
1060}
1061
1062/******************************************************************************/
1063
1064soap_dom_attribute_iterator::soap_dom_attribute_iterator(struct soap_dom_attribute *att)
1065{ this->att = att;
1066  nstr = NULL;
1067  name = NULL;
1068}
1069
1070/******************************************************************************/
1071
1072soap_dom_attribute_iterator::~soap_dom_attribute_iterator()
1073{ }
1074
1075/******************************************************************************/
1076
1077bool soap_dom_attribute_iterator::operator==(const soap_dom_attribute_iterator &iter) const
1078{ return this->att == iter.att;
1079}
1080
1081/******************************************************************************/
1082
1083bool soap_dom_attribute_iterator::operator!=(const soap_dom_attribute_iterator &iter) const
1084{ return this->att != iter.att;
1085}
1086
1087/******************************************************************************/
1088
1089struct soap_dom_attribute &soap_dom_attribute_iterator::operator*() const
1090{ return *this->att;
1091}
1092
1093/******************************************************************************/
1094
1095soap_dom_attribute_iterator &soap_dom_attribute_iterator::operator++()
1096{ while (att)
1097  { att = soap_dom_next_attribute(att);
1098    if (!att)
1099      break;
1100    if (name && att->name)
1101    { if (!soap_tag_cmp(att->name, name))
1102      { if (nstr && att->nstr)
1103        { if (!soap_tag_cmp(att->nstr, nstr))
1104	    break;
1105        }
1106        else
1107          break;
1108      }
1109    }
1110    else
1111      break;
1112  }
1113  return *this;
1114}
1115
1116/******************************************************************************\
1117 *
1118 *	I/O
1119 *
1120\******************************************************************************/
1121
1122#ifndef UNDER_CE
1123
1124std::ostream &operator<<(std::ostream &o, const struct soap_dom_element &e)
1125{ if (!e.soap)
1126  { struct soap soap;
1127    soap_init2(&soap, SOAP_IO_DEFAULT, SOAP_XML_GRAPH);
1128    soap_serialize_xsd__anyType(&soap, &e);
1129    soap_begin_send(&soap);
1130    soap.ns = 2; /* do not dump namespace table */
1131    soap_out_xsd__anyType(&soap, NULL, 0, &e, NULL);
1132    soap_end_send(&soap);
1133    soap_end(&soap);
1134    soap_done(&soap);
1135  }
1136  else
1137  { std::ostream *os = e.soap->os;
1138    e.soap->os = &o;
1139    soap_mode omode = e.soap->omode;
1140    soap_set_omode(e.soap, SOAP_XML_GRAPH);
1141    soap_serialize_xsd__anyType(e.soap, &e);
1142    soap_begin_send(e.soap);
1143    e.soap->ns = 2; /* do not dump namespace table */
1144    soap_out_xsd__anyType(e.soap, NULL, 0, &e, NULL);
1145    soap_end_send(e.soap);
1146    e.soap->os = os;
1147    e.soap->omode = omode;
1148  }
1149  return o;
1150}
1151
1152/******************************************************************************/
1153
1154std::istream &operator>>(std::istream &i, struct soap_dom_element &e)
1155{ if (!e.soap)
1156    e.soap = soap_new();
1157  std::istream *is = e.soap->is;
1158  e.soap->is = &i;
1159  if (soap_begin_recv(e.soap)
1160   || !soap_in_xsd__anyType(e.soap, NULL, &e, NULL)
1161   || soap_end_recv(e.soap))
1162  { /* handle error? Note: e.soap->error is set and app should check */
1163  }
1164  e.soap->is = is;
1165  return i;
1166}
1167
1168#endif
1169
1170#endif
1171