// JavaScript used by all pages

// THESE SCRIPTS ARE THE COPYRIGHT OF JOHN LIDDIARD (C) 2005 AND MAY NOT BE
// COPIED OR USED WITHOUT HIS EXPLICIT CONSENT


// ======================= CONFIGURATION PARAMETRES =======================================
var cookie_prefix='grenadafishing';
var history_unwanted_text_re = /grenada fishing with wayward wind -[\s]*/gi;
var history_limit = 0;
var hist_sort_by = 'p_time'; // can be p_title, p_count or p_time
var debug_flag = 0;
// ===================== END CONFIGURATION PARAMETRES =====================================





// Style info - global with defaults
var Look = {
	Sheet:	"sys_look/sitestyle.css"
	}

// Prefix for web path resolution - global
var prefix = "";
var cgibin = prefix+"sys_cgi-bin/";

var login_cookie = cookie_prefix+'lc';
var user_cookie = cookie_prefix+'uc';
var time_cookie = cookie_prefix+'tc';
var history_cookie = cookie_prefix+'history';

// write to either this doc window or a named window
function write_on_wdow(text,wdow){
	if (wdow) {
		wdow.document.write (text);
		}
	else {
		document.write (text);
		}
	}

// ==================== Start of all docs ===============================

function set_path(path) {
	if (path) {
		prefix = path;
		cgibin = prefix+"sys_cgi-bin/";
		}
	}

// Reference the appropriate style sheet
function include_style(path,wdow) {
	if (path) {
		prefix = path;
		cgibin = prefix+"sys_cgi-bin/";
		}
	var text='<link rel=stylesheet type="text/css" href="'+prefix+Look['Sheet']+'">';
	write_on_wdow (text,wdow);
	}

// ================== Start of all doc bodies ==============================
function page_start(wdow) {
	// set security viz by login authority
	set_sec_viz(wdow);
	// DEBUG
	test_stuff();
	}


// ================== End of all docs ====================================

// Display all the end of page stuff
function page_end(ctr_name,wdow) {
	horizontal_menu_bar(wdow);
	page_end_credit(wdow);
	page_end_ctr(ctr_name,wdow);
	tip_prepare(wdow);
	page_end_diag(wdow);
	}

// Display a credit to me! -----
function page_end_credit(wdow) {
	write_on_wdow ('<br><br><br>',wdow);
	write_on_wdow ('<p class="fn">Web engineering by<br> <a href=http://www.jlunderwater.co.uk/index.htm target=_top>',wdow);
	write_on_wdow ('<img align=middle src='+prefix+'graphics/uwlinkbtn.jpg border=0 alt="John Liddiard Underwater" width=115 height=74></a></p>',wdow);
	write_on_wdow ('<br><br><br>',wdow);
	}

// Put a counter at the end of the page -----
function page_end_ctr(ctr_name,wdow) {
	var docloc = ""+document.location; // force to string type
	var docurl = docloc.split("?")[0];
	var ctrurl;
	var cn;

	// specified counter
	if (ctr_name) {
		cn = ctr_name;
		}

	else {
		// no counter specified or assumed, so don't render it.
		return;
		}

	if (cn==null || cn=='' || cn==' ' || cn.indexOf('.htm')>=0 || cn.indexOf('<!')>=0){
		return;
		}

	var ctr_link_params = 'ctr='+cn;
	ctrurl = cgilink('counter_image.cgi', ctr_link_params);
	var ctr_link = '<img src='+ctrurl+' width=1 height=1 border=0>';

	write_on_wdow (ctr_link, wdow);

	// use counter id to track history as pages are laoded
	if (history_limit){
		add_page_history(ctr_name,wdow);
		}
	}

// Jumps to a location within a page -----
function pageJump(label_name,wdow) {

	if (wdow) {
		wdow.location.hash=label_name;
		}
	else {
		location.hash=label_name;
		}
	}

// ================== History Record ====================================
// records pages visited, with counts and when visited
// used for quick links to history
// may also be useful for histeresis in the way pages & links behave

// object of pages, each page is an obj of time and count
// global to the page
var hist_obj_obj;

function add_page_history (page, wdow) {

	// to switch off the behaviour for all
	// but me when debugging/testing
	//if (!confirm_debug()){
	//	return;
	//	}

	// build hist obj if it doesn't already exist
	// can be built from the cookie at any time
	if (!hist_obj_obj){
		hist_obj_obj = new hist_obj_build();
		}

	page = derive_page_address(page);
	hist_obj_obj.obj_all_page = page;
	// current time
	var sys_time = new Date();

	// some pages just don't get recorded
	if (!skip_index(page)){

		// build hist obj if it doesn't already exist
		// can be built from the cookie at any time
		if (!hist_obj_obj){
			hist_obj_obj = new hist_obj_build();
			}

		// update history obj with current page
		if (hist_obj_obj[page]){
			// repeat visit, update and count
			hist_obj_obj[page].p_title = title_tidy(document.title);
			hist_obj_obj[page].p_count++;
			hist_obj_obj[page].p_time = parseInt(sys_time.getTime()/1000);
			}
		else {
			// first time for this page
			hist_obj_obj[page] = new hist_obj_item_build(document.title);
			}
		}

	var clear_page=''; // page name to skip later?
	// Make a note of the oldest page, to clear if the limit is exceeded.
	var prev_size = hist_obj_obj.obj_all_size;
	if (prev_size > history_limit){
		// work out which item is oldest
		var oldest = parseInt(sys_time.getTime()/1000);
		for (hist_item in hist_obj_obj){
			if (hist_obj_obj[hist_item].p_time < oldest){
				oldest = hist_obj_obj[hist_item].p_time;
				clear_page = hist_item;
				}
			}
		}

	var hc2='';
	// assemble the list to keep in the cookie
	for (hist_item in hist_obj_obj){
		// skip parameters we are not interested in
		if (hist_item.indexOf('obj_all_')==0){
			continue;
			}
		// skip an item if it is the one to be cleared
		if (hist_item != clear_page){
			hc2+= (hist_item+'::'+hist_obj_obj[hist_item]);
			hc2+= '||';
			}
		}
	// tidy up at the end
	hc2=hc2.replace(/\|\|$/,'');

	if (hc2){
		//setCookie(history_cookie, '');
		setCookie(history_cookie, hc2);
		//alert (hc2.replace(/\|\|/gi,'\n'));
		}

	// create a history selection control
	// for display later
	create_history_select_control();

	}

