Fix the potential copyright issue in SocksCommonUtils

- Add StringUtil.toHexString() methods which are based on LoggingHandler's lookup table implementation, and use it wherever possible
This commit is contained in:
Trustin Lee 2014-02-06 14:59:31 -08:00
parent 9bee78f91c
commit c4c71e6d28
5 changed files with 206 additions and 49 deletions

View File

@ -15,6 +15,8 @@
*/
package io.netty.handler.codec.socks;
import io.netty.util.internal.StringUtil;
final class SocksCommonUtils {
public static final SocksRequest UNKNOWN_SOCKS_REQUEST = new UnknownSocksRequest();
public static final SocksResponse UNKNOWN_SOCKS_RESPONSE = new UnknownSocksResponse();
@ -28,7 +30,7 @@ final class SocksCommonUtils {
* A constructor to stop this class being constructed.
*/
private SocksCommonUtils() {
//NOOP
// NOOP
}
public static String intToIp(int i) {
@ -41,10 +43,10 @@ final class SocksCommonUtils {
private static final char[] ipv6conseqZeroFiller = {':', ':'};
private static final char ipv6hextetSeparator = ':';
/*
* Convert numeric IPv6 to compressed format, where
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
*/
/**
* Convert numeric IPv6 to compressed format, where
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
*/
public static String ipv6toCompressedForm(byte[] src) {
assert src.length == 16;
//Find the longest sequence of 0's
@ -77,12 +79,9 @@ final class SocksCommonUtils {
return sb.toString();
}
/*
* Convert numeric IPv6 to standard (non-compressed) format.
*
* Borrowed from Inet6Address.java #numericToTextFormat(byte[])
* Changed StringBuffer -> StringBuilder and ":" -> ':' for performance.
*/
/**
* Converts numeric IPv6 to standard (non-compressed) format.
*/
public static String ipv6toStr(byte[] src) {
assert src.length == 16;
StringBuilder sb = new StringBuilder(39);
@ -90,14 +89,18 @@ final class SocksCommonUtils {
return sb.toString();
}
private static void ipv6toStr(StringBuilder sb, byte[] src,
int fromHextet, int toHextet) {
for (int i = fromHextet; i < toHextet; i++) {
sb.append(Integer.toHexString(src[i << 1] << 8 & 0xff00
| src[(i << 1) + 1] & 0xff));
if (i < toHextet - 1) {
sb.append(ipv6hextetSeparator);
}
private static void ipv6toStr(StringBuilder sb, byte[] src, int fromHextet, int toHextet) {
int i;
toHextet --;
for (i = fromHextet; i < toHextet; i++) {
appendHextet(sb, src, i);
sb.append(ipv6hextetSeparator);
}
appendHextet(sb, src, i);
}
private static void appendHextet(StringBuilder sb, byte[] src, int i) {
StringUtil.toHexString(sb, src, i << 1, 2);
}
}

View File

@ -77,7 +77,8 @@ public class SocksCmdResponseDecoderTest {
"testDomain.com", 80);
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, SocksAddressType.IPv6,
"2001:db8:85a3:42:1000:8a2e:370:7334", 80);
testSocksCmdResponseDecoderWithDifferentParams(cmdStatus, SocksAddressType.IPv6,
"1111:111:11:1:0:0:0:1", 80);
}
}
}

View File

@ -15,6 +15,7 @@
*/
package io.netty.util.internal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
@ -24,13 +25,14 @@ import java.util.List;
*/
public final class StringUtil {
private StringUtil() {
// Unused.
}
public static final String NEWLINE;
private static final String[] BYTE2HEX_PAD = new String[256];
private static final String[] BYTE2HEX_NOPAD = new String[256];
private static final String EMPTY_STRING = "";
static {
// Determine the newline character of the current platform.
String newLine;
try {
@ -41,9 +43,32 @@ public final class StringUtil {
}
NEWLINE = newLine;
}
private static final String EMPTY_STRING = "";
// Generate the lookup table that converts a byte into a 2-digit hexadecimal integer.
int i;
for (i = 0; i < 10; i ++) {
StringBuilder buf = new StringBuilder(2);
buf.append('0');
buf.append(i);
BYTE2HEX_PAD[i] = buf.toString();
BYTE2HEX_NOPAD[i] = String.valueOf(i);
}
for (; i < 16; i ++) {
StringBuilder buf = new StringBuilder(2);
char c = (char) ('a' + i - 10);
buf.append('0');
buf.append(c);
BYTE2HEX_PAD[i] = buf.toString();
BYTE2HEX_NOPAD[i] = String.valueOf(c);
}
for (; i < BYTE2HEX_PAD.length; i ++) {
StringBuilder buf = new StringBuilder(2);
buf.append(Integer.toHexString(i));
String str = buf.toString();
BYTE2HEX_PAD[i] = str;
BYTE2HEX_NOPAD[i] = str;
}
}
/**
* Splits the specified {@link String} with the specified delimiter. This operation is a simplified and optimized
@ -86,6 +111,124 @@ public final class StringUtil {
return res.toArray(new String[res.size()]);
}
/**
* Converts the specified byte value into a 2-digit hexadecimal integer.
*/
public static String byteToHexStringPadded(int value) {
return BYTE2HEX_PAD[value & 0xff];
}
/**
* Converts the specified byte value into a 2-digit hexadecimal integer and appends it to the specified buffer.
*/
public static <T extends Appendable> T byteToHexStringPadded(T buf, int value) {
try {
buf.append(byteToHexStringPadded(value));
} catch (IOException e) {
PlatformDependent.throwException(e);
}
return buf;
}
/**
* Converts the specified byte array into a hexadecimal value.
*/
public static String toHexStringPadded(byte[] src) {
return toHexStringPadded(src, 0, src.length);
}
/**
* Converts the specified byte array into a hexadecimal value.
*/
public static String toHexStringPadded(byte[] src, int offset, int length) {
return toHexStringPadded(new StringBuilder(length << 1), src, offset, length).toString();
}
/**
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
*/
public static <T extends Appendable> T toHexStringPadded(T dst, byte[] src) {
return toHexStringPadded(dst, src, 0, src.length);
}
/**
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
*/
public static <T extends Appendable> T toHexStringPadded(T dst, byte[] src, int offset, int length) {
final int end = offset + length;
for (int i = offset; i < end; i ++) {
byteToHexStringPadded(dst, src[i]);
}
return dst;
}
/**
* Converts the specified byte value into a hexadecimal integer.
*/
public static String byteToHexString(int value) {
return BYTE2HEX_NOPAD[value & 0xff];
}
/**
* Converts the specified byte value into a hexadecimal integer and appends it to the specified buffer.
*/
public static <T extends Appendable> T byteToHexString(T buf, int value) {
try {
buf.append(byteToHexString(value));
} catch (IOException e) {
PlatformDependent.throwException(e);
}
return buf;
}
/**
* Converts the specified byte array into a hexadecimal value.
*/
public static String toHexString(byte[] src) {
return toHexString(src, 0, src.length);
}
/**
* Converts the specified byte array into a hexadecimal value.
*/
public static String toHexString(byte[] src, int offset, int length) {
return toHexString(new StringBuilder(length << 1), src, offset, length).toString();
}
/**
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
*/
public static <T extends Appendable> T toHexString(T dst, byte[] src) {
return toHexString(dst, src, 0, src.length);
}
/**
* Converts the specified byte array into a hexadecimal value and appends it to the specified buffer.
*/
public static <T extends Appendable> T toHexString(T dst, byte[] src, int offset, int length) {
assert length >= 0;
if (length == 0) {
return dst;
}
final int end = offset + length;
final int endMinusOne = end - 1;
int i;
// Skip preceding zeroes.
for (i = offset; i < endMinusOne; i ++) {
if (src[i] != 0) {
break;
}
}
byteToHexString(dst, src[i ++]);
int remaining = end - i;
toHexStringPadded(dst, src, i, remaining);
return dst;
}
/**
* The shortcut to {@link #simpleClassName(Class) simpleClassName(o.getClass())}.
*/
@ -113,4 +256,8 @@ public final class StringUtil {
return clazz.getName();
}
}
private StringUtil() {
// Unused.
}
}

View File

@ -17,37 +17,57 @@ package io.netty.util.internal;
import org.junit.Test;
import static io.netty.util.internal.StringUtil.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
public class StringUtilTest {
@Test
public void ensureNewlineExists() {
assertNotNull(StringUtil.NEWLINE);
assertNotNull(NEWLINE);
}
@Test
public void testToHexString() {
assertThat(toHexString(new byte[] { 0 }), is("0"));
assertThat(toHexString(new byte[] { 1 }), is("1"));
assertThat(toHexString(new byte[] { 0, 0 }), is("0"));
assertThat(toHexString(new byte[] { 1, 0 }), is("100"));
assertThat(toHexString(EmptyArrays.EMPTY_BYTES), is(""));
}
@Test
public void testToHexStringPadded() {
assertThat(toHexStringPadded(new byte[]{0}), is("00"));
assertThat(toHexStringPadded(new byte[]{1}), is("01"));
assertThat(toHexStringPadded(new byte[]{0, 0}), is("0000"));
assertThat(toHexStringPadded(new byte[]{1, 0}), is("0100"));
assertThat(toHexStringPadded(EmptyArrays.EMPTY_BYTES), is(""));
}
@Test
public void splitSimple() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo:bar", ':'));
assertArrayEquals(new String[] { "foo", "bar" }, split("foo:bar", ':'));
}
@Test
public void splitWithTrailingDelimiter() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo,bar,", ','));
assertArrayEquals(new String[] { "foo", "bar" }, split("foo,bar,", ','));
}
@Test
public void splitWithTrailingDelimiters() {
assertArrayEquals(new String[] { "foo", "bar" }, StringUtil.split("foo!bar!!", '!'));
assertArrayEquals(new String[] { "foo", "bar" }, split("foo!bar!!", '!'));
}
@Test
public void splitWithConsecutiveDelimiters() {
assertArrayEquals(new String[] { "foo", "", "bar" }, StringUtil.split("foo$$bar", '$'));
assertArrayEquals(new String[] { "foo", "", "bar" }, split("foo$$bar", '$'));
}
@Test
public void splitWithDelimiterAtBeginning() {
assertArrayEquals(new String[] { "", "foo", "bar" }, StringUtil.split("#foo#bar", '#'));
assertArrayEquals(new String[] { "", "foo", "bar" }, split("#foo#bar", '#'));
}
}

View File

@ -22,6 +22,7 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.logging.InternalLogLevel;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
@ -48,23 +49,8 @@ public class LoggingHandler extends ChannelDuplexHandler {
int i;
// Generate the lookup table for byte-to-hex-dump conversion
for (i = 0; i < 10; i ++) {
StringBuilder buf = new StringBuilder(3);
buf.append(" 0");
buf.append(i);
BYTE2HEX[i] = buf.toString();
}
for (; i < 16; i ++) {
StringBuilder buf = new StringBuilder(3);
buf.append(" 0");
buf.append((char) ('a' + i - 10));
BYTE2HEX[i] = buf.toString();
}
for (; i < BYTE2HEX.length; i ++) {
StringBuilder buf = new StringBuilder(3);
buf.append(' ');
buf.append(Integer.toHexString(i));
BYTE2HEX[i] = buf.toString();
for (i = 0; i < BYTE2HEX.length; i ++) {
BYTE2HEX[i] = ' ' + StringUtil.byteToHexStringPadded(i);
}
// Generate the lookup table for hex dump paddings