// Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049)
//
// This update modifies Microsoft Class Server 3.0 - Teacher so that it runs
// with Windows XP SP2 installed.  See KB article 883049 for more information.
//
// NOTE: Use the /NoPrompt command-line argument to:
//   (a) skip the initial confirmation message box;
//   (a) skip the message (if any) saying this update was already applied;
//   (b) skip the completion message.
//

// non-localized strings
CLIENT_KEY = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Class Server\\Client";
UPDATE_VARIANT = "KB883049"; // string used within Variant to identify update
CSSP_VARIANT = "SP"; // prefix for string used within Variant of Class Server

// localized strings
L_TITLE_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049)";
L_ALREADYAPPLIED_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) has already been installed.";
L_BADJSVERSION_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) requires JScript version 5.6 or later.";
L_CONFIRM_TXT = "This critical update for Microsoft Class Server 3.0 - Teacher addresses issues documented in Microsoft Knowledge Base article 883049.\n\nClick OK to install this update."; // OK/Cancel
L_CSNOTINSTALLED_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because Class Server 3.0 - Teacher is not installed on this computer.";
L_CSSP1NOTINSTALLED_TXT = "Service Pack 1 of Class Server 3.0 - Teacher is not installed on this computer.  We recommend upgrading to Service Pack 1 before installing this update.\n\nDo you want to proceed with this update anyway?"; // Yes/No
L_MISSINGFILETOPATCH_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following file(s) are missing:\n\n{0}\nUninstall and reinstall Class Server 3.0 - Teacher, and then reinstall this update.";
L_CANNOTUPDATEREGISTRY_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following registry key cannot be modified:\n\n{0}\n\nYou may not have the necessary permissions to modify this registry key.";
L_CANNOTUPDATEREGISTRY2_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following registry key cannot be modified:\n\n{0}\n\nYou may not have the necessary permissions to modify this registry key. Uninstall and reinstall Class Server 3.0 - Teacher, and then reinstall this update.";
L_CANNOTMODIFYFILES_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following file(s) cannot be modified:\n\n{0}\nYou may not have the necessary permissions to modify these file(s).";
L_CANNOTBACKUPFILES_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following backup file(s) cannot be created:\n\n{0}\nYou may not have the necessary permissions to create these file(s).";
L_CANNOTPATCHFILES_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the following file(s) have been modified:\n\n{0}\nUninstall and reinstall Class Server 3.0 - Teacher, and then reinstall this update.";
L_PATCHFAILED_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) cannot be installed because the update process failed for the following file(s):\n\n{0}\nUninstall and reinstall Class Server 3.0 - Teacher, and then reinstall this update.";
L_DONE_TXT = "Critical Update for Microsoft Class Server 3.0 - Teacher (KB883049) has been installed successfully.";

// make sure this is the correct version of JScript
if (!CheckJScriptVersion(5, 6))
{
	// don't use QuitWithError() -- may not be defined
	WScript.Echo(L_BADJSVERSION_TXT);
	WScript.Quit();
}

// set <g_fNoPrompt> to true if "/NoPrompt" is specified on the command line
g_fNoPrompt = ((WScript.Arguments.Length == 1) &&
	(WScript.Arguments(0) == "/NoPrompt"));

// get helper objects
var fs = WScript.CreateObject("Scripting.FileSystemObject");
var shell = WScript.CreateObject("WScript.Shell");

// get the user's permission to proceed (unless "/NoPrompt" is specified on
// the command line)
if (!g_fNoPrompt)
{
	if (shell.Popup(L_CONFIRM_TXT, 0, L_TITLE_TXT,
			33/*OK, Cancel, question mark icon*/) != 1/*OK*/)
		WScript.Quit();
}

// make sure V3 TC is installed before proceeding; set <g_strInstallPath> to
// the path it's installed in; set <g_strVariant> to the Variant of the TC
// installation (e.g. "RTL", "SP1", "SP1 KB123456", etc.)
try
{
	// set <strVersion> to the version (e.g. "3.0.nnn") of Class Server -
	// Teacher installed on this machine
	var strVersion = shell.RegRead(
		CLIENT_KEY + "\\Registration\\ProductVersion");
	if (strVersion.match(/^3\.0\./) == null)
		throw false;
	g_strInstallPath = shell.RegRead(CLIENT_KEY + "\\InstallPath");
	g_strVariant = shell.RegRead(CLIENT_KEY + "\\Variant");
}
catch (e)
{
	QuitWithError(L_CSNOTINSTALLED_TXT);
}

