// soap12testsvcdocObj.cpp : Implementation of Csoap12testsvcdocObj

#include "stdafx.h"
#include "soap12testsvcdocObj.h"

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

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

// Csoap12testsvcdocObj

STDMETHODIMP Csoap12testsvcdocObj::OnProcessSoapPost(VARIANT SOAPMsgInterface, BSTR bstrSvcURI, BSTR bstrExtraPath,VARIANT_BOOL *pResult)
{
	*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;
	}
	// process
    m_wstrSvcURI = bstrSvcURI;
    m_wstrExtraPath = bstrExtraPath;
	if (ProcessPostMessage(pIwmsoapmsg) == false)
	{
		GenerateReceiverFault(pIwmsoapmsg, wstring(L"Failed to process SOAP request message (HTTP Method: POST)."));
	}
	pIwmsoapmsg->Release();
	return S_OK;
}

STDMETHODIMP Csoap12testsvcdocObj::OnProcessSoapGet(VARIANT SOAPMsgInterface, BSTR bstrSvcURI, BSTR bstrExtraPath, BSTR bstrQueryString, VARIANT_BOOL *pResult)
{
	*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;
	}
	// process
    m_wstrSvcURI = bstrSvcURI;
    m_wstrExtraPath = bstrExtraPath;
    m_wstrQueryString = bstrQueryString;
	if (ProcessGetMessage(pIwmsoapmsg) == false)
	{
	    GenerateReceiverFault(pIwmsoapmsg, wstring(L"Failed to process request (HTTP Method: GET)."));
	}
	pIwmsoapmsg->Release();
	return S_OK;
}

bool Csoap12testsvcdocObj::ProcessGetMessage(Iwmsoapmsg2 *pIwmsoapmsg)
{
    if (m_wstrExtraPath != L"/getTime")
    {
        wstring wstrMsg = L"Resource '";
        wstrMsg += m_wstrExtraPath;
        wstrMsg += L"' not available (HTTP Method: GET).";
        return GenerateSenderFault(pIwmsoapmsg, wstrMsg);
    }
	// create response tree
    WMXMLElement *pResponse;
	WMXMLElement *pBody = new WMXMLElement(wstring(L"SOAP-ENV:Body"));
	if (pBody != NULL)
	{
    	pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS));
        pResponse = new WMXMLElement(wstring(L"iop:time"));
		if (pResponse == NULL)
		{
            delete pBody;
            return false;
        }
		pResponse->SetNSPrefix(wstring(L"iop"), wstring(L"http://soapinterop.org/"));
        COleDateTime dt = COleDateTime::GetCurrentTime();
        WMXMLDocFragment::SerializeTime(dt, pResponse);
        pBody->AddChildElement(pResponse);
    }
    else
    {
        return false;
    }
    // serialize response
	BSTR bstrXML = pBody->Serialize(NULL);
	BSTR bstrEncodingStyle = SysAllocString(L"");
    VARIANT_BOOL bResult = VARIANT_FALSE;
	pIwmsoapmsg->SetBodyElemLiteral(bstrXML, bstrEncodingStyle, &bResult);
	SysFreeString(bstrXML);
	SysFreeString(bstrEncodingStyle);
	delete pBody;
	return true;
}

bool Csoap12testsvcdocObj::ProcessPostMessage(Iwmsoapmsg2 *pIwmsoapmsg)
{
    if (m_wstrExtraPath != L"")
    {
        wstring wstrMsg = L"Resource '";
        wstrMsg += m_wstrExtraPath;
        wstrMsg += L"' not available (HTTP Method: POST).";
        return GenerateSenderFault(pIwmsoapmsg, wstrMsg);
    }
	BSTR bstrXML;
	wstring wstrXML;
	VARIANT_BOOL bResult;
	HRESULT hRes = pIwmsoapmsg->GetBodyElemLiteral( &bstrXML,
													&bResult);
	if (hRes != S_OK || bResult == VARIANT_FALSE)
	{
		return false;
	}
	// set up for parsing
	WMXMLParser Parser;
	bool bRtn = true;
	// parse the XML fragment representing the header entry
	try
	{
		Parser.ParseXML_WideString(bstrXML, NULL);
	}
	catch(int e)
	{
		int x = e;
		SysFreeString(bstrXML);
		return false;
	}
	SysFreeString(bstrXML);
	// get the WMXMLElement pointer representing root node of parse tree
	WMXMLElement *pRoot = Parser.DetachDocRoot();
	if (pRoot == NULL)
	{
		return false;
	}
	// reset flags
	m_bEchoOkFound = false;
    m_bEchoSenderFault = false;
    m_bEchoReceiverFault = false;
    m_bBadEncoding = false;
	// look for 'echoOk' element
	WMXMLElement *pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS), wstring(L"echoOk"));
	if (pChild != NULL)
	{
		// get content
		m_wstrEchoOk = pChild->GetContent();
		m_bEchoOkFound = true;
        // check encodingStyle
        wstring wstrEncStyle;
        if (pChild->GetAttribute(   wstring(g_pwszSoap12EnvelopeNS),
                                    wstring(L"encodingStyle"),
                                    wstrEncStyle) == true)
        {
            if (wstrEncStyle != L"" &&
                wstrEncStyle != g_pwszSoap12EncodingStyleNone &&
                wstrEncStyle != g_pwszSoap12EncodingNS)
            {
                m_bBadEncoding = true;
            }
        }
		goto response;
	}
	// look for 'echoSenderFault' element
	pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS2), wstring(L"echoSenderFault"));
	if (pChild != NULL)
	{
		m_bEchoSenderFault = true;
		goto response;
	}
	// look for 'echoReceiverFault' element
	pChild = pRoot->GetChildElement(wstring(g_pwszMsgNS2), wstring(L"echoReceiverFault"));
	if (pChild != NULL)
	{
		m_bEchoReceiverFault = true;
		goto response;
	}

