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