diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
index 30d8fc9d974..55f4c1ef37a 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
@@ -447,7 +447,7 @@ public class HttpParser
/* ------------------------------------------------------------------------------- */
enum CharState { ILLEGAL, CR, LF, LEGAL }
- private final static CharState[] __charState;
+ public final static CharState[] TOKEN_CHAR;
static
{
// token = 1*tchar
@@ -462,38 +462,38 @@ public class HttpParser
// ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
// quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
- __charState=new CharState[256];
- Arrays.fill(__charState,CharState.ILLEGAL);
- __charState[LINE_FEED]=CharState.LF;
- __charState[CARRIAGE_RETURN]=CharState.CR;
- __charState[TAB]=CharState.LEGAL;
- __charState[SPACE]=CharState.LEGAL;
+ TOKEN_CHAR =new CharState[256];
+ Arrays.fill(TOKEN_CHAR,CharState.ILLEGAL);
+ TOKEN_CHAR[LINE_FEED]=CharState.LF;
+ TOKEN_CHAR[CARRIAGE_RETURN]=CharState.CR;
+ TOKEN_CHAR[TAB]=CharState.LEGAL;
+ TOKEN_CHAR[SPACE]=CharState.LEGAL;
- __charState['!']=CharState.LEGAL;
- __charState['#']=CharState.LEGAL;
- __charState['$']=CharState.LEGAL;
- __charState['%']=CharState.LEGAL;
- __charState['&']=CharState.LEGAL;
- __charState['\'']=CharState.LEGAL;
- __charState['*']=CharState.LEGAL;
- __charState['+']=CharState.LEGAL;
- __charState['-']=CharState.LEGAL;
- __charState['.']=CharState.LEGAL;
- __charState['^']=CharState.LEGAL;
- __charState['_']=CharState.LEGAL;
- __charState['`']=CharState.LEGAL;
- __charState['|']=CharState.LEGAL;
- __charState['~']=CharState.LEGAL;
+ TOKEN_CHAR['!']=CharState.LEGAL;
+ TOKEN_CHAR['#']=CharState.LEGAL;
+ TOKEN_CHAR['$']=CharState.LEGAL;
+ TOKEN_CHAR['%']=CharState.LEGAL;
+ TOKEN_CHAR['&']=CharState.LEGAL;
+ TOKEN_CHAR['\'']=CharState.LEGAL;
+ TOKEN_CHAR['*']=CharState.LEGAL;
+ TOKEN_CHAR['+']=CharState.LEGAL;
+ TOKEN_CHAR['-']=CharState.LEGAL;
+ TOKEN_CHAR['.']=CharState.LEGAL;
+ TOKEN_CHAR['^']=CharState.LEGAL;
+ TOKEN_CHAR['_']=CharState.LEGAL;
+ TOKEN_CHAR['`']=CharState.LEGAL;
+ TOKEN_CHAR['|']=CharState.LEGAL;
+ TOKEN_CHAR['~']=CharState.LEGAL;
- __charState['"']=CharState.LEGAL;
+ TOKEN_CHAR['"']=CharState.LEGAL;
- __charState['\\']=CharState.LEGAL;
- __charState['(']=CharState.LEGAL;
- __charState[')']=CharState.LEGAL;
- Arrays.fill(__charState,0x21,0x27+1,CharState.LEGAL);
- Arrays.fill(__charState,0x2A,0x5B+1,CharState.LEGAL);
- Arrays.fill(__charState,0x5D,0x7E+1,CharState.LEGAL);
- Arrays.fill(__charState,0x80,0xFF+1,CharState.LEGAL);
+ TOKEN_CHAR['\\']=CharState.LEGAL;
+ TOKEN_CHAR['(']=CharState.LEGAL;
+ TOKEN_CHAR[')']=CharState.LEGAL;
+ Arrays.fill(TOKEN_CHAR,0x21,0x27+1,CharState.LEGAL);
+ Arrays.fill(TOKEN_CHAR,0x2A,0x5B+1,CharState.LEGAL);
+ Arrays.fill(TOKEN_CHAR,0x5D,0x7E+1,CharState.LEGAL);
+ Arrays.fill(TOKEN_CHAR,0x80,0xFF+1,CharState.LEGAL);
}
@@ -502,7 +502,7 @@ public class HttpParser
{
byte ch = buffer.get();
- CharState s = __charState[0xff & ch];
+ CharState s = TOKEN_CHAR[0xff & ch];
switch(s)
{
case ILLEGAL:
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormInputStream.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormInputStream.java
index 5fb4d85bd15..8e68ba43c9d 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormInputStream.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartFormInputStream.java
@@ -52,28 +52,27 @@ import org.eclipse.jetty.util.log.Logger;
/**
* MultiPartInputStream
- *
+ *
* Handle a MultiPart Mime input stream, breaking it up on the boundary into files and strings.
- *
+ *
* @see https://tools.ietf.org/html/rfc7578
*/
public class MultiPartFormInputStream
{
private static final Logger LOG = Log.getLogger(MultiPartFormInputStream.class);
- private final int _bufferSize = 16 * 1024;
- public static final MultipartConfigElement __DEFAULT_MULTIPART_CONFIG = new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
- public static final MultiMap EMPTY_MAP = new MultiMap<>(Collections.emptyMap());
- protected InputStream _in;
- protected MultipartConfigElement _config;
- protected String _contentType;
- protected MultiMap _parts;
- protected Throwable _err;
- protected File _tmpDir;
- protected File _contextTmpDir;
- protected boolean _deleteOnExit;
- protected boolean _writeFilesWithFilenames;
- protected boolean _parsed;
-
+ private static final MultiMap EMPTY_MAP = new MultiMap<>(Collections.emptyMap());
+ private InputStream _in;
+ private MultipartConfigElement _config;
+ private String _contentType;
+ private MultiMap _parts;
+ private Throwable _err;
+ private File _tmpDir;
+ private File _contextTmpDir;
+ private boolean _deleteOnExit;
+ private boolean _writeFilesWithFilenames;
+ private boolean _parsed;
+ private int _bufferSize = 16 * 1024;
+
public class MultiPart implements Part
{
protected String _name;
@@ -85,24 +84,24 @@ public class MultiPartFormInputStream
protected MultiMap _headers;
protected long _size = 0;
protected boolean _temporary = true;
-
- public MultiPart(String name, String filename) throws IOException
+
+ public MultiPart(String name, String filename)
{
_name = name;
_filename = filename;
}
-
+
@Override
public String toString()
{
- return String.format("Part{n=%s,fn=%s,ct=%s,s=%d,tmp=%b,file=%s}",_name,_filename,_contentType,_size,_temporary,_file);
+ return String.format("Part{n=%s,fn=%s,ct=%s,s=%d,tmp=%b,file=%s}", _name, _filename, _contentType, _size, _temporary, _file);
}
-
+
protected void setContentType(String contentType)
{
_contentType = contentType;
}
-
+
protected void open() throws IOException
{
// We will either be writing to a file, if it has a filename on the content-disposition
@@ -119,38 +118,38 @@ public class MultiPartFormInputStream
_out = _bout = new ByteArrayOutputStream2();
}
}
-
+
protected void close() throws IOException
{
_out.close();
}
-
+
protected void write(int b) throws IOException
{
if (MultiPartFormInputStream.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartFormInputStream.this._config.getMaxFileSize())
throw new IllegalStateException("Multipart Mime part " + _name + " exceeds max filesize");
-
+
if (MultiPartFormInputStream.this._config.getFileSizeThreshold() > 0 && _size + 1 > MultiPartFormInputStream.this._config.getFileSizeThreshold()
&& _file == null)
createFile();
-
+
_out.write(b);
_size++;
}
-
+
protected void write(byte[] bytes, int offset, int length) throws IOException
{
if (MultiPartFormInputStream.this._config.getMaxFileSize() > 0 && _size + length > MultiPartFormInputStream.this._config.getMaxFileSize())
throw new IllegalStateException("Multipart Mime part " + _name + " exceeds max filesize");
-
+
if (MultiPartFormInputStream.this._config.getFileSizeThreshold() > 0
&& _size + length > MultiPartFormInputStream.this._config.getFileSizeThreshold() && _file == null)
createFile();
-
- _out.write(bytes,offset,length);
+
+ _out.write(bytes, offset, length);
_size += length;
}
-
+
protected void createFile() throws IOException
{
/*
@@ -158,16 +157,16 @@ public class MultiPartFormInputStream
*/
final boolean USER = true;
final boolean WORLD = false;
-
- _file = File.createTempFile("MultiPart","",MultiPartFormInputStream.this._tmpDir);
- _file.setReadable(false,WORLD); // (reset) disable it for everyone first
- _file.setReadable(true,USER); // enable for user only
-
+
+ _file = File.createTempFile("MultiPart", "", MultiPartFormInputStream.this._tmpDir);
+ _file.setReadable(false, WORLD); // (reset) disable it for everyone first
+ _file.setReadable(true, USER); // enable for user only
+
if (_deleteOnExit)
_file.deleteOnExit();
FileOutputStream fos = new FileOutputStream(_file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
-
+
if (_size > 0 && _out != null)
{
// already written some bytes, so need to copy them into the file
@@ -178,53 +177,38 @@ public class MultiPartFormInputStream
_bout = null;
_out = bos;
}
-
+
protected void setHeaders(MultiMap headers)
{
_headers = headers;
}
-
- /**
- * @see javax.servlet.http.Part#getContentType()
- */
+
@Override
public String getContentType()
{
return _contentType;
}
-
- /**
- * @see javax.servlet.http.Part#getHeader(java.lang.String)
- */
+
@Override
public String getHeader(String name)
{
if (name == null)
return null;
- return _headers.getValue(StringUtil.asciiToLowerCase(name),0);
+ return _headers.getValue(StringUtil.asciiToLowerCase(name), 0);
}
-
- /**
- * @see javax.servlet.http.Part#getHeaderNames()
- */
+
@Override
public Collection getHeaderNames()
{
return _headers.keySet();
}
-
- /**
- * @see javax.servlet.http.Part#getHeaders(java.lang.String)
- */
+
@Override
public Collection getHeaders(String name)
{
return _headers.getValues(name);
}
-
- /**
- * @see javax.servlet.http.Part#getInputStream()
- */
+
@Override
public InputStream getInputStream() throws IOException
{
@@ -236,68 +220,52 @@ public class MultiPartFormInputStream
else
{
// part content is in memory
- return new ByteArrayInputStream(_bout.getBuf(),0,_bout.size());
+ return new ByteArrayInputStream(_bout.getBuf(), 0, _bout.size());
}
}
-
- /**
- * @see javax.servlet.http.Part#getSubmittedFileName()
- */
+
@Override
public String getSubmittedFileName()
{
return getContentDispositionFilename();
}
-
+
public byte[] getBytes()
{
if (_bout != null)
return _bout.toByteArray();
return null;
}
-
- /**
- * @see javax.servlet.http.Part#getName()
- */
+
@Override
public String getName()
{
return _name;
}
-
- /**
- * @see javax.servlet.http.Part#getSize()
- */
+
@Override
public long getSize()
{
return _size;
}
-
- /**
- * @see javax.servlet.http.Part#write(java.lang.String)
- */
+
@Override
public void write(String fileName) throws IOException
{
if (_file == null)
{
_temporary = false;
-
+
// part data is only in the ByteArrayOutputStream and never been written to disk
- _file = new File(_tmpDir,fileName);
-
- BufferedOutputStream bos = null;
- try
+ _file = new File(_tmpDir, fileName);
+
+ try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(_file)))
{
- bos = new BufferedOutputStream(new FileOutputStream(_file));
_bout.writeTo(bos);
bos.flush();
}
finally
{
- if (bos != null)
- bos.close();
_bout = null;
}
}
@@ -305,51 +273,50 @@ public class MultiPartFormInputStream
{
// the part data is already written to a temporary file, just rename it
_temporary = false;
-
+
Path src = _file.toPath();
Path target = src.resolveSibling(fileName);
- Files.move(src,target,StandardCopyOption.REPLACE_EXISTING);
+ Files.move(src, target, StandardCopyOption.REPLACE_EXISTING);
_file = target.toFile();
}
}
-
+
/**
* Remove the file, whether or not Part.write() was called on it (ie no longer temporary)
- *
- * @see javax.servlet.http.Part#delete()
*/
@Override
public void delete() throws IOException
{
if (_file != null && _file.exists())
- _file.delete();
+ if (!_file.delete())
+ throw new IOException("Could Not Delete File");
}
-
+
/**
* Only remove tmp files.
*
- * @throws IOException
- * if unable to delete the file
+ * @throws IOException if unable to delete the file
*/
public void cleanUp() throws IOException
{
if (_temporary && _file != null && _file.exists())
- _file.delete();
+ if (!_file.delete())
+ throw new IOException("Could Not Delete File");
}
-
+
/**
* Get the file
- *
+ *
* @return the file, if any, the data has been written to.
*/
public File getFile()
{
return _file;
}
-
+
/**
* Get the filename from the content-disposition.
- *
+ *
* @return null or the filename
*/
public String getContentDispositionFilename()
@@ -357,16 +324,12 @@ public class MultiPartFormInputStream
return _filename;
}
}
-
+
/**
- * @param in
- * Request input stream
- * @param contentType
- * Content-Type header
- * @param config
- * MultipartConfigElement
- * @param contextTmpDir
- * javax.servlet.context.tempdir
+ * @param in Request input stream
+ * @param contentType Content-Type header
+ * @param config MultipartConfigElement
+ * @param contextTmpDir javax.servlet.context.tempdir
*/
public MultiPartFormInputStream(InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir)
{
@@ -375,10 +338,10 @@ public class MultiPartFormInputStream
_contextTmpDir = contextTmpDir;
if (_contextTmpDir == null)
_contextTmpDir = new File(System.getProperty("java.io.tmpdir"));
-
+
if (_config == null)
_config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
-
+
if (in instanceof ServletInputStream)
{
if (((ServletInputStream)in).isFinished())
@@ -390,7 +353,7 @@ public class MultiPartFormInputStream
}
_in = new BufferedInputStream(in);
}
-
+
/**
* @return whether the list of parsed parts is empty
*/
@@ -402,16 +365,16 @@ public class MultiPartFormInputStream
Collection> values = _parts.values();
for (List partList : values)
{
- if(partList.size() != 0)
+ if (partList.size() != 0)
return false;
}
-
+
return true;
}
/**
* Get the already parsed parts.
- *
+ *
* @return the parts that were parsed
*/
@Deprecated
@@ -419,25 +382,25 @@ public class MultiPartFormInputStream
{
if (_parts == null)
return Collections.emptyList();
-
+
Collection> values = _parts.values();
List parts = new ArrayList<>();
for (List o : values)
{
- List asList = LazyList.getList(o,false);
+ List asList = LazyList.getList(o, false);
parts.addAll(asList);
}
return parts;
}
-
+
/**
* Delete any tmp storage for parts, and clear out the parts list.
*/
public void deleteParts()
{
if (!_parsed)
- return;
-
+ return;
+
Collection parts;
try
{
@@ -447,8 +410,8 @@ public class MultiPartFormInputStream
{
throw new RuntimeException(e);
}
- MultiException err = new MultiException();
+ MultiException err = null;
for (Part p : parts)
{
try
@@ -457,59 +420,58 @@ public class MultiPartFormInputStream
}
catch (Exception e)
{
+ if (err == null)
+ err = new MultiException();
err.add(e);
}
}
_parts.clear();
-
- err.ifExceptionThrowRuntime();
+
+ if (err != null)
+ err.ifExceptionThrowRuntime();
}
-
+
/**
* Parse, if necessary, the multipart data and return the list of Parts.
*
* @return the parts
- * @throws IOException
- * if unable to get the parts
+ * @throws IOException if unable to get the parts
*/
public Collection getParts() throws IOException
{
if (!_parsed)
parse();
throwIfError();
-
+
Collection> values = _parts.values();
List parts = new ArrayList<>();
for (List o : values)
{
- List asList = LazyList.getList(o,false);
+ List asList = LazyList.getList(o, false);
parts.addAll(asList);
}
return parts;
}
-
+
/**
* Get the named Part.
*
- * @param name
- * the part name
+ * @param name the part name
* @return the parts
- * @throws IOException
- * if unable to get the part
+ * @throws IOException if unable to get the part
*/
public Part getPart(String name) throws IOException
{
- if(!_parsed)
+ if (!_parsed)
parse();
throwIfError();
- return _parts.getValue(name,0);
+ return _parts.getValue(name, 0);
}
-
+
/**
* Throws an exception if one has been latched.
- *
- * @throws IOException
- * the exception (if present)
+ *
+ * @throws IOException the exception (if present)
*/
protected void throwIfError() throws IOException
{
@@ -523,10 +485,9 @@ public class MultiPartFormInputStream
throw new IllegalStateException(_err);
}
}
-
+
/**
* Parse, if necessary, the multipart stream.
- *
*/
protected void parse()
{
@@ -537,14 +498,13 @@ public class MultiPartFormInputStream
try
{
-
// initialize
_parts = new MultiMap<>();
-
+
// if its not a multipart request, don't parse it
if (_contentType == null || !_contentType.startsWith("multipart/form-data"))
return;
-
+
// sort out the location to which to write the files
if (_config.getLocation() == null)
_tmpDir = _contextTmpDir;
@@ -556,70 +516,67 @@ public class MultiPartFormInputStream
if (f.isAbsolute())
_tmpDir = f;
else
- _tmpDir = new File(_contextTmpDir,_config.getLocation());
+ _tmpDir = new File(_contextTmpDir, _config.getLocation());
}
-
+
if (!_tmpDir.exists())
_tmpDir.mkdirs();
-
+
String contentTypeBoundary = "";
int bstart = _contentType.indexOf("boundary=");
if (bstart >= 0)
{
- int bend = _contentType.indexOf(";",bstart);
- bend = (bend < 0?_contentType.length():bend);
- contentTypeBoundary = QuotedStringTokenizer.unquote(value(_contentType.substring(bstart,bend)).trim());
+ int bend = _contentType.indexOf(";", bstart);
+ bend = (bend < 0 ? _contentType.length() : bend);
+ contentTypeBoundary = QuotedStringTokenizer.unquote(value(_contentType.substring(bstart, bend)).trim());
}
-
+
Handler handler = new Handler();
- MultiPartParser parser = new MultiPartParser(handler,contentTypeBoundary);
-
- // Create a buffer to store data from stream //
+ MultiPartParser parser = new MultiPartParser(handler, contentTypeBoundary);
+
byte[] data = new byte[_bufferSize];
- int len = 0;
-
- /*
- * keep running total of size of bytes read from input and throw an exception if exceeds MultipartConfigElement._maxRequestSize
- */
+ int len;
long total = 0;
-
+
while (true)
{
-
+
len = _in.read(data);
-
+
if (len > 0)
{
+
+ // keep running total of size of bytes read from input and throw an exception if exceeds MultipartConfigElement._maxRequestSize
total += len;
if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
{
_err = new IllegalStateException("Request exceeds maxRequestSize (" + _config.getMaxRequestSize() + ")");
return;
}
-
+
ByteBuffer buffer = BufferUtil.toBuffer(data);
buffer.limit(len);
- if (parser.parse(buffer,false))
+ if (parser.parse(buffer, false))
break;
- if(buffer.hasRemaining())
+ if (buffer.hasRemaining())
throw new IllegalStateException("Buffer did not fully consume");
-
+
}
else if (len == -1)
{
- parser.parse(BufferUtil.EMPTY_BUFFER,true);
+ parser.parse(BufferUtil.EMPTY_BUFFER, true);
break;
}
-
+
}
-
+
// check for exceptions
if (_err != null)
{
return;
}
-
+
// check we read to the end of the message
if (parser.getState() != MultiPartParser.State.END)
{
@@ -628,39 +585,37 @@ public class MultiPartFormInputStream
else
_err = new IOException("Incomplete Multipart");
}
-
+
if (LOG.isDebugEnabled())
{
- LOG.debug("Parsing Complete {} err={}",parser,_err);
+ LOG.debug("Parsing Complete {} err={}", parser, _err);
}
-
+
}
catch (Throwable e)
{
_err = e;
- return;
}
-
}
-
+
class Handler implements MultiPartParser.Handler
{
private MultiPart _part = null;
private String contentDisposition = null;
private String contentType = null;
private MultiMap headers = new MultiMap<>();
-
+
@Override
public boolean messageComplete()
{
return true;
}
-
+
@Override
public void parsedField(String key, String value)
- {
+ {
// Add to headers and mark if one of these fields. //
- headers.put(StringUtil.asciiToLowerCase(key),value);
+ headers.put(StringUtil.asciiToLowerCase(key), value);
if (key.equalsIgnoreCase("content-disposition"))
contentDisposition = value;
else if (key.equalsIgnoreCase("content-type"))
@@ -668,27 +623,27 @@ public class MultiPartFormInputStream
// Transfer encoding is not longer considers as it is deprecated as per
// https://tools.ietf.org/html/rfc7578#section-4.7
-
+
}
-
+
@Override
public boolean headerComplete()
{
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
{
- LOG.debug("headerComplete {}",this);
+ LOG.debug("headerComplete {}", this);
}
try
- {
+ {
// Extract content-disposition
boolean form_data = false;
if (contentDisposition == null)
{
throw new IOException("Missing content-disposition");
}
-
- QuotedStringTokenizer tok = new QuotedStringTokenizer(contentDisposition,";",false,true);
+
+ QuotedStringTokenizer tok = new QuotedStringTokenizer(contentDisposition, ";", false, true);
String name = null;
String filename = null;
while (tok.hasMoreTokens())
@@ -702,7 +657,7 @@ public class MultiPartFormInputStream
else if (tl.startsWith("filename="))
filename = filenameValue(t);
}
-
+
// Check disposition
if (!form_data)
throw new IOException("Part not form-data");
@@ -714,13 +669,13 @@ public class MultiPartFormInputStream
// have not yet seen a name field.
if (name == null)
throw new IOException("No name in part");
-
-
+
+
// create the new part
- _part = new MultiPart(name,filename);
+ _part = new MultiPart(name, filename);
_part.setHeaders(headers);
_part.setContentType(contentType);
- _parts.add(name,_part);
+ _parts.add(name, _part);
try
{
@@ -737,21 +692,21 @@ public class MultiPartFormInputStream
_err = e;
return true;
}
-
+
return false;
}
-
+
@Override
public boolean content(ByteBuffer buffer, boolean last)
- {
- if(_part == null)
+ {
+ if (_part == null)
return false;
if (BufferUtil.hasContent(buffer))
{
try
{
- _part.write(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
+ _part.write(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
}
catch (IOException e)
{
@@ -759,7 +714,7 @@ public class MultiPartFormInputStream
return true;
}
}
-
+
if (last)
{
try
@@ -772,12 +727,12 @@ public class MultiPartFormInputStream
return true;
}
}
-
+
return false;
}
-
+
@Override
- public void startPart()
+ public void startPart()
{
reset();
}
@@ -786,9 +741,9 @@ public class MultiPartFormInputStream
public void earlyEOF()
{
if (LOG.isDebugEnabled())
- LOG.debug("Early EOF {}",MultiPartFormInputStream.this);
+ LOG.debug("Early EOF {}", MultiPartFormInputStream.this);
}
-
+
public void reset()
{
_part = null;
@@ -797,41 +752,41 @@ public class MultiPartFormInputStream
headers = new MultiMap<>();
}
}
-
+
public void setDeleteOnExit(boolean deleteOnExit)
{
_deleteOnExit = deleteOnExit;
}
-
+
public void setWriteFilesWithFilenames(boolean writeFilesWithFilenames)
{
_writeFilesWithFilenames = writeFilesWithFilenames;
}
-
+
public boolean isWriteFilesWithFilenames()
{
return _writeFilesWithFilenames;
}
-
+
public boolean isDeleteOnExit()
{
return _deleteOnExit;
}
-
+
/* ------------------------------------------------------------ */
- private String value(String nameEqualsValue)
+ private static String value(String nameEqualsValue)
{
int idx = nameEqualsValue.indexOf('=');
String value = nameEqualsValue.substring(idx + 1).trim();
return QuotedStringTokenizer.unquoteOnly(value);
}
-
+
/* ------------------------------------------------------------ */
- private String filenameValue(String nameEqualsValue)
+ private static String filenameValue(String nameEqualsValue)
{
int idx = nameEqualsValue.indexOf('=');
String value = nameEqualsValue.substring(idx + 1).trim();
-
+
if (value.matches(".??[a-z,A-Z]\\:\\\\[^\\\\].*"))
{
// incorrectly escaped IE filenames that have the whole path
@@ -841,8 +796,8 @@ public class MultiPartFormInputStream
value = value.substring(1);
char last = value.charAt(value.length() - 1);
if (last == '"' || last == '\'')
- value = value.substring(0,value.length() - 1);
-
+ value = value.substring(0, value.length() - 1);
+
return value;
}
else
@@ -850,7 +805,22 @@ public class MultiPartFormInputStream
// form a valid escape sequence to remain as many browsers
// even on *nix systems will not escape a filename containing
// backslashes
- return QuotedStringTokenizer.unquoteOnly(value,true);
+ return QuotedStringTokenizer.unquoteOnly(value, true);
+ }
+
+ /**
+ * @return the size of buffer used to read data from the input stream
+ */
+ public int getBufferSize()
+ {
+ return _bufferSize;
+ }
+
+ /**
+ * @param bufferSize the size of buffer used to read data from the input stream
+ */
+ public void setBufferSize(int bufferSize)
+ {
+ _bufferSize = bufferSize;
}
-
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartParser.java
index 5554e64094a..92ece5b07b5 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/MultiPartParser.java
@@ -20,7 +20,6 @@ package org.eclipse.jetty.http;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
import java.util.EnumSet;
import org.eclipse.jetty.http.HttpParser.RequestHandler;
@@ -31,202 +30,146 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
-/** A parser for MultiPart content type.
- *
+
+/**
+ * A parser for MultiPart content type.
+ *
* @see https://tools.ietf.org/html/rfc2046#section-5.1
* @see https://tools.ietf.org/html/rfc2045
*/
public class MultiPartParser
{
public static final Logger LOG = Log.getLogger(MultiPartParser.class);
-
- static final byte COLON = (byte)':';
- static final byte TAB = 0x09;
- static final byte LINE_FEED = 0x0A;
- static final byte CARRIAGE_RETURN = 0x0D;
- static final byte SPACE = 0x20;
- static final byte[] CRLF =
- { CARRIAGE_RETURN, LINE_FEED };
- static final byte SEMI_COLON = (byte)';';
-
+
+ private static final byte COLON = (byte)':';
+ private static final byte TAB = 0x09;
+ private static final byte LINE_FEED = 0x0A;
+ private static final byte CARRIAGE_RETURN = 0x0D;
+ private static final byte SPACE = 0x20;
+
// States
public enum FieldState
{
FIELD,
IN_NAME,
- AFTER_NAME,
+ AFTER_NAME,
VALUE,
IN_VALUE
}
-
+
// States
public enum State
{
PREAMBLE,
DELIMITER,
- DELIMITER_PADDING,
+ DELIMITER_PADDING,
DELIMITER_CLOSE,
BODY_PART,
- FIRST_OCTETS,
+ FIRST_OCTETS,
OCTETS,
- EPILOGUE,
+ EPILOGUE,
END
}
-
- private final static EnumSet __delimiterStates = EnumSet.of(State.DELIMITER,State.DELIMITER_CLOSE,State.DELIMITER_PADDING);
-
+
+ private final static EnumSet __delimiterStates = EnumSet.of(State.DELIMITER, State.DELIMITER_CLOSE, State.DELIMITER_PADDING);
+ private final static int MAX_HEADER_LINE_LENGTH = 998;
+
private final boolean DEBUG = LOG.isDebugEnabled();
private final Handler _handler;
private final SearchPattern _delimiterSearch;
-
+
private String _fieldName;
private String _fieldValue;
-
+
private State _state = State.PREAMBLE;
private FieldState _fieldState = FieldState.FIELD;
private int _partialBoundary = 2; // No CRLF if no preamble
private boolean _cr;
private ByteBuffer _patternBuffer;
-
+
private final Utf8StringBuilder _string = new Utf8StringBuilder();
private int _length;
-
+
private int _totalHeaderLineLength = -1;
- private int _maxHeaderLineLength = 998;
-
+
/* ------------------------------------------------------------------------------- */
public MultiPartParser(Handler handler, String boundary)
{
_handler = handler;
-
+
String delimiter = "\r\n--" + boundary;
_patternBuffer = ByteBuffer.wrap(delimiter.getBytes(StandardCharsets.US_ASCII));
_delimiterSearch = SearchPattern.compile(_patternBuffer.array());
}
-
+
public void reset()
{
_state = State.PREAMBLE;
_fieldState = FieldState.FIELD;
_partialBoundary = 2; // No CRLF if no preamble
}
-
+
/* ------------------------------------------------------------------------------- */
public Handler getHandler()
{
return _handler;
}
-
+
/* ------------------------------------------------------------------------------- */
public State getState()
{
return _state;
}
-
+
/* ------------------------------------------------------------------------------- */
public boolean isState(State state)
{
return _state == state;
}
-
+
/* ------------------------------------------------------------------------------- */
- enum CharState
- {
- ILLEGAL, CR, LF, LEGAL
- }
- private final static CharState[] __charState;
- static
- {
- // token = 1*tchar
- // tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
- // / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
- // / DIGIT / ALPHA
- // ; any VCHAR, except delimiters
- // quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
- // qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
- // obs-text = %x80-FF
- // comment = "(" *( ctext / quoted-pair / comment ) ")"
- // ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text
- // quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
-
- __charState = new CharState[256];
- Arrays.fill(__charState,CharState.ILLEGAL);
- __charState[LINE_FEED] = CharState.LF;
- __charState[CARRIAGE_RETURN] = CharState.CR;
- __charState[TAB] = CharState.LEGAL;
- __charState[SPACE] = CharState.LEGAL;
-
- __charState['!'] = CharState.LEGAL;
- __charState['#'] = CharState.LEGAL;
- __charState['$'] = CharState.LEGAL;
- __charState['%'] = CharState.LEGAL;
- __charState['&'] = CharState.LEGAL;
- __charState['\''] = CharState.LEGAL;
- __charState['*'] = CharState.LEGAL;
- __charState['+'] = CharState.LEGAL;
- __charState['-'] = CharState.LEGAL;
- __charState['.'] = CharState.LEGAL;
- __charState['^'] = CharState.LEGAL;
- __charState['_'] = CharState.LEGAL;
- __charState['`'] = CharState.LEGAL;
- __charState['|'] = CharState.LEGAL;
- __charState['~'] = CharState.LEGAL;
-
- __charState['"'] = CharState.LEGAL;
-
- __charState['\\'] = CharState.LEGAL;
- __charState['('] = CharState.LEGAL;
- __charState[')'] = CharState.LEGAL;
- Arrays.fill(__charState,0x21,0x27 + 1,CharState.LEGAL);
- Arrays.fill(__charState,0x2A,0x5B + 1,CharState.LEGAL);
- Arrays.fill(__charState,0x5D,0x7E + 1,CharState.LEGAL);
- Arrays.fill(__charState,0x80,0xFF + 1,CharState.LEGAL);
-
- }
-
- /* ------------------------------------------------------------------------------- */
- private boolean hasNextByte(ByteBuffer buffer)
+ private static boolean hasNextByte(ByteBuffer buffer)
{
return BufferUtil.hasContent(buffer);
}
-
+
/* ------------------------------------------------------------------------------- */
private byte getNextByte(ByteBuffer buffer)
{
-
+
byte ch = buffer.get();
-
- CharState s = __charState[0xff & ch];
+
+ HttpParser.CharState s = HttpParser.TOKEN_CHAR[0xff & ch];
switch (s)
{
case LF:
_cr = false;
return ch;
-
+
case CR:
if (_cr)
throw new BadMessageException("Bad EOL");
-
+
_cr = true;
if (buffer.hasRemaining())
return getNextByte(buffer);
-
+
// Can return 0 here to indicate the need for more characters,
// because a real 0 in the buffer would cause a BadMessage below
return 0;
-
+
case LEGAL:
if (_cr)
throw new BadMessageException("Bad EOL");
-
+
return ch;
-
+
case ILLEGAL:
default:
- throw new IllegalCharacterException(_state,ch,buffer);
+ throw new IllegalCharacterException(_state, ch, buffer);
}
}
-
+
/* ------------------------------------------------------------------------------- */
private void setString(String s)
{
@@ -234,7 +177,7 @@ public class MultiPartParser
_string.append(s);
_length = s.length();
}
-
+
/* ------------------------------------------------------------------------------- */
/*
* Mime Field strings are treated as UTF-8 as per https://tools.ietf.org/html/rfc7578#section-5.1
@@ -243,91 +186,92 @@ public class MultiPartParser
{
String s = _string.toString();
// trim trailing whitespace.
- if (s.length()>_length)
- s = s.substring(0,_length);
+ if (s.length() > _length)
+ s = s.substring(0, _length);
_string.reset();
_length = -1;
return s;
}
-
+
/* ------------------------------------------------------------------------------- */
+
/**
* Parse until next Event.
- *
+ *
* @param buffer the buffer to parse
- * @param last whether this buffer contains last bit of content
+ * @param last whether this buffer contains last bit of content
* @return True if an {@link RequestHandler} method was called and it returned true;
*/
public boolean parse(ByteBuffer buffer, boolean last)
{
boolean handle = false;
- while (handle == false && BufferUtil.hasContent(buffer))
+ while (!handle && BufferUtil.hasContent(buffer))
{
switch (_state)
{
case PREAMBLE:
parsePreamble(buffer);
continue;
-
+
case DELIMITER:
case DELIMITER_PADDING:
case DELIMITER_CLOSE:
parseDelimiter(buffer);
continue;
-
+
case BODY_PART:
handle = parseMimePartHeaders(buffer);
break;
-
+
case FIRST_OCTETS:
case OCTETS:
handle = parseOctetContent(buffer);
break;
-
+
case EPILOGUE:
BufferUtil.clear(buffer);
break;
-
+
case END:
handle = true;
break;
-
+
default:
throw new IllegalStateException();
-
+
}
}
-
+
if (last && BufferUtil.isEmpty(buffer))
{
if (_state == State.EPILOGUE)
{
_state = State.END;
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
LOG.debug("messageComplete {}", this);
return _handler.messageComplete();
}
else
{
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
LOG.debug("earlyEOF {}", this);
_handler.earlyEOF();
return true;
}
}
-
+
return handle;
}
-
+
/* ------------------------------------------------------------------------------- */
private void parsePreamble(ByteBuffer buffer)
{
if (_partialBoundary > 0)
{
- int partial = _delimiterSearch.startsWith(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining(),_partialBoundary);
+ int partial = _delimiterSearch.startsWith(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining(), _partialBoundary);
if (partial > 0)
{
if (partial == _delimiterSearch.getLength())
@@ -337,29 +281,27 @@ public class MultiPartParser
setState(State.DELIMITER);
return;
}
-
+
_partialBoundary = partial;
BufferUtil.clear(buffer);
return;
}
-
+
_partialBoundary = 0;
}
-
- int delimiter = _delimiterSearch.match(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
+
+ int delimiter = _delimiterSearch.match(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
if (delimiter >= 0)
{
buffer.position(delimiter - buffer.arrayOffset() + _delimiterSearch.getLength());
setState(State.DELIMITER);
return;
}
-
- _partialBoundary = _delimiterSearch.endsWith(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
+
+ _partialBoundary = _delimiterSearch.endsWith(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
BufferUtil.clear(buffer);
-
- return;
}
-
+
/* ------------------------------------------------------------------------------- */
private void parseDelimiter(ByteBuffer buffer)
{
@@ -368,18 +310,18 @@ public class MultiPartParser
byte b = getNextByte(buffer);
if (b == 0)
return;
-
+
if (b == '\n')
{
setState(State.BODY_PART);
- if(LOG.isDebugEnabled())
- LOG.debug("startPart {}",this);
+ if (LOG.isDebugEnabled())
+ LOG.debug("startPart {}", this);
_handler.startPart();
return;
}
-
+
switch (_state)
{
case DELIMITER:
@@ -388,7 +330,7 @@ public class MultiPartParser
else
setState(State.DELIMITER_PADDING);
continue;
-
+
case DELIMITER_CLOSE:
if (b == '-')
{
@@ -397,14 +339,13 @@ public class MultiPartParser
}
setState(State.DELIMITER_PADDING);
continue;
-
+
case DELIMITER_PADDING:
default:
- continue;
}
}
}
-
+
/* ------------------------------------------------------------------------------- */
/*
* Parse the message headers and return true if the handler has signaled for a return
@@ -418,13 +359,13 @@ public class MultiPartParser
byte b = getNextByte(buffer);
if (b == 0)
break;
-
+
if (b != LINE_FEED)
_totalHeaderLineLength++;
-
- if (_totalHeaderLineLength > _maxHeaderLineLength)
+
+ if (_totalHeaderLineLength > MAX_HEADER_LINE_LENGTH)
throw new IllegalStateException("Header Line Exceeded Max Length");
-
+
switch (_fieldState)
{
case FIELD:
@@ -434,10 +375,10 @@ public class MultiPartParser
case TAB:
{
// Folded field value!
-
+
if (_fieldName == null)
throw new IllegalStateException("First field folded");
-
+
if (_fieldValue == null)
{
_string.reset();
@@ -453,26 +394,26 @@ public class MultiPartParser
setState(FieldState.VALUE);
break;
}
-
+
case LINE_FEED:
{
handleField();
setState(State.FIRST_OCTETS);
_partialBoundary = 2; // CRLF is option for empty parts
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
LOG.debug("headerComplete {}", this);
if (_handler.headerComplete())
return true;
break;
}
-
+
default:
{
// process previous header
handleField();
-
+
// New header
setState(FieldState.IN_NAME);
_string.reset();
@@ -481,7 +422,7 @@ public class MultiPartParser
}
}
break;
-
+
case IN_NAME:
switch (b)
{
@@ -490,29 +431,29 @@ public class MultiPartParser
_length = -1;
setState(FieldState.VALUE);
break;
-
+
case SPACE:
// Ignore trailing whitespaces
setState(FieldState.AFTER_NAME);
break;
-
+
case LINE_FEED:
{
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
LOG.debug("Line Feed in Name {}", this);
handleField();
setState(FieldState.FIELD);
break;
}
-
+
default:
_string.append(b);
_length = _string.length();
break;
}
break;
-
+
case AFTER_NAME:
switch (b)
{
@@ -521,22 +462,22 @@ public class MultiPartParser
_length = -1;
setState(FieldState.VALUE);
break;
-
+
case LINE_FEED:
_fieldName = takeString();
_string.reset();
_fieldValue = "";
_length = -1;
break;
-
+
case SPACE:
break;
-
+
default:
- throw new IllegalCharacterException(_state,b,buffer);
+ throw new IllegalCharacterException(_state, b, buffer);
}
break;
-
+
case VALUE:
switch (b)
{
@@ -544,14 +485,14 @@ public class MultiPartParser
_string.reset();
_fieldValue = "";
_length = -1;
-
+
setState(FieldState.FIELD);
break;
-
+
case SPACE:
case TAB:
break;
-
+
default:
_string.append(b);
_length = _string.length();
@@ -559,14 +500,14 @@ public class MultiPartParser
break;
}
break;
-
+
case IN_VALUE:
switch (b)
{
case SPACE:
_string.append(b);
break;
-
+
case LINE_FEED:
if (_length > 0)
{
@@ -576,7 +517,7 @@ public class MultiPartParser
}
setState(FieldState.FIELD);
break;
-
+
default:
_string.append(b);
if (b > SPACE || b < 0)
@@ -584,35 +525,35 @@ public class MultiPartParser
break;
}
break;
-
+
default:
throw new IllegalStateException(_state.toString());
-
+
}
}
return false;
}
-
+
/* ------------------------------------------------------------------------------- */
private void handleField()
{
- if(LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled())
LOG.debug("parsedField: _fieldName={} _fieldValue={} {}", _fieldName, _fieldValue, this);
if (_fieldName != null && _fieldValue != null)
- _handler.parsedField(_fieldName,_fieldValue);
+ _handler.parsedField(_fieldName, _fieldValue);
_fieldName = _fieldValue = null;
}
-
+
/* ------------------------------------------------------------------------------- */
-
+
protected boolean parseOctetContent(ByteBuffer buffer)
{
-
+
// Starts With
if (_partialBoundary > 0)
{
- int partial = _delimiterSearch.startsWith(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining(),_partialBoundary);
+ int partial = _delimiterSearch.startsWith(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining(), _partialBoundary);
if (partial > 0)
{
if (partial == _delimiterSearch.getLength())
@@ -621,12 +562,12 @@ public class MultiPartParser
setState(State.DELIMITER);
_partialBoundary = 0;
- if(LOG.isDebugEnabled())
- LOG.debug("Content={}, Last={} {}",BufferUtil.toDetailString(BufferUtil.EMPTY_BUFFER),true,this);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Content={}, Last={} {}", BufferUtil.toDetailString(BufferUtil.EMPTY_BUFFER), true, this);
- return _handler.content(BufferUtil.EMPTY_BUFFER,true);
+ return _handler.content(BufferUtil.EMPTY_BUFFER, true);
}
-
+
_partialBoundary = partial;
BufferUtil.clear(buffer);
return false;
@@ -642,78 +583,78 @@ public class MultiPartParser
}
content.limit(_partialBoundary);
_partialBoundary = 0;
-
- if(LOG.isDebugEnabled())
- LOG.debug("Content={}, Last={} {}",BufferUtil.toDetailString(content),false,this);
- if (_handler.content(content,false))
+ if (LOG.isDebugEnabled())
+ LOG.debug("Content={}, Last={} {}", BufferUtil.toDetailString(content), false, this);
+
+ if (_handler.content(content, false))
return true;
}
}
-
+
// Contains
- int delimiter = _delimiterSearch.match(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
+ int delimiter = _delimiterSearch.match(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
if (delimiter >= 0)
{
ByteBuffer content = buffer.slice();
content.limit(delimiter - buffer.arrayOffset() - buffer.position());
-
+
buffer.position(delimiter - buffer.arrayOffset() + _delimiterSearch.getLength());
setState(State.DELIMITER);
-
- if(LOG.isDebugEnabled())
- LOG.debug("Content={}, Last={} {}",BufferUtil.toDetailString(content),true,this);
- return _handler.content(content,true);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Content={}, Last={} {}", BufferUtil.toDetailString(content), true, this);
+
+ return _handler.content(content, true);
}
-
+
// Ends With
- _partialBoundary = _delimiterSearch.endsWith(buffer.array(),buffer.arrayOffset() + buffer.position(),buffer.remaining());
+ _partialBoundary = _delimiterSearch.endsWith(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining());
if (_partialBoundary > 0)
{
ByteBuffer content = buffer.slice();
content.limit(content.limit() - _partialBoundary);
-
- if(LOG.isDebugEnabled())
- LOG.debug("Content={}, Last={} {}",BufferUtil.toDetailString(content),false,this);
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("Content={}, Last={} {}", BufferUtil.toDetailString(content), false, this);
BufferUtil.clear(buffer);
- return _handler.content(content,false);
+ return _handler.content(content, false);
}
-
+
// There is normal content with no delimiter
ByteBuffer content = buffer.slice();
- if(LOG.isDebugEnabled())
- LOG.debug("Content={}, Last={} {}",BufferUtil.toDetailString(content),false,this);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Content={}, Last={} {}", BufferUtil.toDetailString(content), false, this);
BufferUtil.clear(buffer);
- return _handler.content(content,false);
+ return _handler.content(content, false);
}
-
+
/* ------------------------------------------------------------------------------- */
private void setState(State state)
{
if (DEBUG)
- LOG.debug("{} --> {}",_state,state);
+ LOG.debug("{} --> {}", _state, state);
_state = state;
}
-
+
/* ------------------------------------------------------------------------------- */
private void setState(FieldState state)
{
if (DEBUG)
- LOG.debug("{}:{} --> {}",_state,_fieldState,state);
+ LOG.debug("{}:{} --> {}", _state, _fieldState, state);
_fieldState = state;
}
-
+
/* ------------------------------------------------------------------------------- */
@Override
public String toString()
{
- return String.format("%s{s=%s}",getClass().getSimpleName(),_state);
+ return String.format("%s{s=%s}", getClass().getSimpleName(), _state);
}
-
+
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
@@ -724,43 +665,45 @@ public class MultiPartParser
*/
public interface Handler
{
- public default void startPart()
+ default void startPart()
{
}
-
- public default void parsedField(String name, String value)
+
+ @SuppressWarnings("unused")
+ default void parsedField(String name, String value)
{
}
-
- public default boolean headerComplete()
+
+ default boolean headerComplete()
{
return false;
}
-
- public default boolean content(ByteBuffer item, boolean last)
+
+ @SuppressWarnings("unused")
+ default boolean content(ByteBuffer item, boolean last)
{
return false;
}
-
- public default boolean messageComplete()
+
+ default boolean messageComplete()
{
return false;
}
-
- public default void earlyEOF()
+
+ default void earlyEOF()
{
}
}
-
+
/* ------------------------------------------------------------------------------- */
@SuppressWarnings("serial")
private static class IllegalCharacterException extends IllegalArgumentException
{
private IllegalCharacterException(State state, byte ch, ByteBuffer buffer)
{
- super(String.format("Illegal character 0x%X",ch));
+ super(String.format("Illegal character 0x%X", ch));
// Bug #460642 - don't reveal buffers to end user
- LOG.warn(String.format("Illegal character 0x%X in state=%s for buffer %s",ch,state,BufferUtil.toDetailString(buffer)));
+ LOG.warn(String.format("Illegal character 0x%X in state=%s for buffer %s", ch, state, BufferUtil.toDetailString(buffer)));
}
}
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormInputStreamTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormInputStreamTest.java
index c12109383a7..4689b743407 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormInputStreamTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartFormInputStreamTest.java
@@ -24,7 +24,6 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
@@ -41,148 +40,142 @@ import java.util.concurrent.TimeUnit;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ReadListener;
-import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
import org.eclipse.jetty.http.MultiPartFormInputStream.MultiPart;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.IO;
-import org.hamcrest.Matchers;
import org.junit.Test;
/**
* MultiPartInputStreamTest
- *
- *
*/
public class MultiPartFormInputStreamTest
{
private static final String FILENAME = "stuff.txt";
protected String _contentType = "multipart/form-data, boundary=AaB03x";
protected String _multi = createMultipartRequestString(FILENAME);
- protected String _dirname = System.getProperty("java.io.tmpdir")+File.separator+"myfiles-"+TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+ protected String _dirname = System.getProperty("java.io.tmpdir") + File.separator + "myfiles-" + TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
protected File _tmpDir = new File(_dirname);
- public MultiPartFormInputStreamTest ()
+ public MultiPartFormInputStreamTest()
{
_tmpDir.deleteOnExit();
}
@Test
public void testBadMultiPartRequest()
- throws Exception
+ throws Exception
{
String boundary = "X0Y0";
- String str = "--" + boundary + "\r\n"+
- "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+
- "Content-Type: application/octet-stream\r\n\r\n"+
- "How now brown cow."+
- "\r\n--" + boundary + "-\r\n"
+ String str = "--" + boundary + "\r\n" +
+ "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n" +
+ "Content-Type: application/octet-stream\r\n\r\n" +
+ "How now brown cow." +
+ "\r\n--" + boundary + "-\r\n"
+ "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"
+ "\r\n";
-
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- "multipart/form-data, boundary="+boundary,
- config,
- _tmpDir);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
+ "multipart/form-data, boundary=" + boundary,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
{
mpis.getParts();
- fail ("Incomplete Multipart");
+ fail("Incomplete Multipart");
}
catch (IOException e)
{
assertTrue(e.getMessage().startsWith("Incomplete"));
}
}
-
-
+
+
@Test
public void testFinalBoundaryOnly()
- throws Exception
+ throws Exception
{
String delimiter = "\r\n";
final String boundary = "MockMultiPartTestBoundary";
-
-
+
+
// Malformed multipart request body containing only an arbitrary string of text, followed by the final boundary marker, delimited by empty lines.
String str =
delimiter +
- "Hello world" +
- delimiter + // Two delimiter markers, which make an empty line.
- delimiter +
- "--" + boundary + "--" + delimiter;
-
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- "multipart/form-data, boundary="+boundary,
- config,
- _tmpDir);
- mpis.setDeleteOnExit(true);
- Collection parts = mpis.getParts();
- assertTrue(mpis.getParts().isEmpty());
- }
-
-
-
- @Test
- public void testEmpty()
- throws Exception
- {
- String delimiter = "\r\n";
- final String boundary = "MockMultiPartTestBoundary";
-
- String str =
- delimiter +
- "--" + boundary + "--" + delimiter;
-
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- "multipart/form-data, boundary="+boundary,
- config,
- _tmpDir);
- mpis.setDeleteOnExit(true);
- assertTrue(mpis.getParts().isEmpty());
- }
-
- @Test
- public void testNoBoundaryRequest()
- throws Exception
- {
- String str = "--\r\n"+
- "Content-Disposition: form-data; name=\"fileName\"\r\n"+
- "Content-Type: text/plain; charset=US-ASCII\r\n"+
- "Content-Transfer-Encoding: 8bit\r\n"+
- "\r\n"+
- "abc\r\n"+
- "--\r\n"+
- "Content-Disposition: form-data; name=\"desc\"\r\n"+
- "Content-Type: text/plain; charset=US-ASCII\r\n"+
- "Content-Transfer-Encoding: 8bit\r\n"+
- "\r\n"+
- "123\r\n"+
- "--\r\n"+
- "Content-Disposition: form-data; name=\"title\"\r\n"+
- "Content-Type: text/plain; charset=US-ASCII\r\n"+
- "Content-Transfer-Encoding: 8bit\r\n"+
- "\r\n"+
- "ttt\r\n"+
- "--\r\n"+
- "Content-Disposition: form-data; name=\"datafile5239138112980980385.txt\"; filename=\"datafile5239138112980980385.txt\"\r\n"+
- "Content-Type: application/octet-stream; charset=ISO-8859-1\r\n"+
- "Content-Transfer-Encoding: binary\r\n"+
- "\r\n"+
- "000\r\n"+
- "----\r\n";
+ "Hello world" +
+ delimiter + // Two delimiter markers, which make an empty line.
+ delimiter +
+ "--" + boundary + "--" + delimiter;
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- "multipart/form-data",
- config,
- _tmpDir);
+ "multipart/form-data, boundary=" + boundary,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ assertTrue(mpis.getParts().isEmpty());
+ }
+
+
+ @Test
+ public void testEmpty()
+ throws Exception
+ {
+ String delimiter = "\r\n";
+ final String boundary = "MockMultiPartTestBoundary";
+
+ String str =
+ delimiter +
+ "--" + boundary + "--" + delimiter;
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
+ "multipart/form-data, boundary=" + boundary,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ assertTrue(mpis.getParts().isEmpty());
+ }
+
+ @Test
+ public void testNoBoundaryRequest()
+ throws Exception
+ {
+ String str = "--\r\n" +
+ "Content-Disposition: form-data; name=\"fileName\"\r\n" +
+ "Content-Type: text/plain; charset=US-ASCII\r\n" +
+ "Content-Transfer-Encoding: 8bit\r\n" +
+ "\r\n" +
+ "abc\r\n" +
+ "--\r\n" +
+ "Content-Disposition: form-data; name=\"desc\"\r\n" +
+ "Content-Type: text/plain; charset=US-ASCII\r\n" +
+ "Content-Transfer-Encoding: 8bit\r\n" +
+ "\r\n" +
+ "123\r\n" +
+ "--\r\n" +
+ "Content-Disposition: form-data; name=\"title\"\r\n" +
+ "Content-Type: text/plain; charset=US-ASCII\r\n" +
+ "Content-Transfer-Encoding: 8bit\r\n" +
+ "\r\n" +
+ "ttt\r\n" +
+ "--\r\n" +
+ "Content-Disposition: form-data; name=\"datafile5239138112980980385.txt\"; filename=\"datafile5239138112980980385.txt\"\r\n" +
+ "Content-Type: application/octet-stream; charset=ISO-8859-1\r\n" +
+ "Content-Transfer-Encoding: binary\r\n" +
+ "\r\n" +
+ "000\r\n" +
+ "----\r\n";
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
+ "multipart/form-data",
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(4));
@@ -193,7 +186,7 @@ public class MultiPartFormInputStreamTest
assertThat(fileName.getSize(), is(3L));
IO.copy(fileName.getInputStream(), baos);
assertThat(baos.toString("US-ASCII"), is("abc"));
-
+
baos = new ByteArrayOutputStream();
Part desc = mpis.getPart("desc");
assertThat(desc, notNullValue());
@@ -206,101 +199,32 @@ public class MultiPartFormInputStreamTest
assertThat(title, notNullValue());
assertThat(title.getSize(), is(3L));
IO.copy(title.getInputStream(), baos);
- assertThat(baos.toString("US-ASCII"), is("ttt"));
+ assertThat(baos.toString("US-ASCII"), is("ttt"));
}
-
+
@Test
public void testNonMultiPartRequest()
- throws Exception
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- "Content-type: text/plain",
- config,
- _tmpDir);
+ "Content-type: text/plain",
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
assertTrue(mpis.getParts().isEmpty());
}
-
+
@Test
public void testNoBody()
- throws Exception
- {
- String body = "";
-
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(body.getBytes()),
- _contentType,
- config,
- _tmpDir);
- mpis.setDeleteOnExit(true);
- try
- {
- mpis.getParts();
- fail ("Missing initial multi part boundary");
- }
- catch (IOException e)
- {
- assertTrue(e.getMessage().contains("Missing initial multi part boundary"));
- }
- }
-
-
- @Test
- public void testBodyAlreadyConsumed()
- throws Exception
{
- ServletInputStream is = new ServletInputStream() {
-
- @Override
- public boolean isFinished()
- {
- return true;
- }
-
- @Override
- public boolean isReady()
- {
- return false;
- }
-
- @Override
- public void setReadListener(ReadListener readListener)
- {
- }
-
- @Override
- public int read() throws IOException
- {
- return 0;
- }
-
- };
+ String body = "";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(is,
- _contentType,
- config,
- _tmpDir);
- mpis.setDeleteOnExit(true);
- Collection parts = mpis.getParts();
- assertEquals(0, parts.size());
- }
-
-
-
- @Test
- public void testWhitespaceBodyWithCRLF()
- throws Exception
- {
- String whitespace = " \n\n\n\r\n\r\n\r\n\r\n";
-
-
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(whitespace.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(body.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
{
@@ -312,55 +236,120 @@ public class MultiPartFormInputStreamTest
assertTrue(e.getMessage().contains("Missing initial multi part boundary"));
}
}
-
+
+
@Test
- public void testWhitespaceBody()
+ public void testBodyAlreadyConsumed()
throws Exception
+ {
+ ServletInputStream is = new ServletInputStream()
+ {
+
+ @Override
+ public boolean isFinished()
{
- String whitespace = " ";
-
+ return true;
+ }
+
+ @Override
+ public boolean isReady()
+ {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener)
+ {
+ }
+
+ @Override
+ public int read()
+ {
+ return 0;
+ }
+
+ };
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(whitespace.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(is,
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection parts = mpis.getParts();
+ assertEquals(0, parts.size());
+ }
+
+
+ @Test
+ public void testWhitespaceBodyWithCRLF()
+ {
+ String whitespace = " \n\n\n\r\n\r\n\r\n\r\n";
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(whitespace.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
{
mpis.getParts();
- fail ("Multipart missing body");
+ fail("Missing initial multi part boundary");
+ }
+ catch (IOException e)
+ {
+ assertTrue(e.getMessage().contains("Missing initial multi part boundary"));
+ }
+ }
+
+ @Test
+ public void testWhitespaceBody()
+ {
+ String whitespace = " ";
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(whitespace.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ try
+ {
+ mpis.getParts();
+ fail("Multipart missing body");
}
catch (IOException e)
{
assertTrue(e.getMessage().startsWith("Missing initial"));
}
}
-
+
@Test
public void testLeadingWhitespaceBodyWithCRLF()
- throws Exception
+ throws Exception
{
- String body = " \n\n\n\r\n\r\n\r\n\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"\r\n"+
- "\r\n"+
- "Joe Blow\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" + "foo.txt" + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"aaaa"+
- "bbbbb"+"\r\n" +
+ String body = " \n\n\n\r\n\r\n\r\n\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"\r\n" +
+ "\r\n" +
+ "Joe Blow\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + "foo.txt" + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "aaaa" +
+ "bbbbb" + "\r\n" +
"--AaB03x--\r\n";
-
-
+
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(body.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
-
- Collection parts = mpis.getParts();
+
+ Collection parts = mpis.getParts();
assertThat(parts, notNullValue());
assertThat(parts.size(), is(2));
Part field1 = mpis.getPart("field1");
@@ -376,71 +365,65 @@ public class MultiPartFormInputStreamTest
assertTrue(baos.toString("US-ASCII").contains("aaaa"));
}
-
-
+
@Test
public void testLeadingWhitespaceBodyWithoutCRLF()
throws Exception
- {
- String body = " "+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"\r\n"+
- "\r\n"+
- "Joe Blow\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" + "foo.txt" + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"aaaa"+
- "bbbbb"+"\r\n" +
+ {
+ String body = " " +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"\r\n" +
+ "\r\n" +
+ "Joe Blow\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + "foo.txt" + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "aaaa" +
+ "bbbbb" + "\r\n" +
"--AaB03x--\r\n";
-
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(body.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
-
- Collection parts = mpis.getParts();
+
+ Collection parts = mpis.getParts();
assertThat(parts, notNullValue());
assertThat(parts.size(), is(1));
-
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Part stuff = mpis.getPart("stuff");
assertThat(stuff, notNullValue());
- baos = new ByteArrayOutputStream();
IO.copy(stuff.getInputStream(), baos);
assertTrue(baos.toString("US-ASCII").contains("bbbbb"));
}
-
-
-
-
@Test
public void testNoLimits()
- throws Exception
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertFalse(parts.isEmpty());
}
-
+
@Test
- public void testRequestTooBig ()
- throws Exception
+ public void testRequestTooBig()
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
@@ -456,21 +439,20 @@ public class MultiPartFormInputStreamTest
@Test
- public void testRequestTooBigThrowsErrorOnGetParts ()
- throws Exception
+ public void testRequestTooBigThrowsErrorOnGetParts()
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
- Collection parts = null;
//cause parsing
try
{
- parts = mpis.getParts();
+ mpis.getParts();
fail("Request should have exceeded maxRequestSize");
}
catch (IllegalStateException e)
@@ -481,7 +463,7 @@ public class MultiPartFormInputStreamTest
//try again
try
{
- parts = mpis.getParts();
+ mpis.getParts();
fail("Request should have exceeded maxRequestSize");
}
catch (IllegalStateException e)
@@ -489,21 +471,20 @@ public class MultiPartFormInputStreamTest
assertTrue(e.getMessage().startsWith("Request exceeds maxRequestSize"));
}
}
-
+
@Test
public void testFileTooBig()
- throws Exception
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
- Collection parts = null;
try
{
- parts = mpis.getParts();
+ mpis.getParts();
fail("stuff.txt should have been larger than maxFileSize");
}
catch (IllegalStateException e)
@@ -514,18 +495,17 @@ public class MultiPartFormInputStreamTest
@Test
public void testFileTooBigThrowsErrorOnGetParts()
- throws Exception
+ throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
- Collection parts = null;
try
{
- parts = mpis.getParts(); //caused parsing
+ mpis.getParts(); //caused parsing
fail("stuff.txt should have been larger than maxFileSize");
}
catch (Throwable e)
@@ -536,7 +516,7 @@ public class MultiPartFormInputStreamTest
//test again after the parsing
try
{
- parts = mpis.getParts(); //caused parsing
+ mpis.getParts(); //caused parsing
fail("stuff.txt should have been larger than maxFileSize");
}
catch (IllegalStateException e)
@@ -546,23 +526,22 @@ public class MultiPartFormInputStreamTest
}
-
@Test
- public void testPartFileNotDeleted () throws Exception
+ public void testPartFileNotDeleted() throws Exception
{
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(createMultipartRequestString("tptfd").getBytes()),
_contentType,
config,
_tmpDir);
mpis.setDeleteOnExit(true);
- Collection parts = mpis.getParts();
+ mpis.getParts();
MultiPart part = (MultiPart)mpis.getPart("stuff");
- File stuff = ((MultiPartFormInputStream.MultiPart)part).getFile();
- assertThat(stuff,notNullValue()); // longer than 100 bytes, should already be a tmp file
+ File stuff = part.getFile();
+ assertThat(stuff, notNullValue()); // longer than 100 bytes, should already be a tmp file
part.write("tptfd.txt");
- File tptfd = new File (_dirname+File.separator+"tptfd.txt");
+ File tptfd = new File(_dirname + File.separator + "tptfd.txt");
assertThat(tptfd.exists(), is(true));
assertThat(stuff.exists(), is(false)); //got renamed
part.cleanUp();
@@ -571,127 +550,125 @@ public class MultiPartFormInputStreamTest
}
@Test
- public void testPartTmpFileDeletion () throws Exception
+ public void testPartTmpFileDeletion() throws Exception
{
- MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(createMultipartRequestString("tptfd").getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
- Collection parts = mpis.getParts();
-
+ mpis.getParts();
+
MultiPart part = (MultiPart)mpis.getPart("stuff");
- File stuff = ((MultiPartFormInputStream.MultiPart)part).getFile();
- assertThat(stuff,notNullValue()); // longer than 100 bytes, should already be a tmp file
- assertThat (stuff.exists(), is(true));
+ File stuff = part.getFile();
+ assertThat(stuff, notNullValue()); // longer than 100 bytes, should already be a tmp file
+ assertThat(stuff.exists(), is(true));
part.cleanUp();
assertThat(stuff.exists(), is(false)); //tmp file was removed after cleanup
}
@Test
public void testLFOnlyRequest()
- throws Exception
+ throws Exception
{
- String str = "--AaB03x\n"+
- "content-disposition: form-data; name=\"field1\"\n"+
- "\n"+
- "Joe Blow"+
- "\r\n--AaB03x\n"+
- "content-disposition: form-data; name=\"field2\"\n"+
- "\n"+
- "Other"+
+ String str = "--AaB03x\n" +
+ "content-disposition: form-data; name=\"field1\"\n" +
+ "\n" +
+ "Joe Blow" +
+ "\r\n--AaB03x\n" +
+ "content-disposition: form-data; name=\"field2\"\n" +
+ "\n" +
+ "Other" +
"\r\n--AaB03x--\n";
-
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(2));
Part p1 = mpis.getPart("field1");
- assertThat(p1, notNullValue());
+ assertThat(p1, notNullValue());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IO.copy(p1.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("Joe Blow"));
-
+
Part p2 = mpis.getPart("field2");
assertThat(p2, notNullValue());
baos = new ByteArrayOutputStream();
IO.copy(p2.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("Other"));
-
-
+
+
}
@Test
public void testCROnlyRequest()
- throws Exception
{
- String str = "--AaB03x\r"+
- "content-disposition: form-data; name=\"field1\"\r"+
- "\r"+
- "Joe Blow\r"+
- "--AaB03x\r"+
- "content-disposition: form-data; name=\"field2\"\r"+
- "\r"+
- "Other\r"+
- "--AaB03x--\r";
-
+ String str = "--AaB03x\r" +
+ "content-disposition: form-data; name=\"field1\"\r" +
+ "\r" +
+ "Joe Blow\r" +
+ "--AaB03x\r" +
+ "content-disposition: form-data; name=\"field2\"\r" +
+ "\r" +
+ "Other\r" +
+ "--AaB03x--\r";
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
{
Collection parts = mpis.getParts();
assertThat(parts.size(), is(2));
-
+
assertThat(parts.size(), is(2));
Part p1 = mpis.getPart("field1");
assertThat(p1, notNullValue());
-
+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IO.copy(p1.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("Joe Blow"));
-
+
Part p2 = mpis.getPart("field2");
assertThat(p2, notNullValue());
baos = new ByteArrayOutputStream();
IO.copy(p2.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("Other"));
}
- catch(Throwable e)
+ catch (Throwable e)
{
assertTrue(e.getMessage().contains("Bad EOL"));
}
}
-
+
@Test
public void testCRandLFMixRequest()
- throws Exception
{
- String str = "--AaB03x\r"+
- "content-disposition: form-data; name=\"field1\"\r"+
- "\r"+
- "\nJoe Blow\n"+
- "\r"+
- "--AaB03x\r"+
- "content-disposition: form-data; name=\"field2\"\r"+
- "\r"+
- "Other\r"+
+ String str = "--AaB03x\r" +
+ "content-disposition: form-data; name=\"field1\"\r" +
+ "\r" +
+ "\nJoe Blow\n" +
+ "\r" +
+ "--AaB03x\r" +
+ "content-disposition: form-data; name=\"field2\"\r" +
+ "\r" +
+ "Other\r" +
"--AaB03x--\r";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
@@ -699,9 +676,9 @@ public class MultiPartFormInputStreamTest
{
Collection parts = mpis.getParts();
assertThat(parts.size(), is(2));
-
+
Part p1 = mpis.getPart("field1");
- assertThat(p1, notNullValue());
+ assertThat(p1, notNullValue());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IO.copy(p1.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("\nJoe Blow\n"));
@@ -712,56 +689,56 @@ public class MultiPartFormInputStreamTest
IO.copy(p2.getInputStream(), baos);
assertThat(baos.toString("UTF-8"), is("Other"));
}
- catch(Throwable e)
+ catch (Throwable e)
{
assertTrue(e.getMessage().contains("Bad EOL"));
}
}
@Test
- public void testBufferOverflowNoCRLF () throws Exception
+ public void testBufferOverflowNoCRLF() throws Exception
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("--AaB03x\r\n".getBytes());
- for (int i=0; i< 3000; i++) //create content that will overrun default buffer size of BufferedInputStream
+ for (int i = 0; i < 3000; i++) //create content that will overrun default buffer size of BufferedInputStream
{
baos.write('a');
}
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(baos.toByteArray()),
- _contentType,
- config,
- _tmpDir);
+ MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(baos.toByteArray()),
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
try
{
mpis.getParts();
- fail ("Header Line Exceeded Max Length");
+ fail("Header Line Exceeded Max Length");
}
catch (Throwable e)
{
assertTrue(e.getMessage().startsWith("Header Line Exceeded Max Length"));
}
-
+
}
@Test
- public void testCharsetEncoding () throws Exception
+ public void testCharsetEncoding() throws Exception
{
String contentType = "multipart/form-data; boundary=TheBoundary; charset=ISO-8859-1";
- String str = "--TheBoundary\r\n"+
- "content-disposition: form-data; name=\"field1\"\r\n"+
- "\r\n"+
- "\nJoe Blow\n"+
- "\r\n"+
+ String str = "--TheBoundary\r\n" +
+ "content-disposition: form-data; name=\"field1\"\r\n" +
+ "\r\n" +
+ "\nJoe Blow\n" +
+ "\r\n" +
"--TheBoundary--\r\n";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(str.getBytes()),
- contentType,
- config,
- _tmpDir);
+ contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(1));
@@ -772,107 +749,101 @@ public class MultiPartFormInputStreamTest
public void testBadlyEncodedFilename() throws Exception
{
- String contents = "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" +"Taken on Aug 22 \\ 2012.jpg" + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"stuff"+
- "aaa"+"\r\n" +
- "--AaB03x--\r\n";
+ String contents = "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + "Taken on Aug 22 \\ 2012.jpg" + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "stuff" +
+ "aaa" + "\r\n" +
+ "--AaB03x--\r\n";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(contents.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(1));
- assertThat(((MultiPartFormInputStream.MultiPart)parts.iterator().next()).getSubmittedFileName(), is("Taken on Aug 22 \\ 2012.jpg"));
+ assertThat(parts.iterator().next().getSubmittedFileName(), is("Taken on Aug 22 \\ 2012.jpg"));
}
@Test
public void testBadlyEncodedMSFilename() throws Exception
{
- String contents = "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" +"c:\\this\\really\\is\\some\\path\\to\\a\\file.txt" + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"stuff"+
- "aaa"+"\r\n" +
- "--AaB03x--\r\n";
+ String contents = "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + "c:\\this\\really\\is\\some\\path\\to\\a\\file.txt" + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "stuff" +
+ "aaa" + "\r\n" +
+ "--AaB03x--\r\n";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(contents.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(1));
- assertThat(((MultiPartFormInputStream.MultiPart)parts.iterator().next()).getSubmittedFileName(), is("c:\\this\\really\\is\\some\\path\\to\\a\\file.txt"));
+ assertThat(parts.iterator().next().getSubmittedFileName(), is("c:\\this\\really\\is\\some\\path\\to\\a\\file.txt"));
}
-
+
@Test
public void testCorrectlyEncodedMSFilename() throws Exception
{
- String contents = "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" +"c:\\\\this\\\\really\\\\is\\\\some\\\\path\\\\to\\\\a\\\\file.txt" + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"stuff"+
- "aaa"+"\r\n" +
- "--AaB03x--\r\n";
+ String contents = "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + "c:\\\\this\\\\really\\\\is\\\\some\\\\path\\\\to\\\\a\\\\file.txt" + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "stuff" +
+ "aaa" + "\r\n" +
+ "--AaB03x--\r\n";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(contents.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(1));
- assertThat(((MultiPartFormInputStream.MultiPart)parts.iterator().next()).getSubmittedFileName(), is("c:\\this\\really\\is\\some\\path\\to\\a\\file.txt"));
+ assertThat(parts.iterator().next().getSubmittedFileName(), is("c:\\this\\really\\is\\some\\path\\to\\a\\file.txt"));
}
- public void testMulti ()
- throws Exception
- {
- testMulti(FILENAME);
- }
-
@Test
public void testMultiWithSpaceInFilename() throws Exception
{
testMulti("stuff with spaces.txt");
}
-
+
@Test
- public void testWriteFilesIfContentDispositionFilename ()
- throws Exception
+ public void testWriteFilesIfContentDispositionFilename()
+ throws Exception
{
- String s = "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"; filename=\"frooble.txt\"\r\n"+
- "\r\n"+
- "Joe Blow\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+"sss"+
- "aaa"+"\r\n" +
+ String s = "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"; filename=\"frooble.txt\"\r\n" +
+ "\r\n" +
+ "Joe Blow\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + "sss" +
+ "aaa" + "\r\n" +
"--AaB03x--\r\n";
//all default values for multipartconfig, ie file size threshold 0
MultipartConfigElement config = new MultipartConfigElement(_dirname);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(s.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
mpis.setWriteFilesWithFilenames(true);
Collection parts = mpis.getParts();
assertThat(parts.size(), is(2));
Part field1 = mpis.getPart("field1"); //has a filename, should be written to a file
File f = ((MultiPartFormInputStream.MultiPart)field1).getFile();
- assertThat(f,notNullValue()); // longer than 100 bytes, should already be a tmp file
+ assertThat(f, notNullValue()); // longer than 100 bytes, should already be a tmp file
Part stuff = mpis.getPart("stuff");
f = ((MultiPartFormInputStream.MultiPart)stuff).getFile(); //should only be in memory, no filename
@@ -880,7 +851,7 @@ public class MultiPartFormInputStreamTest
}
- private void testMulti(String filename) throws IOException, ServletException, InterruptedException
+ private void testMulti(String filename) throws IOException
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(createMultipartRequestString(filename).getBytes()),
@@ -891,126 +862,129 @@ public class MultiPartFormInputStreamTest
Collection parts = mpis.getParts();
assertThat(parts.size(), is(2));
Part field1 = mpis.getPart("field1"); //field 1 too small to go into tmp file, should be in internal buffer
- assertThat(field1,notNullValue());
- assertThat(field1.getName(),is("field1"));
- InputStream is = field1.getInputStream();
+ assertThat(field1, notNullValue());
+ assertThat(field1.getName(), is("field1"));
+
ByteArrayOutputStream os = new ByteArrayOutputStream();
- IO.copy(is, os);
+ try (InputStream is = field1.getInputStream())
+ {
+ IO.copy(is, os);
+ }
assertEquals("Joe Blow", new String(os.toByteArray()));
assertEquals(8, field1.getSize());
-
+
assertNotNull(((MultiPartFormInputStream.MultiPart)field1).getBytes());//in internal buffer
field1.write("field1.txt");
assertNull(((MultiPartFormInputStream.MultiPart)field1).getBytes());//no longer in internal buffer
- File f = new File (_dirname+File.separator+"field1.txt");
+ File f = new File(_dirname + File.separator + "field1.txt");
assertTrue(f.exists());
field1.write("another_field1.txt"); //write after having already written
- File f2 = new File(_dirname+File.separator+"another_field1.txt");
+ File f2 = new File(_dirname + File.separator + "another_field1.txt");
assertTrue(f2.exists());
assertFalse(f.exists()); //should have been renamed
field1.delete(); //file should be deleted
assertFalse(f.exists()); //original file was renamed
assertFalse(f2.exists()); //2nd written file was explicitly deleted
-
+
MultiPart stuff = (MultiPart)mpis.getPart("stuff");
assertThat(stuff.getSubmittedFileName(), is(filename));
- assertThat(stuff.getContentType(),is("text/plain"));
- assertThat(stuff.getHeader("Content-Type"),is("text/plain"));
- assertThat(stuff.getHeaders("content-type").size(),is(1));
- assertThat(stuff.getHeader("content-disposition"),is("form-data; name=\"stuff\"; filename=\"" + filename + "\""));
- assertThat(stuff.getHeaderNames().size(),is(2));
- assertThat(stuff.getSize(),is(51L));
+ assertThat(stuff.getContentType(), is("text/plain"));
+ assertThat(stuff.getHeader("Content-Type"), is("text/plain"));
+ assertThat(stuff.getHeaders("content-type").size(), is(1));
+ assertThat(stuff.getHeader("content-disposition"), is("form-data; name=\"stuff\"; filename=\"" + filename + "\""));
+ assertThat(stuff.getHeaderNames().size(), is(2));
+ assertThat(stuff.getSize(), is(51L));
- File tmpfile = ((MultiPartFormInputStream.MultiPart)stuff).getFile();
- assertThat(tmpfile,notNullValue()); // longer than 50 bytes, should already be a tmp file
- assertThat(stuff.getBytes(),nullValue()); //not in an internal buffer
- assertThat(tmpfile.exists(),is(true));
- assertThat(tmpfile.getName(),is(not("stuff with space.txt")));
+ File tmpfile = stuff.getFile();
+ assertThat(tmpfile, notNullValue()); // longer than 50 bytes, should already be a tmp file
+ assertThat(stuff.getBytes(), nullValue()); //not in an internal buffer
+ assertThat(tmpfile.exists(), is(true));
+ assertThat(tmpfile.getName(), is(not("stuff with space.txt")));
stuff.write(filename);
- f = new File(_dirname+File.separator+filename);
- assertThat(f.exists(),is(true));
+ f = new File(_dirname + File.separator + filename);
+ assertThat(f.exists(), is(true));
assertThat(tmpfile.exists(), is(false));
try
{
- stuff.getInputStream();
+ stuff.getInputStream();
}
catch (Exception e)
{
- fail("Part.getInputStream() after file rename operation");
+ fail("Part.getInputStream() after file rename operation: " + e.getMessage());
}
f.deleteOnExit(); //clean up after test
}
-
+
@Test
- public void testMultiSameNames ()
- throws Exception
+ public void testMultiSameNames()
+ throws Exception
{
- String sameNames = "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"stuff1.txt\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "00000\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"stuff2.txt\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "110000000000000000000000000000000000000000000000000\r\n"+
- "--AaB03x--\r\n";
-
+ String sameNames = "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"stuff1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "00000\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"stuff2.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "110000000000000000000000000000000000000000000000000\r\n" +
+ "--AaB03x--\r\n";
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(sameNames.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertEquals(2, parts.size());
- for (Part p:parts)
+ for (Part p : parts)
assertEquals("stuff", p.getName());
-
+
//if they all have the name name, then only retrieve the first one
Part p = mpis.getPart("stuff");
assertNotNull(p);
assertEquals(5, p.getSize());
}
-
+
@Test
- public void testBase64EncodedContent () throws Exception
+ public void testBase64EncodedContent() throws Exception
{
String contentWithEncodedPart =
- "--AaB03x\r\n"+
- "Content-disposition: form-data; name=\"other\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "other" + "\r\n"+
- "--AaB03x\r\n"+
- "Content-disposition: form-data; name=\"stuff\"; filename=\"stuff.txt\"\r\n"+
- "Content-Transfer-Encoding: base64\r\n"+
- "Content-Type: application/octet-stream\r\n"+
- "\r\n"+
- B64Code.encode("hello jetty") + "\r\n"+
- "--AaB03x\r\n"+
- "Content-disposition: form-data; name=\"final\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "the end" + "\r\n"+
+ "--AaB03x\r\n" +
+ "Content-disposition: form-data; name=\"other\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "other" + "\r\n" +
+ "--AaB03x\r\n" +
+ "Content-disposition: form-data; name=\"stuff\"; filename=\"stuff.txt\"\r\n" +
+ "Content-Transfer-Encoding: base64\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n" +
+ B64Code.encode("hello jetty") + "\r\n" +
+ "--AaB03x\r\n" +
+ "Content-disposition: form-data; name=\"final\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "the end" + "\r\n" +
"--AaB03x--\r\n";
-
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(contentWithEncodedPart.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertEquals(3, parts.size());
-
+
Part p1 = mpis.getPart("other");
assertNotNull(p1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IO.copy(p1.getInputStream(), baos);
assertEquals("other", baos.toString("US-ASCII"));
-
+
Part p2 = mpis.getPart("stuff");
assertNotNull(p2);
baos = new ByteArrayOutputStream();
@@ -1025,70 +999,70 @@ public class MultiPartFormInputStreamTest
}
@Test
- public void testQuotedPrintableEncoding () throws Exception
+ public void testQuotedPrintableEncoding() throws Exception
{
- String contentWithEncodedPart =
- "--AaB03x\r\n"+
- "Content-disposition: form-data; name=\"other\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "other" + "\r\n"+
- "--AaB03x\r\n"+
- "Content-disposition: form-data; name=\"stuff\"; filename=\"stuff.txt\"\r\n"+
- "Content-Transfer-Encoding: quoted-printable\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "truth=3Dbeauty" + "\r\n"+
- "--AaB03x--\r\n";
+ String contentWithEncodedPart =
+ "--AaB03x\r\n" +
+ "Content-disposition: form-data; name=\"other\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "other" + "\r\n" +
+ "--AaB03x\r\n" +
+ "Content-disposition: form-data; name=\"stuff\"; filename=\"stuff.txt\"\r\n" +
+ "Content-Transfer-Encoding: quoted-printable\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "truth=3Dbeauty" + "\r\n" +
+ "--AaB03x--\r\n";
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(contentWithEncodedPart.getBytes()),
- _contentType,
- config,
- _tmpDir);
+ _contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
Collection parts = mpis.getParts();
assertEquals(2, parts.size());
-
+
Part p1 = mpis.getPart("other");
assertNotNull(p1);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IO.copy(p1.getInputStream(), baos);
assertEquals("other", baos.toString("US-ASCII"));
-
+
Part p2 = mpis.getPart("stuff");
assertNotNull(p2);
baos = new ByteArrayOutputStream();
IO.copy(p2.getInputStream(), baos);
assertEquals("truth=3Dbeauty", baos.toString("US-ASCII"));
}
-
-
+
+
@Test
public void testGeneratedForm()
- throws Exception
+ throws Exception
{
String contentType = "multipart/form-data, boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW";
- String body = "Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
- "\r\n" +
- "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
- "Content-Disposition: form-data; name=\"part1\"\r\n" +
- "\n" +
- "wNfミxVamt\r\n" +
- "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\n" +
- "Content-Disposition: form-data; name=\"part2\"\r\n" +
- "\r\n" +
- "&ᄈ취ᅢO\r\n" +
+ String body = "Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
+ "\r\n" +
+ "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
+ "Content-Disposition: form-data; name=\"part1\"\r\n" +
+ "\n" +
+ "wNfミxVamt\r\n" +
+ "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\n" +
+ "Content-Disposition: form-data; name=\"part2\"\r\n" +
+ "\r\n" +
+ "&ᄈ취ᅢO\r\n" +
"--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW--";
-
-
+
+
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(body.getBytes()),
- contentType,
- config,
- _tmpDir);
+ contentType,
+ config,
+ _tmpDir);
mpis.setDeleteOnExit(true);
-
- Collection parts = mpis.getParts();
+
+ Collection parts = mpis.getParts();
assertThat(parts, notNullValue());
assertThat(parts.size(), is(2));
@@ -1097,15 +1071,15 @@ public class MultiPartFormInputStreamTest
Part part2 = mpis.getPart("part2");
assertThat(part2, notNullValue());
}
-
- private String createMultipartRequestString(String filename)
+
+ private static String createMultipartRequestString(String filename)
{
int length = filename.length();
String name = filename;
if (length > 10)
- name = filename.substring(0,10);
- StringBuffer filler = new StringBuffer();
+ name = filename.substring(0, 10);
+ StringBuilder filler = new StringBuilder();
int i = name.length();
while (i < 51)
{
@@ -1113,15 +1087,15 @@ public class MultiPartFormInputStreamTest
i++;
}
- return "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"; filename=\"frooble.txt\"\r\n"+
- "\r\n"+
- "Joe Blow\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"" + filename + "\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+name+
- filler.toString()+"\r\n" +
- "--AaB03x--\r\n";
+ return "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"; filename=\"frooble.txt\"\r\n" +
+ "\r\n" +
+ "Joe Blow\r\n" +
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + filename + "\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" + name +
+ filler.toString() + "\r\n" +
+ "--AaB03x--\r\n";
}
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartParserTest.java
index 009be1af293..40dc519f14e 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartParserTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/MultiPartParserTest.java
@@ -35,119 +35,127 @@ import org.junit.Test;
public class MultiPartParserTest
{
-
+
@Test
public void testEmptyPreamble()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
ByteBuffer data = BufferUtil.toBuffer("");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
}
-
+
@Test
public void testNoPreamble()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY \r\n");
- data = BufferUtil.toBuffer("--BOUNDARY \r\n");
- parser.parse(data,false);
+ parser.parse(data, false);
assertTrue(parser.isState(State.BODY_PART));
- assertThat(data.remaining(),is(0));
+ assertThat(data.remaining(), is(0));
}
@Test
public void testPreamble()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
ByteBuffer data;
data = BufferUtil.toBuffer("This is not part of a part\r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("More data that almost includes \n--BOUNDARY but no CR before.");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("Could be a boundary \r\n--BOUNDAR");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("but not it isn't \r\n--BOUN");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("DARX nor is this");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
}
-
+
@Test
public void testPreambleCompleteBoundary()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
- ByteBuffer data;
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
+ ByteBuffer data = BufferUtil.toBuffer("This is not part of a part\r\n--BOUNDARY \r\n");
- data = BufferUtil.toBuffer("This is not part of a part\r\n--BOUNDARY \r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.BODY_PART));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.BODY_PART));
+ assertThat(data.remaining(), is(0));
}
@Test
public void testPreambleSplitBoundary()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
- ByteBuffer data;
-
- data = BufferUtil.toBuffer("This is not part of a part\r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
+ ByteBuffer data = BufferUtil.toBuffer("This is not part of a part\r\n");
+
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("-");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("-");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("B");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.PREAMBLE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.PREAMBLE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("OUNDARY-");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.DELIMITER_CLOSE));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.DELIMITER_CLOSE));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("ignore\r");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.DELIMITER_PADDING));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.DELIMITER_PADDING));
+ assertThat(data.remaining(), is(0));
data = BufferUtil.toBuffer("\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.BODY_PART));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.BODY_PART));
+ assertThat(data.remaining(), is(0));
}
-
+
@Test
public void testFirstPartNoFields()
{
- MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler(){},"BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
+ MultiPartParser parser = new MultiPartParser(new MultiPartParser.Handler()
+ {
+ }, "BOUNDARY");
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n\r\n");
- data = BufferUtil.toBuffer("--BOUNDARY\r\n\r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.FIRST_OCTETS));
- assertThat(data.remaining(),is(0));
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.FIRST_OCTETS));
+ assertThat(data.remaining(), is(0));
}
@Test
@@ -162,149 +170,136 @@ public class MultiPartParserTest
return true;
}
};
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name0: value0\r\n"
+ "name1 :value1 \r\n"
+ "name2:value\r\n"
+ " 2\r\n"
+ "\r\n"
+ "Content");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.FIRST_OCTETS));
- assertThat(data.remaining(),is(7));
- assertThat(handler.fields,Matchers.contains("name0: value0","name1: value1", "name2: value 2", "<>"));
+
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.FIRST_OCTETS));
+ assertThat(data.remaining(), is(7));
+ assertThat(handler.fields, Matchers.contains("name0: value0", "name1: value1", "name2: value 2", "<>"));
}
@Test
public void testFirstPartNoContent()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\r\n"
+ "\r\n"
+ "\r\n"
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("<>"));
- }
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("<>"));
+ }
@Test
public void testFirstPartNoContentNoCRLF()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\r\n"
+ "\r\n"
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("<>"));
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("<>"));
}
-
+
@Test
public void testFirstPartContentLookingLikeNoCRLF()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\r\n"
+ "\r\n"
+ "-");
- parser.parse(data,false);
+ parser.parse(data, false);
data = BufferUtil.toBuffer("Content!");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.OCTETS));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("-","Content!"));
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("-", "Content!"));
}
-
+
@Test
public void testFirstPartPartialContent()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\n"
+ "\r\n"
+ "Hello\r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.OCTETS));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Hello"));
-
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.OCTETS));
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Hello"));
+
data = BufferUtil.toBuffer(
"Now is the time for all good ment to come to the aid of the party.\r\n"
- + "How now brown cow.\r\n"
- + "The quick brown fox jumped over the lazy dog.\r\n"
- + "this is not a --BOUNDARY\r\n");
- parser.parse(data,false);
- assertThat(parser.getState(),is(State.OCTETS));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Hello","\r\n","Now is the time for all good ment to come to the aid of the party.\r\n"
+ + "How now brown cow.\r\n"
+ + "The quick brown fox jumped over the lazy dog.\r\n"
+ + "this is not a --BOUNDARY\r\n");
+ parser.parse(data, false);
+ assertThat(parser.getState(), is(State.OCTETS));
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Hello", "\r\n", "Now is the time for all good ment to come to the aid of the party.\r\n"
+ "How now brown cow.\r\n"
+ "The quick brown fox jumped over the lazy dog.\r\n"
+ "this is not a --BOUNDARY"));
}
-
+
@Test
public void testFirstPartShortContent()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\n"
+ "\r\n"
+ "Hello\r\n"
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Hello","<>"));
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Hello", "<>"));
}
-
+
@Test
public void testFirstPartLongContent()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
- ByteBuffer data = BufferUtil.toBuffer("");
-
- data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\r\n"
+ "name: value\n"
+ "\r\n"
+ "Now is the time for all good ment to come to the aid of the party.\r\n"
@@ -312,25 +307,23 @@ public class MultiPartParserTest
+ "The quick brown fox jumped over the lazy dog.\r\n"
+ "\r\n"
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Now is the time for all good ment to come to the aid of the party.\r\n"
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Now is the time for all good ment to come to the aid of the party.\r\n"
+ "How now brown cow.\r\n"
- + "The quick brown fox jumped over the lazy dog.\r\n","<>"));
+ + "The quick brown fox jumped over the lazy dog.\r\n", "<>"));
}
@Test
public void testFirstPartLongContentNoCarriageReturn()
{
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
-
- ByteBuffer data = BufferUtil.toBuffer("");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
//boundary still requires carriage return
- data = BufferUtil.toBuffer("--BOUNDARY\n"
+ ByteBuffer data = BufferUtil.toBuffer("--BOUNDARY\n"
+ "name: value\n"
+ "\n"
+ "Now is the time for all good men to come to the aid of the party.\n"
@@ -338,15 +331,15 @@ public class MultiPartParserTest
+ "The quick brown fox jumped over the lazy dog.\n"
+ "\r\n"
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(0));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Now is the time for all good men to come to the aid of the party.\n"
+ assertThat(data.remaining(), is(0));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Now is the time for all good men to come to the aid of the party.\n"
+ "How now brown cow.\n"
- + "The quick brown fox jumped over the lazy dog.\n","<>"));
+ + "The quick brown fox jumped over the lazy dog.\n", "<>"));
}
-
+
@Test
public void testBinaryPart()
@@ -361,30 +354,31 @@ public class MultiPartParserTest
@Override
public boolean content(ByteBuffer buffer, boolean last)
{
- BufferUtil.append(bytes,buffer);
+ BufferUtil.append(bytes, buffer);
return last;
}
};
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
String preamble = "Blah blah blah\r\n--BOUNDARY\r\n\r\n";
String epilogue = "\r\n--BOUNDARY\r\nBlah blah blah!\r\n";
- ByteBuffer data = BufferUtil.allocate(preamble.length()+random.length+epilogue.length());
- BufferUtil.append(data,BufferUtil.toBuffer(preamble));
- BufferUtil.append(data,ByteBuffer.wrap(random));
- BufferUtil.append(data,BufferUtil.toBuffer(epilogue));
+ ByteBuffer data = BufferUtil.allocate(preamble.length() + random.length + epilogue.length());
+ BufferUtil.append(data, BufferUtil.toBuffer(preamble));
+ BufferUtil.append(data, ByteBuffer.wrap(random));
+ BufferUtil.append(data, BufferUtil.toBuffer(epilogue));
- parser.parse(data,true);
+ parser.parse(data, true);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(data.remaining(),is(19));
- assertThat(bytes.array(),is(random));
+ assertThat(data.remaining(), is(19));
+ assertThat(bytes.array(), is(random));
}
@Test
- public void testEpilogue() {
+ public void testEpilogue()
+ {
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
ByteBuffer data = BufferUtil.toBuffer(""
+ "--BOUNDARY\r\n"
@@ -399,20 +393,21 @@ public class MultiPartParserTest
+ "--BOUNDARY");
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(handler.fields,Matchers.contains("name: value", "<>"));
- assertThat(handler.content,Matchers.contains("Hello","<>"));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>"));
+ assertThat(handler.content, Matchers.contains("Hello", "<>"));
- parser.parse(data,true);
+ parser.parse(data, true);
assertThat(parser.getState(), is(State.END));
}
@Test
- public void testMultipleContent() {
+ public void testMultipleContent()
+ {
TestHandler handler = new TestHandler();
- MultiPartParser parser = new MultiPartParser(handler,"BOUNDARY");
+ MultiPartParser parser = new MultiPartParser(handler, "BOUNDARY");
ByteBuffer data = BufferUtil.toBuffer(""
+ "--BOUNDARY\r\n"
@@ -430,211 +425,213 @@ public class MultiPartParserTest
+ "epilogue here");
/* Test First Content Section */
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
assertThat(handler.fields, Matchers.contains("name: value", "<>"));
- assertThat(handler.content, Matchers.contains("Hello","<>"));
+ assertThat(handler.content, Matchers.contains("Hello", "<>"));
/* Test Second Content Section */
- parser.parse(data,false);
+ parser.parse(data, false);
assertThat(parser.getState(), is(State.DELIMITER));
- assertThat(handler.fields, Matchers.contains("name: value", "<>","powerLevel: 9001","<>"));
- assertThat(handler.content, Matchers.contains("Hello","<>","secondary\r\ncontent","<>"));
+ assertThat(handler.fields, Matchers.contains("name: value", "<>", "powerLevel: 9001", "<>"));
+ assertThat(handler.content, Matchers.contains("Hello", "<>", "secondary\r\ncontent", "<>"));
/* Test Progression to END State */
- parser.parse(data,true);
+ parser.parse(data, true);
assertThat(parser.getState(), is(State.END));
- assertThat(data.remaining(),is(0));
+ assertThat(data.remaining(), is(0));
}
-
@Test
- public void testCrAsLineTermination() {
- TestHandler handler = new TestHandler()
- {
- @Override public boolean messageComplete(){ return true; }
-
- @Override
- public boolean content(ByteBuffer buffer, boolean last)
- {
- super.content(buffer,last);
- return false;
- }
- };
- MultiPartParser parser = new MultiPartParser(handler,"AaB03x");
-
- ByteBuffer data = BufferUtil.toBuffer(
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"\r\n"+
- "\r"+
- "Joe Blow\r\n"+
- "--AaB03x--\r\n");
-
-
- try
- {
- parser.parse(data,true);
- fail("Invalid End of Line");
- }
- catch(BadMessageException e) {
- assertTrue(e.getMessage().contains("Bad EOL"));
- }
-
-
- }
-
-
-
- @Test
- public void splitTest()
+ public void testCrAsLineTermination()
{
- TestHandler handler = new TestHandler()
+ TestHandler handler = new TestHandler()
{
@Override
public boolean messageComplete()
{
return true;
}
-
+
@Override
public boolean content(ByteBuffer buffer, boolean last)
{
- super.content(buffer,last);
+ super.content(buffer, last);
+ return false;
+ }
+ };
+ MultiPartParser parser = new MultiPartParser(handler, "AaB03x");
+
+ ByteBuffer data = BufferUtil.toBuffer(
+ "--AaB03x\r\n" +
+ "content-disposition: form-data; name=\"field1\"\r\n" +
+ "\r" +
+ "Joe Blow\r\n" +
+ "--AaB03x--\r\n");
+
+ try
+ {
+ parser.parse(data, true);
+ fail("Invalid End of Line");
+ }
+ catch (BadMessageException e)
+ {
+ assertTrue(e.getMessage().contains("Bad EOL"));
+ }
+ }
+
+
+ @Test
+ public void splitTest()
+ {
+ TestHandler handler = new TestHandler()
+ {
+ @Override
+ public boolean messageComplete()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean content(ByteBuffer buffer, boolean last)
+ {
+ super.content(buffer, last);
return false;
}
};
- MultiPartParser parser = new MultiPartParser(handler,"---------------------------9051914041544843365972754266");
- ByteBuffer data = BufferUtil.toBuffer(""+
- "POST / HTTP/1.1\n" +
- "Host: localhost:8000\n" +
- "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0\n" +
- "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n" +
- "Accept-Language: en-US,en;q=0.5\n" +
- "Accept-Encoding: gzip, deflate\n" +
- "Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET\n" +
- "Connection: keep-alive\n" +
- "Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266\n" +
- "Content-Length: 554\n" +
- "\r\n" +
- "-----------------------------9051914041544843365972754266\n" +
- "Content-Disposition: form-data; name=\"text\"\n" +
- "\n" +
- "text default\r\n" +
- "-----------------------------9051914041544843365972754266\n" +
- "Content-Disposition: form-data; name=\"file1\"; filename=\"a.txt\"\n" +
- "Content-Type: text/plain\n" +
- "\n" +
- "Content of a.txt.\n" +
- "\r\n" +
- "-----------------------------9051914041544843365972754266\n" +
- "Content-Disposition: form-data; name=\"file2\"; filename=\"a.html\"\n" +
- "Content-Type: text/html\n" +
- "\n" +
- "Content of a.html.\n" +
- "\r\n" +
- "-----------------------------9051914041544843365972754266\n" +
- "Field1: value1\n" +
- "Field2: value2\n" +
- "Field3: value3\n" +
- "Field4: value4\n" +
- "Field5: value5\n" +
+ MultiPartParser parser = new MultiPartParser(handler, "---------------------------9051914041544843365972754266");
+ ByteBuffer data = BufferUtil.toBuffer("" +
+ "POST / HTTP/1.1\n" +
+ "Host: localhost:8000\n" +
+ "User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0\n" +
+ "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n" +
+ "Accept-Language: en-US,en;q=0.5\n" +
+ "Accept-Encoding: gzip, deflate\n" +
+ "Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET\n" +
+ "Connection: keep-alive\n" +
+ "Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266\n" +
+ "Content-Length: 554\n" +
+ "\r\n" +
+ "-----------------------------9051914041544843365972754266\n" +
+ "Content-Disposition: form-data; name=\"text\"\n" +
+ "\n" +
+ "text default\r\n" +
+ "-----------------------------9051914041544843365972754266\n" +
+ "Content-Disposition: form-data; name=\"file1\"; filename=\"a.txt\"\n" +
+ "Content-Type: text/plain\n" +
+ "\n" +
+ "Content of a.txt.\n" +
+ "\r\n" +
+ "-----------------------------9051914041544843365972754266\n" +
+ "Content-Disposition: form-data; name=\"file2\"; filename=\"a.html\"\n" +
+ "Content-Type: text/html\n" +
+ "\n" +
+ "Content of a.html.\n" +
+ "\r\n" +
+ "-----------------------------9051914041544843365972754266\n" +
+ "Field1: value1\n" +
+ "Field2: value2\n" +
+ "Field3: value3\n" +
+ "Field4: value4\n" +
+ "Field5: value5\n" +
"Field6: value6\n" +
"Field7: value7\n" +
"Field8: value8\n" +
- "Field9: value\n" +
+ "Field9: value\n" +
" 9\n" +
"\r\n" +
- "-----------------------------9051914041544843365972754266\n" +
- "Field1: value1\n" +
- "\r\n"+
- "But the amount of denudation which the strata have\n" +
- "in many places suffered, independently of the rate\n" +
- "of accumulation of the degraded matter, probably\n" +
- "offers the best evidence of the lapse of time. I remember\n" +
- "having been much struck with the evidence of\n" +
- "denudation, when viewing volcanic islands, which\n" +
- "have been worn by the waves and pared all round\n" +
- "into perpendicular cliffs of one or two thousand feet\n" +
- "in height; for the gentle slope of the lava-streams,\n" +
- "due to their formerly liquid state, showed at a glance\n" +
- "how far the hard, rocky beds had once extended into\n" +
+ "-----------------------------9051914041544843365972754266\n" +
+ "Field1: value1\n" +
+ "\r\n" +
+ "But the amount of denudation which the strata have\n" +
+ "in many places suffered, independently of the rate\n" +
+ "of accumulation of the degraded matter, probably\n" +
+ "offers the best evidence of the lapse of time. I remember\n" +
+ "having been much struck with the evidence of\n" +
+ "denudation, when viewing volcanic islands, which\n" +
+ "have been worn by the waves and pared all round\n" +
+ "into perpendicular cliffs of one or two thousand feet\n" +
+ "in height; for the gentle slope of the lava-streams,\n" +
+ "due to their formerly liquid state, showed at a glance\n" +
+ "how far the hard, rocky beds had once extended into\n" +
"the open ocean.\n" +
"\r\n" +
"-----------------------------9051914041544843365972754266--" +
"===== ajlkfja;lkdj;lakjd;lkjf ==== epilogue here ==== kajflajdfl;kjafl;kjl;dkfja ====\n\r\n\r\r\r\n\n\n");
-
- int length = data.remaining();
- for(int i = 0; i>"
- , "Content-Disposition: form-data; name=\"file1\"; filename=\"a.txt\""
- , "Content-Type: text/plain","<>"
- , "Content-Disposition: form-data; name=\"file2\"; filename=\"a.html\""
- , "Content-Type: text/html","<>"
- , "Field1: value1", "Field2: value2", "Field3: value3"
- , "Field4: value4", "Field5: value5", "Field6: value6"
- , "Field7: value7", "Field8: value8", "Field9: value 9", "<>"
- , "Field1: value1","<>"));
-
-
- assertThat(handler.contentString(), is(new String("text default"+"<>"
- + "Content of a.txt.\n"+"<>"
- + "Content of a.html.\n"+"<>"
- + "<>"
- + "But the amount of denudation which the strata have\n" +
- "in many places suffered, independently of the rate\n" +
- "of accumulation of the degraded matter, probably\n" +
- "offers the best evidence of the lapse of time. I remember\n" +
- "having been much struck with the evidence of\n" +
- "denudation, when viewing volcanic islands, which\n" +
- "have been worn by the waves and pared all round\n" +
- "into perpendicular cliffs of one or two thousand feet\n" +
- "in height; for the gentle slope of the lava-streams,\n" +
- "due to their formerly liquid state, showed at a glance\n" +
- "how far the hard, rocky beds had once extended into\n" +
- "the open ocean.\n"+ "<>")));
-
- handler.clear();
- parser.reset();
- }
+
+ int length = data.remaining();
+ for (int i = 0; i < length - 1; i++)
+ {
+ //partition 0 to i
+ ByteBuffer dataSeg = data.slice();
+ dataSeg.position(0);
+ dataSeg.limit(i);
+ assertThat("First " + i, parser.parse(dataSeg, false), is(false));
+
+ //partition i
+ dataSeg = data.slice();
+ dataSeg.position(i);
+ dataSeg.limit(i + 1);
+ assertThat("Second " + i, parser.parse(dataSeg, false), is(false));
+
+ //partition i to length
+ dataSeg = data.slice();
+ dataSeg.position(i + 1);
+ dataSeg.limit(length);
+ assertThat("Third " + i, parser.parse(dataSeg, true), is(true));
+
+ assertThat(handler.fields, Matchers.contains("Content-Disposition: form-data; name=\"text\"", "<>"
+ , "Content-Disposition: form-data; name=\"file1\"; filename=\"a.txt\""
+ , "Content-Type: text/plain", "<>"
+ , "Content-Disposition: form-data; name=\"file2\"; filename=\"a.html\""
+ , "Content-Type: text/html", "<>"
+ , "Field1: value1", "Field2: value2", "Field3: value3"
+ , "Field4: value4", "Field5: value5", "Field6: value6"
+ , "Field7: value7", "Field8: value8", "Field9: value 9", "<>"
+ , "Field1: value1", "<>"));
+
+
+ assertThat(handler.contentString(), is("text default" + "<>"
+ + "Content of a.txt.\n" + "<>"
+ + "Content of a.html.\n" + "<>"
+ + "<>"
+ + "But the amount of denudation which the strata have\n" +
+ "in many places suffered, independently of the rate\n" +
+ "of accumulation of the degraded matter, probably\n" +
+ "offers the best evidence of the lapse of time. I remember\n" +
+ "having been much struck with the evidence of\n" +
+ "denudation, when viewing volcanic islands, which\n" +
+ "have been worn by the waves and pared all round\n" +
+ "into perpendicular cliffs of one or two thousand feet\n" +
+ "in height; for the gentle slope of the lava-streams,\n" +
+ "due to their formerly liquid state, showed at a glance\n" +
+ "how far the hard, rocky beds had once extended into\n" +
+ "the open ocean.\n" + "<>"));
+
+ handler.clear();
+ parser.reset();
+ }
}
-
+
@Test
- public void testGeneratedForm()
+ public void testGeneratedForm()
{
- TestHandler handler = new TestHandler()
+ TestHandler handler = new TestHandler()
{
@Override
public boolean messageComplete()
{
return true;
}
-
+
@Override
public boolean content(ByteBuffer buffer, boolean last)
{
- super.content(buffer,last);
+ super.content(buffer, last);
return false;
}
@@ -645,24 +642,24 @@ public class MultiPartParserTest
}
};
- MultiPartParser parser = new MultiPartParser(handler,"WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW");
+ MultiPartParser parser = new MultiPartParser(handler, "WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW");
ByteBuffer data = BufferUtil.toBuffer(""
- + "Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
- "\r\n" +
- "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
- "Content-Disposition: form-data; name=\"part1\"\r\n" +
- "\n" +
- "wNfミxVamt\r\n" +
- "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\n" +
- "Content-Disposition: form-data; name=\"part2\"\r\n" +
- "\r\n" +
- "&ᄈ취ᅢO\r\n" +
+ + "Content-Type: multipart/form-data; boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
+ "\r\n" +
+ "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n" +
+ "Content-Disposition: form-data; name=\"part1\"\r\n" +
+ "\n" +
+ "wNfミxVamt\r\n" +
+ "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\n" +
+ "Content-Disposition: form-data; name=\"part2\"\r\n" +
+ "\r\n" +
+ "&ᄈ취ᅢO\r\n" +
"--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW--");
-
- parser.parse(data,true);
+
+ parser.parse(data, true);
assertThat(parser.getState(), is(State.END));
assertThat(handler.fields.size(), is(2));
-
+
}
@@ -670,27 +667,28 @@ public class MultiPartParserTest
{
List fields = new ArrayList<>();
List content = new ArrayList<>();
-
+
@Override
public void parsedField(String name, String value)
{
- fields.add(name+": "+value);
+ fields.add(name + ": " + value);
}
-
+
public String contentString()
{
StringBuilder sb = new StringBuilder();
- for(String s : content) sb.append(s);
+ for (String s : content)
+ sb.append(s);
return sb.toString();
}
-
+
@Override
public boolean headerComplete()
{
fields.add("<>");
return false;
}
-
+
@Override
public boolean content(ByteBuffer buffer, boolean last)
{
@@ -701,11 +699,10 @@ public class MultiPartParserTest
return last;
}
- public void clear() {
+ public void clear()
+ {
fields.clear();
content.clear();
}
-
}
-
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java b/jetty-http/src/test/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java
index 49924222a0c..7bf56f04e09 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/jmh/MultiPartBenchmark.java
@@ -20,7 +20,6 @@ package org.eclipse.jetty.http.jmh;
import java.io.File;
import java.io.InputStream;
-import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
@@ -34,11 +33,6 @@ import javax.servlet.http.Part;
import org.eclipse.jetty.http.MultiPartFormInputStream;
import org.eclipse.jetty.http.MultiPartCaptureTest.MultipartExpectations;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
-import org.eclipse.jetty.toolchain.test.TestingDir;
-import org.eclipse.jetty.util.BufferUtil;
-import org.junit.Rule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
@@ -48,14 +42,13 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
-import org.openjdk.jmh.profile.CompilerProfiler;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
@State(Scope.Benchmark)
-public class MultiPartBenchmark
+public class MultiPartBenchmark
{
public static final int MAX_FILE_SIZE = Integer.MAX_VALUE;
@@ -67,13 +60,14 @@ public class MultiPartBenchmark
static File _file;
static int _numSections;
static int _numBytesPerSection;
-
+
public static List data = new ArrayList<>();
+
static
{
// Capture of raw request body contents from various browsers
-
+
// simple form - 2 fields
data.add("browser-capture-form1-android-chrome");
data.add("browser-capture-form1-android-firefox");
@@ -83,15 +77,15 @@ public class MultiPartBenchmark
data.add("browser-capture-form1-ios-safari");
data.add("browser-capture-form1-msie");
data.add("browser-capture-form1-osx-safari");
-
+
// form submitted as shift-jis
- data.add("browser-capture-sjis-form-edge");
+ data.add("browser-capture-sjis-form-edge");
data.add("browser-capture-sjis-form-msie");
-
+
// form submitted as shift-jis (with HTML5 specific hidden _charset_ field)
data.add("browser-capture-sjis-charset-form-edge");
data.add("browser-capture-sjis-charset-form-msie");
-
+
// form submitted with simple file upload
data.add("browser-capture-form-fileupload-android-chrome");
data.add("browser-capture-form-fileupload-android-firefox");
@@ -101,7 +95,7 @@ public class MultiPartBenchmark
data.add("browser-capture-form-fileupload-ios-safari");
data.add("browser-capture-form-fileupload-msie");
data.add("browser-capture-form-fileupload-safari");
-
+
// form submitted with 2 files (1 binary, 1 text) and 2 text fields
data.add("browser-capture-form-fileupload-alt-chrome");
data.add("browser-capture-form-fileupload-alt-edge");
@@ -109,19 +103,19 @@ public class MultiPartBenchmark
data.add("browser-capture-form-fileupload-alt-msie");
data.add("browser-capture-form-fileupload-alt-safari");
}
-
- @Param({"UTIL","HTTP"})
+
+ @Param({"UTIL", "HTTP"})
public static String parserType;
-
+
@Setup(Level.Trial)
public static void setupTrial() throws Exception
{
- _file = File.createTempFile("test01",null);
+ _file = File.createTempFile("test01", null);
_file.deleteOnExit();
_numSections = 1;
- _numBytesPerSection = 1024*1024*10;
+ _numBytesPerSection = 1024 * 1024 * 10;
_contentType = "multipart/form-data, boundary=WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW";
String initialBoundary = "--WebKitFormBoundary7MA4YWf7OaKlSxkTrZu0gW\r\n";
@@ -130,17 +124,18 @@ public class MultiPartBenchmark
String headerStart = "Content-Disposition: form-data; name=\"";
- for(int i=0; i<_numSections; i++) {
+ for (int i = 0; i < _numSections; i++)
+ {
//boundary and headers
- if(i==0)
+ if (i == 0)
Files.write(_file.toPath(), initialBoundary.getBytes(), StandardOpenOption.APPEND);
else
Files.write(_file.toPath(), boundary.getBytes(), StandardOpenOption.APPEND);
-
+
Files.write(_file.toPath(), headerStart.getBytes(), StandardOpenOption.APPEND);
- Files.write(_file.toPath(), new String("part"+(i+1)).getBytes(), StandardOpenOption.APPEND);
- Files.write(_file.toPath(), new String("\"\r\n\r\n").getBytes(), StandardOpenOption.APPEND);
-
+ Files.write(_file.toPath(), ("part" + (i + 1)).getBytes(), StandardOpenOption.APPEND);
+ Files.write(_file.toPath(), ("\"\r\n\r\n").getBytes(), StandardOpenOption.APPEND);
+
//append random data
byte[] data = new byte[_numBytesPerSection];
new Random().nextBytes(data);
@@ -149,25 +144,9 @@ public class MultiPartBenchmark
//closing boundary
Files.write(_file.toPath(), closingBoundary.getBytes(), StandardOpenOption.APPEND);
-
- /*
- // print out file to verify that it contains valid contents (just for testing)
- InputStream in = Files.newInputStream(_file.toPath());
- System.out.println();
- while(in.available()>0) {
- byte b[] = new byte[100];
- int read = in.read(b,0,100);
- for(int i=0; i