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 <base/log.h>
30 #include <base/result.h>
|
31 krisbash 1.4 #include <pal/strings.h>
32 #include <pal/format.h>
33 #include <indication/common/indicommon.h>
34 #include <base/helpers.h>
35
36 #if defined(CONFIG_ENABLE_WCHAR)
37 # define HASHSTR_CHAR TChar
38 # define HASHSTR_T(STR) L##STR
39 # define HASHSTR_STRCMP wcscmp
40 #endif
|
41 mike 1.1
42 #include "wstags.h"
|
43 krisbash 1.4
44 #if defined(CONFIG_FAVORSIZE)
45 # include "wstags_small.inc"
46 #else
47 # include "wstags_quick.inc"
48 #endif
49
|
50 mike 1.1 #include <wsman/uri.h>
51
|
52 krisbash 1.4 //#if 0
|
53 mike 1.1 #define ENABLE_TRACING
|
54 krisbash 1.4 //#endif
|
55 mike 1.1
|
56 krisbash 1.4 #define TRACE_RETURN
|
57 mike 1.1
58 #if defined(TRACE_RETURN)
59 # define RETURN(X) \
60 do \
61 { \
|
62 krisbash 1.4 trace_WsmanReturn( __FILE__, __LINE__ ); \
|
63 mike 1.1 return X; \
64 } \
65 while (0)
66 #else
67 # define RETURN(X) return X
68 #endif
69
70 /*
71 **==============================================================================
72 **
73 ** Local definitions:
74 **
75 **==============================================================================
76 */
77 static int _GetInstance(
78 XML* xml,
79 XML_Elem *start,
80 Batch* dynamicBatch,
81 MI_Instance** dynamicInstanceParams);
82
|
83 krisbash 1.4 static int _GetReference(
84 XML* xml,
85 XML_Elem *start,
86 Batch* dynamicBatch,
87 MI_Instance** dynamicInstanceParams);
88
|
89 mike 1.1 /****************************************************************************************/
90 /* soap processing */
91
92 static int _MustUnderstandCanBeIgnored(
93 const XML_Elem* e)
94 {
95 size_t i;
96 for (i = 0; i < e->attrsSize; i++)
97 {
|
98 krisbash 1.4 if (e->attrs[i].name.namespaceId == MI_T('s') &&
99 Tcscmp(e->attrs[i].name.data, PAL_T("mustUnderstand")) == 0 &&
100 Tcscmp(e->attrs[i].value, PAL_T("true")) == 0)
|
101 mike 1.1 {
102 RETURN(-1);
103 }
104 }
105 return 0;
106 }
107
|
108 krisbash 1.4 static MI_Boolean IsValidClassname(const TChar* classname)
|
109 mike 1.1 {
|
110 krisbash 1.4 const TChar* p = classname;
|
111 mike 1.1
|
112 krisbash 1.4 if (!isalpha((unsigned int)(*p)) && *p != '_')
|
113 mike 1.1 return MI_FALSE;
114
115 p++;
116
117 for (; *p; p++)
118 {
|
119 krisbash 1.4 if (!isalnum((unsigned int)(*p)) && *p != '_')
|
120 mike 1.1 return MI_FALSE;
121 }
122
123 return MI_TRUE;
124 }
125
|
126 krisbash 1.4 static int _ParseBooleanOption(_In_ XML_Elem *e, _Inout_ MI_Boolean *ptrToOption)
127 {
128 if(Tcscasecmp(e->data.data, PAL_T("true")) == 0)
129 {
130 *ptrToOption = 1;
131 }
132 else if(Tcscasecmp(e->data.data, PAL_T("false")) == 0)
133 {
134 *ptrToOption = 0;
135 }
136 else
137 RETURN(-1);
138
139 return 0;
140 }
141
142 static int _GetOption(
143 _In_ XML* xml,
144 _In_ XML_Elem *e,
145 _Inout_ WSMAN_WSHeader* wsheader)
|
146 mike 1.1 {
147 size_t i;
148
149 for (i = 0; i < e->attrsSize; i++)
150 {
151 /* To support GetClass */
|
152 krisbash 1.4 if ((e->attrs[i].name.namespaceId == 0) &&
153 Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0)
|
154 mike 1.1 {
|
155 krisbash 1.4 int valueHash = 0;
156
157 if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
|
158 mike 1.1 RETURN(-1);
159
|
160 krisbash 1.4 valueHash = HashStr(0, e->attrs[i].value, e->attrs[i].valueSize);
|
161 mike 1.1
|
162 krisbash 1.4 // the WSMAN_OPTION_WMI_* is to check for these options included as custom options
163 if((valueHash == WSMAN_OPTION_INCLUDE_INHERITANCE_HIERARCHY) ||
164 (valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITANCE_HIERARCHY))
165 {
166 if(_ParseBooleanOption(e, &(wsheader->includeInheritanceHierarchy)) != 0)
167 RETURN(-1);
168 }
169 else if((valueHash == WSMAN_OPTION_INCLUDE_INHERITED_ELEMENTS) ||
170 (valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITED_ELEMENTS))
171 {
172 if(_ParseBooleanOption(e, &(wsheader->includeInheritedElements)) != 0)
173 RETURN(-1);
174 }
175 else if((valueHash == WSMAN_OPTION_INCLUDE_QUALIFIERS) ||
176 (valueHash == WSMAN_OPTION_WMI_INCLUDE_QUALIFIERS))
177 {
178 if(_ParseBooleanOption(e, &(wsheader->includeQualifiers)) != 0)
179 RETURN(-1);
180 }
181 else if((valueHash == WSMAN_OPTION_INCLUDE_CLASS_ORIGIN) ||
182 (valueHash == WSMAN_OPTION_WMI_INCLUDE_CLASS_ORIGIN))
183 krisbash 1.4 {
184 if(_ParseBooleanOption(e, &(wsheader->includeClassOrigin)) != 0)
185 RETURN(-1);
186 }
187 else if(valueHash == WSMAN_OPTION_MSFTWINRM_USE_PRECISE_ARRAYS)
188 {
189 if(_ParseBooleanOption(e, &(wsheader->usePreciseArrays)) != 0)
190 RETURN(-1);
191 }
192 }
193 else
194 continue;
195
196 if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Option")) != 0)
197 RETURN(-1);
198
199 break;
200 }
201
202 return 0;
203 }
204 krisbash 1.4
205 static int _GetOptionSet(
206 XML* xml,
207 WSMAN_WSHeader* wsheader)
208 {
209 XML_Elem e;
210
211 if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Option")) != 0)
212 RETURN(-1);
213
214 /* iterate through all option tags */
215 for (;;)
216 {
217 if (0 != _GetOption(
218 xml,
219 &e,
220 wsheader))
221 RETURN(-1);
222
223 /**/
224 if (XML_Next(xml, &e) != 0)
225 krisbash 1.4 RETURN(-1);
226
227 if (XML_END == e.type)
228 break;
229 }
230
231 return 0;
232 }
|
233 mike 1.1
|
234 krisbash 1.4 static int _GetSelector(
235 _In_ XML* xml,
236 _In_ XML_Elem *e,
237 _Inout_ const TChar** ns,
238 _Inout_ const TChar** classname,
239 _Inout_ MI_Instance** instance,
240 _Inout_ Batch** batch)
241 {
242 size_t i;
|
243 mike 1.1
|
244 krisbash 1.4 /* expecting namespace or key */
245 for (i = 0; i < e->attrsSize; i++)
246 {
247 /* To support GetClass */
248 if((e->attrs[i].name.namespaceId == 0) &&
249 (Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0))
|
250 mike 1.1 {
|
251 krisbash 1.4 if (Tcscmp(e->attrs[i].value, PAL_T("ClassName")) == 0)
252 {
253 if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
254 RETURN(-1);
|
255 mike 1.1
|
256 krisbash 1.4 if (!IsValidClassname(e->data.data))
257 RETURN(-1);
258 *classname = e->data.data;
259 }
260 else if(Tcscmp(e->attrs[i].value, PAL_T("__cimnamespace")) == 0)
261 {
262 /* namespace */
263 if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
264 RETURN(-1);
|
265 mike 1.1
|
266 krisbash 1.4 *ns = e->data.data;
267 }
268 else
269 {
270 /* keys */
271 const TChar* propName = e->attrs[i].value;
|
272 mike 1.1
|
273 krisbash 1.4 MI_Boolean selectorIsReference = MI_FALSE;
|
274 mike 1.1
|
275 krisbash 1.4 if (XML_Next(xml, e) != 0)
|
276 mike 1.1 {
|
277 krisbash 1.4 XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR);
|
278 mike 1.1 RETURN(-1);
279 }
280
|
281 krisbash 1.4 if((e->type == XML_START) &&
282 (e->data.namespaceId == MI_T('a')) &&
283 (Tcscmp(PAL_T("EndpointReference"), e->data.data) == 0))
|
284 mike 1.1 {
|
285 krisbash 1.4 if (XML_Next(xml, e) != 0)
286 {
287 XML_Raise(xml, WSMAN_ERROR_BAD_EPR_IN_SELECTOR);
288 RETURN(-1);
289 }
290
291 selectorIsReference = MI_TRUE;
|
292 mike 1.1 }
|
293 krisbash 1.4 else if(e->type != XML_CHARS)
294 {
295 XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR);
296 RETURN(-1);
297 }
|
298 mike 1.1
|
299 krisbash 1.4 /* allocate batch and instance if needed */
300 if (!(*instance))
301 {
302 MI_Result r;
303 TChar* cn;
|
304 mike 1.1
|
305 krisbash 1.4 /* verify that we already received classname */
306 if (!(*classname))
307 {
308 XML_Raise(
309 xml,
310 WSMAN_ERROR_NO_CLASS_NAME_IN_SELECTOR);
311 RETURN(-1);
312 }
313
314 /* Destroy old batch if it exists (from previous operation) */
315 if (*batch)
316 {
317 Batch_Destroy(*batch);
318 }
319
320 *batch = Batch_New(BATCH_MAX_PAGES);
321
322 if (!(*batch))
323 RETURN(-1);
324
325 cn = Batch_Tcsdup(*batch, *classname);
326 krisbash 1.4 if (!cn)
327 RETURN(-1);
328
329 r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch);
330
331 if (MI_RESULT_OK != r)
332 RETURN(-1);
333 }
|
334 mike 1.1
|
335 krisbash 1.4 /* add next property to the instance */
336 {
337 const TChar* wpropName;
338 MI_Result r;
339 MI_Value value;
|
340 mike 1.1
|
341 krisbash 1.4 if (!(*batch))
342 {
343 *batch = Batch_New(BATCH_MAX_PAGES);
344
345 if (!(*batch))
346 RETURN(-1);
347 }
|
348 mike 1.1
|
349 krisbash 1.4 wpropName = Batch_Tcsdup(*batch, propName);
350 if (!wpropName)
351 RETURN(-1);
|
352 mike 1.1
|
353 krisbash 1.4 if(selectorIsReference)
354 {
355 value.instance = 0;
356 if (0 != _GetReference(xml, e, *batch, &(value.instance)))
357 RETURN(-1);
358 }
359 else
360 {
361 value.string = Batch_Tcsdup(*batch, e->data.data);
362 if (!value.string)
363 RETURN(-1);
364 }
|
365 mike 1.1
|
366 krisbash 1.4 // Set the property.
367 r = MI_Instance_AddElement(*instance, wpropName, &value,
368 (selectorIsReference ? MI_REFERENCE : MI_STRING), MI_FLAG_BORROW | MI_FLAG_KEY);
|
369 mike 1.1
|
370 krisbash 1.4 if (MI_RESULT_OK != r)
371 RETURN(-1);
372 }
|
373 mike 1.1 }
374 }
375 else
376 continue;
377
|
378 krisbash 1.4 if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Selector")) != 0)
|
379 mike 1.1 RETURN(-1);
380
381 break;
382 }
383
384 return 0;
385 }
386
387 static int _GetSelectorSet(
388 XML* xml,
389 WSMAN_WSHeader* wsheader)
390 {
391 XML_Elem e;
392
|
393 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Selector")) != 0)
|
394 mike 1.1 RETURN(-1);
395
396 /* iterate through all selector tags */
397 for (;;)
398 {
399 if (0 != _GetSelector(
400 xml,
401 &e,
402 &wsheader->rqtNamespace,
|
403 krisbash 1.4 &wsheader->rqtClassname,
|
404 mike 1.1 &wsheader->instance,
405 &wsheader->instanceBatch))
406 RETURN(-1);
407
408 /**/
409 if (XML_Next(xml, &e) != 0)
410 RETURN(-1);
411
412 if (XML_END == e.type)
413 break;
414
415 }
416
417 return 0;
418 }
419
420 static int _GetReferenceParameters(
|
421 krisbash 1.4 _In_ XML* xml,
422 _In_ Batch* dynamicBatch,
423 _Inout_ MI_Instance** dynamicInstanceParams)
|
424 mike 1.1 {
425 XML_Elem e;
|
426 krisbash 1.4 const TChar* classname = NULL;
427 const TChar* nameSpace = NULL;
|
428 mike 1.1
429 /* extract ResourceURI and SelectorSet */
430 for (;;)
431 {
432 if (XML_Next(xml, &e) != 0)
433 RETURN(-1);
434
|
435 krisbash 1.4 if (e.type == XML_CHARS)
436 {
437 continue;
438 }
439
|
440 mike 1.1 if (XML_END == e.type)
441 break;
442
|
443 krisbash 1.4 if (PAL_T('w') == e.data.namespaceId &&
444 0 == Tcscmp(PAL_T("ResourceURI"), e.data.data))
|
445 mike 1.1 {
|
446 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
447 RETURN(-1);
448 if (XML_StripWhitespace(&e) != 0)
|
449 mike 1.1 RETURN(-1);
|
450 krisbash 1.4 classname = Tcsrchr(e.data.data, '/');
|
451 mike 1.1
452 /* skip '/' */
|
453 krisbash 1.4 if (classname)
|
454 mike 1.1 classname++;
455
|
456 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0)
|
457 mike 1.1 RETURN(-1);
458
459 continue;
460 }
461
|
462 krisbash 1.4 if (PAL_T('w') == e.data.namespaceId &&
463 0 == Tcscmp(PAL_T("SelectorSet"), e.data.data))
|
464 mike 1.1 {
465 /* Allocate an instance */
466 if (!*dynamicInstanceParams)
467 {
468 MI_Result r;
|
469 krisbash 1.4 const TChar* cn;
|
470 mike 1.1
471 if (!classname)
472 {
|
473 krisbash 1.4 XML_Raise(xml, WSMAN_ERROR_NO_RESOURCE_URI);
|
474 mike 1.1 RETURN(-1);
475 }
476
|
477 krisbash 1.4 cn = Batch_Tcsdup(dynamicBatch, classname);
478 if (!cn)
479 {
480 XML_Raise(xml, WSMAN_ERROR_OUTOFMEMORY);
481 RETURN(-1);
482 }
|
483 mike 1.1
484 r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
485 if (MI_RESULT_OK != r)
486 RETURN(-1);
487 }
488
489 /* iterate through all selector tags */
490 for (;;)
491 {
|
492 krisbash 1.4 const TChar* ns = NULL;
493 const TChar* cn = NULL;
|
494 mike 1.1
495 if (_GetSelector(
496 xml,
497 &e,
498 &ns,
|
499 krisbash 1.4 &cn,
|
500 mike 1.1 dynamicInstanceParams,
501 &dynamicBatch) != 0)
502 {
503 RETURN(-1);
504 }
505
506 if (ns)
507 {
508 nameSpace = ns;
509 }
510
511 /**/
512 if (XML_Next(xml, &e) != 0)
513 RETURN(-1);
514
|
515 krisbash 1.4 if (e.type == XML_CHARS)
516 {
517 if (XML_Next(xml, &e) != 0)
518 RETURN(-1);
519 }
|
520 mike 1.1 if (XML_END == e.type)
521 break;
522
523 }
524 continue;
525 }
526 }
527
528 if (nameSpace)
529 (*dynamicInstanceParams)->nameSpace = nameSpace;
530
531 return 0;
532 }
533
534 static int _GetReference(
535 XML* xml,
536 XML_Elem *start,
537 Batch* dynamicBatch,
538 MI_Instance** dynamicInstanceParams)
539 {
540 XML_Elem e;
541 mike 1.1
542 e = *start;
543
544 /* extract all parameters */
545 for (;;)
546 {
|
547 krisbash 1.4 if (e.data.namespaceId != MI_T('a') ||
548 0 != Tcscmp(PAL_T("ReferenceParameters"), e.data.data))
|
549 mike 1.1 {
550 if (XML_Skip(xml) != 0)
551 RETURN(-1);
552
553 if (XML_Next(xml, &e) != 0)
554 RETURN(-1);
|
555 krisbash 1.4 if (e.type == XML_CHARS)
556 {
557 if (XML_Next(xml, &e) != 0)
558 RETURN(-1);
559 continue;
560 }
|
561 mike 1.1 if (e.type == XML_END)
562 break;
563
564 continue;
565 }
566
567 if (0 != _GetReferenceParameters(xml, dynamicBatch, dynamicInstanceParams))
568 RETURN(-1);
569
570 if (XML_Next(xml, &e) != 0)
571 RETURN(-1);
572
|
573 krisbash 1.4 if (e.type == XML_CHARS)
574 {
575 if (XML_Next(xml, &e) != 0)
576 RETURN(-1);
577 }
|
578 mike 1.1 if (e.type == XML_END)
579 break;
580 }
581
582 return 0;
583 }
584
|
585 krisbash 1.4 /*
586 **==============================================================================
587 **
588 ** _GetSingleProperty()
589 **
590 ** This function gets a instance property. The caller has already counsumed
591 ** the start property element. This function reads the value and the
592 ** closing property element.
593 **
594 **==============================================================================
595 */
596
|
597 mike 1.1 static int _GetSingleProperty(
598 XML* xml,
|
599 krisbash 1.4 XML_Elem* start,
|
600 mike 1.1 Batch* dynamicBatch,
|
601 krisbash 1.4 MI_Char nsId,
602 const TChar* propNameChar,
|
603 mike 1.1 MI_Value* value,
|
604 krisbash 1.4 MI_Type* type,
605 MI_Boolean* null)
|
606 mike 1.1 {
607 XML_Elem e;
608
609 if (XML_Next(xml, &e) != 0)
610 RETURN(-1);
611
|
612 krisbash 1.4 while(1)
|
613 mike 1.1 {
|
614 krisbash 1.4 if (e.type == XML_END)
615 {
616 if (nsId != e.data.namespaceId ||
617 Tcscmp(propNameChar, e.data.data) != 0)
618 {
619 trace_OpenCloseMismatch(tcs(propNameChar), tcs(e.data.data));
620 RETURN(-1);
621 }
622
623 /* Check whether this attribute is null or just empty */
624 {
625 const TChar* p = XML_Elem_GetAttr(&e, PAL_T('x'), PAL_T("nil"));
|
626 mike 1.1
|
627 krisbash 1.4 if (p && Tcscmp(p, PAL_T("true")) == 0)
628 {
629 *null = MI_TRUE;
630 }
631 else
632 {
633 *null = MI_FALSE;
634 *type = MI_STRING;
635 value->string = PAL_T("");
636 }
637 }
638
639 return 0;
640 }
641 else if (e.type == XML_CHARS)
642 {
643 XML_Elem tmpElem;
644
645 /* Check to make sure there isn't a start element next */
646 if (XML_Next(xml, &tmpElem) != 0)
647 {
648 krisbash 1.4 RETURN(-1);
649 }
650 if (tmpElem.type == XML_START)
651 {
652 /* This means we have text and a child element. Use the child element for now */
653 e = tmpElem;
654 continue;
655 }
656 if (XML_PutBack(xml, &tmpElem) != 0)
657 {
658 RETURN(-1);
659 }
660
661 /* Plain string property */
662 value->string = Batch_Tcsdup(dynamicBatch, e.data.data);
663 if (!value->string)
664 RETURN(-1);
665 *type = MI_STRING;
666
667 if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0)
668 RETURN(-1);
669 krisbash 1.4
670 *null = MI_FALSE;
671 return 0;
672 }
673 else if ('a' == e.data.namespaceId)
674 {
675 /* Reference as </adddress></ReferenceParameters>*/
676 value->instance = 0;
677 if (0 != _GetReference(xml, &e, dynamicBatch, &value->instance))
678 RETURN(-1);
679
680 *type = MI_REFERENCE;
681 *null = MI_FALSE;
682 return 0;
683 }
684 else
685 {
686 if (e.type == XML_START)
687 {
688 if (Tcscasecmp(e.data.data, PAL_T("CIM_DateTime")) == 0)
689 {
690 krisbash 1.4 /* DateTime property XML*/
691 /* <p0:datetimeProperty xsi:type="cim:cimDateTime"> */
692 /* <CIM_DateTime>19990929195959.000000-420</CIM_DateTime> */
693 /* </p0:datetimeProperty> */
694 if (XML_Next(xml, &e) != 0)
695 RETURN(-1);
696 if (e.type == XML_CHARS)
697 {
698 value->string = Batch_Tcsdup(dynamicBatch, e.data.data);
699 if (!value->string)
700 RETURN(-1);
701 *type = MI_STRING;
702 }
703 else
704 RETURN(-1);
705
706 if (XML_Expect(xml, &e, XML_END, 0, PAL_T("CIM_DateTime")) != 0)
707 RETURN(-1);
708
709 if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0)
710 RETURN(-1);
|
711 mike 1.1
|
712 krisbash 1.4 *null = MI_FALSE;
713 return 0;
714 }
715 }
716 /* Embedded instance */
717 value->instance = 0;
718 XML_PutBack(xml, &e);
|
719 mike 1.1
|
720 krisbash 1.4 if (0 != _GetInstance(xml, start, dynamicBatch, &value->instance))
721 RETURN(-1);
|
722 mike 1.1
723
|
724 krisbash 1.4 *type = MI_INSTANCE;
|
725 mike 1.1
|
726 krisbash 1.4 *null = MI_FALSE;
727 return 0;
728 }
729 }
|
730 mike 1.1 }
731
732 static int _AddValueToArray(
733 Batch* dynamicBatch,
734 MI_Value* valueA,
735 MI_Type typeA,
736 const MI_Value* value,
737 MI_Type type)
738 {
739 /* does type match? */
740 if ((type | MI_ARRAY_BIT) != typeA)
741 RETURN(-1);
742
743 /* do we need to realloc array? */
744 if ((valueA->array.size % 16) == 0)
745 {
746 void* newData = Batch_Get(dynamicBatch, (valueA->array.size + 16) * sizeof(void*));
747
748 if (!newData)
749 RETURN(-1);
750
751 mike 1.1 if (valueA->array.size)
752 memcpy(newData, valueA->array.data, valueA->array.size * sizeof(void*));
753
754 valueA->array.data = newData;
755 }
756
757 if (type == MI_STRING)
758 valueA->stringa.data[valueA->stringa.size] = value->string;
759 else
760 valueA->instancea.data[valueA->instancea.size] = value->instance;
761
762 valueA->array.size++;
763 return 0;
764 }
765
766 static int _GetInstance(
767 XML* xml,
768 XML_Elem *start,
769 Batch* dynamicBatch,
770 MI_Instance** dynamicInstanceParams)
771 {
772 mike 1.1 XML_Elem e;
|
773 krisbash 1.4 const TChar* propNameA = 0;
|
774 mike 1.1 MI_Value valueA;
775 MI_Type typeA = MI_BOOLEAN;
|
776 krisbash 1.4 const TChar* propNamePrev = 0;
|
777 mike 1.1 MI_Value valuePrev;
778 MI_Type typePrev = MI_BOOLEAN;
779
780 memset(&valueA, 0, sizeof(valueA));
781
782 /* extract all parameters */
783 for (;;)
784 {
785 if (XML_Next(xml, &e) != 0)
786 RETURN(-1);
787
|
788 krisbash 1.4 /* Look for closing instance element */
789
790 if (e.type == XML_END && Tcscmp(e.data.data, start->data.data) == 0)
791 {
|
792 mike 1.1 break;
|
793 krisbash 1.4 }
|
794 mike 1.1
795 /* skip possible comments */
796 if (e.type != XML_START)
797 continue;
798
799 /* allocate new instance if needed */
800 if (!*dynamicInstanceParams)
801 {
802 MI_Result r;
|
803 krisbash 1.4 TChar* cn = NULL;
804
805 // We are trying to parse an Instance, The type of the instance may be specified
806 // as a attribute Type or it is same as the element name. We'll attempt to get the
807 // type from attribute ... if not we'll use the element name.
808 // TODO: At this time we don't have the NS support in the XML parser, so using hardcoded
809 // 'xsi:type (good for windows client) once we get the NS support this code should be
810 // updated.
811 const TChar* typeName = XML_Elem_GetAttr(start, PAL_T('x'), PAL_T("type"));
812
813 if(typeName)
814 {
815 TChar* typeStart;
816 cn = Batch_Tcsdup(dynamicBatch, typeName);
817
818 if (!cn)
819 {
820 trace_BatchTcsDup_Failed();
821 RETURN(-1);
822 }
823
824 krisbash 1.4 // Trim the _Type from the name.
825 typeStart = Tcsrchr(cn, '_');
826 if( typeStart )
827 {
828 *typeStart = PAL_T('\0');
829
830 /* trim namespace start too */
831 {
832 TChar* afterColon;
833 afterColon = Tcschr(cn, PAL_T(':'));
834 if (afterColon)
835 {
836 afterColon++;
837 cn = afterColon;
838 }
839 }
840 }
841 else
842 {
843 trace_XsiTypeInvalidValue( cn );
844 RETURN(-1);
845 krisbash 1.4 // cn is allocated on the batch, so it will be release along with it anyway
846 }
847 }
848 else
849 {
850 cn = Batch_Tcsdup(dynamicBatch, start->data.data);
851 if (!cn)
852 {
853 trace_BatchTcsDup_Failed();
854 RETURN(-1);
855 }
856 }
857
858 r = Instance_NewDynamic(
859 dynamicInstanceParams,
860 cn,
861 MI_FLAG_CLASS,
862 dynamicBatch);
|
863 mike 1.1
864 if (MI_RESULT_OK != r)
865 RETURN(-1);
866 }
867
868 /* add next property to the instance */
|
869 krisbash 1.4 if (e.data.size > 0) /* element name should have some data in it */
|
870 mike 1.1 {
871 MI_Result r;
872 MI_Value value;
873 MI_Type type = MI_BOOLEAN;
|
874 krisbash 1.4 const TChar* propNameChar;
875 const TChar* propName;
876 MI_Boolean null;
|
877 mike 1.1
|
878 krisbash 1.4 propNameChar = e.data.data;
|
879 mike 1.2
880 /* Position propName one beyond ':' character */
|
881 krisbash 1.4 propName = Batch_Tcsdup(dynamicBatch, propNameChar);
882
883 if (!propName)
|
884 mike 1.2 {
|
885 krisbash 1.4 trace_BatchTcsDup_Failed();
886 RETURN(-1);
|
887 mike 1.2 }
|
888 mike 1.1
889 type = MI_BOOLEAN;
890
|
891 krisbash 1.4 if (_GetSingleProperty(
892 xml,
893 &e,
894 dynamicBatch,
895 e.data.namespaceId,
896 propNameChar,
897 &value,
898 &type,
899 &null) != 0)
900 {
901 trace_GetSingleProperty_Failed( tcs(propNameChar) );
|
902 mike 1.1 RETURN(-1);
|
903 krisbash 1.4 }
904
905 if (null)
906 {
907 /* Skip null attributes */
908 continue;
909 }
|
910 mike 1.1
911 /* Did we collect array's items? */
912 if (propNameA)
913 {
914 /* if we have array and new property matches array - add new item to the array */
|
915 krisbash 1.4 if (0 == Tcscmp(propNameA, propName))
|
916 mike 1.1 {
917 if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
918 RETURN(-1);
919 }
920 else
921 {
922 r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
923 typeA, MI_FLAG_BORROW);
924
925 if (MI_RESULT_OK != r)
926 RETURN(-1);
927
928 /* Clear array prop name */
929 propNameA = 0;
930
931 propNamePrev = propName;
932 valuePrev = value;
933 typePrev = type;
934 }
935 }
936 else if (propNamePrev)
937 mike 1.1 {
938 /* Check if name is the same and we need to create an array */
|
939 krisbash 1.4 if (0 == Tcscmp(propNamePrev, propName))
|
940 mike 1.1 {
941 /* create array */
942 valueA.array.size = 0;
943 valueA.array.data = 0;
944
945 typeA = type | MI_ARRAY_BIT;
946 propNameA = propName;
947
948 if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &valuePrev, typePrev))
949 RETURN(-1);
950
951 if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
952 RETURN(-1);
953
954 }
955 else
956 {
|
957 krisbash 1.4 r = MI_Instance_AddElement(
958 *dynamicInstanceParams,
959 propNamePrev,
960 &valuePrev,
961 typePrev,
962 MI_FLAG_BORROW);
|
963 mike 1.1
|
964 mike 1.2 /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
965 * for key properties added when the selector set was
966 * parsed earlier.
967 */
968 if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
969 {
|
970 mike 1.1 RETURN(-1);
|
971 mike 1.2 }
|
972 mike 1.1
973 propNamePrev = propName;
974 valuePrev = value;
975 typePrev = type;
976 }
977
978 }
979 else
980 {
981 /* collecting first item */
982 propNamePrev = propName;
983 valuePrev = value;
984 typePrev = type;
985 }
986 }
987 }
988
989 /* if last property was array - add it */
990 if (propNameA)
991 {
992 MI_Result r;
993 mike 1.1
994 r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
995 typeA, MI_FLAG_BORROW);
996
997 if (MI_RESULT_OK != r)
998 RETURN(-1);
999 }
1000 else if (propNamePrev)
1001 {
1002 MI_Result r;
1003
1004 r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev,
1005 typePrev, MI_FLAG_BORROW);
1006
|
1007 krisbash 1.4 /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
1008 * for key properties added when the selector set was
1009 * parsed earlier.
1010 */
1011 if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
1012 {
|
1013 mike 1.1 RETURN(-1);
|
1014 krisbash 1.4 }
|
1015 mike 1.1 }
1016
1017 /* check closing tag */
|
1018 krisbash 1.4 if (Tcscmp(e.data.data, start->data.data) != 0)
|
1019 mike 1.1 RETURN(-1);
1020
1021 return 0;
1022 }
1023
1024 int WS_ParseWSHeader(
1025 XML* xml,
|
1026 krisbash 1.4 WSMAN_WSHeader* wsheader,
1027 UserAgent userAgent)
|
1028 mike 1.1 {
1029 XML_Elem e;
1030
|
1031 krisbash 1.4 if (wsheader->instanceBatch)
1032 {
1033 Batch_Delete(wsheader->instanceBatch);
1034 }
|
1035 mike 1.1 memset(wsheader, 0, sizeof(WSMAN_WSHeader));
1036
|
1037 krisbash 1.4 // WinRM client assumes that ClassOrigin is true by default on the server
1038 // by standards, a wsman option is false by default so in non-WinRM case,
1039 // the includeClassOrigin and all others are set to 0
1040 wsheader->includeClassOrigin = (userAgent == USERAGENT_WINRM) ? 1 : 0;
1041 wsheader->includeInheritanceHierarchy = 0;
1042 wsheader->includeInheritedElements = 0;
1043 wsheader->includeQualifiers = 0;
1044
|
1045 mike 1.1 /* Expect <s:Header> */
|
1046 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Header")) != 0)
|
1047 mike 1.1 RETURN(-1);
1048
1049 for (;;)
1050 {
1051 if (XML_Next(xml, &e) != 0)
1052 RETURN(-1);
1053
1054 if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0)
1055 {
|
1056 krisbash 1.4 int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1057 mike 1.1
1058 if (WSMANTAG_HEADER != tag)
1059 {
|
1060 krisbash 1.4 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
|
1061 mike 1.1 RETURN(-1);
1062 }
1063 //printf("DONE\n");
1064 break;
1065 }
1066
1067 /* skip possible comments */
1068 if (e.type != XML_START)
1069 continue;
1070
|
1071 krisbash 1.4 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
|
1072 mike 1.1 {
1073 case WSMANTAG_TO:
1074 {
|
1075 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1076 mike 1.1 RETURN(-1);
1077
|
1078 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("To")) != 0)
|
1079 mike 1.1 RETURN(-1);
1080 }
1081 break;
1082
1083 case WSMANTAG_RESOURCE_URI:
1084 {
|
1085 krisbash 1.4 int resourceUriHash = 0;
1086
1087 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1088 mike 1.1 RETURN(-1);
|
1089 krisbash 1.4
1090 if (XML_StripWhitespace(&e) != 0)
1091 RETURN(-1);
1092
1093 wsheader->schemaRequestType = NOT_A_SCHEMA_REQUEST;
|
1094 mike 1.1
|
1095 krisbash 1.4 resourceUriHash = HashStr(0, e.data.data, e.data.size);
1096
1097 if(resourceUriHash == WSMAN_RESOURCE_URI_CIM_XML_SCHEMA)
1098 {
1099 wsheader->schemaRequestType = CIM_XML_SCHEMA_REQUEST;
1100 }
1101 else if(resourceUriHash == WSMAN_RESOURCE_URI_WS_CIM_SCHEMA)
1102 {
1103 wsheader->schemaRequestType = WS_CIM_SCHEMA_REQEUST;
1104 }
1105
1106 wsheader->rqtClassname = Tcsrchr(e.data.data, '/');
|
1107 mike 1.1 /* skip '/' */
1108 if (wsheader->rqtClassname)
1109 wsheader->rqtClassname++;
1110
|
1111 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0)
|
1112 mike 1.1 RETURN(-1);
1113 }
1114 break;
1115
1116 case WSMANTAG_REPLY_TO:
1117 {
|
1118 krisbash 1.4 while (1)
1119 {
1120 if (XML_Next(xml, &e) != 0)
1121 RETURN(-1);
1122 /* skip whitespace and comments */
1123 if (e.type == XML_START)
1124 break;
1125 }
1126 if (HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_ADDRESS)
|
1127 mike 1.1 RETURN(-1);
1128
|
1129 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1130 mike 1.1 RETURN(-1);
1131
|
1132 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Address")) != 0)
1133 RETURN(-1);
1134
1135 while (1)
1136 {
1137 if (XML_Next(xml, &e) != 0)
1138 RETURN(-1);
1139 /* skip whitespace and comments */
1140 if (e.type == XML_END)
1141 break;
1142 }
1143 if (e.type != XML_END && HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_REPLY_TO)
|
1144 mike 1.1 RETURN(-1);
1145 }
1146 break;
1147
1148 case WSMANTAG_ACTION:
1149 {
1150 wsheader->foundAction = MI_TRUE;
1151
|
1152 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1153 RETURN(-1);
1154
1155 if (XML_StripWhitespace(&e) != 0)
|
1156 mike 1.1 RETURN(-1);
1157
|
1158 krisbash 1.4 wsheader->rqtAction = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1159 mike 1.1
1160 if (0 == wsheader->rqtAction)
1161 {
|
1162 krisbash 1.4 TChar* s;
|
1163 mike 1.1 /* DSP0226; 9: Custom Actions (Methods) just need to have unique URI.
1164 We are assuming it has format like http://<server>/wbem/wscim/1/cim-schema/2/<class-name>/<method-name> */
1165
|
1166 krisbash 1.4 if (0 != Tcsncmp(e.data.data, PAL_T("http://"), 7))
|
1167 mike 1.1 RETURN(-1);
1168
|
1169 krisbash 1.4 wsheader->rqtServer = e.data.data + 7;
|
1170 mike 1.1
|
1171 krisbash 1.4 s = Tcschr(wsheader->rqtServer, '/');
|
1172 mike 1.1
1173 if (!s)
1174 RETURN(-1);
1175
1176 *s = 0;
1177 s++;
1178
|
1179 krisbash 1.4 if (0 != Tcsncmp(s, PAL_T("wbem/wscim/1/cim-schema/2/"), 26))
|
1180 mike 1.1 RETURN(-1);
1181
1182 s += 26;
1183
1184 wsheader->rqtClassname = s;
|
1185 krisbash 1.4 s = Tcschr(s, '/');
|
1186 mike 1.1
1187 if (!s)
1188 RETURN(-1);
1189
1190 *s = 0;
1191 s++;
1192 wsheader->rqtMethod = s;
1193 }
1194
|
1195 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Action")) != 0)
|
1196 mike 1.1 RETURN(-1);
1197 }
1198 break;
1199
1200 case WSMANTAG_SELECTOR_SET:
1201 {
1202 if (_GetSelectorSet(xml, wsheader) != 0)
1203 RETURN(-1);
1204 }
1205 break;
1206
|
1207 krisbash 1.4 case WSMANTAG_OPTION_SET:
1208 {
1209 if (_GetOptionSet(xml, wsheader) != 0)
1210 RETURN(-1);
1211 }
1212 break;
1213
|
1214 mike 1.1 case WSMANTAG_MESSAGE_ID:
1215 {
|
1216 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1217 RETURN(-1);
1218 if (XML_StripWhitespace(&e) != 0)
1219 RETURN(-1);
1220 wsheader->rqtMessageID = e.data.data;
1221
1222 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("MessageID")) != 0)
1223 RETURN(-1);
1224 }
1225 break;
1226
1227 case WSMANTAG_MAX_ENVELOPE_SIZE:
1228 {
1229 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1230 RETURN(-1);
1231 if (XML_StripWhitespace(&e) != 0)
|
1232 mike 1.1 RETURN(-1);
1233
|
1234 krisbash 1.4 wsheader->maxEnvelopeSize = (MI_Uint32)Tcstoull(
1235 e.data.data, NULL, 10);
|
1236 mike 1.1
|
1237 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxEnvelopeSize")) != 0)
|
1238 mike 1.1 RETURN(-1);
1239 }
1240 break;
1241
|
1242 krisbash 1.4 #ifndef DISABLE_INDICATION
1243 case WSMANTAG_OPERATION_TIMEOUT:
1244 {
1245 /* Expect an xs:duration of form: PnYnMnDTnHnMnS */
1246 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1247 RETURN(-1);
1248
1249 if (XML_StripWhitespace(&e) != 0)
1250 RETURN(-1);
1251
1252 if (-1 == ParseWSManDatetime( e.data.data, &wsheader->operationTimeout.value ) )
1253 RETURN(-1);
1254
1255 wsheader->operationTimeout.exists = MI_TRUE;
1256
1257 if (XML_Expect(xml, &e, XML_END, MI_T('w'), MI_T("OperationTimeout")) != 0)
1258 RETURN(-1);
1259 }
1260 break;
1261
1262 case WSMANTAG_SUBSCRIBE_IDENTIFIER:
|
1263 mike 1.1 {
|
1264 krisbash 1.4 /* For unsubscribe, parse subscribe identifier from header */
1265 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1266 mike 1.1 RETURN(-1);
1267
|
1268 krisbash 1.4 wsheader->contextID = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
1269 trace_WsmanUnsubscribe( wsheader->contextID );
|
1270 mike 1.1
|
1271 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, MI_T('e'), MI_T("Identifier")) != 0)
|
1272 mike 1.1 RETURN(-1);
1273 }
1274 break;
|
1275 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
|
1276 mike 1.1
1277 default:
1278 {
1279 if (_MustUnderstandCanBeIgnored(&e) != 0)
1280 {
|
1281 krisbash 1.4 wsheader->unknownMandatoryTag = e.data.data;
1282 trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
|
1283 mike 1.1 /* validate header will send correct repsonse to the client */
1284 }
1285
1286 if (XML_Skip(xml) != 0)
1287 RETURN(-1);
1288 }
1289 break;
1290
1291 }
1292 }
|
1293 krisbash 1.4 /* DMTF standard requires default namespace to be used */
1294 /* if _cimnamespace selector is not specified as part of request */
1295 if (!wsheader->rqtNamespace)
1296 wsheader->rqtNamespace = DEFAULT_CIMNAMESPACE;
|
1297 mike 1.1 return 0;
1298 }
1299
1300 int WS_ParseSoapEnvelope(XML* xml)
1301 {
1302 XML_Elem e;
1303
1304 /* Ignore the processing instruction (if any) */
1305 {
1306 if (XML_Next(xml, &e) != 0)
1307 {
|
1308 krisbash 1.4 XML_Raise(xml, XML_ERROR_ELEMENT_EXPECTED);
|
1309 mike 1.1 RETURN(-1);
1310 }
1311
1312 if (e.type != XML_INSTRUCTION)
1313 {
1314 if (XML_PutBack(xml, &e) != 0)
1315 RETURN(-1);
1316 }
1317 }
1318
1319 /* Expect <s:Envelope> */
|
1320 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Envelope")) != 0)
|
1321 mike 1.1 RETURN(-1);
1322
1323 return 0;
1324 }
1325
|
1326 krisbash 1.4 static const TChar* _ExpectCharsAndEnd(
|
1327 mike 1.1 XML* xml,
|
1328 krisbash 1.4 TChar nsId,
1329 const TChar* name)
|
1330 mike 1.1 {
1331 XML_Elem e;
|
1332 krisbash 1.4 const TChar* chars;
|
1333 mike 1.1
|
1334 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1335 mike 1.1 return NULL;
1336
|
1337 krisbash 1.4 chars = e.data.data;
|
1338 mike 1.1
|
1339 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, nsId, name) != 0)
|
1340 mike 1.1 return NULL;
1341
1342 return chars;
1343 }
1344
1345 /*
1346 **==============================================================================
1347 **
1348 ** _ParseAssociationFilterObject()
1349 **
1350 ** Example:
1351 ** <b:Object>
1352 ** <a:Address>
1353 ** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
1354 ** </a:Address>
1355 ** <a:ReferenceParameters>
1356 ** <w:ResourceURI>
1357 ** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
1358 ** </w:ResourceURI>
1359 ** <w:SelectorSet>
1360 ** <w:Selector Name="__cimnamespace">
1361 mike 1.1 ** root/cimv2
1362 ** </w:Selector>
1363 ** <w:Selector Name="Key">
1364 ** 1001
1365 ** </w:Selector>
1366 ** </w:SelectorSet>
1367 ** </a:ReferenceParameters>
1368 ** </b:Object>
1369 *
1370 **==============================================================================
1371 */
1372
1373 static int _ParseAssociationFilterObject(
1374 XML* xml,
1375 Batch* batch,
1376 WSMAN_AssociationFilter* filter)
1377 {
1378 XML_Elem e;
1379
1380 /* Parse child elements */
1381
1382 mike 1.1 for (;;)
1383 {
1384 /* Get next element */
1385
1386 if (XML_Next(xml, &e) != 0)
1387 RETURN(-1);
1388
1389 /* Put it back and break out if not a start tag */
1390
1391 if (e.type != XML_START)
1392 {
1393 if (XML_PutBack(xml, &e) != 0)
1394 RETURN(-1);
1395
1396 break;
1397 }
1398
1399 /* Handle "Object" tag */
1400
|
1401 krisbash 1.4 if (PAL_T('a') == e.data.namespaceId &&
1402 Tcscmp(e.data.data, PAL_T("ReferenceParameters")) == 0)
|
1403 mike 1.1 {
1404 if (_GetReferenceParameters(
1405 xml,
1406 batch,
1407 &filter->referenceParameters) != 0)
1408 {
1409 RETURN(-1);
1410 }
1411 }
|
1412 krisbash 1.4 else if (PAL_T('a') == e.data.namespaceId &&
1413 Tcscmp(e.data.data, PAL_T("Address")) == 0)
|
1414 mike 1.1 {
|
1415 krisbash 1.4 filter->address = _ExpectCharsAndEnd(xml, PAL_T('a'), PAL_T("Address"));
|
1416 mike 1.1
1417 if (!filter->address)
1418 RETURN(-1);
1419 }
1420 else
1421 {
1422 if (XML_Skip(xml) != 0)
1423 RETURN(-1);
1424 }
1425 }
1426
1427 /* Expect </Object> */
1428
|
1429 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("Object")) != 0)
|
1430 mike 1.1 RETURN(-1);
1431
1432 return 0;
1433 }
1434
1435 /*
1436 **==============================================================================
1437 **
1438 ** _ParseAssociationFilter()
1439 **
1440 ** Example:
1441 ** <b:AssociatedInstances>
1442 ** <b:Object>
1443 ** <a:Address>
1444 ** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
1445 ** </a:Address>
1446 ** <a:ReferenceParameters>
1447 ** <w:ResourceURI>
1448 ** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
1449 ** </w:ResourceURI>
1450 ** <w:SelectorSet>
1451 mike 1.1 ** <w:Selector Name="__cimnamespace">
1452 ** root/cimv2
1453 ** </w:Selector>
1454 ** <w:Selector Name="Key">
1455 ** 1001
1456 ** </w:Selector>
1457 ** </w:SelectorSet>
1458 ** </a:ReferenceParameters>
1459 ** </b:Object>
1460 ** <b:AssociationClassName>
1461 ** ABC_Connector
1462 ** </b:AssociationClassName>
1463 ** <b:Role>
1464 ** Component
1465 ** </b:Role>
1466 ** <b:ResultClassName>
1467 ** ABC_Gadget
1468 ** </b:ResultClassName>
1469 ** <b:ResultRole>
1470 ** Part
1471 ** </b:ResultRole>
1472 mike 1.1 ** </b:AssociatedInstances>
1473 **
1474 **==============================================================================
1475 */
1476
1477 static int _ParseAssociationFilter(
1478 XML* xml,
1479 Batch* batch,
1480 WSMAN_AssociationFilter* filter)
1481 {
1482 XML_Elem e;
1483
1484 /* Expect <AssociatedInstances> */
1485
|
1486 krisbash 1.4 if (XML_Next(xml, &e) != 0 || e.type != XML_START )
1487 {
1488 RETURN(-1);
1489 }
1490
1491 if (PAL_T('b') == e.data.namespaceId &&
1492 Tcscmp(e.data.data, PAL_T("AssociatedInstances")) == 0)
1493 {
1494 filter->isAssosiatorOperation = MI_TRUE;
1495 }
1496 else if (PAL_T('b') == e.data.namespaceId &&
1497 Tcscmp(e.data.data, PAL_T("AssociationInstances")) == 0)
1498 {
1499 filter->isAssosiatorOperation = MI_FALSE;
1500 }
1501 else
|
1502 mike 1.1 RETURN(-1);
1503
1504 /* Parse child elements */
1505
1506 for (;;)
1507 {
1508 /* Get next element */
1509
1510 if (XML_Next(xml, &e) != 0)
1511 RETURN(-1);
1512
1513 /* Put it back and break out if not a start tag */
1514
1515 if (e.type != XML_START)
1516 {
1517 if (XML_PutBack(xml, &e) != 0)
1518 RETURN(-1);
1519
1520 break;
1521 }
1522
1523 mike 1.1 /* Handle "Object" tag */
1524
|
1525 krisbash 1.4 if (PAL_T('b') == e.data.namespaceId &&
1526 Tcscmp(e.data.data, PAL_T("Object")) == 0)
|
1527 mike 1.1 {
1528 if (_ParseAssociationFilterObject(xml, batch, filter) != 0)
1529 RETURN(-1);
1530 }
|
1531 krisbash 1.4 else if (PAL_T('b') == e.data.namespaceId &&
1532 Tcscmp(e.data.data, PAL_T("AssociationClassName")) == 0)
|
1533 mike 1.1 {
1534 filter->associationClassName = _ExpectCharsAndEnd(
|
1535 krisbash 1.4 xml, PAL_T('b'), PAL_T("AssociationClassName"));
|
1536 mike 1.1
1537 if (!filter->associationClassName)
1538 RETURN(-1);
1539 }
|
1540 krisbash 1.4 else if (PAL_T('b') == e.data.namespaceId &&
1541 Tcscmp(e.data.data, PAL_T("Role")) == 0)
|
1542 mike 1.1 {
|
1543 krisbash 1.4 filter->role = _ExpectCharsAndEnd(xml, PAL_T('b'), PAL_T("Role"));
|
1544 mike 1.1
1545 if (!filter->role)
1546 RETURN(-1);
1547 }
|
1548 krisbash 1.4 else if (PAL_T('b') == e.data.namespaceId &&
1549 Tcscmp(e.data.data, PAL_T("ResultClassName")) == 0)
|
1550 mike 1.1 {
1551 filter->resultClassName = _ExpectCharsAndEnd(
1552 xml,
|
1553 krisbash 1.4 PAL_T('b'),
1554 PAL_T("ResultClassName"));
|
1555 mike 1.1
1556 if (!filter->resultClassName)
1557 RETURN(-1);
1558 }
|
1559 krisbash 1.4 else if (PAL_T('b') == e.data.namespaceId &&
1560 Tcscmp(e.data.data, PAL_T("ResultRole")) == 0)
|
1561 mike 1.1 {
1562 filter->resultRole = _ExpectCharsAndEnd(
1563 xml,
|
1564 krisbash 1.4 PAL_T('b'),
1565 PAL_T("ResultRole"));
|
1566 mike 1.1
1567 if (!filter->resultRole)
1568 RETURN(-1);
1569 }
1570 else
1571 {
1572 if (XML_Skip(xml) != 0)
1573 RETURN(-1);
1574 }
1575 }
1576
|
1577 krisbash 1.4 if(filter->isAssosiatorOperation == MI_TRUE)
1578 {
1579 /* Expect </AssociatedInstances> */
1580 if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociatedInstances")) != 0)
1581 RETURN(-1);
1582 }
1583 else
1584 {
1585 /* Expect </AssociationInstances> */
1586 if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociationInstances")) != 0)
1587 RETURN(-1);
1588 }
1589
1590 return 0;
1591 }
1592
1593 /* Parse query dialect */
1594 static const ZChar* _WS_ParseDialect(
1595 _In_z_ const ZChar* dialect,
1596 MI_Boolean isSubscribe)
1597 {
1598 krisbash 1.4 /* See DSP0202.pdf */
1599 if (Tcscasecmp(ZT("http://schemas.dmtf.org/wbem/cql/1/dsp0202.pdf"), dialect) == 0)
1600 return MI_QUERY_DIALECT_CQL;
1601
1602 if (Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/WQL"), dialect) == 0)
1603 return MI_QUERY_DIALECT_WQL;
|
1604 mike 1.1
|
1605 krisbash 1.4 /* Event stream dialect is not supported yet */
1606 /* if (isSubscribe && Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/MINT"), dialect) == 0)
1607 return QUERY_LANGUAGE_EVENTSTREAM; */
|
1608 mike 1.1
|
1609 krisbash 1.4 if (isSubscribe)
1610 return dialect;
|
1611 mike 1.1
|
1612 krisbash 1.4 return NULL;
|
1613 mike 1.1 }
1614
1615 int WS_ParseEnumerateBody(
1616 XML* xml,
1617 Batch** batch,
1618 WSMAN_WSEnumeratePullBody* wsenumbody)
1619 {
1620 XML_Elem e;
1621
1622 memset(wsenumbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1623
1624 /* Allocate batch (owned by WSMAN_ConnectionData object */
1625
1626 if (*batch == NULL)
1627 {
1628 *batch = Batch_New(BATCH_MAX_PAGES);
1629
1630 if (!*batch)
1631 RETURN(-1);
1632 }
1633
1634 mike 1.1 /* Expect <s:Body> */
|
1635 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
|
1636 mike 1.1 RETURN(-1);
1637
1638 /* Expect <n:Enumerate> */
|
1639 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Enumerate")) != 0)
|
1640 mike 1.1 RETURN(-1);
1641
1642 for (;;)
1643 {
1644 if (XML_Next(xml, &e) != 0)
1645 RETURN(-1);
1646
1647 if (e.type == XML_END)
1648 {
|
1649 krisbash 1.4 int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1650 mike 1.1
1651 if (WSMANTAG_ENUM_ENUMERATE != tag)
1652 {
|
1653 krisbash 1.4 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
|
1654 mike 1.1 RETURN(-1);
1655 }
1656 break;
1657 }
1658
1659 /* skip possible comments */
1660 if (e.type != XML_START)
1661 continue;
1662
|
1663 krisbash 1.4 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
|
1664 mike 1.1 {
1665 case WSMANTAG_ENUM_MAX_ELEMENTS:
1666 {
|
1667 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1668 mike 1.1 RETURN(-1);
1669
|
1670 krisbash 1.4 wsenumbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
|
1671 mike 1.1
|
1672 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxElements")) != 0)
|
1673 mike 1.1 RETURN(-1);
1674 }
1675 break;
1676
1677 case WSMANTAG_ENUM_OPTIMIZE_ENUMERATION:
1678 {
1679 wsenumbody->allowOptimization = MI_TRUE;
1680
1681 if (XML_Skip(xml) != 0)
1682 RETURN(-1);
1683 }
1684 break;
1685
1686 case WSMANTAG_ENUM_POLYMORPHISM_MODE:
1687 {
|
1688 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1689 mike 1.1 RETURN(-1);
1690
|
1691 krisbash 1.4 wsenumbody->polymorphismMode = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1692 mike 1.1
|
1693 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("PolymorphismMode")) != 0)
|
1694 mike 1.1 RETURN(-1);
1695 }
1696 break;
1697
1698 case WSMANTAG_ENUM_MODE:
1699 {
|
1700 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1701 mike 1.1 RETURN(-1);
1702
|
1703 krisbash 1.4 wsenumbody->enumerationMode = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1704 mike 1.1
|
1705 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("EnumerationMode")) != 0)
|
1706 mike 1.1 RETURN(-1);
1707 }
1708 break;
1709
1710 /*
1711 * Examples:
1712 * <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1713 * SELECT Weight FROM Widget WHERE Key = 1001
1714 * </w:Filter>
1715 *
1716 * <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1717 * <b:AssociatedInstances>
1718 * ...
1719 * </b:AssociatedInstances>
1720 * </w:Filter>
1721 */
1722 case WSMANTAG_ENUM_FILTER:
1723 {
|
1724 krisbash 1.4 const TChar* dialect;
|
1725 mike 1.1
1726 /* Get 'Dialect' attribute? */
|
1727 krisbash 1.4 dialect = XML_Elem_GetAttr(&e, 0, PAL_T("Dialect"));
|
1728 mike 1.1 if (!dialect)
1729 {
|
1730 krisbash 1.4 trace_Wsman_FilterTagMissingDialectAttribute();
|
1731 mike 1.1 RETURN(-1);
1732 }
1733
1734 /* Parse the association filter */
|
1735 krisbash 1.4 if (Tcscasecmp(dialect, URI_CIMBINDING PAL_T("/associationFilter")) == 0)
|
1736 mike 1.1 {
|
1737 krisbash 1.4 wsenumbody->dialect = PAL_T("associationFilter");
1738 wsenumbody->foundAssociationOperation = MI_TRUE;
|
1739 mike 1.1
|
1740 krisbash 1.4 if (_ParseAssociationFilter(xml, *batch, &wsenumbody->associationFilter) != 0)
|
1741 mike 1.1 {
1742 RETURN(-1);
1743 }
1744 }
1745 else
1746 {
|
1747 krisbash 1.4 /* Parse the dialect */
1748 wsenumbody->dialect = _WS_ParseDialect(dialect, MI_FALSE);
1749
1750 if (!wsenumbody->dialect)
1751 {
1752 trace_WsmanEnum_UnknownDialect(tcs(dialect));
1753 RETURN(-1);
1754 }
1755
|
1756 mike 1.1 /* Get the filter text */
|
1757 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1758 mike 1.1 RETURN(-1);
1759
|
1760 krisbash 1.4 wsenumbody->filter = e.data.data;
|
1761 mike 1.1 }
1762
1763 /* Check for closing </w:Filter> tag */
|
1764 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("Filter")) != 0)
|
1765 mike 1.1 RETURN(-1);
1766 }
1767 break;
1768
1769 default:
1770 {
1771 if (_MustUnderstandCanBeIgnored(&e) != 0)
1772 {
|
1773 krisbash 1.4 trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
|
1774 mike 1.1 RETURN(-1);
1775 }
1776
1777 if (XML_Skip(xml) != 0)
1778 RETURN(-1);
1779 }
1780 break;
1781
1782 }
1783 }
1784
1785 /* Expect <s:Body> */
|
1786 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
|
1787 mike 1.1 RETURN(-1);
1788
1789 /* Expect </s:Envelope> */
|
1790 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
|
1791 mike 1.1 RETURN(-1);
1792
1793 return 0;
1794 }
1795
1796 int WS_ParseInvokeBody(
1797 XML* xml,
1798 Batch* dynamicBatch,
1799 MI_Instance** dynamicInstanceParams)
1800 {
1801 XML_Elem e;
1802
1803 *dynamicInstanceParams = 0;
1804
1805 /* Expect <s:Body> */
|
1806 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
|
1807 mike 1.1 RETURN(-1);
1808
1809 /* Expect <?:?> parameter's tag */
1810 for (;;)
1811 {
1812 if (XML_Next(xml, &e) != 0)
1813 RETURN(-1);
1814
1815 /* empty body? can be valid for methods without parameters */
1816 if (e.type == XML_END)
1817 return 0;
1818
1819 if (e.type == XML_START)
1820 break;
1821 }
1822
1823 if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1824 RETURN(-1);
1825
1826
1827 /* Expect <s:Body> */
|
1828 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
|
1829 mike 1.1 RETURN(-1);
1830
1831 /* Expect </s:Envelope> */
|
1832 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
|
1833 mike 1.1 RETURN(-1);
1834
1835 return 0;
1836 }
1837
1838 int WS_ParseCreateBody(
1839 XML* xml,
1840 Batch* dynamicBatch,
1841 MI_Instance** dynamicInstanceParams)
1842 {
1843 XML_Elem e;
1844
1845 /* Expect <s:Body> */
|
1846 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
|
1847 mike 1.1 RETURN(-1);
1848
1849 /* Expect <?:?> parameter's tag */
1850 if (XML_Next(xml, &e) != 0)
1851 RETURN(-1);
1852
1853 if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1854 RETURN(-1);
1855
1856 /* Expect <s:Body> */
|
1857 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
|
1858 mike 1.1 RETURN(-1);
1859
1860 /* Expect </s:Envelope> */
|
1861 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
|
1862 mike 1.1 RETURN(-1);
1863
1864 return 0;
1865 }
1866
1867 int WS_ParsePullBody(
1868 XML* xml,
1869 WSMAN_WSEnumeratePullBody* wsenumpullbody)
1870 {
1871 XML_Elem e;
1872
1873 memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1874
1875 /* Expect <s:Body> */
|
1876 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
|
1877 mike 1.1 RETURN(-1);
1878
1879 /* Expect <n:Enumerate> */
|
1880 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Pull")) != 0)
|
1881 mike 1.1 RETURN(-1);
1882
1883 for (;;)
1884 {
1885 if (XML_Next(xml, &e) != 0)
1886 RETURN(-1);
1887
1888 if (e.type == XML_END)
1889 {
|
1890 krisbash 1.4 int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
1891 mike 1.1
1892 if (WSMANTAG_ENUM_PULL != tag)
1893 {
|
1894 krisbash 1.4 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
|
1895 mike 1.1 RETURN(-1);
1896 }
1897 break;
1898 }
1899
1900 /* skip possible comments */
1901 if (e.type != XML_START)
1902 continue;
1903
|
1904 krisbash 1.4 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
|
1905 mike 1.1 {
1906 case WSMANTAG_PULL_MAX_ELEMENTS:
1907 {
|
1908 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1909 RETURN(-1);
1910
1911 wsenumpullbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
1912 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxElements")) != 0)
1913 RETURN(-1);
1914 }
1915 break;
1916
1917 case WSMANTAG_MAX_TIME:
1918 {
1919 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1920 RETURN(-1);
1921
1922 if (-1 == ParseWSManDatetime( e.data.data, &wsenumpullbody->maxTime.value ) )
1923 RETURN(-1);
1924
1925 wsenumpullbody->maxTime.exists = MI_TRUE;
1926
1927 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxTime")) != 0)
1928 RETURN(-1);
1929 krisbash 1.4 }
1930 break;
1931
1932 case WSMANTAG_MAX_CHARACTERS:
1933 {
1934 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1935 mike 1.1 RETURN(-1);
1936
|
1937 krisbash 1.4 wsenumpullbody->maxCharacters.value = Tcstoull(e.data.data, NULL, 10);
1938 wsenumpullbody->maxCharacters.exists = MI_TRUE;
|
1939 mike 1.1
|
1940 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxCharacters")) != 0)
|
1941 mike 1.1 RETURN(-1);
1942 }
1943 break;
1944
1945 case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1946 {
|
1947 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
1948 mike 1.1 RETURN(-1);
1949
|
1950 krisbash 1.4 wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull(
1951 e.data.data, NULL, 10);
|
1952 mike 1.1
|
1953 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0)
|
1954 mike 1.1 RETURN(-1);
1955 }
1956 break;
1957
1958 default:
1959 {
1960 if (_MustUnderstandCanBeIgnored(&e) != 0)
1961 {
|
1962 krisbash 1.4 trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
|
1963 mike 1.1 RETURN(-1);
1964 }
1965
1966 if (XML_Skip(xml) != 0)
1967 RETURN(-1);
1968 }
1969 break;
1970
1971 }
1972 }
1973
1974 /* Expect <s:Body> */
|
1975 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
|
1976 mike 1.1 RETURN(-1);
1977
1978 /* Expect </s:Envelope> */
|
1979 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
|
1980 mike 1.1 RETURN(-1);
1981
1982 return 0;
1983 }
1984
1985 int WS_ParseReleaseBody(
1986 XML* xml,
1987 WSMAN_WSEnumeratePullBody* wsenumpullbody)
1988 {
1989 XML_Elem e;
1990
1991 memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1992
1993 /* Expect <s:Body> */
|
1994 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
|
1995 mike 1.1 RETURN(-1);
1996
1997 /* Expect <n:Release> */
|
1998 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Release")) != 0)
|
1999 mike 1.1 RETURN(-1);
2000
2001 for (;;)
2002 {
2003 if (XML_Next(xml, &e) != 0)
2004 RETURN(-1);
2005
2006 if (e.type == XML_END)
2007 {
|
2008 krisbash 1.4 int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
|
2009 mike 1.1
2010 if (WSMANTAG_ENUM_RELEASE != tag)
2011 {
|
2012 krisbash 1.4 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
|
2013 mike 1.1 RETURN(-1);
2014 }
2015 break;
2016 }
2017
2018 /* skip possible comments */
2019 if (e.type != XML_START)
2020 continue;
2021
|
2022 krisbash 1.4 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
|
2023 mike 1.1 {
2024 case WSMANTAG_PULL_ENUMERATION_CONTEXT:
2025 {
|
2026 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
|
2027 mike 1.1 RETURN(-1);
2028
|
2029 krisbash 1.4 wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull(
2030 e.data.data, NULL, 10);
|
2031 mike 1.1
|
2032 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0)
|
2033 mike 1.1 RETURN(-1);
2034 }
2035 break;
2036
2037 default:
2038 {
2039 if (_MustUnderstandCanBeIgnored(&e) != 0)
2040 {
|
2041 krisbash 1.4 trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
|
2042 mike 1.1 RETURN(-1);
2043 }
2044
2045 if (XML_Skip(xml) != 0)
2046 RETURN(-1);
2047 }
2048 break;
2049
2050 }
2051 }
2052
2053 /* Expect <s:Body> */
|
2054 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
|
2055 mike 1.1 RETURN(-1);
2056
2057 /* Expect </s:Envelope> */
|
2058 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
|
2059 mike 1.1 RETURN(-1);
2060
2061 return 0;
2062 }
2063
2064 int WS_ParseIdentifyBody(
2065 XML* xml)
2066 {
2067 XML_Elem e;
2068
|
2069 krisbash 1.4 if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
2070 RETURN(-1);
2071
2072 if (XML_Expect(xml, &e, XML_START, PAL_T('i'), PAL_T("Identify")) != 0)
2073 RETURN(-1);
2074
2075 if (XML_Expect(xml, &e, XML_END, PAL_T('i'), PAL_T("Identify")) != 0)
2076 RETURN(-1);
2077
2078 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
2079 RETURN(-1);
2080
2081 if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
2082 RETURN(-1);
2083
2084 return 0;
2085 }
2086
2087
2088 #ifndef DISABLE_INDICATION
2089
2090 krisbash 1.4 typedef enum _SubscribeSequence
2091 {
2092 SubscribeSequence_NONE = 0,
2093 SubscribeSequence_EXPIRES = 1,
2094 SubscribeSequence_FILTER = 2,
2095 SubscribeSequence_END = 3
2096 } SubscribeSequence;
2097
2098 /* Parse subscribe body, One example,
2099 <s:Body>
2100 <e:Subscribe>
2101 <e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/Pull">
2102 <w:Heartbeats>PT60.000S</w:Heartbeats>
2103 <w:Locale xml:lang="en-US" s:mustUnderstand="false"/>
2104 <p:DataLocale xml:lang="en-US" s:mustUnderstand="false"/>
2105 <w:ContentEncoding>UTF-16</w:ContentEncoding>
2106 </e:Delivery>
2107 <e:Expires>
2108 "PT60.000S"
2109 </e:Expires>
2110 <w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL">
2111 krisbash 1.4 Select * from My_Alarm"
2112 </w:Filter>
2113 </e:Subscribe>
2114 </s:Body>
2115 */
2116 int WS_ParseSubscribeBody(
2117 XML* xml,
2118 WSMAN_WSEnumeratePullBody* wssubbody)
2119 {
2120 XML_Elem e;
2121 SubscribeSequence sequenceState = SubscribeSequence_NONE;
2122
2123 memset(wssubbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
2124
2125 /* Expect <s:Body> */
2126 if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0)
2127 RETURN(-1);
2128
2129 /* Expect <e:Subscribe> */
2130 if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Subscribe")) != 0)
2131 RETURN(-1);
2132 krisbash 1.4
2133 /* A subscribe message body is made up of an xs:sequence of the following:
2134 * 1 - EndTo (Optional)
2135 * 2 - Delivery
2136 * 3 - Expires (Optional)
2137 * 4 - Filter (Optional)
2138 */
2139
2140 /* Expect <e:Delivery> */
2141 if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Delivery")) != 0)
2142 RETURN(-1);
2143
2144 {
2145 const XML_Char* mode = NULL;
2146
2147 /* Read 'Mode' attribute */
2148 mode = XML_Elem_GetAttr(&e, 0, ZT("Mode"));
2149 if (mode)
2150 {
2151 int tag = HashStr( 0, mode, Tcslen(mode));
2152 if (WSMAN_DELIVERY_MODE_PULL != tag)
2153 krisbash 1.4 {
2154 trace_Wsman_UnsupportedDeliveryMode(mode);
2155 RETURN(-1);
2156 }
2157 else
2158 {
2159 trace_Wsman_DeliveryMode(mode);
2160 }
2161 }
2162 else
2163 {
2164 trace_Wsman_ExpectedDeliveryMode();
2165 RETURN(-1);
2166 }
2167 }
2168
2169 for (;;)
2170 {
2171 if (XML_Next(xml, &e) != 0)
2172 RETURN(-1);
2173
2174 krisbash 1.4 if (e.type == XML_END)
2175 {
2176 int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
2177
2178 /* The end tag for Delivery was encountered, so jump out of the loop. */
2179 if (WSMANTAG_SUBSCRIBE_DELIVER != tag)
2180 {
2181 trace_Wsman_UnexpectedCloseTagWithNamespace(e.data.namespaceId, e.data.data);
2182 RETURN(-1);
2183 }
2184 break;
2185 }
2186
2187 /* skip possible comments */
2188 if (e.type != XML_START)
2189 continue;
2190
2191 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
2192 {
2193 case WSMANTAG_SUBSCRIBE_HEARTBEATS:
2194 {
2195 krisbash 1.4 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2196 RETURN(-1);
2197
2198 if (XML_StripWhitespace(&e) != 0)
2199 RETURN(-1);
2200
2201 if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->heartbeat.value ) )
2202 RETURN(-1);
2203
2204 wssubbody->heartbeat.exists = MI_TRUE;
2205
2206 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Heartbeats")) != 0)
2207 RETURN(-1);
2208 }
2209 break;
2210
2211 case WSMANTAG_SUBSCRIBE_CONTENTENCODING:
2212 {
2213 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2214 RETURN(-1);
2215
2216 krisbash 1.4 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ContentEncoding")) != 0)
2217 RETURN(-1);
2218 }
2219 break;
2220
2221 case WSMANTAG_SUBSCRIBE_CONNECTION_RETRY:
2222 {
2223 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2224 RETURN(-1);
2225
2226 if (XML_StripWhitespace(&e) != 0)
2227 RETURN(-1);
2228
2229 if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->connectionRetry.value ) )
2230 RETURN(-1);
2231
2232 wssubbody->connectionRetry.exists = MI_TRUE;
2233
2234 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ConnectionRetry")) != 0)
2235 RETURN(-1);
2236 }
2237 krisbash 1.4 break;
2238
2239 default:
2240 {
2241 if (_MustUnderstandCanBeIgnored(&e) != 0)
2242 {
2243 trace_Wsman_UnknownMandatoryTagWithNamespace(e.data.namespaceId, e.data.data);
2244 RETURN(-1);
2245 }
2246
2247 if (XML_Skip(xml) != 0)
2248 RETURN(-1);
2249 }
2250 break;
2251
2252 }
2253 }
2254
2255 for (;;)
2256 {
2257 /* Get the next element and check for proper order of optional tags
2258 krisbash 1.4 * within the sequence. This loop ensures order and stops when it
2259 * hits a parse error or encounters the body end tag.*/
2260 if (XML_Next(xml, &e) != 0)
2261 RETURN(-1);
2262
2263 if (e.type == XML_START)
2264 {
2265 switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
2266 {
2267 case WSMANTAG_EXPIRES:
2268 {
2269 /* Parse Expires (if present) */
2270 if (sequenceState >= SubscribeSequence_EXPIRES)
2271 RETURN(-1);
2272 sequenceState = SubscribeSequence_EXPIRES;
2273
2274 /* Expect an xs:duration of form: PnYnMnDTnHnMnS */
2275 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2276 RETURN(-1);
2277
2278 if (XML_StripWhitespace(&e) != 0)
2279 krisbash 1.4 RETURN(-1);
2280
2281 if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->expires.value ) )
2282 RETURN(-1);
2283
2284 wssubbody->expires.exists = MI_TRUE;
2285
2286 /* Check for closing </w:Expires> tag */
2287 if (XML_Expect(xml, &e, XML_END, ZT('e'), ZT("Expires")) != 0)
2288 RETURN(-1);
2289 }
2290 break;
2291 case WSMANTAG_ENUM_FILTER:
2292 {
2293 /* Parse filter and dialect */
2294 const XML_Char* dialect;
2295 if (sequenceState >= SubscribeSequence_FILTER)
2296 RETURN(-1);
2297 sequenceState = SubscribeSequence_FILTER;
2298
2299 /* Read 'Dialect' attribute */
2300 krisbash 1.4 dialect = XML_Elem_GetAttr(&e, 0, ZT("Dialect"));
2301 if (!dialect)
2302 {
2303 trace_Wsman_FilterTagMissingDialectAttribute();
2304 RETURN(-1);
2305 }
2306 wssubbody->dialect = _WS_ParseDialect(dialect, MI_TRUE);
2307 if (!wssubbody->dialect)
2308 {
2309 trace_Wsman_UnknownDialect(dialect);
2310 RETURN(-1);
2311 }
2312 else
2313 trace_Wsman_SubscribeDialect(dialect);
2314
2315 /* Get the filter text */
2316 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2317 RETURN(-1);
2318
2319 wssubbody->filter = e.data.data;
2320 trace_Wsman_SubscribeFilter(wssubbody->filter);
2321 krisbash 1.4
2322 /* Check for closing </w:Filter> tag */
2323 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Filter")) != 0)
2324 RETURN(-1);
2325 }
2326 break;
2327 case WSMANTAG_SEND_BOOKMARKS:
2328 {
2329 wssubbody->sendBookmarks = MI_TRUE;
2330
2331 if (XML_Skip(xml) != 0)
2332 RETURN(-1);
2333 }
2334 break;
2335 case WSMANTAG_BOOKMARK:
2336 {
2337 /* Parse Bookmark */
2338 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2339 RETURN(-1);
2340
2341 if (XML_StripWhitespace(&e) != 0)
2342 krisbash 1.4 RETURN(-1);
2343
2344 wssubbody->initialBookmark = e.data.data;
2345
2346 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Bookmark")) != 0)
2347 RETURN(-1);
2348 }
2349 break;
2350 default:
2351 RETURN(-1);
2352 }
2353 }
2354 else if (e.type == XML_END)
2355 {
2356 /* Expect </e:Subscribe> */
2357 if (ZT('e') == e.data.namespaceId &&
2358 Tcscmp(e.data.data, ZT("Subscribe")) == 0)
2359 {
2360 sequenceState = SubscribeSequence_END;
2361 /* We reached the end of the subscribe body an the end of the
2362 * xs:sequence. Jump out to proceed. */
2363 krisbash 1.4 break;
2364 }
2365 else
2366 RETURN(-1);
2367 }
2368 else
2369 RETURN(-1);
2370 }
2371
2372 /* Expect </s:Body> */
2373 if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Body")) != 0)
2374 RETURN(-1);
2375
2376 /* Expect </s:Envelope> */
2377 if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Envelope")) != 0)
2378 RETURN(-1);
2379
2380 return 0;
2381 }
2382
2383 /* Unsubcribe message sample:
2384 krisbash 1.4 <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd">
2385 <s:Header>
2386 <a:To>http://localhost:5985/wsman</a:To>
2387 <a:ReplyTo>
2388 <a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
2389 </a:ReplyTo>
2390 <a:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action>
2391 ......
2392 <e:Identifier xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing">0860D524-6F0A-46FE-B95E-7CB0C1A2C1B8</e:Identifier>
2393 </s:Header>
2394 <s:Body>
2395 <e:Unsubscribe/>
2396 </s:Body>
2397 </s:Envelope>
2398 */
2399 int WS_ParseUnsubscribeBody(
2400 XML* xml,
2401 WSMAN_WSEnumeratePullBody* wsunsubbody)
2402 {
2403 XML_Elem e;
2404
2405 krisbash 1.4 memset(wsunsubbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
2406
2407 /* Expect <s:Body> */
2408 if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0)
|
2409 mike 1.1 RETURN(-1);
2410
|
2411 krisbash 1.4 /* Expect <e:Subscribe> */
2412 if (XML_Expect(xml, &e, XML_START, MI_T('e'), ZT("Unsubscribe")) != 0)
|
2413 mike 1.1 RETURN(-1);
2414
|
2415 krisbash 1.4 /* Expect </e:Subscribe> */
2416 if (XML_Expect(xml, &e, XML_END, MI_T('e'), ZT("Unsubscribe")) != 0)
|
2417 mike 1.1 RETURN(-1);
2418
|
2419 krisbash 1.4 /* Expect <s:Body> */
2420 if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Body")) != 0)
|
2421 mike 1.1 RETURN(-1);
2422
|
2423 krisbash 1.4 /* Expect </s:Envelope> */
2424 if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Envelope")) != 0)
|
2425 mike 1.1 RETURN(-1);
2426
2427 return 0;
2428 }
|
2429 krisbash 1.4
2430 #endif /* #ifndef DISABLE_INDICATION */
|