172961230a5890071bcca436eb5630172ce84ec41Andreas Huber/* 272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Copyright (C) 2010 The Android Open Source Project 372961230a5890071bcca436eb5630172ce84ec41Andreas Huber * 472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 572961230a5890071bcca436eb5630172ce84ec41Andreas Huber * you may not use this file except in compliance with the License. 672961230a5890071bcca436eb5630172ce84ec41Andreas Huber * You may obtain a copy of the License at 772961230a5890071bcca436eb5630172ce84ec41Andreas Huber * 872961230a5890071bcca436eb5630172ce84ec41Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 972961230a5890071bcca436eb5630172ce84ec41Andreas Huber * 1072961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Unless required by applicable law or agreed to in writing, software 1172961230a5890071bcca436eb5630172ce84ec41Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1372961230a5890071bcca436eb5630172ce84ec41Andreas Huber * See the License for the specific language governing permissions and 1472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * limitations under the License. 1572961230a5890071bcca436eb5630172ce84ec41Andreas Huber */ 1672961230a5890071bcca436eb5630172ce84ec41Andreas Huber 1772961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "base64.h" 1872961230a5890071bcca436eb5630172ce84ec41Andreas Huber 1972961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "ABuffer.h" 2072961230a5890071bcca436eb5630172ce84ec41Andreas Huber#include "ADebug.h" 2172961230a5890071bcca436eb5630172ce84ec41Andreas Huber 2272961230a5890071bcca436eb5630172ce84ec41Andreas Hubernamespace android { 2372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 2472961230a5890071bcca436eb5630172ce84ec41Andreas Hubersp<ABuffer> decodeBase64(const AString &s) { 2572961230a5890071bcca436eb5630172ce84ec41Andreas Huber if ((s.size() % 4) != 0) { 2672961230a5890071bcca436eb5630172ce84ec41Andreas Huber return NULL; 2772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 2872961230a5890071bcca436eb5630172ce84ec41Andreas Huber 2972961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t n = s.size(); 3072961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t padding = 0; 3172961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (n >= 1 && s.c_str()[n - 1] == '=') { 3272961230a5890071bcca436eb5630172ce84ec41Andreas Huber padding = 1; 3372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 3472961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (n >= 2 && s.c_str()[n - 2] == '=') { 3572961230a5890071bcca436eb5630172ce84ec41Andreas Huber padding = 2; 3672961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 3772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 3872961230a5890071bcca436eb5630172ce84ec41Andreas Huber 3972961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t outLen = 3 * s.size() / 4 - padding; 4072961230a5890071bcca436eb5630172ce84ec41Andreas Huber 4172961230a5890071bcca436eb5630172ce84ec41Andreas Huber sp<ABuffer> buffer = new ABuffer(outLen); 4272961230a5890071bcca436eb5630172ce84ec41Andreas Huber 4372961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t *out = buffer->data(); 4472961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t j = 0; 4572961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint32_t accum = 0; 4672961230a5890071bcca436eb5630172ce84ec41Andreas Huber for (size_t i = 0; i < n; ++i) { 4772961230a5890071bcca436eb5630172ce84ec41Andreas Huber char c = s.c_str()[i]; 4872961230a5890071bcca436eb5630172ce84ec41Andreas Huber unsigned value; 4972961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (c >= 'A' && c <= 'Z') { 5072961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = c - 'A'; 5172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c >= 'a' && c <= 'z') { 5272961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 26 + c - 'a'; 5372961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c >= '0' && c <= '9') { 5472961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 52 + c - '0'; 5572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c == '+') { 5672961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 62; 5772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c == '/') { 5872961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 63; 5972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c != '=') { 6072961230a5890071bcca436eb5630172ce84ec41Andreas Huber return NULL; 6172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else { 6272961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (i < n - padding) { 6372961230a5890071bcca436eb5630172ce84ec41Andreas Huber return NULL; 6472961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 6572961230a5890071bcca436eb5630172ce84ec41Andreas Huber 6672961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 0; 6772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 6872961230a5890071bcca436eb5630172ce84ec41Andreas Huber 6972961230a5890071bcca436eb5630172ce84ec41Andreas Huber accum = (accum << 6) | value; 7072961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7172961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (((i + 1) % 4) == 0) { 7272961230a5890071bcca436eb5630172ce84ec41Andreas Huber out[j++] = (accum >> 16); 7372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7472961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 7572961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 7672961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7772961230a5890071bcca436eb5630172ce84ec41Andreas Huber accum = 0; 7872961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 7972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 8072961230a5890071bcca436eb5630172ce84ec41Andreas Huber 8172961230a5890071bcca436eb5630172ce84ec41Andreas Huber return buffer; 8272961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 8372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 8472961230a5890071bcca436eb5630172ce84ec41Andreas Huberstatic char encode6Bit(unsigned x) { 8572961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (x <= 25) { 8672961230a5890071bcca436eb5630172ce84ec41Andreas Huber return 'A' + x; 8772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x <= 51) { 8872961230a5890071bcca436eb5630172ce84ec41Andreas Huber return 'a' + x - 26; 8972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x <= 61) { 9072961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '0' + x - 52; 9172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x == 62) { 9272961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '+'; 9372961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else { 9472961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '/'; 9572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 9672961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 9772961230a5890071bcca436eb5630172ce84ec41Andreas Huber 9872961230a5890071bcca436eb5630172ce84ec41Andreas Hubervoid encodeBase64( 9972961230a5890071bcca436eb5630172ce84ec41Andreas Huber const void *_data, size_t size, AString *out) { 10072961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->clear(); 10172961230a5890071bcca436eb5630172ce84ec41Andreas Huber 10272961230a5890071bcca436eb5630172ce84ec41Andreas Huber const uint8_t *data = (const uint8_t *)_data; 10372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 10472961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t i; 10572961230a5890071bcca436eb5630172ce84ec41Andreas Huber for (i = 0; i < (size / 3) * 3; i += 3) { 10672961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 10772961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x2 = data[i + 1]; 10872961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x3 = data[i + 2]; 10972961230a5890071bcca436eb5630172ce84ec41Andreas Huber 11072961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 11172961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); 11272961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f)); 11372961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x3 & 0x3f)); 11472961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 11572961230a5890071bcca436eb5630172ce84ec41Andreas Huber switch (size % 3) { 11672961230a5890071bcca436eb5630172ce84ec41Andreas Huber case 0: 11772961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 11872961230a5890071bcca436eb5630172ce84ec41Andreas Huber case 2: 11972961230a5890071bcca436eb5630172ce84ec41Andreas Huber { 12072961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 12172961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x2 = data[i + 1]; 12272961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 12372961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); 12472961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x2 << 2) & 0x3f)); 12572961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append('='); 12672961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 12772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 12872961230a5890071bcca436eb5630172ce84ec41Andreas Huber default: 12972961230a5890071bcca436eb5630172ce84ec41Andreas Huber { 13072961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 13172961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 13272961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4) & 0x3f)); 13372961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append("=="); 13472961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 13572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 13672961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 13772961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 13872961230a5890071bcca436eb5630172ce84ec41Andreas Huber 13972961230a5890071bcca436eb5630172ce84ec41Andreas Huber} // namespace android 140