diff options
| author | Joel Klinghed <the_jk@yahoo.com> | 2015-06-25 02:14:18 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@yahoo.com> | 2015-06-25 02:14:18 +0200 |
| commit | 85adf26a787b33d69d07df0dc786516fed800e21 (patch) | |
| tree | 12de4b0cae3999f3da7bbf3d21c631eecf6bf4a3 /src/base64.cc | |
| parent | 0c55606145b6c5d9a303b19b3dba4996ec3ed3a9 (diff) | |
Add basic auth support
Diffstat (limited to 'src/base64.cc')
| -rw-r--r-- | src/base64.cc | 69 |
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 |
