1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <assert.h>
26 #include <ctype.h>
27 #include "wsmanparser.h"
28 #include "wsbuf.h"
29 //#include "http.h"
30 //#include "time.h"
31 //#include <xml/xml.h>
32 //#include <base/buf.h>
33 #include <base/log.h>
34 #include <base/result.h>
35 #include <base/strings.h>
36
37 #include "wstags.h"
38 #include "wstags.inc"
39 #include <wsman/uri.h>
40
41 #define T MI_T
42
43 mike 1.1 #if 0
44 #define ENABLE_TRACING
45 #endif
46
47 #ifdef ENABLE_TRACING
48 #define PRINTF(a) printf a
49 #else
50 #define PRINTF(a)
51 #endif
52
53 #if defined(TRACE_RETURN)
54 # define RETURN(X) \
55 do \
56 { \
57 printf("RETURN[%d]\n", __LINE__); \
58 return X; \
59 } \
60 while (0)
61 #else
62 # define RETURN(X) return X
63 #endif
64 mike 1.1
65 /*
66 **==============================================================================
67 **
68 ** Local definitions:
69 **
70 **==============================================================================
71 */
72 static int _GetInstance(
73 XML* xml,
74 XML_Elem *start,
75 Batch* dynamicBatch,
76 MI_Instance** dynamicInstanceParams);
77
78 /****************************************************************************************/
79 /* soap processing */
80
81 static int _MustUnderstandCanBeIgnored(
82 const XML_Elem* e)
83 {
84 size_t i;
85 mike 1.1 for (i = 0; i < e->attrsSize; i++)
86 {
87 if (strcmp(e->attrs[i].name, "s:mustUnderstand") == 0 &&
88 strcmp(e->attrs[i].value, "true") == 0)
89 {
90 RETURN(-1);
91 }
92 }
93 return 0;
94 }
95
96 #if 1
97 static MI_Boolean IsValidClassname(const char* classname)
98 {
99 const char* p = classname;
100
101 if (!isalpha((unsigned char)(*p)) && *p != '_')
102 return MI_FALSE;
103
104 p++;
105
106 mike 1.1 for (; *p; p++)
107 {
108 if (!isalnum((unsigned char)(*p)) && *p != '_')
109 return MI_FALSE;
110 }
111
112 return MI_TRUE;
113 }
114 #endif
115
116 static int _GetSelector(
117 XML* xml,
118 XML_Elem *e,
119 const char** ns,
120 const char* classname,
121 MI_Instance** instance,
122 Batch** batch)
123 {
124 size_t i;
125
126 /* expecting namespace or key */
127 mike 1.1 for (i = 0; i < e->attrsSize; i++)
128 {
129 #if 1
130 /* To support GetClass */
131 if (strcmp(e->attrs[i].name, "Name") == 0 &&
132 strcmp(e->attrs[i].value, "ClassName") == 0)
133 {
134 if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
135 RETURN(-1);
136
137 PRINTF(("a:Selector:ClassName{%s}\n", e->data));
138
139 if (!IsValidClassname(e->data))
140 RETURN(-1);
141
142 classname = e->data;
143 }
144 else
145 #endif
146 if (strcmp(e->attrs[i].name, "Name") == 0 &&
147 strcmp(e->attrs[i].value, "__cimnamespace") == 0)
148 mike 1.1 {
149 /* namespace */
150 if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
151 RETURN(-1);
152
153 PRINTF(("a:Selector:namespace{%s}\n", e->data));
154 *ns = e->data;
155 }
156 else if (strcmp(e->attrs[i].name, "Name") == 0)
157 {
158 /* keys */
159 const char* propName = e->attrs[i].value;
160
161 if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
162 RETURN(-1);
163
164 PRINTF(("a:Selector:namespace{%s}\n", e->data));
165
166 /* allocate batch and instance if needed */
167 if (!(*instance))
168 {
169 mike 1.1 MI_Result r;
170 MI_Char* cn;
171
172 /* verify that we already received classname */
173 if (!classname)
174 {
175 XML_Raise(xml, "class-name was not found during selector parsing");
176 RETURN(-1);
177 }
178
179 /* Destroy old batch if it exists (from previous operation) */
180 if (*batch)
181 {
182 Batch_Destroy(*batch);
183 }
184
185 *batch = Batch_New(BATCH_MAX_PAGES);
186
187 if (!(*batch))
188 RETURN(-1);
189
190 mike 1.1 cn = Batch_Strdup2(*batch, classname);
191
192 r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch);
193 if (MI_RESULT_OK != r)
194 RETURN(-1);
195 }
196
197 /* add next property to the instance */
198 {
199 const MI_Char* wpropName = Batch_Strdup2(*batch, propName);
200 MI_Result r;
201 MI_Value value;
202
203 value.string = Batch_Strdup2(*batch, e->data);
204
205 // Set the property.
206 r = MI_Instance_AddElement(*instance, wpropName, &value,
207 MI_STRING, MI_FLAG_BORROW | MI_FLAG_KEY);
208
209 if (MI_RESULT_OK != r)
210 RETURN(-1);
211 mike 1.1 }
212 }
213 else
214 continue;
215
216 if (XML_Expect(xml, e, XML_END, "w:Selector") != 0)
217 RETURN(-1);
218
219 break;
220 }
221
222 return 0;
223 }
224
225 static int _GetSelectorSet(
226 XML* xml,
227 WSMAN_WSHeader* wsheader)
228 {
229 XML_Elem e;
230
231 if (XML_Expect(xml, &e, XML_START, "w:Selector") != 0)
232 mike 1.1 RETURN(-1);
233
234 /* iterate through all selector tags */
235 for (;;)
236 {
237 if (0 != _GetSelector(
238 xml,
239 &e,
240 &wsheader->rqtNamespace,
241 wsheader->rqtClassname,
242 &wsheader->instance,
243 &wsheader->instanceBatch))
244 RETURN(-1);
245
246 /**/
247 if (XML_Next(xml, &e) != 0)
248 RETURN(-1);
249
250 if (XML_END == e.type)
251 break;
252
253 mike 1.1 }
254
255 return 0;
256 }
257
258 static int _GetReferenceParameters(
259 XML* xml,
260 Batch* dynamicBatch,
261 MI_Instance** dynamicInstanceParams)
262 {
263 XML_Elem e;
264 const char* classname = 0;
265 const char* nameSpace = NULL;
266
267 /* extract ResourceURI and SelectorSet */
268 for (;;)
269 {
270 if (XML_Next(xml, &e) != 0)
271 RETURN(-1);
272
273 if (XML_END == e.type)
274 mike 1.1 break;
275
276 if (0 == strcmp("w:ResourceURI", e.data))
277 {
278 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
279 RETURN(-1);
280
281 classname = strrchr(e.data, '/');
282 /* skip '/' */
283 if (classname)
284 classname++;
285
286 if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
287 RETURN(-1);
288
289 continue;
290 }
291
292 if (0 == strcmp("w:SelectorSet", e.data))
293 {
294 /* Allocate an instance */
295 mike 1.1 if (!*dynamicInstanceParams)
296 {
297 MI_Result r;
298 const MI_Char* cn;
299
300 if (!classname)
301 {
302 XML_Raise(xml, "ResourceURI tag expected");
303 RETURN(-1);
304 }
305
306 cn = Batch_Strdup2(dynamicBatch, classname);
307
308 r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
309 if (MI_RESULT_OK != r)
310 RETURN(-1);
311 }
312
313 /* iterate through all selector tags */
314 for (;;)
315 {
316 mike 1.1 const char* ns = NULL;
317
318 if (_GetSelector(
319 xml,
320 &e,
321 &ns,
322 classname,
323 dynamicInstanceParams,
324 &dynamicBatch) != 0)
325 {
326 RETURN(-1);
327 }
328
329 if (ns)
330 {
331 nameSpace = ns;
332 }
333
334 /**/
335 if (XML_Next(xml, &e) != 0)
336 RETURN(-1);
337 mike 1.1
338 if (XML_END == e.type)
339 break;
340
341 }
342 continue;
343 }
344 }
345
346 if (nameSpace)
347 (*dynamicInstanceParams)->nameSpace = nameSpace;
348
349 return 0;
350 }
351
352 static int _GetReference(
353 XML* xml,
354 XML_Elem *start,
355 Batch* dynamicBatch,
356 MI_Instance** dynamicInstanceParams)
357 {
358 mike 1.1 XML_Elem e;
359
360 e = *start;
361
362 /* extract all parameters */
363 for (;;)
364 {
365 if (0 != strcmp("a:ReferenceParameters", e.data))
366 {
367 if (XML_Skip(xml) != 0)
368 RETURN(-1);
369
370 if (XML_Next(xml, &e) != 0)
371 RETURN(-1);
372
373 if (e.type == XML_END)
374 break;
375
376 continue;
377 }
378
379 mike 1.1 if (0 != _GetReferenceParameters(xml, dynamicBatch, dynamicInstanceParams))
380 RETURN(-1);
381
382 if (XML_Next(xml, &e) != 0)
383 RETURN(-1);
384
385 if (e.type == XML_END)
386 break;
387 }
388
389 return 0;
390 }
391
392 static int _GetSingleProperty(
393 XML* xml,
394 Batch* dynamicBatch,
395 const char* propNameChar,
396 MI_Value* value,
397 MI_Type* type)
398 {
399 XML_Elem e;
400 mike 1.1
401 if (XML_Next(xml, &e) != 0)
402 RETURN(-1);
403
404 if (e.type == XML_CHARS)
405 {
406 /* Plain string property */
407 value->string = Batch_Strdup2(dynamicBatch, e.data);
408 *type = MI_STRING;
409
410 if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
411 RETURN(-1);
412 }
413 else if ('a' == e.data[0])
414 {
415 /* Reference as </adddress></ReferenceParameters>*/
416 value->instance = 0;
417 if (0 != _GetReference(xml, &e, dynamicBatch, &value->instance))
418 RETURN(-1);
419
420 *type = MI_REFERENCE;
421 mike 1.1 }
422 else
423 {
424 /* Embedded instance */
425 value->instance = 0;
426 if (0 != _GetInstance(xml, &e, dynamicBatch, &value->instance))
427 RETURN(-1);
428
429 *type = MI_INSTANCE;
430
431 if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
432 RETURN(-1);
433 }
434
435
436 return 0;
437 }
438
439 static int _AddValueToArray(
440 Batch* dynamicBatch,
441 MI_Value* valueA,
442 mike 1.1 MI_Type typeA,
443 const MI_Value* value,
444 MI_Type type)
445 {
446 /* does type match? */
447 if ((type | MI_ARRAY_BIT) != typeA)
448 RETURN(-1);
449
450 /* do we need to realloc array? */
451 if ((valueA->array.size % 16) == 0)
452 {
453 void* newData = Batch_Get(dynamicBatch, (valueA->array.size + 16) * sizeof(void*));
454
455 if (!newData)
456 RETURN(-1);
457
458 if (valueA->array.size)
459 memcpy(newData, valueA->array.data, valueA->array.size * sizeof(void*));
460
461 valueA->array.data = newData;
462 }
463 mike 1.1
464 if (type == MI_STRING)
465 valueA->stringa.data[valueA->stringa.size] = value->string;
466 else
467 valueA->instancea.data[valueA->instancea.size] = value->instance;
468
469 valueA->array.size++;
470 return 0;
471 }
472
473 static int _GetInstance(
474 XML* xml,
475 XML_Elem *start,
476 Batch* dynamicBatch,
477 MI_Instance** dynamicInstanceParams)
478 {
479 XML_Elem e;
480 const MI_Char* propNameA = 0;
481 MI_Value valueA;
482 MI_Type typeA = MI_BOOLEAN;
483 const MI_Char* propNamePrev = 0;
484 mike 1.1 MI_Value valuePrev;
485 MI_Type typePrev = MI_BOOLEAN;
486
487 memset(&valueA, 0, sizeof(valueA));
488
489 /* extract all parameters */
490 for (;;)
491 {
492 if (XML_Next(xml, &e) != 0)
493 RETURN(-1);
494
495 if (e.type == XML_END)
496 break;
497
498 /* skip possible comments */
499 if (e.type != XML_START)
500 continue;
501
502 /* allocate new instance if needed */
503 if (!*dynamicInstanceParams)
504 {
505 mike 1.1 MI_Result r;
506 const MI_Char* cn = Batch_Strdup2(dynamicBatch, start->data + 2);
507
508 r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
509 if (MI_RESULT_OK != r)
510 RETURN(-1);
511 }
512
513 /* add next property to the instance */
514 if (e.size > 2) /* ?:<name> */
515 {
516 MI_Result r;
517 MI_Value value;
518 MI_Type type = MI_BOOLEAN;
519 const char* propNameChar;
520 const MI_Char* propName;
521
522 propNameChar = e.data;
|
596 mike 1.1
597 propNamePrev = propName;
598 valuePrev = value;
599 typePrev = type;
600 }
601
602 }
603 else
604 {
605 /* collecting first item */
606 propNamePrev = propName;
607 valuePrev = value;
608 typePrev = type;
609 }
610 }
611 }
612
613 /* if last property was array - add it */
614 if (propNameA)
615 {
616 MI_Result r;
617 mike 1.1
618 r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
619 typeA, MI_FLAG_BORROW);
620
621 if (MI_RESULT_OK != r)
622 RETURN(-1);
623 }
624 else if (propNamePrev)
625 {
626 MI_Result r;
627
628 r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev,
629 typePrev, MI_FLAG_BORROW);
630
631 if (MI_RESULT_OK != r)
632 RETURN(-1);
633 }
634
635 /* check closing tag */
636 if (strcmp(e.data, start->data) != 0)
637 RETURN(-1);
638 mike 1.1
639 return 0;
640 }
641
642 int WS_ParseWSHeader(
643 XML* xml,
644 WSMAN_WSHeader* wsheader)
645 {
646 XML_Elem e;
647
648 memset(wsheader, 0, sizeof(WSMAN_WSHeader));
649
650 /* Expect <s:Header> */
651 if (XML_Expect(xml, &e, XML_START, "s:Header") != 0)
652 RETURN(-1);
653
654 for (;;)
655 {
656 if (XML_Next(xml, &e) != 0)
657 RETURN(-1);
658
659 mike 1.1 if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0)
660 {
661 int tag = HashStr(e.data, e.size);
662
663 if (WSMANTAG_HEADER != tag)
664 {
665 LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
666 RETURN(-1);
667 }
668 //printf("DONE\n");
669 break;
670 }
671
672 /* skip possible comments */
673 if (e.type != XML_START)
674 continue;
675
676 switch (HashStr(e.data, e.size))
677 {
678 case WSMANTAG_TO:
679 {
680 mike 1.1 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
681 RETURN(-1);
682
683 PRINTF(("a:To{%s}\n", e.data));
684
685 if (XML_Expect(xml, &e, XML_END, "a:To") != 0)
686 RETURN(-1);
687 }
688 break;
689
690 case WSMANTAG_RESOURCE_URI:
691 {
692 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
693 RETURN(-1);
694
695 PRINTF(("w:ResourceURI{%s}\n", e.data));
696 wsheader->rqtClassname = strrchr(e.data, '/');
697 /* skip '/' */
698 if (wsheader->rqtClassname)
699 wsheader->rqtClassname++;
700
701 mike 1.1 if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
702 RETURN(-1);
703 }
704 break;
705
706 case WSMANTAG_REPLY_TO:
707 {
708 if (XML_Expect(xml, &e, XML_START, "a:Address") != 0)
709 RETURN(-1);
710
711 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
712 RETURN(-1);
713
714 if (XML_Expect(xml, &e, XML_END, "a:Address") != 0)
715 RETURN(-1);
716
717 if (XML_Expect(xml, &e, XML_END, "a:ReplyTo") != 0)
718 RETURN(-1);
719 }
720 break;
721
722 mike 1.1 case WSMANTAG_ACTION:
723 {
724 wsheader->foundAction = MI_TRUE;
725
726 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
727 RETURN(-1);
728
729 wsheader->rqtAction = HashStr(e.data, e.size);
730
731 if (0 == wsheader->rqtAction)
732 {
733 char* s;
734 /* DSP0226; 9: Custom Actions (Methods) just need to have unique URI.
735 We are assuming it has format like http://<server>/wbem/wscim/1/cim-schema/2/<class-name>/<method-name> */
736
737 if (0 != strncmp(e.data, "http://", 7))
738 RETURN(-1);
739
740 wsheader->rqtServer = e.data + 7;
741
742 s = strchr(wsheader->rqtServer, '/');
743 mike 1.1
744 if (!s)
745 RETURN(-1);
746
747 *s = 0;
748 s++;
749
750 if (0 != strncmp(s, "wbem/wscim/1/cim-schema/2/", 26))
751 RETURN(-1);
752
753 s += 26;
754
755 wsheader->rqtClassname = s;
756 s = strchr(s, '/');
757
758 if (!s)
759 RETURN(-1);
760
761 *s = 0;
762 s++;
763 wsheader->rqtMethod = s;
764 mike 1.1 }
765
766 if (XML_Expect(xml, &e, XML_END, "a:Action") != 0)
767 RETURN(-1);
768 }
769 break;
770
771 case WSMANTAG_SELECTOR_SET:
772 {
773 if (_GetSelectorSet(xml, wsheader) != 0)
774 RETURN(-1);
775 }
776 break;
777
778 case WSMANTAG_MESSAGE_ID:
779 {
780 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
781 RETURN(-1);
782
783 wsheader->rqtMessageID = e.data;
784
785 mike 1.1 if (XML_Expect(xml, &e, XML_END, "a:MessageID") != 0)
786 RETURN(-1);
787 }
788 break;
789
790 case WSMANTAG_MAX_ENVELOPE_SIZE:
791 {
792 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
793 RETURN(-1);
794
795 wsheader->maxEnvelopeSize = (MI_Uint32)Strtoull(e.data, NULL, 10);
796 PRINTF(("maxEnvelopeSize{%d}\n", wsheader->maxEnvelopeSize));
797
798 if (XML_Expect(xml, &e, XML_END, "w:MaxEnvelopeSize") != 0)
799 RETURN(-1);
800 }
801 break;
802
803 default:
804 {
805 if (_MustUnderstandCanBeIgnored(&e) != 0)
806 mike 1.1 {
807 wsheader->unknownMandatoryTag = e.data;
808 LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted",
809 e.data ));
810 /* validate header will send correct repsonse to the client */
811 }
812
813 if (XML_Skip(xml) != 0)
814 RETURN(-1);
815 }
816 break;
817
818 }
819 }
820 return 0;
821 }
822
823 int WS_ParseSoapEnvelope(XML* xml)
824 {
825 XML_Elem e;
826
827 mike 1.1 /* Ignore the processing instruction (if any) */
828 {
829 if (XML_Next(xml, &e) != 0)
830 {
831 XML_Raise(xml, "missing root element");
832 RETURN(-1);
833 }
834
835 if (e.type != XML_INSTRUCTION)
836 {
837 if (XML_PutBack(xml, &e) != 0)
838 RETURN(-1);
839 }
840 }
841
842 /* Expect <s:Envelope> */
843 if (XML_Expect(xml, &e, XML_START, "s:Envelope") != 0)
844 RETURN(-1);
845
846 return 0;
847 }
848 mike 1.1
849 static const char* _ExpectCharsAndEnd(
850 XML* xml,
851 const char* name)
852 {
853 XML_Elem e;
854 const char* chars;
855
856 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
857 return NULL;
858
859 chars = e.data;
860
861 if (XML_Expect(xml, &e, XML_END, name) != 0)
862 return NULL;
863
864 return chars;
865 }
866
867 /*
868 **==============================================================================
869 mike 1.1 **
870 ** _ParseAssociationFilterObject()
871 **
872 ** Example:
873 ** <b:Object>
874 ** <a:Address>
875 ** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
876 ** </a:Address>
877 ** <a:ReferenceParameters>
878 ** <w:ResourceURI>
879 ** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
880 ** </w:ResourceURI>
881 ** <w:SelectorSet>
882 ** <w:Selector Name="__cimnamespace">
883 ** root/cimv2
884 ** </w:Selector>
885 ** <w:Selector Name="Key">
886 ** 1001
887 ** </w:Selector>
888 ** </w:SelectorSet>
889 ** </a:ReferenceParameters>
890 mike 1.1 ** </b:Object>
891 *
892 **==============================================================================
893 */
894
895 static int _ParseAssociationFilterObject(
896 XML* xml,
897 Batch* batch,
898 WSMAN_AssociationFilter* filter)
899 {
900 XML_Elem e;
901
902 /* Parse child elements */
903
904 for (;;)
905 {
906 /* Get next element */
907
908 if (XML_Next(xml, &e) != 0)
909 RETURN(-1);
910
911 mike 1.1 /* Put it back and break out if not a start tag */
912
913 if (e.type != XML_START)
914 {
915 if (XML_PutBack(xml, &e) != 0)
916 RETURN(-1);
917
918 break;
919 }
920
921 /* Handle "Object" tag */
922
923 if (strcmp(e.data, "a:ReferenceParameters") == 0)
924 {
925 if (_GetReferenceParameters(
926 xml,
927 batch,
928 &filter->referenceParameters) != 0)
929 {
930 RETURN(-1);
931 }
932 mike 1.1 }
933 else if (strcmp(e.data, "a:Address") == 0)
934 {
935 filter->address = _ExpectCharsAndEnd(xml, "a:Address");
936
937 if (!filter->address)
938 RETURN(-1);
939 }
940 else
941 {
942 if (XML_Skip(xml) != 0)
943 RETURN(-1);
944 }
945 }
946
947 /* Expect </Object> */
948
949 if (XML_Expect(xml, &e, XML_END, "b:Object") != 0)
950 RETURN(-1);
951
952 return 0;
953 mike 1.1 }
954
955 /*
956 **==============================================================================
957 **
958 ** _ParseAssociationFilter()
959 **
960 ** Example:
961 ** <b:AssociatedInstances>
962 ** <b:Object>
963 ** <a:Address>
964 ** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
965 ** </a:Address>
966 ** <a:ReferenceParameters>
967 ** <w:ResourceURI>
968 ** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
969 ** </w:ResourceURI>
970 ** <w:SelectorSet>
971 ** <w:Selector Name="__cimnamespace">
972 ** root/cimv2
973 ** </w:Selector>
974 mike 1.1 ** <w:Selector Name="Key">
975 ** 1001
976 ** </w:Selector>
977 ** </w:SelectorSet>
978 ** </a:ReferenceParameters>
979 ** </b:Object>
980 ** <b:AssociationClassName>
981 ** ABC_Connector
982 ** </b:AssociationClassName>
983 ** <b:Role>
984 ** Component
985 ** </b:Role>
986 ** <b:ResultClassName>
987 ** ABC_Gadget
988 ** </b:ResultClassName>
989 ** <b:ResultRole>
990 ** Part
991 ** </b:ResultRole>
992 ** </b:AssociatedInstances>
993 **
994 **==============================================================================
995 mike 1.1 */
996
997 static int _ParseAssociationFilter(
998 XML* xml,
999 Batch* batch,
1000 WSMAN_AssociationFilter* filter)
1001 {
1002 XML_Elem e;
1003
1004 /* Expect <AssociatedInstances> */
1005
1006 if (XML_Expect(xml, &e, XML_START, "b:AssociatedInstances") != 0)
1007 RETURN(-1);
1008
1009 /* Parse child elements */
1010
1011 for (;;)
1012 {
1013 /* Get next element */
1014
1015 if (XML_Next(xml, &e) != 0)
1016 mike 1.1 RETURN(-1);
1017
1018 /* Put it back and break out if not a start tag */
1019
1020 if (e.type != XML_START)
1021 {
1022 if (XML_PutBack(xml, &e) != 0)
1023 RETURN(-1);
1024
1025 break;
1026 }
1027
1028 /* Handle "Object" tag */
1029
1030 if (strcmp(e.data, "b:Object") == 0)
1031 {
1032 if (_ParseAssociationFilterObject(xml, batch, filter) != 0)
1033 RETURN(-1);
1034 }
1035 else if (strcmp(e.data, "b:AssociationClassName") == 0)
1036 {
1037 mike 1.1 filter->associationClassName = _ExpectCharsAndEnd(
1038 xml, "b:AssociationClassName");
1039
1040 if (!filter->associationClassName)
1041 RETURN(-1);
1042 }
1043 else if (strcmp(e.data, "b:Role") == 0)
1044 {
1045 filter->role = _ExpectCharsAndEnd(xml, "b:Role");
1046
1047 if (!filter->role)
1048 RETURN(-1);
1049 }
1050 else if (strcmp(e.data, "b:ResultClassName") == 0)
1051 {
1052 filter->resultClassName = _ExpectCharsAndEnd(
1053 xml,
1054 "b:ResultClassName");
1055
1056 if (!filter->resultClassName)
1057 RETURN(-1);
1058 mike 1.1 }
1059 else if (strcmp(e.data, "b:ResultRole") == 0)
1060 {
1061 filter->resultRole = _ExpectCharsAndEnd(
1062 xml,
1063 "b:ResultRole");
1064
1065 if (!filter->resultRole)
1066 RETURN(-1);
1067 }
1068 else
1069 {
1070 if (XML_Skip(xml) != 0)
1071 RETURN(-1);
1072 }
1073 }
1074
1075 #if 0
1076 printf("AssociationFilter\n");
1077 printf("{\n");
1078 Instance_Print(filter->referenceParameters, stdout, 1, MI_TRUE);
1079 mike 1.1 printf(" nameSpace{%s}\n", filter->referenceParameters->nameSpace);
1080 printf(" address{%s}\n", filter->address);
1081 printf(" associationClassName{%s}\n", filter->associationClassName);
1082 printf(" resultClassName{%s}\n", filter->resultClassName);
1083 printf(" role{%s}\n", filter->role);
1084 printf(" resultRole{%s}\n", filter->resultRole);
1085 printf("}\n");
1086 #endif
1087
1088 /* Expect </AssociatedInstances> */
1089
1090 if (XML_Expect(xml, &e, XML_END, "b:AssociatedInstances") != 0)
1091 RETURN(-1);
1092
1093 return 0;
1094 }
1095
1096 int WS_ParseEnumerateBody(
1097 XML* xml,
1098 Batch** batch,
1099 WSMAN_WSEnumeratePullBody* wsenumbody)
1100 mike 1.1 {
1101 XML_Elem e;
1102
1103 memset(wsenumbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1104
1105 /* Allocate batch (owned by WSMAN_ConnectionData object */
1106
1107 if (*batch == NULL)
1108 {
1109 *batch = Batch_New(BATCH_MAX_PAGES);
1110
1111 if (!*batch)
1112 RETURN(-1);
1113 }
1114
1115 /* Expect <s:Body> */
1116 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1117 RETURN(-1);
1118
1119 /* Expect <n:Enumerate> */
1120 if (XML_Expect(xml, &e, XML_START, "n:Enumerate") != 0)
1121 mike 1.1 RETURN(-1);
1122
1123 for (;;)
1124 {
1125 if (XML_Next(xml, &e) != 0)
1126 RETURN(-1);
1127
1128 if (e.type == XML_END)
1129 {
1130 int tag = HashStr(e.data, e.size);
1131
1132 if (WSMANTAG_ENUM_ENUMERATE != tag)
1133 {
1134 LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1135 RETURN(-1);
1136 }
1137 break;
1138 }
1139
1140 /* skip possible comments */
1141 if (e.type != XML_START)
1142 mike 1.1 continue;
1143
1144 switch (HashStr(e.data, e.size))
1145 {
1146 case WSMANTAG_ENUM_MAX_ELEMENTS:
1147 {
1148 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1149 RETURN(-1);
1150
1151 wsenumbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
1152 PRINTF(("maxElements{%d}\n", wsenumbody->maxElements));
1153
1154 if (XML_Expect(xml, &e, XML_END, "w:MaxElements") != 0)
1155 RETURN(-1);
1156 }
1157 break;
1158
1159 case WSMANTAG_ENUM_OPTIMIZE_ENUMERATION:
1160 {
1161 wsenumbody->allowOptimization = MI_TRUE;
1162
1163 mike 1.1 if (XML_Skip(xml) != 0)
1164 RETURN(-1);
1165 }
1166 break;
1167
1168 case WSMANTAG_ENUM_POLYMORPHISM_MODE:
1169 {
1170 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1171 RETURN(-1);
1172
1173 wsenumbody->polymorphismMode = HashStr(e.data, e.size);
1174
1175 if (XML_Expect(xml, &e, XML_END, "b:PolymorphismMode") != 0)
1176 RETURN(-1);
1177 }
1178 break;
1179
1180 case WSMANTAG_ENUM_MODE:
1181 {
1182 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1183 RETURN(-1);
1184 mike 1.1
1185 wsenumbody->enumerationMode = HashStr(e.data, e.size);
1186
1187 if (XML_Expect(xml, &e, XML_END, "w:EnumerationMode") != 0)
1188 RETURN(-1);
1189 }
1190 break;
1191
1192 /*
1193 * Examples:
1194 * <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1195 * SELECT Weight FROM Widget WHERE Key = 1001
1196 * </w:Filter>
1197 *
1198 * <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1199 * <b:AssociatedInstances>
1200 * ...
1201 * </b:AssociatedInstances>
1202 * </w:Filter>
1203 */
1204 case WSMANTAG_ENUM_FILTER:
1205 mike 1.1 {
1206 const char* dialect;
1207 const char* p;
1208
1209 /* Get 'Dialect' attribute? */
1210 dialect = XML_Elem_GetAttr(&e, "Dialect");
1211 if (!dialect)
1212 {
1213 LOGW_CHAR(("wsman: Filter tag missing Dialect attribute"));
1214 RETURN(-1);
1215 }
1216
1217
1218 /* Reduce long dialect name to final component of path */
1219 p = strrchr(dialect, '/');
1220 if (p)
1221 wsenumbody->dialect = p + 1;
1222 else
1223 wsenumbody->dialect = dialect;
1224
1225 /* Parse the association filter */
1226 mike 1.1 if (strcmp(dialect, URI_CIMBINDING "/associationFilter") == 0)
1227 {
1228 wsenumbody->foundAssociationFilter = MI_TRUE;
1229
1230 if (_ParseAssociationFilter(xml, *batch,
1231 &wsenumbody->associationFilter) != 0)
1232 {
1233 RETURN(-1);
1234 }
1235 }
1236 else
1237 {
1238 /* Get the filter text */
1239 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1240 RETURN(-1);
1241
1242 wsenumbody->filter = e.data;
1243 }
1244
1245 /* Check for closing </w:Filter> tag */
1246 if (XML_Expect(xml, &e, XML_END, "w:Filter") != 0)
1247 mike 1.1 RETURN(-1);
1248 }
1249 break;
1250
1251 default:
1252 {
1253 if (_MustUnderstandCanBeIgnored(&e) != 0)
1254 {
1255 LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1256 RETURN(-1);
1257 }
1258
1259 if (XML_Skip(xml) != 0)
1260 RETURN(-1);
1261 }
1262 break;
1263
1264 }
1265 }
1266
1267 /* Expect <s:Body> */
1268 mike 1.1 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1269 RETURN(-1);
1270
1271 /* Expect </s:Envelope> */
1272 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1273 RETURN(-1);
1274
1275 return 0;
1276 }
1277
1278 int WS_ParseInvokeBody(
1279 XML* xml,
1280 Batch* dynamicBatch,
1281 MI_Instance** dynamicInstanceParams)
1282 {
1283 XML_Elem e;
1284
1285 *dynamicInstanceParams = 0;
1286
1287 /* Expect <s:Body> */
1288 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1289 mike 1.1 RETURN(-1);
1290
1291 /* Expect <?:?> parameter's tag */
1292 for (;;)
1293 {
1294 if (XML_Next(xml, &e) != 0)
1295 RETURN(-1);
1296
1297 /* empty body? can be valid for methods without parameters */
1298 if (e.type == XML_END)
1299 return 0;
1300
1301 if (e.type == XML_START)
1302 break;
1303 }
1304
1305 if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1306 RETURN(-1);
1307
1308
1309 /* Expect <s:Body> */
1310 mike 1.1 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1311 RETURN(-1);
1312
1313 /* Expect </s:Envelope> */
1314 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1315 RETURN(-1);
1316
1317 return 0;
1318 }
1319
1320 int WS_ParseCreateBody(
1321 XML* xml,
1322 Batch* dynamicBatch,
1323 MI_Instance** dynamicInstanceParams)
1324 {
1325 XML_Elem e;
1326
1327 /* Expect <s:Body> */
1328 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1329 RETURN(-1);
1330
1331 mike 1.1 /* Expect <?:?> parameter's tag */
1332 if (XML_Next(xml, &e) != 0)
1333 RETURN(-1);
1334
1335 if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1336 RETURN(-1);
1337
1338 /* Expect <s:Body> */
1339 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1340 RETURN(-1);
1341
1342 /* Expect </s:Envelope> */
1343 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1344 RETURN(-1);
1345
1346 return 0;
1347 }
1348
1349 int WS_ParsePullBody(
1350 XML* xml,
1351 WSMAN_WSEnumeratePullBody* wsenumpullbody)
1352 mike 1.1 {
1353 XML_Elem e;
1354
1355 memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1356
1357 /* Expect <s:Body> */
1358 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1359 RETURN(-1);
1360
1361 /* Expect <n:Enumerate> */
1362 if (XML_Expect(xml, &e, XML_START, "n:Pull") != 0)
1363 RETURN(-1);
1364
1365 for (;;)
1366 {
1367 if (XML_Next(xml, &e) != 0)
1368 RETURN(-1);
1369
1370 if (e.type == XML_END)
1371 {
1372 int tag = HashStr(e.data, e.size);
1373 mike 1.1
1374 if (WSMANTAG_ENUM_PULL != tag)
1375 {
1376 LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1377 RETURN(-1);
1378 }
1379 break;
1380 }
1381
1382 /* skip possible comments */
1383 if (e.type != XML_START)
1384 continue;
1385
1386 switch (HashStr(e.data, e.size))
1387 {
1388 case WSMANTAG_PULL_MAX_ELEMENTS:
1389 {
1390 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1391 RETURN(-1);
1392
1393 wsenumpullbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
1394 mike 1.1 PRINTF(("maxElements{%d}\n", wsenumpullbody->maxElements));
1395
1396 if (XML_Expect(xml, &e, XML_END, "n:MaxElements") != 0)
1397 RETURN(-1);
1398 }
1399 break;
1400
1401 case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1402 {
1403 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1404 RETURN(-1);
1405
1406 wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
1407
1408 if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
1409 RETURN(-1);
1410 }
1411 break;
1412
1413 default:
1414 {
1415 mike 1.1 if (_MustUnderstandCanBeIgnored(&e) != 0)
1416 {
1417 LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1418 RETURN(-1);
1419 }
1420
1421 if (XML_Skip(xml) != 0)
1422 RETURN(-1);
1423 }
1424 break;
1425
1426 }
1427 }
1428
1429 /* Expect <s:Body> */
1430 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1431 RETURN(-1);
1432
1433 /* Expect </s:Envelope> */
1434 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1435 RETURN(-1);
1436 mike 1.1
1437 return 0;
1438 }
1439
1440 int WS_ParseReleaseBody(
1441 XML* xml,
1442 WSMAN_WSEnumeratePullBody* wsenumpullbody)
1443 {
1444 XML_Elem e;
1445
1446 memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1447
1448 /* Expect <s:Body> */
1449 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1450 RETURN(-1);
1451
1452 /* Expect <n:Release> */
1453 if (XML_Expect(xml, &e, XML_START, "n:Release") != 0)
1454 RETURN(-1);
1455
1456 for (;;)
1457 mike 1.1 {
1458 if (XML_Next(xml, &e) != 0)
1459 RETURN(-1);
1460
1461 if (e.type == XML_END)
1462 {
1463 int tag = HashStr(e.data, e.size);
1464
1465 if (WSMANTAG_ENUM_RELEASE != tag)
1466 {
1467 LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1468 RETURN(-1);
1469 }
1470 break;
1471 }
1472
1473 /* skip possible comments */
1474 if (e.type != XML_START)
1475 continue;
1476
1477 switch (HashStr(e.data, e.size))
1478 mike 1.1 {
1479 case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1480 {
1481 if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1482 RETURN(-1);
1483
1484 wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
1485
1486 if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
1487 RETURN(-1);
1488 }
1489 break;
1490
1491 default:
1492 {
1493 if (_MustUnderstandCanBeIgnored(&e) != 0)
1494 {
1495 LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1496 RETURN(-1);
1497 }
1498
1499 mike 1.1 if (XML_Skip(xml) != 0)
1500 RETURN(-1);
1501 }
1502 break;
1503
1504 }
1505 }
1506
1507 /* Expect <s:Body> */
1508 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1509 RETURN(-1);
1510
1511 /* Expect </s:Envelope> */
1512 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1513 RETURN(-1);
1514
1515 return 0;
1516 }
1517
1518 int WS_ParseIdentifyBody(
1519 XML* xml)
1520 mike 1.1 {
1521 XML_Elem e;
1522
1523 if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1524 RETURN(-1);
1525
1526 if (XML_Expect(xml, &e, XML_START, "i:Identify") != 0)
1527 RETURN(-1);
1528
1529 if (XML_Expect(xml, &e, XML_END, "i:Identify") != 0)
1530 RETURN(-1);
1531
1532 if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1533 RETURN(-1);
1534
1535 if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1536 RETURN(-1);
1537
1538 return 0;
1539 }
|