// set <g_fCSSP1To9Installed> to true if *any* service pack of Class Server is
// installed -- note that we'll assume that all service packs will include
// the functionality of CS SP1; set <g_fCSSP2To9Installed> to true if CS SP2
// through CS SP9 is installed -- note that we'll assume that any future service
// pack (2 through 9) will include the functionality of this patch
g_fCSSP1To9Installed = false;
g_fCSSP2To9Installed = false;
for (var iSP = 1; iSP <= 9; iSP++)
{
	if (VariantContains(CSSP_VARIANT + iSP))
	{
		g_fCSSP1To9Installed = true;
		if (iSP >= 2)
			g_fCSSP2To9Installed = true;
	}
}

// if the user doesn't have SP1 or above of Teacher Client installed, ask if
// they want to continue
if (!g_fCSSP1To9Installed)
{
	if (shell.Popup(L_CSSP1NOTINSTALLED_TXT, 0, L_TITLE_TXT,
			36/*Yes, No, question mark icon*/) != 6/*Yes*/)
		WScript.Quit();
	g_fNoPrompt = false; // turn off "/NoPrompt" mode
}

// if this update was already installed, or if Class Server service pack 2 or
// above is installed (which we assume has the functionality of this update
// included), tell the user and quit (unless "/NoPrompt" was specified on the
// command line, in which case quit silently)
if (VariantContains(UPDATE_VARIANT) || g_fCSSP2To9Installed)
{
	if (g_fNoPrompt)
		WScript.Quit();
	else
		QuitWithError(L_ALREADYAPPLIED_TXT);
}

// check that the user has write access to the registry
var strKey = CLIENT_KEY + "\\Variant";
try
{
	shell.RegWrite(strKey, g_strVariant);
}
catch (e)
{
	QuitWithError(L_CANNOTUPDATEREGISTRY_TXT.replace(/\{0\}/, strKey));
}

// set <g_astrRelPathsToPatch> and <g_astrRelPathsToAdd> to be arrays of
// relative paths of the files to patch and files to add, respectively
InitializePatchData();

// set <g_astrFullPathsToPatch> and <g_astrFullPathsToAdd> to be the full-path
// equivalents of <g_astrRelPathsToPatch> and <g_astrRelPathsToAdd>
g_astrFullPathsToPatch = new Array;
for (var i in g_astrRelPathsToPatch)
{
	g_astrFullPathsToPatch[i] = fs.BuildPath(g_strInstallPath,
		g_astrRelPathsToPatch[i]);
}
g_astrFullPathsToAdd = new Array;
for (var i in g_astrRelPathsToAdd)
{
	g_astrFullPathsToAdd[i] = fs.BuildPath(g_strInstallPath,
		g_astrRelPathsToAdd[i]);
}

// set <g_astrFullPathsToPatchOrAdd> to be the concatenation of
// <g_astrFullPathsToPatch> and <g_astrFullPathsToAdd>
g_astrFullPathsToPatchOrAdd = new Array;
g_astrFullPathsToPatchOrAdd = g_astrFullPathsToPatchOrAdd.concat(
	g_astrFullPathsToPatch, g_astrFullPathsToAdd);

// set <g_aastrReplacements> to be the "before" and "after" replacement strings
// for the files to patch (see GetReplacements() for more information)
g_aastrReplacements = GetReplacements();

// set <g_aMapNewOrPatchedFileToFullPath> maps the base file name (without a
// path) of a new or patched file to its full path
g_aMapNewOrPatchedFileToFullPath = new Array;
for (var i in g_astrFullPathsToPatchOrAdd)
{
	var strFullPath = g_astrFullPathsToPatchOrAdd[i];
	var strFileName = fs.GetFileName(strFullPath);
	g_aMapNewOrPatchedFileToFullPath[strFileName] = strFullPath;
}

