1 /*
2 * Copyright 1999-2006 University of Chicago
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include "globus_common.h"
19 #include "globus_soap_message.h"
20 #include "globus_i_soap_message.h"
21 #include "globus_soap_message_markers.h"
22 #include "globus_soap_message_handle.h"
23 #include "globus_soap_message_fault.h"
24 #include "globus_xml_buffer.h"
25 #include "openssl/evp.h"
26 #include "globus_xio_buffer.h"
27 #include "xsd_QName.h"
28
29 #define XSI_NS "http://www.w3.org/2001/XMLSchema-instance"
30 #define XSI_NIL "nil"
31
32 /**
33 * @defgroup globus_soap_message_deserialize SOAP deserialization support functions
34 *
35 * These functions are used by XML deserializers to deserialize the various
36 * element and attribute strings from an XML handle.
37 */
38 static
39 globus_result_t
40 globus_l_soap_message_deserialize_read(
41 globus_soap_message_handle_t handle);
42
43 static
44 char *
45 globus_l_soap_message_my_strtok(
46 const char * str,
47 size_t str_length,
48 int * token_start_index,
49 int * token_end_index,
50 const char * delims);
51
52 /**
53 * Push the current XML element onto the deserialization stack
54 * @ingroup globus_soap_message_deserialize
55 * This causes the next attempt to deserialize an element to return the
56 * current element. This is used by functions which want to know the name
57 * of the next element before calling the appropriate deserializer for it.
58 *
59 * @param handle
60 * SOAP message handle which is deserializing the XML content.
61 */
62 void
63 globus_soap_message_deserialize_push_element(
64 globus_soap_message_handle_t handle)
65 7770670 {
66 GlobusFuncName(globus_soap_message_deserialize_push_element);
67 7770670 GlobusSoapMessageDebugEnter();
68
69 7770670 if (handle)
70 {
71 7770670 handle->next_ready++;
72 }
73
74 7770670 GlobusSoapMessageDebugExit();
75 7770670 }
76 /* globus_soap_message_deserialize_push_element() */
77
78 /**
79 * Deserialize the end tag for the named element
80 * @ingroup globus_soap_message_deserialize
81 * Deserialize the closing tag for the current element. If @a qname is
82 * non-NULL, then the element name must match it.
83 *
84 * @param handle
85 * SOAP message handle which is deserializing the XML element.
86 * @param qname
87 * If non-NULL, The name of the element which is being deserialized.
88 *
89 * @retval GLOBUS_SUCCESS
90 * Element close tag deserialized successfully.
91 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
92 * The @a handle parameter was NULL.
93 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_END_ELEMENT
94 * The next XML node was not an end element that matches @a qname.
95 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_NEXT_NODE
96 * The XML document ended before an end element could be parsed.
97 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_WITH_TEXT
98 * The next XML node contained unexpected text content.
99 * @retval GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT
100 * (This is a constant value, not a globus_result_t)
101 *
102 * Other return values may indicate an error generated by a callout function.
103 */
104 globus_result_t
105 globus_soap_message_deserialize_element_end(
106 globus_soap_message_handle_t handle,
107 const xsd_QName * qname)
108 5046816 {
109 5046816 char * idval = NULL;
110 5046816 globus_result_t result = GLOBUS_SUCCESS;
111 5046816 xmlReaderTypes type = XML_READER_TYPE_NONE;
112 5046816 int res = 0;
113 GlobusFuncName(globus_soap_message_deserialize_element_end);
114 5046816 GlobusSoapMessageDebugEnter();
115
116 5046816 if (handle == NULL)
117 {
118 0 result = GlobusSoapMessageErrorNullParam;
119
120 0 goto exit;
121 }
122 5046816 if(xmlTextReaderIsEmptyElement(handle->reader))
123 {
124 2156 if (qname)
125 {
126 xsd_QName tmp;
127 const xmlChar * qname_ns;
128 const xmlChar * qname_local;
129
130 2156 tmp.Namespace = (char *)
131 xmlTextReaderConstString(handle->reader,
132 xmlTextReaderConstNamespaceUri(handle->reader));
133 2156 tmp.local = (char *)
134 xmlTextReaderConstString(handle->reader,
135 xmlTextReaderConstLocalName(handle->reader));
136 2156 qname_ns = xmlTextReaderConstString(handle->reader,
137 (xmlChar *) qname->Namespace);
138 2156 qname_local = xmlTextReaderConstString(handle->reader,
139 (xmlChar *) qname->local);
140 2156 if (qname_ns != (xmlChar *) tmp.Namespace ||
141 qname_local != (xmlChar *) tmp.local)
142 {
143 0 result = GlobusSoapMessageErrorFailedEndElement(
144 handle->verbose,
145 &tmp);
146 0 goto exit;
147 }
148 }
149 2156 res = xmlTextReaderRead(handle->reader);
150 2156 if(res < 0)
151 {
152 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
153 0 goto exit;
154 }
155 2156 handle->next_ready++;
156
157 2156 goto exit;
158 }
159
160 15136953 while(type != XML_READER_TYPE_END_ELEMENT)
161 {
162 5047633 if(handle->next_ready > 0)
163 {
164 78834 handle->next_ready--;
165 }
166 else
167 {
168 4968799 res = xmlTextReaderRead(handle->reader);
169 4968799 if(res < 0)
170 {
171 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
172 0 goto exit;
173 }
174 4968799 else if(res == 0)
175 {
176 0 goto exit;
177 }
178 }
179
180 5047633 type = xmlTextReaderNodeType(handle->reader);
181 5047633 if(type == XML_READER_TYPE_ELEMENT)
182 {
183 xsd_QName unexpected_qn;
184
185 0 if (handle->verbose)
186 {
187 0 unexpected_qn.Namespace = (char *)
188 xmlTextReaderConstNamespaceUri(handle->reader);
189 0 unexpected_qn.local = (char *)
190 xmlTextReaderConstLocalName(handle->reader);
191 }
192 0 result = GlobusSoapMessageErrorFailedEndElement(
193 handle->verbose,
194 &unexpected_qn);
195
196 0 goto exit;
197 }
198 5047633 else if (type == XML_READER_TYPE_TEXT)
199 {
200 0 xmlChar * str = NULL;
201 0 if (handle->verbose)
202 {
203 0 str = xmlTextReaderValue(handle->reader);
204 }
205 0 result = GlobusSoapMessageErrorFailedWithText(handle->verbose, str);
206
207 0 goto exit;
208 }
209 }
210
211 5044660 if(type == XML_READER_TYPE_END_ELEMENT)
212 {
213 xsd_QName qn;
214
215 5044660 if(handle->callout_table)
216 {
217 2749874 qn.local = (char *)
218 xmlTextReaderConstLocalName(handle->reader);
219 2749874 qn.Namespace = (char *)
220 xmlTextReaderConstNamespaceUri(handle->reader);
221
222 2749874 result = globus_soap_message_invoke_callouts(
223 handle,
224 &qn,
225 GLOBUS_SOAP_MESSAGE_CALLOUT_END);
226 }
227
228 5044660 if((idval = (char *) xmlTextReaderGetAttribute(
229 handle->reader,
230 (xmlChar *) "Id")) != NULL)
231 {
232 char * end_idval =
233 26 globus_common_create_string("%s-end", idval);
234
235 26 if(handle->next_ready == 0)
236 {
237 26 result = globus_l_soap_message_deserialize_read(handle);
238 26 if(result != GLOBUS_SUCCESS &&
239 !GlobusSoapMessageStatusFailedElementCheck(result))
240 {
241 2 result = GLOBUS_SUCCESS;
242 2 goto exit;
243 }
244
245 24 globus_soap_message_deserialize_push_element(handle);
246 }
247
248 24 result = globus_soap_message_deserialize_mark(
249 handle, end_idval);
250 24 if(result != GLOBUS_SUCCESS)
251 {
252 0 result = GlobusSoapMessageErrorSettingId(
253 result);
254 0 goto exit;
255 }
256 24 xmlFree(idval);
257 24 globus_free(end_idval);
258 }
259 }
260
261 5046816 exit:
262
263 5046816 GlobusSoapMessageDebugExit();
264 5046816 return result;
265 }
266 /* globus_soap_message_deserialize_element_end() */
267
268 /**
269 * Advance the XML parsing state to the end of the current element's closing tag
270 * @ingroup globus_soap_message_deserialize
271 *
272 * @param handle
273 * SOAP message handle to advance.
274 *
275 * @retval GLOBUS_SUCCESS
276 * XML parsing state advanced successfully.
277 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_FAILED_NEXT_NODE
278 * Unable to read another XML node.
279 */
280 globus_result_t
281 globus_soap_message_deserialize_skip(
282 globus_soap_message_handle_t handle)
283 0 {
284 0 globus_result_t result = GLOBUS_SUCCESS;
285 GlobusFuncName(globus_soap_message_deserialize_skip);
286 0 GlobusSoapMessageDebugEnter();
287
288 0 if(xmlTextReaderSkip(handle->reader, handle->next_ready) <= 0)
289 {
290 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
291 0 goto exit;
292 }
293
294 0 if(!handle->next_ready)
295 {
296 0 handle->next_ready++;
297 }
298
299 0 exit:
300
301 0 GlobusSoapMessageDebugExit();
302 0 return result;
303 }
304 /* globus_soap_message_deserialize_skip() */
305
306 globus_result_t
307 globus_i_soap_message_deserialize_next_content(
308 globus_soap_message_handle_t handle)
309 4920955 {
310 4920955 globus_result_t result = GLOBUS_SUCCESS;
311 4920955 xmlReaderTypes type = XML_READER_TYPE_NONE;
312 GlobusFuncName(globus_i_soap_message_deserialize_next_content);
313 4920955 GlobusSoapMessageDebugEnter();
314
315 4920955 if(xmlTextReaderIsEmptyElement(handle->reader))
316 {
317 0 goto exit;
318 }
319
320 14762865 while(type != XML_READER_TYPE_TEXT)
321 {
322 4920955 if(handle->next_ready > 0)
323 {
324 122 handle->next_ready--;
325 }
326 4920833 else if(xmlTextReaderRead(handle->reader) <= 0)
327 {
328 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
329 0 goto exit;
330 }
331
332 4920955 type = xmlTextReaderNodeType(handle->reader);
333 4920955 if(type == XML_READER_TYPE_END_ELEMENT)
334 {
335 /* no content in between nodes */
336 0 globus_soap_message_deserialize_push_element(handle);
337 0 goto exit;
338 }
339
340 4920955 if(type != XML_READER_TYPE_TEXT &&
341 type != XML_READER_TYPE_ATTRIBUTE)
342 {
343 0 result = GlobusSoapMessageErrorFailedContent();
344 0 goto exit;
345 }
346 }
347
348 4920955 exit:
349
350 4920955 GlobusSoapMessageDebugExit();
351 4920955 return result;
352 }
353 /* globus_i_soap_message_deserialize_next_content() */
354
355 /**
356 * Deserialize a SOAP envelope element
357 * @ingroup globus_soap_message_deserialize
358 * Deserializes the current element and is successfully only if the element
359 * is a SOAP envelope element. Additionally the marker named
360 * GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE will be set at the beginning of the
361 * envelope open element.
362 *
363 * @param handle
364 * SOAP message handle to deserialize the envelope from.
365 *
366 * @retval GLOBUS_SUCCESS
367 * Envelope successfully deserialized.
368 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
369 * Handle was NULL.
370 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
371 * Error deserializing envelope element.
372 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_ELEMENT_NOT_FOUND
373 * The next XML element is not a SOAP envelope element.
374 */
375 globus_result_t
376 globus_soap_message_deserialize_envelope(
377 globus_soap_message_handle_t handle)
378 21468 {
379 xsd_QName local_qn;
380 const xmlChar * local;
381 const xmlChar * soap_env;
382 21468 globus_result_t result = GLOBUS_SUCCESS;
383
384 GlobusFuncName(globus_soap_message_deserialize_envelope);
385 21468 GlobusSoapMessageDebugEnter();
386
387 21468 if (handle == NULL)
388 {
389 0 result = GlobusSoapMessageErrorNullParam;
390
391 0 goto exit;
392 }
393 21468 result = globus_soap_message_set_marker(
394 handle,
395 GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE);
396 21468 if(result != GLOBUS_SUCCESS)
397 {
398 0 result = GlobusSoapMessageErrorDeserializeFailed(
399 result, &soap_env_qname);
400 0 goto exit;
401 }
402
403 21468 result = globus_i_soap_message_deserialize_next_element(handle);
404 21468 if(result != GLOBUS_SUCCESS)
405 {
406 0 result = GlobusSoapMessageErrorDeserializeFailed(
407 result, &soap_env_qname);
408 0 goto exit;
409 }
410
411 21468 soap_env = xmlTextReaderConstString(handle->reader, (xmlChar *) SOAP_ENV);
412 21468 local = xmlTextReaderConstLocalName(handle->reader);
413 21468 if(soap_env != local)
414 {
415 0 if (handle->verbose)
416 {
417 0 local_qn.Namespace = (char *)
418 xmlTextReaderConstNamespaceUri(handle->reader);
419 0 local_qn.local = (char *) local;
420 }
421 0 result = GlobusSoapMessageErrorElementNotFound(
422 handle->verbose,
423 &soap_env_qname,
424 &local_qn);
425 0 goto exit;
426 }
427
428 21468 exit:
429
430 21468 GlobusSoapMessageDebugExit();
431 21468 return result;
432 }
433 /* globus_soap_message_deserialize_envelope() */
434
435 /**
436 * Deserialize the end tag for a SOAP envelope element
437 * @ingroup globus_soap_message_deserialize
438 * Deserializes the end tag of the element currently being processed and is
439 * successfully only if the element is a SOAP envelope element. Additionally
440 * the marker named GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE_END will be set at the
441 * end of the envelope close tag.
442 *
443 * @param handle
444 * SOAP message handle to deserialize the envelope from.
445 *
446 * @retval GLOBUS_SUCCESS
447 * Envelope successfully deserialized.
448 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
449 * Handle was NULL.
450 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
451 * Error deserializing envelope end tag.
452 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_WITH_MARKER
453 * Error setting end-of-envelope marker in the XML stream.
454 */
455 globus_result_t
456 globus_soap_message_deserialize_envelope_end(
457 globus_soap_message_handle_t handle)
458 21466 {
459 21466 globus_result_t result = GLOBUS_SUCCESS;
460 GlobusFuncName(globus_soap_message_deserialize_envelope_end);
461 21466 GlobusSoapMessageDebugEnter();
462
463 21466 result = globus_soap_message_deserialize_element_end(
464 handle,
465 &soap_env_qname);
466 21466 if(result != GLOBUS_SUCCESS)
467 {
468 0 result = GlobusSoapMessageErrorDeserializeFailed(
469 result, &soap_env_qname);
470 0 goto exit;
471 }
472
473 21466 result = globus_xio_handle_cntl(
474 handle->xio_handle, globus_i_soap_message_buffer_driver,
475 GLOBUS_XIO_BUFFER_SET_READ_MARKER_AT_INDEX,
476 GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE_END,
477 xmlTextReaderReadPosition(handle->reader));
478 21466 if(result != GLOBUS_SUCCESS)
479 {
480 0 result = GlobusSoapMessageErrorWithMarker(
481 result, "Failed to set read marker: %s",
482 GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE_END);
483 0 goto exit;
484 }
485
486 21466 exit:
487
488 21466 GlobusSoapMessageDebugExit();
489 21466 return result;
490 }
491 /* globus_soap_message_deserialize_envelope_end() */
492
493 /**
494 * Deserialize a SOAP header element
495 * @ingroup globus_soap_message_deserialize
496 * Deserializes the current element and is successfully only if the element
497 * is a SOAP header.
498 *
499 * @param handle
500 * SOAP message handle to deserialize the header from.
501 *
502 * @retval GLOBUS_SUCCESS
503 * Header successfully deserialized.
504 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
505 * Handle was NULL.
506 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
507 * Error deserializing header element.
508 */
509 globus_result_t
510 globus_soap_message_deserialize_header(
511 globus_soap_message_handle_t handle)
512 21468 {
513 const xmlChar * local;
514 const xmlChar * soap_header;
515 21468 globus_result_t result = GLOBUS_SUCCESS;
516
517 GlobusFuncName(globus_soap_message_deserialize_header);
518 21468 GlobusSoapMessageDebugEnter();
519
520 21468 if (handle == NULL)
521 {
522 0 result = GlobusSoapMessageErrorNullParam;
523
524 0 goto exit;
525 }
526 21468 result = globus_i_soap_message_deserialize_next_element(handle);
527 21468 if(result != GLOBUS_SUCCESS)
528 {
529 0 result = GlobusSoapMessageErrorDeserializeFailed(
530 result, &soap_header_qname);
531 0 goto exit;
532 }
533
534 21468 soap_header = xmlTextReaderConstString(
535 handle->reader,
536 (xmlChar *) SOAP_HEADER);
537 21468 local = xmlTextReaderConstLocalName(handle->reader);
538 21468 if(soap_header != local)
539 {
540 1 xsd_QName local_qn = { NULL, NULL };
541 1 if (handle->verbose)
542 {
543 0 local_qn.Namespace = (char *)
544 xmlTextReaderNamespaceUri(handle->reader);
545 0 local_qn.local = (char *) local;
546 }
547
548 1 result = GlobusSoapMessageErrorElementNotFound(
549 handle->verbose,
550 &soap_body_qname,
551 &local_qn);
552 1 goto exit;
553 }
554
555 21468 exit:
556
557 21468 GlobusSoapMessageDebugExit();
558 21468 return result;
559 }
560 /* globus_soap_message_deserialize_header() */
561
562 /**
563 * Deserialize the end tag for a SOAP header element
564 * @ingroup globus_soap_message_deserialize
565 * Deserializes the end tag of the element currently being processed and is
566 * successfully only if the element is a SOAP header element.
567 *
568 * @param handle
569 * SOAP message handle to deserialize the header from.
570 *
571 * @retval GLOBUS_SUCCESS
572 * Header successfully deserialized.
573 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
574 * Handle was NULL.
575 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
576 * Error deserializing header end tag.
577 */
578 globus_result_t
579 globus_soap_message_deserialize_header_end(
580 globus_soap_message_handle_t handle)
581 21467 {
582 21467 globus_result_t result = GLOBUS_SUCCESS;
583 GlobusFuncName(globus_soap_message_deserialize_header_end);
584 21467 GlobusSoapMessageDebugEnter();
585
586 21467 if (handle == NULL)
587 {
588 0 result = GlobusSoapMessageErrorNullParam;
589
590 0 goto exit;
591 }
592 21467 result = globus_soap_message_deserialize_element_end(
593 handle,
594 &soap_header_qname);
595 21467 if(result != GLOBUS_SUCCESS)
596 {
597 0 GlobusSoapMessageErrorDeserializeFailed(
598 result, &soap_header_qname);
599 0 goto exit;
600 }
601
602 21467 exit:
603
604 21467 GlobusSoapMessageDebugExit();
605 21467 return result;
606 }
607 /* globus_soap_message_deserialize_header_end() */
608
609 /**
610 * Add the QName of a header which must be understood
611 * @ingroup globus_soap_message_deserialize
612 * This is used internally by the SOAP processor to require that some trigger
613 * handles the named header element. The function
614 * globus_soap_message_check_required_headers() is called after processing
615 * all headers to determine that all necessary headers have been parsed.
616 *
617 * @param handle
618 * SOAP message handle to add the processing requirement to.
619 * @param qn
620 * Name of the element which must be processed
621 *
622 * @retval GLOBUS_SUCCESS
623 * Header element QName added to the mustUnderstand list successfully.
624 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
625 * One of @a handle or @a qn is NULL.
626 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
627 * Insufficient memory to add the header element QName to the
628 * mustUnderstand list.
629 */
630 globus_result_t
631 globus_soap_message_add_required_header_element(
632 globus_soap_message_handle_t handle,
633 const xsd_QName * qn)
634 3 {
635 3 globus_result_t result = GLOBUS_SUCCESS;
636 int rc;
637 xsd_QName * value;
638 GlobusFuncName(globus_soap_message_add_required_header_element);
639 3 GlobusSoapMessageDebugEnter();
640
641 3 if (handle == NULL || qn == NULL)
642 {
643 0 result = GlobusSoapMessageErrorNullParam;
644
645 0 goto out;
646 }
647 3 if(!handle->mustUnderstand_hash)
648 {
649 1 rc = globus_hashtable_init(
650 &handle->mustUnderstand_hash,
651 7,
652 xsd_QName_hash,
653 xsd_QName_keyeq);
654 1 if (rc != GLOBUS_SUCCESS)
655 {
656 0 result = GlobusSoapMessageErrorOutOfMemory;
657 0 goto out;
658 }
659 }
660
661 3 if (globus_hashtable_lookup(
662 &handle->mustUnderstand_hash,
663 (void *) qn) != NULL)
664 {
665 /* Already in the hash. Not really an error, I guess */
666 0 goto out;
667 }
668
669 3 result = xsd_QName_copy(&value, qn);
670 3 if (result != GLOBUS_SUCCESS)
671 {
672 0 goto out;
673 }
674
675 3 rc = globus_hashtable_insert(
676 &handle->mustUnderstand_hash,
677 value, value);
678 3 if (rc != GLOBUS_SUCCESS)
679 {
680 0 result = GlobusSoapMessageErrorNullParam;
681 }
682
683 3 out:
684 3 GlobusSoapMessageDebugExit();
685 3 return result;
686 }
687 /* globus_soap_message_add_required_header_element() */
688
689 /**
690 * Remove the QName of a header which must be understood from the list after processing it
691 * @ingroup globus_soap_message_deserialize
692 * This is used by header element triggers to indicate that they've processed
693 * a required SOAP header element.
694 *
695 * @param handle
696 * SOAP message handle to remove the processing requirement from.
697 * @param qn
698 * Name of the element which was processed.
699 *
700 * @retval GLOBUS_SUCCESS
701 * Header element QName removed from the mustUnderstand list successfully.
702 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
703 * One of @a handle or @a qn is NULL.
704 */
705 globus_result_t
706 globus_soap_message_remove_required_header_element(
707 globus_soap_message_handle_t handle,
708 const xsd_QName * qn)
709 40087 {
710 xsd_QName * entry;
711 40087 globus_result_t result = GLOBUS_SUCCESS;
712 GlobusFuncName(globus_soap_message_remove_required_header_element);
713 40087 GlobusSoapMessageDebugEnter();
714
715 40087 if (handle == NULL || qn == NULL)
716 {
717 0 result = GlobusSoapMessageErrorNullParam;
718
719 0 goto out;
720 }
721 40087 if(handle->mustUnderstand_hash)
722 {
723 15 entry = globus_hashtable_remove(
724 &handle->mustUnderstand_hash, (void *)qn);
725 15 if (entry)
726 {
727 3 xsd_QName_destroy(entry);
728 }
729 }
730
731 40087 out:
732 40087 GlobusSoapMessageDebugExit();
733 40087 return result;
734 }
735 /* globus_soap_message_remove_required_header_element() */
736
737 /**
738 * Verify that all headers which must be understood have been processed
739 * @ingroup globus_soap_message_deserialize
740 * This is used internally by the SOAP processor to check that all headers
741 * which had the mustUnderstand attribute have been processed by a handler.
742 *
743 * @param handle
744 * SOAP message handle to check.
745 *
746 * @retval GLOBUS_SUCCESS
747 * All required headers have been processed.
748 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
749 * @a Handle is NULL.
750 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_MUST_UNDERSTAND
751 * Some required header was not processed.
752 */
753 globus_result_t
754 globus_soap_message_check_required_headers(
755 globus_soap_message_handle_t handle)
756 21216 {
757 xsd_QName * element;
758 21216 globus_result_t result = GLOBUS_SUCCESS;
759 GlobusFuncName(globus_soap_message_check_required_headers);
760 21216 GlobusSoapMessageDebugEnter();
761
762 21216 if (handle == NULL)
763 {
764 0 result = GlobusSoapMessageErrorNullParam;
765
766 0 goto out;
767 }
768 21216 if(!handle->mustUnderstand_hash)
769 {
770 /* Nothing to understand, so we're fine. */
771 21213 goto out;
772 }
773
774 3 element = globus_hashtable_first(&handle->mustUnderstand_hash);
775
776 6 while(element)
777 {
778 0 result = GlobusSoapMessageErrorMustUnderstand(
779 result, element);
780 0 element = globus_hashtable_next(&handle->mustUnderstand_hash);
781 }
782
783 3 GlobusSoapMessageDebugExit();
784 21216 out:
785 21216 return result;
786 }
787 /* globus_soap_message_check_required_headers() */
788
789 /**
790 * Deserialize a SOAP body element
791 * @ingroup globus_soap_message_deserialize
792 * Deserializes the current element and is successfully only if the element
793 * is a SOAP body.
794 *
795 * @param handle
796 * SOAP message handle to deserialize the body from.
797 *
798 * @retval GLOBUS_SUCCESS
799 * Header successfully deserialized.
800 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
801 * Handle was NULL.
802 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
803 * Error deserializing body element.
804 */
805 globus_result_t
806 globus_soap_message_deserialize_body(
807 globus_soap_message_handle_t handle)
808 21468 {
809 const xmlChar * local;
810 const xmlChar * soap_body;
811 xsd_QName local_qn;
812 21468 globus_result_t result = GLOBUS_SUCCESS;
813
814 GlobusFuncName(globus_soap_message_deserialize_body);
815 21468 GlobusSoapMessageDebugEnter();
816
817 /* Should this just be a call to globus_soap_message_deserialize_element()?
818 */
819 21468 result = globus_i_soap_message_deserialize_next_element(handle);
820 21468 if(result != GLOBUS_SUCCESS)
821 {
822 0 result = GlobusSoapMessageErrorDeserializeFailed(
823 result, &soap_body_qname);
824 0 goto exit;
825 }
826
827 21468 soap_body = xmlTextReaderConstString(handle->reader, (xmlChar *) SOAP_BODY);
828 21468 local = xmlTextReaderConstLocalName(handle->reader);
829 21468 if(soap_body != local)
830 {
831 0 if (handle->verbose)
832 {
833 0 local_qn.Namespace = (char *)
834 xmlTextReaderNamespaceUri(handle->reader);
835 0 local_qn.local = (char *) local;
836 }
837
838 0 result = GlobusSoapMessageErrorElementNotFound(
839 handle->verbose,
840 &soap_body_qname,
841 &local_qn);
842 0 goto exit;
843 }
844
845 21468 exit:
846
847 21468 GlobusSoapMessageDebugExit();
848 21468 return result;
849 }
850
851 /**
852 * Deserialize a SOAP fault
853 * @ingroup globus_soap_message_deserialize
854 * Deserializes a SOAP fault element, calling @a fault_callback to convert
855 * the fault element type to the service-specific fault type enumeration
856 * value.
857 *
858 * @param handle
859 * SOAP message handle to deserialize the fault from.
860 * @param soap_fault_handle
861 * Pointer to the fault implementation.
862 * @param fault_callback
863 * Service-specific callback function to invoke
864 * @param fault_any
865 * Pointer to be set to the value of the fault detail.
866 * @param fault_type
867 * Pointer to be set to the service-specific fault enumeration value
868 * by the @a fault_callback.
869 */
870 globus_result_t
871 globus_soap_message_deserialize_fault(
872 globus_soap_message_handle_t handle,
873 globus_soap_message_fault_t * soap_fault_handle,
874 globus_soap_fault_callback_func_t fault_callback,
875 xsd_any ** fault_any,
876 int * fault_type)
877 11447 {
878 const xmlChar * local;
879 const xmlChar * soap_fault;
880 const xmlChar * element_name;
881 const xmlChar * faultcode_name;
882 const xmlChar * faultstring_name;
883 const xmlChar * faultactor_name;
884 const xmlChar * detail_name;
885 globus_xml_buffer * detail_buffer;
886 11447 globus_result_t result = GLOBUS_SUCCESS;
887 11447 globus_soap_message_fault_t fault = NULL;
888 GlobusFuncName(globus_soap_message_deserialize_fault);
889
890 /* This seems pretty complicated. Can this be replaced by an automatic
891 * deserializer generated from a schema?
892 */
893 11447 GlobusSoapMessageDebugEnter();
894
895 11447 if (handle == NULL || soap_fault_handle == NULL ||
896 fault_any == NULL || fault_type == NULL)
897 {
898 0 result = GlobusSoapMessageErrorNullParam;
899 0 goto exit;
900 }
901
902 11447 result = globus_i_soap_message_deserialize_next_element(handle);
903 11447 if(result != GLOBUS_SUCCESS)
904 {
905 0 result = GlobusSoapMessageErrorDeserializeFailed(
906 result, &soap_fault_qname);
907 0 goto exit;
908 }
909
910 11447 soap_fault = xmlTextReaderConstString(
911 handle->reader,
912 (xmlChar *) SOAP_FAULT);
913 11447 local = xmlTextReaderConstLocalName(handle->reader);
914 11447 if(soap_fault != local)
915 {
916 11195 globus_soap_message_deserialize_push_element(handle);
917 11195 goto exit;
918 }
919
920 252 globus_soap_message_fault_init(&fault);
921
922 252 faultcode_name = xmlTextReaderConstString(
923 handle->reader, (xmlChar *) SOAP_FAULTCODE);
924 252 faultactor_name = xmlTextReaderConstString(
925 handle->reader, (xmlChar *) SOAP_FAULTACTOR);
926 252 faultstring_name = xmlTextReaderConstString(
927 handle->reader, (xmlChar *) SOAP_FAULTSTRING);
928 252 detail_name = xmlTextReaderConstString(
929 handle->reader, (xmlChar *) SOAP_FAULT_DETAIL);
930
931 1008 while(result == GLOBUS_SUCCESS)
932 {
933 756 result = globus_i_soap_message_deserialize_next_element(handle);
934 756 if(result != GLOBUS_SUCCESS)
935 {
936 7 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
937 GlobusSoapMessageStatusFailedWithTextCheck(result))
938 {
939 7 globus_soap_message_deserialize_push_element(handle);
940 7 result = GLOBUS_SUCCESS;
941 7 break;
942 }
943
944 0 result = GlobusSoapMessageErrorDeserializeFailed(
945 result, &soap_fault_qname);
946 0 goto exit;
947 }
948
949 749 element_name = xmlTextReaderConstLocalName(handle->reader);
950 749 if(element_name == faultcode_name)
951 {
952 252 result = globus_i_soap_message_deserialize_next_content(handle);
953 252 if(result != GLOBUS_SUCCESS)
954 {
955 0 result = GlobusSoapMessageErrorDeserializeFailed(
956 result, &soap_fault_qname);
957 0 goto exit;
958 }
959
960 252 fault->faultcode = (char *) xmlTextReaderValue(handle->reader);
961 }
962 497 else if(element_name == faultstring_name)
963 {
964 252 result = globus_i_soap_message_deserialize_next_content(handle);
965 252 if(result != GLOBUS_SUCCESS)
966 {
967 0 result = GlobusSoapMessageErrorDeserializeFailed(
968 result, &soap_faultstring_qname);
969 0 goto exit;
970 }
971
972 252 fault->faultstring = (char *) xmlTextReaderValue(handle->reader);
973 }
974 245 else if(element_name == faultactor_name)
975 {
976 0 result = globus_i_soap_message_deserialize_next_content(handle);
977 0 if(result != GLOBUS_SUCCESS)
978 {
979 0 result = GlobusSoapMessageErrorDeserializeFailed(
980 result, &soap_fault_qname);
981 0 goto exit;
982 }
983
984 0 fault->faultactor = (char *) xmlTextReaderValue(handle->reader);
985 }
986 245 else if(element_name == detail_name)
987 {
988 245 xsd_any * dummy_any = NULL;
989 xsd_QName fault_qname;
990
991 245 result = globus_soap_message_deserialize_element_unknown(
992 handle, &fault_qname);
993 245 if(result != GLOBUS_SUCCESS)
994 {
995 0 result = GlobusSoapMessageErrorDeserializeFailed(
996 result, &soap_fault_detail_qname);
997 0 goto exit;
998 }
999
1000 245 globus_soap_message_deserialize_push_element(handle);
1001
1002 245 globus_soap_message_set_marker(handle, "FAULT_DETAIL_BEGIN");
1003
1004 245 xsd_any_init(fault_any);
1005
1006 245 result = xsd_any_deserialize(
1007 NULL, (*fault_any), handle, 0);
1008 245 if(result != GLOBUS_SUCCESS)
1009 {
1010 0 result = GlobusSoapMessageErrorDeserializeFailed(
1011 result, &soap_fault_detail_qname);
1012 0 goto exit;
1013 }
1014
1015 245 globus_soap_message_set_marker(handle, "FAULT_DETAIL_END");
1016
1017 245 xsd_any_init(&fault->detail);
1018 245 fault->detail->any_info = (&globus_xml_buffer_contents_info);
1019
1020 245 globus_xml_buffer_init(&detail_buffer);
1021 245 result = globus_soap_message_get_marked_buffers(
1022 handle,
1023 "FAULT_DETAIL_BEGIN",
1024 "FAULT_DETAIL_END",
1025 &detail_buffer->buffer,
1026 (size_t *)&detail_buffer->length);
1027 245 if(result != GLOBUS_SUCCESS)
1028 {
1029 0 globus_xml_buffer_destroy(detail_buffer);
1030 0 result = GlobusSoapMessageErrorDeserializeFailed(
1031 result, &soap_fault_detail_qname);
1032 0 goto exit;
1033 }
1034
1035 245 fault->detail->value = detail_buffer;
1036
1037 245 if (fault_callback != NULL)
1038 {
1039 245 fault_callback(handle,
1040 (*fault_any)->any_info->type,
1041 fault_type);
1042 }
1043
1044 do
1045 {
1046 245 result = xsd_any_deserialize_pointer(
1047 NULL, &dummy_any, handle, 0);
1048 245 if(result != GLOBUS_SUCCESS)
1049 {
1050 245 if(GlobusSoapMessageStatusFailedElementCheck(result))
1051 {
1052 245 result = GLOBUS_SUCCESS;
1053 245 goto exit;
1054 }
1055
1056 0 result = GlobusSoapMessageErrorDeserializeFailed(
1057 result, &soap_fault_detail_qname);
1058 0 goto exit;
1059 }
1060 0 xsd_any_destroy(dummy_any);
1061 0 dummy_any = NULL;
1062
1063 0 } while(result == GLOBUS_SUCCESS);
1064
1065 0 break;
1066 }
1067 else
1068 {
1069 0 result = GlobusSoapMessageErrorUnexpectedElement(
1070 &soap_fault_qname);
1071 0 goto exit;
1072 }
1073
1074 504 result = globus_soap_message_deserialize_element_end(
1075 handle,
1076 &soap_fault_qname);
1077 504 if(result != GLOBUS_SUCCESS)
1078 {
1079 0 result = GlobusSoapMessageErrorDeserializeFailed(
1080 result, &soap_fault_qname);
1081 0 goto exit;
1082 }
1083 }
1084
1085 11447 exit:
1086
1087 11447 *soap_fault_handle = fault;
1088
1089 11447 GlobusSoapMessageDebugExit();
1090 11447 return result;
1091 }
1092 /* globus_soap_message_deserialize_fault() */
1093
1094 /**
1095 * Predicate returns true if the element being deserialized has a true xsi:nil attribute
1096 * @ingroup globus_soap_message_serialize
1097 * Checks to see if the element currently being deserialized has
1098 * the {http://www.w3.org/2001/XMLSchema-instance}nil attribute with the
1099 * value <code>true</code>. If so, this function returns GLOBUS_TRUE;
1100 * otherwise, it returns GLOBUS_FALSE.
1101 *
1102 * @param handle
1103 * Handle to check for a xsi:nil attribute.
1104 *
1105 * @retval GLOBUS_TRUE
1106 * The current element is nil.
1107 * @retval GLOBUS_FALSE
1108 * The current element is not nil.
1109 */
1110 globus_bool_t
1111 globus_soap_message_deserialize_element_is_nil(
1112 globus_soap_message_handle_t handle)
1113 4832956 {
1114 xmlChar * nil_value;
1115 GlobusFuncName(globus_soap_message_deserialize_element_is_nil);
1116 4832956 GlobusSoapMessageDebugEnter();
1117
1118 4832956 globus_assert(handle != NULL);
1119
1120 4832956 nil_value = xmlTextReaderGetAttributeNs(
1121 handle->reader,
1122 (xmlChar *) XSI_NIL,
1123 (xmlChar *) XSI_NS);
1124 4832956 if(nil_value && !(xmlStrcmp(nil_value, (xmlChar *) "true")))
1125 {
1126 26 xmlFree(nil_value);
1127 26 return GLOBUS_TRUE;
1128 }
1129
1130 4832930 if(!nil_value)
1131 {
1132 4832930 xmlFree(nil_value);
1133 }
1134
1135 4832930 return GLOBUS_FALSE;
1136 }
1137 /* globus_soap_message_deserialize_element_is_nil() */
1138
1139 /**
1140 * Deserialize the next element and return its QName
1141 * @ingroup globus_soap_message_deserialize
1142 * Deserializes the opening tag of the next element. If
1143 * the parser is able to read an element, @a qname will be populated with
1144 * the contents of the element's QName. The caller is responsible for freeing
1145 * the QName.
1146 *
1147 * @param handle
1148 * The SOAP message handle to parse the next element on.
1149 * @param qname
1150 * Pointer to an xsd_QName. If parsing is successful, the
1151 * Namespace and local fields of this will be modified to contain
1152 * information about the element's QName.
1153 *
1154 * @retval GLOBUS_SUCCESS
1155 * The element was successfully deserialized.
1156 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1157 * One of @a handle or @a qname is NULL.
1158 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
1159 * Insufficient memory to set the fields of @a qname.
1160 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
1161 * Unable to parse the next XML element.
1162 */
1163 globus_result_t
1164 globus_soap_message_deserialize_element_unknown(
1165 globus_soap_message_handle_t handle,
1166 xsd_QName * qname)
1167 2804870 {
1168 2804870 globus_result_t result = GLOBUS_SUCCESS;
1169 const xmlChar * tmp;
1170 GlobusFuncName(globus_soap_message_deserialize_element);
1171
1172 2804870 GlobusSoapMessageDebugEnter();
1173
1174 2804870 if (handle == NULL || qname == NULL)
1175 {
1176 0 result = GlobusSoapMessageErrorNullParam;
1177
1178 0 goto exit;
1179 }
1180
1181 2804870 result = globus_i_soap_message_deserialize_next_element(handle);
1182 2804870 if(result != GLOBUS_SUCCESS)
1183 {
1184 22008 xsd_QName * q = NULL;
1185
1186 22008 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
1187 GlobusSoapMessageStatusFailedWithTextCheck(result))
1188 {
1189 22008 globus_soap_message_deserialize_push_element(handle);
1190 22008 goto exit;
1191 }
1192 else
1193 {
1194 0 result = GlobusSoapMessageErrorDeserializeFailed(
1195 result, q);
1196 }
1197 0 goto exit;
1198 }
1199
1200 2782862 qname->local = globus_libc_strdup(
1201 (char *) xmlTextReaderConstLocalName(handle->reader));
1202 2782862 if (qname->local == NULL)
1203 {
1204 0 result = GlobusSoapMessageErrorOutOfMemory;
1205
1206 0 goto push_element_exit;
1207 }
1208 2782862 tmp = xmlTextReaderConstNamespaceUri(handle->reader);
1209 2782862 if (tmp)
1210 {
1211 2782811 qname->Namespace = globus_libc_strdup((char *) tmp);
1212 2782811 if (qname->Namespace == NULL)
1213 {
1214 0 result = GlobusSoapMessageErrorOutOfMemory;
1215
1216 0 goto free_local_exit;
1217 }
1218 }
1219 else
1220 {
1221 51 qname->Namespace = NULL;
1222 }
1223
1224 2782862 if (result != GLOBUS_SUCCESS)
1225 {
1226 0 free_local_exit:
1227 0 free(qname->local);
1228 0 qname->local = NULL;
1229 0 push_element_exit:
1230 0 globus_soap_message_deserialize_push_element(handle);
1231 }
1232 2804870 exit:
1233
1234 2804870 GlobusSoapMessageDebugExit();
1235 2804870 return result;
1236 }
1237 /* globus_soap_message_deserialize_element_unknown() */
1238
1239 /**
1240 * Predicate returns true if the element being deserialized has no content
1241 * @ingroup globus_soap_message_serialize
1242 * Checks to see if the element currently being deserialized has
1243 * any content within the element start and end tags. If not, this function
1244 * returns GLOBUS_TRUE; otherwise, GLOBUS_FALSE.
1245 *
1246 * @param handle
1247 * Handle to check for an element without any content.
1248 *
1249 * @retval GLOBUS_TRUE
1250 * The elemnet currently being deserialized has no content or subelements.
1251 * @retval GLOBUS_FALSE
1252 * The elemnet currently being deserialized has content or subelements.
1253 */
1254 globus_bool_t
1255 globus_soap_message_deserialize_element_is_empty(
1256 globus_soap_message_handle_t handle)
1257 2652438 {
1258 2652438 globus_assert(handle != NULL);
1259 2652438 return ((handle->next_ready == 0) &&
1260 xmlTextReaderIsEmptyElement(handle->reader));
1261 }
1262 /* globus_soap_message_deserialize_element_is_empty() */
1263
1264 /**
1265 * Deserialize the next element from a SOAP message handle
1266 * @ingroup globus_soap_message_deserialize
1267 * Deserializes the next open element tag on a SOAP message handle. Returns
1268 * success only if the next node in the XML stream is an element tag and
1269 * the element's name matches @a qname (provided @a qname is non-NULL).
1270 *
1271 * @param handle
1272 * The SOAP message handle to parse the next element on.
1273 * @param qname
1274 * QName of the expected element.
1275 *
1276 * @retval GLOBUS_SUCCESS
1277 * Element deserialized successfully.
1278 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1279 * The @a handle parameter is NULL.
1280 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
1281 * Unable to deserialize the next element.
1282 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_ELEMENT_NOT_FOUND
1283 * The next XML element does not match @a qname.
1284 */
1285 globus_result_t
1286 globus_soap_message_deserialize_element(
1287 globus_soap_message_handle_t handle,
1288 const xsd_QName * qname)
1289 9914218 {
1290 const xmlChar * local;
1291 const xmlChar * local_ns;
1292 const xmlChar * element;
1293 const xmlChar * element_ns;
1294 xsd_QName local_qn;
1295 9914218 globus_result_t result = GLOBUS_SUCCESS;
1296 GlobusFuncName(globus_soap_message_deserialize_element);
1297
1298 9914218 GlobusSoapMessageDebugEnter();
1299
1300 9914218 if (handle == NULL)
1301 {
1302 0 result = GlobusSoapMessageErrorNullParam;
1303
1304 0 goto exit;
1305 }
1306
1307 9914218 result = globus_i_soap_message_deserialize_next_element(handle);
1308 9914218 if(result != GLOBUS_SUCCESS)
1309 {
1310 97494 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
1311 GlobusSoapMessageStatusFailedWithTextCheck(result))
1312 {
1313 97494 if (!xmlTextReaderIsEmptyElement(handle->reader))
1314 {
1315 97210 globus_soap_message_deserialize_push_element(handle);
1316 }
1317
1318 97494 goto exit;
1319 }
1320 else
1321 {
1322 0 result = GlobusSoapMessageErrorDeserializeFailed(
1323 result, qname);
1324 }
1325 0 goto exit;
1326 }
1327
1328 9816724 if(qname)
1329 {
1330 4972929 element = xmlTextReaderConstString(
1331 handle->reader,
1332 (xmlChar *) qname->local);
1333 4972929 local = xmlTextReaderConstString(
1334 handle->reader, xmlTextReaderConstLocalName(handle->reader));
1335 4972929 if(element != local)
1336 {
1337 926 if (handle->verbose)
1338 {
1339 632 local_qn.Namespace = (char *) xmlTextReaderConstString(
1340 handle->reader,
1341 xmlTextReaderConstNamespaceUri(handle->reader));
1342 632 local_qn.local = (char *) local;
1343 }
1344 926 globus_soap_message_deserialize_push_element(handle);
1345
1346 926 result = GlobusSoapMessageErrorElementNotFound(
1347 handle->verbose,
1348 qname,
1349 &local_qn);
1350 926 goto exit;
1351 }
1352
1353 4972003 element_ns = xmlTextReaderConstString(
1354 handle->reader, (xmlChar *) qname->Namespace);
1355 4972003 local_ns = xmlTextReaderConstString(
1356 handle->reader, xmlTextReaderConstNamespaceUri(handle->reader));
1357 4972003 if((local_ns && element_ns != local_ns)
1358 /* || (element_ns && !local_ns) */)
1359 {
1360 0 if (handle->verbose)
1361 {
1362 0 local_qn.Namespace = (char *) local_ns;
1363 0 local_qn.local = (char *) local;
1364 }
1365 0 result = GlobusSoapMessageErrorElementNotFound(
1366 handle->verbose,
1367 qname,
1368 &local_qn);
1369 0 goto exit;
1370 }
1371 }
1372
1373 9914218 exit:
1374
1375 9914218 GlobusSoapMessageDebugExit();
1376 9914218 return result;
1377 }
1378 /* globus_soap_message_deserialize_element() */
1379
1380 /**
1381 * Deserialize an XML attribute of the current element
1382 * @ingroup globus_soap_message_deserialize
1383 * Attempts to deserialize an XML attribute (named @a attr_qname) of the
1384 * current element being deserialized. If it is present, its NULL-terminated
1385 * string value will be copied into a newly allocated buffer and @a content
1386 * will be updated to point to the value.
1387 *
1388 * @param handle
1389 * SOAP message handle to deserialize the attribute from.
1390 * @param attr_qname
1391 * QName of the attribute to deserialize.
1392 * @param content
1393 * Pointer to be set to the value of the attribute. If this is set to
1394 * point to a non-NULL value, the caller must free the buffer
1395 * by calling xmlFree().
1396 *
1397 * @retval GLOBUS_SUCCESS
1398 * Attribute deserialized successfully.
1399 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1400 * One of @a handle, @a attr_qname, or @a content is NULL.
1401 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_ATTRIBUTE_NOT_FOUND
1402 * The attrbute is not present.
1403 */
1404 globus_result_t
1405 globus_soap_message_deserialize_attribute(
1406 globus_soap_message_handle_t handle,
1407 const xsd_QName * attr_qname,
1408 xmlChar ** content)
1409 157971 {
1410 const xmlChar * attr_ns;
1411 const xmlChar * local_ns;
1412 const xmlChar * attr_local;
1413 157971 globus_result_t result = GLOBUS_SUCCESS;
1414
1415 157971 if (handle == NULL || attr_qname == NULL || content == NULL ||
1416 attr_qname->local == NULL)
1417 {
1418 0 result = GlobusSoapMessageErrorNullParam;
1419
1420 0 goto exit;
1421 }
1422 157971 attr_ns = xmlTextReaderConstString(
1423 handle->reader, (xmlChar *) attr_qname->Namespace);
1424 157971 local_ns = xmlTextReaderConstNamespaceUri(handle->reader);
1425 157971 attr_local = xmlTextReaderConstString(
1426 handle->reader, (xmlChar *) attr_qname->local);
1427
1428 160696 if (xmlTextReaderNodeType(handle->reader) == XML_READER_TYPE_ATTRIBUTE &&
1429 attr_ns == local_ns &&
1430 xmlTextReaderConstLocalName(handle->reader) == attr_local)
1431 {
1432 2725 *content = xmlTextReaderValue(handle->reader);
1433 }
1434 285493 else if(attr_ns != local_ns && (attr_ns != NULL) && (*attr_ns != '\0'))
1435 {
1436 130247 *content = xmlTextReaderGetAttributeNs(
1437 handle->reader,
1438 (xmlChar *) attr_qname->local,
1439 attr_ns);
1440 }
1441 else
1442 {
1443 24999 *content = xmlTextReaderGetAttribute(
1444 handle->reader, (xmlChar *) attr_qname->local);
1445 }
1446 157971 if(! (*content))
1447 {
1448 147960 result = GlobusSoapMessageErrorAttributeNotFound(
1449 handle->verbose,
1450 attr_qname);
1451 147960 goto exit;
1452 }
1453 157971 exit:
1454 157971 return result;
1455 }
1456 /* globus_soap_message_deserialize_attribute() */
1457
1458 /**
1459 * Set a named deserialization marker at the current location in the XML stream
1460 * @ingroup globus_soap_message_deserialize
1461 *
1462 * @param handle
1463 * SOAP message handle to mark.
1464 * @param idval
1465 * Name of the marker.
1466 *
1467 * @retval GLOBUS_SUCCESS
1468 * Marker set successfully.
1469 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1470 * One of @a handle or @a idval is NULL.
1471 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_WITH_MARKER
1472 * Unable to set the marker.
1473 */
1474 globus_result_t
1475 globus_soap_message_deserialize_mark(
1476 globus_soap_message_handle_t handle,
1477 const char * idval)
1478 97 {
1479 97 globus_result_t result = GLOBUS_SUCCESS;
1480 GlobusFuncName(globus_soap_message_deserialize_mark);
1481 97 GlobusSoapMessageDebugEnter();
1482
1483 97 if (handle == NULL || idval == NULL)
1484 {
1485 0 result = GlobusSoapMessageErrorNullParam;
1486 0 goto exit;
1487 }
1488
1489 97 GlobusSoapMessageDebugPrintf(
1490 GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
1491 ("SETTING MARK: %s\n", idval));
1492
1493 97 if(handle->xio_handle)
1494 {
1495 93 result = globus_xio_handle_cntl(
1496 handle->xio_handle, globus_i_soap_message_buffer_driver,
1497 GLOBUS_XIO_BUFFER_SET_READ_MARKER_AT_INDEX,
1498 idval,
1499 xmlTextReaderReadPosition(handle->reader));
1500 93 if(result != GLOBUS_SUCCESS)
1501 {
1502 0 result = GlobusSoapMessageErrorWithMarker(
1503 result, "Failed to set read marker: %s", idval);
1504 0 goto exit;
1505 }
1506 }
1507
1508 97 exit:
1509
1510 97 GlobusSoapMessageDebugExit();
1511 97 return result;
1512 }
1513 /* globus_soap_message_deserialize_mark() */
1514
1515 /**
1516 * Deserialize a concrete path expression
1517 * @ingroup globus_soap_message_serialize
1518 * Deserializes the current element's content, and maps strings of the form
1519 * prefix:pathel[/pathel...] to a namespace and array of path elements. This
1520 * is used by the TopicExpression path deserializer.
1521 *
1522 * @param handle
1523 * SOAP message handle to deserialize the concrete path from.
1524 * @param Namespace
1525 * Pointer to an xsd_anyURI which will be populated by this function with
1526 * the namespace of the path.
1527 * @param path
1528 * Pointer to an array of xsd_NCName values which will be set to the
1529 * elements of the path.
1530 *
1531 * @retval GLOBUS_SUCCESS
1532 * Concrete path deserialized successfully.
1533 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1534 * One of @a handle, @a Namespace, or @a path is NULL.
1535 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_DESERIALIZE_FAILED
1536 * Unable to deserialize the content of the current element, or it
1537 * does not match the concrete path content pattern.
1538 */
1539 globus_result_t
1540 globus_soap_message_deserialize_concrete_path(
1541 globus_soap_message_handle_t handle,
1542 xsd_anyURI * Namespace,
1543 xsd_NCName_array * path)
1544 0 {
1545 xmlChar * prefix;
1546 const char * tmp_value;
1547 xmlChar * token;
1548 0 globus_result_t result = GLOBUS_SUCCESS;
1549 int start_token;
1550 int end_token;
1551 xmlChar * val;
1552 xsd_NCName * el;
1553
1554 GlobusFuncName(globus_soap_message_deserialize_concrete_path);
1555 0 GlobusSoapMessageDebugEnter();
1556
1557 0 if (handle == NULL || Namespace == NULL || path == NULL)
1558 {
1559 0 result = GlobusSoapMessageErrorNullParam;
1560
1561 0 goto exit;
1562 }
1563
1564 0 result = globus_i_soap_message_deserialize_next_content(handle);
1565 0 if(result != GLOBUS_SUCCESS)
1566 {
1567 0 result = GlobusSoapMessageErrorDeserializeFailed(
1568 result, &xsd_QName_qname);
1569 0 goto exit;
1570 }
1571
1572 0 tmp_value = (const char *) xmlTextReaderConstValue(handle->reader);
1573 0 if(!tmp_value)
1574 {
1575 0 result = GlobusSoapMessageErrorDeserializeFailed(
1576 result, &xsd_QName_qname);
1577 0 goto exit;
1578 }
1579 0 token = (xmlChar *) globus_l_soap_message_my_strtok(
1580 tmp_value,
1581 strlen(tmp_value), &start_token, &end_token, "\n\t /");
1582 0 if (token == NULL)
1583 {
1584 0 result = GlobusSoapMessageErrorDeserializeFailed(
1585 result, &xsd_QName_qname);
1586 0 goto exit;
1587 }
1588
1589 0 val = xmlSplitQName2(token, &prefix);
1590 0 el = xsd_NCName_array_push(path);
1591 0 *el = (xsd_NCName) val;
1592 0 if(prefix)
1593 {
1594 0 *Namespace =
1595 (xsd_anyURI) xmlTextReaderLookupNamespace(handle->reader, prefix);
1596 0 xmlFree(prefix);
1597 }
1598 0 free(token);
1599 0 tmp_value += end_token;
1600
1601 do
1602 {
1603 0 token = (xmlChar *) globus_l_soap_message_my_strtok(
1604 tmp_value, strlen(tmp_value), &start_token, &end_token, "\n\t /");
1605 0 tmp_value += end_token;
1606
1607 0 if (token != NULL && strlen((char *) token) != 0)
1608 {
1609 0 el = xsd_NCName_array_push(path);
1610 0 *el = (xsd_NCName) token;
1611 }
1612 }
1613 0 while (token != NULL && end_token != -1);
1614
1615 0 exit:
1616
1617 0 GlobusSoapMessageDebugExit();
1618 0 return result;
1619 }
1620 /* globus_soap_message_deserialize_concrete_path() */
1621
1622 /**
1623 * Get the namespace prefixes defined in the current XML deserialization context
1624 * @ingroup globus_soap_message_deserialize
1625 * Modifies the contents of the @a namespace_prefixes parameter to have an
1626 * entry of the form "prefix=namespace" for each namespace prefix defined in
1627 * the current XML deserialization context.
1628 *
1629 * @param handle
1630 * SOAP message handle to get the namespaces list from.
1631 * @param namespace_prefixes
1632 * Pointer to an uninitialized xsd_string_array. After successful
1633 * completion, this will be updated to include an array entry for
1634 * each namespace.
1635 *
1636 * @retval GLOBUS_SUCCESS
1637 * Namespace prefixes successfully copied to @a namespace_prefixes.
1638 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_NULL_PARAM
1639 * One of @a handle or @a namespace_prefixes is NULL.
1640 * @retval GLOBUS_SOAP_MESSAGE_ERROR_TYPE_OUT_OF_MEMORY
1641 * Insufficient memory to copy namespace prefix definitions into the
1642 * @a namespace_prefixes array.
1643 */
1644 globus_result_t
1645 globus_soap_message_deserialize_get_prefixes(
1646 globus_soap_message_handle_t handle,
1647 xsd_string_array * namespace_prefixes)
1648 2661633 {
1649 xsd_string * new_string;
1650 xmlNsPtr * ns_list;
1651 2661633 globus_result_t result = GLOBUS_SUCCESS;
1652 int i;
1653 GlobusFuncName(globus_soap_message_get_prefixes);
1654 2661633 GlobusSoapMessageDebugEnter();
1655
1656 2661633 if (handle == NULL || namespace_prefixes == NULL)
1657 {
1658 0 result = GlobusSoapMessageErrorNullParam;
1659
1660 0 goto out;
1661 }
1662 2661633 result = xsd_string_array_init_contents(namespace_prefixes);
1663
1664 2661633 if (result != GLOBUS_SUCCESS)
1665 {
1666 0 goto out;
1667 }
1668 2661633 handle->doc_to_free = xmlTextReaderCurrentDoc(handle->reader);
1669 2661633 ns_list = xmlGetNsList(
1670 handle->doc_to_free,
1671 xmlTextReaderCurrentNode(handle->reader));
1672
1673 2661633 if (ns_list != NULL)
1674 {
1675 16396592 for (i = 0; ns_list[i] != NULL; i++)
1676 {
1677 13734959 if (ns_list[i]->prefix != NULL)
1678 {
1679 11103531 new_string = xsd_string_array_push(namespace_prefixes);
1680
1681 11103531 if (new_string == NULL)
1682 {
1683 0 result = GlobusSoapMessageErrorOutOfMemory;
1684
1685 0 goto free_nslist;
1686 }
1687 11103531 *new_string = globus_common_create_string(
1688 "%s=%s",
1689 ns_list[i]->prefix,
1690 ns_list[i]->href);
1691 11103531 if (*new_string == NULL)
1692 {
1693 0 goto free_nslist;
1694 }
1695 }
1696 }
1697 }
1698
1699 2661633 free_nslist:
1700 2661633 if (ns_list != NULL)
1701 {
1702 2661633 xmlFree(ns_list);
1703 }
1704 2661633 if (result != GLOBUS_SUCCESS)
1705 {
1706 0 xsd_string_array_destroy_contents(namespace_prefixes);
1707 }
1708 2661633 out:
1709 2661633 return result;
1710 }
1711 /* globus_soap_message_deserialize_get_prefixes() */
1712
1713 #ifndef GLOBUS_DONT_DOCUMENT_INTERNAL
1714 static
1715 char *
1716 globus_l_soap_message_my_strtok(
1717 const char * str,
1718 size_t str_length,
1719 int * token_start_index,
1720 int * token_end_index,
1721 const char * delims)
1722 0 {
1723 const char * locator;
1724 const char * start_token;
1725 int delim_count,
1726 ind,
1727 i,
1728 between_tokens,
1729 len;
1730 0 char * new_token = NULL;
1731 0 ind = 0;
1732 0 i = 0;
1733 0 between_tokens = 0;
1734 0 delim_count = strlen(delims);
1735 0 locator = str;
1736
1737 0 for(i = 0; i < delim_count; ++i)
1738 {
1739 0 if(*locator == delims[i])
1740 {
1741 0 between_tokens = 1;
1742 }
1743 }
1744
1745 0 while(between_tokens && locator && ind < str_length)
1746 {
1747 0 for(i = 0; i < delim_count; ++i)
1748 {
1749 0 if(*locator == delims[i])
1750 {
1751 0 break;
1752 }
1753 }
1754
1755 0 if(i == delim_count)
1756 {
1757 0 between_tokens = 0;
1758 0 break;
1759 }
1760
1761 0 locator++;
1762 0 ind++;
1763 }
1764
1765 0 start_token = locator;
1766 0 if(token_start_index)
1767 {
1768 0 *token_start_index = ind;
1769 }
1770
1771 0 while(!between_tokens && *locator && ind < str_length)
1772 {
1773 0 for(i = 0; i < delim_count; ++i)
1774 {
1775 0 if(*locator == delims[i])
1776 {
1777 0 if(token_end_index)
1778 {
1779 0 *token_end_index = ind;
1780 }
1781 0 between_tokens = 1;
1782 0 break;
1783 }
1784 }
1785
1786 0 locator++;
1787 0 ind++;
1788 }
1789
1790 0 if(ind == str_length)
1791 {
1792 0 *token_end_index = -1;
1793 }
1794 else
1795 {
1796 0 ind--;
1797 }
1798
1799 0 len = ind + (str - start_token);
1800 0 if(len > 0)
1801 {
1802 0 new_token = malloc(len+1);
1803 0 memcpy(new_token, start_token, len + 1);
1804 0 new_token[len] = '\0';
1805 }
1806
1807 0 return new_token;
1808 }
1809
1810 static
1811 globus_result_t
1812 globus_l_soap_message_deserialize_read(
1813 globus_soap_message_handle_t handle)
1814 26 {
1815 26 globus_result_t result = GLOBUS_SUCCESS;
1816 GlobusFuncName(globus_l_soap_message_deserialize_read);
1817 26 GlobusSoapMessageDebugEnter();
1818
1819 26 if(xmlTextReaderNodeType(handle->reader) != XML_READER_TYPE_NONE &&
1820 xmlTextReaderIsEmptyElement(handle->reader))
1821 {
1822 0 if(handle->next_ready > 0)
1823 {
1824 0 handle->next_ready--;
1825 }
1826 else
1827 {
1828 0 result = GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT;
1829 }
1830
1831 0 goto exit;
1832 }
1833
1834 26 if(handle->next_ready > 0)
1835 {
1836 0 handle->next_ready--;
1837 }
1838 else
1839 {
1840 26 if(xmlTextReaderRead(handle->reader) <= 0)
1841 {
1842 2 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
1843 2 goto exit;
1844 }
1845 }
1846
1847 26 exit:
1848 26 GlobusSoapMessageDebugExit();
1849 26 return result;
1850 }
1851 /* globus_l_soap_message_deserialize_read() */
1852
1853 globus_result_t
1854 globus_i_soap_message_deserialize_next_element(
1855 globus_soap_message_handle_t handle)
1856 12817653 {
1857 12817653 globus_result_t result = GLOBUS_SUCCESS;
1858 12817653 xmlChar * idval = NULL;
1859 GlobusFuncName(globus_i_soap_message_deserialize_next_element);
1860 12817653 xmlReaderTypes type = XML_READER_TYPE_NONE;
1861
1862 12817653 GlobusSoapMessageDebugEnter();
1863
1864 12817653 if(xmlTextReaderNodeType(handle->reader) != type &&
1865 xmlTextReaderIsEmptyElement(handle->reader))
1866 {
1867 3055 if(handle->next_ready > 0)
1868 {
1869 2771 handle->next_ready--;
1870 }
1871 else
1872 {
1873 284 result = GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT;
1874 }
1875
1876 3055 goto exit;
1877 }
1878
1879 38335185 while(type != XML_READER_TYPE_ELEMENT)
1880 {
1881 12825459 if(handle->next_ready > 0)
1882 {
1883 7658377 handle->next_ready--;
1884 }
1885 else
1886 {
1887 5167082 if(xmlTextReaderRead(handle->reader) <= 0)
1888 {
1889 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
1890 0 goto exit;
1891 }
1892 }
1893
1894 12825459 type = xmlTextReaderNodeType(handle->reader);
1895 12825459 if(type == XML_READER_TYPE_END_ELEMENT)
1896 {
1897 119000 result = GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT;
1898 119000 goto exit;
1899 }
1900 12706459 else if(type == XML_READER_TYPE_TEXT)
1901 {
1902 470 xmlChar * str = NULL;
1903 470 if (handle->verbose)
1904 {
1905 396 str = xmlTextReaderValue(handle->reader);
1906 }
1907 470 result = GlobusSoapMessageErrorFailedWithText(handle->verbose, str);
1908
1909 470 if (str)
1910 {
1911 396 xmlFree(str);
1912 }
1913
1914 470 goto exit;
1915 }
1916 }
1917
1918 12695128 if(type == XML_READER_TYPE_ELEMENT)
1919 {
1920 12695128 if(handle->callout_table)
1921 {
1922 xsd_QName qn;
1923
1924 8105332 qn.local = (char *)
1925 xmlTextReaderConstLocalName(handle->reader);
1926 8105332 qn.Namespace = (char *)
1927 xmlTextReaderConstNamespaceUri(handle->reader);
1928
1929 8105332 result = globus_soap_message_invoke_callouts(
1930 handle,
1931 &qn,
1932 GLOBUS_SOAP_MESSAGE_CALLOUT_BEGIN);
1933 8105332 if(result != GLOBUS_SUCCESS)
1934 {
1935 0 result = GlobusSoapMessageErrorFailedNextNode(result);
1936 0 goto exit;
1937 }
1938 }
1939
1940 12695128 if ((idval = xmlTextReaderGetAttribute(
1941 handle->reader,
1942 (xmlChar *) "Id")) != NULL)
1943 {
1944 67 result = globus_soap_message_deserialize_mark(
1945 handle,
1946 (char *) idval);
1947 67 if(result != GLOBUS_SUCCESS)
1948 {
1949 0 result = GlobusSoapMessageErrorSettingId(
1950 result);
1951 0 goto exit;
1952 }
1953 67 xmlFree(idval);
1954 }
1955 }
1956
1957 12817653 exit:
1958
1959 12817653 GlobusSoapMessageDebugExit();
1960 12817653 return result;
1961 }
1962 /* globus_i_soap_message_deserialize_next_element() */
1963
1964 char *
1965 globus_soap_message_normalize_string(
1966 const xmlChar * str)
1967 100537 {
1968 char * copied;
1969 char * res;
1970 int i;
1971 int start, end;
1972
1973 100537 if (str == NULL)
1974 {
1975 0 return NULL;
1976 }
1977 100537 copied = res = malloc(strlen((const char *) str)+1);
1978 100537 copied[0] = 0;
1979
1980 /* first time through, consume whitespace */
1981 100537 i = 0;
1982 201471 while (str[i] != 0 && isspace(str[i]))
1983 {
1984 397 i++;
1985 }
1986 100537 start = i;
1987 6175820 while (str[i] != 0 && !isspace(str[i]))
1988 {
1989 5974746 i++;
1990 }
1991 100537 end = i;
1992
1993 100537 if ((end-start) > 0)
1994 {
1995 100537 memcpy(copied, str+start, end-start);
1996 100537 copied += end-start;
1997
1998 /* rest of the times, copy a ' ' between tokens */
1999 201091 while (str[i] != 0)
2000 {
2001 363 while (str[i] != 0 && isspace(str[i]))
2002 {
2003 329 i++;
2004 }
2005 17 start = i;
2006 34 while (str[i] != 0 && !isspace(str[i]))
2007 {
2008 0 i++;
2009 }
2010 17 end = i;
2011
2012 17 if ((end - start) > 0)
2013 {
2014 0 *(copied++) = ' ';
2015 0 memcpy(copied, str+start, end-start);
2016 0 copied += end-start;
2017 }
2018 }
2019 }
2020 100537 *copied = 0;
2021 100537 return res;
2022 }