// soap12testhdrdocObj.cpp : Implementation of Csoap12testhdrdocObj

#include "stdafx.h"
#include "soap12testhdrdocObj.h"

#include "..\soap_source\xmlparser.h"
#include "..\soap_source\xmldocfragment.h"
#include "..\soap_source\charencode.h"
#include "..\wmsoapmsg\wmsoapmsg_i.c"
#include "..\wmsoapmsg\wmsoapmsg.h"
#include "..\soap_source\soap.h"

static wchar_t *g_pwszHeaderNS = L"http://example.org/ts-tests";

// Csoap12testhdrdocObj

STDMETHODIMP Csoap12testhdrdocObj::OnTestMUHeaderBlock(BSTR bstrNamespace, BSTR bstrLocalName, VARIANT_BOOL *pResult)
{
    *pResult = VARIANT_FALSE;
    if (wcscmp(bstrNamespace, g_pwszHeaderNS) == 0)
    {
        if (wcscmp(bstrLocalName, L"echoOk") == 0 ||
            wcscmp(bstrLocalName, L"concatAndForwardEchoOk") == 0 ||
            wcscmp(bstrLocalName, L"concatAndForwardEchoOkArg1") == 0 ||
            wcscmp(bstrLocalName, L"concatAndForwardEchoOkArg2") == 0)
        {
            *pResult = VARIANT_TRUE;
            return S_OK;
        }
    }
    return S_OK;
}

STDMETHODIMP Csoap12testhdrdocObj::OnProcessHeader(VARIANT SOAPMsgInterface, VARIANT_BOOL *pResult)
{
	// set up, assume success
	m_bAbortProcessing = false;
	*pResult = VARIANT_TRUE;
	// get interface ptr
	IDispatch *pIDispatch = SOAPMsgInterface.pdispVal;
	Iwmsoapmsg2 *pIwmsoapmsg;
	HRESULT hRes = pIDispatch->QueryInterface(IID_Iwmsoapmsg2, (void **)&pIwmsoapmsg);
	if (hRes != S_OK)
	{
		return E_FAIL;
	}
	VARIANT_BOOL bResult;
	pIwmsoapmsg->IsRequestPhase(&bResult);
	if (bResult == VARIANT_TRUE)
	{
		// this is request phase
		if (ProcessRequest(pIwmsoapmsg) == false)
		{
            m_bAbortProcessing = true;
		}
		pIwmsoapmsg->Release();
		// abort processing?
		if (m_bAbortProcessing == true)
		{
			// set out parameter to signal abort
			*pResult = VARIANT_FALSE;
		}
		return S_OK;
	}
	// response phase
	if (ProcessResponse(pIwmsoapmsg) == false)
	{
        m_bAbortProcessing = true;
	}
	pIwmsoapmsg->Release();
	if (m_bAbortProcessing == true)
	{
		// set out parameter to signal abort
		*pResult = VARIANT_FALSE;
	}
	return S_OK;
}

