window.octopv_fileVersion="plugin100-1003251"; 
window.octopv_group = ""; // global group used when group is not defined in the octolink.
window.octopvDebugDiv = "octopv_debugDiv"; // see comment to octopv_debug2 function	
window.octopvDebugTopPost = false;	
window.octopv_appletDisplayName = 'Octoshape Grid Delivery Enhancement';
window.octopv_abortAutoLaunch=false;
window.octopv_randomId=(Math.floor(Math.random()*1000000000)).toString(36); 
window.octopv_jsInitMillis=(new Date().getTime());


/* #################################################################################### 
							PATHS TO FILES USED (and variants)
								
   #################################################################################### 
   If necessary override some or all of the following 10 variables in a separate js file.
   for instance (can be done either before or after including this file):
	window.octofbp2_swf=		'http://www.mydomain.com/octoshape/launchers/';
	window.octoinit_jar=		'http://www.mydomain.com/octoshape/launchers/';
	window.octolauncher_jar=	'http://www.mydomain.com/octoshape/launchers/';
	window.AC_OETags_js=		'http://www.mydomain.com/octoshape/launchers/';
	window.octoeula_swf=		'http://www.mydomain.com/octoshape/installers/';
	window.octosetup_cab=		'http://www.mydomain.com/octoshape/installers/';
	window.octosetup_jar=		'http://www.mydomain.com/octoshape/installers/';
	window.octosetup_mac_jar=	'http://www.mydomain.com/octoshape/installers/';
	window.octoshapeVariantEula='MYVAR';
	window.octoshapeVariant=	'MYVAR'; 
 */

function octopv_paths_contructor(){
	this.allFiles=new Array();
	
	this.get=function(fileName){
		var id = fileName.replace('.','_');
		id = id.replace('-','_');
		var p = this[id+'_path'];
		if(typeof(window[id])=='string'){
			p = window[id];
		}
		if((p.charAt(p.length-1)!='/') && p.length>0){
			octopv_debug('inserting / at the end of: '+id+', now it is '+p);
			p = p+'/';
		}
		var f = this[id+'_file'];
		var octoVar='';
		var octoVarEula='';
		if(typeof (window.octoshapeVariant) == 'string'){
			octoVar=window.octoshapeVariant;
		}
		if(typeof (window.octoshapeVariantEula) == 'string'){
			octoVarEula=window.octoshapeVariantEula;
		}
		f = f.replace('_OCTOVAR_',octoVar);
		f = f.replace('_OCTOVAREULA_',octoVarEula);
		return p+f;
	}
	
	this.add=function(file,path){
		var id = file.replace('.','_');
		id = id.replace('-','_');
		id = id.replace('_OCTOVAREULA_','');
		id = id.replace('_OCTOVAR_','');
		this[id+'_file']=file;
		this[id+'_path']=path;
		this.allFiles.push(id);
	}

	
}

window.octopv_paths=new octopv_paths_contructor();
octopv_paths.add('octofbp2.swf',			'http://www.octoshape.com/plugin/util/');
octopv_paths.add('octoinit.jar',			'http://www.octoshape.com/plugin/util/');
octopv_paths.add('octolauncher.jar',		'http://www.octoshape.com/plugin/util/');
octopv_paths.add('AC_OETags.js',			'http://www.octoshape.com/javascripts/');
octopv_paths.add('octoeula_OCTOVAREULA_.swf','http://www.octoshape.com/plugin/autoinstall/');
octopv_paths.add('octosetup_OCTOVAR_.cab',	'http://www.octoshape.com/files/');
octopv_paths.add('octosetup_OCTOVAR_.jar',	'http://www.octoshape.com/files/');
octopv_paths.add('octosetup_OCTOVAR_-mac.jar','http://www.octoshape.com/files/');

window.octopv_setVariant = function setVariant(installer, eula){
	window.octoshapeVariantEula=eula;
	window.octoshapeVariant=installer;
}

window.octopv_disableFlashEula = function disableFlashEula(){
	window.octopve_disableEula=true;
}


/* #################################################################################### 
						         STATUS CODES 
                      the single object for status error codes
   #################################################################################### */

/** 
   Status codes layout (the closer to 0, the more certain the answer is.):
		       0: Octoshape is installed and running.
	-100 to -199: User said no to octoshape.
				  -100 to -109: User rejected the EULA, either we should not use Octoshape or 
  								  we should tell the user not to reject. 
				  -110 to -119: User cancelled a security alert, either we should not use Octoshape or 
  								  we should tell the user not to cancel. 
	-200 to -299: We are pretty sure octoshape is installed and that the user just needs to 
					refresh the page or re-start the browser to make everything work.
	-300 to -399: We are pretty sure that octo is or has been installed, but is now in some error state. 
				  User should do manual re-install.
	-400 to -499: We are pretty sure octo is not installed. User should do manual install.
	-500 to -599: We think octo is installed, but not running. If octoshape is installed, 
		       		user should manually launch octoshape and then refresh page, if no octoshape then manual install.
	-600 to -699: We have no idea if octo is installed or not. Ask user for advice.
	-900 to -999: There was a web integration error. This should not happen. What should the user do? (manuel install?)
*/

function ErrorCodes(){
	this.CODE_USER_DECLINED = 			-1;
	this.CODE_USER_SHOULD_REFRESH = 	-2;
	this.CODE_USER_SHOULD_REINSTALL = 	-3;
	this.CODE_USER_SHOULD_INSTALL = 	-4;
	this.CODE_USER_SHOULD_LAUNCH = 		-5;
	this.CODE_UNKNOWN_STATUS = 			-6;
	this.CODE_ERROR = 					-9;
	
	this.FLASH_EULA_REJECT = 		-100;
	this.INSTALL_APPLET_EULA_REJECT=-101;	

	this.LAUNCH_APPLET_SECURITY=	-110;
	this.INSTALL_APPLET_SECURITY= 	-111;

	this.LAUNCH_APPLET_AFTER_INSTALL=-200;
	this.BP_AFTER_INSTALL=			-201;
	// -299 is used is asosa.

	this.PLUGIN_ANSWER_BP_SUB=		-300; 
	this.PLUGIN_ANSWER_APP_SUB=		-310; 

	this.NO_BROWSER_PLUGIN=			-490;
	this.LAUNCH_APPLET_NO_PLUGIN=	-491;
	
	this.FLASH_BP_NOT_LAUNCHED=     -500;	
	this.CAB_AFTER_INSTALL=			-501;
	this.BROWSER_PLUGIN_NO_METHOD=	-502;
	
	this.LAUNCH_APPLET_TIMEOUT=		-600;	
	this.PRELOAD_APPLET_TIMEOUT=	-601;	
	this.JS_ABORTED=				-602;
	this.JSHTTP_CONNECT=			-603;
	this.JSHTTP_CONNECT_TIMEOUT=	-604;
	this.JSHTTP_CONNECT_EX=			-605;
	this.JSHTTP_NOT_XML=			-606;
	this.JSHTTP_XML=				-607;
	this.JSHTTP_TIMEOUT=			-608;
	this.FLASH_BP_TIMEOUT=			-609;
	this.FLASH_BP_UNKNOWN=			-610;
	this.FLASH_BP_NO_CALLBACK=		-611;
	
	this.LAUNCH_APPLET_IMPOSSIBLE=	-620;
	this.FLASH_BP_IMPOSSIBLE= 		-622;
	this.JSHTTP_IMPOSSIBLE= 		-623;
	this.PRELOAD_APPLET_IMPOSSIBLE=	-624;
	this.JAVA_NOT_ENABLED=			-625;
	this.CAB_IMPOSSIBLE=			-626;
	this.CAB_IMPOSSIBLE_VISTA=		-627;

	this.LAUNCH_APPLET_REPLY=		-630;
	this.LAUNCH_APPLET_WRITE=		-631;
	this.INSTALL_APPLET_JS=			-632;
	this.INSTALL_APPLET_NO_FILE= 	-633;		
	this.INSTALL_APPLET_EXECUTION= 	-634;
	this.INSTALL_APPLET_UNKNOWN= 	-635;
	this.CAB_READY_STATE=			-636; // Ready state not defined
	this.PROTOCAL_LAUNCH_AFTER=		-637; 
	this.PROTOCAL_LAUNCH_ERROR=		-638; 
	this.LAUNCH_APPLET_JAVASCRIPT=	-639;
	
	this.JS=						-900;
	this.JSHTTP_UNKNOWN=			-901;
	this.LAUNCH_APPLET_UNKNOWN = 	-902;
	this.LAUNCH_APPLET_NOT_READY=	-903;
	this.PRELOAD_APPLET_INSERT=		-905;

	this.PRELOAD_APPLET_OK=			-910;	// only used for internal workings
	this.FLASH_EULA_ACCEPT= 		-911;	// only used for internal workings
	this.INSTALL_APPLET_OK= 		-912;	// only used for internal workings

	this.NOT_SET= 		-999;	// Do not change. it is used from silver-osa
	
	this.getCode=function(err){
		if(err==0) return 0;
		if(err<=-700) return this.CODE_ERROR;
		if(err<=-600) return this.CODE_UNKNOWN_STATUS;
		if(err<=-500) return this.CODE_USER_SHOULD_LAUNCH;
		if(err<=-400) return this.CODE_USER_SHOULD_INSTALL;
		if(err<=-300) return this.CODE_USER_SHOULD_REINSTALL;
		if(err<=-200) return this.CODE_USER_SHOULD_REFRESH;
		if(err<=-100) return this.CODE_USER_DECLINED;
		return this.CODE_ERROR;
	}
	
	
	this.print=function(err){
		var e = " ("+err+")";
		switch(err){
		case 0: 							return "Success";
		
		case this.JS:						return "JavaScript error"+e;
		case this.JS_ABORTED:				return "JavaScript Aborted"+e;
		
		case this.JSHTTP_CONNECT: 			return "JavaScript-HTTP error on connect (Plugin not running)"+e;
		case this.JSHTTP_CONNECT_TIMEOUT: 	return "JavaScript-HTTP connect time-out reached"+e;
		case this.JSHTTP_CONNECT_EX:		return "JavaScript-HTTP exception while connecting"+e;
		case this.JSHTTP_NOT_XML: 			return "JavaScript-HTTP plugin did not reply with xml doc"+e;
		case this.JSHTTP_XML: 				return "JavaScript-HTTP plugin replied with incorrect base node tag"+e;
		case this.JSHTTP_TIMEOUT: 			return "JavaScript-HTTP master time-out reached"+e;
		case this.JSHTTP_UNKNOWN: 			return "JavaScript-HTTP unknown error"+e;
		case this.JSHTTP_IMPOSSIBLE:		return "JavaScript-HTTP can not be used"+e;
		
		case this.FLASH_BP_IMPOSSIBLE:		return "Flash-bp can not be used"+e;
		case this.FLASH_BP_TIMEOUT:			return "Flash-bp time-out reached"+e;
		case this.FLASH_BP_NOT_LAUNCHED:	return "Flash-bp could not reach plug-in, but it is installed"+e;
		case this.FLASH_BP_UNKNOWN:			return "Flash-bp could not reach plug-in"+e;
		case this.FLASH_BP_NO_CALLBACK:		return "Flash-bp had no callback function"+e;		

		case this.PRELOAD_APPLET_INSERT:    return "Preload applet could not be inserted to the page"+e;

		case this.PRELOAD_APPLET_IMPOSSIBLE:return "Preload applet could not be used"+e;
		case this.PRELOAD_APPLET_TIMEOUT:	return "Preload applet timeout"+e;
		case this.PRELOAD_APPLET_OK:		return "Preload applet success"+e;
		case this.FLASH_EULA_ACCEPT:		return "Flash EULA accepted"+e;
		
		case this.LAUNCH_APPLET_TIMEOUT: 	return "Launch applet timeout reached"+e;
		case this.LAUNCH_APPLET_REPLY: 		return "Launch applet reply error"+e;
		case this.LAUNCH_APPLET_SECURITY:	return "Launch applet not trusted by user"+e;
		case this.LAUNCH_APPLET_WRITE: 		return "Launch applet disk write error"+e;
		case this.LAUNCH_APPLET_IMPOSSIBLE:	return "Launch applet can not be used"+e;
		case this.LAUNCH_APPLET_NOT_READY:	return "Launch applet is not ready"+e;
		case this.LAUNCH_APPLET_UNKNOWN: 	return "Launch applet unknown error"+e;
		case this.LAUNCH_APPLET_JAVASCRIPT:	return "Launch applet javascript error"+e;
		case this.NO_BROWSER_PLUGIN:		return "Could not find browser plug-in"+e;
		case this.BROWSER_PLUGIN_NO_METHOD:	return "Browser plugin is missing a method definition"+e;
		case this.LAUNCH_APPLET_NO_PLUGIN:	return "Launch applet did not find plugin"+e;
		case this.JAVA_NOT_ENABLED:			return "Java disabled in browser"+e;
		case this.LAUNCH_APPLET_AFTER_INSTALL:return "Launch applet did not work after applet install"+e;
		case this.BP_AFTER_INSTALL:return "Browser plugin did not work after applet install"+e;
		case this.CAB_IMPOSSIBLE:			return "Cab install can not be done"+e;
		case this.CAB_IMPOSSIBLE_VISTA:		return "Cab install can not be done on Vista"+e;
		case this.CAB_AFTER_INSTALL:		return "Cab has run"+e;
		case this.CAB_READY_STATE:			return "Cab ready state not defined"+e;
		case this.PROTOCAL_LAUNCH_AFTER:	return "Protocol launch has run"+e; 
		case this.PROTOCAL_LAUNCH_ERROR:	return "Protocol launch error"+e; 
		
		case this.FLASH_EULA_REJECT:		return "Flash EULA rejected"+e;
		case this.INSTALL_APPLET_JS:		return "Install applet JavaScript error"+e;
		case this.INSTALL_APPLET_UNKNOWN:	return "Install applet unknown error"+e;
		case this.INSTALL_APPLET_EXECUTION:	return "Install applet execution error"+e;
		case this.INSTALL_APPLET_NO_FILE:	return "Install applet no file error"+e;
		case this.INSTALL_APPLET_SECURITY:	return "Install applet not trusted by user"+e;
		case this.INSTALL_APPLET_EULA_REJECT:return "Install applet EULA rejected"+e;
		case this.NOT_SET:					return "JS value is not set."+e;
		}
		if((this.PLUGIN_ANSWER_BP_SUB-10) < err && err < this.PLUGIN_ANSWER_BP_SUB){
											return "Plugin error (BR): "+((-this.PLUGIN_ANSWER_BP_SUB) + err);
		}
		if((this.PLUGIN_ANSWER_APP_SUB-10) < err && err < this.PLUGIN_ANSWER_APP_SUB){
											return "Plugin error (APP): "+((-this.PLUGIN_ANSWER_APP_SUB) + err);
		}
		
		return "unknown"+e;
	};
	
		
	/**
		True iff the error code is from the an instance of the browser plugin,
		that is, we are installed but in some error state.  
	*/
	this.isBrowserPluginError = function(err){
		return ((this.PLUGIN_ANSWER_BP_SUB+10) < err && err < this.PLUGIN_ANSWER_BP_SUB);
	};
}

