/*=======================================================================*
*	         Copyright 2002-10 by Virtual Gallerie, LLC.             *
*     This material is the confidential trade secret and proprietary     *
*     information of Virtual Gallerie, LLC. It may not be reproduced,    *
*     used, sold or transferred to any third party without the prior     *
*     written consent of Virtual Gallerie, LLC. All rights reserved.	 *
*=======================================================================*/

var fso = null;
var go_bigFSO = null;

var go_mozFSO = null;

var DIR_SEP = "/";//isRunningLocal() ? "\\" : "/";

var myDir = getFileDocURLBaseIf(false, true); // w/o final slash and html/file
var myDirURL = getFileDocURLBaseIf(false, false); // w/o final slash

try {
	myDir = gs_override_myDir;
}
catch(er) {

}
try {
	myDirURL = gs_override_myDirURL;
}
catch(er) {

}

var fbo = null;
var fbt_NONE = 0;
var fbt_SAVEAS = 1;
var fbt_SEL_FLDR = 2;
var fbt_SEL_FILE = 3;
var fbt_SEL_FILES = 4;


var snaggitObj = null;
var fileFieldEnterFunc = "";

var cr = String.fromCharCode(13, 10);

var gi_maxFldrDisplayChars = 24; // per line...

var gb_LockingEnabled = false;
var gs_attrib_FILE_PATH = "filePath";
var gs_attrib_FILE_PATH_INTERNAL = "filePathI";
var gs_lastErr = null;
var go_lastErr = null;
var gs_tmp_dir = myDir;

var fio_ALLOW_NAV_TYPE_None = 0,
	fio_ALLOW_NAV_TYPE_Any = 1,
	fio_ALLOW_NAV_TYPE_Pos = 2;

var fio_FOLDER_SORT_TYPE_None = 0,
	fio_FOLDER_SORT_TYPE_NameA = 1,
	fio_FOLDER_SORT_TYPE_NameD = 2,
	fio_FOLDER_SORT_TYPE_DateA = 3,
	fio_FOLDER_SORT_TYPE_DateD = 4;

var fio_INITIAL_SORT_TYPE = fio_FOLDER_SORT_TYPE_NameA;

var gs_sortAscending = " >",
	gs_sortDescending = " <";

var gi_fileLenMult = 10;

var gb_webFileBrowsing = false;

var gs_openerURL = null;

var gs_filePrefix = "file:///"
var gi_filePrefixLen = gs_filePrefix.length;

var ga_iconPaths = null;
var gs_filesDivName = "filesDiv";


if (opener) {
	try {
		gs_openerURL = opener.location.toString();
	}
	catch (er) {

	}

}

var gb_weveGotWeb = false;
var gs_urlPrefix = "file:///";
var gb_https = false;

if (!gb_weveGotWeb) {
	var doc_loc_str = document.location.toString();

	if (doc_loc_str.indexOf("http") == 0) {
		gb_weveGotWeb = true;
		if (doc_loc_str.indexOf("https") == -1) {
			gs_urlPrefix = "http://";
		} else {
			gs_urlPrefix = "https://";
			gb_https = true;
		}
	}
}

//override to init the fbo w/ appropriate stuff
function initFBOCheck() {

}

function initFileKeys() {
	fso.o_file_keys = {s : "", b_any : false, cs : null, a : null, tod : 250, tos : "doSelFileKeyCheck()"};

	fso.setFileKeysVal = function (o, s) {
		var i;
		if (!(o.b_any = ((o.s = s) != ""))) {
			o.cs = null;
			o.a = null;
		} else if ((i = o.s.indexOf("*")) == -1) {
			o.cs = s;
			o.a = null;
		} else if (i == (o.s.length - 1)) {
			o.cs = o.s.substring(0, o.s.length - 1); //last char, so same as if no * at all,
			//unless it's the only char, which would be "", which would be everything :)
			o.a = null;
		} else {//at least 1, and if only 1, it's not the last char
			o.cs = null;
			o.a = o.s.split("*");
		}
		o.ls = o.cs;
	}
	fso.fileKeysFromPram = function(o_file_keys0) {
		return o_file_keys0 ? o_file_keys0 : this.o_file_keys;
	}
	fso.anyFileKeys = function(o_file_keys0) {
		return this.fileKeysFromPram(o_file_keys0).b_any;
	}
	fso.getFileKeyValIfOrDflt = function(o_file_keys0, dflt) {
		if (!o_file_keys0) o_file_keys0 = this.o_file_keys;
		return o_file_keys0.b_any ? o_file_keys0.s : dflt;
	}
	fso.goodFileKeys = function (name, o_file_keys) {
		var i, ii, li, ni, s;

		if (!o_file_keys) o_file_keys = this.o_file_keys;

		if (!o_file_keys.b_any) return true;
		else if (!o_file_keys.a) {
			return name.toLowerCase().indexOf(o_file_keys.cs) == 0;
		} else {
			var c = 0;
			i = 0;
			name = name.toLowerCase();
			if ((s = o_file_keys.a[0]) != "") {
				if (name.indexOf(s) != 0) return false;
				else {
					c = 1;
					i = s.length;
				}
			}
			for (c = c; c < o_file_keys.a.length; c++) { //would b an array
				if ((i = name.indexOf(s = o_file_keys.a[c], i)) > -1) {
					i += s.length;
				} else {
					return false;
				}
			}
			return true;
		}
	}
}

function fsoInitted() {
	var the_fso;

	if (fso) return true;
	else if (hasGoodOpener()) {
		try {
			fso = opener.fso;
		}
		catch(er) {}
		if (fso) return true;
	}

	if (ismoz()) {
		fso = initMozFSO();//go_mozFSO;
		if (!fso) alert(getNoActiveXObjAlert("Couldn't access the local file system."));
	} else {
		try {
			go_bigFSO = new ActiveXObject("Scripting.FileSystemObject");
		}
		catch (er) {
			alert(getNoActiveXObjAlert("Couldn't access the local file system. The browser said '" + er.message + "'."));
			go_bigFSO = null;
		}
		the_fso = go_bigFSO;
	}
	//initFBOCheck();

	if (the_fso || fso) {
		function initCommonFSO() {
			fso.b_local = isRunningLocal(); //doesn't it have to be?
			fso.b_mac = gb_mac;

			fso.addFileErr = function(err, src_path0, dst_path0) {
				if (!this.a_err) this.a_err = new Array();
				apush(this.a_err, {err : err, sp : src_path0, dp : dst_path0});
				return err;
			};
			fso.clearFileErr = function() { this.a_err = null };

			fso.getFilesListStr = function(a, sep0) {
				var s = "";
				var sep = sep0 ? sep0 : ", ";

				if (a && a.length) {
					if (a.length == 1) {
						s = "The file '" + a[0] + "'";
					} else {
						s = "The files '" + a[0] + "'";

						for (var i = 1; i < a.length; i++) {
							s += sep + "'" + a[i] + "'";
						}
					}
				}
				return s;
			}
			fso.getErrFilesListStr = function (b_dst, sep0) { //todo: look for only one type of error as a potential? ie, copy error but not dne....
				var s = "";
				var sep = sep0 ? sep0 : ", ";
				var a;
				if ((a == this.a_err) && a.length) {
					if (a.length == 1) {
						s = "The file '" + (b_dst ? a[0].dp : a[0].sp) + "'";
					} else {
						s = "The files '" + (b_dst ? a[0].dp : a[0].sp) + "'";

						for (var i = 1; i < a.length; i++) {
							s += sep + "'" + (b_dst ? a[i].dp : a[i].sp) + "'";
						}
					}
				}
				return s;
			}
			initFileKeys();
			fso.getFolderO = function(path) {
				var f = this.GetFolder(path);
				return f ? {fldr : f, path : path} : null;
			};

		}

		if (gb_IE) {
			fso = {fso : the_fso, b_moz : false};
			initCommonFSO();

			fso.FixPath = function(path) {
				if (this.b_local) {
					if (!this.b_mac) return GetReplaced(path, DIR_SEP, "\\");
					else {
						var np = GetReplaced(path, "\\", DIR_SEP);


						np = (np.charAt(0) != DIR_SEP)
							? DIR_SEP + np
							: np;

						return np;
					}
				} else {
					return path;
				}
			}
			fso.FolderExists = function(path) { return this.fso.FolderExists(path);};
			fso.FileExists = function(path) { return this.fso.FileExists(path);};
			fso.GetFolder = function(path) { return this.fso.GetFolder(path);};
			fso.GetFile = function(path) {return this.fso.GetFile(path);};
			fso.GetFileIf = function(path) {return this.fso.FileExists(path) ? this.fso.GetFile(path) : null; };
			fso.GetFolderIf = function(path) {return this.FolderExists(path) ? this.GetFolder(path) : null; };

			fso.CreateFolder = function(path) {return this.fso.CreateFolder(path);};
			fso.CreateTextFile = function(path, b_overwrite, b_ascii) //(unicode = false)
				{ return this.fso.CreateTextFile(path, b_overwrite, b_ascii);};
			fso.OpenTextFile = function(path, flag) {return this.fso.OpenTextFile(path, flag);};

			fso.GetExtensionName = function(file_obj) {return this.fso.GetExtensionName(file_obj).toLowerCase();};
			fso.CopyFile = function(src_path, dst_path) {return this.fso.CopyFile(src_path, dst_path);};

			fso.GetName = function (fo) { return fo.Name; };
			fso.GetModDate = function(fo) {
				if ((typeof(fo) == "string") && ((fo = this.GetFileIf(fo)) == null)) return 0;
				return fo.DateLastModified;
			};
			fso.GetFolderPath = function(fo) { return fo.Path;};

			fso.GetParentFolderO = function(f) {
				if (f.ParentFolder) {
					return {fldr : f.ParentFolder, path : f.ParentFolder.Path};
				}
				return null;
			}
			fso.IsFolderNonEmpty = function(f) {
				return f && (f.Files || f.SubFolders);
			}
			fso.GetFilesInFolderArray = function (o_fldr, as_file_types, show_folders_type, o_file_keys) { //sft: 0 none, 1 all, 2 non-empty


				var one_f;


				var a_files = new Array(), a_dirs = null;
				var num_files = 0;
				var b_all_folders = (show_folders_type == 1);


				var fldr = o_fldr.fldr;
				var eFolder = (fldr.Files) ? new Enumerator(fldr.Files) : null;
				var eSub = (show_folders_type && fldr.SubFolders) ? new Enumerator(fldr.SubFolders) : null;

				if (eSub) {
					while (!eSub.atEnd()) {
						var f = eSub.item();

						if ((b_all_folders || this.IsFolderNonEmpty(f)) && this.goodFileKeys(this.GetName(f), o_file_keys)) {
							if (!a_dirs) a_dirs = new Array();
							apush(a_dirs, new Array(this.GetName(f))); //todo: some flag for if there are sub folders as well?
						}

						eSub.moveNext();

					}
				}

				if (eFolder) {

					if (as_file_types || this.anyFileKeys(o_file_keys)) { // more efficient to only check each file if it matters
						while (!eFolder.atEnd()) {
							one_f = eFolder.item();

							if (isFileOfProperExtension(one_f, as_file_types) && this.goodFileKeys(this.GetName(one_f), o_file_keys)) {
								a_files[num_files++] = new Array(one_f.Name, new Date(one_f.DateLastModified));
							}
							eFolder.moveNext();
						}
					} else {
						while (!eFolder.atEnd()) {
							one_f = eFolder.item();
							a_files[num_files++] = new Array(one_f.Name, new Date(one_f.DateLastModified), fi);
							eFolder.moveNext();
						}

					}
				}

				if (num_files == 0) a_files = null;

				return {a_files : a_files, num_files : num_files, a_dirs : a_dirs, num_dirs : (a_dirs ? a_dirs.length : 0)}
			};
			fso.GetFolderWithFileArray = function (o_fldr, file_name, show_folders_type, hiders, o_file_keys) { //sft: 0 none, 1 all, 2 non-empty

				var one_f;


				var a_files = new Array(), a_dirs = null;
				var num_files = 0;
				var b_all_folders = (show_folders_type == 1);


				var fldr = o_fldr.fldr;
				var eFolder = (fldr.Files) ? new Enumerator(fldr.Files) : null;
				var eSub = fldr.SubFolders ? new Enumerator(fldr.SubFolders) : null;
				var one_file;
				//debugger;
				if (eSub) {
					while (!eSub.atEnd()) {
						one_f = eSub.item();

						if ((!hiders || !hiderMatch(hiders, one_f.Name)) && this.goodFileKeys(one_f.Name, o_file_keys)) {
							if (one_file = fso.GetFileIf(one_f.Path + "\\" + file_name)) {
								a_files[num_files++] = new Array(one_f.Name, new Date(one_file.DateLastModified));
							} else {
								switch(show_folders_type) {
								case 2:
									if (!this.IsFolderNonEmpty(one_f)) {
										break;
									} //else ift
								case 1:
									if (!a_dirs) a_dirs = new Array();
									apush(a_dirs, new Array(this.GetName(one_f)));
									break;
								}
							}
						}

						eSub.moveNext();

					}
				}


				if (num_files == 0) a_files = null;

				return {a_files : a_files, num_files : num_files, a_dirs : a_dirs, num_dirs : (a_dirs ? a_dirs.length : 0)}
			};

		} else {
			fso.b_moz = true;
			initCommonFSO();
			//fso.fso_temp = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

			fso.FixPath = function(path) {
				if (this.b_local) {
					if (!this.b_mac) return GetReplaced(path, DIR_SEP, "\\");
					else {
						var np = GetReplaced(path, "\\", DIR_SEP);


						np = (np.charAt(0) != DIR_SEP)
							? DIR_SEP + np
							: np;

						return np;
					}
				} else {
					return path;
				}
				//return this.b_local
				//? (!this.b_mac ? GetReplaced(path, DIR_SEP, "\\") : GetReplaced(path, "\\", DIR_SEP))
				//: path;};
						//todo: try/catch stuff here? in case illegal paths et alia?
			}
			fso.CopyFile = function(src_path, dst_path) {
				var fo = this.GetFile(src_path);
				if (fo) this.CopyFileO(fo, dst_path);
			};
			fso.InitWithPath = function(fo, p) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				fo.initWithPath(this.FixPath(p));
			};
			fso.CopyFileO = function(fo, dst_path) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				this.InitWithPath(this.fso_temp, dst_path);
				if (this.fso_temp.exists()) this.fso_temp.remove( false );
				fo.copyTo(this.fso_temp.parent, "");
			};
			fso.CreateFolder = function(path) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				this.InitWithPath(this.fso_temp, path);
				if (this.fso_temp.exists()) return this.fso_temp;
				try {
					this.fso_temp.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
					return this.fso_temp;
				}
				catch(er) {
					return null;
				}
			}

			fso.objType_FLDR = 1;
			fso.objType_FILE = 2;

			fso.ObjectExists = function(path) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				this.InitWithPath(this.fso_temp, path);
				return this.fso_temp.exists() ? (this.fso_temp.isDirectory() ? this.objType_FLDR : this.objType_FILE) : 0;
			}
			//the caller can check to see if it exists and is the wrong type... though shoudn't be possible if the paths are valid
			fso.FolderExists = function(path) {
				return this.ObjectExists(path);
			};
			fso.FileExists = function(path) {
				return this.ObjectExists(path);
			};

			fso.GetObject = function(path, b_fldr) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var o = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
				this.InitWithPath(o, path);
				return (o.exists() && (b_fldr == o.isDirectory())) ? o : null;
			};
			fso.GetFolder = function(path) {
				return this.GetObject(path, true);
			};

			fso.GetFile = function(path) {
				return this.GetObject(path, false);
			};

			fso.GetFileIf = fso.GetFile;
			fso.GetFolderIf = fso.GetFolder;
			fso.GetFolderPath = function(fo) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				return fo.path;
			};
			fso.GetParentFolderO = function(f) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				if (f.parent) {
					return {fldr : f.parent, path : f.parent.path};
				}
				return null;
			};
			fso.IsFolderNonEmpty = function(f) {
				if (!f) return false;
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var de = f.directoryEntries;

				return de.hasMoreElements() ? true : false;
			}
			fso.GetFilesInFolderArray = function (o_fldr, as_file_types, show_folders_type, o_file_keys) { //sft: 0 none, 1 all, 2 non-empty


				var one_f;


				var a_files = new Array(), a_dirs = null, fn;
				var num_files = 0;
				var b_all_folders = (show_folders_type == 1);


				var fldr = o_fldr.fldr;
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var de = fldr.directoryEntries;
				while (de.hasMoreElements()) {
					one_f = de.getNext().QueryInterface(Components.interfaces.nsILocalFile);
					fn = this.GetName(one_f);
					if (this.goodFileKeys(fn, o_file_keys)) {
						if (!this.b_mac || (fn.charAt(0) != ".")) { //ignore "." which should be hidden
							try {
								if (one_f.isDirectory()) {
									switch(show_folders_type) {
									case 2:
										if (!this.IsFolderNonEmpty(one_f)) {
											break;
										} //else ift
									case 1:
										if (!a_dirs) a_dirs = new Array();
										apush(a_dirs, new Array(fn));
										break;
									}

								} else if (one_f.isFile()) { //is there any other possiblity? bbbb
									//3.26.09 removed , fi) from the new Array, b/c wasn't in ie one, and was messing up the dims (which assume _W will be there!
									if (as_file_types) {
										if (isFileOfProperExtension(one_f, as_file_types)) {
											a_files[num_files++] = new Array(fn, new Date(one_f.lastModifiedTime));
										}
									} else {
										a_files[num_files++] = new Array(fn, new Date(one_f.lastModifiedTime));
									}
								}
							}
							catch (er) {
								//can fail on mac for aliases
							}
						}
					}
				}
				if (num_files == 0) a_files = null;

				return {a_files : a_files, num_files : num_files, a_dirs : a_dirs, num_dirs : (a_dirs ? a_dirs.length : 0)}

			}
			fso.GetNamedFileInFolder = function (fn, f) { //todo: can we look for the name directly? ... fldr path + fn?
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var de = f.directoryEntries, one_f;
				while (de.hasMoreElements()) {
					one_f = de.getNext().QueryInterface(Components.interfaces.nsILocalFile);
					if (one_f.isFile() && (one_f.leafName == fn)) {
						return one_f;
					}
				}
				return null;
			}
			fso.GetFolderWithFileArray = function (o_fldr, file_name, show_folders_type, hiders, o_file_keys) { //sft: 0 none, 1 all, 2 non-empty


				var one_f, one_file;


				var a_files = new Array(), a_dirs = null;
				var num_files = 0;
				var b_all_folders = (show_folders_type == 1);


				var fldr = o_fldr.fldr;
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var de = fldr.directoryEntries;
				while (de.hasMoreElements()) {
					one_f = de.getNext().QueryInterface(Components.interfaces.nsILocalFile);
					if (one_f.isDirectory() && (!hiders || !hiderMatch(hiders, one_f.leafName)) && this.goodFileKeys(one_f.leafName, o_file_keys)) {
						if (one_file = this.GetNamedFileInFolder(file_name, one_f)) {
							a_files[num_files++] = new Array(one_f.leafName, new Date(one_file.lastModifiedTime));
						} else {
							switch(show_folders_type) {
							case 2:
								if (!this.IsFolderNonEmpty(one_f)) {
									break;
								} //else ift
							case 1:
								if (!a_dirs) a_dirs = new Array();
								apush(a_dirs, new Array(this.GetName(one_f)));
								break;
							}
						}

					}
				}
				if (num_files == 0) a_files = null;

				return {a_files : a_files, num_files : num_files, a_dirs : a_dirs, num_dirs : (a_dirs ? a_dirs.length : 0)}

			}

			fso.GetExtensionName = function(f) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				var i = f.leafName.lastIndexOf('.');

				return (i > -1) ? f.leafName.substring(i + 1).toLowerCase() : "";
			};
			fso.GetName = function(f) {
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				return f.leafName;
			};
			fso.GetModDate = function(f) {
				if ((typeof(f) == "string") && ((f = this.GetFileIf(f)) == null)) return 0;
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				return f.lastModifiedTime;
			};
			fso.FilePathIsWritable = function(path) {
				var fo = fso.GetFile(path);
				netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
				return (fo && fo.isWritable());

			};
		}
	}
	return fso != null;
}