function hist_obj_build() {
	var hc = getCookie(history_cookie);
	var hix;
	var hist_item;
	this.obj_all_size=0;
	if (hc) {
		//alert ('HC before \n'+hc);
		for (hix in (hc.split('||'))){
			hist_item = hc.split('||')[hix];
			if (!hist_item){
				continue;
				}
			var p_name = hist_item.split('::')[0];
			var p_count = hist_item.split('::')[1]||'';
			var p_time = hist_item.split('::')[2]||'';
			var p_title = hist_item.split('::')[3]||p_name;
			if (p_name && p_count && p_time) {
				this[p_name] = new hist_obj_item_build(p_title, p_count, p_time);
				this.obj_all_size++;
				}
			}
		}
	}

// build an item in the hist_obj_obj. count defaulkts to 1, time defaults to now.
function hist_obj_item_build (p_title, p_count, p_time){
	this.p_title = title_tidy(p_title);
	this.p_count = parseInt(p_count)||1;
	if (p_time){
		this.p_time = parseInt(p_time);
		}
	else {
		// current time
		var sys_time = new Date();
		// not interested in milliseconds, so save some space in the cookie
		this.p_time = parseInt(sys_time.getTime()/1000);
		}
	this.toString = function () {
		return this.p_count+'::'+this.p_time+'::'+this.p_title;}
	}

// turn what may be a page address or counter into a simple address within the site
function derive_page_address(page){
	page=page.replace(/^[\.\/\/]+/, '');
	page=page.replace(/\.[a-zA-Z0-9]+$/, '');
	return page;
	}

// get absolute page address
function get_site_base_addr(){
	// options lower down the list carry progressively more risk of
	// failing later, but may be less likely to fail now!!
	var site ='document.location.href';

	try{
		if (document && document.location && document.location.hostname){
			site = document.location.hostname;
			}
		else if (parent && parent.location && parent.location.hostname){
			site = parent.location.hostname;
			}
		else if (top && top.location && top.location.hostname){
			site = top.location.hostname;
			}
		else if (window && window.location && window.location.hostname){
			site = window.location.hostname;
			}
		else if (parent && parent.location && parent.location.href){
			site = parent.location.href;
			}
		else if (top && top.location && top.location.href){
			site = top.location.href;
			}
		else if (window && window.location && window.location.href){
			site = window.location.href;
			}
		else {
			site = document.location.href;
			}
		}
	catch (exception_obj){

		}

	// trim any 'http://' from the start
	site = site.replace(/(^http:\/\/)/,'');
	// trim any other parameters from the end
	if (site.indexOf('/')>0){
		var s_result;
		// maybe in a local path, which means we have to keep up to &
		// including docs. eg http://localhost/psa/docs/.....
		if (
				(s_result = site.match(/(localhost\/.+\/docs)/))
				&&
				(s_result != null)
			){
			site = s_result[1];
			}
		// maybe just have parameters on a real web address
		// so cut them off. eg http://www.psainternational.co.uk/info/...
		else {
			site = site.split('/')[0];
			}
		}

	// final catch for offline - should have been sorted earlier
	if (site == 'localhost'){
		var s_result;
		// maybe in a local path, which means we have to keep up to &
		// including docs. eg http://localhost/psa/docs/.....
		if (
				(s_result = document.location.href.match(/localhost(\/.+\/docs)/))
				&&
				(s_result != null)
			){
			site += s_result[1];
			}
		// worst case assumption - within psa development
		else {
			site+='/new_hwhyde/docs';
			}
		}
	return site;
	}

// look for pages that we don't include, like those already in the menu
function skip_index(page){
	if (page == 'home_page'){
		return 1;
		}
	return;


	// remainder ignored
	var m_page='';
	var m_item="";
	var usr_sec;
	// Menu_Data is a global array
	for (m_ix in Menu_Data){
		// loop through menu data array, looking for our page
		m_item=Menu_Data[m_ix];
		if (! m_item){
			continue;
			};
		m_page = m_item.split('||')[1]||'';
		if (! m_page){
			continue;
			};
		m_page = m_page.replace(/^[\.\/\/]+/, ''); // remove leading stuff
		m_page = m_page.replace(/\.[a-zA-Z0-9]+$/, ''); // remove extension

		// use indexOf to test, because page is absolute, whereas index is relative
		if (page.indexOf(m_page)>=0){
			return 1;
			}
		}
	return;
	}

// actually create the control to select from history
function create_history_select_control(){
	// build hist obj if it doesn't already exist
	// can be built from the cookie at any time
	if (!hist_obj_obj){
		hist_obj_obj = new hist_obj_build();
		}

	// assemble the page list from the cookie
	var hist_op =new Array();
	for (hist_item in hist_obj_obj){
		// skip parameters we are not interested in
		if (hist_item.indexOf('obj_all')>=0){
			continue;
			}
		// skip current page
		if (hist_item == hist_obj_obj.obj_all_page){
			continue;
			}
		hist_op.push(hist_item);
		}
	// no display if no history
	if (hist_op.length<1){
		return;
		}
	hist_op.sort(hist_cmp);

	// generate select options from the page list
	var hist_op2 =new Array();
	var hix;
	for (hix in hist_op){
		hist_item = hist_op[hix]
		var p_title = hist_obj_obj[hist_item].p_title;
		p_title = title_tidy(p_title);
		var hsel = '<option value="'+hist_item+'">'+p_title;
		//alert (hsel);
		hist_op2.push(hsel);
		}

	// no display if no history
	if (hist_op2.length<1){
		return;
		}

	var op='';
	op += '\n<div class="hm" id="history_bar_div">';
	op += '<center><form><select name="history_menu" onChange="return hist_go(this.form);">';
	op += hist_op2.join('\n');
	op += '</select>';
	op += '<input type="submit" value="Go" onClick="return hist_go(this.form);">';
	op += ' ';
	op += '<input type="submit" value="What&#146;s New" onClick="return whats_new_go(this.form);">';
	op += ' ';
	op += '<input type="textfield" name="search_terms" size="20" maxlength="100">';
	op += '<input type="submit" value="Search" onClick="return search_go(this.form);">';
	op += '</center></form>';
	op += '</div>\n';
	write_on_wdow (op);
	var hm_id = document.getElementById("history_bar_div");
	hm_id.style.visibility="hidden";

	var op2='';
	op2+='\n<script>document.onLoad = activate_history_select();</script>\n';
	write_on_wdow (op2);
	}

