diff --git a/chrome/content/zotero/bindings/itembox.xml b/chrome/content/zotero/bindings/itembox.xml index 4bbbe6093f..ee63273f21 100644 --- a/chrome/content/zotero/bindings/itembox.xml +++ b/chrome/content/zotero/bindings/itembox.xml @@ -416,10 +416,12 @@ } // TEMP - NSF (homepage) - if ((fieldName == 'url' || fieldName == 'homepage') && val) { + if ((fieldName == 'url' || fieldName == 'homepage') + // Only make plausible HTTP URLs clickable + && Zotero.Utilities.isHTTPURL(val, true)) { label.classList.add("pointer"); // TODO: make getFieldValue non-private and use below instead - label.setAttribute("onclick", "ZoteroPane_Local.loadURI(this.nextSibling.firstChild ? this.nextSibling.firstChild.nodeValue : this.nextSibling.value, event)"); + label.setAttribute("onclick", "Zotero.launchURL(this.nextSibling.firstChild ? this.nextSibling.firstChild.nodeValue : this.nextSibling.value)"); label.setAttribute("tooltiptext", Zotero.getString('locate.online.tooltip')); } else if (fieldName == 'DOI' && val && typeof val == 'string') { diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js index 39d6dbafca..d677064f05 100644 --- a/chrome/content/zotero/xpcom/utilities.js +++ b/chrome/content/zotero/xpcom/utilities.js @@ -183,7 +183,13 @@ Zotero.Utilities = { var x = x.replace(/^[\x00-\x27\x29-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F\s]+/, ""); return x.replace(/[\x00-\x28\x2A-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F\s]+$/, ""); }, - + + isHTTPURL: function (url, allowNoScheme = false) { + // From https://stackoverflow.com/a/3809435 + var noSchemeRE = /^[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; + return /^https?:\/\//.test(url) || (allowNoScheme && noSchemeRE.test(url)); + }, + /** * Cleans a http url string * @param url {String} diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index db46d6151b..ca98cab9e7 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -1028,8 +1028,13 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js"); * Used only by Standalone */ this.launchURL = function (url) { - if (!url.match(/^https?/)) { - throw new Error("launchURL() requires an HTTP(S) URL"); + if (!Zotero.Utilities.isHTTPURL(url)) { + if (Zotero.Utilities.isHTTPURL(url, true)) { + url = 'http://' + url; + } + else { + throw new Error("launchURL() requires an HTTP(S) URL"); + } } try { diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index 3f76aae7a9..31f49a406a 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -3270,8 +3270,8 @@ var ZoteroPane = new function() return; } - if(uri.match(/^https?/)) { - this.launchURL(uri); + if (uri.match(/^(chrome|resource):/)) { + Zotero.openInViewer(uri); continue; } @@ -3287,7 +3287,7 @@ var ZoteroPane = new function() } } - Zotero.openInViewer(uri); + this.launchURL(uri); } } diff --git a/test/tests/utilitiesTest.js b/test/tests/utilitiesTest.js index 81d035a3fb..d24450f017 100644 --- a/test/tests/utilitiesTest.js +++ b/test/tests/utilitiesTest.js @@ -34,6 +34,33 @@ describe("Zotero.Utilities", function() { }); + describe("#isHTTPURL()", function () { + it("should return true for HTTP URL", function () { + assert.isTrue(Zotero.Utilities.isHTTPURL('http://example.com')); + }); + + it("should return true for HTTPS URL", function () { + assert.isTrue(Zotero.Utilities.isHTTPURL('https://example.com')); + }); + + it("should return false for plausible HTTP URL if allowNoScheme not provided", function () { + assert.isFalse(Zotero.Utilities.isHTTPURL('example.com')); + }); + + it("should return false for plausible HTTP URL if allowNoScheme is true", function () { + assert.isTrue(Zotero.Utilities.isHTTPURL('example.com', true)); + }); + + it("should return false for file URL", function () { + assert.isFalse(Zotero.Utilities.isHTTPURL('file:///c:/path/to/file.txt')); + }); + + it("should return false for zotero: URL", function () { + assert.isFalse(Zotero.Utilities.isHTTPURL('zotero://select/library/items/AAAAAAAA')); + }); + }); + + describe("#cleanDOI()", function () { var cleanDOI = Zotero.Utilities.cleanDOI; var doi = '10.1088/1748-9326/11/4/048002';