Mercurial > prosody-modules
diff mod_s2s_v6mesh/base32.lib.lua @ 6472:9f43226c7de1
mod_s2s_v6mesh: DNS-less federation for IPv6 networks
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Tue, 17 Mar 2026 16:37:04 +0000 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_s2s_v6mesh/base32.lib.lua Tue Mar 17 16:37:04 2026 +0000 @@ -0,0 +1,138 @@ +--[[ + borrowed from basexx library for Lua, under MIT License (MIT) + Copyright (c) 2013 aiq +The MIT License (MIT) + +Copyright (c) 2013 aiq + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +----------------------------------------------------------------------------]] + +local function ignore_set( str, set ) + if set then + str = str:gsub( "["..set.."]", "" ) + end + return str +end + +local function divide_string( str, max ) + local result = {} + + local start = 1 + for i = 1, #str do + if i % max == 0 then + table.insert( result, str:sub( start, i ) ) + start = i + 1 + elseif i == #str then + table.insert( result, str:sub( start, i ) ) + end + end + + return result +end + +function to_bit( str ) + return ( str:gsub( '.', function ( c ) + local byte = string.byte( c ) + local bits = {} + for _ = 1,8 do + table.insert( bits, byte % 2 ) + byte = math.floor( byte / 2 ) + end + return table.concat( bits ):reverse() + end ) ) +end + +local function number_to_bit( num, length ) + local bits = {} + + while num > 0 do + local rest = math.floor( math.fmod( num, 2 ) ) + table.insert( bits, rest ) + num = ( num - rest ) / 2 + end + + while #bits < length do + table.insert( bits, "0" ) + end + + return string.reverse( table.concat( bits ) ) +end + +local function pure_from_bit( str ) + return ( str:gsub( '........', function ( cc ) + return string.char( tonumber( cc, 2 ) ) + end ) ) +end + +local function unexpected_char_error( str, pos ) + local c = string.sub( str, pos, pos ) + return string.format( "unexpected character at position %d: '%s'", pos, c ) +end + +local function from_basexx( str, alphabet, bits ) + local result = {} + for i = 1, #str do + local c = string.sub( str, i, i ) + if c ~= '=' then + local index = string.find( alphabet, c, 1, true ) + if not index then + return nil, unexpected_char_error( str, i ) + end + table.insert( result, number_to_bit( index - 1, bits ) ) + end + end + + local value = table.concat( result ) + local pad = #value % 8 + return pure_from_bit( string.sub( value, 1, #value - pad ) ) +end + +local function to_basexx( str, alphabet, bits, pad ) + local bitString = to_bit( str ) + + local chunks = divide_string( bitString, bits ) + local result = {} + for _,value in ipairs( chunks ) do + if ( #value < bits ) then + value = value .. string.rep( '0', bits - #value ) + end + local pos = tonumber( value, 2 ) + 1 + table.insert( result, alphabet:sub( pos, pos ) ) + end + + table.insert( result, pad ) + return table.concat( result ) +end + +local base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567" +local base32PadMap = { "", "======", "====", "===", "=" } + +local function from_base32( str, ignore ) + str = ignore_set( str, ignore ) + return from_basexx( string.lower( str ), base32Alphabet, 5 ) +end + +function to_base32( str ) + return to_basexx( str, base32Alphabet, 5, base32PadMap[ #str % 5 + 1 ] ) +end + +return { + decode = from_base32; + encode = to_base32; +};
