Additional adjustments to URL handling

Follow-up to df40ee7216

- Restore opening of non-HTTP URL schemes in link attachments
- Remove scheme whitelist for link attachments, since it's not enforced
  via the API anyway and we prompt before an external application is
  opened. Instead, just block a few schemes (e.g., 'javascript') from
  launching.

TODO:

- Provide some way to change/reset an application association if the
  user checks the box to automatically open that scheme.
- Show an error message if a link attachment with an invalid URL is
  double-clicked
This commit is contained in:
Dan Stillman 2020-01-04 02:18:00 -05:00
parent 8172f00941
commit 3d2afa9c7f
4 changed files with 33 additions and 23 deletions

View file

@ -606,24 +606,13 @@ Zotero.Attachments = new function(){
var title = options.title;
var collections = options.collections;
/* Throw error on invalid URLs
We currently accept the following protocols:
PersonalBrain (brain://)
DevonThink (x-devonthink-item://)
Notational Velocity (nv://)
MyLife Organized (mlo://)
Evernote (evernote://)
OneNote (onenote://)
Kindle (kindle://)
Logos (logosres:)
Bear (bear://)
MarginNote (marginnoteapp://)
Zotero (zotero://) */
var urlRe = /^((https?|zotero|evernote|onenote|brain|nv|mlo|kindle|x-devonthink-item|bear|marginnoteapp|ftp):\/\/|logosres:)[^\s]*$/;
var matches = urlRe.exec(url);
var matches = url.match(/^([a-z]+):(\/\/)?.+/);
if (!matches) {
throw ("Invalid URL '" + url + "' in Zotero.Attachments.linkFromURL()");
throw new Error(`Invalid URL '${url}'`);
}
var scheme = matches[1];
if (['javascript', 'data', 'chrome', 'resource', 'mailto'].includes(scheme)) {
throw new Error(`Invalid scheme '${scheme}'`);
}
// If no title provided, figure it out from the URL

View file

@ -187,7 +187,8 @@ Zotero.Utilities = {
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));
return /^https?:\/\//.test(url)
|| (allowNoScheme && !url.startsWith('mailto:') && noSchemeRE.test(url));
},
/**

View file

@ -1023,17 +1023,32 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
/**
* Launch an HTTP URL externally, the best way we can
*
* Used only by Standalone
* Launch a URL externally, the best way we can
*/
this.launchURL = function (url) {
if (!Zotero.Utilities.isHTTPURL(url)) {
if (Zotero.Utilities.isHTTPURL(url, true)) {
url = 'http://' + url;
}
// Launch non-HTTP URLs
else {
throw new Error("launchURL() requires an HTTP(S) URL");
let matches = url.match(/^([a-z]+):/);
if (!matches) {
throw new Error(`Invalid URL '${url}'`);
}
let scheme = matches[1];
if (['javascript', 'data', 'chrome', 'resource'].includes(scheme)) {
throw new Error(`Invalid scheme '${scheme}'`);
}
let svc = Components.classes['@mozilla.org/uriloader/external-protocol-service;1']
.getService(Components.interfaces.nsIExternalProtocolService);
let found = {};
let handlerInfo = svc.getProtocolHandlerInfoFromOS(scheme, found);
if (!found.value) {
throw new Error(`Handler not found for '${scheme}' URLs`);
}
svc.loadURI(Services.io.newURI(url, null, null));
return;
}
}
@ -1058,7 +1073,8 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
let exec = Zotero.File.pathToFile(path);
if (!exec.exists()) {
throw ("Fallback executable not found -- check extensions.zotero." + pref + " in about:config");
throw new Error("Fallback executable not found -- "
+ "check extensions.zotero." + pref + " in about:config");
}
var proc = Components.classes["@mozilla.org/process/util;1"]

View file

@ -55,6 +55,10 @@ describe("Zotero.Utilities", function() {
assert.isFalse(Zotero.Utilities.isHTTPURL('file:///c:/path/to/file.txt'));
});
it("should return false for mailto URLs in allowNoScheme mode", function () {
assert.isFalse(Zotero.Utilities.isHTTPURL('mailto:foo@example.com', true));
});
it("should return false for zotero: URL", function () {
assert.isFalse(Zotero.Utilities.isHTTPURL('zotero://select/library/items/AAAAAAAA'));
});