/******************************************************************************

	[clientlibrary] soap.js

	Simple implementation of a jScript SOAP broker. The broker is capable or 
	transmitting simple arguments (strings) and return compound and simple
	types from the server.

	The current version has no associated schema information, so there is 
	no way to query the server for the capabilities of the publice webservices or
	to verify the structure of the compound types returned from the server.

	[author]		Ulf Johansen
	[version]		3.0
	[package]		clientcore

******************************************************************************/

///////////////////////////////////////////////////////////////////////////
//
// Globals
//
///////////////////////////////////////////////////////////////////////////

var g_nErrorState 		= 0;	// Global state to prevent endless loop
var g_strDebugTemplate 	= null; // Template for holding debug messages

///////////////////////////////////////////////////////////////////////////
//
// Public Functions
//
///////////////////////////////////////////////////////////////////////////


function SOAPDecodeType( objInstance )
{
	// Check for null elements
	var objNullAttribute = objInstance.attributes.getNamedItem( "xsi:null" );
	if ( objNullAttribute )
	{
		return null;
	}

	var strType = objInstance.attributes.getNamedItem( "xsi:type" ).nodeValue;
	switch ( strType )
	{
		case "xsd:string":
			return objInstance.text;

		case "xsd:xml":
			return objInstance.childNodes( 0 ).xml;

		case "xsd:int":
			return parseInt( objInstance.text );

		case "xsd:float":
			return parseFloat( objInstance.text );
		
		case "xsd:boolean":
			return objInstance.text == "true";

		case "SOAP-ENC:Array":
			var objResult = new Array();
			for ( var i = 0; i < objInstance.childNodes.length; i++ )
			{
				objResult[ i ] = SOAPDecodeType( objInstance.childNodes( i ) );
			}
			return objResult;

		default:

			var objResult = new Array();
			for ( var i = 0; i < objInstance.childNodes.length; i++ )
			{
				var strName		= objInstance.childNodes( i ).nodeName;
				var objValue	= SOAPDecodeType( objInstance.childNodes( i ) );

				objResult[ strName ] = objValue;
			}
			return objResult;
	}
}


/**********************************************************

	[function]	SOAPEncodeArgument

	Create SOAP encoding of a jScript variable argument

	[in]		objInstance		The jScript variable
	[in]		nIndex			Argument number

	[return]	The SOAP encoding of the jScript variable

**********************************************************/
function SOAPEncodeArgument( objArgument, nIndex )
{
	if ( objArgument == null )
	{
		return '<arg-' + nIndex + ' xsi:null="1"/>\n';
	}

	var strType = typeof( objArgument );
	switch( strType )
	{
		case "string":
			if ( objArgument.indexOf( "<![CDATA[" ) == -1 )
			{
				return '<arg-' + nIndex + ' xsi:type="xsd:string"><![CDATA[' + objArgument + ']]></arg-' + nIndex + '>\n';
			}
			else
			{
				// Make sure it is XML
				var objXML = ParseXML( objArgument );
				return '<arg-' + nIndex + ' xsi:type="xsd:xml">' + objArgument + '</arg-' + nIndex + '>\n';
			}

		case "number":
			if ( Math.floor( objArgument ) == objArgument )
			{
				return '<arg-' + nIndex + ' xsi:type="xsd:int">' + objArgument + '</arg-' + nIndex + '>\n';
			}
			else
			{
				return '<arg-' + nIndex + ' xsi:type="xsd:float">' + objArgument + '</arg-' + nIndex + '>\n';
			}

		case "boolean":
			return '<arg-' + nIndex + ' xsi:type="xsd:boolean">' + ( objArgument ? "true" : "false" ) + '</arg-' + nIndex + '>\n';

		default:
			// NOTE: functions, objects and arrays are not marshalled			
	}
}

function CallServer( strURL, strMethod, strEncoding, arg1, arg2, arg3, arg4, arg5, arg6, arg6, arg7, arg8 )
{
	// Construct SOAP envelope	
	var strXML =	'<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\n' + 
					'	<SOAP-ENV:Body>\n' +
					'		<cms:' + strMethod + ' xmlns:cms="http://www.software-innovation.com/growBusiness/cms/rpc1.0">\n';

	for ( var i = 3; i < arguments.length; i++ )
	{
		strXML +=	'			' + SOAPEncodeArgument( arguments[ i ], ( i- 2 ) ) + '\n';
	}


	strXML +=		'		</cms:' + strMethod + '>\n' +
					'	</SOAP-ENV:Body>\n' +
					'</SOAP-ENV:Envelope>';

	// Call server
	var objHTTP = new ActiveXObject( "MSXML2.XMLHTTP" );
	if ( strEncoding == "GET" )
	{
		objHTTP.open( "GET", strURL + "?" + strXML, false, null, null );
		objHTTP.setRequestHeader( "SOAPAction", strURL + "#" + strMethod );

		objHTTP.send();
	}
	else 
	{
		// Default for posting data to the server.

		objHTTP.open( "POST", strURL, false, null, null );
		objHTTP.setRequestHeader( "Content-Type", 'text/xml; charset="utf-8"' );
		objHTTP.setRequestHeader( "SOAPAction", strURL + "#" + strMethod );

		objHTTP.send( strXML );
	}

	// Check the result
	if ( objHTTP.responseXML.parseError.errorCode == 0 )
	{
		var objBody = objHTTP.responseXML.selectSingleNode( "/SOAP-ENV:Envelope/SOAP-ENV:Body" );
		if ( objBody )
		{
			var objChild = objBody.childNodes( 0 );
			var strNodeName = objChild.nodeName;

			switch ( objChild.nodeName )
			{
				case  strMethod + "-Response":
					return SOAPDecodeType( objChild );
				
				case "SOAP-ENV:Fault":
					alert( objChild.selectSingleNode( "detail" ).text );
					return null;
	
				default:
					alert( "Unknown SOAP child name! Excepted: '" + strMethod + "-Response' but got '" + objChild.nodeName + "'" );
					return null;
			}
		}
	}
	else
	{
		alert( "SOAP XML parse error:" + objHTTP.responseXML.parseError.reason );
	}

	// If we get here, we got an error
	try
	{
		var objWindow = window.open( '', '_soaperror', 'toolbar=no, menubar=no, location=no, resizable=yes, status=yes' );
		objWindow.document.write( "<h1>SOAP internal error</h1>" + objHTTP.responseText + "<br><br>SOAP Broker:" + strURL + "<br>Method:" + strMethod + "<br><br>Markup:<hr>" + objHTTP.responseText.replace( /</g, "&lt;" ).replace( />/g, "&gt;" ) );
	}
	catch( e )
	{
		window.showModalDialog( GetSiteRootPath() + "/solution/soapError.html", new Array( "<h1>SOAP internal error</h1>" + objHTTP.responseText + "<br><br>SOAP Broker:" + strURL + "<br>Method:" + strMethod + "<br><br>Markup:<hr>" + objHTTP.responseText.replace( /</g, "&lt;" ).replace( />/g, "&gt;" ) ), "center:1;status:0;help:0;scroll:0;dialogWidth:800px;dialogHeight:844px" );
	}
	return null;
}