diff options
author | Simon Tatham <anakin@pobox.com> | 2022-05-01 13:19:10 +0300 |
---|---|---|
committer | Simon Tatham <anakin@pobox.com> | 2022-05-01 13:27:37 +0300 |
commit | d06ae2f5c345741192a0e3f9086765382690e37b (patch) | |
tree | 23d359ead0c832f3328c7b67de5566db62980def /utils | |
parent | 2a44b6354f5a251afe3dd3a1b835cea4517ee629 (diff) |
New utility function base64_valid().
For when you want to tell the difference between a base64-encoded
string and some other kind of string that might replace it.
Diffstat (limited to 'utils')
-rw-r--r-- | utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | utils/base64_valid.c | 54 |
2 files changed, 55 insertions, 0 deletions
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 949166f5..9d079ecb 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -5,6 +5,7 @@ add_sources_from_current_dir(utils base64_decode.c base64_encode_atom.c base64_encode.c + base64_valid.c bufchain.c buildinfo.c burnstr.c diff --git a/utils/base64_valid.c b/utils/base64_valid.c new file mode 100644 index 00000000..8eb1f3a0 --- /dev/null +++ b/utils/base64_valid.c @@ -0,0 +1,54 @@ +/* + * Determine whether a string looks like valid base64-encoded data. + */ + +#include "misc.h" + +static inline bool valid_char_main(char c) +{ + return ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '+' || c == '/'); +} + +bool base64_valid(ptrlen data) +{ + size_t blocklen = 0, nequals = 0; + + for (size_t i = 0; i < data.len; i++) { + char c = ((const char *)data.ptr)[i]; + + if (c == '\n' || c == '\r') + continue; + + if (valid_char_main(c)) { + if (nequals) /* can't go back to data after = */ + return false; + blocklen++; + if (blocklen == 4) + blocklen = 0; + continue; + } + + if (c == '=') { + if (blocklen == 0 && nequals) /* started a fresh block */ + return false; + + nequals++; + blocklen++; + if (blocklen == 4) { + if (nequals > 2) + return false; /* nonsensical final block */ + blocklen = 0; + } + continue; + } + + return false; /* bad character */ + } + + if (blocklen == 0 || blocklen == 2 || blocklen == 3) + return true; /* permit eliding the trailing = */ + return false; +} |