function snaggitInitted() {
	if (snaggitObj) return true;
	try {
		snaggitObj = new ActiveXObject("SnagIt.ImageCapture");
	}
	catch (er) {
		alert(getNoActiveXObjAlert("Couldn't start the SnagIt object."));
		snaggitObj = null;
	}
	return snaggitObj != null;

	//objSnagIt.Capture
}

function getNoActiveXObjAlert(ss) {
	var b_show_ff = false;
	var os = BrowserDetect.OS, brz = BrowserDetect.browser;
	var ns = "";

	if (os == "Windows") {
		if (brz == "Explorer") {
			ns = "Did you say 'No' to the ActiveX dialog?"
				+ " If you said 'Yes' to the dialog, then you may have anti-virus software that prevents this action!"
				+ " You'll have to relaunch the gallery and say 'Yes' to the ActiveX dialog to enable this action."
				+ " You may want to try running VG in Firefox instead.";
		} else if (brz == "Firefox") {
			ns = "Did you say 'Deny' to the Internet Security dialog?"
				+ " If you said 'Allow' to the dialog, then you may have anti-virus software that prevents this action!"
				+ " You'll have to relaunch the gallery and say 'Allow' to the Internet Security dialog to enable this action."
				+ " You may want to try running VG in Internet Explorer instead.";
		} else {
			ns = "You can only access the local file system in Windows when running VG in Firefox or Internet Explorer.";
		}
	} else if (os == "Mac") {
		if (brz == "Firefox") {
			ns = "Did you say 'Deny' to the Internet Security dialog?"
				+ " If you said 'Allow' to the dialog, then you may have anti-virus software that prevents this action!"
				+ " You'll have to relaunch the gallery and say 'Allow' to the Internet Security dialog to enable this action."
		} else {
			ns = "You can only access the local file system on the Mac when running VG in Firefox.";
		}
	} else {
		ns = "You can only access the local file system when running VG in Firefox on Windows or Mac, or Internet Explorer on Windows.";
	}

	return ss + cr + ns;

}

function createFldrIfDNE(fpath, levels_to_create) {
	if (fsoInitted()) {
		if (fso.FolderExists(fpath)) return true;
		var b_e = false;
		try {
			fso.CreateFolder(fpath);
		}
		catch(e) {
			//if (e.number == -2146828212)
			//if (e.description == "Path not found")
			b_e = true;
		}

		if (b_e) {
			if (fso.b_moz) return false; //moz would already create the other parts if successful
			else if (levels_to_create) {
				var up_one = getPathUp(fpath, 1);
				if (!fso.FolderExists(up_one)) {
					var up_two = getPathUp(up_one, 1);

					if (fso.FolderExists(up_two)) {
						fso.CreateFolder(up_one);
						return createFldrIfDNE(fpath, 0);
					}
				}

			}
			//alert("The folder '" + fldr_path + "' could not be accessed.");
			//return false;
		} else {
			return true;
		}
	}
	return false;
}


/*7.5.9 ... moved this stuff to layers.js
function GetReplacedFSS(src, search_str, repl_str) { //assume whacky regexp chars... so just manually do it...


	var i, ss = "";
	var sl = search_str.length;

	while ((i = src.indexOf(search_str)) > -1) {
		ss += src.substring(0, i) + repl_str;
		src = src.substring(i + sl);
	}
	ss += src;
	return ss;


}
//check to see if the version of JavaScript/JScript supports the "g" in RegExp
var gb_goodRegExp = ("abb".replace(RegExp("b", "g"),"a") == "aaa");
//change the one in xml.js if changing this
function GetReplaced(src, search_str, repl_str) {
	if (gb_goodRegExp) {
	//todo: always just do the GetReplacedFSS?
	if (search_str == "\\") {
		return src.replace(new RegExp("\\\\", "g"), repl_str);
	} else if (search_str.indexOf("\\") != -1) {


		var i = 0;

		while ((i = search_str.indexOf("\\", i)) > -1) {
			search_str = search_str.substring(0, i) + "\\" + search_str.substring(i);
			i += 2;
		}
	}
	if ((search_str.indexOf(")") != -1) || (search_str.indexOf("(") != -1)) {//this would create an invalid RegExp, or one that was an erroneous flag
		var i = 0;

		while ((i = search_str.indexOf("(", i)) > -1) {
			search_str = search_str.substring(0, i) + "\\" + search_str.substring(i);
			i += 2;
		}
		i = 0;
		while ((i = search_str.indexOf(")", i)) > -1) {
			search_str = search_str.substring(0, i) + "\\" + search_str.substring(i);
			i += 2;
		}
	}

	return src.replace(RegExp(search_str, "g"),repl_str);
	} else if ((src != "") && (src.indexOf(search_str) != -1)) {
		return GetReplacedFSS(src, search_str, repl_str);
		var c1 = src;
		var lps = "xxoo--ooxx";

		do {
			if (c1 == (src = src.replace(search_str, lps))) break;
			else c1 = src;
		} while (1);

		do {
			if (c1 == (src = src.replace(lps, repl_str))) break;
			else c1 = src;
		} while (1);


	}
return src;
}
*/
function hasGoodOpener() {
	if (opener && !opener.closed) {
		if (!gs_openerURL) return true;
		else {
			try {
				var url = opener.location.toString();

				return url == gs_openerURL; //different page now...
			}
			catch (er) {
				//can't get to the url, most likely no permission, which means it's a different one
			}
		}
	}
	return false;
}

function getEndOfPath(path) {
	path = replaceToDirSep(path);
	var i = path.lastIndexOf(DIR_SEP);

	if (i != -1) {
		if (i == (path.length - 1)) return "";
		else return path.substr(i + 1);
	} else {
		return path;
	}
}

function getPathWithoutEnd(path) {
	path = replaceToDirSep(path);
	var i = path.lastIndexOf(DIR_SEP);

	if (i != -1) {
		return path.substring(0, i); //will return w/o the slash...
	} else {
		return ""; //it's all the end...
	}
}

function getFileDocURLBaseIf(b_include_last_slash, b_pull_file) {
	var url = getLocStr();//window.document.URL;
	var qi;
	url = replaceToDirSep(url);

	if ((qi = url.indexOf("?")) > -1) {
		url = url.substring(0, qi);
	}

	var start_i = 0;

	if (b_pull_file) {
		var pi = url.indexOf(":" + DIR_SEP + DIR_SEP + DIR_SEP);
		if (pi > -1) start_i = pi + (!gb_mac ? 4 : 4); //always pulling it all off now!
		else if ((pi = url.indexOf(":" + DIR_SEP + DIR_SEP)) > -1) {
			start_i = pi + (!gb_mac ? 3 : 3);
		}
	}

	var end_i = url.lastIndexOf(DIR_SEP);

	if (b_include_last_slash) end_i++;

	return url.substring(start_i, end_i);
}


function getLocStr() {
	return window.location.toString();
}
function getQuerylessLocStr() {
	var loc = getLocStr();
	var vni = loc.indexOf("?");
	if (vni > -1) {
		return loc.substring(0, vni);
	}
	return loc;
}

function getQueryArray(loc_str) {
	var loc = loc_str ? loc_str : getLocStr();
	var vni = loc.indexOf("?");
	if (vni > -1) {
		var qs = unescape(loc.substring(vni + 1));
		var qa = new Array();
		var ei, i;

		var qaa = qs.split("&");

		for (i = 0; i < qaa.length; i++) {
			ei = qaa[i].indexOf("=");
			qa[i] = new Object();
			qa[i].n = qaa[i].substring(0, ei).toLowerCase();
			//qa[i].v = unescape(qaa[i].substring(ei + 1));
			qa[i].v = qaa[i].substring(ei + 1);
		}


		//for(i = 0; i < qa.length; i++) {
		//	alert(qa[i].n + ":" + qa[i].v);
		//}
		return qa;

	}
	return null;
}

function getQueryValFromQA(qa, qvn) {
	if (qa) {
		var i;
		qvn = qvn.toLowerCase();
		for (i = 0; i < qa.length; i++) {
			if (qa[i].n == qvn) return qa[i].v;
		}
	}
	return null;
}

function getQueryValFromQA_INT(qa, qvn) {
	var qv;
	if (qv = getQueryValFromQA(qa, qvn)) {
		return new Number(qv);
	}
	return null;
}

function getQueryValFromQA_PATH(qa, qvn) {
	var qv;
	if (qv = getQueryValFromQA(qa, qvn)) {
		return unescape(qv);
	}
	return null;
}

//note, if os ends in \ or /, it will be ignored in the count (ie, levels_up will be ++'d
function getPathUp(os, levels_up) {

	var i;
	var slashi, slashi2;
	var s = os;

	if (lastCharMatch2(os, "\\", "/")) levels_up++;

	for(i = 0; i < levels_up; i++) {
		slashi = s.lastIndexOf("\\");
		if ((slashi2 = s.lastIndexOf("/")) > slashi)
			slashi = slashi2;


		if (slashi == -1) break;
		else s = s.substring(0, slashi);
	}
	return s;
}

function getDisplayPathForCmdVGRoot(file_path, cmd, b_file) {

	return b_file ? removeEndSlashIfOne(file_path) : addEndSlashIfNone(file_path);
}

function getFileFromPath(file_path) {
	return fso.FileExists(file_path) ? fso.GetFile(file_path) : null;
}
//this is just one file path
function getFilesObjForFilePath(file_path, as_file_types) {
	var files;
	if (fsoInitted()) {
		var f, f_a, f_t, f_f;

		function getSubTypeFromMainName(fn) {
			if (strEnds(fn, gs_subFileTypePostfix_THUMB)) return "t";
			else if (strEnds(fn, gs_subFileTypePostfix_ALPHA)) return "a";
			return "m";
		}

		//assumes t != nt
		function doFileNameFromConvertedFilePath(fp, t, nt) {

			var nfp, f = null;
			switch(t) {
			default:
				nfp = fileNameWithNoExtension(fp);
				break;
			case "a":
				nfp = fp.substring(0, fp.length - gi_subFileTypePostfixLen_ALPHA);
				break;
			case "t":
				nfp = fp.substring(0, fp.length - gi_subFileTypePostfixLen_THUMB);
				break;
			}

			switch(nt) {
			default:
				if (f = getFileFromPath(nfp + ".jpg")) {
					f_f = fso.GetName(f);
				} else if (f = getFileFromPath(nfp + ".pwc")) {
					f_f = fso.GetName(f);
				}
				break;
			case "a":
				if (f = getFileFromPath(nfp + gs_subFileTypePostfix_ALPHA)) {
					f_a = fso.GetName(f);
				}
				break;
			case "t":
				if (f = getFileFromPath(nfp + gs_subFileTypePostfix_THUMB)) {
					f_t = fso.GetName(f);
				}
				break;
			}
			return f != null;
		}

		if ((f = getFileFromPath(file_path)) && (!as_file_types || (isFileOfProperExtension(f, as_file_types)))) {
			var fn = fso.GetName(f);
			var st = getSubTypeFromMainName(fn);
			var nfn;

			files = getNewFilesObj(fso.GetParentFolderO(f).path); //this has the fldr and its path

			switch(st) {
			default:
				f_f = fn;
				doFileNameFromConvertedFilePath(file_path, st, "a");
				doFileNameFromConvertedFilePath(file_path, st, "t");
				break;
			case "a":
				if (doFileNameFromConvertedFilePath(file_path, st, "m")) {
					doFileNameFromConvertedFilePath(file_path, st, "t");
					f_a = fn;
				}
				break;
			case "t":
				if (doFileNameFromConvertedFilePath(file_path, st, "m")) {
					doFileNameFromConvertedFilePath(file_path, st, "a");
					f_t = fn;
				}
				break;
			}

			if (f_f) {
				files.num_files = 1;
				files.a_files[0] = new Array();
				files.a_files[0][VG_FILE_ARRAY_INDEX_Type] = 1;
				files.a_files[0][VG_FILE_ARRAY_INDEX_Name] = f_f;
				if (f_a) files.a_files[0][VG_FILE_ARRAY_INDEX_Alpha] = f_a;
				if (f_t) files.a_files[0][VG_FILE_ARRAY_INDEX_Thumb] = f_t;

				return files;
			}
		}
	}
	return null;
}
function getFilesInFolderContainingFilePath(file_path, as_file_types, sort_type, o_file_keys) { // we don't actually sort now
	if (fsoInitted()) {
		var f;

		if (f = getFileFromPath(file_path)) {
			return getFilesInFolderObj(fso.GetParentFolderO(f), as_file_types, sort_type, o_file_keys);
		}
	}
	return "";
}
/* unused
function getFilesInFolderPath(fldr_path, as_file_types, sort_type) {
	if (fsoInitted()) {
		var fldr = fso.FolderExists(fldr_path) ? fso.GetFolder(fldr_path) : null;

		if (fldr) {
			return getFilesInFolderObj(fldr, as_file_types, sort_type);
		}
	}
	return "";
}
*/

