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 8882453 {
66 GlobusFuncName(globus_soap_message_deserialize_push_element);
67 8882453 GlobusSoapMessageDebugEnter();
68
69 8882453 if (handle)
70 {
71 8882453 handle->next_ready++;
72 }
73
74 8882453 GlobusSoapMessageDebugExit();
75 8882453 }
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 5766058 {
109 5766058 char * idval = NULL;
110 5766058 globus_result_t result = GLOBUS_SUCCESS;
111 5766058 xmlReaderTypes type = XML_READER_TYPE_NONE;
112 5766058 int res = 0;
113 GlobusFuncName(globus_soap_message_deserialize_element_end);
114 5766058 GlobusSoapMessageDebugEnter();
115
116 5766058 if (handle == NULL)
117 {
118 0 result = GlobusSoapMessageErrorNullParam;
119
120 0 goto exit;
121 }
122 5766058 if(xmlTextReaderIsEmptyElement(handle->reader))
123 {
124 2204 if (qname)
125 {
126 xsd_QName tmp;
127 const xmlChar * qname_ns;
128 const xmlChar * qname_local;
129
130 2204 tmp.Namespace = (char *)
131 xmlTextReaderConstString(handle->reader,
132 xmlTextReaderConstNamespaceUri(handle->reader));
133 2204 tmp.local = (char *)
134 xmlTextReaderConstString(handle->reader,
135 xmlTextReaderConstLocalName(handle->reader));
136 2204 qname_ns = xmlTextReaderConstString(handle->reader,
137 (xmlChar *) qname->Namespace);
138 2204 qname_local = xmlTextReaderConstString(handle->reader,
139 (xmlChar *) qname->local);
140 2204 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 2204 res = xmlTextReaderRead(handle->reader);
150 2204 if(res < 0)
151 {
152 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
153 0 goto exit;
154 }
155 2204 handle->next_ready++;
156
157 2204 goto exit;
158 }
159
160 17294562 while(type != XML_READER_TYPE_END_ELEMENT)
161 {
162 5766854 if(handle->next_ready > 0)
163 {
164 87781 handle->next_ready--;
165 }
166 else
167 {
168 5679073 res = xmlTextReaderRead(handle->reader);
169 5679073 if(res < 0)
170 {
171 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
172 0 goto exit;
173 }
174 5679073 else if(res == 0)
175 {
176 0 goto exit;
177 }
178 }
179
180 5766854 type = xmlTextReaderNodeType(handle->reader);
181 5766854 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 5766854 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 5763854 if(type == XML_READER_TYPE_END_ELEMENT)
212 {
213 xsd_QName qn;
214
215 5763854 if(handle->callout_table)
216 {
217 3147467 qn.local = (char *)
218 xmlTextReaderConstLocalName(handle->reader);
219 3147467 qn.Namespace = (char *)
220 xmlTextReaderConstNamespaceUri(handle->reader);
221
222 3147467 result = globus_soap_message_invoke_callouts(
223 handle,
224 &qn,
225 GLOBUS_SOAP_MESSAGE_CALLOUT_END);
226 }
227
228 5763854 if((idval = (char *) xmlTextReaderGetAttribute(
229 handle->reader,
230 (xmlChar *) "Id")) != NULL)
231 {
232 char * end_idval =
233 0 globus_common_create_string("%s-end", idval);
234
235 0 if(handle->next_ready == 0)
236 {
237 0 result = globus_l_soap_message_deserialize_read(handle);
238 0 if(result != GLOBUS_SUCCESS &&
239 !GlobusSoapMessageStatusFailedElementCheck(result))
240 {
241 0 result = GLOBUS_SUCCESS;
242 0 goto exit;
243 }
244
245 0 globus_soap_message_deserialize_push_element(handle);
246 }
247
248 0 result = globus_soap_message_deserialize_mark(
249 handle, end_idval);
250 0 if(result != GLOBUS_SUCCESS)
251 {
252 0 result = GlobusSoapMessageErrorSettingId(
253 result);
254 0 goto exit;
255 }
256 0 xmlFree(idval);
257 0 globus_free(end_idval);
258 }
259 }
260
261 5766058 exit:
262
263 5766058 GlobusSoapMessageDebugExit();
264 5766058 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 5626414 {
310 5626414 globus_result_t result = GLOBUS_SUCCESS;
311 5626414 xmlReaderTypes type = XML_READER_TYPE_NONE;
312 GlobusFuncName(globus_i_soap_message_deserialize_next_content);
313 5626414 GlobusSoapMessageDebugEnter();
314
315 5626414 if(xmlTextReaderIsEmptyElement(handle->reader))
316 {
317 3 goto exit;
318 }
319
320 16879233 while(type != XML_READER_TYPE_TEXT)
321 {
322 5626411 if(handle->next_ready > 0)
323 {
324 123 handle->next_ready--;
325 }
326 5626288 else if(xmlTextReaderRead(handle->reader) <= 0)
327 {
328 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
329 0 goto exit;
330 }
331
332 5626411 type = xmlTextReaderNodeType(handle->reader);
333 5626411 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 5626411 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 5626414 exit:
349
350 5626414 GlobusSoapMessageDebugExit();
351 5626414 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 23871 {
379 xsd_QName local_qn;
380 const xmlChar * local;
381 const xmlChar * soap_env;
382 23871 globus_result_t result = GLOBUS_SUCCESS;
383
384 GlobusFuncName(globus_soap_message_deserialize_envelope);
385 23871 GlobusSoapMessageDebugEnter();
386
387 23871 if (handle == NULL)
388 {
389 0 result = GlobusSoapMessageErrorNullParam;
390
391 0 goto exit;
392 }
393 23871 result = globus_soap_message_set_marker(
394 handle,
395 GLOBUS_SOAP_MESSAGE_MARKER_ENVELOPE);
396 23871 if(result != GLOBUS_SUCCESS)
397 {
398 0 result = GlobusSoapMessageErrorDeserializeFailed(
399 result, &soap_env_qname);
400 0 goto exit;
401 }
402
403 23871 result = globus_i_soap_message_deserialize_next_element(handle);
404 23871 if(result != GLOBUS_SUCCESS)
405 {
406 0 result = GlobusSoapMessageErrorDeserializeFailed(
407 result, &soap_env_qname);
408 0 goto exit;
409 }
410
411 23871 soap_env = xmlTextReaderConstString(handle->reader, (xmlChar *) SOAP_ENV);
412 23871 local = xmlTextReaderConstLocalName(handle->reader);
413 23871 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 23871 exit:
429
430 23871 GlobusSoapMessageDebugExit();
431 23871 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 23865 {
459 23865 globus_result_t result = GLOBUS_SUCCESS;
460 GlobusFuncName(globus_soap_message_deserialize_envelope_end);
461 23865 GlobusSoapMessageDebugEnter();
462
463 23865 result = globus_soap_message_deserialize_element_end(
464 handle,
465 &soap_env_qname);
466 23865 if(result != GLOBUS_SUCCESS)
467 {
468 0 result = GlobusSoapMessageErrorDeserializeFailed(
469 result, &soap_env_qname);
470 0 goto exit;
471 }
472
473 23865 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 23865 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 23865 exit:
487
488 23865 GlobusSoapMessageDebugExit();
489 23865 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 23871 {
513 const xmlChar * local;
514 const xmlChar * soap_header;
515 23871 globus_result_t result = GLOBUS_SUCCESS;
516
517 GlobusFuncName(globus_soap_message_deserialize_header);
518 23871 GlobusSoapMessageDebugEnter();
519
520 23871 if (handle == NULL)
521 {
522 0 result = GlobusSoapMessageErrorNullParam;
523
524 0 goto exit;
525 }
526 23871 result = globus_i_soap_message_deserialize_next_element(handle);
527 23871 if(result != GLOBUS_SUCCESS)
528 {
529 0 result = GlobusSoapMessageErrorDeserializeFailed(
530 result, &soap_header_qname);
531 0 goto exit;
532 }
533
534 23871 soap_header = xmlTextReaderConstString(
535 handle->reader,
536 (xmlChar *) SOAP_HEADER);
537 23871 local = xmlTextReaderConstLocalName(handle->reader);
538 23871 if(soap_header != local)
539 {
540 2 xsd_QName local_qn = { NULL, NULL };
541 2 if (handle->verbose)
542 {
543 0 local_qn.Namespace = (char *)
544 xmlTextReaderNamespaceUri(handle->reader);
545 0 local_qn.local = (char *) local;
546 }
547
548 2 result = GlobusSoapMessageErrorElementNotFound(
549 handle->verbose,
550 &soap_body_qname,
551 &local_qn);
552 2 goto exit;
553 }
554
555 23871 exit:
556
557 23871 GlobusSoapMessageDebugExit();
558 23871 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 23866 {
582 23866 globus_result_t result = GLOBUS_SUCCESS;
583 GlobusFuncName(globus_soap_message_deserialize_header_end);
584 23866 GlobusSoapMessageDebugEnter();
585
586 23866 if (handle == NULL)
587 {
588 0 result = GlobusSoapMessageErrorNullParam;
589
590 0 goto exit;
591 }
592 23866 result = globus_soap_message_deserialize_element_end(
593 handle,
594 &soap_header_qname);
595 23866 if(result != GLOBUS_SUCCESS)
596 {
597 0 GlobusSoapMessageErrorDeserializeFailed(
598 result, &soap_header_qname);
599 0 goto exit;
600 }
601
602 23866 exit:
603
604 23866 GlobusSoapMessageDebugExit();
605 23866 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 0 {
635 0 globus_result_t result = GLOBUS_SUCCESS;
636 int rc;
637 xsd_QName * value;
638 GlobusFuncName(globus_soap_message_add_required_header_element);
639 0 GlobusSoapMessageDebugEnter();
640
641 0 if (handle == NULL || qn == NULL)
642 {
643 0 result = GlobusSoapMessageErrorNullParam;
644
645 0 goto out;
646 }
647 0 if(!handle->mustUnderstand_hash)
648 {
649 0 rc = globus_hashtable_init(
650 &handle->mustUnderstand_hash,
651 7,
652 xsd_QName_hash,
653 xsd_QName_keyeq);
654 0 if (rc != GLOBUS_SUCCESS)
655 {
656 0 result = GlobusSoapMessageErrorOutOfMemory;
657 0 goto out;
658 }
659 }
660
661 0 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 0 result = xsd_QName_copy(&value, qn);
670 0 if (result != GLOBUS_SUCCESS)
671 {
672 0 goto out;
673 }
674
675 0 rc = globus_hashtable_insert(
676 &handle->mustUnderstand_hash,
677 value, value);
678 0 if (rc != GLOBUS_SUCCESS)
679 {
680 0 result = GlobusSoapMessageErrorNullParam;
681 }
682
683 0 out:
684 0 GlobusSoapMessageDebugExit();
685 0 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 43920 {
710 xsd_QName * entry;
711 43920 globus_result_t result = GLOBUS_SUCCESS;
712 GlobusFuncName(globus_soap_message_remove_required_header_element);
713 43920 GlobusSoapMessageDebugEnter();
714
715 43920 if (handle == NULL || qn == NULL)
716 {
717 0 result = GlobusSoapMessageErrorNullParam;
718
719 0 goto out;
720 }
721 43920 if(handle->mustUnderstand_hash)
722 {
723 0 entry = globus_hashtable_remove(
724 &handle->mustUnderstand_hash, (void *)qn);
725 0 if (entry)
726 {
727 0 xsd_QName_destroy(entry);
728 }
729 }
730
731 43920 out:
732 43920 GlobusSoapMessageDebugExit();
733 43920 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 23615 {
757 xsd_QName * element;
758 23615 globus_result_t result = GLOBUS_SUCCESS;
759 GlobusFuncName(globus_soap_message_check_required_headers);
760 23615 GlobusSoapMessageDebugEnter();
761
762 23615 if (handle == NULL)
763 {
764 0 result = GlobusSoapMessageErrorNullParam;
765
766 0 goto out;
767 }
768 23615 if(!handle->mustUnderstand_hash)
769 {
770 /* Nothing to understand, so we're fine. */
771 23615 goto out;
772 }
773
774 0 element = globus_hashtable_first(&handle->mustUnderstand_hash);
775
776 0 while(element)
777 {
778 0 result = GlobusSoapMessageErrorMustUnderstand(
779 result, element);
780 0 element = globus_hashtable_next(&handle->mustUnderstand_hash);
781 }
782
783 0 GlobusSoapMessageDebugExit();
784 23615 out:
785 23615 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 23868 {
809 const xmlChar * local;
810 const xmlChar * soap_body;
811 xsd_QName local_qn;
812 23868 globus_result_t result = GLOBUS_SUCCESS;
813
814 GlobusFuncName(globus_soap_message_deserialize_body);
815 23868 GlobusSoapMessageDebugEnter();
816
817 /* Should this just be a call to globus_soap_message_deserialize_element()?
818 */
819 23868 result = globus_i_soap_message_deserialize_next_element(handle);
820 23868 if(result != GLOBUS_SUCCESS)
821 {
822 0 result = GlobusSoapMessageErrorDeserializeFailed(
823 result, &soap_body_qname);
824 0 goto exit;
825 }
826
827 23868 soap_body = xmlTextReaderConstString(handle->reader, (xmlChar *) SOAP_BODY);
828 23868 local = xmlTextReaderConstLocalName(handle->reader);
829 23868 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 23868 exit:
846
847 23868 GlobusSoapMessageDebugExit();
848 23868 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 12888 {
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 12888 globus_result_t result = GLOBUS_SUCCESS;
887 12888 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 12888 GlobusSoapMessageDebugEnter();
894
895 12888 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 12888 result = globus_i_soap_message_deserialize_next_element(handle);
903 12888 if(result != GLOBUS_SUCCESS)
904 {
905 0 result = GlobusSoapMessageErrorDeserializeFailed(
906 result, &soap_fault_qname);
907 0 goto exit;
908 }
909
910 12888 soap_fault = xmlTextReaderConstString(
911 handle->reader,
912 (xmlChar *) SOAP_FAULT);
913 12888 local = xmlTextReaderConstLocalName(handle->reader);
914 12888 if(soap_fault != local)
915 {
916 12635 globus_soap_message_deserialize_push_element(handle);
917 12635 goto exit;
918 }
919
920 253 globus_soap_message_fault_init(&fault);
921
922 253 faultcode_name = xmlTextReaderConstString(
923 handle->reader, (xmlChar *) SOAP_FAULTCODE);
924 253 faultactor_name = xmlTextReaderConstString(
925 handle->reader, (xmlChar *) SOAP_FAULTACTOR);
926 253 faultstring_name = xmlTextReaderConstString(
927 handle->reader, (xmlChar *) SOAP_FAULTSTRING);
928 253 detail_name = xmlTextReaderConstString(
929 handle->reader, (xmlChar *) SOAP_FAULT_DETAIL);
930
931 1012 while(result == GLOBUS_SUCCESS)
932 {
933 759 result = globus_i_soap_message_deserialize_next_element(handle);
934 759 if(result != GLOBUS_SUCCESS)
935 {
936 6 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
937 GlobusSoapMessageStatusFailedWithTextCheck(result))
938 {
939 6 globus_soap_message_deserialize_push_element(handle);
940 6 result = GLOBUS_SUCCESS;
941 6 break;
942 }
943
944 0 result = GlobusSoapMessageErrorDeserializeFailed(
945 result, &soap_fault_qname);
946 0 goto exit;
947 }
948
949 753 element_name = xmlTextReaderConstLocalName(handle->reader);
950 753 if(element_name == faultcode_name)
951 {
952 253 result = globus_i_soap_message_deserialize_next_content(handle);
953 253 if(result != GLOBUS_SUCCESS)
954 {
955 0 result = GlobusSoapMessageErrorDeserializeFailed(
956 result, &soap_fault_qname);
957 0 goto exit;
958 }
959
960 253 fault->faultcode = (char *) xmlTextReaderValue(handle->reader);
961 }
962 500 else if(element_name == faultstring_name)
963 {
964 253 result = globus_i_soap_message_deserialize_next_content(handle);
965 253 if(result != GLOBUS_SUCCESS)
966 {
967 0 result = GlobusSoapMessageErrorDeserializeFailed(
968 result, &soap_faultstring_qname);
969 0 goto exit;
970 }
971
972 253 fault->faultstring = (char *) xmlTextReaderValue(handle->reader);
973 }
974 247 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 247 else if(element_name == detail_name)
987 {
988 247 xsd_any * dummy_any = NULL;
989 xsd_QName fault_qname;
990
991 247 result = globus_soap_message_deserialize_element_unknown(
992 handle, &fault_qname);
993 247 if(result != GLOBUS_SUCCESS)
994 {
995 0 result = GlobusSoapMessageErrorDeserializeFailed(
996 result, &soap_fault_detail_qname);
997 0 goto exit;
998 }
999
1000 247 globus_soap_message_deserialize_push_element(handle);
1001
1002 247 globus_soap_message_set_marker(handle, "FAULT_DETAIL_BEGIN");
1003
1004 247 xsd_any_init(fault_any);
1005
1006 247 result = xsd_any_deserialize(
1007 NULL, (*fault_any), handle, 0);
1008 247 if(result != GLOBUS_SUCCESS)
1009 {
1010 0 result = GlobusSoapMessageErrorDeserializeFailed(
1011 result, &soap_fault_detail_qname);
1012 0 goto exit;
1013 }
1014
1015 247 globus_soap_message_set_marker(handle, "FAULT_DETAIL_END");
1016
1017 247 xsd_any_init(&fault->detail);
1018 247 fault->detail->any_info = (&globus_xml_buffer_contents_info);
1019
1020 247 globus_xml_buffer_init(&detail_buffer);
1021 247 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 247 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 247 fault->detail->value = detail_buffer;
1036
1037 247 if (fault_callback != NULL)
1038 {
1039 247 fault_callback(handle,
1040 (*fault_any)->any_info->type,
1041 fault_type);
1042 }
1043
1044 do
1045 {
1046 247 result = xsd_any_deserialize_pointer(
1047 NULL, &dummy_any, handle, 0);
1048 247 if(result != GLOBUS_SUCCESS)
1049 {
1050 247 if(GlobusSoapMessageStatusFailedElementCheck(result))
1051 {
1052 247 result = GLOBUS_SUCCESS;
1053 247 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 506 result = globus_soap_message_deserialize_element_end(
1075 handle,
1076 &soap_fault_qname);
1077 506 if(result != GLOBUS_SUCCESS)
1078 {
1079 0 result = GlobusSoapMessageErrorDeserializeFailed(
1080 result, &soap_fault_qname);
1081 0 goto exit;
1082 }
1083 }
1084
1085 12888 exit:
1086
1087 12888 *soap_fault_handle = fault;
1088
1089 12888 GlobusSoapMessageDebugExit();
1090 12888 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 5528743 {
1114 xmlChar * nil_value;
1115 GlobusFuncName(globus_soap_message_deserialize_element_is_nil);
1116 5528743 GlobusSoapMessageDebugEnter();
1117
1118 5528743 globus_assert(handle != NULL);
1119
1120 5528743 nil_value = xmlTextReaderGetAttributeNs(
1121 handle->reader,
1122 (xmlChar *) XSI_NIL,
1123 (xmlChar *) XSI_NS);
1124 5528743 if(nil_value && !(xmlStrcmp(nil_value, (xmlChar *) "true")))
1125 {
1126 27 xmlFree(nil_value);
1127 27 return GLOBUS_TRUE;
1128 }
1129
1130 5528716 if(!nil_value)
1131 {
1132 5528716 xmlFree(nil_value);
1133 }
1134
1135 5528716 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 3206125 {
1168 3206125 globus_result_t result = GLOBUS_SUCCESS;
1169 const xmlChar * tmp;
1170 GlobusFuncName(globus_soap_message_deserialize_element);
1171
1172 3206125 GlobusSoapMessageDebugEnter();
1173
1174 3206125 if (handle == NULL || qname == NULL)
1175 {
1176 0 result = GlobusSoapMessageErrorNullParam;
1177
1178 0 goto exit;
1179 }
1180
1181 3206125 result = globus_i_soap_message_deserialize_next_element(handle);
1182 3206125 if(result != GLOBUS_SUCCESS)
1183 {
1184 24414 xsd_QName * q = NULL;
1185
1186 24414 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
1187 GlobusSoapMessageStatusFailedWithTextCheck(result))
1188 {
1189 24414 globus_soap_message_deserialize_push_element(handle);
1190 24414 goto exit;
1191 }
1192 else
1193 {
1194 0 result = GlobusSoapMessageErrorDeserializeFailed(
1195 result, q);
1196 }
1197 0 goto exit;
1198 }
1199
1200 3181711 qname->local = globus_libc_strdup(
1201 (char *) xmlTextReaderConstLocalName(handle->reader));
1202 3181711 if (qname->local == NULL)
1203 {
1204 0 result = GlobusSoapMessageErrorOutOfMemory;
1205
1206 0 goto push_element_exit;
1207 }
1208 3181711 tmp = xmlTextReaderConstNamespaceUri(handle->reader);
1209 3181711 if (tmp)
1210 {
1211 3181659 qname->Namespace = globus_libc_strdup((char *) tmp);
1212 3181659 if (qname->Namespace == NULL)
1213 {
1214 0 result = GlobusSoapMessageErrorOutOfMemory;
1215
1216 0 goto free_local_exit;
1217 }
1218 }
1219 else
1220 {
1221 52 qname->Namespace = NULL;
1222 }
1223
1224 3181711 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 3206125 exit:
1233
1234 3206125 GlobusSoapMessageDebugExit();
1235 3206125 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 3037446 {
1258 3037446 globus_assert(handle != NULL);
1259 3037446 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 11332978 {
1290 const xmlChar * local;
1291 const xmlChar * local_ns;
1292 const xmlChar * element;
1293 const xmlChar * element_ns;
1294 xsd_QName local_qn;
1295 11332978 globus_result_t result = GLOBUS_SUCCESS;
1296 GlobusFuncName(globus_soap_message_deserialize_element);
1297
1298 11332978 GlobusSoapMessageDebugEnter();
1299
1300 11332978 if (handle == NULL)
1301 {
1302 0 result = GlobusSoapMessageErrorNullParam;
1303
1304 0 goto exit;
1305 }
1306
1307 11332978 result = globus_i_soap_message_deserialize_next_element(handle);
1308 11332978 if(result != GLOBUS_SUCCESS)
1309 {
1310 109019 if(GlobusSoapMessageStatusFailedElementCheck(result) ||
1311 GlobusSoapMessageStatusFailedWithTextCheck(result))
1312 {
1313 109019 if (!xmlTextReaderIsEmptyElement(handle->reader))
1314 {
1315 108734 globus_soap_message_deserialize_push_element(handle);
1316 }
1317
1318 109019 goto exit;
1319 }
1320 else
1321 {
1322 0 result = GlobusSoapMessageErrorDeserializeFailed(
1323 result, qname);
1324 }
1325 0 goto exit;
1326 }
1327
1328 11223959 if(qname)
1329 {
1330 5683991 element = xmlTextReaderConstString(
1331 handle->reader,
1332 (xmlChar *) qname->local);
1333 5683991 local = xmlTextReaderConstString(
1334 handle->reader, xmlTextReaderConstLocalName(handle->reader));
1335 5683991 if(element != local)
1336 {
1337 898 if (handle->verbose)
1338 {
1339 636 local_qn.Namespace = (char *) xmlTextReaderConstString(
1340 handle->reader,
1341 xmlTextReaderConstNamespaceUri(handle->reader));
1342 636 local_qn.local = (char *) local;
1343 }
1344 898 globus_soap_message_deserialize_push_element(handle);
1345
1346 898 result = GlobusSoapMessageErrorElementNotFound(
1347 handle->verbose,
1348 qname,
1349 &local_qn);
1350 898 goto exit;
1351 }
1352
1353 5683093 element_ns = xmlTextReaderConstString(
1354 handle->reader, (xmlChar *) qname->Namespace);
1355 5683093 local_ns = xmlTextReaderConstString(
1356 handle->reader, xmlTextReaderConstNamespaceUri(handle->reader));
1357 5683093 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 11332978 exit:
1374
1375 11332978 GlobusSoapMessageDebugExit();
1376 11332978 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 175639 {
1410 const xmlChar * attr_ns;
1411 const xmlChar * local_ns;
1412 const xmlChar * attr_local;
1413 175639 globus_result_t result = GLOBUS_SUCCESS;
1414
1415 175639 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 175639 attr_ns = xmlTextReaderConstString(
1423 handle->reader, (xmlChar *) attr_qname->Namespace);
1424 175639 local_ns = xmlTextReaderConstNamespaceUri(handle->reader);
1425 175639 attr_local = xmlTextReaderConstString(
1426 handle->reader, (xmlChar *) attr_qname->local);
1427
1428 178374 if (xmlTextReaderNodeType(handle->reader) == XML_READER_TYPE_ATTRIBUTE &&
1429 attr_ns == local_ns &&
1430 xmlTextReaderConstLocalName(handle->reader) == attr_local)
1431 {
1432 2735 *content = xmlTextReaderValue(handle->reader);
1433 }
1434 317892 else if(attr_ns != local_ns && (attr_ns != NULL) && (*attr_ns != '\0'))
1435 {
1436 144988 *content = xmlTextReaderGetAttributeNs(
1437 handle->reader,
1438 (xmlChar *) attr_qname->local,
1439 attr_ns);
1440 }
1441 else
1442 {
1443 27916 *content = xmlTextReaderGetAttribute(
1444 handle->reader, (xmlChar *) attr_qname->local);
1445 }
1446 175639 if(! (*content))
1447 {
1448 165557 result = GlobusSoapMessageErrorAttributeNotFound(
1449 handle->verbose,
1450 attr_qname);
1451 165557 goto exit;
1452 }
1453 175639 exit:
1454 175639 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 0 {
1479 0 globus_result_t result = GLOBUS_SUCCESS;
1480 GlobusFuncName(globus_soap_message_deserialize_mark);
1481 0 GlobusSoapMessageDebugEnter();
1482
1483 0 if (handle == NULL || idval == NULL)
1484 {
1485 0 result = GlobusSoapMessageErrorNullParam;
1486 0 goto exit;
1487 }
1488
1489 0 GlobusSoapMessageDebugPrintf(
1490 GLOBUS_SOAP_MESSAGE_DEBUG_DEBUG,
1491 ("SETTING MARK: %s\n", idval));
1492
1493 0 if(handle->xio_handle)
1494 {
1495 0 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 0 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 0 exit:
1509
1510 0 GlobusSoapMessageDebugExit();
1511 0 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 3047168 {
1649 xsd_string * new_string;
1650 xmlNsPtr * ns_list;
1651 3047168 globus_result_t result = GLOBUS_SUCCESS;
1652 int i;
1653 GlobusFuncName(globus_soap_message_get_prefixes);
1654 3047168 GlobusSoapMessageDebugEnter();
1655
1656 3047168 if (handle == NULL || namespace_prefixes == NULL)
1657 {
1658 0 result = GlobusSoapMessageErrorNullParam;
1659
1660 0 goto out;
1661 }
1662 3047168 result = xsd_string_array_init_contents(namespace_prefixes);
1663
1664 3047168 if (result != GLOBUS_SUCCESS)
1665 {
1666 0 goto out;
1667 }
1668 3047168 handle->doc_to_free = xmlTextReaderCurrentDoc(handle->reader);
1669 3047168 ns_list = xmlGetNsList(
1670 handle->doc_to_free,
1671 xmlTextReaderCurrentNode(handle->reader));
1672
1673 3047168 if (ns_list != NULL)
1674 {
1675 18701193 for (i = 0; ns_list[i] != NULL; i++)
1676 {
1677 15654025 if (ns_list[i]->prefix != NULL)
1678 {
1679 12640292 new_string = xsd_string_array_push(namespace_prefixes);
1680
1681 12640292 if (new_string == NULL)
1682 {
1683 0 result = GlobusSoapMessageErrorOutOfMemory;
1684
1685 0 goto free_nslist;
1686 }
1687 12640292 *new_string = globus_common_create_string(
1688 "%s=%s",
1689 ns_list[i]->prefix,
1690 ns_list[i]->href);
1691 12640292 if (*new_string == NULL)
1692 {
1693 0 goto free_nslist;
1694 }
1695 }
1696 }
1697 }
1698
1699 3047168 free_nslist:
1700 3047168 if (ns_list != NULL)
1701 {
1702 3047168 xmlFree(ns_list);
1703 }
1704 3047168 if (result != GLOBUS_SUCCESS)
1705 {
1706 0 xsd_string_array_destroy_contents(namespace_prefixes);
1707 }
1708 3047168 out:
1709 3047168 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 0 {
1815 0 globus_result_t result = GLOBUS_SUCCESS;
1816 GlobusFuncName(globus_l_soap_message_deserialize_read);
1817 0 GlobusSoapMessageDebugEnter();
1818
1819 0 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 0 if(handle->next_ready > 0)
1835 {
1836 0 handle->next_ready--;
1837 }
1838 else
1839 {
1840 0 if(xmlTextReaderRead(handle->reader) <= 0)
1841 {
1842 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
1843 0 goto exit;
1844 }
1845 }
1846
1847 0 exit:
1848 0 GlobusSoapMessageDebugExit();
1849 0 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 14648725 {
1857 14648725 globus_result_t result = GLOBUS_SUCCESS;
1858 14648725 xmlChar * idval = NULL;
1859 GlobusFuncName(globus_i_soap_message_deserialize_next_element);
1860 14648725 xmlReaderTypes type = XML_READER_TYPE_NONE;
1861
1862 14648725 GlobusSoapMessageDebugEnter();
1863
1864 14648725 if(xmlTextReaderNodeType(handle->reader) != type &&
1865 xmlTextReaderIsEmptyElement(handle->reader))
1866 {
1867 3098 if(handle->next_ready > 0)
1868 {
1869 2813 handle->next_ready--;
1870 }
1871 else
1872 {
1873 285 result = GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT;
1874 }
1875
1876 3098 goto exit;
1877 }
1878
1879 43814739 while(type != XML_READER_TYPE_ELEMENT)
1880 {
1881 14656886 if(handle->next_ready > 0)
1882 {
1883 8757871 handle->next_ready--;
1884 }
1885 else
1886 {
1887 5899015 if(xmlTextReaderRead(handle->reader) <= 0)
1888 {
1889 0 result = GlobusSoapMessageErrorFailedNextNode(handle->result);
1890 0 goto exit;
1891 }
1892 }
1893
1894 14656886 type = xmlTextReaderNodeType(handle->reader);
1895 14656886 if(type == XML_READER_TYPE_END_ELEMENT)
1896 {
1897 132922 result = GLOBUS_SOAP_MESSAGE_STATUS_FAILED_ELEMENT;
1898 132922 goto exit;
1899 }
1900 14523964 else if(type == XML_READER_TYPE_TEXT)
1901 {
1902 479 xmlChar * str = NULL;
1903 479 if (handle->verbose)
1904 {
1905 396 str = xmlTextReaderValue(handle->reader);
1906 }
1907 479 result = GlobusSoapMessageErrorFailedWithText(handle->verbose, str);
1908
1909 479 if (str)
1910 {
1911 396 xmlFree(str);
1912 }
1913
1914 479 goto exit;
1915 }
1916 }
1917
1918 14512226 if(type == XML_READER_TYPE_ELEMENT)
1919 {
1920 14512226 if(handle->callout_table)
1921 {
1922 xsd_QName qn;
1923
1924 9279953 qn.local = (char *)
1925 xmlTextReaderConstLocalName(handle->reader);
1926 9279953 qn.Namespace = (char *)
1927 xmlTextReaderConstNamespaceUri(handle->reader);
1928
1929 9279953 result = globus_soap_message_invoke_callouts(
1930 handle,
1931 &qn,
1932 GLOBUS_SOAP_MESSAGE_CALLOUT_BEGIN);
1933 9279953 if(result != GLOBUS_SUCCESS)
1934 {
1935 0 result = GlobusSoapMessageErrorFailedNextNode(result);
1936 0 goto exit;
1937 }
1938 }
1939
1940 14512226 if ((idval = xmlTextReaderGetAttribute(
1941 handle->reader,
1942 (xmlChar *) "Id")) != NULL)
1943 {
1944 0 result = globus_soap_message_deserialize_mark(
1945 handle,
1946 (char *) idval);
1947 0 if(result != GLOBUS_SUCCESS)
1948 {
1949 0 result = GlobusSoapMessageErrorSettingId(
1950 result);
1951 0 goto exit;
1952 }
1953 0 xmlFree(idval);
1954 }
1955 }
1956
1957 14648725 exit:
1958
1959 14648725 GlobusSoapMessageDebugExit();
1960 14648725 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 111899 {
1968 char * copied;
1969 char * res;
1970 int i;
1971 int start, end;
1972
1973 111899 if (str == NULL)
1974 {
1975 3 return NULL;
1976 }
1977 111896 copied = res = malloc(strlen((const char *) str)+1);
1978 111896 copied[0] = 0;
1979
1980 /* first time through, consume whitespace */
1981 111896 i = 0;
1982 224293 while (str[i] != 0 && isspace(str[i]))
1983 {
1984 501 i++;
1985 }
1986 111896 start = i;
1987 6841810 while (str[i] != 0 && !isspace(str[i]))
1988 {
1989 6618018 i++;
1990 }
1991 111896 end = i;
1992
1993 111896 if ((end-start) > 0)
1994 {
1995 111896 memcpy(copied, str+start, end-start);
1996 111896 copied += end-start;
1997
1998 /* rest of the times, copy a ' ' between tokens */
1999 223813 while (str[i] != 0)
2000 {
2001 459 while (str[i] != 0 && isspace(str[i]))
2002 {
2003 417 i++;
2004 }
2005 21 start = i;
2006 42 while (str[i] != 0 && !isspace(str[i]))
2007 {
2008 0 i++;
2009 }
2010 21 end = i;
2011
2012 21 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 111896 *copied = 0;
2021 111896 return res;
2022 }