summaryrefslogtreecommitdiff
path: root/src/base64.cc
diff options
context:
space:
mode:
authorJoel Klinghed <the_jk@yahoo.com>2015-06-25 02:14:18 +0200
committerJoel Klinghed <the_jk@yahoo.com>2015-06-25 02:14:18 +0200
commit85adf26a787b33d69d07df0dc786516fed800e21 (patch)
tree12de4b0cae3999f3da7bbf3d21c631eecf6bf4a3 /src/base64.cc
parent0c55606145b6c5d9a303b19b3dba4996ec3ed3a9 (diff)
Add basic auth support
Diffstat (limited to 'src/base64.cc')
-rw-r--r--src/base64.cc69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/base64.cc b/src/base64.cc
new file mode 100644
index 0000000..da72de1
--- /dev/null
+++ b/src/base64.cc
@@ -0,0 +1,69 @@
+#include "common.hh"
+
+#include "base64.hh"
+
+namespace stuff {
+
+namespace {
+
+int8_t value(char c) {
+ if (c >= 'A' && c <= 'Z') {
+ return c - 'A';
+ }
+ if (c >= 'a' && c <= 'z') {
+ return 26 + c - 'a';
+ }
+ if (c >= '0' && c <= '9') {
+ return 52 + c - '0';
+ }
+ if (c == '+' || c == '-') {
+ return 62;
+ }
+ if (c == '/' || c == '_') {
+ return 63;
+ }
+ return -1;
+}
+
+bool decode_one(const int8_t buf[4], std::string* output) {
+ if (buf[1] == -1 || buf[0] == -1) {
+ // There is no reason for the first or the second char to be
+ // padding
+ return false;
+ }
+ output->push_back((buf[0] << 2) | (buf[1] >> 4));
+ if (buf[2] == -1) {
+ return buf[3] == -1; // No padding between non-padding
+ }
+ output->push_back(((buf[1] & 0xf) << 4) | (buf[2] >> 2));
+ if (buf[3] == -1) return true;
+ output->push_back(((buf[2] & 0x3) << 6) | buf[3]);
+ return true;
+}
+
+} // namespace
+
+bool Base64::decode(const std::string& input, std::string* output) {
+ int8_t buf[4];
+ size_t fill = 0;
+ bool done = false;
+ output->clear();
+ for (auto it = input.begin(); it != input.end(); ++it) {
+ buf[fill] = value(*it);
+ if (buf[fill] != -1 || *it == '=') {
+ if (done) return false; // crap after padding
+ if (++fill == 4) {
+ if (!decode_one(buf, output)) return false;
+ done = buf[3] == -1;
+ fill = 0;
+ }
+ }
+ }
+ if (fill != 0) {
+ while (fill < 4) buf[fill] = -1;
+ if (!decode_one(buf, output)) return false;
+ }
+ return true;
+}
+
+} // namespace stuff