// sort compare function for history
function hist_cmp(a,b){
	// build hist obj if it doesn't already exist
	// can be built from the cookie at any time
	if (!hist_obj_obj){
		hist_obj_obj = new hist_obj_build();
		}
	// hist_sort_by is a global config that
	// names the attribute to sort by
	var a_m = hist_obj_obj[a][hist_sort_by];
	var b_m = hist_obj_obj[b][hist_sort_by];

	// number (time?) sorts to highest first
	if (typeof(a_m) == 'number'){
		if (a_m < b_m) return 1;
		if (a_m > b_m) return -1;
		return 0;
		}
	// anything else sorts to lowest first
	if (a_m > b_m) return 1;
	if (a_m < b_m) return -1;
	return 0;
	}

// tidy up a title
function title_tidy (title_text){
	title_text = title_text.replace(/<[^>]+>/gi, ''); // remove any formatting tags
	title_text = title_text.replace(/\([^\)]+\)/gi, ''); // remove any parenthesis
	title_text = title_text.replace(history_unwanted_text_re, ''); // remove any others
	title_text = title_text.replace(/\&amp\;/, 'and'); // amphersand
	return title_text;
	}

// history control is only activated on load
function activate_history_select(){
	var hm_id = document.getElementById("history_bar_div");
	if (hm_id){
		var co_ords = new guess_history_co_ords();
		hm_id.style.position="absolute";
		hm_id.style.left=co_ords.c_left;
		hm_id.style.top=co_ords.c_top;
		hm_id.style.visibility="visible";
		}
	}

function guess_history_co_ords(){
	this.c_left = '0px';
	this.c_top = '0px';
	if (document.getElementsByTagName("h1")){
		var first_h1 = document.getElementsByTagName("h1")[0];
		if (first_h1){
			this.c_left = first_h1.offsetLeft;
			this.c_top = first_h1.offsetTop;
			//alert('h1 found LEFT:'+this.c_left+' TOP:'+this.c_top);
			}
		}
	return;
	}

// actually navigate to the selected history page, when the go button is clicked
function hist_go(hmf){
	var page = hmf.history_menu.value;
	var site = get_site_base_addr();
	//alert ('http://'+site +'/'+ page + '.htm');
	top.location.href = 'http://'+site +'/'+ page + '.htm';
	return false;
	}

function search_go(sf){
	var page = 'sys_cgi-bin/search_site.cgi';
	var site = get_site_base_addr();
	var sterms = 'search_terms='+sf.search_terms.value;
	document.location.href = 'http://'+site +'/'+ page + '?'+ sterms;
	return false;
	}

function whats_new_go(sf){
	var page = 'info/whats_new.htm';
	var site = get_site_base_addr();
	top.location.href = 'http://'+site +'/'+ page;
	return false;
	}

// ================== Menu Display ====================================
function autosub(form_name){
	document.forms[form_name].submit();
	}

function menuLoad(){
	var wname = '../sys_menu/menu.htm';
	//alert(wname);
	parent.menu.location=wname;
	}

var ml_1 = '<tr><td class=mnu id=';
var ml_1H = '<nobr><span class=mnu id=';
var ml_2 = ' onClick="return click_menu_item(';
var ml_2a = ')" onMouseOut="return unhover_menu_item(event,';
var ml_2b =	')" onMouseOver="return hover_menu_item(event,';
var ml_2c =	')" onContextMenu="return right_click_menu_item(event,';
var ml_3 = ')">&nbsp;';
var ml_4 = '&nbsp;</td></tr>\n\n';
var ml_4H = '&nbsp;</span></nobr>\n\n';

function write_v_menu_item (item_to, item_label, ix, wdow){
	var lbl_name = "'"+item_label+"'"; // not used
	var item_id = "'"+item_label+ix+"'";
	var click_to = "'"+item_to+"'";
	write_on_wdow(ml_1+item_id+ml_2+click_to+ml_2a+item_id+ml_2b+item_id+ml_2c+item_id+ml_3+item_label+ml_4+'\n', wdow);
	}

function write_h_menu_item (item_to, item_label, ix, wdow){
	var lbl_name = "'"+item_label+"'";// not used
	var item_id = "'"+item_label+ix+"'";
	var click_to = "'"+item_to+"'";
	write_on_wdow(ml_1H+item_id+ml_2+click_to+ml_2a+item_id+ml_2b+item_id+ml_2c+item_id+ml_3+item_label+ml_4H+'\n', wdow);
	}


function click_menu_item(click_to){
	top.location.href = prefix+click_to;
	}
function hover_menu_item(event_id, item_id){
//debug ('hover_menu_item '+event_id+item_id);
	var menu_obj=document.getElementById(item_id);
	menu_obj.className="mnu_on";
	}
function unhover_menu_item(event_id, item_id){
//debug ('unhover_menu_item '+event_id+item_id);
	var menu_obj=document.getElementById(item_id);
	menu_obj.className="mnu";
	}
function right_click_menu_item(event_id, item_id){
	return false;
	}