// make sure all the files being patched exist on the user's machine
var strErrorFiles = "";
for (var istrFullPathsToPatch in g_astrFullPathsToPatch)
{
	var strFullPath = g_astrFullPathsToPatch[istrFullPathsToPatch]
	if (!fs.FileExists(strFullPath))
		strErrorFiles += strFullPath + "\n";
}
if (strErrorFiles.length > 0)
	QuitWithError(L_MISSINGFILETOPATCH_TXT.replace(/\{0\}/, strErrorFiles));

// make all the files, and their ".backup" versions, be read/write, and make
// sure we can write to these files
var strErrorFiles = "";
for (var istrFullPathsToPatchOrAdd in g_astrFullPathsToPatchOrAdd)
{
	var strFullPath = g_astrFullPathsToPatchOrAdd[istrFullPathsToPatchOrAdd]
	try
	{
		MakeFileReadWrite(strFullPath);
		if (fs.FileExists(strFullPath))
			TestWriteAccess(strFullPath);
	}
	catch (e)
	{
		strErrorFiles += strFullPath + "\n";
	}
	strFullPath += ".backup";
	try
	{
		MakeFileReadWrite(strFullPath);
		if (fs.FileExists(strFullPath))
			TestWriteAccess(strFullPath);
	}
	catch (e)
	{
		strErrorFiles += strFullPath + "\n";
	}
}
if (strErrorFiles.length > 0)
	QuitWithError(L_CANNOTMODIFYFILES_TXT.replace(/\{0\}/, strErrorFiles));

// make backups of all files we're about to patch or add
var strErrorFiles = "";
for (var istrFullPathsToPatchOrAdd in g_astrFullPathsToPatchOrAdd)
{
	var strFullPath = g_astrFullPathsToPatchOrAdd[istrFullPathsToPatchOrAdd]
	var strBackupFullPath = strFullPath + ".backup";
	try
	{
		if (fs.FileExists(strFullPath))
			fs.CopyFile(strFullPath, strBackupFullPath, true);
	}
	catch (e)
	{
		strErrorFiles += strBackupFullPath + "\n";
	}
}
if (strErrorFiles.length > 0)
	QuitWithError(L_CANNOTBACKUPFILES_TXT.replace(/\{0\}/, strErrorFiles));

// execute two passes: in the first pass, check to see that the "before"
// strings for all files being patched already exist; in the second pass,
// make the replacements (or add the files, in the case of new files)
for (var iPass = 1; iPass <= 2; iPass++)
{
	var strErrorFiles = "";
	for (var iastrReplacements in g_aastrReplacements)
	{
		// set <astrReplacement> to be the array within <g_aastrReplacements>
		// that contains information about all the replacements to make within
		// a single file -- see GetReplacements() for more information
		var astrReplacement = g_aastrReplacements[iastrReplacements];

		// set <fNewFile> if this file is a new file, i.e. it doesn't exist
		// before the patch is applied
		var fNewFile = (astrReplacement[1] == "<NEW>");

		// set <strFileName> to the base file name (without a path) of the file
		// to patch; set <strFullPath> to its full path
		var strFileName = astrReplacement[0]; // see GetReplacements()
		var strFullPath = g_aMapNewOrPatchedFileToFullPath[strFileName];

		DebugWrite("** Pass " + iPass + ": " + strFullPath);

		// set <strFileContents> to the new or changed contents of this file
		if (fNewFile)
		{
			// this is a new file that needs to be copied to the user's machine
			var strFileContents = astrReplacement[2];
		}
		else
		{
			// this is an existing file that needs to be patched...

			// load the file into <strFileContents>
			try
			{
				var stream = fs.OpenTextFile(strFullPath);
				var strFileContents = stream.ReadAll();
				stream.Close();
			}
			catch (e)
			{
				// this error is unexpected, since we previously checked to make
				// sure <strFullPath> exists and is writable
				QuitWithError(L_MISSINGFILETOPATCH_TXT.replace(/\{0\}/,
					strFullPath + "\n"));
			}

			// loop once for each replacement to make
			var istrReplacement = 0;
			var fError = false;
			while (!fError)
			{
				// set <strBefore> and <strAfter> to the "before" and "after"
				// strings for this replacement
				var strBefore = astrReplacement[++istrReplacement];
				if (strBefore == null)
					break;
				var strAfter = astrReplacement[++istrReplacement];

				// make <reBefore> be a regular expression corresponding to
				// <strBefore>
				var reBefore = MakeRegularExpression(strBefore);

				// check that the text we're looking for exists in
				// <strFileContents>; if so, make the replacement (which will
				// only get written back to the file if this is pass 2)
				if (!reBefore.test(strFileContents))
				{
					fError = true;
					DebugWrite("** Not found: " + strBefore);
					DebugWrite("** RE: " + reBefore);
				}
				else
				{
					strFileContents = strFileContents.replace(reBefore,
						strAfter);
				}
			}
			if (fError)
				strErrorFiles += strFullPath + "\n";
		}

		// in the second pass, write <strFileContents> back to the file
		if (iPass == 2)
		{
			try
			{
				MakeFileReadWrite(strFullPath);
				var stream = fs.CreateTextFile(strFullPath, true);
				stream.Write(strFileContents);
				stream.Close();
			}
			catch (e)
			{
				strErrorFiles += strFullPath + "\n";
			}
		}
	}
	if (strErrorFiles.length > 0)
	{
		if (iPass == 1)
		{
			// failure during the first pass -- no harm done
			QuitWithError(L_CANNOTPATCHFILES_TXT.replace(/\{0\}/,
				strErrorFiles));
		}
		else
		{
			// failure during the second pass -- the user's machine may have
			// a corrupt installation of TC at this point, so we need to tell
			// them to reinstall TC
			QuitWithError(L_PATCHFAILED_TXT.replace(/\{0\}/,
				strErrorFiles));
		}
	}
}

