2 local ipairs, pairs = ipairs, pairs;
3 local setmetatable = setmetatable;
4 local tostring = tostring;
6 local t_remove = table.remove;
7 local os_remove = os.remove;
8 local io_open = io.open;
10 local paths = require"util.paths";
11 local st = require "util.stanza";
12 local parse_xml_real = require "util.xml".parse;
14 local function getXml(user, host)
15 local jid = user.."@"..host;
16 local path = paths.join(prosody.paths.data, jid..".xml");
17 local f = io_open(path);
18 if not f then return; end
19 local s = f:read("*a");
20 return parse_xml_real(s);
22 local function setXml(user, host, xml)
23 local jid = user.."@"..host;
24 local path = paths.join(prosody.paths.data, jid..".xml");
26 local f = io_open(path, "w");
27 if not f then return; end
28 local s = tostring(xml);
33 return os_remove(path);
36 local function getUserElement(xml)
37 if xml and xml.name == "server-data" then
38 local host = xml.tags[1];
39 if host and host.name == "host" then
40 local user = host.tags[1];
41 if user and user.name == "user" then
47 local function createOuterXml(user, host)
48 return st.stanza("server-data", {xmlns='http://www.xmpp.org/extensions/xep-0227.html#ns'})
49 :tag("host", {jid=host})
50 :tag("user", {name = user});
52 local function removeFromArray(array, value)
53 for i,item in ipairs(array) do
60 local function removeStanzaChild(s, child)
61 removeFromArray(s.tags, child);
62 removeFromArray(s, child);
68 get = function(self, user)
69 local user = getUserElement(getXml(user, self.host));
70 if user and user.attr.password then
71 return { password = user.attr.password };
74 set = function(self, user, data)
75 if data and data.password then
76 local xml = getXml(user, self.host);
77 if not xml then xml = createOuterXml(user, self.host); end
78 local usere = getUserElement(xml);
79 usere.attr.password = data.password;
80 return setXml(user, self.host, xml);
82 return setXml(user, self.host, nil);
87 get = function(self, user)
88 local user = getUserElement(getXml(user, self.host));
90 local vcard = user:get_child("vCard", 'vcard-temp');
92 return st.preserialize(vcard);
96 set = function(self, user, data)
97 local xml = getXml(user, self.host);
98 local usere = xml and getUserElement(xml);
100 local vcard = usere:get_child("vCard", 'vcard-temp');
102 removeStanzaChild(usere, vcard);
107 vcard = st.deserialize(data);
108 usere:add_child(vcard);
110 return setXml(user, self.host, xml);
116 get = function(self, user)
117 local user = getUserElement(getXml(user, self.host));
119 local private = user:get_child("query", "jabber:iq:private");
122 for _, tag in ipairs(private.tags) do
123 r[tag.name..":"..tag.attr.xmlns] = st.preserialize(tag);
129 set = function(self, user, data)
130 local xml = getXml(user, self.host);
131 local usere = xml and getUserElement(xml);
133 local private = usere:get_child("query", 'jabber:iq:private');
134 if private then removeStanzaChild(usere, private); end
135 if data and next(data) ~= nil then
136 private = st.stanza("query", {xmlns='jabber:iq:private'});
137 for _,tag in pairs(data) do
138 private:add_child(st.deserialize(tag));
140 usere:add_child(private);
142 return setXml(user, self.host, xml);
148 -----------------------------
151 function driver:open(host, datastore, typ)
152 local instance = setmetatable({}, self);
153 instance.host = host;
154 instance.datastore = datastore;
155 local handler = handlers[datastore];
156 if not handler then return nil; end
157 for key,val in pairs(handler) do
160 if instance.init then instance:init(); end
164 module:provides("storage", driver);