// put together the menu as prescribed by menu.js file
function vertical_menu_bar(wdow) {
	write_on_wdow ('<p class="mr"><table class=all_menu>');
	var ix=1;
	var M_Item_Name='';
	var M_Item_Link='';
	var M_Item_Security='';
	var Menu_Item="";
	var usr_sec;
	for (Menu_Index in Menu_Data){
		// loop through menu data array, displaying each item
		Menu_Item=Menu_Data[Menu_Index];
		if (! Menu_Item){
			continue;
			};
		M_Item_Name = Menu_Item.split('||')[0]||'';
		M_Item_Link = Menu_Item.split('||')[1]||'';
		M_Item_Security = Menu_Item.split('||')[2]||'All';

		if (! M_Item_Name){
			continue;
			};
		if (! M_Item_Link){
			continue;
			};
		if (! M_Item_Security){
			M_Item_Security='All';
			};

		// Security test to be inserted. Next if fails;
		usr_sec = user_security_ok(M_Item_Security);
		if (usr_sec == M_Item_Security){
			if (check_browser_capability()){
				// Display menu line
				write_v_menu_item(M_Item_Link, M_Item_Name, ix, wdow);
				}
			else {
				// Display simpler menu link
				write_on_wdow ('<tr><td align=right>');
				write_on_wdow ('<a href='+prefix+M_Item_Link+' target=_top>'+M_Item_Name+'</a>',wdow);
				write_on_wdow ('</td></tr>',wdow);
				}
			}
		ix++;
		}
	write_on_wdow ('</table></p>');
	write_on_wdow ('<br clear=all>',wdow);

	// Counter
	var set_ctr_string = '<img src="../sys_cgi-bin/counter_image.cgi" width=1 height=1 border=0>';

	// only do counter if more than 1 mins since last here
	// last time
	var tc = getCookie(time_cookie);
	last_time = parseInt(tc);
	// this time
	var sys_time = new Date();
	var the_time = sys_time.getTime();
	setCookie(time_cookie, the_time+' ');

	if (((the_time-last_time)/(1000*60))>1){
		document.write(set_ctr_string);
		//debug ('counter\n'+(the_time-last_time)/1000 + ' seconds');
		}
	else {
		//debug ('no counter\n'+(the_time-last_time)/1000+ ' seconds');
		}
	}

function horizontal_menu_bar(wdow) {
	write_on_wdow ('<p class="mc">');
	var ix=1;
	var M_Item_Name='';
	var M_Item_Link='';
	var M_Item_Security='';
	var Menu_Item="";
	for (Menu_Index in Menu_Data){
		// loop through menu data array, displaying each item
		Menu_Item=Menu_Data[Menu_Index];
		if (! Menu_Item){
			continue;
			};
		M_Item_Name = Menu_Item.split('||')[0]||'';
		M_Item_Link = Menu_Item.split('||')[1]||'';
		M_Item_Security = Menu_Item.split('||')[2]||'All';

		if (! M_Item_Name){
			continue;
			};
		if (! M_Item_Link){
			continue;
			};
		if (! M_Item_Security){
			M_Item_Security='All';
			};

		// Security test. Next if fails;
		if (user_security_ok(M_Item_Security) == M_Item_Security){
			// display depending on script version..
			if (check_browser_capability()){
				// Display flashy menu line
				write_h_menu_item(M_Item_Link, M_Item_Name, ix, wdow);
				}
			else {
				// Display simpler menu link
				write_on_wdow ('<nobr>[',wdow);
				write_on_wdow ('<a href='+prefix+M_Item_Link+' target=_top>'+M_Item_Name+'</a>',wdow);
				write_on_wdow (']</nobr> ',wdow);
				}
			}
		ix++;
		}
	write_on_wdow ('</p><br clear=all>',wdow);
	}

function check_browser_capability() {
	brs_v = navigator.appVersion;
	if (parseInt(brs_v) >= 5) return true;
	var ua=navigator.userAgent;
	var MSIEOffset = ua.indexOf("MSIE ");
	if (MSIEOffset>=0) {
		var iev = parseFloat(ua.substring(MSIEOffset+5, ua.indexOf(";",MSIEOffset)));
		if (iev >= 5) return true;
		}

	// before v5, so work in reduced menu...

	return false;
	}


//=======================Security related =========================
function set_sec_viz(wdow){
	// enable display of restricted info by changing
	// a style rule
	return; // bypassed - not needed with the crypted conditional write. Kee in case a use later.
	var ns1a = 'SPAN.xri';
	var ns1b = 'DIV.xri';
	var ns2a = '{display:inline}\n'; // show it
	var ns2b = '{display:none}\n';   // dont show it
	var new_style;
	write_on_wdow ('<style type="text/css">',wdow);
	var security_cats = list_security_cats ();
	// loop through security cats, setting styles to show or not show
	// the secured info
	var authority = get_authority(login_cookie);
	for (var rix in security_cats){
		ref_level = security_cats[rix];
		if (ref_level=="All"){
			continue;
			}
		if (check_authority (authority, ref_level)){
			nsspn = ns1a+ref_level+ns2a;
			nsdiv = ns1b+ref_level+ns2a;
			}
		else {
			nsspn = ns1a+ref_level+ns2b;
			nsdiv = ns1b+ref_level+ns2b;
			}
		write_on_wdow (nsspn,wdow);
		write_on_wdow (nsdiv,wdow);
		}
 	write_on_wdow ('</style>',wdow);
	}

function xrieval(eref_level, esection, op2){
	// inline reveal fn

	var ref_level = dec_cg_param(eref_level);
	var section = dec_cg_param(esection);
	var dec_op2 = dec_cg_param(op2);

	var authority = get_authority(login_cookie);
	if (check_authority (authority, ref_level)){
		//alert(cookieDump() + '\n' + authority);
		write_on_wdow (dec_op2);
		}
	return;
	}

// do whatever decoding is necessary
function dec_cg_param (enc_cg){

	// unescape uri
	var dec_cg = decodeURIComponent(enc_cg);
	// remove other encoding
	var unenc_cg = unenc_it(dec_cg);
	return unenc_cg;
	}