window.octoErrors = new ErrorCodes();


/* #################################################################################### 
						GENERAL PLUGIN INTERFACE FUNCTIONS
                      functions integrated with auto-install
   #################################################################################### */

/**  */
window.octoAbortAutoLaunch = function abortAutoLaunch(){
	octopv_debug('Aborting auto-launch');
	window.octopv_abortAutoLaunch=true;
	window.octopv_pluginLauncherApplet.resetAll(); // TODO should only be necesarry if we are currently running applet launch ...
};

/**  */
window.octoManualLaunch = function manualLaunch(){
	octopv_debug('Doing protocol launch');
	octopv_launchByProtocol();
};

/** 
	Starts up octoshape and reports the status to functionInt(status)
 */
window.octoGetPluginStatus = function(functionInt, tryAutoInstall, messageFunction){
	octopv_pluginLaunch(1, functionInt,null,tryAutoInstall, messageFunction);
};

/** 
	Starts up octoshape and reports the full ip address + port to functionIntString(status, url)
	on success status is 0
	on error status is <0 and the url may be undefined or null.	
 */
window.octoGetConnectUrl = function(functionIntString, tryAutoInstall, messageFunction,statFunction){
	octopv_pluginLaunch(2, functionIntString,null,tryAutoInstall, messageFunction,statFunction);
};

/** 
 */
/*doc <!--
<function id="octoGetPlayLink" group="ajavascript functions"> 
	<description>
		Call this function every time you wish to play a link. 
		It will start up the Octoshape plugin-in and report the converted play link to the supplied reply function.
		<BR /><BR />
		Do not call this function from the head section of an html document.
	</description>			
	<param id="octolink" description="The unique OctoLink you got from Octoshape" />
	<param id="replyFunctionIntString" 	>
		This must be a JavaScript function taking 2 arguments, a status (number) and the play link (string). 
		On a successfull launch (/and install) of the plug-in, the status is 0 and the string is the converted play link.
		On error status is less than 0 and the string is null or undefined. 
	</param>
	
	<param id="player_width" 	description="The width in pixels you want the embedded media player to have" />
	<param id="player_height">
		The height in pixels you want the viewing area of the embedded media player to have. 
		The actual player (including the controls below) is an additional 46 pixels high.
	</param>
	<param id="tryAutoInstall" optional="true" >
		If true we will attempt to perform an auto-install if the plug-in if it is not there already.
	</param>
	<param id="messageFunction" optional="true" >
		A function taking a string argument. It will be called during the auto-install with various
		messages, for instance 'Initializing installation', 'Running installer' etc.
	</param>
</function> 
 --> **/
window.octoGetPlayLink = function(octolink, functionIntString, tryAutoInstall, messageFunction){
	octopv_pluginLaunch(3, functionIntString, octolink,tryAutoInstall, messageFunction);
};

/** 
	Starts up octoshape and reports the option to functionIntString(status, resultSting)
	on success status is 0	
	on error status is <0 and the string can be null	
 */
window.octoGetStringOption = function(option,functionIntString, tryAutoInstall, messageFunction){
	octopv_pluginLaunch(4, functionIntString, option, tryAutoInstall, messageFunction);
};

/** 
	Starts up octoshape and reports the sua veriosn to functionIntString(status, verisionString)
	on success status is 0
	on error status is <0 and the version may be undefined or null.	
 */
window.octoGetSuaVersion = function(functionIntString, tryAutoInstall, messageFunction){
	octopv_pluginLaunch(5, functionIntString,null,tryAutoInstall, messageFunction);
};

window.octopv_disableLaunches=new Object();



window.octopv_LAUNCH_START_UP=			1;
window.octopv_LAUNCH_GET_CONNECT_URL=	2;
window.octopv_LAUNCH_CONVERT_LINK=		3;
window.octopv_LAUNCH_GET_STRING=		4;
window.octopv_LAUNCH_GET_SUA_VERSION=	5;

