//Function to detect browser. NOTE: This can over-ridden by the user!! So, do not trust it completely
/*function detectBrowser() {
	var browser=navigator.appName;
	var b_version=navigator.appVersion;
	var version=parseFloat(b_version);
	alert(browser+version);
	if (!((browser=="Netscape") && (version>=4)))
	{
		alert("Your browser is currently not supported. The application may not be function correctly. Please open the web page using Mozilla Firefox.");
	}
}*/



// Function to switch images when a tab is pressed
// While making the call to this function, please use the format - "onClick="buttonpress(this.id, <the tab number starting from 0>, <total number of tabs>)"
// Make sure the id of the images is "tab#" where # is the tab number
// Make sure the name of the image is the file name without the extension

function buttonpress(tab_no, total_tabs) {
	for (i=0; i<total_tabs; i++)
		document.getElementById("tab" + i).className = "apps-tabs-active";
	document.getElementById("tab"+tab_no).className = "apps-tabs-selected";
	changeHelpImg(tab_no);	
}

// Function to get a printout of all elements in the form
function printElem() {
	for (i=0; i<document.cvoExpressForm.elements.length; i++)
		document.write(document.cvoExpressForm[i].id + '<br />');
}

function dimOff()
    {
    	document.getElementById("blanket").style.display = "none";
    }
function dimOn()
    {
             var objDiv = document.getElementById("blanket");  
             objDiv.style.display = "";   
             objDiv.style.width = document.body.scrollWidth;  
             objDiv.style.height = document.body.scrollHeight;     
    }
function activatetab(tabIndex, total_tabs)
	{
		var TabbedPanels1 = new Spry.Widget.TabbedPanels('configInput', {defaultTab:tabIndex});	
		buttonpress(tabIndex,total_tabs);
	}
function accept_disclaimer()
	{
		dimOff();
		document.getElementById("disclaimer").style.display = "none";
		document.getElementById("exportDiv").style.display = "none";	
		document.getElementById("ie6fix").style.visibility = "visible";
	}
function decline_disclaimer()
	{
		// @bug : A cleaner look in case the user declines.
		document.write("Thank you. For questions, please contact <a href=\"mailto:ask-cvo@cisco.com\">ask-cvo@cisco.com</a>.");
		document.close();
	}
function suppress_all_input_dialogs()
	{
		document.getElementById("addSubnetDiv1").style.display = "none";
		document.getElementById("addSubnetDiv2").style.display = "none";
		document.getElementById("bigPictureDiv").style.display = "none";
		document.getElementById("exportDiv").style.display = "none";
		document.getElementById("aboutbox").style.display = "none";
	}
function show_big_picture()
	{
		dimOn();
		document.getElementById("bigPictureDiv").style.display = "";
	}
function show_about_box()
	{
		dimOn();
		document.getElementById("aboutbox").style.display = "block";
	}
function hide_about_box()
	{
		dimOff();
		document.getElementById("aboutbox").style.display = "none";
	}
		
function makeExport() {
	//
	// Function to export all data filled in the form and all selections
	//
	dimOn();
	document.getElementById("exportDiv").style.display="";
	var exportString = "";
	
	// Hide the 'Import' button and show the 'Done' button
	var myButton = document.getElementById("importNow");
	myButton.value = "Done";
	myButton.onClick = function () {accept_disclaimer()};

	// Change the text - from showHide.js
	document.getElementById("expAdvice").innerHTML = exportText;

	// For each variable in the form
	for (var formIter=0; formIter < document.cvoExpressForm.elements.length; formIter++) {
		var paramType = document.cvoExpressForm.elements[formIter].type;
		var formParameter = document.cvoExpressForm.elements[formIter].id;
		var parameterValue = '';
		
		if (paramType == "button" || paramType == "textarea")
			continue;

		if (paramType == "text" || paramType == "hidden") {
			parameterValue = document.cvoExpressForm.elements[formIter].value;
			exportString += paramType+':'+formParameter+'='+parameterValue+',\n';
		}
		else if (paramType == "checkbox") {
			var checkStatus = document.getElementById(formParameter).checked.toString();
			exportString += paramType+':'+formParameter+'='+checkStatus+',\n';
		}
		else if (paramType == "select-one") {
			var mySelectBox = document.getElementById(formParameter);
			for(var i=0; i <= mySelectBox.options.length-1; i++) {
				if(mySelectBox.options[i].selected)
					break;
			} 
			exportString += paramType+':'+formParameter+'='+i.toString()+',\n';
		}
		else if (paramType == "select-multiple") {
			var mySelectBox = document.getElementById(formParameter);
			for(var i=0; i < mySelectBox.options.length; i++) {
				var dataIn = mySelectBox.options[i].value;
				exportString += paramType+':'+formParameter+'='+dataIn+',\n';
			}
		}
	}
	document.getElementById("exportText").value = exportString;
	
	// Change the value of the "Done" button
	document.getElementById("importNow").onclick = function () {accept_disclaimer()};
}

function importData() {
	dimOn();
	document.getElementById("exportDiv").style.display="";
	document.getElementById("exportText").value = "";

	// Hide the 'Import' button and show the 'Done' button
	var myButton = document.getElementById("importNow");
	myButton.src = "images/importExport/importDOWN.png";
	myButton.onClick = function () {getImport()};
	myButton.alt = "Done";

	// Change the text - from showHide.js
	document.getElementById("expAdvice").innerHTML = importText;
}


function getImport() {
	//
	// Import all data values and selections of the form from the given text
	//
	var exportString = document.getElementById("exportText").value;
	var fieldList = exportString.split(",\n");

	// Make a first run and click on all the right check-boxes
	for (var i=0; i<fieldList.length -1; i++) {
		// The above -1 is to eliminate the trailing comma
		var paramType = fieldList[i].split(":")[0];
		var elementId = fieldList[i].split(":")[1].split("=")[0];
		var elemValue = fieldList[i].split(":")[1].split("=")[1];
		var docElement = document.getElementById(elementId);
		if (paramType == "checkbox") {
			// If the current condition is unchecked and it needs
			// to be checked, then do the click event
			// If the current condition is checked and it needs
			// to be unchecked, then again do the click event
			// Otherwise there doesn't need to be a change of status
			if ((elemValue == "true" && docElement.checked == false) ||
					(elemValue == "false" && docElement.checked == true)) {
				docElement.focus();
				docElement.click();
				docElement.blur();
			}
		}
	}

	for (var i=0; i<fieldList.length -1; i++) {
		// The above -1 is to eliminate the trailing comma
		var paramType = fieldList[i].split(":")[0];
		var elementId = fieldList[i].split(":")[1].split("=")[0];
		var elemValue = fieldList[i].split(":")[1].split("=")[1];
		var docElement = document.getElementById(elementId);

		if (paramType == "text" || paramType == "hidden")
			docElement.value = elemValue;
		else if (paramType == "checkbox")
			continue;
		else if (paramType == "select-one")
			docElement.selectedIndex = elemValue;
		else if (paramType == "select-multiple" && elemValue != "") {
			docElement.style.visibility = "visible"
			var optn = document.createElement("OPTION");
			optn.text = elemValue;
			optn.value = elemValue;
			docElement.options.add(optn);
			if (length <6) 
				docElement.size +=1;
		}
	}
	accept_disclaimer();
}


