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_soap_message.h"
19 #include "xsd_any.h"
20 #include "xsd_QName.h"
21 #include "globus_xml_buffer.h"
22
23 void
24 xsd_any_destroy_contents(
25 xsd_any * instance)
26 7530847 {
27 GlobusFuncName(xsd_any_destroy_contents);
28 7530847 GlobusSoapMessageDebugEnter();
29
30 7530847 if(instance)
31 {
32 7530847 if(instance->value && instance->any_info)
33 {
34 7529024 instance->any_info->destroy(instance->value);
35 7529024 instance->value = NULL;
36 }
37
38 7530847 if(instance->element)
39 {
40 7521944 xsd_QName_destroy(instance->element);
41 7521944 instance->element = NULL;
42 }
43
44 7530847 xsd_string_array_destroy_contents(&instance->namespaces);
45 }
46
47 7530847 GlobusSoapMessageDebugExit();
48 7530847 }
49
50 globus_result_t
51 xsd_any_copy_contents(
52 xsd_any * dest,
53 const xsd_any * src)
54 2698360 {
55 2698360 globus_result_t result = GLOBUS_SUCCESS;
56 GlobusFuncName(xsd_any_copy_contents);
57 2698360 GlobusSoapMessageDebugEnter();
58
59 2698360 if(dest && src)
60 {
61 2698360 *dest = *src;
62 2698360 if(src->element)
63 {
64 2690511 result = xsd_QName_copy(&dest->element, src->element);
65 2690511 if(result != GLOBUS_SUCCESS)
66 {
67 0 goto error;
68 }
69 }
70
71 2698360 if(src->value && src->any_info)
72 {
73 2698324 result = src->any_info->copy(&dest->value, src->value);
74 2698324 if(result != GLOBUS_SUCCESS)
75 {
76 0 if(dest->element)
77 {
78 0 xsd_QName_destroy(dest->element);
79 0 dest->element = NULL;
80 0 goto error;
81 }
82 }
83 }
84 2698360 xsd_string_array_init_contents(&dest->namespaces);
85 2698360 xsd_string_array_copy_contents(&dest->namespaces, &src->namespaces);
86 }
87
88 2698360 error:
89 2698360 GlobusSoapMessageDebugExit();
90 2698360 return result;
91 }
92
93 globus_result_t
94 xsd_any_serialize(
95 const xsd_QName * element_qname,
96 const xsd_any * anyinst,
97 globus_soap_message_handle_t message_handle,
98 globus_xsd_element_options_t options)
99 2201918 {
100 2201918 globus_result_t result = GLOBUS_SUCCESS;
101 GlobusFuncName(xsd_any_serialize);
102 2201918 GlobusSoapMessageDebugEnter();
103
104 2201918 options &= ~GLOBUS_XSD_ELEMENT_CONTENTS_ONLY;
105 /* serialize contents of type. If there's no element, just serialize
106 * contents
107 */
108 2201918 if (anyinst->element == NULL)
109 {
110 266 options |= GLOBUS_XSD_ELEMENT_CONTENTS_ONLY;
111 }
112 2201918 if (anyinst->value == NULL)
113 {
114 18 options |= GLOBUS_XSD_ELEMENT_NIL;
115 }
116 2201918 result = anyinst->any_info->serialize(
117 anyinst->element,
118 anyinst->value,
119 message_handle,
120 options | GLOBUS_XSD_ELEMENT_TYPE_ATTR);
121 2201918 if(result != GLOBUS_SUCCESS)
122 {
123 0 result = GlobusSoapMessageErrorSerializeFailed(
124 result,
125 "Serialization of xsd:any failed",
126 anyinst->element);
127 0 goto exit;
128 }
129
130 2201918 exit:
131
132 2201918 GlobusSoapMessageDebugExit();
133 2201918 return result;
134 }
135
136 globus_result_t
137 globus_i_xsd_deserialize_from_element_qname(
138 const xsd_QName * deselem_qname,
139 globus_xsd_type_info_t * found_any_info,
140 globus_xsd_type_registry_t registry,
141 globus_soap_message_handle_t message_handle)
142 2650718 {
143 2650718 globus_result_t result = GLOBUS_SUCCESS;
144 2650718 globus_xsd_type_info_t any_info = NULL;
145 GlobusFuncName(globus_i_xsd_deserialize_from_element_qname);
146 2650718 GlobusSoapMessageDebugEnter();
147
148 2650718 GlobusSoapMessageDebugPrintf(
149 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
150 ("\tLooking for element {%s}%s:\n",
151 deselem_qname->Namespace,
152 deselem_qname->local));
153
154 2650718 GlobusSoapMessageDebugPrintf(
155 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
156 ("\t\tin instance registry\n"));
157
158 2650718 if(registry)
159 {
160 /* look for element QName in instance registry */
161 0 result = globus_xsd_type_registry_get_element(
162 registry, deselem_qname, &any_info);
163 0 if(result != GLOBUS_SUCCESS)
164 {
165 0 result = GlobusSoapMessageErrorFailedRegistryLookup(
166 result, deselem_qname);
167 0 goto exit;
168 }
169
170 0 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS))
171 {
172 0 if(any_info)
173 {
174 0 GlobusSoapMessageDebugPrintf(
175 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
176 ("\tFound type info: {%s}%s\n",
177 any_info->type->Namespace,
178 any_info->type->local));
179 }
180 }
181 }
182
183 2650718 if(!any_info)
184 {
185 2650718 GlobusSoapMessageDebugPrintf(
186 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
187 ("\t\tin global registry\n"));
188
189 2650718 result = globus_xsd_type_registry_get_element(
190 GLOBUS_GLOBAL_TYPE_REGISTRY, deselem_qname, &any_info);
191 2650718 if(result != GLOBUS_SUCCESS)
192 {
193 0 result = GlobusSoapMessageErrorFailedRegistryLookup(
194 result, deselem_qname);
195 0 goto exit;
196 }
197
198 2650718 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS))
199 {
200 0 if(any_info)
201 {
202 0 GlobusSoapMessageDebugPrintf(
203 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
204 ("Found type info: {%s}%s\n",
205 any_info->type->Namespace,
206 any_info->type->local));
207 }
208 }
209 }
210
211 2650718 exit:
212
213 2650718 *found_any_info = any_info;
214
215 2650718 GlobusSoapMessageDebugExit();
216 2650718 return result;
217 }
218
219
220 globus_result_t
221 globus_i_xsd_deserialize_from_xsi_type(
222 globus_xsd_type_info_t * found_any_info,
223 globus_xsd_type_registry_t registry,
224 globus_soap_message_handle_t message_handle)
225 23531 {
226 23531 globus_result_t result = GLOBUS_SUCCESS;
227 23531 globus_xsd_type_info_t any_info = NULL;
228 23531 xsd_QName * type = NULL;
229 xsd_QName type_attr_name =
230 {
231 XSI_NS,
232 "type"
233 23531 };
234 GlobusFuncName(globus_i_xsd_deserialize_from_xsi_type);
235 23531 GlobusSoapMessageDebugEnter();
236
237 23531 result = xsd_QName_deserialize_attribute_pointer(
238 &type_attr_name,
239 &type,
240 message_handle,
241 0);
242
243 23531 if (type == NULL ||
244 result != GLOBUS_SUCCESS ||
245 xsd_QName_keyeq(type, &xsd_any_qname) ||
246 xsd_QName_keyeq(type, &xsd_anyType_qname))
247 {
248 goto exit;
249 }
250
251 2172 GlobusSoapMessageDebugPrintf(
252 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
253 ("\tLooking for xsi:type {%s}%s:\n",
254 type->Namespace, type->local));
255
256 2172 if(!any_info && registry)
257 {
258 0 GlobusSoapMessageDebugPrintf(
259 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
260 ("\t\tin instance registry\n"));
261
262 0 result = globus_xsd_type_registry_get(
263 registry, type, &any_info);
264 0 if(result != GLOBUS_SUCCESS)
265 {
266 0 result = GlobusSoapMessageErrorFailedRegistryLookup(result, type);
267 0 goto exit;
268 }
269
270 0 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS))
271 {
272 0 if(any_info)
273 {
274 0 GlobusSoapMessageDebugPrintf(
275 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
276 ("\t\tFound any info: {%s}%s\n",
277 any_info->type->Namespace, any_info->type->local));
278 }
279 }
280 }
281
282 2172 if(!any_info)
283 {
284 2172 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS))
285 {
286 0 if(any_info)
287 {
288 0 GlobusSoapMessageDebugPrintf(
289 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
290 ("\tFound any info: {%s}%s\n",
291 any_info->type->Namespace,
292 any_info->type->local));
293 }
294 }
295 }
296
297 2172 if(!any_info)
298 {
299 2172 GlobusSoapMessageDebugPrintf(
300 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
301 ("\t\tin global registry\n"));
302
303 2172 result = globus_xsd_type_registry_get(
304 GLOBUS_GLOBAL_TYPE_REGISTRY, type, &any_info);
305 2172 if(result != GLOBUS_SUCCESS)
306 {
307 0 result = GlobusSoapMessageErrorFailedRegistryLookup(
308 result, type);
309 0 goto exit;
310 }
311
312 2172 if(GlobusSoapMessageDebug(GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS))
313 {
314 0 if(any_info)
315 {
316 0 GlobusSoapMessageDebugPrintf(
317 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
318 ("\tFound any info: {%s}%s\n",
319 any_info->type->Namespace,
320 any_info->type->local));
321 }
322 }
323 }
324
325 2172 if(!any_info)
326 {
327 0 any_info = &globus_xml_buffer_contents_info;
328 }
329
330 23531 exit:
331
332 23531 *found_any_info = any_info;
333
334 23531 if (type != NULL)
335 {
336 2172 xsd_QName_destroy(type);
337 }
338
339 23531 GlobusSoapMessageDebugEnter();
340 23531 return result;
341 }
342
343 globus_result_t
344 xsd_any_deserialize(
345 const xsd_QName * element_qname,
346 xsd_any * instance,
347 globus_soap_message_handle_t message_handle,
348 globus_xsd_element_options_t options)
349 10957 {
350 10957 globus_result_t result = GLOBUS_SUCCESS;
351 10957 xsd_QName deselem_qname = { NULL, NULL };
352 10957 int element_exists = 0;
353 GlobusFuncName(xsd_any_deserialize);
354 10957 GlobusSoapMessageDebugEnter();
355
356 10957 if (options & GLOBUS_XSD_ELEMENT_CONTENTS_ONLY)
357 {
358 797 if (!instance->any_info)
359 {
360 0 instance->any_info = &globus_xml_buffer_contents_info;
361 }
362 }
363 else
364 {
365 10160 result = globus_soap_message_deserialize_element_unknown(
366 message_handle, &deselem_qname);
367
368 10160 if(result != GLOBUS_SUCCESS)
369 {
370 122 if(GlobusSoapMessageStatusFailedWithTextCheck(result))
371 {
372 122 element_exists = 0;
373 122 if (!instance->any_info)
374 {
375 0 instance->any_info = &globus_xml_buffer_contents_info;
376 }
377 }
378 0 else if(!GlobusSoapMessageStatusCheck(result))
379 {
380 0 result = GlobusSoapMessageErrorDeserializeFailed(
381 result, &xsd_any_qname);
382 0 goto exit;
383 }
384 else
385 {
386 goto exit;
387 }
388 }
389 else
390 {
391 10038 element_exists = 1;
392 10038 globus_soap_message_deserialize_push_element(message_handle);
393 }
394
395 10160 if (element_exists && element_qname &&
396 !xsd_QName_keyeq(element_qname, &xsd_any_qname))
397 {
398 93 if (deselem_qname.Namespace == NULL)
399 {
400 /* No namespace present: only valid if ##any or ##local is
401 * allowed
402 */
403 0 if (strstr(element_qname->Namespace, "##any") ||
404 strstr(element_qname->Namespace, "##local"))
405 {
406 /* OK */
407 }
408 else
409 {
410 0 result = GlobusSoapMessageErrorDeserializeFailed(
411 result, &xsd_any_qname);
412
413 0 goto exit;
414 }
415 }
416 93 else if (strncmp(element_qname->Namespace, "##other{",8) == 0)
417 {
418 3 if (strncmp(element_qname->Namespace+8,
419 deselem_qname.Namespace,
420 strlen(element_qname->Namespace+8)-1) != 0)
421 {
422 /* OK */
423 }
424 else
425 {
426 0 result = GlobusSoapMessageErrorDeserializeFailed(
427 result, &xsd_any_qname);
428 0 goto exit;
429 }
430 }
431 90 else if (strstr(element_qname->Namespace, "##any"))
432 {
433 /* OK */
434 }
435 0 else if (strstr(element_qname->Namespace, deselem_qname.Namespace))
436 {
437 /* OK */
438 }
439 else
440 {
441 0 result = GlobusSoapMessageErrorDeserializeFailed(
442 result, &xsd_any_qname);
443 0 goto exit;
444 }
445 }
446 }
447
448 /* Deserialize current namespace prefixes into the any */
449 10957 result = globus_soap_message_deserialize_get_prefixes(
450 message_handle,
451 &instance->namespaces);
452 10957 if (result != GLOBUS_SUCCESS)
453 {
454 0 goto exit;
455 }
456
457 10957 GlobusSoapMessageDebugPrintf(
458 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS, ("\n\nDeserializing xsd:any\n"));
459
460 /* only if an element exists, set the instance->element to it */
461 10957 if(element_exists)
462 {
463 10038 result = xsd_QName_init(&instance->element);
464 10038 if (result != GLOBUS_SUCCESS)
465 {
466 0 goto exit;
467 }
468 10038 instance->element->Namespace = deselem_qname.Namespace;
469 10038 instance->element->local = deselem_qname.local;
470
471 10038 deselem_qname.Namespace = NULL;
472 10038 deselem_qname.local = NULL;
473
474 /* if instance->any_info isn't set, then look for info in registry
475 * based on QName of element
476 */
477 10038 if(!instance->any_info)
478 {
479 338 result = globus_i_xsd_deserialize_from_element_qname(
480 instance->element,
481 &instance->any_info,
482 instance->registry,
483 message_handle);
484 338 if(result != GLOBUS_SUCCESS)
485 {
486 0 result = GlobusSoapMessageErrorDeserializeFailed(
487 result, &xsd_any_qname);
488 0 goto exit;
489 }
490 }
491 }
492
493 /* no any_info, look for xsi:type */
494 10957 if(!instance->any_info)
495 {
496 5 result = globus_i_xsd_deserialize_from_xsi_type(
497 &instance->any_info,
498 instance->registry,
499 message_handle);
500 5 if(result != GLOBUS_SUCCESS)
501 {
502 0 result = GlobusSoapMessageErrorDeserializeFailed(
503 result, &xsd_any_qname);
504 0 goto exit;
505 }
506 }
507
508 10957 if(!instance->any_info)
509 {
510 5 instance->any_info = (&globus_xml_buffer_contents_info);
511 }
512
513 10957 GlobusSoapMessageDebugPrintf(
514 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
515 ("Using any info: {%s}%s\n",
516 instance->any_info->type->Namespace,
517 instance->any_info->type->local));
518
519 10957 result = instance->any_info->deserialize(
520 instance->element,
521 &instance->value,
522 message_handle,
523 options);
524 10957 if(result != GLOBUS_SUCCESS)
525 {
526 0 result = GlobusSoapMessageErrorDeserializeFailed(
527 result, instance->any_info->type);
528 0 goto exit;
529 }
530 10957 if (instance->any_info == &xsd_QName_info ||
531 instance->any_info == &xsd_QName_contents_info)
532 {
533 0 xsd_string_array_destroy_contents(&instance->namespaces);
534 }
535
536 10957 exit:
537
538 10957 if(result != GLOBUS_SUCCESS)
539 {
540 0 xsd_any_destroy_contents(instance);
541 }
542 10957 xsd_QName_destroy_contents(&deselem_qname);
543
544 10957 GlobusSoapMessageDebugExit();
545 10957 return result;
546 }
547
548 globus_result_t
549 xsd_any_deserialize_pointer(
550 const xsd_QName * element_qname,
551 xsd_any ** ip,
552 globus_soap_message_handle_t message_handle,
553 globus_xsd_element_options_t options)
554 2651042 {
555 xsd_any * instance;
556 2651042 xsd_QName deselem_qname = { NULL, NULL };
557 int element_exists;
558 2651042 globus_result_t result = GLOBUS_SUCCESS;
559 GlobusFuncName(xsd_any_deserialize_pointer);
560 2651042 GlobusSoapMessageDebugEnter();
561
562 2651042 result = xsd_any_init(&instance);
563 2651042 if(result != GLOBUS_SUCCESS)
564 {
565 0 result = GlobusSoapMessageErrorDeserializeFailed(
566 result, &xsd_any_qname);
567 0 goto exit;
568 }
569
570 2651042 result = globus_soap_message_deserialize_element_unknown(
571 message_handle, &deselem_qname);
572 2651042 if(result != GLOBUS_SUCCESS)
573 {
574 419 if(GlobusSoapMessageStatusElementNotFoundCheck(result) ||
575 GlobusSoapMessageStatusFailedWithTextCheck(result))
576 {
577 174 element_exists = 0;
578 174 if (!instance->any_info)
579 {
580 174 instance->any_info = &globus_xml_buffer_contents_info;
581 }
582 174 result = GLOBUS_SUCCESS;
583 }
584 245 else if(!GlobusSoapMessageStatusCheck(result))
585 {
586 0 result = GlobusSoapMessageErrorDeserializeFailed(
587 result, &xsd_any_qname);
588 0 goto exit;
589 }
590 else
591 {
592 goto exit;
593 }
594 }
595 else
596 {
597 2650623 element_exists = 1;
598 2650623 globus_soap_message_deserialize_push_element(message_handle);
599 }
600
601 /* When deserializing a pointer, namespace validation failures can
602 * be ignored and we'll just return no element
603 */
604 2650797 if (element_exists && element_qname)
605 {
606 2640854 if (deselem_qname.Namespace == NULL)
607 {
608 /* No namespace present: only valid if ##any or ##local is
609 * allowed
610 */
611 48 if (strstr(element_qname->Namespace, "##any") ||
612 strstr(element_qname->Namespace, "##local"))
613 {
614 /* OK */
615 }
616 else
617 {
618 0 goto exit;
619 }
620 }
621 2640806 else if (strncmp(element_qname->Namespace, "##other{",8) == 0)
622 {
623 264 if (strncmp(element_qname->Namespace+8,
624 deselem_qname.Namespace,
625 strlen(element_qname->Namespace+8)-1) != 0)
626 {
627 /* OK */
628 }
629 else
630 {
631 243 goto exit;
632 }
633 }
634 2640542 else if (strstr(element_qname->Namespace, "##any"))
635 {
636 /* OK */
637 }
638 0 else if (strstr(element_qname->Namespace, deselem_qname.Namespace))
639 {
640 /* OK */
641 }
642 else
643 {
644 0 goto exit;
645 }
646 }
647 2650554 result = globus_soap_message_deserialize_get_prefixes(
648 message_handle,
649 &instance->namespaces);
650 2650554 if (result != GLOBUS_SUCCESS)
651 {
652 0 goto exit;
653 }
654
655 2650554 GlobusSoapMessageDebugPrintf(
656 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS, ("\n\nDeserializing xsd:any\n"));
657
658 2650554 if(element_exists)
659 {
660 2650380 result = xsd_QName_init(&instance->element);
661 2650380 if (result != GLOBUS_SUCCESS)
662 {
663 0 goto exit;
664 }
665
666 2650380 instance->element->Namespace = deselem_qname.Namespace;
667 2650380 instance->element->local = deselem_qname.local;
668 2650380 deselem_qname.Namespace = NULL;
669 2650380 deselem_qname.local = NULL;
670
671 /* if instance->any_info isn't set, then look for info in registry
672 * based on QName of element
673 */
674 2650380 if(!instance->any_info)
675 {
676 2650380 result = globus_i_xsd_deserialize_from_element_qname(
677 instance->element,
678 &instance->any_info,
679 instance->registry,
680 message_handle);
681 2650380 if(result != GLOBUS_SUCCESS)
682 {
683 0 result = GlobusSoapMessageErrorDeserializeFailed(
684 result, &xsd_any_qname);
685 0 goto exit;
686 }
687 }
688 }
689
690 /* no any_info, look for xsi:type */
691 2650554 if(!instance->any_info)
692 {
693 23178 result = globus_i_xsd_deserialize_from_xsi_type(
694 &instance->any_info,
695 instance->registry,
696 message_handle);
697 23178 if(result != GLOBUS_SUCCESS)
698 {
699 0 result = GlobusSoapMessageErrorDeserializeFailed(
700 result, &xsd_any_qname);
701 0 goto exit;
702 }
703 }
704
705 2650554 if(!instance->any_info)
706 {
707 21006 instance->any_info = (&globus_xml_buffer_contents_info);
708 }
709
710 2650554 GlobusSoapMessageDebugPrintf(
711 GLOBUS_SOAP_MESSAGE_DEBUG_WILDCARDS,
712 ("Using any info: {%s}%s\n",
713 instance->any_info->type->Namespace,
714 instance->any_info->type->local));
715
716 2650554 result = instance->any_info->deserialize(
717 instance->element,
718 &instance->value,
719 message_handle,
720 options);
721 2650554 if(result != GLOBUS_SUCCESS)
722 {
723 0 result = GlobusSoapMessageErrorDeserializeFailed(
724 result, instance->any_info->type);
725 0 goto exit;
726 }
727
728 2650554 *ip = instance;
729
730 2650554 if (instance->any_info == &xsd_QName_info ||
731 instance->any_info == &xsd_QName_contents_info)
732 {
733 0 xsd_string_array_destroy_contents(&instance->namespaces);
734 }
735 2651042 exit:
736
737 2651042 if(result != GLOBUS_SUCCESS)
738 {
739 245 xsd_any_destroy(instance);
740 }
741 2651042 xsd_QName_destroy_contents(&deselem_qname);
742
743 2651042 GlobusSoapMessageDebugExit();
744 2651042 return result;