// will fail if the file has both no-extension, and a dot, ie, my.file.wooha would return my.file
//can also be used on a path
function fileNameWithNoExtension(full_name) {
	var li = full_name.lastIndexOf(".");

	return (li > 0) ? full_name.substring(0, li) : full_name;
}
//likewise, will be incorrect if no ext, or, as above, if file has no ext and dot
function fileExtensionFromName(full_name) {
	var li = full_name.lastIndexOf(".");

	return (li > 0) ? full_name.substring(li + 1).toLowerCase() : "";
}

function fileNameFromFullPath(full_path, b_pull_off_ext) {
	var fn = getEndOfPath(full_path);

	return b_pull_off_ext ? fileNameWithNoExtension(fn) : fn;
}

function isFileOrHTTP(s) {
	return ((s.indexOf("http://") == 0) || (s.indexOf("https://") == 0) || (s.indexOf("file:") == 0));
}

function pullOffFileOrHTTP(s) {
	var i;
	if ( ((i = s.indexOf("://")) == 4) || (i == 5)) {
		if (s.indexOf(":///") == i) return s.substring(i + 4);
		return s.substring(i + 3);
	}
	return s;
}

function pullOffFile(s) { //note: should be file:/// (gs_filePrefix))
	if (s.indexOf("file:///") == 0) return s.substring(8);
	else if (s.indexOf("file://") == 0) return s.substring(7);
	else return s;
}

function addFileIfAbsLocFile(p) {//todo: mac? //?
	if (gb_mac) {
		var i = p.indexOf("private/");
		if ((i == 0) || (i == 1) || ((i = p.indexOf("volumes/")) == 0) || (i == 1)) {
			return gs_filePrefix + p.substring(8 + i);
		} else if ((i = p.indexOf("Users/")) == 0) {
			return gs_filePrefix + p;
		} else if (i == 1) {
			return gs_filePrefix + p.substring(1);
		} else if (p.indexOf("/") == 0) {
			return gs_filePrefix + p.substring(1);
		}
	} else if ((p.indexOf(":\\") == 1) || (p.indexOf(":/") == 1)) {
		return gs_filePrefix + p;
	}
	return p;
}

function convertAbsToGoodLocalIfNotWebPath(p, b_no_file) {///todomac
	if (gb_IE) return (b_no_file) ? pullOffFile(p) : addFileIfAbsLocFile(p);
	if (p.indexOf("http") == 0) return replaceToDirSep(p);

	//else if (!gb_mac) p = GetReplaced(p, "/", "\\");
	//else p = replaceToDirSep(p);
	p = replaceToDirSep(p);
	if (!b_no_file) {
		if (p.indexOf("file:") == 0) return p;
		else if (gb_mac && p.charAt(0) == DIR_SEP) p = p.substring(1);

		return gs_filePrefix + p;
	} else {
		if (p.indexOf(gs_filePrefix) == 0) p = p.substr(gi_filePrefixLen);
		if (gb_mac && (p.charAt(0) != DIR_SEP)) return DIR_SEP + p;
		else return p;
	}
}

function getPreviousCharMatch(s, si, mc) {
	for (var i = si; i > 0; i--) {
		if (s.charAt(i) == mc) {
			return i;
		}
	}
	return -1;
}

function getAbsPathFromRelPath(os_rp) {
	var ap;
	var i, bi = fi = lev = ni = ofi = 0;
	var b_mid = false;
	var ss = ".." + DIR_SEP;
	var s = "";

	while ((i = os_rp.indexOf(ss, fi)) != -1) {
		if (i == ni) {
			fi = i + 1;
			lev++;
			ni += 3;
			if (b_mid) b_mid = false; //because we popped all the way to the previous ..// and have more levels to go
		} else { //it's (also) in the middle... need to do a paired compress, ie, for each .., go back one...
			//until we get to the previous ../, or run out of ../ in the mid
			var pdi = getPreviousCharMatch(os_rp, i - 2, DIR_SEP);
			if (!b_mid) {
				b_mid = true;
				ofi = fi;
			}
			if (pdi > -1) {
				os_rp = os_rp.substring(0, pdi + 1) + os_rp.substring(i + 3);
			}
			fi = pdi;
		}
	}

	if (!lev) s = (os_rp.charAt(0) == DIR_SEP) ? myDir + os_rp : myDir + DIR_SEP + os_rp;
	else {
		if (b_mid) fi = ofi;

		fi += ss.length - 1;
		bi = myDir.length;
		for (i = lev; i > 0; i--) {
			bi = myDir.lastIndexOf(DIR_SEP, bi - 1);
		}

		s = myDir.substring(0, bi) + os_rp.substring(fi - 1);
	}
	return s;
}

function getAbsPathFromPath(p) {
	return isFileOrHTTP(p) ? p : getAbsPathFromRelPath(p);
}

function getAbsURLFromPath(p, b_escape_filename) {

	if (!b_escape_filename) {
		return isFileOrHTTP(p) ? p : addURLPrefixIfNecessary(getAbsPathFromRelPath(p));
	} else {
		p = isFileOrHTTP(p) ? p : addURLPrefixIfNecessary(getAbsPathFromRelPath(p));
		var fn = fileNameFromFullPath(p), efn = escape(fn);
		return (fn == efn)
			? p
			: p.substring(0, p.length - fn.length) + efn;

	}
}

function isPathAbs(p) {
	return isFileOrHTTP(p) || (p.charAt(1) == ":") || (p.indexOf("//") == 0);
}
//todo: this will only work on mac for file browse field paths...
function getRawAbsPathFromAnyPath(p) {
	if (isFileOrHTTP(p)) return p;//return pullOffFileOrHTTP(p);
	else if (gb_mac) {//todo: why file:// for some and not others?
		var i = p.indexOf("private/");
		if ((i == 0) || (i == 1) || ((i = p.indexOf("volumes/")) == 0) || (i == 1)) return gs_filePrefix + p.substring(i + 7);
        	else if (p.indexOf("/") == 0) return p;
		else if (p.indexOf("Users") == 0) return DIR_SEP + p;
	} else {
		if (p.charAt(1) == ":") return p;
	}
	return getAbsPathFromRelPath(p);
}

function cleanOutBackPaths(os_rp, b_force_fwd_slash) {
	var i, bi, ni;

	if (b_force_fwd_slash) os_rp = replaceToDirSep(os_rp);

	while ((i = os_rp.indexOf("..")) > -1) {
		if (i) {
			if (os_rp.charAt(i - 1) == "/") {
				if ((bi = os_rp.lastIndexOf("/", i - 2)) > -1) {
					if ((ni = os_rp.indexOf("/", i)) > -1) {
						os_rp = os_rp.substring(0, bi) + os_rp.substring(ni);
					}
				}
			}
		} else { // first char of all is ..
			break;
		}
	}
	return os_rp;
}

function standardizePathForCompare(p) {
	var p = addEndSlashIfNone(replaceToDirSep(p));
	if (!gb_mac) return p;
	var i;
	if (((i = p.indexOf("volumes/")) == 0) || (i == 1) || ((i = p.indexOf("private/")) == 0) || (i == 1)) return p.substring(i + 7)
	else if (p.indexOf("://") > -1) return p;
	else return (p.charAt(0) == DIR_SEP) ? p : DIR_SEP + p;

}

function isPath1BelowOrSameAsPath2_Loc(p1, p2) {
	if (!gb_mac) return isPath1BelowOrSameAsPath2(p1, p2);
	else {
		function pullOffPrivvy(p) {
			if (p.indexOf("volumes/") == 0) return p.substring(8);
			else if (p.indexOf("private/") == 0) return p.substring(8);
			else return p;
		}
		p1 = pullOffPrivvy(pullOffFileOrHTTP(p1));
		p2 = pullOffPrivvy(pullOffFileOrHTTP(p2));
		return isPath1BelowOrSameAsPath2(p1, p2);
	}
}
function isPath1BelowOrSameAsPath2(p1, p2) {
	var os = pullOffFileOrHTTP(p1);
	var dp = pullOffFileOrHTTP(p2);

	return (os.indexOf(dp) == 0);
}

function getPath1RelPath2IfBelowElseAbs(p1, p2, b_fix) {
	if (b_fix) {
		p1 = replaceToDirSep(p1);
		p2 = replaceToDirSep(p2);
	}
	if (isPath1BelowOrSameAsPath2(p1, p2)) {
		return p1.substring(p2.length);
	} else {
		return p1;
	}
}

//is a path below a 2nd path, or, if not, is it below a third path below which is 2, else abs...
//assumes 2 is indeed below 3, so don't call this!
function getPath1RelPath2IfBelowItOrParent3ElseAbs(p1, p2, p3, b_fix, b_file) {
	if (b_fix) {
		p1 = replaceToDirSep(p1);
		p2 = replaceToDirSep(p2);
	}
	if (isPath1BelowOrSameAsPath2(p1, p2)) {
		return p1.substring(p2.length);
	} else {
		if (b_fix) p3 = replaceToDirSep(p3);
		if (isPath1BelowOrSameAsPath2(p1, p3)) {
			if (b_file) {
				var o_ff = getBrokenApartFileAndFolderPaths(p1);
				return getFldrPath1RelToFldrPath(o_ff.fldr, p2).ps + o_ff.file;
			} else {
				return getFldrPath1RelToFldrPath(p1, p2).ps;
			}
		}
	}
	return p1;
}

function getFilePathRelToFldrPath(file_path, fldr_path, b_ret_obj) {
	file_path = addFileIfAbsLocFile(file_path);
	fldr_path = addFileIfAbsLocFile(fldr_path);

	var fldr = getPathWithoutEnd(file_path);
	var fo = getFldrPath1RelToFldrPath(fldr, fldr_path);

	fo.ps += file_path.substring(fldr.length + 1); //doesn't add DIR_SEP

	return b_ret_obj ? fo : fo.ps;
}

//note: may return path that starts w/ "/"
function getFldrPath1RelToFldrPath(os_p1, os_p2) {
	//note: if they're the same dir, will wind up doing "../<dir name>" ... which is harmless, but "" didn't work down the line...
	// ie, if p1 = file://c:/hooha/moolah/
	// and p2 = file://c:/hooha/foo/bar/
	// would be ../../moolah
	// first thing is to go from start towards end until there's no match
	var i_p1, i_p2, len_p1, len_p2;

	os_p1 = standardizePathForCompare(os_p1);
	os_p2 = standardizePathForCompare(os_p2);

	var p1 = os_p1.toLowerCase();
	var p2 = os_p2.toLowerCase();

	var fss = "\\"; // is it always? only if local!
	fss = "/";
	var fsi_s1, fsi_s2, fsi_e1, fsi_e2, e1, e2, i1, i2;

	var s, end_part;
	var back_part = "";

	var path_obj = new Object();

	var part_of_i = p1.indexOf(p2);

	var b_done = false;

	path_obj.b_abs = false;
	path_obj.ps = "";

	fsi_e1 = -1;
	fsi_e2 = -1;

	if (!gb_mac && (p1.charAt(0) != p2.charAt(0))) {
		path_obj.b_abs = true;
		path_obj.ps = os_p1; // if the drive letters don't match, return the whole string!
	} else if (gb_mac && (((i1 = p1.indexOf(DIR_SEP, 1)) != (i2 = p2.indexOf(DIR_SEP, 1))) ||
			(p1.substring(1, i1).toLowerCase() != p2.substring(1, i2).toLowerCase()))) {
		path_obj.b_abs = true;
		path_obj.ps = os_p1;
	} else if (part_of_i == 0) {
		if (p1 != p2) { // they're not (lowerCase) equal
			path_obj.ps = os_p1.substring(os_p2.length); //return based on original capitalization
		}
	} else if ((part_of_i = p2.indexOf(p1)) == 0) { // path 2 is actually in path 1
		// so it's only .....
		var si = p1.length;

		while ((si = p2.indexOf("/", si)) > -1) {
			path_obj.ps += (path_obj.ps == "") ? ".." : "/..";
			si++;
		}


	} else {
		while ( ((fsi_s1 = p1.indexOf(fss, fsi_e1)) > -1)
			&& ((fsi_s2 = p2.indexOf(fss, fsi_e2)) > -1)) {

			e1 = p1.indexOf(fss, fsi_s1 + 1);
			e2 = p2.indexOf(fss, fsi_s2 + 1);

			if ((e1 != e2) || (p1.substring(fsi_s1, e1) != p2.substring(fsi_s2, e2)) ) {
				break;
			} else if (e1 != -1) {
				fsi_e1 = fsi_e2 = e1;
			} else { // the folders are in the same directory

				path_obj.ps = "../" + os_p1.substring(fsi_s1 + 1); //since sfi_s1 is the "/"

				b_done = true;
				break;
			}

		}

		if (!b_done) {
			if ((fsi_e1 == -1) && (fsi_e2 == -1)) {
				if (fsi_s1 > -1) {
					if (p1.charAt(fsi_s1 - 1) == ':') {
						end_part = os_p1.substring(fsi_s1 + 1);
						// entirely different path, so return the whole thing, since we want to include the drive letter
						path_obj.b_abs = true;
						path_obj.ps = os_p1;
						b_done = true;
					}
				}


			} else if (fsi_s1 == -1) {
				// =>
				if ((fsi_s2 = p2.indexOf(fss, fsi_e2 + 1)) == -1) { // wouldnt have been set above, since fsi_s1 == -1 would have break'd
					//they both came to the end... but they may not be the same directory!
					// this may actually never happen, since it would have returned above, i think.
					if (p1.substring(fsi_e1) != p2.substring(fsi_e1)) { //diffrnt
						path_obj.ps = "../" + os_p1.substring(fsi_e1);
					}
					b_done = true;
				} else if (p1.substring(fsi_e1) == p2.substring(fsi_e1, fsi_s2 - 1)) {
					//os_p2 is actually a subdirectory of os_p1!
					end_part = ""; // just calc the .. things
				} else {
					end_part = os_p1.substring(fsi_e1 + 1);
					back_part += "../";// since we're one directory up for the fsi
				}
			} else if (fsi_s2 == -1) { // os_p1 is a subdirectory of os_p2
				if (p2.substring(fsi_e2) == p1.substring(fsi_e1, fsi_s1)) {
					path_obj.ps = os_p1.substring(fsi_s1 + 1);
				} else {
					path_obj.ps = "../" + os_p1.substring(fsi_e1 + 1);
				}
				b_done = true;

			} else {
				end_part = "../" + os_p1.substring(fsi_e1 + 1);
			}
			if (!b_done) {
				fsi_s2 = fsi_e2;


				while (((fsi_s2 = p2.indexOf(fss, fsi_s2 + 1)) > -1) && (fsi_s2 != (p2.length - 1))) {
					back_part += "../";
				}

				path_obj.ps = back_part + end_part;
			}
		}

	}
	if (!path_obj.b_abs && (path_obj.ps != "")) {
		path_obj.ps = addEndSlashIfNone(path_obj.ps);
		if (path_obj.ps.charAt(0) == DIR_SEP) path_obj.ps = path_obj.ps.substring(1);
	}
	//path will always end in DIR_SEP, and will never start w/ it (unless abs and MAC!)... and all slashes will be /
	return path_obj;

}