// Make it into a decimal and dot string
function enc_it (inp){
	// numbers from x22 to xEE
	var hkey = parseInt(16*parseInt(Math.random()*12+2)+parseInt(Math.random()*12+2))%256;
	var hinp = " ";
	var ch1;
	var ch2;
	for (var chix=0; chix<inp.length; chix++ ) {
		ch1 = inp.charCodeAt(chix)%256;
		ch2= parseInt(ch1^hkey);
		hinp = hinp+"."+ch2;
//		alert (chix+'\n'+ch1+'\n'+ch2+'\n'+hinp);
		}
	hinp=hinp.substr(2);
	hinp=hinp+"."+hkey;
 	return hinp;
	}

function test_stuff(){
//	var ts='Hello John!';
//	var encts = enc_it(ts);
//	alert (ts+'\n'+encts+'\n'+conditional_unenc_it(encts) );
//alert (cookieDump());
	}


// turn decimal and dot back into text
// - nothing that secure, just designed to stop idle curiosity
function unenc_it (hinp){
	var inp="";
	var hch1;
	var hch2;
	var hchix;
	var hinp_chars =new Array();
	hinp_chars = hinp.split('.');
	var hkey = parseInt(hinp_chars.pop())%256; // last item is the key
	for (hchix in hinp_chars) {
		hch1 = parseInt(hinp_chars[hchix])%256;
		hch2=(hch1^hkey)%256;
		inp = inp + String.fromCharCode(hch2);
		}
	return inp;
	}

function conditional_unenc_it (hinp){
	if (!hinp){  //empty str
		return "";
		}
	if (	(hinp.match(/[^0-9\.]{1}/)) || // anything other than 0-9 or dot
			(hinp.indexOf('.')==-1)		 // or no dots in it
		){
		// not crypted
		return hinp;
		}
	return unenc_it (hinp);
	}

function conditional_enc_it (inp){
	if (!inp){ //empty str
		return "";
		}

	if (	(inp.match(/[^0-9\.]{1}/)) || // anything other than 0-9 or dot
			(inp.indexOf('.')==-1)		 // or no dots in it
		){
		// not crypted
		return enc_it (inp);
		}
	return inp;
	}


function get_authority (cookiename){
	// get any long term user info from cookie
	// usr||pw||authority
	// authority has optional -L, -X
	if (getCookie(cookiename) && getCookie(cookiename).split('||')[2] ) {
		return (getCookie(cookiename).split('||')[2]);
		}
	return 'All';
	}

function user_security_ok (req_level){
	// authority of a remembered user
	var usr_level=get_authority(user_cookie);
	// authority of a logged in user
	var auth_level=get_authority(login_cookie);

	// Simple exit if visible to all
	if (req_level == 'All'){
		return req_level;
		}

	// trim -L from end
	var subreq=req_level;
	if (req_level.indexOf('-')>0) {
		subreq=req_level.split('-')[0];
		//debug('user_level='+usr_level+'\nauth_level='+auth_level+'\nreq_level='+req_level+'\nsubreq='+subreq);
		}

	// looking for login specific level - get from user_authority
	if (req_level.indexOf('-L')>0){
		// -X inverts the filter
		// as inverted, both usr & login auth are important
		if (req_level.indexOf('-X')>0){
			if (check_authority(usr_level,subreq)){
				return 'All';
				}
			else if (check_authority(auth_level,subreq)){
				return 'All';
				}
			else {
				return req_level;
				}
			}
		// filter not inverted
		if (check_authority(usr_level,subreq)){
			return req_level;
			}
		}

	// looking for authority of a logged in user - get from li_authority

	// -X inverts the filter
	if (req_level.indexOf('-X')>0){
		if (check_authority(auth_level,subreq)){
			return 'All';
			}
		else {
			return req_level;
			}

		}
	// Filter not inverted
	if (check_authority(auth_level,subreq)){
		return req_level;
		}

	// Anything else is All

	return 'All';
	}

//check the reuired level is as good as or better than the user's level
function check_authority (user_auth, req_auth){
	// quick solution for 'All'
	if (req_auth=='All'){
		return true;
		}

	// quick solution for exact match
	if (user_auth == req_auth){
		return true;
		}

	// quick solution for grouping numbers
	var sra= req_auth.replace(/[\d]+/, '');
	if (user_auth == sra){
		return true;
		}

	// user_auth contains a digit, and $req_auth is in the same group
	// but they are not the same (as shown above)
	var sua = user_auth.replace(/[\d]+/, '');
	if ((sua != user_auth)&&(sua == sra)){
		return false;
		}
	// (can now ignore grouping numbers)

	// now check actual levels
	var auth_levels = '|'+ list_security_cats().join('|')+'|';
	if (auth_levels.indexOf('|'+user_auth+'|') >= auth_levels.indexOf('|'+req_auth+'|')){
		return 1;
		}
	return false;
	}


//list all security levels
function list_security_cats () {
	var Level_Index;
	var Level;
	var Sub_Level_Items = new Array();
	var Sub_Level_Index;
	var Sub_Level;
	var All_Cats_List = new Array();
	var ix=0;
	for (Level_Index in Security_Levels){
		// loop through security level array
		Level=Security_Levels[Level_Index];
		if (! Level){
			continue;
			};
		Sub_Level_Items = Level.split(',');
		for (Sub_Level_Index in Sub_Level_Items){
			// loop through security sub level
			Sub_Level=Sub_Level_Items[Sub_Level_Index];
			if (! Sub_Level){
				continue;
				};
			All_Cats_List[ix]=Sub_Level;
			ix++;
			}
		}
	return All_Cats_List;
	}

// =================== Preview tips - on status bar and in popup =======================
// (Nothing to do with page level tips)

var currentdescription;
var tid;
var i=0;

// Clear the tip
function cPrev() {
	window.clearTimeout(tid);
	currentdescription=' ';
	// link to code for popup tool tips
	clear_tool_tip();
	window.status=' ';
	i = 0;
	return true;
	}

