/* * This file is part of the Flowee project * Copyright (C) 2009-2010 Satoshi Nakamoto * Copyright (C) 2009-2016 The Bitcoin Core developers * Copyright (C) 2023 Tom Zander * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "StringUtils.h" #include "utilstrencodings.h" #include std::vector StringUtils::parseHex(const char *string, int size) { const char *end = string + size; std::vector answer; while (string < end) { while (isspace(*string)) string++; signed char c = HexDigit(*string++); if (c == (signed char)-1) break; unsigned char n = (c << 4); c = HexDigit(*string++); if (c == (signed char)-1) break; n |= c; answer.push_back(n); } return answer; } std::vector StringUtils::parseHex(const std::string &source) { return parseHex(source.c_str(), source.size()); } std::string StringUtils::decodeBase64(const std::string &source) { std::vector vchRet = decodeBase64(source.c_str()); if (vchRet.empty()) return std::string(); return std::string((const char*)&vchRet[0], vchRet.size()); } std::string StringUtils::encodeBase64(const char *source, size_t length) { static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string answer; answer.reserve((length+2)/3*4); int mode = 0, left = 0; const uint8_t *ptr = reinterpret_cast(source); const uint8_t *end = ptr + length; while (ptr < end) { int enc = *(ptr++); switch (mode) { case 0: // we have no bits answer += pbase64[enc >> 2]; left = (enc & 3) << 4; mode = 1; break; case 1: // we have two bits answer += pbase64[left | (enc >> 4)]; left = (enc & 15) << 2; mode = 2; break; case 2: // we have four bits answer += pbase64[left | (enc >> 6)]; answer += pbase64[enc & 63]; mode = 0; break; } } if (mode) { answer += pbase64[left]; answer += '='; if (mode == 1) answer += '='; } return answer; } std::string StringUtils::encodeBase64(const std::string &source) { return encodeBase64(source.c_str(), source.size()); } std::vector StringUtils::decodeBase64(const char *source, bool *ok) { static const int decode64_table[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; if (ok) *ok = true; std::vector answer; answer.reserve(strlen(source) * 3 / 4); int mode = 0; int left = 0; while (true) { int dec = decode64_table[(unsigned char)*source]; if (dec == -1) break; source++; switch (mode) { case 0: // we have no bits and get 6 left = dec; mode = 1; break; case 1: // we have 6 bits and keep 4 answer.push_back((left<<2) | (dec>>4)); left = dec & 15; mode = 2; break; case 2: // we have 4 bits and get 6, we keep 2 answer.push_back((left<<4) | (dec>>2)); left = dec & 3; mode = 3; break; case 3: // we have 2 bits and get 6 answer.push_back((left<<6) | dec); mode = 0; break; } } if (ok) switch (mode) { case 0: break; // 4n base64 characters processed: ok case 1: // 4n+1 base64 character processed: impossible *ok = false; break; case 2: // 4n+2 base64 characters processed: require '==' if (left || source[0] != '=' || source[1] != '=' || decode64_table[(unsigned char)source[2]] != -1) *ok = false; break; case 3: // 4n+3 base64 characters processed: require '=' if (left || source[0] != '=' || decode64_table[(unsigned char)source[1]] != -1) *ok = false; break; } return answer; }