function getRelBacks(num) {
	var s = "";
	for (var i = 0; i < num; i++) {
		s += ".." + DIR_SEP;
	}
	return s;
}

function getFolderNameFromFolderPath(fp) {
	if (!fp || (fp == "")) return null;

	var fp = removeEndSlashIfOne(replaceToDirSep(fp));

	var si = fp.lastIndexOf("/");

	if (si > -1) {
		return fp.substring(si + 1);
	} else if ((si = fp.indexOf(":")) > -1) {
		return fp.substring(si + 1);
	} else {
		return fp;
	}

}

function getNewFilesObj(folder_path_0) {
	var files = new Object();
	files.a_files = new Array();
	files.path = folder_path_0 ? replaceToDirSep(folder_path_0) : "";
	files.num_files = 0;

	return files;
}

function isFileOfProperExtension(one_f, fta, fe) { // this never needs the fe
	var i;
	var s_file_type;

	s_file_type = fso.GetExtensionName(one_f);
	if (fta.x) {
		for (i = 0; i < fta.x.length; i++) {
			if (s_file_type == fta.x[i]) {
				return true;
			}
		}
	} else {
		for (i = 0; i < fta.length; i++) {
			if (s_file_type == fta[i]) {
				return true;
			}
		}
	}
	return false;
}

function getFileExtensionIndex(one_f, fta, fe) {
	var i;
	var s_file_type;

	s_file_type = fso.GetExtensionName(one_f);
	for (i = 0; i < fta.length; i++) {
		if (s_file_type == fta[i]) {
			if (fe) {
				return (fso.GetName(one_f).toLowerCase().indexOf(fe) > -1) ? i : -1; //todo: or should we check that it's the end?
			} else {
				return i;
			}
		}
	}
	return -1;
}
//xxtodo
var gs_subFileTypePostfix_THUMB = "_THUMB.jpg", gs_subFileTypePostfix_ALPHA = "_ALPHA.jpg",
	gi_subFileTypePostfixLen_THUMB = gs_subFileTypePostfix_THUMB.length,
	gi_subFileTypePostfixLen_ALPHA = gs_subFileTypePostfix_ALPHA.length;

var VG_FILE_ARRAY_INDEX_Type = 0,
VG_FILE_ARRAY_INDEX_Name = 1,
VG_FILE_ARRAY_INDEX_Date = 2,
VG_FILE_ARRAY_INDEX_W = 3,
VG_FILE_ARRAY_INDEX_H = 4,
	VG_FILE_ARRAY_INDEX_Thumb = 5,
	VG_FILE_ARRAY_INDEX_Alpha = 6,
	VG_FILE_ARRAY_INDEX_Alpha_W = 7,
	VG_FILE_ARRAY_INDEX_Alpha_H = 8,
	VG_FILE_ARRAY_INDEX_Checked = 9;

var VG_FILE_ARRAY_INDEX_Lock = 4; //for galleries.... check the number if non web implement!

//note: the result here is that you CAN'T have an actual work that hast _THUMB.jpg or _ALPHA.jpg at the end..
//we've reserved these for this specific function....
function getFilesInFolderObj(o_fldr, as_file_types, sort_type, o_file_keys) { // we don't do any sort but name


	//var
	var o_af = o_fldr;

	var o_af;


	var files = getNewFilesObj(o_fldr.path);

	if (!o_fldr.a) {
		o_af = getFilesInFolder_AS_ARRAY_OBJ(o_fldr, as_file_types, 0, o_file_keys);
	} else {
		//o_af = new Object();
		//o_af.
		//return {a_files : a_files, num_files : num_files, a_dirs : a_dirs, num_dirs : (a_dirs ? a_dirs.length : 0)}
		files.a_files = o_fldr.a;
		files.num_files = o_fldr.a.length;
		o_fldr.a;
		return files;
	}

	var num_files = 0, num_alpha = 0, num_thumbs = 0;
	var one_f;
	var b_sort_descending = false;
	var a_thumbs = null, a_alphas = null;

	function addFileToProperArray(fa) {
		if (strEnds(fn = fa[0], gs_subFileTypePostfix_THUMB)) {
			if (!a_thumbs) a_thumbs = new Array();
			a_thumbs[fn] = true;
		} else if (strEnds(fn, gs_subFileTypePostfix_ALPHA)) {
			if (!a_alphas) a_alphas = new Array();
			a_alphas[fn] = true;
		} else {
			//todo: not like this!
			var a = new Array(1, 0); //0 is just b/c array(1) makes an array w/ length 1 :|

			for (var i = 0; i < fa.length; i++) {
				a[i + 1] = fa[i];
			}
			files.a_files[num_files++] = a;
		}
	}
	if (!sort_type || (sort_type <= fio_FOLDER_SORT_TYPE_NameD)) {
		var i;
		for (i = 0; i < o_af.num_files; i++) {
			addFileToProperArray(o_af.a_files[i]);
		}

		if (sort_type == fio_FOLDER_SORT_TYPE_NameD) b_sort_descending = true;
	} else {
		switch(sort_type) {

		}

	}

	if (b_sort_descending) files.a_files.reverse();

	files.num_files = num_files;

	if (a_thumbs || a_alphas) {
		var i, i_nf = files.a_files.length;
		function checkMainFile(atype) {
			var ffn;
			//note: on success, we set the index of the item the same as in files..
			//todo: just create an object for the file?
			if (atype == "a") { //alpha ...main file can only be jpg
				if (a_alphas[ffn = (fileNameWithNoExtension(files.a_files[i][VG_FILE_ARRAY_INDEX_Name]) + gs_subFileTypePostfix_ALPHA)]) {
					files.a_files[i][VG_FILE_ARRAY_INDEX_Alpha] = ffn;
				}
			} else if (a_thumbs[ffn = (fileNameWithNoExtension(files.a_files[i][VG_FILE_ARRAY_INDEX_Name]) + gs_subFileTypePostfix_THUMB)]) {
				files.a_files[i][VG_FILE_ARRAY_INDEX_Thumb] = ffn;
			}
		}
		if (a_thumbs) {
			if (a_alphas) {
				for (i = 0; i < i_nf; i++) {
					checkMainFile("a");
					checkMainFile("t");
				}
			} else {
				for (i = 0; i < i_nf; i++) {
					checkMainFile("t");
				}
			}
		} else { //alphas only
			for (i = 0; i < i_nf; i++) {
				checkMainFile("a");
			}
		}
	}

	return files;
}

var gs_fileIconAlignStr = gb_IE ? " align=center" : "";

function initFBO(fldr_icon_path, up_icon_path, form_name, in_fld_name, in_fld_w) {
	if (!fbo) fbo = new Object();

	fbo.fldr_icn = fldr_icon_path;
	fbo.up_icn = up_icon_path;
	fbo.type = fbt_NONE;
	fbo.cmd = null;
	fbo.start_path = "";
	fbo.crnt_path = "";
	fbo.ifn = in_fld_name;
	fbo.ifw = in_fld_w;
	fbo.crnt_file_name = "";
	fbo.form_name = form_name;
	fbo.b_ff = false;
	fbo.efta = new Object();
	fbo.efta.x = new Array();
	fbo.efta.x[0] = null;
	fbo.efta.fe = null;
	fbo.fn_nox = "";
	fbo.show_new = false;
	fbo.locker = null;
	fbo.locker_path = null;
	fbo.b_sort_name_d = false; // ascending
	fbo.b_sort_date_d = true; //descending
	fbo.b_moz = ismoz();
	fbo.o_fldr = new Object();
	fbo.a_drives = null;
	fbo.b_drives = false;

	fbo.SetFolder = function(fldr) {
		fbo.o_fldr.fldr = fldr;
		if (fbo.b_moz) {
			netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
			fbo.o_fldr.path = fldr.path + "";
		} else {
			fbo.o_fldr.path = fldr.path;
		}
	};

	fbo.GetFolderHTML = function(fa, b_no_nav) { //todo: have no onclick for b_no_nav... currently we just do it in the browseClick_FLDR function
		var n = fa[0];//fso.GetName(fa);


		return '<a onclick="browseClick_FLDR(' + "'" + n + "'); return false;" + '">'
			+ '<img' + gs_fileIconAlignStr + ' src="' + this.fldr_icn + '"/>'
			+ nbs + n + "</a>";
	};

	setFilesSortingType(fio_INITIAL_SORT_TYPE);
}

function setFilesSortingType(st) {
	//below is since wierd switch error later if we use the actual st passed in :|
	if (st == fio_FOLDER_SORT_TYPE_NameA) st = fio_FOLDER_SORT_TYPE_NameA;
	else if (st == fio_FOLDER_SORT_TYPE_NameD) st = fio_FOLDER_SORT_TYPE_NameD;
	else if (st == fio_FOLDER_SORT_TYPE_DateA) st = fio_FOLDER_SORT_TYPE_DateA;
	else if (st == fio_FOLDER_SORT_TYPE_DateD) st = fio_FOLDER_SORT_TYPE_DateD;
	else st = fio_FOLDER_SORT_TYPE_None;

	if (!fbo) fio_INITIAL_SORT_TYPE = st;
	else {
		fbo.sort_type = st;
		switch(st) { //we only do the ones we know about...
		case fio_FOLDER_SORT_TYPE_NameA:
			fbo.b_sort_name_d = false;
			break
		case fio_FOLDER_SORT_TYPE_NameD:
			fbo.b_sort_name_d = true;
			break;
		case fio_FOLDER_SORT_TYPE_DateA:
			fbo.b_sort_date_d = false;
			break;
		case fio_FOLDER_SORT_TYPE_DateD:
			fbo.b_sort_date_d = true;
			break;
		}
	}
}

var gs_sortAscending = " >",
	gs_sortDescending = " <",
	gs_sortBlank = "";

function initSortIconsFromPaths(pa, pd, pn) {
	gs_sortAscending = nbs + "<img src='" + pa + "'/>";
	gs_sortDescending = nbs + "<img src='" + pd + "'/>";
	gs_sortBlank = nbs + "<img src='" + pn + "'/>";
}


//override, most likely
function startFileBrowse(fbt, cmd, label, start_path, start_file0, nav_type, nav_start_lvl, b_show_new, as_file_types, hiders, file_icn_if_ff) {
	startFileBrowse_PRIV(fbt, cmd, label, start_path, start_file0, nav_type, nav_start_lvl, b_show_new, as_file_types, hiders, file_icn_if_ff);
}

function getFixedAbsLocPath(p) {
	p = replaceToDirSep(p);
	if (!fso.b_mac) return p;
	return (p.charAt(0) != "/") ? ("/" + p) : p;
}

function startFileBrowse_PRIV(fbt, cmd, label, start_path, start_file0,
		nav_type, nav_start_lvl,
		b_show_new, as_file_types, hiders, file_icn_if_ff) {

	if (!fsoInitted()) return fbo.type = fbt_NONE;
	switch(fbo.type = fbt) {
	case fbt_SAVEAS:
	case fbt_SEL_FLDR:
	case fbt_SEL_FILE:
	default:
		break;
	}

	start_path = unescape(start_path);

	if (!start_path || (start_path == "")) fbo.start_path = fbo.crnt_path;
	else {
		fbo.start_path = fbo.crnt_path = fso.FixPath(start_path);
	}


	fbo.nav_type = nav_type;
	fbo.show_new = b_show_new;
	fbo.label = label;
	fbo.hiders = hiders;
	fbo.crnt_file_name = start_file0 ? start_file0 : "";
	fbo.b_image_browse = false;


	if (fbo.crnt_path) {
		if (nav_type == fio_ALLOW_NAV_TYPE_Pos) {
			fbo.max_nav_up_path = getPathUp(start_path, nav_start_lvl);
			if (fso.b_local) {
				fbo.max_nav_up_path = getFixedAbsLocPath(fbo.max_nav_up_path);
			}
			fbo.max_nav_up_path_lc = fbo.max_nav_up_path.toLowerCase();
		} else {
			fbo.max_nav_up_path = null;
		}

		if (fso.FolderExists(fbo.crnt_path)) {
			fbo.SetFolder(fso.GetFolder(fbo.crnt_path));
		} else {
			fbo.o_fldr.fldr = null;
		}
		//fbo.fldr = fso.FolderExists(fbo.crnt_path) ? fso.GetFolder(fbo.crnt_path) : null;

		if (fbo.o_fldr.fldr) {
			if (file_icn_if_ff) {
				fbo.ff_fn = as_file_types;
				fbo.ff_fi = file_icn_if_ff;
				fbo.ft = fbo.efta;
				fbo.b_ff = true;
			} else {
				fbo.ft = as_file_types;
				fbo.b_ff = false;
			}
			drawCurrentBrowseDirectory();
			fbo.cmd = cmd;
			return fbo.type;
		} else {
			alert("Can't find the folder: " + fbo.crnt_path);
		}

	}
	return fbo.type = fbt_NONE;

}
//override!
function redrawLoaderForImages() {
}

//return 0 if paths the same, >1 if the p is a child of the max, and -1 if the p is NOT a child (error?)
function compMaxPath(p) {
	p = replaceToDirSep(p).toLowerCase();
	if (p == fbo.max_nav_up_path_lc) return 0;
	else if (p.indexOf(fbo.max_nav_up_path_lc) > -1) return 1;
	return -1;
}

function drawCurrentBrowseDirectory() {

	var nav_type;

	if ((nav_type = fbo.nav_type) == fio_ALLOW_NAV_TYPE_Pos) {
		var ci;
		//if (fbo.max_nav_up_path != replaceToDirSep(fbo.o_fldr.path)) {
		if ((ci = compMaxPath(fbo.o_fldr.path)) > 0) {
			nav_type = fio_ALLOW_NAV_TYPE_Any;
		} else if (ci < 0) {// illegal!
			Debugger();
		}
	}
	if (fbo.b_image_browse) {
		redrawLoaderForImages();
	} else if (fbo.b_drives) {
		drawNewBrowseDirectory(getDrives_AS_HTML(fbo.type, fbo.label, nav_type, fbo.show_new, fbo.sort_type, fso.o_file_keys));
	} else if (!fbo.b_ff) {
		drawNewBrowseDirectory(getFilesInFolder_AS_HTML(fbo.type, fbo.o_fldr, fbo.ft, fbo.label, fbo.hiders, nav_type, fbo.show_new, fbo.sort_type, fso.o_file_keys));
	} else {
		drawNewBrowseDirectory(getFolderWithFilesInFolder_AS_HTML(fbo.type, fbo.o_fldr, fbo.ff_fn, fbo.ff_fi, fbo.label, fbo.hiders, nav_type, fbo.show_new, fbo.sort_type, fso.o_file_keys));
	}
}


function drawNewBrowseDirectory(the_html) {
	//draw the html of the phylez in yer paige!
}

function browsingDone(b_redraw, msg0) {
	var old_type = fbo.type;

	msg0 = (msg0) ? msg0 : "";

	if (b_redraw) drawNewBrowseDirectory(msg0);
	fbo.type = fbt_NONE;
	browsingDoneCallback(old_type);
}

//override...
function browsingDoneCallback(old_type) {
	//
}

function browsingDoneIfAny() {
	if (fbo && (fbo.type != fbt_NONE)) {
		browsingDone(true);
	}
}

function clearBCTO() {
	if (fbo.to) {
		clearTimeout(fbo.to);
		fbo.to = null;
	}
	clearSelFileKey();
}

