diff src/luan/webserver/RequestParser.java @ 1147:30d87b7d1d62

webserver - support multipart/form-data
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 01 Feb 2018 22:06:37 -0700
parents 2dda3c92a473
children 49fb4e83484f
line wrap: on
line diff
--- a/src/luan/webserver/RequestParser.java	Thu Feb 01 03:08:21 2018 -0700
+++ b/src/luan/webserver/RequestParser.java	Thu Feb 01 22:06:37 2018 -0700
@@ -15,7 +15,7 @@
 	}
 
 	void parseUrlencoded() throws ParseException {
-		this.parser = new Parser(request.body);
+		this.parser = new Parser(Util.toString(request.body));
 		parseQuery();
 		require( parser.endOfInput() );
 	}
@@ -195,4 +195,64 @@
 		}
 	}
 
+
+	private static final String contentTypeStart = "multipart/form-data; boundary=";
+
+	void parseMultipart() throws ParseException {
+		String contentType = (String)request.headers.get("Content-Type");
+		if( !contentType.startsWith(contentTypeStart) )
+			throw new RuntimeException(contentType);
+		String boundary = "--"+contentType.substring(contentTypeStart.length());
+		this.parser = new Parser(Util.toString(request.body));
+		require( parser.match(boundary) );
+		boundary = "\r\n" + boundary;
+		while( !parser.match("--\r\n") ) {
+			require( parser.match("\r\n") );
+			require( parser.match("Content-Disposition: form-data; name=") );
+			String name = quotedString();
+			String filename = null;
+			boolean isBinary = false;
+			if( parser.match("; filename=") ) {
+				filename = quotedString();
+				require( parser.match("\r\n") );
+				require( parser.match("Content-Type: ") );
+				if( parser.match("application/octet-stream") ) {
+					isBinary = true;
+				} else if( parser.match("text/plain") ) {
+					isBinary = false;
+				} else
+					throw new ParseException(parser,"bad file content-type");
+			}
+			require( parser.match("\r\n") );
+			require( parser.match("\r\n") );
+			int start = parser.currentIndex();
+			while( !parser.test(boundary) ) {
+				require( parser.anyChar() );
+			}
+			String value = parser.textFrom(start);
+			if( filename == null ) {
+				Util.add(request.parameters,name,value);
+			} else {
+				Object content = isBinary ? Util.toBytes(value) : value;
+				Request.MultipartFile mf = new Request.MultipartFile(filename,content);
+				Util.add(request.parameters,name,mf);
+			}
+			require( parser.match(boundary) );
+		}
+	}
+
+	private String quotedString() throws ParseException {
+		StringBuilder sb = new StringBuilder();
+		require( parser.match('"') );
+		while( !parser.match('"') ) {
+			if( parser.match("\\\"") ) {
+				sb.append('"');
+			} else {
+				require( parser.anyChar() );
+				sb.append( parser.lastChar() );
+			}
+		}
+		return sb.toString();
+	}
+
 }