function hideFields(inputCheckbox) {
	// Function to universally hide or show fields 
	// dependent upon certain checkboxes. This should be the
	// only function being called from the HTML page
	// rather than all sorts of show calls. The list of 
	// dependent variables is in another file, called showHide.js
	// Also, related checkboxes and AAA dependencies are taken
	var depFields = showHide[inputCheckbox.id];
	var aaaShow = aaaDependent[inputCheckbox.id];
	
	var hdrCheck = new RegExp(/^hdr*/);

	for (var i=0; i<depFields.length; i++) {
		if (depFields[i].match(hdrCheck)) {
			// If it is a header field, just hide it
			var myField = document.getElementById(depFields[i]);
		}
		else {
			// Ignore dummy boxes
			if (depFields[i] == "dummyBox")
				continue;
			// Else, hide the entire div related to the field
			var myField = document.getElementById('div_' + depFields[i]);
		}
		//alert(depFields[i]);
		
		if (inputCheckbox.checked == true) {
			myField.style.visibility = "visible";
			try {
				document.getElementById(depFields[i]).style.visibility = "visible";
			} catch (err) {
				var dummy = 0;
			}
		}
		else {
			myField.style.visibility = "hidden"; 
			// Try to hide the field itself if possible - if it does not exist
			// then just catch a dummy
			try {
				document.getElementById(depFields[i]).style.visibility = "hidden";
			} catch (err) {
				var dummy = 0;
			}
		}
	}

	// Call the AAA show hide function only if the current field
	// depends on the AAA values.
	if (aaaShow == true)
		show_AAA_Options(aaaShow);

	// Special call for wireless
	if (inputCheckbox.id == "client_wireless") {
		if (inputCheckbox.checked == true)
			document.getElementById('wirelessMessage').innerHTML = 'WPA Enterprise encryption enabled on wireless network. This can do EAP-PEAP with optional certificates.';
		else
			document.getElementById('wirelessMessage').innerHTML = '';

	}

	// Special call for twin hubs
	if (inputCheckbox.id == "add_mgmt_hub") {
		for (var dependent in dualHubCA) {
			if (dependent.match(hdrCheck))
				document.getElementById(dependent).innerHTML = getLabel(dependent);
			else
				document.getElementById(dependent).innerHTML = getLabel(dependent)+': '+ requiredStar;
		}
		// If two hubs are chosen, then there must be management subnets. Adding that manually to emptyVars
		// since it isn't a text field. 
		if (inputCheckbox.checked == true) {
			if (document.cvoExpressForm.sdp_mmgt.length == 0) {
				removeEmpty('sdp_mmgt');
				emptyVars.push('sdp_mmgt');
			}
			else
				removeEmpty('sdp_mmgt');
		}
		else
			removeEmpty('sdp_mmgt');
			
			
		// Hide or show the special back and next buttons
		var oppositeHide = new Array('hdndSplBack', 'hdndSplNext', 'advGenConfSpl');
		for (var oppCtr = 0; oppCtr<oppositeHide.length; oppCtr++) {
			var oppDiv = document.getElementById('div_' + oppositeHide[oppCtr]);
			if (inputCheckbox.checked == true)
				oppDiv.style.visibility = "hidden";
			else
				oppDiv.style.visibility = "visible";
		}
		
	}
	
	// If someone selects split tunneling as well, the corporate data subnets to be excluded
	// must be specified.
	if (inputCheckbox.id == "splitTunnelEnable") {
		if (inputCheckbox.checked == true) {
			if (document.cvoExpressForm.ezvpn_data_subnets.length == 0) {
				removeEmpty('ezvpn_data_subnets');
				emptyVars.push('ezvpn_data_subnets');
			}
			else
				removeEmpty('ezvpn_data_subnets');
		}
		else
			removeEmpty('ezvpn_data_subnets');
	}

	// In general, whenever a checkbox is clicked/unclicked,
	// the help image might change
	var tabIndex = TabbedPanels1.getCurrentTabIndex();
	changeHelpImg(tabIndex);
}

function pushIfEmpty (textElem) {
	// When a field is made visible, if it is a text box
	// then we add it to the list of empty variables unless it has a default value
	var myObject = document.getElementById(textElem);
	if(myObject.type == "text" )
		if (myObject.value == "" || myObject.value.match(/\s/))
			emptyVars.push(textElem);
}

function changeOnHover (myTab) {
	if (myTab.className != "apps-tabs-selected")
		myTab.className = "apps-tabs-active-on";
}

function restoreNoHover (myTab) {
		if (myTab.className != "apps-tabs-selected")
		myTab.className = "apps-tabs-active";
}

function makeImageName (tabIndex, isEZVPNHdnd) {
	// Function that returns the help image to be put
	// based on the current document condition. Also modifies the
	// hidden big picture source

	// The number of hubs - this determines the first part of the image name
	// We also keep calculating the big picture image name in parallel
	var imgName = "";
	var bigImage = "";
	if (document.getElementById("add_mgmt_hub").checked == true) {
		imgName = "two_";
		bigImage = "images/helpImgs/two_bigPicture_"; 
		document.getElementById("bigPictureDiv").style.width = "880px";
	}
	else {
		imgName = "one_";
		bigImage = "images/helpImgs/one_bigPicture_";
		document.getElementById("bigPictureDiv").style.width = "680px";
	}

	// The corporate info, configs generated and the advanced configs have the
	// same image - the small image showing the setup.
	if (tabIndex == 0 || tabIndex == 3 || tabIndex == 4) {
		imgName += "smallPicture_";
		}
	// Else it is the vpn headends tab
	else if (tabIndex == 1) {
		if (document.getElementById("add_mgmt_hub").checked == true) {
			if (isEZVPNHdnd == true)
				imgName += "vpn_";
			else
				imgName += "mgmt_";
			}
		else
			imgName += "";
		}
	// If its the spoke tab, then the next word would be 'spoke'
	else if (tabIndex == 2) {
		imgName += "spoke_";
		if (document.getElementById("client_wireless").checked == true)
			imgName += "w_wl.png";
		else
			imgName += "no_wl.png";
	}

	// Complete the image names
	var retainForSpoke = imgName;
	if (document.getElementById("CE_Enabled").checked == true) {
		imgName += "with_ce.png";
		bigImage += "with_ce.png";
		}
	else {
		imgName += "no_ce.png";
		bigImage += "no_ce.png";
	}
	// Except if its a spoke tab... then the help image name is already complete
	if (tabIndex == 2)
		imgName = retainForSpoke;

	// The big picture might change in the background whenever 
	// any small component changes.
	document.getElementById("bigPicture").src = bigImage;

	// Finally, return the new small help image name
	return imgName;
}

function changeHelpImg (tab_no, isEZVPNHdnd) {
	// Default parameter handling
	if (isEZVPNHdnd == null)
		isEZVPNHdnd = false;

	document.getElementById("helpImage").src = "images/helpImgs/" + makeImageName(tab_no, isEZVPNHdnd);
}

function helpText(helpNumber) {
	// Look up the help text in the array (stored in a separate file)
	// and change the helpBox text.
	document.getElementById("helpBox").value = helpTexts[helpNumber];
	return false;
}

function clearHelp() {
	// Clear the helpbox, typically to be called on blur
	document.getElementById("helpBox").value = "";
}


