1 ///////////////////////////////////////////////////////////////////////////// 2 // Copyright (c) 2009-2014 Alan Wright. All rights reserved. 3 // Distributable under the terms of either the Apache License (Version 2.0) 4 // or the GNU Lesser General Public License. 5 ///////////////////////////////////////////////////////////////////////////// 6 7 #include "LuceneInc.h" 8 #include "Base64.h" 9 #include "MiscUtils.h" 10 #include "UnicodeUtils.h" 11 12 namespace Lucene { 13 14 const String Base64::BASE64_CHARS = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 15 ~Base64()16Base64::~Base64() { 17 } 18 encode(ByteArray bytes)19String Base64::encode(ByteArray bytes) { 20 return encode(bytes.get(), bytes.size()); 21 } 22 encode(const uint8_t * bytes,int32_t length)23String Base64::encode(const uint8_t* bytes, int32_t length) { 24 String result; 25 uint8_t byteArray3[3]; 26 uint8_t byteArray4[4]; 27 int32_t i = 0; 28 29 while (length--) { 30 byteArray3[i++] = *(bytes++); 31 if (i == 3) { 32 byteArray4[0] = (byteArray3[0] & 0xfc) >> 2; 33 byteArray4[1] = ((byteArray3[0] & 0x03) << 4) + ((byteArray3[1] & 0xf0) >> 4); 34 byteArray4[2] = ((byteArray3[1] & 0x0f) << 2) + ((byteArray3[2] & 0xc0) >> 6); 35 byteArray4[3] = byteArray3[2] & 0x3f; 36 37 for (i = 0; i < 4; ++i) { 38 result += BASE64_CHARS[byteArray4[i]]; 39 } 40 i = 0; 41 } 42 } 43 44 if (i != 0) { 45 for (int32_t j = i; j < 3; ++j) { 46 byteArray3[j] = 0; 47 } 48 49 byteArray4[0] = (byteArray3[0] & 0xfc) >> 2; 50 byteArray4[1] = ((byteArray3[0] & 0x03) << 4) + ((byteArray3[1] & 0xf0) >> 4); 51 byteArray4[2] = ((byteArray3[1] & 0x0f) << 2) + ((byteArray3[2] & 0xc0) >> 6); 52 byteArray4[3] = byteArray3[2] & 0x3f; 53 54 for (int32_t j = 0; j < i + 1; ++j) { 55 result += BASE64_CHARS[byteArray4[j]]; 56 } 57 58 while (i++ < 3) { 59 result += L'='; 60 } 61 } 62 return result; 63 } 64 decode(const String & str)65ByteArray Base64::decode(const String& str) { 66 int32_t length = str.length(); 67 uint8_t byteArray4[4]; 68 uint8_t byteArray3[3]; 69 70 int32_t i = 0; 71 int32_t charIndex = 0; 72 73 ByteArray result(ByteArray::newInstance(length / 2)); 74 int32_t resultIndex = 0; 75 76 while (length-- && str[charIndex] != L'=' && isBase64(str[charIndex])) { 77 byteArray4[i++] = (uint8_t)str[charIndex++]; 78 if (i == 4) { 79 for (i = 0; i < 4; ++i) { 80 byteArray4[i] = static_cast<uint8_t>(BASE64_CHARS.find(byteArray4[i])); 81 } 82 byteArray3[0] = (byteArray4[0] << 2) + ((byteArray4[1] & 0x30) >> 4); 83 byteArray3[1] = ((byteArray4[1] & 0xf) << 4) + ((byteArray4[2] & 0x3c) >> 2); 84 byteArray3[2] = ((byteArray4[2] & 0x3) << 6) + byteArray4[3]; 85 86 for (i = 0; i < 3; ++i) { 87 if (resultIndex >= result.size()) { 88 result.resize((int32_t)((double)result.size() * 1.5)); 89 } 90 result[resultIndex++] = byteArray3[i]; 91 } 92 93 i = 0; 94 } 95 } 96 97 if (i != 0) { 98 for (int32_t j = i; j < 4; ++j) { 99 byteArray4[j] = 0; 100 } 101 for (int32_t j = 0; j < 4; ++j) { 102 byteArray4[j] = static_cast<uint8_t>(BASE64_CHARS.find(byteArray4[j])); 103 } 104 byteArray3[0] = (byteArray4[0] << 2) + ((byteArray4[1] & 0x30) >> 4); 105 byteArray3[1] = ((byteArray4[1] & 0xf) << 4) + ((byteArray4[2] & 0x3c) >> 2); 106 byteArray3[2] = ((byteArray4[2] & 0x3) << 6) + byteArray4[3]; 107 108 for (int32_t j = 0; j < i - 1; ++j) { 109 if (resultIndex >= result.size()) { 110 result.resize((int32_t)((double)result.size() * 1.5)); 111 } 112 result[resultIndex++] = byteArray3[j]; 113 } 114 } 115 116 result.resize(resultIndex); 117 118 return result; 119 } 120 isBase64(wchar_t ch)121bool Base64::isBase64(wchar_t ch) { 122 return (UnicodeUtil::isAlnum(ch) || ch == L'+' || ch == L'/'); 123 } 124 125 } 126