bool Csoap12testhdrdocObj::ProcessRequest(Iwmsoapmsg2 *pIwmsoapmsg)
{
    // reset flags
    m_bEchoOkFound = false;
    m_bConcatAndFwdFound = false;
    m_bConcatAndFwdArg1Found = false;
    m_bConcatAndFwdArg2Found = false;
    // get "echoOk" header element
	BSTR bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	BSTR bstrLocalName = SysAllocString(L"echoOk");
	BSTR bstrXML = NULL;
	wstring wstrXML;
	VARIANT_BOOL bResult = VARIANT_FALSE;
	HRESULT hRes = pIwmsoapmsg->GetHeaderElemLiteral(bstrNamespaceURI, bstrLocalName, &bstrXML, &bResult);
	SysFreeString(bstrLocalName);
	SysFreeString(bstrNamespaceURI);
	if (hRes != S_OK)
	{
		return false;
	}
    if (bResult == VARIANT_TRUE)
    {
	    wstrXML = bstrXML;
	    SysFreeString(bstrXML);
        bstrXML = NULL;
	    // set up for parsing
	    WMXMLParser Parser;
	    bool bRtn = true;
	    // parse the XML fragment representing the header entry
	    try
	    {
		    Parser.ParseXML_WideString(wstrXML, NULL);
	    }
	    catch(int e)
	    {
		    int x = e;
		    return false;
	    }
	    // get the WMXMLElement pointer representing root node of parse tree
	    WMXMLElement *pRoot = Parser.DetachDocRoot();
	    if (pRoot == NULL)
	    {
		    return false;
	    }
        // was this targeted at role "none"?
        wstring wstrRole;
        bool bIgnoreIt = false;
        if (pRoot->GetAttribute(g_pwszSoap12EnvelopeNS, wstring(L"role"), wstrRole) == true)
        {
            if (wstrRole == g_pwszSoap12RoleNone)
            {
                bIgnoreIt = true;
            }
        }
        if (bIgnoreIt == false)
        {
	        m_wstrEchoOk = pRoot->GetContent();
            m_bEchoOkFound = true;
        }
	    delete pRoot;
    }
    // get "concatAndForwardEchoOk" header element
    bResult = VARIANT_FALSE;
	bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	bstrLocalName = SysAllocString(L"concatAndForwardEchoOk");
	hRes = pIwmsoapmsg->GetHeaderElemLiteral(bstrNamespaceURI, bstrLocalName, &bstrXML, &bResult);
	SysFreeString(bstrLocalName);
	SysFreeString(bstrNamespaceURI);
	if (hRes != S_OK)
	{
		return false;
	}
    if (bResult == VARIANT_TRUE)
    {
	    wstrXML = bstrXML;
	    SysFreeString(bstrXML);
        bstrXML = NULL;
	    // set up for parsing
	    WMXMLParser Parser;
	    bool bRtn = true;
	    // parse the XML fragment representing the header entry
	    try
	    {
		    Parser.ParseXML_WideString(wstrXML, NULL);
	    }
	    catch(int e)
	    {
		    int x = e;
		    return false;
	    }
	    // get the WMXMLElement pointer representing root node of parse tree
	    WMXMLElement *pRoot = Parser.DetachDocRoot();
	    if (pRoot == NULL)
	    {
		    return false;
	    }
        // was this targeted at role "none"?
        wstring wstrRole;
        bool bIgnoreIt = false;
        if (pRoot->GetAttribute(g_pwszSoap12EnvelopeNS, wstring(L"role"), wstrRole) == true)
        {
            if (wstrRole == g_pwszSoap12RoleNone)
            {
                bIgnoreIt = true;
            }
        }
        if (bIgnoreIt == false)
        {
            m_bConcatAndFwdFound = true;
            GetConcatAndFwdArgs(pIwmsoapmsg);
            if (m_bConcatAndFwdArg1Found == true &&
                m_bConcatAndFwdArg2Found == true)
            {
	            // create new header entry
	            WMXMLElement *pEchoOk = new WMXMLElement(wstring(L"test:echoOk"));
	            if (pEchoOk == NULL)
	            {
		            return false;
	            }
		        pEchoOk->SetNSPrefix(wstring(L"test"), wstring(g_pwszHeaderNS));
    	        pEchoOk->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS));
                wstring wstrTemp = m_wstrArg1;
                wstrTemp += m_wstrArg2;
		        pEchoOk->AppendContent(wstrTemp);

	            // now serialize
	            wstring wstrBuffer;
	            pEchoOk->Serialize(NULL, wstrBuffer);
	            delete pEchoOk;

	            BSTR bstrBuffer = SysAllocString(wstrBuffer.c_str());
	            BSTR bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	            BSTR bstrLocalName = SysAllocString(L"echoOk");
	            VARIANT_BOOL bMustUnderstand = VARIANT_TRUE;
	            BSTR bstrActorURI = SysAllocString(L"http://example.org/ts-tests/C");
	            BSTR bstrEncodingStyle = SysAllocString(L"");
	            VARIANT_BOOL bResult;
		        pIwmsoapmsg->AddHeaderElemLiteral(  bstrNamespaceURI,
											        bstrLocalName,
											        bstrBuffer,
											        bMustUnderstand,
											        bstrActorURI,
											        bstrEncodingStyle,
											        &bResult);
	            SysFreeString(bstrNamespaceURI);
	            SysFreeString(bstrLocalName);
	            SysFreeString(bstrActorURI);
	            SysFreeString(bstrEncodingStyle);
	            SysFreeString(bstrBuffer);
                if (bResult == VARIANT_FALSE)
                {
                    return false;
                }
            }
        }
	    delete pRoot;
    }
    ProcessBody(pIwmsoapmsg);
	return true;
}

