function frombase64url( url64str [, ignore] ) --> str, err


Decodes a base 64 encoded string with URL and filename safe alphabet to a data string. It is possible to ignore characters like \n in url64str via the optional ignore string.



The base 64 encoded string with URL and filename safe alphabet that should be decoded.


String that represents a optional set of characters that should be ignored in url64str.

Return Values


The decoded data string or nil if an error occurs.


A message that explains the error, otherwise nil.


local function frombase64url( url64str, ignore ) --> str, err
   local bitMap = {
      A="000000", B="000001", C="000010", D="000011", E="000100", F="000101",
      G="000110", H="000111", I="001000", J="001001", K="001010", L="001011",
      M="001100", N="001101", O="001110", P="001111", Q="010000", R="010001",
      S="010010", T="010011", U="010100", V="010101", W="010110", X="010111",
      Y="011000", Z="011001",
      a="011010", b="011011", c="011100", d="011101", e="011110", f="011111",
      g="100000", h="100001", i="100010", j="100011", k="100100", l="100101",
      m="100110", n="100111", o="101000", p="101001", q="101010", r="101011",
      s="101100", t="101101", u="101110", v="101111", w="110000", x="110001",
      y="110010", z="110011",
      ["0"]="110100", ["1"]="110101", ["2"]="110110", ["3"]="110111",
      ["4"]="111000", ["5"]="111001", ["6"]="111010", ["7"]="111011",
      ["8"]="111100", ["9"]="111101", ["-"]="111110", ["_"]="111111"
   local errchar = "unexpected character at position %d: '%s'"

   if ignore then url64str = url64str:gsub( "["..ignore.."]", "" ) end
   local bitTab = {}
   for i = 1, #url64str do
      local c = string.sub( url64str, i, i )
      if c ~= '=' then
         local bitStr = bitMap[ c ]
         if not bitStr then
            return nil, string.format( errchar, i, c )
         table.insert( bitTab, bitStr )

   local fullBitStr = table.concat( bitTab )
   local len = #fullBitStr
   local pad = len % 8
   fullBitStr = string.sub( fullBitStr, 1, len - pad )
   return fullBitStr:gsub( '........', function ( cc )
      return string.char( tonumber( cc, 2 ) )
   end )

return frombase64url


local t = require( "taptest" )
local frombase64url = require( "frombase64url" )

t( frombase64url( "TWFu"), "Man" )
t( frombase64url( "bGVhc3VyZS4" ), "leasure." )
t( frombase64url( "cGxlYXN1cmUu" ), "pleasure." )
t( frombase64url( "ZWFzdXJlLg" ), "easure." )
t( frombase64url( "c3VyZS4" ), "sure." )

local longtxt = "Man is distinguished, not only by his reason, but by "..
                "this singular passion from other animals, which is a "..
                "lust of the mind, that by a perseverance of delight in "..
                "the continued and indefatigable generation of knowledge, "..
                "exceeds the short vehemence of any carnal pleasure."
local long64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb2"..
t( frombase64url( long64 ), longtxt )

local msgtxt = '{"msg_en":"Hello","msg_jp":"こんにちは","msg_cn":"你好"'..
               ',"msg_de":"Grüß Gott"}'
local msg64 = 'eyJtc2dfZW4iOiJIZWxsbyIsIm1zZ19qcCI6IuOBk-OCk-OBq-OBoeOBryI'..
t( frombase64url( msg64 ), msgtxt )

--ignore characters
t( frombase64url( "TW-Fu\n", "-\n" ), "Man" )


Inspired by