//<SCRIPT>
////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// UTILS_LIBRARY.JS                                                           //
//                                                                            //
// Library of general functions which are language independant and can be     //
// used by authors of any pages.                                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

var UTILS_LIBRARY;
////////////////////////////////////////////////////////////////////////////////
// Undefined is required for pre IE5.5 browsers, as undefined is undefined????
var undefined;

// This needs to be changed every year.
var utilsCurrentYear=(new Date()).getYear();

/////////////////////////////////////////////////////////////////////////////////
// Array functions missing from pre IE5.5 browsers.
// 
if(Array.prototype.push && [0].push(true) == true)
{
  Array.prototype.push = null;
}

if(!Array.prototype.push)
{
  function arrayPush(object)
  {
    this[this.length] = object;
    return this.length;
  } 
  Array.prototype.push = arrayPush;
}


if(!Array.prototype.pop)
{
  function arrayPop()
  {
    var lastElement = this[this.length - 1];
    this.length = Math.max(this.length - 1,0);
    return lastElement;
  }
  Array.prototype.pop = arrayPop;
}

if(!Array.prototype.shift)
{
  function arrayShift()
  {
    var firstElement = this[0];
    this.reverse();
    this.length = Math.max(this.length - 1,0);
    this.reverse();
    return firstElement;
  }
  Array.prototype.shift = arrayShift;
}

if(!Array.prototype.splice)
{
  function arraySplice(start,deleteCount)
  {
    // First remove the items from the original array, we will return then in a new array
    var deletedItems = new Array;
    for(i = start; i < (start + deleteCount); i ++)
    {
      deletedItems[deletedItems.length] = this[i];
      // Now insert the new item into the array.
      // We need to use the arguments array as the function has a variable length parameter list.
      this[i] = arguments[deletedItems.length];
    }
    return deletedItems;
  }
  Array.prototype.splice = arraySplice;
}

////////////////////////////////////////////////////////////////////////////////
// Browser Version Checking
//
//
// The following object's constructor investigates the browser.
// To establish the browser type, look at its attributes.
//
// Attribute    Meaning
// ---------    -------
// .ns          Netscape derivative
// .ns4up       Netscape 4 or above
// .ns6up       Netscape 6 or above
//
// .ie          Internet Explorer derivative
// .ie4up       Internet Explorer 4 or above
// .ie5         Internet Explorer 5 (exactly)
// .ie55        Internet Explorer 5.5 (exactly)
// .ie6         Internet Explorer 6 (exactly)
//
function UTILS_Browser()
{
	// Get basic information
	var agent =		navigator.userAgent.toLowerCase();
	this.minor =	parseInt(navigator.appVersion);
	this.major =	parseFloat(navigator.appVersion);
	
	// Netscape checks
	this.ns =		(agent.indexOf('mozilla') != -1) &&
					(agent.indexOf('spoofer') == -1) &&
					(agent.indexOf('compatible') == -1);
					
	this.ns4up =	(this.ns) &&
					(this.major >= 4);
					
	this.ns6up =	(this.ns) &&
					(this.major >= 5);
	
	// Internet Explorer checks
	this.ie =		(agent.indexOf('msie') != -1);

	this.ie4up =	(this.ie) && 
					(this.major >= 4);

	this.ie5 =		(this.ie4up) &&
					(agent.indexOf('msie 5.0') != -1);
					
	this.ie55 =		(this.ie4up) &&
					(agent.indexOf('msie 5.5') != -1);


	this.ie6 =		(this.ie4up) &&
					( (agent.indexOf('msie 6.0') != -1) ||
                                          (agent.indexOf('msie 8')   != -1) );

}

////////////////////////////////////////////////////////////////////////////////
// Main RD web site utilities
//
//
// The following function brings the user back to the main RD web site.
// This is complicated by the fact that the main web site may have created
// the window.  So we must close the window in this case.
//

function UTILS_returnToRdHome(url)
{
	if (url == undefined)
		url = 'http://www.radiodetection.com';
		
	// Are we in the header or not?
	if (top.location.href == self.location.href)
	{ // Before header is created
		UTILS_windowClosed = true;
		mytop = self;
	}	
	else
	{ // After header is created
		top.frameHeader.allowToClose();
		mytop = top;
	}

	if (mytop.window.opener == undefined) // If the window was opened directly
	{
		mytop.location.href = url;
	}
	else if (mytop.window.opener.closed) // If the opening window has disappeared, then open it again
	{
		go = window.open(url, 'radiodetection', 'toolbar=yes,location=yes,menubar=yes,status=yes,scrollbars=yes,resizable=yes,width=800,height=600');
		go.focus();
		mytop.window.close();
	}
	else // The opening window is still open
	{
		mytop.window.opener.focus();
		mytop.window.close();
	}
	return false;
}


