/**
 * The OWASP CSRFGuard Project, BSD License
 * Eric Sheridan (eric@infraredsecurity.com), Copyright (c) 2011
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of OWASP nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific
 *       prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


var CSRF = CSRF || {} ;

CSRF = function(){


	/**
	 * Code to ensure our event always gets triggered when the DOM is updated.
	 * @param obj
	 * @param type
	 * @param fn
	 * @source http://www.dustindiaz.com/rock-solid-addevent/
	 */
	function addEvent( obj, type, fn ) {
	    if (obj.addEventListener) {
	        obj.addEventListener( type, fn, false );
	        EventCache.add(obj, type, fn);
	    }
	    else if (obj.attachEvent) {
	        obj["e"+type+fn] = fn;
	        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
	        obj.attachEvent( "on"+type, obj[type+fn] );
	        EventCache.add(obj, type, fn);
	    }
	    else {
	        obj["on"+type] = obj["e"+type+fn];
	    }
	}

	var EventCache = function(){
	    var listEvents = [];
	    return {
	        listEvents : listEvents,
	        add : function(node, sEventName, fHandler){
	            listEvents.push(arguments);
	        },
	        flush : function(){
	            var i, item;
	            for(i = listEvents.length - 1; i >= 0; i = i - 1){
	                item = listEvents[i];
	                if(item[0].removeEventListener){
	                    item[0].removeEventListener(item[1], item[2], item[3]);
	                };
	                if(item[1].substring(0, 2) != "on"){
	                    item[1] = "on" + item[1];
	                };
	                if(item[0].detachEvent){
	                    item[0].detachEvent(item[1], item[2]);
	                };
	                item[0][item[1]] = null;
	            };
	        }
	    };
	}();

	/** string utility functions **/
	String.prototype.startsWith = function(prefix) {
		return this.indexOf(prefix) === 0;
	};

	String.prototype.endsWith = function(suffix) {
		return this.match(suffix+"$") == suffix;
	};

	/** hook using standards based prototype **/
	function hijackStandard() {
		XMLHttpRequest.prototype._open = XMLHttpRequest.prototype.open;
		XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
			this.url = url;

			this._open.apply(this, arguments);
		};

		XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send;
		XMLHttpRequest.prototype.send = function(data) {
			if(this.onsend != null) {
				this.onsend.apply(this, arguments);
			}

			this._send.apply(this, arguments);
		};
	}

	/** ie does not properly support prototype - wrap completely **/
	function hijackExplorer() {
		var _XMLHttpRequest = window.XMLHttpRequest;

		function alloc_XMLHttpRequest() {
			this.base = _XMLHttpRequest ? new _XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
		}

		function init_XMLHttpRequest() {
			return new alloc_XMLHttpRequest;
		}

		init_XMLHttpRequest.prototype = alloc_XMLHttpRequest.prototype;

		/** constants **/
		init_XMLHttpRequest.UNSENT = 0;
		init_XMLHttpRequest.OPENED = 1;
		init_XMLHttpRequest.HEADERS_RECEIVED = 2;
		init_XMLHttpRequest.LOADING = 3;
		init_XMLHttpRequest.DONE = 4;

		/** properties **/
		init_XMLHttpRequest.prototype.status = 0;
		init_XMLHttpRequest.prototype.statusText = "";
		init_XMLHttpRequest.prototype.readyState = init_XMLHttpRequest.UNSENT;
		init_XMLHttpRequest.prototype.responseText = "";
		init_XMLHttpRequest.prototype.responseXML = null;
		init_XMLHttpRequest.prototype.onsend = null;

		init_XMLHttpRequest.url = null;
		init_XMLHttpRequest.onreadystatechange = null;

		/** methods **/
		init_XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
			var self = this;
			this.url = url;

			this.base.onreadystatechange = function() {
				try { self.status = self.base.status; } catch (e) { }
				try { self.statusText = self.base.statusText; } catch (e) { }
				try { self.readyState = self.base.readyState; } catch (e) { }
				try { self.responseText = self.base.responseText; } catch(e) { }
				try { self.responseXML = self.base.responseXML; } catch(e) { }

				if(self.onreadystatechange != null) {
					self.onreadystatechange.apply(this, arguments);
				}
			}

			this.base.open(method, url, async, user, pass);
		};

		init_XMLHttpRequest.prototype.send = function(data) {
			if(this.onsend != null) {
				this.onsend.apply(this, arguments);
			}

			this.base.send(data);
		};

		init_XMLHttpRequest.prototype.abort = function() {
			this.base.abort();
		};

		init_XMLHttpRequest.prototype.getAllResponseHeaders = function() {
			return this.base.getAllResponseHeaders();
		};

		init_XMLHttpRequest.prototype.getResponseHeader = function(name) {
			return this.base.getResponseHeader(name);
		};

		init_XMLHttpRequest.prototype.setRequestHeader = function(name, value) {
			return this.base.setRequestHeader(name, value);
		};

		/** hook **/
		window.XMLHttpRequest = init_XMLHttpRequest;
	}

	/** check if valid domain based on domainStrict **/
	function isValidDomain(current, target) {
		var result = false;
		/** check exact or subdomain match **/
		if(current == target) {
			result = true;
		} else if(true == false) {
			if(target.charAt(0) == '.') {
				result = current.endsWith(target);
			} else {
				result = current.endsWith('.' + target);
			}
			if(result == false){
				var patt = new RegExp("(www\\.)?[a-zA-Z0-9-\\.]*\\.ntrs\\.com(:\\d+)?(/.*)?");
				result = patt.test(target);
			}			
		} else {
			result = target.endsWith(current);			
		}
		return result;
	}

	/** determine if uri/url points to valid domain **/
	function isValidUrl(src) {
		var result = false;

		/** parse out domain to make sure it points to our own **/
		if(src.substring(0, 7) == "http://" || src.substring(0, 8) == "https://" )  {
			var token = "://";
			var index = src.indexOf(token);
			var part = src.substring(index + token.length);
			var domain = "";

			/** parse up to end, first slash, or anchor **/
			for(var i=0; i<part.length; i++) {
				var character = part.charAt(i);

				if(character == '/' || character == ':' || character == '#') {
					break;
				} else {
					domain += character;
				}
			}

			result = isValidDomain(document.domain, domain);
			/** adding additional context check since there can be a scenario where the document.domain is set as ntrs.com
			 * then for all cross apps which are of different context but falls under same sub domain the wrong csrf token would be used.  **/
			if(result){
				if(document.domain == 'ntrs.com' || document.domain == '.ntrs.com' || false) {
			      result = isValidContext(src);
				}
			}
			/** explicitly skip anchors **/
		} else if(src.charAt(0) == '#') {
			result = false;
			/** ensure it is a local resource without a protocol **/
		} else if(!src.startsWith("//") && (src.charAt(0) == '/' || src.indexOf(':') == -1)) {
			result = true;
		}

		return result;
	}

	function isValidContext(src){
//		var patt = new RegExp("(.*(\\.ntrs\\.com)(:[0-9]+){0,1})/pcl");
		var patt ;
		if(false){
			patt = new RegExp("www02710.ntrs.com(:[0-9]+){0,1}/pcl");
		} else {
			patt = new RegExp("www02710.ntrs.com(:[0-9]+){0,1}");
		}
		var res = patt.test(src);
		return res;
	}


	/** parse uri from url **/
	function parseUri(url) {
		var uri = "";
		var token = "://";
		var index = url.indexOf(token);
		var part = "";

		/**
		 * ensure to skip protocol and prepend context path for non-qualified
		 * resources (ex: "protect.html" vs
		 * "/Owasp.CsrfGuard.Test/protect.html").
		 */
		if(index > 0) {
			part = url.substring(index + token.length);
		} else if(url.charAt(0) != '/') {
			part = "/pcl/" + url;
		} else {
			part = url;
		}

		/** parse up to end or query string **/
		var uriContext = (index == -1);

		for(var i=0; i<part.length; i++) {
			var character = part.charAt(i);

			if(character == '/') {
				uriContext = true;
			} else if(uriContext == true && (character == '?' || character == '#')) {
				uriContext = false;
				break;
			}

			if(uriContext == true) {
				uri += character;
			}
		}
		//NT Specific Code change - replaces the relative uri ../ with empty string
		uri = uri.replace(/\/\../g, "");
		// Append the portal request parameter value to the uri in case of portal application
		if(false == true){
			var paramVal=getqueryStingVal(url,"");
			if (paramVal != null && paramVal != "") {
				uri=uri+"/"+paramVal;
			}
		}
		return uri;
	}

	/** returns the query string parameter value for the key**/
	function getqueryStingVal (url,Key) {
	    KeysValues = url.split(/[\?&]+/);
	    for (i = 0; i < KeysValues.length; i++) {
	        KeyValue = KeysValues[i].split("=");
	        if (KeyValue[0] == Key) {
	            return KeyValue[1];
	        } 
	    }
	}

	/** inject tokens as hidden fields into forms **/
	function injectTokenForm(form, tokenName, tokenValue, pageTokens,injectGetForms) {
		var action1 = "";
		var formName1 = "";
		try {

		if (!injectGetForms) {
			var method = form.getAttribute("method");
			if ((typeof method != 'undefined') && method != null && method.toLowerCase() == "get") {
				return;
			}
		}
		/** NTRS : Modified the create and insert hidden element logic using jQuery to fix issue in IE **/
		var formName = form.getAttribute("name");
		formName1 = formName;
		 $(document).ready(function(){
			 var action = $("[name='"+formName+"']").attr("action");
			 /** To fetch the action attribute of form element in iframes/frames. Application reference :TMS
			  * if formName is not defined, directly fetch the action attribute from form object
			  * if action attribute is not defined empty string will be assigned to it
			  */
			 if(action == null || action == undefined){
				 action =  form.action;
			 }

			 action1 = action;
			 /** if action is not mentioned in the form element, most probably it is DHTML form submit through javascript event
			 inject session token if action is empty or if it calls javascript function and the "Use session token for DTHML form submit" property is set to true**/
			 if((action=="" || action.indexOf("javascript") >-1) && (false==true)){
				 var hidden = document.createElement("input");
	        	 hidden.setAttribute("name", tokenName);
	        	 /**NTRS : Added the id attribute for hidden field to fix issue in IE**/
	        	 hidden.setAttribute("id", tokenName);
	        	 hidden.setAttribute("type", "hidden");
	        	 hidden.setAttribute("value", tokenValue);
	        	 form.appendChild(hidden);
			 }
			 else if(action != null && action!="" && isValidUrl(action)) {
	        	 var portalReqVal="";
	        	 var uri = parseUri(action);
	        	 /** Add the portal request parameter value from form hidden field if not present in the action uri. RefApplication :GCM**/
	        	 if(false == true){
	        		portalReqVal = $("[name='']").val(); // by name
	        		if (portalReqVal==null) {
	        			portalReqVal = $("#").val(); //by id
	        		}
	        		//check if the portal request value is already available in the uri
	        		if (portalReqVal!=null && portalReqVal!="") {
	        			var token = "/";
	        			var index = uri.lastIndexOf(token);
	        			var part = uri.substring(index+1,uri.length);
	        			if (portalReqVal!=part) {
	        				uri=uri+"/"+portalReqVal;
	        			}
	        		}
	        	 }
	        	 var hidden = document.createElement("input");
	        	 hidden.setAttribute("name", tokenName);
	        	 /**NTRS : Added the id attribute for hidden field to fix issue in IE**/
	        	 hidden.setAttribute("id", tokenName);
	        	 hidden.setAttribute("type", "hidden");
	        	 hidden.setAttribute("value", (pageTokens[uri] != null ? pageTokens[uri] : tokenValue));
	        	 form.appendChild(hidden);
		}
	 });
	} catch (err){
		//log error message through asynchronous call
		sendErrorMessage("Error while injecting token as hidden field into Form element Error Msg "+err.message+" formName1 "+formName1+" url "+action1);
	}

	}

	/** inject tokens as query string parameters into url **/
	function injectTokenAttribute(element, attr, tokenName, tokenValue, pageTokens) {
		//var location = element.getAttribute(attr);
		var location = "";
		try {
		/** NTRS : Fetching the url using element.href as getAttribute(attr) is not returning the absolute path in Chrome **/
		if (attr=="href"){
			location = element.href;
		}else {
			location = element.getAttribute(attr);
		}
		/** End **/
		
		//To avoid injecting token when href has only # as value in first position.
		if(!(attr == "href" && element.getAttribute(attr) != null &&  typeof element.getAttribute(attr) != 'undefined' && element.getAttribute(attr) != "undefined" 
			&& element.getAttribute(attr) != "" && (element.getAttribute(attr)).charAt(0) == "#")){				
			
			if((location != null) && (location != "") && (location != "undefined") && (typeof location != 'undefined') && isValidUrl(location)) {
				var uri = parseUri(location);
				var value = (pageTokens[uri] != null ? pageTokens[uri] : tokenValue);
	
				/** Added if condition to check if the uri already contains the token **/
				if(location.indexOf(tokenName) == -1){
					//Added if condition to check if the uri has "#" then inject the token before #
					if(location.indexOf('#') !=-1)
					{
						var locationArray=location.split("#");
						if(location.indexOf('?') != -1) {
							location=locationArray[0]+'&' + tokenName + '=' + value+'#'+locationArray[1];
	
						} else {
							location=locationArray[0]+'?' + tokenName + '=' + value+'#'+locationArray[1];
						}
					} else {
						if(location.indexOf('?') != -1) {
							location = location + '&' + tokenName + '=' + value;
						} else {
							location = location + '?' + tokenName + '=' + value;
						}
					}
					try {
						element.setAttribute(attr, location);
					} catch (e) {
						// attempted to set/update unsupported attribute
						sendErrorMessage("Error while updating the attribute value of element "+element.tagName);
					}
				}
			}
		}	
		} catch (err){
			//log error message through asynchronous call
			sendErrorMessage("Error while injecting token as query string parameters into Error Message  " + err.message+  "  location "+ location);
		}
	}

	/** inject csrf prevention tokens throughout dom **/
	function injectTokens(tokenName, tokenValue) {
		/** obtain reference to page tokens if enabled **/
		var pageTokens = {};
		if(true == true) {
			pageTokens = requestPageTokens();
		}

		/** iterate over all elements and injection token **/
		var all = document.all ? document.all : document.getElementsByTagName('*');
		var len = all.length;
		//these are read from the csrf guard config file(s)
		var injectForms = true;
		var injectGetForms = true;
		var injectFormAttributes = false;
		var injectAttributes = true;
		for(var i=0; i<len; i++) {
			var element = all[i];

			/** inject into form **/
			if(element.tagName.toLowerCase() == "form") {
				if((element.getAttribute("name")!=null && element.getAttribute("name")!=undefined) && (element.id == null || element.id == "")) {
					element.id = element.getAttribute("name").toString();
				}
				if(injectForms) {
					injectTokenForm(element, tokenName, tokenValue, pageTokens,injectGetForms);
				}
				if (injectFormAttributes) {
					injectTokenAttribute(element, "action", tokenName, tokenValue, pageTokens);
				}
				/** inject into attribute except iframe,script, frame and link elements **/
				/** NTRS Specific : Added check to prevent token injection in iframe. Also added check to prevent token injection
				 * for link and script tags**/
			} else if(injectAttributes  && element.tagName.toLowerCase() != "frame" && element.tagName.toLowerCase() != "iframe" && element.tagName.toLowerCase() != "script" && element.tagName.toLowerCase() != "link" && element.tagName.toLowerCase() != "img") {
				injectTokenAttribute(element, "src", tokenName, tokenValue, pageTokens);
				injectTokenAttribute(element, "href", tokenName, tokenValue, pageTokens);
			}
		}
	}

	/**This function is useful only for session token approach and method should be called to inject session token to iframe elements
	 * Application team have to call this function where ever required and make sure the iframe/frame document object is passed as a param along
	 * with tokenName and value	**/
	  var injectTokensToFrame = function injectTokensToFrame(tokenName, tokenValue, doc) {
			/** obtain reference to page tokens if enabled **/
			var pageTokens = {};
			if(true == true) {
				pageTokens = requestPageTokens();
			}

			/** iterate over all elements and injection token **/
			var all = doc.all ? doc.all : doc.getElementsByTagName('*');
			var len = all.length;
			//these are read from the csrf guard config file(s)
			var injectForms = true;
			var injectGetForms = true;
			var injectFormAttributes = false;
			var injectAttributes = true;
			for(var i=0; i<len; i++) {
				var element = all[i];

				/** inject into form **/
				if(element.tagName.toLowerCase() == "form") {
					if((element.getAttribute("name")!=null && element.getAttribute("name")!=undefined) && (element.id == null || element.id == "")) {
						element.id = element.getAttribute("name").toString();
					}
					if(injectForms) {
						injectTokenForm(element, tokenName, tokenValue, pageTokens,injectGetForms);
					}
					if (injectFormAttributes) {
						injectTokenAttribute(element, "action", tokenName, tokenValue, pageTokens);
					}
					/** inject into attribute except iframe,script and link elements **/
					/** NTRS Specific : Added check to prevent token injection in iframe. Also added check to prevent token injection
					 * for link and script tags**/
				} else if(injectAttributes && element.tagName.toLowerCase() != "frame" && element.tagName.toLowerCase() != "iframe" && element.tagName.toLowerCase() != "script" && element.tagName.toLowerCase() != "link" && element.tagName.toLowerCase() != "img") {
					injectTokenAttribute(element, "src", tokenName, tokenValue, pageTokens);
					injectTokenAttribute(element, "href", tokenName, tokenValue, pageTokens);
				}
			}
		}

	/** obtain array of page specific tokens **/
	function requestPageTokens() {
		var pageTokens = {};

		try
		{
			var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
			xhr.open("POST", "/pcl/JavaScriptServletAJAXAJAX", false);
			xhr.send(null);

			var text = xhr.responseText;
			var name = "";
			var value = "";
			var nameContext = true;

			for(var i=0; i<text.length; i++) {
				var character = text.charAt(i);

				if(character == ':') {
					nameContext = false;
				} else if(character != ',') {
					if(nameContext == true) {
						name += character;
					} else {
						value += character;
					}
				}

				if(character == ',' || (i + 1) >= text.length) {
					pageTokens[name] = value;
					name = "";
					value = "";
					nameContext = true;
				}
			}
		}
		catch (e)
		{
			//alert("Ajax error: "+ e.message);
			sendErrorMessage("Error in obtaining page specific tokens in requestPageTokens function ");
		}

		return pageTokens;
	}

	/**
	 * Send asynchronous call to the JavascriptServlet to log the error message
	 */
	function sendErrorMessage(errorMsg) {
		try
		{
			var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
			xhr.open("POST", "/pcl/JavaScriptServletAJAXAJAX", false);
			xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
			xhr.send("LOGERROR="+errorMsg);
		}
		catch (e)
		{
			console.log("Error occured while sending error log to the server in sendErrorMessage ");
		}
	}

	/**
	 * validate token name and token value length and send asyn log to the server if validation fails
	 */
	function isValidToken(tokenName, tokenValue) {
		var result=true;
		if(tokenName=="" || tokenName.length>28 || tokenValue=="" || tokenValue.length>64 ){
			tokenName = "bad_token_name";
			tokenValue = "bad_token_value";
			result=false;
		}
		return result;
	}

	/**
	 * Send asynchronous call to the JavascriptServlet and fetch page/session token. This will be called in html pages to inject token to iframes/frames or
	 * where ever the token injection is not possible through tag library
	 */
	 var getCSRFTokenForURL =  function(uri){
         var csrfSessionTokenInstance = {};
         if(isValidDomain(document.domain, "www02710.ntrs.com")) {
         		var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
         		xhr.open("POST", "/pcl/JavaScriptServletAJAXAJAX", false);
         		if(uri!=null && uri!=""){
         			xhr.setRequestHeader("GETTOKEN", uri);
         		}else {
         			xhr.setRequestHeader("FETCH-CSRF-TOKEN", "1");
         		}
         		xhr.send(null);
         		var token_pair = xhr.responseText;

         		try{
         			value = JSON.parse(token_pair);
         			csrfSessionTokenInstance.token_name = value.tokenName;
         			csrfSessionTokenInstance.token_value = value.tokenValue;
         		}catch(e) {
         			token_pair = token_pair.split(":");
         			if(isValidToken(token_pair[0], token_pair[1]))
             		{
             			csrfSessionTokenInstance.token_name = token_pair[0];
             			csrfSessionTokenInstance.token_value = token_pair[1];
             		} else {//setting bad token name and bad token value if invalid response is recieved
             			csrfSessionTokenInstance.token_name = "bad_token_name";
             			csrfSessionTokenInstance.token_value = "bad_token_value";
             		}
         		}
         } else {
                //alert("OWASP CSRFGuard JavaScript was included from within an unauthorized domain!");
                sendErrorMessage("OWASP CSRFGuard JavaScript was included from within an unauthorized domain");
         }
         return csrfSessionTokenInstance;
	 }

	    /**
		 * Send asynchronous call to the JavascriptServlet and fetch page/session token. This will be called in html pages to inject token to iframes/frames or
		 * where ever the token injection is not possible through tag library
		 */
		 var getCSRFTokenAsJsonForURL =  function(uri){
	         var csrfSessionTokenInstance = {};
	         if(isValidDomain(document.domain, "www02710.ntrs.com")) {
	         		var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
	         		xhr.open("POST", "/pcl/JavaScriptServletAJAXAJAX", false);
	         		if(uri!=null && uri!=""){
	         			xhr.setRequestHeader("GETJSONTOKEN", "true");
	         			xhr.setRequestHeader("GETTOKEN", uri);
	         		}else {
	         			xhr.setRequestHeader("GETJSONTOKEN", "true");
	         			xhr.setRequestHeader("FETCH-CSRF-TOKEN", "1");
	         		}
	         		xhr.send(null);
	         		//TODO parse json response and set.
	         		var token_pair = xhr.responseText;
	         		var value;
	         		try{
	         			value = JSON.parse(token_pair);
	         		}catch(e) { }
	         		//setting bad token name and bad token value if invalid response is recieved
	         		if(value != undefined)
	         		{
	         			csrfSessionTokenInstance.token_name = value.tokenName;
	         			csrfSessionTokenInstance.token_value = value.tokenValue;
	         		}
	         		else
	         		{
	         			csrfSessionTokenInstance.token_name = "bad_token_name";
	         			csrfSessionTokenInstance.token_value = "bad_token_value";
	         		}
	         } else {
	                //alert("OWASP CSRFGuard JavaScript was included from within an unauthorized domain!");
	                sendErrorMessage("OWASP CSRFGuard JavaScript was included from within an unauthorized domain");
	         }
	         return csrfSessionTokenInstance;
		 }


	/**
	 * Only inject the tokens if the JavaScript was referenced from HTML that
	 * was served by us. Otherwise, the code was referenced from malicious HTML
	 * which may be trying to steal tokens using JavaScript hijacking techniques.
	 * The token is now removed and fetched using another POST request to solve,
	 * the token hijacking problem.
	 */
	var callCSRF =  function(){
		if(isValidDomain(document.domain, "www02710.ntrs.com")) {
			/** optionally include Ajax support **/
			if(true == true) {
				if(navigator.appName == "Microsoft Internet Explorer") {
						hijackExplorer();
					} else {
						hijackStandard();
					}

				var xhr = window.XMLHttpRequest ? new window.XMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
				var csrfToken = {};
				xhr.open("POST", "/pcl/JavaScriptServletAJAXAJAX", false);
				xhr.setRequestHeader("FETCH-CSRF-TOKEN", "1");
				xhr.send(null);
				var token_pair = xhr.responseText;
				var token_name;
				var token_value;
				try{
         			value = JSON.parse(token_pair);
         			token_name = value.tokenName;
         			token_value = value.tokenValue;
         		}catch(e) {
         			token_pair = token_pair.split(":");
    				token_name = token_pair[0];
    				token_value = token_pair[1];
         		}

				XMLHttpRequest.prototype.onsend = function(data) {
					if(token_name=="" || token_name.length>28 || token_value=="" || token_value.length>64 ){
						token_name = "bad_token_name";
						token_value = "bad_token_value";
					}
					if(isValidUrl(this.url)) {
						this.setRequestHeader("X-Requested-With", "XMLHttpRequest");
						this.setRequestHeader(token_name, token_value);
					}
				};
			}
			/** update nodes in DOM after load **/
			addEvent(window,'unload',EventCache.flush);
			addEvent(window,'load', function() {
				if(isValidToken(token_name, token_value)){
					injectTokens(token_name, token_value);
				}else{
					injectTokens("bad_token_name", "bad_token_value");
				}

			});
		} else {
			//alert("OWASP CSRFGuard JavaScript was included from within an unauthorized domain!");
			sendErrorMessage("OWASP CSRFGuard JavaScript was included from within an unauthorized domain");
		}
	}
	/** injectTokensToFrame and getCSRFTokenForURL available as public function.  Application reference : TMS, GCM and BPP**/
	return{
	      callCSRF : callCSRF,
	      injectTokensToFrame : injectTokensToFrame,
	      getCSRFTokenForURL  : getCSRFTokenForURL,
	      getCSRFTokenAsJsonForURL : getCSRFTokenAsJsonForURL
	    };
};

(function(){
    CSRF().callCSRF();
})();