function show_AAA_Options () {
	// If any one of the wireless, auth proxy or dot1x remain checked
	// then the AAA details should remain no matter what the change to the
	// current box has been.
	var checkBoxesLinkedAll = new Array ("client_wireless", 
							"client_authproc", 
							"dot1xEnable");
	myCheckbox = document.getElementById('client_aaa');
	myCheckbox.checked= false;
	var myField="";
	for (var chkBoxCtr=0; chkBoxCtr <checkBoxesLinkedAll.length; chkBoxCtr++) {
		myField = document.getElementById(checkBoxesLinkedAll[chkBoxCtr]);
		if (myField.checked == true) {
			myCheckbox.checked = true;
			break;
		}
	}

	hideFields(myCheckbox);

}

function removeOptions(button, selectbox) {
	var i;
	var mySelectBox = document.getElementById(selectbox);

	for(i=mySelectBox.options.length-1;i>=0;i--) {
		if(mySelectBox.options[i].selected)
			mySelectBox.remove(i);
	}

	if (mySelectBox.options.length >= 6)
		mySelectBox.size = 6;
	else
		mySelectBox.size = mySelectBox.options.length;

	if (mySelectBox.options.length == 0) {
		mySelectBox.style.visibility="hidden";
		// Also add it to the list of mandatory but empty variables
		removeEmpty(selectbox);
		emptyVars.push(selectbox);
	}

	return false;
}


function addReferenceIP(button, selectbox) {
	var optn = document.createElement("OPTION");
	var net;
	var value;
	var mySelectBox = document.getElementById(selectbox);
	var length = mySelectBox.options.length;

	msg = "Enter IP address";
	//all we have to do is return the return value of the confirm() method
	net = prompt(msg);
	optn.text = net;
	optn.value = net;
	if(checkIP(net) == false)
		optn.style.color="#FF0000";
	// Mark the field as filled if there is something added
	if (!(net == "" || net.match(/^\s*$/))) {
		removeEmpty(selectbox);
	}
	mySelectBox.options.add(optn);
	if (length <6) 
		mySelectBox.size +=1;
	mySelectBox.style.visibility='visible';

	return false;
}

function addSubnet(divlayer) {
	dimOn();
	document.getElementById(divlayer).style.display="";
	return false;
}


function addSubnetData (selectbox, divlayer, form_number) {
	// Since this is called only when the subnet has been submitted, we need to remove
	// the marker that the necessary subnet is missing
	removeEmpty(selectbox);
	
	var optn = document.createElement("OPTION");
	//var selectbox = document.getElementById("hiddenSubnetSelect").value;
	var mySelectBox = document.getElementById(selectbox);
	var length = mySelectBox.options.length;
	var net = document.getElementById("addIPDiv"+form_number).value;
	var mask = document.getElementById("addNetmaskDiv"+form_number).value;
	if(checkIP(net) == false || checkMask(mask) == false)
		optn.style.color="#FF0000";
	var value = net + "/"+ mask;
	optn.text = value;
	optn.value = value;
	mySelectBox.options.add(optn);
	if (length <6) 
		mySelectBox.size +=1;
	mySelectBox.style.visibility="visible";

	net.value = "";
	mask.value = "";
	cancelSubnetAdd(divlayer, form_number);

	return false;
}

function cancelSubnetAdd (divlayer, form_number) {
	dimOff();
	document.getElementById(divlayer).style.display="none";
	document.getElementById("addIPDiv"+form_number).value = "";
	document.getElementById("addNetmaskDiv"+form_number).value = "";
	return false;
}

function convertACLSubnet(inputMask) {
	var novoArray = inputMask.split('.');
	var outputMask = "";

	outputMask = (novoArray[0] - 255)*-1 + "."+ 
				(novoArray[1] - 255)*-1 +"." + 
				(novoArray[2] - 255)*-1 + "." + 
				(novoArray[3] - 255)*-1;
	return outputMask;
}

function set_client_acct_port() {
	var s = document.getElementById("client_auth_port");
	if (s.options[s.selectedIndex].value == "1812")
		document.getElementById("client_acct_port").value = "1813";
	else
		document.getElementById("client_acct_port").value = "1646";
}

function checkIP (ipAddress) {
	// Check if the IP address passed as an argument is a valid one
	var octets = ipAddress.split(/\./g);
	if (octets.length != 4) {
		return false;
	}
	for (var i=0; i<4; i++) {
		var octetValue = octets[i];
		var matchNumber = /\d/.test(octetValue);
		if (matchNumber == false) {
			return false;
		}
		if (octetValue<0 || octetValue >255) {
			return false;
		}
	}
	return true;
}

function changeColorForIP(field) {
	// Change the color to red if the IP address is not a correct format
	// Wrapper for the checkIP function
	var myField = document.getElementById(field);
	if (checkIP(myField.value) == true)
		myField.style.color = "#000000";
	else
		myField.style.color = "#FF0000";
}

function checkMask (netMask) {
	// Check if the subnet mask passed as an argument is a valid one
	var octets = netMask.split(/\./g);
	var maskValues = new Array (255,254,252,248,240,224,192,128,0);
	if (octets.length != 4) {
		return false;
	}
	var lastOctetWas255 = true;
	for (var i=0; i<4; i++) {
		var octetValue = octets[i];
		// If this octet is not a number at all, return
		var matchNumber = /\d/.test(octetValue);
		if (matchNumber == false) {
			return false;
		}
		var passedValues = false;
		for (var j=0; j<10; j++) {
			// The number must belong to one of the values above
			if (octetValue == maskValues[j]) {
				passedValues = true;
				break;
			}
		}
		if (passedValues == false)
			return false;
		//The number can be non-255 only if the last one was 255
		//This ensures that the netmask is a continuous series of ones
		if (lastOctetWas255 == false && octetValue != 0)
			return false;
		if (octetValue != 255)
			lastOctetWas255 = false;
	}
	return true;
}

function changeColorForMask(field) {
	// Change the color to red if the subnet mask is not a correct format
	// Wrapper for the checkMask function
	var myField = document.getElementById(field);
	if (checkMask(myField.value) == true)
		myField.style.color = "#000000";
	else
		myField.style.color = "#FF0000";
}

function checkPwdLength() {
	// Change the color to red if the length of the PKI Server
	// password is not at least 8 chars
	var myField = document.getElementById("sdp_pki_passwd");
	if (myField.value.length >= 8)
		myField.style.color = "#000000";
	else
		myField.style.color = "#FF0000";
}

function restoreColorOnFocus(field) {
	// If a field is clicked for editing, restore its color to black
	var myField = document.getElementById(field);
	myField.style.color="#000000";
}	

function getTimeStamp() {
	var monthName = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	var currentTime = new Date();
	var month = monthName[currentTime.getMonth()];
	var day = currentTime.getDate();
	var year = currentTime.getFullYear();
	var hour = currentTime.getHours();
	var min = currentTime.getMinutes();
	var sec = currentTime.getSeconds();
	
	var timeString = hour+':'+min+':'+sec+" "+day+" "+month+" "+year;
	return timeString;
}

function set_time_zone_diff() {
	// Function sets the variable sdp_timezone_diff
	// by parsing the value selected in the drop down menu in the form
	var d = document.getElementById("DropDownTimezone");
	var dropDown = d.options[d.selectedIndex].value;

	// Assume there is no minus sign, and adjust if there is one
	var minusSign = "";
	var mainHr = dropDown.split("\.")[0];
	if (dropDown[0] == "-") {
		minusSign = "-";
		mainHr = dropDown.split("-")[1].split("\.")[0];
	}

	// Deal with the minutes. This needs to be converted to a
	// minute format in 0 - 59. Only values except .0 are .5 and .75
	var moreMins = dropDown.split("\.")[1];
	if (moreMins == "5")
		moreMins = "30";
	if (moreMins == "75")
		moreMins = "45";

	// Set the final field
	document.getElementById("sdp_timezone_diff").value = minusSign+ mainHr+ " "+moreMins;
}