////////////////////////////////////////////////////////////////////////////////
// Applet Utilities
//
//
// The following object is used to store the necessary parameters for an
// applet, and to write these into the appropriate applet tag for the browser
//
// Usage:
//        1. Declare ( e.g. a = new AppletMaker() )
//        2. Define attributes ( e.g. a.name="TestApplet" )
//        3. Add params if used ( e.g. a.addUserParam("COLOUR", "RED") )
//        4. Insert into doc ( e.g. document.writeln(a.getTagForMyBrowser()) )
//
function UTILS_AppletMaker()
{
	//
	// Attributes
	//
	this.code; this.codebase; this.archive; this.alt;
	this.align; this.height; this.width; this.hspace;
	this.vspace; this.mayscript; this.scriptable;
	this.name; this.title;
	this.cache_option; this.cache_archive;
	
	this.userParams = new Array();

	//
	// Methods
	//
	this.addUserParam = function(name, value)
	{
		var param = new Object();
		param.name = name;
		param.value = value;
		this.userParams.push(param);
	}
	
	this.getTagForMyBrowser = function()
	{
		var browser = new UTILS_Browser();
		if(browser.ie)
			return this.objectTag();
		else if (browser.ns6)
			return this.appletTag();
		else if (browser.ns4)
			return this.embedTag();
		else
			return this.appletTag();
	}
	
	this.objectTag = function()
	{
		var tag = "<OBJECT ";
		tag += "classid=" + doublequotes('clsid:CAFEEFAC-0014-0000-0000-ABCDEFFEDCBA') + " ";
		tag += this.conditionalAddToTag("width");
		tag += this.conditionalAddToTag("height");
		tag += this.conditionalAddToTag("name");
		tag += this.conditionalAddToTag("align");
		tag += this.conditionalAddToTag("vspace");
		tag += this.conditionalAddToTag("hspace");
		tag += this.conditionalAddToTag("alt");
		tag += "codebase=" + doublequotes('http'+'://java.sun.com/products/plugin/autodl/jinstall-1_4_0-win.cab#Version=1,4,0,0') + ">\n";
		
		tag += this.conditionalAddParamToTag("code");
		tag += this.conditionalAddParamToTag("codebase");
		tag += this.conditionalAddParamToTag("archive");
		tag += this.conditionalAddParamToTag("name");
		tag += this.conditionalAddParamToTag("mayscript");
		tag += this.conditionalAddParamToTag("scriptable");
		tag += this.conditionalAddParamToTag("cache_option");
		tag += this.conditionalAddParamToTag("cache_archive");
		tag += "<PARAM name=" + doublequotes('type')+ " value=" + 
			doublequotes('application/x-java-applet;version=1.3') + ">\n";

		
		for(var i = 0; i < this.userParams.length; i++)
			tag += this.addParamToTag(this.userParams[i].name, this.userParams[i].value);
			
		tag += "\n</OBJECT>";
		return tag;
	}
	
	this.embedTag = function()
	{
		var tag = "<EMBED ";
		tag += "type=" + doublequotes('application/x-java-applet;version=1.3') + " ";
		tag += this.conditionalAddToTag("code");
		tag += this.conditionalAddToTag("codebase");
		tag += this.conditionalAddToTag("archive");
		tag += this.conditionalAddToTag("alt");
		tag += this.conditionalAddToTag("name");
		tag += this.conditionalAddToTag("width");
		tag += this.conditionalAddToTag("height");
		tag += this.conditionalAddToTag("align");
		tag += this.conditionalAddToTag("vspace");
		tag += this.conditionalAddToTag("hspace");
		tag += this.conditionalAddToTag("mayscript");
		tag += this.conditionalAddToTag("scriptable");
		tag += this.conditionalAddToTag("cache_option");
		tag += this.conditionalAddToTag("cache_archive");
		
		tag += "\n";
		
		for(var i = 0; i < this.userParams.length; i++)
			tag += this.userParams[i].name + "=" + doublequotes(this.userParams[i].value) + "\n";
		
		tag += "pluginspage=" + doublequotes('http'+'://java.sun.com/products/plugin/1.3/plugin-install.html') + ">\n";
		tag += "</EMBED>";
		return tag;
	}
	
	this.appletTag = function()
	{
		var tag = "<APPLET ";
		tag += this.conditionalAddToTag("code");
		tag += this.conditionalAddToTag("codebase");
		tag += this.conditionalAddToTag("archive");
		tag += this.conditionalAddToTag("alt");
		tag += this.conditionalAddToTag("align");
		tag += this.conditionalAddToTag("height");
		tag += this.conditionalAddToTag("width");
		tag += this.conditionalAddToTag("hspace");
		tag += this.conditionalAddToTag("vspace");
		tag += this.conditionalAddToTag("cache_option");
		tag += this.conditionalAddToTag("cache_archive");
		
		if(this.mayscript != undefined) tag += "mayscript ";
		tag += this.conditionalAddToTag("name");
		tag += this.conditionalAddToTag("title");
		tag +=">\n";
		
		for(var i = 0; i < this.userParams.length; i++)
			tag += this.addParamToTag(this.userParams[i].name, this.userParams[i].value);
		
		tag+="</APPLET>";
		
		return tag;
	}
	
	this.conditionalAddParamToTag = function(field)
	{
		var str = "";
		if(eval("this." + field) != undefined)
		{
			str += "<PARAM NAME = " + doublequotes(field) + " VALUE = " + doublequotes(eval("this." + field)) + ">\n";
		}
		return str;
	}

	this.addParamToTag = function(name, value)
	{
		return "<PARAM name=" + doublequotes(name) + " value=" + doublequotes(value) + ">\n";
	}

	this.conditionalAddToTag = function(field)
	{
		var str = "";
		if(eval("this." + field) != undefined)
		{
			str = field + "=" + doublequotes(eval("this." + field)) + " ";
		}
		return str;
	}
}

