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");
21 return parse_xml_real(s);
23 local function setXml(user, host, xml)
24 local jid = user.."@"..host;
25 local path = paths.join(prosody.paths.data, jid..".xml");
27 local f = io_open(path, "w");
28 if not f then return; end
29 local s = tostring(xml);
34 return os_remove(path);
37 local function getUserElement(xml)
38 if xml and xml.name == "server-data" then
39 local host = xml.tags[1];
40 if host and host.name == "host" then
41 local user = host.tags[1];
42 if user and user.name == "user" then
48 local function createOuterXml(user, host)
49 return st.stanza("server-data", {xmlns='http://www.xmpp.org/extensions/xep-0227.html#ns'})
50 :tag("host", {jid=host})
51 :tag("user", {name = user});
53 local function removeFromArray(array, value)
54 for i,item in ipairs(array) do
61 local function removeStanzaChild(s, child)
62 removeFromArray(s.tags, child);
63 removeFromArray(s, child);
69 get = function(self, user)
70 local user = getUserElement(getXml(user, self.host));
71 if user and user.attr.password then
72 return { password = user.attr.password };
75 set = function(self, user, data)
76 if data and data.password then
77 local xml = getXml(user, self.host);
78 if not xml then xml = createOuterXml(user, self.host); end
79 local usere = getUserElement(xml);
80 usere.attr.password = data.password;
81 return setXml(user, self.host, xml);
83 return setXml(user, self.host, nil);
88 get = function(self, user)
89 local user = getUserElement(getXml(user, self.host));
91 local vcard = user:get_child("vCard", 'vcard-temp');
93 return st.preserialize(vcard);
97 set = function(self, user, data)
98 local xml = getXml(user, self.host);
99 local usere = xml and getUserElement(xml);
101 local vcard = usere:get_child("vCard", 'vcard-temp');
103 removeStanzaChild(usere, vcard);
108 vcard = st.deserialize(data);
109 usere:add_child(vcard);
111 return setXml(user, self.host, xml);
117 get = function(self, user)
118 local user = getUserElement(getXml(user, self.host));
120 local private = user:get_child("query", "jabber:iq:private");
123 for _, tag in ipairs(private.tags) do
124 r[tag.name..":"..tag.attr.xmlns] = st.preserialize(tag);
130 set = function(self, user, data)
131 local xml = getXml(user, self.host);
132 local usere = xml and getUserElement(xml);
134 local private = usere:get_child("query", 'jabber:iq:private');
135 if private then removeStanzaChild(usere, private); end
136 if data and next(data) ~= nil then
137 private = st.stanza("query", {xmlns='jabber:iq:private'});
138 for _,tag in pairs(data) do
139 private:add_child(st.deserialize(tag));
141 usere:add_child(private);
143 return setXml(user, self.host, xml);
149 -----------------------------
152 function driver:open(host, datastore, typ)
153 local instance = setmetatable({}, self);
154 instance.host = host;
155 instance.datastore = datastore;
156 local handler = handlers[datastore];
157 if not handler then return nil; end
158 for key,val in pairs(handler) do
161 if instance.init then instance:init(); end
165 module:provides("storage", driver);