Unverified Commit a5cbe4c1 authored by Medicean's avatar Medicean Committed by GitHub

Release v2.0.5

Merge pull request #130 from AntSwordProject/v2.0.x
parents 942c059a f2b12127
......@@ -2,6 +2,38 @@
> 有空会补补BUG、添添新功能。
> 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT.
## 2019/03/04 `v(2.0.5)`
### 后端模块
* 新增 chunked 流式传输
![chunk-2.png](https://i.loli.net/2019/01/28/5c4e8869c83ae.png)
### Shell 管理
* 新增「测试连接」功能
* 其它设置增加「开启分块传输」开关,设置「最小分块」和「最大分块」。每次分块大小为[n, m]区间。
![chunk-1.png](https://i.loli.net/2019/01/28/5c4e8868f178a.png)
### 文件管理
* 编辑文件标签打开时显示正在编辑的文件的「IP地址」和「绝对路径」 (#129)
* 编辑文件「保存」按钮移动到右侧
### 插件市场
* 支持使用代理访问插件市场,当配置了代理之后,默认开启
### 浏览网站
* 新增代理开关, 在配置了代理之后,可通过该开关控制是否使用代理浏览目标网站
### Other
* 调整 aproxy uri 初始化 URL 格式
## 2019/01/21 `v(2.0.4)`
### 后端模块
......
# AntSword [![release](https://img.shields.io/badge/release-v2.0.4-blue.svg?style=flat-square)][url-release]
# AntSword [![release](https://img.shields.io/badge/release-v2.0.5-blue.svg?style=flat-square)][url-release]
> AntSword in your hands, no worries in your mind!
......@@ -22,6 +22,17 @@ This software, of which the development thought is modularization, is intended t
![][url-mainui]
<details>
<summary>More Screenshots</summary>
![][url-filemanager]
![][url-terminal]
![][url-database]
![][url-pluginstore]
</details>
## Quick Start
See document: [Quick Start][url-quickstart]
......@@ -41,7 +52,7 @@ See document: [Make contributions to AntSword][url-contribute]
[url-doczh]: README_CN.md
[url-changelog]: CHANGELOG.md
[url-document]: http://doc.u0u.us/en/
[url-release]: https://github.com/AntSwordProject/AntSword/releases/tag/2.0.0
[url-release]: https://github.com/AntSwordProject/AntSword/releases/
[url-electron]: http://electron.atom.io/
[url-es6]: http://es6.ruanyifeng.com/
[url-dhtmlx]: http://dhtmlx.com/
......@@ -50,4 +61,8 @@ See document: [Make contributions to AntSword][url-contribute]
[url-release]: https://github.com/AntSwordProject/AntSword/releases
[url-quickstart]: https://doc.u0u.us/en/getting_started/index.html
[url-contribute]: https://doc.u0u.us/en/contribute_docs.html
[url-mainui]: http://7xtigg.com1.z0.glb.clouddn.com/doc/getting_started/get_antsword_2.jpg
\ No newline at end of file
[url-mainui]: http://as.xuanbo.cc/doc/getting_started/get_antsword_2.jpg
[url-filemanager]: http://as.xuanbo.cc/doc/file_manager/main_page_1.png
[url-terminal]: http://as.xuanbo.cc/doc/terminal/main_page_1.png
[url-database]: http://as.xuanbo.cc/doc/database/main_page_1.png
[url-pluginstore]: http://as.xuanbo.cc/doc/plugin_store/main_page_2.jpg
# 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.4-blue.svg?style=flat-square)][url-release]
# 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.5-blue.svg?style=flat-square)][url-release]
> 一剑在手,纵横无忧!
......@@ -20,6 +20,17 @@
![][url-mainui]
<details>
<summary>更多截图</summary>
![][url-filemanager]
![][url-terminal]
![][url-database]
![][url-pluginstore]
</details>
## 快速入门
参见文档 [快速入门][url-quickstart]
......@@ -41,7 +52,7 @@
[url-docen]: README.md
[url-changelog]: CHANGELOG.md
[url-document]: http://doc.u0u.us/zh-hans/
[url-release]: https://github.com/AntSwordProject/AntSword/releases/tag/2.0.0
[url-release]: https://github.com/AntSwordProject/AntSword/releases/
[url-electron]: http://electron.atom.io/
[url-es6]: http://es6.ruanyifeng.com/
[url-dhtmlx]: http://dhtmlx.com/
......@@ -50,4 +61,8 @@
[url-release]: https://github.com/AntSwordProject/AntSword/releases
[url-quickstart]: https://doc.u0u.us/zh-hans/getting_started/index.html
[url-contribute]: https://doc.u0u.us/zh-hans/contribute_docs.html
[url-mainui]: http://7xtigg.com1.z0.glb.clouddn.com/doc/getting_started/get_antsword_2.jpg
\ No newline at end of file
[url-mainui]: http://as.xuanbo.cc/doc/getting_started/get_antsword_2.jpg
[url-filemanager]: http://as.xuanbo.cc/doc/file_manager/main_page_1.png
[url-terminal]: http://as.xuanbo.cc/doc/terminal/main_page_1.png
[url-database]: http://as.xuanbo.cc/doc/database/main_page_1.png
[url-pluginstore]: http://as.xuanbo.cc/doc/plugin_store/main_page_2.jpg
......@@ -12,6 +12,7 @@ const fs = require('fs'),
CONF = require('./config'),
superagent = require('superagent'),
superagentProxy = require('superagent-proxy');
const { Readable } = require("stream");
let logger;
// 请求UA
......@@ -109,49 +110,95 @@ class Request {
}
// 自定义body
const _postData = Object.assign({}, opts.body, opts.data);
// 通过替换函数方式来实现发包方式切换, 后续可改成别的
const old_send = _request.send;
if(opts['useMultipart'] == 1) {
_request.send = _request.field;
}else{
_request.send = old_send;
}
_request
.proxy(APROXY_CONF['uri'])
.type('form')
// 超时
.timeout(opts.timeout || REQ_TIMEOUT)
// 忽略HTTPS
.ignoreHTTPS(opts['ignoreHTTPS'])
.send(_postData)
.parse((res, callback) => {
this.parse(opts['tag_s'], opts['tag_e'], (chunk) => {
event.sender.send('request-chunk-' + opts['hash'], chunk);
}, res, callback);
})
.end((err, ret) => {
if (!ret) {
// 请求失败 TIMEOUT
return event.sender.send('request-error-' + opts['hash'], err);
if (opts['useChunk'] == 1){
logger.debug("request with Chunked");
let _postarr = [];
for(var key in _postData){
if(_postData.hasOwnProperty(key)){
_postarr.push(`${key}=${encodeURIComponent(_postData[key])}`);
}
let buff = ret.hasOwnProperty('body') ? ret.body : new Buffer();
// 解码
let text = "";
// 自动猜测编码
let encoding = detectEncoding(buff, {defaultEncoding:"unknown"});
logger.debug("detect encoding:", encoding);
encoding = encoding != "unknown" ? encoding : opts['encode'];
text = iconv.decode(buff, encoding);
if (err && text == "") {
return event.sender.send('request-error-' + opts['hash'], err);
};
// 回调数据
event.sender.send('request-' + opts['hash'], {
text: text,
buff: buff,
encoding: encoding
}
let antstream = new AntRead(_postarr.join("&"), {'step': parseInt(opts['chunkStepMin']), 'stepmax': parseInt(opts['chunkStepMax'])});
let _datasuccess = false; // 表示是否是 404 类shell
_request
.proxy(APROXY_CONF['uri'])
.type('form')
// .set('Content-Type', 'application/x-www-form-urlencoded')
.timeout(opts.timeout || REQ_TIMEOUT)
.ignoreHTTPS(opts['ignoreHTTPS'])
.parse((res, callback) => {
this.parse(opts['tag_s'], opts['tag_e'], (chunk) => {
event.sender.send('request-chunk-' + opts['hash'], chunk);
}, res, (err, ret)=>{
let buff = ret ? ret : new Buffer();
// 自动猜测编码
let encoding = detectEncoding(buff, {defaultEncoding: "unknown"});
logger.debug("detect encoding:", encoding);
encoding = encoding != "unknown" ? encoding : opts['encode'];
let text = iconv.decode(buff, encoding);
if (err && text == "") {
return event.sender.send('request-error-' + opts['hash'], err);
};
// 回调数据
event.sender.send('request-' + opts['hash'], {
text: text,
buff: buff,
encoding: encoding
});
_datasuccess = true;
callback(null, ret);
});
}).on('error', (err) => {
if(_datasuccess == false) {
return event.sender.send('request-error-' + opts['hash'], err);
}
});
});
antstream.pipe(_request);
}else{
// 通过替换函数方式来实现发包方式切换, 后续可改成别的
const old_send = _request.send;
if(opts['useMultipart'] == 1) {
_request.send = _request.field;
}else{
_request.send = old_send;
}
_request
.proxy(APROXY_CONF['uri'])
.type('form')
// 超时
.timeout(opts.timeout || REQ_TIMEOUT)
// 忽略HTTPS
.ignoreHTTPS(opts['ignoreHTTPS'])
.send(_postData)
.parse((res, callback) => {
this.parse(opts['tag_s'], opts['tag_e'], (chunk) => {
event.sender.send('request-chunk-' + opts['hash'], chunk);
}, res, callback);
})
.end((err, ret) => {
if (!ret) {
// 请求失败 TIMEOUT
return event.sender.send('request-error-' + opts['hash'], err);
}
let buff = ret.hasOwnProperty('body') ? ret.body : new Buffer();
// 解码
let text = "";
// 自动猜测编码
let encoding = detectEncoding(buff, {defaultEncoding:"unknown"});
logger.debug("detect encoding:", encoding);
encoding = encoding != "unknown" ? encoding : opts['encode'];
text = iconv.decode(buff, encoding);
if (err && text == "") {
return event.sender.send('request-error-' + opts['hash'], err);
};
// 回调数据
event.sender.send('request-' + opts['hash'], {
text: text,
buff: buff,
encoding: encoding
});
});
}
}
/**
......@@ -181,48 +228,92 @@ class Request {
}
// 自定义body
const _postData = Object.assign({}, opts.body, opts.data);
// 通过替换函数方式来实现发包方式切换, 后续可改成别的
const old_send = _request.send;
if(opts['useMultipart'] == 1) {
_request.send = _request.field;
}else{
_request.send = old_send;
}
_request
.proxy(APROXY_CONF['uri'])
.type('form')
// 设置超时会导致文件过大时写入出错
// .timeout(timeout)
// 忽略HTTPS
.ignoreHTTPS(opts['ignoreHTTPS'])
.send(_postData)
.pipe(through(
(chunk) => {
// 判断数据流中是否包含后截断符?长度++
let temp = chunk.indexOf(opts['tag_e']);
if (temp !== -1) {
indexEnd = Buffer.concat(tempData).length + temp;
};
tempData.push(chunk);
event.sender.send('download-progress-' + opts['hash'], chunk.length);
},
() => {
let tempDataBuffer = Buffer.concat(tempData);
indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0;
// 截取最后的数据
let finalData = new Buffer(tempDataBuffer.slice(
indexStart + opts['tag_s'].length,
indexEnd
), 'binary');
// 写入文件流&&关闭
rs.write(finalData);
rs.close();
event.sender.send('download-' + opts['hash'], finalData.length);
// 删除内存数据
finalData = tempDataBuffer = tempData = null;
if (opts['useChunk'] == 1){
logger.debug("request with Chunked");
let _postarr = [];
for(var key in _postData){
if(_postData.hasOwnProperty(key)){
_postarr.push(`${key}=${_postData[key]}`);
}
}
let antstream = new AntRead(_postarr.join("&"), {'step': parseInt(opts['chunkStepMin']), 'stepmax': parseInt(opts['chunkStepMax'])});
let _datasuccess = false; // 表示是否是 404 类shell
_request
.proxy(APROXY_CONF['uri'])
.type('form')
.ignoreHTTPS(opts['ignoreHTTPS'])
.pipe(through(
(chunk) => {
// 判断数据流中是否包含后截断符?长度++
let temp = chunk.indexOf(opts['tag_e']);
if (temp !== -1) {
indexEnd = Buffer.concat(tempData).length + temp;
};
tempData.push(chunk);
event.sender.send('download-progress-' + opts['hash'], chunk.length);
},
() => {
let tempDataBuffer = Buffer.concat(tempData);
indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0;
// 截取最后的数据
let finalData = new Buffer(tempDataBuffer.slice(
indexStart + opts['tag_s'].length,
indexEnd
), 'binary');
// 写入文件流&&关闭
rs.write(finalData);
rs.close();
event.sender.send('download-' + opts['hash'], finalData.length);
// 删除内存数据
finalData = tempDataBuffer = tempData = null;
}
));
antstream.pipe(_request);
}else{
// 通过替换函数方式来实现发包方式切换, 后续可改成别的
const old_send = _request.send;
if(opts['useMultipart'] == 1) {
_request.send = _request.field;
}else{
_request.send = old_send;
}
_request
.proxy(APROXY_CONF['uri'])
.type('form')
// 设置超时会导致文件过大时写入出错
// .timeout(timeout)
// 忽略HTTPS
.ignoreHTTPS(opts['ignoreHTTPS'])
.send(_postData)
.pipe(through(
(chunk) => {
// 判断数据流中是否包含后截断符?长度++
let temp = chunk.indexOf(opts['tag_e']);
if (temp !== -1) {
indexEnd = Buffer.concat(tempData).length + temp;
};
tempData.push(chunk);
event.sender.send('download-progress-' + opts['hash'], chunk.length);
},
() => {
let tempDataBuffer = Buffer.concat(tempData);
indexStart = tempDataBuffer.indexOf(opts['tag_s']) || 0;
// 截取最后的数据
let finalData = new Buffer(tempDataBuffer.slice(
indexStart + opts['tag_s'].length,
indexEnd
), 'binary');
// 写入文件流&&关闭
rs.write(finalData);
rs.close();
event.sender.send('download-' + opts['hash'], finalData.length);
// 删除内存数据
finalData = tempDataBuffer = tempData = null;
}
));
}
}
/**
......@@ -326,4 +417,59 @@ function detectEncoding(buffer, options) {
}
};
/**
* 控步长的可读流
* @param data [string|buffer] 输入源
* @param options {} 配置
* step 步长
* stepmax 最大步长,默认与步长相等,如果大于步长,则每次读取时后随机返回 [step, stepmax] 长度的数据
*/
class AntRead extends Readable {
constructor(data, options={}) {
super();
this.index = 0;
let o = {};
o.step = options.hasOwnProperty('step') ? parseInt(options['step']) : 2;
o.step = o.step < 1 ? 2 : o.step;
o.stepmax = options.hasOwnProperty('stepmax') ? options['stepmax'] : o.step ;
if (o.stepmax < o.step) {
o.stepmax = o.step;
}
let chunk;
if('string' === typeof data) {
chunk = data;
}else if('object' === typeof data && Buffer.isBuffer(data)) { // buffer
chunk = new Buffer(data).toString();
}else{
throw Error("data must be string, buffer.");
}
this.chunk = chunk;
this.o = o;
}
// 重写自定义的可读流的 _read 方法
_read() {
let step = this.randomNum(this.o.step, this.o.stepmax);
if (this.index >= this.chunk.length) {
this.push(null);
}else{
this.push(this.chunk.substring(this.index, this.index + step) + "");
}
this.index += step;
}
// random [n, m]
randomNum(minNum, maxNum){
switch(arguments.length){
case 1:
return parseInt(Math.random()*minNum+1,10);
case 2:
return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10);
default:
return 0;
}
}
}
module.exports = Request;
{
"name": "antsword",
"version": "2.0.4",
"version": "2.0.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "antsword",
"version": "2.0.4",
"version": "2.0.5",
"description": "中国蚁剑是一款跨平台的开源网站管理工具",
"main": "app.js",
"dependencies": {
......
......@@ -189,7 +189,7 @@ antSword['aproxyauth'] = (
!aproxy['username'] || !aproxy['password']
) ? '' : `${aproxy['username']}:${aproxy['password']}`;
antSword['aproxyuri'] = `${aproxy['protocol']}:\/\/${antSword['aproxyauth']}@${aproxy['server']}:${aproxy['port']}`;
antSword['aproxyuri'] = `${aproxy['protocol']}:\/\/${antSword['aproxyauth']}${antSword['aproxyauth']===""?"":"@"}${aproxy['server']}:${aproxy['port']}`;
// 通知后端设置代理
ipcRenderer.send('aproxy', {
......
......@@ -245,6 +245,9 @@ class Base {
tag_e: opt['tag_e'],
encode: this.__opts__['encode'],
ignoreHTTPS: (this.__opts__['otherConf'] || {})['ignore-https'] === 1,
useChunk: (this.__opts__['otherConf'] || {})['use-chunk'] === 1,
chunkStepMin: (this.__opts__['otherConf'] || {})['chunk-step-byte-min'] || 2,
chunkStepMax: (this.__opts__['otherConf'] || {})['chunk-step-byte-max'] || 3,
useMultipart: (this.__opts__['otherConf'] || {})['use-multipart'] === 1,
timeout: parseInt((this.__opts__['otherConf'] || {})['request-timeout']),
headers: (this.__opts__['httpConf'] || {})['headers'] || {},
......
......@@ -106,6 +106,7 @@ module.exports = {
add: {
title: 'Add shell',
toolbar: {
test: 'Test Connection',
add: 'Add',
clear: 'Clear'
},
......@@ -117,6 +118,8 @@ module.exports = {
type: 'Shell type',
encoder: 'Encoder'
},
test_success: 'Connection Successful!',
test_warning: 'Response is null!',
warning: 'Please enter the full!',
success: 'Add shell success!',
error: (err) => antSword.noxss(`Add shell failed!\n${err}`)
......@@ -169,6 +172,13 @@ module.exports = {
otherConf: {
nohttps: 'Ignore HTTPS certificate',
usemultipart: 'Use Multipart send payload',
chunk: {
title: 'Chunked Transfer (Experimentally)',
usechunk: 'Use Chunked send payload.',
min: 'Min Block',
max: 'Max Block',
exphint: 'This feature is currently experimental and cannot be used with Multipart. Some types of servers may not support Chunked transfers. In addition, it is recommended to set the timeout period to 30s or more to avoid data transmission when the network speed is not good.',
},
terminalCache: "Use the terminal's cache",
filemanagerCache: "Use the filemanager's cache",
uploadFragment: "Upload File Fragmentation Size",
......@@ -700,6 +710,7 @@ module.exports = {
},
viewsite: {
toolbar: {
useproxy: (s) => `Proxy: ${s?'ON':'OFF'}`,
save: 'Save',
view: 'View'
},
......
......@@ -107,6 +107,7 @@ module.exports = {
add: {
title: '添加数据',
toolbar: {
test: '测试连接',
add: '添加',
clear: '清空'
},
......@@ -118,6 +119,8 @@ module.exports = {
type: '连接类型',
encoder: '编码器'
},
test_success: '连接成功!',
test_warning: '返回数据为空',
warning: '请输入完整!',
success: '添加数据成功!',
error: (err) => antSword.noxss(`添加数据失败!\n${err}`)
......@@ -170,6 +173,13 @@ module.exports = {
otherConf: {
nohttps: '忽略HTTPS证书',
usemultipart: '使用 Multipart 发包',
chunk: {
title: '分块传输(实验性功能)',
usechunk: '开启分块传输发包',
min: '最小分块',
max: '最大分块',
exphint: '该功能目前为实验性功能, 无法与 Multipart 同时使用,部分类型的服务端可能不支持Chunked传输。此外,建议超时时长设置30s以上,避免网速不好的情况下影响数据传输。',
},
terminalCache: '虚拟终端使用缓存',
filemanagerCache: '文件管理使用缓存',
uploadFragment: '上传文件分片大小',
......@@ -700,6 +710,7 @@ module.exports = {
},
viewsite: {
toolbar: {
useproxy: (s) => `代理: ${s?'开':'关'}`,
save: '保存',
view: '浏览'
},
......
......@@ -1503,7 +1503,6 @@ class PHP {
dumpResult() {
const grid = this.manager.result.layout.getAttachedObject();
let filename = `${this.core.__opts__.ip}_${new Date().format("yyyyMMddhhmmss")}.csv`;
antSword['test'] = this;
dialog.showSaveDialog({
title: LANG['result']['dump']['title'],
defaultPath: filename
......
......@@ -809,6 +809,7 @@ class FileManager {
let editor = null;
let codes = '';
let win;
let hinttext = '';
if (openfileintab == false){
win = this.createWin({
title: LANG['editor']['title'](path),
......@@ -823,6 +824,7 @@ class FileManager {
null, null, true, true
);
win = antSword['tabbar'].cells(`tab_file_${_id}`);
hinttext = `IP:${this.opts['ip']} File:${path}`;
}
win.progressOn();
......@@ -854,9 +856,11 @@ class FileManager {
_options.push(_opt);
}
toolbar.loadStruct([
{ id: 'save', type: 'button', icon: 'save', text: LANG['editor']['toolbar']['save'] },
{ id: 'hinttext', type: 'text', text: hinttext},
{ type: 'separator' },
{ type: 'spacer' },
{ id: 'save', type: 'button', icon: 'save', text: LANG['editor']['toolbar']['save'] },
{ type: 'separator' },
{
id: 'encode', type: 'buttonSelect', icon: 'language', openAll: true,
text: LANG['editor']['toolbar']['encode'],
......
......@@ -39,10 +39,17 @@ class Plugin {
win.on('close', () => {
this.win = win = null;
});
win.loadURL(url);
win.show();
// win.openDevTools();
this.win = win;
let ses = win.webContents.session;
let proxyuri = "";
if(antSword.aproxymode != "noproxy") {
proxyuri = antSword.aproxyuri;
}
ses.setProxy({proxyRules: proxyuri}, ()=>{
win.loadURL(url);
win.show();
// win.openDevTools();
this.win = win;
});
}
......
......@@ -27,36 +27,82 @@ class Form {
// toolbar点击事件
this.toolbar.attachEvent('onClick', (id) => {
if (id === 'clear') {
return this.baseForm.clear();
}
// 检测表单数据
if (
!this.baseForm.validate() ||
!this.httpForm.validate() ||
!this.otherForm.validate()
) {
return toastr.warning(LANG['list']['add']['warning'], LANG_T['warning']);
};
// 回调数据
if (callback) {
win.progressOn();
setTimeout(() => {
callback(this._parseFormData(
switch(id){
case 'clear':
this.baseForm.clear();
break;
case 'test':
if (
!this.baseForm.validate() ||
!this.httpForm.validate() ||
!this.otherForm.validate()
) {
return toastr.warning(LANG['list']['add']['warning'], LANG_T['warning']);
};
let opts = this._parseFormData(
this.baseForm.getValues(),
this.httpForm.getValues(),
this.otherForm.getValues()
)).then((msg) => {
// 添加/保存完毕后回调
win.close();
toastr.success(msg, LANG_T['success']);
}).catch((msg) => {
// 添加/保存错误
);
let opt = {
"url": opts.base['url'],
"pwd": opts.base['pwd'],
"type": opts.base['type'],
"encode": opts.base['encode'],
"encoder": opts.base['encoder'],
"httpConf": opts.http,
"otherConf": opts.other,
}
win.progressOn();
let core = new antSword["core"][opt['type']](opt);
core.request(
core.base.info()
)
.then((ret) => {
if(ret['text'].length > 0){
toastr.success(LANG['list']['add']['test_success'], LANG_T['success']);
}else{
toastr.warning(LANG['list']['add']['test_warning'], LANG_T['warning']);
}
win.progressOff();
})
.catch((err)=>{
toastr.error(JSON.stringify(err), LANG_T['error']);
win.progressOff();
toastr.error(msg, LANG_T['error']);
});
}, 100);
};
break;
case 'act':
// 检测表单数据
if (
!this.baseForm.validate() ||
!this.httpForm.validate() ||
!this.otherForm.validate()
) {
return toastr.warning(LANG['list']['add']['warning'], LANG_T['warning']);
};
// 回调数据
if (callback) {
win.progressOn();
setTimeout(() => {
callback(this._parseFormData(
this.baseForm.getValues(),
this.httpForm.getValues(),
this.otherForm.getValues()
)).then((msg) => {
// 添加/保存完毕后回调
win.close();
toastr.success(msg, LANG_T['success']);
}).catch((msg) => {
// 添加/保存错误
win.progressOff();
toastr.error(msg, LANG_T['error']);
});
}, 100);
};
break;
default:
break;
}
});
}
......@@ -109,7 +155,10 @@ class Form {
type: 'button',
icon: 'remove',
text: LANG['list']['add']['toolbar']['clear']
}]);
},
{ type: 'separator' },
{ id: 'test', type: 'button', 'icon': 'spinner', text: LANG['list']['add']['toolbar']['test'] },
]);
return toolbar;
}
......@@ -318,6 +367,9 @@ class Form {
const opt = Object.assign({}, {
'ignore-https': 0,
'use-multipart': 0,
'use-chunk': 0,
'chunk-step-byte-min': 2,
'chunk-step-byte-max': 3,
'terminal-cache': 0,
'filemanager-cache': 1,
'upload-fragment': '500',
......@@ -334,7 +386,60 @@ class Form {
}, {
type: "checkbox", name: 'use-multipart', label: LANG['list']['otherConf']['usemultipart'],
checked: opt['use-multipart'] === 1
}, {
}, { type: 'fieldset', offsetLeft: 0, label: LANG['list']['otherConf']['chunk']['title'], list: [
{ type: 'block', offsetLeft: 0, list: [
{
type: "checkbox", name: 'use-chunk', label: LANG['list']['otherConf']['chunk']['usechunk'], checked: opt['use-chunk'] === 1
},
]},
{ type: 'block', offsetLeft: 0, list: [
{ type:'label', label: LANG['list']['otherConf']['chunk']['min']},
{ type:'newcolumn' },
{
type: 'combo', label: '/byte', validate: 'ValidNumeric', inputWidth: 50, name: "chunk-step-byte-min",
options: ((items) => {
let ret = [];
// 如果自定义的路径不在items里,则++
if (items.indexOf(opt['chunk-step-byte-min']) === -1) {
items.unshift(opt['chunk-step-byte-min']);
}
items.map((_) => {
ret.push({
text: _,
value: _,
selected: opt['chunk-step-byte-min'] === _
})
});
return ret;
})([
'2', '4', '10', '50', '100', '500'
])
},
{ type:'newcolumn',},
{ type:'label', label: LANG['list']['otherConf']['chunk']['max'], offsetLeft: 30,},
{ type:'newcolumn' },
{
type: 'combo', label: '/byte', validate: 'ValidNumeric', inputWidth: 50, name: "chunk-step-byte-max",
options: ((items) => {
let ret = [];
// 如果自定义的路径不在items里,则++
if (items.indexOf(opt['chunk-step-byte-max']) === -1) {
items.unshift(opt['chunk-step-byte-max']);
}
items.map((_) => {
ret.push({
text: _,
value: _,
selected: opt['chunk-step-byte-max'] === _
})
});
return ret;
})([
'2', '4', '10', '50', '100', '500'
])
},
]},
]}, {
type: "checkbox", name: 'terminal-cache', label: LANG['list']['otherConf']['terminalCache'],
checked: opt['terminal-cache'] === 1
}, {
......@@ -405,6 +510,28 @@ class Form {
])
}
]}], true);
form.attachEvent('onChange', (name, value, state)=>{
switch(name){
case 'use-multipart':
if(state == true && form.isItemChecked('use-chunk')) {
form.uncheckItem('use-chunk');
}
break;
case 'use-chunk':
if(state == true && form.isItemChecked('use-multipart')) {
form.uncheckItem('use-multipart');
}
if(state == true) {
layer.open({
title: LANG_T['info']
,content: LANG['list']['otherConf']['chunk']['exphint']
});
}
break;
default:
break;
}
});
return form;
}
......
......@@ -24,7 +24,7 @@ class ViewSite {
this.opts = opts;
this.cell = tabbar.cells(`tab_viewsite_${hash}`);
this.useproxy = antSword.aproxymode !== "noproxy";
// 初始化工具栏
this.toolbar = this._initToolbar();
......@@ -52,10 +52,21 @@ class ViewSite {
const toolbar = this.cell.attachToolbar();
toolbar.loadStruct([
{ id: 'url', width: 400, type: 'buttonInput', value: this.opts.url || 'loading..' },
{ type: 'separator' },
{ id: 'useproxy', type: 'buttonTwoState', icon: 'paper-plane', text: LANG['toolbar'].useproxy(this.useproxy), pressed: this.useproxy, disabled: antSword.aproxymode === "noproxy"},
{ type: 'separator' },
{ id: 'view', type: 'button', icon: 'chrome', text: LANG['toolbar'].view },
{ type: 'separator' },
{ id: 'save', type: 'button', icon: 'save', text: LANG['toolbar'].save },
]);
toolbar.attachEvent('onStateChange', (id, state) => {
switch(id) {
case 'useproxy':
this.useproxy = state;
toolbar.setItemText('useproxy', `<i class="fa fa-paper-plane"></i> ${LANG['toolbar'].useproxy(this.useproxy)}`);
break;
}
});
toolbar.attachEvent('onClick', (id) => {
switch(id) {
case 'save':
......@@ -171,9 +182,19 @@ class ViewSite {
},
title: url
});
win.loadURL(url);
win.show();
win.openDevTools();
win.on('close', () => {
win = null;
});
let ses = win.webContents.session;
let proxyuri = "";
if(this.useproxy && antSword.aproxymode != "noproxy") {
proxyuri = antSword.aproxyuri;
}
ses.setProxy({proxyRules: proxyuri}, ()=>{
win.loadURL(url);
win.show();
win.openDevTools();
});
}
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment