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