function copyConfigLocation() {
	if(document.getElementById("auxTemplateSameLoc").checked == true) {
		// TODO: sanity checks on the location, including eliminating
		// the last '/'.
		var templLoc = document.getElementById("sdp_tftp_path").value;
		if (templLoc.substr(0,5) == "flash")
			document.getElementById("sdp_otherTemplates").value = "flash:";
		else {
			var split_on_slash = templLoc.split("/");
			var myLoc = "";
			for (var i=0; i< (split_on_slash.length-1); i++)
				myLoc += split_on_slash[i]+'/';
			document.getElementById("sdp_otherTemplates").value = myLoc;
		}
	}
	else
		document.getElementById("sdp_otherTemplates").value = "";
}

function setConfigLocation() {
	if (document.getElementById("sdp_otherTemplates").value == "flash:") {
		var readableTemplateLoc = "flash memory of the SDP Server";
	} else {
		var readableTemplateLoc = document.getElementById("sdp_otherTemplates").value;
	}
	document.getElementById("templateLoc").innerHTML = '<div class="apps-form-row-text"><div class="applabel">Please use IOS version 22.T2 or 24.T1 and above as the IOS image on the spoke</div></div>' +
	'<div class="apps-form-header">Step 3: Other Template Files</div>'+
	'<div class="apps-form-row-text"><div class="applabel">'+
	'<ol><li>Please download this file: <a href="CVO_SDP_Templates.zip">'+
	'CVO_SDP_Templates.zip</a> and unzip it.</li>'+ 
	'<li>Update the <strong>1-sdp_start.html</strong> file by modifying this section:<br />'+
	'<p><span class="apps-form-hint">'+
	'\/\/\/\/\/\/ Webpage mandatory HTML constant \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br />'+
'constants["testConnectionPage"] = "http:\/\/your_corporate_internal_homepage"<br />'+
'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br />'+
'<br />'+
'\/\/\/\/\/\/ Webpage Optional HTML constant \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br />'+
'\/\/\/\/\/\/ ASCII character only \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/<br />'+
'constants["companyImageSource"] = "https:\/\/www.cisco.com\/swa\/i\/logo.gif";<br />'+
'constants["smallHeader"] = "Zero-touch Configuration";<br />'+
'constants["bigHeader"] = "Welcome to Cisco Virtual Office (CVO)";<br />'+
'constants["banner"] = "Welcome!";<br />'+
'constants["progressBarTimer"] = 210000; \/\/ Time to fully fill progress bar in milliseconds<br />'+
'constants["supportEmail"] = "cvo-admin@company.com";<br />'+
'\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/</span></p></li>'+
	'<li>Save these template files as they are in the location <span style="color:#000000; font-weight:bold">'+
	readableTemplateLoc +'</span>. '+
	'If you choose to change this location, please modify the <em>SDP template files location</em> in the VPN Headend section under the <em><u>Advanced Options</u></em> tab'+
	'</li></ol></div></div>';

	var enrollString = 'https://'+document.getElementById("sdp_wan_ip").value+'/ezsdd/intro';
	
	var sRM = document.getElementById("spokeRouter");
	var spokeRouterModel = sRM.options[sRM.selectedIndex].value;
	var spoke_wan_int = wanInt[spokeRouterModel];
	var port_to_connect_PC = connectPC[spokeRouterModel];

	document.getElementById("testConnection").innerHTML = '<div class="apps-form-header">Step 4: Remote Device Provisioning</div>'+
	'<div class="apps-form-row-text"><div class="applabel"><ol><li>Make sure the remote device has the <em>"CVO Default"</em> config on it. </li>'+
	'<li>Connect the '+spoke_wan_int+' interface of the router to your ISP device, and '+port_to_connect_PC+' interface to your PC</li>'+
	'<li>Type the url <a href="'+enrollString+'" target="_blank">'+enrollString+'</a> into your browser</li>'+
	'<li>Type in the username and password <em>'+document.getElementById("sdp_local_username").value+'/'+
	  document.getElementById("sdp_local_password").value+'</em> when prompted. To change these credentials, please modify'+
	  ' the "Username" and "Password" fields under the VPN Headends tab.</li>'+
	'<li>If prompted for credentials again, please enter <em>cisco/cisco</em></li>'+ 
	'<li>In a few minutes, your router will be provisioned.</li></ol></div></div>';
}

function noCommas(field) {
	var myCertField = field.value;
	var noCommaRegex = new RegExp (".?,.?");

	if (noCommaRegex.test(myCertField) == true)
		field.style.color="#FF0000";
}

function hideWireless() {
	// If its not an 871, unclick wireless and declare no-can-do
	var s = document.getElementById("spokeRouter");
	var spokeVal = s.options[s.selectedIndex].value;
	var wirelessChecked = document.getElementById("client_wireless").checked;
	if (spokeVal == "881" || spokeVal == "891") {
		if (wirelessChecked == true)
			document.getElementById("client_wireless").click();
		document.getElementById("client_wireless").style.visibility="hidden";
		document.getElementById("sorryNoWireless").innerHTML="Wireless functionality is currently not supported on the 881 &amp; 891 platforms";
	}
	else if (spokeVal == "871" || spokeVal == "1811") {
		document.getElementById("client_wireless").style.visibility="visible";
		document.getElementById("sorryNoWireless").innerHTML="";
	}
}

function daylightTimeZone() {
	// Clear the daylight saving time if any other time zone is selected
	var s = document.getElementById("DropDownTimezone");
	var tz = s.options[s.selectedIndex].value;
	var summerTime = document.getElementById("sdp_summer_time_zone");
	if (tz != "-8.0")
		summerTime.value = '';
	else
		summerTime.value = "PDT";
}

function checkWirelessNoSpace() {
	var w= document.getElementById("wireless_ssid");
	if (w.value.match(/\s/)) {
		w.style.color = "#FF0000";
		helpText(29);
	}
	else
		w.style.color = "#000000";
}

var retainFTPValue = "ftp://";
function changedCertLoc (myElem) {
	if (myElem.value != "flash:") {
		document.getElementById("div_sdp_cert_path").style.visibility="visible";		
		document.getElementById("div_sdp_cert_user").style.visibility="visible";
		document.getElementById("div_sdp_cert_pwd").style.visibility="visible";
		document.getElementById("div_sdp_flashCertDir").style.visibility = "hidden";
		document.getElementById("sdp_cert_path").value=retainFTPValue;
		// If the user chooses it to be an ftp server, then this can be empty
		removeEmpty("sdp_flashCertDir");
	} else {
		document.getElementById("div_sdp_cert_path").style.visibility="hidden";
		document.getElementById("div_sdp_cert_user").style.visibility="hidden";		
		document.getElementById("div_sdp_cert_pwd").style.visibility="hidden";
		document.getElementById("div_sdp_flashCertDir").style.visibility = "visible";
		retainFTPValue = document.getElementById("sdp_cert_path").value;
		document.getElementById("sdp_cert_path").value="flash:";
		// The field must be filled if the disk storage is chosen
		onBlurMandatory(document.getElementById("sdp_flashCertDir"));
	}
}

