<commit_before>
var sbBrowserOverlay = {

	lastLocation: "",
	editMode: false,
	infoMode: false,
	resource: null,
	locateMe: null,

	webProgressListener: {
		onLocationChange: function(aProgress, aRequest, aURI) {
			sbBrowserOverlay.onLocationChange(aURI ? aURI.spec : "about:blank");
		},
		onStateChange      : function(){},
		onProgressChange   : function(){},
		onStatusChange     : function(){},
		onSecurityChange   : function(){},
		onLinkIconAvailable: function(){},
		QueryInterface: function(aIID) {
			if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
			    aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
			    aIID.equals(Components.interfaces.nsISupports))
				return this;
			throw Components.results.NS_NOINTERFACE;
		},
	},

	init: function()
	{
		document.getElementById("contentAreaContextMenu").addEventListener(
			"popupshowing", this, false
		);
		this.refresh();
		gBrowser.addProgressListener(this.webProgressListener);
		if (sbCommonUtils.getPref("ui.contextMenu", false) && 
		    sbCommonUtils.getPref("ui.contextSubMenu", false)) {
			var callback = function() {
				document.getElementById("ScrapBookContextSubmenu").hidden = false;
				for (var i = 1; i <= 10; i++) {
					document.getElementById("ScrapBookContextSubmenu").firstChild.appendChild(
						document.getElementById("ScrapBookContextMenu" + i)
					);
				}
			};
			window.setTimeout(callback, 1000);
		}
		if (sbCommonUtils.getPref("ui.menuBar.icon", false)) {
			var menu   = document.getElementById("ScrapBookMenu");
			var button = document.createElement("toolbarbutton");
			var attrs = menu.attributes;
			for (var i = 0; i < attrs.length; i++)
				button.setAttribute(attrs[i].nodeName, attrs[i].nodeValue);
			while (menu.hasChildNodes())
				button.appendChild(menu.firstChild);
			button.removeAttribute("label");
			button.setAttribute("type", "menu");
			button.setAttribute("image", "chrome://scrapbook/skin/main_16.png");
			var menubar = document.getElementById("main-menubar");
			menubar.appendChild(button);
			menubar.removeChild(menu);
		}
		var key = sbCommonUtils.getPref("key.menubar", "");
		if (key.length == 1) {
			var elt = document.getElementById("ScrapBookMenu");
			elt.setAttribute("accesskey", key);
		}
		var keyMap = {
			"key.sidebar"       : "key_openScrapBookSidebar",
			"key.capture"       : "key_ScrapBookCapture",
			"key.captureAs"     : "key_ScrapBookCaptureAs",
			"key.captureAllTabs": "key_ScrapBookSaveAllTabs",
			"key.bookmark"      : "key_BookmarkWithScrapBook",
		};
		for (let [pref, id] in Iterator(keyMap)) {
			var key = sbCommonUtils.getPref(pref, "");
			var elt = document.getElementById(id);
			if (key.length == 1)
				elt.setAttribute("key", key);
			else
				elt.parentNode.removeChild(elt);
		}
	},

	destroy: function()
	{
		gBrowser.removeProgressListener(this.webProgressListener);
	},

	rebuild: function()
	{
		sbMenuHandler.shouldRebuild = true;
	},

	refresh: function()
	{
		this.lastLocation = "";
		this.dataTitle = "";
		this.editMode = sbPageEditor.TOOLBAR.getAttribute("autoshow") == "true";
		this.infoMode = sbInfoViewer.TOOLBAR.getAttribute("autoshow") == "true";
		document.getElementById("ScrapBookMenu").hidden        = !sbCommonUtils.getPref("ui.menuBar", false);
		if ( !sbCommonUtils._fxVer4 ) {
			document.getElementById("ScrapBookStatusPanel").hidden = !sbCommonUtils.getPref("ui.statusBar", false);
		}
		document.getElementById("ScrapBookToolsMenu").hidden   = !sbCommonUtils.getPref("ui.toolsMenu", false);
		sbDataSource.backup();
		this.setProtocolSubstitution();
		var file = sbCommonUtils.getScrapBookDir().clone();
		file.append("folders.txt");
		if (file.exists()) {
			sbCommonUtils.setPref("ui.folderList", sbCommonUtils.readFile(file));
		}
		else {
			var ids = sbCommonUtils.getPref("ui.folderList", "");
			sbCommonUtils.writeFile(file, ids, "UTF-8");
		}
		this.onLocationChange(gBrowser.currentURI.spec);
	},

	setProtocolSubstitution: function()
	{
		var baseURL = sbCommonUtils.getBaseHref(sbDataSource.data.URI);
		var RPH = sbCommonUtils.IO.getProtocolHandler("resource")
		          .QueryInterface(Components.interfaces.nsIResProtocolHandler);
		if (RPH.hasSubstitution("scrapbook") && (RPH.getSubstitution("scrapbook").spec == baseURL))
			return;
		RPH.setSubstitution("scrapbook", sbCommonUtils.convertURLToObject(baseURL));
	},

	getID: function(aURL)
	{
		if (!aURL)
			aURL = gBrowser.currentURI ? gBrowser.currentURI.spec : "";
		var editable = (aURL.indexOf("file") == 0 && aURL.match(/\/data\/(\d{14})\//));
		return editable ? RegExp.$1 : null;
	},

	onLocationChange: function(aURL)
	{
		if (aURL && aURL != (gBrowser.currentURI ? gBrowser.currentURI.spec : ""))
			return;
		if (aURL.indexOf("file") != 0 && aURL == this.lastLocation)
			return;
		var id = this.getID(aURL);
		document.getElementById("ScrapBookToolbox").hidden = id ? false : true;
		if (id) {
			this.resource = sbCommonUtils.RDF.GetResource("urn:scrapbook:item" + id);
			if (this.editMode)
				window.setTimeout(function() { sbPageEditor.init(id); }, 20);
			else
				window.setTimeout(function() { sbPageEditor.showHide(false); }, 0);
			if (this.infoMode)
				window.setTimeout(function() { sbInfoViewer.init(id); }, 50);
		}
		this.locateMe = null;
		this.lastLocation = aURL;
	},

	buildPopup: function(aPopup)<commit_msg>Use precise detection of ID in sbBrowserOverlay.getID to prevent leaks. Exclude the "?" search or "#" hash, and allow only real files (excluding folders).<commit_after>
var sbBrowserOverlay = {

	lastLocation: "",
	editMode: false,
	infoMode: false,
	resource: null,
	locateMe: null,

	webProgressListener: {
		onLocationChange: function(aProgress, aRequest, aURI) {
			sbBrowserOverlay.onLocationChange(aURI ? aURI.spec : "about:blank");
		},
		onStateChange      : function(){},
		onProgressChange   : function(){},
		onStatusChange     : function(){},
		onSecurityChange   : function(){},
		onLinkIconAvailable: function(){},
		QueryInterface: function(aIID) {
			if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
			    aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
			    aIID.equals(Components.interfaces.nsISupports))
				return this;
			throw Components.results.NS_NOINTERFACE;
		},
	},

	init: function()
	{
		document.getElementById("contentAreaContextMenu").addEventListener(
			"popupshowing", this, false
		);
		this.refresh();
		gBrowser.addProgressListener(this.webProgressListener);
		if (sbCommonUtils.getPref("ui.contextMenu", false) && 
		    sbCommonUtils.getPref("ui.contextSubMenu", false)) {
			var callback = function() {
				document.getElementById("ScrapBookContextSubmenu").hidden = false;
				for (var i = 1; i <= 10; i++) {
					document.getElementById("ScrapBookContextSubmenu").firstChild.appendChild(
						document.getElementById("ScrapBookContextMenu" + i)
					);
				}
			};
			window.setTimeout(callback, 1000);
		}
		if (sbCommonUtils.getPref("ui.menuBar.icon", false)) {
			var menu   = document.getElementById("ScrapBookMenu");
			var button = document.createElement("toolbarbutton");
			var attrs = menu.attributes;
			for (var i = 0; i < attrs.length; i++)
				button.setAttribute(attrs[i].nodeName, attrs[i].nodeValue);
			while (menu.hasChildNodes())
				button.appendChild(menu.firstChild);
			button.removeAttribute("label");
			button.setAttribute("type", "menu");
			button.setAttribute("image", "chrome://scrapbook/skin/main_16.png");
			var menubar = document.getElementById("main-menubar");
			menubar.appendChild(button);
			menubar.removeChild(menu);
		}
		var key = sbCommonUtils.getPref("key.menubar", "");
		if (key.length == 1) {
			var elt = document.getElementById("ScrapBookMenu");
			elt.setAttribute("accesskey", key);
		}
		var keyMap = {
			"key.sidebar"       : "key_openScrapBookSidebar",
			"key.capture"       : "key_ScrapBookCapture",
			"key.captureAs"     : "key_ScrapBookCaptureAs",
			"key.captureAllTabs": "key_ScrapBookSaveAllTabs",
			"key.bookmark"      : "key_BookmarkWithScrapBook",
		};
		for (let [pref, id] in Iterator(keyMap)) {
			var key = sbCommonUtils.getPref(pref, "");
			var elt = document.getElementById(id);
			if (key.length == 1)
				elt.setAttribute("key", key);
			else
				elt.parentNode.removeChild(elt);
		}
	},

	destroy: function()
	{
		gBrowser.removeProgressListener(this.webProgressListener);
	},

	rebuild: function()
	{
		sbMenuHandler.shouldRebuild = true;
	},

	refresh: function()
	{
		this.lastLocation = "";
		this.dataTitle = "";
		this.editMode = sbPageEditor.TOOLBAR.getAttribute("autoshow") == "true";
		this.infoMode = sbInfoViewer.TOOLBAR.getAttribute("autoshow") == "true";
		document.getElementById("ScrapBookMenu").hidden        = !sbCommonUtils.getPref("ui.menuBar", false);
		if ( !sbCommonUtils._fxVer4 ) {
			document.getElementById("ScrapBookStatusPanel").hidden = !sbCommonUtils.getPref("ui.statusBar", false);
		}
		document.getElementById("ScrapBookToolsMenu").hidden   = !sbCommonUtils.getPref("ui.toolsMenu", false);
		sbDataSource.backup();
		this.setProtocolSubstitution();
		var file = sbCommonUtils.getScrapBookDir().clone();
		file.append("folders.txt");
		if (file.exists()) {
			sbCommonUtils.setPref("ui.folderList", sbCommonUtils.readFile(file));
		}
		else {
			var ids = sbCommonUtils.getPref("ui.folderList", "");
			sbCommonUtils.writeFile(file, ids, "UTF-8");
		}
		this.onLocationChange(gBrowser.currentURI.spec);
	},

	setProtocolSubstitution: function()
	{
		var baseURL = sbCommonUtils.getBaseHref(sbDataSource.data.URI);
		var RPH = sbCommonUtils.IO.getProtocolHandler("resource")
		          .QueryInterface(Components.interfaces.nsIResProtocolHandler);
		if (RPH.hasSubstitution("scrapbook") && (RPH.getSubstitution("scrapbook").spec == baseURL))
			return;
		RPH.setSubstitution("scrapbook", sbCommonUtils.convertURLToObject(baseURL));
	},

	getID: function(aURL)
	{
		if (!aURL) aURL = gBrowser.currentURI ? gBrowser.currentURI.spec : "";
		var file = sbCommonUtils.convertURLToFile(aURL);
		if (!file || !file.isFile()) return null;
		var aURL = sbCommonUtils.convertFilePathToURL(file.path);
		var editable = (aURL.indexOf("file:") == 0 && aURL.match(/\/data\/(\d{14})\//));
		return editable ? RegExp.$1 : null;
	},

	onLocationChange: function(aURL)
	{
		if (aURL && aURL != (gBrowser.currentURI ? gBrowser.currentURI.spec : ""))
			return;
		if (aURL.indexOf("file") != 0 && aURL == this.lastLocation)
			return;
		var id = this.getID(aURL);
		document.getElementById("ScrapBookToolbox").hidden = id ? false : true;
		if (id) {
			this.resource = sbCommonUtils.RDF.GetResource("urn:scrapbook:item" + id);
			if (this.editMode)
				window.setTimeout(function() { sbPageEditor.init(id); }, 20);
			else
				window.setTimeout(function() { sbPageEditor.showHide(false); }, 0);
			if (this.infoMode)
				window.setTimeout(function() { sbInfoViewer.init(id); }, 50);
		}
		this.locateMe = null;
		this.lastLocation = aURL;
	},

	buildPopup: function(aPopup)
{'fraction_non_alphanumeric': 0.15307608299963596, 'fraction_numerical': 0.004368401892974154, 'mean_word_length': 4.489010989010989, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '802387', 'n_tokens_mistral': 4047, 'n_tokens_neox': 3599, 'n_words': 571}