| 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
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;  | 
 | 
    }  | 
 | 
}  |