From 5b3d9978960e40dd90b28dae19dafeda4ccd681a Mon Sep 17 00:00:00 2001 From: Andrew Bettison Date: Tue, 20 Sep 2016 12:29:08 +0930 Subject: [PATCH] Move Base64 conversions from "str.h" to "base64.h" --- base64.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++ base64.h | 98 ++++++++++++++++++++++ headerfiles.mk | 1 + http_server.c | 1 + meshms_restful.c | 1 + rhizome_restful.c | 1 + sourcefiles.mk | 1 + str.c | 193 +----------------------------------------- str.h | 75 +---------------- 9 files changed, 315 insertions(+), 264 deletions(-) create mode 100644 base64.c create mode 100644 base64.h diff --git a/base64.c b/base64.c new file mode 100644 index 00000000..3e3f1ac9 --- /dev/null +++ b/base64.c @@ -0,0 +1,208 @@ +/* + Serval Base64 primitives + Copyright (C) 2012-2016 Serval Project Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "base64.h" +#include "str.h" // for Serval ctype +#include // for uint8_t +#include // for NULL +#include // for iovec +#include + +const char base64_symbols[65] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', + '=' +}; + +const char base64url_symbols[65] = { + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', + 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', + 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', + 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_', + '=' +}; + +static size_t _base64_encodev(const char symbols[], char *dstBase64, const struct iovec *const iov, int const iovcnt) +{ + char *dst = dstBase64; + unsigned place = 0; + unsigned char buf = 0; + int iovc = 0; + for (iovc = 0; iovc != iovcnt; ++iovc) { + unsigned char *src = iov[iovc].iov_base; + size_t cnt = iov[iovc].iov_len; + for (; cnt; --cnt, ++src) { + switch (place) { + case 0: + *dst++ = symbols[*src >> 2]; + buf = (*src << 4) & 0x3f; + place = 1; + break; + case 1: + *dst++ = symbols[(*src >> 4) | buf]; + buf = (*src << 2) & 0x3f; + place = 2; + break; + case 2: + *dst++ = symbols[(*src >> 6) | buf]; + *dst++ = symbols[*src & 0x3f]; + place = 0; + break; + } + } + } + if (place) + *dst++ = symbols[buf]; + switch (place) { + case 1: + *dst++ = symbols[64]; + case 2: + *dst++ = symbols[64]; + } + return dst - dstBase64; +} + +size_t base64_encodev(char *dstBase64, const struct iovec *const iov, int const iovcnt) +{ + return _base64_encodev(base64_symbols, dstBase64, iov, iovcnt); +} + +size_t base64url_encodev(char *dstBase64, const struct iovec *const iov, int const iovcnt) +{ + return _base64_encodev(base64url_symbols, dstBase64, iov, iovcnt); +} + +size_t base64_encode(char *const dstBase64, const unsigned char *src, size_t srclen) +{ + struct iovec iov; + iov.iov_base = (void *) src; + iov.iov_len = srclen; + return _base64_encodev(base64_symbols, dstBase64, &iov, 1); +} + +size_t base64url_encode(char *const dstBase64, const unsigned char *src, size_t srclen) +{ + struct iovec iov; + iov.iov_base = (void *) src; + iov.iov_len = srclen; + return _base64_encodev(base64url_symbols, dstBase64, &iov, 1); +} + +char *to_base64_str(char *const dstBase64, const unsigned char *srcBinary, size_t srcBytes) +{ + dstBase64[base64_encode(dstBase64, srcBinary, srcBytes)] = '\0'; + return dstBase64; +} + +char *to_base64url_str(char *const dstBase64, const unsigned char *srcBinary, size_t srcBytes) +{ + dstBase64[base64url_encode(dstBase64, srcBinary, srcBytes)] = '\0'; + return dstBase64; +} + +static size_t _base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, + const char **afterp, int flags, int (*skip_pred)(int), + int (*isdigit_pred)(int), int (*ispad_pred)(int), uint8_t (*todigit)(char) + ) +{ + uint8_t buf = 0; + size_t digits = 0; + unsigned pads = 0; + size_t bytes = 0; + const char *const srcend = srcBase64 + srclen; + const char *src = srcBase64; + const char *first_pad = NULL; + for (; srclen == 0 || (src < srcend); ++src) { + int isdigit = isdigit_pred(*src); + int ispad = ispad_pred(*src); + if (!isdigit && !ispad && skip_pred && skip_pred(*src)) + continue; + assert(pads <= 2); + if (pads == 2) + break; + int place = digits & 3; + if (pads == 1) { + if (place == 3) + break; + assert(place == 2); + if (ispad) { + ++pads; + continue; // consume trailing space before ending + } + // If only one pad character was present but there should be two, then don't consume the first + // one. + assert(first_pad != NULL); + src = first_pad; + break; + } + assert(pads == 0); + if (ispad && place >= 2) { + first_pad = src; + ++pads; + continue; + } + if (!isdigit) + break; + ++digits; + if (dstBinary && bytes < dstsiz) { + uint8_t d = todigit(*src); + switch (place) { + case 0: + buf = d << 2; + break; + case 1: + dstBinary[bytes++] = buf | (d >> 4); + buf = d << 4; + break; + case 2: + dstBinary[bytes++] = buf | (d >> 2); + buf = d << 6; + break; + case 3: + dstBinary[bytes++] = buf | d; + break; + } + } else if (flags & B64_CONSUME_ALL) { + switch (place) { + case 1: case 2: case 3: ++bytes; + } + } else + break; + } + if (afterp) + *afterp = src; + else if (*src) + return 0; + return bytes; +} + +size_t base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, + const char **afterp, int flags, int (*skip_pred)(int)) +{ + return _base64_decode(dstBinary, dstsiz, srcBase64, srclen, afterp, flags, skip_pred, is_base64_digit, is_base64_pad, base64_digit); +} + + +size_t base64url_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, + const char **afterp, int flags, int (*skip_pred)(int)) +{ + return _base64_decode(dstBinary, dstsiz, srcBase64, srclen, afterp, flags, skip_pred, is_base64url_digit, is_base64url_pad, base64url_digit); +} diff --git a/base64.h b/base64.h new file mode 100644 index 00000000..b294763e --- /dev/null +++ b/base64.h @@ -0,0 +1,98 @@ +/* + Serval Base64 primitives + Copyright (C) 2012-2016 Serval Project Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __SERVAL_DNA__BASE64_H__ +#define __SERVAL_DNA__BASE64_H__ + +#include // for size_t +#include + +/* Return the number of bytes required to represent 'binaryBytes' bytes of binary data encoded + * into Base64 form. + * + * @author Andrew Bettison + */ +#define BASE64_ENCODED_LEN(binaryBytes) (((size_t)(binaryBytes) + 2) / 3 * 4) + +/* Array of encoding symbols. Entry [64] is the pad character (usually '='). + */ +extern const char base64_symbols[65]; +extern const char base64url_symbols[65]; + +/* Encode 'srcBytes' bytes of binary data at 'srcBinary' into Base64 representation at 'dstBase64' + * (or Base64-URL representation at 'dstBase64url'), which must point to at least + * 'BASE64_ENCODED_LEN(srcBytes)' bytes. The encoding is terminated by a "=" or "==" pad to bring + * the total number of encoded bytes up to a multiple of 4. + * + * Returns the total number of encoded bytes writtent at 'dstBase64'. + * + * The base64_encodev() is a multi-buffer gather variant, analagous to readv(2) and writev(2). + * + * @author Andrew Bettison + */ +size_t base64_encode(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); +size_t base64url_encode(char *dstBase64url, const unsigned char *srcBinary, size_t srcBytes); +struct iovec; +size_t base64_encode(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); +size_t base64url_encodev(char *dstBase64url, const struct iovec *iov, int iovcnt); + +/* The same as base64_encode() but appends a terminating NUL character to the encoded string, + * so 'dstBase64' must point to at least 'BASE64_ENCODED_LEN(srcBytes) + 1' bytes. + * + * @author Andrew Bettison + */ +char *to_base64_str(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); +char *to_base64url_str(char *dstBase64url, const unsigned char *srcBinary, size_t srcBytes); + +#define alloca_base64(buf,len) to_base64_str(alloca(BASE64_ENCODED_LEN(len) + 1), (buf), (len)) +#define alloca_base64url(buf,len) to_base64url_str(alloca(BASE64_ENCODED_LEN(len) + 1), (buf), (len)) + +/* Decode the string at 'srcBase64' as ASCII Base64 or Base64-URL (as per RFC-4648), writing up to + * 'dstsiz' decoded binary bytes at 'dstBinary'. Returns the number of decoded binary bytes + * produced. If 'dstsiz' is zero or 'dstBinary' is NULL, no binary bytes are produced and returns + * zero. + * + * If the 'afterp' pointer is not NULL, then sets *afterp to point to the first character in + * 'srcBase64' where decoding stopped for whatever reason. + * + * If 'srclen' is 0, then the string at 'stcBase64' is assumed to be NUL-terminated, and decoding + * runs until the first non-Base64-digit is encountered. If 'srclen' is nonzero, then decoding will + * cease at the first non-Base64-digit or when 'srclen' bytes at 'srcBase64' have been decoded, + * whichever comes first. + * + * If 'skip_pred' is not NULL, then all leading, internal and trailing characters C which are not a + * valid Base64 digit or pad '=' will be skipped if skip_pred(C) returns true. Otherwise, decoding + * ends at C. + * + * If the B64_CONSUME_ALL flag is set, then once the 'dstsiz' limit is reached (or if 'dstBinary' is + * NULL), the Base64 decoding process continues without actually writing decoded bytes, but instead + * counts them and advances through the 'srcBase64' buffer as usual. The return value is then the + * number of binary bytes that would be decoded were all available Base64 decoded from 'srcBase64', + * and *afterp points to the first character beyond the end of the decoded source characters. + * + * @author Andrew Bettison + */ +size_t base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, + const char **afterp, int flags, int (*skip_pred)(int)); +size_t base64url_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64url, size_t srclen, + const char **afterp, int flags, int (*skip_pred)(int)); + +#define B64_CONSUME_ALL (1 << 0) + +#endif // __SERVAL_DNA__BASE64_H__ diff --git a/headerfiles.mk b/headerfiles.mk index 9be61be1..e39b2256 100644 --- a/headerfiles.mk +++ b/headerfiles.mk @@ -24,6 +24,7 @@ HDRS= fifo.h \ cli.h \ str.h \ numeric_str.h \ + base64.h \ rotbuf.h \ mem.h \ os.h \ diff --git a/http_server.c b/http_server.c index a0fcdcb2..8b80b3a6 100644 --- a/http_server.c +++ b/http_server.c @@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "log.h" #include "debug.h" #include "numeric_str.h" +#include "base64.h" #include "strbuf.h" #include "strbuf_helpers.h" #include "net.h" diff --git a/meshms_restful.c b/meshms_restful.c index 1ebf88a8..2146e466 100644 --- a/meshms_restful.c +++ b/meshms_restful.c @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "conf.h" #include "httpd.h" #include "numeric_str.h" +#include "base64.h" #include "strbuf_helpers.h" DECLARE_HANDLER("/restful/meshms/", restful_meshms_); diff --git a/rhizome_restful.c b/rhizome_restful.c index eb1855c1..1801b585 100644 --- a/rhizome_restful.c +++ b/rhizome_restful.c @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "serval.h" #include "conf.h" #include "httpd.h" +#include "base64.h" #include "strbuf_helpers.h" DECLARE_HANDLER("/restful/rhizome/bundlelist.json", restful_rhizome_bundlelist_json); diff --git a/sourcefiles.mk b/sourcefiles.mk index 3b8c82fb..4737a72f 100644 --- a/sourcefiles.mk +++ b/sourcefiles.mk @@ -24,6 +24,7 @@ SERVAL_CLIENT_SOURCES = \ strbuf_helpers.c \ str.c \ numeric_str.c \ + base64.c \ strlcpy.c \ uuid.c \ whence.c \ diff --git a/str.c b/str.c index 75dd21ef..4cdb82d3 100644 --- a/str.c +++ b/str.c @@ -20,17 +20,14 @@ #define __SERVAL_DNA__STR_INLINE #include "str.h" #include "strbuf_helpers.h" -#include "constants.h" #include -#include -#include -#include -#include +#include // for NULL +#include // for iovec +#include // for strlen(), strncmp() etc. #include #include #include -#include const char hexdigit_upper[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; const char hexdigit_lower[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; @@ -194,190 +191,6 @@ size_t www_form_uri_decode(char *const dst, ssize_t dstsiz, const char *srcUrien return _uri_decode(1, dst, dstsiz, srcUrienc, srclen, afterp); } -const char base64_symbols[65] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', - '=' -}; - -const char base64url_symbols[65] = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', - 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', - 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', - 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_', - '=' -}; - -static size_t _base64_encodev(const char symbols[], char *dstBase64, const struct iovec *const iov, int const iovcnt) -{ - char *dst = dstBase64; - unsigned place = 0; - unsigned char buf = 0; - int iovc = 0; - for (iovc = 0; iovc != iovcnt; ++iovc) { - unsigned char *src = iov[iovc].iov_base; - size_t cnt = iov[iovc].iov_len; - for (; cnt; --cnt, ++src) { - switch (place) { - case 0: - *dst++ = symbols[*src >> 2]; - buf = (*src << 4) & 0x3f; - place = 1; - break; - case 1: - *dst++ = symbols[(*src >> 4) | buf]; - buf = (*src << 2) & 0x3f; - place = 2; - break; - case 2: - *dst++ = symbols[(*src >> 6) | buf]; - *dst++ = symbols[*src & 0x3f]; - place = 0; - break; - } - } - } - if (place) - *dst++ = symbols[buf]; - switch (place) { - case 1: - *dst++ = symbols[64]; - case 2: - *dst++ = symbols[64]; - } - return dst - dstBase64; -} - -size_t base64_encodev(char *dstBase64, const struct iovec *const iov, int const iovcnt) -{ - return _base64_encodev(base64_symbols, dstBase64, iov, iovcnt); -} - -size_t base64url_encodev(char *dstBase64, const struct iovec *const iov, int const iovcnt) -{ - return _base64_encodev(base64url_symbols, dstBase64, iov, iovcnt); -} - -size_t base64_encode(char *const dstBase64, const unsigned char *src, size_t srclen) -{ - struct iovec iov; - iov.iov_base = (void *) src; - iov.iov_len = srclen; - return _base64_encodev(base64_symbols, dstBase64, &iov, 1); -} - -size_t base64url_encode(char *const dstBase64, const unsigned char *src, size_t srclen) -{ - struct iovec iov; - iov.iov_base = (void *) src; - iov.iov_len = srclen; - return _base64_encodev(base64url_symbols, dstBase64, &iov, 1); -} - -char *to_base64_str(char *const dstBase64, const unsigned char *srcBinary, size_t srcBytes) -{ - dstBase64[base64_encode(dstBase64, srcBinary, srcBytes)] = '\0'; - return dstBase64; -} - -char *to_base64url_str(char *const dstBase64, const unsigned char *srcBinary, size_t srcBytes) -{ - dstBase64[base64url_encode(dstBase64, srcBinary, srcBytes)] = '\0'; - return dstBase64; -} - -static size_t _base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, - const char **afterp, int flags, int (*skip_pred)(int), - int (*isdigit_pred)(int), int (*ispad_pred)(int), uint8_t (*todigit)(char) - ) -{ - uint8_t buf = 0; - size_t digits = 0; - unsigned pads = 0; - size_t bytes = 0; - const char *const srcend = srcBase64 + srclen; - const char *src = srcBase64; - const char *first_pad = NULL; - for (; srclen == 0 || (src < srcend); ++src) { - int isdigit = isdigit_pred(*src); - int ispad = ispad_pred(*src); - if (!isdigit && !ispad && skip_pred && skip_pred(*src)) - continue; - assert(pads <= 2); - if (pads == 2) - break; - int place = digits & 3; - if (pads == 1) { - if (place == 3) - break; - assert(place == 2); - if (ispad) { - ++pads; - continue; // consume trailing space before ending - } - // If only one pad character was present but there should be two, then don't consume the first - // one. - assert(first_pad != NULL); - src = first_pad; - break; - } - assert(pads == 0); - if (ispad && place >= 2) { - first_pad = src; - ++pads; - continue; - } - if (!isdigit) - break; - ++digits; - if (dstBinary && bytes < dstsiz) { - uint8_t d = todigit(*src); - switch (place) { - case 0: - buf = d << 2; - break; - case 1: - dstBinary[bytes++] = buf | (d >> 4); - buf = d << 4; - break; - case 2: - dstBinary[bytes++] = buf | (d >> 2); - buf = d << 6; - break; - case 3: - dstBinary[bytes++] = buf | d; - break; - } - } else if (flags & B64_CONSUME_ALL) { - switch (place) { - case 1: case 2: case 3: ++bytes; - } - } else - break; - } - if (afterp) - *afterp = src; - else if (*src) - return 0; - return bytes; -} - -size_t base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, - const char **afterp, int flags, int (*skip_pred)(int)) -{ - return _base64_decode(dstBinary, dstsiz, srcBase64, srclen, afterp, flags, skip_pred, is_base64_digit, is_base64_pad, base64_digit); -} - - -size_t base64url_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, - const char **afterp, int flags, int (*skip_pred)(int)) -{ - return _base64_decode(dstBinary, dstsiz, srcBase64, srclen, afterp, flags, skip_pred, is_base64url_digit, is_base64url_pad, base64url_digit); -} - - #define _B64 _SERVAL_CTYPE_0_BASE64 #define _B64U _SERVAL_CTYPE_0_BASE64URL diff --git a/str.h b/str.h index 11cb2bdc..3d7ffe8d 100644 --- a/str.h +++ b/str.h @@ -130,80 +130,6 @@ int fromhexstrn(unsigned char *dstBinary, size_t nbinary, const char *srcHex, si */ size_t strn_fromhex(unsigned char *dstBinary, ssize_t dstsiz, const char *src, const char **afterp); -/* -------------------- Base64 encoding and decoding -------------------- */ - -/* Return the number of bytes required to represent 'binaryBytes' bytes of binary data encoded - * into Base64 form. - * - * @author Andrew Bettison - */ -#define BASE64_ENCODED_LEN(binaryBytes) (((size_t)(binaryBytes) + 2) / 3 * 4) - -/* Array of encoding symbols. Entry [64] is the pad character (usually '='). - */ -extern const char base64_symbols[65]; -extern const char base64url_symbols[65]; - -/* Encode 'srcBytes' bytes of binary data at 'srcBinary' into Base64 representation at 'dstBase64' - * (or Base64-URL representation at 'dstBase64url'), which must point to at least - * 'BASE64_ENCODED_LEN(srcBytes)' bytes. The encoding is terminated by a "=" or "==" pad to bring - * the total number of encoded bytes up to a multiple of 4. - * - * Returns the total number of encoded bytes writtent at 'dstBase64'. - * - * The base64_encodev() is a multi-buffer gather variant, analagous to readv(2) and writev(2). - * - * @author Andrew Bettison - */ -size_t base64_encode(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); -size_t base64url_encode(char *dstBase64url, const unsigned char *srcBinary, size_t srcBytes); -struct iovec; -size_t base64_encode(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); -size_t base64url_encodev(char *dstBase64url, const struct iovec *iov, int iovcnt); - -/* The same as base64_encode() but appends a terminating NUL character to the encoded string, - * so 'dstBase64' must point to at least 'BASE64_ENCODED_LEN(srcBytes) + 1' bytes. - * - * @author Andrew Bettison - */ -char *to_base64_str(char *dstBase64, const unsigned char *srcBinary, size_t srcBytes); -char *to_base64url_str(char *dstBase64url, const unsigned char *srcBinary, size_t srcBytes); - -#define alloca_base64(buf,len) to_base64_str(alloca(BASE64_ENCODED_LEN(len) + 1), (buf), (len)) -#define alloca_base64url(buf,len) to_base64url_str(alloca(BASE64_ENCODED_LEN(len) + 1), (buf), (len)) - -/* Decode the string at 'srcBase64' as ASCII Base64 or Base64-URL (as per RFC-4648), writing up to - * 'dstsiz' decoded binary bytes at 'dstBinary'. Returns the number of decoded binary bytes - * produced. If 'dstsiz' is zero or 'dstBinary' is NULL, no binary bytes are produced and returns - * zero. - * - * If the 'afterp' pointer is not NULL, then sets *afterp to point to the first character in - * 'srcBase64' where decoding stopped for whatever reason. - * - * If 'srclen' is 0, then the string at 'stcBase64' is assumed to be NUL-terminated, and decoding - * runs until the first non-Base64-digit is encountered. If 'srclen' is nonzero, then decoding will - * cease at the first non-Base64-digit or when 'srclen' bytes at 'srcBase64' have been decoded, - * whichever comes first. - * - * If 'skip_pred' is not NULL, then all leading, internal and trailing characters C which are not a - * valid Base64 digit or pad '=' will be skipped if skip_pred(C) returns true. Otherwise, decoding - * ends at C. - * - * If the B64_CONSUME_ALL flag is set, then once the 'dstsiz' limit is reached (or if 'dstBinary' is - * NULL), the Base64 decoding process continues without actually writing decoded bytes, but instead - * counts them and advances through the 'srcBase64' buffer as usual. The return value is then the - * number of binary bytes that would be decoded were all available Base64 decoded from 'srcBase64', - * and *afterp points to the first character beyond the end of the decoded source characters. - * - * @author Andrew Bettison - */ -size_t base64_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64, size_t srclen, - const char **afterp, int flags, int (*skip_pred)(int)); -size_t base64url_decode(unsigned char *dstBinary, size_t dstsiz, const char *const srcBase64url, size_t srclen, - const char **afterp, int flags, int (*skip_pred)(int)); - -#define B64_CONSUME_ALL (1 << 0) - /* -------------------- Character classes -------------------- */ #define _SERVAL_CTYPE_0_BASE64_MASK 0x3f @@ -437,6 +363,7 @@ char *str_str(char *haystack, const char *needle, size_t haystack_len); size_t uri_encode(char *const dstUrienc, ssize_t dstsiz, const char *src, size_t srclen, const char **afterp); size_t www_form_uri_encode(char *const dstUrienc, ssize_t dstsiz, const char *src, size_t srclen, const char **afterp); +struct iovec; size_t uri_encodev(char *const dstUrienc, ssize_t dstsiz, struct iovec **iovp, int *iovcntp); // modifies *iovp, (*iovp)[...] and *iovcntp size_t www_form_uri_encodev(char *const dstUrienc, ssize_t dstsiz, struct iovec **iovp, int *iovcntp); // modifies *iovp, (*iovp)[...] and *iovcntp