String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, "");
}; 

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

var URI = {

	regex : new RegExp( "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?" ),
	inURI : new Array (),

	setURI : function(input) {
		if (input != null) {
			var output = this.regex.exec(input);
			this.inURI = output;
		}
	},

	scheme : function() {
		if ( typeof( this.inURI[2] ) != "undefined" )
			return this.inURI[2]
		else
			return null
	},
	
	authority : function() {
		if ( typeof( this.inURI[4] ) != "undefined" )
			return this.inURI[4]
		else
			return null
	},
	
	path : function() {
		if ( typeof( this.inURI[5] ) != "undefined" )
			return this.inURI[5]
		else
			return null
	},
	
	query : function() {
		if ( typeof( this.inURI[7] ) != "undefined" )
			return this.inURI[7]
		else
			return null
	},
	
	fragment : function() {
		if ( typeof( this.inURI[9] ) != "undefined" )
			return this.inURI[9]
		else
			return null
	},
	
	param : function() {
		if (this.query() != null) {

			var argList = new Array();
			var temp = this.query().split('&');

			for (var i=0;i<temp.length;i++) {

				var temp2 = temp[i].split('=');
				argList[temp2[0]] = temp2[1];
			}

			return (argList);

		} else {

			return null;
		}
	},
	
	hasQuery : function() {
	    if (this.query != null)
			return true
		else
			return false;
	},
  
	getUriNoQuery : function() {
		return (this.scheme + "://" + this.authority + this.path);
	}
}


var cookies = {

	getKeys : function () {
		var ca = document.cookie.split(';').trim();
		var list = new Array();		
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			list.push(c.split('=')[0]);
		}
		return list;
	},
	
	getValue : function (name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	},

	createCookie : function (name,value,days) {
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		document.cookie = name+"="+value+expires+"; path=/";
	},

	eraseCookie : function (name) {
		createCookie(name,"",-1);
	}
}

var EJutils = {

	keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
	
	decode64 : function(input) {
	
		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

		do {
			enc1 = this.keyStr.indexOf(input.charAt(i++));
		    enc2 = this.keyStr.indexOf(input.charAt(i++));
		    enc3 = this.keyStr.indexOf(input.charAt(i++));
		    enc4 = this.keyStr.indexOf(input.charAt(i++));

		    chr1 = (enc1 << 2) | (enc2 >> 4);
		    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
		    chr3 = ((enc3 & 3) << 6) | enc4;

		    output = output + String.fromCharCode(chr1);

		    if (enc3 != 64) {
		        output = output + String.fromCharCode(chr2);
		    }
		    if (enc4 != 64) {
		        output = output + String.fromCharCode(chr3);
		    }
		} while (i < input.length);
		return output;
	},
	
	encode64 : function(input) {

		var output = "";
		var chr1, chr2, chr3;
		var enc1, enc2, enc3, enc4;
		var i = 0;

		do {
			chr1 = input.charCodeAt(i++);
			chr2 = input.charCodeAt(i++);
			chr3 = input.charCodeAt(i++);

			enc1 = chr1 >> 2;
			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
			enc4 = chr3 & 63;

			if (isNaN(chr2)) {
				enc3 = enc4 = 64;
			} else if (isNaN(chr3)) {
				enc4 = 64;
			}

			output = output + this.keyStr.charAt(enc1) + this.keyStr.charAt(enc2) + 
					this.keyStr.charAt(enc3) + this.keyStr.charAt(enc4);
		} while (i < input.length);
		return output;
	},
	
	
	thaw : function(input) {

		var resultArray = new Array();
		var initoff = 4;
		
		if (input.substr(0,initoff).indexOf('FrT;')) initoff = 0;
		
		this.thawScalar(initoff,input,resultArray);
		
		return resultArray;
	},

	thawScalar : function(offset, input, resultArray) {
		
		var key = input.substring(offset, offset + 1);
		var localOffset = offset;
		
		if (key === "$")
			localOffset = this.thawString(offset, input, resultArray);
		else if( key === "@")
			localOffset = this.thawArray(offset, input, resultArray);

		return localOffset;
	},
	
	thawString : function (offset, input, resultArray) {
	
		var regexS = "^\\$(\\d+)|";
		var regex = new RegExp( regexS );
		var results = regex.exec( input.substring(offset) );

		if ( results === null ) return null;

		var count = new Number(results[1]);

		if (isNaN(count)) return null;
		if( input.length - offset <= results[1].length + 1 + count ) return null
		
		var newOffset = offset + results[1].length + 2 + count;
		
		var resStr = input.substring(offset + results[1].length + 2, newOffset); 		
		resultArray.push(resStr);
		
		return newOffset;
	},
	
	thawArray: function (offset,input, resultArray) {
	
		var regexS = "^[%@](\\d+)|";
		var regex = new RegExp( regexS );
		var results = regex.exec( input.substring(offset) );
	
		if ( results === null ) return null;

		var count = new Number(results[1]);
		
		if (isNaN(count)) return null;

		var off = offset + 2 + results[1].length;
		
		while(count + input.length > off) {
			off = this.thawScalar(off, input, resultArray);
			--count;
		}
		return off;
	}
}

