正在查看: St.John's v1.0.9 应用的 HTTPSession.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
正在查看: St.John's v1.0.9 应用的 HTTPSession.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
package org.nanohttpd.protocols.http;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.regex.Matcher;
import javax.net.ssl.SSLException;
import org.ccil.cowan.tagsoup.XMLWriter;
import org.nanohttpd.protocols.http.NanoHTTPD;
import org.nanohttpd.protocols.http.content.ContentType;
import org.nanohttpd.protocols.http.content.CookieHandler;
import org.nanohttpd.protocols.http.request.Method;
import org.nanohttpd.protocols.http.response.Response;
import org.nanohttpd.protocols.http.response.Status;
import org.nanohttpd.protocols.http.tempfiles.ITempFile;
import org.nanohttpd.protocols.http.tempfiles.ITempFileManager;
import org.springframework.util.MimeTypeUtils;
public class HTTPSession implements IHTTPSession {
public static final int BUFSIZE = 8192;
public static final int MAX_HEADER_SIZE = 1024;
private static final int MEMORY_STORE_LIMIT = 1024;
public static final String POST_DATA = "postData";
private static final int REQUEST_BUFFER_LEN = 512;
private CookieHandler cookies;
private Map<String, String> headers;
private final NanoHTTPD httpd;
private final BufferedInputStream inputStream;
private Method method;
private final OutputStream outputStream;
private Map<String, List<String>> parms;
private String protocolVersion;
private String queryParameterString;
private String remoteHostname;
private String remoteIp;
private int rlen;
private int splitbyte;
private final ITempFileManager tempFileManager;
private String uri;
public HTTPSession(NanoHTTPD nanoHTTPD, ITempFileManager iTempFileManager, InputStream inputStream, OutputStream outputStream) {
this.httpd = nanoHTTPD;
this.tempFileManager = iTempFileManager;
this.inputStream = new BufferedInputStream(inputStream, 8192);
this.outputStream = outputStream;
}
public HTTPSession(NanoHTTPD nanoHTTPD, ITempFileManager iTempFileManager, InputStream inputStream, OutputStream outputStream, InetAddress inetAddress) {
this.httpd = nanoHTTPD;
this.tempFileManager = iTempFileManager;
this.inputStream = new BufferedInputStream(inputStream, 8192);
this.outputStream = outputStream;
this.remoteIp = (inetAddress.isLoopbackAddress() || inetAddress.isAnyLocalAddress()) ? "127.0.0.1" : inetAddress.getHostAddress().toString();
this.remoteHostname = (inetAddress.isLoopbackAddress() || inetAddress.isAnyLocalAddress()) ? "localhost" : inetAddress.getHostName().toString();
this.headers = new HashMap();
}
private void decodeHeader(BufferedReader bufferedReader, Map<String, String> map, Map<String, List<String>> map2, Map<String, String> map3) throws NanoHTTPD.ResponseException {
String decodePercent;
try {
String readLine = bufferedReader.readLine();
if (readLine == null) {
return;
}
StringTokenizer stringTokenizer = new StringTokenizer(readLine);
if (!stringTokenizer.hasMoreTokens()) {
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
}
map.put(XMLWriter.METHOD, stringTokenizer.nextToken());
if (!stringTokenizer.hasMoreTokens()) {
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html");
}
String nextToken = stringTokenizer.nextToken();
int indexOf = nextToken.indexOf(63);
if (indexOf >= 0) {
decodeParms(nextToken.substring(indexOf + 1), map2);
decodePercent = NanoHTTPD.decodePercent(nextToken.substring(0, indexOf));
} else {
decodePercent = NanoHTTPD.decodePercent(nextToken);
}
if (stringTokenizer.hasMoreTokens()) {
this.protocolVersion = stringTokenizer.nextToken();
} else {
this.protocolVersion = "HTTP/1.1";
NanoHTTPD.LOG.log(Level.FINE, "no protocol version specified, strange. Assuming HTTP/1.1.");
}
String readLine2 = bufferedReader.readLine();
while (readLine2 != null && !readLine2.trim().isEmpty()) {
int indexOf2 = readLine2.indexOf(58);
if (indexOf2 >= 0) {
map3.put(readLine2.substring(0, indexOf2).trim().toLowerCase(Locale.US), readLine2.substring(indexOf2 + 1).trim());
}
readLine2 = bufferedReader.readLine();
}
map.put("uri", decodePercent);
} catch (IOException e) {
throw new NanoHTTPD.ResponseException(Status.INTERNAL_ERROR, "SERVER INTERNAL ERROR: IOException: " + e.getMessage(), e);
}
}
private void decodeMultipartFormData(ContentType contentType, ByteBuffer byteBuffer, Map<String, List<String>> map, Map<String, String> map2) throws NanoHTTPD.ResponseException {
String str;
try {
int[] boundaryPositions = getBoundaryPositions(byteBuffer, contentType.getBoundary().getBytes());
int i = 2;
if (boundaryPositions.length < 2) {
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but contains less than two boundary strings.");
}
int i2 = 1024;
byte[] bArr = new byte[1024];
int i3 = 0;
int i4 = 0;
int i5 = 0;
while (true) {
int i6 = 1;
if (i4 >= boundaryPositions.length - 1) {
return;
}
byteBuffer.position(boundaryPositions[i4]);
int remaining = byteBuffer.remaining() < i2 ? byteBuffer.remaining() : 1024;
byteBuffer.get(bArr, i3, remaining);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bArr, i3, remaining), Charset.forName(contentType.getEncoding())), remaining);
String readLine = bufferedReader.readLine();
if (readLine == null || !readLine.contains(contentType.getBoundary())) {
break;
}
String readLine2 = bufferedReader.readLine();
String str2 = null;
String str3 = null;
String str4 = null;
int i7 = 2;
while (readLine2 != null && readLine2.trim().length() > 0) {
Matcher matcher = NanoHTTPD.CONTENT_DISPOSITION_PATTERN.matcher(readLine2);
if (matcher.matches()) {
Matcher matcher2 = NanoHTTPD.CONTENT_DISPOSITION_ATTRIBUTE_PATTERN.matcher(matcher.group(i));
while (matcher2.find()) {
String group = matcher2.group(i6);
if ("name".equalsIgnoreCase(group)) {
str = matcher2.group(2);
} else {
if ("filename".equalsIgnoreCase(group)) {
String group2 = matcher2.group(2);
if (!group2.isEmpty()) {
if (i5 > 0) {
str = str2 + String.valueOf(i5);
str3 = group2;
i5++;
} else {
i5++;
}
}
str3 = group2;
}
i6 = 1;
}
str2 = str;
i6 = 1;
}
}
Matcher matcher3 = NanoHTTPD.CONTENT_TYPE_PATTERN.matcher(readLine2);
if (matcher3.matches()) {
str4 = matcher3.group(2).trim();
}
readLine2 = bufferedReader.readLine();
i7++;
i = 2;
i6 = 1;
}
int i8 = 0;
while (true) {
int i9 = i7 - 1;
if (i7 <= 0) {
break;
}
i8 = scipOverNewLine(bArr, i8);
i7 = i9;
}
if (i8 >= remaining - 4) {
throw new NanoHTTPD.ResponseException(Status.INTERNAL_ERROR, "Multipart header size exceeds MAX_HEADER_SIZE.");
}
int i10 = boundaryPositions[i4] + i8;
i4++;
int i11 = boundaryPositions[i4] - 4;
byteBuffer.position(i10);
List<String> list = map.get(str2);
if (list == null) {
list = new ArrayList<>();
map.put(str2, list);
}
if (str4 == null) {
byte[] bArr2 = new byte[i11 - i10];
byteBuffer.get(bArr2);
list.add(new String(bArr2, contentType.getEncoding()));
} else {
String saveTmpFile = saveTmpFile(byteBuffer, i10, i11 - i10, str3);
if (!map2.containsKey(str2)) {
map2.put(str2, saveTmpFile);
} else {
int i12 = 2;
while (true) {
if (!map2.containsKey(str2 + i12)) {
break;
} else {
i12++;
}
}
map2.put(str2 + i12, saveTmpFile);
}
list.add(str3);
}
i2 = 1024;
i = 2;
i3 = 0;
}
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but chunk does not start with boundary.");
} catch (NanoHTTPD.ResponseException e) {
throw e;
} catch (Exception e2) {
throw new NanoHTTPD.ResponseException(Status.INTERNAL_ERROR, e2.toString());
}
}
private int scipOverNewLine(byte[] bArr, int i) {
while (bArr[i] != 10) {
i++;
}
return i + 1;
}
private void decodeParms(String str, Map<String, List<String>> map) {
String trim;
String str2;
if (str == null) {
this.queryParameterString = "";
return;
}
this.queryParameterString = str;
StringTokenizer stringTokenizer = new StringTokenizer(str, "&");
while (stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken();
int indexOf = nextToken.indexOf(61);
if (indexOf >= 0) {
trim = NanoHTTPD.decodePercent(nextToken.substring(0, indexOf)).trim();
str2 = NanoHTTPD.decodePercent(nextToken.substring(indexOf + 1));
} else {
trim = NanoHTTPD.decodePercent(nextToken).trim();
str2 = "";
}
List<String> list = map.get(trim);
if (list == null) {
list = new ArrayList<>();
map.put(trim, list);
}
list.add(str2);
}
}
@Override
public void execute() throws IOException {
byte[] bArr;
Response response = null;
try {
try {
try {
try {
bArr = new byte[8192];
this.splitbyte = 0;
this.rlen = 0;
this.inputStream.mark(8192);
} catch (NanoHTTPD.ResponseException e) {
Response.newFixedLengthResponse(e.getStatus(), "text/plain", e.getMessage()).send(this.outputStream);
NanoHTTPD.safeClose(this.outputStream);
}
} catch (SSLException e2) {
Response.newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "SSL PROTOCOL FAILURE: " + e2.getMessage()).send(this.outputStream);
NanoHTTPD.safeClose(this.outputStream);
} catch (IOException e3) {
Response.newFixedLengthResponse(Status.INTERNAL_ERROR, "text/plain", "SERVER INTERNAL ERROR: IOException: " + e3.getMessage()).send(this.outputStream);
NanoHTTPD.safeClose(this.outputStream);
}
try {
int read = this.inputStream.read(bArr, 0, 8192);
if (read == -1) {
NanoHTTPD.safeClose(this.inputStream);
NanoHTTPD.safeClose(this.outputStream);
throw new SocketException("NanoHttpd Shutdown");
}
while (read > 0) {
int i = this.rlen + read;
this.rlen = i;
int findHeaderEnd = findHeaderEnd(bArr, i);
this.splitbyte = findHeaderEnd;
if (findHeaderEnd > 0) {
break;
}
BufferedInputStream bufferedInputStream = this.inputStream;
int i2 = this.rlen;
read = bufferedInputStream.read(bArr, i2, 8192 - i2);
}
if (this.splitbyte < this.rlen) {
this.inputStream.reset();
this.inputStream.skip(this.splitbyte);
}
this.parms = new HashMap();
Map<String, String> map = this.headers;
if (map == null) {
this.headers = new HashMap();
} else {
map.clear();
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bArr, 0, this.rlen)));
HashMap hashMap = new HashMap();
decodeHeader(bufferedReader, hashMap, this.parms, this.headers);
String str = this.remoteIp;
if (str != null) {
this.headers.put("remote-addr", str);
this.headers.put("http-client-ip", this.remoteIp);
}
Method lookup = Method.lookup(hashMap.get(XMLWriter.METHOD));
this.method = lookup;
if (lookup == null) {
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Syntax error. HTTP verb " + hashMap.get(XMLWriter.METHOD) + " unhandled.");
}
this.uri = hashMap.get("uri");
this.cookies = new CookieHandler(this.headers);
String str2 = this.headers.get("connection");
boolean z = "HTTP/1.1".equals(this.protocolVersion) && (str2 == null || !str2.matches("(?i).*close.*"));
response = this.httpd.handle(this);
if (response == null) {
throw new NanoHTTPD.ResponseException(Status.INTERNAL_ERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");
}
String str3 = this.headers.get("accept-encoding");
this.cookies.unloadQueue(response);
response.setRequestMethod(this.method);
if (str3 == null || !str3.contains("gzip")) {
response.setUseGzip(false);
}
response.setKeepAlive(z);
response.send(this.outputStream);
if (!z || response.isCloseConnection()) {
throw new SocketException("NanoHttpd Shutdown");
}
} catch (SSLException e4) {
throw e4;
} catch (IOException unused) {
NanoHTTPD.safeClose(this.inputStream);
NanoHTTPD.safeClose(this.outputStream);
throw new SocketException("NanoHttpd Shutdown");
}
} catch (SocketException e5) {
throw e5;
} catch (SocketTimeoutException e6) {
throw e6;
}
} finally {
NanoHTTPD.safeClose(null);
this.tempFileManager.clear();
}
}
private int findHeaderEnd(byte[] bArr, int i) {
int i2;
int i3 = 0;
while (true) {
int i4 = i3 + 1;
if (i4 >= i) {
return 0;
}
byte b = bArr[i3];
if (b == 13 && bArr[i4] == 10 && (i2 = i3 + 3) < i && bArr[i3 + 2] == 13 && bArr[i2] == 10) {
return i3 + 4;
}
if (b == 10 && bArr[i4] == 10) {
return i3 + 2;
}
i3 = i4;
}
}
private int[] getBoundaryPositions(ByteBuffer byteBuffer, byte[] bArr) {
int[] iArr = new int[0];
if (byteBuffer.remaining() < bArr.length) {
return iArr;
}
int length = bArr.length + 4096;
byte[] bArr2 = new byte[length];
int remaining = byteBuffer.remaining() < length ? byteBuffer.remaining() : length;
byteBuffer.get(bArr2, 0, remaining);
int length2 = remaining - bArr.length;
int i = 0;
do {
for (int i2 = 0; i2 < length2; i2++) {
for (int i3 = 0; i3 < bArr.length && bArr2[i2 + i3] == bArr[i3]; i3++) {
if (i3 == bArr.length - 1) {
int[] iArr2 = new int[iArr.length + 1];
System.arraycopy(iArr, 0, iArr2, 0, iArr.length);
iArr2[iArr.length] = i + i2;
iArr = iArr2;
}
}
}
i += length2;
System.arraycopy(bArr2, length - bArr.length, bArr2, 0, bArr.length);
length2 = length - bArr.length;
if (byteBuffer.remaining() < length2) {
length2 = byteBuffer.remaining();
}
byteBuffer.get(bArr2, bArr.length, length2);
} while (length2 > 0);
return iArr;
}
@Override
public CookieHandler getCookies() {
return this.cookies;
}
@Override
public final Map<String, String> getHeaders() {
return this.headers;
}
@Override
public final InputStream getInputStream() {
return this.inputStream;
}
@Override
public final Method getMethod() {
return this.method;
}
@Override
@Deprecated
public final Map<String, String> getParms() {
HashMap hashMap = new HashMap();
for (String str : this.parms.keySet()) {
hashMap.put(str, this.parms.get(str).get(0));
}
return hashMap;
}
@Override
public final Map<String, List<String>> getParameters() {
return this.parms;
}
@Override
public String getQueryParameterString() {
return this.queryParameterString;
}
private RandomAccessFile getTmpBucket() {
try {
return new RandomAccessFile(this.tempFileManager.createTempFile(null).getName(), "rw");
} catch (Exception e) {
throw new Error(e);
}
}
@Override
public final String getUri() {
return this.uri;
}
public long getBodySize() {
if (this.headers.containsKey("content-length")) {
return Long.parseLong(this.headers.get("content-length"));
}
if (this.splitbyte < this.rlen) {
return r1 - r0;
}
return 0L;
}
@Override
public void parseBody(Map<String, String> map) throws IOException, NanoHTTPD.ResponseException {
long bodySize;
RandomAccessFile tmpBucket;
ByteArrayOutputStream byteArrayOutputStream;
DataOutput dataOutput;
ByteBuffer map2;
RandomAccessFile randomAccessFile = null;
try {
bodySize = getBodySize();
if (bodySize < 1024) {
byteArrayOutputStream = new ByteArrayOutputStream();
dataOutput = new DataOutputStream(byteArrayOutputStream);
tmpBucket = null;
} else {
tmpBucket = getTmpBucket();
byteArrayOutputStream = null;
dataOutput = tmpBucket;
}
} catch (Throwable th) {
th = th;
}
try {
byte[] bArr = new byte[512];
while (this.rlen >= 0 && bodySize > 0) {
int read = this.inputStream.read(bArr, 0, (int) Math.min(bodySize, 512L));
this.rlen = read;
bodySize -= read;
if (read > 0) {
dataOutput.write(bArr, 0, read);
}
}
if (byteArrayOutputStream != null) {
map2 = ByteBuffer.wrap(byteArrayOutputStream.toByteArray(), 0, byteArrayOutputStream.size());
} else {
map2 = tmpBucket.getChannel().map(FileChannel.MapMode.READ_ONLY, 0L, tmpBucket.length());
tmpBucket.seek(0L);
}
if (Method.POST.equals(this.method)) {
ContentType contentType = new ContentType(this.headers.get("content-type"));
if (contentType.isMultipart()) {
if (contentType.getBoundary() == null) {
throw new NanoHTTPD.ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
}
decodeMultipartFormData(contentType, map2, this.parms, map);
} else {
byte[] bArr2 = new byte[map2.remaining()];
map2.get(bArr2);
String trim = new String(bArr2, contentType.getEncoding()).trim();
if (MimeTypeUtils.APPLICATION_FORM_URLENCODED_VALUE.equalsIgnoreCase(contentType.getContentType())) {
decodeParms(trim, this.parms);
} else if (trim.length() != 0) {
map.put(POST_DATA, trim);
}
}
} else if (Method.PUT.equals(this.method)) {
map.put("content", saveTmpFile(map2, 0, map2.limit(), null));
}
NanoHTTPD.safeClose(tmpBucket);
} catch (Throwable th2) {
th = th2;
randomAccessFile = tmpBucket;
NanoHTTPD.safeClose(randomAccessFile);
throw th;
}
}
private String saveTmpFile(ByteBuffer byteBuffer, int i, int i2, String str) {
ITempFile createTempFile;
ByteBuffer duplicate;
FileOutputStream fileOutputStream;
if (i2 <= 0) {
return "";
}
FileOutputStream fileOutputStream2 = null;
try {
try {
createTempFile = this.tempFileManager.createTempFile(str);
duplicate = byteBuffer.duplicate();
fileOutputStream = new FileOutputStream(createTempFile.getName());
} catch (Exception e) {
e = e;
}
} catch (Throwable th) {
th = th;
}
try {
FileChannel channel = fileOutputStream.getChannel();
duplicate.position(i).limit(i + i2);
channel.write(duplicate.slice());
String name = createTempFile.getName();
NanoHTTPD.safeClose(fileOutputStream);
return name;
} catch (Exception e2) {
e = e2;
fileOutputStream2 = fileOutputStream;
throw new Error(e);
} catch (Throwable th2) {
th = th2;
fileOutputStream2 = fileOutputStream;
NanoHTTPD.safeClose(fileOutputStream2);
throw th;
}
}
@Override
public String getRemoteIpAddress() {
return this.remoteIp;
}
@Override
public String getRemoteHostName() {
return this.remoteHostname;
}
}