// update the Variant of the TC installation to reflect the fact that this
// update has been applied
g_strVariant += " " + UPDATE_VARIANT;
var strKey = CLIENT_KEY + "\\Variant";
try
{
	shell.RegWrite(strKey, g_strVariant);
}
catch (e)
{
	// this error shouldn't happen since we tested above to make sure we
	// can access the registry
	QuitWithError(L_CANNOTUPDATEREGISTRY2_TXT.replace(/\{0\}/, strKey));
}

// done -- tell the user (unless "/NoPrompt" was specified on the command line)
if (!g_fNoPrompt)
	shell.Popup(L_DONE_TXT, 0, L_TITLE_TXT);

function QuitWithError(strMessage)
{
	// quit with error message <strMessage>
	shell.Popup(strMessage, 0, L_TITLE_TXT);
	WScript.Quit();
}

function CheckJScriptVersion(iMajorMin, iMinorMin)
{
	// return true if the JScript version is at least <iMajorMin>.<iMinorMin>,
	// false otherwise; note that 5.10 is treated as greater than 5.9
	var iMajor = Number(ScriptEngineMajorVersion());
	var iMinor = Number(ScriptEngineMinorVersion());
	return (iMajor > iMajorMin) ||
		((iMajor == iMajorMin) && (iMinor >= iMinorMin));
}

function MakeRegularExpression(str)
{
	// return a regular expression that matches string <str>
	str = str.replace(/\\/g, "\\\\");
	str = str.replace(/\?/g, "\\?");
	str = str.replace(/\./g, "\\.");
	str = str.replace(/\(/g, "\\(");
	str = str.replace(/\)/g, "\\)");
	str = str.replace(/\*/g, "\\*");
	str = str.replace(/\+/g, "\\+");
	return new RegExp(str, "g");
}

function MakeFileReadWrite(strPath)
{
	// if file <strPath> (a full path to a file) exists, change its attributes
	// if necessary to make them read/write
	if (fs.FileExists(strPath))
	{
		var file = fs.GetFile(strPath);
		var iAttrs = file.Attributes;
		if (iAttrs & 1/*ReadOnly*/)
			file.Attributes = iAttrs & ~1/*ReadOnly*/;
	}
}

function TestWriteAccess(strPath)
{
	// check to see if file <strPath> (a full path to a text file) can be open
	// for writing
	var stream = fs.OpenTextFile(strPath, 8/*ForAppending*/);
	stream.Close();
}

function VariantContains(strWord)
{
	// return true if <g_strVariant> contains <strWord> (as an entire word)
	var re = new RegExp("\\b" + strWord + "\\b");
	return re.test(g_strVariant);
}

function DebugWrite(str)
{
	// output debug information
	//WScript.Echo(str); // comment out this line except when debugging
}

//============================== PATCH DATA ==============================

