diff --git a/src/futils.cpp b/src/futils.cpp index dc9e460d..82596d4b 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -139,131 +139,105 @@ namespace Exiv2 { delete [] decodeStr; } - int base64encode(const void* data_buf, size_t dataLength, char* result, size_t resultSize) { - const char base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - const uint8_t* data = (const uint8_t*)data_buf; - size_t resultIndex = 0; - size_t x; - uint32_t n = 0; - size_t padCount = dataLength % 3; - uint8_t n0, n1, n2, n3; - - /* increment over the length of the string, three characters at a time */ - for (x = 0; x < dataLength; x += 3) - { - /* these three 8-bit (ASCII) characters become one 24-bit number */ - n = data[x] << 16; - - if((x+1) < dataLength) - n += data[x+1] << 8; - - if((x+2) < dataLength) - n += data[x+2]; - - /* this 24-bit number gets separated into four 6-bit numbers */ - n0 = (uint8_t)(n >> 18) & 63; - n1 = (uint8_t)(n >> 12) & 63; - n2 = (uint8_t)(n >> 6) & 63; - n3 = (uint8_t)n & 63; - - /* - * if we have one byte available, then its encoding is spread - * out over two characters - */ - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex++] = base64chars[n0]; - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex++] = base64chars[n1]; - - /* - * if we have only two bytes available, then their encoding is - * spread out over three chars - */ - if((x+1) < dataLength) - { - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex++] = base64chars[n2]; - } - - /* - * if we have all three bytes available, then their encoding is spread - * out over four characters - */ - if((x+2) < dataLength) - { - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex++] = base64chars[n3]; - } - } - - /* - * create and add padding that is required if we did not have a multiple of 3 - * number of characters available - */ - if (padCount > 0) - { - for (; padCount < 3; padCount++) - { - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex++] = '='; - } - } - if(resultIndex >= resultSize) return 0; /* indicate failure: buffer too small */ - result[resultIndex] = 0; - return 1; /* indicate success */ - } // base64encode - // https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c - static const std::string base64_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; + static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); + } - static inline bool is_base64(unsigned char c) { - return (isalnum(c) || (c == '+') || (c == '/')); - } + static std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; - static std::string base64_decode(std::string const& encoded_string) { - int in_len = encoded_string.size(); - int i = 0; - int j = 0; - int in_ = 0; - unsigned char char_array_4[4], char_array_3[3]; - std::string ret; + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; - while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { - char_array_4[i++] = encoded_string[in_]; in_++; - if (i ==4) { - for (i = 0; i <4; i++) - char_array_4[i] = base64_chars.find(char_array_4[i]); + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + if (i) { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; - for (i = 0; (i < 3); i++) - ret += char_array_3[i]; - i = 0; - } - } + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; - if (i) { - for (j = i; j <4; j++) - char_array_4[j] = 0; + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; - for (j = 0; j <4; j++) - char_array_4[j] = base64_chars.find(char_array_4[j]); + while((i++ < 3)) + ret += '='; + } + return ret; + } - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + static std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; - for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; - } + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); - return ret; - } + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; + } + + int base64encode(const void* data_buf, size_t dataLength, char* result, size_t resultSize) { + int rc = 0 ; // failed + std::string encoded = base64_encode((unsigned char const*)data_buf, (unsigned int) dataLength) ; + if (encoded.size() < resultSize ) { + memcpy(result,encoded.c_str(),encoded.size()); + rc = 1 ; // indicate success + } + return rc; + } // base64encode long base64decode(const char *in, char *out, size_t out_size) {