function browseNavToFldrOneDown(fn, b_check_file_name) {
	var i;
	if (!b_check_file_name || ((i = fn.indexOf("..")) == -1)) {
		if (fso.FolderExists(fbo.o_fldr.path + "\\" + fn)) { // should allus exist, eh?
			fbo.SetFolder(fso.GetFolder(fbo.o_fldr.path + "\\" + fn));
			drawCurrentBrowseDirectory();
			return true;
		} else if (fbo.b_drives && fso.FolderExists(fn + "\\")) {
			fbo.SetFolder(fso.GetFolder(fn + "\\"));
			fbo.b_drives = false;
			drawCurrentBrowseDirectory();
			return true;
		}
	} else { //user manually entered, so we need to check for .. etc ..todo: do we ever get this now?
		var fldr = null;
		try {
			if (fso.FolderExists(fbo.o_fldr.path + "\\" + fn)) {
				fldr = fso.GetFolder(fbo.o_fldr.path + "\\" + fn);
			}
		}
		catch(er) {
			return false;
		}
		//xxtodo: fix fldr GetOFolder ?
		if (fldr) { //only if it exists at all do we deal
			var fp;
			if (fbo.nav_type == fio_ALLOW_NAV_TYPE_Any) { //we assume that we don't even have this function called if fio_ALLOW_NAV_TYPE_None
				fbo.SetFolder(fldr);
				drawCurrentBrowseDirectory();
				return true;
			} else {

				//need permissions thing here!

				//if (replaceToDirSep(fldr.path).indexOf(fbo.max_nav_up_path) == 0) {
				if (compMaxPath(fldr.path) > -1) {
					fbo.SetFolder(fldr);
					drawCurrentBrowseDirectory();
				} else { // do we draw the root? or do nothing?... for now, the root
					fbo.SetFolder(fso.GetFolder(fbo.max_nav_up_path)); //+ DIR_SEP?
					drawCurrentBrowseDirectory();
				}
				return true;
			}
		}
	}
	return false;
}

function browseClick_FLDR(fn) {
	if (fbo.nav_type == fio_ALLOW_NAV_TYPE_None) return;
	clearBCTO();
	browseNavToFldrOneDown(fn, false);


}
function browseClick_FILE(fn) {
	if (fbo.type == fbt_SEL_FILE) {

		fbo.fn = fn;

		clearBCTO();
		fbo.to = setTimeout("bcdcc()", 150);
	} else { //save_as
		fbo.fn = fn;
		bcdcc();
	}
}
//override this!
function browserFileOpened(file_path, cmd, a_fileinfo0) {
	alert(file_path);
}

function browserFileSavedAs(file_path, cmd, b_not_from_browse) {

}

// for any kind
function browseFilesCancelled(cmd, msg0) {

}

function browseFilesCancel(msg0) {
	clearBCTO();
	browseFilesCancelled(fbo.cmd, msg0);
	fbo.type = fbt_NONE;
}

function bcdcc() {
	setNamedFormFldVal(fbo.form_name, fbo.ifn, fbo.fn);

	//document[fbo.form_name].[fbo.ifn].value = fbo.fn;
}

function doesFileNameEndInDirSep(s) {
	switch(s.charAt(s.length - 1)) {
	case "\\": case "/":
		return true;
	}
	return false;
}
function browseFileSelected_PRIV() {

	var fn = getNamedFormFldVal(fbo.form_name, fbo.ifn);

	clearBCTO();

	if (fn && (fn != "")) {
		if (!doesFileNameEndInDirSep(fn)) {
			var fp = fbo.o_fldr.path + "\\" + giveFileProperExtension(fn, fbo.ft.x[0]);
			if (fso.FileExists(fp)) {
				fbo.fp = fp;
				fbo.fn_nox = fn;
				fbo.crnt_path = fbo.o_fldr.path;
				browserFileOpened(fbo.fp, fbo.cmd);
				fbo.type = fbt_NONE;
			} else {
				showFileOpenError(fbo.o_fldr.path, fn, fbo.ft.x[0]);
			}
		} else if (fbo.nav_type == fio_ALLOW_NAV_TYPE_None) {
			showAlertRefocus("You can not browse to another folder.");
		} else if (browseNavToFldrOneDown(fn, true)) {

		} else {
			showAlertRefocus("The folder '" + fn + "' can not be found.");
		}
	}
}

function getFileOpenError_PRIV(main_folder, fn, e, err_str0) {
	var err_str = err_str0 ? err_str0 + gs_finalErrPunct : "can not be found. Please select another.";

	return "The File: '" + addEndSlashIfNone(main_folder) + giveFileProperExtension(fn, e) + "' " + err_str;
}

function showFileOpenError(main_folder, fn, e, err_str0) {
	showAlertRefocus(getFileOpenError(main_folder, fn, e, err_str0));
}
function getFileOpenError(main_folder, fn, e, err_str0) {
	return getFileOpenError_PRIV(main_folder, fn, e, err_str0);
}

function emptyLocker() {
	if (fbo.locker) {
		fbo.locker.close();
		fbo.locker = null;
		fbo.locker_path = null;
	}
}

function isThisPathLockerPath(pth) {
	return !fbo.locker_path ? false
		: GetReplaced(fbo.locker_path, "/", "\\") == GetReplaced(pth, "/", "\\");
}
///// REVISIT FOR MOZ IF ENABLING //////
function readAndCloseFile(pth) {
	if (!fsoInitted()) return {err : -1, s : ""};
	else if (!fso.FileExists(pth)) {
			return {err : 2, s : ""};
	}
	if (fso.b_moz) return readFileMoz(pth);

	var reto = new Object();
	var f = null, ts = null;
	reto.err = 0;
	reto.s = "";


	try {
		f = fso.GetFile(pth);
	}
	catch(e) {
		reto.err = e;
		return reto;
	}


	try {
		ts = f.OpenAsTextStream(1, 0); //1 read 2 write 8 append
	}

	catch(e) {
		reto.err = e;
		return reto;
	}

	reto.s = ts.ReadAll();
	ts.Close();

	return reto;

}

function loadLockerForFolder(fldr_path) {

	if (!gb_LockingEnabled) return true;

	var pth  = fldr_path +  "Locker.txt";
	var f = null;
	var ts = null;

	if (fbo.locker) {
		if (isThisPathLockerPath(pth)) return true; // we already have it
		fbo.locker.close();
		fbo.locker = null;
		fbo.locker_path = null;
	}

	if (!fso.FileExists(pth)) {
		try {
			ts = fso.CreateTextFile(pth, true);
		}
		catch(e) {
			showAlertRefocus("The folder '" + fldr_path + "' could not be accessed.");
			return false;
		}
		ts.close();
		ts = null;
	}

	f = fso.GetFile(pth);
	try {
		ts = f.OpenAsTextStream(2, 0); //1 read 2 write 8 append
	}

	catch(e) {
		return false;
	}

	fbo.locker = ts;
	fbo.locker_path = pth;

	var usr = getCurrentUserName();

	if (usr) ts.write(usr);

	return true;
}

function weCanClaimLocker(pth) {
	if (fso.FolderExists(pth)) {
		pth += DIR_SEP + "Locker.txt";
		if (fso.FileExists(pth)) {
			var f = fso.GetFile(pth);
			var lf = null;
			try {
				lf = f.OpenAsTextStream(2, 0);
			}
			catch(e) {
				return isThisPathLockerPath(pth);
			}
			lf.close();
		}
	}
	return true;
}
/////END REVISIT FOR MOZ IF ENABLING////

function browseDC_FILE(fn) {
	if (fbo.type == fbt_SEL_FILE) {
		clearBCTO();
		setNamedFormFldVal(fbo.form_name, fbo.ifn, fn);
		browseFileSelected_PRIV();
	}
}

function browseClick_UP() {
	var op = fso.GetParentFolderO(fbo.o_fldr.fldr);
	if (op) {
		fbo.SetFolder(op.fldr);
		fbo.b_drives = false;
	} else if (!fbo.b_moz) {
		if (fbo.o_fldr.fldr.IsRootFolder) {


			fbo.b_drives = true;

		}

	}
	clearSelFileKey();
	drawCurrentBrowseDirectory();
}

function giveFileProperExtension(fn, e) {
	return giveFileProperExtension_PRIV(fn, e);
}

function giveFileProperExtension_PRIV(fn, e) {
	if (e) {

		var li = fn.lastIndexOf(".");


		if ((li == -1) || (fn.substr(li) == e)) fn += "." + e;
	}
	return fn;
}

function browseFileOverwriteWarning() {

	var s = "<b>'" + getTruncatedFilePath(getDisplayPathForCmdVGRoot(fbo.fp, fbo.cmd, true), gi_maxFldrDisplayChars) + "'" + br + "already exists. Do you want to over-write it?";
	//var s = "<b>'" + fbo.fp + "'" + br + "already exists. Do you want to over-write it?";

	s += "</b>";

	s += br + getNewButtonDef("o", getLocalUIString_FIO("Overwrite"), "fileBrowseOWClick")
		+ br + getNewButtonDef("a", getLocalUIString_FIO("Enter Another Name"), "fileBrowseOWClick")
		+ br + getNewButtonDef("c", getLocalUIString_FIO("Cancel"), "fileBrowseOWClick");

	drawNewBrowseDirectory(s);

}

function fileBrowseOWClick(bn) {
	switch (bn) {
	case "o":
		if (canBrowsedFileBeOverwritten(true)) {
			browserFileSavedAs_PRIV();
			break;
		} //else ift
	case "a":
		drawNewBrowseDirectory(fbo.html);
		break;
	case "c":
		browseFilesCancel();
		break;

	}

}

function fileBrowseSelClick(bn) {
	switch (bn) {
	case "c": browseFilesCancel(); break;
	case "o": browseFileSelected_PRIV(); break;
	case "n": case "nfs": browseFilesClickedNew (bn); break;
	}
}
function browseFilesClickedNew(bn) {
	//override.
}

//override
function showLockerAlert(folder_path) {
	showAlertRefocus("The gallery project '" + folder_path + "' can't be saved. It's most likely been opened by someone else. Please use a different file name.");
}

function isFileNameValidForSaving(fn, b_show_err) {
	var es;

	if (!fn || (fn == "")) {
		es  = "Please enter a file name.";
	} else if ((fn.indexOf("\\") > -1)
			|| (fn.indexOf("/") > -1)
			|| (fn.indexOf("?") > -1)
			|| (fn.indexOf(":") > -1)
			|| (fn.indexOf("*") > -1)
			|| (fn.indexOf(">") > -1)
			|| (fn.indexOf("<") > -1)
			|| (fn.indexOf("|") > -1)
			|| (fn.indexOf("#") > -1)
			|| (fn.indexOf("}") > -1) //these two are pulse related
			|| (fn.indexOf("{") > -1)
		) {

		es = "The file name '" + fn + "' contains at least one illegal character. Please do not use any of the following characters: ";
		es += cr + cr + "\\ / | < > { } # ? : *" + cr + cr + "Thanks.";

	} else {
		return true;
	}

	if (b_show_err) {
		showAlertRefocus(es);
	}
	return false;
}

function fileBrowseSaveClick(bn) {
	clearBCTO();

	if (bn == "s") {
		var fp = getNamedFormFldVal(fbo.form_name, fbo.ifn);
		if (isFileNameValidForSaving(fp, true)) {
			fp = fbo.o_fldr.path + "\\" + giveFileProperExtension(fp, fbo.ft.x[0]);

			var b_ow = !fbo.b_ff ? fso.FileExists(fp) : fso.FolderExists(fp);

			if (b_ow) {
				if (!fso.FileExists(fp + "\\" + fbo.ff_fn)) {
					showAlertRefocus("You can not overwrite this file when saving!");
					//to the user, it's always appears as a file, even if it's really a gallery folder
					return false;
				}
			}


			if (doWeNeedToCheckForLocker(fbo.label)) {
				if (!weCanClaimLocker(fp)) {
					showLockerAlert(fp);
					return false;
				}
			}

			fbo.fp = fp;
			if (b_ow) {
				browseFileOverwriteWarning();
			} else {
				browserFileSavedAs_PRIV();
			}
		} else {
			return; // or cancelled?
		}
	} else {
		browseFilesCancel();
	}
}

//override!
function doWeNeedToCheckForLocker(label) {
	return false;
}

function canBrowsedFileBeOverwritten(b_show_alert) {
	if (!fbo.b_ff) { // file
		if (fso.b_moz) {
			if (fso.FilePathIsWritable(fbo.fp) || !fso.FileExists(fbo.fp)) return true;
		} else if (fso.FileExists(fbo.fp)) {
			var wf;

			//note: this won't change the file mod date :)
			try {
				if (wf = fso.OpenTextFile(fbo.fp, 8)) { //try to temporarily open it for appending
					wf.Close();
					return true;
				}
			}
			catch(e) {

			}

		} else {
			return true;
		}
		if (b_show_alert) {
			gs_lastErr = "The File: '" + fbo.fp + "' can not be written to. Is it currently open in another application?";
			alert(gs_lastErr);
		}
		return false;
	} else if (fso.FolderExists(fbo.fp)) { //how to do this one?
		return true;
	}
	return true;

}
function browserFileSavedAs_PRIV() {
	fbo.crnt_path = fbo.o_fldr.path;

	browserFileSavedAs(fbo.fp, fbo.cmd);
	fbo.type == fbt_NONE;
}

function removeEndDotz(p) {//assumes the path has at least something other than the /.. and doesn't have any in the middle...


	var ps = p.split(DIR_SEP + "..");
	if (ps.length <= 1) return p; //no dotz
	else {
		var num_up = ps.length - 1;
		var np = getPathUp(ps[0], num_up);

		return np;
	}
}
function removeMiddleDotz(p) {//assumes has at least one set of .. in the middle


	var ps = p.split(DIR_SEP + "..");
	if (ps.length <= 1) return p; //no dotz
	else {
		if (ps[length - 1] != "") {
			var num_up = ps.length - 1;
			var np = getPathUp(ps[0], num_up);

			return np + ps[num_up];
		} else {
			return removeEndDotz(p);
		}
	}
}