// Show the tip
function dPrev(description,evt,frameflag) {
	evt=(evt)?evt:event;
	window.clearTimeout(tid);
	currentdescription=' '+description;
	i = 0;

	// link to code for popup tool tips
	// frame flag used my menu to tell tip to pop in main window
	if (frameflag) {
		show_frame_tool_tip(currentdescription,evt);
		}
	else {
		show_tool_tip(currentdescription,evt);
		}

	if (currentdescription.length>100) {
		currentdescription='          '+description+'          ';
		window.status=currentdescription;
		scrollStatus();
		return true;
		}
	else {
		window.status=currentdescription;
		return true;
		}

	return true;
	}

// Scroll long tips
function scrollStatus() {
	window.status = currentdescription.substring(i,currentdescription.length) + currentdescription.substring(0,i-1);
	if (i < currentdescription.length) {
		i++;
		}
	else {
		i = 0;
		}
	tid = setTimeout('scrollStatus()',150);
	return true;
	}

// filter click action to only link for real events.
function cFilter(description) {
	window.clearTimeout(tid);
	window.status=' ';
	currentdescription=' '+description;
	i = 0;
	return true;
	}

//===========================tool tips in a pseudo window========================

// Init tip system for later content
var tipon=0;
var tipid;
function tip_prepare(wdow) {
	// may need to quit early for old browsers...
	if (tipon) return;
	if (!document.getElementById)return;
	tipon ++;
	var tip_style1="position:absolute;top:0px;left:0px;background-color:#ffffe8;";
	var tip_style2="color:black;font-size:10pt;text-align:left;font-family:Arial;border-width:1;border-color=black;border-style:solid;padding:3px 3px;";

	write_on_wdow ('<div id="tipdiv" style="'+tip_style1+tip_style2+'" visible=false>',wdow);
	write_on_wdow ('tip', wdow);
	write_on_wdow ('</div>',wdow);

	tipid = document.getElementById("tipdiv");

	tipid.style.visibility="hidden";
	return;
	}

function getPageEventCoords(evt) {
    var coords = {left:0, top:0};
    if (evt.pageX) {
        coords.left = evt.pageX;
        coords.top = evt.pageY;
    	}
    else if (evt.clientX) {
        coords.left =
            evt.clientX + document.body.scrollLeft - document.body.clientLeft;
        coords.top =
            evt.clientY + document.body.scrollTop - document.body.clientTop;
        // include html element space, if applicable
        if (document.body.parentElement && document.body.parentElement.clientLeft) {
            var bodParent = document.body.parentElement;
            coords.left += bodParent.scrollLeft - bodParent.clientLeft;
            coords.top += bodParent.scrollTop - bodParent.clientTop;
        	}
    	}
    return coords;
	}

function show_tool_tip(tip,evt){
	if (!tipid) return;
	if (!tip) return;
	if (!document.createTextNode) return;

	// kill any leading date stuff, as most likely hovering on a date anyway
	var ntip=tip.replace(/^\s*[0-9]{1,2}-[a-z]{3}\s*/i,'');
	var ntip=ntip.replace(/^\s*is\s*/,'');

	var coords = getPageEventCoords(evt);
	var tipmsg = document.createTextNode(ntip);
	var oldmsg = tipid.replaceChild(tipmsg, tipid.firstChild);

	var units = (typeof tipid.style.left == "string")?"px":0;
	tipid.style.left=(coords.left>width_trip(tip))?(width_trip(tip)+units):(coords.left+20+units);
	tipid.style.top=coords.top+15+units;

	tipid.style.visibility="visible";
	}

// Tip code for displaying tip in other frame
var frtipid;
function show_frame_tool_tip(tip,evt){
	if (!tip) return;
	// confirm support for functionality
	if (!parent) return;
	if (!parent.frames[1]) return;
	if (!parent.frames[1].document) return;
	if (!parent.frames[1].document.getElementById) return;
	if (!document.createTextNode) return;
	// Get the id of the tip popup
	frtipid=parent.frames[1].document.getElementById("dstipdiv");
	if (!frtipid) return;

	// kill any leading date stuff, as most likely hovering on a date anyway
	var ntip=tip.replace(/^\s*[0-9]{1,2}-[a-z]{3}\s*/i,'');
	var ntip=ntip.replace(/^\s*is\s*/,'');

	var coords = getPageEventCoords(evt);

	var units = (typeof frtipid.style.left == "string")?"px":0;
	var left_offset=3;
	var top_offset=5;

	// allow for scrolling of other window
	if (parent.frames[1].document.body.scrollTop){
		top_offset+= parent.frames[1].document.body.scrollTop;
		}

	var tipmsg = parent.frames[1].document.createTextNode(ntip);
	var oldmsg = frtipid.replaceChild(tipmsg, frtipid.firstChild);

	frtipid.style.left = left_offset+units;
	frtipid.style.top=coords.top+top_offset+units;
	frtipid.style.visibility="visible";
	}

// Erase any tips displayed in this or other frame - no need to be clever and track it,
// just clear everything
function clear_tool_tip(){
	if (tipid) {
		if (tipid.style.visibility){
			tipid.style.visibility="hidden";
			}
		}
	if (frtipid){
		if (frtipid.style.visibility){
			frtipid.style.visibility="hidden";
			}
		}
	return;
	}

// work out what number to trip on when approaching right margin
function width_trip(tip) {
	var room = (tipid.style.width)?(tipid.style.width):'300px';
	room = parseInt(room.replace(/[^0-9]+/g,''))+30;
	// trip for short text...
	room = (tip.length<30)?150:room;

	if (window.innerWidth) {
		return (window.innerWidth-room);
		}
	if (document.body && document.body.clientWidth){
		return (document.body.clientWidth-room);
		}
	var dwidth=900;
	return (dwidth - room);
	}


// ================================== Cookies ==============================

// retrieve cookie by name
function getCookie(name) {
    var lookfor = name + "=";
    var cookiestext = document.cookie;
    var i = 0;
    while (i < cookiestext.length) {
        var j = i + lookfor.length;
        if (cookiestext.substring(i, j) == lookfor) {
    		var k = cookiestext.indexOf (";", j);
    		if (k < 0) {
        		k = cookiestext.length;
    		}
    	cookietext = cookiestext.substring(j, k);
   	   	return unescape(conditional_unenc_it(cookietext));
        }
        i = cookiestext.indexOf(" ", i) + 1;
        if (i == 0) return null;
    }
    return null;
}