/* PRIVATE function  
	There are 4 different possible argument sets of the first 3 arguments: 
	(1,functionInt,null): 			startup up octoshape and return status.
	(2,functionIntString,null):		Starts up octoshape and reports the connect url
	(3,functionIntString,octolink):	Starts up octoshape and reports the converted link
	(4,functionIntString,option):	Starts up octoshape and reports the option
	(5,functionIntString,option):	Starts up octoshape and reports the sua version
	Plus all functions will be called with a statistic reportString as last argument.
	NB: If the status argument to the reply function is negative(indicates an error state), 
		any subsequent argments may be undefined (except for the reportString)!
	
	
	
	tryAutoInstall:	may be undefined or boolean
	messageFunction: may be undefined or null or a function taking a string.
	
*/
window.octopv_pluginLaunch = function pluginLaunch(replyKind, replyFunction1, arg, tryAutoInstall, messageFunction, statFunction){
	octopv_debug('-------------------------------------');
	octopv_debug('Auto-Launch ('+replyKind+ ') called. Auto-install: '+tryAutoInstall);
	window.octopv_abortAutoLaunch=false;
	var doAutoInstall = (typeof(tryAutoInstall)=='boolean' && tryAutoInstall);
	
	
	// the number of parameters to the reply function.
	var replyFunctionParameterNum = replyKind==octopv_LAUNCH_START_UP?1:2;
	
	/* ************************       The js stat       *********************** */
	var stat = new octopv_WebIntegrationStatistics(statFunction);

	/* We report a 'super' attempt for the entire pluginLaunch function.
	   To ensure that we close this attempt again we make a wrapper for the 
	   callers replyFunction1 */
	var myStatName = "PluginLaunch"+replyKind;
	if(doAutoInstall){
		myStatName+="wInstall";
	}else{
		myStatName+="noInstall";
	}
	var superAttId = stat.beginAttempt(myStatName);
	function replyFunction(theIntState, theStringReply){
		if(octopv_abortAutoLaunch) return;
		stat.endAttempt(myStatName,theIntState,superAttId);
		var report = stat.getReportString();
		octopv_debug('Final report: '+report);
		octopv_debug('Final status: '+octoErrors.print(theIntState));
		octopv_debug('String reply: '+theStringReply);
		/* Note to self: no we can not just use replyFunction1.apply(this,arguments)
			since we do not want to change the value og 'this' inside the callers 
			reply-function.  */
		if(replyFunctionParameterNum==1){
			replyFunction1(theIntState, report);
		}else{
			replyFunction1(theIntState, theStringReply, report);
		}
	}
	
	/* **********************    Message function helpers    ********************* */
	/*  Some helper wrappers for the callers message funstion 
		(which is an optional argument). */

	function doMessage(mess){
		if(typeof(messageFunction)=='function'){
			messageFunction(mess);
		}
	}
	
	function launchMessage(mess){
		if(typeof(mess)=='string'){
			doMessage("Launching Octoshape by" + mess);
		}else{
			doMessage("Launching Octoshape");
		}
	}

	function installMessage(mess){
		if(typeof(mess)=='string'){
			doMessage("Installing Octoshape by" + mess);
		}else{
			doMessage("Installing Octoshape");
		}
	}

	/* ************************       Launch attempts.      *********************** */
	/** 
		When defining a run object this must be done:
		- call octopv_RunObject.call(this, "myname",stat) in the constructor 
			where myname is a string of only letters and numbers.
		- define function void run();
			On success this.closeOk(); and replyFunction(..) should be called.
			On fail this.closeError(theErrorCode); should be called.
		- optionally define function int canAnswer(); 
			where the reply is 0 on yes and an error code on no. (if no canAnswer 
			function is added it is assumed that he object can answer everything).
	*/
	
	function JsHttp(portToTry){
		octopv_RunObject.call(this, "JsHttp"+portToTry,stat);
		this.canAnswer = function(){
			if(octoJavaScriptHttpCanDo()){
				switch(replyKind){
					case octopv_LAUNCH_START_UP:  		return 0;
					case octopv_LAUNCH_GET_CONNECT_URL: return 0;
					case octopv_LAUNCH_GET_SUA_VERSION:	return 0;
				}
			}
			return octoErrors.JSHTTP_IMPOSSIBLE;
		};
		var me=this;
		this.run = function JsHttpRun(){
			octopv_debug('Doing js-http for port '+portToTry);
			launchMessage();
			var tryUrl = '127.0.0.1:'+portToTry;
			
			octoJavaScriptHttp(tryUrl,2000,function(status,version){
				if(status==0){
					octopv_debug('Found ipport by XDomainRequest: '+tryUrl);
					me.closeOk(); 
					switch(replyKind){
						case octopv_LAUNCH_START_UP:  		
							replyFunction(0);
							break;
						case octopv_LAUNCH_GET_CONNECT_URL: 
							replyFunction(0,tryUrl);
							break;
						case octopv_LAUNCH_GET_SUA_VERSION:	
							replyFunction(0,version);
							break;
						default:
							octopv_debug('ERROR: (jshttp) unknown reply kind was: '+replyKind);
					}
				}else{
					octopv_debug('Reply from XDomainRequest('+tryUrl+') was: '+status);
					me.closeError(status); 
				}
			});
		};
	}

	function PortFlash(port1,port2){
		octopv_RunObject.call(this, "FlashPort",stat);
		//-- PortFlash.canAnswer if the user has flash version with ActionScript 3 support 
		this.canAnswer=function(){
			if(typeof(window.octopv_disableLaunches["FlashGetPort"])=='boolean' && 
			window.octopv_disableLaunches["FlashGetPort"]) return octoErrors.FLASH_BP_IMPOSSIBLE;
			if(window.octopv_flashOk()){
				switch(replyKind){
					case octopv_LAUNCH_START_UP:  		return 0;
					case octopv_LAUNCH_GET_CONNECT_URL: return 0;
				}
			}
			return octoErrors.FLASH_BP_IMPOSSIBLE;
		};
		var me=this;
		this.run=function portFlashRun(){
			launchMessage();
			window.octopv_FlashBP(function(portReply){
				octopv_debug('reply from octopv_FlashBP:'+portReply);
				if(portReply>0){
					me.closeOk();
					if(replyKind==octopv_LAUNCH_START_UP){
						replyFunction(0);
					}else if(replyKind==octopv_LAUNCH_GET_CONNECT_URL){
						replyFunction(0, '127.0.0.1:'+portReply);
					}
				}else{
					if(portReply==octoErrors.FLASH_BP_NOT_LAUNCHED){
						// TODO can we do something special here? 
						//  add the LaunchByProtocol to the loop?
					}
					//octopv_debug('we try to go on:'+getPropertiesString(me));
					me.closeError(portReply);
				}
			},port1,port2); 
		};
	}
	
	function AppletTest(timeoutMillis){
		octopv_RunObject.call(this, "AppletTest",stat);
		//-- AppletTest.canAnswer if we are on windows or mac os x and have java enabled (in the browser)
		this.canAnswer=function(){
			if(window.octopv_isWindows() || window.octopv_isOSX()){
				if(!window.navigator.javaEnabled()){
					if(octopv_isWindows() && octopv_isFirefox()){
						octopv_debug("Java does not appear to be enabled, but we have windows+firefox, so we try anyway.");
					 	return 0;
					}else{
						octopv_debug("Can not do applet launch since java is not enabled."+window.navigator.javaEnabled());
					 	return octoErrors.JAVA_NOT_ENABLED; 
					}
				}
				return 0;
			}else{
				// not windows and not mac os x.
				octopv_debug("Can not do applet launch since OS is not windows or mac os x ");
				return octoErrors.LAUNCH_APPLET_IMPOSSIBLE;
			}
		};
		var me=this;
		this.run=function AppletTestRun(){
			octopv_preloadApplet(function(ok,major,minor,micro,osVersion){
				if(ok==0){
					me.major=major;
					me.minor=minor;
					me.micro=micro;
					me.osVersion=osVersion;
					me.closeError(octoErrors.PRELOAD_APPLET_OK);
				}else{
					me.closeError(ok);
				}
			},timeoutMillis); 
		};
	}
	
	function AppletLaunch(){
		octopv_RunObject.call(this, "AppletLaunch",stat);
		//-- AppletLaunch.canAnswer if we are not on mac os and we have Applet cookie set 
		this.canAnswer=function(){
			if(octopv_isOSX()){
				octopv_debug('can not use applet launch since we are on mac os.');
				return octoErrors.LAUNCH_APPLET_IMPOSSIBLE;
			}
			if(octopv_preferencePluginLaunch_cookieCanUse("Applet")){
				return 0;
			}else{
				octopv_debug('can not use applet launch since there is no cookie');
				return octoErrors.LAUNCH_APPLET_IMPOSSIBLE;
			}
		};
		var me=this;
		this.run=function AppletLaunchRun(onError){
			launchMessage();
			window.octoPluginLauncherApplet(function(status, fromPlugin){
				/* For some odd reason the getStatus replies from jni has 2 as success. 
					(both applet and browser plugin uses the same code) */
				var pluginStatus = status==2?0:status;	
				var appletStatus = status-1000;			// we set -1000 to distinguish it from plugin errors.
				var statStatus = fromPlugin?pluginStatus:appletStatus;
				var debugString = 'pluginStatus '+pluginStatus+' appletStatus: '+appletStatus+' statStatus:'+statStatus+'';
				octopv_debug('fromPlugin('+fromPlugin+'): '+debugString);
			
				if(fromPlugin){
					// The applet was initialized ok and the reply is from jni. 
					// If the status is an error reply, it is not going to be different from the browser plugin reply.
					if(pluginStatus==0){
						// Applet replied that octoshape is up and running
						me.closeOk();
						window.octopv_preferencePluginLaunch_cookieSetCanUse("Applet");
						switch(replyKind){
						case octopv_LAUNCH_START_UP: replyFunction(0); break;
						case octopv_LAUNCH_GET_CONNECT_URL: 
							var xml = window.octopv_pluginLauncherApplet.getStringOption('xmlbound');
							replyFunction(0,xml); 
							break;
						case octopv_LAUNCH_CONVERT_LINK: replyFunction(0, window.octopv_pluginLauncherApplet.getPlayLink(arg)); break;
						case octopv_LAUNCH_GET_STRING: replyFunction(0, window.octopv_pluginLauncherApplet.getStringOption(arg)); break;
						case octopv_LAUNCH_GET_SUA_VERSION: 
							var xml = window.octopv_pluginLauncherApplet.getStringOption('suaversion');
							replyFunction(0,xml); 
							break;
						}
					}else{
						// Applet replied that octoshape is in some error state (or not installed).
						var err = octoErrors.PLUGIN_ANSWER_APP_SUB-pluginStatus;
						if(pluginStatus==-1){
							// this is most likely because we are not installed.
							err = octoErrors.LAUNCH_APPLET_NO_PLUGIN; 
						}
						octopv_debug('Replying with error('+typeof(pluginStatus)+') '+pluginStatus+' ('+err+') ');
						me.closeError(err); 
					}
				}else{
					// we got error reply from applet launcher
					me.closeError(status);  
				}
			});
		};
	}
	
	function BrowserPlugin(){
		octopv_RunObject.call(this, "BrowserPlugin",stat);
		this.canAnswer=function(){
			return 0;
		};
		var me=this;
		this.run=function BrowserPluginRun(){
			launchMessage();
			octopv_bpGet(function(result, plug){
				if(result==0){
					var error = octopv_bpReady(plug, function(){
						me.closeOk();
						window.octopv_preferencePluginLaunch_cookieSetCanUse("BrowserPlugin");
						switch(replyKind){
						case octopv_LAUNCH_START_UP: replyFunction(0); break;
						case octopv_LAUNCH_GET_CONNECT_URL: 
							var xml = plug.getString('xmlbound');
							replyFunction(0,xml); 
							break;
						case octopv_LAUNCH_CONVERT_LINK: 	
							var playlink = plug.getLink(arg,false);
							octopv_debug('Got play link from browser plugin: '+playlink+'.');
							replyFunction(0, playlink); 
							break;
						case octopv_LAUNCH_GET_STRING: replyFunction(0, plug.getString(arg)); break;
						case octopv_LAUNCH_GET_SUA_VERSION:
							var xml = plug.getString('suaversion');
							replyFunction(0,xml); 
							break;
						}
					});
					if(error<0){
						octopv_debug('Has error: '+error+' ');
						me.closeError(-((-octoErrors.PLUGIN_ANSWER_BP_SUB)+(-error)));
					}
				}else{
					var browserNotIE=navigator.userAgent.toLowerCase().indexOf("msie") == -1;
					var hasCookie=octopv_preferencePluginLaunch_cookieCanUse("BrowserPlugin");
					octopv_debug('Not found ('+result+'). We trust this answer? cookie:'+hasCookie +' / non-ie:'+ browserNotIE);
					me.closeError(result);
				}
			});
		};	
	}
	
	function LaunchByProtocol(){
		octopv_RunObject.call(this, "ProtocolLaunch",stat);
		this.canAnswer=function(){
			return true;
		};
		var me=this;
		this.run=function LaunchByProtocolRun(){
			launchMessage();
			octopv_launchByProtocol(function(err){
				me.closeError(err); 
			});
		};
	}
	
	/* ************************       Install attempts.      *********************** */
	
	function CabInstall(timeout, eula){
		octopv_RunObject.call(this, "CabInstall",stat);
		//-- CabInstall.canAnswer if we are on non-vista-windows and browser IE 
		this.canAnswer=function cabInstallCan(){
			if(!window.octopv_isWindows()){
				// not windows.
				octopv_debug("Can not do cab install since OS is not windows.");
				return octoErrors.CAB_IMPOSSIBLE;
			}
			if(!window.octopv_isIE()){
				// not explorer.
				octopv_debug("Can not do cab install since browser is not ie.");
				return octoErrors.CAB_IMPOSSIBLE;
			}
			// Temporarily disabled for all vista users.
			if(octopv_isVista()){
				// we have vista 
				octopv_debug("Can not do cab install since we are on vista. ");
				//return 0;
				return octoErrors.CAB_IMPOSSIBLE_VISTA; 
			}
			return 0;
		};
		var me=this;
		this.run=function cabInstallRun(){
			installMessage("cab");
			var divCab="octopv_topCabDiv";
			octopv_createNewDiv2(divCab);

			eula.start(function(err1){
				if(err1==octoErrors.FLASH_EULA_ACCEPT){
					octopv_doCabInstall(divCab, timeout, function(err){
						// cab complete.
						// but we do not know if: there was a success, a fail, or vista is showing a yellow bar to the user.
						if(err==0){
							octopv_debug('Cab finished, but was it successful?.');
							me.closeError(octoErrors.CAB_AFTER_INSTALL);
						}else{
							me.closeError(err);
						}
					});
				}else{
					me.closeError(err1);
				}
			});
		};
	}
	
	function PreloadInstallApplet(appTest,timeoutMillis){
		octopv_RunObject.call(this, "PreloadInstallApplet",stat);
		this.canAnswer=function preloadInstallAppletCan(){
			//--- PreloadInstallApplet.canAnswer 
			//- if #AppletTest.canAnswer 
			//- and AppletTest have completed 
			if(appTest.canAnswer() && appTest.closed){
				var userAgent = navigator.userAgent.toLowerCase();
				//- if on mac os x  
				if(octopv_isOSX()){
					// the user.agent detection of os version is not perfect for mac, 
					// so we might have some pre-10.4 users to deny auto-install here.
					function hasVersion(str){ return (appTest.osVersion.indexOf(str) != -1); }
					//- if AppletTest reported 10.3 or lower os version 
					if(hasVersion("10.0")||hasVersion("10.1")||hasVersion("10.2")||hasVersion("10.3")){
						//- we can not use applet install 
						return octoErrors.INSTALL_APPLET_NOT_POSSIBLE; 
					}
				//- else if IE and Vista
				}else if(octopv_isIE() && octopv_isVista()){
					//- if java version strictly higher than 1.6.0_07 
					//- (that and earlier java versions does not use vistas broker process) 
					if(appTest.major < 6 || (appTest.major==6 && appTest.minor==0 && appTest.micro < 8)){
						// we are on vista and have ie and have a too old java version!
						//- we can not do applet install
						octopv_debug("no applet install since: vista + ie + java<=1.6.0_07: "+major+"/"+minor+"/"+micro);
						return octoErrors.INSTALL_APPLET_NOT_POSSIBLE; 
					}
				}
				//- else all is well for applet install proceed
				return 0;
			}
			//- else (AppletTest did not show applet support) then applet install is not possible
			return octoErrors.INSTALL_APPLET_NOT_POSSIBLE; 
		};
		
		var me=this;
		this.run=function preloadInstallAppletRun(){
			octopv_preloadApplet(function(ok){
				if(ok==0){
					me.closeError(octoErrors.PRELOAD_APPLET_OK);
				}else{
					me.closeError(ok);
				}
			},timeoutMillis,octopv_installjar()); 
		};
	}
	
	function InstallApplet(){
		octopv_RunObject.call(this, "InstallApplet",stat);
		this.canAnswer=function(){
			return 0;
		};
		var me=this;
		this.run=function appletInstallRun(){
			installMessage("applet");
			var div3="octopv_appletDiv3";
			octopv_createNewDiv(div3);
			octopv_doAppletInstall(div3, function(result){
				octopv_debug('applet install answer: '+result);
				if(window.octopv_abortAutoLaunch){
					octopv_debug('NB: octopv_abortAutoLaunch false after running applet install.');
				}
				if(result<0){
					me.closeError(result);
				}else{
					octopv_preferencePluginLaunch_cookieSetCanUse("Applet");
					if(octopv_LAUNCH_START_UP==replyKind){
						me.closeOk(0);
						replyFunction(0);
					}else if(octopv_LAUNCH_GET_CONNECT_URL==replyKind && result>0){
						me.closeOk(0);
						replyFunction(0, '127.0.0.1:'+result);
					}else{
						me.closeError(octoErrors.INSTALL_APPLET_OK); 
					}
				}
			}, messageFunction);
		};
	}
	
	function InstallByApplet(eula, tApp, pApp, iApp){
		octopv_RunObject.call(this, "InstallByApplet",stat);
		this.canAnswer=function(){
			octopv_debug('trying can answer');
			if(tApp.canAnswer()==0){
				if(pApp.canAnswer()==0){
					return iApp.canAnswer();
				}else{
					return pApp.canAnswer();
				}
			}else{
				return tApp.canAnswer();
			}
		};
		var me=this;
		this.run=function installByAppletRun(){
			//--- The auto-install procedure
			//- Two procedures are started to run in parallel, and we wait for both to complete before moving on.
			//- The first one:
			//- if AppletTest returns that we have applet support
				//- then if #PreloadInstallApplet.canAnswer 
					//- then preload applet is run to download the install applet.
			//- The second runs the falsh eula. 
			//- (the result is that we download the install applet while the user contemplates the eula).
			//- When both have finished with positive results, we run the actual install applet
			function afterEulaAndPreload(){
				octopv_debug('after eula called ... ');
				if(eula.closed && tApp.closed && !pApp.running){
					if(pApp.exitState == octoErrors.PRELOAD_APPLET_OK){
						// we must try the install applet.
						iApp.start(function(err4){
							me.closeError(err4);
						},function(){
							// install applet returned success 
							// we just need to close our self down so stat4 will be correct.
							me.closeOk(0);
						}); 
					}else{
						if(pApp.closed){
							me.closeError(preInstall.exitState);
						}else{
							me.closeError(appTest.exitState);
						}
					}
				}
			}
			
			tApp.start(function(err3){
				if(err3==octoErrors.PRELOAD_APPLET_OK){
					pApp.start(function(err2){
						afterEulaAndPreload();
					});
				}else{
					afterEulaAndPreload();
				}
			});
				
			eula.start(function(err1){
				if(err1==octoErrors.FLASH_EULA_ACCEPT){
					afterEulaAndPreload();
				}else{ 
					me.closeError(err1);
				}
			});
		};
	}

	function ShowEula(){
		octopv_RunObject.call(this, "FlashEula",stat);
		this.prototype=new octopv_RunObject();
		this.canAnswer=function(){
			return true;
		};
		var me=this;
		this.run=function showEulaRun(){
			var divEula="octopv_topEulaDiv";
			octopve_spawnEula(function(proceed){
				octopv_debug('Eula reply: '+proceed);
				if(proceed){
					me.closeError(octoErrors.FLASH_EULA_ACCEPT);
				}else{
					me.closeError(octoErrors.FLASH_EULA_REJECT);
				}
			}, divEula);
		};
	}
	
	
	
	/* *******************       Filling Launch and install attempts      ****************** */
	
	octopv_debug('Beginning the launch ... ');
	
	//--- The auto-launch procedure
	
	// we only make one AppletTest and use it everywhere, since running it a second time 
	// will not actually insert the applet again, but just return the previous answer. 
	var appletTest = new AppletTest(8000); // TODO timeout ok?
	// Likewise we only have one eula.
	var eula = new ShowEula();
	
	var arr=new Array();
	if(octoJavaScriptHttpCanDo()){	//-	if JsHttp is possible
		//-	we try JsHttp port 6498 and 8247
		arr.push(new JsHttp(6498),new JsHttp(8247));
		arr.push(new BrowserPlugin());
	}else{	//-	else
		arr.push(new BrowserPlugin());
		arr.push(new PortFlash(6498,8247));
	}
	octopv_runAllRunObjects2(0,arr,function(bpErr){
		appletTest.start(function(errTapp){
			//-	if #AppletTest.canAnswer we run AppletTest 
			//- (to see if user has applet support) and if that was a success 
			if(errTapp==octoErrors.PRELOAD_APPLET_OK){
				//-	if #AppletLaunch.canAnswer we run the AppletLaunch 
				var lApp = new AppletLaunch();
				lApp.start(function(errLapp){
					//-	if we should not do auto-install
					if(!doAutoInstall){
						//-	if AppletLaunch was run 
						if(lApp.canAnswer()!=octoErrors.LAUNCH_APPLET_IMPOSSIBLE){							
							//-	we return the AppletLaunch error
							replyFunction(errLapp);
						}else{ // - else (AppletLaunch could not run)
							//-	we return the BrowserPlugin error
							replyFunction(bpErr);
						}
					}else{	//- else (should do auto-install)
						//- This probably means that octoshape is not installed,
						//- But 1: If we are on windows and has IE, this might mean that a yellow
						//-		bar is showing, so we do not trust the negative answer completely.
						//- But 2: We should be able to trust the 'no octo' answer in FX, but 
						//-		super-tester-1 had an issue in FX where this did not work 
						//-		(after an install, without browser re-start).
						//-	So we run the applet install procedure in all cases 
						//-	we start the applet install procedure
						var appInstall = new InstallByApplet(eula, appletTest, new PreloadInstallApplet(appletTest, 20000), new InstallApplet());
						appInstall.start(function(errApp){
							//-	if the install was successful but did not return the port
							if(errApp==octoErrors.INSTALL_APPLET_OK){
								var nlApp = new AppletLaunch();
								if(nlApp.canAnswer()!=octoErrors.LAUNCH_APPLET_IMPOSSIBLE){
									//-	if #AppletLaunch.canAnswer
									//-	we try the applet launcher
									nlApp.start(function(errLApp){
										//-	if that fails we return that we think we are installed, but could not get port.
										replyFunction(octoErrors.LAUNCH_APPLET_AFTER_INSTALL);
									});
								}else{ //- else (AppletLaunch failed)
									var nlBp = new BrowserPlugin();
									//-	we try the BrowserPlugin
									nlBp.start(function(errBp2){
										//-	if that fails we return that we think we are installed, but could not get port.
										replyFunction(octoErrors.BP_AFTER_INSTALL);
									});
								}
							}else{ //- else (install applet was not successful)
								//- we return the install applet error (might be no to the eula etc.)
								replyFunction(errApp);
							}
						});
					}
					
				});
			}else{ //- else (AppletTest failed) 
				//- if we should not do auto-install
				if(!doAutoInstall){
					//- we return the browser plugin error code 
					replyFunction(bpErr);
				}else{ //- else (we should do auto-install)
					var cab = new CabInstall(3000,eula);
					cab.start(function(errCab){
						//- if #CabInstall.canAnswer 
						//- we try the CabInstall (with flash eula) and 
						//- if there were no errors (does not mean that it was successful) 
						if(errCab==octoErrors.CAB_AFTER_INSTALL){
							//- if we can do JsHttp 
							if(octoJavaScriptHttpCanDo()){
								//- we try JsHttp with port 6498 and 8247 and then the BrowserPlugin
								octopv_runAllRunObjects(new JsHttp(6498),new JsHttp(8247),new BrowserPlugin(),replyFunction);
							}else{ //- else (no JsHttp)
								//- we try PortFlash with port 6498 and 8247 and then the BrowserPlugin
								octopv_runAllRunObjects(new PortFlash(6498,8247),new BrowserPlugin(),replyFunction);
							}
						}else{ //- else (CabInstall failed) 
							//- we report that 
							replyFunction(bpErr);
						}
					});
				}
			}
		});
	});
};