function getExactFileNameOrFirstMatchFromFileDisplay(id) {

	var o_t = layerFromID(gs_filesDivName), a, ocs, big_s = o_t.innerHTML.toLowerCase(), s, n_m = 0, i_s = 0, i_s2;

	id = id.toLowerCase();

	function get_one_find(b_file, b_full) {
		var ss = (b_file ? "dc_file" : "ck_fldr") + "('" + id + (b_full ? "'" : "");

		var i = big_s.indexOf(ss);

		if (i > -1) {
			i += 9;
			return {i : i, fn : (b_full ? big_s.substring(i, id.length + 1) : big_s.substring(i, big_s.indexOf("'", i + 1))) }
		} else {
			return 0;
		}
	}

	var o_fldr = get_one_find(false, true), o_file = get_one_find(true, true), o_good;

	if (!o_fldr && !o_file) {
		o_fldr = get_one_find(false, false);
		o_file = get_one_find(true, false);
	}
	if (o_good = o_fldr) { //ieq
		if (o_file && (o_file.i < o_fldr.i)) {
			o_good = o_file;
		}
	} else {
		o_good = o_file;
	}

	return o_good ? o_good.fn : null;
}
function fileFieldKeyEvent(the_event, fld) {

	if (the_event.keyCode == 13) {
		var np;
		clearSelFileKey();
		if ((np = fld.value) == "") return false;
		else if (!fso.b_local) { //currently, not for navving...
			doSelFileKey(true);
			var fn = getExactFileNameOrFirstMatchFromFileDisplay(np);

			if (fn) fld.value = fn;

			setTimeout(fileFieldEnterFunc, 1);
			return false;
		} else {//todo: diff for gallery, since it's a folder to begin with :|
			var fldr = null, file;
			var tp = null, tp2, di;
			var b_2 = false;

			np = replaceToDirSep(np);
			if ((di = np.indexOf(".")) == 0) {

				if (np.charAt(1) != ".") {
					np = ".." + np.substring(1);
				}
				if ((np.charAt(np.length - 1) == ".") && (np.charAt(np.length - 2) != ".")) {
					np += ".";
				}
				np = GetReplaced(np, DIR_SEP + "." + DIR_SEP, DIR_SEP + ".." + DIR_SEP);

				var i = np.lastIndexOf("..");
				if (np.charAt(i + 2) != DIR_SEP) np = np.substring(0, i + 2) + DIR_SEP + np.substring(i + 2); //they
						//forgot the final / before the folder name.. let us fix it...

				tp = fbo.o_fldr.path + DIR_SEP + np;

				if (i == (np.length - 3)) { //it actually ends in the dotz
					tp = removeEndDotz(tp.substring(0, tp.length - 1));
				} else {
					tp = removeMiddleDotz(tp);
				}
			} else if ((di > -1) && ((np.indexOf("..") > -1) || (np.indexOf(DIR_SEP + ".") > -1) || (np.indexOf("." + DIR_SEP) > -1)
					)) {
					//|| (np.charAt(np.length - 1) == "."))) { //todo: why was this here? caused probs for names w/ dots, like A4.this.that and had typed A4.
				showAlertRefocus("Please enter a valid path!");
				return false;

			} else if (np.indexOf(":") == 1) {
				tp = np;
				if (np.length == 2) np += "\\";
			} else if (getLastChar(np) ==  "/") {
				tp = fbo.o_fldr.path + DIR_SEP + np;
			} else {
				tp2 = fbo.o_fldr.path + DIR_SEP + np;
				tp = tp2 + DIR_SEP;
				b_2 = true;
			} //todo: mac? also, what if non-full path w/ .. ?
			//todo: what if they use the name of an existing gallery folder? might work for gallery ;)
			//todo: what if they put in the name of the actual file?
			if (tp) {
				tp = GetReplaced(tp, "/", "\\");
				if (file = fso.GetFileIf(tp)) {
					fldr = fso.GetParentFolderO(file).fldr;
				}
				if (!fldr && !(fldr = fso.GetFolderIf(tp)) && b_2) {
					/*
					1) is the base folder valid?
					2) is there then a folder/file match?
					3) then if a match if found, just follow the stuff below

						a) can the last char, above, be a "\".... i guess if it is, don't do this, eh?
					*/

					doSelFileKey(true); //to force the draw, in case they typed quickly and then hit return
					var o_t = layerFromID(gs_filesDivName), a, ocs, big_s = o_t.innerHTML.toLowerCase(), s, n_m = 0, i_s = 0, s_id = fld.value, i_s2;
					var s_len;

					if (fso.o_file_keys.b_any) { //then just take whatever is first in the list :), so no id needed
						s_id = "";
					}
					if ((i_s = big_s.indexOf("browseclick_fldr('" + s_id)) == -1) {
						i_s = big_s.indexOf("browsedc_file('" + s_id);
					}
					if (i_s > -1) {
						eval(o_t.innerHTML.substring(i_s, big_s.indexOf(";", i_s + 18) + 1));
						return false;
					}
				}

				if (fldr) {
					var b_can_nav_here = false;
					var fp = fso.GetFolderPath(fldr);
					var b_return = true;
					switch(fbo.nav_type) {
					case fio_ALLOW_NAV_TYPE_Pos:

						if (fbo.max_nav_up_path) {
							//if (fp.indexOf(fbo.max_nav_up_path) == 0) {
							if (compMaxPath(fp) > -1) {
								b_can_nav_here = true;
							}
						} else {
							b_can_nav_here = false; // true?
						}
						break;
					case fio_ALLOW_NAV_TYPE_None: //aren't allowed to nav for saving, remember, currently, due to other xml dependencies!
						//if we allow that, would need to check fbo.b_ff and act accordingly
						break;
					case fio_ALLOW_NAV_TYPE_Any:
						b_can_nav_here = true;
						break;
					}
					if (b_can_nav_here) {
						if (file) { //assume it's the CORRect type of file...
							fbo.SetFolder(fldr);
							fld.value = fso.GetName(file);
							eval(fileFieldEnterFunc);
						} else if (fbo.b_ff && fso.FileExists(fp + DIR_SEP + fbo.ff_fn)) { //is it actually one of these?
							var pf = fso.GetParentFolderO(fldr);
							fbo.SetFolder(pf.fldr);
							fld.value = fso.GetName(fldr);
							eval(fileFieldEnterFunc);
						} else {
							fbo.SetFolder(fldr);
							drawCurrentBrowseDirectory();
						}
					} else if (fbo.b_ff && b_2) {
						b_return = false;
					} else {
						showAlertRefocus("You can't navigate to this path!");
						fld.focus();
					}
					if (b_return) return false;
				} else if (!b_2) { //their intent was to try!
					showAlertRefocus("Please enter a valid path!");

					//fld.focus();
					return false;
				}
			}
		}
		eval(fileFieldEnterFunc);
		return false;
	}
	return true;
}

function startSelFileKey() {
	clearSelFileKey(true);
	fso.o_file_keys.to = setTimeout(fso.o_file_keys.tos, fso.o_file_keys.tod);
}

function clearSelFileKey(b_ingore_key) {
	if (!b_ingore_key) {
		fso.setFileKeysVal(fso.o_file_keys, "");
	}
	if (fso.o_file_keys.to) {
		clearTimeout(fso.o_file_keys.to);
		fso.o_file_keys.to = null;
	}
}

function doSelFileKeyCheck() {
	var o = objFromID(fbo.ifn);
	if (o) {
		var s = o.value;
		if (s != "") s = replaceToDirSep(s).toLowerCase();
		if (s != fso.o_file_keys.ls) {
			fso.o_file_keys.ls = s;
		} else if (s != fso.o_file_keys.s) {
			doSelFileKey();
			return;
		}
		clearTimeout(fso.o_file_keys.to);
		fso.o_file_keys.to = setTimeout(fso.o_file_keys.tos, fso.o_file_keys.tod);
	}
}

function doSelFileKey(b_dont_set_timeout) {
	clearTimeout(fso.o_file_keys.to);
	fso.o_file_keys.to = null;
	var o = objFromID(fbo.ifn);

	if (o) { //todo: do the stuff from above for .. etc
		var s = o.value;

		if (s != "") s = replaceToDirSep(s).toLowerCase();
		if (s != fso.o_file_keys.s) {
			if ((s.indexOf(DIR_SEP) == -1) && (s.indexOf("..") == -1)) {
				fso.setFileKeysVal(fso.o_file_keys, s);
				drawCurrentBrowseDirectory();
			}
		}
		if (!b_dont_set_timeout) fso.o_file_keys.to = setTimeout(fso.o_file_keys.tos, fso.o_file_keys.tod);
		/*
		if (s != "") {
			var a = new Array();
			s = replaceToDirSep(s);
			if ((s.indexOf(DIR_SEP) == -1) && (s.indexOf(".") == -1)){
				//s = replaceToDirSep(fbo.o_fldr.path) + DIR_SEP + s;
				//alert(s);
				//we should already know the complete list, so just get em from THAt
				//var a_new getMatchingFilesArrayFromFilesArray(a, s);
				//fbo.o_af;
				s = s.toLowerCase();
				fbo.file_keys = s;
				drawCurrentBrowseDirectory();
				return;
				var l = fbo.o_af.num_files, fa = fbo.o_af.a_files;
				for (var i = 0; i < l; i++) {
					if (fa[i][0].toLowerCase().indexOf(s) == 0) {
						apush(a, i);
					}
				}
				if (a.length) {
					//draw in these files
					debugger;
				} else {
					//draw in some "Not matching files" thing....
				}
				fbo.a_keysMatch = a;
			} else {
				fbo.a_keysMatch = null;
			}
		} else { //just display the whole thing (agin!);
			fbo.a_keysMatch = null;
		}
		//redrawCurrentDirForKeysMatch();
		if (fbo.a_keysMatch) {

		} else { //draw in regular one

		}
		*/
	} else { //no field, means it should have been cleared.... failsafe
		clearSelFileKey();
	}
}

function getIconFileAndDateLine(name, d, fi0) {
	var fi;
	switch(typeof(fi0)) {
	case "object":
		var fe = fileExtensionFromName(name);
		fi = fi0.i[fi0.v[fe]];
		break;
	case "string":
		fi = fi0;
		break;
	default:
	case "undefined":
		fi = ga_iconPaths[fileExtensionFromName(name)];
		break;
	}

	d = getFileDisplayDateStr(d);

	return '<tr ondblclick="browseDC_FILE(' + "'" + name + "'" + '); return false" onclick="browseClick_FILE(' + "'" + name + "'); return false;" + '">'
			+ '<td><img' + gs_fileIconAlignStr + ' src="' + fi + '"/>' + nbs + name + "</td>"
			+ "<td>" + d + "</td>"
		+ "</tr>";


	return '<a ondblclick="browseDC_FILE(' + "'" + name + "'" + '); return false" onclick="browseClick_FILE(' + "'" + name + "'); return false;" + '">'
		+ '<tr><td><img src="' + fi + '"/>' + nbs + name + "</td>"
		+ "<td>" + d + "</td>"
		+ "</tr></a>";
}

//allways call this for showing file date, so that could use a pref to change how it's displayed :)
function getFileDisplayDateStr(d) {
	if (typeof(d) != "object") d = new Date(d);
	return getDateString(d, "dws.d.ms.y", "12z");
}
function getFileDisplayDateStr_C(d, s_format_date, s_format_time) {
	if (typeof(d) != "object") d = new Date(d);
	return getDateString(d, s_format_date, s_format_time);
}

function getDrives_AS_HTML(fbt, label, b_show_new, sort_type, o_file_keys) {

	var one_f;
	var s = (label == "") ? "" : "<b>" + label + ":</b>" + br;
	var b_sort_descending = false;
	var one_l = "";
	var files_s = "", subs_s = "", table_s = "";


	var border=1, cellpadding=1, cellspacing=0, bcolor="#555555";


	var a_drives = new Array();
	function addCharToDriveListIf(c) {
		if (fso.FolderExists(c + ":\\")) {
			apush(a_drives, new Array(c + ":"));
		}
	}
	if (!gb_mac) {
		addCharToDriveListIf("C");
		addCharToDriveListIf("D");
		addCharToDriveListIf("E");
		addCharToDriveListIf("F");
		addCharToDriveListIf("G");
		addCharToDriveListIf("H");
		addCharToDriveListIf("I");
		addCharToDriveListIf("J");
		addCharToDriveListIf("K");
		addCharToDriveListIf("L");
		addCharToDriveListIf("M");
		addCharToDriveListIf("N");
		addCharToDriveListIf("O");
		addCharToDriveListIf("P");
		addCharToDriveListIf("Q");
		addCharToDriveListIf("R");
		addCharToDriveListIf("S");
		addCharToDriveListIf("T");
		addCharToDriveListIf("U");
		addCharToDriveListIf("V");
		addCharToDriveListIf("W");
		addCharToDriveListIf("X");
		addCharToDriveListIf("Y");
		addCharToDriveListIf("Z");
	} else { //put in Volumes, Users, Desktop ?
		Debugger();
		return;
	}
	if (!a_drives.length) {
		Debugger();
		return;
	}
	fbo.a_drives = a_drives;

	if (sort_type == fio_FOLDER_SORT_TYPE_NameD) {
		b_sort_descending = true;
	}


	s += "Drives:" + br;


	switch(fbt) {
		case fbt_SAVEAS:
		case fbt_SEL_FILE:
			//s += getNewFieldDef(true, fbo.ifn, as_file_types.x[0], fbo.ifw, "");
			s += getNewFieldDef(true, fbo.ifn, fbo.crnt_file_name, fbo.ifw, "fileFieldKeyEvent");
			s += br + getSaveSelButts(fbt, false, b_show_new);
			/*
			if (fbt == fbt_SAVEAS) {
				fileFieldEnterFunc = "fileBrowseSaveClick('s')";
				//s += getNewFIOButt("s", true); //can't save here
				s += br + getNewFIOButt("c", true) + br + br;
			} else { //SEL_FILE
				fileFieldEnterFunc = "fileBrowseSelClick('o')";
				s += getNewFIOButt("o", false);
				if (b_show_new) s += getNewButtonDef("n", getLocalUIString_FIO("New"), "fileBrowseSelClick");
				s += br + getNewFIOButt("c", false) + br + br;
			}
			*/
			break;
		case fbt_SEL_FLDR:
		default:
			break;
	}



	for (var i = 0; i < fbo.a_drives.length; i++) {
		one_l = fbo.GetFolderHTML(fbo.a_drives[i]);

		if (!b_sort_descending) subs_s += one_l + br;
		else subs_s = br + one_l + subs_s;
	}
	if (b_sort_descending) subs_s = subs_s.substr(br.length);


	var twidth = 0;//23 * gi_fileLenMult;

	table_s = getTableHTML_START_BCCBgBc(twidth, null, border, cellpadding, cellspacing, null, bcolor);

	table_s += getSortHeadsForFiles(sort_type);

	if (subs_s != "") {
		table_s += "<tr><td colspan=2>" + subs_s + "</td></tr>";
	}

	table_s += "</table>";

	if (!fso.anyFileKeys(o_file_keys)) {
		clearSelFileKey();
		s += getFilesDisplayDiv(table_s);
	} else {
		getFilesDisplayDiv(table_s, true);
		return null;
	}

	return (fbo.html = s);
}

//override
function getLocalUIString_FIO(s) {
	return s;
	/* like this....
	switch(s) {
	case "Save": return "Speichern";
	case "Cancel": return "Cancel";
	case "Open": return "Open";
	case "New": return "New";
	case "Filename": return "Filename";
	case "Modified Date": return "Modified Date";
	case "Overwrite": return "Overwrite";
	case "Enter Another Name": return "Enter Another Name";
	default: return s;
	}
	*/
}

function getNewFIOButt(val, b_save) {
	var func = "fileBrowse" + (b_save ? "Save" : "Sel") + "Click";
	var s = "";
	switch(val) {
	case "s": s = "Save"; break;
	case "o": s = "Open"; break;
	case "n": s = "New"; break;
	case "c": s = "Cancel"; break;
	}

	return getNewButtonDef(val, getLocalUIString_FIO(s), func);
}

