aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/util.cc59
-rw-r--r--src/libutil/util.hh5
2 files changed, 64 insertions, 0 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 4f3010880..be0a9bf31 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -1208,4 +1208,63 @@ string filterANSIEscapes(const string & s, bool nixOnly)
}
+static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+string base64Encode(const string & s)
+{
+ string res;
+ int data = 0, nbits = 0;
+
+ for (char c : s) {
+ data = data << 8 | (unsigned char) c;
+ nbits += 8;
+ while (nbits >= 6) {
+ nbits -= 6;
+ res.push_back(base64Chars[data >> nbits & 0x3f]);
+ }
+ }
+
+ if (nbits) res.push_back(base64Chars[data << (6 - nbits) & 0x3f]);
+ while (res.size() % 4) res.push_back('=');
+
+ return res;
+}
+
+
+string base64Decode(const string & s)
+{
+ bool init = false;
+ char decode[256];
+ if (!init) {
+ // FIXME: not thread-safe.
+ memset(decode, -1, sizeof(decode));
+ for (int i = 0; i < 64; i++)
+ decode[(int) base64Chars[i]] = i;
+ init = true;
+ }
+
+ string res;
+ unsigned int d = 0, bits = 0;
+
+ for (char c : s) {
+ if (c == '=') break;
+ if (c == '\n') continue;
+
+ char digit = decode[(unsigned char) c];
+ if (digit == -1)
+ throw Error("invalid character in Base64 string");
+
+ bits += 6;
+ d = d << 6 | digit;
+ if (bits >= 8) {
+ res.push_back(d >> (bits - 8) & 0xff);
+ bits -= 8;
+ }
+ }
+
+ return res;
+}
+
+
}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 1a2dda527..20330fb76 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -398,4 +398,9 @@ void ignoreException();
string filterANSIEscapes(const string & s, bool nixOnly = false);
+/* Base64 encoding/decoding. */
+string base64Encode(const string & s);
+string base64Decode(const string & s);
+
+
}