window.octopv_runAllRunObjects=function runAllRunObjects(){
	var endFunction = arguments[arguments.length-1];
	var arr=new Array(arguments.length-1);
	for(var i=0;i<arr.length;i++){
		arr[i] = arguments[i];
	}
	window.octopv_runAllRunObjects2(0,arr, endFunction);
};

window.octopv_runAllRunObjects2=function runAllRunObjects2(i,arr, endFunction){
	var toRun = arr[i];
	toRun.start(function(err){
		var i2=i+1;
		if(i2<arr.length){
			window.octopv_runAllRunObjects2(i+1,arr,endFunction);
		}else{
			endFunction(err);
		}
	});
};


/*  
	Using this constructor: 
	Set an instance as prototype for an object and then add a 'run' function.
*/
window.octopv_RunObject=function RunObject(myId, stat){
	/* PRIVATE functions and properties  */
	this.runId=myId;
	this.closed=false;
	this.running=false;
	this.exitState=octoErrors.JS;
	this.onErrorFunction=null;
	this.onSuccessFunction=null;
	this.statAttId="";
	
	/** private function */
	this.close=function RunObjCloseErr(state, ok){
		octopv_debug(' --- Closing '+this.runId+': '+octoErrors.print(state)+' --- ');
		if(this.closed){
			octopv_debug('ERROR: calling close on already closed obj: '+this.runId+' ');
			return;
		}
		this.closed=true; 
		this.running=false;
		this.exitState=state;
		stat.endAttempt(this.runId,state,this.statAttId);
		if((!ok) && this.onErrorFunction!=null){
			this.onErrorFunction(state);
		}
		if(ok && this.onSuccessFunction!=null){
			this.onSuccessFunction();
		}
	};
	
	/** Public function */
	this.closeOk=function RunObjCloseOk(state){
		if(typeof(state)=='undefined'){
			this.close(0,true);
		}else{
			this.close(state,true);
		}
	};

	/** Public function */
	this.closeError=function RunObjectClose(state){
		this.close(state,false);
	};

	/** Public function */
	this.start=function RunObjectStart(onError, unSuccess){
		// we can use this run object
		if(this.closed){
			octopv_debug('Returning old run state for '+this.runId+'');
			if(this.exitState>=0 && unSuccess){
				if(typeof(unSuccess)=='function'){
					unSuccess();
				}
			}else{
				onError(this.exitState);
			}
			return;
		}
		this.running=true;
		this.onErrorFunction=onError;
		if(typeof(unSuccess)=='function'){
			this.onSuccessFunction=unSuccess;
		}
		this.statAttId=stat.beginAttempt(this.runId); 
		if(typeof(this.canAnswer)=='function'){
			var canDo = this.canAnswer();
			if(canDo<0){
				// we can not use this run object
				octopv_debug(' --- Skipping '+this.runId+' ('+canDo+') --- ');
				this.closeError(canDo,false);
				return;
			}
		}
		octopv_debug(' --- Running '+this.runId+' --- ');
		this.run();
	};
}


/* #################################################################################### 
					WRAPPER OF GENERAL PLUGIN INTERFACE FUNCTIONS
                      			for use by osas 
   #################################################################################### */


window.octoGetConnectUrlOsa = function getConnectUrlOsa(swfname, tryAutoInstall){
	var asosa=null;
   	if (navigator.appName.indexOf("Microsoft") != -1) {
   		asosa=window[swfname];
   	}else{
   		asosa=document[swfname];
	}
   	if(typeof(asosa)=='undefined'){
		octopv_debug('ERROR!: could not get a hold of asosa swf: '+swfname);
		
		//TODO octopv_debug('ERROR!: could not get a hold of asosa swf: '+swfname);
   	}
	window.octoGetConnectUrl(function(intStatus, stringReply){
		//octopv_debug('Calling callback reply function');
		asosa.octopvAS_jsreply(intStatus,stringReply);
	},tryAutoInstall,
	function(message){
		//octopv_debug('Calling callback message function');
		if(typeof(message)=="string"){
			try{
				asosa.octopvAS_jsmessage(message);
			}catch(ex){
				octopv_debug('Could not call message function on asosa: '+ex);
			}
		}
	},
	function(versionInt,attId,ranId,jsId,cookieId, millis,name,result){
		//octopv_debug('Calling callback stat function');
		try{
			if(versionInt==5 && typeof(asosa.octopvAS_jsstat5)=="function"){
				asosa.octopvAS_jsstat5(attId,ranId,jsId,cookieId,millis,name,result);
			}else {
				octopv_debug('asosa-stat version is: '+versionInt);
			}
		}catch(ex){
			octopv_debug('Could not stat function on asosa: '+ex);
		}
	});
};

// silver-osa:
window.octopv_osaPullCount = 0;
window.octopv_osaPullObjectConstructor = function osaPullObjectConstructor(){
	octopv_osaPullCount++;
	this.name = "octopv_osaPullObject"+octopv_osaPullCount;
	this.status = octoErrors.NOT_SET; // -999
	this.url = "";
	this.message = "";
	this.statustype = "url";

	// set from outside.
	this.tryAutoInstall = false; 	// public
	this.updatelink = null;			// public
	this.okSuaVersion=null;			// public
	
	this.setMessage=function(m){
		if(typeof(m)=="string"){
			this.message=m;
		}
	};
	this.setResult = function(s,u){
		this.status=s;
		if(s==0){
			this.url=u;
		}
	}
	
	// public
	this.start=function(){
		var me=this;
		window.octoGetConnectUrl(function(intStatus, stringReply){
			if(intStatus==0 && me.updatelink!=null && me.okSuaVersion!=null){
				me.doSuaUpdate(intStatus, stringReply);
			}else{
				me.setResult(intStatus, stringReply); 
			}},
			me.tryAutoInstall,
			function(message){ me.setMessage(message);},
			function(versionInt,attId,ranId,jsId,cookieId, millis,name,result){}
		);
	};
	
	this.doSuaUpdate=function(intStatus, stringReply){
		var me=this;
		window.octopv_forceSuaUpdateIfNeeded(me.updatelink, me.okSuaVersion, function(suaResult){
			if(suaResult == 0){
				// the current sua version was ok
				me.setResult(intStatus, stringReply); 
			}else if(suaResult == 1){
				// we have updated the sua, and are now ready again.
				me.okSuaVersion=null;
				me.updatelink=null;
				me.start();				
			}else{
				// If octoshape not installed or there was some error with the browser plugin
				octopv_debug('We failed at sua update after success at get url. Sua result: '+octoErrors.print(suaResult));
				me.statustype='sua';
				me.setResult(suaResult, ""); 
			}
		});
	};
};

window.octoGetConnectUrlOsaPullBegin = function octoGetConnectUrlOsaPullBegin(tryAutoInstall, updatelink, okSuaVersion){
	var pullObject = new octopv_osaPullObjectConstructor();
	window[pullObject.name] = pullObject;
	pullObject.tryAutoInstall=tryAutoInstall;
	if(typeof(updatelink)=='string' && updatelink!="" && typeof(okSuaVersion)=='string' && okSuaVersion!=""){
		octopv_debug('Yes sua update. '+updatelink+'/'+okSuaVersion);
		pullObject.updatelink=updatelink;
		pullObject.okSuaVersion=okSuaVersion;
	}else{
		octopv_debug('No sua update. '+updatelink+'/'+okSuaVersion);
	}
	pullObject.start();
	return pullObject.name;
};

// kind must be one of 'status', 'url', 'message', or 'statustype' (kan be 'sua' or 'url').
window.octoGetConnectUrlOsaPull = function octoGetConnectUrlOsaPull(name, kind){
	var obj = window[name];
	return obj[kind];
}

window.octoCleanOsaPull = function octoCleanOsaPull(name){
	if(typeof(window[name])!='undefined'){
		delete window[name];
		octopv_debug('have deleted '+name+'. type now: '+(typeof(window[name])));
	}
}


/* #################################################################################### 
                                 USER PREFERENCES
                             variables and functions
   #################################################################################### */

window.octopv_preferencePluginLaunch_cookieCanUse=function(id){
	return octopv_hasCookie("octoweb"+id+"=true");
};

// TODO should also be called by windows applet install when installer tells us that we are preaproved.
window.octopv_preferencePluginLaunch_cookieSetCanUse=function cookieSetCanUse(id){
	octopv_debug('Setting cookie for: '+id+' ');
	var date = new Date();
	date.setTime(date.getTime()+(31*24*60*60*1000)); // one month expiry
	document.cookie = "octoweb"+id+"=true; expires="+date.toGMTString()+"; path=/";
};

/* #################################################################################### 
                                    STATISTICS 
                             variables and functions
   #################################################################################### */


/**
  Returns an object with 5 functions:
	- void init(calledFunction, attList, usingAutoInstall); 
		where: 	calledFunction is string
				attList is '-'-seperated list
				usingAutoInstall is boolean
	- void beginAttempt(String str);
		if beginAttempt is used, endAttempt must follow
	- void updateAttempt(String str, String info);
		updateAttempt can only happen in between beginAttempt and endAttempt
	- void endAttempt(String attemptName, String whatHappend, int resultCode);
		endAttempt can be used without prior beginAttempt
 */
window.octopv_WebIntegrationStatistics=function WebIntegrationStatistics(statFunction){
	this.messageCount=0;
	this.ranId = (Math.floor(Math.random()*1000000000)).toString(36); 
	this.cookieId = octopv_webIntegrationStatisticsUserId();
	this.reportString='';
	this.beginMillis=(new Date().getTime());
	
	/* Public function*/
	this.beginAttempt=function(name){
		var millis = (new Date().getTime());
		var attId = (Math.floor(Math.random()*1000000000)).toString(36);
		if(typeof(statFunction)=='function'){
			statFunction(5,attId,this.ranId,window.octopv_randomId,this.cookieId,millis,name,999);
		}
		octopv_debug('TimeStamp (begin '+name+'): '+(millis-this.beginMillis));
		return attId;
	};
	
	/* Public function*/
	this.endAttempt=function stat5EndAttempt(name, intResult, attId){
		var millis = (new Date().getTime());
		var value = name+":"+intResult;
		this.reportString+=("result",value+'&');
		if(typeof(statFunction)=='function'){
			statFunction(5,attId,this.ranId,window.octopv_randomId,this.cookieId,millis,name,intResult);
		}
		octopv_debug('TimeStamp (end '+name+'): '+(millis-this.beginMillis));
	};
	
	/* Public function*/
	this.getReportString=function stat5GetReportString(){
		// report string always ends with & (or is the empty string)
		return this.reportString + this.getIdString();
	};

	/* private function */
	this.getIdString=function(){
		return 'id='+this.ranId+'&jsid='+window.octopv_randomId+'&cookid='+this.cookieId+'&version=5';
	}
}


window.octopv_webIntegrationStatisticsUserId=function statisticsUserId(){
	var statId = octopv_getCookie("octowebstatid");
	if(statId!=null&&statId!=""){
		return statId;
	}else{
		var id = (Math.floor(Math.random()*1000000000)).toString(36);
		var date = new Date();
		date.setTime(date.getTime()+(365*24*60*60*1000)); // one year expiry
		document.cookie = "octowebstatid="+id+"; expires="+date.toGMTString()+"; path=/";
		return id; 
	}
}


/* #################################################################################### 
                                 BROWSER PLUGIN 
                             variables and functions
   #################################################################################### */

window.octopv_bpHelperObject = new Array(2);

