Merge remote branch 'upstream/master'

This commit is contained in:
Jestan Nirojan 2012-02-08 00:04:03 +05:30
commit fd610f2f28
850 changed files with 14820 additions and 9736 deletions

18
.gitignore vendored
View File

@ -1,10 +1,12 @@
/.project
/.classpath
/.settings
.project
.classpath
.settings
*.iml
*.ipr
*.iws
.idea/
.geany
/target
*/target
/reports
/src/main/java/io/netty/util/Version.java
/*.iml
/*.ipr
/*.iws
/*.geany
*/reports

29
all/assembly.xml Normal file
View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>all-in-one</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<scope>test</scope>
<unpack>true</unpack>
<useStrictFiltering>true</useStrictFiltering>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveFiltering>true</useTransitiveFiltering>
<includes>
<include>${project.groupId}:*</include>
</includes>
<unpackOptions>
<includes>
<include>io/netty/**</include>
</includes>
</unpackOptions>
</dependencySet>
</dependencySets>
</assembly>

117
all/pom.xml Normal file
View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2011 The Netty Project
~
~ The Netty Project licenses this file to you under the Apache License,
~ version 2.0 (the "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at:
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
~ License for the specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>4.0.0.Alpha1-SNAPSHOT</version>
</parent>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
<packaging>jar</packaging>
<name>Netty/All-in-One</name>
<dependencies>
<!-- The example depends on all modules either directly or transitively -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-example</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.2</version>
<executions>
<execution>
<id>all-in-one</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>${project.basedir}/assembly.xml</descriptor>
</descriptors>
<tarLongFileMode>gnu</tarLongFileMode>
</configuration>
</execution>
</executions>
</plugin>
<!-- Disable all plugin executions configured by jar packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>default-resources</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testResources</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
<executions>
<execution>
<id>default-test</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

40
buffer/pom.xml Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2011 The Netty Project
~
~ The Netty Project licenses this file to you under the Apache License,
~ version 2.0 (the "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at:
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
~ License for the specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>4.0.0.Alpha1-SNAPSHOT</version>
</parent>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<packaging>jar</packaging>
<name>Netty/Buffer</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -135,7 +135,7 @@ public abstract class AbstractChannelBuffer implements ChannelBuffer {
@Override
public boolean getBoolean(int index) {
return (getByte(index) == 1);
return getByte(index) != 0;
}
@Override
@ -278,7 +278,7 @@ public abstract class AbstractChannelBuffer implements ChannelBuffer {
@Override
public boolean readBoolean() {
return (readByte() == 1);
return readByte() != 0;
}
@Override

View File

@ -47,7 +47,7 @@ import java.nio.charset.UnsupportedCharsetException;
*
* <pre>
* {@link ChannelBuffer} buffer = ...;
* for (int i = 0; i &lt; buffer.capacity(); i ++</strong>) {
* for (int i = 0; i &lt; buffer.capacity(); i ++) {
* byte b = buffer.getByte(i);
* System.out.println((char) b);
* }
@ -130,6 +130,8 @@ import java.nio.charset.UnsupportedCharsetException;
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER discardReadBytes()
*
* +------------------+--------------------------------------+
@ -160,6 +162,8 @@ import java.nio.charset.UnsupportedCharsetException;
* +-------------------+------------------+------------------+
* | | | |
* 0 <= readerIndex <= writerIndex <= capacity
*
*
* AFTER clear()
*
* +---------------------------------------------------------+

View File

@ -84,7 +84,7 @@ import io.netty.util.CharsetUtil;
* @apiviz.landmark
* @apiviz.has io.netty.buffer.ChannelBuffer oneway - - creates
*/
public class ChannelBuffers {
public final class ChannelBuffers {
/**
* Big endian byte order.
@ -307,7 +307,11 @@ public class ChannelBuffers {
return EMPTY_BUFFER;
}
if (buffer.hasArray()) {
return wrappedBuffer(buffer.order(), buffer.array(), buffer.arrayOffset() + buffer.position(),buffer.remaining());
return wrappedBuffer(
buffer.order(),
buffer.array(),
buffer.arrayOffset() + buffer.position(),
buffer.remaining());
} else {
return new ByteBufferBackedChannelBuffer(buffer);
}

View File

@ -57,9 +57,9 @@ public class DirectChannelBufferFactory extends AbstractChannelBufferFactory {
private final Object bigEndianLock = new Object();
private final Object littleEndianLock = new Object();
private final int preallocatedBufferCapacity;
private ChannelBuffer preallocatedBigEndianBuffer = null;
private ChannelBuffer preallocatedBigEndianBuffer;
private int preallocatedBigEndianBufferPosition;
private ChannelBuffer preallocatedLittleEndianBuffer = null;
private ChannelBuffer preallocatedLittleEndianBuffer;
private int preallocatedLittleEndianBufferPosition;
/**

View File

@ -27,7 +27,7 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.easymock.classextension.EasyMock;
import org.easymock.EasyMock;
import org.junit.Test;
/**

45
codec-http/pom.xml Normal file
View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2011 The Netty Project
~
~ The Netty Project licenses this file to you under the Apache License,
~ version 2.0 (the "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at:
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
~ License for the specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.netty</groupId>
<artifactId>netty-parent</artifactId>
<version>4.0.0.Alpha1-SNAPSHOT</version>
</parent>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<packaging>jar</packaging>
<name>Netty/Codec/HTTP</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-codec</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-handler</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -32,14 +32,11 @@ import io.netty.buffer.ChannelBuffers;
*/
public abstract class AbstractDiskHttpData extends AbstractHttpData {
protected File file = null;
protected File file;
private boolean isRenamed;
private FileChannel fileChannel;
private boolean isRenamed = false;
private FileChannel fileChannel = null;
public AbstractDiskHttpData(String name, Charset charset, long size)
throws NullPointerException, IllegalArgumentException {
public AbstractDiskHttpData(String name, Charset charset, long size) {
super(name, charset, size);
}

View File

@ -23,17 +23,12 @@ import java.nio.charset.Charset;
public abstract class AbstractHttpData implements HttpData {
protected final String name;
protected long definedSize = 0;
protected long size = 0;
protected long definedSize;
protected long size;
protected Charset charset = HttpCodecUtil.DEFAULT_CHARSET;
protected boolean completed;
protected boolean completed = false;
public AbstractHttpData(String name, Charset charset, long size)
throws NullPointerException, IllegalArgumentException {
public AbstractHttpData(String name, Charset charset, long size) {
if (name == null) {
throw new NullPointerException("name");
}

View File

@ -32,14 +32,11 @@ import io.netty.buffer.ChannelBuffers;
*/
public abstract class AbstractMemoryHttpData extends AbstractHttpData {
private ChannelBuffer channelBuffer = null;
private ChannelBuffer channelBuffer;
private int chunkPosition;
protected boolean isRenamed;
private int chunkPosition = 0;
protected boolean isRenamed = false;
public AbstractMemoryHttpData(String name, Charset charset, long size)
throws NullPointerException, IllegalArgumentException {
public AbstractMemoryHttpData(String name, Charset charset, long size) {
super(name, charset, size);
}

View File

@ -18,8 +18,6 @@ package io.netty.handler.codec.http;
import java.io.Serializable;
import java.util.Comparator;
/**
*/
final class CaseIgnoringComparator implements Comparator<String>, Serializable {
private static final long serialVersionUID = 4582133183775373862L;

View File

@ -41,10 +41,10 @@ import java.util.regex.Pattern;
*/
public class CookieDecoder {
private final static Pattern PATTERN =
private static final Pattern PATTERN =
Pattern.compile("(?:\\s|[;,])*\\$*([^;=]+)(?:=(?:[\"']((?:\\\\.|[^\"])*)[\"']|([^;,]*)))?(\\s*(?:[;,]+\\s*|$))");
private final static String COMMA = ",";
private static final String COMMA = ",";
private final boolean lenient;

View File

@ -204,8 +204,10 @@ public class CookieEncoder {
}
}
if(sb.length() > 0)
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}

View File

@ -15,8 +15,6 @@
*/
package io.netty.handler.codec.http;
/**
*/
final class CookieHeaderNames {
static final String PATH = "Path";

View File

@ -35,11 +35,11 @@ public class DefaultHttpDataFactory implements HttpDataFactory {
*/
public static long MINSIZE = 0x4000;
private boolean useDisk = false;
private boolean useDisk;
private boolean checkSize = false;
private boolean checkSize;
private long minSize = 0L;
private long minSize;
/**
* Keep all HttpDatas until cleanAllHttpDatas() is called.
@ -91,8 +91,7 @@ public class DefaultHttpDataFactory implements HttpDataFactory {
}
@Override
public Attribute createAttribute(HttpRequest request, String name) throws NullPointerException,
IllegalArgumentException {
public Attribute createAttribute(HttpRequest request, String name) {
if (useDisk) {
Attribute attribute = new DiskAttribute(name);
List<HttpData> fileToDelete = getList(request);
@ -107,12 +106,8 @@ public class DefaultHttpDataFactory implements HttpDataFactory {
return new MemoryAttribute(name);
}
/* (non-Javadoc)
* @see io.netty.handler.codec.http2.HttpDataFactory#createAttribute(java.lang.String, java.lang.String)
*/
@Override
public Attribute createAttribute(HttpRequest request, String name, String value)
throws NullPointerException, IllegalArgumentException {
public Attribute createAttribute(HttpRequest request, String name, String value) {
if (useDisk) {
Attribute attribute;
try {
@ -137,13 +132,10 @@ public class DefaultHttpDataFactory implements HttpDataFactory {
}
}
/* (non-Javadoc)
* @see io.netty.handler.codec.http2.HttpDataFactory#createFileUpload(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public FileUpload createFileUpload(HttpRequest request, String name, String filename,
String contentType, String contentTransferEncoding, Charset charset,
long size) throws NullPointerException, IllegalArgumentException {
long size) {
if (useDisk) {
FileUpload fileUpload = new DiskFileUpload(name, filename, contentType,
contentTransferEncoding, charset, size);

View File

@ -96,8 +96,7 @@ public class DefaultHttpMessage implements HttpMessage {
@Override
public String getHeader(final String name) {
List<String> values = getHeaders(name);
return values.size() > 0 ? values.get(0) : null;
return headers.getHeader(name);
}
@Override

View File

@ -24,7 +24,7 @@ import io.netty.buffer.ChannelBuffers;
* Disk implementation of Attributes
*/
public class DiskAttribute extends AbstractDiskHttpData implements Attribute {
public static String baseDirectory = null;
public static String baseDirectory;
public static boolean deleteOnExitTemporaryFile = true;
@ -47,8 +47,7 @@ public class DiskAttribute extends AbstractDiskHttpData implements Attribute {
* @throws IllegalArgumentException
* @throws IOException
*/
public DiskAttribute(String name, String value)
throws NullPointerException, IllegalArgumentException, IOException {
public DiskAttribute(String name, String value) throws IOException {
super(name, HttpCodecUtil.DEFAULT_CHARSET, 0); // Attribute have no default size
setValue(value);
}

View File

@ -22,7 +22,7 @@ import java.nio.charset.Charset;
* Disk FileUpload implementation that stores file into real files
*/
public class DiskFileUpload extends AbstractDiskHttpData implements FileUpload {
public static String baseDirectory = null;
public static String baseDirectory;
public static boolean deleteOnExitTemporaryFile = true;
@ -30,15 +30,14 @@ public class DiskFileUpload extends AbstractDiskHttpData implements FileUpload {
public static String postfix = ".tmp";
private String filename = null;
private String filename;
private String contentType = null;
private String contentType;
private String contentTransferEncoding = null;
private String contentTransferEncoding;
public DiskFileUpload(String name, String filename, String contentType,
String contentTransferEncoding, Charset charset, long size)
throws NullPointerException, IllegalArgumentException {
String contentTransferEncoding, Charset charset, long size) {
super(name, charset, size);
setFilename(filename);
setContentType(contentType);
@ -50,17 +49,11 @@ public class DiskFileUpload extends AbstractDiskHttpData implements FileUpload {
return HttpDataType.FileUpload;
}
/* (non-Javadoc)
* @see io.netty.handler.codec.http2.FileUpload#getFilename()
*/
@Override
public String getFilename() {
return filename;
}
/* (non-Javadoc)
* @see io.netty.handler.codec.http2.FileUpload#setFilename(java.lang.String)
*/
@Override
public void setFilename(String filename) {
if (filename == null) {

View File

@ -20,9 +20,7 @@ import java.util.List;
import io.netty.util.CharsetUtil;
/**
*/
class HttpCodecUtil {
final class HttpCodecUtil {
//space ' '
static final byte SP = 32;

View File

@ -30,16 +30,20 @@ import io.netty.handler.codec.embedder.EncoderEmbedder;
public class HttpContentCompressor extends HttpContentEncoder {
private final int compressionLevel;
private final int windowBits;
private final int memLevel;
/**
* Creates a new handler with the default compression level (<tt>6</tt>).
* Creates a new handler with the default compression level (<tt>6</tt>),
* default window size (<tt>15</tt>) and default memory level (<tt>8</tt>).
*/
public HttpContentCompressor() {
this(6);
}
/**
* Creates a new handler with the specified compression level.
* Creates a new handler with the specified compression level, default
* window size (<tt>15</tt>) and default memory level (<tt>8</tt>).
*
* @param compressionLevel
* {@code 1} yields the fastest compression and {@code 9} yields the
@ -47,12 +51,45 @@ public class HttpContentCompressor extends HttpContentEncoder {
* compression level is {@code 6}.
*/
public HttpContentCompressor(int compressionLevel) {
this(compressionLevel, 15, 8);
}
/**
* Creates a new handler with the specified compression level, window size,
* and memory level..
*
* @param compressionLevel
* {@code 1} yields the fastest compression and {@code 9} yields the
* best compression. {@code 0} means no compression. The default
* compression level is {@code 6}.
* @param windowBits
* The base two logarithm of the size of the history buffer. The
* value should be in the range {@code 9} to {@code 15} inclusive.
* Larger values result in better compression at the expense of
* memory usage. The default value is {@code 15}.
* @param memLevel
* How much memory should be allocated for the internal compression
* state. {@code 1} uses minimum memory and {@code 9} uses maximum
* memory. Larger values result in better and faster compression
* at the expense of memory usage. The default value is {@code 8}
*/
public HttpContentCompressor(int compressionLevel, int windowBits, int memLevel) {
if (compressionLevel < 0 || compressionLevel > 9) {
throw new IllegalArgumentException(
"compressionLevel: " + compressionLevel +
" (expected: 0-9)");
}
if (windowBits < 9 || windowBits > 15) {
throw new IllegalArgumentException(
"windowBits: " + windowBits + " (expected: 9-15)");
}
if (memLevel < 1 || memLevel > 9) {
throw new IllegalArgumentException(
"memLevel: " + memLevel + " (expected: 1-9)");
}
this.compressionLevel = compressionLevel;
this.windowBits = windowBits;
this.memLevel = memLevel;
}
@Override
@ -83,17 +120,47 @@ public class HttpContentCompressor extends HttpContentEncoder {
return new Result(
targetContentEncoding,
new EncoderEmbedder<ChannelBuffer>(
new ZlibEncoder(wrapper, compressionLevel)));
new ZlibEncoder(wrapper, compressionLevel, windowBits, memLevel)));
}
private ZlibWrapper determineWrapper(String acceptEncoding) {
// FIXME: Use the Q value.
if (acceptEncoding.indexOf("gzip") >= 0) {
protected ZlibWrapper determineWrapper(String acceptEncoding) {
float starQ = -1.0f;
float gzipQ = -1.0f;
float deflateQ = -1.0f;
for (String encoding : acceptEncoding.split(",")) {
float q = 1.0f;
int equalsPos = encoding.indexOf('=');
if (equalsPos != -1) {
try {
q = Float.valueOf(encoding.substring(equalsPos + 1));
} catch (NumberFormatException e) {
// Ignore encoding
q = 0.0f;
}
}
if (encoding.indexOf("*") >= 0) {
starQ = q;
} else if (encoding.indexOf("gzip") >= 0 && q > gzipQ) {
gzipQ = q;
} else if (encoding.indexOf("deflate") >= 0 && q > deflateQ) {
deflateQ = q;
}
}
if (gzipQ > 0.0f || deflateQ > 0.0f) {
if (gzipQ >= deflateQ) {
return ZlibWrapper.GZIP;
} else {
return ZlibWrapper.ZLIB;
}
}
if (starQ > 0.0f) {
if (gzipQ == -1.0f) {
return ZlibWrapper.GZIP;
}
if (acceptEncoding.indexOf("deflate") >= 0) {
if (deflateQ == -1.0f) {
return ZlibWrapper.ZLIB;
}
}
return null;
}
}

View File

@ -29,8 +29,7 @@ public interface HttpDataFactory {
* @throws NullPointerException
* @throws IllegalArgumentException
*/
Attribute createAttribute(HttpRequest request, String name)
throws NullPointerException, IllegalArgumentException;
Attribute createAttribute(HttpRequest request, String name);
/**
*
@ -41,8 +40,7 @@ public interface HttpDataFactory {
* @throws NullPointerException
* @throws IllegalArgumentException
*/
Attribute createAttribute(HttpRequest request, String name, String value)
throws NullPointerException, IllegalArgumentException;
Attribute createAttribute(HttpRequest request, String name, String value);
/**
*
@ -56,7 +54,7 @@ public interface HttpDataFactory {
*/
FileUpload createFileUpload(HttpRequest request, String name, String filename,
String contentType, String contentTransferEncoding, Charset charset,
long size) throws NullPointerException, IllegalArgumentException;
long size);
/**
* Remove the given InterfaceHttpData from clean list (will not delete the file, except if the file

View File

@ -568,11 +568,9 @@ public abstract class HttpMessageDecoder extends ReplayingDecoder<HttpMessageDec
if (nextByte == HttpCodecUtil.LF) {
return sb.toString();
}
}
else if (nextByte == HttpCodecUtil.LF) {
} else if (nextByte == HttpCodecUtil.LF) {
return sb.toString();
}
else {
} else {
if (lineLength >= maxLineLength) {
// TODO: Respond with Bad Request and discard the traffic
// or close the connection.

View File

@ -25,6 +25,8 @@ import io.netty.buffer.ChannelBuffer;
import io.netty.buffer.ChannelBuffers;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpHeaders.Values;
import io.netty.handler.codec.oneone.OneToOneEncoder;
import io.netty.util.CharsetUtil;
@ -59,7 +61,17 @@ public abstract class HttpMessageEncoder extends OneToOneEncoder {
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
if (msg instanceof HttpMessage) {
HttpMessage m = (HttpMessage) msg;
boolean chunked = this.chunked = HttpCodecUtil.isTransferEncodingChunked(m);
boolean chunked;
if (m.isChunked()) {
// check if the Transfer-Encoding is set to chunked already.
// if not add the header to the message
if (!HttpCodecUtil.isTransferEncodingChunked(m)) {
m.addHeader(Names.TRANSFER_ENCODING, Values.CHUNKED);
}
chunked = this.chunked = true;
} else {
chunked = this.chunked = HttpCodecUtil.isTransferEncodingChunked(m);
}
ChannelBuffer header = ChannelBuffers.dynamicBuffer(
channel.getConfig().getBufferFactory());
encodeInitialLine(header, m);

View File

@ -23,7 +23,8 @@ import io.netty.util.CharsetUtil;
/**
* Shared Static object between HttpMessageDecoder, HttpPostRequestDecoder and HttpPostRequestEncoder
*/
public class HttpPostBodyUtil {
final class HttpPostBodyUtil {
public static int chunkSize = 8096;
/**
* HTTP content disposition header name.

View File

@ -50,12 +50,12 @@ public class HttpPostRequestDecoder {
/**
* Does request have a body to decode
*/
private boolean bodyToDecode = false;
private boolean bodyToDecode;
/**
* Does the last chunk already received
*/
private boolean isLastChunk = false;
private boolean isLastChunk;
/**
* HttpDatas from Body
@ -71,28 +71,28 @@ public class HttpPostRequestDecoder {
/**
* The current channelBuffer
*/
private ChannelBuffer undecodedChunk = null;
private ChannelBuffer undecodedChunk;
/**
* Does this request is a Multipart request
*/
private boolean isMultipart = false;
private boolean isMultipart;
/**
* Body HttpDatas current position
*/
private int bodyListHttpDataRank = 0;
private int bodyListHttpDataRank;
/**
* If multipart, this is the boundary for the flobal multipart
*/
private String multipartDataBoundary = null;
private String multipartDataBoundary;
/**
* If multipart, there could be internal multiparts (mixed) to the global multipart.
* Only one level is allowed.
*/
private String multipartMixedBoundary = null;
private String multipartMixedBoundary;
/**
* Current status
@ -102,17 +102,17 @@ public class HttpPostRequestDecoder {
/**
* Used in Multipart
*/
private Map<String, Attribute> currentFieldAttributes = null;
private Map<String, Attribute> currentFieldAttributes;
/**
* The current FileUpload that is currently in decode process
*/
private FileUpload currentFileUpload = null;
private FileUpload currentFileUpload;
/**
* The current Attribute that is currently in decode process
*/
private Attribute currentAttribute = null;
private Attribute currentAttribute;
/**
*
@ -122,8 +122,7 @@ public class HttpPostRequestDecoder {
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
*/
public HttpPostRequestDecoder(HttpRequest request)
throws ErrorDataDecoderException, IncompatibleDataDecoderException,
NullPointerException {
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE),
request, HttpCodecUtil.DEFAULT_CHARSET);
}
@ -137,8 +136,7 @@ public class HttpPostRequestDecoder {
* @throws ErrorDataDecoderException if the default charset was wrong when decoding or other errors
*/
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request)
throws ErrorDataDecoderException, IncompatibleDataDecoderException,
NullPointerException {
throws ErrorDataDecoderException, IncompatibleDataDecoderException {
this(factory, request, HttpCodecUtil.DEFAULT_CHARSET);
}
@ -153,7 +151,7 @@ public class HttpPostRequestDecoder {
*/
public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request,
Charset charset) throws ErrorDataDecoderException,
IncompatibleDataDecoderException, NullPointerException {
IncompatibleDataDecoderException {
if (factory == null) {
throw new NullPointerException("factory");
}
@ -452,6 +450,16 @@ public class HttpPostRequestDecoder {
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);
currentAttribute.setValue(""); // empty
addHttpData(currentAttribute);
currentAttribute = null;
firstpos = currentpos;
contRead = true;
}
break;
case FIELD:// search '&' or end of line

View File

@ -51,16 +51,16 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Chunked false by default
*/
private boolean isChunked = false;
private boolean isChunked;
/**
* InterfaceHttpData for Body (without encoding)
*/
private List<InterfaceHttpData> bodyListDatas = null;
private List<InterfaceHttpData> bodyListDatas;
/**
* The final Multipart List of InterfaceHttpData including encoding
*/
private List<InterfaceHttpData> multipartHttpDatas = null;
private List<InterfaceHttpData> multipartHttpDatas;
/**
* Does this request is a Multipart request
@ -70,17 +70,17 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* If multipart, this is the boundary for the flobal multipart
*/
private String multipartDataBoundary = null;
private String multipartDataBoundary;
/**
* If multipart, there could be internal multiparts (mixed) to the global multipart.
* Only one level is allowed.
*/
private String multipartMixedBoundary = null;
private String multipartMixedBoundary;
/**
* To check if the header has been finalized
*/
private boolean headerFinalized = false;
private boolean headerFinalized;
/**
*
@ -90,7 +90,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpRequest request, boolean multipart)
throws ErrorDataEncoderException, NullPointerException {
throws ErrorDataEncoderException {
this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE),
request, multipart, HttpCodecUtil.DEFAULT_CHARSET);
}
@ -104,7 +104,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request, boolean multipart)
throws ErrorDataEncoderException, NullPointerException {
throws ErrorDataEncoderException {
this(factory, request, multipart, HttpCodecUtil.DEFAULT_CHARSET);
}
@ -118,8 +118,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the request is not a POST
*/
public HttpPostRequestEncoder(HttpDataFactory factory, HttpRequest request,
boolean multipart, Charset charset) throws ErrorDataEncoderException,
NullPointerException {
boolean multipart, Charset charset) throws ErrorDataEncoderException {
if (factory == null) {
throw new NullPointerException("factory");
}
@ -157,24 +156,24 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Does the last non empty chunk already encoded so that next chunk will be empty (last chunk)
*/
private boolean isLastChunk = false;
private boolean isLastChunk;
/**
* Last chunk already sent
*/
private boolean isLastChunkSent = false;
private boolean isLastChunkSent;
/**
* The current FileUpload that is currently in encode process
*/
private FileUpload currentFileUpload = null;
private FileUpload currentFileUpload;
/**
* While adding a FileUpload, is the multipart currently in Mixed Mode
*/
private boolean duringMixedMode = false;
private boolean duringMixedMode;
/**
* Global Body size
*/
private long globalBodySize = 0;
private long globalBodySize;
/**
* True if this request is a Multipart request
@ -224,7 +223,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void setBodyHttpDatas(List<InterfaceHttpData> datas)
throws NullPointerException, ErrorDataEncoderException {
throws ErrorDataEncoderException {
if (datas == null) {
throw new NullPointerException("datas");
}
@ -246,7 +245,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyAttribute(String name, String value)
throws NullPointerException, ErrorDataEncoderException {
throws ErrorDataEncoderException {
if (name == null) {
throw new NullPointerException("name");
}
@ -268,7 +267,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @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 NullPointerException, ErrorDataEncoderException {
throws ErrorDataEncoderException {
if (name == null) {
throw new NullPointerException("name");
}
@ -307,7 +306,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @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)
throws NullPointerException, ErrorDataEncoderException {
throws ErrorDataEncoderException {
if (file.length != contentType.length && file.length != isText.length) {
throw new NullPointerException("Different array length");
}
@ -323,7 +322,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
* @throws ErrorDataEncoderException if the encoding is in error or if the finalize were already done
*/
public void addBodyHttpData(InterfaceHttpData data)
throws NullPointerException, ErrorDataEncoderException {
throws ErrorDataEncoderException {
if (headerFinalized) {
throw new ErrorDataEncoderException("Cannot add value once finalized");
}
@ -554,7 +553,7 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* Iterator to be used when encoding will be called chunk after chunk
*/
private ListIterator<InterfaceHttpData> iterator = null;
private ListIterator<InterfaceHttpData> iterator;
/**
* Finalize the request by preparing the Header in the request and
@ -675,11 +674,11 @@ public class HttpPostRequestEncoder implements ChunkedInput {
/**
* The ChannelBuffer currently used by the encoder
*/
private ChannelBuffer currentBuffer = null;
private ChannelBuffer currentBuffer;
/**
* The current InterfaceHttpData to encode (used if more chunks are available)
*/
private InterfaceHttpData currentData = null;
private InterfaceHttpData currentData;
/**
* If not multipart, does the currentBuffer stands for the Key or for the Value
*/

View File

@ -36,8 +36,7 @@ public class MemoryAttribute extends AbstractMemoryHttpData implements Attribute
* @throws IllegalArgumentException
* @throws IOException
*/
public MemoryAttribute(String name, String value)
throws NullPointerException, IllegalArgumentException, IOException {
public MemoryAttribute(String name, String value) throws IOException {
super(name, HttpCodecUtil.DEFAULT_CHARSET, 0); // Attribute have no default size
setValue(value);
}

View File

@ -24,15 +24,14 @@ import java.nio.charset.Charset;
*/
public class MemoryFileUpload extends AbstractMemoryHttpData implements FileUpload {
private String filename = null;
private String filename;
private String contentType = null;
private String contentType;
private String contentTransferEncoding = null;
private String contentTransferEncoding;
public MemoryFileUpload(String name, String filename, String contentType,
String contentTransferEncoding, Charset charset, long size)
throws NullPointerException, IllegalArgumentException {
String contentTransferEncoding, Charset charset, long size) {
super(name, charset, size);
setFilename(filename);
setContentType(contentType);

View File

@ -26,20 +26,16 @@ import io.netty.buffer.ChannelBuffer;
* Mixed implementation using both in Memory and in File with a limit of size
*/
public class MixedAttribute implements Attribute {
private Attribute attribute = null;
private Attribute attribute;
private long limitSize = 0;
private long limitSize;
public MixedAttribute(String name,
long limitSize) throws NullPointerException,
IllegalArgumentException {
public MixedAttribute(String name, long limitSize) {
this.limitSize = limitSize;
attribute = new MemoryAttribute(name);
}
public MixedAttribute(String name, String value,
long limitSize) throws NullPointerException,
IllegalArgumentException {
public MixedAttribute(String name, String value, long limitSize) {
this.limitSize = limitSize;
if (value.length() > this.limitSize) {
try {
@ -62,8 +58,7 @@ public class MixedAttribute implements Attribute {
}
@Override
public void addContent(ChannelBuffer buffer, boolean last)
throws IOException {
public void addContent(ChannelBuffer buffer, boolean last) throws IOException {
if (attribute instanceof MemoryAttribute) {
if (attribute.length() + buffer.readableBytes() > limitSize) {
DiskAttribute diskAttribute = new DiskAttribute(attribute

View File

@ -26,16 +26,15 @@ import io.netty.buffer.ChannelBuffer;
* Mixed implementation using both in Memory and in File with a limit of size
*/
public class MixedFileUpload implements FileUpload {
private FileUpload fileUpload = null;
private FileUpload fileUpload;
private long limitSize = 0;
private long limitSize;
private long definedSize = 0;
private long definedSize;
public MixedFileUpload(String name, String filename, String contentType,
String contentTransferEncoding, Charset charset, long size,
long limitSize) throws NullPointerException,
IllegalArgumentException {
long limitSize) {
this.limitSize = limitSize;
if (size > this.limitSize) {
fileUpload = new DiskFileUpload(name, filename, contentType,

View File

@ -32,10 +32,25 @@ import io.netty.util.CharsetUtil;
* <pre>
* {@link QueryStringDecoder} decoder = new {@link QueryStringDecoder}("/hello?recipient=world&x=1;y=2");
* assert decoder.getPath().equals("/hello");
* assert decoder.getParameters().get("recipient").equals("world");
* assert decoder.getParameters().get("x").equals("1");
* assert decoder.getParameters().get("y").equals("2");
* assert decoder.getParameters().get("recipient").get(0).equals("world");
* assert decoder.getParameters().get("x").get(0).equals("1");
* assert decoder.getParameters().get("y").get(0).equals("2");
* </pre>
*
* This decoder can also decode the content of an HTTP POST request whose
* content type is <tt>application/x-www-form-urlencoded</tt>:
* <pre>
* {@link QueryStringDecoder} decoder = new {@link QueryStringDecoder}("recipient=world&x=1;y=2", false);
* ...
* </pre>
*
* <h3>HashDOS vulnerability fix</h3>
*
* As a workaround to the <a href="http://events.ccc.de/congress/2011/Fahrplan/attachments/2007_28C3_Effective_DoS_on_web_application_platforms.pdf">HashDOS</a>
* vulnerability, the decoder limits the maximum number of decoded key-value
* parameter pairs, up to {@literal 1024} by default, and you can configure it
* when you construct the decoder by passing an additional integer parameter.
*
* @see QueryStringEncoder
*
* @apiviz.stereotype utility
@ -43,10 +58,15 @@ import io.netty.util.CharsetUtil;
*/
public class QueryStringDecoder {
private static final int DEFAULT_MAX_PARAMS = 1024;
private final Charset charset;
private final String uri;
private final boolean hasPath;
private final int maxParams;
private String path;
private Map<String, List<String>> params;
private int nParams;
/**
* Creates a new decoder that decodes the specified URI. The decoder will
@ -56,21 +76,51 @@ public class QueryStringDecoder {
this(uri, HttpCodecUtil.DEFAULT_CHARSET);
}
/**
* Creates a new decoder that decodes the specified URI encoded in the
* specified charset.
*/
public QueryStringDecoder(String uri, boolean hasPath) {
this(uri, HttpCodecUtil.DEFAULT_CHARSET, hasPath);
}
/**
* Creates a new decoder that decodes the specified URI encoded in the
* specified charset.
*/
public QueryStringDecoder(String uri, Charset charset) {
this(uri, charset, true);
}
/**
* Creates a new decoder that decodes the specified URI encoded in the
* specified charset.
*/
public QueryStringDecoder(String uri, Charset charset, boolean hasPath) {
this(uri, charset, hasPath, DEFAULT_MAX_PARAMS);
}
/**
* Creates a new decoder that decodes the specified URI encoded in the
* specified charset.
*/
public QueryStringDecoder(String uri, Charset charset, boolean hasPath, int maxParams) {
if (uri == null) {
throw new NullPointerException("uri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
// http://en.wikipedia.org/wiki/Query_string
this.uri = uri.replace(';', '&');
this.charset = charset;
this.maxParams = maxParams;
this.hasPath = hasPath;
}
/**
@ -86,16 +136,30 @@ public class QueryStringDecoder {
* specified charset.
*/
public QueryStringDecoder(URI uri, Charset charset) {
this(uri, charset, DEFAULT_MAX_PARAMS);
}
/**
* Creates a new decoder that decodes the specified URI encoded in the
* specified charset.
*/
public QueryStringDecoder(URI uri, Charset charset, int maxParams) {
if (uri == null) {
throw new NullPointerException("uri");
}
if (charset == null) {
throw new NullPointerException("charset");
}
if (maxParams <= 0) {
throw new IllegalArgumentException(
"maxParams: " + maxParams + " (expected: a positive integer)");
}
// http://en.wikipedia.org/wiki/Query_string
this.uri = uri.toASCIIString().replace(';', '&');
this.charset = charset;
this.maxParams = maxParams;
hasPath = false;
}
/**
@ -103,11 +167,14 @@ public class QueryStringDecoder {
*/
public String getPath() {
if (path == null) {
if (!hasPath) {
return path = "";
}
int pathEndPos = uri.indexOf('?');
if (pathEndPos < 0) {
path = uri;
}
else {
} else {
return path = uri.substring(0, pathEndPos);
}
}
@ -119,17 +186,25 @@ public class QueryStringDecoder {
*/
public Map<String, List<String>> getParameters() {
if (params == null) {
if (hasPath) {
int pathLength = getPath().length();
if (uri.length() == pathLength) {
return Collections.emptyMap();
}
params = decodeParams(uri.substring(pathLength + 1));
decodeParams(uri.substring(pathLength + 1));
} else {
if (uri.isEmpty()) {
return Collections.emptyMap();
}
decodeParams(uri);
}
}
return params;
}
private Map<String, List<String>> decodeParams(String s) {
Map<String, List<String>> params = new LinkedHashMap<String, List<String>>();
private void decodeParams(String s) {
Map<String, List<String>> params = this.params = new LinkedHashMap<String, List<String>>();
nParams = 0;
String name = null;
int pos = 0; // Beginning of the unprocessed region
int i; // End of the unprocessed region
@ -146,9 +221,13 @@ public class QueryStringDecoder {
// We haven't seen an `=' so far but moved forward.
// Must be a param of the form '&a&' so add it with
// an empty value.
addParam(params, decodeComponent(s.substring(pos, i), charset), "");
if (!addParam(params, decodeComponent(s.substring(pos, i), charset), "")) {
return;
}
} else if (name != null) {
addParam(params, name, decodeComponent(s.substring(pos, i), charset));
if (!addParam(params, name, decodeComponent(s.substring(pos, i), charset))) {
return;
}
name = null;
}
pos = i + 1;
@ -157,15 +236,34 @@ public class QueryStringDecoder {
if (pos != i) { // Are there characters we haven't dealt with?
if (name == null) { // Yes and we haven't seen any `='.
addParam(params, decodeComponent(s.substring(pos, i), charset), "");
if (!addParam(params, decodeComponent(s.substring(pos, i), charset), "")) {
return;
}
} else { // Yes and this must be the last value.
addParam(params, name, decodeComponent(s.substring(pos, i), charset));
if (!addParam(params, name, decodeComponent(s.substring(pos, i), charset))) {
return;
}
}
} else if (name != null) { // Have we seen a name without value?
addParam(params, name, "");
if (!addParam(params, name, "")) {
return;
}
}
}
return params;
private boolean addParam(Map<String, List<String>> params, String name, String value) {
if (nParams >= maxParams) {
return false;
}
List<String> values = params.get(name);
if (values == null) {
values = new ArrayList<String>(1); // Often there's only 1 value.
params.put(name, values);
}
values.add(value);
nParams ++;
return true;
}
/**
@ -284,13 +382,4 @@ public class QueryStringDecoder {
return Character.MAX_VALUE;
}
}
private static void addParam(Map<String, List<String>> params, String name, String value) {
List<String> values = params.get(name);
if (values == null) {
values = new ArrayList<String>(1); // Often there's only 1 value.
params.put(name, values);
}
values.add(value);
}
}

View File

@ -29,7 +29,7 @@ import java.util.List;
* This encoder is for one time use only. Create a new instance for each URI.
*
* <pre>
* {@link QueryStringEncoder} encoder = new {@link QueryStringDecoder}("/hello");
* {@link QueryStringEncoder} encoder = new {@link QueryStringEncoder}("/hello");
* encoder.addParam("recipient", "world");
* assert encoder.toString().equals("/hello?recipient=world");
* </pre>

Some files were not shown because too many files have changed in this diff Show More