Used codec implementation of Base64 encoding. Thanks to Steven Osborn (steve918)
This commit is contained in:
parent
6f9a886a36
commit
91796814eb
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Red Hat, Inc.
|
||||
*
|
||||
* Red Hat 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.
|
||||
*/
|
||||
package org.jboss.netty.handler.codec.http.websocketx;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
||||
/**
|
||||
* Encodes binary data to plain text as Base64.
|
||||
*
|
||||
* Despite there being a gazillion other Base64 implementations out there, this
|
||||
* has been written as part of XStream as it forms a core part but is too
|
||||
* trivial to warrant an extra dependency.
|
||||
*
|
||||
* This meets the standard as described in RFC 1521, section 5.2
|
||||
* <http://www.freesoft.org/CIE/RFC/1521/7.htm>, allowing other Base64 tools to
|
||||
* manipulate the data.
|
||||
*
|
||||
* This code originally came from the XStream http://xstream.codehaus.org
|
||||
* project by Joe Walnes. Relicensed to Webbit.
|
||||
*/
|
||||
public class Base64 {
|
||||
|
||||
// Here's how encoding works:
|
||||
//
|
||||
// 1) Incoming bytes are broken up into groups of 3 (each byte having 8
|
||||
// bits).
|
||||
//
|
||||
// 2) The combined 24 bits (3 * 8) are split into 4 groups of 6 bits.
|
||||
//
|
||||
// input |------||------||------| (3 values each with 8 bits)
|
||||
// 101010101010101010101010
|
||||
// output |----||----||----||----| (4 values each with 6 bits)
|
||||
//
|
||||
// 3) Each of these 4 groups of 6 bits are converted back to a number, which
|
||||
// will fall in the range of 0 - 63.
|
||||
//
|
||||
// 4) Each of these 4 numbers are converted to an alphanumeric char in a
|
||||
// specified mapping table, to create
|
||||
// a 4 character string.
|
||||
//
|
||||
// 5) This is repeated for all groups of three bytes.
|
||||
//
|
||||
// 6) Special padding is done at the end of the stream using the '=' char.
|
||||
|
||||
private static final char[] SIXTY_FOUR_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
.toCharArray();
|
||||
private static final int[] REVERSE_MAPPING = new int[123];
|
||||
|
||||
static {
|
||||
for (int i = 0; i < SIXTY_FOUR_CHARS.length; i++)
|
||||
REVERSE_MAPPING[SIXTY_FOUR_CHARS[i]] = i + 1;
|
||||
}
|
||||
|
||||
public static String encode(byte[] input) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
int outputCharCount = 0;
|
||||
for (int i = 0; i < input.length; i += 3) {
|
||||
int remaining = Math.min(3, input.length - i);
|
||||
int oneBigNumber = (input[i] & 0xff) << 16 | (remaining <= 1 ? 0 : input[i + 1] & 0xff) << 8
|
||||
| (remaining <= 2 ? 0 : input[i + 2] & 0xff);
|
||||
for (int j = 0; j < 4; j++)
|
||||
result.append(remaining + 1 > j ? SIXTY_FOUR_CHARS[0x3f & oneBigNumber >> 6 * (3 - j)] : '=');
|
||||
if ((outputCharCount += 4) % 76 == 0)
|
||||
result.append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public static byte[] decode(String input) {
|
||||
try {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
StringReader in = new StringReader(input);
|
||||
for (int i = 0; i < input.length(); i += 4) {
|
||||
int a[] = { mapCharToInt(in), mapCharToInt(in), mapCharToInt(in), mapCharToInt(in) };
|
||||
int oneBigNumber = (a[0] & 0x3f) << 18 | (a[1] & 0x3f) << 12 | (a[2] & 0x3f) << 6 | (a[3] & 0x3f);
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (a[j + 1] >= 0) {
|
||||
out.write(0xff & oneBigNumber >> 8 * (2 - j));
|
||||
}
|
||||
}
|
||||
}
|
||||
return out.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new Error(e + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static int mapCharToInt(Reader input) throws IOException {
|
||||
int c;
|
||||
while ((c = input.read()) != -1) {
|
||||
int result = REVERSE_MAPPING[c];
|
||||
if (result != 0)
|
||||
return result - 1;
|
||||
if (c == '=')
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -19,9 +19,13 @@ import java.net.URI;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.base64.Base64;
|
||||
import org.jboss.netty.handler.codec.http.HttpResponse;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Base class for web socket client handshake implementations
|
||||
@ -162,6 +166,18 @@ public abstract class WebSocketClientHandshaker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base 64 encoding
|
||||
*
|
||||
* @param bytes
|
||||
* Bytes to encode
|
||||
* @return encoded string
|
||||
*/
|
||||
protected String base64Encode(byte[] bytes) {
|
||||
ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes);
|
||||
return Base64.encode(hashed).toString(CharsetUtil.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates some random bytes
|
||||
*
|
||||
|
@ -109,11 +109,11 @@ public class WebSocketClientHandshaker10 extends WebSocketClientHandshaker {
|
||||
|
||||
// Get 16 bit nonce and base 64 encode it
|
||||
byte[] nonce = createRandomBytes(16);
|
||||
String key = Base64.encode(nonce);
|
||||
String key = base64Encode(nonce);
|
||||
|
||||
String acceptSeed = key + MAGIC_GUID;
|
||||
byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
|
||||
this.expectedChallengeResponseString = Base64.encode(sha1);
|
||||
this.expectedChallengeResponseString = base64Encode(sha1);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("HyBi10 Client Handshake key: %s. Expected response: %s.", key,
|
||||
|
@ -18,8 +18,12 @@ package org.jboss.netty.handler.codec.http.websocketx;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.base64.Base64;
|
||||
import org.jboss.netty.handler.codec.http.HttpRequest;
|
||||
import org.jboss.netty.util.CharsetUtil;
|
||||
|
||||
/**
|
||||
* Base class for server side web socket opening and closing handshakes
|
||||
@ -146,6 +150,18 @@ public abstract class WebSocketServerHandshaker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base 64 encoding
|
||||
*
|
||||
* @param bytes
|
||||
* Bytes to encode
|
||||
* @return encoded string
|
||||
*/
|
||||
protected String base64Encode(byte[] bytes) {
|
||||
ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes);
|
||||
return Base64.encode(hashed).toString(CharsetUtil.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the first matching supported sub protocol
|
||||
*
|
||||
|
@ -125,7 +125,7 @@ public class WebSocketServerHandshaker10 extends WebSocketServerHandshaker {
|
||||
}
|
||||
String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID;
|
||||
byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
|
||||
String accept = Base64.encode(sha1);
|
||||
String accept = base64Encode(sha1);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("HyBi10 Server Handshake key: %s. Response: %s.", key, accept));
|
||||
|
Loading…
Reference in New Issue
Block a user