From eec61f52891822de524c14c76662c2e302deca6c Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Fri, 25 May 2018 14:11:26 -0700 Subject: [PATCH] Fine-tune file protocol filter --- app/protocol_filter.js | 39 ++++++++++++++++++++------------ main.js | 1 + test/app/protocol_filter_test.js | 14 ++++++++++-- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/app/protocol_filter.js b/app/protocol_filter.js index f0e33cc89e6..121117f5b19 100644 --- a/app/protocol_filter.js +++ b/app/protocol_filter.js @@ -1,23 +1,29 @@ const path = require('path'); -const FILE_SCHEME = /^file:\/\//; -const WINDOWS_PREFIX = /^\/[A-Z]:/; -function _urlToPath(targetUrl) { - let withoutScheme = targetUrl.replace(FILE_SCHEME, ''); - if (WINDOWS_PREFIX.test(withoutScheme)) { - withoutScheme = withoutScheme.slice(1); +function _eliminateAllAfterCharacter(string, character) { + const index = string.indexOf(character); + if (index < 0) { + return string; } - const withoutQuerystring = withoutScheme.replace(/\?.*$/, ''); - const withoutHash = withoutQuerystring.replace(/#.*$/, ''); - - return decodeURIComponent(withoutHash); + return string.slice(0, index); } -function _createFileHandler({ userDataPath, installPath }) { +function _urlToPath(targetUrl, options = {}) { + const { isWindows } = options; + + const decoded = decodeURIComponent(targetUrl); + const withoutScheme = decoded.slice(isWindows ? 8 : 7); + const withoutQuerystring = _eliminateAllAfterCharacter(withoutScheme, '?'); + const withoutHash = _eliminateAllAfterCharacter(withoutQuerystring, '#'); + + return withoutHash; +} + +function _createFileHandler({ userDataPath, installPath, isWindows }) { return (request, callback) => { // normalize() is primarily useful here for switching / to \ on windows - const target = path.normalize(_urlToPath(request.url)); + const target = path.normalize(_urlToPath(request.url, { isWindows })); if (!path.isAbsolute(target)) { return callback(); @@ -34,10 +40,15 @@ function _createFileHandler({ userDataPath, installPath }) { }; } -function installFileHandler({ protocol, userDataPath, installPath }) { +function installFileHandler({ + protocol, + userDataPath, + installPath, + isWindows, +}) { protocol.interceptFileProtocol( 'file', - _createFileHandler({ userDataPath, installPath }) + _createFileHandler({ userDataPath, installPath, isWindows }) ); } diff --git a/main.js b/main.js index 64bca6edb65..81dd73eedef 100644 --- a/main.js +++ b/main.js @@ -452,6 +452,7 @@ app.on('ready', () => { protocol: electronProtocol, userDataPath, installPath, + isWindows: process.platform === 'win32', }); } diff --git a/test/app/protocol_filter_test.js b/test/app/protocol_filter_test.js index 11411431d52..11964224591 100644 --- a/test/app/protocol_filter_test.js +++ b/test/app/protocol_filter_test.js @@ -34,12 +34,13 @@ describe('Protocol Filter', () => { expect(actual).to.equal(expected); }); - it('returns proper file path for windows style file URI', () => { + it('returns proper file path for file URI on windows', () => { const path = 'file:///C:/Users/Someone/dev/desktop/background.html?name=Signal&locale=en&version=2.4.0'; const expected = 'C:/Users/Someone/dev/desktop/background.html'; + const isWindows = true; - const actual = _urlToPath(path, { isWindows: true }); + const actual = _urlToPath(path, { isWindows }); expect(actual).to.equal(expected); }); @@ -72,6 +73,15 @@ describe('Protocol Filter', () => { expect(actual).to.equal(expected); }); + it('handles SMB share path on windows', () => { + const path = 'file://relative/path'; + const expected = 'elative/path'; + const isWindows = true; + + const actual = _urlToPath(path, { isWindows }); + expect(actual).to.equal(expected); + }); + it('hands back a path with .. in it', () => { const path = 'file://../../..'; const expected = '../../..';