int WS_ParseFaultBody()

in Unix/wsman/wsmanparser.c [3073:3318]


int WS_ParseFaultBody(
    XML* xml,
    WSMAN_WSFault *fault)
{
    XML_Elem e;
    fault->code[0] = '\0';
    fault->subcode[0] = '\0';
    fault->reason = NULL;
    fault->detail = NULL;
    fault->mi_result = 0;
    fault->mi_message = NULL;
                        
    /* Expect <s:Body> */
    if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
        RETURN(-1);

    /* Expect <s:Body> */
    if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Fault")) != 0)
        RETURN(-1);

    for (;;)
    {
        if (GetNextSkipCharsAndComments(xml, &e) != 0)
            RETURN(-1);

        if (e.type == XML_END && (Tcscmp(e.data.data, ZT("Fault")) == 0))
            break;

        if (e.type != XML_START)
            continue;

        if (ZT('s') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("Code")) == 0))
        {
            for (;;)
            {
                if (GetNextSkipCharsAndComments(xml, &e) != 0)
                    RETURN(-1);

                if (e.type == XML_END && (Tcscmp(e.data.data, ZT("Code")) == 0))
                    break;

                if (e.type != XML_START)
                    continue;

                if (ZT('s') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("Value")) == 0))
                {
                    if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
                        RETURN(-1);

                    if (XML_ParseCharFault(xml, e.data.data, fault->code, sizeof(fault->code)/sizeof(MI_Char)) != 0)
                        RETURN(-1);

                    if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Value")) != 0)
                        RETURN(-1);
                }
                else if (ZT('s') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("Subcode")) == 0))
                {
                    if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Value")) != 0)
                        RETURN(-1);

                    if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
                        RETURN(-1);

                    if (XML_ParseCharFault(xml, e.data.data, fault->subcode, sizeof(fault->subcode)/sizeof(MI_Char)) != 0)
                        RETURN(-1);

                    if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Value")) != 0)
                        RETURN(-1);

                    if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Subcode")) != 0)
                        RETURN(-1);
                }
            }
        }
        else if (ZT('s') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("Reason")) == 0))
        {
            if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Text")) != 0)
                RETURN(-1);

            if (XML_Next(xml, &e) != 0)
                RETURN(-1);
            
            if (e.type == XML_CHARS)
            {
                fault->reason = e.data.data;

                if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Text")) != 0)
                    RETURN(-1);
            }
            else if (e.type != XML_END || (Tcscmp(e.data.data, ZT("Text")) != 0))
                    RETURN(-1);

            if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Reason")) != 0)
                RETURN(-1);
        }
        else if (ZT('s') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("Detail")) == 0))        
        {
            for (;;)
            {
                if (XML_Next(xml, &e) != 0)
                    RETURN(-1);

                if (e.type == XML_END && (Tcscmp(e.data.data, ZT("Detail")) == 0))
                    break;

                if (e.type != XML_START)
                    continue;

                if (ZT('w') == e.data.namespaceId && (Tcscmp(e.data.data, ZT("FaultDetail")) == 0))
                {
                    if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
                        RETURN(-1);

                    fault->detail = e.data.data;

                    if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("FaultDetail")) != 0)
                        RETURN(-1);
                }
                else if (Tcscmp(e.data.data, ZT("OMI_Error")) == 0)
                {
                    const XML_Char* value = XML_Elem_GetAttr(&e, PAL_T('b'), ZT("IsCIM_Error"));
                    if (value != NULL && Tcscmp(value, ZT("true")) == 0)
                    {
                        // CIM Error
                        for (;;)
                        {
                            if (XML_Next(xml, &e) != 0)
                                RETURN(-1);

                            if (e.type == XML_END && (Tcscmp(e.data.data, ZT("OMI_Error")) == 0))
                                break;

                            if (e.type != XML_START)
                                continue;

                            if (Tcscmp(e.data.data, ZT("MessageID")) == 0)
                            {
                                if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
                                    RETURN(-1);

                                if (Tcsncmp(e.data.data, ZT("OMI:MI_Result:"), 14) == 0)
                                {
                                    fault->mi_result = Tcstol(&e.data.data[14], NULL, 10);
                                }

                                if (XML_Expect(xml, &e, XML_END, 0, PAL_T("MessageID")) != 0)
                                    RETURN(-1);
                            }
                            else if (Tcscmp(e.data.data, ZT("Message")) == 0)
                            {
                                if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
                                    RETURN(-1);

                                fault->mi_message = e.data.data;

                                if (XML_Expect(xml, &e, XML_END, 0, PAL_T("Message")) != 0)
                                    RETURN(-1);
                            }
                        }
                    }
                }
                else if (Tcscmp(e.data.data, ZT("WSManFault")) == 0)
                {
                    /* fault->mi_result should be MI_RESULT_FAILED for WSManFault */
                    fault->mi_result = MI_RESULT_FAILED;
    
                    if (XML_Expect(xml, &e, XML_START, 0, PAL_T("Message")) != 0)
                        RETURN(-1);

                    /* ProviderFault from Windows response:
                    WSMANTAG_ACTION_FAULT_ADDRESSING case:
                    <f:WSManFault>
                            <f:Message>
                                    <f:ProviderFault>
                                            <f:WSManFault>
                                                    <f:Message>...</f:Message>
                                            </f:WSManFault>
                                            <f:ExtendedError>...</f:ExtendedError>
                                    </f:ProviderFault>
                            </f:Message>
                    </f:WSManFault>
                    
                    Normal ProviderFault respones:
                    ERROR_INTERNAL_ERROR case:
                    <f:WSManFault>
                            <f:Message>
                                    <f:ProviderFault>...</f:ProviderFault>
                            </f:Message>
                    </f:WSManFault>
                    ERROR_WSMAN_OPERATION_TIMEDOUT case:
                    <f:WSManFault>
                            <f:Message>...</f:Message>
                    </f:WSManFault>
                    */
                    MI_Result providerFault = MI_FALSE;
                    MI_Result isSetDetail = MI_FALSE;
                    for (;;)
                    {
                        if (XML_Next(xml, &e) != 0)
                            RETURN(-1);
                        
                        if (e.type == XML_CHARS)
                        {
                            if(isSetDetail == MI_FALSE)
                            {
                                /*we will not set detail again once it is setted.*/
                                fault->detail = e.data.data;
                                isSetDetail = MI_TRUE;
                            }
                            
                            if(providerFault == MI_FALSE)
                            {
                                /*providerFault doesn't exist and the current element is a message string.*/
                                break;
                            }
                        }
                        else if (e.type == XML_START && Tcscmp(e.data.data, ZT("ProviderFault")) == 0)
                        {
                            providerFault = MI_TRUE;
                        }
                        else if (e.type == XML_END && Tcscmp(e.data.data, ZT("ProviderFault")) == 0)
                        {
                            break;
                        }
                    }

                    if (XML_Expect(xml, &e, XML_END, 0, PAL_T("Message")) != 0)
                        RETURN(-1);

                    if (XML_Expect(xml, &e, XML_END, 0, PAL_T("WSManFault")) != 0)
                        RETURN(-1);
                }
            }
        }
    }

    /* Expect <s:Body> */
    if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
        RETURN(-1);

    /* Expect </s:Envelope> */
    if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
        RETURN(-1);

    return 0;
}