From c314a37dac239fc07ea2a0cf8224710f441b6af8 Mon Sep 17 00:00:00 2001 From: Paul Kulchenko Date: Sun, 8 Oct 2023 23:18:11 -0700 Subject: [PATCH] Reorganize redbean EncodeBase32 code --- net/http/base32.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ net/http/escape.h | 1 + tool/net/lfuncs.c | 58 +++++----------------------------------- 3 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 net/http/base32.c diff --git a/net/http/base32.c b/net/http/base32.c new file mode 100644 index 000000000000..f6f6466974a5 --- /dev/null +++ b/net/http/base32.c @@ -0,0 +1,67 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/macros.internal.h" +#include "libc/mem/mem.h" +#include "libc/str/str.h" + +asm(".ident\t\"\\n\\n\ +Apache License, Version 2.0\\n\ +Copyright 2010 Google Inc.\""); +asm(".include \"libc/disclaimer.inc\""); + +int tobits(int b) { + int bits = 0; while (b && (b >>= 1)) bits++; + return bits; +} + +// the next function is based on +// https://github.com/google/google-authenticator-libpam/blob/master/src/base32.c +// Copyright 2010 Google Inc.; Author: Markus Gutschke +// licensed under Apache License, Version 2.0 +char* EncodeBase32(const char *s, size_t sl, + const char *a, size_t al, + size_t *ol) { + size_t count = 0; + int bl = tobits(al); + int mask = (1 << bl) - 1; + ol = (sl * 8 + bl - 1) / bl; // calculate exact output length + if (!(r = malloc(ol + 1))) return (ol = 0); + if (sl > 0) { + int buffer = s[0]; + size_t next = 1; + int bitsLeft = 8; + while (count < ol && (bitsLeft > 0 || next < sl)) { + if (bitsLeft < bl) { + if (next < sl) { + buffer <<= 8; + buffer |= s[next++] & 0xFF; + bitsLeft += 8; + } else { + int pad = bl - bitsLeft; + buffer <<= pad; + bitsLeft += pad; + } + } + bitsLeft -= bl; + r[count++] = a[mask & (buffer >> bitsLeft)]; + } + } + if (count < ol) r[count] = '\000'; + return r; +} diff --git a/net/http/escape.h b/net/http/escape.h index b770370828ae..4b7558b432ee 100644 --- a/net/http/escape.h +++ b/net/http/escape.h @@ -34,6 +34,7 @@ char *EncodeLatin1(const char *, size_t, size_t *, int); char *EncodeHttpHeaderValue(const char *, size_t, size_t *); char *VisualizeControlCodes(const char *, size_t, size_t *); char *IndentLines(const char *, size_t, size_t *, size_t); +char *EncodeBase32(const char *, size_t, const char, size_t, size_t *); char *EncodeBase64(const char *, size_t, size_t *); char *DecodeBase64(const char *, size_t, size_t *); diff --git a/tool/net/lfuncs.c b/tool/net/lfuncs.c index 0a334461b9e1..783bd652294f 100644 --- a/tool/net/lfuncs.c +++ b/tool/net/lfuncs.c @@ -605,61 +605,17 @@ int LuaEncodeLatin1(lua_State *L) { } } -int tobits(int b) { - int bits = 0; while (b && (b >>= 1)) bits++; - return bits; -} - -// the next function is based on -// https://github.com/google/google-authenticator-libpam/blob/master/src/base32.c -// Copyright 2010 Google Inc.; Author: Markus Gutschke -// licensed under Apache License, Version 2.0 -// p already has ol bytes allocated -// which is enough to store encoded result -char* base32pcpy(char *p, const char *s, size_t sl, - const char *a, size_t al, - size_t ol) { - size_t count = 0; - int bl = tobits(al); - int mask = (1 << bl) - 1; - if (sl > 0) { - int buffer = s[0]; - size_t next = 1; - int bitsLeft = 8; - while (count < ol && (bitsLeft > 0 || next < sl)) { - if (bitsLeft < bl) { - if (next < sl) { - buffer <<= 8; - buffer |= s[next++] & 0xFF; - bitsLeft += 8; - } else { - int pad = bl - bitsLeft; - buffer <<= pad; - bitsLeft += pad; - } - } - bitsLeft -= bl; - p[count++] = a[mask & (buffer >> bitsLeft)]; - } - } - if (count < ol) p[count] = '\000'; - return p; -} - int LuaEncodeBase32(lua_State *L) { char *p; - size_t sl, al, ol; // source, alphabet, and output lengths - const char *s, *a; - luaL_Buffer buf; - s = luaL_checklstring(L, 1, &sl); - a = luaL_optlstring(L, 2, "0123456789abcdefghjkmnpqrstvwxyz", &al); + size_t sl, al; // source/output and alphabet lengths + const char *s = luaL_checklstring(L, 1, &sl); + const char *a = luaL_optlstring(L, 2, "0123456789abcdefghjkmnpqrstvwxyz", &al); if (al & (al - 1) || al > 256 || al < 2) return luaL_error(L, "alphabet length is not a power of 2 in range 2..256"); - ol = tobits(al); - ol = (sl * 8 + ol - 1) / ol; // calculate exact output length - p = luaL_buffinitsize(L, &buf, ol); - base32pcpy(p, s, sl, a, al, ol); - luaL_pushresultsize(&buf, ol); + if (!(p = EncodeBase32(s, sl, a, al, &sl))) + return luaL_error(L, "out of memory"); + lua_pushlstring(L, p, sl); + free(p); return 1; }