function InitializePatchData()
{
	// initialize global variables with information about the patch...

	// set <g_astrRelPathsToPatch> to be the relative paths (relative to the
	// installation directory) of the files to patch
	g_astrRelPathsToPatch = new Array(
		"Web\\Client\\Standards\\AsPreview.htm", // setTimeout bug too
		"Web\\Client\\AssignWiz\\Include\\Events.js",
		"Web\\Client\\Dialogs\\Include\\ImportLRM.js", // setTimeout bug too
		"Web\\Client\\TeacherClient\\Include\\Launcher.js",
		"Web\\Client\\LREdit\\Include\\PageViewContainer.js",
		"Web\\Client\\Standards\\Include\\AsInfo.js",
		"Web\\Client\\Dialogs\\IMSPreview.htm",
		// added due to setTimeout bug:
		"Web\\Client\\AssignWiz\\Include\\Main.js",
		"Web\\Client\\Dialogs\\Sharing.htm",
		"Web\\Client\\GradeAssignment\\include\\GradingDialog.js",
		"Web\\Client\\GradeAssignment\\include\\PageView.js",
		"Web\\Client\\GradeAssignment\\ReportWizard.htm",
		"Web\\Client\\LREdit\\include\\LREditDlg.js",
		"Web\\Client\\LREdit\\include\\SlugEdit.js",
		"Web\\Client\\Standards\\AsPrintDialog.htm",
		"Web\\Client\\Sync\\Include\\ClientLogin.js",
		"Web\\Client\\Sync\\Include\\Progress.js",
		"Web\\Client\\Sync\\Include\\Sync.js",
		"Web\\Client\\TeacherClient\\Include\\AsTree.js",
		"Web\\Client\\TeacherClient\\Include\\HomeTask.js",
		"Web\\Client\\TeacherClient\\Include\\TeacherClient.js");

	// set <g_astrRelPathsToAdd> to be the relative paths of the files to add
	// (i.e. files that didn't previously exist)
	g_astrRelPathsToAdd = new Array(
		"Web\\Client\\Standards\\AsContent.htm");
}