bool Csoap12testhdrdocObj::ProcessResponse(Iwmsoapmsg2 *pIwmsoapmsg)
{
    if (m_bEchoOkFound == true)
    {
	    // create new header entry
	    WMXMLElement *pResponseOk = new WMXMLElement(wstring(L"test:responseOk"));
	    if (pResponseOk == NULL)
	    {
		    return false;
	    }
		pResponseOk->SetNSPrefix(wstring(L"test"), wstring(g_pwszHeaderNS));
    	pResponseOk->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS));
		pResponseOk->AppendContent(m_wstrEchoOk);

	    // now serialize
	    wstring wstrBuffer;
	    pResponseOk->Serialize(NULL, wstrBuffer);
	    delete pResponseOk;

	    BSTR bstrBuffer = SysAllocString(wstrBuffer.c_str());
	    BSTR bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	    BSTR bstrLocalName = SysAllocString(L"responseOk");
	    VARIANT_BOOL bMustUnderstand = VARIANT_FALSE;
	    BSTR bstrActorURI = SysAllocString(L"");
	    BSTR bstrEncodingStyle = SysAllocString(L"");
	    VARIANT_BOOL bResult;
		pIwmsoapmsg->AddHeaderElemLiteral(  bstrNamespaceURI,
											bstrLocalName,
											bstrBuffer,
											bMustUnderstand,
											bstrActorURI,
											bstrEncodingStyle,
											&bResult);
	    SysFreeString(bstrNamespaceURI);
	    SysFreeString(bstrLocalName);
	    SysFreeString(bstrActorURI);
	    SysFreeString(bstrEncodingStyle);
	    SysFreeString(bstrBuffer);
        if (bResult == VARIANT_FALSE)
        {
            return false;
        }
    }
	return true;
}

bool Csoap12testhdrdocObj::GetConcatAndFwdArgs(Iwmsoapmsg2 *pIwmsoapmsg)
{
    // get "concatAndForwardEchoOkArg1" header element
	BSTR bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	BSTR bstrLocalName = SysAllocString(L"concatAndForwardEchoOkArg1");
	BSTR bstrXML;
	wstring wstrXML;
	VARIANT_BOOL bResult;
	HRESULT hRes = pIwmsoapmsg->GetHeaderElemLiteral(bstrNamespaceURI, bstrLocalName, &bstrXML, &bResult);
	SysFreeString(bstrLocalName);
	SysFreeString(bstrNamespaceURI);
	if (hRes != S_OK)
	{
		return false;
	}
    if (bResult == VARIANT_TRUE)
    {
	    wstrXML = bstrXML;
	    SysFreeString(bstrXML);
	    // set up for parsing
	    WMXMLParser Parser;
	    bool bRtn = true;
	    // parse the XML fragment representing the header entry
	    try
	    {
		    Parser.ParseXML_WideString(wstrXML, NULL);
	    }
	    catch(int e)
	    {
		    int x = e;
		    return false;
	    }
	    // get the WMXMLElement pointer representing root node of parse tree
	    WMXMLElement *pRoot = Parser.DetachDocRoot();
	    if (pRoot == NULL)
	    {
		    return false;
	    }
        // was this targeted at role "none"?
        wstring wstrRole;
        bool bIgnoreIt = false;
        if (pRoot->GetAttribute(g_pwszSoap12EnvelopeNS, wstring(L"role"), wstrRole) == true)
        {
            if (wstrRole == g_pwszSoap12RoleNone)
            {
                bIgnoreIt = true;
            }
        }
        if (bIgnoreIt == false)
        {
	        m_wstrArg1 = pRoot->GetContent();
            m_bConcatAndFwdArg1Found = true;
        }
	    delete pRoot;
    }
    // get "concatAndForwardEchoOkArg2" header element
	bstrNamespaceURI = SysAllocString(g_pwszHeaderNS);
	bstrLocalName = SysAllocString(L"concatAndForwardEchoOkArg2");
	hRes = pIwmsoapmsg->GetHeaderElemLiteral(bstrNamespaceURI, bstrLocalName, &bstrXML, &bResult);
	SysFreeString(bstrLocalName);
	SysFreeString(bstrNamespaceURI);
	if (hRes != S_OK)
	{
		return false;
	}
    if (bResult == VARIANT_TRUE)
    {
	    wstrXML = bstrXML;
	    SysFreeString(bstrXML);
	    // set up for parsing
	    WMXMLParser Parser;
	    bool bRtn = true;
	    // parse the XML fragment representing the header entry
	    try
	    {
		    Parser.ParseXML_WideString(wstrXML, NULL);
	    }
	    catch(int e)
	    {
		    int x = e;
		    return false;
	    }
	    // get the WMXMLElement pointer representing root node of parse tree
	    WMXMLElement *pRoot = Parser.DetachDocRoot();
	    if (pRoot == NULL)
	    {
		    return false;
	    }
        // was this targeted at role "none"?
        wstring wstrRole;
        bool bIgnoreIt = false;
        if (pRoot->GetAttribute(g_pwszSoap12EnvelopeNS, wstring(L"role"), wstrRole) == true)
        {
            if (wstrRole == g_pwszSoap12RoleNone)
            {
                bIgnoreIt = true;
            }
        }
        if (bIgnoreIt == false)
        {
	        m_wstrArg2 = pRoot->GetContent();
            m_bConcatAndFwdArg2Found = true;
        }
	    delete pRoot;
    }
	return true;
}

