diff options
Diffstat (limited to 'Swiften/StringCodecs')
-rw-r--r-- | Swiften/StringCodecs/Base64.cpp | 191 |
1 files changed, 91 insertions, 100 deletions
diff --git a/Swiften/StringCodecs/Base64.cpp b/Swiften/StringCodecs/Base64.cpp index 195987e..76e2833 100644 --- a/Swiften/StringCodecs/Base64.cpp +++ b/Swiften/StringCodecs/Base64.cpp @@ -4,6 +4,8 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ +// Code copied & adapted from LibTomCrypt by Tom St Denis + #include <boost/numeric/conversion/cast.hpp> #include <algorithm> @@ -11,120 +13,109 @@ #include <Swiften/StringCodecs/Base64.h> #include <Swiften/Base/Algorithm.h> -namespace Swift { - #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wconversion" + +static const char *codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + namespace { template<typename TargetType, typename SourceType> - TargetType base64Encode(const SourceType& s) { - int i; - int len = s.size(); - char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - int a, b, c; - - TargetType p; - p.resize((len+2)/3*4); - int at = 0; - for( i = 0; i < len; i += 3 ) { - a = ((unsigned char) (s[i]) & 3) << 4; - if(i + 1 < len) { - a += (unsigned char) (s[i + 1]) >> 4; - b = ((unsigned char) (s[i + 1]) & 0xF) << 2; - if(i + 2 < len) { - b += (unsigned char) (s[i + 2]) >> 6; - c = (unsigned char) (s[i + 2]) & 0x3F; - } - else - c = 64; - } - else { - b = c = 64; - } - - p[at++] = tbl[(unsigned char) (s[i]) >> 2]; - p[at++] = tbl[a]; - p[at++] = tbl[b]; - p[at++] = tbl[c]; - } - return p; - } + TargetType base64Encode(const SourceType& in) { + TargetType out; + + size_t i; + unsigned int leven = 3*(in.size() / 3); + for (i = 0; i < leven; i += 3) { + out.push_back(codes[(in[i] >> 2) & 0x3F]); + out.push_back(codes[(((in[i] & 3) << 4) + (in[i+1] >> 4)) & 0x3F]); + out.push_back(codes[(((in[i+1] & 0xf) << 2) + (in[i+2] >> 6)) & 0x3F]); + out.push_back(codes[in[i+2] & 0x3F]); + } + if (i < in.size()) { + unsigned int a = in[i]; + unsigned int b = (i+1 < in.size()) ? in[i+1] : 0; + + out.push_back(codes[(a >> 2) & 0x3F]); + out.push_back(codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]); + out.push_back((i+1 < in.size()) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='); + out.push_back('='); + } + return out; + } } -std::string Base64::encode(const ByteArray &s) { - return base64Encode<std::string, ByteArray>(s); -} +static const unsigned char map[256] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, + 255, 254, 255, 255, 255, 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, 255, 255, 255, 255, 255, + 255, 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, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255 }; -SafeByteArray Base64::encode(const SafeByteArray &s) { - return base64Encode<SafeByteArray, SafeByteArray>(s); -} +namespace Swift { + std::string Base64::encode(const ByteArray &s) { + return base64Encode<std::string, ByteArray>(s); + } -ByteArray Base64::decode(const std::string& input) { - std::string inputWithoutNewlines(input); - erase(inputWithoutNewlines, '\n'); - - const std::string& s = inputWithoutNewlines; - ByteArray p; - - // -1 specifies invalid - // 64 specifies eof - // everything else specifies data - - char tbl[] = { - -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,64,-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, - }; - - // this should be a multiple of 4 - int len = s.size(); - - if(len % 4) { - return p; + SafeByteArray Base64::encode(const SafeByteArray &s) { + return base64Encode<SafeByteArray, SafeByteArray>(s); } - p.resize(len / 4 * 3); + ByteArray Base64::decode(const std::string& input) { + std::string inputWithoutNewlines(input); + erase(inputWithoutNewlines, '\n'); + + const std::string& s = inputWithoutNewlines; + ByteArray out; - int i; - int at = 0; + int g = 3; + size_t y, t; + for (size_t x = y = t = 0; x < s.size(); ++x) { + unsigned char c = map[s[x]&0xFF]; + if (c == 255) { + continue; + } + /* the final = symbols are read and used to trim the remaining bytes */ + if (c == 254) { + c = 0; + /* prevent g < 0 which would potentially allow an overflow later */ + if (--g < 0) { + return ByteArray(); + } + } else if (g != 3) { + /* we only allow = to be at the end */ + return ByteArray(); + } - int a, b, c, d; - c = d = 0; + t = (t<<6)|c; - for( i = 0; i < len; i += 4 ) { - a = tbl[boost::numeric_cast<int>(s[i])]; - b = tbl[boost::numeric_cast<int>(s[i + 1])]; - c = tbl[boost::numeric_cast<int>(s[i + 2])]; - d = tbl[boost::numeric_cast<int>(s[i + 3])]; - if((a == 64 || b == 64) || (a < 0 || b < 0 || c < 0 || d < 0)) { - p.resize(0); - return p; + if (++y == 4) { + out.push_back((unsigned char)((t>>16)&255)); + if (g > 1) out.push_back((unsigned char)((t>>8)&255)); + if (g > 2) out.push_back((unsigned char)(t&255)); + y = t = 0; + } + } + if (y != 0) { + return ByteArray(); } - p[at++] = ((a & 0x3F) << 2) | ((b >> 4) & 0x03); - p[at++] = ((b & 0x0F) << 4) | ((c >> 2) & 0x0F); - p[at++] = ((c & 0x03) << 6) | ((d >> 0) & 0x3F); + return out; } - - if(c & 64) - p.resize(at - 2); - else if(d & 64) - p.resize(at - 1); - - return p; -} - } |