Mercurial > prosody-modules
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 6471:be2f75957552 | 6472:9f43226c7de1 |
|---|---|
| 1 --[[ | |
| 2 borrowed from basexx library for Lua, under MIT License (MIT) | |
| 3 Copyright (c) 2013 aiq | |
| 4 The MIT License (MIT) | |
| 5 | |
| 6 Copyright (c) 2013 aiq | |
| 7 | |
| 8 Permission is hereby granted, free of charge, to any person obtaining a copy of | |
| 9 this software and associated documentation files (the "Software"), to deal in | |
| 10 the Software without restriction, including without limitation the rights to | |
| 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
| 12 the Software, and to permit persons to whom the Software is furnished to do so, | |
| 13 subject to the following conditions: | |
| 14 | |
| 15 The above copyright notice and this permission notice shall be included in all | |
| 16 copies or substantial portions of the Software. | |
| 17 | |
| 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | |
| 20 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |
| 21 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | |
| 22 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| 23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| 24 ----------------------------------------------------------------------------]] | |
| 25 | |
| 26 local function ignore_set( str, set ) | |
| 27 if set then | |
| 28 str = str:gsub( "["..set.."]", "" ) | |
| 29 end | |
| 30 return str | |
| 31 end | |
| 32 | |
| 33 local function divide_string( str, max ) | |
| 34 local result = {} | |
| 35 | |
| 36 local start = 1 | |
| 37 for i = 1, #str do | |
| 38 if i % max == 0 then | |
| 39 table.insert( result, str:sub( start, i ) ) | |
| 40 start = i + 1 | |
| 41 elseif i == #str then | |
| 42 table.insert( result, str:sub( start, i ) ) | |
| 43 end | |
| 44 end | |
| 45 | |
| 46 return result | |
| 47 end | |
| 48 | |
| 49 function to_bit( str ) | |
| 50 return ( str:gsub( '.', function ( c ) | |
| 51 local byte = string.byte( c ) | |
| 52 local bits = {} | |
| 53 for _ = 1,8 do | |
| 54 table.insert( bits, byte % 2 ) | |
| 55 byte = math.floor( byte / 2 ) | |
| 56 end | |
| 57 return table.concat( bits ):reverse() | |
| 58 end ) ) | |
| 59 end | |
| 60 | |
| 61 local function number_to_bit( num, length ) | |
| 62 local bits = {} | |
| 63 | |
| 64 while num > 0 do | |
| 65 local rest = math.floor( math.fmod( num, 2 ) ) | |
| 66 table.insert( bits, rest ) | |
| 67 num = ( num - rest ) / 2 | |
| 68 end | |
| 69 | |
| 70 while #bits < length do | |
| 71 table.insert( bits, "0" ) | |
| 72 end | |
| 73 | |
| 74 return string.reverse( table.concat( bits ) ) | |
| 75 end | |
| 76 | |
| 77 local function pure_from_bit( str ) | |
| 78 return ( str:gsub( '........', function ( cc ) | |
| 79 return string.char( tonumber( cc, 2 ) ) | |
| 80 end ) ) | |
| 81 end | |
| 82 | |
| 83 local function unexpected_char_error( str, pos ) | |
| 84 local c = string.sub( str, pos, pos ) | |
| 85 return string.format( "unexpected character at position %d: '%s'", pos, c ) | |
| 86 end | |
| 87 | |
| 88 local function from_basexx( str, alphabet, bits ) | |
| 89 local result = {} | |
| 90 for i = 1, #str do | |
| 91 local c = string.sub( str, i, i ) | |
| 92 if c ~= '=' then | |
| 93 local index = string.find( alphabet, c, 1, true ) | |
| 94 if not index then | |
| 95 return nil, unexpected_char_error( str, i ) | |
| 96 end | |
| 97 table.insert( result, number_to_bit( index - 1, bits ) ) | |
| 98 end | |
| 99 end | |
| 100 | |
| 101 local value = table.concat( result ) | |
| 102 local pad = #value % 8 | |
| 103 return pure_from_bit( string.sub( value, 1, #value - pad ) ) | |
| 104 end | |
| 105 | |
| 106 local function to_basexx( str, alphabet, bits, pad ) | |
| 107 local bitString = to_bit( str ) | |
| 108 | |
| 109 local chunks = divide_string( bitString, bits ) | |
| 110 local result = {} | |
| 111 for _,value in ipairs( chunks ) do | |
| 112 if ( #value < bits ) then | |
| 113 value = value .. string.rep( '0', bits - #value ) | |
| 114 end | |
| 115 local pos = tonumber( value, 2 ) + 1 | |
| 116 table.insert( result, alphabet:sub( pos, pos ) ) | |
| 117 end | |
| 118 | |
| 119 table.insert( result, pad ) | |
| 120 return table.concat( result ) | |
| 121 end | |
| 122 | |
| 123 local base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567" | |
| 124 local base32PadMap = { "", "======", "====", "===", "=" } | |
| 125 | |
| 126 local function from_base32( str, ignore ) | |
| 127 str = ignore_set( str, ignore ) | |
| 128 return from_basexx( string.lower( str ), base32Alphabet, 5 ) | |
| 129 end | |
| 130 | |
| 131 function to_base32( str ) | |
| 132 return to_basexx( str, base32Alphabet, 5, base32PadMap[ #str % 5 + 1 ] ) | |
| 133 end | |
| 134 | |
| 135 return { | |
| 136 decode = from_base32; | |
| 137 encode = to_base32; | |
| 138 }; |