window.octopv_bpReadyReset = function bpReadyReset(){
	octopv_bpHelperObject.upstart=function(){};
	octopv_bpHelperObject.play=function(){};
	octopv_bpHelperObject.status=function(){};
};

window.octopv_bpReadyReset();

// theOctoshapeClient is assumed to be a valid octoshape browser plug-in. 
// playfunction must be a function with no arguments.
window.octopv_bpReady=function bpReady(theOctoshapeClient, readyfunction, startingupFunction){
	octopv_bpReadyReset();
	octopv_bpHelperObject.play = readyfunction;
	
	octopv_bpHelperObject.status = function(){
		return theOctoshapeClient.getStatus(true);
	}
	if(typeof(startingupFunction) != 'undefined'){
		octopv_debug('setting startingupFunction to '+startingupFunction);
		octopv_bpHelperObject.upstart = startingupFunction;
	}
	
	try {
		return octopv_bpReadyRepeat();
	}
	catch (exception) {
		octopv_debug('octopv_bpReady exception '+exception);
		return -6;
	}
}

window.octopv_bpReadyRepeat=function bpReadyRepeat(){
	var result = octopv_bpHelperObject.status();
	switch (result){
 		case 1:
			// we call our self again in 2000 milli-seconds
			var id = setTimeout("octopv_bpReadyRepeat();",2000);
			if(typeof(octopv_bpHelperObject.upstart) == 'function'){
				octopv_bpHelperObject.upstart();
			}
			return result;
		case 2:
			// octoshape is already started up, so we just play the link
			
			octopv_bpHelperObject.play();
			octopv_bpReadyReset();
 			return result;
 		default:
 			return result;
	 }
}

/*
 *	we start up octoshape and 
 *	replyFunction is a function taking and int reply/error code + the octoshape plugin instance 
 *		where the second argumet may be undefined if the first is non-zero.
 * **/
window.octopv_bpGet=function bpGet(replyFunction, group){
	var local_group;
	if(arguments[0] instanceof String){
		local_group = group;
	}else{
		local_group = octopv_group;
	}
	
	function bpCheck(octoobject){
		if (octoobject==null || typeof(octoobject) == "undefined"){
			octopv_debug('Octoobject('+octoobject+'): is typeof undefined');
			return octoErrors.NO_BROWSER_PLUGIN;
		}
		if (typeof(octoobject.getStatus) == "undefined") {
			octopv_debug('Octoobject('+octoobject+'): has no getStatus method');
			return octoErrors.BROWSER_PLUGIN_NO_METHOD;	
		}
		return 0;
	}

	
	// Do not call this from the head section of a document.
	function bpMimeType() {
		var octomime = "application/x-octoshapeplugin"+local_group+"-client";
		octopv_debug("Trying to get browser plugin by mime type: "+octomime);
						
		if (navigator && navigator.mimeTypes && navigator.mimeTypes.length > 0) {
			var mimetype = navigator.mimeTypes[octomime];

			if (!mimetype && (navigator.plugins)) {
				octopv_debug("Refreshing plugins");
				navigator.plugins.refresh(false);
				mimetype = navigator.mimeTypes[octomime];
			}

			if (!mimetype) {
				octomime = octomime.toLowerCase();
				mimetype = navigator.mimeTypes[octomime];
			}
			
			if (mimetype) {
				var name = 'octoshapeclientobject';
				var octoshape = document.getElementById(name);
				if (!octoshape) {
					octopv_debug("We have no "+name+" object");
					var html = "";
					if(octopv_isOSX()){
						html = '<embed id="'+name+'" type="'+octomime+'" hidden="true"></embed>';
					}else{
						html = '<object id="'+name+'" type="'+octomime+'" style="height:0px; width:1px; visibility:hidden;" />';
					}
					octopv_writeInNewDiv(html);
					octoshape = document.getElementById(name);
				}
				octopv_debug("Have inserted html mime type object, now checking object. ");
				if (bpCheck(octoshape)==0) {
					octopv_debug("Client loaded using mimeTypes:" + octomime);
					replyFunction(0, octoshape);
					return true;
				}else{
					octopv_debug("Mime type "+octomime+" was not known. inserted object was: "+octoshape);
					octopv_debug("We try to wait 1 second ... ");
					
					octopv_setTimeoutFunction(1000, function(){
						octopv_debug("After waiting 1 second for browser plugin");
						var octoDims = document.getElementById('octoshapeclientobject');
						if (octoDims==null || typeof(octoDims) == "undefined"){
							replyFunction(octoErrors.NO_BROWSER_PLUGIN,null);
						}
						if (typeof(octoDims.getStatus) == "undefined") {
							replyFunction(octoErrors.BROWSER_PLUGIN_NO_METHOD,null);
						}
						octopv_debug("Browser plugin ok after wait");
						replyFunction(0,octoDims);
					});
					return true;
				}
			} 
		}
		return false;
	}
	var errorCode = octoErrors.NO_BROWSER_PLUGIN;
	try {
		if (window.ActiveXObject) {
			try {
				var octoshape = new ActiveXObject("octoshapeplugin"+local_group+".client");
				errorCode = bpCheck(octoshape);
				if(errorCode==0){ 
					octopv_debug("Client loaded using ActiveXObject");
					replyFunction(0, octoshape);
					return; 
				}
			} catch(exception) {}
		}
	
		if (window.GeckoActiveXObject) {
			try {
				var octoshape = new GeckoActiveXObject("octoshapeplugin"+local_group+".client");
				errorCode = bpCheck(octoshape);
				if(errorCode==0){ 
					octopv_debug("Client loaded using GeckoActiveXObject");
					replyFunction(0, octoshape);
					return;
				}
			} catch(exception) {}
		}
		
		// Crashes opera
		if (false && navigator && navigator.plugins && navigator.plugins.length > 0) {
			var octoshape = navigator.plugins["application/x-octoshapeplugin"+local_group+".client"];
			errorCode = bpCheck(octoshape);
			if(errorCode==0){ 
				octopv_debug("Client loaded using navigator.plugins");
				replyFunction(0, octoshape);
				return;
			}
		}
	
		if(navigator && navigator.mimeTypes && navigator.mimeTypes.length > 0) {
			if(bpMimeType()) return;
		}
	} catch (exception) {
		if(bpMimeType()) return;
	}
	octopv_debug("Client loading failed all together.");
	replyFunction(errorCode, null);
}

window.octoCanHaveBrowserPlugin=function canHaveBrowserPlugin(){
	var text = navigator.userAgent.toLowerCase();
	if (text.indexOf("windows") >= 0 || text.indexOf("mac os x") >= 0 ) {
		return (text.indexOf("opera") == -1);
	} 
	return false;
}




/* #################################################################################### 
                                 APPLET PRELOADER                                        
                             
   #################################################################################### */

window.octopv_preloadAppletCount=0;
window.octopv_preloadAppletReplies=new Object();
window.octopv_initAppletInited=function initAppletInited(callbackId, major,minor,micro,osVersion){
	window.octopv_debug("got applet reply for "+callbackId);
	if(arguments.length>=4){
		octopv_debug('System info: java version 1.'+major+'.'+minor+'_'+micro);
	}
	window.octopv_preloadAppletReplies[callbackId](major,minor,micro,osVersion);
}

/**
	This can be used for testing to see if java works and for preloading jar archive files.
	arguments:
	- replyFunction takes an int that is either:
		0: 										applet loaded
		octoErrors.PRELOAD_APPLET_INSERT: 	web error
		octoErrors.PRELOAD_APPLET_TIMEOUT:	timeout reached before we got reply.
	- timeoutMillis are the milli seconds we wait for the applet to load.
	- archive1 and archive2 are both optional (they are the archives that will be preloaded).
*/
window.octopv_preloadApplet=function preloadApplet(replyFunction, timeoutMillis, archive1){
	var answered=false;
	var name = 'func'+window.octopv_preloadAppletCount;
	var reply = 'window.octopv_preloadAppletReplies.'+name+'();';
	window.octopv_preloadAppletReplies[name]=function(major,minor,micro,osVersion){
		if(answered){
			window.octopv_debug("got applet reply from "+name+" but we have already answered!");
		}else{
			window.octopv_debug("got applet reply from "+name);
			answered=true;
			replyFunction(0,major,minor,micro,osVersion);
		}
	};

	var div = 'octopv_preloadApplet'+window.octopv_preloadAppletCount;
	window.octopv_preloadAppletCount++;
	var html='';
	var initcode='octoshape.applets.init.OctoTestApplet.class';
	var initjar = octopv_paths.get('octoinit.jar');
	if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
		// browser is IE:
		octopv_debug("generating test applet ie tag");
		html += '<OBJECT ';
		html += 'NAME="'+name+'" ';
		html += 'ID="'+name+'" ';
	  	html += 'classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
		html += 'width="1" height="1"> ';
		html += '<PARAM NAME="code" value="'+initcode+'" /> ';
		if(typeof(archive1)=='string'){
			html += '<PARAM NAME="archive" VALUE="'+initjar+','+archive1+'">';
		}else{
			html += '<PARAM NAME="archive" VALUE="'+initjar+'" />';
		}
	  	html += '<PARAM NAME="mayscript" VALUE="true" />';
	  	html += '<PARAM NAME="callbackstring" VALUE="'+name+'" />';
		html += '</OBJECT> ';
	}else{
		// not IE:
		octopv_debug("generating test applet non-ie tag");
		html += '<applet code="'+initcode+'" '; 
		html += 'width="1" height="1" ';
		if(typeof(archive1)=='string'){
			html+='archive="'+initjar+','+archive1+'" ';
		}else{
			html+='archive="'+initjar+'" ';
		}
        html += 'scriptable="true" ';
        html += 'mayscript="true" ';
		html += 'callbackstring="'+name+'" ';
		html += '>';
		html += '<PARAM name="callbackstring" value="'+name+'">';	// mac os safari needs params in this way
		html += '</applet>';
	}
	
	
	var timeoutName=name+'timeout'; 
	var timeout = 'window.octopv_preloadAppletReplies.'+timeoutName+'();';
	window.octopv_preloadAppletReplies[timeoutName]=function(){
		if(answered){
			window.octopv_debug("(Reached timeout for "+name+" but we have already answered)");
		}else{
			window.octopv_debug("Reached timeout for "+name);
			answered=true;
			replyFunction(octoErrors.PRELOAD_APPLET_TIMEOUT);
		}
	};
	
	octopv_debug("Writing test applet tag to page.");
	if(octopv_writeToDiv(div, html, true)){
		if(answered){
			window.octopv_debug("Not setting timeout since we already have answered");
		}else{
			window.octopv_debug("Setting timeout to "+timeoutMillis);
			setTimeout(timeout,timeoutMillis);
		}
	}else{
		replyFunction(octoErrors.PRELOAD_APPLET_INSERT); 
	}
}

/* #################################################################################### 
                                 APPLET LAUNCHER                                        
                             variables and functions
   #################################################################################### */

window.octopv_pluginLauncherApplet=new Object();
/*
  -10: timeout reached.
   -4: applet reply error
   -3: applet not trusted by user
   -2: there was some error in initializing the applet (writing to disk)
   -1: we can not do applet install

	0: init finished answer from applet

	1: not written to page
    2: applet written to page
    3: applet init answer, still waiting for finish
*/ 
window.octopv_pluginLauncherApplet.status=1;
window.octopv_pluginLauncherApplet.name = 'octopv_pluginLauncherAppletApplet';
window.octopv_pluginLauncherApplet.readyFunction=null;

window.octopv_pluginLauncherApplet.resetAll=function(){
	this.readyFunction=null;
}

window.octopv_pluginLauncherApplet.resetAll();

window.octopv_pluginLauncherApplet.doReadyFunction=function pluginLauncherAppletDo(){
	/* This function is actually called from the applet start() function,
	but we dont want to continue till after that function has returned. 
	So we postpone replying half a second .*/
	setTimeout("window.octopv_pluginLauncherApplet.doReadyFunctionReal();",500);
};
window.octopv_pluginLauncherApplet.doReadyFunctionReal=function pluginLauncherAppletDoReal(){
	if(this.readyFunction!=null){
		octopv_debug('Launcher applet: calling ready function');
		this.readyFunction();
	}
	this.readyFunction=null;
};
/* 	
	Inserts the applet in the container.
*/
window.octopv_pluginLauncherApplet.insert=function pluginLauncherAppletInsert(){
	try{
		this.status=2;
		var html='';
		var mainClass = 'octoshape.applets.OctoPluginLauncherApplet.class';
		var jarFile = octopv_paths.get("octolauncher.jar");
		var initJarFile = octopv_paths.get("octoinit.jar");
		if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
			// browser is IE:
			html += '<OBJECT ';
			html += 'NAME="'+this.name+'" ';
			html += 'ID="'+this.name+'" ';
		  	html += 'classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
			html += 'width="1" height="1"> ';
			html += '<PARAM NAME="code" value="'+mainClass+'" /> ';
			html += '<PARAM NAME="archive" VALUE="'+initJarFile+','+jarFile+'" />';
		  	html += '<PARAM NAME="mayscript" VALUE="true" />';
		  	html += '<PARAM NAME="scriptable" VALUE="true" />';
		  	html += '<PARAM NAME="callbackstring" VALUE="launcher" />';
		  	html += '<PARAM NAME="initfunction" VALUE="octopv_pluginLauncherAppletInited" />';
		  	html += '<PARAM NAME="NAME" VALUE="'+octopv_appletDisplayName+'">';
		  	html += octopv_appletDebugParams(true);
			html += '</OBJECT> ';
		}else{
			// not IE:
			html += '<embed code="'+mainClass+'" '; 
			html += 'width="1" height="1" type="application/x-java-applet;version=1.1" ';
			html += 'pluginspage="http://java.sun.com/javase/downloads/" ';
	        html += 'id="'+this.name+'" ';
			html += 'NAME="'+octopv_appletDisplayName+'" ';
			html += 'archive="'+initJarFile+','+jarFile+'" ';
	        html += 'scriptable="true" ';
	        html += 'mayscript="true" ';
			html += 'callbackstring="launcher" ';
		  	html += 'initfunction="octopv_pluginLauncherAppletInited" ';
		  	html += octopv_appletDebugParams(false);
			html += '/>';
		}
		if(!octopv_writeToDiv('octopv_pluginLauncherAppletDiv', html, true)){
			return false;
		}
		return true;
	
	}catch(ex){ 
		octopv_debug('JavaScript error: '+ex.message);
		return false;
	}
}

