Mercurial > prosody-modules
comparison mod_archive/mod_archive.lua @ 165:fd8d76daad97
mod_archive: preference handling is done.
author | shinysky<shinysky1986(AT)gmail.com> |
---|---|
date | Sun, 06 Jun 2010 00:04:04 +0800 |
parents | 9a37898f4f7c |
children | ac826882a8cf |
comparison
equal
deleted
inserted
replaced
164:0b238b2b0801 | 165:fd8d76daad97 |
---|---|
4 -- This project is MIT/X11 licensed. Please see the | 4 -- This project is MIT/X11 licensed. Please see the |
5 -- COPYING file in the source package for more information. | 5 -- COPYING file in the source package for more information. |
6 -- | 6 -- |
7 | 7 |
8 local st = require "util.stanza"; | 8 local st = require "util.stanza"; |
9 local dm = require "util.datamanager" | 9 local dm = require "util.datamanager"; |
10 | |
11 local PREFS_DIR = "archive_prefs"; | |
12 local ARCHIVE_DIR = "archive"; | |
10 | 13 |
11 module:add_feature("urn:xmpp:archive"); | 14 module:add_feature("urn:xmpp:archive"); |
12 module:add_feature("urn:xmpp:archive:auto"); | 15 module:add_feature("urn:xmpp:archive:auto"); |
13 module:add_feature("urn:xmpp:archive:manage"); | 16 module:add_feature("urn:xmpp:archive:manage"); |
14 module:add_feature("urn:xmpp:archive:manual"); | 17 module:add_feature("urn:xmpp:archive:manual"); |
15 module:add_feature("urn:xmpp:archive:pref"); | 18 module:add_feature("urn:xmpp:archive:pref"); |
16 | 19 |
20 ------------------------------------------------------------ | |
21 -- Utils | |
22 ------------------------------------------------------------ | |
23 local function load_prefs(node, host, dir) | |
24 return st.deserialize(dm.load(node, host, dir or PREFS_DIR)); | |
25 end | |
26 | |
27 local function store_prefs(data, node, host, dir) | |
28 dm.store(node, host, dir or PREFS_DIR, st.preserialize(data)); | |
29 end | |
30 | |
31 ------------------------------------------------------------ | |
32 -- Preferences | |
33 ------------------------------------------------------------ | |
17 local function preferences_handler(event) | 34 local function preferences_handler(event) |
18 local origin, stanza = event.origin, event.stanza; | 35 local origin, stanza = event.origin, event.stanza; |
19 module:log("debug", "-- Enter preferences_handler()"); | 36 module:log("debug", "-- Enter preferences_handler()"); |
20 module:log("debug", "-- pref:\n%s", tostring(stanza)); | 37 module:log("debug", "-- pref:\n%s", tostring(stanza)); |
21 if stanza.attr.type == "get" then | 38 if stanza.attr.type == "get" then |
22 -- dm.store(origin.username, origin.host, "archive_prefs", st.preserialize(reply.tags[1])); | 39 local data = load_prefs(origin.username, origin.host); |
23 local data = st.deserialize(dm.load(origin.username, origin.host, "archive_prefs")); | |
24 if data then | 40 if data then |
25 origin.send(st.reply(stanza):add_child(data)); | 41 origin.send(st.reply(stanza):add_child(data)); |
26 else | 42 else |
27 local reply = st.reply(stanza):tag('pref', {xmlns='urn:xmpp:archive'}); | 43 local reply = st.reply(stanza):tag('pref', {xmlns='urn:xmpp:archive'}); |
28 reply:tag('default', {otr='concede', save='false', unset='true'}):up(); | 44 reply:tag('default', {otr='concede', save='false', unset='true'}):up(); |
29 reply:tag('method', {type='auto', use='concede'}):up(); | 45 reply:tag('method', {type='auto', use='concede'}):up(); |
30 reply:tag('method', {type='local', use='concede'}):up(); | 46 reply:tag('method', {type='local', use='concede'}):up(); |
31 reply:tag('method', {type='manual', use='concede'}):up(); | 47 reply:tag('method', {type='manual', use='concede'}):up(); |
32 reply:tag('auto', {save='false'}):up(); | 48 reply:tag('auto', {save='false'}):up(); |
33 origin.send(reply); | 49 origin.send(reply); |
34 -- origin.send(st.reply(stanza)); | 50 end |
35 end | |
36 return true; | |
37 elseif stanza.attr.type == "set" then | 51 elseif stanza.attr.type == "set" then |
38 return false; | 52 local node, host = origin.username, origin.host; |
39 end | 53 local data = load_prefs(node, host); |
54 if not data then | |
55 data = st.stanza('pref', {xmlns='urn:xmpp:archive'}); | |
56 data:tag('default', {otr='concede', save='false'}):up(); | |
57 data:tag('method', {type='auto', use='concede'}):up(); | |
58 data:tag('method', {type='local', use='concede'}):up(); | |
59 data:tag('method', {type='manual', use='concede'}):up(); | |
60 data:tag('auto', {save='false'}):up(); | |
61 end | |
62 local elem = stanza.tags[1].tags[1]; -- iq:pref:xxx | |
63 if not elem then return false end | |
64 -- "default" | "item" | "session" | "method" | |
65 -- FIXME there may be many item/session/method sections!! | |
66 elem.attr["xmlns"] = nil; -- TODO why there is an extra xmlns attr? | |
67 if elem.name == "default" then | |
68 local setting = data:child_with_name(elem.name) | |
69 for k, v in pairs(elem.attr) do | |
70 setting.attr[k] = v; | |
71 end | |
72 -- setting.attr["unset"] = nil | |
73 elseif elem.name == "item" then | |
74 local found = false; | |
75 for child in data:children() do | |
76 -- TODO bare JID or full JID? | |
77 if child.name == elem.name and child.attr["jid"] == elem.attr["jid"] then | |
78 for k, v in pairs(elem.attr) do | |
79 child.attr[k] = v; | |
80 end | |
81 found = true; | |
82 break; | |
83 end | |
84 end | |
85 if not found then | |
86 data:tag(elem.name, elem.attr):up(); | |
87 end | |
88 elseif elem.name == "session" then | |
89 local found = false; | |
90 for child in data:children() do | |
91 if child.name == elem.name and child.attr["thread"] == elem.attr["thread"] then | |
92 for k, v in pairs(elem.attr) do | |
93 child.attr[k] = v; | |
94 end | |
95 found = true; | |
96 break; | |
97 end | |
98 end | |
99 if not found then | |
100 data:tag(elem.name, elem.attr):up(); | |
101 end | |
102 elseif elem.name == "method" then | |
103 local newpref = stanza.tags[1]; -- iq:pref | |
104 for _, e in ipairs(newpref.tags) do | |
105 -- if e.name ~= "method" then continue end | |
106 local found = false; | |
107 for child in data:children() do | |
108 if child.name == "method" and child.attr["type"] == e.attr["type"] then | |
109 child.attr["use"] = e.attr["use"]; | |
110 found = true; | |
111 break; | |
112 end | |
113 end | |
114 if not found then | |
115 data:tag(e.name, e.attr):up(); | |
116 end | |
117 end | |
118 end | |
119 store_prefs(data, node, host); | |
120 origin.send(st.reply(stanza)); | |
121 local user = bare_sessions[node.."@"..host]; | |
122 local push = st.iq({type="set"}); | |
123 push = push:tag('pref', {xmlns='urn:xmpp:archive'}); | |
124 if elem.name == "method" then | |
125 for child in data:children() do | |
126 if child.name == "method" then | |
127 push:add_child(child); | |
128 end | |
129 end | |
130 else | |
131 push:add_child(elem); | |
132 end | |
133 push = push:up(); | |
134 for _, res in pairs(user and user.sessions or NULL) do -- broadcast to all resources | |
135 if res.presence then -- to resource | |
136 push.attr.to = res.full_jid; -- TODO how to gen the message that new modes're set? | |
137 res.send(push); | |
138 end | |
139 end | |
140 end | |
141 return true; | |
142 end | |
143 | |
144 local function itemremove_handler(event) | |
145 local origin, stanza = event.origin, event.stanza; | |
146 if stanza.attr.type ~= "set" then | |
147 return false; | |
148 end | |
149 local elem = stanza.tags[1].tags[1]; | |
150 if not elem or elem.name ~= "item" then | |
151 return false; | |
152 end | |
153 local node, host = origin.username, origin.host; | |
154 local data = load_prefs(node, host); | |
155 if not data then | |
156 return false; | |
157 end | |
158 for i, child in ipairs(data) do | |
159 if child.name == "item" and child.attr["jid"] == elem.attr["jid"] then | |
160 table.remove(data, i) | |
161 break; | |
162 end | |
163 end | |
164 store_prefs(data, node, host); | |
165 origin.send(st.reply(stanza)); | |
166 return true; | |
167 end | |
168 | |
169 local function sessionremove_handler(event) | |
170 local origin, stanza = event.origin, event.stanza; | |
171 if stanza.attr.type ~= "set" then | |
172 return false; | |
173 end | |
174 local elem = stanza.tags[1].tags[1]; | |
175 if not elem or elem.name ~= "session" then | |
176 return false; | |
177 end | |
178 local node, host = origin.username, origin.host; | |
179 local data = load_prefs(node, host); | |
180 if not data then | |
181 return false; | |
182 end | |
183 for i, child in ipairs(data) do | |
184 if child.name == "session" and child.attr["thread"] == elem.attr["thread"] then | |
185 table.remove(data, i) | |
186 break; | |
187 end | |
188 end | |
189 store_prefs(data, node, host); | |
190 origin.send(st.reply(stanza)); | |
191 return true; | |
40 end | 192 end |
41 | 193 |
42 local function auto_handler(event) | 194 local function auto_handler(event) |
43 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 195 -- event.origin.send(st.error_reply(event.stanza, "cancel", "feature-not-implemented")); |
44 if event.stanza.attr.type == "set" then | 196 local origin, stanza = event.origin, event.stanza; |
45 event.origin.send(st.error_reply(event.stanza, "cancel", "feature-not-implemented")); | 197 if stanza.attr.type ~= "set" then |
46 return true; | 198 return false; |
47 end | 199 end |
200 local elem = stanza.tags[1]; | |
201 local node, host = origin.username, origin.host; | |
202 local data = load_prefs(node, host); | |
203 if not data then | |
204 return false; | |
205 end | |
206 local setting = data:child_with_name(elem.name) | |
207 setting.attr["save"] = elem.attr["save"]; | |
208 store_prefs(data, node, host); | |
209 origin.send(st.reply(stanza)); | |
210 return true; | |
48 end | 211 end |
49 | 212 |
50 local function chat_handler(event) | 213 local function chat_handler(event) |
51 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 214 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
52 return true; | 215 return true; |
53 end | 216 end |
54 | 217 |
55 local function itemremove_handler(event) | |
56 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | |
57 return true; | |
58 end | |
59 | |
60 local function list_handler(event) | 218 local function list_handler(event) |
61 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 219 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
62 return true; | 220 return true; |
63 end | 221 end |
64 | 222 |
81 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); | 239 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); |
82 return true; | 240 return true; |
83 end | 241 end |
84 | 242 |
85 module:hook("iq/self/urn:xmpp:archive:pref", preferences_handler); | 243 module:hook("iq/self/urn:xmpp:archive:pref", preferences_handler); |
244 module:hook("iq/self/urn:xmpp:archive:itemremove", itemremove_handler); | |
245 module:hook("iq/self/urn:xmpp:archive:sessionremove", sessionremove_handler); | |
86 module:hook("iq/self/urn:xmpp:archive:auto", auto_handler); | 246 module:hook("iq/self/urn:xmpp:archive:auto", auto_handler); |
87 module:hook("iq/self/urn:xmpp:archive:chat", chat_handler); | 247 -- module:hook("iq/self/urn:xmpp:archive:chat", chat_handler); |
88 module:hook("iq/self/urn:xmpp:archive:itemremove", itemremove_handler); | |
89 module:hook("iq/self/urn:xmpp:archive:list", list_handler); | 248 module:hook("iq/self/urn:xmpp:archive:list", list_handler); |
90 module:hook("iq/self/urn:xmpp:archive:modified", modified_handler); | 249 module:hook("iq/self/urn:xmpp:archive:modified", modified_handler); |
91 module:hook("iq/self/urn:xmpp:archive:remove", remove_handler); | 250 module:hook("iq/self/urn:xmpp:archive:remove", remove_handler); |
92 module:hook("iq/self/urn:xmpp:archive:retrieve", retrieve_handler); | 251 module:hook("iq/self/urn:xmpp:archive:retrieve", retrieve_handler); |
93 module:hook("iq/self/urn:xmpp:archive:save", save_handler); | 252 module:hook("iq/self/urn:xmpp:archive:save", save_handler); |