Replace dynamic regular expressions with precompiled Patterns or new StringUtil.split()
This commit is contained in:
parent
8c0e5626c2
commit
e21dc5925d
@ -15,6 +15,8 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http;
|
||||
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -40,7 +42,7 @@ import java.util.TreeSet;
|
||||
*/
|
||||
public final class CookieDecoder {
|
||||
|
||||
private static final String COMMA = ",";
|
||||
private static final char COMMA = ',';
|
||||
|
||||
/**
|
||||
* Decodes the specified HTTP header value into {@link Cookie}s.
|
||||
@ -131,7 +133,7 @@ public final class CookieDecoder {
|
||||
} else if (CookieHeaderNames.VERSION.equalsIgnoreCase(name)) {
|
||||
version = Integer.parseInt(value);
|
||||
} else if (CookieHeaderNames.PORT.equalsIgnoreCase(name)) {
|
||||
String[] portList = value.split(COMMA);
|
||||
String[] portList = StringUtil.split(value, COMMA);
|
||||
for (String s1: portList) {
|
||||
try {
|
||||
ports.add(Integer.valueOf(s1));
|
||||
|
@ -16,6 +16,7 @@
|
||||
package io.netty.handler.codec.http;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A utility class mainly for use with HTTP codec classes
|
||||
|
@ -18,6 +18,7 @@ package io.netty.handler.codec.http;
|
||||
import io.netty.channel.embedded.EmbeddedByteChannel;
|
||||
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||
import io.netty.handler.codec.compression.ZlibWrapper;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
/**
|
||||
* Compresses an {@link HttpMessage} and an {@link HttpChunk} in {@code gzip} or
|
||||
@ -126,7 +127,7 @@ public class HttpContentCompressor extends HttpContentEncoder {
|
||||
float starQ = -1.0f;
|
||||
float gzipQ = -1.0f;
|
||||
float deflateQ = -1.0f;
|
||||
for (String encoding : acceptEncoding.split(",")) {
|
||||
for (String encoding: StringUtil.split(acceptEncoding, ',')) {
|
||||
float q = 1.0f;
|
||||
int equalsPos = encoding.indexOf('=');
|
||||
if (equalsPos != -1) {
|
||||
|
@ -15,15 +15,6 @@
|
||||
*/
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.handler.codec.http.HttpChunk;
|
||||
import io.netty.handler.codec.http.HttpConstants;
|
||||
@ -33,6 +24,17 @@ import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadNoBackArrayException;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostBodyUtil.SeekAheadOptimize;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostBodyUtil.TransferEncodingMechanism;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static io.netty.buffer.Unpooled.*;
|
||||
|
||||
/**
|
||||
@ -254,7 +256,7 @@ public class HttpPostRequestDecoder {
|
||||
String[] headerContentType = splitHeaderContentType(contentType);
|
||||
if (headerContentType[0].toLowerCase().startsWith(HttpHeaders.Values.MULTIPART_FORM_DATA)
|
||||
&& headerContentType[1].toLowerCase().startsWith(HttpHeaders.Values.BOUNDARY)) {
|
||||
String[] boundary = headerContentType[1].split("=");
|
||||
String[] boundary = StringUtil.split(headerContentType[1], '=');
|
||||
if (boundary.length != 2) {
|
||||
throw new ErrorDataDecoderException("Needs a boundary value");
|
||||
}
|
||||
@ -955,7 +957,7 @@ public class HttpPostRequestDecoder {
|
||||
if (checkSecondArg) {
|
||||
// read next values and store them in the map as Attribute
|
||||
for (int i = 2; i < contents.length; i++) {
|
||||
String[] values = contents[i].split("=");
|
||||
String[] values = StringUtil.split(contents[i], '=');
|
||||
Attribute attribute;
|
||||
try {
|
||||
attribute = factory.createAttribute(request, values[0].trim(),
|
||||
@ -994,7 +996,7 @@ public class HttpPostRequestDecoder {
|
||||
// Take care of possible "multipart/mixed"
|
||||
if (contents[1].equalsIgnoreCase(HttpPostBodyUtil.MULTIPART_MIXED)) {
|
||||
if (currentStatus == MultiPartStatus.DISPOSITION) {
|
||||
String[] values = contents[2].split("=");
|
||||
String[] values = StringUtil.split(contents[2], '=');
|
||||
multipartMixedBoundary = "--" + values[1];
|
||||
currentStatus = MultiPartStatus.MIXEDDELIMITER;
|
||||
return decodeMultipart(MultiPartStatus.MIXEDDELIMITER);
|
||||
@ -1004,7 +1006,7 @@ public class HttpPostRequestDecoder {
|
||||
} else {
|
||||
for (int i = 1; i < contents.length; i++) {
|
||||
if (contents[i].toLowerCase().startsWith(HttpHeaders.Values.CHARSET)) {
|
||||
String[] values = contents[i].split("=");
|
||||
String[] values = StringUtil.split(contents[i], '=');
|
||||
Attribute attribute;
|
||||
try {
|
||||
attribute = factory.createAttribute(request, HttpHeaders.Values.CHARSET,
|
||||
|
@ -18,6 +18,7 @@ package io.netty.handler.codec.http.websocketx;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.util.internal.StringUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
@ -57,7 +58,7 @@ public abstract class WebSocketServerHandshaker {
|
||||
this.version = version;
|
||||
this.webSocketUrl = webSocketUrl;
|
||||
if (subprotocols != null) {
|
||||
String[] subprotocolArray = subprotocols.split(",");
|
||||
String[] subprotocolArray = StringUtil.split(subprotocols, ',');
|
||||
for (int i = 0; i < subprotocolArray.length; i++) {
|
||||
subprotocolArray[i] = subprotocolArray[i].trim();
|
||||
}
|
||||
@ -132,7 +133,7 @@ public abstract class WebSocketServerHandshaker {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] requestedSubprotocolArray = requestedSubprotocols.split(",");
|
||||
String[] requestedSubprotocolArray = StringUtil.split(requestedSubprotocols, ',');
|
||||
for (String p: requestedSubprotocolArray) {
|
||||
String requestedSubprotocol = p.trim();
|
||||
|
||||
|
@ -23,6 +23,7 @@ import java.security.PrivilegedExceptionAction;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
@ -41,6 +42,8 @@ public final class DetectionUtil {
|
||||
private static final boolean IS_ROOT;
|
||||
|
||||
static {
|
||||
|
||||
Pattern PERMISSION_DENIED = Pattern.compile(".*permission.*denied.*");
|
||||
String os = SystemPropertyUtil.get("os.name", "").toLowerCase(Locale.UK);
|
||||
// windows
|
||||
IS_WINDOWS = os.contains("win");
|
||||
@ -63,7 +66,7 @@ public final class DetectionUtil {
|
||||
message = "";
|
||||
}
|
||||
message = message.toLowerCase();
|
||||
if (message.matches(".*permission.*denied.*")) {
|
||||
if (PERMISSION_DENIED.matcher(message).matches()) {
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
|
@ -15,7 +15,9 @@
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* String utility class.
|
||||
@ -40,4 +42,47 @@ public final class StringUtil {
|
||||
NEWLINE = newLine;
|
||||
|
||||
}
|
||||
|
||||
private static final String EMPTY_STRING = "";
|
||||
|
||||
/**
|
||||
* Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
|
||||
* version of {@link String#split(String)}.
|
||||
*/
|
||||
public static String[] split(String value, char delim) {
|
||||
final int end = value.length();
|
||||
final List<String> res = new ArrayList<String>();
|
||||
|
||||
int start = 0;
|
||||
for (int i = 0; i < end; i ++) {
|
||||
if (value.charAt(i) == delim) {
|
||||
if (start == i) {
|
||||
res.add(EMPTY_STRING);
|
||||
} else {
|
||||
res.add(value.substring(start, i));
|
||||
}
|
||||
start = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == 0) { // If no delimiter was found in the value
|
||||
res.add(value);
|
||||
} else {
|
||||
if (start != end) {
|
||||
// Add the last element if it's not empty.
|
||||
res.add(value.substring(start, end));
|
||||
} else {
|
||||
// Truncate trailing empty elements.
|
||||
for (int i = res.size() - 1; i >= 0; i --) {
|
||||
if (res.get(i).length() == 0) {
|
||||
res.remove(i);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.toArray(new String[res.size()]);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import io.netty.logging.InternalLoggerFactory;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A collection of utility methods to retrieve and parse the values of the Java system properties.
|
||||
@ -122,6 +123,8 @@ public final class SystemPropertyUtil {
|
||||
return def;
|
||||
}
|
||||
|
||||
private static final Pattern INTEGER_PATTERN = Pattern.compile("-?[0-9]+");
|
||||
|
||||
/**
|
||||
* Returns the value of the Java system property with the specified
|
||||
* {@code key}, while falling back to the specified default value if
|
||||
@ -138,7 +141,7 @@ public final class SystemPropertyUtil {
|
||||
}
|
||||
|
||||
value = value.trim().toLowerCase();
|
||||
if (value.matches("-?[0-9]+")) {
|
||||
if (INTEGER_PATTERN.matcher(value).matches()) {
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (Exception e) {
|
||||
@ -169,7 +172,7 @@ public final class SystemPropertyUtil {
|
||||
}
|
||||
|
||||
value = value.trim().toLowerCase();
|
||||
if (value.matches("-?[0-9]+")) {
|
||||
if (INTEGER_PATTERN.matcher(value).matches()) {
|
||||
try {
|
||||
return Long.parseLong(value);
|
||||
} catch (Exception e) {
|
||||
|
@ -15,14 +15,39 @@
|
||||
*/
|
||||
package io.netty.util.internal;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class StringUtilTest {
|
||||
|
||||
@Test
|
||||
public void ensureNewlineExists() {
|
||||
assertNotNull(StringUtil.NEWLINE);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void splitSimple() {
|
||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo:bar", ':'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitWithTrailingDelimiter() {
|
||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo,bar,", ','));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitWithTrailingDelimiters() {
|
||||
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo!bar!!", '!'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitWithConsecutiveDelimiters() {
|
||||
assertArrayEquals(new String[] { "foo", "", "bar" }, StringUtil.split("foo$$bar", '$'));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitWithDelimiterAtBeginning() {
|
||||
assertArrayEquals(new String[] { "", "foo", "bar" }, StringUtil.split("#foo#bar", '#'));
|
||||
}
|
||||
}
|
||||
|
@ -15,11 +15,6 @@
|
||||
*/
|
||||
package io.netty.example.http.file;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
@ -33,6 +28,7 @@ import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.handler.stream.ChunkedFile;
|
||||
import io.netty.util.CharsetUtil;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.RandomAccessFile;
|
||||
@ -44,8 +40,13 @@ import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.activation.MimetypesFileTypeMap;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
||||
import static io.netty.handler.codec.http.HttpHeaders.*;
|
||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||
|
||||
/**
|
||||
* A simple handler that serves incoming HTTP requests to send their respective
|
||||
@ -194,6 +195,8 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
|
||||
}
|
||||
}
|
||||
|
||||
private static final Pattern INSECURE_URI = Pattern.compile(".*[<>&\"].*");
|
||||
|
||||
private static String sanitizeUri(String uri) {
|
||||
// Decode the path.
|
||||
try {
|
||||
@ -218,7 +221,7 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
|
||||
if (uri.contains(File.separator + ".") ||
|
||||
uri.contains("." + File.separator) ||
|
||||
uri.startsWith(".") || uri.endsWith(".") ||
|
||||
uri.matches(".*[<>&\"].*")) {
|
||||
INSECURE_URI.matcher(uri).matches()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -226,6 +229,8 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
|
||||
return System.getProperty("user.dir") + File.separator + uri;
|
||||
}
|
||||
|
||||
private static final Pattern ALLOWED_FILE_NAME = Pattern.compile("[A-Za-z0-9][-_A-Za-z0-9\\.]*");
|
||||
|
||||
private static void sendListing(ChannelHandlerContext ctx, File dir) {
|
||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK);
|
||||
response.setHeader(CONTENT_TYPE, "text/html; charset=UTF-8");
|
||||
@ -252,7 +257,7 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda
|
||||
}
|
||||
|
||||
String name = f.getName();
|
||||
if (!name.matches("[A-Za-z0-9][-_A-Za-z0-9\\.]*")) {
|
||||
if (!ALLOWED_FILE_NAME.matcher(name).matches()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
|
||||
@ -101,10 +102,12 @@ public class LocalTimeClient {
|
||||
" localhost 8080 America/New_York Asia/Seoul");
|
||||
}
|
||||
|
||||
private static final Pattern CITY_PATTERN = Pattern.compile("^[_A-Za-z]+/[_A-Za-z]+$");
|
||||
|
||||
private static List<String> parseCities(String[] args, int offset) {
|
||||
List<String> cities = new ArrayList<String>();
|
||||
for (int i = offset; i < args.length; i ++) {
|
||||
if (!args[i].matches("^[_A-Za-z]+/[_A-Za-z]+$")) {
|
||||
if (!CITY_PATTERN.matcher(args[i]).matches()) {
|
||||
System.err.println("Syntax error: '" + args[i] + "'");
|
||||
printUsage();
|
||||
return null;
|
||||
|
@ -32,12 +32,15 @@ import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LocalTimeClientHandler extends ChannelInboundMessageHandlerAdapter<LocalTimes> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(
|
||||
LocalTimeClientHandler.class.getName());
|
||||
|
||||
private static final Pattern DELIM = Pattern.compile("/");
|
||||
|
||||
// Stateful properties
|
||||
private volatile Channel channel;
|
||||
private final BlockingQueue<LocalTimes> answer = new LinkedBlockingQueue<LocalTimes>();
|
||||
@ -46,7 +49,7 @@ public class LocalTimeClientHandler extends ChannelInboundMessageHandlerAdapter<
|
||||
Locations.Builder builder = Locations.newBuilder();
|
||||
|
||||
for (String c: cities) {
|
||||
String[] components = c.split("/");
|
||||
String[] components = DELIM.split(c);
|
||||
builder.addLocation(Location.newBuilder().
|
||||
setContinent(Continent.valueOf(components[0].toUpperCase())).
|
||||
setCity(components[1]).build());
|
||||
|
Loading…
Reference in New Issue
Block a user