aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/datamanager.lua79
-rw-r--r--util/jid.lua8
-rw-r--r--util/stanza.lua138
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 = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
+ 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
+