// ----- the following function is generated by DiffToJScript.exe -----
// -----       plus manual additions due to setTimeout bug        -----
// ----- ("Repro#N" comments refer to XPSP2_setTimeout_CSV3.xls) -----
function GetReplacements()
{
	// returns an array of elements, one per file to patch;
	// each element is an array with N elements:
	//   -- [0] = base file name of file to patch;
	//   -- [1] = "before" text #1 **;
	//   -- [2] = "after" text #1;
	//   -- [3] = "before" text #2;
	//   -- [4] = "after" text #2;
	//      ...
	//   -- [N*2-1] = "before" text #N;
	//   -- [N*2] = "after" text #N;
	//   -- [N*2+1] = null
	// ** special case: may be "<NEW>" for a new file

	return new Array(

		new Array("AsContent.htm",
			"<NEW>"
			,
			"<html>\r\n"
			+ "<body leftmargin=0 topmargin=0 scroll=no>\r\n"
			+ "<script>\r\n"
			+ "\r\n"
			+ "// set sContentUrl to be the URL of the content to preview (set in AsInfo.js)\r\n"
			+ "sContentUrl = top.g_sPreviewURL;\r\n"
			+ "\r\n"
			+ "// do some minimal HTML-encoding of sContentURL to avoid script insertion bugs\r\n"
			+ "var sContentUrlHtml = sContentUrl.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\");\r\n"
			+ "\r\n"
			+ "// generate an iframe to contain the content to preview\r\n"
			+ "document.write(\"<iframe application=no style=\\\"width: 100%; height: 100%;\\\" frameborder=no src=\\\"\" + sContentUrlHtml + \"\\\"></iframe>\");\r\n"
			+ "\r\n"
			+ "</script>\r\n"
			+ "</body>\r\n"
			+ "</html>\r\n"
			,
			null) // "AsContent.htm"

		,//----------

		new Array("AsInfo.js",
			"\t\tidLRLink.href = sPreviewURL;\r\n"
			,
			"\t{\r\n"
			+ "\t\ttop.g_sPreviewURL = sPreviewURL;\r\n"
			+ "\t\tidLRLink.href = \"AsContent.htm\";\r\n"
			+ "\t}\r\n"
			,
			null) // "AsInfo.js"

		,//----------

		new Array("AsPreview.htm",
			"\tonbeforeunload=\"onBeforeUnload()\">\r\n"
			,
			"\tonload=\"onLoad()\"\r\n"
			+ "\tonbeforeunload=\"onBeforeUnload()\">\r\n"
			,
			"\t<iframe id=idPreviewFrame onload=\"onLoadInfo()\" src=\"AsInfo.htm\" style=\"width:100%; height:100%\" frameBorder=\"yes\" application=no>\r\n"
			,
			"\t<iframe id=idPreviewFrame onload=\"onLoadInfo()\" src=\"AsInfo.htm\" style=\"width:100%; height:100%\" frameBorder=\"yes\" application=yes>\r\n"
			,
			"function onLoadCallback(oArg)\r\n"
			+ "{\r\n"
			+ "\targ = oArg;\r\n"
			,
			"function onLoad()\r\n"
			+ "{\t\r\n"
			+ "\targ = dialogArguments;\r\n"
			,
			"\t\tg_sPreviewURL = \"javascript:top.onServerLogin()\"; // ;\r\n"
			,
			"\t\tvar nDefaultServer = parseInt(arg.oTCStore.SchInfo(arg.oTCStore.CurSchGUID, \"DefaultServer\"));\r\n"
			+ "\t\tvar sServerURL = arg.oTCStore.SchInfo(arg.oTCStore.CurSchGUID, \"Server\" + nDefaultServer);\r\n"
			+ "\t\tg_sPreviewURL = sServerURL + \"/\" + arg.sServerPreviewURL;\r\n"
			,
			"\t// Display button bank as appropriate\r\n"
			+ "\tvar bCrawlMode = arg.oTCStore.ConfigurationNode.GetChild(\"Preferences\").GetAttribute(\"ModeDefault\") == \"2\";\r\n"
			,
			"\t// Set bCrawlMode to true in Basic View\r\n"
			+ "\tvar bCrawlMode = arg.oTCStore.ConfigurationNode.GetChild(\"Preferences\").GetAttribute(\"ModeDefault\") == \"2\";\r\n"
			+ "\r\n"
			+ "\t// If we're in Basic View, bring TC to foreground -- important\r\n"
			+ "\t// for opening LR from curriculum library\r\n"
			+ "\tif (arg.oActivity && arg.fnOpenLRCallback && bCrawlMode)\r\n"
			+ "\t\tdocument.body.activateTCWindow(arg.oTCHelp);\r\n"
			+ "\r\n"
			+ "\t// Restore the dialog position from Config.xml (if saved previously)\r\n"
			+ "\tdocument.body.loadModalDialogPositioned(arg.oTCStore, null, false, false, false);\r\n"
			,
			"\tidAsPropertiesSpan.style.display = (g_sPreviewURL) ? \"inline\" : \"none\";\r\n"
			,
			"\t// Display button bank as appropriate\r\n"
			+ "\tidAsPropertiesSpan.style.display = (g_sPreviewURL) ? \"inline\" : \"none\";\r\n"
			,
			"function onServerLogin()\r\n"
			+ "{\r\n"
			+ "\t// remember in case we need to revisit the URL\r\n"
			+ "\tg_sPreviewURL = document.body.serverLogin(arg.oTCStore, arg.sOnlinePassword, arg.sServerPreviewURL, idPreviewFrame.document);\r\n"
			+ "}\r\n"
			+ "\r\n"
			,
			""
			,
			"function onBeforeUnload()\r\n"
			+ "{\r\n"
			+ "\twindow.close();\r\n"
			+ "}\r\n"
			,
			"function onBeforeUnload()\r\n"
			+ "{\r\n"
			+ "\ttry { document.body.saveModalDialogPositioned(arg.oTCStore); } catch (e) { }\r\n"
			+ "}\r\n"
			,
			"window.setTimeout(close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#1*/
			,
			null) // "AsPreview.htm"

		,//----------

		new Array("Events.js",
			"\tdocument.body.openDialogWindow(\"../Standards/AsPreview.htm?1\", param, 620, 450);\r\n"
			,
			"\tdocument.body.showModalDialogPositioned(g_oTCStore, \"../Standards/AsPreview.htm?1\", param, null);\r\n"
			,
			null) // "Events.js"

		,//----------

		new Array("IMSPreview.htm",
			"<body style=\"margin:0px;\" onkeydown=\"if (document.readyState == 'complete') onKeyDown()\" >\r\n"
			,
			"<body style=\"margin:0px;\" onkeydown=\"if (document.readyState == 'complete') onKeyDown()\" onload=\"onLoad()\" onunload=\"onUnload()\">\r\n"
			,
			"function onLoadCallback(oArg)\r\n"
			,
			"function onLoad()\r\n"
			,
			"\targ = oArg;\r\n"
			+ "\tidPreviewFrame.navigate(oArg.href);\r\n"
			+ "}\r\n"
			+ "\r\n"
			+ "\r\n"
			+ "\r\n"
			+ "function onKeyDown()\r\n"
			,
			"\targ = dialogArguments;\r\n"
			+ "\r\n"
			+ "\t// Restore the dialog position from Config.xml (if saved previously)\r\n"
			+ "\tdocument.body.loadModalDialogPositioned(arg.oTCStore, null, false, false, false);\r\n"
			+ "\r\n"
			+ "\tidPreviewFrame.navigate(arg.href);\r\n"
			+ "}\r\n"
			+ "\r\n"
			+ "function onUnload()\r\n"
			+ "{\r\n"
			+ "\t// Save the dialog position to Config.xml\r\n"
			+ "\ttry { document.body.saveModalDialogPositioned(arg.oTCStore); } catch (e) { }\r\n"
			+ "}\r\n"
			+ "\r\n"
			+ "\r\n"
			+ "function onKeyDown()\r\n"
			,
			null) // "IMSPreview.htm"

		,//----------

		new Array("ImportLRM.js",
			"\tdocument.body.openDialogWindow(\"../Standards/AsPreview.htm?2\", param, 620, 450);\r\n"
			,
			"\tdocument.body.showModalDialogPositioned(arg.oTCStore, \"../Standards/AsPreview.htm?2\", param, null);\r\n"
			,
			"window.setTimeout(idOK.click, 1);"
			,
			"window.setTimeout(\"idOK.click()\", 1);"/*Repro#2*/
			,
			"window.setTimeout(idOK.focus, 1);"
			,
			"window.setTimeout(\"idOK.focus()\", 1);"/*Repro#3*/
			,
			null) // "ImportLRM.js"

		,//----------

		new Array("Launcher.js",
			"\topenDialogWindow(\"../Standards/AsPreview.htm?\" + ((bAsNotLR) ? \"1\" : \"2\"), param, screen.width*2/3, screen.height*2/3);\r\n"
			,
			"\tshowModalDialogPositioned(g_oTCStore, \"../Standards/AsPreview.htm?\" + ((bAsNotLR) ? \"1\" : \"2\"), param, null);\r\n"
			,
			"\tvar param = new Object;\r\n"
			+ "\tparam.sPassword = g_oSync.m_sSyncPassword;\r\n"
			+ "\tparam.oTCStore = oTCStore;\r\n"
			+ "\tparam.fnSetFindWindow = fnSetFindWindow;\r\n"
			+ "\t\r\n"
			+ "\topenDialogWindow(\"../Dialogs/Find.htm\", param, 400, 400);\r\n"
			,
			"\tdocument.body.serverLogin(g_oTCStore, g_oSync.m_sSyncPassword, \"/Find/Home.htm\");\r\n"
			,
			null) // "Launcher.js"

		,//----------

		new Array("PageViewContainer.js",
			"\t\t\t\t\topenDialogWindow(\"../Standards/AsPreview.htm?2\", param, 620, 450);\r\n"
			,
			"\t\t\t\t\tshowModalDialogPositioned(g_oTCStore, \"../Standards/AsPreview.htm?2\", param, null);\r\n"
			,
			"\t\tvar topPos = parseInt(window.external.dialogTop);\r\n"
			+ "\t\tif (topPos < 1) topPos = 1;\r\n"
			+ "\t\tvar leftPos = parseInt(window.external.dialogLeft);\r\n"
			+ "\t\tif (leftPos < 1) leftPos = 1;\r\n"
			+ "\t\t\t\t\r\n"
			+ "\t\topenDialogWindow(\"../Dialogs/IMSPreview.htm\", param, parseInt(window.external.dialogWidth)-5, parseInt(window.external.dialogHeight)-40, topPos, leftPos);\r\n"
			,
			"\t\tdocument.body.showModalDialogPositioned(g_oTCStore, \"../Dialogs/IMSPreview.htm\", param, null);\r\n"
			,
			null) // "PageViewContainer.js"

		,//========== added due to setTimeout bug ==========

		new Array("Main.js",
			"window.setTimeout(window.close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#4*/
			,
			null) // "Main.js",

		,//----------

		new Array("Sharing.htm",
			"window.setTimeout(idShareSchLabel2.click, 1);"
			,
			"window.setTimeout(\"idShareSchLabel2.click()\", 1);"/*Repro#5*/
			,
			"window.setTimeout(idShareNetLabel2.click, 1);"
			,
			"window.setTimeout(\"idShareNetLabel2.click()\", 1);"/*Repro#6*/
			,
			null) // "Sharing.htm",

		,//----------

		new Array("GradingDialog.js",
			"window.setTimeout(idCloseButton.click, 1);"
			,
			"window.setTimeout(\"idCloseButton.click()\", 1);"/*Repro#7*/
			,
			null) // "GradingDialog.js",

		,//----------

		new Array("PageView.js",
			"window.setTimeout(oFocus.focus, 1);"
			,
			"window.setTimeout(\"top.getFocusElement().focus()\", 1);"/*Repro#8*/
			,
			null) // "PageView.js",

		,//----------

		new Array("ReportWizard.htm",
			"window.setTimeout(window.close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#9*/
			,
			null) // "ReportWizard.htm",

		,//----------

		new Array("LREditDlg.js",
			"oDom.parentWindow.setTimeout(oDom.parentWindow.close, 1);"
			,
			"g_oDom = oDom; function CloseDomParent() { g_oDom.parentWindow.close(); } oDom.parentWindow.setTimeout(CloseDomParent, 1);"/*Repro#10*/
			,
			null) // "LREditDlg.js",

		,//----------

		new Array("SlugEdit.js",
			"setTimeout(top.g_oPageViewFrame.oTriedit.DOM.focus, 1);"
			,
			"setTimeout(\"top.g_oPageViewFrame.oTriedit.DOM.focus()\", 1);"/*Repro#11*/
			,
			null) // "SlugEdit.js",

		,//----------

		new Array("AsPrintDialog.htm",
			"window.setTimeout(window.close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#12*/
			,
			null) // "AsPrintDialog.htm",

		,//----------

		new Array("ClientLogin.js",
			"window.setTimeout(idPassword.focus, 1);"
			,
			"window.setTimeout(\"idPassword.focus()\", 1);"/*Repro#13*/
			,
			"window.setTimeout(idOK.click, 1);"
			,
			"window.setTimeout(\"idOK.click()\", 1);"/*Repro#14*/
			,
			null) // "ClientLogin.js",

		,//----------

		new Array("Progress.js",
			"window.setTimeout(window.close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#15*/
			,
			null) // "Progress.js",

		,//----------

		new Array("Sync.js",
			"window.setTimeout(window.close, 1);"
			,
			"window.setTimeout(\"window.close()\", 1);"/*Repro#16*/
			,
			null) // "Sync.js",

		,//----------

		new Array("AsTree.js",
			"window.setTimeout(rowA.click, 1);"
			,
			"window.setTimeout(\"rowA.click()\", 1);"/*Repro#17*/
			,
			"window.setTimeout(rowB.click, 1);"
			,
			"window.setTimeout(\"rowB.click()\", 1);"/*Repro#18*/
			,
			null) // "AsTree.js",

		,//----------

		new Array("HomeTask.js",
			"try { window.setTimeout(tableLayout.focus, 1); }"
			,
			"try { window.setTimeout(\"try { tableLayout.focus() } catch (e) { }\", 1); }"/*Repro#19*/
			,
			null) // "HomeTask.js",

		,//----------

		new Array("TeacherClient.js",
			"window.setTimeout(idHomeViewLayout.focus, 1);"
			,
			"window.setTimeout(\"try { idHomeViewLayout.focus() } catch (e) { }\", 1);"/*Repro#20*/
			,
			null) // 

	);
}
