mirror of https://github.com/bjc/prosody
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.
168 lines
4.3 KiB
168 lines
4.3 KiB
|
|
local st = require "util.stanza";
|
|
|
|
local function getXml(user, host)
|
|
local jid = user.."@"..host;
|
|
local path = "data/"..jid..".xml";
|
|
local f = io.open(path);
|
|
if not f then return; end
|
|
local s = f:read("*a");
|
|
return parse_xml_real(s);
|
|
end
|
|
local function setXml(user, host, xml)
|
|
local jid = user.."@"..host;
|
|
local path = "data/"..jid..".xml";
|
|
if xml then
|
|
local f = io.open(path, "w");
|
|
if not f then return; end
|
|
local s = tostring(xml);
|
|
f:write(s);
|
|
f:close();
|
|
return true;
|
|
else
|
|
return os.remove(path);
|
|
end
|
|
end
|
|
local function getUserElement(xml)
|
|
if xml and xml.name == "server-data" then
|
|
local host = xml.tags[1];
|
|
if host and host.name == "host" then
|
|
local user = host.tags[1];
|
|
if user and user.name == "user" then
|
|
return user;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
local function createOuterXml(user, host)
|
|
return st.stanza("server-data", {xmlns='http://www.xmpp.org/extensions/xep-0227.html#ns'})
|
|
:tag("host", {jid=host})
|
|
:tag("user", {name = user});
|
|
end
|
|
local function removeFromArray(array, value)
|
|
for i,item in ipairs(array) do
|
|
if item == value then
|
|
table.remove(array, i);
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
local function removeStanzaChild(s, child)
|
|
removeFromArray(s.tags, child);
|
|
removeFromArray(s, child);
|
|
end
|
|
|
|
local handlers = {};
|
|
|
|
handlers.accounts = {
|
|
get = function(self, user)
|
|
local user = getUserElement(getXml(user, self.host));
|
|
if user and user.attr.password then
|
|
return { password = user.attr.password };
|
|
end
|
|
end;
|
|
set = function(self, user, data)
|
|
if data and data.password then
|
|
local xml = getXml(user, self.host);
|
|
if not xml then xml = createOuterXml(user, self.host); end
|
|
local usere = getUserElement(xml);
|
|
usere.attr.password = data.password;
|
|
return setXml(user, self.host, xml);
|
|
else
|
|
return setXml(user, self.host, nil);
|
|
end
|
|
end;
|
|
};
|
|
handlers.vcard = {
|
|
get = function(self, user)
|
|
local user = getUserElement(getXml(user, self.host));
|
|
if user then
|
|
local vcard = user:get_child("vCard", 'vcard-temp');
|
|
if vcard then
|
|
return st.preserialize(vcard);
|
|
end
|
|
end
|
|
end;
|
|
set = function(self, user, data)
|
|
local xml = getXml(user, self.host);
|
|
local usere = xml and getUserElement(xml);
|
|
if usere then
|
|
local vcard = usere:get_child("vCard", 'vcard-temp');
|
|
if vcard then
|
|
removeStanzaChild(usere, vcard);
|
|
elseif not data then
|
|
return true;
|
|
end
|
|
if data then
|
|
vcard = st.deserialize(data);
|
|
usere:add_child(vcard);
|
|
end
|
|
return setXml(user, self.host, xml);
|
|
end
|
|
return true;
|
|
end;
|
|
};
|
|
handlers.private = {
|
|
get = function(self, user)
|
|
local user = getUserElement(getXml(user, self.host));
|
|
if user then
|
|
local private = user:get_child("query", "jabber:iq:private");
|
|
if private then
|
|
local r = {};
|
|
for _, tag in ipairs(private.tags) do
|
|
r[tag.name..":"..tag.attr.xmlns] = st.preserialize(tag);
|
|
end
|
|
return r;
|
|
end
|
|
end
|
|
end;
|
|
set = function(self, user, data)
|
|
local xml = getXml(user, self.host);
|
|
local usere = xml and getUserElement(xml);
|
|
if usere then
|
|
local private = usere:get_child("query", 'jabber:iq:private');
|
|
if private then removeStanzaChild(usere, private); end
|
|
if data and next(data) ~= nil then
|
|
private = st.stanza("query", {xmlns='jabber:iq:private'});
|
|
for _,tag in pairs(data) do
|
|
private:add_child(st.deserialize(tag));
|
|
end
|
|
usere:add_child(private);
|
|
end
|
|
return setXml(user, self.host, xml);
|
|
end
|
|
return true;
|
|
end;
|
|
};
|
|
|
|
-----------------------------
|
|
local driver = {};
|
|
driver.__index = driver;
|
|
|
|
function driver:open(host, datastore, typ)
|
|
local cache_key = host.." "..datastore;
|
|
if self.ds_cache[cache_key] then return self.ds_cache[cache_key]; end
|
|
local instance = setmetatable({}, self);
|
|
instance.host = host;
|
|
instance.datastore = datastore;
|
|
local handler = handlers[datastore];
|
|
if not handler then return nil; end
|
|
for key,val in pairs(handler) do
|
|
instance[key] = val;
|
|
end
|
|
if instance.init then instance:init(); end
|
|
self.ds_cache[cache_key] = instance;
|
|
return instance;
|
|
end
|
|
|
|
-----------------------------
|
|
local _M = {};
|
|
|
|
function _M.new()
|
|
local instance = setmetatable({}, driver);
|
|
instance.__index = instance;
|
|
instance.ds_cache = {};
|
|
return instance;
|
|
end
|
|
|
|
return _M;
|
|
|