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; 364bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber 374bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber if (n >= 3 && s.c_str()[n - 3] == '=') { 384bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber padding = 3; 394bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber } 4072961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 4172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 4272961230a5890071bcca436eb5630172ce84ec41Andreas Huber 4372961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t outLen = 3 * s.size() / 4 - padding; 4472961230a5890071bcca436eb5630172ce84ec41Andreas Huber 4572961230a5890071bcca436eb5630172ce84ec41Andreas Huber sp<ABuffer> buffer = new ABuffer(outLen); 4672961230a5890071bcca436eb5630172ce84ec41Andreas Huber 4772961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t *out = buffer->data(); 4872961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t j = 0; 4972961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint32_t accum = 0; 5072961230a5890071bcca436eb5630172ce84ec41Andreas Huber for (size_t i = 0; i < n; ++i) { 5172961230a5890071bcca436eb5630172ce84ec41Andreas Huber char c = s.c_str()[i]; 5272961230a5890071bcca436eb5630172ce84ec41Andreas Huber unsigned value; 5372961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (c >= 'A' && c <= 'Z') { 5472961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = c - 'A'; 5572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c >= 'a' && c <= 'z') { 5672961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 26 + c - 'a'; 5772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c >= '0' && c <= '9') { 5872961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 52 + c - '0'; 5972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c == '+') { 6072961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 62; 6172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c == '/') { 6272961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 63; 6372961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (c != '=') { 6472961230a5890071bcca436eb5630172ce84ec41Andreas Huber return NULL; 6572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else { 6672961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (i < n - padding) { 6772961230a5890071bcca436eb5630172ce84ec41Andreas Huber return NULL; 6872961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 6972961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7072961230a5890071bcca436eb5630172ce84ec41Andreas Huber value = 0; 7172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 7272961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7372961230a5890071bcca436eb5630172ce84ec41Andreas Huber accum = (accum << 6) | value; 7472961230a5890071bcca436eb5630172ce84ec41Andreas Huber 7572961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (((i + 1) % 4) == 0) { 7672961230a5890071bcca436eb5630172ce84ec41Andreas Huber out[j++] = (accum >> 16); 7772961230a5890071bcca436eb5630172ce84ec41Andreas Huber 784bbfff2dbf3968c267c3b2ea9f8912a38372a9daAndreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 7972961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 8072961230a5890071bcca436eb5630172ce84ec41Andreas Huber 8172961230a5890071bcca436eb5630172ce84ec41Andreas Huber accum = 0; 8272961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 8372961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 8472961230a5890071bcca436eb5630172ce84ec41Andreas Huber 8572961230a5890071bcca436eb5630172ce84ec41Andreas Huber return buffer; 8672961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 8772961230a5890071bcca436eb5630172ce84ec41Andreas Huber 8872961230a5890071bcca436eb5630172ce84ec41Andreas Huberstatic char encode6Bit(unsigned x) { 8972961230a5890071bcca436eb5630172ce84ec41Andreas Huber if (x <= 25) { 9072961230a5890071bcca436eb5630172ce84ec41Andreas Huber return 'A' + x; 9172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x <= 51) { 9272961230a5890071bcca436eb5630172ce84ec41Andreas Huber return 'a' + x - 26; 9372961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x <= 61) { 9472961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '0' + x - 52; 9572961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else if (x == 62) { 9672961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '+'; 9772961230a5890071bcca436eb5630172ce84ec41Andreas Huber } else { 9872961230a5890071bcca436eb5630172ce84ec41Andreas Huber return '/'; 9972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 10072961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 10172961230a5890071bcca436eb5630172ce84ec41Andreas Huber 10272961230a5890071bcca436eb5630172ce84ec41Andreas Hubervoid encodeBase64( 10372961230a5890071bcca436eb5630172ce84ec41Andreas Huber const void *_data, size_t size, AString *out) { 10472961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->clear(); 10572961230a5890071bcca436eb5630172ce84ec41Andreas Huber 10672961230a5890071bcca436eb5630172ce84ec41Andreas Huber const uint8_t *data = (const uint8_t *)_data; 10772961230a5890071bcca436eb5630172ce84ec41Andreas Huber 10872961230a5890071bcca436eb5630172ce84ec41Andreas Huber size_t i; 10972961230a5890071bcca436eb5630172ce84ec41Andreas Huber for (i = 0; i < (size / 3) * 3; i += 3) { 11072961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 11172961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x2 = data[i + 1]; 11272961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x3 = data[i + 2]; 11372961230a5890071bcca436eb5630172ce84ec41Andreas Huber 11472961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 11572961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); 11672961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f)); 11772961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x3 & 0x3f)); 11872961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 11972961230a5890071bcca436eb5630172ce84ec41Andreas Huber switch (size % 3) { 12072961230a5890071bcca436eb5630172ce84ec41Andreas Huber case 0: 12172961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 12272961230a5890071bcca436eb5630172ce84ec41Andreas Huber case 2: 12372961230a5890071bcca436eb5630172ce84ec41Andreas Huber { 12472961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 12572961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x2 = data[i + 1]; 12672961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 12772961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f)); 12872961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x2 << 2) & 0x3f)); 12972961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append('='); 13072961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 13172961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 13272961230a5890071bcca436eb5630172ce84ec41Andreas Huber default: 13372961230a5890071bcca436eb5630172ce84ec41Andreas Huber { 13472961230a5890071bcca436eb5630172ce84ec41Andreas Huber uint8_t x1 = data[i]; 13572961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit(x1 >> 2)); 13672961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append(encode6Bit((x1 << 4) & 0x3f)); 13772961230a5890071bcca436eb5630172ce84ec41Andreas Huber out->append("=="); 13872961230a5890071bcca436eb5630172ce84ec41Andreas Huber break; 13972961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 14072961230a5890071bcca436eb5630172ce84ec41Andreas Huber } 14172961230a5890071bcca436eb5630172ce84ec41Andreas Huber} 14272961230a5890071bcca436eb5630172ce84ec41Andreas Huber 14372961230a5890071bcca436eb5630172ce84ec41Andreas Huber} // namespace android 144