diff options
Diffstat (limited to 'lib/session.lua')
-rw-r--r-- | lib/session.lua | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/session.lua b/lib/session.lua new file mode 100644 index 0000000..f23f5a5 --- /dev/null +++ b/lib/session.lua @@ -0,0 +1,143 @@ +-- Session handling routines - written for acf +-- Copyright (C) 2007 N. Angelacos - GPL2 License + +module (..., package.seeall) + +local b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-" + +-- Return a sessionid of at least size bits length +random_hash = function (size) + local file = io.open("/dev/urandom") + local str = "" + if file == nil then return nil end + while (size > 0 ) do + local offset = (string.byte(file:read(1)) % 64) + 1 + str = str .. string.sub (b64, offset, offset) + size = size - 6 + end + return str +end + +hash_ip_addr = function (string) + local str = "" + for i in string.gmatch(string, "%d+") do + str = str .. string.format("%02x", i ) + end + return str +end + +ip_addr_from_hash = function (string) + local str = "" + for i in string.gmatch(string, "..") do + str = str .. string.format("%d", "0x" .. i) .. "." + end + return string.sub(str, 1, string.len(str)-1) +end + + +--[[ + These functions serialize a table, including nested tables. + The code based on code in PiL 2nd edition p113 +]]-- +local function basicSerialize (o) + if type(o) == "number" then + return tostring(o) + else + return string.format("%q", o) + end +end + + +function serialize (name, value, saved ) + local str = str or "" + saved = saved or {} + str = str .. name .. " = " + if type(value) == "number" or type(value) == "string" then + str = str .. basicSerialize (value) .. "\n" + elseif type(value) == "table" then + if saved[value] then + str = str .. saved[value] .. "\n" + else + saved[value] = name + str = str .. "{}\n" + for k,v in pairs(value) do + local fieldname = string.format("%s[%s]", name, basicSerialize(k)) + str = str .. serialize (fieldname, v, saved) + end + end + elseif type(value) == "boolean" then + str = str .. tostring(value) .. "\n" + else + str = str .. "nil\n" -- cannot save other types, so skip them + end + return str +end + +save_session = function( sessionpath, session, sessiontable) + local file = io.open(sessionpath .. "/" .. session , "w") + if file then + file:write ( "-- This is an ACF session table.\nlocal timestamp=" .. os.time() ) + file:write ( "\nlocal " ) + file:write ( serialize("s", sessiontable) ) + file:write ( "return timestamp, s\n") + file:close() + return true + else + return false + end +end + + +--- FIXME: This is really a generic "test if file exists" thing. + +-- Tests if a session is valid +-- Returns true if valid, false if not +session_is_valid = function (session) + local file = io.open(session) + if file then + file:close() + return true + else + return false + end +end + +-- Loads a session +-- Returns a timestamp (when the session data was saved) and the session table. +load_session = function ( sessionpath, session ) + -- session can only have b64 characters in it + session = string.gsub ( session, "[^" .. b64 .. "]", "") + if #session == 0 then + return nil, {} + end + session = sessionpath .. "/" .. session + if (session_is_valid(session)) then + local file = io.open(session) + return dofile(session) + else + return nil, {} + end +end + +-- unlinks a session +invalidate_session = function (sessionpath, session) + if type(session) ~= "string" then return nil end + local s = string.gsub (session, "[^" .. b64 .. "]", "") + if s ~= session then + return nil + end + session = sessionpath .. "/" .. s + os.remove (session) + return nil +end + + +expire_old_sessions = function ( sessiondir ) + file = io.popen("ls " .. sessiondir ) + x = file:read("*a") + file:close() + for a in string.gmatch(x, "[^%c]+") do + timestamp, foo = load_session ( sessiondir .. "/" .. a ) + print ( a .. " is " .. os.time() - timestamp .. " seconds old") + end +end |