Replaced tabs with 4 spaces.
This commit is contained in:
parent
802e5366b2
commit
66b4735acd
File diff suppressed because it is too large
Load Diff
@ -28,13 +28,14 @@ import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(HttpUploadClientHandler.class);
|
||||
private static final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(HttpUploadClientHandler.class);
|
||||
|
||||
private volatile boolean readingChunks;
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
||||
throws Exception {
|
||||
if (!readingChunks) {
|
||||
HttpResponse response = (HttpResponse) e.getMessage();
|
||||
|
||||
@ -42,8 +43,8 @@ public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
|
||||
logger.info("VERSION: " + response.getProtocolVersion());
|
||||
|
||||
if (!response.getHeaderNames().isEmpty()) {
|
||||
for (String name: response.getHeaderNames()) {
|
||||
for (String value: response.getHeaders(name)) {
|
||||
for (String name : response.getHeaderNames()) {
|
||||
for (String value : response.getHeaders(name)) {
|
||||
logger.info("HEADER: " + name + " = " + value);
|
||||
}
|
||||
}
|
||||
|
@ -41,8 +41,8 @@ public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
// Enable HTTPS if necessary.
|
||||
if (ssl) {
|
||||
SSLEngine engine =
|
||||
SecureChatSslContextFactory.getClientContext().createSSLEngine();
|
||||
SSLEngine engine = SecureChatSslContextFactory.getClientContext()
|
||||
.createSSLEngine();
|
||||
engine.setUseClientMode(true);
|
||||
|
||||
pipeline.addLast("ssl", new SslHandler(engine));
|
||||
@ -50,7 +50,8 @@ public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
|
||||
|
||||
pipeline.addLast("codec", new HttpClientCodec());
|
||||
|
||||
// Remove the following line if you don't want automatic content decompression.
|
||||
// Remove the following line if you don't want automatic content
|
||||
// decompression.
|
||||
pipeline.addLast("inflater", new HttpContentDecompressor());
|
||||
|
||||
// to be used since huge file transfer
|
||||
|
@ -64,8 +64,8 @@ import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private static final InternalLogger logger =
|
||||
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
|
||||
private static final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(HttpUploadServerHandler.class);
|
||||
|
||||
private volatile HttpRequest request;
|
||||
|
||||
@ -96,7 +96,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
|
||||
throws Exception {
|
||||
if (!readingChunks) {
|
||||
// clean previous FileUpload if Any
|
||||
if (decoder != null) {
|
||||
@ -115,18 +116,18 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
|
||||
responseContent.append("===================================\r\n");
|
||||
|
||||
responseContent.append("VERSION: " +
|
||||
request.getProtocolVersion().getText() + "\r\n");
|
||||
responseContent.append("VERSION: "
|
||||
+ request.getProtocolVersion().getText() + "\r\n");
|
||||
|
||||
responseContent.append("REQUEST_URI: " + request.getUri() +
|
||||
"\r\n\r\n");
|
||||
responseContent.append("REQUEST_URI: " + request.getUri()
|
||||
+ "\r\n\r\n");
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
// new method
|
||||
List<Entry<String, String>> headers = request.getHeaders();
|
||||
for (Entry<String, String> entry: headers) {
|
||||
responseContent.append("HEADER: " + entry.getKey() + "=" +
|
||||
entry.getValue() + "\r\n");
|
||||
for (Entry<String, String> entry : headers) {
|
||||
responseContent.append("HEADER: " + entry.getKey() + "="
|
||||
+ entry.getValue() + "\r\n");
|
||||
}
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
@ -139,19 +140,19 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
CookieDecoder decoder = new CookieDecoder();
|
||||
cookies = decoder.decode(value);
|
||||
}
|
||||
for (Cookie cookie: cookies) {
|
||||
for (Cookie cookie : cookies) {
|
||||
responseContent.append("COOKIE: " + cookie.toString() + "\r\n");
|
||||
}
|
||||
responseContent.append("\r\n\r\n");
|
||||
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(request
|
||||
.getUri());
|
||||
QueryStringDecoder decoderQuery = new QueryStringDecoder(
|
||||
request.getUri());
|
||||
Map<String, List<String>> uriAttributes = decoderQuery
|
||||
.getParameters();
|
||||
for (String key: uriAttributes.keySet()) {
|
||||
for (String valuen: uriAttributes.get(key)) {
|
||||
responseContent.append("URI: " + key + "=" + valuen +
|
||||
"\r\n");
|
||||
for (String key : uriAttributes.keySet()) {
|
||||
for (String valuen : uriAttributes.get(key)) {
|
||||
responseContent.append("URI: " + key + "=" + valuen
|
||||
+ "\r\n");
|
||||
}
|
||||
}
|
||||
responseContent.append("\r\n\r\n");
|
||||
@ -174,10 +175,10 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
responseContent.append("Is Chunked: " + request.isChunked() +
|
||||
"\r\n");
|
||||
responseContent.append("IsMultipart: " + decoder.isMultipart() +
|
||||
"\r\n");
|
||||
responseContent.append("Is Chunked: " + request.isChunked()
|
||||
+ "\r\n");
|
||||
responseContent.append("IsMultipart: " + decoder.isMultipart()
|
||||
+ "\r\n");
|
||||
if (request.isChunked()) {
|
||||
// Chunk version
|
||||
responseContent.append("Chunks: ");
|
||||
@ -202,7 +203,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
return;
|
||||
}
|
||||
responseContent.append("o");
|
||||
// example of reading chunk by chunk (minimize memory usage due to Factory)
|
||||
// example of reading chunk by chunk (minimize memory usage due to
|
||||
// Factory)
|
||||
readHttpDataChunkByChunk(e.getChannel());
|
||||
// example of reading only if at the end
|
||||
if (chunk.isLast()) {
|
||||
@ -230,7 +232,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
Channels.close(channel);
|
||||
return;
|
||||
}
|
||||
for (InterfaceHttpData data: datas) {
|
||||
for (InterfaceHttpData data : datas) {
|
||||
writeHttpData(data);
|
||||
}
|
||||
responseContent.append("\r\n\r\nEND OF CONTENT AT FINAL END\r\n");
|
||||
@ -267,25 +269,25 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
} catch (IOException e1) {
|
||||
// Error while reading data from File, only print name and error
|
||||
e1.printStackTrace();
|
||||
responseContent.append("\r\nBODY Attribute: " +
|
||||
attribute.getHttpDataType().name() + ": " +
|
||||
attribute.getName() + " Error while reading value: " +
|
||||
e1.getMessage() + "\r\n");
|
||||
responseContent.append("\r\nBODY Attribute: "
|
||||
+ attribute.getHttpDataType().name() + ": "
|
||||
+ attribute.getName() + " Error while reading value: "
|
||||
+ e1.getMessage() + "\r\n");
|
||||
return;
|
||||
}
|
||||
if (value.length() > 100) {
|
||||
responseContent.append("\r\nBODY Attribute: " +
|
||||
attribute.getHttpDataType().name() + ": " +
|
||||
attribute.getName() + " data too long\r\n");
|
||||
responseContent.append("\r\nBODY Attribute: "
|
||||
+ attribute.getHttpDataType().name() + ": "
|
||||
+ attribute.getName() + " data too long\r\n");
|
||||
} else {
|
||||
responseContent.append("\r\nBODY Attribute: " +
|
||||
attribute.getHttpDataType().name() + ": " +
|
||||
attribute.toString() + "\r\n");
|
||||
responseContent.append("\r\nBODY Attribute: "
|
||||
+ attribute.getHttpDataType().name() + ": "
|
||||
+ attribute.toString() + "\r\n");
|
||||
}
|
||||
} else {
|
||||
responseContent.append("\r\nBODY FileUpload: " +
|
||||
data.getHttpDataType().name() + ": " + data.toString() +
|
||||
"\r\n");
|
||||
responseContent.append("\r\nBODY FileUpload: "
|
||||
+ data.getHttpDataType().name() + ": " + data.toString()
|
||||
+ "\r\n");
|
||||
if (data.getHttpDataType() == HttpDataType.FileUpload) {
|
||||
FileUpload fileUpload = (FileUpload) data;
|
||||
if (fileUpload.isCompleted()) {
|
||||
@ -303,8 +305,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.append("\r\n");
|
||||
} else {
|
||||
responseContent
|
||||
.append("\tFile too long to be printed out:" +
|
||||
fileUpload.length() + "\r\n");
|
||||
.append("\tFile too long to be printed out:"
|
||||
+ fileUpload.length() + "\r\n");
|
||||
}
|
||||
// fileUpload.isInMemory();// tells if the file is in Memory
|
||||
// or on File
|
||||
@ -322,15 +324,15 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
|
||||
private void writeResponse(Channel channel) {
|
||||
// Convert the response content to a ChannelBuffer.
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
|
||||
.toString(), CharsetUtil.UTF_8);
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(
|
||||
responseContent.toString(), CharsetUtil.UTF_8);
|
||||
responseContent.setLength(0);
|
||||
|
||||
// Decide whether to close the connection or not.
|
||||
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request
|
||||
.getHeader(HttpHeaders.Names.CONNECTION)) ||
|
||||
request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) &&
|
||||
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
|
||||
.getHeader(HttpHeaders.Names.CONNECTION))
|
||||
|| request.getProtocolVersion().equals(HttpVersion.HTTP_1_0)
|
||||
&& !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
|
||||
.getHeader(HttpHeaders.Names.CONNECTION));
|
||||
|
||||
// Build the response object.
|
||||
@ -343,8 +345,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
if (!close) {
|
||||
// There's no need to add 'Content-Length' header
|
||||
// if this is the last response.
|
||||
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String
|
||||
.valueOf(buf.readableBytes()));
|
||||
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
|
||||
String.valueOf(buf.readableBytes()));
|
||||
}
|
||||
|
||||
Set<Cookie> cookies;
|
||||
@ -358,11 +360,11 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
if (!cookies.isEmpty()) {
|
||||
// Reset the cookies if necessary.
|
||||
CookieEncoder cookieEncoder = new CookieEncoder(true);
|
||||
for (Cookie cookie: cookies) {
|
||||
for (Cookie cookie : cookies) {
|
||||
cookieEncoder.addCookie(cookie);
|
||||
}
|
||||
response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder
|
||||
.encode());
|
||||
response.addHeader(HttpHeaders.Names.SET_COOKIE,
|
||||
cookieEncoder.encode());
|
||||
}
|
||||
// Write the response.
|
||||
ChannelFuture future = channel.write(response);
|
||||
@ -468,16 +470,16 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
|
||||
responseContent.append("</body>");
|
||||
responseContent.append("</html>");
|
||||
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
|
||||
.toString(), CharsetUtil.UTF_8);
|
||||
ChannelBuffer buf = ChannelBuffers.copiedBuffer(
|
||||
responseContent.toString(), CharsetUtil.UTF_8);
|
||||
// Build the response object.
|
||||
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
|
||||
HttpResponseStatus.OK);
|
||||
response.setContent(buf);
|
||||
response.setHeader(HttpHeaders.Names.CONTENT_TYPE,
|
||||
"text/html; charset=UTF-8");
|
||||
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf
|
||||
.readableBytes()));
|
||||
response.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
|
||||
String.valueOf(buf.readableBytes()));
|
||||
// Write the response.
|
||||
e.getChannel().write(response);
|
||||
}
|
||||
|
@ -30,15 +30,17 @@ public class HttpUploadServerPipelineFactory implements ChannelPipelineFactory {
|
||||
ChannelPipeline pipeline = pipeline();
|
||||
|
||||
// Uncomment the following line if you want HTTPS
|
||||
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||
//engine.setUseClientMode(false);
|
||||
//pipeline.addLast("ssl", new SslHandler(engine));
|
||||
// SSLEngine engine =
|
||||
// SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||
// engine.setUseClientMode(false);
|
||||
// pipeline.addLast("ssl", new SslHandler(engine));
|
||||
|
||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||
|
||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||
|
||||
// Remove the following line if you don't want automatic content compression.
|
||||
// Remove the following line if you don't want automatic content
|
||||
// compression.
|
||||
pipeline.addLast("deflater", new HttpContentCompressor());
|
||||
|
||||
pipeline.addLast("handler", new HttpUploadServerHandler());
|
||||
|
@ -21,8 +21,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
|
||||
/**
|
||||
* Default factory giving Attribute and FileUpload according to constructor
|
||||
*
|
||||
|
@ -18,8 +18,6 @@ package org.jboss.netty.handler.codec.http;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.jboss.netty.handler.codec.http.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Disk FileUpload implementation that stores file into real files
|
||||
*/
|
||||
|
@ -26,21 +26,12 @@ import java.util.TreeMap;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.handler.codec.http.HttpChunk;
|
||||
import org.jboss.netty.handler.codec.http.HttpHeaders;
|
||||
import org.jboss.netty.handler.codec.http.HttpMethod;
|
||||
import org.jboss.netty.handler.codec.http.HttpPostBodyUtil.TransferEncodingMechanism;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
|
||||
|
||||
/**
|
||||
* This decoder will decode Body and can handle POST BODY.
|
||||
*/
|
||||
public class HttpPostRequestDecoder {
|
||||
|
||||
static final String MULTIPART_FORM_DATA = "multipart/form-data";
|
||||
static final String BOUNDARY = "boundary";
|
||||
|
||||
/**
|
||||
* Factory used to create InterfaceHttpData
|
||||
*/
|
||||
@ -98,8 +89,8 @@ public class HttpPostRequestDecoder {
|
||||
private String multipartDataBoundary;
|
||||
|
||||
/**
|
||||
* If multipart, there could be internal multiparts (mixed) to the global
|
||||
* multipart. Only one level is allowed.
|
||||
* If multipart, there could be internal multiparts (mixed) to the global multipart.
|
||||
* Only one level is allowed.
|
||||
*/
|
||||
private String multipartMixedBoundary;
|
||||
|
||||
@ -125,15 +116,10 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
* the request to decode
|
||||
* @throws NullPointerException
|
||||
* for request
|
||||
* @throws IncompatibleDataDecoderException
|
||||
* if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException
|
||||
* if the default charset was wrong when decoding or other
|
||||
* errors
|
||||
* @param request the request to decode
|
||||
* @throws NullPointerException for request
|
||||
* @throws IncompatibleDataDecoderException if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
|
||||
*/
|
||||
public HttpPostRequestDecoder(HttpRequest request)
|
||||
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
|
||||
@ -143,17 +129,11 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param factory
|
||||
* the factory used to create InterfaceHttpData
|
||||
* @param request
|
||||
* the request to decode
|
||||
* @throws NullPointerException
|
||||
* for request or factory
|
||||
* @throws IncompatibleDataDecoderException
|
||||
* if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException
|
||||
* if the default charset was wrong when decoding or other
|
||||
* errors
|
||||
* @param factory the factory used to create InterfaceHttpData
|
||||
* @param request the request to decode
|
||||
* @throws NullPointerException for request or factory
|
||||
* @throws IncompatibleDataDecoderException if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
|
||||
*/
|
||||
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request)
|
||||
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
|
||||
@ -162,19 +142,12 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param factory
|
||||
* the factory used to create InterfaceHttpData
|
||||
* @param request
|
||||
* the request to decode
|
||||
* @param charset
|
||||
* the charset to use as default
|
||||
* @throws NullPointerException
|
||||
* for request or charset or factory
|
||||
* @throws IncompatibleDataDecoderException
|
||||
* if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException
|
||||
* if the default charset was wrong when decoding or other
|
||||
* errors
|
||||
* @param factory the factory used to create InterfaceHttpData
|
||||
* @param request the request to decode
|
||||
* @param charset the charset to use as default
|
||||
* @throws NullPointerException for request or charset or factory
|
||||
* @throws IncompatibleDataDecoderException if the request has no body to decode
|
||||
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
|
||||
*/
|
||||
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request,
|
||||
Charset charset) throws ErrorDataDecoderException,
|
||||
@ -190,16 +163,14 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
this.request = request;
|
||||
HttpMethod method = request.getMethod();
|
||||
if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT)
|
||||
|| method.equals(HttpMethod.PATCH)) {
|
||||
if (method.equals(HttpMethod.POST) || method.equals(HttpMethod.PUT) || method.equals(HttpMethod.PATCH)) {
|
||||
bodyToDecode = true;
|
||||
}
|
||||
this.charset = charset;
|
||||
this.factory = factory;
|
||||
// Fill default values
|
||||
if (this.request.containsHeader(HttpHeaders.Names.CONTENT_TYPE)) {
|
||||
checkMultipart(this.request
|
||||
.getHeader(HttpHeaders.Names.CONTENT_TYPE));
|
||||
checkMultipart(this.request.getHeader(HttpHeaders.Names.CONTENT_TYPE));
|
||||
} else {
|
||||
isMultipart = false;
|
||||
}
|
||||
@ -214,43 +185,61 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* states follow NOTSTARTED PREAMBLE ( (HEADERDELIMITER DISPOSITION (FIELD |
|
||||
* FILEUPLOAD))* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE (MIXEDDELIMITER
|
||||
* MIXEDDISPOSITION MIXEDFILEUPLOAD)+ MIXEDCLOSEDELIMITER)* CLOSEDELIMITER)+
|
||||
* EPILOGUE
|
||||
* states follow
|
||||
* NOTSTARTED PREAMBLE (
|
||||
* (HEADERDELIMITER DISPOSITION (FIELD | FILEUPLOAD))*
|
||||
* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE
|
||||
* (MIXEDDELIMITER MIXEDDISPOSITION MIXEDFILEUPLOAD)+
|
||||
* MIXEDCLOSEDELIMITER)*
|
||||
* CLOSEDELIMITER)+ EPILOGUE
|
||||
*
|
||||
* First status is: NOSTARTED
|
||||
*
|
||||
* Content-type: multipart/form-data, boundary=AaB03x => PREAMBLE in Header
|
||||
*
|
||||
* --AaB03x => HEADERDELIMITER content-disposition: form-data; name="field1"
|
||||
* => DISPOSITION
|
||||
*
|
||||
* Joe Blow => FIELD --AaB03x => HEADERDELIMITER content-disposition:
|
||||
* form-data; name="pics" => DISPOSITION Content-type: multipart/mixed,
|
||||
* boundary=BbC04y
|
||||
*
|
||||
* --BbC04y => MIXEDDELIMITER Content-disposition: attachment;
|
||||
* filename="file1.txt" => MIXEDDISPOSITION Content-Type: text/plain
|
||||
*
|
||||
* ... contents of file1.txt ... => MIXEDFILEUPLOAD --BbC04y =>
|
||||
* MIXEDDELIMITER Content-disposition: file; filename="file2.gif" =>
|
||||
* MIXEDDISPOSITION Content-type: image/gif Content-Transfer-Encoding:
|
||||
* binary
|
||||
*
|
||||
* ...contents of file2.gif... => MIXEDFILEUPLOAD --BbC04y-- =>
|
||||
* MIXEDCLOSEDELIMITER --AaB03x-- => CLOSEDELIMITER
|
||||
*
|
||||
* Once CLOSEDELIMITER is found, last status is EPILOGUE
|
||||
|
||||
Content-type: multipart/form-data, boundary=AaB03x => PREAMBLE in Header
|
||||
|
||||
--AaB03x => HEADERDELIMITER
|
||||
content-disposition: form-data; name="field1" => DISPOSITION
|
||||
|
||||
Joe Blow => FIELD
|
||||
--AaB03x => HEADERDELIMITER
|
||||
content-disposition: form-data; name="pics" => DISPOSITION
|
||||
Content-type: multipart/mixed, boundary=BbC04y
|
||||
|
||||
--BbC04y => MIXEDDELIMITER
|
||||
Content-disposition: attachment; filename="file1.txt" => MIXEDDISPOSITION
|
||||
Content-Type: text/plain
|
||||
|
||||
... contents of file1.txt ... => MIXEDFILEUPLOAD
|
||||
--BbC04y => MIXEDDELIMITER
|
||||
Content-disposition: file; filename="file2.gif" => MIXEDDISPOSITION
|
||||
Content-type: image/gif
|
||||
Content-Transfer-Encoding: binary
|
||||
|
||||
...contents of file2.gif... => MIXEDFILEUPLOAD
|
||||
--BbC04y-- => MIXEDCLOSEDELIMITER
|
||||
--AaB03x-- => CLOSEDELIMITER
|
||||
|
||||
Once CLOSEDELIMITER is found, last status is EPILOGUE
|
||||
*/
|
||||
private enum MultiPartStatus {
|
||||
NOTSTARTED, PREAMBLE, HEADERDELIMITER, DISPOSITION, FIELD, FILEUPLOAD, MIXEDPREAMBLE, MIXEDDELIMITER, MIXEDDISPOSITION, MIXEDFILEUPLOAD, MIXEDCLOSEDELIMITER, CLOSEDELIMITER, PREEPILOGUE, EPILOGUE
|
||||
NOTSTARTED,
|
||||
PREAMBLE,
|
||||
HEADERDELIMITER,
|
||||
DISPOSITION,
|
||||
FIELD,
|
||||
FILEUPLOAD,
|
||||
MIXEDPREAMBLE,
|
||||
MIXEDDELIMITER,
|
||||
MIXEDDISPOSITION,
|
||||
MIXEDFILEUPLOAD,
|
||||
MIXEDCLOSEDELIMITER,
|
||||
CLOSEDELIMITER,
|
||||
PREEPILOGUE,
|
||||
EPILOGUE
|
||||
}
|
||||
|
||||
/**
|
||||
* Check from the request ContentType if this request is a Multipart
|
||||
* request.
|
||||
*
|
||||
* Check from the request ContentType if this request is a Multipart request.
|
||||
* @param contentType
|
||||
* @throws ErrorDataDecoderException
|
||||
*/
|
||||
@ -259,9 +248,9 @@ public class HttpPostRequestDecoder {
|
||||
// Check if Post using "multipart/form-data; boundary=--89421926422648"
|
||||
String[] headerContentType = splitHeaderContentType(contentType);
|
||||
if (headerContentType[0].toLowerCase().startsWith(
|
||||
MULTIPART_FORM_DATA)
|
||||
&& headerContentType[1].toLowerCase().startsWith(
|
||||
BOUNDARY)) {
|
||||
HttpHeaders.Values.MULTIPART_FORM_DATA) &&
|
||||
headerContentType[1].toLowerCase().startsWith(
|
||||
HttpHeaders.Values.BOUNDARY)) {
|
||||
String[] boundary = headerContentType[1].split("=");
|
||||
if (boundary.length != 2) {
|
||||
throw new ErrorDataDecoderException("Needs a boundary value");
|
||||
@ -276,7 +265,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* True if this request is a Multipart request
|
||||
*
|
||||
* @return True if this request is a Multipart request
|
||||
*/
|
||||
public boolean isMultipart() {
|
||||
@ -286,12 +274,11 @@ public class HttpPostRequestDecoder {
|
||||
/**
|
||||
* This method returns a List of all HttpDatas from body.<br>
|
||||
*
|
||||
* If chunked, all chunks must have been offered using offer() method. If
|
||||
* not, NotEnoughDataDecoderException will be raised.
|
||||
* If chunked, all chunks must have been offered using offer() method.
|
||||
* If not, NotEnoughDataDecoderException will be raised.
|
||||
*
|
||||
* @return the list of HttpDatas from Body part for POST method
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* Need more chunks
|
||||
* @throws NotEnoughDataDecoderException Need more chunks
|
||||
*/
|
||||
public List<InterfaceHttpData> getBodyHttpDatas()
|
||||
throws NotEnoughDataDecoderException {
|
||||
@ -302,16 +289,14 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a List of all HttpDatas with the given name from
|
||||
* body.<br>
|
||||
*
|
||||
* If chunked, all chunks must have been offered using offer() method. If
|
||||
* not, NotEnoughDataDecoderException will be raised.
|
||||
* This method returns a List of all HttpDatas with the given name from body.<br>
|
||||
*
|
||||
* If chunked, all chunks must have been offered using offer() method.
|
||||
* If not, NotEnoughDataDecoderException will be raised.
|
||||
|
||||
* @param name
|
||||
* @return All Body HttpDatas with the given name (ignore case)
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* need more chunks
|
||||
* @throws NotEnoughDataDecoderException need more chunks
|
||||
*/
|
||||
public List<InterfaceHttpData> getBodyHttpDatas(String name)
|
||||
throws NotEnoughDataDecoderException {
|
||||
@ -322,17 +307,14 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the first InterfaceHttpData with the given name from
|
||||
* body.<br>
|
||||
* This method returns the first InterfaceHttpData with the given name from body.<br>
|
||||
*
|
||||
* If chunked, all chunks must have been offered using offer() method. If
|
||||
* not, NotEnoughDataDecoderException will be raised.
|
||||
* If chunked, all chunks must have been offered using offer() method.
|
||||
* If not, NotEnoughDataDecoderException will be raised.
|
||||
*
|
||||
* @param name
|
||||
* @return The first Body InterfaceHttpData with the given name (ignore
|
||||
* case)
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* need more chunks
|
||||
* @return The first Body InterfaceHttpData with the given name (ignore case)
|
||||
* @throws NotEnoughDataDecoderException need more chunks
|
||||
*/
|
||||
public InterfaceHttpData getBodyHttpData(String name)
|
||||
throws NotEnoughDataDecoderException {
|
||||
@ -348,23 +330,19 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Initialized the internals from a new chunk
|
||||
*
|
||||
* @param chunk
|
||||
* the new received chunk
|
||||
* @throws ErrorDataDecoderException
|
||||
* if there is a problem with the charset decoding or other
|
||||
* errors
|
||||
* @param chunk the new received chunk
|
||||
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
|
||||
* other errors
|
||||
*/
|
||||
public void offer(HttpChunk chunk) throws ErrorDataDecoderException {
|
||||
ChannelBuffer chunked = chunk.getContent();
|
||||
if (undecodedChunk == null) {
|
||||
undecodedChunk = chunked;
|
||||
} else {
|
||||
// undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk,
|
||||
// chunk.getContent());
|
||||
//undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk, chunk.getContent());
|
||||
// less memory usage
|
||||
undecodedChunk = ChannelBuffers.wrappedBuffer(undecodedChunk,
|
||||
chunked);
|
||||
undecodedChunk = ChannelBuffers.wrappedBuffer(
|
||||
undecodedChunk, chunked);
|
||||
}
|
||||
if (chunk.isLast()) {
|
||||
isLastChunk = true;
|
||||
@ -373,14 +351,12 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* True if at current status, there is an available decoded
|
||||
* InterfaceHttpData from the Body.
|
||||
* True if at current status, there is an available decoded InterfaceHttpData from the Body.
|
||||
*
|
||||
* This method works for chunked and not chunked request.
|
||||
*
|
||||
* @return True if at current status, there is a decoded InterfaceHttpData
|
||||
* @throws EndOfDataDecoderException
|
||||
* No more data will be available
|
||||
* @throws EndOfDataDecoderException No more data will be available
|
||||
*/
|
||||
public boolean hasNext() throws EndOfDataDecoderException {
|
||||
if (currentStatus == MultiPartStatus.EPILOGUE) {
|
||||
@ -389,18 +365,16 @@ public class HttpPostRequestDecoder {
|
||||
throw new EndOfDataDecoderException();
|
||||
}
|
||||
}
|
||||
return bodyListHttpData.size() > 0
|
||||
&& bodyListHttpDataRank < bodyListHttpData.size();
|
||||
return bodyListHttpData.size() > 0 &&
|
||||
bodyListHttpDataRank < bodyListHttpData.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available InterfaceHttpData or null if, at the time it
|
||||
* is called, there is no more available InterfaceHttpData. A subsequent
|
||||
* call to offer(httpChunk) could enable more data.
|
||||
* Returns the next available InterfaceHttpData or null if, at the time it is called, there is no more
|
||||
* available InterfaceHttpData. A subsequent call to offer(httpChunk) could enable more data.
|
||||
*
|
||||
* @return the next available InterfaceHttpData or null if none
|
||||
* @throws EndOfDataDecoderException
|
||||
* No more data will be available
|
||||
* @throws EndOfDataDecoderException No more data will be available
|
||||
*/
|
||||
public InterfaceHttpData next() throws EndOfDataDecoderException {
|
||||
if (hasNext()) {
|
||||
@ -411,14 +385,12 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* This method will parse as much as possible data and fill the list and map
|
||||
*
|
||||
* @throws ErrorDataDecoderException
|
||||
* if there is a problem with the charset decoding or other
|
||||
* errors
|
||||
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
|
||||
* other errors
|
||||
*/
|
||||
private void parseBody() throws ErrorDataDecoderException {
|
||||
if (currentStatus == MultiPartStatus.PREEPILOGUE
|
||||
|| currentStatus == MultiPartStatus.EPILOGUE) {
|
||||
if (currentStatus == MultiPartStatus.PREEPILOGUE ||
|
||||
currentStatus == MultiPartStatus.EPILOGUE) {
|
||||
if (isLastChunk) {
|
||||
currentStatus = MultiPartStatus.EPILOGUE;
|
||||
}
|
||||
@ -433,7 +405,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Utility function to add a new decoded data
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
private void addHttpData(InterfaceHttpData data) {
|
||||
@ -450,12 +421,11 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method fill the map and list with as much Attribute as possible from
|
||||
* Body in not Multipart mode.
|
||||
* This method fill the map and list with as much Attribute as possible from Body in
|
||||
* not Multipart mode.
|
||||
*
|
||||
* @throws ErrorDataDecoderException
|
||||
* if there is a problem with the charset decoding or other
|
||||
* errors
|
||||
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or
|
||||
* other errors
|
||||
*/
|
||||
private void parseBodyAttributes() throws ErrorDataDecoderException {
|
||||
int firstpos = undecodedChunk.readerIndex();
|
||||
@ -476,19 +446,15 @@ public class HttpPostRequestDecoder {
|
||||
currentStatus = MultiPartStatus.FIELD;
|
||||
equalpos = currentpos - 1;
|
||||
String key = decodeAttribute(
|
||||
undecodedChunk.toString(firstpos, equalpos
|
||||
- firstpos, charset), charset);
|
||||
currentAttribute = factory
|
||||
.createAttribute(request, key);
|
||||
undecodedChunk.toString(firstpos, equalpos - firstpos, charset),
|
||||
charset);
|
||||
currentAttribute = factory.createAttribute(request, key);
|
||||
firstpos = currentpos;
|
||||
} else if (read == '&') { // special empty FIELD
|
||||
currentStatus = MultiPartStatus.DISPOSITION;
|
||||
ampersandpos = currentpos - 1;
|
||||
String key = decodeAttribute(
|
||||
undecodedChunk.toString(firstpos, ampersandpos
|
||||
- firstpos, charset), charset);
|
||||
currentAttribute = factory
|
||||
.createAttribute(request, key);
|
||||
String key = decodeAttribute(undecodedChunk.toString(firstpos, ampersandpos - firstpos, charset), charset);
|
||||
currentAttribute = factory.createAttribute(request, key);
|
||||
currentAttribute.setValue(""); // empty
|
||||
addHttpData(currentAttribute);
|
||||
currentAttribute = null;
|
||||
@ -500,8 +466,7 @@ public class HttpPostRequestDecoder {
|
||||
if (read == '&') {
|
||||
currentStatus = MultiPartStatus.DISPOSITION;
|
||||
ampersandpos = currentpos - 1;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos,
|
||||
ampersandpos - firstpos));
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
firstpos = currentpos;
|
||||
contRead = true;
|
||||
} else if (read == HttpCodecUtil.CR) {
|
||||
@ -511,15 +476,14 @@ public class HttpPostRequestDecoder {
|
||||
if (read == HttpCodecUtil.LF) {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 2;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos,
|
||||
ampersandpos - firstpos));
|
||||
setFinalBuffer(
|
||||
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
} else {
|
||||
// Error
|
||||
contRead = false;
|
||||
throw new ErrorDataDecoderException(
|
||||
"Bad end of line");
|
||||
throw new ErrorDataDecoderException("Bad end of line");
|
||||
}
|
||||
} else {
|
||||
currentpos--;
|
||||
@ -527,8 +491,8 @@ public class HttpPostRequestDecoder {
|
||||
} else if (read == HttpCodecUtil.LF) {
|
||||
currentStatus = MultiPartStatus.PREEPILOGUE;
|
||||
ampersandpos = currentpos - 1;
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos,
|
||||
ampersandpos - firstpos));
|
||||
setFinalBuffer(
|
||||
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
firstpos = currentpos;
|
||||
contRead = false;
|
||||
}
|
||||
@ -542,9 +506,9 @@ public class HttpPostRequestDecoder {
|
||||
// special case
|
||||
ampersandpos = currentpos;
|
||||
if (ampersandpos > firstpos) {
|
||||
setFinalBuffer(undecodedChunk.slice(firstpos, ampersandpos
|
||||
- firstpos));
|
||||
} else if (!currentAttribute.isCompleted()) {
|
||||
setFinalBuffer(
|
||||
undecodedChunk.slice(firstpos, ampersandpos - firstpos));
|
||||
} else if (! currentAttribute.isCompleted()) {
|
||||
setFinalBuffer(ChannelBuffers.EMPTY_BUFFER);
|
||||
}
|
||||
firstpos = currentpos;
|
||||
@ -555,8 +519,8 @@ public class HttpPostRequestDecoder {
|
||||
// reset index except if to continue in case of FIELD status
|
||||
if (currentStatus == MultiPartStatus.FIELD) {
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(firstpos, currentpos
|
||||
- firstpos), false);
|
||||
undecodedChunk.slice(firstpos, currentpos - firstpos),
|
||||
false);
|
||||
firstpos = currentpos;
|
||||
}
|
||||
undecodedChunk.readerIndex(firstpos);
|
||||
@ -574,11 +538,11 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
private void setFinalBuffer(ChannelBuffer buffer)
|
||||
throws ErrorDataDecoderException, IOException {
|
||||
private void setFinalBuffer(ChannelBuffer buffer) throws ErrorDataDecoderException, IOException {
|
||||
currentAttribute.addContent(buffer, true);
|
||||
String value = decodeAttribute(currentAttribute.getChannelBuffer()
|
||||
.toString(charset), charset);
|
||||
String value = decodeAttribute(
|
||||
currentAttribute.getChannelBuffer().toString(charset),
|
||||
charset);
|
||||
currentAttribute.setValue(value);
|
||||
addHttpData(currentAttribute);
|
||||
currentAttribute = null;
|
||||
@ -586,7 +550,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Decode component
|
||||
*
|
||||
* @param s
|
||||
* @param charset
|
||||
* @return the decoded component
|
||||
@ -607,9 +570,7 @@ public class HttpPostRequestDecoder {
|
||||
/**
|
||||
* Parse the Body for multipart
|
||||
*
|
||||
* @throws ErrorDataDecoderException
|
||||
* if there is a problem with the charset decoding or other
|
||||
* errors
|
||||
* @throws ErrorDataDecoderException if there is a problem with the charset decoding or other errors
|
||||
*/
|
||||
private void parseBodyMultipart() throws ErrorDataDecoderException {
|
||||
if (undecodedChunk == null || undecodedChunk.readableBytes() == 0) {
|
||||
@ -619,8 +580,8 @@ public class HttpPostRequestDecoder {
|
||||
InterfaceHttpData data = decodeMultipart(currentStatus);
|
||||
while (data != null) {
|
||||
addHttpData(data);
|
||||
if (currentStatus == MultiPartStatus.PREEPILOGUE
|
||||
|| currentStatus == MultiPartStatus.EPILOGUE) {
|
||||
if (currentStatus == MultiPartStatus.PREEPILOGUE ||
|
||||
currentStatus == MultiPartStatus.EPILOGUE) {
|
||||
break;
|
||||
}
|
||||
data = decodeMultipart(currentStatus);
|
||||
@ -641,8 +602,7 @@ public class HttpPostRequestDecoder {
|
||||
*
|
||||
* @param state
|
||||
* @return the next decoded InterfaceHttpData or null if none until now.
|
||||
* @throws ErrorDataDecoderException
|
||||
* if an error occurs
|
||||
* @throws ErrorDataDecoderException if an error occurs
|
||||
*/
|
||||
private InterfaceHttpData decodeMultipart(MultiPartStatus state)
|
||||
throws ErrorDataDecoderException {
|
||||
@ -687,8 +647,8 @@ public class HttpPostRequestDecoder {
|
||||
.get(HttpPostBodyUtil.NAME);
|
||||
if (currentAttribute == null) {
|
||||
try {
|
||||
currentAttribute = factory.createAttribute(request,
|
||||
nameAttribute.getValue());
|
||||
currentAttribute = factory.createAttribute(request, nameAttribute
|
||||
.getValue());
|
||||
} catch (NullPointerException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@ -742,13 +702,9 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Find the next Multipart Delimiter
|
||||
*
|
||||
* @param delimiter
|
||||
* delimiter to find
|
||||
* @param dispositionStatus
|
||||
* the next status if the delimiter is a start
|
||||
* @param closeDelimiterStatus
|
||||
* the next status if the delimiter is a close delimiter
|
||||
* @param delimiter delimiter to find
|
||||
* @param dispositionStatus the next status if the delimiter is a start
|
||||
* @param closeDelimiterStatus the next status if the delimiter is a close delimiter
|
||||
* @return the next InterfaceHttpData if any
|
||||
* @throws ErrorDataDecoderException
|
||||
*/
|
||||
@ -787,7 +743,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Find the next Disposition
|
||||
*
|
||||
* @return the next InterfaceHttpData if any
|
||||
* @throws ErrorDataDecoderException
|
||||
*/
|
||||
@ -809,29 +764,25 @@ public class HttpPostRequestDecoder {
|
||||
return null;
|
||||
}
|
||||
String[] contents = splitMultipartHeader(newline);
|
||||
if (contents[0]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.CONTENT_DISPOSITION)) {
|
||||
if (contents[0].equalsIgnoreCase(HttpPostBodyUtil.CONTENT_DISPOSITION)) {
|
||||
boolean checkSecondArg = false;
|
||||
if (currentStatus == MultiPartStatus.DISPOSITION) {
|
||||
checkSecondArg = contents[1]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.FORM_DATA);
|
||||
} else {
|
||||
checkSecondArg = contents[1]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.ATTACHMENT)
|
||||
|| contents[1]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.ATTACHMENT) ||
|
||||
contents[1]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.FILE);
|
||||
}
|
||||
if (checkSecondArg) {
|
||||
// read next values and store them in the map as Attribute
|
||||
for (int i = 2; i < contents.length; i++) {
|
||||
for (int i = 2; i < contents.length; i ++) {
|
||||
String[] values = contents[i].split("=");
|
||||
Attribute attribute;
|
||||
try {
|
||||
attribute = factory.createAttribute(
|
||||
request,
|
||||
values[0].trim(),
|
||||
decodeAttribute(cleanString(values[1]),
|
||||
charset));
|
||||
attribute = factory.createAttribute(request, values[0].trim(),
|
||||
decodeAttribute(cleanString(values[1]), charset));
|
||||
} catch (NullPointerException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@ -869,11 +820,9 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
currentFieldAttributes.put(HttpHeaders.Names.CONTENT_LENGTH,
|
||||
attribute);
|
||||
} else if (contents[0]
|
||||
.equalsIgnoreCase(HttpHeaders.Names.CONTENT_TYPE)) {
|
||||
} else if (contents[0].equalsIgnoreCase(HttpHeaders.Names.CONTENT_TYPE)) {
|
||||
// Take care of possible "multipart/mixed"
|
||||
if (contents[1]
|
||||
.equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
|
||||
if (contents[1].equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
|
||||
if (currentStatus == MultiPartStatus.DISPOSITION) {
|
||||
String[] values = contents[2].split("=");
|
||||
multipartMixedBoundary = "--" + values[1];
|
||||
@ -884,7 +833,7 @@ public class HttpPostRequestDecoder {
|
||||
"Mixed Multipart found in a previous Mixed Multipart");
|
||||
}
|
||||
} else {
|
||||
for (int i = 1; i < contents.length; i++) {
|
||||
for (int i = 1; i < contents.length; i ++) {
|
||||
if (contents[i].toLowerCase().startsWith(
|
||||
HttpHeaders.Values.CHARSET)) {
|
||||
String[] values = contents[i].split("=");
|
||||
@ -898,17 +847,14 @@ public class HttpPostRequestDecoder {
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
currentFieldAttributes.put(
|
||||
HttpHeaders.Values.CHARSET, attribute);
|
||||
currentFieldAttributes.put(HttpHeaders.Values.CHARSET,
|
||||
attribute);
|
||||
} else {
|
||||
Attribute attribute;
|
||||
try {
|
||||
attribute = factory.createAttribute(
|
||||
request,
|
||||
attribute = factory.createAttribute(request,
|
||||
contents[0].trim(),
|
||||
decodeAttribute(
|
||||
cleanString(contents[i]),
|
||||
charset));
|
||||
decodeAttribute(cleanString(contents[i]), charset));
|
||||
} catch (NullPointerException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
} catch (IllegalArgumentException e) {
|
||||
@ -920,8 +866,8 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ErrorDataDecoderException("Unknown Params: "
|
||||
+ newline);
|
||||
throw new ErrorDataDecoderException("Unknown Params: " +
|
||||
newline);
|
||||
}
|
||||
}
|
||||
// Is it a FileUpload
|
||||
@ -954,9 +900,7 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Get the FileUpload (new one or current one)
|
||||
*
|
||||
* @param delimiter
|
||||
* the delimiter to use
|
||||
* @param delimiter the delimiter to use
|
||||
* @return the InterfaceHttpData if any
|
||||
* @throws ErrorDataDecoderException
|
||||
*/
|
||||
@ -978,8 +922,7 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT7.value)) {
|
||||
localCharset = HttpPostBodyUtil.US_ASCII;
|
||||
} else if (code
|
||||
.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value)) {
|
||||
} else if (code.equals(HttpPostBodyUtil.TransferEncodingMechanism.BIT8.value)) {
|
||||
localCharset = HttpPostBodyUtil.ISO_8859_1;
|
||||
mechanism = TransferEncodingMechanism.BIT8;
|
||||
} else if (code
|
||||
@ -1015,7 +958,7 @@ public class HttpPostRequestDecoder {
|
||||
.get(HttpHeaders.Names.CONTENT_LENGTH);
|
||||
long size;
|
||||
try {
|
||||
size = lengthAttribute != null ? Long.parseLong(lengthAttribute
|
||||
size = lengthAttribute != null? Long.parseLong(lengthAttribute
|
||||
.getValue()) : 0L;
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
@ -1023,7 +966,8 @@ public class HttpPostRequestDecoder {
|
||||
size = 0;
|
||||
}
|
||||
try {
|
||||
currentFileUpload = factory.createFileUpload(request,
|
||||
currentFileUpload = factory.createFileUpload(
|
||||
request,
|
||||
nameAttribute.getValue(), filenameAttribute.getValue(),
|
||||
contentTypeAttribute.getValue(), mechanism.value,
|
||||
localCharset, size);
|
||||
@ -1078,25 +1022,21 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all Attributes that should be cleaned between two FileUpload in
|
||||
* Mixed mode
|
||||
* Remove all Attributes that should be cleaned between two FileUpload in Mixed mode
|
||||
*/
|
||||
private void cleanMixedAttributes() {
|
||||
currentFieldAttributes.remove(HttpHeaders.Values.CHARSET);
|
||||
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_LENGTH);
|
||||
currentFieldAttributes
|
||||
.remove(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING);
|
||||
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TRANSFER_ENCODING);
|
||||
currentFieldAttributes.remove(HttpHeaders.Names.CONTENT_TYPE);
|
||||
currentFieldAttributes.remove(HttpPostBodyUtil.FILENAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one line up to the CRLF or LF
|
||||
*
|
||||
* @return the String from one line
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* Need more chunks and reset the readerInder to the previous
|
||||
* value
|
||||
* @throws NotEnoughDataDecoderException Need more chunks and
|
||||
* reset the readerInder to the previous value
|
||||
*/
|
||||
private String readLine() throws NotEnoughDataDecoderException {
|
||||
int readerIndex = undecodedChunk.readerIndex();
|
||||
@ -1126,13 +1066,10 @@ public class HttpPostRequestDecoder {
|
||||
/**
|
||||
* Read a FileUpload data as Byte (Binary) and add the bytes directly to the
|
||||
* FileUpload. If the delimiter is found, the FileUpload is completed.
|
||||
*
|
||||
* @param delimiter
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* Need more chunks but do not reset the readerInder since some
|
||||
* values will be already added to the FileOutput
|
||||
* @throws ErrorDataDecoderException
|
||||
* write IO error occurs with the FileUpload
|
||||
* @throws NotEnoughDataDecoderException Need more chunks but
|
||||
* do not reset the readerInder since some values will be already added to the FileOutput
|
||||
* @throws ErrorDataDecoderException write IO error occurs with the FileUpload
|
||||
*/
|
||||
private void readFileUploadByteMultipart(String delimiter)
|
||||
throws NotEnoughDataDecoderException, ErrorDataDecoderException {
|
||||
@ -1147,7 +1084,7 @@ public class HttpPostRequestDecoder {
|
||||
if (newLine) {
|
||||
// Check the delimiter
|
||||
if (nextByte == delimiter.codePointAt(index)) {
|
||||
index++;
|
||||
index ++;
|
||||
if (delimiter.length() == index) {
|
||||
found = true;
|
||||
break;
|
||||
@ -1196,8 +1133,8 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
}
|
||||
}
|
||||
ChannelBuffer buffer = undecodedChunk.slice(readerIndex, lastPosition
|
||||
- readerIndex);
|
||||
ChannelBuffer buffer = undecodedChunk.slice(readerIndex, lastPosition -
|
||||
readerIndex);
|
||||
if (found) {
|
||||
// found so lastPosition is correct and final
|
||||
try {
|
||||
@ -1208,8 +1145,7 @@ public class HttpPostRequestDecoder {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
} else {
|
||||
// possibly the delimiter is partially found but still the last
|
||||
// position is OK
|
||||
// possibly the delimiter is partially found but still the last position is OK
|
||||
try {
|
||||
currentFileUpload.addContent(buffer, false);
|
||||
// last valid char (not CR, not LF, not beginning of delimiter)
|
||||
@ -1223,9 +1159,7 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Load the field value from a Multipart request
|
||||
*
|
||||
* @throws NotEnoughDataDecoderException
|
||||
* Need more chunks
|
||||
* @throws NotEnoughDataDecoderException Need more chunks
|
||||
* @throws ErrorDataDecoderException
|
||||
*/
|
||||
private void loadFieldMultipart(String delimiter)
|
||||
@ -1242,7 +1176,7 @@ public class HttpPostRequestDecoder {
|
||||
if (newLine) {
|
||||
// Check the delimiter
|
||||
if (nextByte == delimiter.codePointAt(index)) {
|
||||
index++;
|
||||
index ++;
|
||||
if (delimiter.length() == index) {
|
||||
found = true;
|
||||
break;
|
||||
@ -1291,13 +1225,12 @@ public class HttpPostRequestDecoder {
|
||||
}
|
||||
if (found) {
|
||||
// found so lastPosition is correct
|
||||
// but position is just after the delimiter (either close
|
||||
// delimiter or simple one)
|
||||
// but position is just after the delimiter (either close delimiter or simple one)
|
||||
// so go back of delimiter size
|
||||
try {
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition
|
||||
- readerIndex), true);
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex),
|
||||
true);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
@ -1305,8 +1238,8 @@ public class HttpPostRequestDecoder {
|
||||
} else {
|
||||
try {
|
||||
currentAttribute.addContent(
|
||||
undecodedChunk.slice(readerIndex, lastPosition
|
||||
- readerIndex), false);
|
||||
undecodedChunk.slice(readerIndex, lastPosition - readerIndex),
|
||||
false);
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataDecoderException(e);
|
||||
}
|
||||
@ -1321,13 +1254,12 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Clean the String from any unallowed character
|
||||
*
|
||||
* @return the cleaned String
|
||||
*/
|
||||
private String cleanString(String field) {
|
||||
StringBuilder sb = new StringBuilder(field.length());
|
||||
int i = 0;
|
||||
for (i = 0; i < field.length(); i++) {
|
||||
for (i = 0; i < field.length(); i ++) {
|
||||
char nextChar = field.charAt(i);
|
||||
if (nextChar == HttpCodecUtil.COLON) {
|
||||
sb.append(HttpCodecUtil.SP);
|
||||
@ -1350,7 +1282,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Skip one empty line
|
||||
*
|
||||
* @return True if one empty line was skipped
|
||||
*/
|
||||
private boolean skipOneLine() {
|
||||
@ -1378,7 +1309,6 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Split the very first line (Content-Type value) in 2 Strings
|
||||
*
|
||||
* @param sb
|
||||
* @return the array of 2 Strings
|
||||
*/
|
||||
@ -1394,7 +1324,7 @@ public class HttpPostRequestDecoder {
|
||||
return new String[] { sb, "" };
|
||||
}
|
||||
if (sb.charAt(aEnd) == ';') {
|
||||
aEnd--;
|
||||
aEnd --;
|
||||
}
|
||||
bStart = HttpPostBodyUtil.findNonWhitespace(sb, aEnd);
|
||||
bEnd = HttpPostBodyUtil.findEndOfString(sb);
|
||||
@ -1404,10 +1334,9 @@ public class HttpPostRequestDecoder {
|
||||
|
||||
/**
|
||||
* Split one header in Multipart
|
||||
*
|
||||
* @param sb
|
||||
* @return an array of String where rank 0 is the name of the header,
|
||||
* follows by several values that were separated by ';' or ','
|
||||
* @return an array of String where rank 0 is the name of the header, follows by several
|
||||
* values that were separated by ';' or ','
|
||||
*/
|
||||
private String[] splitMultipartHeader(String sb) {
|
||||
ArrayList<String> headers = new ArrayList<String>(1);
|
||||
@ -1417,15 +1346,15 @@ public class HttpPostRequestDecoder {
|
||||
int valueStart;
|
||||
int valueEnd;
|
||||
nameStart = HttpPostBodyUtil.findNonWhitespace(sb, 0);
|
||||
for (nameEnd = nameStart; nameEnd < sb.length(); nameEnd++) {
|
||||
for (nameEnd = nameStart; nameEnd < sb.length(); nameEnd ++) {
|
||||
char ch = sb.charAt(nameEnd);
|
||||
if (ch == ':' || Character.isWhitespace(ch)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (colonEnd = nameEnd; colonEnd < sb.length(); colonEnd++) {
|
||||
for (colonEnd = nameEnd; colonEnd < sb.length(); colonEnd ++) {
|
||||
if (sb.charAt(colonEnd) == ':') {
|
||||
colonEnd++;
|
||||
colonEnd ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1439,19 +1368,19 @@ public class HttpPostRequestDecoder {
|
||||
} else {
|
||||
values = svalue.split(",");
|
||||
}
|
||||
for (String value : values) {
|
||||
for (String value: values) {
|
||||
headers.add(value.trim());
|
||||
}
|
||||
String[] array = new String[headers.size()];
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
for (int i = 0; i < headers.size(); i ++) {
|
||||
array[i] = headers.get(i);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception when try reading data from request in chunked format, and not
|
||||
* enough data are available (need more chunks)
|
||||
* Exception when try reading data from request in chunked format, and not enough
|
||||
* data are available (need more chunks)
|
||||
*/
|
||||
public static class NotEnoughDataDecoderException extends Exception {
|
||||
/**
|
||||
|
@ -73,8 +73,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
private String multipartDataBoundary;
|
||||
|
||||
/**
|
||||
* If multipart, there could be internal multiparts (mixed) to the global
|
||||
* multipart. Only one level is allowed.
|
||||
* If multipart, there could be internal multiparts (mixed) to the global multipart.
|
||||
* Only one level is allowed.
|
||||
*/
|
||||
private String multipartMixedBoundary;
|
||||
/**
|
||||
@ -84,14 +84,10 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
* the request to encode
|
||||
* @param multipart
|
||||
* True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @throws NullPointerException
|
||||
* for request
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the request is not a POST
|
||||
* @param request the request to encode
|
||||
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @throws NullPointerException for request
|
||||
* @throws ErrorDataEncoderException if the request is not a POST
|
||||
*/
|
||||
public HttpPostRequestEncoder(HttpRequest request, boolean multipart)
|
||||
throws ErrorDataEncoderException {
|
||||
@ -101,40 +97,28 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param factory
|
||||
* the factory used to create InterfaceHttpData
|
||||
* @param request
|
||||
* the request to encode
|
||||
* @param multipart
|
||||
* True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @throws NullPointerException
|
||||
* for request and factory
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the request is not a POST
|
||||
* @param factory the factory used to create InterfaceHttpData
|
||||
* @param request the request to encode
|
||||
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @throws NullPointerException for request and factory
|
||||
* @throws ErrorDataEncoderException if the request is not a POST
|
||||
*/
|
||||
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request,
|
||||
boolean multipart) throws ErrorDataEncoderException {
|
||||
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request, boolean multipart)
|
||||
throws ErrorDataEncoderException {
|
||||
this(factory, request, multipart, HttpCodecUtil.DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param factory
|
||||
* the factory used to create InterfaceHttpData
|
||||
* @param request
|
||||
* the request to encode
|
||||
* @param multipart
|
||||
* True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @param charset
|
||||
* the charset to use as default
|
||||
* @throws NullPointerException
|
||||
* for request or charset or factory
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the request is not a POST
|
||||
* @param factory the factory used to create InterfaceHttpData
|
||||
* @param request the request to encode
|
||||
* @param multipart True if the FORM is a ENCTYPE="multipart/form-data"
|
||||
* @param charset the charset to use as default
|
||||
* @throws NullPointerException for request or charset or factory
|
||||
* @throws ErrorDataEncoderException if the request is not a POST
|
||||
*/
|
||||
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request,
|
||||
boolean multipart, Charset charset)
|
||||
throws ErrorDataEncoderException {
|
||||
boolean multipart, Charset charset) throws ErrorDataEncoderException {
|
||||
if (factory == null) {
|
||||
throw new NullPointerException("factory");
|
||||
}
|
||||
@ -145,8 +129,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
throw new NullPointerException("charset");
|
||||
}
|
||||
if (request.getMethod() != HttpMethod.POST) {
|
||||
throw new ErrorDataEncoderException(
|
||||
"Cannot create a Encoder if not a POST");
|
||||
throw new ErrorDataEncoderException("Cannot create a Encoder if not a POST");
|
||||
}
|
||||
this.request = request;
|
||||
this.charset = charset;
|
||||
@ -171,8 +154,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the last non empty chunk already encoded so that next chunk will be
|
||||
* empty (last chunk)
|
||||
* Does the last non empty chunk already encoded so that next chunk will be empty (last chunk)
|
||||
*/
|
||||
private boolean isLastChunk;
|
||||
/**
|
||||
@ -195,7 +177,6 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* True if this request is a Multipart request
|
||||
*
|
||||
* @return True if this request is a Multipart request
|
||||
*/
|
||||
public boolean isMultipart() {
|
||||
@ -228,7 +209,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* This method returns a List of all InterfaceHttpData from body part.<br>
|
||||
*
|
||||
|
||||
* @return the list of InterfaceHttpData from Body part
|
||||
*/
|
||||
public List<InterfaceHttpData> getBodyListAttributes() {
|
||||
@ -237,13 +218,9 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* Set the Body HttpDatas list
|
||||
*
|
||||
* @param datas
|
||||
* @throws NullPointerException
|
||||
* for datas
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* @throws NullPointerException for datas
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public void setBodyHttpDatas(List<InterfaceHttpData> datas)
|
||||
throws ErrorDataEncoderException {
|
||||
@ -255,23 +232,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
currentFileUpload = null;
|
||||
duringMixedMode = false;
|
||||
multipartHttpDatas.clear();
|
||||
for (InterfaceHttpData data : datas) {
|
||||
for (InterfaceHttpData data: datas) {
|
||||
addBodyHttpData(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a simple attribute in the body as Name=Value
|
||||
*
|
||||
* @param name
|
||||
* name of the parameter
|
||||
* @param value
|
||||
* the value of the parameter
|
||||
* @throws NullPointerException
|
||||
* for name
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* @param name name of the parameter
|
||||
* @param value the value of the parameter
|
||||
* @throws NullPointerException for name
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public void addBodyAttribute(String name, String value)
|
||||
throws ErrorDataEncoderException {
|
||||
@ -288,25 +259,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* Add a file as a FileUpload
|
||||
*
|
||||
* @param name
|
||||
* the name of the parameter
|
||||
* @param file
|
||||
* the file to be uploaded (if not Multipart mode, only the
|
||||
* filename will be included)
|
||||
* @param contentType
|
||||
* the associated contentType for the File
|
||||
* @param isText
|
||||
* True if this file should be transmitted in Text format (else
|
||||
* binary)
|
||||
* @throws NullPointerException
|
||||
* for name and file
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* @param name the name of the parameter
|
||||
* @param file the file to be uploaded (if not Multipart mode, only the filename will be included)
|
||||
* @param contentType the associated contentType for the File
|
||||
* @param isText True if this file should be transmitted in Text format (else binary)
|
||||
* @throws NullPointerException for name and file
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public void addBodyFileUpload(String name, File file, String contentType,
|
||||
boolean isText) throws ErrorDataEncoderException {
|
||||
public void addBodyFileUpload(String name, File file, String contentType, boolean isText)
|
||||
throws ErrorDataEncoderException {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
}
|
||||
@ -325,9 +286,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
if (!isText) {
|
||||
contentTransferEncoding = HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value;
|
||||
}
|
||||
FileUpload fileUpload = factory.createFileUpload(request, name,
|
||||
file.getName(), scontentType, contentTransferEncoding, null,
|
||||
file.length());
|
||||
FileUpload fileUpload = factory.createFileUpload(request, name, file.getName(),
|
||||
scontentType, contentTransferEncoding, null, file.length());
|
||||
try {
|
||||
fileUpload.setContent(file);
|
||||
} catch (IOException e) {
|
||||
@ -337,26 +297,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a series of Files associated with one File parameter (implied Mixed
|
||||
* mode in Multipart)
|
||||
*
|
||||
* @param name
|
||||
* the name of the parameter
|
||||
* @param file
|
||||
* the array of files
|
||||
* @param contentType
|
||||
* the array of content Types associated with each file
|
||||
* @param isText
|
||||
* the array of isText attribute (False meaning binary mode) for
|
||||
* each file
|
||||
* @throws NullPointerException
|
||||
* also throws if array have different sizes
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* Add a series of Files associated with one File parameter (implied Mixed mode in Multipart)
|
||||
* @param name the name of the parameter
|
||||
* @param file the array of files
|
||||
* @param contentType the array of content Types associated with each file
|
||||
* @param isText the array of isText attribute (False meaning binary mode) for each file
|
||||
* @throws NullPointerException also throws if array have different sizes
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public void addBodyFileUploads(String name, File[] file,
|
||||
String[] contentType, boolean[] isText)
|
||||
public void addBodyFileUploads(String name, File[] file, String[] contentType, boolean[] isText)
|
||||
throws ErrorDataEncoderException {
|
||||
if (file.length != contentType.length && file.length != isText.length) {
|
||||
throw new NullPointerException("Different array length");
|
||||
@ -368,37 +317,30 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* Add the InterfaceHttpData to the Body list
|
||||
*
|
||||
* @param data
|
||||
* @throws NullPointerException
|
||||
* for data
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* @throws NullPointerException for data
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public void addBodyHttpData(InterfaceHttpData data)
|
||||
throws ErrorDataEncoderException {
|
||||
if (headerFinalized) {
|
||||
throw new ErrorDataEncoderException(
|
||||
"Cannot add value once finalized");
|
||||
throw new ErrorDataEncoderException("Cannot add value once finalized");
|
||||
}
|
||||
if (data == null) {
|
||||
throw new NullPointerException("data");
|
||||
}
|
||||
bodyListDatas.add(data);
|
||||
if (!isMultipart) {
|
||||
if (! isMultipart) {
|
||||
if (data instanceof Attribute) {
|
||||
Attribute attribute = (Attribute) data;
|
||||
try {
|
||||
// name=value& with encoded name and attribute
|
||||
String key = encodeAttribute(attribute.getName(), charset);
|
||||
String value = encodeAttribute(attribute.getValue(),
|
||||
charset);
|
||||
Attribute newattribute = factory.createAttribute(request,
|
||||
key, value);
|
||||
String value = encodeAttribute(attribute.getValue(), charset);
|
||||
Attribute newattribute = factory.createAttribute(request, key, value);
|
||||
multipartHttpDatas.add(newattribute);
|
||||
globalBodySize += newattribute.getName().length() + 1
|
||||
+ newattribute.length() + 1;
|
||||
globalBodySize += newattribute.getName().length() + 1 +
|
||||
newattribute.length() + 1;
|
||||
} catch (IOException e) {
|
||||
throw new ErrorDataEncoderException(e);
|
||||
}
|
||||
@ -407,35 +349,45 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
FileUpload fileUpload = (FileUpload) data;
|
||||
// name=filename& with encoded name and filename
|
||||
String key = encodeAttribute(fileUpload.getName(), charset);
|
||||
String value = encodeAttribute(fileUpload.getFilename(),
|
||||
charset);
|
||||
Attribute newattribute = factory.createAttribute(request, key,
|
||||
value);
|
||||
String value = encodeAttribute(fileUpload.getFilename(), charset);
|
||||
Attribute newattribute = factory.createAttribute(request, key, value);
|
||||
multipartHttpDatas.add(newattribute);
|
||||
globalBodySize += newattribute.getName().length() + 1
|
||||
+ newattribute.length() + 1;
|
||||
globalBodySize += newattribute.getName().length() + 1 +
|
||||
newattribute.length() + 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Logic: if not Attribute: add Data to body list if (duringMixedMode)
|
||||
* add endmixedmultipart delimiter currentFileUpload = null
|
||||
* duringMixedMode = false; add multipart delimiter, multipart body
|
||||
* header and Data to multipart list reset currentFileUpload,
|
||||
* duringMixedMode if FileUpload: take care of multiple file for one
|
||||
* field => mixed mode if (duringMixeMode) if (currentFileUpload.name ==
|
||||
* data.name) add mixedmultipart delimiter, mixedmultipart body header
|
||||
* and Data to multipart list else add endmixedmultipart delimiter,
|
||||
* multipart body header and Data to multipart list currentFileUpload =
|
||||
* data duringMixedMode = false; else if (currentFileUpload.name ==
|
||||
* data.name) change multipart body header of previous file into
|
||||
* multipart list to mixedmultipart start, mixedmultipart body header
|
||||
* add mixedmultipart delimiter, mixedmultipart body header and Data to
|
||||
* multipart list duringMixedMode = true else add multipart delimiter,
|
||||
* multipart body header and Data to multipart list currentFileUpload =
|
||||
* data duringMixedMode = false; Do not add last delimiter! Could be: if
|
||||
* duringmixedmode: endmixedmultipart + endmultipart else only
|
||||
* endmultipart
|
||||
* Logic:
|
||||
* if not Attribute:
|
||||
* add Data to body list
|
||||
* if (duringMixedMode)
|
||||
* add endmixedmultipart delimiter
|
||||
* currentFileUpload = null
|
||||
* duringMixedMode = false;
|
||||
* add multipart delimiter, multipart body header and Data to multipart list
|
||||
* reset currentFileUpload, duringMixedMode
|
||||
* if FileUpload: take care of multiple file for one field => mixed mode
|
||||
* if (duringMixeMode)
|
||||
* if (currentFileUpload.name == data.name)
|
||||
* add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list
|
||||
* else
|
||||
* add endmixedmultipart delimiter, multipart body header and Data to multipart list
|
||||
* currentFileUpload = data
|
||||
* duringMixedMode = false;
|
||||
* else
|
||||
* if (currentFileUpload.name == data.name)
|
||||
* change multipart body header of previous file into multipart list to
|
||||
* mixedmultipart start, mixedmultipart body header
|
||||
* add mixedmultipart delimiter, mixedmultipart body header and Data to multipart list
|
||||
* duringMixedMode = true
|
||||
* else
|
||||
* add multipart delimiter, multipart body header and Data to multipart list
|
||||
* currentFileUpload = data
|
||||
* duringMixedMode = false;
|
||||
* Do not add last delimiter! Could be:
|
||||
* if duringmixedmode: endmixedmultipart + endmultipart
|
||||
* else only endmultipart
|
||||
*/
|
||||
if (data instanceof Attribute) {
|
||||
if (duringMixedMode) {
|
||||
@ -454,16 +406,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
internal.addValue("--" + multipartDataBoundary + "\r\n");
|
||||
// content-disposition: form-data; name="field1"
|
||||
Attribute attribute = (Attribute) data;
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
|
||||
+ HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME
|
||||
+ "=\"" + encodeAttribute(attribute.getName(), charset)
|
||||
+ "\"\r\n");
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
|
||||
HttpPostBodyUtil.FORM_DATA + "; " +
|
||||
HttpPostBodyUtil.NAME + "=\"" +
|
||||
encodeAttribute(attribute.getName(), charset) + "\"\r\n");
|
||||
Charset localcharset = attribute.getCharset();
|
||||
if (localcharset != null) {
|
||||
// Content-Type: charset=charset
|
||||
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": "
|
||||
+ HttpHeaders.Values.CHARSET + "=" + localcharset
|
||||
+ "\r\n");
|
||||
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " +
|
||||
HttpHeaders.Values.CHARSET + "=" + localcharset + "\r\n");
|
||||
}
|
||||
// CRLF between body header and data
|
||||
internal.addValue("\r\n");
|
||||
@ -479,23 +430,20 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
boolean localMixed = false;
|
||||
if (duringMixedMode) {
|
||||
if (currentFileUpload != null
|
||||
&& currentFileUpload.getName().equals(
|
||||
fileUpload.getName())) {
|
||||
if (currentFileUpload != null &&
|
||||
currentFileUpload.getName().equals(fileUpload.getName())) {
|
||||
// continue a mixed mode
|
||||
|
||||
localMixed = true;
|
||||
} else {
|
||||
// end a mixed mode
|
||||
|
||||
// add endmixedmultipart delimiter, multipart body header
|
||||
// and
|
||||
// add endmixedmultipart delimiter, multipart body header and
|
||||
// Data to multipart list
|
||||
internal.addValue("--" + multipartMixedBoundary + "--");
|
||||
multipartHttpDatas.add(internal);
|
||||
multipartMixedBoundary = null;
|
||||
// start a new one (could be replaced if mixed start again
|
||||
// from here
|
||||
// start a new one (could be replaced if mixed start again from here
|
||||
internal = new InternalAttribute();
|
||||
internal.addValue("\r\n");
|
||||
localMixed = false;
|
||||
@ -504,20 +452,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
duringMixedMode = false;
|
||||
}
|
||||
} else {
|
||||
if (currentFileUpload != null
|
||||
&& currentFileUpload.getName().equals(
|
||||
fileUpload.getName())) {
|
||||
if (currentFileUpload != null &&
|
||||
currentFileUpload.getName().equals(fileUpload.getName())) {
|
||||
// create a new mixed mode (from previous file)
|
||||
|
||||
// change multipart body header of previous file into
|
||||
// multipart list to
|
||||
// change multipart body header of previous file into multipart list to
|
||||
// mixedmultipart start, mixedmultipart body header
|
||||
|
||||
// change Internal (size()-2 position in multipartHttpDatas)
|
||||
// from (line starting with *)
|
||||
// --AaB03x
|
||||
// * Content-Disposition: form-data; name="files";
|
||||
// filename="file1.txt"
|
||||
// * Content-Disposition: form-data; name="files"; filename="file1.txt"
|
||||
// Content-Type: text/plain
|
||||
// to (lines starting with *)
|
||||
// --AaB03x
|
||||
@ -528,42 +473,33 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
// * Content-Disposition: file; filename="file1.txt"
|
||||
// Content-Type: text/plain
|
||||
initMixedMultipart();
|
||||
InternalAttribute pastAttribute = (InternalAttribute) multipartHttpDatas
|
||||
.get(multipartHttpDatas.size() - 2);
|
||||
InternalAttribute pastAttribute =
|
||||
(InternalAttribute) multipartHttpDatas.get(multipartHttpDatas.size() - 2);
|
||||
// remove past size
|
||||
globalBodySize -= pastAttribute.size();
|
||||
String replacement = HttpPostBodyUtil.CONTENT_DISPOSITION
|
||||
+ ": " + HttpPostBodyUtil.FORM_DATA + "; "
|
||||
+ HttpPostBodyUtil.NAME + "=\""
|
||||
+ encodeAttribute(fileUpload.getName(), charset)
|
||||
+ "\"\r\n";
|
||||
replacement += HttpHeaders.Names.CONTENT_TYPE + ": "
|
||||
+ HttpPostBodyUtil.MULTIPART_MIXED + "; "
|
||||
+ HttpHeaders.Values.BOUNDARY + "="
|
||||
+ multipartMixedBoundary + "\r\n\r\n";
|
||||
String replacement = HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
|
||||
HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" +
|
||||
encodeAttribute(fileUpload.getName(), charset) + "\"\r\n";
|
||||
replacement += HttpHeaders.Names.CONTENT_TYPE + ": " +
|
||||
HttpPostBodyUtil.MULTIPART_MIXED + "; " + HttpHeaders.Values.BOUNDARY +
|
||||
"=" + multipartMixedBoundary + "\r\n\r\n";
|
||||
replacement += "--" + multipartMixedBoundary + "\r\n";
|
||||
replacement += HttpPostBodyUtil.CONTENT_DISPOSITION
|
||||
+ ": "
|
||||
+ HttpPostBodyUtil.FILE
|
||||
+ "; "
|
||||
+ HttpPostBodyUtil.FILENAME
|
||||
+ "=\""
|
||||
+ encodeAttribute(fileUpload.getFilename(), charset)
|
||||
+ "\"\r\n";
|
||||
replacement += HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
|
||||
HttpPostBodyUtil.FILE + "; " + HttpPostBodyUtil.FILENAME + "=\"" +
|
||||
encodeAttribute(fileUpload.getFilename(), charset) +
|
||||
"\"\r\n";
|
||||
pastAttribute.setValue(replacement, 1);
|
||||
// update past size
|
||||
globalBodySize += pastAttribute.size();
|
||||
|
||||
// now continue
|
||||
// add mixedmultipart delimiter, mixedmultipart body header
|
||||
// and
|
||||
// add mixedmultipart delimiter, mixedmultipart body header and
|
||||
// Data to multipart list
|
||||
localMixed = true;
|
||||
duringMixedMode = true;
|
||||
} else {
|
||||
// a simple new multipart
|
||||
// add multipart delimiter, multipart body header and Data
|
||||
// to multipart list
|
||||
//add multipart delimiter, multipart body header and Data to multipart list
|
||||
localMixed = false;
|
||||
currentFileUpload = fileUpload;
|
||||
duringMixedMode = false;
|
||||
@ -575,42 +511,36 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
// Data to multipart list
|
||||
internal.addValue("--" + multipartMixedBoundary + "\r\n");
|
||||
// Content-Disposition: file; filename="file1.txt"
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
|
||||
+ HttpPostBodyUtil.FILE + "; "
|
||||
+ HttpPostBodyUtil.FILENAME + "=\""
|
||||
+ encodeAttribute(fileUpload.getFilename(), charset)
|
||||
+ "\"\r\n");
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
|
||||
HttpPostBodyUtil.FILE + "; " + HttpPostBodyUtil.FILENAME + "=\"" +
|
||||
encodeAttribute(fileUpload.getFilename(), charset) +
|
||||
"\"\r\n");
|
||||
|
||||
} else {
|
||||
internal.addValue("--" + multipartDataBoundary + "\r\n");
|
||||
// Content-Disposition: form-data; name="files";
|
||||
// filename="file1.txt"
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": "
|
||||
+ HttpPostBodyUtil.FORM_DATA + "; "
|
||||
+ HttpPostBodyUtil.NAME + "=\""
|
||||
+ encodeAttribute(fileUpload.getName(), charset)
|
||||
+ "\"; " + HttpPostBodyUtil.FILENAME + "=\""
|
||||
+ encodeAttribute(fileUpload.getFilename(), charset)
|
||||
+ "\"\r\n");
|
||||
// Content-Disposition: form-data; name="files"; filename="file1.txt"
|
||||
internal.addValue(HttpPostBodyUtil.CONTENT_DISPOSITION + ": " +
|
||||
HttpPostBodyUtil.FORM_DATA + "; " + HttpPostBodyUtil.NAME + "=\"" +
|
||||
encodeAttribute(fileUpload.getName(), charset) + "\"; " +
|
||||
HttpPostBodyUtil.FILENAME + "=\"" +
|
||||
encodeAttribute(fileUpload.getFilename(), charset) +
|
||||
"\"\r\n");
|
||||
}
|
||||
// Content-Type: image/gif
|
||||
// Content-Type: text/plain; charset=ISO-8859-1
|
||||
// Content-Transfer-Encoding: binary
|
||||
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": "
|
||||
+ fileUpload.getContentType());
|
||||
String contentTransferEncoding = fileUpload
|
||||
.getContentTransferEncoding();
|
||||
if (contentTransferEncoding != null
|
||||
&& contentTransferEncoding
|
||||
.equals(HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value)) {
|
||||
internal.addValue("\r\n"
|
||||
+ HttpHeaders.Names.CONTENT_TRANSFER_ENCODING
|
||||
+ ": "
|
||||
+ HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value
|
||||
+ "\r\n\r\n");
|
||||
internal.addValue(HttpHeaders.Names.CONTENT_TYPE + ": " +
|
||||
fileUpload.getContentType());
|
||||
String contentTransferEncoding = fileUpload.getContentTransferEncoding();
|
||||
if (contentTransferEncoding != null &&
|
||||
contentTransferEncoding.equals(
|
||||
HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value)) {
|
||||
internal.addValue("\r\n" + HttpHeaders.Names.CONTENT_TRANSFER_ENCODING +
|
||||
": " + HttpPostBodyUtil.TransferEncodingMechanism.BINARY.value +
|
||||
"\r\n\r\n");
|
||||
} else if (fileUpload.getCharset() != null) {
|
||||
internal.addValue("; " + HttpHeaders.Values.CHARSET + "="
|
||||
+ fileUpload.getCharset() + "\r\n\r\n");
|
||||
internal.addValue("; " + HttpHeaders.Values.CHARSET + "=" +
|
||||
fileUpload.getCharset() + "\r\n\r\n");
|
||||
} else {
|
||||
internal.addValue("\r\n\r\n");
|
||||
}
|
||||
@ -626,20 +556,19 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
private ListIterator<InterfaceHttpData> iterator;
|
||||
|
||||
/**
|
||||
* Finalize the request by preparing the Header in the request and returns
|
||||
* the request ready to be sent.<br>
|
||||
* Finalize the request by preparing the Header in the request and
|
||||
* returns the request ready to be sent.<br>
|
||||
* Once finalized, no data must be added.<br>
|
||||
* If the request does not need chunk (isChunked() == false), this request
|
||||
* is the only object to send to the remote server.
|
||||
* If the request does not need chunk (isChunked() == false),
|
||||
* this request is the only object to send to
|
||||
* the remote server.
|
||||
*
|
||||
* @return the request object (chunked or not according to size of body)
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error or if the finalize were already
|
||||
* done
|
||||
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
|
||||
*/
|
||||
public HttpRequest finalizeRequest() throws ErrorDataEncoderException {
|
||||
// Finalize the multipartHttpDatas
|
||||
if (!headerFinalized) {
|
||||
if (! headerFinalized) {
|
||||
if (isMultipart) {
|
||||
InternalAttribute internal = new InternalAttribute();
|
||||
if (duringMixedMode) {
|
||||
@ -656,13 +585,12 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
} else {
|
||||
throw new ErrorDataEncoderException("Header already encoded");
|
||||
}
|
||||
List<String> contentTypes = request
|
||||
.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
|
||||
List<String> transferEncoding = request
|
||||
.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||
List<String> contentTypes = request.getHeaders(HttpHeaders.Names.CONTENT_TYPE);
|
||||
List<String> transferEncoding =
|
||||
request.getHeaders(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||
if (contentTypes != null) {
|
||||
request.removeHeader(HttpHeaders.Names.CONTENT_TYPE);
|
||||
for (String contentType : contentTypes) {
|
||||
for (String contentType: contentTypes) {
|
||||
// "multipart/form-data; boundary=--89421926422648"
|
||||
if (contentType.toLowerCase().startsWith(
|
||||
HttpHeaders.Values.MULTIPART_FORM_DATA)) {
|
||||
@ -671,14 +599,13 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED)) {
|
||||
// ignore
|
||||
} else {
|
||||
request.addHeader(HttpHeaders.Names.CONTENT_TYPE,
|
||||
contentType);
|
||||
request.addHeader(HttpHeaders.Names.CONTENT_TYPE, contentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isMultipart) {
|
||||
String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; "
|
||||
+ HttpHeaders.Values.BOUNDARY + "=" + multipartDataBoundary;
|
||||
String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; " +
|
||||
HttpHeaders.Values.BOUNDARY + "=" + multipartDataBoundary;
|
||||
request.addHeader(HttpHeaders.Names.CONTENT_TYPE, value);
|
||||
} else {
|
||||
// Not multipart
|
||||
@ -693,18 +620,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
realSize -= 1; // last '&' removed
|
||||
iterator = multipartHttpDatas.listIterator();
|
||||
}
|
||||
request.setHeader(HttpHeaders.Names.CONTENT_LENGTH,
|
||||
String.valueOf(realSize));
|
||||
request.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String
|
||||
.valueOf(realSize));
|
||||
if (realSize > HttpPostBodyUtil.chunkSize) {
|
||||
isChunked = true;
|
||||
if (transferEncoding != null) {
|
||||
request.removeHeader(HttpHeaders.Names.TRANSFER_ENCODING);
|
||||
for (String v : transferEncoding) {
|
||||
for (String v: transferEncoding) {
|
||||
if (v.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
|
||||
// ignore
|
||||
} else {
|
||||
request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING,
|
||||
v);
|
||||
request.addHeader(HttpHeaders.Names.TRANSFER_ENCODING, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -728,12 +654,10 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
/**
|
||||
* Encode one attribute
|
||||
*
|
||||
* @param s
|
||||
* @param charset
|
||||
* @return the encoded attribute
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error
|
||||
* @throws ErrorDataEncoderException if the encoding is in error
|
||||
*/
|
||||
private static String encodeAttribute(String s, Charset charset)
|
||||
throws ErrorDataEncoderException {
|
||||
@ -752,26 +676,24 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
*/
|
||||
private ChannelBuffer currentBuffer;
|
||||
/**
|
||||
* The current InterfaceHttpData to encode (used if more chunks are
|
||||
* available)
|
||||
* The current InterfaceHttpData to encode (used if more chunks are available)
|
||||
*/
|
||||
private InterfaceHttpData currentData;
|
||||
/**
|
||||
* If not multipart, does the currentBuffer stands for the Key or for the
|
||||
* Value
|
||||
* If not multipart, does the currentBuffer stands for the Key or for the Value
|
||||
*/
|
||||
private boolean isKey = true;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the next ChannelBuffer to send as a HttpChunk and modifying
|
||||
* currentBuffer accordingly
|
||||
* @return the next ChannelBuffer to send as a HttpChunk and modifying currentBuffer
|
||||
* accordingly
|
||||
*/
|
||||
private ChannelBuffer fillChannelBuffer() {
|
||||
int length = currentBuffer.readableBytes();
|
||||
if (length > HttpPostBodyUtil.chunkSize) {
|
||||
ChannelBuffer slice = currentBuffer.slice(
|
||||
currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
|
||||
ChannelBuffer slice =
|
||||
currentBuffer.slice(currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
|
||||
currentBuffer.skipBytes(HttpPostBodyUtil.chunkSize);
|
||||
return slice;
|
||||
} else {
|
||||
@ -783,18 +705,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* From the current context (currentBuffer and currentData), returns the
|
||||
* next HttpChunk (if possible) trying to get sizeleft bytes more into the
|
||||
* currentBuffer. This is the Multipart version.
|
||||
* From the current context (currentBuffer and currentData), returns the next HttpChunk
|
||||
* (if possible) trying to get sizeleft bytes more into the currentBuffer.
|
||||
* This is the Multipart version.
|
||||
*
|
||||
* @param sizeleft
|
||||
* the number of bytes to try to get from currentData
|
||||
* @param sizeleft the number of bytes to try to get from currentData
|
||||
* @return the next HttpChunk or null if not enough bytes were found
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error
|
||||
* @throws ErrorDataEncoderException if the encoding is in error
|
||||
*/
|
||||
private HttpChunk encodeNextChunkMultipart(int sizeleft)
|
||||
throws ErrorDataEncoderException {
|
||||
private HttpChunk encodeNextChunkMultipart(int sizeleft) throws ErrorDataEncoderException {
|
||||
if (currentData == null) {
|
||||
return null;
|
||||
}
|
||||
@ -832,7 +751,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
if (currentBuffer == null) {
|
||||
currentBuffer = buffer;
|
||||
} else {
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, buffer);
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer,
|
||||
buffer);
|
||||
}
|
||||
if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) {
|
||||
currentData = null;
|
||||
@ -843,18 +763,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
|
||||
/**
|
||||
* From the current context (currentBuffer and currentData), returns the
|
||||
* next HttpChunk (if possible) trying to get sizeleft bytes more into the
|
||||
* currentBuffer. This is the UrlEncoded version.
|
||||
* From the current context (currentBuffer and currentData), returns the next HttpChunk
|
||||
* (if possible) trying to get sizeleft bytes more into the currentBuffer.
|
||||
* This is the UrlEncoded version.
|
||||
*
|
||||
* @param sizeleft
|
||||
* the number of bytes to try to get from currentData
|
||||
* @param sizeleft the number of bytes to try to get from currentData
|
||||
* @return the next HttpChunk or null if not enough bytes were found
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error
|
||||
* @throws ErrorDataEncoderException if the encoding is in error
|
||||
*/
|
||||
private HttpChunk encodeNextChunkUrlEncoded(int sizeleft)
|
||||
throws ErrorDataEncoderException {
|
||||
private HttpChunk encodeNextChunkUrlEncoded(int sizeleft) throws ErrorDataEncoderException {
|
||||
if (currentData == null) {
|
||||
return null;
|
||||
}
|
||||
@ -866,14 +783,14 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
buffer = ChannelBuffers.wrappedBuffer(key.getBytes());
|
||||
isKey = false;
|
||||
if (currentBuffer == null) {
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(buffer,
|
||||
ChannelBuffers.wrappedBuffer("=".getBytes()));
|
||||
// continue
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(
|
||||
buffer, ChannelBuffers.wrappedBuffer("=".getBytes()));
|
||||
//continue
|
||||
size -= buffer.readableBytes() + 1;
|
||||
} else {
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer,
|
||||
buffer, ChannelBuffers.wrappedBuffer("=".getBytes()));
|
||||
// continue
|
||||
//continue
|
||||
size -= buffer.readableBytes() + 1;
|
||||
}
|
||||
if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) {
|
||||
@ -890,8 +807,9 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
if (buffer.readableBytes() < size) {
|
||||
// delimiter
|
||||
isKey = true;
|
||||
delimiter = iterator.hasNext() ? ChannelBuffers.wrappedBuffer("&"
|
||||
.getBytes()) : null;
|
||||
delimiter = iterator.hasNext() ?
|
||||
ChannelBuffers.wrappedBuffer("&".getBytes()) :
|
||||
null;
|
||||
}
|
||||
if (buffer.capacity() == 0) {
|
||||
// end for current InterfaceHttpData, need potentially more data
|
||||
@ -912,7 +830,8 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
if (currentBuffer == null) {
|
||||
if (delimiter != null) {
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(buffer, delimiter);
|
||||
currentBuffer = ChannelBuffers.wrappedBuffer(buffer,
|
||||
delimiter);
|
||||
} else {
|
||||
currentBuffer = buffer;
|
||||
}
|
||||
@ -938,18 +857,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
// NO since the user can want to reuse (broadcast for instance)
|
||||
// cleanFiles();
|
||||
//NO since the user can want to reuse (broadcast for instance) cleanFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next available HttpChunk. The caller is responsible to test
|
||||
* if this chunk is the last one (isLast()), in order to stop calling this
|
||||
* method.
|
||||
* Returns the next available HttpChunk. The caller is responsible to test if this chunk is the
|
||||
* last one (isLast()), in order to stop calling this method.
|
||||
*
|
||||
* @return the next available HttpChunk
|
||||
* @throws ErrorDataEncoderException
|
||||
* if the encoding is in error
|
||||
* @throws ErrorDataEncoderException if the encoding is in error
|
||||
*/
|
||||
@Override
|
||||
public HttpChunk nextChunk() throws ErrorDataEncoderException {
|
||||
@ -964,7 +880,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
size -= currentBuffer.readableBytes();
|
||||
}
|
||||
if (size <= 0) {
|
||||
// NextChunk from buffer
|
||||
//NextChunk from buffer
|
||||
buffer = fillChannelBuffer();
|
||||
return new DefaultHttpChunk(buffer);
|
||||
}
|
||||
@ -979,15 +895,15 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
} else {
|
||||
HttpChunk chunk = encodeNextChunkUrlEncoded(size);
|
||||
if (chunk != null) {
|
||||
// NextChunk Url from currentData
|
||||
//NextChunk Url from currentData
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes();
|
||||
}
|
||||
if (!iterator.hasNext()) {
|
||||
if (! iterator.hasNext()) {
|
||||
isLastChunk = true;
|
||||
// NextChunk as last non empty from buffer
|
||||
//NextChunk as last non empty from buffer
|
||||
buffer = currentBuffer;
|
||||
currentBuffer = null;
|
||||
return new DefaultHttpChunk(buffer);
|
||||
@ -1002,21 +918,20 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
}
|
||||
if (chunk == null) {
|
||||
// not enough
|
||||
size = HttpPostBodyUtil.chunkSize
|
||||
- currentBuffer.readableBytes();
|
||||
size = HttpPostBodyUtil.chunkSize - currentBuffer.readableBytes();
|
||||
continue;
|
||||
}
|
||||
// NextChunk from data
|
||||
//NextChunk from data
|
||||
return chunk;
|
||||
}
|
||||
// end since no more data
|
||||
isLastChunk = true;
|
||||
if (currentBuffer == null) {
|
||||
isLastChunkSent = true;
|
||||
// LastChunk with no more data
|
||||
//LastChunk with no more data
|
||||
return new DefaultHttpChunk(ChannelBuffers.EMPTY_BUFFER);
|
||||
}
|
||||
// Previous LastChunk with no more data
|
||||
//Previous LastChunk with no more data
|
||||
buffer = currentBuffer;
|
||||
currentBuffer = null;
|
||||
return new DefaultHttpChunk(buffer);
|
||||
@ -1027,7 +942,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
return isLastChunkSent;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public boolean hasNextChunk() throws Exception {
|
||||
return !isLastChunkSent;
|
||||
}
|
||||
@ -1067,5 +982,4 @@ public class HttpPostRequestEncoder implements ChunkedInput {
|
||||
super(arg0, arg1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ package org.jboss.netty.handler.codec.http;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.jboss.netty.handler.codec.http.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Default FileUpload implementation that stores file into memory.<br><br>
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user