(file) Return to wsmanparser.c CVS log (file) (dir) Up to [OMI] / omi / protocol

File: [OMI] / omi / protocol / Attic / wsmanparser.c (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years, 1 month ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** 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;
}

ViewCVS 0.9.2