/*
login.js, by Scriptar
Do whatever you want with it.

This JS file must be accessed through a server because it will not
be able to access local files though XMLHttpRequest() to check for existence.
Also, there needs to be a status code, which is provided by a web server.

Typical Usage:

<div id="login"></div>
<script type="text/javascript">
window.onload = function() {
	loginApp.initLoginForm({container: "login"});
};
</script>

It is possible to replace and override the doLogin() and displayFailure() methods
(or any others) by setting them to your own methods. For example:

loginApp.doLogin = function(url) {
	alert("You guessed the password.");
};

or:

loginApp.displayFailure = function(msg) {
	document.getElementById("errMsg").innerHTML = msg; 
};

Possible arguments to loginApp.initLoginForm({...}):

container (string)
	Required. The CSS ID of your login form container.
	Ex: <div id="login"></div> where container = "login"

classtoadd	(string)
	Optional. This CSS class will be added to your container on init.
	This argument would be used when a custom form already exists but starts off hidden.
	Ex: div#login.show {display: block;} where classtoadd = "show"

usernameprompt (string)
	If not provided, defaults to "User Name:".
	If empty string, username prompt will not be visible.

passwordprompt (string)
	If not provided, defaults to "Password:".
	If empty string, password prompt will not be visible.
	If both usernameprompt and passwordprompt are empty strings, be sure to provide an classtoadd and an existing form.

loginHTML (string)
	Optional. Use this only if you wanted to pass in your own login form XHTML (better to use classtoadd instead).

invalidpassword (string)
	Text to alert() when user enters an invalid username and/or password.
	Defaults to: "Sorry, wrong password."

urlprefix (string)
	If the prefix is an empty string (default), it will look in the page's directory.
	The prefix should lead to a relative directory, not http or https (must have same origin.)

urlsuffix (string)
	This is appended to the end of the hash. Defaults to ".html"
	URLs take the following form:
	urlprefix + hash(of username and/or password) + urlsuffix
	Ex: "" + "5f4dcc3b5aa765d61d8327deb882cf99" + ".html"

md5url (string)
	Use this to change the default location of the required md5.js file before the initial call to initMD5().
	A better idea is to include the following in your own pages:
	<script type="text/javascript" src="md5.js"></script>
	md5.js can be downloaded from: http://pajhome.org.uk/crypt/md5/

*/
var loginApp = {
	prefix: "",
	suffix: ".html",
	md5url: "",
	invalidPasswordMsg: "Sorry, wrong password.",
	doLogin: function(url, pageexists) {
		// if the file exists, go to it.
		if (!pageexists) {
			alert("Unable to verify page location. Attempting redirect.");
		}
		// TODO: initialize cookies session variables?
		location.href = url;
	},
	displayFailure: function(msg) {
		// otherwise, notify user
		alert(msg);
	},
	getAjaxObject: function() {
		// This script is limited by the "same origin policy" since it uses XMLHttpRequest
		// You would have to set up a proxy on your server for it to work across different domains
		var oXh = null,
		i,
		xmlHTTPversions = ["Msxml2.XMLHTTP.7.0", "Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
		if (typeof XMLHttpRequest === "function") {
			oXh = new XMLHttpRequest();
		} else if (typeof ActiveXObject === "function") {
			for (i = 0; i < xmlHTTPversions.length; i += 1) {
				try {
					oXh = new ActiveXObject(xmlHTTPversions[i]);
					if (oXh) {
						break;
					}
				} catch(e) {
					// check for next version
				}
			}
		}
		return oXh;
	},
	initMD5: function() {
		// Use dynamic script tags to include md5.js if not already included with <script> tags
		if (typeof hex_md5 === "function") {
			return; //md5.js already loaded
		}
		loginApp.md5url = (typeof loginApp.md5url === "string" && loginApp.md5url.length > 0) ? loginApp.md5url : "http://scriptar.com/JavaScript/md5.js";
		if (loginApp.md5url.indexOf("?") === -1) {
			loginApp.md5url += "?ref=" + encodeURIComponent(location.href);
		}
		var head = document.getElementsByTagName("head").item(0),
		scriptTag = document.getElementById("loadScript"),
		script = document.createElement("script");
		if (scriptTag) {
			head.removeChild(scriptTag);
		}
		script.src = loginApp.md5url;
		script.type = "text/javascript";
		script.id = "loadScript";
		head.appendChild(script);
	},
	getHash: function(username, password) {
		// Convert a username and/or password to an MD5 hash.
		var str = "";
		if (typeof hex_md5 === "function") {
			if (username.length > 0 && password.length > 0) {
				str = username + "|" + password;
			} else if (username.length > 0) {
				str = username;
			} else if (password.length > 0) {
				str = password;
			}
			str = hex_md5(str);
		}
		return str;
	},
	checkLogin: function(f) {
		// This function is called from the onsubmit event of a login form.
		// It checks to see if a page exists (which corresponds to a hashed username and/or password).
		// If the page exists, it calls loginApp.doLogin(), othewise, it calls displayFailure().
		if (typeof f !== "object") {
			//alert("f is not an object");
			return false;
		}
		if (typeof hex_md5 !== "function") {
			alert("MD5.js not loaded.");
			return false;
		}
		var objUserName = (typeof f.username === "object") ? f.username : null,
		objPassword = (typeof f.pwd === "object") ? f.pwd : null,
		root = (typeof loginApp.prefix === "string") ? loginApp.prefix : "",
		fileExt = (typeof loginApp.suffix === "string") ? loginApp.suffix : ".html",
		btnSubmit = document.getElementById("loginfrmSubmit"),
		originalValue = "",
		url = "",
		oXht = null;
		if (btnSubmit) {
			originalValue = btnSubmit.value;
			btnSubmit.value = "Please wait";
			btnSubmit.disabled = true;
		}
		if (objUserName && objPassword) {
			url = loginApp.getHash(objUserName.value, objPassword.value);
			objPassword.value = "";
		} else if (objUserName) {
			url = loginApp.getHash(objUserName.value, "");
		} else if (objPassword) {
			url = loginApp.getHash("", objPassword.value);
			objPassword.value = "";
		} else {
			//alert("nothing to lookup");
			return false;
		}
		url = root + url + fileExt;
		// Instantiate an XMLHttpRequest object.
		oXht = loginApp.getAjaxObject();
		if (typeof oXht !== "object") {
			loginApp.doLogin(url, false);
		} else {
			// Issue a HEAD request to check for file existence.
			oXht.open("HEAD", url, true);
			oXht.onreadystatechange = function() {
				if (oXht.readyState === 4) {
					// A status of 200 means the file was found.
					// Anything else, such as 404, means not found or error.
					if (oXht.status === 200) {
						loginApp.doLogin(url, true);
					} else {
						loginApp.displayFailure(loginApp.invalidPasswordMsg);
						if (btnSubmit) {
							btnSubmit.value = originalValue;
							btnSubmit.disabled = false;
						}
					}
				}
			};
			oXht.send(null);
		}
		return false;
	},
	initLoginForm: function(args) {
		// This method creates a login form and puts it inside of an XHTML container.
		// If you want to use your own form, set usernameprompt and passwordprompt to empty strings.
		// Pass in a classtoadd parameter to give your pre-existing forms a CSS class on init.
		var ph, phClasses = [], placeholderID = (typeof args.container === "string") ? args.container : "login",
		classtoadd = (typeof args.classtoadd === "string") ? args.classtoadd : "",
		usernamePromptText = (typeof args.usernameprompt === "string") ? args.usernameprompt : "User Name:",
		passwordPromptText = (typeof args.passwordprompt === "string") ? args.passwordprompt : "Password:",
		loginHTML = (typeof args.loginHTML === "string") ? args.loginHTML : "";
		loginApp.invalidPasswordMsg = (typeof args.invalidpassword === "string") ? args.invalidpassword : loginApp.invalidPasswordMsg;
		loginApp.prefix = (typeof args.urlprefix === "string") ? args.urlprefix : loginApp.prefix;
		loginApp.suffix = (typeof args.urlsuffix === "string") ? args.urlsuffix : loginApp.suffix;
		loginApp.md5url = (typeof args.md5url === "string") ? args.md5url : loginApp.md5url;
		loginApp.initMD5();
		if (!document.getElementById || !document.getElementById(placeholderID)) {
			return;
		}
		ph = document.getElementById(placeholderID);
		if (classtoadd.length > 0) {
			phClasses = ph.className.split(" ");
			phClasses.push(classtoadd);
			ph.className = phClasses.join(" ");
		}
		if (usernamePromptText.length > 0 || passwordPromptText.length > 0) {
			if (loginHTML.length === 0) {
				loginHTML = "<form name=\"loginForm\" id=\"loginForm\" autocomplete=\"off\" " +
					"onsubmit=\"return loginApp.checkLogin(this);\">\n" +
					"<dl><dt>$usernameprompt</dt><dd>$username</dd>\n" +
					"<dt>$passwordprompt</dt><dd>$password</dd></dl>\n" +
					"<input type=\"submit\" id=\"loginfrmSubmit\" value=\"Login\" />\n" +
					"</form>";
			}
			if (usernamePromptText.length > 0) {
				loginHTML = loginHTML.replace(/\$usernameprompt/g, "<label for=\"loginfrmUsername\">" + usernamePromptText + "</label>");
				loginHTML = loginHTML.replace(/\$username/g, "<input type=\"text\" id=\"loginfrmUsername\" name=\"username\" />");
			} else {
				loginHTML = loginHTML.replace(/\$usernameprompt/g, "").replace(/\$username/g, "");
			}
			if (passwordPromptText.length > 0) {
				loginHTML = loginHTML.replace(/\$passwordprompt/g, "<label for=\"loginfrmPassword\">" + passwordPromptText + "</label>");
				loginHTML = loginHTML.replace(/\$password/g, "<input type=\"password\" id=\"loginfrmPassword\" name=\"pwd\" />");
			} else {
				loginHTML = loginHTML.replace(/\$passwordprompt/g, "").replace(/\$password/g, "");
			}
			loginHTML = loginHTML.replace(/<d(t|d)><\/d(t|d)>/g, "");
			ph.innerHTML = loginHTML;
		}
	}
};