Skip to content

Commit

Permalink
Squashed 'vendor/whistle/' changes from ce0b2be01d..c646ec6560
Browse files Browse the repository at this point in the history
c646ec6560 Release v2.9.56
98fd6f4cbe refactor: remove node-native-zip
e438fedcc0 docs: w2 add --client
b98c4184ac chore: ignore bin/import
0b13eba49d feat: support ipv6-only network
7efa8828fe feat: support esmodule
1fae083bfe docs: client
812dd3ccb6 Release v2.9.55
8bd7b9c018 refactor: update plugins
1d7a20a63d style: refine ui
9ee9ff87f4 Release v2.9.54
b9de59e821 Release v2.9.54
9e542adb9e feat: refine json tree
5975051f80 refactor: refine code
32ce2934ed fix: 暗色模式下,图片受滤镜影响,颜色不正确
4b1c5c0d96 Release v2.9.53
b098b871ac Release v2.9.53
13ab1b0777 feat: darm mode
2c7aff82dd feat: enable://forHttp|forHttps
0ab0004336 docs: update
aeabb07810 Update expired link in README.md
5f7f3b3976 Release v2.9.52
d9628fe581 refactor: refine code
f87496e4ff refactor: refine file://path
ef77eeb064 Release v2.9.51
050a70fd03 Release v2.9.51
9be635db41 fix: avwo/whistle#912
d361eda074 Release v2.9.50
b83f7d11b6 Release v2.9.50
bf0dd13b03 feat: --uiport ip:port
5610a5b046 feat: --uiport ip:port
d5d1bcb224 fix: http.request of Node v20.1.0
ef99f187b3 style: refine ui
5f6cd6a3ae refactor: refine ui
8e9fe8aba9 refactor: show the tunnel request of CAPTURE TUNNEL CONNECTS error
b2e6e09f71 Release v2.9.49
5273d631be feat: refine editor history
f158c7e5cf feat: add sharedStorage
9ac793ac4f fix: command line flags '--cluster' and '--config'
6b93f52608 refactor: refine code
c4d939aea1 style: clear cache
9321baabd2 style: clear cache
d64487f1a1 refactor: refine code
30ec22f25d refactor: refine code
edcc53df53 feat:make the component——editor's history independent
99139f1e2a fix: conflict
c73af9c1e6 refactor: refine code
e305e8721e fix: headerReplace://req.host
335f8d8354 refactor: headerReplace://reqH.xxx === headerReplace://req.xxx
e1c625ddbf Release v2.9.48
66fd5419b0 Release v2.9.48
bbaa81ad6f fix: socksv5 proxy
f00e3565ab style: Compose -> Edit
b79d6a347e style: exportSessions(sessions, type, name)
98d6244c68 refactor: refine code
d9504761ae Release v2.9.47
4e397f001e feat: add activeList
42b40c3479 feat: add customData
f4d0cc2a0a feat: add updateUI
3a069a61a5 Release v2.9.46
ef1ebfc87f refactor: refine tpl protocol
897ba0b001 feat: add copyText

git-subtree-dir: vendor/whistle
git-subtree-split: c646ec6560610b63ee0acaf614ae33fd8c46d848
  • Loading branch information
shejinxin committed Aug 3, 2023
1 parent d9fb5dd commit 3e6d41e
Show file tree
Hide file tree
Showing 94 changed files with 3,384 additions and 9,251 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
/biz/webui/htdocs/src/js/components
/test/assets/values
/test/plugins/whistle.test/assets
/bin/import.js
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,49 @@

# v2.9.56
1. feat: 支持通过 `Online / IPv6-only network` 强制 dns 获取 ipv6(命令行版本还可以通过 `-M ipv6Only` 开启)
2. feat: `w2 add` 命令支持 `type: module`
# v2.9.55
1. feat: 显示 `captureError`,且可以通过插件获取到这类型错误的抓包数据
2. fix: 完善 `refreshPlugins` 方法(内部方法)

# v2.9.54
1. fix: 修复 Dark Mode 模式下图片显示问题
2. fix: JSON 过滤搜索时保留数组的 index

