version 1.3, 2015/04/20 18:10:36
|
version 1.4, 2015/04/20 18:20:37
|
|
|
#include <ctype.h> | #include <ctype.h> |
#include "wsmanparser.h" | #include "wsmanparser.h" |
#include "wsbuf.h" | #include "wsbuf.h" |
//#include "http.h" |
|
//#include "time.h" |
|
//#include <xml/xml.h> |
|
//#include <base/buf.h> |
|
#include <base/log.h> | #include <base/log.h> |
#include <base/result.h> | #include <base/result.h> |
#include <base/strings.h> |
#include <pal/strings.h> |
|
#include <pal/format.h> |
|
#include <indication/common/indicommon.h> |
|
#include <base/helpers.h> |
|
|
|
#if defined(CONFIG_ENABLE_WCHAR) |
|
# define HASHSTR_CHAR TChar |
|
# define HASHSTR_T(STR) L##STR |
|
# define HASHSTR_STRCMP wcscmp |
|
#endif |
| |
#include "wstags.h" | #include "wstags.h" |
#include "wstags.inc" |
|
#include <wsman/uri.h> |
|
| |
#define T MI_T |
#if defined(CONFIG_FAVORSIZE) |
|
# include "wstags_small.inc" |
|
#else |
|
# include "wstags_quick.inc" |
|
#endif |
|
|
|
#include <wsman/uri.h> |
| |
#if 0 |
//#if 0 |
#define ENABLE_TRACING | #define ENABLE_TRACING |
#endif |
//#endif |
| |
#ifdef ENABLE_TRACING |
#define TRACE_RETURN |
#define PRINTF(a) printf a |
|
#else |
|
#define PRINTF(a) |
|
#endif |
|
| |
#if defined(TRACE_RETURN) | #if defined(TRACE_RETURN) |
# define RETURN(X) \ | # define RETURN(X) \ |
do \ | do \ |
{ \ | { \ |
printf("RETURN[%d]\n", __LINE__); \ |
trace_WsmanReturn( __FILE__, __LINE__ ); \ |
return X; \ | return X; \ |
} \ | } \ |
while (0) | while (0) |
|
|
Batch* dynamicBatch, | Batch* dynamicBatch, |
MI_Instance** dynamicInstanceParams); | MI_Instance** dynamicInstanceParams); |
| |
|
static int _GetReference( |
|
XML* xml, |
|
XML_Elem *start, |
|
Batch* dynamicBatch, |
|
MI_Instance** dynamicInstanceParams); |
|
|
/****************************************************************************************/ | /****************************************************************************************/ |
/* soap processing */ | /* soap processing */ |
| |
|
|
size_t i; | size_t i; |
for (i = 0; i < e->attrsSize; i++) | for (i = 0; i < e->attrsSize; i++) |
{ | { |
if (strcmp(e->attrs[i].name, "s:mustUnderstand") == 0 && |
if (e->attrs[i].name.namespaceId == MI_T('s') && |
strcmp(e->attrs[i].value, "true") == 0) |
Tcscmp(e->attrs[i].name.data, PAL_T("mustUnderstand")) == 0 && |
|
Tcscmp(e->attrs[i].value, PAL_T("true")) == 0) |
{ | { |
RETURN(-1); | RETURN(-1); |
} | } |
|
|
return 0; | return 0; |
} | } |
| |
#if 1 |
static MI_Boolean IsValidClassname(const TChar* classname) |
static MI_Boolean IsValidClassname(const char* classname) |
|
{ | { |
const char* p = classname; |
const TChar* p = classname; |
| |
if (!isalpha((unsigned char)(*p)) && *p != '_') |
if (!isalpha((unsigned int)(*p)) && *p != '_') |
return MI_FALSE; | return MI_FALSE; |
| |
p++; | p++; |
| |
for (; *p; p++) | for (; *p; p++) |
{ | { |
if (!isalnum((unsigned char)(*p)) && *p != '_') |
if (!isalnum((unsigned int)(*p)) && *p != '_') |
return MI_FALSE; | return MI_FALSE; |
} | } |
| |
return MI_TRUE; | return MI_TRUE; |
} | } |
#endif |
|
| |
static int _GetSelector( |
static int _ParseBooleanOption(_In_ XML_Elem *e, _Inout_ MI_Boolean *ptrToOption) |
XML* xml, |
{ |
XML_Elem *e, |
if(Tcscasecmp(e->data.data, PAL_T("true")) == 0) |
const char** ns, |
{ |
const char* classname, |
*ptrToOption = 1; |
MI_Instance** instance, |
} |
Batch** batch) |
else if(Tcscasecmp(e->data.data, PAL_T("false")) == 0) |
|
{ |
|
*ptrToOption = 0; |
|
} |
|
else |
|
RETURN(-1); |
|
|
|
return 0; |
|
} |
|
|
|
static int _GetOption( |
|
_In_ XML* xml, |
|
_In_ XML_Elem *e, |
|
_Inout_ WSMAN_WSHeader* wsheader) |
{ | { |
size_t i; | size_t i; |
| |
/* expecting namespace or key */ |
|
for (i = 0; i < e->attrsSize; i++) | for (i = 0; i < e->attrsSize; i++) |
{ | { |
#if 1 |
|
/* To support GetClass */ | /* To support GetClass */ |
if (strcmp(e->attrs[i].name, "Name") == 0 && |
if ((e->attrs[i].name.namespaceId == 0) && |
strcmp(e->attrs[i].value, "ClassName") == 0) |
Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0) |
{ | { |
if (XML_Expect(xml, e, XML_CHARS, NULL) != 0) |
int valueHash = 0; |
|
|
|
if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
PRINTF(("a:Selector:ClassName{%s}\n", e->data)); |
valueHash = HashStr(0, e->attrs[i].value, e->attrs[i].valueSize); |
| |
if (!IsValidClassname(e->data)) |
// the WSMAN_OPTION_WMI_* is to check for these options included as custom options |
|
if((valueHash == WSMAN_OPTION_INCLUDE_INHERITANCE_HIERARCHY) || |
|
(valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITANCE_HIERARCHY)) |
|
{ |
|
if(_ParseBooleanOption(e, &(wsheader->includeInheritanceHierarchy)) != 0) |
|
RETURN(-1); |
|
} |
|
else if((valueHash == WSMAN_OPTION_INCLUDE_INHERITED_ELEMENTS) || |
|
(valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITED_ELEMENTS)) |
|
{ |
|
if(_ParseBooleanOption(e, &(wsheader->includeInheritedElements)) != 0) |
|
RETURN(-1); |
|
} |
|
else if((valueHash == WSMAN_OPTION_INCLUDE_QUALIFIERS) || |
|
(valueHash == WSMAN_OPTION_WMI_INCLUDE_QUALIFIERS)) |
|
{ |
|
if(_ParseBooleanOption(e, &(wsheader->includeQualifiers)) != 0) |
|
RETURN(-1); |
|
} |
|
else if((valueHash == WSMAN_OPTION_INCLUDE_CLASS_ORIGIN) || |
|
(valueHash == WSMAN_OPTION_WMI_INCLUDE_CLASS_ORIGIN)) |
|
{ |
|
if(_ParseBooleanOption(e, &(wsheader->includeClassOrigin)) != 0) |
RETURN(-1); | RETURN(-1); |
|
} |
classname = e->data; |
else if(valueHash == WSMAN_OPTION_MSFTWINRM_USE_PRECISE_ARRAYS) |
|
{ |
|
if(_ParseBooleanOption(e, &(wsheader->usePreciseArrays)) != 0) |
|
RETURN(-1); |
|
} |
} | } |
else | else |
#endif |
continue; |
if (strcmp(e->attrs[i].name, "Name") == 0 && |
|
strcmp(e->attrs[i].value, "__cimnamespace") == 0) |
if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Option")) != 0) |
|
RETURN(-1); |
|
|
|
break; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int _GetOptionSet( |
|
XML* xml, |
|
WSMAN_WSHeader* wsheader) |
|
{ |
|
XML_Elem e; |
|
|
|
if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Option")) != 0) |
|
RETURN(-1); |
|
|
|
/* iterate through all option tags */ |
|
for (;;) |
|
{ |
|
if (0 != _GetOption( |
|
xml, |
|
&e, |
|
wsheader)) |
|
RETURN(-1); |
|
|
|
/**/ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_END == e.type) |
|
break; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static int _GetSelector( |
|
_In_ XML* xml, |
|
_In_ XML_Elem *e, |
|
_Inout_ const TChar** ns, |
|
_Inout_ const TChar** classname, |
|
_Inout_ MI_Instance** instance, |
|
_Inout_ Batch** batch) |
|
{ |
|
size_t i; |
|
|
|
/* expecting namespace or key */ |
|
for (i = 0; i < e->attrsSize; i++) |
|
{ |
|
/* To support GetClass */ |
|
if((e->attrs[i].name.namespaceId == 0) && |
|
(Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0)) |
|
{ |
|
if (Tcscmp(e->attrs[i].value, PAL_T("ClassName")) == 0) |
|
{ |
|
if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (!IsValidClassname(e->data.data)) |
|
RETURN(-1); |
|
*classname = e->data.data; |
|
} |
|
else if(Tcscmp(e->attrs[i].value, PAL_T("__cimnamespace")) == 0) |
{ | { |
/* namespace */ | /* namespace */ |
if (XML_Expect(xml, e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
PRINTF(("a:Selector:namespace{%s}\n", e->data)); |
*ns = e->data.data; |
*ns = e->data; |
|
} | } |
else if (strcmp(e->attrs[i].name, "Name") == 0) |
else |
{ | { |
/* keys */ | /* keys */ |
const char* propName = e->attrs[i].value; |
const TChar* propName = e->attrs[i].value; |
|
|
|
MI_Boolean selectorIsReference = MI_FALSE; |
|
|
|
if (XML_Next(xml, e) != 0) |
|
{ |
|
XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR); |
|
RETURN(-1); |
|
} |
| |
if (XML_Expect(xml, e, XML_CHARS, NULL) != 0) |
if((e->type == XML_START) && |
|
(e->data.namespaceId == MI_T('a')) && |
|
(Tcscmp(PAL_T("EndpointReference"), e->data.data) == 0)) |
|
{ |
|
if (XML_Next(xml, e) != 0) |
|
{ |
|
XML_Raise(xml, WSMAN_ERROR_BAD_EPR_IN_SELECTOR); |
RETURN(-1); | RETURN(-1); |
|
} |
| |
PRINTF(("a:Selector:namespace{%s}\n", e->data)); |
selectorIsReference = MI_TRUE; |
|
} |
|
else if(e->type != XML_CHARS) |
|
{ |
|
XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR); |
|
RETURN(-1); |
|
} |
| |
/* allocate batch and instance if needed */ | /* allocate batch and instance if needed */ |
if (!(*instance)) | if (!(*instance)) |
{ | { |
MI_Result r; | MI_Result r; |
MI_Char* cn; |
TChar* cn; |
| |
/* verify that we already received classname */ | /* verify that we already received classname */ |
if (!classname) |
if (!(*classname)) |
{ | { |
XML_Raise(xml, "class-name was not found during selector parsing"); |
XML_Raise( |
|
xml, |
|
WSMAN_ERROR_NO_CLASS_NAME_IN_SELECTOR); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
|
|
if (!(*batch)) | if (!(*batch)) |
RETURN(-1); | RETURN(-1); |
| |
cn = Batch_Strdup2(*batch, classname); |
cn = Batch_Tcsdup(*batch, *classname); |
|
if (!cn) |
|
RETURN(-1); |
| |
r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch); | r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch); |
|
|
if (MI_RESULT_OK != r) | if (MI_RESULT_OK != r) |
RETURN(-1); | RETURN(-1); |
} | } |
| |
/* add next property to the instance */ | /* add next property to the instance */ |
{ | { |
const MI_Char* wpropName = Batch_Strdup2(*batch, propName); |
const TChar* wpropName; |
MI_Result r; | MI_Result r; |
MI_Value value; | MI_Value value; |
| |
value.string = Batch_Strdup2(*batch, e->data); |
if (!(*batch)) |
|
{ |
|
*batch = Batch_New(BATCH_MAX_PAGES); |
|
|
|
if (!(*batch)) |
|
RETURN(-1); |
|
} |
|
|
|
wpropName = Batch_Tcsdup(*batch, propName); |
|
if (!wpropName) |
|
RETURN(-1); |
|
|
|
if(selectorIsReference) |
|
{ |
|
value.instance = 0; |
|
if (0 != _GetReference(xml, e, *batch, &(value.instance))) |
|
RETURN(-1); |
|
} |
|
else |
|
{ |
|
value.string = Batch_Tcsdup(*batch, e->data.data); |
|
if (!value.string) |
|
RETURN(-1); |
|
} |
| |
// Set the property. | // Set the property. |
r = MI_Instance_AddElement(*instance, wpropName, &value, | r = MI_Instance_AddElement(*instance, wpropName, &value, |
MI_STRING, MI_FLAG_BORROW | MI_FLAG_KEY); |
(selectorIsReference ? MI_REFERENCE : MI_STRING), MI_FLAG_BORROW | MI_FLAG_KEY); |
| |
if (MI_RESULT_OK != r) | if (MI_RESULT_OK != r) |
RETURN(-1); | RETURN(-1); |
} | } |
} | } |
|
} |
else | else |
continue; | continue; |
| |
if (XML_Expect(xml, e, XML_END, "w:Selector") != 0) |
if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Selector")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
break; | break; |
|
|
{ | { |
XML_Elem e; | XML_Elem e; |
| |
if (XML_Expect(xml, &e, XML_START, "w:Selector") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Selector")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* iterate through all selector tags */ | /* iterate through all selector tags */ |
|
|
xml, | xml, |
&e, | &e, |
&wsheader->rqtNamespace, | &wsheader->rqtNamespace, |
wsheader->rqtClassname, |
&wsheader->rqtClassname, |
&wsheader->instance, | &wsheader->instance, |
&wsheader->instanceBatch)) | &wsheader->instanceBatch)) |
RETURN(-1); | RETURN(-1); |
|
|
} | } |
| |
static int _GetReferenceParameters( | static int _GetReferenceParameters( |
XML* xml, |
_In_ XML* xml, |
Batch* dynamicBatch, |
_In_ Batch* dynamicBatch, |
MI_Instance** dynamicInstanceParams) |
_Inout_ MI_Instance** dynamicInstanceParams) |
{ | { |
XML_Elem e; | XML_Elem e; |
const char* classname = 0; |
const TChar* classname = NULL; |
const char* nameSpace = NULL; |
const TChar* nameSpace = NULL; |
| |
/* extract ResourceURI and SelectorSet */ | /* extract ResourceURI and SelectorSet */ |
for (;;) | for (;;) |
|
|
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
|
if (e.type == XML_CHARS) |
|
{ |
|
continue; |
|
} |
|
|
if (XML_END == e.type) | if (XML_END == e.type) |
break; | break; |
| |
if (0 == strcmp("w:ResourceURI", e.data)) |
if (PAL_T('w') == e.data.namespaceId && |
|
0 == Tcscmp(PAL_T("ResourceURI"), e.data.data)) |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
if (XML_StripWhitespace(&e) != 0) |
RETURN(-1); | RETURN(-1); |
|
classname = Tcsrchr(e.data.data, '/'); |
| |
classname = strrchr(e.data, '/'); |
|
/* skip '/' */ | /* skip '/' */ |
if (classname) | if (classname) |
classname++; | classname++; |
| |
if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
continue; | continue; |
} | } |
| |
if (0 == strcmp("w:SelectorSet", e.data)) |
if (PAL_T('w') == e.data.namespaceId && |
|
0 == Tcscmp(PAL_T("SelectorSet"), e.data.data)) |
{ | { |
/* Allocate an instance */ | /* Allocate an instance */ |
if (!*dynamicInstanceParams) | if (!*dynamicInstanceParams) |
{ | { |
MI_Result r; | MI_Result r; |
const MI_Char* cn; |
const TChar* cn; |
| |
if (!classname) | if (!classname) |
{ | { |
XML_Raise(xml, "ResourceURI tag expected"); |
XML_Raise(xml, WSMAN_ERROR_NO_RESOURCE_URI); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
cn = Batch_Strdup2(dynamicBatch, classname); |
cn = Batch_Tcsdup(dynamicBatch, classname); |
|
if (!cn) |
|
{ |
|
XML_Raise(xml, WSMAN_ERROR_OUTOFMEMORY); |
|
RETURN(-1); |
|
} |
| |
r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch); | r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch); |
if (MI_RESULT_OK != r) | if (MI_RESULT_OK != r) |
|
|
/* iterate through all selector tags */ | /* iterate through all selector tags */ |
for (;;) | for (;;) |
{ | { |
const char* ns = NULL; |
const TChar* ns = NULL; |
|
const TChar* cn = NULL; |
| |
if (_GetSelector( | if (_GetSelector( |
xml, | xml, |
&e, | &e, |
&ns, | &ns, |
classname, |
&cn, |
dynamicInstanceParams, | dynamicInstanceParams, |
&dynamicBatch) != 0) | &dynamicBatch) != 0) |
{ | { |
|
|
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
|
if (e.type == XML_CHARS) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
} |
if (XML_END == e.type) | if (XML_END == e.type) |
break; | break; |
| |
|
|
/* extract all parameters */ | /* extract all parameters */ |
for (;;) | for (;;) |
{ | { |
if (0 != strcmp("a:ReferenceParameters", e.data)) |
if (e.data.namespaceId != MI_T('a') || |
|
0 != Tcscmp(PAL_T("ReferenceParameters"), e.data.data)) |
{ | { |
if (XML_Skip(xml) != 0) | if (XML_Skip(xml) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
|
if (e.type == XML_CHARS) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
continue; |
|
} |
if (e.type == XML_END) | if (e.type == XML_END) |
break; | break; |
| |
|
|
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
|
if (e.type == XML_CHARS) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
} |
if (e.type == XML_END) | if (e.type == XML_END) |
break; | break; |
} | } |
|
|
return 0; | return 0; |
} | } |
| |
|
/* |
|
**============================================================================== |
|
** |
|
** _GetSingleProperty() |
|
** |
|
** This function gets a instance property. The caller has already counsumed |
|
** the start property element. This function reads the value and the |
|
** closing property element. |
|
** |
|
**============================================================================== |
|
*/ |
|
|
static int _GetSingleProperty( | static int _GetSingleProperty( |
XML* xml, | XML* xml, |
|
XML_Elem* start, |
Batch* dynamicBatch, | Batch* dynamicBatch, |
const char* propNameChar, |
MI_Char nsId, |
|
const TChar* propNameChar, |
MI_Value* value, | MI_Value* value, |
MI_Type* type) |
MI_Type* type, |
|
MI_Boolean* null) |
{ | { |
XML_Elem e; | XML_Elem e; |
| |
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (e.type == XML_CHARS) |
while(1) |
|
{ |
|
if (e.type == XML_END) |
|
{ |
|
if (nsId != e.data.namespaceId || |
|
Tcscmp(propNameChar, e.data.data) != 0) |
|
{ |
|
trace_OpenCloseMismatch(tcs(propNameChar), tcs(e.data.data)); |
|
RETURN(-1); |
|
} |
|
|
|
/* Check whether this attribute is null or just empty */ |
|
{ |
|
const TChar* p = XML_Elem_GetAttr(&e, PAL_T('x'), PAL_T("nil")); |
|
|
|
if (p && Tcscmp(p, PAL_T("true")) == 0) |
|
{ |
|
*null = MI_TRUE; |
|
} |
|
else |
|
{ |
|
*null = MI_FALSE; |
|
*type = MI_STRING; |
|
value->string = PAL_T(""); |
|
} |
|
} |
|
|
|
return 0; |
|
} |
|
else if (e.type == XML_CHARS) |
|
{ |
|
XML_Elem tmpElem; |
|
|
|
/* Check to make sure there isn't a start element next */ |
|
if (XML_Next(xml, &tmpElem) != 0) |
|
{ |
|
RETURN(-1); |
|
} |
|
if (tmpElem.type == XML_START) |
{ | { |
|
/* This means we have text and a child element. Use the child element for now */ |
|
e = tmpElem; |
|
continue; |
|
} |
|
if (XML_PutBack(xml, &tmpElem) != 0) |
|
{ |
|
RETURN(-1); |
|
} |
|
|
/* Plain string property */ | /* Plain string property */ |
value->string = Batch_Strdup2(dynamicBatch, e.data); |
value->string = Batch_Tcsdup(dynamicBatch, e.data.data); |
|
if (!value->string) |
|
RETURN(-1); |
*type = MI_STRING; | *type = MI_STRING; |
| |
if (XML_Expect(xml, &e, XML_END, propNameChar) != 0) |
if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0) |
RETURN(-1); | RETURN(-1); |
|
|
|
*null = MI_FALSE; |
|
return 0; |
} | } |
else if ('a' == e.data[0]) |
else if ('a' == e.data.namespaceId) |
{ | { |
/* Reference as </adddress></ReferenceParameters>*/ | /* Reference as </adddress></ReferenceParameters>*/ |
value->instance = 0; | value->instance = 0; |
|
|
RETURN(-1); | RETURN(-1); |
| |
*type = MI_REFERENCE; | *type = MI_REFERENCE; |
|
*null = MI_FALSE; |
|
return 0; |
} | } |
else | else |
{ | { |
/* Embedded instance */ |
if (e.type == XML_START) |
value->instance = 0; |
{ |
if (0 != _GetInstance(xml, &e, dynamicBatch, &value->instance)) |
if (Tcscasecmp(e.data.data, PAL_T("CIM_DateTime")) == 0) |
|
{ |
|
/* DateTime property XML*/ |
|
/* <p0:datetimeProperty xsi:type="cim:cimDateTime"> */ |
|
/* <CIM_DateTime>19990929195959.000000-420</CIM_DateTime> */ |
|
/* </p0:datetimeProperty> */ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
if (e.type == XML_CHARS) |
|
{ |
|
value->string = Batch_Tcsdup(dynamicBatch, e.data.data); |
|
if (!value->string) |
|
RETURN(-1); |
|
*type = MI_STRING; |
|
} |
|
else |
RETURN(-1); | RETURN(-1); |
| |
*type = MI_INSTANCE; |
if (XML_Expect(xml, &e, XML_END, 0, PAL_T("CIM_DateTime")) != 0) |
|
RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, propNameChar) != 0) |
if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0) |
RETURN(-1); | RETURN(-1); |
|
|
|
*null = MI_FALSE; |
|
return 0; |
|
} |
} | } |
|
/* Embedded instance */ |
|
value->instance = 0; |
|
XML_PutBack(xml, &e); |
|
|
|
if (0 != _GetInstance(xml, start, dynamicBatch, &value->instance)) |
|
RETURN(-1); |
|
|
| |
|
*type = MI_INSTANCE; |
| |
|
*null = MI_FALSE; |
return 0; | return 0; |
} | } |
|
} |
|
} |
| |
static int _AddValueToArray( | static int _AddValueToArray( |
Batch* dynamicBatch, | Batch* dynamicBatch, |
|
|
MI_Instance** dynamicInstanceParams) | MI_Instance** dynamicInstanceParams) |
{ | { |
XML_Elem e; | XML_Elem e; |
const MI_Char* propNameA = 0; |
const TChar* propNameA = 0; |
MI_Value valueA; | MI_Value valueA; |
MI_Type typeA = MI_BOOLEAN; | MI_Type typeA = MI_BOOLEAN; |
const MI_Char* propNamePrev = 0; |
const TChar* propNamePrev = 0; |
MI_Value valuePrev; | MI_Value valuePrev; |
MI_Type typePrev = MI_BOOLEAN; | MI_Type typePrev = MI_BOOLEAN; |
| |
|
|
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (e.type == XML_END) |
/* Look for closing instance element */ |
|
|
|
if (e.type == XML_END && Tcscmp(e.data.data, start->data.data) == 0) |
|
{ |
break; | break; |
|
} |
| |
/* skip possible comments */ | /* skip possible comments */ |
if (e.type != XML_START) | if (e.type != XML_START) |
|
|
if (!*dynamicInstanceParams) | if (!*dynamicInstanceParams) |
{ | { |
MI_Result r; | MI_Result r; |
const MI_Char* cn = Batch_Strdup2(dynamicBatch, start->data + 2); |
TChar* cn = NULL; |
|
|
|
// We are trying to parse an Instance, The type of the instance may be specified |
|
// as a attribute Type or it is same as the element name. We'll attempt to get the |
|
// type from attribute ... if not we'll use the element name. |
|
// TODO: At this time we don't have the NS support in the XML parser, so using hardcoded |
|
// 'xsi:type (good for windows client) once we get the NS support this code should be |
|
// updated. |
|
const TChar* typeName = XML_Elem_GetAttr(start, PAL_T('x'), PAL_T("type")); |
|
|
|
if(typeName) |
|
{ |
|
TChar* typeStart; |
|
cn = Batch_Tcsdup(dynamicBatch, typeName); |
|
|
|
if (!cn) |
|
{ |
|
trace_BatchTcsDup_Failed(); |
|
RETURN(-1); |
|
} |
|
|
|
// Trim the _Type from the name. |
|
typeStart = Tcsrchr(cn, '_'); |
|
if( typeStart ) |
|
{ |
|
*typeStart = PAL_T('\0'); |
|
|
|
/* trim namespace start too */ |
|
{ |
|
TChar* afterColon; |
|
afterColon = Tcschr(cn, PAL_T(':')); |
|
if (afterColon) |
|
{ |
|
afterColon++; |
|
cn = afterColon; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
trace_XsiTypeInvalidValue( cn ); |
|
RETURN(-1); |
|
// cn is allocated on the batch, so it will be release along with it anyway |
|
} |
|
} |
|
else |
|
{ |
|
cn = Batch_Tcsdup(dynamicBatch, start->data.data); |
|
if (!cn) |
|
{ |
|
trace_BatchTcsDup_Failed(); |
|
RETURN(-1); |
|
} |
|
} |
|
|
|
r = Instance_NewDynamic( |
|
dynamicInstanceParams, |
|
cn, |
|
MI_FLAG_CLASS, |
|
dynamicBatch); |
| |
r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch); |
|
if (MI_RESULT_OK != r) | if (MI_RESULT_OK != r) |
RETURN(-1); | RETURN(-1); |
} | } |
| |
/* add next property to the instance */ | /* add next property to the instance */ |
if (e.size > 2) /* ?:<name> */ |
if (e.data.size > 0) /* element name should have some data in it */ |
{ | { |
MI_Result r; | MI_Result r; |
MI_Value value; | MI_Value value; |
MI_Type type = MI_BOOLEAN; | MI_Type type = MI_BOOLEAN; |
const char* propNameChar; |
const TChar* propNameChar; |
const MI_Char* propName; |
const TChar* propName; |
|
MI_Boolean null; |
| |
propNameChar = e.data; |
propNameChar = e.data.data; |
| |
/* Position propName one beyond ':' character */ | /* Position propName one beyond ':' character */ |
{ |
propName = Batch_Tcsdup(dynamicBatch, propNameChar); |
const MI_Char* p = strchr(propNameChar, ':'); |
|
| |
if (!p) |
if (!propName) |
|
{ |
|
trace_BatchTcsDup_Failed(); |
RETURN(-1); | RETURN(-1); |
|
|
propName = Batch_Strdup2(dynamicBatch, p + 1); |
|
} | } |
| |
type = MI_BOOLEAN; | type = MI_BOOLEAN; |
| |
if (0 != _GetSingleProperty(xml, dynamicBatch, propNameChar, &value, &type)) |
if (_GetSingleProperty( |
|
xml, |
|
&e, |
|
dynamicBatch, |
|
e.data.namespaceId, |
|
propNameChar, |
|
&value, |
|
&type, |
|
&null) != 0) |
|
{ |
|
trace_GetSingleProperty_Failed( tcs(propNameChar) ); |
RETURN(-1); | RETURN(-1); |
|
} |
|
|
|
if (null) |
|
{ |
|
/* Skip null attributes */ |
|
continue; |
|
} |
| |
/* Did we collect array's items? */ | /* Did we collect array's items? */ |
if (propNameA) | if (propNameA) |
{ | { |
/* if we have array and new property matches array - add new item to the array */ | /* if we have array and new property matches array - add new item to the array */ |
if (0 == Zcmp(propNameA, propName)) |
if (0 == Tcscmp(propNameA, propName)) |
{ | { |
if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type)) | if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type)) |
RETURN(-1); | RETURN(-1); |
|
|
else if (propNamePrev) | else if (propNamePrev) |
{ | { |
/* Check if name is the same and we need to create an array */ | /* Check if name is the same and we need to create an array */ |
if (0 == Zcmp(propNamePrev, propName)) |
if (0 == Tcscmp(propNamePrev, propName)) |
{ | { |
/* create array */ | /* create array */ |
valueA.array.size = 0; | valueA.array.size = 0; |
|
|
} | } |
else | else |
{ | { |
r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, |
r = MI_Instance_AddElement( |
typePrev, MI_FLAG_BORROW); |
*dynamicInstanceParams, |
|
propNamePrev, |
|
&valuePrev, |
|
typePrev, |
|
MI_FLAG_BORROW); |
| |
/* Note that the MI_RESULT_ALREADY_EXISTS error is okay | /* Note that the MI_RESULT_ALREADY_EXISTS error is okay |
* for key properties added when the selector set was | * for key properties added when the selector set was |
|
|
r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, | r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, |
typePrev, MI_FLAG_BORROW); | typePrev, MI_FLAG_BORROW); |
| |
if (MI_RESULT_OK != r) |
/* Note that the MI_RESULT_ALREADY_EXISTS error is okay |
|
* for key properties added when the selector set was |
|
* parsed earlier. |
|
*/ |
|
if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS) |
|
{ |
RETURN(-1); | RETURN(-1); |
} | } |
|
} |
| |
/* check closing tag */ | /* check closing tag */ |
if (strcmp(e.data, start->data) != 0) |
if (Tcscmp(e.data.data, start->data.data) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
| |
int WS_ParseWSHeader( | int WS_ParseWSHeader( |
XML* xml, | XML* xml, |
WSMAN_WSHeader* wsheader) |
WSMAN_WSHeader* wsheader, |
|
UserAgent userAgent) |
{ | { |
XML_Elem e; | XML_Elem e; |
| |
|
if (wsheader->instanceBatch) |
|
{ |
|
Batch_Delete(wsheader->instanceBatch); |
|
} |
memset(wsheader, 0, sizeof(WSMAN_WSHeader)); | memset(wsheader, 0, sizeof(WSMAN_WSHeader)); |
| |
|
// WinRM client assumes that ClassOrigin is true by default on the server |
|
// by standards, a wsman option is false by default so in non-WinRM case, |
|
// the includeClassOrigin and all others are set to 0 |
|
wsheader->includeClassOrigin = (userAgent == USERAGENT_WINRM) ? 1 : 0; |
|
wsheader->includeInheritanceHierarchy = 0; |
|
wsheader->includeInheritedElements = 0; |
|
wsheader->includeQualifiers = 0; |
|
|
/* Expect <s:Header> */ | /* Expect <s:Header> */ |
if (XML_Expect(xml, &e, XML_START, "s:Header") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Header")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
for (;;) | for (;;) |
|
|
| |
if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0) | if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0) |
{ | { |
int tag = HashStr(e.data, e.size); |
int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (WSMANTAG_HEADER != tag) | if (WSMANTAG_HEADER != tag) |
{ | { |
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data )); |
trace_Wsman_UnexpectedCloseTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
//printf("DONE\n"); | //printf("DONE\n"); |
|
|
if (e.type != XML_START) | if (e.type != XML_START) |
continue; | continue; |
| |
switch (HashStr(e.data, e.size)) |
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
{ | { |
case WSMANTAG_TO: | case WSMANTAG_TO: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
PRINTF(("a:To{%s}\n", e.data)); |
if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("To")) != 0) |
|
|
if (XML_Expect(xml, &e, XML_END, "a:To") != 0) |
|
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
| |
case WSMANTAG_RESOURCE_URI: | case WSMANTAG_RESOURCE_URI: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
int resourceUriHash = 0; |
|
|
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
PRINTF(("w:ResourceURI{%s}\n", e.data)); |
if (XML_StripWhitespace(&e) != 0) |
wsheader->rqtClassname = strrchr(e.data, '/'); |
RETURN(-1); |
|
|
|
wsheader->schemaRequestType = NOT_A_SCHEMA_REQUEST; |
|
|
|
resourceUriHash = HashStr(0, e.data.data, e.data.size); |
|
|
|
if(resourceUriHash == WSMAN_RESOURCE_URI_CIM_XML_SCHEMA) |
|
{ |
|
wsheader->schemaRequestType = CIM_XML_SCHEMA_REQUEST; |
|
} |
|
else if(resourceUriHash == WSMAN_RESOURCE_URI_WS_CIM_SCHEMA) |
|
{ |
|
wsheader->schemaRequestType = WS_CIM_SCHEMA_REQEUST; |
|
} |
|
|
|
wsheader->rqtClassname = Tcsrchr(e.data.data, '/'); |
/* skip '/' */ | /* skip '/' */ |
if (wsheader->rqtClassname) | if (wsheader->rqtClassname) |
wsheader->rqtClassname++; | wsheader->rqtClassname++; |
| |
if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
| |
case WSMANTAG_REPLY_TO: | case WSMANTAG_REPLY_TO: |
{ | { |
if (XML_Expect(xml, &e, XML_START, "a:Address") != 0) |
while (1) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
/* skip whitespace and comments */ |
|
if (e.type == XML_START) |
|
break; |
|
} |
|
if (HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_ADDRESS) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, "a:Address") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Address")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, "a:ReplyTo") != 0) |
while (1) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
/* skip whitespace and comments */ |
|
if (e.type == XML_END) |
|
break; |
|
} |
|
if (e.type != XML_END && HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_REPLY_TO) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
{ | { |
wsheader->foundAction = MI_TRUE; | wsheader->foundAction = MI_TRUE; |
| |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsheader->rqtAction = HashStr(e.data, e.size); |
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
wsheader->rqtAction = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (0 == wsheader->rqtAction) | if (0 == wsheader->rqtAction) |
{ | { |
char* s; |
TChar* s; |
/* DSP0226; 9: Custom Actions (Methods) just need to have unique URI. | /* 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> */ | 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)) |
if (0 != Tcsncmp(e.data.data, PAL_T("http://"), 7)) |
RETURN(-1); | RETURN(-1); |
| |
wsheader->rqtServer = e.data + 7; |
wsheader->rqtServer = e.data.data + 7; |
| |
s = strchr(wsheader->rqtServer, '/'); |
s = Tcschr(wsheader->rqtServer, '/'); |
| |
if (!s) | if (!s) |
RETURN(-1); | RETURN(-1); |
|
|
*s = 0; | *s = 0; |
s++; | s++; |
| |
if (0 != strncmp(s, "wbem/wscim/1/cim-schema/2/", 26)) |
if (0 != Tcsncmp(s, PAL_T("wbem/wscim/1/cim-schema/2/"), 26)) |
RETURN(-1); | RETURN(-1); |
| |
s += 26; | s += 26; |
| |
wsheader->rqtClassname = s; | wsheader->rqtClassname = s; |
s = strchr(s, '/'); |
s = Tcschr(s, '/'); |
| |
if (!s) | if (!s) |
RETURN(-1); | RETURN(-1); |
|
|
wsheader->rqtMethod = s; | wsheader->rqtMethod = s; |
} | } |
| |
if (XML_Expect(xml, &e, XML_END, "a:Action") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Action")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
} | } |
break; | break; |
| |
case WSMANTAG_MESSAGE_ID: |
case WSMANTAG_OPTION_SET: |
|
{ |
|
if (_GetOptionSet(xml, wsheader) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_MESSAGE_ID: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
wsheader->rqtMessageID = e.data.data; |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("MessageID")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_MAX_ENVELOPE_SIZE: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
wsheader->maxEnvelopeSize = (MI_Uint32)Tcstoull( |
|
e.data.data, NULL, 10); |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxEnvelopeSize")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
#ifndef DISABLE_INDICATION |
|
case WSMANTAG_OPERATION_TIMEOUT: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
/* Expect an xs:duration of form: PnYnMnDTnHnMnS */ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_StripWhitespace(&e) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsheader->rqtMessageID = e.data; |
if (-1 == ParseWSManDatetime( e.data.data, &wsheader->operationTimeout.value ) ) |
|
RETURN(-1); |
|
|
|
wsheader->operationTimeout.exists = MI_TRUE; |
| |
if (XML_Expect(xml, &e, XML_END, "a:MessageID") != 0) |
if (XML_Expect(xml, &e, XML_END, MI_T('w'), MI_T("OperationTimeout")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
| |
case WSMANTAG_MAX_ENVELOPE_SIZE: |
case WSMANTAG_SUBSCRIBE_IDENTIFIER: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
/* For unsubscribe, parse subscribe identifier from header */ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsheader->maxEnvelopeSize = (MI_Uint32)Strtoull(e.data, NULL, 10); |
wsheader->contextID = (MI_Uint32)Tcstoull(e.data.data, NULL, 10); |
PRINTF(("maxEnvelopeSize{%d}\n", wsheader->maxEnvelopeSize)); |
trace_WsmanUnsubscribe( wsheader->contextID ); |
| |
if (XML_Expect(xml, &e, XML_END, "w:MaxEnvelopeSize") != 0) |
if (XML_Expect(xml, &e, XML_END, MI_T('e'), MI_T("Identifier")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
#endif /* ifndef DISABLE_INDICATION */ |
| |
default: | default: |
{ | { |
if (_MustUnderstandCanBeIgnored(&e) != 0) | if (_MustUnderstandCanBeIgnored(&e) != 0) |
{ | { |
wsheader->unknownMandatoryTag = e.data; |
wsheader->unknownMandatoryTag = e.data.data; |
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", |
trace_Wsman_UnknownMandatoryTag(tcs(e.data.data)); |
e.data )); |
|
/* validate header will send correct repsonse to the client */ | /* validate header will send correct repsonse to the client */ |
} | } |
| |
|
|
| |
} | } |
} | } |
|
/* DMTF standard requires default namespace to be used */ |
|
/* if _cimnamespace selector is not specified as part of request */ |
|
if (!wsheader->rqtNamespace) |
|
wsheader->rqtNamespace = DEFAULT_CIMNAMESPACE; |
return 0; | return 0; |
} | } |
| |
|
|
{ | { |
if (XML_Next(xml, &e) != 0) | if (XML_Next(xml, &e) != 0) |
{ | { |
XML_Raise(xml, "missing root element"); |
XML_Raise(xml, XML_ERROR_ELEMENT_EXPECTED); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
|
|
} | } |
| |
/* Expect <s:Envelope> */ | /* Expect <s:Envelope> */ |
if (XML_Expect(xml, &e, XML_START, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
} | } |
| |
static const char* _ExpectCharsAndEnd( |
static const TChar* _ExpectCharsAndEnd( |
XML* xml, | XML* xml, |
const char* name) |
TChar nsId, |
|
const TChar* name) |
{ | { |
XML_Elem e; | XML_Elem e; |
const char* chars; |
const TChar* chars; |
| |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
return NULL; | return NULL; |
| |
chars = e.data; |
chars = e.data.data; |
| |
if (XML_Expect(xml, &e, XML_END, name) != 0) |
if (XML_Expect(xml, &e, XML_END, nsId, name) != 0) |
return NULL; | return NULL; |
| |
return chars; | return chars; |
|
|
| |
/* Handle "Object" tag */ | /* Handle "Object" tag */ |
| |
if (strcmp(e.data, "a:ReferenceParameters") == 0) |
if (PAL_T('a') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("ReferenceParameters")) == 0) |
{ | { |
if (_GetReferenceParameters( | if (_GetReferenceParameters( |
xml, | xml, |
|
|
RETURN(-1); | RETURN(-1); |
} | } |
} | } |
else if (strcmp(e.data, "a:Address") == 0) |
else if (PAL_T('a') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("Address")) == 0) |
{ | { |
filter->address = _ExpectCharsAndEnd(xml, "a:Address"); |
filter->address = _ExpectCharsAndEnd(xml, PAL_T('a'), PAL_T("Address")); |
| |
if (!filter->address) | if (!filter->address) |
RETURN(-1); | RETURN(-1); |
|
|
| |
/* Expect </Object> */ | /* Expect </Object> */ |
| |
if (XML_Expect(xml, &e, XML_END, "b:Object") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("Object")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
| |
/* Expect <AssociatedInstances> */ | /* Expect <AssociatedInstances> */ |
| |
if (XML_Expect(xml, &e, XML_START, "b:AssociatedInstances") != 0) |
if (XML_Next(xml, &e) != 0 || e.type != XML_START ) |
|
{ |
|
RETURN(-1); |
|
} |
|
|
|
if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("AssociatedInstances")) == 0) |
|
{ |
|
filter->isAssosiatorOperation = MI_TRUE; |
|
} |
|
else if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("AssociationInstances")) == 0) |
|
{ |
|
filter->isAssosiatorOperation = MI_FALSE; |
|
} |
|
else |
RETURN(-1); | RETURN(-1); |
| |
/* Parse child elements */ | /* Parse child elements */ |
|
|
| |
/* Handle "Object" tag */ | /* Handle "Object" tag */ |
| |
if (strcmp(e.data, "b:Object") == 0) |
if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("Object")) == 0) |
{ | { |
if (_ParseAssociationFilterObject(xml, batch, filter) != 0) | if (_ParseAssociationFilterObject(xml, batch, filter) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
else if (strcmp(e.data, "b:AssociationClassName") == 0) |
else if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("AssociationClassName")) == 0) |
{ | { |
filter->associationClassName = _ExpectCharsAndEnd( | filter->associationClassName = _ExpectCharsAndEnd( |
xml, "b:AssociationClassName"); |
xml, PAL_T('b'), PAL_T("AssociationClassName")); |
| |
if (!filter->associationClassName) | if (!filter->associationClassName) |
RETURN(-1); | RETURN(-1); |
} | } |
else if (strcmp(e.data, "b:Role") == 0) |
else if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("Role")) == 0) |
{ | { |
filter->role = _ExpectCharsAndEnd(xml, "b:Role"); |
filter->role = _ExpectCharsAndEnd(xml, PAL_T('b'), PAL_T("Role")); |
| |
if (!filter->role) | if (!filter->role) |
RETURN(-1); | RETURN(-1); |
} | } |
else if (strcmp(e.data, "b:ResultClassName") == 0) |
else if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("ResultClassName")) == 0) |
{ | { |
filter->resultClassName = _ExpectCharsAndEnd( | filter->resultClassName = _ExpectCharsAndEnd( |
xml, | xml, |
"b:ResultClassName"); |
PAL_T('b'), |
|
PAL_T("ResultClassName")); |
| |
if (!filter->resultClassName) | if (!filter->resultClassName) |
RETURN(-1); | RETURN(-1); |
} | } |
else if (strcmp(e.data, "b:ResultRole") == 0) |
else if (PAL_T('b') == e.data.namespaceId && |
|
Tcscmp(e.data.data, PAL_T("ResultRole")) == 0) |
{ | { |
filter->resultRole = _ExpectCharsAndEnd( | filter->resultRole = _ExpectCharsAndEnd( |
xml, | xml, |
"b:ResultRole"); |
PAL_T('b'), |
|
PAL_T("ResultRole")); |
| |
if (!filter->resultRole) | if (!filter->resultRole) |
RETURN(-1); | RETURN(-1); |
|
|
} | } |
} | } |
| |
#if 0 |
if(filter->isAssosiatorOperation == MI_TRUE) |
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> */ | /* Expect </AssociatedInstances> */ |
|
if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociatedInstances")) != 0) |
if (XML_Expect(xml, &e, XML_END, "b:AssociatedInstances") != 0) |
RETURN(-1); |
|
} |
|
else |
|
{ |
|
/* Expect </AssociationInstances> */ |
|
if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociationInstances")) != 0) |
RETURN(-1); | RETURN(-1); |
|
} |
| |
return 0; | return 0; |
} | } |
| |
|
/* Parse query dialect */ |
|
static const ZChar* _WS_ParseDialect( |
|
_In_z_ const ZChar* dialect, |
|
MI_Boolean isSubscribe) |
|
{ |
|
/* See DSP0202.pdf */ |
|
if (Tcscasecmp(ZT("http://schemas.dmtf.org/wbem/cql/1/dsp0202.pdf"), dialect) == 0) |
|
return MI_QUERY_DIALECT_CQL; |
|
|
|
if (Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/WQL"), dialect) == 0) |
|
return MI_QUERY_DIALECT_WQL; |
|
|
|
/* Event stream dialect is not supported yet */ |
|
/* if (isSubscribe && Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/MINT"), dialect) == 0) |
|
return QUERY_LANGUAGE_EVENTSTREAM; */ |
|
|
|
if (isSubscribe) |
|
return dialect; |
|
|
|
return NULL; |
|
} |
|
|
int WS_ParseEnumerateBody( | int WS_ParseEnumerateBody( |
XML* xml, | XML* xml, |
Batch** batch, | Batch** batch, |
|
|
} | } |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect <n:Enumerate> */ | /* Expect <n:Enumerate> */ |
if (XML_Expect(xml, &e, XML_START, "n:Enumerate") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Enumerate")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
for (;;) | for (;;) |
|
|
| |
if (e.type == XML_END) | if (e.type == XML_END) |
{ | { |
int tag = HashStr(e.data, e.size); |
int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (WSMANTAG_ENUM_ENUMERATE != tag) | if (WSMANTAG_ENUM_ENUMERATE != tag) |
{ | { |
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data )); |
trace_Wsman_UnexpectedCloseTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
if (e.type != XML_START) | if (e.type != XML_START) |
continue; | continue; |
| |
switch (HashStr(e.data, e.size)) |
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
{ | { |
case WSMANTAG_ENUM_MAX_ELEMENTS: | case WSMANTAG_ENUM_MAX_ELEMENTS: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10); |
wsenumbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10); |
PRINTF(("maxElements{%d}\n", wsenumbody->maxElements)); |
|
| |
if (XML_Expect(xml, &e, XML_END, "w:MaxElements") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxElements")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
| |
case WSMANTAG_ENUM_POLYMORPHISM_MODE: | case WSMANTAG_ENUM_POLYMORPHISM_MODE: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumbody->polymorphismMode = HashStr(e.data, e.size); |
wsenumbody->polymorphismMode = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (XML_Expect(xml, &e, XML_END, "b:PolymorphismMode") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("PolymorphismMode")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
| |
case WSMANTAG_ENUM_MODE: | case WSMANTAG_ENUM_MODE: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumbody->enumerationMode = HashStr(e.data, e.size); |
wsenumbody->enumerationMode = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (XML_Expect(xml, &e, XML_END, "w:EnumerationMode") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("EnumerationMode")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
*/ | */ |
case WSMANTAG_ENUM_FILTER: | case WSMANTAG_ENUM_FILTER: |
{ | { |
const char* dialect; |
const TChar* dialect; |
const char* p; |
|
| |
/* Get 'Dialect' attribute? */ | /* Get 'Dialect' attribute? */ |
dialect = XML_Elem_GetAttr(&e, "Dialect"); |
dialect = XML_Elem_GetAttr(&e, 0, PAL_T("Dialect")); |
if (!dialect) | if (!dialect) |
{ | { |
LOGW_CHAR(("wsman: Filter tag missing Dialect attribute")); |
trace_Wsman_FilterTagMissingDialectAttribute(); |
RETURN(-1); | 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 */ | /* Parse the association filter */ |
if (strcmp(dialect, URI_CIMBINDING "/associationFilter") == 0) |
if (Tcscasecmp(dialect, URI_CIMBINDING PAL_T("/associationFilter")) == 0) |
{ | { |
wsenumbody->foundAssociationFilter = MI_TRUE; |
wsenumbody->dialect = PAL_T("associationFilter"); |
|
wsenumbody->foundAssociationOperation = MI_TRUE; |
| |
if (_ParseAssociationFilter(xml, *batch, |
if (_ParseAssociationFilter(xml, *batch, &wsenumbody->associationFilter) != 0) |
&wsenumbody->associationFilter) != 0) |
|
{ | { |
RETURN(-1); | RETURN(-1); |
} | } |
} | } |
else | else |
{ | { |
|
/* Parse the dialect */ |
|
wsenumbody->dialect = _WS_ParseDialect(dialect, MI_FALSE); |
|
|
|
if (!wsenumbody->dialect) |
|
{ |
|
trace_WsmanEnum_UnknownDialect(tcs(dialect)); |
|
RETURN(-1); |
|
} |
|
|
/* Get the filter text */ | /* Get the filter text */ |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumbody->filter = e.data; |
wsenumbody->filter = e.data.data; |
} | } |
| |
/* Check for closing </w:Filter> tag */ | /* Check for closing </w:Filter> tag */ |
if (XML_Expect(xml, &e, XML_END, "w:Filter") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("Filter")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
{ | { |
if (_MustUnderstandCanBeIgnored(&e) != 0) | if (_MustUnderstandCanBeIgnored(&e) != 0) |
{ | { |
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data )); |
trace_Wsman_UnknownMandatoryTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
|
|
} | } |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect </s:Envelope> */ | /* Expect </s:Envelope> */ |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
*dynamicInstanceParams = 0; | *dynamicInstanceParams = 0; |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect <?:?> parameter's tag */ | /* Expect <?:?> parameter's tag */ |
|
|
| |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect </s:Envelope> */ | /* Expect </s:Envelope> */ |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
XML_Elem e; | XML_Elem e; |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect <?:?> parameter's tag */ | /* Expect <?:?> parameter's tag */ |
|
|
RETURN(-1); | RETURN(-1); |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect </s:Envelope> */ | /* Expect </s:Envelope> */ |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); | memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect <n:Enumerate> */ | /* Expect <n:Enumerate> */ |
if (XML_Expect(xml, &e, XML_START, "n:Pull") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Pull")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
for (;;) | for (;;) |
|
|
| |
if (e.type == XML_END) | if (e.type == XML_END) |
{ | { |
int tag = HashStr(e.data, e.size); |
int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (WSMANTAG_ENUM_PULL != tag) | if (WSMANTAG_ENUM_PULL != tag) |
{ | { |
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data )); |
trace_Wsman_UnexpectedCloseTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
if (e.type != XML_START) | if (e.type != XML_START) |
continue; | continue; |
| |
switch (HashStr(e.data, e.size)) |
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
{ | { |
case WSMANTAG_PULL_MAX_ELEMENTS: | case WSMANTAG_PULL_MAX_ELEMENTS: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
wsenumpullbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10); |
|
if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxElements")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_MAX_TIME: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (-1 == ParseWSManDatetime( e.data.data, &wsenumpullbody->maxTime.value ) ) |
|
RETURN(-1); |
|
|
|
wsenumpullbody->maxTime.exists = MI_TRUE; |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxTime")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_MAX_CHARACTERS: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumpullbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10); |
wsenumpullbody->maxCharacters.value = Tcstoull(e.data.data, NULL, 10); |
PRINTF(("maxElements{%d}\n", wsenumpullbody->maxElements)); |
wsenumpullbody->maxCharacters.exists = MI_TRUE; |
| |
if (XML_Expect(xml, &e, XML_END, "n:MaxElements") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxCharacters")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
| |
case WSMANTAG_PULL_ENUMERATION_CONTEXT: | case WSMANTAG_PULL_ENUMERATION_CONTEXT: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10); |
wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull( |
|
e.data.data, NULL, 10); |
| |
if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
{ | { |
if (_MustUnderstandCanBeIgnored(&e) != 0) | if (_MustUnderstandCanBeIgnored(&e) != 0) |
{ | { |
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data )); |
trace_Wsman_UnknownMandatoryTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
|
|
} | } |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect </s:Envelope> */ | /* Expect </s:Envelope> */ |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); | memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect <n:Release> */ | /* Expect <n:Release> */ |
if (XML_Expect(xml, &e, XML_START, "n:Release") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Release")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
for (;;) | for (;;) |
|
|
| |
if (e.type == XML_END) | if (e.type == XML_END) |
{ | { |
int tag = HashStr(e.data, e.size); |
int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
| |
if (WSMANTAG_ENUM_RELEASE != tag) | if (WSMANTAG_ENUM_RELEASE != tag) |
{ | { |
LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data )); |
trace_Wsman_UnexpectedCloseTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
if (e.type != XML_START) | if (e.type != XML_START) |
continue; | continue; |
| |
switch (HashStr(e.data, e.size)) |
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
{ | { |
case WSMANTAG_PULL_ENUMERATION_CONTEXT: | case WSMANTAG_PULL_ENUMERATION_CONTEXT: |
{ | { |
if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0) |
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
RETURN(-1); | RETURN(-1); |
| |
wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10); |
wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull( |
|
e.data.data, NULL, 10); |
| |
if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0) |
RETURN(-1); | RETURN(-1); |
} | } |
break; | break; |
|
|
{ | { |
if (_MustUnderstandCanBeIgnored(&e) != 0) | if (_MustUnderstandCanBeIgnored(&e) != 0) |
{ | { |
LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data )); |
trace_Wsman_UnknownMandatoryTag(tcs(e.data.data)); |
RETURN(-1); | RETURN(-1); |
} | } |
| |
|
|
} | } |
| |
/* Expect <s:Body> */ | /* Expect <s:Body> */ |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
/* Expect </s:Envelope> */ | /* Expect </s:Envelope> */ |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
|
|
{ | { |
XML_Elem e; | XML_Elem e; |
| |
if (XML_Expect(xml, &e, XML_START, "s:Body") != 0) |
if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_Expect(xml, &e, XML_START, PAL_T('i'), PAL_T("Identify")) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('i'), PAL_T("Identify")) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0) |
|
RETURN(-1); |
|
|
|
return 0; |
|
} |
|
|
|
|
|
#ifndef DISABLE_INDICATION |
|
|
|
typedef enum _SubscribeSequence |
|
{ |
|
SubscribeSequence_NONE = 0, |
|
SubscribeSequence_EXPIRES = 1, |
|
SubscribeSequence_FILTER = 2, |
|
SubscribeSequence_END = 3 |
|
} SubscribeSequence; |
|
|
|
/* Parse subscribe body, One example, |
|
<s:Body> |
|
<e:Subscribe> |
|
<e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/Pull"> |
|
<w:Heartbeats>PT60.000S</w:Heartbeats> |
|
<w:Locale xml:lang="en-US" s:mustUnderstand="false"/> |
|
<p:DataLocale xml:lang="en-US" s:mustUnderstand="false"/> |
|
<w:ContentEncoding>UTF-16</w:ContentEncoding> |
|
</e:Delivery> |
|
<e:Expires> |
|
"PT60.000S" |
|
</e:Expires> |
|
<w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL"> |
|
Select * from My_Alarm" |
|
</w:Filter> |
|
</e:Subscribe> |
|
</s:Body> |
|
*/ |
|
int WS_ParseSubscribeBody( |
|
XML* xml, |
|
WSMAN_WSEnumeratePullBody* wssubbody) |
|
{ |
|
XML_Elem e; |
|
SubscribeSequence sequenceState = SubscribeSequence_NONE; |
|
|
|
memset(wssubbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); |
|
|
|
/* Expect <s:Body> */ |
|
if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0) |
|
RETURN(-1); |
|
|
|
/* Expect <e:Subscribe> */ |
|
if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Subscribe")) != 0) |
|
RETURN(-1); |
|
|
|
/* A subscribe message body is made up of an xs:sequence of the following: |
|
* 1 - EndTo (Optional) |
|
* 2 - Delivery |
|
* 3 - Expires (Optional) |
|
* 4 - Filter (Optional) |
|
*/ |
|
|
|
/* Expect <e:Delivery> */ |
|
if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Delivery")) != 0) |
|
RETURN(-1); |
|
|
|
{ |
|
const XML_Char* mode = NULL; |
|
|
|
/* Read 'Mode' attribute */ |
|
mode = XML_Elem_GetAttr(&e, 0, ZT("Mode")); |
|
if (mode) |
|
{ |
|
int tag = HashStr( 0, mode, Tcslen(mode)); |
|
if (WSMAN_DELIVERY_MODE_PULL != tag) |
|
{ |
|
trace_Wsman_UnsupportedDeliveryMode(mode); |
|
RETURN(-1); |
|
} |
|
else |
|
{ |
|
trace_Wsman_DeliveryMode(mode); |
|
} |
|
} |
|
else |
|
{ |
|
trace_Wsman_ExpectedDeliveryMode(); |
|
RETURN(-1); |
|
} |
|
} |
|
|
|
for (;;) |
|
{ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
|
|
if (e.type == XML_END) |
|
{ |
|
int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size); |
|
|
|
/* The end tag for Delivery was encountered, so jump out of the loop. */ |
|
if (WSMANTAG_SUBSCRIBE_DELIVER != tag) |
|
{ |
|
trace_Wsman_UnexpectedCloseTagWithNamespace(e.data.namespaceId, e.data.data); |
|
RETURN(-1); |
|
} |
|
break; |
|
} |
|
|
|
/* skip possible comments */ |
|
if (e.type != XML_START) |
|
continue; |
|
|
|
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
|
{ |
|
case WSMANTAG_SUBSCRIBE_HEARTBEATS: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->heartbeat.value ) ) |
|
RETURN(-1); |
|
|
|
wssubbody->heartbeat.exists = MI_TRUE; |
|
|
|
if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Heartbeats")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_SUBSCRIBE_CONTENTENCODING: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ContentEncoding")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
case WSMANTAG_SUBSCRIBE_CONNECTION_RETRY: |
|
{ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->connectionRetry.value ) ) |
|
RETURN(-1); |
|
|
|
wssubbody->connectionRetry.exists = MI_TRUE; |
|
|
|
if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ConnectionRetry")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
default: |
|
{ |
|
if (_MustUnderstandCanBeIgnored(&e) != 0) |
|
{ |
|
trace_Wsman_UnknownMandatoryTagWithNamespace(e.data.namespaceId, e.data.data); |
|
RETURN(-1); |
|
} |
|
|
|
if (XML_Skip(xml) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
|
|
} |
|
} |
|
|
|
for (;;) |
|
{ |
|
/* Get the next element and check for proper order of optional tags |
|
* within the sequence. This loop ensures order and stops when it |
|
* hits a parse error or encounters the body end tag.*/ |
|
if (XML_Next(xml, &e) != 0) |
|
RETURN(-1); |
|
|
|
if (e.type == XML_START) |
|
{ |
|
switch (HashStr(e.data.namespaceId, e.data.data, e.data.size)) |
|
{ |
|
case WSMANTAG_EXPIRES: |
|
{ |
|
/* Parse Expires (if present) */ |
|
if (sequenceState >= SubscribeSequence_EXPIRES) |
|
RETURN(-1); |
|
sequenceState = SubscribeSequence_EXPIRES; |
|
|
|
/* Expect an xs:duration of form: PnYnMnDTnHnMnS */ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->expires.value ) ) |
|
RETURN(-1); |
|
|
|
wssubbody->expires.exists = MI_TRUE; |
|
|
|
/* Check for closing </w:Expires> tag */ |
|
if (XML_Expect(xml, &e, XML_END, ZT('e'), ZT("Expires")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
case WSMANTAG_ENUM_FILTER: |
|
{ |
|
/* Parse filter and dialect */ |
|
const XML_Char* dialect; |
|
if (sequenceState >= SubscribeSequence_FILTER) |
|
RETURN(-1); |
|
sequenceState = SubscribeSequence_FILTER; |
|
|
|
/* Read 'Dialect' attribute */ |
|
dialect = XML_Elem_GetAttr(&e, 0, ZT("Dialect")); |
|
if (!dialect) |
|
{ |
|
trace_Wsman_FilterTagMissingDialectAttribute(); |
|
RETURN(-1); |
|
} |
|
wssubbody->dialect = _WS_ParseDialect(dialect, MI_TRUE); |
|
if (!wssubbody->dialect) |
|
{ |
|
trace_Wsman_UnknownDialect(dialect); |
|
RETURN(-1); |
|
} |
|
else |
|
trace_Wsman_SubscribeDialect(dialect); |
|
|
|
/* Get the filter text */ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
wssubbody->filter = e.data.data; |
|
trace_Wsman_SubscribeFilter(wssubbody->filter); |
|
|
|
/* Check for closing </w:Filter> tag */ |
|
if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Filter")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
case WSMANTAG_SEND_BOOKMARKS: |
|
{ |
|
wssubbody->sendBookmarks = MI_TRUE; |
|
|
|
if (XML_Skip(xml) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
case WSMANTAG_BOOKMARK: |
|
{ |
|
/* Parse Bookmark */ |
|
if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0) |
|
RETURN(-1); |
|
|
|
if (XML_StripWhitespace(&e) != 0) |
|
RETURN(-1); |
|
|
|
wssubbody->initialBookmark = e.data.data; |
|
|
|
if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Bookmark")) != 0) |
|
RETURN(-1); |
|
} |
|
break; |
|
default: |
|
RETURN(-1); |
|
} |
|
} |
|
else if (e.type == XML_END) |
|
{ |
|
/* Expect </e:Subscribe> */ |
|
if (ZT('e') == e.data.namespaceId && |
|
Tcscmp(e.data.data, ZT("Subscribe")) == 0) |
|
{ |
|
sequenceState = SubscribeSequence_END; |
|
/* We reached the end of the subscribe body an the end of the |
|
* xs:sequence. Jump out to proceed. */ |
|
break; |
|
} |
|
else |
|
RETURN(-1); |
|
} |
|
else |
|
RETURN(-1); |
|
} |
|
|
|
/* Expect </s:Body> */ |
|
if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Body")) != 0) |
|
RETURN(-1); |
|
|
|
/* Expect </s:Envelope> */ |
|
if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Envelope")) != 0) |
|
RETURN(-1); |
|
|
|
return 0; |
|
} |
|
|
|
/* Unsubcribe message sample: |
|
<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"> |
|
<s:Header> |
|
<a:To>http://localhost:5985/wsman</a:To> |
|
<a:ReplyTo> |
|
<a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address> |
|
</a:ReplyTo> |
|
<a:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action> |
|
...... |
|
<e:Identifier xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing">0860D524-6F0A-46FE-B95E-7CB0C1A2C1B8</e:Identifier> |
|
</s:Header> |
|
<s:Body> |
|
<e:Unsubscribe/> |
|
</s:Body> |
|
</s:Envelope> |
|
*/ |
|
int WS_ParseUnsubscribeBody( |
|
XML* xml, |
|
WSMAN_WSEnumeratePullBody* wsunsubbody) |
|
{ |
|
XML_Elem e; |
|
|
|
memset(wsunsubbody, 0, sizeof(WSMAN_WSEnumeratePullBody)); |
|
|
|
/* Expect <s:Body> */ |
|
if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_START, "i:Identify") != 0) |
/* Expect <e:Subscribe> */ |
|
if (XML_Expect(xml, &e, XML_START, MI_T('e'), ZT("Unsubscribe")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, "i:Identify") != 0) |
/* Expect </e:Subscribe> */ |
|
if (XML_Expect(xml, &e, XML_END, MI_T('e'), ZT("Unsubscribe")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, "s:Body") != 0) |
/* Expect <s:Body> */ |
|
if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Body")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0) |
/* Expect </s:Envelope> */ |
|
if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Envelope")) != 0) |
RETURN(-1); | RETURN(-1); |
| |
return 0; | return 0; |
} | } |
|
|
|
#endif /* #ifndef DISABLE_INDICATION */ |