/* called from applet. called with 
   <0: error happend
	0: finished init
   >0: still running init
*/
window.octopv_pluginLauncherAppletInited=function pluginLauncherAppletInited(reply){
	var init = octopv_convertToNumber(reply, octoErrors.LAUNCH_APPLET_REPLY);
	var stat = window.octopv_pluginLauncherApplet.status;
	octopv_debug('Launcher applet inited with '+init+'. Status is '+stat);
	if(init>0){
		window.octopv_pluginLauncherApplet.status=3; 
	}else{
		if(init==0){
			window.octopv_pluginLauncherApplet.status=0;
		}else if(init==-2){
			window.octopv_pluginLauncherApplet.status=octoErrors.LAUNCH_APPLET_WRITE;
		}else if(init==-3){
			window.octopv_pluginLauncherApplet.status=octoErrors.LAUNCH_APPLET_SECURITY;
		}else{
			window.octopv_pluginLauncherApplet.status=octoErrors.LAUNCH_APPLET_UNKNOWN; 
		}
		window.octopv_pluginLauncherApplet.doReadyFunction();
	}
}
	
/* PUBLIC function for starting up both applet and octoshape
 functIntBool is a function taking an int status and a bool 
 		if the status is an error status, 
			then if bool is true the error is from the octoshape plugin
			else the error is from the applet.
	TODO make timeout for no answer
*/ 
window.octoPluginLauncherApplet=function pluginLauncherApplet(functIntBool){
	window.octopv_pluginLauncherApplet.setReadyFunction(function(){
		try{
			var s = window.octopv_pluginLauncherApplet.status;
			if(s<0){
				functIntBool(s,false);
			}else{
				window.octopv_loopUntil("appletPluginLaunch",function(count){
					var os = window.octopv_pluginLauncherApplet.getStatus(count==1);
					if(os==0 ||os==1){
						return 1000; // run again in 1000 millis
					}else{
						functIntBool(os,true);
						return 0; // done
					}
				});
			}
		}catch(ex){ 
			octopv_debug('JavaScript error: '+ex.message);
		}
	});
}


/** whenReady must be a function taking no arguments.
	when it is called the status variable can be accessed  */
window.octopv_pluginLauncherApplet.setReadyFunction=function pluginLauncherAppletRegister(whenReady){
	if(octopv_pluginLauncherApplet.status<=0){
		whenReady();
	}else{
		octopv_pluginLauncherApplet.readyFunction=whenReady;
		if(octopv_pluginLauncherApplet.status==1){	
			if(!octopv_pluginLauncherApplet.insert()){
				octopv_pluginLauncherApplet.status=octoErrors.LAUNCH_APPLET_JAVASCRIPT;
				whenReady();
			}
		}
	}
}

window.octopv_pluginLauncherApplet.getPlayLink=function pluginLauncherAppletGetPlayLink(octolink){
	if(this.status!=0) return "";
	return document[this.name].getLink(octolink, false);
};

window.octopv_pluginLauncherApplet.getStringOption=function(option){
	if(this.status!=0) return "";
	return document[this.name].getString(option);
};

window.octopv_pluginLauncherApplet.getStatus=function pluginLauncherAppletGetStatus(startup){
	try{
		if(this.status<0){
			return status;
		} 
		if(this.status>0){
			return octoErrors.LAUNCH_APPLET_NOT_READY;
		}
		var reply = document[this.name].getStatus(startup);
		octopv_debug('stat: '+this.status+'. Reply from getStatus('+typeof(reply)+'): '+reply);
		return reply;
	}catch(ex){ 
		octopv_debug('JavaScript error: '+ex.message);
		return octoErrors.JS;
	}
};


/* #################################################################################### 
                         JAVASCRIPT HTTP-REQUEST PORT TEST                                        
                              variables and functions
   #################################################################################### */

/** used by both octopv_flashOctoIsRunningTester and octoJavaScriptHttpAll */
//window.octopv_defaultPorts = new Array(6498,8247);


window.octoJavaScriptHttpCanDo=function javaScriptHttpCanDo(){
	return window.XDomainRequest;
}

/** 
Testing if octoshape is running by http request from JavaScript. 
May return false negative, but not false positive.<b> 
Primary function returns true if this method can be used, otherwise false.
If it returns true the reply function will be called at some time, otherwise it will not be called.

For test to be performed we need:
 	- IE 8
 	- a sua > 090512
 And it still may falsely return false (if octoshape is bound on some secondary port).
  ipport is the ip addres + port to connect to.
  timeout is in millis. (2000 should be ok)
  replyFunction must take 1 int argument (the status) + 1 string argument (the plugin version).
	 0: succes.
	 some error-code on error (<0)
*/
window.octoJavaScriptHttp=function javaScriptHttp(ipport, timeout, replyFunction){
	if (!window.octoJavaScriptHttpCanDo()){
		replyFunction(octoErrors.JSHTTP_IMPOSSIBLE,null); 
		return;
	}
	octopv_debug('Trying ip+port: '+ipport);
	var finished=false;
	try{
		// we need a single run object since we always reach the javascript timeout.
		//var replyOnce = octopv_toSingleRunFunction(this, replyFunction);
		octopv_debug('Making XDomainRequest object ...');
		var xdr=new XDomainRequest(); 
		if(!xdr){
			octopv_debug('Could not make object.');
			replyFunction(octoErrors.JSHTTP_IMPOSSIBLE,null); 
			return;
		}
		xdr.onload=function(){
			octopv_debug('onload called');
			var reply = octoErrors.JSHTTP_UNKNOWN;
			var version = "";
			try {
				var xmlDoc=new ActiveXObject('Microsoft.XMLDOM');
				xmlDoc.async='false';
				var text = xdr.responseText;
				xmlDoc.loadXML(text);
				if(xmlDoc.documentElement.tagName=='octoshapesua'){
					reply = 0;
					version = xmlDoc.documentElement.getAttribute('version');
				}else{
					reply = octoErrors.JSHTTP_XML;
				}
				octopv_debug('version: '+version);
				octopv_debug('reply was: '+text);
			}catch(e){
				octopv_debug('Err '+e.name+': '+e.message, arguments.callee);
				reply = octoErrors.JSHTTP_NOT_XML;
			}
			finished=true;
			replyFunction(reply,version);
		};
		xdr.onerror = function(){
			octopv_debug('onerror called');
			finished=true;
			replyFunction(octoErrors.JSHTTP_CONNECT,null);
		};
        xdr.ontimeout = function(){
			octopv_debug('ontimeout called');
			finished=true;
			replyFunction(octoErrors.JSHTTP_CONNECT_TIMEOUT,null);
		};
  		xdr.timeout = timeout;
  		var req = 'http://'+ipport+'/octoshapeprobe.xml';
  		// we use post to make sure that the answer is not cached.
  		xdr.open('POST', req);
		
		octopv_setTimeoutFunction(timeout+1500, function(){
			if(finished){
				octopv_debug('We reached javascript timeout, but have already answered.');
			}else{
				finished=true;
				replyFunction(octoErrors.JSHTTP_TIMEOUT,null);
			}
		});
  		var randomStr = 'random'+(Math.floor(Math.random()*100000));
		octopv_debug('Sending request: '+req+' post: '+randomStr);
		xdr.send(randomStr);
	}catch(ex){
		octopv_debug('Caught exception: '+ex);
		finished=true;
		replyFunction(octoErrors.JSHTTP_CONNECT_EX,null);
	}
}




/* #################################################################################### 
                                FLASH PORT TEST                                        
                            variables and functions
   #################################################################################### */

//	window.octopv_flashOctoIsRunningTester.initDone=false;
window.octopv_counter=0;
window.octopv_getJsUniqueId=function(){
	window.octopv_counter++;
	return ('id'+window.octopv_counter);
};


// replyfunc must be a function taking 1 int argument (the port, or <0 on error).
window.octopv_FlashBP=function FlashBP(replyfunc){

	if(!window.octopv_flashOk()){
		replyfunc(octoErrors.FLASH_BP_IMPOSSIBLE); 
	};

	var myId=octopv_getJsUniqueId();
	
	var replyfunctionName='octopv_flashOctoIsRunningTester_reply'+myId;
	var timeoutfunctionName='octopv_flashOctoIsRunningTester_timeout'+myId;
	var initfunctionName='octopv_flashOctoIsRunningTester_init'+myId;
	var flashName='octopv_flash_bp'+myId;

	var path = octopv_paths.get('octofbp2.swf');

  	var html  = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';
   	html += ' id="'+flashName+'" width="0" height="0"';
    html += ' codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">';
    html += ' <param name="movie" value="'+path+'" />';
    html += ' <param name="FlashVars" value="init='+initfunctionName+'" />';
    html += ' <param name="wmode" value="transparent" />';
    html += ' <param name="AllowScriptAccess" value="always" />';
    html += ' <embed src="'+path+'"';
    html += ' width="1" height="1" name="'+flashName+'"';
    html += ' AllowScriptAccess="always"';
    html += ' FlashVars="init='+initfunctionName+'"';
    html += ' play="true" loop="false" wmode="transparent"';
    html += ' type="application/x-shockwave-flash" ';
    html += ' pluginspage="http://www.adobe.com/go/getflashplayer">';
    html += ' </embed></object>';

	octopv_debug('Inserts flash helper from '+path);
	
	var portsArr = new Array();
	var debugStr = '';
	for(var i=1; i<arguments.length; i++){
        portsArr.push(arguments[i]);
	}
	
	for(var i=0; i<portsArr.length; i++){
        debugStr+=(portsArr[i]+',');
	}
	octopv_debug('Ports to check ('+portsArr.length+'): '+debugStr);
	
	window[initfunctionName]=function flashBP_init(swfname){
		octopv_debug('init-function called');
		var dims=null;
    	if (navigator.appName.indexOf("Microsoft") != -1) {
        	dims=window[swfname];
    	}else{
	        dims=document[swfname];
 		}
		window[timeoutfunctionName]=function flashBP_timeout(){
			octopv_debug('(Timeout has been reached, but we already replied)');
		};
		octopv_debug('Calling flash bp: '+dims);
		window[replyfunctionName]=function flashBP_reply(intResult){
			if(intResult==-1){
				replyfunc(octoErrors.FLASH_BP_UNKNOWN);
			}else if(intResult==0){
				octopv_debug('Installed but not launched reply from flash!');
				replyfunc(octoErrors.FLASH_BP_NOT_LAUNCHED);
			}else{
				replyfunc(intResult);
			}
		};
		
		// TODO currently when called from silverlight osa the call to the flash function 
		// never generates a return call to the replyFunction. 
		// temp solotion is to avoid the flash tester when calling from silverlight
		
		try{
	   		dims.octopvAS_beginCheck(replyfunctionName,2000,portsArr);
    	}catch(ex){
			octopv_debug('ex:'+ex);
			octopv_debug('try to wait 1 second and then try again ...');
			octopv_setTimeoutFunction(1000, function(){
				try{
					octopv_debug('After wait of 1 second.');
			   		dims.octopvAS_beginCheck(replyfunctionName,2000,portsArr);
		    	}catch(ex){
					octopv_debug('After wait of 1 second we still got ex!:'+ex);
		    		replyfunc(octoErrors.FLASH_BP_NO_CALLBACK);
		    	}
			});
    	}
	};
    if(octopv_writeInNewDiv(html)){
		// We set a timeout here just in case there is something wrong with the swf,
		//  and it does not get initialized. It should never happen though.
		window[timeoutfunctionName]=function flashBP_timeout2(){
			octopv_debug('Timeout has been reached and we had no answer from flash -- ');
			window[initfunctionName]=function flashBP_init2(){
				octopv_debug('Flash answer was inited after timeout. ');
			};
			window[replyfunctionName]=function flashBP_reply2(intResult){
				octopv_debug('Flash answer got after timeout: '+intResult);
			};
			replyfunc(octoErrors.FLASH_BP_TIMEOUT);
		};
		setTimeout("window."+timeoutfunctionName+"();",4500);
    }else{
		octopv_debug('Could not write to div octopv_flashOctoIsRunningTesterDiv');
		replyfunc(octoErrors.FLASH_BP_IMPOSSIBLE); 
    }
}


/* #################################################################################### 
                               FORCE SUA UPDATE 
                            variables and functions
   #################################################################################### */


/**
	replyFunction must be a function taking an int argument indicating:
		<0: if octoshape not installed or there was some error with the browser plugin
		 0: the current sua version was ok
		 1: we have updated the sua, and are now ready again.
*/
window.octopv_forceSuaUpdateIfNeeded=function forceSuaUpdateIfNeeded(updatelink, okSuaVersion, replyFunction){
	octopv_debug("Function called. updatelink: "+updatelink+" sua:"+okSuaVersion);
	
	octoGetSuaVersion(function(intStatus, stringVersion){
		if(intStatus==0){
			var ver = stringVersion;
			var doUpdate = false;
	   		if (ver.Length == okSuaVersion.Length) {
			    	doUpdate = ver < okSuaVersion; // lexicographical javascript compare!
		    } else {
    			doUpdate = ver.Length < okSuaVersion.Length;
    		}
    		if(doUpdate){
    			octopv_debug("Doing sua update since current ver is "+ver+" and marker is "+okSuaVersion);
    			octoGetPlayLink(updatelink, function(intStatus2,playlink){
    				if(intStatus2<0){
    					replyFunction(intStatus2);
    				}else{
    					// we have the update playlink.
						octopv_insertInvisibleIframe(playlink);
						window.octopv_forceSuaUpdateIfNeededLoopReply=replyFunction;
						setTimeout("octopv_forceSuaUpdateIfNeededLoop();",3000);
    				}
    			}, false);
    		}else{
				replyFunction(0);
    		}
		}else{
			replyFunction(intStatus);
		}
	}, false);
}