// store cookie value for 1 yr, site wide.
function setCookie(name, value) {
    var expDate = new Date();
    expDate.setDate(expDate.getDate() + parseInt(365));
    var expires = expDate.toGMTString();
    document.cookie = name + "=" + escape (value) +
    				"; expires=" + expires +
     			  	"; path=" + "/" ;
    return true;
	}


// delete cookie value, site wide.
function deleteCookie(name) {
    var expDate = new Date();
   	expDate.setDate(expDate.getDate() - parseInt(3)); // 3 days ago!!
    var expires = expDate.toGMTString();
    document.cookie = name + "=" +
    				"; expires=" + expires +
     			  	"; path=" + "/" ;
    return true;
	}

// ====================== Popup Preview Windows =========================
// for previews of pics, schedule rows etc...
function show_preview_window_of_online_pic (pic){
	if ((pic=='none')||(!pic)){
		return false;
		}
	var body_text = '<p class=c><IMG src='+ docs_base() + pic +'><br clear=all>' + pic +'</p>';
	show_preview_window ("Preview of file online", "File online", body_text);
	}

function show_preview_window_of_local_pic (pic){
	if ((pic=='none')||(!pic)){
		return false;
		}
	var body_text = '<p class=c><IMG src=file:///'+ pic +'><br clear=all>' + pic +'</p>';
	show_preview_window ("File on your PC - ready for upload", "File on your PC", body_text);
	}

function show_preview_window (title, head, body_text){
	var PreviewWindow = window.open('','preview','scrollbars=yes,resizable=yes,width=900,height=700');
	write_on_wdow('<HTML><HEAD><TITLE>'+title+'</TITLE>', PreviewWindow);
	include_style (docs_base(), PreviewWindow);
	write_on_wdow('<h1>'+head+'</h1>',PreviewWindow);
	write_on_wdow(body_text,PreviewWindow);
	page_end_credit(PreviewWindow);
	write_on_wdow('</BODY></html>',PreviewWindow);
	PreviewWindow.document.close();
	PreviewWindow.focus();
	}

// Work out host/target doc base from the referencing docs url
function docs_base (){
		return "../";
	}


// ======================== CGI linking & frame building ==============================

// Attach any relevant params to a cgi/uri - from parent, from doc, or from param string passed.
function cgilink (cgi, params){
	var baselink = cgibin+cgi;

	// used to have top.location.search in here, but problems with security if framed from outside
	try {
		if (window && window.location && window.location.search){
			baselink = add_srch_params (baselink, window.location.search);
			}
		}
	catch (exception_obj){
		}
	try {
		if (parent && parent.location && parent.location.search){
			baselink = add_srch_params (baselink, parent.location.search);
			}
		}
	catch (exception_obj){
		}
	try {
		if (document && document.location && document.location.search){
			baselink = add_srch_params (baselink, document.location.search);
			}
		}
	catch (exception_obj){
		}

	if (params){
		baselink = add_srch_params (baselink, params);
		}return baselink;
	}

// Adds more ?& params nicely to the end of a path
function add_srch_params (srchstr, params) {
	var webstr=srchstr;
	if (params) {
		// cut anything unwanted inc '?' of the start of the params
		if (params.indexOf('?')>=0){
			params = params.substring(params.indexOf('?')+1);
			}
		if (srchstr.indexOf('?')>0){
			// extend params
			webstr= srchstr+'&'+params;
			}
		else {
			webstr= srchstr+'?'+params;
			}
		}
	webstr = remove_duplicate_params (webstr);
	return webstr;
	}

// Remove duplicate params from uri - the methods used above to
// make sure all params are collected can catch some twice!
function remove_duplicate_params (webstr){
	if (webstr.indexOf('?')<1) {
		return webstr;
		}
	var uri = webstr.split('?')[0];
	var paramlist = webstr.split('?')[1];

	if (! (paramlist.indexOf('&')>=0)){
		// only 1 parameter
		return uri + '?' + paramlist;
		}

	var paramparts = new Array();
	paramparts = paramlist.split ('&');
	paramparts = paramparts.sort();
	var outparams="?";
	var currentparam;
	var lastparam="";
	for (iparam in paramparts) {
		currentparam = paramparts[iparam];
		if (!(currentparam == lastparam)){
			if (outparams=="?"){
				outparams = outparams+currentparam;
				}
			else {
				outparams = outparams+"&"+currentparam;
				}
			}
		lastparam=currentparam;
		}
	return uri + outparams;
	}


// Outputs a framed page with dsmenu and specified cgi in frame
function make_framed_cgi (cgi, params){
	var page_link = cgilink (cgi, params);
	var menu_set = '<frameset cols = "210,*" border=0 frameborder=0><frame name="menu" src="'+prefix+'sys_menu/menu.htm" marginwidth=0 marginheight=0 scrolling="auto" noresize>';

	var frame_intro = ' <frameset border=0 frameborder=0><frame name="indiv" src="';
	var frame_end = '" marginwidth=10 marginheight=0 scrolling="auto"></frameset>';

	write_on_wdow (deepsea_menu_set);
	write_on_wdow (frame_intro+page_link+frame_end);
	}

// Outputs a framed page with menu and specified doc in frame
function make_framed_htm (htm, params){
	var page_link = htm;
	if (top.location.search){
		page_link = add_srch_params (page_link, top.location.search);
		}
	if (document.location.search){
		page_link = add_srch_params (page_link, document.location.search);
		}
	if (params){
		page_link = add_srch_params (page_link, params);
		}

	var deepsea_menu_set = '<frameset cols = "210,*" border=0 frameborder=0><frame name="menu" src="'+prefix+'sys_menu/menu.htm" marginwidth=0 marginheight=0 scrolling="auto" noresize>';

	var frame_intro = ' <frameset border=0 frameborder=0><frame name="indiv" src="';
	var frame_end = '" marginwidth=10 marginheight=0 scrolling="auto"></frameset>';

	write_on_wdow (deepsea_menu_set);
	write_on_wdow (frame_intro+page_link+frame_end);
	}


