|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.org.apache.xml.internal.security.c14n.implementations; |
|
|
|
import java.io.IOException; |
|
import java.io.OutputStream; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Map; |
|
|
|
public final class UtfHelpper { |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static final boolean OLD_UTF8 = |
|
AccessController.doPrivileged((PrivilegedAction<Boolean>) |
|
() -> Boolean.getBoolean("com.sun.org.apache.xml.internal.security.c14n.oldUtf8")); |
|
|
|
private UtfHelpper() { |
|
// complete |
|
} |
|
|
|
public static void writeByte( |
|
final String str, |
|
final OutputStream out, |
|
Map<String, byte[]> cache |
|
) throws IOException { |
|
byte[] result = cache.get(str); |
|
if (result == null) { |
|
result = getStringInUtf8(str); |
|
cache.put(str, result); |
|
} |
|
|
|
out.write(result); |
|
} |
|
|
|
public static void writeCodePointToUtf8(final int c, final OutputStream out) throws IOException { |
|
if (!Character.isValidCodePoint(c) || c >= 0xD800 && c <= 0xDBFF || c >= 0xDC00 && c <= 0xDFFF) { |
|
|
|
out.write(0x3f); |
|
return; |
|
} |
|
if (OLD_UTF8 && c >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { |
|
|
|
out.write(0x3f); |
|
out.write(0x3f); |
|
return; |
|
} |
|
|
|
if (c < 0x80) { |
|
// 0x00000000 - 0x0000007F |
|
|
|
out.write(c); |
|
return; |
|
} |
|
byte extraByte = 0; |
|
if (c < 0x800) { |
|
// 0x00000080 - 0x000007FF |
|
|
|
extraByte = 1; |
|
} else if (c < 0x10000) { |
|
// 0x00000800 - 0x0000FFFF |
|
|
|
extraByte = 2; |
|
} else if (c < 0x200000) { |
|
// 0x00010000 - 0x001FFFFF |
|
|
|
extraByte = 3; |
|
} else if (c < 0x4000000) { |
|
// 0x00200000 - 0x03FFFFFF |
|
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 4; |
|
} else if (c <= 0x7FFFFFFF) { |
|
// 0x04000000 - 0x7FFFFFFF |
|
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 5; |
|
} else { |
|
// 0x80000000 - 0xFFFFFFFF |
|
|
|
out.write(0x3f); |
|
return; |
|
} |
|
|
|
byte write; |
|
int shift = 6 * extraByte; |
|
write = (byte)((0xFE << (6 - extraByte)) | (c >>> shift)); |
|
out.write(write); |
|
for (int i = extraByte - 1; i >= 0; i--) { |
|
shift -= 6; |
|
write = (byte)(0x80 | ((c >>> shift) & 0x3F)); |
|
out.write(write); |
|
} |
|
} |
|
|
|
@Deprecated |
|
public static void writeCharToUtf8(final char c, final OutputStream out) throws IOException { |
|
if (c < 0x80) { |
|
out.write(c); |
|
return; |
|
} |
|
if (c >= 0xD800 && c <= 0xDBFF || c >= 0xDC00 && c <= 0xDFFF) { |
|
|
|
out.write(0x3f); |
|
return; |
|
} |
|
int bias; |
|
int write; |
|
char ch; |
|
if (c > 0x07FF) { |
|
ch = (char)(c>>>12); |
|
write = 0xE0; |
|
if (ch > 0) { |
|
write |= ch & 0x0F; |
|
} |
|
out.write(write); |
|
write = 0x80; |
|
bias = 0x3F; |
|
} else { |
|
write = 0xC0; |
|
bias = 0x1F; |
|
} |
|
ch = (char)(c>>>6); |
|
if (ch > 0) { |
|
write |= ch & bias; |
|
} |
|
out.write(write); |
|
out.write(0x80 | ((c) & 0x3F)); |
|
|
|
} |
|
|
|
public static void writeStringToUtf8( |
|
final String str, final OutputStream out |
|
) throws IOException { |
|
final int length = str.length(); |
|
int i = 0; |
|
int c; |
|
while (i < length) { |
|
c = str.codePointAt(i); |
|
i += Character.charCount(c); |
|
if (!Character.isValidCodePoint(c) || c >= 0xD800 && c <= 0xDBFF || c >= 0xDC00 && c <= 0xDFFF) { |
|
|
|
out.write(0x3f); |
|
continue; |
|
} |
|
if (OLD_UTF8 && c >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { |
|
|
|
out.write(0x3f); |
|
out.write(0x3f); |
|
continue; |
|
} |
|
if (c < 0x80) { |
|
out.write(c); |
|
continue; |
|
} |
|
byte extraByte = 0; |
|
if (c < 0x800) { |
|
// 0x00000080 - 0x000007FF |
|
|
|
extraByte = 1; |
|
} else if (c < 0x10000) { |
|
// 0x00000800 - 0x0000FFFF |
|
|
|
extraByte = 2; |
|
} else if (c < 0x200000) { |
|
// 0x00010000 - 0x001FFFFF |
|
|
|
extraByte = 3; |
|
} else if (c < 0x4000000) { |
|
// 0x00200000 - 0x03FFFFFF |
|
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 4; |
|
} else if (c <= 0x7FFFFFFF) { |
|
// 0x04000000 - 0x7FFFFFFF |
|
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 5; |
|
} else { |
|
// 0x80000000 - 0xFFFFFFFF |
|
|
|
out.write(0x3f); |
|
continue; |
|
} |
|
byte write; |
|
int shift = 6 * extraByte; |
|
write = (byte)((0xFE << (6 - extraByte)) | (c >>> shift)); |
|
out.write(write); |
|
for (int j = extraByte - 1; j >= 0; j--) { |
|
shift -= 6; |
|
write = (byte)(0x80 | ((c >>> shift) & 0x3F)); |
|
out.write(write); |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
public static byte[] getStringInUtf8(final String str) { |
|
final int length = str.length(); |
|
boolean expanded = false; |
|
byte[] result = new byte[length]; |
|
int i = 0; |
|
int out = 0; |
|
int c; |
|
while (i < length) { |
|
c = str.codePointAt(i); |
|
i += Character.charCount(c); |
|
if (!Character.isValidCodePoint(c) || c >= 0xD800 && c <= 0xDBFF || c >= 0xDC00 && c <= 0xDFFF) { |
|
|
|
result[out++] = (byte)0x3f; |
|
continue; |
|
} |
|
if (OLD_UTF8 && c >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { |
|
|
|
result[out++] = (byte)0x3f; |
|
result[out++] = (byte)0x3f; |
|
continue; |
|
} |
|
if (c < 0x80) { |
|
result[out++] = (byte)c; |
|
continue; |
|
} |
|
if (!expanded) { |
|
byte newResult[] = new byte[6*length]; |
|
System.arraycopy(result, 0, newResult, 0, out); |
|
result = newResult; |
|
expanded = true; |
|
} |
|
byte extraByte = 0; |
|
if (c < 0x800) { |
|
// 0x00000080 - 0x000007FF |
|
|
|
extraByte = 1; |
|
} else if (c < 0x10000) { |
|
// 0x00000800 - 0x0000FFFF |
|
|
|
extraByte = 2; |
|
} else if (c < 0x200000) { |
|
// 0x00010000 - 0x001FFFFF |
|
|
|
extraByte = 3; |
|
} else if (c < 0x4000000) { |
|
// 0x00200000 - 0x03FFFFFF |
|
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 4; |
|
} else if (c <= 0x7FFFFFFF) { |
|
// 0x04000000 - 0x7FFFFFFF |
|
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
|
|
|
extraByte = 5; |
|
} else { |
|
// 0x80000000 - 0xFFFFFFFF |
|
|
|
result[out++] = 0x3f; |
|
continue; |
|
} |
|
byte write; |
|
int shift = 6 * extraByte; |
|
write = (byte)((0xFE << (6 - extraByte)) | (c >>> shift)); |
|
result[out++] = write; |
|
for (int j = extraByte - 1; j >= 0; j--) { |
|
shift -= 6; |
|
write = (byte)(0x80 | ((c >>> shift) & 0x3F)); |
|
result[out++] = write; |
|
} |
|
} |
|
if (expanded) { |
|
byte newResult[] = new byte[out]; |
|
System.arraycopy(result, 0, newResult, 0, out); |
|
result = newResult; |
|
} |
|
return result; |
|
} |
|
} |