window.octopv_forceSuaUpdateIfNeededLoopReply=null;
window.octopv_forceSuaUpdateIfNeededLoop=function forceSuaUpdateIfNeededLoop(){
	octopv_debug("calling after wait.");
	octoGetPluginStatus(function(intStatus){
		if(intStatus<0){
			window.octopv_forceSuaUpdateIfNeededLoopReply(intStatus);
		}else{
			window.octopv_forceSuaUpdateIfNeededLoopReply(1);
		}
	}, false);
}

/* #################################################################################### 
                               SIMPLE LAUNCH 
                            variables and functions
   #################################################################################### */


/**
if callback is a function then it must be a function taking no argument. 
It will be called after a delay, where we might be started up. 
*/
window.octopv_launchByProtocol=function launchByProtocol(callback,timeout){
	try{
		var name = "octopv_launchByProtocolFrame";
		var e = document.getElementById(name);
		if(e==null){
			e = document.createElement("iframe");
			e.id=name;
			e.name=name;
			e.width=0;
			e.height=0;
			e.style.display = "none";
			e.src="OCTOSHAPE:";
			document.body.insertBefore(e,document.body.firstChild);
		}else{
			e.src="OCTOSHAPE:";
		}
		if(typeof(callback)=='function'){
			var to = (typeof(timeout)=='number')?timeout:3000;
			octopv_debug("After launch by protocol we wait for "+to+" milli-secs before returning ...");
			octopv_setTimeoutFunction(to, function(){
				callback(octoErrors.PROTOCAL_LAUNCH_AFTER);
			});
		}
	}catch(ex){
		octopv_debug("Exception "+ex);
		if(typeof(callback)=='function'){
			callback(octoErrors.PROTOCAL_LAUNCH_ERROR);
		}
	}
}


/* #################################################################################### 
                               INSTALL APPLET FUNCTIONS

   #################################################################################### */

/**
This JavaScript file contains functions to install octoshape on windows by a signed applet.
It requires 2 files to be present:
	- octoinit.jar
	- octoinstall.jar
**/

window.octopv_installcode=function installcode(){
	if(octopv_isOSX()){
		return 'octoshape.applets.OctoInstallAppletMac.class';
	}else{
		return 'octoshape.applets.OctoInstallApplet.class';
	}
}
window.octopv_installjar=function installjar(){
	if(octopv_isOSX()){
		return octopv_paths.get('octosetup-mac.jar');
	}else{
		return octopv_paths.get('octosetup.jar');
	}
}

var octopv_topObject = new Object();
octopv_topObject.installCompleted=null;
octopv_topObject.progress=null;
octopv_topObject.waitFinishedCount=0;

/** if indiv is null, we write directly
 * 	onComplete must be a function taking an int (or not defined):
	* 		  - 4: installation error ... disk?
	* 		  - 3: user denied applet security
	* 		  - 2: eula not accepted
	* 		  (- 1: could not do applet install)
	* 		    >0: all is well and finished with the install and this is the port to bind to
	*/
window.octopv_doAppletInstall=function doAppletInstall(indiv, onComplete, progressFunction){
	if(typeof(onComplete)=='function'){
		octopv_topObject.installCompleted=onComplete;
	}
	
	if(progressFunction instanceof Function){
		octopv_topObject.progress=progressFunction;
	}else if(arguments.length == 3){
		octopv_setProgressFunction(function(str){
			octopv_writeToDiv(progressFunction,str);
		});
	}
	
	var html='';
	var app = octopv_installjar();
	var initJarFile = octopv_paths.get("octoinit.jar");
	if(navigator.userAgent.toLowerCase().indexOf("msie") != -1){
		// browser is IE:
		html += '<OBJECT NAME="octopv_applet"';
	  	html += 'classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" ';
		html += 'width="1" height="1"> ';
		html += '<PARAM NAME="code" value="'+octopv_installcode()+'"> ';
		html += '<PARAM NAME="archive" VALUE="'+initJarFile+','+app+'">';
	  	html += '<PARAM NAME="mayscript" VALUE="true">';
	  	html += '<PARAM NAME="NAME" VALUE="'+octopv_appletDisplayName+'">';
	  	if(arguments.length == 4){
			html += '<PARAM name="'+param1+'" VALUE="'+value1+'"/>';
		}
	  	html += octopv_appletDebugParams(true);
		html += '</OBJECT> ';
	}else{
		// not IE:
		html += '<embed code="'+octopv_installcode()+'" '; 
		html += 'NAME="'+octopv_appletDisplayName+'" ';
		html += 'width="1" height="1" type="application/x-java-applet;version=1.1" ';
		html += 'pluginspage="http://java.sun.com/javase/downloads/" ';
		html += 'archive="'+initJarFile+','+app+'" ';
        html += 'scriptable="true" ';
        html += 'mayscript="true" ';
		html += 'callbackstring="install" ';
	  	html += octopv_appletDebugParams(false);
		html += '/>';
	}
	octopv_debug("insering install-jar from: "+app);
	octopv_writeToDiv(indiv, html);
}






/* ** Applet callback functions */


/**
	called by install applet
*/
window.octopv_appletProgress=function appletProgress(message){
	octopv_debug("applet install progress: "+message+"", arguments.callee);
	if(octopv_topObject.progress != null){
		octopv_topObject.progress(message);
	}
}

/**
	called by install applet
	0: ok, <0 not ok. 
	result might be a string
*/
window.octopv_installAppletFinishedInstall=function installAppletFinishedInstall(result){
	octopv_debug("applet finished install (1): "+result);
	var r=octoErrors.INSTALL_APPLET_JS;
	try{
		r = parseInt(result);
		if(r>=0){
			window.octopv_preferencePluginLaunch_cookieSetCanUse("Applet");
		}else{
			switch(r){
				case -5: r=octoErrors.INSTALL_APPLET_EXECUTION; 	break;
				case -4: r=octoErrors.INSTALL_APPLET_NO_FILE;		break;
				case -3: r=octoErrors.INSTALL_APPLET_SECURITY;		break;
				case -2: r=octoErrors.INSTALL_APPLET_EULA_REJECT;	break;
				default: r=octoErrors.INSTALL_APPLET_UNKNOWN;		break;
			}
		}
		octopv_debug("applet install result converted to: "+r);
	}catch(ex){ 
		octopv_debug('JavaScript error (result was '+result+': '+ex.message);
	}
	if(octopv_topObject.installCompleted!=null){
		octopv_debug("calling install completed: "+result);
		octopv_topObject.installCompleted(r);
	}else{
		octopv_debug("ERROR?: there was nor installcompleted function. ");
	}
};


/* #################################################################################### 
                                 FLASH EULA FUNCTIONS

   #################################################################################### */

var octopve_callbackFunc = null;
var octopve_containerid = null;
var octopve_disableEula = false;

/** callback */
window.octopve_spawnEula=function spawnEula(callback, containerid) {
	//if user does not have flash, we return true to let call callback(true)
	if(!window.octopv_flashOk()){
		callback(true);
		return;
	};
	
	if(octopve_disableEula){
		callback(true);
		return;
	}
	octopve_callbackFunc = callback;
	octopve_containerid = containerid

	var container = document.getElementById(containerid);
	if(container==null){
		container=document.createElement("div");
		container.id=containerid;
		container.style.position='absolute';
		container.style.zIndex='9999';
		container.style.width='100%';
		container.style.height='100%';
		container.style.top='0px';
		container.style.left='0px';
		document.body.insertBefore(container,document.body.firstChild);
	}
	if(container == null){
		octopve_callbackFunc(true);
		return;
	}
	var path = octopv_paths.get("octoeula.swf");

  	var html  = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';
    html += ' id="octopveula" width="100%" height="100%"';
    html += ' codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">';
    html += ' <param name="movie" value="'+path+'" />';
    html += ' <param name="wmode" value="transparent" />';
    html += ' <param name="AllowScriptAccess" value="always" />';
    html += ' <param name="FlashVars" value="containerId='+octopve_containerid+'" />';

    html += ' <embed src="'+path+'"';
    html += ' width="100%" height="100%" name="octopveula"';
    html += ' AllowScriptAccess="always"';
    html += ' play="true" loop="false" wmode="transparent"';
    html += ' type="application/x-shockwave-flash" FlashVars="containerId='+octopve_containerid+'"';
    html += ' pluginspage="http://www.adobe.com/go/getflashplayer">';
    html += ' </embed></object>';

	octopv_debug('Showing eula from:' +path);
    container.innerHTML = html;
}

/* #################################################################################### 
                                 CAB INSTALLER

   #################################################################################### */

var octopvCAB_topobject = new Object();
octopvCAB_topobject.onComplete=null;
octopvCAB_topobject.timeout=0;

window.octopv_doCabInstall=function doCabInstall(indiv, timeout, onComplete){
	octopvCAB_topobject.onComplete = onComplete;
	octopvCAB_topobject.timeout=timeout;
	var file = octopv_paths.get('octosetup.cab');
	var html = '<OBJECT onreadystatechange="javascript:octopv_cabReadychange();"';
	html += ' CODEBASE="'+file+'#version=1.0.0.0"';
	html += ' id="OctoshapeCabInstaller" CLASSID="CLSID:7D4733C0-C43B-4A81-AF43-F9B20D1F8348"';
	html += ' width="0" height="0" >';
	html += '</OBJECT>';
	octopv_debug("Inserting cab file from "+file);
	octopv_writeToDiv(indiv, html);
}

window.octopv_cabReadychange=function cabReadychange(dontWait){
	try{
		var state = document.all["OctoshapeCabInstaller"].readyState;
		octopv_debug("Ready state changed to "+state);
		if(state==4){
			if(octopvCAB_topobject.onComplete!=null){
				window.setTimeout("octopvCAB_topobject.onComplete(0);",octopvCAB_topobject.timeout);
			}
		}
	}catch(ex){
		if(typeof dontWait == 'boolean' && !dontWait){
			octopv_debug("Ready state not defined: "+ex);
			// If we do not report complete back here then we might end up in an 
			// error state where we never report back.
			if(octopvCAB_topobject.onComplete!=null){
				octopvCAB_topobject.onComplete(octoErrors.CAB_READY_STATE);
			}
		}else{
			octopv_debug("Ready state not defined: "+ex+" trying to wait a little ... ");
			window.setTimeout("octopv_cabReadychange(true);",500);
		}
	}
}


/* #################################################################################### 
                               UTILITY FUNCTIONS

   #################################################################################### */
   
/* 
  functions named octopvpv* are internal unility functions 
*/

/** 
  Helper to set a function to be called after timeout. 
 */
window.octopv_setTimeoutFunction=function setTimeoutFunction(millis, func){
	octopv_setTimeoutFunctionObject.count++;
	var name = "name"+octopv_setTimeoutFunctionObject.count;
	window.octopv_setTimeoutFunctionObject[name] = function(){
		func();
	};
	setTimeout("octopv_setTimeoutFunctionObject."+name+"();",millis);
}
window.octopv_setTimeoutFunctionObject = new Object();
window.octopv_setTimeoutFunctionObject.count=0;


/**	
	This wrapper will ensure that the argument function only will be called 1 time.
	The returned object has a function .callme, that calls the function 
	(and returns true if the function was called).
*/
window.octopv_toSingleRunFunction=function toSingleRunFunction(thisReference, func){
	var obj = new Object();
	obj.done = false;
	obj.func = func;
	obj.thisref=thisReference;
	obj.callme=function(){
		if(this.done){
   			octopv_debug("Stopping multiple calls to "+obj.thisref);
			return false;
		}
		this.done=true;
		this.func.apply(this.thisref,arguments);
		return true;
	};
	return obj;
};


window.octopv_getCookie=function getCookie(name){
	var cs = document.cookie.split(';');
	for(var i=0;i < cs.length;i++) {
		var c = cs[i];
		// trimming c
		while (c.charAt(0)==' '){
			c = c.substring(1,c.length);
		}
		if (c.indexOf(name) == 0) {
			// we need to split the key from the value
			var kv = c.split('=');
			if(kv.length >= 1&&kv[0]==name){
				if(kv.length==2){
					return kv[1];
				}else{
					return"";
				}
			}
		}
	}
	return null;
}

window.octopv_hasCookie=function hasCookie(name){
	var cs = document.cookie.split(';');
	for(var i=0;i < cs.length;i++) {
		var c = cs[i];
		while (c.charAt(0)==' '){
			c = c.substring(1,c.length);
		}
		if (c.indexOf(name) == 0) {
			return true;
		}
	}
	return false;
}


window.octopv_portFromXmlBoundString=function portFromXmlBoundString(xmlBoundReply){
	if((typeof (xmlBoundReply)=='undefined') || xmlBoundReply==null || xmlBoundReply==""){
		return -1;
	}
	try{
		var p = xmlBoundReply.substring(xmlBoundReply.indexOf(":",0)+1,xmlBoundReply.length);
		var port = parseInt(p); 
		return port;
	}catch(e){
		return -1;
	}
}



window.octopv_insertInvisibleIframe=function insertInvisibleIframe(source){
	var iframe = document.createElement("iframe");
	iframe.setAttribute("width", 0);
	iframe.setAttribute("height", 0);
	iframe.setAttribute("src", source);
	iframe.style.display = "none";
	document.body.insertBefore(iframe,document.body.firstChild);
}

window.octopvpv_postponedError = null;
window.octopv_includeJSFile=function includeJSFile(path){
	var script = document.createElement("script");
	script.setAttribute("language", "JavaScript");
	script.setAttribute("type", "text/javascript");
	script.setAttribute("src", path);
	try{
		var head = document.getElementsByTagName("head")[0];
		head.insertBefore(script,head.lastChild);
	}catch(e){
		octopvpv_postponedError="ERROR inserting js in head: "+e.name+"; "+e.message;
	}
}


