diff --git a/src/futils.cpp b/src/futils.cpp index 67c910ac..dc9e460d 100644 --- a/src/futils.cpp +++ b/src/futils.cpp @@ -212,51 +212,70 @@ namespace Exiv2 { result[resultIndex] = 0; return 1; /* indicate success */ } // base64encode - - long base64decode(const char *in, char *out, size_t out_size) { - static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW" - "$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; - long len; - long i; - long done = 0; - unsigned char v; - unsigned char quad[4]; - - while (*in) { - len = 0; - for (i = 0; i < 4 && *in; i++) { - v = 0; - while (*in && !v) { - v = *in++; - v = (v < 43 || v > 122) ? 0 : decode[v - 43]; - if (v) - v = (v == '$') ? 0 : v - 61; - if (*in) { - len++; - if (v) - quad[i] = v - 1; - } else - quad[i] = 0; - } - } - if (!len) - continue; - if (out_size < (size_t) (done + len - 1)) - /* out buffer is too small */ - return -1; - if (len >= 2) - *out++ = quad[0] << 2 | quad[1] >> 4; - if (len >= 3) - *out++ = quad[1] << 4 | quad[2] >> 2; - if (len >= 4) - *out++ = ((quad[2] << 6) & 0xc0) | quad[3]; - done += len - 1; - } - if ((size_t)(done + 1) >= out_size) - return -1; - *out++ = '\0'; - return done; - } // base64decode + + // https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c + static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + + static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); + } + + 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-- && ( 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]); + + 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; + } + + long base64decode(const char *in, char *out, size_t out_size) + { + std::string in_string(in); + std::string out_string = base64_decode(in_string); + long result = (long) out_string.size(); + if ( (long) out_size > result ) { + memcpy(out,out_string.c_str(),result); + out[result] = 0; + } else result = -1 ; + return result; + } Protocol fileProtocol(const std::string& path) { Protocol result = pFile ;