response:
	delete pRoot;
    if (m_bEchoSenderFault == true)
    {
	    return GenerateSenderFault(pIwmsoapmsg, wstring(L"This is a Sender fault."));
    }
    else if (m_bEchoReceiverFault == true)
    {
	    return GenerateReceiverFault(pIwmsoapmsg, wstring(L"This is a Receiver fault."));
    }
    else if (m_bBadEncoding == true)
    {
	    return GenerateDataEncUnkFault(pIwmsoapmsg, wstring(L"Encountered unsupported SOAP encoding style."));
    }
	// create response
	WMXMLElement *pBody = new WMXMLElement(wstring(L"SOAP-ENV:Body"));
	if (pBody != NULL)
	{
   		pBody->SetNSPrefix(wstring(L"SOAP-ENV"), wstring(g_pwszSoap12EnvelopeNS));
		if (m_bEchoOkFound == true)
		{
			WMXMLElement *pElem = new WMXMLElement(wstring(L"iop:responseOk"));
			if (pElem != NULL)
			{
				pElem->SetNSPrefix(wstring(L"iop"), wstring(g_pwszMsgNS));
				pElem->AppendContent(m_wstrEchoOk);
				pBody->AddChildElement(pElem);
			}
		}
		BSTR bstrXML = pBody->Serialize(NULL);
		BSTR bstrEncodingStyle = SysAllocString(L"");
		pIwmsoapmsg->SetBodyElemLiteral(bstrXML, bstrEncodingStyle, &bResult);
		SysFreeString(bstrXML);
		SysFreeString(bstrEncodingStyle);
		delete pBody;
	}
	return true;
}

bool Csoap12testsvcdocObj::GenerateSenderFault(Iwmsoapmsg2 *pIwmsoapmsg, const wstring& wstrMsg)
{
	BSTR bstrCode = SysAllocString(L"Sender");
    BSTR bstrCodeNS = SysAllocString(g_pwszSoap12EnvelopeNS);
	BSTR bstrSubcode = SysAllocString(L"");
    BSTR bstrSubcodeNS = SysAllocString(L"");
    BSTR bstrReason = SysAllocString(wstrMsg.c_str());
    BSTR bstrLangId = SysAllocString(L"en");
	VARIANT_BOOL bNeedDetail = VARIANT_TRUE;
    VARIANT_BOOL bResult;
	pIwmsoapmsg->SetSOAP12Fault(bstrCode, bstrCodeNS, bstrSubcode, bstrSubcodeNS, bstrReason, bstrLangId, &bResult);
	SysFreeString(bstrCode);
	SysFreeString(bstrCodeNS);
	SysFreeString(bstrSubcode);
	SysFreeString(bstrSubcodeNS);
	SysFreeString(bstrReason);
	SysFreeString(bstrLangId);
	return true;
}

bool Csoap12testsvcdocObj::GenerateReceiverFault(Iwmsoapmsg2 *pIwmsoapmsg, const wstring& wstrMsg)
{
	BSTR bstrCode = SysAllocString(L"Receiver");
    BSTR bstrCodeNS = SysAllocString(g_pwszSoap12EnvelopeNS);
	BSTR bstrSubcode = SysAllocString(L"");
    BSTR bstrSubcodeNS = SysAllocString(L"");
    BSTR bstrReason = SysAllocString(wstrMsg.c_str());
    BSTR bstrLangId = SysAllocString(L"en");
	VARIANT_BOOL bNeedDetail = VARIANT_TRUE;
    VARIANT_BOOL bResult;
	pIwmsoapmsg->SetSOAP12Fault(bstrCode, bstrCodeNS, bstrSubcode, bstrSubcodeNS, bstrReason, bstrLangId, &bResult);
	SysFreeString(bstrCode);
	SysFreeString(bstrCodeNS);
	SysFreeString(bstrSubcode);
	SysFreeString(bstrSubcodeNS);
	SysFreeString(bstrReason);
	SysFreeString(bstrLangId);
	return true;
}

bool Csoap12testsvcdocObj::GenerateDataEncUnkFault(Iwmsoapmsg2 *pIwmsoapmsg, const wstring& wstrMsg)
{
	BSTR bstrCode = SysAllocString(L"DataEncodingUnknown");
    BSTR bstrCodeNS = SysAllocString(g_pwszSoap12EnvelopeNS);
	BSTR bstrSubcode = SysAllocString(L"");
    BSTR bstrSubcodeNS = SysAllocString(L"");
    BSTR bstrReason = SysAllocString(wstrMsg.c_str());
    BSTR bstrLangId = SysAllocString(L"en");
	VARIANT_BOOL bNeedDetail = VARIANT_TRUE;
    VARIANT_BOOL bResult;
	pIwmsoapmsg->SetSOAP12Fault(bstrCode, bstrCodeNS, bstrSubcode, bstrSubcodeNS, bstrReason, bstrLangId, &bResult);
	SysFreeString(bstrCode);
	SysFreeString(bstrCodeNS);
	SysFreeString(bstrSubcode);
	SysFreeString(bstrSubcodeNS);
	SysFreeString(bstrReason);
	SysFreeString(bstrLangId);
	return true;
}