window.octopvpv_loopArray = new Object();

/** name is a string id for the loop
	theFunction is a int function taking 1 int argument, 
		the argument is the count of times the loop has run (the first time it gives 1)
		the return value must be number of millis to loop next (0 or negative when loop no more). 
		NB: the function will be assigned to a special (global) object when run, 
			so it should only reference global functions and variables.  */
window.octopv_loopUntil=function(name, theFunction){
	octopvpv_loopArray[name]=theFunction;
	octopvpv_loopArray[name+"Count"]=0;
	window.octopvpv_loopUntilDo(name);
}

/** private */
window.octopvpv_loopUntilDo=function(name){
	octopvpv_loopArray[name+"Count"]++;
	var time = octopvpv_loopArray[name](octopvpv_loopArray[name+"Count"]);
	if(time>0){
		setTimeout("octopvpv_loopUntilDo('"+name+"');",time);
	}
}

window.octopv_appletDebugParams=function(paramParams){
	if(octopvDebugDiv && document.getElementById(octopvDebugDiv)!=null){
		if(paramParams){
			return '<param name="display" value="debug_console_div"/>';
		}else{
			return 'display="debug_console_div" ';
		}
	}else{
		 return '';
	}
}

window.octopv_convertToNumber=function(reply, def){
	var intReply=def;
	if(typeof reply == 'number'){
		intReply=reply;
	}else{
		var parsed=parseInt(reply);
		if(!isNaN(parsed)){
			intReply=parsed;
		}
	}
	return intReply;
}


window.octopv_hasProperty=function hasProperty(obj, element){
	for (var i in obj){ 
		if(obj[i].toLowerCase() == element.toLowerCase()){
			return true;
		}
	}
	return false;
}

window.octopv_getPropertiesString=function getPropertiesString(obj){
	var result = "[";
	var delim = "";
	for (var i in obj){ 
		result += (delim + i);
		delim = ",";
	}
	return result+"]";
}

/**
 * Insets a new div at the top of the page an adds the html into it.
 * returns true on success. 
 * */
window.octopv_writeInNewDiv = function writeInNewDiv(html){
	try{
		var oDiv = document.createElement("div");
		var id = octopv_getJsUniqueId();
		oDiv.id=id;
		if(octopv_isFirefox() || octopv_isSafari()){
			oDiv.style.height = "0px"; 
		}
		document.body.insertBefore(oDiv,document.body.firstChild);
		return octopv_writeToDiv(id, html);
	}catch(ex){
		return false;
	}
};

window.octopv_createNewDiv2=function(idName){
	var elem = document.getElementById(idName);
	if(elem==null){
		var oDiv = document.createElement("div");
		oDiv.id=idName;
		document.body.insertBefore(oDiv,document.body.firstChild);
		return true;
	}else{
		return false;
	}
}

window.octopv_createNewDiv=function createNewDiv(idName){
	try{
		var elem = document.getElementById(idName);
		if(elem==null){
			var oDiv = document.createElement("div");
			oDiv.id=idName;
			oDiv.style.height = "0px"; 
			oDiv.style.width = "1px"; 
			document.body.insertBefore(oDiv,document.body.firstChild);
			return true;
		}else{
			return false;
		}
	}catch(ex){ 
		octopv_debug('JavaScript error: '+ex.message);
		return false;
	}
}

window.octopv_writeToDiv=function writeToDiv(indiv, html, create, noStyle){
	try{
		if( typeof(create)=='boolean' &&  create) {
			if(typeof(noStyle)=='boolean' && noStyle){
				octopv_createNewDiv2(indiv);
			}else{
				octopv_createNewDiv(indiv);
			}
		}
	 	var div = null;
	 	if(indiv!=null){
	 		div = document.getElementById(indiv);
	 		if(div==null){
	 			octopv_debug("div "+indiv+" does not exist.");
	 			return false;
	 		}
	 	}
	 	if(indiv==null){
	 		document.write(html);
	 	}else{
	 		div.innerHTML=html;
	 	}
	 	octopv_debug("inserted HTML into div "+indiv);
	 	return true;
	}catch(ex){ 
		octopv_debug('JavaScript error for div '+indiv+': '+ex.message);
		return false;
	}
}

window.octopv_writeToIdLessDiv=function writeToIdLessDiv(html){
	var oDiv = document.createElement("div");
	oDiv.style.height = "0px";
	oDiv.style.width = "1px";
	oDiv.innerHTML=html;
	document.body.insertBefore(oDiv,document.body.firstChild);
 	octopv_debug("inserted HTML into nameless div ");
 	return true;
}

window.octopv_activexdisabled=function(){
	var text = navigator.userAgent.toLowerCase();
	if (text.indexOf("msie") >= 0){ 
		try{
			var test = new ActiveXObject("Scripting.Dictionary");
		}catch(e){
			return true;
		}
	}
	return false;
}

window.octopv_isOSX=function isOSX(){
	return navigator.userAgent.toLowerCase().indexOf("mac os x") != -1;
}

window.octopv_isOSX106=function isOSX106(){
	var str = navigator.userAgent.toLowerCase();
	return str.indexOf("mac os x 10_6") != -1 || str.indexOf("mac os x 10.6") != -1;
}

window.octopv_isWindows=function isWindows(){
	return navigator.userAgent.toLowerCase().indexOf("windows") != -1;
}

window.octopv_isSafari=function isSafari(){
	return navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1;
}

window.octopv_isFirefox=function isFirefox(){
	return navigator.userAgent.toLowerCase().indexOf("firefox") != -1;
}

window.octopv_isFirefox3=function isFirefox3(){
	return navigator.userAgent.toLowerCase().indexOf("firefox/3") != -1;
}

window.octopv_isIE=function isIE(){
	return navigator.userAgent.toLowerCase().indexOf("msie") != -1;
}

window.octopv_isVista=function isVista(){
	return navigator.userAgent.toLowerCase().indexOf("windows nt 6.0") != -1;
}

window.octopv_isXP=function isXP(){
	var str = navigator.userAgent.toLowerCase();
	return (str.indexOf("windows nt 5.1") != -1 || str.indexOf("windows nt 5.2") != -1);
}





// returns true iff there is a plugin registered for the mime type mimeID and
//  the name of this plugin contains pluginName (case oblivious).
window.octopv_mime_plugin_is=function(mimeID, pluginName){
	if(navigator && navigator.mimeTypes && navigator.mimeTypes.length){
		var mime =  navigator.mimeTypes[mimeID];
		if(mime){
			var text  = mime.enabledPlugin.name.toLowerCase();
			return (text.indexOf(pluginName.toLowerCase()) >=0);
		}
	}
	return false;
}

// returns true if there is a plug-in installed that can handle the video/x-ms-asf mime-type
window.octopv_has_mime=function(mimeID){
	if(navigator && navigator.mimeTypes && navigator.mimeTypes.length){
		var mime =  navigator.mimeTypes[mimeID];
		if(mime && mime.enabledPlugin){
			return true;
		}
	}
	return false;
}

window.octopv_debugDo=function(){
	if(typeof(octopvDebugDiv) == 'boolean' && !octopvDebugDiv){
		return false;
	}
	try{
		var	div = document.getElementById(octopvDebugDiv);
		if(div)return true;
	}catch (exception) { }
	return false;
}


window.octopv_debug=function octopv_debug(str, func){
	if(octopvpv_postponedError!=null){
		window.octopv_debug2(octopvpv_postponedError,"postponed");
		octopvpv_postponedError=null;
	}
	window.octopv_debug2(str,func);
}

/** call with 'arguments.callee' to get current function name. */
window.octopv_getFunctionName=function (func, anonymous){
	var funcStr = func.toString();
	var a1 = funcStr.toLowerCase().indexOf('function');
	var b1 = funcStr.indexOf("(");
	var a=a1==0?8:0;
	var b=b1>0?b1:funcStr.length;
	funcStr = funcStr.substring(a,b);
	funcStr = funcStr.replace(/ /, "");
	if(funcStr.length==0){
		if(typeof(anonymous)=='undefined'){
			funcStr="anonymous";
		}else{
			funcStr=anonymous;
		}
	}
	return funcStr;
}

window.octopv_QueryStringMap=function QueryStringMap(){
	this.map = new Object();
	this.size = 0;
	var qs = window.location.search;
	if(qs.length>1){
		qs = qs.substring(1);
		var arr = qs.split('&');
		var i=0;
		for(;i<arr.length;i++){
			var v = arr[i]; 
			if(v.length>0){
				this.size++;
				if(v.indexOf("=")== -1){
					this.map[v] = "";
				}else{
					var a = v.split('=',2);
					this.map[a[0]] = a[1];
				}
			}
		}
	}
	
	this.get=function(name,defaultValue){
		if(typeof(this.map[name])=='undefined'){
			return defaultValue;
		}else{
			return this.map[name];
		}
	}
	
}

/** Returns false if the adobe JavaScript file AC_OETags.js has not been included
or ActioScript 3 is not available  */
window.octopv_flashOk = function flashOk(){
	try{
		if(window.DetectFlashVer && window.DetectFlashVer(9,0,0)){
			return true;
		}else if(window.DetectFlashVer){
			octopv_debug('User has no flash or only old flash.');
			return false;
		}else{
			octopv_debug('We had no AC_OETags.js - assuming user has flash 9');
			return true;
		}
	}catch(ex){
		octopv_debug('Cought exception while testing for flash:'+ex.message);
		return false;
	}
};

/*
About the variable octopvDebugDiv:
	if this is set (to a divID name) we display debug in the div, if the div exists.
	if it does not exist, but the html querystring contains octoshapejsdebug=true then 
		we append the div to the html page (end of body)
	if it does not exist and there is no querystring setting, the debug will be saved, 
		but not shown (maybe later a debug div will be there) 
	To avoid any debug info what so ever to be saved at all, set octopvDebugDiv=false  
*/

function debugFromQueryString(){
	var map  = new octopv_QueryStringMap();
	var value = map.get('octoshapejsdebug','false');
	return (value=='true');
};
window.octopv_debugFromQueryString=debugFromQueryString();

window.octopv_debug2Arr=new Array();
/* returns true if we are in debug mode.  */
window.octopv_debug2=function debug2(str){
	if(typeof(octopvDebugDiv) == 'boolean' && !octopvDebugDiv){
		return false;  
	}
	try{
		var func = arguments.callee.caller.caller;
		var name = null;
		if(typeof(func)=='function'){
			name = octopv_getFunctionName(func,null);
		}
		if(name==null){
			name = 'unknown';
		}
		var millis = (new Date().getTime()) - window.octopv_jsInitMillis;
		if(str!=null){
			octopv_debug2Arr.push('<TR><TD ALIGN="right">' + millis + '<TD>' + name + '<TD>|<TD>' + str + '</TR>');
		}
		
		var	div = document.getElementById(octopvDebugDiv);
		
		// If div does not exist 
		if((!div) && octopv_debugFromQueryString){
			// Div does not exist, but we should add it according to the qs settings
			var oDiv = document.createElement("div");
			oDiv.id=octopvDebugDiv;
			oDiv.style.backgroundColor = "white";
			document.body.appendChild(oDiv);
		} 
		
		if(div){
			var theString = "<table>";
			theString+=("<TR STYLE=\"background-color:#B0B0B0; font-weight: bold;\"><TD colspan=4>OCTOSHAPE JAVASCRIPT DEBUG OUTPUT</TR>");
			theString+=("<TR STYLE=\"background-color:#D8D8D8;\"><TD><TD>SETTINGS<TD>|<TD></TR>");
			
			theString+=("<TR ><TD><TD>js-version<TD>|<TD>"+ window.octopv_fileVersion +"</TR>");
			theString+=("<TR ><TD><TD>user-agent<TD>|<TD>"+ navigator.userAgent +" </TR>");
			theString+=("<TR ><TD><TD>variant<TD>|<TD>"+ window.octoshapeVariant +" </TR>");
			theString+=("<TR ><TD><TD>EULA variant<TD>|<TD>"+ window.octoshapeVariantEula +" </TR>");
			
			var arr = octopv_paths.allFiles;
			for(var i2=0;i2<arr.length;i2++){
				var file = arr[i2];
				var path = octopv_paths.get(file);
				var link = '<span STYLE="color:blue;text-decoration:underline;cursor:pointer;" onclick="javascript:window.open(\''+path+'\'); return false; ">get</span>';
				theString+=("<TR ><TD><TD>"+file+"<TD>|<TD> "+ link + " " +path +"</TR>");
			}
			theString+=("<TR STYLE=\"background-color:#D8D8D8;\"><TD><TD>LOGS<TD>|<TD> size: " + octopv_debug2Arr.length + "</TR>"); 
			
			for(var i=0;i<octopv_debug2Arr.length;i++){
				theString+=octopv_debug2Arr[i];
			}
			theString+="</table>";
			div.innerHTML = theString;
			return true;
		}
	}catch (exception) {}
	return false;
}

function octopv_debugInitFromQueryString(){
	octopv_debug('onload window event');
	octopv_debug(null);
}

if(octopv_debugFromQueryString){
	if(typeof (window.addEventListener) != 'undefined'){
		window.addEventListener("load", octopv_debugInitFromQueryString, false);
	}else if (typeof (document.addEventListener) != 'undefined'){
		document.addEventListener("load", octopv_debugInitFromQueryString, false);
	}else if(typeof (window.attachEvent) != 'undefined'){
		window.attachEvent("onload", octopv_debugInitFromQueryString, false);
	}else{
		alert('Octoshape js debug could not set eventlistener\nYour query-string has octoshapejsdebug=true set');
	}
}


// This adobe JavaScript file is included to be able to test if the user has Flash Player installed.
if(!window.DetectFlashVer) window.octopv_includeJSFile(octopv_paths.get("AC_OETags.js"));
window.octopv_fileInitFunction=function fileInitFunction(){  return octopv_fileVersion;  };