bool Csoap12testhdrdocObj::ProcessBody(Iwmsoapmsg2 *pIwmsoapmsg)
{
    wstring wstrTestNS1(L"http://soapinterop.org/");
    map<wstring, wstring> mapNS;
    mapNS.insert(map<wstring, wstring>::value_type(wstring(L"n1"), wstrTestNS1));

    wstring wstrValue;
    wstring wstrSOAPEnvNS = g_pwszSoap12EnvelopeNS;

	BSTR bstrXML;
	VARIANT_BOOL bResult;
	HRESULT hRes = pIwmsoapmsg->GetBodyElemLiteral( &bstrXML,
													&bResult);
	if (hRes != S_OK || bResult == VARIANT_FALSE)
	{
    	return false;
	}
	// set up for parsing
    WMXMLDocFragment msg;
    if (msg.DeserializeXML(bstrXML) == false)
	{
    	return false;
	}
	bool bRtn = true;
	SysFreeString(bstrXML);
    bstrXML = NULL;

	// reset flags
	bool bEchoStringFound = false;
    bool bIsNil = false;
	// look for 'echoString' request
    if (msg.SelectElems(wstring(L"/n1:echoString"),
                                mapNS) == true)
	{
        WMXMLElement *pElem = msg.NextElem();
        if (pElem == NULL)
        {
            return false;
        }
        if (msg.SelectElems(pElem,
                            wstring(L"n1:inputString"),
                            mapNS) == true)
	    {
            WMXMLElement *pElem = msg.NextElem();
            if (pElem == NULL)
            {
                return false;
            }
            if (msg.IsNilElement(pElem) == true)
            {
                bIsNil = true;
            }
            else if (msg.DeserializeString(wstrValue, pElem) == false)
            {
                return false;
            }
        }
		bEchoStringFound = true;
	}
	if (bEchoStringFound == true)
	{
        // uppercase string
        for (wstring::iterator iter = wstrValue.begin();
            iter != wstrValue.end();
            iter++)
        {
            *iter = towupper(*iter);
        }
        // clone the received Body element... we must preserve
        // certain infoset items of Body received, e.g. namespace prefixes
        WMXMLElement *pBody = new WMXMLElement( msg.GetRootElem()->GetQualifiedName(),
                                                msg.GetRootElem()->GetURI(),
                                                msg.GetRootElem()->GetLocalName());
        if (pBody == NULL)
		{
			return false;
		}
	    // copy prefix map
        pBody->GetNSPrefixMap() = msg.GetRootElem()->GetNSPrefixMap();
	    // copy default ns
	    pBody->SetDefaultNS(msg.GetRootElem()->GetDefaultNS());
	    // copy attribute list
	    WMXMLAttributeMap::iterator iM;
	    for (iM = msg.GetRootElem()->GetAttributeMap().begin();
		    iM != msg.GetRootElem()->GetAttributeMap().end();
		    iM++)
	    {
		    WMXMLAttribute *pDest = new WMXMLAttribute(*(iM->second));
		    if (pDest != NULL)
		    {
                pBody->GetAttributeMap().insert(WMXMLAttributeMap::value_type(iM->first, pDest));
		    }
	    }
	    // create response
        msg.SetRootElem(pBody);
        // create response element
        WMXMLElement *pWrapper = msg.CreateChildElem(
                                                        pBody,
                                                        wstring(wstrTestNS1),
                                                        wstring(L""),
                                                        wstring(L"echoString"));
	    if (pWrapper == NULL)
	    {
            return false;
        }
        WMXMLElement *pParam = msg.CreateChildElem(
                                                    pWrapper,
                                                    wstring(L""),
                                                    wstring(L""),
                                                    wstring(L"inputString"));
        if (pParam == NULL)
	    {
            return false;
        }
        if (bIsNil == true)
        {
            pParam->SetAttribute(wstring(L"xsi:nil"), wstring(g_pwszXMLSchemaInstNS2001), wstring(L"true"));
        }
        else if (msg.SerializeString(wstrValue, pParam) == false)
	    {
            return false;
        }
	    // serialize response
	    msg.SerializeXML(&bstrXML);
        if (bstrXML == NULL)
        {
            return false;
        }
	    BSTR bstrEncodingStyle = SysAllocString(L"");
	    pIwmsoapmsg->SetBodyElemLiteral(bstrXML, bstrEncodingStyle, &bResult);
	    SysFreeString(bstrXML);
	    SysFreeString(bstrEncodingStyle);
    }
    return true;
}