# v2.9.53
1. feat: 支持通过 `enable://forHttp|forHttps` 设置 `enable://capture` 只对 http 或 https 生效
2. feat: 支持通过请求参数设置登录态
3. feat: 支持 `Dark Mode`,且可以通过界面 `Online -> 打开对话框 -> Disable dark mode` 关闭自动切换 `Dark Mode`

# v2.9.52
1. feat: 跨域请求本地替换自动设置 cors,可以通过 `disable://autoCors``lineProps://disableAutoCors` 关闭

# v2.9.51
1. fix: https://github.com/avwo/whistle/issues/912
# v2.9.50
1. fix: Node 20.1.0 版本 `http.request` 只支持通过 `options.search` 设置参数问题
2. feat: 支持通过 `--uiport "127.0.0.1:8080"` 限制 WebUI 只能通过指定网卡和端口访问

# v2.9.49
1. fix: `headerReplace://req.host:pattern=value` 无效问题
2. feat: 插件添加 `sharedStorage` 方便插件在不同实例中共享存储数据
3. style: https://github.com/avwo/whistle/pull/898

# v2.9.48
1. feat: 插件扩展的右键菜单和 Tab 添加 `exportSessions(sessions, type, name)` 方法
2. feat: 插件 server 的 options 添加 `generateSaz(sessions): Buffer``extract(saz: Buffer, cb(sessions))` 方法
3. refactor: 兼容 saz 的 comment,需要配合插件使用:https://github.com/whistle-plugins/whistle.comment.git
4. fix: 修复访问 socks 代理可能出现 pending 的问题
5. style: 界面优化

# v2.9.47
1. refactor: 解决安装时依赖包安全警告问题
2. feat: 支持自定义右键菜单获取树结点下的所有抓包数据

# v2.9.46
1. feat: 扩展 Tab 支持 `copyText` 方法
2. feat: `tpl` 协议支持模板字符串语法

