| 1 | // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file | 
|---|
| 2 | // for details. All rights reserved. Use of this source code is governed by a | 
|---|
| 3 | // BSD-style license that can be found in the LICENSE file. | 
|---|
| 4 |  | 
|---|
| 5 | #include "vm/base64.h" | 
|---|
| 6 |  | 
|---|
| 7 | #include "vm/os.h" | 
|---|
| 8 |  | 
|---|
| 9 | namespace dart { | 
|---|
| 10 |  | 
|---|
| 11 | // Taken from lib/_http/crypto.dart | 
|---|
| 12 |  | 
|---|
| 13 | // Lookup table used for finding Base 64 alphabet index of a given byte. | 
|---|
| 14 | // -2 : Outside Base 64 alphabet. | 
|---|
| 15 | // -1 : '\r' or '\n' | 
|---|
| 16 | //  0 : = (Padding character). | 
|---|
| 17 | // >0 : Base 64 alphabet index of given byte. | 
|---|
| 18 | static const int8_t decode_table[] = { | 
|---|
| 19 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -1, -2, -2,  // | 
|---|
| 20 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 21 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, 62, -2, 63,  // | 
|---|
| 22 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, 00, -2, -2,  // | 
|---|
| 23 | -2, 00, 01, 02, 03, 04, 05, 06, 07, 8,  9,  10, 11, 12, 13, 14,  // | 
|---|
| 24 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, 63,  // | 
|---|
| 25 | -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,  // | 
|---|
| 26 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,  // | 
|---|
| 27 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 28 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 29 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 30 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 31 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 32 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 33 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,  // | 
|---|
| 34 | -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}; | 
|---|
| 35 |  | 
|---|
| 36 | static const char PAD = '='; | 
|---|
| 37 |  | 
|---|
| 38 | uint8_t* DecodeBase64(const char* str, intptr_t* out_decoded_len) { | 
|---|
| 39 | intptr_t len = strlen(str); | 
|---|
| 40 | if (len == 0 || (len % 4 != 0)) { | 
|---|
| 41 | return nullptr; | 
|---|
| 42 | } | 
|---|
| 43 |  | 
|---|
| 44 | int pad_length = 0; | 
|---|
| 45 | for (intptr_t i = len - 1; i >= 0; i--) { | 
|---|
| 46 | const uint8_t current_code_unit = str[i]; | 
|---|
| 47 | if (decode_table[current_code_unit] > 0) break; | 
|---|
| 48 | if (current_code_unit == PAD) pad_length++; | 
|---|
| 49 | } | 
|---|
| 50 | intptr_t decoded_en = ((len * 6) >> 3) - pad_length; | 
|---|
| 51 | uint8_t* bytes = static_cast<uint8_t*>(malloc(decoded_en)); | 
|---|
| 52 |  | 
|---|
| 53 | for (int i = 0, o = 0; o < decoded_en;) { | 
|---|
| 54 | // Accumulate 4 valid 6 bit Base 64 characters into an int. | 
|---|
| 55 | int x = 0; | 
|---|
| 56 | for (int j = 4; j > 0;) { | 
|---|
| 57 | int c = decode_table[(uint8_t)str[i++]]; | 
|---|
| 58 | if (c >= 0) { | 
|---|
| 59 | x = ((x << 6) & 0xFFFFFF) | c; | 
|---|
| 60 | j--; | 
|---|
| 61 | } | 
|---|
| 62 | } | 
|---|
| 63 | bytes[o++] = x >> 16; | 
|---|
| 64 | if (o < decoded_en) { | 
|---|
| 65 | bytes[o++] = (x >> 8) & 0xFF; | 
|---|
| 66 | if (o < decoded_en) bytes[o++] = x & 0xFF; | 
|---|
| 67 | } | 
|---|
| 68 | } | 
|---|
| 69 | if (out_decoded_len != nullptr) { | 
|---|
| 70 | *out_decoded_len = decoded_en; | 
|---|
| 71 | } | 
|---|
| 72 | return bytes; | 
|---|
| 73 | } | 
|---|
| 74 |  | 
|---|
| 75 | }  // namespace dart | 
|---|
| 76 |  | 
|---|