quarta-feira, 29 de outubro de 2008

Base64 em Lua

--implementacao de Base64 em linguagem Lua.

local bin = { }

function bin.imod(a, b)
return a - math.floor(a / b) * b
end

function bin.rshift(a, b)
if (a < 0) then
a = 4294967296 + a
end
if (b < 0) then
b = 4294967296 + b
end

a = bin.imod(a, 4294967296)
b = bin.imod(b, 4294967296)

return math.floor(a / (2 ^ b))
end

function bin.lshift(a, b)
if (a < 0) then
a = 4294967296 + a
end
if (b < 0) then
b = 4294967296 + b
end

a = bin.imod(a, 4294967296)
b = bin.imod(b, 4294967296)

return math.floor(a * (2 ^ b))
end

function bin.band(a, b)
local i, v, r, b1, b2

if (a < 0) then
a = 4294967296 + a
end
if (b < 0) then
b = 4294967296 + b
end

a = bin.imod(a, 4294967296)
b = bin.imod(b, 4294967296)

r = 0
for i = 31, 0, -1 do
v = 2 ^ i
b1 = a >= v
b2 = b >= v

if (b1) and (b2) then
r = r + v
end

if (b1) then
a = a - v
end
if (b2) then
b = b - v
end
end

return r
end

function bin.bor(a, b)
local i, v, r, b1, b2

if (a < 0) then
a = 4294967296 + a
end
if (b < 0) then
b = 4294967296 + b
end

a = bin.imod(a, 4294967296)
b = bin.imod(b, 4294967296)

r = 0
for i = 31, 0, -1 do
v = 2 ^ i
b1 = a >= v
b2 = b >= v

if (b1) or (b2) then
r = r + v
end

if (b1) then
a = a - v
end
if (b2) then
b = b - v
end
end

return r
end

function bin.bxor(a, b)
local i, v, r, b1, b2

if (a < 0) then
a = 4294967296 + a
end
if (b < 0) then
b = 4294967296 + b
end

a = bin.imod(a, 4294967296)
b = bin.imod(b, 4294967296)

r = 0
for i = 31, 0, -1 do
v = 2 ^ i
b1 = a >= v
b2 = b >= v

if (b1 ~= b2) then
r = r + v
end

if (b1) then
a = a - v
end
if (b2) then
b = b - v
end
end

return r
end

function bin.bnot(a)
local i, v, r, b

if (a < 0) then
a = 4294967296 + a
end

a = bin.imod(a, 4294967296)

r = 0
for i = 31, 0, -1 do
v = 2 ^ i
b = a >= v

if (b) then
a = a - v
else
r = r + v
end
end

return r
end

local cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

b64 = {}

local function istr(p)
return string.sub(cb64, p + 1, p + 1)
end

function b64.encodeblock(in_tab, len)
local s1, s2, s3, s4

in_tab[0] = in_tab[1] or 0
in_tab[1] = in_tab[2] or 0
in_tab[2] = in_tab[3] or 0

s1 = istr(bin.rshift(in_tab[0], 2))
s2 = istr(bin.bor(bin.lshift(bin.band(in_tab[0], 3), 4), bin.rshift(bin.band(in_tab[1], 240), 4)))
s3 = (len > 1 and istr(bin.bor(bin.lshift(bin.band(in_tab[1], 15), 2), bin.rshift(bin.band(in_tab[2], 192), 6))) or "=")
s4 = (len > 2 and istr( bin.band(in_tab[2], 63)) or "=")

return s1..s2..s3..s4
end

function b64.encode(stream, stream_size)
local encoded = ""
local e_block
local in_tab, len, i, s_pos

s_pos = 0

while stream_size > 0 do
in_tab = {}

len = stream_size >= 3 and 3 or stream_size

for i = 1, len do
in_tab[i] = stream[s_pos + i]
end

e_block = b64.encodeblock(in_tab, len)

encoded = encoded .. e_block

s_pos = s_pos + 3
stream_size = stream_size - 3
end

return encoded
end

local function stri(s)
return s == "=" and -1 or (string.find(cb64, s) - 1)
end

function b64.decodeblock(s1, s2, s3, s4)
local b1, b2, b3, len

len = s3 == "=" and 1 or s4 == "=" and 2 or 3

s3 = s3 == "=" and "A" or s3
s4 = s4 == "=" and "A" or s4

s1 = stri(s1)
s2 = stri(s2)
s3 = stri(s3)
s4 = stri(s4)

b1 = bin.bor(bin.lshift(s1, 2), bin.rshift(s2, 4))
b2 = bin.bor(bin.band(bin.lshift(s2, 4), 255), bin.rshift(s3, 2))
b3 = bin.bor(bin.band(bin.lshift(s3, 6), 240), s4)

return {b1, b2, b3}, len
end

function b64.decode(str_in)
local s_len = string.len(str_in) / 4
local out, len, i, j, t_out, s1, s2, s3, s4, t_len = {}, 0

for i = 1, s_len do
s1 = string.sub(str_in, i * 4 - 3, i * 4 - 3)
s2 = string.sub(str_in, i * 4 - 2, i * 4 - 2)
s3 = string.sub(str_in, i * 4 - 1, i * 4 - 1)
s4 = string.sub(str_in, i * 4 - 0, i * 4 - 0)
t_out, t_len = b64.decodeblock(s1, s2, s3, s4)

for j = 1, t_len do
out[i * 3 - 3 + j] = t_out[j]
end

len = len + t_len
end

return out, len
end



b64_test_in = {
48, 49, 50, 51, 52, 53, 54, 55, 56, 57
}

b64_test_enc = "MDEyMzQ1Njc4OQ=="

function test_b64()
local enc, dec, i, len

enc = b64.encode(b64_test_in, 10)
assert(enc == b64_test_enc)
dec, len = b64.decode(enc)
assert(len == 10)
for i = 1, len do
assert(b64_test_in[i] == dec[i])
end
end

test_b64()
print(b64.encode(b64_test_in, 10))

Nenhum comentário: