Confectionery Chaos Quest v2.0.0版本的 MD5 值为:0a215dcdba438eef8c81d54c9027e977
以下内容为反编译后的 NanoHTTPD.java 源代码,内容仅作参考
package com.mostafa_panda_cake;
import android.util.Log;
import androidx.browser.trusted.sharing.ShareTarget;
import com.google.android.gms.measurement.api.AppMeasurementSdk;
import com.google.common.net.HttpHeaders;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.Vector;
import okhttp3.internal.ws.RealWebSocket;
public class NanoHTTPD {
public static final String HTTP_BADREQUEST = "400 Bad Request";
public static final String HTTP_FORBIDDEN = "403 Forbidden";
public static final String HTTP_INTERNALERROR = "500 Internal Server Error";
public static final String HTTP_NOTFOUND = "404 Not Found";
public static final String HTTP_NOTIMPLEMENTED = "501 Not Implemented";
public static final String HTTP_NOTMODIFIED = "304 Not Modified";
public static final String HTTP_OK = "200 OK";
public static final String HTTP_PARTIALCONTENT = "206 Partial Content";
public static final String HTTP_RANGE_NOT_SATISFIABLE = "416 Requested Range Not Satisfiable";
public static final String HTTP_REDIRECT = "301 Moved Permanently";
private static final String LICENCE = "Copyright (C) 2001,2005-2011 by Jarno Elonen <elonen@iki.fi>\nand Copyright (C) 2010 by Konstantinos Togias <info@ktogias.gr>\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer. Redistributions in\nbinary form must reproduce the above copyright notice, this list of\nconditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution. The name of the author may not\nbe used to endorse or promote products derived from this software without\nspecific prior written permission. \n \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
public static final String MIME_DEFAULT_BINARY = "application/octet-stream";
public static final String MIME_HTML = "text/html";
public static final String MIME_PLAINTEXT = "text/plain";
public static final String MIME_XML = "text/xml";
private static SimpleDateFormat gmtFrmt;
private static int theBufferSize;
private static Hashtable theMimeTypes = new Hashtable();
private final String LOGTAG = "NanoHTTPD";
private AndroidFile myRootDir;
private final ServerSocket myServerSocket;
private int myTcpPort;
private Thread myThread;
public Response serve(String str, String str2, Properties properties, Properties properties2, Properties properties3) {
Log.i("NanoHTTPD", str2 + " '" + str + "' ");
properties.setProperty(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
properties.setProperty(HttpHeaders.PRAGMA, "no-cache");
properties.setProperty(HttpHeaders.EXPIRES, "0");
return serveFile(str, properties, this.myRootDir, true);
}
public class Response {
public InputStream data;
public Properties header;
public String mimeType;
public String status;
public Response() {
this.header = new Properties();
this.status = NanoHTTPD.HTTP_OK;
}
public Response(String str, String str2, InputStream inputStream) {
this.header = new Properties();
this.status = str;
this.mimeType = str2;
this.data = inputStream;
}
public Response(String str, String str2, String str3) {
this.header = new Properties();
this.status = str;
this.mimeType = str2;
try {
this.data = new ByteArrayInputStream(str3.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void addHeader(String str, String str2) {
this.header.put(str, str2);
}
}
public NanoHTTPD(InetSocketAddress inetSocketAddress, AndroidFile androidFile) throws IOException {
this.myTcpPort = inetSocketAddress.getPort();
this.myRootDir = androidFile;
ServerSocket serverSocket = new ServerSocket();
this.myServerSocket = serverSocket;
serverSocket.bind(inetSocketAddress);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
NanoHTTPD nanoHTTPD = NanoHTTPD.this;
new HTTPSession(nanoHTTPD.myServerSocket.accept());
} catch (IOException unused) {
return;
}
}
}
});
this.myThread = thread;
thread.setDaemon(true);
this.myThread.start();
}
public NanoHTTPD(int i, AndroidFile androidFile) throws IOException {
this.myTcpPort = i;
this.myRootDir = androidFile;
this.myServerSocket = new ServerSocket(this.myTcpPort);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
NanoHTTPD nanoHTTPD = NanoHTTPD.this;
new HTTPSession(nanoHTTPD.myServerSocket.accept());
} catch (IOException unused) {
return;
}
}
}
});
this.myThread = thread;
thread.setDaemon(true);
this.myThread.start();
}
public void stop() {
try {
this.myServerSocket.close();
this.myThread.join();
} catch (IOException | InterruptedException unused) {
}
}
public static void main(String[] strArr) {
PrintStream printStream = System.out;
PrintStream printStream2 = System.err;
printStream.println("NanoHTTPD 1.25 (C) 2001,2005-2011 Jarno Elonen and (C) 2010 Konstantinos Togias\n(Command line options: [-p port] [-d root-dir] [--licence])\n");
File absoluteFile = new File(".").getAbsoluteFile();
int i = 80;
for (int i2 = 0; i2 < strArr.length; i2++) {
if (strArr[i2].equalsIgnoreCase("-p")) {
i = Integer.parseInt(strArr[i2 + 1]);
} else if (strArr[i2].equalsIgnoreCase("-d")) {
absoluteFile = new File(strArr[i2 + 1]).getAbsoluteFile();
} else if (strArr[i2].toLowerCase().endsWith("licence")) {
printStream.println("Copyright (C) 2001,2005-2011 by Jarno Elonen <elonen@iki.fi>\nand Copyright (C) 2010 by Konstantinos Togias <info@ktogias.gr>\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer. Redistributions in\nbinary form must reproduce the above copyright notice, this list of\nconditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution. The name of the author may not\nbe used to endorse or promote products derived from this software without\nspecific prior written permission. \n \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n");
break;
}
}
try {
new NanoHTTPD(i, new AndroidFile(absoluteFile.getPath()));
} catch (IOException e) {
printStream2.println("Couldn't start server:\n" + e);
System.exit(-1);
}
printStream.println("Now serving files in port " + i + " from \"" + absoluteFile + "\"");
printStream.println("Hit Enter to stop.\n");
try {
System.in.read();
} catch (Throwable unused) {
}
}
private class HTTPSession implements Runnable {
private Socket mySocket;
public HTTPSession(Socket socket) {
this.mySocket = socket;
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.start();
}
@Override
public void run() {
long parseInt;
int i;
byte[] bArr;
ByteArrayOutputStream byteArrayOutputStream;
Response serve;
int read;
try {
InputStream inputStream = this.mySocket.getInputStream();
if (inputStream == null) {
return;
}
byte[] bArr2 = new byte[8192];
int read2 = inputStream.read(bArr2, 0, 8192);
int i2 = 0;
int i3 = 0;
while (read2 > 0) {
i2 += read2;
i3 = findHeaderEnd(bArr2, i2);
if (i3 > 0) {
break;
} else {
read2 = inputStream.read(bArr2, i2, 8192 - i2);
}
}
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bArr2, 0, i2)));
Properties properties = new Properties();
Properties properties2 = new Properties();
Properties properties3 = new Properties();
Properties properties4 = new Properties();
decodeHeader(bufferedReader, properties, properties2, properties3);
String property = properties.getProperty("method");
String property2 = properties.getProperty("uri");
String property3 = properties3.getProperty("content-length");
if (property3 != null) {
try {
parseInt = Integer.parseInt(property3);
} catch (NumberFormatException unused) {
}
ByteArrayOutputStream byteArrayOutputStream2 = new ByteArrayOutputStream();
if (i3 < i2) {
byteArrayOutputStream2.write(bArr2, i3, i2 - i3);
}
if (i3 >= i2) {
parseInt -= (i2 - i3) + 1;
} else if (i3 == 0 || parseInt == Long.MAX_VALUE) {
parseInt = 0;
}
i = 512;
bArr = new byte[512];
while (i2 >= 0 && parseInt > 0) {
read = inputStream.read(bArr, 0, i);
parseInt -= read;
if (read <= 0) {
byteArrayOutputStream2.write(bArr, 0, read);
}
i2 = read;
i = 512;
}
byte[] byteArray = byteArrayOutputStream2.toByteArray();
BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray)));
if (property.equalsIgnoreCase(ShareTarget.METHOD_POST)) {
byteArrayOutputStream = byteArrayOutputStream2;
} else {
StringTokenizer stringTokenizer = new StringTokenizer(properties3.getProperty("content-type"), "; ");
String str = "";
if ((stringTokenizer.hasMoreTokens() ? stringTokenizer.nextToken() : "").equalsIgnoreCase(ShareTarget.ENCODING_TYPE_MULTIPART)) {
if (!stringTokenizer.hasMoreTokens()) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary missing. Usage: GET /example/file.html");
}
StringTokenizer stringTokenizer2 = new StringTokenizer(stringTokenizer.nextToken(), "=");
if (stringTokenizer2.countTokens() != 2) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but boundary syntax error. Usage: GET /example/file.html");
}
stringTokenizer2.nextToken();
byteArrayOutputStream = byteArrayOutputStream2;
decodeMultipartData(stringTokenizer2.nextToken(), byteArray, bufferedReader2, properties2, properties4);
} else {
byteArrayOutputStream = byteArrayOutputStream2;
char[] cArr = new char[512];
for (int read3 = bufferedReader2.read(cArr); read3 >= 0 && !str.endsWith("\r\n"); read3 = bufferedReader2.read(cArr)) {
str = str + String.valueOf(cArr, 0, read3);
}
decodeParms(str.trim(), properties2);
}
}
if (property.equalsIgnoreCase("PUT")) {
properties4.put("content", saveTmpFile(byteArray, 0, byteArrayOutputStream.size()));
}
serve = NanoHTTPD.this.serve(property2, property, properties3, properties2, properties4);
if (serve != null) {
sendError(NanoHTTPD.HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");
} else {
sendResponse(serve.status, serve.mimeType, serve.header, serve.data);
}
bufferedReader2.close();
inputStream.close();
}
parseInt = Long.MAX_VALUE;
ByteArrayOutputStream byteArrayOutputStream22 = new ByteArrayOutputStream();
if (i3 < i2) {
}
if (i3 >= i2) {
}
i = 512;
bArr = new byte[512];
while (i2 >= 0) {
read = inputStream.read(bArr, 0, i);
parseInt -= read;
if (read <= 0) {
}
i2 = read;
i = 512;
}
byte[] byteArray2 = byteArrayOutputStream22.toByteArray();
BufferedReader bufferedReader22 = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(byteArray2)));
if (property.equalsIgnoreCase(ShareTarget.METHOD_POST)) {
}
if (property.equalsIgnoreCase("PUT")) {
}
serve = NanoHTTPD.this.serve(property2, property, properties3, properties2, properties4);
if (serve != null) {
}
bufferedReader22.close();
inputStream.close();
} catch (IOException e) {
sendError(NanoHTTPD.HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + e.getMessage());
} catch (Throwable unused2) {
}
}
private void decodeHeader(BufferedReader bufferedReader, Properties properties, Properties properties2, Properties properties3) throws InterruptedException {
String decodePercent;
try {
String readLine = bufferedReader.readLine();
if (readLine == null) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
}
StringTokenizer stringTokenizer = new StringTokenizer(readLine);
if (!stringTokenizer.hasMoreTokens()) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html");
}
properties.put("method", stringTokenizer.nextToken());
if (!stringTokenizer.hasMoreTokens()) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "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), properties2);
decodePercent = decodePercent(nextToken.substring(0, indexOf));
} else {
decodePercent = decodePercent(nextToken);
}
if (stringTokenizer.hasMoreTokens()) {
String readLine2 = bufferedReader.readLine();
while (readLine2 != null && readLine2.trim().length() > 0) {
int indexOf2 = readLine2.indexOf(58);
if (indexOf2 >= 0) {
properties3.put(readLine2.substring(0, indexOf2).trim().toLowerCase(), readLine2.substring(indexOf2 + 1).trim());
}
readLine2 = bufferedReader.readLine();
}
}
properties.put("uri", decodePercent);
} catch (IOException e) {
sendError(NanoHTTPD.HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + e.getMessage());
}
}
private void decodeMultipartData(String str, byte[] bArr, BufferedReader bufferedReader, Properties properties, Properties properties2) throws InterruptedException {
String readLine;
Properties properties3;
String str2;
try {
int[] boundaryPositions = getBoundaryPositions(bArr, str.getBytes());
int i = 1;
for (String readLine2 = bufferedReader.readLine(); readLine2 != null; readLine2 = readLine) {
if (readLine2.indexOf(str) == -1) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but next chunk does not start with boundary. Usage: GET /example/file.html");
}
i++;
Properties properties4 = new Properties();
readLine = bufferedReader.readLine();
while (readLine != null && readLine.trim().length() > 0) {
int indexOf = readLine.indexOf(58);
if (indexOf != -1) {
properties4.put(readLine.substring(0, indexOf).trim().toLowerCase(), readLine.substring(indexOf + 1).trim());
}
readLine = bufferedReader.readLine();
}
if (readLine != null) {
String property = properties4.getProperty("content-disposition");
if (property == null) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Content type is multipart/form-data but no content-disposition info found. Usage: GET /example/file.html");
}
StringTokenizer stringTokenizer = new StringTokenizer(property, "; ");
Properties properties5 = new Properties();
while (stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken();
int indexOf2 = nextToken.indexOf(61);
if (indexOf2 != -1) {
properties5.put(nextToken.substring(0, indexOf2).trim().toLowerCase(), nextToken.substring(indexOf2 + 1).trim());
}
}
String property2 = properties5.getProperty(AppMeasurementSdk.ConditionalUserProperty.NAME);
String substring = property2.substring(1, property2.length() - 1);
String str3 = "";
if (properties4.getProperty("content-type") == null) {
while (readLine != null && readLine.indexOf(str) == -1) {
readLine = bufferedReader.readLine();
if (readLine != null) {
int indexOf3 = readLine.indexOf(str);
if (indexOf3 == -1) {
str2 = str3 + readLine;
} else {
str2 = str3 + readLine.substring(0, indexOf3 - 2);
}
str3 = str2;
}
}
properties3 = properties;
} else {
if (i > boundaryPositions.length) {
sendError(NanoHTTPD.HTTP_INTERNALERROR, "Error processing request");
}
properties2.put(substring, saveTmpFile(bArr, stripMultipartHeaders(bArr, boundaryPositions[i - 2]), (boundaryPositions[i - 1] - r5) - 4));
String property3 = properties5.getProperty("filename");
str3 = property3.substring(1, property3.length() - 1);
do {
readLine = bufferedReader.readLine();
if (readLine == null) {
break;
}
} while (readLine.indexOf(str) == -1);
properties3 = properties;
}
properties3.put(substring, str3);
}
}
} catch (IOException e) {
sendError(NanoHTTPD.HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + e.getMessage());
}
}
private int findHeaderEnd(byte[] bArr, int i) {
int i2 = 0;
while (true) {
int i3 = i2 + 3;
if (i3 >= i) {
return 0;
}
if (bArr[i2] == 13 && bArr[i2 + 1] == 10 && bArr[i2 + 2] == 13 && bArr[i3] == 10) {
return i2 + 4;
}
i2++;
}
}
public int[] getBoundaryPositions(byte[] bArr, byte[] bArr2) {
Vector vector = new Vector();
int i = 0;
int i2 = 0;
int i3 = -1;
while (i < bArr.length) {
if (bArr[i] == bArr2[i2]) {
if (i2 == 0) {
i3 = i;
}
i2++;
if (i2 == bArr2.length) {
vector.addElement(Integer.valueOf(i3));
} else {
i++;
}
} else {
i -= i2;
}
i2 = 0;
i3 = -1;
i++;
}
int size = vector.size();
int[] iArr = new int[size];
for (int i4 = 0; i4 < size; i4++) {
iArr[i4] = ((Integer) vector.elementAt(i4)).intValue();
}
return iArr;
}
private String saveTmpFile(byte[] bArr, int i, int i2) {
if (i2 <= 0) {
return "";
}
try {
File createTempFile = File.createTempFile("NanoHTTPD", "", new File(System.getProperty("java.io.tmpdir")));
FileOutputStream fileOutputStream = new FileOutputStream(createTempFile);
fileOutputStream.write(bArr, i, i2);
fileOutputStream.close();
return createTempFile.getAbsolutePath();
} catch (Exception e) {
Log.e("NanoHTTPD", "Error: " + e.getMessage());
return "";
}
}
private int stripMultipartHeaders(byte[] bArr, int i) {
while (i < bArr.length) {
if (bArr[i] == 13) {
i++;
if (bArr[i] == 10) {
i++;
if (bArr[i] == 13) {
i++;
if (bArr[i] == 10) {
break;
}
} else {
continue;
}
} else {
continue;
}
}
i++;
}
return i + 1;
}
private String decodePercent(String str) throws InterruptedException {
try {
StringBuffer stringBuffer = new StringBuffer();
int i = 0;
while (i < str.length()) {
char charAt = str.charAt(i);
if (charAt == '%') {
stringBuffer.append((char) Integer.parseInt(str.substring(i + 1, i + 3), 16));
i += 2;
} else if (charAt == '+') {
stringBuffer.append(' ');
} else {
stringBuffer.append(charAt);
}
i++;
}
return stringBuffer.toString();
} catch (Exception unused) {
sendError(NanoHTTPD.HTTP_BADREQUEST, "BAD REQUEST: Bad percent-encoding.");
return null;
}
}
private void decodeParms(String str, Properties properties) throws InterruptedException {
if (str == null) {
return;
}
StringTokenizer stringTokenizer = new StringTokenizer(str, "&");
while (stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken();
int indexOf = nextToken.indexOf(61);
if (indexOf >= 0) {
properties.put(decodePercent(nextToken.substring(0, indexOf)).trim(), decodePercent(nextToken.substring(indexOf + 1)));
}
}
}
private void sendError(String str, String str2) throws InterruptedException {
sendResponse(str, NanoHTTPD.MIME_PLAINTEXT, null, new ByteArrayInputStream(str2.getBytes()));
throw new InterruptedException();
}
private void sendResponse(String str, String str2, Properties properties, InputStream inputStream) {
try {
try {
if (str == null) {
throw new Error("sendResponse(): Status can't be null.");
}
OutputStream outputStream = this.mySocket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.print("HTTP/1.0 " + str + " \r\n");
if (str2 != null) {
printWriter.print("Content-Type: " + str2 + "\r\n");
}
if (properties == null || properties.getProperty(HttpHeaders.DATE) == null) {
printWriter.print("Date: " + NanoHTTPD.gmtFrmt.format(new Date()) + "\r\n");
}
if (properties != null) {
Enumeration keys = properties.keys();
while (keys.hasMoreElements()) {
String str3 = (String) keys.nextElement();
printWriter.print(str3 + ": " + properties.getProperty(str3) + "\r\n");
}
}
printWriter.print("\r\n");
printWriter.flush();
if (inputStream != null) {
int available = inputStream.available();
byte[] bArr = new byte[NanoHTTPD.theBufferSize];
while (available > 0) {
int read = inputStream.read(bArr, 0, available > NanoHTTPD.theBufferSize ? NanoHTTPD.theBufferSize : available);
if (read <= 0) {
break;
}
outputStream.write(bArr, 0, read);
available -= read;
}
}
outputStream.flush();
outputStream.close();
if (inputStream != null) {
inputStream.close();
}
} catch (Throwable unused) {
}
} catch (IOException unused2) {
this.mySocket.close();
}
}
}
private String encodeUri(String str) {
StringTokenizer stringTokenizer = new StringTokenizer(str, "/ ", true);
String str2 = "";
while (stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken();
if (nextToken.equals("/")) {
str2 = str2 + "/";
} else if (nextToken.equals(" ")) {
str2 = str2 + "%20";
} else {
str2 = str2 + URLEncoder.encode(nextToken);
}
}
return str2;
}
public Response serveFile(String str, Properties properties, AndroidFile androidFile, boolean z) {
String str2;
AndroidFile androidFile2;
String str3;
String str4;
Response response;
String str5;
String hexString;
String property;
long j;
Response response2;
long j2;
int indexOf;
String[] strArr;
String str6;
String str7;
String str8;
String substring;
int lastIndexOf;
boolean isDirectory = androidFile.isDirectory();
String str9 = MIME_PLAINTEXT;
Response response3 = !isDirectory ? new Response(HTTP_INTERNALERROR, MIME_PLAINTEXT, "INTERNAL ERRROR: serveFile(): given homeDir is not a directory.") : null;
if (response3 == null) {
str2 = str.trim().replace(File.separatorChar, '/');
if (str2.indexOf(63) >= 0) {
str2 = str2.substring(0, str2.indexOf(63));
}
if (str2.startsWith("..") || str2.endsWith("..") || str2.indexOf("../") >= 0) {
response3 = new Response(HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Won't serve ../ for security reasons.");
}
} else {
str2 = str;
}
AndroidFile androidFile3 = new AndroidFile(androidFile, str2);
if (response3 == null && !androidFile3.exists()) {
response3 = new Response(HTTP_NOTFOUND, MIME_PLAINTEXT, "Error 404, file not found.");
}
if (response3 == null && androidFile3.isDirectory()) {
String str10 = "\">";
if (!str2.endsWith("/")) {
str2 = str2 + "/";
response3 = new Response(HTTP_REDIRECT, MIME_HTML, "<html><body>Redirected: <a href=\"" + str2 + "\">" + str2 + "</a></body></html>");
response3.addHeader(HttpHeaders.LOCATION, str2);
}
if (response3 == null) {
if (new AndroidFile(androidFile3, "index.html").exists()) {
androidFile3 = new AndroidFile(androidFile, str2 + "/index.html");
} else if (new AndroidFile(androidFile3, "index.htm").exists()) {
androidFile3 = new AndroidFile(androidFile, str2 + "/index.htm");
} else if (z && androidFile3.canRead()) {
String[] list = androidFile3.list();
String str11 = "<html><body><h1>Directory " + str2 + "</h1><br/>";
if (str2.length() > 1 && (lastIndexOf = (substring = str2.substring(0, str2.length() - 1)).lastIndexOf(47)) >= 0 && lastIndexOf < substring.length()) {
str11 = str11 + "<b><a href=\"" + str2.substring(0, lastIndexOf + 1) + "\">..</a></b><br/>";
}
if (list != null) {
int i = 0;
while (i < list.length) {
AndroidFile androidFile4 = new AndroidFile(androidFile3, list[i]);
boolean isDirectory2 = androidFile4.isDirectory();
AndroidFile androidFile5 = androidFile3;
if (isDirectory2) {
list[i] = list[i] + "/";
str11 = str11 + "<b>";
}
String str12 = str2;
String str13 = str11 + "<a href=\"" + encodeUri(str2 + list[i]) + str10 + list[i] + "</a>";
if (androidFile4.isFile()) {
long length = androidFile4.length();
String str14 = str13 + " <font size=2>(";
if (length < RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE) {
str8 = str14 + length + " bytes";
strArr = list;
str6 = str9;
str7 = str10;
} else {
strArr = list;
if (length < 1048576) {
str6 = str9;
str7 = str10;
str8 = str14 + (length / RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE) + "." + (((length % RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE) / 10) % 100) + " KB";
} else {
str6 = str9;
str7 = str10;
str8 = str14 + (length / 1048576) + "." + (((length % 1048576) / 10) % 100) + " MB";
}
}
str13 = str8 + ")</font>";
} else {
strArr = list;
str6 = str9;
str7 = str10;
}
String str15 = str13 + "<br/>";
if (isDirectory2) {
str15 = str15 + "</b>";
}
str11 = str15;
i++;
list = strArr;
str9 = str6;
androidFile3 = androidFile5;
str2 = str12;
str10 = str7;
}
}
androidFile2 = androidFile3;
response3 = new Response(HTTP_OK, MIME_HTML, str11 + "</body></html>");
str9 = str9;
} else {
androidFile2 = androidFile3;
str9 = MIME_PLAINTEXT;
response3 = new Response(HTTP_FORBIDDEN, str9, "FORBIDDEN: No directory listing.");
}
}
if (response3 == null) {
try {
int lastIndexOf2 = androidFile3.getCanonicalPath().lastIndexOf(46);
str5 = lastIndexOf2 >= 0 ? (String) theMimeTypes.get(androidFile3.getCanonicalPath().substring(lastIndexOf2 + 1).toLowerCase()) : null;
if (str5 == null) {
str5 = MIME_DEFAULT_BINARY;
}
hexString = Integer.toHexString((androidFile3.getAbsolutePath() + androidFile3.lastModified() + "" + androidFile3.length()).hashCode());
property = properties.getProperty("range");
} catch (IOException unused) {
str3 = str9;
str4 = HTTP_FORBIDDEN;
}
if (property != null && property.startsWith("bytes=") && (indexOf = (property = property.substring(6)).indexOf(45)) > 0) {
try {
j = Long.parseLong(property.substring(0, indexOf));
try {
str3 = Long.parseLong(property.substring(indexOf + 1));
} catch (NumberFormatException unused2) {
}
} catch (NumberFormatException unused3) {
}
long length2 = androidFile3.length();
if (property != null || j < 0) {
if (!hexString.equals(properties.getProperty("if-none-match"))) {
response3 = new Response(HTTP_NOTMODIFIED, str5, "");
} else {
response2 = new Response(HTTP_OK, str5, androidFile3.getInputStream());
response2.addHeader(HttpHeaders.CONTENT_LENGTH, "" + length2);
response2.addHeader(HttpHeaders.ETAG, hexString);
response3 = response2;
}
} else if (j >= length2) {
response2 = new Response(HTTP_RANGE_NOT_SATISFIABLE, str9, "");
response2.addHeader(HttpHeaders.CONTENT_RANGE, "bytes 0-0/" + length2);
response2.addHeader(HttpHeaders.ETAG, hexString);
response3 = response2;
} else {
long j3 = str3;
if (str3 < 0) {
j3 = length2 - 1;
}
long j4 = j3;
long j5 = (j4 - j) + 1;
if (j5 < 0) {
str4 = HTTP_FORBIDDEN;
j2 = 0;
} else {
str4 = HTTP_FORBIDDEN;
j2 = j5;
}
try {
InputStream inputStream = androidFile3.getInputStream();
inputStream.skip(j);
Response response4 = new Response(HTTP_PARTIALCONTENT, str5, inputStream);
response4.addHeader(HttpHeaders.CONTENT_LENGTH, "" + j2);
response4.addHeader(HttpHeaders.CONTENT_RANGE, "bytes " + j + "-" + j4 + "/" + length2);
response4.addHeader(HttpHeaders.ETAG, hexString);
response3 = response4;
} catch (IOException unused4) {
str3 = str9;
response = new Response(str4, str3, "FORBIDDEN: Reading file failed.");
response.addHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
return response;
}
}
response.addHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
return response;
}
j = 0;
str3 = -1;
long length22 = androidFile3.length();
if (property != null) {
}
if (!hexString.equals(properties.getProperty("if-none-match"))) {
}
}
response = response3;
response.addHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
return response;
}
androidFile2 = androidFile3;
androidFile3 = androidFile2;
if (response3 == null) {
}
response = response3;
response.addHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
return response;
}
static {
StringTokenizer stringTokenizer = new StringTokenizer("css\t\ttext/css htm\t\ttext/html html\t\ttext/html xml\t\ttext/xml txt\t\ttext/plain asc\t\ttext/plain gif\t\timage/gif jpg\t\timage/jpeg jpeg\t\timage/jpeg png\t\timage/png mp3\t\taudio/mpeg m3u\t\taudio/mpeg-url mp4\t\tvideo/mp4 ogv\t\tvideo/ogg flv\t\tvideo/x-flv mov\t\tvideo/quicktime swf\t\tapplication/x-shockwave-flash js\t\t\tapplication/javascript pdf\t\tapplication/pdf doc\t\tapplication/msword ogg\t\tapplication/x-ogg zip\t\tapplication/octet-stream exe\t\tapplication/octet-stream class\t\tapplication/octet-stream ");
while (stringTokenizer.hasMoreTokens()) {
theMimeTypes.put(stringTokenizer.nextToken(), stringTokenizer.nextToken());
}
theBufferSize = 16384;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
gmtFrmt = simpleDateFormat;
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
}
}