Files
opus-apps/builder/apis/base64.lua

155 lines
3.1 KiB
Lua

-- Base64 Encoder / Decoder
-- By KillaVanilla
-- see: http://www.computercraft.info/forums2/index.php?/topic/12450-killavanillas-various-apis/
local Base64 = { }
local bit = _G.bit
local _brshift = bit.brshift
local _bor = bit.bor
local _blshift = bit.blshift
local _band = bit.band
local _sub = string.sub
local os = _G.os
local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
local function sixBitToBase64(input)
return _sub(alphabet, input+1, input+1)
end
local function base64ToSixBit(input)
for i=1, 64 do
if input == _sub(alphabet, i, i) then
return i-1
end
end
end
local function octetToBase64(o1, o2, o3)
local i1 = sixBitToBase64(_brshift(_band(o1, 0xFC), 2))
local i2
local i3 = "="
local i4 = "="
if o2 then
i2 = sixBitToBase64(_bor( _blshift(_band(o1, 3), 4), _brshift(_band(o2, 0xF0), 4) ))
if not o3 then
i3 = sixBitToBase64(_blshift(_band(o2, 0x0F), 2))
else
i3 = sixBitToBase64(_bor( _blshift(_band(o2, 0x0F), 2), _brshift(_band(o3, 0xC0), 6) ))
end
else
i2 = sixBitToBase64(_blshift(_band(o1, 3), 4))
end
if o3 then
i4 = sixBitToBase64(_band(o3, 0x3F))
end
return i1..i2..i3..i4
end
-- octet 1 needs characters 1/2
-- octet 2 needs characters 2/3
-- octet 3 needs characters 3/4
local function base64ToThreeOctet(s1)
local c1 = base64ToSixBit(_sub(s1, 1, 1))
local c2 = base64ToSixBit(_sub(s1, 2, 2))
local c3
local c4
local o1
local o2
local o3
if _sub(s1, 3, 3) == "=" then
c3 = nil
c4 = nil
elseif _sub(s1, 4, 4) == "=" then
c3 = base64ToSixBit(_sub(s1, 3, 3))
c4 = nil
else
c3 = base64ToSixBit(_sub(s1, 3, 3))
c4 = base64ToSixBit(_sub(s1, 4, 4))
end
o1 = _bor( _blshift(c1, 2), _brshift(_band( c2, 0x30 ), 4) )
if c3 then
o2 = _bor( _blshift(_band(c2, 0x0F), 4), _brshift(_band( c3, 0x3C ), 2) )
else
o2 = nil
end
if c4 then
o3 = _bor( _blshift(_band(c3, 3), 6), c4 )
else
o3 = nil
end
return o1, o2, o3
end
local function splitIntoBlocks(bytes)
local blockNum = 1
local blocks = {}
for i=1, #bytes, 3 do
blocks[blockNum] = {bytes[i], bytes[i+1], bytes[i+2]}
--[[
if #blocks[blockNum] < 3 then
for j=#blocks[blockNum]+1, 3 do
table.insert(blocks[blockNum], 0)
end
end
]]
blockNum = blockNum+1
end
return blocks
end
function Base64.encode(bytes)
local blocks = splitIntoBlocks(bytes)
local output = ""
for i=1, #blocks do
output = output..octetToBase64( unpack(blocks[i]) )
end
return output
end
local function Throttle()
local ts = os.clock()
local timeout = .095
return function()
local nts = os.clock()
if nts > ts + timeout then
os.sleep(0)
ts = os.clock()
end
end
end
function Base64.decode(str)
local bytes = {}
local blocks = {}
local blockNum = 1
local throttle = Throttle()
for i=1, #str, 4 do
blocks[blockNum] = _sub(str, i, i+3)
blockNum = blockNum+1
end
for i=1, #blocks do
local o1, o2, o3 = base64ToThreeOctet(blocks[i])
table.insert(bytes, o1)
table.insert(bytes, o2)
table.insert(bytes, o3)
throttle()
end
-- Remove padding:
--[[
for i=#bytes, 1, -1 do
if bytes[i] ~= 0 then
break
else
bytes[i] = nil
end
end
]]
return bytes
end
return Base64