diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/datamanager.lua | 79 | ||||
-rw-r--r-- | util/jid.lua | 8 | ||||
-rw-r--r-- | util/stanza.lua | 138 |
3 files changed, 225 insertions, 0 deletions
diff --git a/util/datamanager.lua b/util/datamanager.lua new file mode 100644 index 00000000..be63673e --- /dev/null +++ b/util/datamanager.lua @@ -0,0 +1,79 @@ +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; + +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 string.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(" [", format("%q", 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) + return format("data/%s/%s/%s.dat", encode(host), datastore, encode(username)); +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.."@"..host); 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.."@"..host); 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.."@"..host); return nil; end + f:write("return "); + simplesave(f, data); + f:close(); + return true; +end + diff --git a/util/jid.lua b/util/jid.lua new file mode 100644 index 00000000..9d01e2af --- /dev/null +++ b/util/jid.lua @@ -0,0 +1,8 @@ + +local match = string.match; + +module "jid" + +function split(jid) + return match(jid, "^([^@]+)@([^/]+)/?(.*)$"); +end diff --git a/util/stanza.lua b/util/stanza.lua new file mode 100644 index 00000000..35277e9c --- /dev/null +++ b/util/stanza.lua @@ -0,0 +1,138 @@ +local t_insert = table.insert; +local t_remove = table.remove; +local format = string.format; +local tostring = tostring; +local setmetatable = setmetatable; +local pairs = pairs; +local ipairs = ipairs; +local type = type; +local s_gsub = string.gsub; +module "stanza" + +stanza_mt = {}; +stanza_mt.__index = stanza_mt; + +function stanza(name, attr) + local stanza = { name = name, attr = attr or {}, tags = {}, last_add = {}}; + return setmetatable(stanza, stanza_mt); +end + +function stanza_mt:iq(attrs) + return self + stanza("iq", attrs) +end +function stanza_mt:message(attrs) + return self + stanza("message", attrs) +end +function stanza_mt:presence(attrs) + return self + stanza("presence", attrs) +end +function stanza_mt:query(xmlns) + return self:tag("query", { xmlns = xmlns }); +end +function stanza_mt:tag(name, attrs) + local s = stanza(name, attrs); + (self.last_add[#self.last_add] or self):add_child(s); + t_insert(self.last_add, s); + return self; +end + +function stanza_mt:text(text) + (self.last_add[#self.last_add] or self):add_child(text); + return self; +end + +function stanza_mt:up() + t_remove(self.last_add); + return self; +end + +function stanza_mt:add_child(child) + if type(child) == "table" then + t_insert(self.tags, child); + end + t_insert(self, child); +end + +function stanza_mt:child_with_name(name) + for _, child in ipairs(self) do + if child.name == name then return child; end + end +end + +function stanza_mt:children() + local i = 0; + return function (a) + i = i + 1 + local v = a[i] + if v then return v; end + end, self, i; + +end +function stanza_mt:childtags() + local i = 0; + return function (a) + i = i + 1 + local v = self.tags[i] + if v then return v; end + end, self.tags[1], i; + +end + +do + local xml_entities = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" }; + function xml_escape(s) return s_gsub(s, "['&<>\"]", xml_entities); end +end + +local xml_escape = xml_escape; + +function stanza_mt.__tostring(t) + local children_text = ""; + for n, child in ipairs(t) do + if type(child) == "string" then + children_text = children_text .. xml_escape(child); + else + children_text = children_text .. tostring(child); + end + end + + local attr_string = ""; + if t.attr then + for k, v in pairs(t.attr) do if type(k) == "string" then attr_string = attr_string .. format(" %s='%s'", k, tostring(v)); end end + end + + return format("<%s%s>%s</%s>", t.name, attr_string, children_text, t.name); +end + +function stanza_mt.__add(s1, s2) + return s1:add_child(s2); +end + + +do + local id = 0; + function new_id() + id = id + 1; + return "lx"..id; + end +end + +function message(attr, body) + if not body then + return stanza("message", attr); + else + return stanza("message", attr):tag("body"):text(body); + end +end +function iq(attr) + if attr and not attr.id then attr.id = new_id(); end + return stanza("iq", attr or { id = new_id() }); +end + +function reply(orig) + return stanza(orig.name, orig.attr and { to = orig.attr.from, from = orig.attr.to, id = orig.attr.id, type = ((orig.name == "iq" and "result") or nil) }); +end + +function presence(attr) + return stanza("presence", attr); +end + |