org.eclipse.jetty.util.B64Code Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
//
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Base64;
/**
* Fast B64 Encoder/Decoder as described in RFC 1421.
* Does not insert or interpret whitespace as described in RFC
* 1521. If you require this you must pre/post process your data.
*
Note that in a web context the usual case is to not want
* linebreaks or other white space in the encoded output.
*
* @deprecated use {@link java.util.Base64} instead
*/
@Deprecated
public class B64Code
{
private static final char __pad = '=';
private static final char[] __rfc1421alphabet =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};
private static final byte[] __rfc1421nibbles;
static
{
__rfc1421nibbles = new byte[256];
for (int i = 0; i < 256; i++)
{
__rfc1421nibbles[i] = -1;
}
for (byte b = 0; b < 64; b++)
{
__rfc1421nibbles[(byte)__rfc1421alphabet[b]] = b;
}
__rfc1421nibbles[(byte)__pad] = 0;
}
private static final char[] __rfc4648urlAlphabet =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};
private static final byte[] __rfc4648urlNibbles;
static
{
__rfc4648urlNibbles = new byte[256];
for (int i = 0; i < 256; i++)
{
__rfc4648urlNibbles[i] = -1;
}
for (byte b = 0; b < 64; b++)
{
__rfc4648urlNibbles[(byte)__rfc4648urlAlphabet[b]] = b;
}
__rfc4648urlNibbles[(byte)__pad] = 0;
}
private B64Code()
{
}
/**
* Base 64 encode as described in RFC 1421.
*
Does not insert whitespace as described in RFC 1521.
*
* @param s String to encode.
* @return String containing the encoded form of the input.
* @deprecated use {@link Base64.Encoder#encodeToString(byte[])}} instead.
*/
public static String encode(String s)
{
// NOTE: no Jetty mainline code uses this anymore
return encode(s, (Charset)null);
}
/**
* Base 64 encode as described in RFC 1421.
*
Does not insert whitespace as described in RFC 1521.
*
* @param s String to encode.
* @param charEncoding String representing the name of
* the character encoding of the provided input String.
* @return String containing the encoded form of the input.
*/
public static String encode(String s, String charEncoding)
{
// NOTE: no Jetty mainline code uses this anymore
byte[] bytes;
if (charEncoding == null)
bytes = s.getBytes(StandardCharsets.ISO_8859_1);
else
bytes = s.getBytes(Charset.forName(charEncoding));
return new String(encode(bytes));
}
/**
* Base 64 encode as described in RFC 1421.
*
Does not insert whitespace as described in RFC 1521.
*
* @param s String to encode.
* @param charEncoding The character encoding of the provided input String.
* @return String containing the encoded form of the input.
*/
public static String encode(String s, Charset charEncoding)
{
// NOTE: no Jetty mainline code uses this anymore
byte[] bytes = s.getBytes(charEncoding == null ? StandardCharsets.ISO_8859_1 : charEncoding);
return new String(encode(bytes));
}
/**
* Fast Base 64 encode as described in RFC 1421.
*
Does not insert whitespace as described in RFC 1521.
*
Avoids creating extra copies of the input/output.
*
* @param b byte array to encode.
* @return char array containing the encoded form of the input.
*/
public static char[] encode(byte[] b)
{
// NOTE: no Jetty mainline code uses this anymore
if (b == null)
return null;
int bLen = b.length;
int cLen = ((bLen + 2) / 3) * 4;
char[] c = new char[cLen];
int ci = 0;
int bi = 0;
byte b0;
byte b1;
byte b2;
int stop = (bLen / 3) * 3;
while (bi < stop)
{
b0 = b[bi++];
b1 = b[bi++];
b2 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f];
c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f | (b2 >>> 6) & 0x03];
c[ci++] = __rfc1421alphabet[b2 & 0x3f];
}
if (bLen != bi)
{
switch (bLen % 3)
{
case 2:
b0 = b[bi++];
b1 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f];
c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f];
c[ci++] = __pad;
break;
case 1:
b0 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f];
c[ci++] = __pad;
c[ci++] = __pad;
break;
default:
break;
}
}
return c;
}
/**
* Fast Base 64 encode as described in RFC 1421 and RFC2045
*
Does not insert whitespace as described in RFC 1521, unless rfc2045 is passed as true.
*
Avoids creating extra copies of the input/output.
*
* @param b byte array to encode.
* @param rfc2045 If true, break lines at 76 characters with CRLF
* @return char array containing the encoded form of the input.
*/
public static char[] encode(byte[] b, boolean rfc2045)
{
// NOTE: no Jetty mainline code uses this anymore
if (b == null)
return null;
if (!rfc2045)
return encode(b);
int bLen = b.length;
int cLen = ((bLen + 2) / 3) * 4;
cLen += 2 + 2 * (cLen / 76);
char[] c = new char[cLen];
int ci = 0;
int bi = 0;
byte b0;
byte b1;
byte b2;
int stop = (bLen / 3) * 3;
int l = 0;
while (bi < stop)
{
b0 = b[bi++];
b1 = b[bi++];
b2 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f];
c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f | (b2 >>> 6) & 0x03];
c[ci++] = __rfc1421alphabet[b2 & 0x3f];
l += 4;
if (l % 76 == 0)
{
c[ci++] = 13;
c[ci++] = 10;
}
}
if (bLen != bi)
{
switch (bLen % 3)
{
case 2:
b0 = b[bi++];
b1 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f | (b1 >>> 4) & 0x0f];
c[ci++] = __rfc1421alphabet[(b1 << 2) & 0x3f];
c[ci++] = __pad;
break;
case 1:
b0 = b[bi++];
c[ci++] = __rfc1421alphabet[(b0 >>> 2) & 0x3f];
c[ci++] = __rfc1421alphabet[(b0 << 4) & 0x3f];
c[ci++] = __pad;
c[ci++] = __pad;
break;
default:
break;
}
}
c[ci++] = 13;
c[ci++] = 10;
return c;
}
/**
* Base 64 decode as described in RFC 2045.
*
Unlike {@link #decode(char[])}, extra whitespace is ignored.
*
* @param encoded String to decode.
* @param charEncoding String representing the character encoding
* used to map the decoded bytes into a String. If null
* the platforms default charset is used.
* @return String decoded byte array.
* @throws UnsupportedCharsetException if the encoding is not supported
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
@SuppressWarnings("DefaultCharset")
public static String decode(String encoded, String charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] decoded = decode(encoded);
if (charEncoding == null)
return new String(decoded);
return new String(decoded, Charset.forName(charEncoding));
}
/**
* Base 64 decode as described in RFC 2045.
*
Unlike {@link #decode(char[])}, extra whitespace is ignored.
*
* @param encoded String to decode.
* @param charEncoding Character encoding
* used to map the decoded bytes into a String. If null
* the platforms default charset is used.
* @return String decoded byte array.
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
@SuppressWarnings("DefaultCharset")
public static String decode(String encoded, Charset charEncoding)
{
// FIXME: no Jetty mainline code uses this anymore
byte[] decoded = decode(encoded);
if (charEncoding == null)
return new String(decoded);
return new String(decoded, charEncoding);
}
/**
* Fast Base 64 decode as described in RFC 1421.
*
*
Unlike other decode methods, this does not attempt to
* cope with extra whitespace as described in RFC 1521/2045.
*
Avoids creating extra copies of the input/output.
*
Note this code has been flattened for performance.
*
* @param b char array to decode.
* @return byte array containing the decoded form of the input.
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
public static byte[] decode(char[] b)
{
// FIXME: no Jetty mainline code uses this anymore
if (b == null)
return null;
int bLen = b.length;
if (bLen % 4 != 0)
throw new IllegalArgumentException("Input block size is not 4");
int li = bLen - 1;
while (li >= 0 && b[li] == (byte)__pad)
{
li--;
}
if (li < 0)
return new byte[0];
// Create result array of exact required size.
int rLen = ((li + 1) * 3) / 4;
byte[] r = new byte[rLen];
int ri = 0;
int bi = 0;
int stop = (rLen / 3) * 3;
byte b0;
byte b1;
byte b2;
byte b3;
try
{
while (ri < stop)
{
b0 = __rfc1421nibbles[b[bi++]];
b1 = __rfc1421nibbles[b[bi++]];
b2 = __rfc1421nibbles[b[bi++]];
b3 = __rfc1421nibbles[b[bi++]];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException("Not B64 encoded");
r[ri++] = (byte)(b0 << 2 | b1 >>> 4);
r[ri++] = (byte)(b1 << 4 | b2 >>> 2);
r[ri++] = (byte)(b2 << 6 | b3);
}
if (rLen != ri)
{
switch (rLen % 3)
{
case 2:
b0 = __rfc1421nibbles[b[bi++]];
b1 = __rfc1421nibbles[b[bi++]];
b2 = __rfc1421nibbles[b[bi++]];
if (b0 < 0 || b1 < 0 || b2 < 0)
throw new IllegalArgumentException("Not B64 encoded");
r[ri++] = (byte)(b0 << 2 | b1 >>> 4);
r[ri++] = (byte)(b1 << 4 | b2 >>> 2);
break;
case 1:
b0 = __rfc1421nibbles[b[bi++]];
b1 = __rfc1421nibbles[b[bi++]];
if (b0 < 0 || b1 < 0)
throw new IllegalArgumentException("Not B64 encoded");
r[ri++] = (byte)(b0 << 2 | b1 >>> 4);
break;
default:
break;
}
}
}
catch (IndexOutOfBoundsException e)
{
throw new IllegalArgumentException("char " + bi + " was not B64 encoded");
}
return r;
}
/**
* Base 64 decode as described in RFC 2045.
*
Unlike {@link #decode(char[])}, extra whitespace is ignored.
*
* @param encoded String to decode.
* @return byte array containing the decoded form of the input.
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
public static byte[] decode(String encoded)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded == null)
return null;
ByteArrayOutputStream bout = new ByteArrayOutputStream(4 * encoded.length() / 3);
decode(encoded, bout);
return bout.toByteArray();
}
/**
* Base 64 decode as described in RFC 2045.
*
Unlike {@link #decode(char[])}, extra whitespace is ignored.
*
* @param encoded String to decode.
* @param bout stream for decoded bytes
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
public static void decode(String encoded, ByteArrayOutputStream bout)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded == null)
return;
if (bout == null)
throw new IllegalArgumentException("No outputstream for decoded bytes");
int ci = 0;
byte[] nibbles = new byte[4];
int s = 0;
while (ci < encoded.length())
{
char c = encoded.charAt(ci++);
if (c == __pad)
break;
if (Character.isWhitespace(c))
continue;
byte nibble = __rfc1421nibbles[c];
if (nibble < 0)
throw new IllegalArgumentException("Not B64 encoded");
nibbles[s++] = __rfc1421nibbles[c];
switch (s)
{
case 1:
break;
case 2:
bout.write(nibbles[0] << 2 | nibbles[1] >>> 4);
break;
case 3:
bout.write(nibbles[1] << 4 | nibbles[2] >>> 2);
break;
case 4:
bout.write(nibbles[2] << 6 | nibbles[3]);
s = 0;
break;
}
}
return;
}
public static byte[] decodeRFC4648URL(String encoded)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded == null)
return null;
ByteArrayOutputStream bout = new ByteArrayOutputStream(4 * encoded.length() / 3);
decodeRFC4648URL(encoded, bout);
return bout.toByteArray();
}
/**
* Base 64 decode as described in RFC 4648 URL.
*
Unlike {@link #decode(char[])}, extra whitespace is ignored.
*
* @param encoded String to decode.
* @param bout stream for decoded bytes
* @throws IllegalArgumentException if the input is not a valid
* B64 encoding.
*/
public static void decodeRFC4648URL(String encoded, ByteArrayOutputStream bout)
{
// FIXME: no Jetty mainline code uses this anymore
if (encoded == null)
return;
if (bout == null)
throw new IllegalArgumentException("No outputstream for decoded bytes");
int ci = 0;
byte[] nibbles = new byte[4];
int s = 0;
while (ci < encoded.length())
{
char c = encoded.charAt(ci++);
if (c == __pad)
break;
if (Character.isWhitespace(c))
continue;
byte nibble = __rfc4648urlNibbles[c];
if (nibble < 0)
throw new IllegalArgumentException("Not B64 encoded");
nibbles[s++] = __rfc4648urlNibbles[c];
switch (s)
{
case 1:
break;
case 2:
bout.write(nibbles[0] << 2 | nibbles[1] >>> 4);
break;
case 3:
bout.write(nibbles[1] << 4 | nibbles[2] >>> 2);
break;
case 4:
bout.write(nibbles[2] << 6 | nibbles[3]);
s = 0;
break;
}
}
return;
}
public static void encode(int value, Appendable buf) throws IOException
{
// FIXME: no Jetty mainline code uses this anymore
buf.append(__rfc1421alphabet[0x3f & ((0xFC000000 & value) >> 26)]);
buf.append(__rfc1421alphabet[0x3f & ((0x03F00000 & value) >> 20)]);
buf.append(__rfc1421alphabet[0x3f & ((0x000FC000 & value) >> 14)]);
buf.append(__rfc1421alphabet[0x3f & ((0x00003F00 & value) >> 8)]);
buf.append(__rfc1421alphabet[0x3f & ((0x000000FC & value) >> 2)]);
buf.append(__rfc1421alphabet[0x3f & ((0x00000003 & value) << 4)]);
}
public static void encode(long lvalue, Appendable buf) throws IOException
{
// FIXME: no Jetty mainline code uses this anymore
int value = (int)(0xFFFFFFFC & (lvalue >> 32));
buf.append(__rfc1421alphabet[0x3f & ((0xFC000000 & value) >> 26)]);
buf.append(__rfc1421alphabet[0x3f & ((0x03F00000 & value) >> 20)]);
buf.append(__rfc1421alphabet[0x3f & ((0x000FC000 & value) >> 14)]);
buf.append(__rfc1421alphabet[0x3f & ((0x00003F00 & value) >> 8)]);
buf.append(__rfc1421alphabet[0x3f & ((0x000000FC & value) >> 2)]);
buf.append(__rfc1421alphabet[0x3f & ((0x00000003 & value) << 4) + (0xf & (int)(lvalue >> 28))]);
value = 0x0FFFFFFF & (int)lvalue;
buf.append(__rfc1421alphabet[0x3f & ((0x0FC00000 & value) >> 22)]);
buf.append(__rfc1421alphabet[0x3f & ((0x003F0000 & value) >> 16)]);
buf.append(__rfc1421alphabet[0x3f & ((0x0000FC00 & value) >> 10)]);
buf.append(__rfc1421alphabet[0x3f & ((0x000003F0 & value) >> 4)]);
buf.append(__rfc1421alphabet[0x3f & ((0x0000000F & value) << 2)]);
}
}