From 85e1e6c19cc8dc847417d25b0f720788ad31653c Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 21 2019 22:13:20 +0000
Subject: [PATCH 1/8] Version number bump.


---

diff --git a/manifest.json b/manifest.json
index 1a0471e..b299846 100644
--- a/manifest.json
+++ b/manifest.json
@@ -2,7 +2,7 @@
   "manifest_version": 2,
   "name": "GNU LibreJS [webExtensions]",
   "short_name": "LibreJS [experimental]",
-  "version": "7.19rc3",
+  "version": "7.19rc4",
   "author": "various",
   "description": "Only allows free and/or trivial Javascript to run.",
   "applications": {

From 14bed707e5c9891d4502e276a757bbef014e6b4e Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 21 2019 23:41:05 +0000
Subject: [PATCH 2/8] Deduplicate inline scripts and provide widgets to show them in main UI.


---

diff --git a/html/display_panel/content/display-panel.html b/html/display_panel/content/display-panel.html
index 0e4df97..5eccf60 100644
--- a/html/display_panel/content/display-panel.html
+++ b/html/display_panel/content/display-panel.html
@@ -73,7 +73,8 @@
           </p>
           <ul>
             <li id="li-template">
-                <a class="script-url" href="#"></a>:
+                <button class="toggle-source" title="Show/Hide code inline">👓</button><a class="script-url" href="#"></a>:
+                <pre class="source">No code</pre>
                 <p class="reason"></p>
                 <div class="buttons">
                   <button class="whitelist">Whitelist</button>
@@ -81,6 +82,7 @@
                   <button class="forget">Forget</button>
                   <button class="forget" name="*">Forget <span class="domain"></span></button>
                 </div>
+
               </li>
           </ul>
         </div>
diff --git a/html/display_panel/content/main_panel.js b/html/display_panel/content/main_panel.js
index 7934fee..60eae55 100644
--- a/html/display_panel/content/main_panel.js
+++ b/html/display_panel/content/main_panel.js
@@ -55,6 +55,10 @@ liTemplate.remove();
 
 document.querySelector("#info").addEventListener("click", e => {
 	let button = e.target;
+  if (button.matches(".toggle-source")) {
+    let sourceContainer = button.parentNode.querySelector(".source").classList.toggle("visible");
+    return;
+  }
 	if (!button.matches(".buttons > button")) return;
 	let li = button.closest("li");
 	let entry = li && li._scriptEntry || [currentReport.url, "Page's site"];
@@ -111,7 +115,7 @@ function createList(data, group){
    container.classList.add("empty");
  }
  // generate list
- let viewSourceToHuman = /^view-source:(.*)#line(\d+)\(([^)]*)\).*/;
+ let viewSourceToHuman = /^view-source:(.*)#line(\d+)\(([^)]*)\)[^]*/;
  for (let entry of entries) {
    let [scriptId, reason] = entry;
 	 let li = liTemplate.cloneNode(true);
@@ -119,6 +123,11 @@ function createList(data, group){
 	 a.href = scriptId.split("(")[0];
    if (scriptId.startsWith("view-source:")) {
      a.target ="LibreJS-ViewSource";
+     let source = scriptId.split("\n")[1];
+     if (source)  {
+       li.querySelector(".source").textContent = decodeURIComponent(source);
+       li.querySelector(".toggle-source").style.display = "inline";
+     }
      scriptId = scriptId.replace(viewSourceToHuman, "$3 at line $2 of $1");
    }
    a.textContent = scriptId;
diff --git a/html/display_panel/content/panel-styles.css b/html/display_panel/content/panel-styles.css
index d5c3528..1bacc01 100644
--- a/html/display_panel/content/panel-styles.css
+++ b/html/display_panel/content/panel-styles.css
@@ -109,6 +109,20 @@ button:disabled {
   color: #888 !important;
 }
 
+button.toggle-source {
+  display: none;
+}
+pre.source {
+  display: none;
+  background: white;
+  border: 1px solid #444;
+  padding: .5em;
+  overflow: auto;
+  max-height: 8em;
+  white-space: pre-wrap;
+}
+pre.source.visible { display: block }
+
 span.accepted, span.blocked {
     color:#008e00;
     font-size:145%;
diff --git a/main_background.js b/main_background.js
index 65ffe60..324c68e 100644
--- a/main_background.js
+++ b/main_background.js
@@ -1064,6 +1064,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 		// Do not process inline scripts
 		scripts = [];
 	} else {
+		let dejaVu = new Map(); // deduplication map & edited script cache
 		let modified = false;
 		// Deal with intrinsic events
 		let intrinsecindex = 0;
@@ -1071,21 +1072,27 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 		for (let element of html_doc.all) {
 			let line = -1;
 			for (let attr of element.attributes) {
-				if (attr.name.startsWith("on") || (attr.name === "href" && attr.value.toLowerCase().startsWith("javascript:"))){
+				let {name, value} = attr;
+				value = value.trim();
+				if (name.startsWith("on") || (name === "href" && value.toLowerCase().startsWith("javascript:"))){
 					intrinsecindex++;
 					if (line === -1) {
 						line = findLine(intrinsicFinder);
 					}
 					try {
-						let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${attr.name}>)(${intrinsicIndex})`;
-						let edited = await get_script(attr.value, url, tabId, whitelist.contains(url));
-							if (edited) {
-								let value = edited;
-								if (value !== attr.value) {
-									modified = true;
-									attr.value = value;
-								}
-							}
+						let key = `<${element.tagName} ${name}="${value}">`;
+						let edited;
+						if (dejaVu.has(key)) {
+							edited = dejaVu.get(key);
+						} else {
+							let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${name}>)\n${encodeURIComponent(value.trim())}`;
+							edited = await get_script(value, url, tabId, whitelist.contains(documentUrl));
+							dejaVu.set(key, edited);
+						}
+						if (edited && edited !== value) {
+							modified = true;
+							attr.value = edited;
+						}
 					} catch (e) {
 						console.error(e);
 					}
@@ -1099,14 +1106,19 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 			let script = scripts[i];
 			let line = findLine(scriptFinder);
 			if (!script.src && !(script.type && script.type !== "text/javascript")) {
-				let source = script.textContent;
-				let url = `view-source:${documentUrl}#line${line}(<SCRIPT>)(${i})`;
-				let edited = await get_script(source, url, tabId, whitelisted, i);
-				if (edited) {
-					let edited_source = edited[0];
-					let unedited_source = source.trim();
-					if (edited_source.trim() !== unedited_source) {
-						script.textContent = edited_source;
+				let source = script.textContent.trim();
+				let editedSource;
+				if (dejaVu.has(source)) {
+					editedSource = dejaVu.get(source);
+				} else {
+					let url = `view-source:${documentUrl}#line${line}(<SCRIPT>)\n${encodeURIComponent(source)}`;
+					let edited = await get_script(source, url, tabId, whitelisted, i);
+					editedSource = edited && edited[0].trim();
+					dejaVu.set(url, editedSource);
+				}
+				if (editedSource) {
+					if (source !== editedSource) {
+						script.textContent = editedSource;
 						modified = modifiedInline = true;
 					}
 				}

From c80d6d7f2842e7e07bd2b070d975f898f23b54dd Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 25 2019 12:04:09 +0000
Subject: [PATCH 3/8] Fixed bug preventing javascript: URLs from being correctly processed.


---

diff --git a/main_background.js b/main_background.js
index 324c68e..ebf9358 100644
--- a/main_background.js
+++ b/main_background.js
@@ -1086,6 +1086,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 							edited = dejaVu.get(key);
 						} else {
 							let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${name}>)\n${encodeURIComponent(value.trim())}`;
+							if (name === "href") value = decodeURIComponent(value);
 							edited = await get_script(value, url, tabId, whitelist.contains(documentUrl));
 							dejaVu.set(key, edited);
 						}

From ee895dd3e5e9fd743f6980f57008ce28b71c3bb0 Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 25 2019 12:05:26 +0000
Subject: [PATCH 4/8] Test for inline scripts in attributes, including (de)duplication.


---

diff --git a/test/spec/LibreJSSpec.js b/test/spec/LibreJSSpec.js
index 3d61973..57c7f65 100644
--- a/test/spec/LibreJSSpec.js
+++ b/test/spec/LibreJSSpec.js
@@ -94,6 +94,10 @@ describe("LibreJS' components", () => {
     let addScript = (html, script, before = "</head>") =>
       html.replace(before, `<script>${script}</script>${before}`);
 
+    let addToBody = (html, fragment) => html.replace("</body>", `${fragment}</body>`);
+
+    let jsUrl = js => `javascript:${encodeURIComponent(js)}`;
+
     function extractScripts(html, def = "") {
       let matches = html && html.match(/<script>[^]*?<\/script>/g);
       return matches && matches.join("") || def;
@@ -165,6 +169,21 @@ describe("LibreJS' components", () => {
       expect(scripts).toContain(licensed);
       expect(scripts.replace(licensed, "")).not.toContain(nontrivial);
     });
+
+    it("should correctly process (de)duplicated inline scripts", async () => {
+      let trivialAsUrl = jsUrl(trivial);
+      let nontrivialAsUrl = jsUrl(nontrivial);
+      let a = (url, label) => `<a href="${url}">${label}</a>`;
+      let mixedPage = `<body></body>`;
+      for (let dup = 0; dup < 3; dup++) {
+        mixedPage = addToBody(mixedPage, a(trivialAsUrl, `Trivial #${dup}`));
+        mixedPage = addToBody(mixedPage, a(nontrivialAsUrl, `Nontrivial #${dup}`));
+      }
+      let processed = await processHtml(mixedPage);
+      expect(processed).not.toBeNull();
+      expect(processed).toContain(trivialAsUrl);
+      expect(processed).not.toContain(nontrivialAsUrl);
+    });
   });
 
   describe("The external (Web Labels) license checker", () => {

From 881101334654012dd2289b5a73f123bb5d55a462 Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 25 2019 21:22:13 +0000
Subject: [PATCH 5/8] Generate code view widget for first inline script with global license too.


---

diff --git a/main_background.js b/main_background.js
index ebf9358..7bbc237 100644
--- a/main_background.js
+++ b/main_background.js
@@ -1053,13 +1053,15 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 	let findLine = finder => finder.test(html) && html.substring(0, finder.lastIndex).split(/\n/).length || 0;
 	if (read_metadata(meta_element) || license) {
 		console.log("Valid license for intrinsic events found");
-		let line = 0;
+		let line, extras;
 		if (meta_element) {
 		  line = findLine(/id\s*=\s*['"]?LibreJS-info\b/gi);
+			extras = "(0)";
 		} else if (license) {
 			line = html.substring(0, html.indexOf(first_script_src)).split(/\n/).length;
+			extras = "\n" + encodeURIComponent(first_script_src);
 		}
-		let viewUrl = line ? `view-source:${documentUrl}#line${line}(<${meta_element ? meta_element.tagName : "SCRIPT"}>)(0)` : url;
+		let viewUrl = line ? `view-source:${documentUrl}#line${line}(<${meta_element ? meta_element.tagName : "SCRIPT"}>)${extras}` : url;
 		addReportEntry(tabId, url, {url, "accepted":[viewUrl, `Global license for the page: ${license}`]});
 		// Do not process inline scripts
 		scripts = [];

From 5d9ab3778bcdb12913333deff64196590688789f Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Feb 25 2019 22:05:22 +0000
Subject: [PATCH 6/8] Cosmetic changes to the inline code viewer toggle button.


---

diff --git a/html/display_panel/content/display-panel.html b/html/display_panel/content/display-panel.html
index 5eccf60..5b9f99f 100644
--- a/html/display_panel/content/display-panel.html
+++ b/html/display_panel/content/display-panel.html
@@ -73,8 +73,10 @@
           </p>
           <ul>
             <li id="li-template">
-                <button class="toggle-source" title="Show/Hide code inline">👓</button><a class="script-url" href="#"></a>:
-                <pre class="source">No code</pre>
+                <button class="toggle-source show" title="Show code inline">Show</button>
+                <button class="toggle-source hide" title="Hide code inline">Hide</button>
+                <a class="script-url" href="#" target="librejs_viewsource"></a>:
+                <pre class="source"></pre>
                 <p class="reason"></p>
                 <div class="buttons">
                   <button class="whitelist">Whitelist</button>
diff --git a/html/display_panel/content/main_panel.js b/html/display_panel/content/main_panel.js
index 60eae55..022be8c 100644
--- a/html/display_panel/content/main_panel.js
+++ b/html/display_panel/content/main_panel.js
@@ -55,8 +55,17 @@ liTemplate.remove();
 
 document.querySelector("#info").addEventListener("click", e => {
 	let button = e.target;
+  if (button.tagName === "A") {
+    setTimeout(close, 100);
+    return;
+  }
   if (button.matches(".toggle-source")) {
-    let sourceContainer = button.parentNode.querySelector(".source").classList.toggle("visible");
+    let parent = button.parentNode;
+    if (!parent.querySelector(".source").textContent) {
+      parent.querySelector("a").click();
+    } else {
+      parent.classList.toggle("visible");
+    }
     return;
   }
 	if (!button.matches(".buttons > button")) return;
diff --git a/html/display_panel/content/panel-styles.css b/html/display_panel/content/panel-styles.css
index 1bacc01..502323f 100644
--- a/html/display_panel/content/panel-styles.css
+++ b/html/display_panel/content/panel-styles.css
@@ -110,8 +110,12 @@ button:disabled {
 }
 
 button.toggle-source {
-  display: none;
+  color: #004;
+  margin-right: .5em;
+  width: 4em;
+  overflow: hide;
 }
+
 pre.source {
   display: none;
   background: white;
@@ -121,7 +125,11 @@ pre.source {
   max-height: 8em;
   white-space: pre-wrap;
 }
-pre.source.visible { display: block }
+
+button.hide { display: none  }
+.visible > button.show { display: none !important}
+.visible > pre.source { display: block }
+.visible > button.hide { display: initial }
 
 span.accepted, span.blocked {
     color:#008e00;

From 3f325cea256c5fd082a1c029d27f63ab93440ba6 Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Mar 04 2019 23:58:13 +0000
Subject: [PATCH 7/8] Fixed inline whitelisting regressions (issue #35).


---

diff --git a/bg/ListManager.js b/bg/ListManager.js
index e0a85e9..354866d 100644
--- a/bg/ListManager.js
+++ b/bg/ListManager.js
@@ -50,6 +50,14 @@ class ListManager {
   */
   getStatus(key, defValue = "unknown") {
     let {blacklist, whitelist} = this.lists;
+    let inline = ListStore.viewSourceItem(key);
+    if (inline) {
+      return blacklist.contains(inline)
+        ? "blacklisted"
+        : whitelist.contains(inline) ? "whitelisted"
+        : defValue;
+    }
+
     let match = key.match(/\(([^)]+)\)(?=[^()]*$)/);
     if (!match) {
       let url = ListStore.urlItem(key);
@@ -61,7 +69,6 @@ class ListManager {
     }
 
   	let [hashItem, srcHash] = match; // (hash), hash
-
   	return blacklist.contains(hashItem) ? "blacklisted"
   			: this.builtInHashes.has(srcHash) || whitelist.contains(hashItem)
         ? "whitelisted"
diff --git a/common/Storage.js b/common/Storage.js
index a83ce8f..415b4bb 100644
--- a/common/Storage.js
+++ b/common/Storage.js
@@ -66,6 +66,9 @@ class ListStore {
     });
   }
 
+  static viewSourceItem(url) {
+    return url.startsWith("view-source:") && url.replace(/#line\d+/,"#");
+  }
   static hashItem(hash) {
     return hash.startsWith("(") ? hash : `(${hash})`;
   }
diff --git a/html/display_panel/content/main_panel.js b/html/display_panel/content/main_panel.js
index 022be8c..83c3a6b 100644
--- a/html/display_panel/content/main_panel.js
+++ b/html/display_panel/content/main_panel.js
@@ -132,9 +132,9 @@ function createList(data, group){
 	 a.href = scriptId.split("(")[0];
    if (scriptId.startsWith("view-source:")) {
      a.target ="LibreJS-ViewSource";
-     let source = scriptId.split("\n")[1];
+     let source = scriptId.match(/\n([^]*)/);
      if (source)  {
-       li.querySelector(".source").textContent = decodeURIComponent(source);
+       li.querySelector(".source").textContent = source[1];
        li.querySelector(".toggle-source").style.display = "inline";
      }
      scriptId = scriptId.replace(viewSourceToHuman, "$3 at line $2 of $1");
diff --git a/main_background.js b/main_background.js
index 7bbc237..4442c6d 100644
--- a/main_background.js
+++ b/main_background.js
@@ -336,7 +336,11 @@ async function connected(p) {
 		for (let action of ["whitelist", "blacklist", "forget"]) {
 			if (m[action]) {
 				let [key] = m[action];
-				if (m.site) key = ListStore.siteItem(key);
+				if (m.site) {
+					key = ListStore.siteItem(key);
+				} else {
+					key = ListStore.viewSourceItem(key) || key;
+				}
 				await listManager[action](key);
 				update = true;
 			}
@@ -776,23 +780,20 @@ async function get_script(response, url, tabId = -1, whitelisted = false, index 
 	let report = activityReports[tabId] || (activityReports[tabId] = await createReport({tabId}));
 	updateBadge(tabId, report, !verdict);
 	let category = await addReportEntry(tabId, sourceHash, {"url": domain, [verdict ? "accepted" : "blocked"]: [url, reason]});
-	let scriptSource = verdict ? response : editedSource;
 	switch(category) {
 		case "blacklisted":
-			if (response.startsWith("javascript:"))
-				return result(`# LibreJS: script ${category} by user.`);
-			else
-				return result(`/* LibreJS: script ${category} by user. */`);
+			editedSource = `/* LibreJS: script ${category} by user. */`;
+			return result(response.startsWith("javascript:")
+				? `javascript:void(${encodeURIComponent(editedSource)})` : editedSource);
 		case "whitelisted":
-			if (response.startsWith("javascript:"))
-				return result(scriptSource);
-			else
-				return result(`/* LibreJS: script ${category} by user. */\n${scriptSource}`);
+			return result(response.startsWith("javascript:")
+				? response : `/* LibreJS: script ${category} by user. */\n${response}`);
 		default:
-                        if (response.startsWith("javascript:"))
-				return result(scriptSource);
-			else
-				return result(`/* LibreJS: script ${category}. */\n${scriptSource}`);
+			let scriptSource = verdict ? response : editedSource;
+      return result(response.startsWith("javascript:")
+				? (verdict ? scriptSource : `javascript:void(/* ${scriptSource} */)`)
+				: `/* LibreJS: script ${category}. */\n${scriptSource}`
+			);
 	}
 }
 
@@ -1059,7 +1060,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 			extras = "(0)";
 		} else if (license) {
 			line = html.substring(0, html.indexOf(first_script_src)).split(/\n/).length;
-			extras = "\n" + encodeURIComponent(first_script_src);
+			extras = "\n" + first_script_src;
 		}
 		let viewUrl = line ? `view-source:${documentUrl}#line${line}(<${meta_element ? meta_element.tagName : "SCRIPT"}>)${extras}` : url;
 		addReportEntry(tabId, url, {url, "accepted":[viewUrl, `Global license for the page: ${license}`]});
@@ -1087,10 +1088,9 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 						if (dejaVu.has(key)) {
 							edited = dejaVu.get(key);
 						} else {
-							let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${name}>)\n${encodeURIComponent(value.trim())}`;
+							let url = `view-source:${documentUrl}#line${line}(<${element.tagName} ${name}>)\n${value.trim()}`;
 							if (name === "href") value = decodeURIComponent(value);
-							edited = await get_script(value, url, tabId, whitelist.contains(documentUrl));
-							dejaVu.set(key, edited);
+							edited = await get_script(value, url, tabId, whitelist.contains(url));						dejaVu.set(key, edited);
 						}
 						if (edited && edited !== value) {
 							modified = true;
@@ -1114,7 +1114,7 @@ async function editHtml(html, documentUrl, tabId, frameId, whitelisted){
 				if (dejaVu.has(source)) {
 					editedSource = dejaVu.get(source);
 				} else {
-					let url = `view-source:${documentUrl}#line${line}(<SCRIPT>)\n${encodeURIComponent(source)}`;
+					let url = `view-source:${documentUrl}#line${line}(<SCRIPT>)\n${source}`;
 					let edited = await get_script(source, url, tabId, whitelisted, i);
 					editedSource = edited && edited[0].trim();
 					dejaVu.set(url, editedSource);

From 1e4ce528dec55b79501e15ef08b751b4f533d756 Mon Sep 17 00:00:00 2001
From: hackademix <giorgio@maone.net>
Date: Mar 11 2019 22:57:36 +0000
Subject: [PATCH 8/8] Fix for large scripts thrashing the black/white lists when added.


---

diff --git a/bg/ListManager.js b/bg/ListManager.js
index 354866d..2f5f74e 100644
--- a/bg/ListManager.js
+++ b/bg/ListManager.js
@@ -50,7 +50,7 @@ class ListManager {
   */
   getStatus(key, defValue = "unknown") {
     let {blacklist, whitelist} = this.lists;
-    let inline = ListStore.viewSourceItem(key);
+    let inline = ListStore.inlineItem(key);
     if (inline) {
       return blacklist.contains(inline)
         ? "blacklisted"
diff --git a/common/Storage.js b/common/Storage.js
index 415b4bb..8010f3f 100644
--- a/common/Storage.js
+++ b/common/Storage.js
@@ -66,8 +66,12 @@ class ListStore {
     });
   }
 
-  static viewSourceItem(url) {
-    return url.startsWith("view-source:") && url.replace(/#line\d+/,"#");
+  static inlineItem(url) {
+    // here we simplify and hash inline script references
+    return url.startsWith("inline:") ? url
+      : url.startsWith("view-source:")
+        && url.replace(/^view-source:[\w-+]+:\/+([^/]+).*#line\d+/,"inline://$1#")
+              .replace(/\n[^]*/, s => s.replace(/\s+/g, ' ').substring(0, 16) + "…" + hash(s.trim()));
   }
   static hashItem(hash) {
     return hash.startsWith("(") ? hash : `(${hash})`;
@@ -128,6 +132,14 @@ class ListStore {
     return this.items.has(item);
   }
 }
+
+var jssha = require('jssha');
+function hash(source){
+	var shaObj = new jssha("SHA-256","TEXT")
+	shaObj.update(source);
+	return shaObj.getHash("HEX");
+}
+
 if (typeof module === "object") {
-  module.exports = { ListStore, Storage };
+  module.exports = { ListStore, Storage, hash };
 }
diff --git a/main_background.js b/main_background.js
index 4442c6d..8060ebd 100644
--- a/main_background.js
+++ b/main_background.js
@@ -22,10 +22,9 @@
 
 var acorn = require('acorn');
 var acornLoose = require('acorn-loose');
-var jssha = require('jssha');
 var legacy_license_lib = require("./legacy_license_check.js");
 var {ResponseProcessor} = require("./bg/ResponseProcessor");
-var {Storage, ListStore} = require("./common/Storage");
+var {Storage, ListStore, hash} = require("./common/Storage");
 var {ListManager} = require("./bg/ListManager");
 var {ExternalLicenses} = require("./bg/ExternalLicenses");
 
@@ -51,16 +50,6 @@ function dbg_print(a,b){
 	}
 }
 
-/**
-*	Wrapper around crypto lib
-*
-*/
-function hash(source){
-	var shaObj = new jssha("SHA-256","TEXT")
-	shaObj.update(source);
-	return shaObj.getHash("HEX");
-}
-
 /*
 	NONTRIVIAL THINGS:
 	- Fetch
@@ -339,7 +328,7 @@ async function connected(p) {
 				if (m.site) {
 					key = ListStore.siteItem(key);
 				} else {
-					key = ListStore.viewSourceItem(key) || key;
+					key = ListStore.inlineItem(key) || key;
 				}
 				await listManager[action](key);
 				update = true;

