IMPORTANT: due to a drive failure, as of 13-Mar-2021, the Mercurial repository had to be re-mirrored, which changed every commit SHA. The old SHAs and trees are backed up in the vault branches. Please migrate to the new branches as soon as you can.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
prosody/util/datamanager.lua

95 lines
2.5 KiB

local format = string.format;
local setmetatable, type = setmetatable, type;
local pairs = pairs;
local char = string.char;
local loadfile, setfenv, pcall = loadfile, setfenv, pcall;
local log = log;
local io_open = io.open;
local tostring = tostring;
module "datamanager"
---- utils -----
local encode, decode;
local log = function (type, msg) return log(type, "datamanager", msg); end
do
local urlcodes = setmetatable({}, { __index = function (t, k) t[k] = char(tonumber("0x"..k)); return t[k]; end });
decode = function (s)
return s and (s:gsub("+", " "):gsub("%%([a-fA-F0-9][a-fA-F0-9])", urlcodes));
end
encode = function (s)
return s and (s:gsub("%W", function (c) return format("%%%x", c:byte()); end));
end
end
local function basicSerialize (o)
if type(o) == "number" or type(o) == "boolean" then
return tostring(o)
else -- assume it is a string
return format("%q", tostring(o))
end
end
local function simplesave (f, o)
if type(o) == "number" then
f:write(o)
elseif type(o) == "string" then
f:write(format("%q", o))
elseif type(o) == "table" then
f:write("{\n")
for k,v in pairs(o) do
f:write(" [", basicSerialize(k), "] = ")
simplesave(f, v)
f:write(",\n")
end
f:write("}\n")
else
error("cannot serialize a " .. type(o))
end
end
------- API -------------
function getpath(username, host, datastore)
if username then
return format("data/%s/%s/%s.dat", encode(host), datastore, encode(username));
elseif host then
return format("data/%s/%s.dat", encode(host), datastore);
else
return format("data/%s.dat", datastore);
end
end
function load(username, host, datastore)
local data, ret = loadfile(getpath(username, host, datastore));
if not data then
log("warn", "Failed to load "..datastore.." storage ('"..ret.."') for user: "..(username or nil).."@"..(host or nil));
return nil;
end
setfenv(data, {});
local success, ret = pcall(data);
if not success then
log("error", "Unable to load "..datastore.." storage ('"..ret.."') for user: "..(username or nil).."@"..(host or nil));
return nil;
end
return ret;
end
function store(username, host, datastore, data)
local f, msg = io_open(getpath(username, host, datastore), "w+");
if not f then
log("error", "Unable to write to "..datastore.." storage ('"..msg.."') for user: "..(username or nil).."@"..(host or nil));
return nil;
end
f:write("return ");
simplesave(f, data);
f:close();
return true;
end