mirror of https://github.com/laurent22/joplin.git
parent
2c4cf9fbdb
commit
8bb5b4a557
|
@ -325,6 +325,7 @@
|
||||||
"homenote",
|
"homenote",
|
||||||
"hotfolder",
|
"hotfolder",
|
||||||
"Howver",
|
"Howver",
|
||||||
|
"hpagent",
|
||||||
"Hrvatska",
|
"Hrvatska",
|
||||||
"htmlentities",
|
"htmlentities",
|
||||||
"htmlfile",
|
"htmlfile",
|
||||||
|
@ -950,4 +951,4 @@
|
||||||
"မြန်မာ",
|
"မြန်မာ",
|
||||||
"កម្ពុជា"
|
"កម្ពុជា"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import Setting, { Env } from './models/Setting';
|
import Setting, { Env } from './models/Setting';
|
||||||
import Logger, { TargetType, LoggerWrapper } from './Logger';
|
import Logger, { TargetType, LoggerWrapper } from './Logger';
|
||||||
import shim from './shim';
|
import shim from './shim';
|
||||||
|
const { setupProxySettings } = require('./shim-init-node');
|
||||||
import BaseService from './services/BaseService';
|
import BaseService from './services/BaseService';
|
||||||
import reducer, { setStore } from './reducer';
|
import reducer, { setStore } from './reducer';
|
||||||
import KeychainServiceDriver from './services/keychain/KeychainServiceDriver.node';
|
import KeychainServiceDriver from './services/keychain/KeychainServiceDriver.node';
|
||||||
|
@ -456,6 +457,14 @@ export default class BaseApplication {
|
||||||
syswidecas.addCAs(f);
|
syswidecas.addCAs(f);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'net.proxyEnabled': async () => {
|
||||||
|
setupProxySettings({
|
||||||
|
maxConcurrentConnections: Setting.value('sync.maxConcurrentConnections'),
|
||||||
|
proxyTimeout: Setting.value('net.proxyTimeout'),
|
||||||
|
proxyEnabled: Setting.value('net.proxyEnabled'),
|
||||||
|
proxyUrl: Setting.value('net.proxyUrl'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// Note: this used to run when "encryption.enabled" was changed, but
|
// Note: this used to run when "encryption.enabled" was changed, but
|
||||||
// now we run it anytime any property of the sync target info is
|
// now we run it anytime any property of the sync target info is
|
||||||
|
@ -491,6 +500,9 @@ export default class BaseApplication {
|
||||||
sideEffects['locale'] = sideEffects['dateFormat'];
|
sideEffects['locale'] = sideEffects['dateFormat'];
|
||||||
sideEffects['encryption.passwordCache'] = sideEffects['syncInfoCache'];
|
sideEffects['encryption.passwordCache'] = sideEffects['syncInfoCache'];
|
||||||
sideEffects['encryption.masterPassword'] = sideEffects['syncInfoCache'];
|
sideEffects['encryption.masterPassword'] = sideEffects['syncInfoCache'];
|
||||||
|
sideEffects['sync.maxConcurrentConnections'] = sideEffects['net.proxyEnabled'];
|
||||||
|
sideEffects['sync.proxyTimeout'] = sideEffects['net.proxyEnabled'];
|
||||||
|
sideEffects['sync.proxyUrl'] = sideEffects['net.proxyEnabled'];
|
||||||
|
|
||||||
if (action) {
|
if (action) {
|
||||||
const effect = sideEffects[action.key];
|
const effect = sideEffects[action.key];
|
||||||
|
|
|
@ -1384,7 +1384,37 @@ class Setting extends BaseModel {
|
||||||
label: () => _('Ignore TLS certificate errors'),
|
label: () => _('Ignore TLS certificate errors'),
|
||||||
storage: SettingStorage.File,
|
storage: SettingStorage.File,
|
||||||
},
|
},
|
||||||
|
'net.proxyEnabled': {
|
||||||
|
value: false,
|
||||||
|
type: SettingItemType.Bool,
|
||||||
|
advanced: true,
|
||||||
|
section: 'sync',
|
||||||
|
isGlobal: true,
|
||||||
|
public: true,
|
||||||
|
label: () => _('Proxy enabled (beta)'),
|
||||||
|
storage: SettingStorage.File,
|
||||||
|
},
|
||||||
|
'net.proxyUrl': {
|
||||||
|
value: '',
|
||||||
|
type: SettingItemType.String,
|
||||||
|
advanced: true,
|
||||||
|
section: 'sync',
|
||||||
|
isGlobal: true,
|
||||||
|
public: true,
|
||||||
|
label: () => _('Proxy URL (beta)'),
|
||||||
|
description: () => _('e.g "http://my.proxy.com:80". You can also set via environment variables'),
|
||||||
|
storage: SettingStorage.File,
|
||||||
|
},
|
||||||
|
'net.proxyTimeout': {
|
||||||
|
value: 1,
|
||||||
|
type: SettingItemType.Int,
|
||||||
|
advanced: true,
|
||||||
|
section: 'sync',
|
||||||
|
isGlobal: true,
|
||||||
|
public: true,
|
||||||
|
label: () => _('proxy timeout (seconds) (beta)'),
|
||||||
|
storage: SettingStorage.File,
|
||||||
|
},
|
||||||
'sync.wipeOutFailSafe': {
|
'sync.wipeOutFailSafe': {
|
||||||
value: true,
|
value: true,
|
||||||
type: SettingItemType.Bool,
|
type: SettingItemType.Bool,
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
"follow-redirects": "^1.2.4",
|
"follow-redirects": "^1.2.4",
|
||||||
"form-data": "^2.1.4",
|
"form-data": "^2.1.4",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
|
"hpagent": "^1.0.0",
|
||||||
"html-entities": "^1.2.1",
|
"html-entities": "^1.2.1",
|
||||||
"html-minifier": "^3.5.15",
|
"html-minifier": "^3.5.15",
|
||||||
"image-data-uri": "^2.0.0",
|
"image-data-uri": "^2.0.0",
|
||||||
|
|
|
@ -13,12 +13,15 @@ const urlValidator = require('valid-url');
|
||||||
const { _ } = require('./locale');
|
const { _ } = require('./locale');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
|
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
|
||||||
const toRelative = require('relative');
|
const toRelative = require('relative');
|
||||||
const timers = require('timers');
|
const timers = require('timers');
|
||||||
const zlib = require('zlib');
|
const zlib = require('zlib');
|
||||||
const dgram = require('dgram');
|
const dgram = require('dgram');
|
||||||
const { basename, fileExtension, safeFileExtension } = require('./path-utils');
|
const { basename, fileExtension, safeFileExtension } = require('./path-utils');
|
||||||
|
|
||||||
|
const proxySettings = {};
|
||||||
|
|
||||||
function fileExists(filePath) {
|
function fileExists(filePath) {
|
||||||
try {
|
try {
|
||||||
return fs.statSync(filePath).isFile();
|
return fs.statSync(filePath).isFile();
|
||||||
|
@ -27,6 +30,20 @@ function fileExists(filePath) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isUrlHttps(url) {
|
||||||
|
return url.startsWith('https');
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveProxyUrl(proxyUrl) {
|
||||||
|
return (
|
||||||
|
proxyUrl ||
|
||||||
|
process.env['http_proxy'] ||
|
||||||
|
process.env['https_proxy'] ||
|
||||||
|
process.env['HTTP_PROXY'] ||
|
||||||
|
process.env['HTTPS_PROXY']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/sindresorhus/callsites/blob/main/index.js
|
// https://github.com/sindresorhus/callsites/blob/main/index.js
|
||||||
function callsites() {
|
function callsites() {
|
||||||
const _prepareStackTrace = Error.prepareStackTrace;
|
const _prepareStackTrace = Error.prepareStackTrace;
|
||||||
|
@ -64,6 +81,13 @@ const gunzipFile = function(source, destination) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function setupProxySettings(options) {
|
||||||
|
proxySettings.maxConcurrentConnections = options.maxConcurrentConnections;
|
||||||
|
proxySettings.proxyTimeout = options.proxyTimeout;
|
||||||
|
proxySettings.proxyEnabled = options.proxyEnabled;
|
||||||
|
proxySettings.proxyUrl = options.proxyUrl;
|
||||||
|
}
|
||||||
|
|
||||||
function shimInit(options = null) {
|
function shimInit(options = null) {
|
||||||
options = {
|
options = {
|
||||||
sharp: null,
|
sharp: null,
|
||||||
|
@ -79,6 +103,7 @@ function shimInit(options = null) {
|
||||||
const keytar = (shim.isWindows() || shim.isMac()) && !shim.isPortable() ? options.keytar : null;
|
const keytar = (shim.isWindows() || shim.isMac()) && !shim.isPortable() ? options.keytar : null;
|
||||||
const appVersion = options.appVersion;
|
const appVersion = options.appVersion;
|
||||||
|
|
||||||
|
|
||||||
shim.setNodeSqlite(options.nodeSqlite);
|
shim.setNodeSqlite(options.nodeSqlite);
|
||||||
|
|
||||||
shim.fsDriver = () => {
|
shim.fsDriver = () => {
|
||||||
|
@ -420,10 +445,11 @@ function shimInit(options = null) {
|
||||||
return new Buffer(data).toString('base64');
|
return new Buffer(data).toString('base64');
|
||||||
};
|
};
|
||||||
|
|
||||||
shim.fetch = async function(url, options = null) {
|
shim.fetch = async function(url, options = {}) {
|
||||||
const validatedUrl = urlValidator.isUri(url);
|
const validatedUrl = urlValidator.isUri(url);
|
||||||
if (!validatedUrl) throw new Error(`Not a valid URL: ${url}`);
|
if (!validatedUrl) throw new Error(`Not a valid URL: ${url}`);
|
||||||
|
const resolvedProxyUrl = resolveProxyUrl(proxySettings.proxyUrl);
|
||||||
|
options.agent = (resolvedProxyUrl && proxySettings.proxyEnabled) ? shim.proxyAgent(url, resolvedProxyUrl) : null;
|
||||||
return shim.fetchWithRetry(() => {
|
return shim.fetchWithRetry(() => {
|
||||||
return nodeFetch(url, options);
|
return nodeFetch(url, options);
|
||||||
}, options);
|
}, options);
|
||||||
|
@ -466,6 +492,9 @@ function shimInit(options = null) {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolvedProxyUrl = resolveProxyUrl(proxySettings.proxyUrl);
|
||||||
|
requestOptions.agent = (resolvedProxyUrl && proxySettings.proxyEnabled) ? shim.proxyAgent(url, resolvedProxyUrl) : null;
|
||||||
|
|
||||||
const doFetchOperation = async () => {
|
const doFetchOperation = async () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let file = null;
|
let file = null;
|
||||||
|
@ -572,6 +601,27 @@ function shimInit(options = null) {
|
||||||
return url.startsWith('https') ? shim.httpAgent_.https : shim.httpAgent_.http;
|
return url.startsWith('https') ? shim.httpAgent_.https : shim.httpAgent_.http;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
shim.proxyAgent = (serverUrl, proxyUrl) => {
|
||||||
|
const proxyAgentConfig = {
|
||||||
|
keepAlive: true,
|
||||||
|
maxSockets: proxySettings.maxConcurrentConnections,
|
||||||
|
keepAliveMsecs: 5000,
|
||||||
|
proxy: proxyUrl,
|
||||||
|
timeout: proxySettings.proxyTimeout * 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Based on https://github.com/delvedor/hpagent#usage
|
||||||
|
if (!isUrlHttps(proxyUrl) && !isUrlHttps(serverUrl)) {
|
||||||
|
return new HttpProxyAgent(proxyAgentConfig);
|
||||||
|
} else if (isUrlHttps(proxyUrl) && !isUrlHttps(serverUrl)) {
|
||||||
|
return new HttpProxyAgent(proxyAgentConfig);
|
||||||
|
} else if (!isUrlHttps(proxyUrl) && isUrlHttps(serverUrl)) {
|
||||||
|
return new HttpsProxyAgent(proxyAgentConfig);
|
||||||
|
} else {
|
||||||
|
return new HttpsProxyAgent(proxyAgentConfig);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
shim.openOrCreateFile = (filepath, defaultContents) => {
|
shim.openOrCreateFile = (filepath, defaultContents) => {
|
||||||
// If the file doesn't exist, create it
|
// If the file doesn't exist, create it
|
||||||
if (!fs.existsSync(filepath)) {
|
if (!fs.existsSync(filepath)) {
|
||||||
|
@ -634,4 +684,4 @@ function shimInit(options = null) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { shimInit };
|
module.exports = { shimInit, setupProxySettings };
|
||||||
|
|
|
@ -16,7 +16,7 @@ let isTestingEnv_ = false;
|
||||||
// (app-desktop, app-mobile, etc.) since we are sure they won't be dependency to
|
// (app-desktop, app-mobile, etc.) since we are sure they won't be dependency to
|
||||||
// other packages (unlike the lib which can be included anywhere).
|
// other packages (unlike the lib which can be included anywhere).
|
||||||
//
|
//
|
||||||
// Regarding the type - althought we import React, we only use it as a type
|
// Regarding the type - although we import React, we only use it as a type
|
||||||
// using `typeof React`. This is just to get types in hooks.
|
// using `typeof React`. This is just to get types in hooks.
|
||||||
//
|
//
|
||||||
// https://stackoverflow.com/a/42816077/561309
|
// https://stackoverflow.com/a/42816077/561309
|
||||||
|
|
|
@ -3436,6 +3436,7 @@ __metadata:
|
||||||
follow-redirects: ^1.2.4
|
follow-redirects: ^1.2.4
|
||||||
form-data: ^2.1.4
|
form-data: ^2.1.4
|
||||||
fs-extra: ^5.0.0
|
fs-extra: ^5.0.0
|
||||||
|
hpagent: ^1.0.0
|
||||||
html-entities: ^1.2.1
|
html-entities: ^1.2.1
|
||||||
html-minifier: ^3.5.15
|
html-minifier: ^3.5.15
|
||||||
image-data-uri: ^2.0.0
|
image-data-uri: ^2.0.0
|
||||||
|
@ -16672,6 +16673,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"hpagent@npm:^1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "hpagent@npm:1.0.0"
|
||||||
|
checksum: 911a9ba612747f5c9403fb60c1abd0c47a27fa634826caad9aecad41b899533489da36c92758b5cd83576e2bf9e84e23a4374a40aa513106d5450f62856c4b2d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"html-encoding-sniffer@npm:^1.0.2":
|
"html-encoding-sniffer@npm:^1.0.2":
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
resolution: "html-encoding-sniffer@npm:1.0.2"
|
resolution: "html-encoding-sniffer@npm:1.0.2"
|
||||||
|
|
Loading…
Reference in New Issue