diff options
author | Simon Rettberg | 2015-09-04 15:50:33 +0200 |
---|---|---|
committer | Simon Rettberg | 2015-09-04 15:50:33 +0200 |
commit | cf5c2c886f65e61870b951546258949e3a4030f8 (patch) | |
tree | 7ac4dfeb26c60a3213e9e4fa4c69f515a42e2e16 /dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java | |
parent | [*] OS now has mem and cpu info (diff) | |
download | tutor-module-cf5c2c886f65e61870b951546258949e3a4030f8.tar.gz tutor-module-cf5c2c886f65e61870b951546258949e3a4030f8.tar.xz tutor-module-cf5c2c886f65e61870b951546258949e3a4030f8.zip |
[server] mailtest RPC methods, bugfixes to nanohttpd
Diffstat (limited to 'dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java')
-rw-r--r-- | dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java b/dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java index f8e44fa8..8d38f577 100644 --- a/dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java +++ b/dozentenmodulserver/src/main/java/fi/iki/elonen/NanoHTTPD.java @@ -50,6 +50,7 @@ import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URLDecoder; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; @@ -66,6 +67,8 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.log4j.Logger; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; @@ -121,6 +124,9 @@ import org.joda.time.format.DateTimeFormatter; * licence) */ public abstract class NanoHTTPD implements Runnable { + + private static final Logger LOGGER = Logger.getLogger(NanoHTTPD.class); + /** * Maximum time to wait on Socket.getInputStream().read() (in milliseconds) * This is required as the Keep-Alive HTTP connections would otherwise @@ -150,6 +156,8 @@ public abstract class NanoHTTPD implements Runnable { */ private AsyncRunner asyncRunner; + protected int maxRequestSize = 0; + /** * Constructs an HTTP server on given port. */ @@ -847,6 +855,8 @@ public abstract class NanoHTTPD implements Runnable { if (splitbyte > 0) break; read = inputStream.read(buf, rlen, BUFSIZE - rlen); + if (maxRequestSize != 0 && rlen > maxRequestSize) + throw new SocketException("Request too large"); } } @@ -909,7 +919,6 @@ public abstract class NanoHTTPD implements Runnable { @Override public void parseBody(Map<String, String> files) throws IOException, ResponseException { - final Reader in = new InputStreamReader(inputStream); long size; if (headers.containsKey("content-length")) { size = Integer.parseInt(headers.get("content-length")); @@ -922,36 +931,50 @@ public abstract class NanoHTTPD implements Runnable { // If the method is POST, there may be parameters // in data section, too, read it: if (Method.POST.equals(method)) { - String contentType = ""; + String contentType = null; + String contentEncoding = null; String contentTypeHeader = headers.get("content-type"); StringTokenizer st = null; if (contentTypeHeader != null) { - st = new StringTokenizer(contentTypeHeader, ",; "); + st = new StringTokenizer(contentTypeHeader, ","); if (st.hasMoreTokens()) { - contentType = st.nextToken(); + String part[] = st.nextToken().split(";\\s*", 2); + contentType = part[0]; + if (part.length == 2) { + contentEncoding = part[1]; + } } } + Charset cs = StandardCharsets.ISO_8859_1; + if (contentEncoding != null) { + try { + cs = Charset.forName(contentEncoding); + } catch (Exception e) { + } + } + LOGGER.debug("Content type is '" + contentType + "', encoding '" + cs.name() + "'"); if ("multipart/form-data".equalsIgnoreCase(contentType)) { throw new ResponseException(Response.Status.BAD_REQUEST, "BAD REQUEST: Content type is multipart/form-data, which is not supported"); } else { - String postLine = ""; - StringBuilder postLineBuffer = new StringBuilder(); - char pbuf[] = new char[512]; - while (rlen >= 0 && size > 0 && !postLine.endsWith("\r\n")) { - rlen = in.read(pbuf, 0, (int) Math.min(size, 512)); - if (rlen <= 0) + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte pbuf[] = new byte[1000]; + while (size > 0) { + int ret = inputStream.read(pbuf, 0, (int) Math.min(size, pbuf.length)); + if (ret <= 0) + break; + if (ret >= 2 && pbuf[ret - 1] == '\n' && pbuf[ret - 2] == '\r') break; - postLine = String.valueOf(pbuf, 0, rlen); - postLineBuffer.append(postLine); + size -= ret; + baos.write(pbuf, 0, ret); } - postLine = postLineBuffer.toString().trim(); + String postLine = new String(baos.toByteArray(), cs); // Handle application/x-www-form-urlencoded if ("application/x-www-form-urlencoded".equalsIgnoreCase(contentType)) { decodeParms(postLine, parms); - } else if (postLine.length() != 0) { + } else if (files != null && postLine.length() != 0) { // Special case for raw POST data => create a special files entry "postData" with raw content data files.put("postData", postLine); } |