function getSaveSelButts(fbt, b_can_save, b_show_new) {
	s = "";

	if (fbt == fbt_SAVEAS) {
		fileFieldEnterFunc = "fileBrowseSaveClick('s')";
		if (b_can_save) s += getNewButtonDef("s", getLocalUIString_FIO("Save"), "fileBrowseSaveClick");
		s += br + getNewFIOButt("c", true) + br + br;
	} else { //SEL_FILE
		fileFieldEnterFunc = "fileBrowseSelClick('o')";
		s += getNewFIOButt("o", false);
		if (b_show_new) s += getNewButtonsFromShowNew(b_show_new);//s += getNewButtonDef("n", getLocalUIString_FIO("New"), "fileBrowseSelClick");
		s += getNewFIOButt("c", false) + br + br;
	}
	return s;
}
function getFilesInFolder_AS_HTML(fbt, o_fldr, as_file_types, label, hiders, nav_type, b_show_new, sort_type, o_file_keys) {

	var one_f;
	var s = (label == "") ? "" : "<b>" + label + ":</b>" + br;
	var fi = -1;
	var b_sort_descending = false;
	var one_l = "";
	var files_s = "", subs_s = "", table_s = "";
	var ll = 0, mll = 0;
	var ar;
	var fldr_search_type = (nav_type == fio_ALLOW_NAV_TYPE_None) ? 0 : 1;


	var border=1, cellpadding=1, cellspacing=0, bcolor="#555555";

	s += getTruncatedFldr(o_fldr, gi_maxFldrDisplayChars) + br;


	switch(fbt) {
		case fbt_SAVEAS:
		case fbt_SEL_FILE:
			//s += getNewFieldDef(true, fbo.ifn, as_file_types.x[0], fbo.ifw, "");
			s += getNewFieldDef(true, fbo.ifn, fbo.crnt_file_name, fbo.ifw, "fileFieldKeyEvent");
			s += br + getSaveSelButts(fbt, true, b_show_new);
			/*
			if (fbt == fbt_SAVEAS) {
				fileFieldEnterFunc = "fileBrowseSaveClick('s')";
				s += getNewButtonDef("s", getLocalUIString_FIO("Save"), "fileBrowseSaveClick");
				s += br + getNewFIOButt("c", true) + br + br;
			} else { //SEL_FILE
				fileFieldEnterFunc = "fileBrowseSelClick('o')";
				s += getNewFIOButt("o", false);
				if (b_show_new) s += getNewButtonDef("n", getLocalUIString_FIO("New"), "fileBrowseSelClick");
				s += br + getNewFIOButt("c", false) + br + br;
			}
			*/
			break;
		case fbt_SEL_FLDR:
		default:
			break;
	}

	if (nav_type == fio_ALLOW_NAV_TYPE_Any) {
		s += '<a onclick="browseClick_UP(); return false;">'
			+ '<img src="' + fbo.up_icn + '"/>'
			+ ".." + "</a>" + br;

	}
	/*
	if (!fso.b_moz) {
		var fldr = o_fldr.fldr;
		var eFolder = (fldr.Files && (fbt != fbt_SEL_FLDR)) ? new Enumerator(fldr.Files) : null;
		var eSub = (nav_type != fio_ALLOW_NAV_TYPE_None) && fldr.SubFolders ? new Enumerator(fldr.SubFolders) : null;

		if (eSub) {
			if (sort_type == fio_FOLDER_SORT_TYPE_NameD) b_sort_descending = true;
			while (!eSub.atEnd()) {

				one_l = fbo.GetFolderHTML(eSub.item());

				if (!b_sort_descending) subs_s += one_l + br;
				else subs_s = br + one_l + subs_s;

				eSub.moveNext();

			}
			if (b_sort_descending) subs_s = subs_s.substr(br.length);
			b_sort_descending = false;
		}

		if (eFolder) {

			if (as_file_types) { // more efficient to only check each file if it matters
				while (!eFolder.atEnd()) {
					one_f = eFolder.item();

					if ((fi = getFileExtensionIndex(one_f, as_file_types.x, as_file_types.fe)) != -1) {
						ar[num_files++] = new Array(one_f.Name, new Date(one_f.DateLastModified), fi);
					}
					eFolder.moveNext();
				}
			} else {
				while (!eFolder.atEnd()) {
					one_f = eFolder.item();
					ar[num_files++] = new Array(one_f.Name, new Date(one_f.DateLastModified), fi);
					eFolder.moveNext();
				}

			}
		}
	} else {
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		var de = fbo.o_fldr.fldr.directoryEntries;
		while (de.hasMoreElements()) {
			one_f = de.getNext().QueryInterface(Components.interfaces.nsILocalFile);
			if (one_f.isDirectory()) {
				one_l = fbo.GetFolderHTML(one_f);

				if (!b_sort_descending) subs_s += one_l + br;
				else subs_s = br + one_l + subs_s;

			} else if (one_f.isFile()) { //is there any other possiblity? bbbb
				if (as_file_types) {
					if ((fi = getFileExtensionIndex(one_f, as_file_types.x, as_file_types.fe)) != -1) {
						ar[num_files++] = new Array(one_f.leafName, new Date(one_f.lastModifiedTime), fi);
					}
				} else {
					ar[num_files++] = new Array(one_f.leafName, new Date(one_f.lastModifiedTime), fi);
				}
			}
		}
	}
	*/

	var o_af = getFilesInFolder_AS_ARRAY_OBJ(o_fldr, as_file_types, fldr_search_type, o_file_keys);

	if (o_af.num_dirs) {

		o_af.a_dirs.sort(sortFolderArrayName);

		if (fbo.b_sort_name_d) {
			o_af.a_dirs.reverse();
		}

		for (var i = 0; i < o_af.num_dirs; i++) {
			one_l = fbo.GetFolderHTML(o_af.a_dirs[i]);
			subs_s += one_l + br;
		}
	}

	if (o_af.num_files) {
		var i = 0, d;
		var name;

		switch(sort_type) {
		case fio_FOLDER_SORT_TYPE_NameD:
			b_sort_descending = true; //ift
		case fio_FOLDER_SORT_TYPE_None:
		case fio_FOLDER_SORT_TYPE_NameA:
			o_af.a_files.sort(sortFileArrayNameSimple);
			break;
		case fio_FOLDER_SORT_TYPE_DateD:
			b_sort_descending = true; //ift
		case fio_FOLDER_SORT_TYPE_DateA:
			o_af.a_files.sort(sortFileArrayDate);
			break;
		}

//function getFileClickStrForVal(val) {

//}
		if (b_sort_descending) o_af.a_files.reverse();

		for (i = 0; i < o_af.num_files; i++) {
			name = o_af.a_files[i][0];

			files_s += getIconFileAndDateLine(name, d = o_af.a_files[i][1], as_file_types);

			if ((ll = (name.length + d.toString().length)) > mll) {
				mll = ll;
			}

		}
	}

	var twidth = 0;//o_af.num_files ? mll * gi_fileLenMult : 23 * gi_fileLenMult;

//	if (o_af.num_files) {
		table_s = getTableHTML_START_BCCBgBc(twidth, null, border, cellpadding, cellspacing, null, bcolor);
//	}

	table_s += getSortHeadsForFiles(sort_type);

	if (subs_s != "") {
		table_s += "<tr><td" + ((files_s != "") ? " colspan=2>" : ">") + subs_s + "</td></tr>";
	}

	table_s += files_s + "</table>";
	if (!fso.anyFileKeys(o_file_keys)) {
		clearSelFileKey();
		s += getFilesDisplayDiv(table_s);
	} else {
		getFilesDisplayDiv(table_s, true);
		return null;
	}

	return (fbo.html = s);
}


function getFilesInFolder_AS_ARRAY_OBJ(o_fldr, as_file_types, show_folders_type, o_file_keys) { //sft: 0 none, 1 all, 2 non-empty

	var ao = fso.GetFilesInFolderArray(o_fldr, as_file_types, show_folders_type, o_file_keys);
	return ao;

}

//note that this will call as the result of a function that originally was called with a sort_type, although
// this would now actually set the global..... though theorhetically this function could somehow do something difrnt
function browseC_SORT(whichn) {
	var b_current_is_name;

	switch(fbo.sort_type) {
	case fio_FOLDER_SORT_TYPE_DateD:
	case fio_FOLDER_SORT_TYPE_DateA:
		b_current_is_name = false;
		break;
	default:
		b_current_is_name = true;
	}

	switch(whichn) {
	case 'n':
		if (b_current_is_name) fbo.b_sort_name_d = !fbo.b_sort_name_d;
		fbo.sort_type = fbo.b_sort_name_d ? fio_FOLDER_SORT_TYPE_NameD : fio_FOLDER_SORT_TYPE_NameA;
		break;
	case 'd':
		if (!b_current_is_name) fbo.b_sort_date_d = !fbo.b_sort_date_d;
		fbo.sort_type = fbo.b_sort_date_d ? fio_FOLDER_SORT_TYPE_DateD : fio_FOLDER_SORT_TYPE_DateA;
		break;
	}

	sendPrefsModElemToPlayer("files", "sortType", fbo.sort_type);

	redrawCurrentBrowseDirectory();
}

//override... this assumes no navigation, but so that can override the call to drawCurrentBrowseDirectory
function redrawCurrentBrowseDirectory() {
	drawCurrentBrowseDirectory();
}


function getSortHeadsForFiles(sort_type, pre_head) {
	var s_name = getLocalUIString_FIO("Filename"), s_date = getLocalUIString_FIO("Modified Date");
	var s = "<tr>";

	if (pre_head) s += pre_head;

	switch(sort_type) {
	case fio_FOLDER_SORT_TYPE_NameD:
		s_name = getBoldedText(s_name + gs_sortDescending);
		s_date += gs_sortBlank;
		break;
	default:
	case fio_FOLDER_SORT_TYPE_None:
	case fio_FOLDER_SORT_TYPE_NameA:
		s_name = getBoldedText(s_name + gs_sortAscending);
		s_date += gs_sortBlank;
		break;
	case fio_FOLDER_SORT_TYPE_DateD:
		s_date = getBoldedText(s_date + gs_sortDescending);
		s_name += gs_sortBlank;
		break;
	case fio_FOLDER_SORT_TYPE_DateA:
		s_date = getBoldedText(s_date + gs_sortAscending);
		s_name += gs_sortBlank;
		break;
	}

	s += '<td><a onclick="browseC_SORT(' +"'n'" + '); return false">' + s_name + "</a></td>"
	  +  '<td><a onclick="browseC_SORT(' +"'d'" + '); return false">' + s_date + "</a></td>"
	  + "</tr>";

	return s;

}
//todo: is this the correct index? why not 1?
function sortFolderArrayName(a1, a2) {
	return a1[0].toLowerCase() > a2[0].toLowerCase() ? 1 : -1;
}

function sortFileArrayDate(a1, a2) {
	var v;
	//on the off-chance they have the same date (time, etc), we sort via the last name sort type
	return (v = (a1[1] - a2[1])) ? v :
		((a1[0].toLowerCase() > a2[0].toLowerCase())
			? (fbo.b_sort_name_d ? 1 : -1) : (fbo.b_sort_name_d ? -1 : 1));
}

function sortFileArrayDate2(a1, a2) {
	var v;
	//on the off-chance they have the same date (time, etc), we sort via the last name sort type
	return (v = (a1[VG_FILE_ARRAY_INDEX_Date] - a2[VG_FILE_ARRAY_INDEX_Date])) ? v :
		((a1[VG_FILE_ARRAY_INDEX_Name].toLowerCase() > a2[VG_FILE_ARRAY_INDEX_Name].toLowerCase())
			? (fbo.b_sort_name_d ? 1 : -1) : (fbo.b_sort_name_d ? -1 : 1));
}

function sortFileArrayName(a1, a2) {

	return a1[VG_FILE_ARRAY_INDEX_Name].toLowerCase() > a2[VG_FILE_ARRAY_INDEX_Name].toLowerCase() ? 1 : -1;
}
function sortFileArrayNameSimple(a1, a2) {

	return a1[0].toLowerCase() > a2[0].toLowerCase() ? 1 : -1;
}


function getTruncatedPath_OLD(path_str, num_chars, b_file) {

	if (path_str.length > num_chars) {
		var beg_max = Math.floor(num_chars / 2) - 5;
		var end_max = (num_chars - beg_max) - 3;
		var end_start = path_str.length - end_max;
		return path_str.substring(0,beg_max) + "..."
			+ br + "..."
			+ path_str.substring(end_start);
	}
	return path_str;
}

function getTruncatedPath(path_str, max_per_line, b_file) {

	var sep_char = DIR_SEP;

	if (path_str.length < max_per_line) return path_str;

	if (sep_char != "\\") {
		path_str = replaceToDirSep(path_str);
	}

	//path_str = GetReplaced(path_str, sep_char, "(*&234$#");
	//return GetReplaced(path_str, "(*&234$#", sep_char + " ");

	path_str = pullOffLastCharIfMatch(path_str, sep_char); //remove the end, or the array will have 1 too many

	var dirs = path_str.split(sep_char);
	var nl = 0;
	var cls = "";
	var s = "";

	for (i = 0; i < dirs.length; i++) {
		if ((dirs[i].length + 1) > max_per_line) { // one part is too long
			if (cls != "") {
				s += cls + " ";
				cls = "";
				nl++;
			}
			s += dirs[i] + sep_char + " ";
			nl++;

		} else if ((cls.length + dirs[i].length + 1) > max_per_line) { // the current combo is too long
			if (nl) {
				s += " ";
			}
			nl++;
			s += cls;
			cls = "";
			i--;
		} else { //add to the current combo
			cls += dirs[i] + sep_char;
		}

	}

	if (cls != "") {
		s += " " + cls;
		if (b_file) {
			s = pullOffLastChar(s);
		}
	}

	return s;

}

//getSpacedFilePath(file_path, num_chars) {} // to add spaces to the long path so it'll break accross line....
function getTruncatedFilePath(file_path, num_chars) {
	return getTruncatedPath(file_path, num_chars, true);
}

function getTruncatedFldrPath(fldr_path, num_chars) {
	return getTruncatedPath(fldr_path, num_chars, false);
}

function getTruncatedFldr(o_fldr, num_chars) {
	return getTruncatedFldrPath(o_fldr.path, num_chars, false);
}

function getNewButtonsFromShowNew(show_new_type, sep) {
	if (show_new_type) {
		if (sep == null) sep = "  "; //br
		var s = sep + getNewButtonDef("n", "New", "fileBrowseSelClick");
		if (show_new_type == 2) s += sep + getNewButtonDef("nfs", "New From Scratch", "fileBrowseSelClick");
		return s;
	}
	return "";
}

// show a folder that containes the named file, as if it were a file... otherwise, only folders w/ other folders can be shown
function getFolderWithFilesInFolder_AS_HTML(fbt, o_fldr, file_name, file_icon, label, hiders, nav_type, b_show_new, sort_type, o_file_keys) {


	var fldrs_type = 1;//(nav_type != fio_ALLOW_NAV_TYPE_None) ? 1 : 0;

	var o_af = fso.GetFolderWithFileArray (o_fldr, file_name, fldrs_type, hiders, o_file_keys);


	var one_f, one_file;
	var s = (label == "") ? "" : "<b>" + label + ":</b>" + br;
	var fi = -1;
	var b_sort_descending = false;
	var one_l = "", files_s = "", subs_s = "", table_s = "";
	var border=1, cellpadding=1, cellspacing=0, bcolor="#555555";

	s += getTruncatedFldr(o_fldr, gi_maxFldrDisplayChars) + br;


	switch(fbt) {
		case fbt_SAVEAS:
		case fbt_SEL_FILE:
			var field_val = fso.getFileKeyValIfOrDflt(o_file_keys, fbo.crnt_file_name);
			//s += getNewFieldDef(true, fbo.ifn, as_file_types.x[0], fbo.ifw, "");
			s += getNewFieldDef(true, fbo.ifn, field_val, fbo.ifw, "fileFieldKeyEvent");
			s += br + getSaveSelButts(fbt, true, b_show_new);
			/*
			if (fbt == fbt_SAVEAS) {
				fileFieldEnterFunc = "fileBrowseSaveClick('s')";
				s += getNewButtonDef("s", getLocalUIString_FIO("Save"), "fileBrowseSaveClick");
				s += br + getNewFIOButt("c", true) + br + br;
			} else { //SEL_FILE
				fileFieldEnterFunc = "fileBrowseSelClick('o')";
				s += getNewFIOButt("o", false);
				s += getNewButtonsFromShowNew(b_show_new);
				s += br + getNewButtonDef("c",getLocalUIString_FIO("Cancel"), "fileBrowseSelClick") + br + br;
			}
			*/
			break;
		case fbt_SEL_FLDR:
		default:
			break;
	}

	if (nav_type == fio_ALLOW_NAV_TYPE_Any) {
		s += '<a onclick="browseClick_UP(); return false;">'
			+ '<img src="' + fbo.up_icn + '"/>'
			+ ".." + "</a>";
	}

	if (o_af.num_files || o_af.num_dirs) {
		var num_files = 0;
		var ar = new Array();
		//directories come in sorted by ascending date :|

		if (o_af.num_dirs) {

			o_af.a_dirs.sort(sortFolderArrayName);

			if (fbo.b_sort_name_d) {
				o_af.a_dirs.reverse();
			}

			for (var i = 0; i < o_af.num_dirs; i++) {
				one_l = fbo.GetFolderHTML(o_af.a_dirs[i]);
				subs_s += one_l + br;
			}

		}
		if (o_af.num_files) {
			var i = 0, mll = 0, ll = 0;
			var name, d;

			switch(sort_type) {
			case fio_FOLDER_SORT_TYPE_NameD:
				b_sort_descending = true; //ift
			case fio_FOLDER_SORT_TYPE_None:
			case fio_FOLDER_SORT_TYPE_NameA:
				o_af.a_files.sort(sortFileArrayNameSimple);
				break;
			case fio_FOLDER_SORT_TYPE_DateD:
				b_sort_descending = true; //ift
			case fio_FOLDER_SORT_TYPE_DateA:
				o_af.a_files.sort(sortFileArrayDate);
				break;
			}

			if (b_sort_descending) o_af.a_files.reverse();


			for (i = 0; i < o_af.num_files; i++) {
				name = o_af.a_files[i][0];

				files_s += getIconFileAndDateLine(name, d = o_af.a_files[i][1], file_icon);


				if ((ll = (name.length + d.toString().length)) > mll) {
					mll = ll;
				}
			}
		}

		var twidth = 0;//o_af.num_files ? mll * gi_fileLenMult : 23 * gi_fileLenMult;

		table_s = getTableHTML_START_BCCBgBc(twidth, null, border, cellpadding, cellspacing, null, bcolor);

		/*
		if (num_files) {
			table_s = getTableHTML_START(mll * gi_fileLenMult);
		} else {
			table_s = getTableHTML_START(23 * gi_fileLenMult);
		}
		*/
		table_s += getSortHeadsForFiles(sort_type);

		if (subs_s != "") {
			table_s += "<tr valign=center><td" + ((files_s != "") ? " colspan=2>" : ">") + subs_s + "</td></tr>";
		}

		table_s += files_s + "</table>";

		if (!fso.anyFileKeys(o_file_keys)) {
			clearSelFileKey();
			s += getFilesDisplayDiv(table_s);
		} else {
			getFilesDisplayDiv(table_s, true);
			return null;
		}

	} else if (fso.anyFileKeys(o_file_keys)) {
		getFilesDisplayDiv(table_s, true);
		return null;
	}

	return (fbo.html = s);
}