function setDiskPath () {
	// Hack for the certificate server storage if this is a 7206
	var ca_server = document.getElementById("sdp_router");
	var cert_storage = ca_server.options[ca_server.selectedIndex].value;
	var myElem = document.cvoExpressForm.sdp_cert_store;
	var diskPath = "";

	for (var i=0; i < myElem.length; i++) {
		if (myElem[i].checked)
			diskPath = myElem[i].value;
	}
	
	if (cert_storage == "gi 0/1" && diskPath == "flash:")
		diskPath = "disk2:";

	if (diskPath == "flash:" || diskPath =="disk2:") {
		var storeCertHere = diskPath + "/" + document.getElementById("sdp_flashCertDir").value + "/";
		document.getElementById("sdp_cert_path").value = storeCertHere;
	}
	
	// Also, if the path where the template config files
	// will be stored is set to flash:, then it must change
	var templatePath = document.getElementById("sdp_tftp_path").value;
	if (templatePath.match(/^flash:*/) && cert_storage == "gi 0/1") {
		var templ_filename = templatePath.split(/^flash:/)[1];
		document.getElementById("sdp_tftp_path").value = "disk2:"+templ_filename;
	}
	
	// This is where the spoke configs are stored
	if (cert_storage == "gi 0/1" && document.getElementById("sdp_otherTemplates").value == "flash:")
		document.getElementById("sdp_otherTemplates").value = "disk2:";
}


function onBlurMandatory (myObject) {
	// To be called from any input text box
	// when its a mandatory field. If a blank input is detected
	// it will change the class and color of the corresponding label as well
	var myLabel = document.getElementById('lbl_' + myObject.id);

	///////////// The selectboxes like NTP servers
	if (myObject.type == "select-multiple" || myObject.type == "select-one") {
		if (myObject.length == 0) {
			myLabel.className="apps-form-label-error";
			myLabel.innerHTML = errorCross + getLabel(myLabel.id)+': ' + requiredStar;
			removeEmpty(myObject.id);
			emptyVars.push(myObject.id);
		} else {
			myLabel.className="apps-form-label"; 
			myLabel.innerHTML = labelLookup[myLabel.id] + requiredStar;			
			removeEmpty(myObject.id);
		}
	}

	if (myObject.type == "text") {
		if(myObject.value == "" || myObject.value.match(/^\s*$/)) {
			// Error
			myLabel.className="apps-form-label-error";
			myLabel.innerHTML = errorCross + getLabel(myLabel.id)+': ' + requiredStar;
			// Just to make sure that this object isn't present from the outset
			removeEmpty(myObject.id);
			emptyVars.push(myObject.id);
		} else {
			// No error
			myLabel.className="apps-form-label"; 
			myLabel.innerHTML = labelLookup[myLabel.id] + requiredStar;
			removeEmpty(myObject.id);
		}
	}
}

function removeEmpty (elemId) {
	// Function to remove an object id once it has been 
	// verified by the onBlurMandatory() function to be
	// non - empty.
	fullArrayLen = emptyVars.length
	var copyArray = new Array();
	for (var i=0; i<fullArrayLen; i++) {
		if (emptyVars[i] == elemId) 
			continue;
		else
			copyArray.push(emptyVars[i]);
	}
	emptyVars = copyArray;
}

function getLabel(object_id) {
	// Returns the correct label text associated with any object id
	// after consulting the status of the number of hubs being designed
	var depends_2hub = false;
	var mapped_object = '';
	// Is the label to be borrowed from the EZVPN labels?
	for (var dependent in dualHubCA) {
		if (object_id == dependent) {
			depends_2hub = true;
			mapped_object = dualHubCA[dependent];
			break;
		}
	}
	
	// NOTE that we're ignoring the visiblity aspect - thats handled by the div itself
	// If a call has been made to this function, then it IS visible


	// If it has no relation with two hubs being enabled
	if (depends_2hub == false)
		return labelLookup[object_id];
	else {
		// If it depends, and we have only one hub, then it borrows the label from EZVPN
		if (document.getElementById('add_mgmt_hub').checked == false)
			return labelLookup[mapped_object];
		else
			return labelLookup[object_id];
	}
}

// Although we start off with a pre-defined set of variables that are free,
// the user can refresh the form after filling in data in which case
// the fields already filled in need to be removed. This function does that.
function checkEmptyVarsOnLoad() {
	var copy = new Array();
	copy = emptyVars;
	emptyVars=[];
	for (var i=0; i<copy.length; i++) {
		// If it is a select-box, then just check its length
		if (document.getElementById(copy[i]).type == 'select-one' || document.getElementById(copy[i]).type == 'select-multiple') {
			if (document.getElementById(copy[i]).options.length == 0)
				emptyVars.push(copy[i]);
			continue;
		}
		// Else see the data content (i.e. most likely a text-box)
		var valueNow = document.getElementById(copy[i]).value;
		if(valueNow == "" || valueNow.match(/^\s*$/))
			emptyVars.push(copy[i]);
	}
}

//////////////////////////////////////////////////////////
/////	  MAIN CONFIGURATION GENERATION FUNCTION	//////
//////////////////////////////////////////////////////////

