cbbase64.java

来自「JAVA开源LDAP浏览器jxplorer的源码!」· Java 代码 · 共 626 行 · 第 1/2 页

JAVA
626
字号
    public static byte[] decode(byte[] rawData)
    {
        try
        {

            int resultLength = (int) (rawData.length * .75); // set upper limit for binary array

            byte result[] = new byte[resultLength];

            int noBytesWritten = 0;
            int validCharacters = 0;

            byte c;
            byte quad[] = new byte[4]; // temp store for a quad of base64 byte characters
            int bytes;                // temp store for a triplet of bytes
            int numfound = 0;          // number of chars found for quad
             
             
            // iterate through, finding valid quads, and converting to byte triplets 
    
            for (int i = 0; i < rawData.length; i++)
            {
                c = rawData[i];
                if ((c >= (byte) 'A' && c <= (byte) 'Z') || (c >= (byte) 'a' && c <= (byte) 'z') || (c >= '0' && c <= '9') || (c == '+') || (c == (byte) '/') || (c == (byte) '='))
                {
                    quad[numfound++] = c;
                    validCharacters++;
                }
                else if (" \r\n\t\f".indexOf((char) c) == -1)
                {
                    //CBUtility.log("error... bad character (" + (char)c + ") read from base64 encoded string", 6);
                    return null;
                }

                // write the quad; paying special attention to possible 'filler'
                // characters '=' or '==' at the end of the string (see rfc).
                 
                if (numfound == 4)
                {
                    bytes = convertQuad(quad);
                    result[noBytesWritten++] = (byte) ((bytes & 0xFF0000) >> 16);
                    if (c != '=')
                    {
                        result[noBytesWritten++] = (byte) ((bytes & 0xFF00) >> 8);
                        result[noBytesWritten++] = (byte) (bytes & 0xFF);
                    }
                    else if (rawData[i - 1] != '=')
                    {
                        result[noBytesWritten++] = (byte) ((bytes & 0xFF00) >> 8);
                        if ((bytes & 0xFF) > 0)
                        {
                            //CBUtility.log("Warning: Corrupt base64 Encoded File - contains trailing bits after file end.", 6);
                            return null;
                        }
                    }
                    else if ((bytes & 0xFF00) > 0)
                    {
                        //CBUtility.log("Warning: Corrupt base64 Encoded File  - contains trailing bits after file end.", 6);
                        return null;
                    }

                    numfound = 0;
                }
            }
             
            // check that the number of real characters is correct - must be cleanly
            // divisible by 4...
             
            if (validCharacters % 4 != 0)
            {
                //CBUtility.log("Warning: Corrupt base64 Encoded File - Length (" + validCharacters + ") of valid characters not divisible by 4.", 6);
                return null;
            }


            byte finalResult[] = new byte[noBytesWritten];
            System.arraycopy(result, 0, finalResult, 0, noBytesWritten);
            return finalResult;
        }
        catch (Exception e)
        {
            //CBUtility.log("unable to create final decoded byte array from base64 bytes: " + e, 6);
            return null;
        }

    }

    /**
     * Decodes a byte array containing base64 encoded data.
     *
     * @param chars a String, each character of which is a seven-bit ASCII value.
     * @return the raw binary data, each byte of which may have any value from
     *         0 - 255.  This value will be null if a decoding error occurred.
     */

    public static byte[] decode(String chars)
            throws CBBase64EncodingException
    {

        if (chars == null) return null;

        byte rawData[];

        try
        {
            rawData = chars.getBytes("US-ASCII");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new CBBase64EncodingException("unable to convert base64 encoded data to bytes using US-ASCII encoding", e);
        }

        int resultLength = (int) (rawData.length * .75); // set upper limit for binary array

        byte result[] = new byte[resultLength];

        int noBytesWritten = 0;
        int validCharacters = 0;

        byte c;
        byte quad[] = new byte[4]; // temp store for a quad of base64 byte characters
        int bytes;                // temp store for a triplet of bytes
        int numfound = 0;          // number of chars found for quad


        // iterate through, finding valid quads, and converting to byte triplets

        for (int i = 0; i < rawData.length; i++)
        {
            c = rawData[i];
            if ((c >= (byte) 'A' && c <= (byte) 'Z') || (c >= (byte) 'a' && c <= (byte) 'z') || (c >= '0' && c <= '9') || (c == '+') || (c == (byte) '/') || (c == (byte) '='))
            {
                quad[numfound++] = c;
                validCharacters++;
            }
            else if (" \r\n\t\f".indexOf((char) c) == -1)
            {
                throw new CBBase64EncodingException("error... bad character (" + (char) c + ") read from base64 encoded string");
            }

            // write the quad; paying special attention to possible 'filler'
            // characters '=' or '==' at the end of the string (see rfc).

            if (numfound == 4)
            {
                bytes = convertQuad(quad);
                result[noBytesWritten++] = (byte) ((bytes & 0xFF0000) >> 16);
                if (c != '=')
                {
                    result[noBytesWritten++] = (byte) ((bytes & 0xFF00) >> 8);
                    result[noBytesWritten++] = (byte) (bytes & 0xFF);
                }
                else if (rawData[i - 1] != '=')
                {
                    result[noBytesWritten++] = (byte) ((bytes & 0xFF00) >> 8);
                    if ((bytes & 0xFF) > 0)
                    {
                        throw new CBBase64EncodingException("Warning: Corrupt base64 Encoded Data - contains trailing bits after end of base 64 data.");
                    }
                }
                else if ((bytes & 0xFF00) > 0)
                {
                    throw new CBBase64EncodingException("Warning: Corrupt base64 Encoded File  - contains trailing bits after end of base64 data.");
                }

                numfound = 0;
            }
        }

        // check that the number of real characters is correct - must be cleanly
        // divisible by 4...

        if (validCharacters % 4 != 0)
        {
            throw new CBBase64EncodingException("Warning: Corrupt base64 Encoded Data - Length (" + validCharacters + ") of valid characters not divisible by 4.");
        }


        byte finalResult[] = new byte[noBytesWritten];
        System.arraycopy(result, 0, finalResult, 0, noBytesWritten);
        return finalResult;

    }


    /**
     * Converts three bytes to 4 base 64 values...
     * a half hearted attempt has been made to make it go fast...
     *
     * @param a       the first byte to convert
     * @param b       the second byte to convert
     * @param c       the third byte to convert
     * @param Num     the Number of 'real' bytes to convert - i.e. 1 (just a),
     *                2 (a and b), or 3 (a,b and c).
     * @param buff    the result buffer to put the final values in.
     * @param buffpos the position to start filling the result buffer from.
     */

    private static void convertTriplet(byte a, byte b, byte c, int Num, byte[] buff, int buffpos)
            throws CBBase64EncodingException
    {
        byte w, x, y, z;  // the four 6 bit values extracted.
        int trip = (a << 16) | ((b << 8) & 0xFF00) | (c & 0xFF);

        w = (byte) ((trip & 0xFC0000) >> 18);
        x = (byte) ((trip & 0x03F000) >> 12);
        y = (byte) ((trip & 0x000FC0) >> 6);
        z = (byte) (trip & 0x00003F);

        buff[buffpos] = convertFrom6Bit(w);
        buff[buffpos + 1] = convertFrom6Bit(x);

        if (Num == 1)
        {
            buff[buffpos + 2] = (byte) '=';
            buff[buffpos + 3] = (byte) '=';
        }
        else
        {
            buff[buffpos + 2] = convertFrom6Bit(y);

            if (Num == 2)
            {
                buff[buffpos + 3] = (byte) '=';
            }
            else
            {
                buff[buffpos + 3] = convertFrom6Bit(z);
            }
        }
    }

    /**
     * Use rfc 1521 specified character conversions
     * (I wonder if a preset array would be faster?)
     *
     * @param b the 6 significant bit byte to be converted
     * @return the converted base64 character
     */

    // this might be sped up using an array index as provided above...

    private static byte convertFrom6Bit(byte b)
            throws CBBase64EncodingException
    {
        byte c;

        if (b < 26)
            return (byte) ('A' + b);           // 'A' -> 'Z'
        else if (b < 52)
            return (byte) (('a' - 26) + b);  // 'a' -> 'z'
        else if (b < 62)
            return (byte) (('0' - 52) + b);  // '0' -> '9'
        else if (b == 62)
            return ((byte) '+');
        else if (b == 63)
            return ((byte) '/');
        else                // error - should never happen
        {
            throw new CBBase64EncodingException("erroroneous value " + (char) b + " passed in convertFrom6bit");
        }
    }

    /**
     * Use rfc 1521 specified character conversions
     * (I wonder if a preset array would be faster?)
     *
     * @param c a byte representing a single base64 encoded character
     * @return the corresponding raw 6 bit 'true' value.
     */

    private static byte convertTo6Bit(byte c)
            throws CBBase64EncodingException
    {
        if (c == (byte) '+')
            return 62;
        else if (c == (byte) '/')
            return 63;
        else if (c == (byte) '=')  // this result not actually used by calling program...
            return 0;
        else if (c <= (byte) '9')
            return (byte) (c - (byte) '0' + 52);
        else if (c <= (byte) 'Z')
            return (byte) (c - (byte) 'A');
        else if (c <= (byte) 'z')
            return (byte) (c - (byte) 'a' + 26);
        else                // error - should never happen
        {
            throw new CBBase64EncodingException("erroroneous value " + (char) c + " passed in convertTo6bit");
        }
    }

    /**
     * Takes a triplet of base64 encoded characters, and returns
     * a triplet of appropriate bytes
     *
     * @param quad four base 64 encoded characters
     * @return the corresponding 'true' 24 bit value, as an int.
     */

    private static int convertQuad(byte[] quad)
            throws CBBase64EncodingException
    {
        byte a = convertTo6Bit(quad[0]);
        byte b = convertTo6Bit(quad[1]);
        byte c = convertTo6Bit(quad[2]);
        byte d = convertTo6Bit(quad[3]);

        int ret = (a << 18) + (b << 12) + (c << 6) + d;

        return ret;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?