/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
**
** Licensed under the Apache License, Version 2.0 (the "License"); you may not
** use this file except in compliance with the License. You may obtain a copy
** of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
** MERCHANTABLITY OR NON-INFRINGEMENT.
**
** See the Apache 2 License for the specific language governing permissions
** and limitations under the License.
**
**==============================================================================
*/
#include <assert.h>
#include "wsmanparser.h"
#include "wsmanbuffer.h"
//#include "http.h"
//#include "time.h"
//#include <xml/xml.h>
//#include <base/buf.h>
#include <base/log.h>
#include <base/result.h>
#include <base/strings.h>
#include "wstags.h"
#include "wstags.inc"
#include "uri.h"
#define T MI_T
#if 0
#define ENABLE_TRACING
#endif
#ifdef ENABLE_TRACING
#define PRINTF(a) printf a
#else
#define PRINTF(a)
#endif
/*
**==============================================================================
**
** Local definitions:
**
**==============================================================================
*/
static int _GetInstance(
XML* xml,
XML_Elem *start,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams);
/****************************************************************************************/
/* soap processing */
static int _MustUnderstandCanBeIgnored(
const XML_Elem* e)
{
size_t i;
for (i = 0; i < e->attrsSize; i++)
{
if (strcmp(e->attrs[i].name, "s:mustUnderstand") == 0 &&
strcmp(e->attrs[i].value, "true") == 0)
{
return -1;
}
}
return 0;
}
static int _GetSelector(
XML* xml,
XML_Elem *e,
const char** ns,
const char* classname,
MI_Instance** instance,
Batch** batch)
{
size_t i;
/* expecting namespace or key */
for (i = 0; i < e->attrsSize; i++)
{
if (strcmp(e->attrs[i].name, "Name") == 0 &&
strcmp(e->attrs[i].value, "__cimnamespace") == 0)
{
/* namespace */
if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
return -1;
PRINTF(("a:Selector:namespace{%s}\n", e->data));
*ns = e->data;
}
else if (strcmp(e->attrs[i].name, "Name") == 0)
{
/* keys */
const char* propName = e->attrs[i].value;
if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
return -1;
PRINTF(("a:Selector:namespace{%s}\n", e->data));
/* allocate batch and instance if needed */
if (!(*instance))
{
MI_Result r;
MI_Char* cn;
/* verify that we already received classname */
if (!classname)
{
XML_Raise(xml, "class-name was not found druing selector parsing");
return -1;
}
/* Destroy old batch if it exists (from previous operation) */
if (*batch)
{
Batch_Destroy(*batch);
}
*batch = Batch_New(BATCH_MAX_PAGES);
if (!(*batch))
return -1;
cn = Batch_Strdup2(*batch, classname);
r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch);
if (MI_RESULT_OK != r)
return -1;
}
/* add next property to the instance */
{
const MI_Char* wpropName = Batch_Strdup2(*batch, propName);
MI_Result r;
MI_Value value;
value.string = Batch_Strdup2(*batch, e->data);
// Set the property.
r = MI_Instance_AddElement(*instance, wpropName, &value,
MI_STRING, MI_FLAG_BORROW | MI_FLAG_KEY);
if (MI_RESULT_OK != r)
return -1;
}
}
else
continue;
if (XML_Expect(xml, e, XML_END, "w:Selector") != 0)
return -1;
break;
}
return 0;
}
static int _GetSelectorSet(
XML* xml,
WSMAN_WSHeader* wsheader)
{
XML_Elem e;
if (XML_Expect(xml, &e, XML_START, "w:Selector") != 0)
return -1;
/* iterate through all selector tags */
for (;;)
{
if (0 != _GetSelector(
xml,
&e,
&wsheader->rqtNamespace,
wsheader->rqtClassname,
&wsheader->instance,
&wsheader->instanceBatch))
return -1;
/**/
if (XML_Next(xml, &e) != 0)
return -1;
if (XML_END == e.type)
break;
}
return 0;
}
static int _GetReferenceParameters(
XML* xml,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams)
{
XML_Elem e;
const char* classname = 0;
const char* nameSpace = NULL;
/* extract ResourceURI and SelectorSet */
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (XML_END == e.type)
break;
if (0 == strcmp("w:ResourceURI", e.data))
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
classname = strrchr(e.data, '/');
/* skip '/' */
if (classname)
classname++;
if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
return -1;
continue;
}
if (0 == strcmp("w:SelectorSet", e.data))
{
/* Allocate an instance */
if (!*dynamicInstanceParams)
{
MI_Result r;
const MI_Char* cn;
if (!classname)
{
XML_Raise(xml, "ResourceURI tag expected");
return -1;
}
cn = Batch_Strdup2(dynamicBatch, classname);
r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
if (MI_RESULT_OK != r)
return -1;
}
/* iterate through all selector tags */
for (;;)
{
const char* ns = NULL;
if (_GetSelector(
xml,
&e,
&ns,
classname,
dynamicInstanceParams,
&dynamicBatch) != 0)
{
return -1;
}
if (ns)
{
nameSpace = ns;
}
/**/
if (XML_Next(xml, &e) != 0)
return -1;
if (XML_END == e.type)
break;
}
continue;
}
}
if (nameSpace)
(*dynamicInstanceParams)->nameSpace = nameSpace;
return 0;
}
static int _GetReference(
XML* xml,
XML_Elem *start,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams)
{
XML_Elem e;
e = *start;
/* extract all parameters */
for (;;)
{
if (0 != strcmp("a:ReferenceParameters", e.data))
{
if (XML_Skip(xml) != 0)
return -1;
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
break;
continue;
}
if (0 != _GetReferenceParameters(xml, dynamicBatch, dynamicInstanceParams))
return -1;
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
break;
}
return 0;
}
static int _GetSingleProperty(
XML* xml,
Batch* dynamicBatch,
const char* propNameChar,
MI_Value* value,
MI_Type* type)
{
XML_Elem e;
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_CHARS)
{
/* Plain string property */
value->string = Batch_Strdup2(dynamicBatch, e.data);
*type = MI_STRING;
if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
return -1;
}
else if ('a' == e.data[0])
{
/* Reference as </adddress></ReferenceParameters>*/
value->instance = 0;
if (0 != _GetReference(xml, &e, dynamicBatch, &value->instance))
return -1;
*type = MI_REFERENCE;
}
else
{
/* Embedded instance */
value->instance = 0;
if (0 != _GetInstance(xml, &e, dynamicBatch, &value->instance))
return -1;
*type = MI_INSTANCE;
if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
return -1;
}
return 0;
}
static int _AddValueToArray(
Batch* dynamicBatch,
MI_Value* valueA,
MI_Type typeA,
const MI_Value* value,
MI_Type type)
{
/* does type match? */
if ((type | MI_ARRAY_BIT) != typeA)
return -1;
/* do we need to realloc array? */
if ((valueA->array.size % 16) == 0)
{
void* newData = Batch_Get(dynamicBatch, (valueA->array.size + 16) * sizeof(void*));
if (!newData)
return -1;
if (valueA->array.size)
memcpy(newData, valueA->array.data, valueA->array.size * sizeof(void*));
valueA->array.data = newData;
}
if (type == MI_STRING)
valueA->stringa.data[valueA->stringa.size] = value->string;
else
valueA->instancea.data[valueA->instancea.size] = value->instance;
valueA->array.size++;
return 0;
}
static int _GetInstance(
XML* xml,
XML_Elem *start,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams)
{
XML_Elem e;
const MI_Char* propNameA = 0;
MI_Value valueA;
MI_Type typeA = MI_BOOLEAN;
const MI_Char* propNamePrev = 0;
MI_Value valuePrev;
MI_Type typePrev = MI_BOOLEAN;
memset(&valueA, 0, sizeof(valueA));
/* extract all parameters */
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
break;
/* skip possible comments */
if (e.type != XML_START)
continue;
/* allocate new instance if needed */
if (!*dynamicInstanceParams)
{
MI_Result r;
const MI_Char* cn = Batch_Strdup2(dynamicBatch, start->data + 2);
r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
if (MI_RESULT_OK != r)
return -1;
}
/* add next property to the instance */
if (e.size > 2) /* ?:<name> */
{
MI_Result r;
MI_Value value;
MI_Type type = MI_BOOLEAN;
const char* propNameChar;
const MI_Char* propName;
propNameChar = e.data;
propName = Batch_Strdup2(dynamicBatch, propNameChar + 2);
type = MI_BOOLEAN;
if (0 != _GetSingleProperty(xml, dynamicBatch, propNameChar, &value, &type))
return -1;
/* Did we collect array's items? */
if (propNameA)
{
/* if we have array and new property matches array - add new item to the array */
if (0 == Zcmp(propNameA, propName))
{
if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
return -1;
}
else
{
r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
typeA, MI_FLAG_BORROW);
if (MI_RESULT_OK != r)
return -1;
/* Clear array prop name */
propNameA = 0;
propNamePrev = propName;
valuePrev = value;
typePrev = type;
}
}
else if (propNamePrev)
{
/* Check if name is the same and we need to create an array */
if (0 == Zcmp(propNamePrev, propName))
{
/* create array */
valueA.array.size = 0;
valueA.array.data = 0;
typeA = type | MI_ARRAY_BIT;
propNameA = propName;
if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &valuePrev, typePrev))
return -1;
if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
return -1;
}
else
{
r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev,
typePrev, MI_FLAG_BORROW);
if (MI_RESULT_OK != r)
return -1;
propNamePrev = propName;
valuePrev = value;
typePrev = type;
}
}
else
{
/* collecting first item */
propNamePrev = propName;
valuePrev = value;
typePrev = type;
}
}
}
/* if last property was array - add it */
if (propNameA)
{
MI_Result r;
r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA,
typeA, MI_FLAG_BORROW);
if (MI_RESULT_OK != r)
return -1;
}
else if (propNamePrev)
{
MI_Result r;
r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev,
typePrev, MI_FLAG_BORROW);
if (MI_RESULT_OK != r)
return -1;
}
/* check closing tag */
if (strcmp(e.data, start->data) != 0)
return -1;
return 0;
}
int WS_ParseWSHeader(
XML* xml,
WSMAN_WSHeader* wsheader)
{
XML_Elem e;
memset(wsheader, 0, sizeof(WSMAN_WSHeader));
/* Expect <s:Header> */
if (XML_Expect(xml, &e, XML_START, "s:Header") != 0)
return -1;
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0)
{
int tag = HashStr(e.data, e.size);
if (WSMANTAG_HEADER != tag)
{
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
return -1;
}
//printf("DONE\n");
break;
}
/* skip possible comments */
if (e.type != XML_START)
continue;
switch (HashStr(e.data, e.size))
{
case WSMANTAG_TO:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
PRINTF(("a:To{%s}\n", e.data));
if (XML_Expect(xml, &e, XML_END, "a:To") != 0)
return -1;
}
break;
case WSMANTAG_RESOURCE_URI:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
PRINTF(("w:ResourceURI{%s}\n", e.data));
wsheader->rqtClassname = strrchr(e.data, '/');
/* skip '/' */
if (wsheader->rqtClassname)
wsheader->rqtClassname++;
if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
return -1;
}
break;
case WSMANTAG_REPLY_TO:
{
if (XML_Expect(xml, &e, XML_START, "a:Address") != 0)
return -1;
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
if (XML_Expect(xml, &e, XML_END, "a:Address") != 0)
return -1;
if (XML_Expect(xml, &e, XML_END, "a:ReplyTo") != 0)
return -1;
}
break;
case WSMANTAG_ACTION:
{
wsheader->foundAction = MI_TRUE;
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsheader->rqtAction = HashStr(e.data, e.size);
if (0 == wsheader->rqtAction)
{
char* s;
/* DSP0226; 9: Custom Actions (Methods) just need to have unique URI.
We are assuming it has format like http://<server>/wbem/wscim/1/cim-schema/2/<class-name>/<method-name> */
if (0 != strncmp(e.data, "http://", 7))
return -1;
wsheader->rqtServer = e.data + 7;
s = strchr(wsheader->rqtServer, '/');
if (!s)
return -1;
*s = 0;
s++;
if (0 != strncmp(s, "wbem/wscim/1/cim-schema/2/", 26))
return -1;
s += 26;
wsheader->rqtClassname = s;
s = strchr(s, '/');
if (!s)
return -1;
*s = 0;
s++;
wsheader->rqtMethod = s;
}
if (XML_Expect(xml, &e, XML_END, "a:Action") != 0)
return -1;
}
break;
case WSMANTAG_SELECTOR_SET:
{
if (_GetSelectorSet(xml, wsheader) != 0)
return -1;
}
break;
case WSMANTAG_MESSAGE_ID:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsheader->rqtMessageID = e.data;
if (XML_Expect(xml, &e, XML_END, "a:MessageID") != 0)
return -1;
}
break;
case WSMANTAG_MAX_ENVELOPE_SIZE:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsheader->maxEnvelopeSize = (MI_Uint32)Strtoull(e.data, NULL, 10);
PRINTF(("maxEnvelopeSize{%d}\n", wsheader->maxEnvelopeSize));
if (XML_Expect(xml, &e, XML_END, "w:MaxEnvelopeSize") != 0)
return -1;
}
break;
default:
{
if (_MustUnderstandCanBeIgnored(&e) != 0)
{
wsheader->unknownMandatoryTag = e.data;
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted",
e.data ));
/* validate header will send correct repsonse to the client */
}
if (XML_Skip(xml) != 0)
return -1;
}
break;
}
}
return 0;
}
int WS_ParseSoapEnvelope(XML* xml)
{
XML_Elem e;
/* Ignore the processing instruction (if any) */
{
if (XML_Next(xml, &e) != 0)
{
XML_Raise(xml, "missing root element");
return -1;
}
if (e.type != XML_INSTRUCTION)
{
if (XML_PutBack(xml, &e) != 0)
return -1;
}
}
/* Expect <s:Envelope> */
if (XML_Expect(xml, &e, XML_START, "s:Envelope") != 0)
return -1;
return 0;
}
static const char* _ExpectCharsAndEnd(
XML* xml,
const char* name)
{
XML_Elem e;
const char* chars;
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return NULL;
chars = e.data;
if (XML_Expect(xml, &e, XML_END, name) != 0)
return NULL;
return chars;
}
/*
**==============================================================================
**
** _ParseAssociationFilterObject()
**
** Example:
** <b:Object>
** <a:Address>
** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
** </a:Address>
** <a:ReferenceParameters>
** <w:ResourceURI>
** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
** </w:ResourceURI>
** <w:SelectorSet>
** <w:Selector Name="__cimnamespace">
** root/cimv2
** </w:Selector>
** <w:Selector Name="Key">
** 1001
** </w:Selector>
** </w:SelectorSet>
** </a:ReferenceParameters>
** </b:Object>
*
**==============================================================================
*/
static int _ParseAssociationFilterObject(
XML* xml,
Batch* batch,
WSMAN_AssociationFilter* filter)
{
XML_Elem e;
/* Parse child elements */
for (;;)
{
/* Get next element */
if (XML_Next(xml, &e) != 0)
return -1;
/* Put it back and break out if not a start tag */
if (e.type != XML_START)
{
if (XML_PutBack(xml, &e) != 0)
return -1;
break;
}
/* Handle "Object" tag */
if (strcmp(e.data, "a:ReferenceParameters") == 0)
{
if (_GetReferenceParameters(
xml,
batch,
&filter->referenceParameters) != 0)
{
return -1;
}
}
else if (strcmp(e.data, "a:Address") == 0)
{
filter->address = _ExpectCharsAndEnd(xml, "a:Address");
if (!filter->address)
return -1;
}
else
{
if (XML_Skip(xml) != 0)
return -1;
}
}
/* Expect </Object> */
if (XML_Expect(xml, &e, XML_END, "b:Object") != 0)
return -1;
return 0;
}
/*
**==============================================================================
**
** _ParseAssociationFilter()
**
** Example:
** <b:AssociatedInstances>
** <b:Object>
** <a:Address>
** http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
** </a:Address>
** <a:ReferenceParameters>
** <w:ResourceURI>
** http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
** </w:ResourceURI>
** <w:SelectorSet>
** <w:Selector Name="__cimnamespace">
** root/cimv2
** </w:Selector>
** <w:Selector Name="Key">
** 1001
** </w:Selector>
** </w:SelectorSet>
** </a:ReferenceParameters>
** </b:Object>
** <b:AssociationClassName>
** ABC_Connector
** </b:AssociationClassName>
** <b:Role>
** Component
** </b:Role>
** <b:ResultClassName>
** ABC_Gadget
** </b:ResultClassName>
** <b:ResultRole>
** Part
** </b:ResultRole>
** </b:AssociatedInstances>
**
**==============================================================================
*/
static int _ParseAssociationFilter(
XML* xml,
Batch* batch,
WSMAN_AssociationFilter* filter)
{
XML_Elem e;
/* Expect <AssociatedInstances> */
if (XML_Expect(xml, &e, XML_START, "b:AssociatedInstances") != 0)
return -1;
/* Parse child elements */
for (;;)
{
/* Get next element */
if (XML_Next(xml, &e) != 0)
return -1;
/* Put it back and break out if not a start tag */
if (e.type != XML_START)
{
if (XML_PutBack(xml, &e) != 0)
return -1;
break;
}
/* Handle "Object" tag */
if (strcmp(e.data, "b:Object") == 0)
{
if (_ParseAssociationFilterObject(xml, batch, filter) != 0)
return -1;
}
else if (strcmp(e.data, "b:AssociationClassName") == 0)
{
filter->associationClassName = _ExpectCharsAndEnd(
xml, "b:AssociationClassName");
if (!filter->associationClassName)
return -1;
}
else if (strcmp(e.data, "b:Role") == 0)
{
filter->role = _ExpectCharsAndEnd(xml, "b:Role");
if (!filter->role)
return -1;
}
else if (strcmp(e.data, "b:ResultClassName") == 0)
{
filter->resultClassName = _ExpectCharsAndEnd(
xml,
"b:ResultClassName");
if (!filter->resultClassName)
return -1;
}
else if (strcmp(e.data, "b:ResultRole") == 0)
{
filter->resultRole = _ExpectCharsAndEnd(
xml,
"b:ResultRole");
if (!filter->resultRole)
return -1;
}
else
{
if (XML_Skip(xml) != 0)
return -1;
}
}
#if 0
printf("AssociationFilter\n");
printf("{\n");
Instance_Print(filter->referenceParameters, stdout, 1, MI_TRUE);
printf(" nameSpace{%s}\n", filter->referenceParameters->nameSpace);
printf(" address{%s}\n", filter->address);
printf(" associationClassName{%s}\n", filter->associationClassName);
printf(" resultClassName{%s}\n", filter->resultClassName);
printf(" role{%s}\n", filter->role);
printf(" resultRole{%s}\n", filter->resultRole);
printf("}\n");
#endif
/* Expect </AssociatedInstances> */
if (XML_Expect(xml, &e, XML_END, "b:AssociatedInstances") != 0)
return -1;
return 0;
}
int WS_ParseEnumerateBody(
XML* xml,
Batch** batch,
WSMAN_WSEnumeratePullBody* wsenumbody)
{
XML_Elem e;
memset(wsenumbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
/* Allocate batch (owned by WSMAN_ConnectionData object */
if (*batch == NULL)
{
*batch = Batch_New(BATCH_MAX_PAGES);
if (!*batch)
return -1;
}
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
/* Expect <n:Enumerate> */
if (XML_Expect(xml, &e, XML_START, "n:Enumerate") != 0)
return -1;
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
{
int tag = HashStr(e.data, e.size);
if (WSMANTAG_ENUM_ENUMERATE != tag)
{
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
return -1;
}
break;
}
/* skip possible comments */
if (e.type != XML_START)
continue;
switch (HashStr(e.data, e.size))
{
case WSMANTAG_ENUM_MAX_ELEMENTS:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
PRINTF(("maxElements{%d}\n", wsenumbody->maxElements));
if (XML_Expect(xml, &e, XML_END, "w:MaxElements") != 0)
return -1;
}
break;
case WSMANTAG_ENUM_OPTIMIZE_ENUMERATION:
{
wsenumbody->allowOptimization = MI_TRUE;
if (XML_Skip(xml) != 0)
return -1;
}
break;
case WSMANTAG_ENUM_POLYMORPHISM_MODE:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumbody->polymorphismMode = HashStr(e.data, e.size);
if (XML_Expect(xml, &e, XML_END, "b:PolymorphismMode") != 0)
return -1;
}
break;
case WSMANTAG_ENUM_MODE:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumbody->enumerationMode = HashStr(e.data, e.size);
if (XML_Expect(xml, &e, XML_END, "w:EnumerationMode") != 0)
return -1;
}
break;
/*
* Examples:
* <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
* SELECT Weight FROM Widget WHERE Key = 1001
* </w:Filter>
*
* <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
* <b:AssociatedInstances>
* ...
* </b:AssociatedInstances>
* </w:Filter>
*/
case WSMANTAG_ENUM_FILTER:
{
const char* dialect;
const char* p;
/* Get 'Dialect' attribute? */
dialect = XML_Elem_GetAttr(&e, "Dialect");
if (!dialect)
{
LOGW_CHAR(("wsman: Filter tag missing Dialect attribute"));
return -1;
}
/* Reduce long dialect name to final component of path */
p = strrchr(dialect, '/');
if (p)
wsenumbody->dialect = p + 1;
else
wsenumbody->dialect = dialect;
/* Parse the association filter */
if (strcmp(dialect, URI_CIMBINDING "/associationFilter") == 0)
{
wsenumbody->foundAssociationFilter = MI_TRUE;
if (_ParseAssociationFilter(xml, *batch,
&wsenumbody->associationFilter) != 0)
{
return -1;
}
}
else
{
/* Get the filter text */
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumbody->filter = e.data;
}
/* Check for closing </w:Filter> tag */
if (XML_Expect(xml, &e, XML_END, "w:Filter") != 0)
return -1;
}
break;
default:
{
if (_MustUnderstandCanBeIgnored(&e) != 0)
{
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
return -1;
}
if (XML_Skip(xml) != 0)
return -1;
}
break;
}
}
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
/* Expect </s:Envelope> */
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}
int WS_ParseInvokeBody(
XML* xml,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams)
{
XML_Elem e;
*dynamicInstanceParams = 0;
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
/* Expect <?:?> parameter's tag */
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
/* empty body? can be valid for methods without parameters */
if (e.type == XML_END)
return 0;
if (e.type == XML_START)
break;
}
if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
return -1;
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
/* Expect </s:Envelope> */
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}
int WS_ParseCreateBody(
XML* xml,
Batch* dynamicBatch,
MI_Instance** dynamicInstanceParams)
{
XML_Elem e;
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
/* Expect <?:?> parameter's tag */
if (XML_Next(xml, &e) != 0)
return -1;
if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
return -1;
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
/* Expect </s:Envelope> */
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}
int WS_ParsePullBody(
XML* xml,
WSMAN_WSEnumeratePullBody* wsenumpullbody)
{
XML_Elem e;
memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
/* Expect <n:Enumerate> */
if (XML_Expect(xml, &e, XML_START, "n:Pull") != 0)
return -1;
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
{
int tag = HashStr(e.data, e.size);
if (WSMANTAG_ENUM_PULL != tag)
{
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
return -1;
}
break;
}
/* skip possible comments */
if (e.type != XML_START)
continue;
switch (HashStr(e.data, e.size))
{
case WSMANTAG_PULL_MAX_ELEMENTS:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumpullbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
PRINTF(("maxElements{%d}\n", wsenumpullbody->maxElements));
if (XML_Expect(xml, &e, XML_END, "n:MaxElements") != 0)
return -1;
}
break;
case WSMANTAG_PULL_ENUMERATION_CONTEXT:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
return -1;
}
break;
default:
{
if (_MustUnderstandCanBeIgnored(&e) != 0)
{
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
return -1;
}
if (XML_Skip(xml) != 0)
return -1;
}
break;
}
}
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
/* Expect </s:Envelope> */
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}
int WS_ParseReleaseBody(
XML* xml,
WSMAN_WSEnumeratePullBody* wsenumpullbody)
{
XML_Elem e;
memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
/* Expect <n:Release> */
if (XML_Expect(xml, &e, XML_START, "n:Release") != 0)
return -1;
for (;;)
{
if (XML_Next(xml, &e) != 0)
return -1;
if (e.type == XML_END)
{
int tag = HashStr(e.data, e.size);
if (WSMANTAG_ENUM_RELEASE != tag)
{
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
return -1;
}
break;
}
/* skip possible comments */
if (e.type != XML_START)
continue;
switch (HashStr(e.data, e.size))
{
case WSMANTAG_PULL_ENUMERATION_CONTEXT:
{
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
return -1;
wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
return -1;
}
break;
default:
{
if (_MustUnderstandCanBeIgnored(&e) != 0)
{
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
return -1;
}
if (XML_Skip(xml) != 0)
return -1;
}
break;
}
}
/* Expect <s:Body> */
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
/* Expect </s:Envelope> */
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}
int WS_ParseIdentifyBody(
XML* xml)
{
XML_Elem e;
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
return -1;
if (XML_Expect(xml, &e, XML_START, "i:Identify") != 0)
return -1;
if (XML_Expect(xml, &e, XML_END, "i:Identify") != 0)
return -1;
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
return -1;
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
return -1;
return 0;
}