# v2.9.45
1. feat: 插件界面提供 `copyText` 方法
2. feat: 支持 `lineProps://strictHtml``lineProsy://safeHtml` 只对当前行的规则生效
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
[![NPM count](https://img.shields.io/npm/dt/whistle.svg?style=flat-square)](https://www.npmjs.com/package/whistle)
[![License](https://img.shields.io/npm/l/whistle.svg?style=flat-square)](https://www.npmjs.com/package/whistle)

**Mac 或 Windows 系统推荐使用客户端版本:https://github.com/avwo/whistle-client**

Whistle 是基于 Node 实现的跨平台抓包调试工具,其主要特点:
1. **完全跨平台**:支持 Mac、Windows 等桌面系统,且支持服务端等命令行系统
2. **功能强大(理论上可以对请求做任意修改)**
Expand Down
1 change: 1 addition & 0 deletions assets/fiddler/meta.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
<SessionFlag N="x-hostip" V="${hostip}" />
<SessionFlag N="x-clientport" V="${clientport}" />
<SessionFlag N="x-serverport" V="${serverport}" />
<SessionFlag N="ui-comments" V="${ui-comments}" />
</SessionFlags>
</Session>
6 changes: 3 additions & 3 deletions assets/launcher/windows/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Windows上配置开机重启whistle
首先,下载Windows上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/raw/avenwu/assets/launcher/windows/whistle.zip)
首先,下载Windows上的whistle脚步文件:[whistle.zip](https://github.com/avwo/whistle/raw/master/assets/launcher/windows/whistle.zip)

1. 解压whistle.zip获取whistle.bat的脚本文件,把该脚本文件拷贝一份到Windows的桌面,这样可以直接在Mac的桌面上刊登whistle的启动脚本,双击即可重启whistle(会先弹出一个命令行窗口,等3秒左右就会自动消失);
1. 解压whistle.zip获取whistle.bat的脚本文件,把该脚本文件拷贝一份到Windows的桌面,这样可以直接在Windows的桌面上看到whistle的启动脚本,双击即可重启whistle(会先弹出一个命令行窗口,等3秒左右就会自动消失);

2. 把桌面上的whistle.bat文件拖到桌面左下角的系统**开始菜单 --> 所有程序 --> 启动**目录下面,或者直接拷贝到系统目录`C:\Users\{yourAccount}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup`(可以直接在开始菜单或者文件管理器中的输入框输入`%appData%\Microsoft\Windows\Start Menu\Programs\Startup`快速定位到启动菜单目录),这样就配置好了开机自动重启whistle。

![设置Windows开机重启whistle](whistle.gif)
![设置Windows开机重启whistle](whistle.gif)
2 changes: 2 additions & 0 deletions assets/menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,13 @@
Object.keys(options.msgBox).forEach(function(name) {
toast[name] = options.msgBox[name];
});
whistleBridge.updateUI = options.updateUI;
whistleBridge.copyText = options.copyText;
whistleBridge.pageId = options.pageId;
whistleBridge.compose = options.compose;
whistleBridge.decodeBase64 = options.decodeBase64;
whistleBridge.importSessions = options.importSessions;
whistleBridge.exportSessions = options.exportSessions;
whistleBridge.request = options.request;
whistleBridge.createRequest = options.createRequest;
whistleBridge.showModal = options.showModal;
Expand Down
3 changes: 3 additions & 0 deletions assets/tab.html
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,13 @@
});
getActiveSession = options.getActiveSession;
getSelectedSessionList = options.getSelectedSessionList;
whistleBridge.updateUI = options.updateUI;
whistleBridge.copyText = options.copyText;
whistleBridge.pageId = options.pageId;
whistleBridge.compose = options.compose;
whistleBridge.decodeBase64 = options.decodeBase64;
whistleBridge.importSessions = options.importSessions;
whistleBridge.exportSessions = options.exportSessions;
whistleBridge.request = options.request;
whistleBridge.createRequest = options.createRequest;
whistleBridge.showModal = options.showModal;
Expand Down
23 changes: 23 additions & 0 deletions bin/import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
var fs = require('fs');

function importModle(filepath, callback) {
return import(filepath).then(callback);
}

module.exports = function(filepath, callback) {
try {
return callback(require(filepath));
} catch (e) {
var code =e && e.code;
if (code === 'ERR_REQUIRE_ESM') {
// ignore eslint & fix type=module
return importModle(filepath, callback);
} else if (code === 'MODULE_NOT_FOUND' && /\.js$/i.test(filepath)) {
filepath = filepath.slice(0, -3) + '.mjs';
if (fs.existsSync(filepath)) {
return importModle(filepath, callback);
}
}
throw e;
}
};
15 changes: 2 additions & 13 deletions bin/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,21 @@ var commonUtil = require('../lib/util/common');

var getWhistlePath = commonUtil.getWhistlePath;
var REMOTE_URL_RE = commonUtil.REMOTE_URL_RE;
var WHISTLE_PLUGIN_RE = commonUtil.WHISTLE_PLUGIN_RE;
const getPlugins = commonUtil.getPlugins;
var CMD_SUFFIX = process.platform === 'win32' ? '.cmd' : '';
var CUSTOM_PLUGIN_PATH = path.join(getWhistlePath(), 'custom_plugins');
var DEFAULT_PATH = commonUtil.getDefaultWhistlePath();
var REGISTRY_LIST = path.join(DEFAULT_PATH, '.registry.list');
var PACKAGE_JSON = '{"repository":"https://github.com/avwo/whistle","license":"MIT"}';
var LICENSE = 'Copyright (c) 2019 avwo';
var RESP_URL = 'https://github.com/avwo/whistle';
var WHISTLE_PLUGIN_RE = /^((?:@[\w-]+\/)?whistle\.[a-z\d_-]+)(?:\@([\w.^~*-]*))?$/;
var MAX_REG_COUNT = 100;

function getInstallPath(name, dir) {
return path.join(dir || CUSTOM_PLUGIN_PATH, name);
}

function getPlugins(argv, isInstall) {
return argv.filter(function(name, i) {
if (WHISTLE_PLUGIN_RE.test(name)) {
return true;
}
if (argv[i - 1] === '--registry') {
return false;
}
return isInstall && REMOTE_URL_RE.test(name);
});
}

function removeDir(installPath) {
if (fs.existsSync(installPath)) {
fse.removeSync(installPath);
Expand Down
95 changes: 65 additions & 30 deletions bin/use.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ var path = require('path');
var fs = require('fs');
var http = require('http');
var url = require('url');
var Buffer = require('safe-buffer').Buffer;
var util = require('./util');
var importModule = require('./import');
var pkg = require('../package.json');
var getHomedir = require('../lib/util/common').getHomedir;

var isRunning = util.isRunning;
var error = util.error;
Expand All @@ -14,24 +17,28 @@ var MAX_RULES_LEN = 1024 * 256;
var DEFAULT_OPTIONS = { host: '127.0.0.1', port: 8899 };
var options;

function showStartWhistleTips(storage) {
error('No running whistle, execute `w2 start' + (storage ? ' -S ' + storage : '')
+ '` to start whistle on the cli.');
function showStartWhistleTips(storage, isClient) {
if (isClient) {
error('No running whistle client, please install and start the latest whistle client: https://github.com/avwo/whistle-client');
} else {
error('No running whistle, execute `w2 start' + (storage ? ' -S ' + storage : '') + '` to start whistle on the cli.');
}
}

function handleRules(filepath, callback, port) {
var getRules = require(filepath);
if (typeof getRules !== 'function') {
return callback(getRules);
}
var opts = {
port: port,
existsPlugin: existsPlugin
};
if (options && options.host) {
opts.host = options.host;
}
getRules(callback, opts);
importModule(filepath, function(getRules) {
if (typeof getRules !== 'function') {
return callback(getRules);
}
var opts = {
port: port,
existsPlugin: existsPlugin
};
if (options && options.host) {
opts.host = options.host;
}
getRules(callback, opts);
});
}

function getString(str) {
Expand Down Expand Up @@ -75,10 +82,13 @@ function request(body, callback) {
reqOptions.headers = {
'content-type': 'application/x-www-form-urlencoded'
};
if (options.specialAuth) {
reqOptions.headers['x-whistle-special-auth'] = options.specialAuth;
}
reqOptions.method = 'POST';
if (options.username || options.password) {
var auth = [options.username || '', options.password || ''].join(':');
reqOptions.headers.authorization = 'Basic ' + new Buffer(auth).toString('base64');
reqOptions.headers.authorization = 'Basic ' + new Buffer.from(auth).toString('base64');
}
}
var req = http.request(reqOptions, function(res) {
Expand All @@ -93,10 +103,13 @@ function request(body, callback) {
req.end(body);
}

function checkDefault(running, storage, callback) {
function checkDefault(running, storage, isClient, callback) {
if (running) {
return callback();
}
if (isClient) {
return callback(true);
}
var execCallback = function(err) {
callback && callback(err);
callback = null;
Expand All @@ -114,20 +127,42 @@ function checkDefault(running, storage, callback) {
req.end();
}

module.exports = function(filepath, storage, force) {
storage = storage || '';
var dir = encodeURIComponent(storage);
var config = readConfig(dir) || '';
function readClientConfig() {
var procPath = path.join(getHomedir(), '.whistle_client.pid');
try {
var info = fs.readFileSync(procPath, { encoding: 'utf-8' }).split(',');
if (info.length === 4) {
return {
pid: info[0],
options: {
host: info[1],
port: info[2],
specialAuth: info[3]
}
};
}
} catch (e) {}
}

module.exports = function(filepath, storage, force, isClient) {
var config;
var dir = '';
if (isClient) {
storage = '';
config = readClientConfig() || '';
} else {
storage = storage || '';
dir = encodeURIComponent(storage);
config = readConfig(dir) || '';
if (config.options) {
delete config.options.specialAuth;
}
}
options = config.options || '';
var pid = options && config.pid;
var addon = options && options.addon;
var conf = require('../lib/config');
conf.addon = addon && typeof addon === 'string' ? addon.split(/[|,]/) : null;
conf.noGlobalPlugins = options && options.noGlobalPlugins;
isRunning(pid, function(running) {
checkDefault(running, dir, function(err, port) {
isRunning(options && config.pid, function(running) {
checkDefault(running, dir, isClient, function(err, port) {
if (err) {
return showStartWhistleTips(storage);
return showStartWhistleTips(storage, isClient);
}
filepath = path.resolve(filepath || '.whistle.js');
if (port) {
Expand Down Expand Up @@ -158,7 +193,7 @@ module.exports = function(filepath, storage, force) {
'groupName=' + encodeURIComponent(groupName.trim())
].join('&');
request(body, function() {
info('Setting whistle (' + (options.host || '127.0.0.1') + ':' + port + ') rules successful.');
info('Setting whistle' + (isClient ? ' client' : '') + ' (' + (options.host || '127.0.0.1') + ':' + port + ') rules successful.');
});
};
if (force) {
Expand Down
2 changes: 1 addition & 1 deletion bin/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function showUsage(isRunning, options, restart) {
info('[i] ' + config.name + '@' + config.version + (restart ? ' restarted' : ' started'));
}
var port = /^\d+$/.test(options.port) && options.port > 0 ? options.port : config.port;
var list = options.host ? [options.host] : getIpList();
var list = options.host && typeof options.host === 'string' ? [options.host] : getIpList();
info('[i] 1. use your device to visit the following URL list, gets the ' + colors.bold('IP') + ' of the URL you can access:');
info(list.map(function(ip) {
return ' http://' + colors.bold(getIpHost(ip)) + (port && port != 80 ? ':' + port : '') + '/';
Expand Down
16 changes: 13 additions & 3 deletions bin/whistle.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ program
.option('-F, --frameCacheSize [frameCacheSize]', 'set the cache size of webSocket and socket\'s frames (512 by default)', String, undefined)
.option('-A, --addon [pluginPaths]', 'add custom plugin paths', String, undefined)
.option('--init [bypass]', 'auto set global proxy (and bypass) and install root CA')
.option('--config [workers]', 'start the cluster server and set worker number (os.cpus().length by default)', String, undefined)
.option('--cluster [config]', 'load the startup config from a local file', String, undefined)
.option('--cluster [workers]', 'start the cluster server and set worker number (os.cpus().length by default)', String, undefined)
.option('--config [config]', 'load the startup config from a local file', String, undefined)
.option('--dnsServer [dnsServer]', 'set custom dns servers', String, undefined)
.option('--socksPort [socksPort]', 'set the socksv5 server port', String, undefined)
.option('--httpPort [httpPort]', 'set the http server port', String, undefined)
Expand Down Expand Up @@ -179,6 +179,16 @@ if (cmd === 'status') {
if (force) {
argv.splice(index, 1);
}
index = argv.indexOf('-c');
var isClient = index !== -1;
if (isClient) {
argv.splice(index, 1);
}
index = argv.indexOf('--client');
if (index !== -1) {
isClient = true;
argv.splice(index, 1);
}
var filepath = argv[3];
if (filepath === '-S') {
filepath = null;
Expand All @@ -189,7 +199,7 @@ if (cmd === 'status') {
if (filepath && /^-/.test(filepath)) {
filepath = null;
}
useRules(filepath, storage, force);
useRules(filepath, storage, force, isClient);
} else if ((cmd === 'run' || cmd === 'exec') && argv[3] && /^[^-]/.test(argv[3])) {
cmd = argv[3];
argv = Array.prototype.slice.call(argv, 4);
Expand Down
12 changes: 10 additions & 2 deletions biz/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ var CUSTOM_PLUGIN_RE = new RegExp('^/[\\w.-]*\\.whistle-path\\.5b6af7b9884e1165[
var REAL_WEBUI_HOST_PARAM = /_whistleInternalHost_=(__([a-z\d.-]+)(?:__(\d{1,5}))?__)/;
var OUTER_PLUGIN_RE = /^(?:\/whistle)?\/((?:whistle|plugin)\.[a-z\\d_-]+)::(\d{1,5})\//;


function transformUI(req, res) {
if (config.customUIHost && !config.keepProxyUI) {
return res.status(404).end();
}
return handleUIReq(req, res);
}

module.exports = function(req, res, next) {
var config = this.config;
var pluginMgr = this.pluginMgr;
Expand Down Expand Up @@ -133,7 +141,7 @@ module.exports = function(req, res, next) {
if (isWeinre) {
handleWeinreReq(req, res);
} else {
handleUIReq(req, res);
transformUI(req, res);
}
}
} else if (localRule = rules.resolveLocalRule(req)) {
Expand All @@ -142,7 +150,7 @@ module.exports = function(req, res, next) {
req.headers.host = '127.0.0.1:' + localRule.realPort;
util.transformReq(req, res, localRule.realPort);
} else {
handleUIReq(req, res);
transformUI(req, res);
}
} else {
next();
Expand Down
Loading

0 comments on commit 3e6d41e

Please sign in to comment.