1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007 Esmertec AG. 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007 The Android Open Source Project 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage android.support.v7.mms.pdu; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class Base64 { 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Used to get the number of Quadruples. 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final int FOURBYTE = 4; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Byte used to pad output. 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final byte PAD = (byte) '='; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * The base length. 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final int BASELENGTH = 255; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Create arrays to hold the base64 characters 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static byte[] base64Alphabet = new byte[BASELENGTH]; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Populating the character arrays 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static { 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < BASELENGTH; i++) { 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet[i] = (byte) -1; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 'Z'; i >= 'A'; i--) { 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet[i] = (byte) (i - 'A'); 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 'z'; i >= 'a'; i--) { 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet[i] = (byte) (i - 'a' + 26); 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = '9'; i >= '0'; i--) { 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet[i] = (byte) (i - '0' + 52); 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet['+'] = 62; 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Alphabet['/'] = 63; 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Decodes Base64 data into octects 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param base64Data Byte array containing Base64 data 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return Array containing decoded data. 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static byte[] decodeBase64(byte[] base64Data) { 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // RFC 2045 requires that we discard ALL non-Base64 characters 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd base64Data = discardNonBase64(base64Data); 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // handle the edge case, so we don't have to worry about it later 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (base64Data.length == 0) { 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new byte[0]; 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int numberQuadruple = base64Data.length / FOURBYTE; 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd byte decodedData[] = null; 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0; 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Throw away anything not in base64Data 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int encodedIndex = 0; 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int dataIndex = 0; 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd { 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // this sizes the output array properly - rlw 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int lastData = base64Data.length; 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ignore the '=' padding 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (base64Data[lastData - 1] == PAD) { 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (--lastData == 0) { 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new byte[0]; 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData = new byte[lastData - numberQuadruple]; 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < numberQuadruple; i++) { 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd dataIndex = i * 4; 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd marker0 = base64Data[dataIndex + 2]; 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd marker1 = base64Data[dataIndex + 3]; 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd b1 = base64Alphabet[base64Data[dataIndex]]; 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd b2 = base64Alphabet[base64Data[dataIndex + 1]]; 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (marker0 != PAD && marker1 != PAD) { 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd //No PAD e.g 3cQl 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd b3 = base64Alphabet[marker0]; 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd b4 = base64Alphabet[marker1]; 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex + 1] = 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4); 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (marker0 == PAD) { 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd //Two PAD e.g. 3c[Pad][Pad] 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (marker1 == PAD) { 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd //One PAD e.g. 3cQ[Pad] 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd b3 = base64Alphabet[marker0]; 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4); 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd decodedData[encodedIndex + 1] = 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf)); 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd encodedIndex += 3; 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return decodedData; 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Check octect wheter it is a base64 encoding. 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param octect to be checked byte 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return ture if it is base64 encoding, false otherwise. 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static boolean isBase64(byte octect) { 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (octect == PAD) { 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (base64Alphabet[octect] == -1) { 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Discards any characters outside of the base64 alphabet, per 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * the requirements on page 25 of RFC 2045 - "Any characters 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * outside of the base64 alphabet are to be ignored in base64 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * encoded data." 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param data The base-64 encoded data to groom 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @return The data, less non-base64 characters (see RFC 2045). 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static byte[] discardNonBase64(byte[] data) { 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd byte groomedData[] = new byte[data.length]; 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int bytesCopied = 0; 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < data.length; i++) { 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isBase64(data[i])) { 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd groomedData[bytesCopied++] = data[i]; 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd byte packedData[] = new byte[bytesCopied]; 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd System.arraycopy(groomedData, 0, packedData, 0, bytesCopied); 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return packedData; 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 168