Skip to content

Commit

Permalink
Add EncodeBase32 to Redbean
Browse files Browse the repository at this point in the history
  • Loading branch information
pkulchenko committed Oct 11, 2023
1 parent af7cb3c commit 9abacaa
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 0 deletions.
79 changes: 79 additions & 0 deletions net/http/base32.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*-*- 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/assert.h"
#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\"");

const char base32def[] = "0123456789abcdefghjkmnpqrstvwxyz";

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;
char *r;
if (al == 0) {
a = base32def;
al = sizeof(base32def)/sizeof(a[0]);
}
unassert(2 <= al && al <= 128);
int bl = tobits(al);
int mask = (1 << bl) - 1;
*ol = (sl * 8 + bl - 1) / bl; // calculate exact output length
if (!(r = malloc(*ol + 1))) {
*ol = 0;
return r;
}
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;
}
1 change: 1 addition & 0 deletions net/http/escape.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
5 changes: 5 additions & 0 deletions test/tool/net/lfuncs_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ assert(bin(0x1940efe9d47ae889) == "0b0001100101000000111011111110100111010100011
assert(EncodeHex("\1\2\3\4\255") == "01020304ff")
assert(DecodeHex("01020304ff") == "\1\2\3\4\255")

assert(EncodeBase32("123456") == "64s36d1n6r")
assert(EncodeBase32("12") == "64s0")
assert(EncodeBase32("\33", "01") == "00100001")
assert(EncodeBase32("\33", "0123456789abcdef") == "21")

assert(EscapeHtml(nil) == nil)
assert(EscapeHtml("?hello&there<>") == "?hello&amp;there&lt;&gt;")

Expand Down
4 changes: 4 additions & 0 deletions tool/net/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,10 @@ FUNCTIONS
Turns ASCII base-16 hexadecimal byte string into binary string,
case-insensitively. Non-hex characters may not appear in string.

EncodeBase32(binary:str[, alphabet:str]) → ascii:str
Turns binary into ASCII using provided alphabet (using Crockford's
base32 encoding by default).

DecodeBase64(ascii:str) → binary:str
Turns ASCII into binary, in a permissive way that ignores
characters outside the base64 alphabet, such as whitespace. See
Expand Down
15 changes: 15 additions & 0 deletions tool/net/lfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,21 @@ int LuaEncodeLatin1(lua_State *L) {
}
}

int LuaEncodeBase32(lua_State *L) {
char *p;
size_t sl, al; // source/output and alphabet lengths
const char *s = luaL_checklstring(L, 1, &sl);
// use an empty string, as EncodeBase32 provides a default value
const char *a = luaL_optlstring(L, 2, "", &al);
if (al & (al - 1) || al > 128 || al == 1)
return luaL_error(L, "alphabet length is not a power of 2 in range 2..128");
if (!(p = EncodeBase32(s, sl, a, al, &sl)))
return luaL_error(L, "out of memory");
lua_pushlstring(L, p, sl);
free(p);
return 1;
}

int LuaEncodeHex(lua_State *L) {
char *p;
size_t n;
Expand Down
1 change: 1 addition & 0 deletions tool/net/lfuncs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int LuaDecodeBase64(lua_State *);
int LuaDecodeHex(lua_State *);
int LuaDecodeLatin1(lua_State *);
int LuaDeflate(lua_State *);
int LuaEncodeBase32(lua_State *);
int LuaEncodeBase64(lua_State *);
int LuaEncodeHex(lua_State *);
int LuaEncodeLatin1(lua_State *);
Expand Down
1 change: 1 addition & 0 deletions tool/net/redbean.c
Original file line number Diff line number Diff line change
Expand Up @@ -5132,6 +5132,7 @@ static const luaL_Reg kLuaFuncs[] = {
{"DecodeJson", LuaDecodeJson}, //
{"DecodeLatin1", LuaDecodeLatin1}, //
{"Deflate", LuaDeflate}, //
{"EncodeBase32", LuaEncodeBase32}, //
{"EncodeBase64", LuaEncodeBase64}, //
{"EncodeHex", LuaEncodeHex}, //
{"EncodeJson", LuaEncodeJson}, //
Expand Down

0 comments on commit 9abacaa

Please sign in to comment.