whistle 2.9.13 → 2.9.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/bin/ca/cli.js +95 -0
- package/bin/ca/index.d.ts +1 -0
- package/bin/ca/index.js +43 -0
- package/bin/proxy/cli.js +76 -0
- package/bin/proxy/index.d.ts +9 -0
- package/bin/proxy/index.js +49 -0
- package/bin/proxy/mac/Whistle +0 -0
- package/bin/proxy/mac/index.js +61 -0
- package/bin/proxy/win/index.js +32 -0
- package/bin/proxy/win/refresh.exe +0 -0
- package/bin/status.js +6 -6
- package/bin/use.js +2 -2
- package/bin/util.js +19 -2
- package/bin/whistle.js +37 -8
- package/biz/index.js +1 -1
- package/biz/webui/cgi-bin/certs/remove.js +1 -1
- package/biz/webui/cgi-bin/rootca.js +5 -1
- package/biz/webui/cgi-bin/util.js +1 -1
- package/biz/webui/htdocs/img/qrcode-cer.png +0 -0
- package/biz/webui/htdocs/img/qrcode-pem.png +0 -0
- package/biz/webui/htdocs/img/qrcode.png +0 -0
- package/biz/webui/htdocs/index.html +1 -1
- package/biz/webui/htdocs/js/index.js +7 -7
- package/biz/webui/lib/index.js +10 -4
- package/lib/config.js +9 -9
- package/lib/https/ca.js +36 -19
- package/lib/plugins/get-plugins-sync.js +1 -0
- package/lib/plugins/index.js +3 -1
- package/lib/plugins/load-plugin.js +2 -0
- package/lib/rules/util.js +10 -4
- package/lib/upgrade.js +1 -1
- package/lib/util/common.js +21 -0
- package/lib/util/index.js +4 -1
- package/lib/util/is-utf8.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -179,6 +179,7 @@ Debugging mode:
|
|
|
179
179
|
For more details, please visit [install and start](https://avwo.github.io/whistle/install.html)
|
|
180
180
|
|
|
181
181
|
# Proxing Settings
|
|
182
|
+
> https://wproxy.org/whistle/proxy.html
|
|
182
183
|
##### configuring server & port
|
|
183
184
|
1. proxying server:127.0.0.1(if whistle is deployed in remote server or virtual machine, change this address to corresponding IP address)
|
|
184
185
|
2. default port:8899(if port 8899 is used already, you can specify new port using `-p` when start. More details can be visited by executing `whistle help` or `w2 help` (only supported in `v0.7.0` and higher version)
|
|
@@ -321,6 +322,7 @@ Open [Rules](http://local.whistlejs.com/) tab in whistle, and create a group nam
|
|
|
321
322
|
|
|
322
323
|
# Documentation
|
|
323
324
|
1. [Install and start](https://avwo.github.io/whistle/install.html)
|
|
325
|
+
1. [Setting proxy](https://wproxy.org/whistle/proxy.html)
|
|
324
326
|
2. [CLI operation](https://avwo.github.io/whistle/cli.html)
|
|
325
327
|
2. [How to update](https://avwo.github.io/whistle/update.html)
|
|
326
328
|
3. [Quickly start](https://avwo.github.io/whistle/quickstart.html)
|
package/bin/ca/cli.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
var net = require('net');
|
|
2
|
+
var fs = require('fs');
|
|
3
|
+
var path = require('path');
|
|
4
|
+
var installRootCA = require('./index');
|
|
5
|
+
var util = require('../util');
|
|
6
|
+
var fileMgr = require('../../lib/util/file-mgr');
|
|
7
|
+
var httpMgr = require('../../lib/util/http-mgr');
|
|
8
|
+
var commonUtil = require('../../lib/util/common');
|
|
9
|
+
var config = require('../../lib/config');
|
|
10
|
+
|
|
11
|
+
var NUM_RE = /^\d+$/;
|
|
12
|
+
var HOST_SUFFIX_RE = /\:(\d+|auto)?$/;
|
|
13
|
+
var HOST_RE = /^[a-z\d_-]+(?:\.[a-z\d_-]+)*$/i;
|
|
14
|
+
var URL_RE = /^https?:\/\/./i;
|
|
15
|
+
var MAX_LEN = 1024 * 1024;
|
|
16
|
+
|
|
17
|
+
function installCert(certFile, url) {
|
|
18
|
+
try {
|
|
19
|
+
installRootCA(fileMgr.convertSlash(certFile));
|
|
20
|
+
util.info('Install root CA (' + (url || certFile) + ') successful.');
|
|
21
|
+
} catch (e) {
|
|
22
|
+
util.error(e.message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function install(addr) {
|
|
27
|
+
if (addr.file) {
|
|
28
|
+
return installCert(addr.file);
|
|
29
|
+
}
|
|
30
|
+
addr.needRawData = true;
|
|
31
|
+
addr.maxLength = MAX_LEN;
|
|
32
|
+
addr.headers = {
|
|
33
|
+
'user-agent': 'whistle/' + config.name
|
|
34
|
+
};
|
|
35
|
+
httpMgr.request(addr, function(err, body, res) {
|
|
36
|
+
if (err) {
|
|
37
|
+
return util.error(err.message);
|
|
38
|
+
}
|
|
39
|
+
if (res.statusCode != 200) {
|
|
40
|
+
return util.error('Bad response (' + res.statusCode + ').');
|
|
41
|
+
}
|
|
42
|
+
if (!body || !body.length) {
|
|
43
|
+
return util.error('No content.');
|
|
44
|
+
}
|
|
45
|
+
var tempFile = path.join(commonUtil.getWhistlePath(), Date.now() + '-' + util.getHash(addr.url) + '.crt');
|
|
46
|
+
fs.writeFileSync(tempFile, body);
|
|
47
|
+
installCert(tempFile, addr.url);
|
|
48
|
+
fs.unlinkSync(tempFile);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = function(argv) {
|
|
53
|
+
var options = {};
|
|
54
|
+
argv.forEach(function(arg) {
|
|
55
|
+
if (NUM_RE.test(arg)) {
|
|
56
|
+
delete options.addr;
|
|
57
|
+
options.port = parseInt(arg, 10) || options.port;
|
|
58
|
+
} else if (net.isIP(arg)) {
|
|
59
|
+
delete options.addr;
|
|
60
|
+
options.host = arg || options.host;
|
|
61
|
+
} else if (HOST_SUFFIX_RE.test(arg)) {
|
|
62
|
+
delete options.port;
|
|
63
|
+
delete options.addr;
|
|
64
|
+
var port = RegExp.$1;
|
|
65
|
+
if (port > 0) {
|
|
66
|
+
options.port = parseInt(port, 10) || options.port;
|
|
67
|
+
}
|
|
68
|
+
var host = arg.slice(0, - port.length - 1);
|
|
69
|
+
if (host[0] === '[') {
|
|
70
|
+
host = host.substring(1);
|
|
71
|
+
}
|
|
72
|
+
var lastIndex = host.length - 1;
|
|
73
|
+
if (host[lastIndex] === ']') {
|
|
74
|
+
host = host.substring(0, lastIndex);
|
|
75
|
+
}
|
|
76
|
+
if (host && (net.isIP(host) || HOST_RE.test(host))) {
|
|
77
|
+
options.host = host || options.host;
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
delete options.port;
|
|
81
|
+
delete options.host;
|
|
82
|
+
if (URL_RE.test(arg)) {
|
|
83
|
+
options.addr = { url: arg };
|
|
84
|
+
} else {
|
|
85
|
+
options.addr = { file: arg };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
if (!options.addr) {
|
|
90
|
+
var host = options.host || '127.0.0.1';
|
|
91
|
+
var port = options.port || util.getDefaultPort();
|
|
92
|
+
options.addr = { url: 'http://' + host + ':' + port + '/cgi-bin/rootca' };
|
|
93
|
+
}
|
|
94
|
+
install(options.addr);
|
|
95
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function (certFile: String): void;
|
package/bin/ca/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
var spawnSync = require('child_process').spawnSync;
|
|
2
|
+
|
|
3
|
+
function checkSuccess(result) {
|
|
4
|
+
var stderr = result.stderr;
|
|
5
|
+
if (stderr && stderr.length) {
|
|
6
|
+
throw new Error(stderr + '');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function getKeyChain() {
|
|
11
|
+
var result = spawnSync('security', ['default-keychain']);
|
|
12
|
+
checkSuccess(result);
|
|
13
|
+
return (result.stdout + '').split('"')[1];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function installMac(certPath) {
|
|
17
|
+
var result = spawnSync('security', ['add-trusted-cert', '-k', getKeyChain(), certPath]);
|
|
18
|
+
checkSuccess(result);
|
|
19
|
+
var msg = result.stdout + '';
|
|
20
|
+
if (/Error:/i.test(msg)) {
|
|
21
|
+
throw new Error(msg);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
function installWin(certFile) {
|
|
27
|
+
var result = spawnSync('certutil', ['-addstore', '-user', 'Root', certFile]);
|
|
28
|
+
checkSuccess(result);
|
|
29
|
+
if (/ERROR_CANCELLED/i.test(result.stdout + '')) {
|
|
30
|
+
throw new Error('The authorization was canceled by the user.');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = function(certFile) {
|
|
35
|
+
var platform = process.platform;
|
|
36
|
+
if (platform === 'darwin') {
|
|
37
|
+
return installMac(certFile);
|
|
38
|
+
}
|
|
39
|
+
if (platform === 'win32') {
|
|
40
|
+
return installWin(certFile);
|
|
41
|
+
}
|
|
42
|
+
throw new Error('Platform ' + platform + ' is unsupported to install root CA for now.');
|
|
43
|
+
};
|
package/bin/proxy/cli.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
var net = require('net');
|
|
2
|
+
var proxy = require('./index');
|
|
3
|
+
var util = require('../util');
|
|
4
|
+
|
|
5
|
+
var OFF_RE = /^(?:o|0|-{0,2}off)$/i;
|
|
6
|
+
var BYPASS_RE = /^(?:-{0,2}bypass|-x|-b)$/i;
|
|
7
|
+
var NUM_RE = /^\d+$/;
|
|
8
|
+
var HOST_SUFFIX_RE = /\:(\d+|auto)?$/;
|
|
9
|
+
var HOST_RE = /^[a-z\d_-]+(?:\.[a-z\d_-]+)*$/i;
|
|
10
|
+
|
|
11
|
+
function enableProxy(options) {
|
|
12
|
+
try {
|
|
13
|
+
if (proxy.enableProxy(options)) {
|
|
14
|
+
util.info('Setting global proxy (' + options.host + ':' + options.port + ') successful.');
|
|
15
|
+
} else {
|
|
16
|
+
util.error('Failed to set global proxy (' + options.host + ':' + options.port + ').');
|
|
17
|
+
}
|
|
18
|
+
} catch (e) {
|
|
19
|
+
util.error(e.message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function disableProxy() {
|
|
24
|
+
try {
|
|
25
|
+
if (proxy.disableProxy()) {
|
|
26
|
+
util.info('Turn off global proxy successful.');
|
|
27
|
+
} else {
|
|
28
|
+
util.error('Failed to turn off global proxy.');
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
util.error(e.message);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = function(argv) {
|
|
36
|
+
var cmd = argv[0];
|
|
37
|
+
if (OFF_RE.test(cmd)) {
|
|
38
|
+
return disableProxy();
|
|
39
|
+
}
|
|
40
|
+
var options = {};
|
|
41
|
+
var skip;
|
|
42
|
+
argv.forEach(function(arg) {
|
|
43
|
+
if (skip) {
|
|
44
|
+
options.bypass = arg;
|
|
45
|
+
skip = false;
|
|
46
|
+
} else if (BYPASS_RE.test(arg)) {
|
|
47
|
+
skip = true;
|
|
48
|
+
} else if (NUM_RE.test(arg)) {
|
|
49
|
+
options.port = parseInt(arg, 10) || options.port;
|
|
50
|
+
} else if (net.isIP(arg)) {
|
|
51
|
+
options.host = arg || options.host;
|
|
52
|
+
} else if (HOST_SUFFIX_RE.test(arg)) {
|
|
53
|
+
var port = RegExp.$1;
|
|
54
|
+
delete options.port;
|
|
55
|
+
if (port > 0) {
|
|
56
|
+
options.port = parseInt(port, 10) || options.port;
|
|
57
|
+
}
|
|
58
|
+
var host = arg.slice(0, - port.length - 1);
|
|
59
|
+
if (host[0] === '[') {
|
|
60
|
+
host = host.substring(1);
|
|
61
|
+
}
|
|
62
|
+
var lastIndex = host.length - 1;
|
|
63
|
+
if (host[lastIndex] === ']') {
|
|
64
|
+
host = host.substring(0, lastIndex);
|
|
65
|
+
}
|
|
66
|
+
if (host && (net.isIP(host) || HOST_RE.test(host))) {
|
|
67
|
+
options.host = host || options.host;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
if (!options.port) {
|
|
72
|
+
options.port = util.getDefaultPort();
|
|
73
|
+
}
|
|
74
|
+
options.host = options.host || '127.0.0.1';
|
|
75
|
+
enableProxy(options);
|
|
76
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
var os = require('os');
|
|
2
|
+
var net = require('net');
|
|
3
|
+
var mac = require('./mac');
|
|
4
|
+
var win = require('./win');
|
|
5
|
+
|
|
6
|
+
var platform = os.platform();
|
|
7
|
+
var BYPASS_RE = /^[*a-z\d_-]+(?:\.[*a-z\d_-]+)*$/i;
|
|
8
|
+
|
|
9
|
+
function getBypass(bypass) {
|
|
10
|
+
if (!bypass || typeof bypass !== 'string') {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
var map = {};
|
|
14
|
+
bypass = bypass.trim().toLowerCase();
|
|
15
|
+
return bypass.split(/[\s,;]+/).filter(function(host) {
|
|
16
|
+
if (!map[host] && (host === '<local>' || net.isIP(host) || BYPASS_RE.test(host))) {
|
|
17
|
+
map[host] = 1;
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// only support mac & win
|
|
25
|
+
function getProxyMgr() {
|
|
26
|
+
if (platform === 'win32') {
|
|
27
|
+
return win;
|
|
28
|
+
}
|
|
29
|
+
if (platform === 'darwin') {
|
|
30
|
+
return mac;
|
|
31
|
+
}
|
|
32
|
+
throw new Error('Platform ' + platform + ' is unsupported to set global proxy for now.');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
exports.enableProxy = function(options) {
|
|
36
|
+
var host = options.host.toLowerCase();
|
|
37
|
+
var enableProxy = getProxyMgr().enableProxy;
|
|
38
|
+
var bypass = getBypass(options.bypass);
|
|
39
|
+
return enableProxy({
|
|
40
|
+
host: host,
|
|
41
|
+
port: options.port,
|
|
42
|
+
bypass: bypass
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports.disableProxy = function() {
|
|
47
|
+
var disableProxy = getProxyMgr().disableProxy;
|
|
48
|
+
return disableProxy();
|
|
49
|
+
};
|
|
Binary file
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var execSync = require('child_process').execSync;
|
|
2
|
+
var join = require('path').join;
|
|
3
|
+
|
|
4
|
+
var PROXY_HELPER = join(__dirname, 'Whistle');
|
|
5
|
+
|
|
6
|
+
function getProxyServer(isSecure) {
|
|
7
|
+
var str = execSync('networksetup -get' + (isSecure ? 'secure' : '') + 'webproxy "Wi-Fi"') + '';
|
|
8
|
+
var result = {};
|
|
9
|
+
str.split(/[\r\n]+/).forEach(function(line) {
|
|
10
|
+
var index = line.indexOf(':');
|
|
11
|
+
var key = line.substring(0, index).trim().toLowerCase();
|
|
12
|
+
var value = line.substring(index + 1).trim().toLowerCase();
|
|
13
|
+
if (key === 'enabled') {
|
|
14
|
+
result.enabled = value === 'yes';
|
|
15
|
+
} else if (key === 'server') {
|
|
16
|
+
result.host = value;
|
|
17
|
+
} else if (key === 'port') {
|
|
18
|
+
result.port = value;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function getCurProxy() {
|
|
25
|
+
return {
|
|
26
|
+
http: getProxyServer(),
|
|
27
|
+
https: getProxyServer(true)
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function checkProxy(p1, p2) {
|
|
32
|
+
if (!p1.enabled) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return p1.host == p2.host && p1.port == p2.port;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
exports.enableProxy = function(options) {
|
|
39
|
+
var bypass = options.bypass;
|
|
40
|
+
var port = options.port;
|
|
41
|
+
if (bypass) {
|
|
42
|
+
bypass = ' -x "' + bypass + '"';
|
|
43
|
+
} else {
|
|
44
|
+
bypass = '';
|
|
45
|
+
}
|
|
46
|
+
execSync('\'' + PROXY_HELPER + '\' -m global -p ' + port + ' -r ' + port + ' -s ' + options.host + bypass);
|
|
47
|
+
try {
|
|
48
|
+
var curProxy = getCurProxy();
|
|
49
|
+
return checkProxy(curProxy.http, options) && checkProxy(curProxy.https, options);
|
|
50
|
+
} catch (e) {}
|
|
51
|
+
return true;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
exports.disableProxy = function() {
|
|
55
|
+
execSync('\'' + PROXY_HELPER + '\' -m off');
|
|
56
|
+
try {
|
|
57
|
+
var curProxy = getCurProxy();
|
|
58
|
+
return !curProxy.http.enabled && !curProxy.https.enabled;
|
|
59
|
+
} catch (e) {}
|
|
60
|
+
return true;
|
|
61
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
var execSync = require('child_process').execSync;
|
|
2
|
+
var join = require('path').join;
|
|
3
|
+
|
|
4
|
+
var REFRESH_PROXY = join(__dirname, 'refresh');
|
|
5
|
+
var REG_PATH = 'reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" /v';
|
|
6
|
+
|
|
7
|
+
function disableProxy() {
|
|
8
|
+
var proxyCmd = REG_PATH + ' ProxyEnable /t REG_DWORD /d 0 /f';
|
|
9
|
+
var pacCmd = REG_PATH + ' AutoConfigURL /t REG_DWORD /d 0 /f';
|
|
10
|
+
var detectCmd = REG_PATH + ' AutoDetect /t REG_DWORD /d 0 /f';
|
|
11
|
+
execSync(proxyCmd + ' & ' + pacCmd + ' & ' + detectCmd);
|
|
12
|
+
execSync(REFRESH_PROXY);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
exports.enableProxy = function(options) {
|
|
17
|
+
disableProxy();
|
|
18
|
+
var bypass = options.bypass;
|
|
19
|
+
var setCmd = REG_PATH + ' ProxyServer /t REG_SZ /d ' + options.host + ':' + options.port + ' /f';
|
|
20
|
+
var enableCmd = REG_PATH + ' ProxyEnable /t REG_DWORD /d 1 /f';
|
|
21
|
+
var cmd = setCmd + ' & ' + enableCmd;
|
|
22
|
+
|
|
23
|
+
if (bypass) {
|
|
24
|
+
bypass = REG_PATH + ' ProxyOverride /t REG_SZ /d "' + bypass.join(';') + '" /f';
|
|
25
|
+
cmd = cmd + ' & ' + bypass;
|
|
26
|
+
}
|
|
27
|
+
execSync(cmd);
|
|
28
|
+
execSync(REFRESH_PROXY);
|
|
29
|
+
return true;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.disableProxy = disableProxy;
|
|
Binary file
|
package/bin/status.js
CHANGED
|
@@ -26,15 +26,15 @@ function showAll(byStop) {
|
|
|
26
26
|
if (!len) {
|
|
27
27
|
warn('[!] No running whistle.');
|
|
28
28
|
} else {
|
|
29
|
-
var tips = [
|
|
29
|
+
var tips = ['[i] All running whistle:'];
|
|
30
30
|
confList.forEach(function(conf, i) {
|
|
31
31
|
++i;
|
|
32
32
|
var options = conf.options;
|
|
33
|
-
tips.push(' ' + i + '.
|
|
34
|
-
+
|
|
35
|
-
+ (options.
|
|
36
|
-
+ (
|
|
37
|
-
+ (byStop ? colors.red(' (
|
|
33
|
+
tips.push(' ' + i + '.' + (conf.pid ? ' PID: ' + conf.pid + ',' : '')
|
|
34
|
+
+ ' Port: ' + (options.port || pkg.port)
|
|
35
|
+
+ (options.host ? ', Host: ' + options.host : '')
|
|
36
|
+
+ (options.storage ? ', Storage: ' + options.storage : '')
|
|
37
|
+
+ (byStop ? colors.red(' (Stop cmd: ' + (options.storage ? 'w2 stop -S ' + options.storage : 'w2 stop') + ')') : ''));
|
|
38
38
|
});
|
|
39
39
|
byStop && warn('[!] This whistle is not running.');
|
|
40
40
|
info(tips.join('\n'));
|
package/bin/use.js
CHANGED
|
@@ -113,7 +113,7 @@ function checkDefault(running, storage, callback) {
|
|
|
113
113
|
module.exports = function(filepath, storage, force) {
|
|
114
114
|
storage = storage || '';
|
|
115
115
|
var config = readConfig(storage) || '';
|
|
116
|
-
options = config.options;
|
|
116
|
+
options = config.options;
|
|
117
117
|
var pid = options && config.pid;
|
|
118
118
|
var addon = options && options.addon;
|
|
119
119
|
var conf = require('../lib/config');
|
|
@@ -151,7 +151,7 @@ module.exports = function(filepath, storage, force) {
|
|
|
151
151
|
'rules=' + encodeURIComponent(rules)
|
|
152
152
|
].join('&');
|
|
153
153
|
request(body, function() {
|
|
154
|
-
info('Setting whistle
|
|
154
|
+
info('Setting whistle (' + (options.host || '127.0.0.1') + ':' + port + ') rules successful.');
|
|
155
155
|
});
|
|
156
156
|
};
|
|
157
157
|
if (force) {
|
package/bin/util.js
CHANGED
|
@@ -7,12 +7,13 @@ var config = require('../lib/config');
|
|
|
7
7
|
var colors = require('colors/safe');
|
|
8
8
|
var path = require('path');
|
|
9
9
|
var createHmac = require('crypto').createHmac;
|
|
10
|
+
|
|
10
11
|
/*eslint no-console: "off"*/
|
|
11
12
|
var CHECK_RUNNING_CMD = process.platform === 'win32' ?
|
|
12
13
|
'tasklist /fi "PID eq %s" | findstr /i "node.exe"'
|
|
13
14
|
: 'ps -f -p %s | grep "node"';
|
|
14
15
|
var isWin = process.platform === 'win32';
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
function isRunning(pid, callback) {
|
|
17
18
|
pid ? cp.exec(util.format(CHECK_RUNNING_CMD, pid),
|
|
18
19
|
function (err, stdout, stderr) {
|
|
@@ -88,6 +89,15 @@ function showUsage(isRunning, options, restart) {
|
|
|
88
89
|
if (parseInt(process.version.slice(1), 10) < 6) {
|
|
89
90
|
warn(colors.bold('\nWarning: The current Node version is too low, access https://nodejs.org to install the latest version, or may not be able to Capture HTTPS CONNECTs\n'));
|
|
90
91
|
}
|
|
92
|
+
var bypass = options.init;
|
|
93
|
+
if (bypass == null) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
host: options.host || '127.0.0.1',
|
|
98
|
+
port: port,
|
|
99
|
+
bypass: typeof bypass === 'string' ? bypass : undefined
|
|
100
|
+
};
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
exports.showUsage = showUsage;
|
|
@@ -146,4 +156,11 @@ exports.readConfigList = readConfigList;
|
|
|
146
156
|
exports.getHash = function(str) {
|
|
147
157
|
var hmac = createHmac('sha256', 'a secret');
|
|
148
158
|
return hmac.update(str).digest('hex');
|
|
149
|
-
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
exports.getDefaultPort = function () {
|
|
162
|
+
var conf = readConfig();
|
|
163
|
+
conf = conf && conf.options;
|
|
164
|
+
var port = conf && conf.port;
|
|
165
|
+
return port > 0 ? port : 8899;
|
|
166
|
+
};
|
package/bin/whistle.js
CHANGED
|
@@ -7,14 +7,30 @@ var useRules = require('./use');
|
|
|
7
7
|
var showStatus = require('./status');
|
|
8
8
|
var util = require('./util');
|
|
9
9
|
var plugin = require('./plugin');
|
|
10
|
+
var setProxy = require('./proxy/cli');
|
|
11
|
+
var installCA = require('./ca/cli');
|
|
10
12
|
|
|
11
|
-
var showUsage = util.showUsage;
|
|
12
13
|
var error = util.error;
|
|
13
14
|
var info = util.info;
|
|
15
|
+
var hasInit;
|
|
16
|
+
|
|
17
|
+
function handleEnd(err, options, restart) {
|
|
18
|
+
options = util.showUsage(err, options, restart);
|
|
19
|
+
if (!options || !hasInit) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
var host = options.host + ':' + options.port;
|
|
23
|
+
var argv = [host];
|
|
24
|
+
if (options.bypass) {
|
|
25
|
+
argv.push('-x', options.bypass);
|
|
26
|
+
}
|
|
27
|
+
setProxy(argv);
|
|
28
|
+
installCA([host]);
|
|
29
|
+
}
|
|
14
30
|
|
|
15
31
|
function showStartupInfo(err, options, debugMode, restart) {
|
|
16
32
|
if (!err || err === true) {
|
|
17
|
-
return
|
|
33
|
+
return handleEnd(err, options, restart);
|
|
18
34
|
}
|
|
19
35
|
if (/listen EADDRINUSE/.test(err)) {
|
|
20
36
|
options = util.formatOptions(options);
|
|
@@ -54,7 +70,7 @@ program.setConfig({
|
|
|
54
70
|
showStartupInfo(err, options, true);
|
|
55
71
|
return;
|
|
56
72
|
}
|
|
57
|
-
|
|
73
|
+
handleEnd(false, options);
|
|
58
74
|
console.log('Press [Ctrl+C] to stop ' + config.name + '...');
|
|
59
75
|
},
|
|
60
76
|
startCallback: showStartupInfo,
|
|
@@ -80,15 +96,19 @@ program
|
|
|
80
96
|
.command('status')
|
|
81
97
|
.description('Show the running status');
|
|
82
98
|
program
|
|
83
|
-
.command('add
|
|
99
|
+
.command('add')
|
|
84
100
|
.description('Add rules from local js file (.whistle.js by default)');
|
|
101
|
+
program.command('proxy')
|
|
102
|
+
.description('Set global proxy');
|
|
103
|
+
program.command('ca')
|
|
104
|
+
.description('Install root CA');
|
|
85
105
|
program.command('install')
|
|
86
|
-
.description('Install
|
|
106
|
+
.description('Install whistle plugin');
|
|
87
107
|
program.command('uninstall')
|
|
88
|
-
.description('Uninstall
|
|
108
|
+
.description('Uninstall whistle plugin');
|
|
89
109
|
program.command('exec')
|
|
90
|
-
.description('Exec whistle plugin
|
|
91
|
-
|
|
110
|
+
.description('Exec whistle plugin cmd');
|
|
111
|
+
|
|
92
112
|
program
|
|
93
113
|
.option('-D, --baseDir [baseDir]', 'set the configured storage root path', String, undefined)
|
|
94
114
|
.option('-z, --certDir [directory]', 'set custom certificate store directory', String, undefined)
|
|
@@ -114,6 +134,7 @@ program
|
|
|
114
134
|
.option('-R, --reqCacheSize [reqCacheSize]', 'set the cache size of request data (600 by default)', String, undefined)
|
|
115
135
|
.option('-F, --frameCacheSize [frameCacheSize]', 'set the cache size of webSocket and socket\'s frames (512 by default)', String, undefined)
|
|
116
136
|
.option('-A, --addon [pluginPaths]', 'add custom plugin paths', String, undefined)
|
|
137
|
+
.option('--init [bypass]', 'auto set global proxy (and bypass) and install root CA')
|
|
117
138
|
.option('--config [workers]', 'start the cluster server and set worker number (os.cpus().length by default)', String, undefined)
|
|
118
139
|
.option('--cluster [config]', 'load the startup config from a local file', String, undefined)
|
|
119
140
|
.option('--dnsServer [dnsServer]', 'set custom dns servers', String, undefined)
|
|
@@ -132,12 +153,20 @@ var removeItem = function(list, name) {
|
|
|
132
153
|
var i = list.indexOf(name);
|
|
133
154
|
i !== -1 && list.splice(i, 1);
|
|
134
155
|
};
|
|
156
|
+
if (argv.indexOf('--init') !== -1) {
|
|
157
|
+
hasInit = true;
|
|
158
|
+
process.env.WHISTLE_MODE = (process.env.WHISTLE_MODE || '') + '|persistentCapture';
|
|
159
|
+
}
|
|
135
160
|
if (cmd === 'status') {
|
|
136
161
|
var all = argv[3] === '--all' || argv[3] === '-l';
|
|
137
162
|
if (argv[3] === '-S') {
|
|
138
163
|
storage = argv[4];
|
|
139
164
|
}
|
|
140
165
|
showStatus(all, storage);
|
|
166
|
+
} else if (cmd === 'proxy') {
|
|
167
|
+
setProxy(Array.prototype.slice.call(argv, 3));
|
|
168
|
+
} else if (cmd === 'ca') {
|
|
169
|
+
installCA(Array.prototype.slice.call(argv, 3));
|
|
141
170
|
} else if (/^([a-z]{1,2})?uni(nstall)?$/.test(cmd)) {
|
|
142
171
|
plugin.uninstall(Array.prototype.slice.call(argv, 3));
|
|
143
172
|
} else if (/^([a-z]{1,2})?i(nstall)?$/.test(cmd)) {
|
package/biz/index.js
CHANGED
|
@@ -138,7 +138,7 @@ module.exports = function(req, res, next) {
|
|
|
138
138
|
} else if (localRule = rules.resolveLocalRule(req)) {
|
|
139
139
|
req.url = localRule.url;
|
|
140
140
|
if (localRule.realPort) {
|
|
141
|
-
req.headers.host = '127.0.0.1:' + localRule.realPort;
|
|
141
|
+
req.headers.host = '127.0.0.1:' + localRule.realPort;
|
|
142
142
|
util.transformReq(req, res, localRule.realPort);
|
|
143
143
|
} else {
|
|
144
144
|
handleUIReq(req, res);
|
|
@@ -2,7 +2,7 @@ var ca = require('../../../../lib/https/ca');
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
module.exports = function(req, res) {
|
|
5
|
-
ca.removeCert(req.body
|
|
5
|
+
ca.removeCert(req.body);
|
|
6
6
|
var isparsed = req.query.dataType === 'parsed';
|
|
7
7
|
res.json(isparsed ? ca.getCustomCertsInfo() : ca.getCustomCertsFiles());
|
|
8
8
|
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
var getRootCAFile = require('../../../lib/https/ca').getRootCAFile;
|
|
2
2
|
|
|
3
3
|
module.exports = function(req, res) {
|
|
4
|
-
|
|
4
|
+
var type = req.query.type;
|
|
5
|
+
if (type !== 'cer' && type !== 'pem') {
|
|
6
|
+
type = 'crt';
|
|
7
|
+
}
|
|
8
|
+
res.download(getRootCAFile(), 'rootCA.' + type);
|
|
5
9
|
};
|
|
@@ -148,7 +148,7 @@ exports.sendGzip = function(req, res, data) {
|
|
|
148
148
|
res.json(data);
|
|
149
149
|
} catch (e) {
|
|
150
150
|
res.status(500).send(config.debugMode ?
|
|
151
|
-
'<pre>' + util.getErrorStack(err) + '</pre>' : 'Internal Server Error');
|
|
151
|
+
'<pre>' + util.encodeHtml(util.getErrorStack(err)) + '</pre>' : 'Internal Server Error');
|
|
152
152
|
}
|
|
153
153
|
return;
|
|
154
154
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|