var EJcookies = Object.create(cookies);
EJcookies.getValue = function(name) {
	var value = cookies.getValue(name);
	if (value) {
		value.replace("@","\n").trim();

		var value = String(EJutils.thaw(EJutils.decode64(value)));
		var ca =  new Array();
		ca = value.split(',');

		var results = new Array ();
		var key = "";
		for (var i=0;i < ca.length;i++) {
		
			if (key === "") {
				key = ca[i];
			} else {
				results[key] = ca[i];
				key = "";
			}
		}
		return results;
	}
}

//**************************
// Detects in a more comprehensive way if the current device is a mobile device.
function isMobileDevice()
{
	//Initialize our user agent string.
	var uagent = navigator.userAgent.toLowerCase();

   //Attempt to detect most mobile devices, 
   //   especially mass market feature phones.
   // NOTE: Doesn't usually work reliably...
   if (uagent.search(/wap|midp|wml|brew/) > -1 || 
       uagent.search(/iphone|ipod/) > -1 ||   //We repeat the searches here because some iPods may report themselves as an iPhone, which is ok.
       uagent.search(/android/) > -1 ||   //Check if this is an android device
       uagent.search(/symbian|series60|series70|series80|series90/) > -1 ||   //Check for other Symbian devices - older S60, UIQ, other.
       uagent.search(/windows ce|iemobile|wm5 pie/) > -1 ||   //Most devices use 'Windows CE', but some report 'iemobile' and some older ones report as 'PIE' for Pocket IE.
       uagent.search(/blackberry/) > -1 ||   //Next, look for a BlackBerry
       uagent.search(/palm|blazer|xiino/) > -1 ||
       uagent.search(/xv6875/) > -1 ||   //HTC Pro Touch 2
       uagent.search(/netfront/) > -1 ||   //Check for Netfront Browser
       uagent.search(/playstation/) > -1 ||   //Check for a Playstation
       uagent.search(/pda/) > -1 ||   //Check for a generic PDA
       uagent.search(/docomo/) > -1 ||   //Check for NTT Docomo
       uagent.search(/kddi/) > -1 ||   //Check for KDDI
       uagent.search(/nitro/) > -1 ||   //Check for Nintendo DS
       uagent.search(/vodafone/) > -1 ||   //Check for Vodafone 3G
       uagent.search(/sec-sgh/) > -1 ||   //Finally, detect for certain very old devices with stupid useragent strings.
	   uagent.search(/sonyericsson|ericsson/) > -1 || 
	   (uagent.search(/pre/) > -1) && (uagent.search(/webkit/) > -1)) //PreOS with WebKit.
	   return true;

   return false;
};