////////////////////////////////////////////////////////////////////////////////
// Parsing Utilities
//
function UTILS_Parser(str)
{
	this.str = str.replace(/\"/g, "\'"); // FIXME - check this (browser?)
	this.pos = 0;
	
	this.remainder = function()
	{
		var remainder;
		if(this.pos == this.str.length)
			remainder = "";
		else
			remainder = this.str.substring(this.pos, this.str.length);
		
		return remainder;
	}
	
	this.reset = function()
	{
		this.pos = 0;
	}
	
	this.removeLeadWhitespace = function()
	{
		WHITESPACE = " \n";
		
		if(this.pos != this.str.length)
		{
			var nextchar = this.str.substring(this.pos, this.pos + 1);
			
			while(WHITESPACE.indexOf(nextchar) != -1 && this.pos < this.str.length)
			{
				this.pos++;
				nextchar = this.str.substring(this.pos, this.pos + 1);
			}
		}
	}
	
	this.extract = function(before, after)
	{
		var extractedString = "";
		var indexA, indexB;
		
		if(before == undefined)
			indexA = this.pos;
		else
			indexA = this.str.indexOf(before, this.pos);
			
		if(indexA != -1)
		{
			if(before != undefined)
				indexA += before.length;
			
			if(after == undefined)
				indexB = this.str.length;
			else
				indexB = this.str.indexOf(after, indexA);
				
			if(indexB != -1)
			{
				extractedString = this.str.substring(indexA, indexB);
			}
		}
		return extractedString;
	}

	this.nextLine = function()
	{
		var line;
		if(this.pos == this.str.length)
		{
			line = "";
		}
		else
		{
			var index = this.str.indexOf("\n", this.pos);
			if(index == -1)
			{
				// Last line
				line = this.str.substring(this.pos, this.str.length);
				this.pos = this.str.length;
			}
			else
			{
				line = this.str.substring(this.pos, index);
				this.pos = index + 1;
			}
		}
		
		return line;
	}
	
	this.nextString = function()
	{
		var nextString;
		
		if(this.pos == this.str.length)
		{
			nextString = "";
		}
		else
		{
			var indexA = this.str.indexOf("'", this.pos);
			var indexB = this.str.indexOf("'", indexA + 1);
		
			if(indexA == -1 || indexB == -1)
			{
				nextString = "";
				this.pos = this.str.length;
			}
			else
			{
				nextString = this.str.substring(indexA + 1, indexB);
				this.pos = indexB + 1;
			}
		}

		return nextString;
	}
	
	this.nextWord = function()
	{
		var word;
		
		this.removeLeadWhitespace();
		
		if(this.pos == this.str.length)
		{
			word = "";
		}
		else
		{
			var index;
			var nextNewline = this.str.indexOf("\n", this.pos);
			var nextSpace = this.str.indexOf(" ", this.pos);
			
			if(nextNewline == -1)
			{
				index = nextSpace;
			}
			else if(nextSpace == -1)
			{
				index = nextNewline;
			}
			else
			{
				index = (nextSpace < nextNewline) ? nextSpace : nextNewline;
			}
			
			if(index == -1) index = this.str.length;
			
			word = this.str.substring(this.pos, index);
			this.pos = index;
			
		}
		return word;
	}
	
	this.nextInteger = function()
	{
		var nextInt;
		
		if(this.pos != this.str.length)
		{
			var nextWord = this.nextWord();
			var num;
			while(nextWord != "")
			{
				num = parseInt(nextWord, 10);
				if(isNaN(num) == false)
				{
					nextInt = num;
					break;
				}
				nextWord = this.nextWord();
			}
		}
		
		return nextInt;
	}

	this.nextFloat = function()
	{
		var nextFloat;
		
		if(this.pos != this.str.length)
		{
			var nextWord = this.nextWord();
			
			while(nextWord != "")
			{
				var num = parseFloat(nextWord);
				if(isNaN(num) == false)
				{
					nextFloat = num;
					break;
				}
				nextWord = this.nextWord();
			}
		}
		
		return nextFloat;
	}
}

function UTILS_UrlParser(url)
{
	// Extracted info (may be undefined)
	this.hostname = "";
	this.filename = "";
	this.subhostname = "";
	this.subsection = "";
	this.product = "";
	this.language = "";
	this.path = "";
	this.suffix = "";
		
	// Remember the url 'as is'
	this.completeURL = new String(url);

	// First, if there is a suffix, separate it from the filename
	var index = url.indexOf("?");
	if(index != -1)
	{
		this.suffix = url.substring(index + 1, url.length);
		url = url.substring(0, index);
	}

	url = url.toLowerCase();
		
	// Remove protocol
	if(url.substring(0, 7) == "http://")
		url = url.substring(7, url.length);
			
	// Up to the next "/" is the host
	index = url.indexOf("/");
	if(index > -1)
	{
		this.hostname = url.substring(0, index);
		url = url.substring(index + 1, url.length);
	}
		
	// Check for further folders
	index = url.indexOf("/");
	if(index == -1)
	{
		// We are in the root
		this.filename = url;
		url = "";
	}
	else
	{
		// Check if the next folder is a subhost (e.g. xxxtest)
		var cont = true;
		while (cont)
		{
			index = url.indexOf("/");
			var folder = url.substring(0, index);
			if(index != -1 && folder != "products" && folder != "header" && folder != "connection")
			{
				// There _is_ a subhost
				if (this.subhostname.length > 0)
					this.subhostname += "/";
				this.subhostname += folder;
				url = url.substring(index + 1, url.length);
				
				// Check for root of subweb
				if(url.indexOf("/") == -1)
				{
					this.filename = url;
					url = "";
				}
			}
			else
				cont = false;
		}
	}
		
	// Is there anything left?
	if(url.length > 0)
	{
		// The next folder _should_ be the subsection
		index = url.indexOf("/");
		if(index == -1)
		{
			alert("error!");
		}
		else
		{
			this.subsection = url.substring(0, index);
			url = url.substring(index + 1, url.length);
		}
			
		// Check subsection
		if(this.subsection == "products")
		{
			// We are in the products section
			index = url.indexOf("/");
			if(index == -1)
			{
				alert("error!");
			}
			else
			{
				this.product = url.substring(0, index);
				url = url.substring(index + 1, url.length);
			}
		}
			
		// The next folder _should_ be the language
		index = url.indexOf("/");
		if(index == -1)
		{
			alert("error!");
		}
		else
		{
			this.language = url.substring(0, index);
			url  = url.substring(index + 1, url.length);
		}
			
		// If there are any "/"s left, there is a path
		index = url.lastIndexOf("/");
		if(index > -1)
		{
			this.path = url.substring(0, index);
			this.filename = url.substring(index + 1, url.length);
		}
		else
		{
			this.filename = url;
		}
			
		url = this.completeURL;
	}
}

////////////////////////////////////////////////////////////////////////////////
// Debug flag
//

// Detect if we are in debug mode.
var utilsDebugMode = false;
if (UTILS_getCookie("RD_Debug") == "TRUE")
  utilsDebugMode = true;

function UTILS_setDebugMode(newDebugMode)
{
  utilsDebugMode = newDebugMode;
  if (utilsDebugMode == true)
    UTILS_setCookie("RD_Debug", "TRUE"); 
  else  
    UTILS_setCookie("RD_Debug", "FALSE"); 
}
  
function UTILS_debugMode()
{
  return utilsDebugMode;  
}



////////////////////////////////////////////////////////////////////////////////
// JavaScript Cache
//

var UTILS_CACHE_STD_SIZE = 10;

function UTILS_CacheEntry(key, data)
{
	this.key = key;
	this.data = data;
	this.locked = false;
	
	this.dumpContents = function()
	{
		var html = "<TR valign=top>";
		html += "<TD>" + this.key + (this.locked ? " (locked)" : "") + "</TD>";
		html += "<TD>" + this.data + "</TD>";
		html += "</TR>";
		return html.replace(/\n/g, "<BR>");
	}
}

function UTILS_Cache(name, maxSize)
{
	this.name = name;
	this.maxSize = parseInt(maxSize);
	this.elements = new Array();
	
	if(this.name == undefined) this.name = "anonymous cache";
	if(isNaN(this.maxSize)) this.maxSize = UTILS_CACHE_STD_SIZE;
	if(this.maxSize < 1) this.maxSize = UTILS_CACHE_STD_SIZE;

	this.store = function(key, data)
	{
		var stored = false;
		var index = this.find(key);
		if(index == undefined)
		{
			if(this.elements.length < this.maxSize)
			{
				this.elements.push(new UTILS_CacheEntry(key, data));
				stored = true;
			}
		}
		else
		{
			if(this.elements[index].locked == false)
			{
				this.elements[index].data = data;
				stored = true;
			}
		}
		return stored;
	}
	
	this.retrieve = function(key)
	{
		var retrieved;
		var index = this.find(key);
		if(index != undefined)
		{
			retrieved = this.elements[index].data;
		}
		return retrieved;
	}
	
	this.lock = function(key)
	{
		var locked = false;
		var index = this.find(key);
		if(index != undefined)
		{
			this.elements[index].locked = true;
			locked = true;
		}
		return locked;
	}
	
	this.unlock = function(key)
	{
		var unlocked = false;
		var index = this.find(key);
		if(index != undefined)
		{
			this.elements[index].locked = false;
			unlocked = true;
		}
		return unlocked;
	}
	
	this.deleteEntry = function(key)
	{
		var deleted = false;
		var index = this.find(key);
		if(index != undefined)
		{
			if(this.elements[index].locked == false)
			{
				this.elements.splice(index, 1);
				deleted = true;
			}
		}
		return deleted;
	}
	
	this.deleteAllUnlocked = function()
	{
		var hitList = new Array();
		for(var i = 0; i < this.elements.length; i++)
			hitList.push(this.elements[i].key);

		var name;
		while(hitList.length > 0)
		{
			name = hitList.pop();
			this.deleteEntry(name);
		}
	}

	this.find = function(key)
	{
		var index;
		for(var i = 0; i < this.elements.length; i++)
			if(this.elements[i].key == key) index = i;
		return index;
	}
	
	this.dumpContents = function(targetPage)
	{
		targetPage.writeln("<P>");
		targetPage.writeln("NAME: " + this.name + "<BR>");
		targetPage.writeln("SIZE: " + this.maxSize + "<BR>");
		if(this.elements.length > 0)
		{
			targetPage.writeln("Data...<BR>");
			targetPage.writeln("<TABLE width = 100% border=2>");
			targetPage.writeln("<TR><TH>key</TH><TH>value</TH></TR>");
			for(i = 0; i < this.elements.length; i++)
				targetPage.writeln(this.elements[i].dumpContents());
			targetPage.writeln("</TABLE>");
		}
		else
		{
			targetPage.writeln("no data<BR>");
		}
		targetPage.writeln("</P>");
	}
}

////////////////////////////////////////////////////////////////////////////////
// Cookie Utilities
//
function UTILS_setCookie(name, value)
{
	// Session cookies only!!
	document.cookie = name + "=" + escape(value) + ";path=/;";
}

function UTILS_getCookie(name)
{
	var identifier = name + "=";
	var cookieData = document.cookie;
	var value;
	var indexA, indexB;
	
	indexA = cookieData.indexOf(identifier);
	if(indexA > -1)
	{
		// Found cookie
		indexB = cookieData.indexOf(";", indexA);
		if(indexB == -1)indexB = cookieData.length;
		value =unescape(cookieData.substring(indexA + identifier.length, indexB));
	}
	
	return value;
}

////////////////////////////////////////////////////////////////////////////////
// General Utilities (NOTE no "UTILS_" prefix for clarity)
//

function quotes(str)
{
	return " \'" + str + "\'";
}

function doublequotes(str)
{
	return " \"" + str + "\"";
}

//</SCRIPT>