summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/StringCodecs')
-rw-r--r--Swiften/StringCodecs/Base64.cpp191
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;
-}
-
}