move protocol_filter to typescript

This commit is contained in:
Audric Ackermann 2022-03-29 12:28:04 +11:00
parent 38774a9344
commit 5b1379f930
2 changed files with 104 additions and 88 deletions

View file

@ -1,88 +0,0 @@
const path = require('path');
const fs = require('fs');
function _eliminateAllAfterCharacter(string, character) {
const index = string.indexOf(character);
if (index < 0) {
return string;
}
return string.slice(0, index);
}
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, { isWindows }));
// here we attempt to follow symlinks to the ultimate final path, reflective of what
// we do in main.js on userDataPath and installPath
const realPath = fs.existsSync(target) ? fs.realpathSync(target) : target;
// finally we do case-insensitive checks on windows
const properCasing = isWindows ? realPath.toLowerCase() : realPath;
if (!path.isAbsolute(realPath)) {
console.log(`Warning: denying request to non-absolute path '${realPath}'`);
return callback();
}
if (
!properCasing.startsWith(isWindows ? userDataPath.toLowerCase() : userDataPath) &&
!properCasing.startsWith(isWindows ? installPath.toLowerCase() : installPath)
) {
console.log(
`Warning: denying request to path '${realPath}' (userDataPath: '${userDataPath}', installPath: '${installPath}')`
);
return callback();
}
return callback({
path: realPath,
});
};
}
function installFileHandler({ protocol, userDataPath, installPath, isWindows }) {
protocol.interceptFileProtocol(
'file',
_createFileHandler({ userDataPath, installPath, isWindows })
);
}
// Turn off browser URI scheme since we do all network requests via Node.js
function _disabledHandler(request, callback) {
return callback();
}
function installWebHandler({ protocol }) {
protocol.interceptFileProtocol('about', _disabledHandler);
protocol.interceptFileProtocol('content', _disabledHandler);
protocol.interceptFileProtocol('chrome', _disabledHandler);
protocol.interceptFileProtocol('cid', _disabledHandler);
protocol.interceptFileProtocol('data', _disabledHandler);
protocol.interceptFileProtocol('filesystem', _disabledHandler);
protocol.interceptFileProtocol('ftp', _disabledHandler);
protocol.interceptFileProtocol('gopher', _disabledHandler);
protocol.interceptFileProtocol('http', _disabledHandler);
protocol.interceptFileProtocol('https', _disabledHandler);
protocol.interceptFileProtocol('javascript', _disabledHandler);
protocol.interceptFileProtocol('mailto', _disabledHandler);
protocol.interceptFileProtocol('ws', _disabledHandler);
protocol.interceptFileProtocol('wss', _disabledHandler);
}
module.exports = {
_urlToPath,
installFileHandler,
installWebHandler,
};

104
ts/node/protocol_filter.ts Normal file
View file

@ -0,0 +1,104 @@
import path from 'path';
import fs from 'fs';
import { Protocol } from 'electron';
import { ProtocolRequest } from 'electron/main';
// tslint:disable: no-console
function eliminateAllAfterCharacter(str: string, character: string) {
const index = str.indexOf(character);
if (index < 0) {
return str;
}
return str.slice(0, index);
}
function urlToPath(targetUrl: string, options: { isWindows?: boolean } = {}) {
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,
}: {
isWindows: boolean;
installPath: string;
userDataPath: string;
}) {
return (request: ProtocolRequest, callback: any) => {
// normalize() is primarily useful here for switching / to \ on windows
const target = path.normalize(urlToPath(request.url, { isWindows }));
// here we attempt to follow symlinks to the ultimate final path, reflective of what
// we do in main.js on userDataPath and installPath
// tslint:disable-next-line: non-literal-fs-path
const realPath = fs.existsSync(target) ? fs.realpathSync(target) : target;
// finally we do case-insensitive checks on windows
const properCasing = isWindows ? realPath.toLowerCase() : realPath;
if (!path.isAbsolute(realPath)) {
console.log(`Warning: denying request to non-absolute path '${realPath}'`);
return callback();
}
if (
!properCasing.startsWith(isWindows ? userDataPath.toLowerCase() : userDataPath) &&
!properCasing.startsWith(isWindows ? installPath.toLowerCase() : installPath)
) {
console.log(
`Warning: denying request to path '${realPath}' (userDataPath: '${userDataPath}', installPath: '${installPath}')`
);
return callback();
}
return callback({
path: realPath,
});
};
}
export function installFileHandler({
protocol,
userDataPath,
installPath,
isWindows,
}: {
protocol: Protocol;
userDataPath: string;
installPath: string;
isWindows: boolean;
}) {
protocol.interceptFileProtocol(
'file',
createFileHandler({ userDataPath, installPath, isWindows })
);
}
// Turn off browser URI scheme since we do all network requests via Node.js
function disabledHandler(_request: any, callback: any) {
return callback();
}
export function installWebHandler({ protocol }: { protocol: Protocol }) {
protocol.interceptFileProtocol('about', disabledHandler);
protocol.interceptFileProtocol('content', disabledHandler);
protocol.interceptFileProtocol('chrome', disabledHandler);
protocol.interceptFileProtocol('cid', disabledHandler);
protocol.interceptFileProtocol('data', disabledHandler);
protocol.interceptFileProtocol('filesystem', disabledHandler);
protocol.interceptFileProtocol('ftp', disabledHandler);
protocol.interceptFileProtocol('gopher', disabledHandler);
protocol.interceptFileProtocol('http', disabledHandler);
protocol.interceptFileProtocol('https', disabledHandler);
protocol.interceptFileProtocol('javascript', disabledHandler);
protocol.interceptFileProtocol('mailto', disabledHandler);
protocol.interceptFileProtocol('ws', disabledHandler);
protocol.interceptFileProtocol('wss', disabledHandler);
}