function testResults (cvoExpressForm) {

	// Change the help text
	helpText(27);
	checkEmptyVarsOnLoad();
	// Verify all mandatory fields are filled
	// The mandatoryViolation variable will be displayed at the beginning of the 
	// router configs tab when the configs are generated
	var mandatoryViolation = '';
	var numEmpty = emptyVars.length;
	if (numEmpty != 0) {
		mandatoryViolation = '<div class="apps-form-header" style="color:#990000">Errors</div>'+
			'<div class="applabel" style="color: #990000">You have not filled in the following mandatory field(s):'+
			'<ol style="color: #990000">';
		for (emptyCtr =0; emptyCtr < numEmpty; emptyCtr++) {
			try {
				mandatoryViolation = mandatoryViolation + '<li><span style="color: #990000"> '+ getLabel('lbl_'+emptyVars[emptyCtr]) +' </span></li>';
			} catch (err) {
				alert("Label for "+emptyVars[emptyCtr]+" not found.");
			}
		}
		mandatoryViolation = mandatoryViolation + '</ol>The configurations generated below may not be correct.</div>';
	}

	var scriptFiles = new Array (authproxy_Data, //0
		client_Data, //1
		dot1x_Data, //2
		ezvpn_Data, //3
		sdp_Data, //4
		split_tunnel_Data, //5
		wireless_Data, //6
		bottomEvents_Data, //7
		ce_Data, //8
		policyBased_Data, //9
		aaa_Data,//10
		secondVI_Data,//11				Please note that these
		second_ipsecClient_Data,//12	(last four) data string variables
		second_bvi1_Data,//13			are actually imported from the same
		second_eem_Data,//14			file called secondHub.js
        second_VI_QOS_Data,//15
		dot1x_dependent_Data);//16
	////////////////////// Hidden field manipulations
	set_client_acct_port();
	set_time_zone_diff();
	setConfigLocation();
	setDiskPath();

	// For each file
	for (var fileIter = 0; fileIter < scriptFiles.length; fileIter++) {
		currentFile = scriptFiles[fileIter];

		// For each variable in the form
		for (var formIter=0; formIter < document.cvoExpressForm.elements.length; formIter++) {
			var formParameter = document.cvoExpressForm.elements[formIter].name;
			var parameterValue = document.cvoExpressForm.elements[formIter].value;
			
			// For form parameters without names, such as buttons, we skip ahead
			if (formParameter == null || formParameter == '')
				continue;
			
			var myRegExp = new RegExp (formParameter, "g");
			currentFile = currentFile.replace(myRegExp, parameterValue);
		}

		scriptFiles[fileIter] = currentFile;
	}

	///////////////////////////////////////////////////// 
	////////////        SDP Server config    ////////////
	/////////////////////////////////////////////////////

	var sdpConfig = scriptFiles[4];
	
	// If the value of the storage location is not "flash:", then
	// we need a username/password to access the ftp or tftp server
	var cert_login = "";
	var create_certDir = "";
	var certificate_storage_path = document.getElementById("sdp_cert_path").value;
	if (!(certificate_storage_path.match(/^flash:*/) || certificate_storage_path.match(/^disk2:*/))) {
		cert_user = document.getElementById("sdp_cert_user").value;
		cert_pwd = document.getElementById("sdp_cert_pwd").value;
		cert_login = " ip ftp username "+cert_user+"\n ip ftp password "+cert_pwd;
	}
	else {
		// Create the directory where the certs will be stored
		create_certDir = "mkdir "+certificate_storage_path + "\n\n";
	}
	
	sdpConfig = sdpConfig.replace("!!!Database access credentials", cert_login);
	sdpConfig = sdpConfig.replace("!!!Make cert directory", create_certDir);
	
	// Set the server as a temporary NTP server with low priority
	var setMyClock = "clock set "+getTimeStamp();
	sdpConfig = sdpConfig.replace("!!!Clock set", setMyClock);
	
	// The management server ACL needs to be mandatory no matter what
	// Please note that we are assuming the management subnets to be mandatory
	var sdpMmgtACLContent = "";
	var sdpMmgtACLReference = "";

	////////////// Only if split tunneling is enabled or a second hub added
	////////////// will the following be added to the SDP config
	if (document.getElementById("splitTunnelEnable").checked == true ||
		document.getElementById("add_mgmt_hub").checked == true) {
		var sdpACLName = document.cvoExpressForm.sdp_mmgt_acl_name.value;
		sdpMmgtACLReference = "acl "+sdpACLName+" \n";

		if (document.getElementById("add_mgmt_hub").checked == true)
			var aclSubnetsToConsider = document.getElementById("sdp_mmgt");
		else
			var aclSubnetsToConsider = document.getElementById("ezvpn_data_subnets");
	
		sdpMmgtACLContent = "ip access-list extended "+sdpACLName+" \n";
		if (aclSubnetsToConsider.length >0) {
			for (var sdpACLCtr=0; sdpACLCtr<aclSubnetsToConsider.length; sdpACLCtr++) {
				var mmgtSubnet = aclSubnetsToConsider[sdpACLCtr].value;
				var mmgtNetwork = mmgtSubnet.split("/")[0];
				var mmgtNetmask = mmgtSubnet.split("/")[1];
		
				sdpMmgtACLContent += "permit ip "+ mmgtNetwork + " " +
								convertACLSubnet(mmgtNetmask) + " any\n";
			}
		}
	}
	sdpConfig = sdpConfig.replace("!!!SDP Management ACL", sdpMmgtACLReference);
	sdpConfig = sdpConfig.replace("!!!SDP Mmgt ACL Content", sdpMmgtACLContent);
	
	// Adding code for additional NTP servers
	// which will be duplicated at the EZVPN and the client configs
	var addNTPServersACL = "";
	var addNTPServersIP = "";
	for (var ntpCtr =0; ntpCtr < document.cvoExpressForm.sdp_ntp_srvrs.length; ntpCtr++) {
		ntpIP = document.cvoExpressForm.sdp_ntp_srvrs[ntpCtr].value;
		addNTPServersACL = addNTPServersACL +"permit udp host "+ntpIP+" eq ntp any\n";
		addNTPServersIP = addNTPServersIP + "ntp server "+ntpIP + " iburst" +"\n";
	}
	sdpConfig = sdpConfig.replace("!!!Additional NTP Servers", addNTPServersIP);

	//////////////////////////// Add username password if the template config is restricted
	var configCredentials = "";
	if (document.getElementById("sdp_tftp_user_yes_no").checked == true) {
		var user = document.getElementById("sdp_tftp_username").value;
		var pwd = document.getElementById("sdp_tftp_passwd").value;
		configCredentials = "template username "+user;
		if (pwd != "")
			configCredentials += " password "+pwd;
	}
	sdpConfig = sdpConfig.replace("!!!Template config credentials", configCredentials);


	///////////////////////////////////////////////////// 
	////////////      EZVPN Server config    ////////////
	/////////////////////////////////////////////////////

	var ezvpnConfig = scriptFiles[3];
	// In case of split tunneling, add the ACL to the 
	// ISAKMP client config group and create it
	var ezvpnMmgtACLContent = "";
	var ezvpnMmgtACLReference = "";
	if (document.cvoExpressForm.splitTunnelEnable.checked == true 
		&& document.cvoExpressForm.ezvpn_data_subnets.length > 0) {
		var ezvpnACLName = document.cvoExpressForm.ezvpn_mmgt_acl_name.value;
		ezvpnMmgtACLReference = "acl "+ezvpnACLName+" \n";

		ezvpnMmgtACLContent = "ip access-list extended "+ezvpnACLName+" \n";
		if (document.cvoExpressForm.ezvpn_data_subnets.length > 0) {
			for (var ezvpnACLCtr=0; ezvpnACLCtr<document.cvoExpressForm.ezvpn_data_subnets.length; ezvpnACLCtr++) {
				var mmgtSubnet = document.cvoExpressForm.ezvpn_data_subnets[ezvpnACLCtr].value;
				var mmgtNetwork = mmgtSubnet.split("/")[0];
				var mmgtNetmask = mmgtSubnet.split("/")[1];
	
				ezvpnMmgtACLContent += "permit ip "+ mmgtNetwork + " " +
								convertACLSubnet(mmgtNetmask) + " any\n";
			}
		}
	}	
	ezvpnConfig = ezvpnConfig.replace("!!!EZVPN Management ACL Ref", ezvpnMmgtACLReference);
	ezvpnConfig = ezvpnConfig.replace("!!!EZVPN Mmgt ACL Content", ezvpnMmgtACLContent);
	// From the SDP advanced config input
	ezvpnConfig = ezvpnConfig.replace("!!!Additional NTP Servers", addNTPServersIP);
	ezvpnConfig = ezvpnConfig.replace("!!!Clock set", setMyClock);

	///////////////////////////////////////////////////// 
	//////////      Client template config    ///////////
	/////////////////////////////////////////////////////

	// For the client, you begin with the basic config, and then
	// keep adding as per the values set on the checkboxes
	var clientConfig = scriptFiles[1];
	if (document.cvoExpressForm.dot1xEnable.checked == true) {
		clientConfig += scriptFiles[2];
	}
	if (document.cvoExpressForm.client_authproc.checked == true) {
		clientConfig += scriptFiles[0];
	}
	if (document.cvoExpressForm.client_wireless.checked == true) {
		clientConfig += scriptFiles[6];
	}
	if (document.cvoExpressForm.CE_Enabled.checked == true) {
		clientConfig += scriptFiles[8];
	}

	//////////////////////////// Voice Servers
	var addVoiceServers = "";
	if (document.getElementById("enableVoice").checked == true) {
		for (var voiceCtr =0; voiceCtr < document.cvoExpressForm.voice_srvrs.length; voiceCtr++) {
			voiceIP = document.cvoExpressForm.voice_srvrs[voiceCtr].value;
			addVoiceServers = addVoiceServers +" p t a h "+voiceIP+" eq www\n";
		}
	}
	clientConfig = clientConfig.replace(/!!!Additional Voice Servers/g, addVoiceServers);


	//////////////////////////// NAT changes for split tunneling
	var natACL_10_subnet = "";
	if (document.cvoExpressForm.splitTunnelEnable.checked == true) {
		natACL_10_subnet = "permit ip 10.1.1.0 0.0.0.255 any"
	} 
	clientConfig = clientConfig.replace(/!!!Add 10 subnet/g, natACL_10_subnet);

	//////////////////////////// Option 150 TFTP IP to be optionally included
	var CUCM_present = "";
	if (document.cvoExpressForm.haveCUCM.checked == true) {
		CUCM_present = "option 150 ip "+document.getElementById("client_pool_150_ip").value;
	} 
	clientConfig = clientConfig.replace(/!!!Add Call Manager IP/g, CUCM_present);

	//////////////////////////// If ssh is enabled, add additional line to ACL
	var sshEnabledString = "";
	if (document.cvoExpressForm.client_allow_ssh.checked == true) {
		sshEnabledString = "permit tcp any any eq 22";
	} 
	clientConfig = clientConfig.replace("!!!Allow SSH", sshEnabledString);

	//////////////////////////// From the SDP advanced config input add NTP servers
	clientConfig = clientConfig.replace("!!!Additional NTP Servers", addNTPServersIP);
	clientConfig = clientConfig.replace("!!!Additional NTP Servers ACL", addNTPServersACL);

	//////////////////////////// Add policy based routing in case split tunneling is disabled
	var policyConfig = scriptFiles[9];
	var addPolicy = "";
	if (document.cvoExpressForm.splitTunnelEnable.checked == false)
		addPolicy = policyConfig;
	clientConfig = clientConfig.replace("!!!Policy based routing", addPolicy);

	//////////////////////////// AAA data goes in only for any of wireless or dot1x or authproxy
	var aaaConfig = scriptFiles[10];
	var addAAA = "";
	if (document.cvoExpressForm.client_wireless.checked == true ||
		document.cvoExpressForm.client_authproc.checked == true ||
		document.cvoExpressForm.dot1xEnable.checked == true)
		addAAA = aaaConfig;
	clientConfig = clientConfig.replace("!!!AAA Data", addAAA);

	//////////////////////////// Auth Proxy additional configs
	var authP_ACL = "";
	var authP_inbound_ACL = "";
	if (document.cvoExpressForm.client_authproc.checked == true) {
		///////////// With split tunneling
		if (document.cvoExpressForm.splitTunnelEnable.checked == true) {
			var permitNW = "";
			var denyNW = "";
			var mmgtNets = "";
			var corpNets = "";
		
			////// All management subnets in the permit section
			if (document.cvoExpressForm.sdp_mmgt.length > 0) {
				for (var authpCtr =0; authpCtr < document.cvoExpressForm.sdp_mmgt.length; authpCtr++) {
					permitNW = document.cvoExpressForm.sdp_mmgt[authpCtr].value;
					var permitAuthpSubnet = permitNW.split("/")[0];
					var permitAuthpNetmask = permitNW.split("/")[1];
					mmgtNets = mmgtNets +"permit tcp any "+permitAuthpSubnet+" "+convertACLSubnet(permitAuthpNetmask)+" eq www 443\n";
				}
			}
		
			////// All data subnets in the permit section
			if (document.cvoExpressForm.ezvpn_data_subnets.length > 0) {
				for (var authpCtr =0; authpCtr < document.cvoExpressForm.ezvpn_data_subnets.length; authpCtr++) {
					permitNW = document.cvoExpressForm.ezvpn_data_subnets[authpCtr].value;
					var permitAuthpSubnet = permitNW.split("/")[0];
					var permitAuthpNetmask = permitNW.split("/")[1];
					corpNets = corpNets +"permit tcp any "+permitAuthpSubnet+" "+convertACLSubnet(permitAuthpNetmask)+" eq www 443\n";
				}
			}

			authP_ACL = mmgtNets + corpNets;
			var additionalNets = "";

			////// All data subnets also go into the deny section
			if (document.cvoExpressForm.ezvpn_data_subnets.length > 0) {
				for (var authpCtr =0; authpCtr < document.cvoExpressForm.ezvpn_data_subnets.length; authpCtr++) {
					denyNW = document.cvoExpressForm.ezvpn_data_subnets[authpCtr].value;
					var denyAuthpSubnet = denyNW.split("/")[0];
					var denyAuthpNetmask = denyNW.split("/")[1];
					additionalNets = additionalNets +"deny ip any "+denyAuthpSubnet+" "+convertACLSubnet(denyAuthpNetmask)+" \n";
				}
			}
			authP_inbound_ACL = additionalNets;
			authP_inbound_ACL += "permit ip any any\n\n";
		}
			
		///////////// Without split tunneling
		else {
			authP_ACL = "permit tcp any any eq www 443";
			authP_inbound_ACL = "deny ip any any";
		}
	}
	clientConfig = clientConfig.replace("!!!Auth Proxy deny list", authP_ACL);
	clientConfig = clientConfig.replace("!!!Auth Proxy inbound ACL", authP_inbound_ACL);

	// Close off the client code and append the EEM Script data
	var lastEEMScript = scriptFiles[7];
	clientConfig += lastEEMScript;
	clientConfig += "\nend";
	
	// Change to include the EEM for Auth Proxy
	var includeAuthP_EEM = "";
	if (document.cvoExpressForm.client_authproc.checked == true)
		includeAuthP_EEM = 'action a41 cli command "ip access-group auth_proxy_inbound_acl in"\n action a42 cli command "ip admission pxy"';
	clientConfig = clientConfig.replace("!!!Auth proxy action", includeAuthP_EEM);
	
	//Change to include the EEM for dot1x
	var includeDot1x_EEM = "";
	if (document.cvoExpressForm.dot1xEnable.checked == true)
	     includeDot1x_EEM = 'action a23 cli command "dot1x pae authenticator"\n action a24 cli command "dot1x port-control auto"\n action a25 cli command "dot1x reauthentication"\n action a26 cli command "dot1x guest-vlan 20"\n action a27 cli command "dot1x auth-fail vlan 20"';
    clientConfig = clientConfig.replace("!!!Dot1x action", includeDot1x_EEM);
	
	///////////// The default assumption is that we are going to have a single
	///////////// hub configured. The following gets added to the client config
	///////////// only if the secondary management hub is selected
	var secondVI = "";
	var second_ipsecClient = "";
	var second_bvi1 = "";
	var second_eem = "";
	var second_VI_QOS = "";

	if (document.getElementById("add_mgmt_hub").checked == true) {
		secondVI = scriptFiles[11];
		second_ipsecClient = scriptFiles[12];
		second_bvi1 = scriptFiles[13];
		second_eem = scriptFiles[14];
		second_VI_QOS = scriptFiles[15];
	}
	clientConfig = clientConfig.replace(/!!!Add EZVPN Primary hub interface/g, secondVI);
	clientConfig = clientConfig.replace(/!!!Add EZVPN Primary hub ipsec client/g, second_ipsecClient);
	clientConfig = clientConfig.replace(/!!!Add EZVPN Primary hub ipsec nat/g, second_bvi1);
	clientConfig = clientConfig.replace(/!!!Add EZVPN Primary hub cli command/g, second_eem);
	clientConfig = clientConfig.replace(/!!!Add EZVPN Primary hub virtual interface 2 qos command/g, second_VI_QOS);

	//////////////////////////// Dot1x dependent interface config
	var dot1xDepIntConfig = "";
	if (document.getElementById("dot1xEnable").checked == false)
		dot1xDepIntConfig = dot1x_dependent_Data;
	clientConfig = clientConfig.replace(/!!!Dot1x dependent configs for interfaces/g, dot1xDepIntConfig);


	//////////////////////////// Spoke hack for router type
	var sRM = document.getElementById("spokeRouter");
	var spokeRouterModel = sRM.options[sRM.selectedIndex].value;
	if (spokeRouterModel == "871" || spokeRouterModel == "1811")
		var spoke_871_881 = "bvi1";
	else if (spokeRouterModel == "881" || spokeRouterModel == "891")
		var spoke_871_881 = "vlan10";
	clientConfig = clientConfig.replace (/spoke_871_881/g, spoke_871_881);
	// Replace the wan interface, using values from the wanInt array defined in showHide
	clientConfig = clientConfig.replace (/spoke_wan_interface/g, wanInt[spokeRouterModel]);
	var corpStart = corpLan[spokeRouterModel].split('-')[0];
	var corpEnd = corpLan[spokeRouterModel].split('-')[1];
	var guestStart = guestLan[spokeRouterModel].split('-')[0];
	var guestEnd = guestLan[spokeRouterModel].split('-')[1];
	clientConfig = clientConfig.replace (/corpStart/g, corpStart);
	clientConfig = clientConfig.replace (/corpEnd/g, corpEnd);
	clientConfig = clientConfig.replace (/guestStart/g, guestStart);
	clientConfig = clientConfig.replace (/guestEnd/g, guestEnd);

	//////////////////////////// Replace the text for spoke router model
	var repl_881 = new RegExp ("!!!Spoke 881 on change", "g");
	var select_871_value = spoke_871_881;

	// First substitute for whatever appears if 881 is chosen
	// Note: in the HTML file, we've kept 871 as bvi1 and 881 as vlan10
	// for easy replacement during the entire search-and-replace globally
	if (select_871_value == "bvi1") {
		var replText = "";
		var makeVlan10 = ""; 
	}
	else {
		var replText = "switchport access vlan 10";
		var makeVlan10 = "vlan 10\n state active\nint vlan 10\n no autostate";
	}
	clientConfig = clientConfig.replace(repl_881, replText);
	clientConfig = clientConfig.replace(/!!!Create vlan 10 for 881/g, makeVlan10);

	// Then remove for 881 and put in for 871
	for (var ctr_871=0; ctr_871 < spoke_881_off.length; ctr_871 ++) {
		if (select_871_value == "bvi1")
			var on_871_text = spoke_881_off[ctr_871];
		else
			var on_871_text = "";
		clientConfig = clientConfig.replace("!!!Spoke 881 off change "+ (ctr_871 +1).toString(), on_871_text);
	}
	

	/////////////////////////////// Finally, generate and put the configs
	for (var showHeaders = 0; showHeaders<3; showHeaders++) {
		var myHeader = document.getElementById(show_generated_configs[showHeaders]);
		myHeader.style.visibility = "visible";
	}
	
	var server1Label = document.getElementById("hdr_configGen_Mgmt");
	var server2Label = document.getElementById("hdr_configGen_VPN");
	var spokeLabel = document.getElementById("hdr_configGen_Spoke");
	var copyPasteLabel = document.getElementById("copyPasteConfig");
	var saveLabel = document.getElementById("saveConfig");

	if (document.getElementById("add_mgmt_hub").checked == true) {
		server1Label.innerHTML = "Management Headend Configuration";
		server2Label.innerHTML = "VPN Headend Configuration";
		// The primary EZVPN server config and labels show up only if
		// a second hub has been selected.
		document.cvoExpressForm.ezvpnOutput_1.rows=10;
		document.cvoExpressForm.ezvpnOutput_1.value=ezvpnConfig;
		document.cvoExpressForm.ezvpnOutput_1.style.visibility="visible";
	}
	else {
		server1Label.innerHTML = "VPN Headend Configuration";
		server2Label.innerHTML = "";
		document.cvoExpressForm.ezvpnOutput_1.rows=1;
		document.cvoExpressForm.ezvpnOutput_1.value='';
		document.cvoExpressForm.ezvpnOutput_1.style.visibility="hidden";
	}	
	
	document.getElementById("grantCertText").style.visibility="visible";
	
	spokeLabel.innerHTML = "Step 2: Spoke Configuration";

	document.cvoExpressForm.sdpOutput_1.rows=10;
	document.cvoExpressForm.sdpOutput_1.value=sdpConfig;
	document.cvoExpressForm.sdpOutput_1.style.visibility="visible";
	
	var saveFileLoc = document.getElementById("sdp_tftp_path").value;
	//alert(saveFileLoc);
	var readableFileLoc = "";
	if (saveFileLoc == 'flash:spoke.cfg') {
		readableFileLoc = 'flash: on the SDP server, with filename "spoke.cfg"';
	} else if (saveFileLoc == 'disk2:spoke.cfg') {
		readableFileLoc = 'disk2: on the SDP server, with filename "spoke.cfg"';
	} else {
		readableFileLoc = saveFileLoc;
	}
	
	copyPasteLabel.innerHTML=mandatoryViolation+'<div class="apps-form-header">Step 1: Headend Configuration(s)'+
	'</div><div class="applabel">The time and date on the headend router configuration(s) has been hardcoded below based on' +
	  ' the system browser time on this PC/laptop. We recommend that you paste the configs <em>immediately</em>. If you ' +
	  'wish to do this at a later time, please update the "<em>clock set</em>" lines at the beginning of the '+
	  'headend config(s). <br /><br />You must <em><u>copy and paste</u></em> '+
	  'the following config(s) into your headend routers at the command line interface.</div>';
	saveLabel.innerHTML="Please <em><u>save</u></em> the following config in the location <strong>"+readableFileLoc+"</strong>. "+
	  "If you choose to change this location, please modify the <em>Location</em> field "+
	  "under the <em>VPN Headends</em> tab, or modify the following line <em><u>(in the SDP Server config)</u></em> to point to the desired location."+
	  "<p><span style='font-family:\"Courier New\"; color:#000000' size='10'>template config "+saveFileLoc+"</span></p>"+
	  "This file does not need to be pasted into the CLI but will be automatically pushed to the spoke through using Secure Device Provisioning (SDP) during the provisioning process.";

	document.cvoExpressForm.clientOutput_1.rows=10;
	document.cvoExpressForm.clientOutput_1.value=clientConfig;
	document.cvoExpressForm.clientOutput_1.style.visibility="visible";

	// Update last generated timestamp
	document.getElementById("lastGenerated").innerHTML = "Last generated: "+getTimeStamp();

	return false;
}