function get_nice_path(){
	if (window.location.pathname) {
		return window.location.pathname;
		}
	if (window.location.href) {
		var pathstuff = window.location.href;
		pathstuff = pathstuff.replace (/\?.*/, ''); // kill all after ?....
		return pathstuff;
		}
	if (document.location.pathname) {
		return  document.location.pathname;
		}
	if (document.location.href) {
		var pathstuff = document.location.href;
		pathstuff = pathstuff.replace (/\?.*/, ''); // kill all after ?....
		return  pathstuff;
		}
	if (document.url.pathname) {
		return  document.location.pathname;
		}
	if (document.url.href) {
		var pathstuff = document.location.href;
		pathstuff = pathstuff.replace (/\?.*/, ''); // kill all after ?....
		return  pathstuff;
		}
	return "";
	}


// === Error code diagnosis ======================================

var http_error_codes = {
	err400: "Bad Request:Our web server could not process the request due to a bad command or syntax.",
	err401: "Authorisation Required:Our web server could not process the request because you are not authorised to enter this restricted area of our site.",
	err403: "Forbidden:Our web server could not process the request because you have attempted to enter a forbidden area of our site.",
	err404: "File Not Found:Our web server could not process the request because the file or script could not be found.",
	err500: "Internal Server Error:Our web server has encountered an unexpected condition that prevented it from completing the request.",
	err501: "Not Implemented:Our web server does not support the functionality required to fulfill the submitted request.",
	err503: "Service Unavailable:Our web server is currently unable to handle the submitted request due to a temporary overloading or maintenance of the server.",
	err505: "HTTP Version Not Supported:Our web server does not support the protocol used in the request.",
	errunk: ""
}

// Retrieve error code from the table
function html_error_lookup (ecode){
	var msgtext;
	ecode = 'err'+ecode;
	msgtext = http_error_codes[ecode];
	if (msgtext) return msgtext;
	return ; // return empty string if nothing found.
	}

// Display error message associated with any current http error codes
function display_error_info(){
	var errors = new Array();
	var ecode ='';
	var emsg ='';
	var head ='';
	var body ='';
	//dummy will inherit the parameters passed
	var dummy_address = cgilink ('dummy','dummy');
	var params = dummy_address.split ('?')[1]||'errunk';
	//alert(params);
	if (params) {
		errors = params.split('&');
		for (var i=0; i<errors.length; i++){
			ecode = errors[i].split('=')[1];
			if (ecode) {
				emsg = html_error_lookup (ecode);
				if (emsg) {
					var head = emsg.split(':')[0];
					var body = emsg.split(':')[1];
					write_on_wdow ('<h3>Error: '+ecode);
					if (head) write_on_wdow (' - '+head);
					write_on_wdow ('</h3><p>'+body+'</p><br>');
					break;
					}
				}
			}
		}
	return;
	}



// === Debug/diagnostic utilities ======================================
function confirm_debug() {
	// Debug only shown for webmaster
	// return 0;
	if ((user_security_ok('Webmaster') == 'Webmaster') && debug_flag) {
		return 1;
		}
	return 0;
	}

function debug (msg){
	if (confirm_debug()) {
		alert ('DEBUG\n\n'+msg);
		}
	// else - ignore
	}

// text of cookie values
function cookieDump(){
	return 	'user_cookie='+getCookie(user_cookie)
			 +'\n'+
			'login_cookie='+getCookie(login_cookie)
			 +'\n';
	}

// Only write on page if debug enabled
function write_debug_on_wdow(text,wdow){
	if (confirm_debug()) {
		write_on_wdow(text,wdow);
		}
	// else - ignore
	}

function diplay_rendered_html(wdow){
	if (confirm_debug()){
		var diagw = window.open("","","");

		var opstyle = '<style "TYPE=text/css">em{color:navy}; H1,H2,H3,H4{color:red}; pre{font-size:10pt}</style>';

		// doc uri, formatted to break on each parameter
		var d_title = unescape(document.location.href);
		d_title = d_title.replace (/\?/ig, "<br>?");
		d_title = d_title.replace (/\&/ig, "<br>&");
		diagw.document.write('<html><body><pre>'+opstyle+'<h3>'+d_title+'</h3></pre>');

		diagw.document.write('<pre>'+cookieDump()+'</pre>');



		// get the entire doc body
		var d_body = document.body.parentNode.innerHTML+"\n\n\n\n";

		// formatted to break on tags,
		d_body = d_body.replace ( />/ig, ">\n");
		// change the colour of tags and make them displayable
		d_body = d_body.replace ( /</ig, "&lt;");
		d_body = d_body.replace ( />/ig, "&gt;");
		d_body = d_body.replace ( /\&lt\;/ig, "<em>&lt;");
		d_body = d_body.replace ( /&gt\;/ig, "&gt;</em>");
		// write pre-formatted to follow \n in text
		diagw.document.write("<pre>"+d_body+"</pre><br><br></body></html>");
		}
	return false;
	// else - ignore
	}

function page_end_diag(wdow) {
	if (confirm_debug()){
		// show rendered html after js has executed ------
		write_debug_on_wdow ('<p class=fn>', wdow);
		write_debug_on_wdow ('<a href="'+prefix+'error.htm" onClick="return diplay_rendered_html()" target=_top>', wdow);
		write_debug_on_wdow ('View Rendered HTML</a></p>', wdow);


		// obj model browser------------------------------
		write_debug_on_wdow ('<p class=fn>', wdow);
		write_debug_on_wdow ('<a href="'+prefix+'sys_look/objbrowser.htm" target=debug>', wdow);
		write_debug_on_wdow ('Object Browser</a></p>', wdow);

		}
	}




//======= end disgnostic stuff ===========================================