var gto_resizeFilesDiv = null;

function getFilesDisplayDiv(s, b_update_lyr) {
	if (b_update_lyr) {
		var l = layerFromID(gs_filesDivName);
		l.innerHTML = s;
		//setTimeout("resizeFilesDiv(\"filesDiv\");", 2);
		resizeFilesDiv(gs_filesDivName);
		return;
	}


	var ds = "<div" + getNewNameIDTag(gs_filesDivName) + getNewStyleStr("left", "5px", "overflow", "auto", "position", "relative",
		"height", " 100") + ">" + s + "</div>";
	gto_resizeFilesDiv = setTimeout("resizeFilesDiv(\"" + gs_filesDivName + "\");", 2);
	return ds;

}

function resizeFilesDiv(s_div, b_x2) {
if (gto_resizeFilesDiv) {
	clearTimeout(gto_resizeFilesDiv);
	gto_resizeFilesDiv = null;
}
	var div = layerFromID(s_div);
	var pdiv;
	if (!b_x2) {
		if (div && (pdiv = getAParentElement_TYPED(div, "DIV"))) {
			var ph = getLayerDimH(pdiv), lt = getLayerTop(div), pw = getLayerDimW(pdiv);

			var nlh = ph - lt;
nlh -= 24;
			div.style.height = nlh + "px";
			div.style.width = pw - div.offsetLeft;

			//setTimeout("resizeFilesDiv(\"" + s_div + "\",true);", 1);
			if (fbo.type == fbt_SEL_FILE) startSelFileKey();
		}
	} else {
		debugger;
	}
}
function hiderMatch(ha, fname) {
	var i;
	for (i = 0; i < ha.length; i++) {
		if (ha[i] == fname) return true;
	}
	return false;

}

function folderPathFromPathWithFile(full_path) { //pullse off the final DIR_SEP!

	var fp = replaceToDirSep(full_path);

	return fp.substring(0, fp.lastIndexOf("/"));
}
function getBrokenApartFileAndFolderPaths(full_path, b_inc_dirsep) {
	var fp = replaceToDirSep(full_path);
	var fi = fp.lastIndexOf(DIR_SEP) + 1;

	return {fldr : fp.substring(0, fi - (b_inc_dirsep ? 0 : 1)), file : fp.substring(fi)};

}

function writeTempXMLFile(the_file_text, b_dont_show_bad_alert) {
	//todo: make random file name?
	if (fsoInitted()) {

		var p = gs_tmp_dir + DIR_SEP + "tmp.xml";

		if (writeTextFile(p, the_file_text, b_dont_show_bad_alert)) {
			return p;
		}
	}
	return null;
}

//assumes fso is already valid
function readFileMoz(file_path) {
	var reto = new Object();
	reto.err = 0;
	reto.s = "";

	try {
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
	} catch (e) {
		reto.err = e;
		return;
	}
	var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
	fso.InitWithPath(file, file_path);

	if ( file.exists() == false ) {
		reto.err = 2; //;)
	}
	var is = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance( Components.interfaces.nsIFileInputStream );
	is.init( file,0x01, 00004, null);
	var sis = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance( Components.interfaces.nsIScriptableInputStream );
	sis.init( is );

	reto.s = sis.read( sis.available() );
	sis.close();

	return reto;
}
/*
// pngBinary already exists
var aFile = Components.classes["@mozilla.org/file/local;1"]
                      .createInstance(Components.interfaces.nsILocalFile);

aFile.initWithPath( "/tmp/mypicture.png" );
aFile.createUnique( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 600);

var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"].
                       createInstance(Components.interfaces.nsIFileOutputStream);
stream.init(aFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate

stream.write(pngBinary, pngBinary.length);
if (stream instanceof Components.interfaces.nsISafeOutputStream) {
    stream.finish();
} else {
    stream.close();
}
https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FO
*/
function writeFileMoz( sFilePath, sFileContent, b_dont_show_bad_alert, cmd0 )
{
	var b_good = false;

	try {
		netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
		var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
		file.QueryInterface(Components.interfaces.nsIFile);
		fso.InitWithPath(file, sFilePath);

		if( file.exists() == true ) file.remove( false );
		else file.create(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0x04 | 0x08);

		var strm = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
		strm.QueryInterface(Components.interfaces.nsIOutputStream);
		strm.QueryInterface(Components.interfaces.nsISeekableStream);
		strm.init( file, 0x04 | 0x08, 420, 0 );
		strm.write( sFileContent, sFileContent.length );
		strm.flush();
		strm.close();
	}
	catch(er){
		if (b_dont_show_bad_alert) {

		} else {
			go_lastErr = er;
			gs_lastErr = "The File: '" + sFilePath + "' could not be written to. Is it currently open?";
			alert(gs_lastErr); //er.message
		}
		return false;
	}
	return true;

}


function writeTextFile(the_file_path, the_file_text, b_dont_show_bad_alert, cmd0) { //todo: is cmd0 sposed to fire a cmd?
	if (!fsoInitted()) return false;

	if (fso.b_moz) return writeFileMoz(the_file_path, the_file_text,b_dont_show_bad_alert, cmd0);

	var b_good = false;
	if (the_file_text && (the_file_text != "")) {
		var a = null;

		the_file_path = unescape(the_file_path);
		b_good = true;

		try {
			a = fso.CreateTextFile(the_file_path, true, false); // overwrite, ascii (unicode = false)
		}
		catch(er) {
			b_good = false;
			go_lastErr = er;
		}

		if (!b_good) {
			// does the folder exist?
			var folder_path = folderPathFromPathWithFile(the_file_path);

			if (!fso.FolderExists(folder_path)) {
				gs_lastErr = "The Folder: '" + folder_path + "' could not be found!";

			} else if (!fso.GetFolder(folder_path)) {
				gs_lastErr = "The Folder: '" + folder_path + "' could not be accessed!";
			} else {
				gs_lastErr = "The File: '" + the_file_path + "' could not be written to. Is it currently open?";
			}

			if (b_dont_show_bad_alert) {

			} else {
				alert(gs_lastErr);
			}
			return false;

		}
		try {
			a.Write(the_file_text);
			a.Close();
		}
		catch(er) {
			if (b_dont_show_bad_alert) {

			} else {
				go_lastErr = er;
				gs_lastErr = "The File: '" + the_file_path + "' could not be written to. Is it currently open?";
				alert(gs_lastErr);
			}
			return false;
		}
	}
	return b_good;
}

// will overwrite it! currently doesn't check
// only writes if the_file_text is non-null and non-empty, so can call and do the checkin here...
function writeXMLFile(the_file_path, the_file_text, b_dont_show_bad_alert, cmd0) {
	return writeTextFile(the_file_path, PulseXMLIfyElems(the_file_text), b_dont_show_bad_alert, cmd0);
}

//assumes fso exists, so we don't have to check
var FIO_COPY_FILE_ERR_None = 0,
	FIO_COPY_FILE_ERR_SrcDNE = 1,
	FIO_COPY_FILE_ERR_DstExists = 2,
	FIO_COPY_FILE_ERR_CopyFailed = 3;


function copyFile(the_dst_path, the_src_path, b_overwrite) {

	the_dst_path = unescape(the_dst_path);
	the_src_path = unescape(the_src_path);

	if (fso.FileExists(the_src_path)) {
		if (!fso.FileExists(the_dst_path) || b_overwrite) {

			try {
				fso.CopyFile(the_src_path, the_dst_path);
			}
			catch(er) {
				alert("The File: '" + the_dst_path + "' could not be written to. Is it currently open? Or is the drive locked?");
				return fso.addFileErr(FIO_COPY_FILE_ERR_CopyFailed, the_src_path, the_dst_path);
			}
			return FIO_COPY_FILE_ERR_None;
		}
		return fso.addFileErr(FIO_COPY_FILE_ERR_DstExists, the_src_path, the_dst_path);
	}

	return fso.addFileErr(FIO_COPY_FILE_ERR_SrcDNE, the_src_path, the_dst_path);

}

function areFolderPathsTheSame(p1, p2) {
	p1 = getValidFolderPathName(p1).toLowerCase();
	p2 = getValidFolderPathName(p2).toLowerCase();

	return GetReplaced(p1, "/", "\\") == GetReplaced(p2, "/", "\\");

}
function getValidFolderPathName(pn) {
	return pullOffLastCharIfMatch2(unescape(pn), "\\", "/");
}

function emptyFolder(fldr_path) {
	var fldr = fso.GetFolderIf(getValidFolderPathName(fldr_path));
	if (fldr) {

	}
	return true; ///hmmmmm... well, it's not really an error :).... there was just nuttin 2 do!

}
//assume checked if valid to overwrite
function createFolder(new_path, b_overwrite, b_show_err) {
	var new_fldr = null;
	new_path = getValidFolderPathName(new_path);
	try {
		if (fso.FolderExists(new_path)) {
			if (b_overwrite) new_fldr = fso.GetFolder(new_path);
		} else {
			new_fldr = fso.CreateFolder(new_path);
		}
	}
	catch(er) {

	}
	return new_fldr;
}
function copyFolder(dst_path, src_path, b_overwrite) {

	dst_path = getValidFolderPathName(dst_path);
	src_path = getValidFolderPathName(src_path);

	if (fsoInitted()) {
		var src_fldr, dst_fldr;

		if (src_fldr = fso.GetFolderIf(src_path)) {

			try {

				if (fso.FolderExists(dst_path)) {
					dst_fldr = b_overwrite ? fso.GetFolder(dst_path) : null;
				} else {
					dst_fldr = fso.CreateFolder(dst_path);
				}

				if (dst_fldr) {
					var src_file_name, dst_file_name;

					if (!fso.b_moz) {
						var eFolder = new Enumerator(src_fldr.Files);

						while (!eFolder.atEnd()) {
							one_f = eFolder.item();
							dst_file_name = dst_fldr + "/" + one_f.Name;
							fso.CopyFile(one_f, dst_file_name);
							eFolder.moveNext();
						}
					} else {
						netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
						var de = src_fldr.directoryEntries;

						while (de.hasMoreElements()) {
							one_f = de.getNext().QueryInterface(Components.interfaces.nsILocalFile);
							if (one_f.isFile()) { //is there any other possiblity? bbbb

								try {
									fso.CopyFileO(one_f, dst_path + "/" + fso.GetName(one_f));
								}
								catch(er) {
									return false;
								}
							}
						}
					}

					return true;

				}
			}//xxtodo: proper errors for moz
			catch(er) {
				var s = "There was an error trying to copy files on your hard-drive: " + er.description + ":" + dst_path;
				if (er.number == -2146828218) {
					s += cr + "You do not have permission to write to the folder " + dst_path;
					s += cr + "Please have your administrator install Virtual Gallerie into a folder that you have permission to write files to.";
				}
				alert(s);
				return false;
			}

		} else {
			alert ("The folder you were trying to copy: '" + src_path + "' does not exist!");
		}
	}
	return false;
}


function folderExists(fldr_path) {
	if (fsoInitted() && fso.FolderExists(fldr_path)) return true;
	return false;
}

function getFolderOrCreate(fldr_path) {
	if (fsoInitted()) {
		if (fso.FolderExists(fldr_path)) return fso.GetFolder(fldr_path);
		else return fso.CreateFolder(fldr_path);
	}
	return null;
}

function getConcatCrntPathAndNox() {
	return (getLastChar(fbo.crnt_path) == DIR_SEP)
		? fbo.crnt_path + fbo.fn_nox
		: fbo.crnt_path + DIR_SEP + fbo.fn_nox;
}

function replaceToDirSep(s) {
	return GetReplaced(s, "\\", DIR_SEP);
}

function addEndSlashIfNone(p) {
	if (getLastChar(p) != DIR_SEP) p += DIR_SEP;
	return p;
}

function removeEndSlashIfOne(p) {
	return (getLastChar(p) == DIR_SEP) ? pullOffLastChar(p) : p;
}

function addURLPrefixIfNecessary(p) {
	return ((p.charAt(0) == ".") || (p.indexOf(gs_urlPrefix) == 0)) ? p : gs_urlPrefix + p;
}

function addToPath(u) {
	var a = addToPath.arguments;

	if (a.length > 1) {
		u = pullOffLastCharIfMatch(u, DIR_SEP);
		for (var i = 1; i < a.length; i++) {
			u += DIR_SEP + a[i];
		}
	}
	return u;
}

function copySrcFileIfNotBelowDst(orig_src, dst_pre_path, b_overwrite) {

	var os = pullOffFileOrHTTP(orig_src);
	var dp = pullOffFileOrHTTP(dst_pre_path);

	if (os.indexOf(dp) == 0) {
		return "";
	}

	return copySrcFile(orig_src, dst_pre_path, b_overwrite);

}

function prependMyDirOrPullFile(p) {
	if (p.indexOf(gs_filePrefix) == 0) return p.substr(gi_filePrefixLen);
	else if(p.indexOf("file:") == 0) return p.substr(7);
	else return myDir + DIR_SEP + p;
}

function copySrcFile(orig_src, dst_pre_path, b_overwrite) {
	var fi = orig_src.lastIndexOf("/");

	if (fi > -1) {
		var file_name = orig_src.substr(fi + 1);
		var dst_path = dst_pre_path + file_name;
		var src_path = prependMyDirOrPullFile(orig_src);

		dst_path = unescape(GetReplaced(dst_path, "/", "\\"));
		src_path = unescape(GetReplaced(src_path, "/", "\\"));
		//alert(src_path);
		switch(copyFile(dst_path, src_path, b_overwrite)) {
		case FIO_COPY_FILE_ERR_CopyFailed:
		case FIO_COPY_FILE_ERR_SrcDNE:
			return "";
			break;
		case FIO_COPY_FILE_ERR_None:
		case FIO_COPY_FILE_ERR_DstExists:
			return file_name;
			break;
		}
	}
	return ""; // didn't replace anything, either didnt need it, or failed, but implies "don't change this attrib in the elem!"
}

function pathIsLocal(p) {
	return p.indexOf("file:" == 0);
}

function fixImagePathForSrc(p) { //this is local

	if (gb_mac) {
		var i = p.indexOf("private/");
		if ((i == 0) || (i == 1) || ((i = p.indexOf("volumes/")) == 0) || (i == 1)) return gs_filePrefix + p.substring(i + 8);
		else if (p.indexOf("/") == 0) return gs_filePrefix + p.substring(1);
		else if (p.indexOf("Users") == 0) return gs_filePrefix + p;
        //if (p.indexOf("/Users") == 0) return gs_filePrefix + p.substring(1);
	} else {
		if (p.indexOf(":") == 1) { //local drive... need to fix for mac todo: mac
			return ismoz() ? gs_filePrefix + p : p;
		}
	}

	if (!ismoz()) {
		return pullOffFile(p);
	}
	return p;
}

