Comparison

mod_privacy/mod_privacy.lua @ 20:2675dc25445b

mod_privacy: overworked error returns while creating, editing, deleting or de/activating lists.
author Thilo Cestonaro <thilo@cestona.ro>
date Wed, 30 Sep 2009 21:35:29 +0200
parent 19:e400ee8471b0
child 27:d91cb13ef0ee
comparison
equal deleted inserted replaced
19:e400ee8471b0 20:2675dc25445b
32 end 32 end
33 end 33 end
34 return ret; 34 return ret;
35 end 35 end
36 36
37 function isListUsed(origin, name, privacy_lists)
38 if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then
39 for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do
40 if resource ~= origin.resource then
41 if session.activePrivacyList == name then
42 module:log("debug", "List {0} is in use.", name);
43 return true;
44 elseif session.activePrivacyList == nil and privacy_lists.default == name then
45 module:log("debug", "List {0} is in use.", name);
46 return true;
47 end
48 end
49 end
50 end
51 module:log("debug", "List {0} is in NOT use.", name);
52 return false;
53 end
54
55 function isAnotherSessionUsingDefaultList(origin)
56 local ret = false
57 if bare_sessions[origin.username.."@"..origin.host].sessions ~= nil then
58 for resource, session in pairs(bare_sessions[origin.username.."@"..origin.host].sessions) do
59 if resource ~= origin.resource and session.activePrivacyList == nil then
60 module:log("debug", "Default list is used by another resource.");
61 ret = true;
62 break;
63 end
64 end
65 end
66 return ret;
67 end
68
37 function declineList (privacy_lists, origin, stanza, which) 69 function declineList (privacy_lists, origin, stanza, which)
38 module:log("info", "User requests to decline the use of privacy list: %s", which); 70 module:log("info", "User requests to decline the use of privacy list: %s", which);
39 if which == "default" then 71 if which == "default" then
40 privacy_lists.default = nil; -- TODO check if used! 72 if isAnotherSessionUsingDefaultList(origin) then
73 return { "cancel", "conflict", "Another session is online and using the default list."};
74 end
75 privacy_lists.default = nil;
76 origin.send(st.reply(stanza));
41 elseif which == "active" then 77 elseif which == "active" then
42 origin.activePrivacyList = nil; 78 origin.activePrivacyList = nil;
43 end 79 origin.send(st.reply(stanza));
44 origin.send(st.reply(stanza)); 80 else
81 return {"modify", "bad-request", "Neither default nor active list specifed to decline."};
82 end
45 return true; 83 return true;
46 end 84 end
47 85
48 function activateList (privacy_lists, origin, stanza, which, name) 86 function activateList (privacy_lists, origin, stanza, which, name)
49 module:log("info", "User requests to change the privacy list: %s, to be list named %s", which, name); 87 module:log("info", "User requests to change the privacy list: %s, to be list named %s", which, name);
50 local ret = false;
51 local idx = findNamedList(privacy_lists, name); 88 local idx = findNamedList(privacy_lists, name);
52 89
53 if privacy_lists[which] == nil then 90 if privacy_lists.default == nil then
54 privacy_lists[which] = ""; 91 privacy_lists.default = "";
55 end 92 end
56 93 if origin.activePrivacyList == nil then
57 if which == "default" and privacy_lists.default ~= name and idx ~= nil then 94 origin.activePrivacyList = "";
58 privacy_lists.default = name; -- TODO check if used! 95 end
59 ret = true; 96
60 elseif which == "active" and origin.activePrivacyList ~= name and idx ~= nil then 97 if which == "default" and idx ~= nil then
98 if isAnotherSessionUsingDefaultList(origin) then
99 return {"cancel", "conflict", "Another session is online and using the default list."};
100 end
101 privacy_lists.default = name;
102 origin.send(st.reply(stanza));
103 elseif which == "active" and idx ~= nil then
61 origin.activePrivacyList = name; 104 origin.activePrivacyList = name;
62 ret = true;
63 end
64 if ret == true then
65 origin.send(st.reply(stanza)); 105 origin.send(st.reply(stanza));
66 end 106 else
67 return ret; 107 return {"modify", "bad-request", "Either not active or default given or unknown list name specified."};
108 end
109 return true;
68 end 110 end
69 111
70 function deleteList (privacy_lists, origin, stanza, name) 112 function deleteList (privacy_lists, origin, stanza, name)
71 module:log("info", "User requests to delete privacy list: %s", name); 113 module:log("info", "User requests to delete privacy list: %s", name);
72 local ret = false;
73 local idx = findNamedList(privacy_lists, name); 114 local idx = findNamedList(privacy_lists, name);
74 115
75 if idx ~= nil then 116 if idx ~= nil then
76 table.remove(privacy_lists.lists, idx); -- TODO check if used! 117 if isListUsed(origin, name, privacy_lists) then
118 return {"cancel", "conflict", "Another session is online and using the list which should be deleted."};
119 end
120 table.remove(privacy_lists.lists, idx);
77 origin.send(st.reply(stanza)); 121 origin.send(st.reply(stanza));
78 ret = true; 122 return true;
79 end 123 end
80 return ret; 124 return {"modify", "bad-request", "Not existing list specifed to be deleted."};
81 end 125 end
82 126
83 local function sortByOrder(a, b) 127 local function sortByOrder(a, b)
84 if a.order < b.order then 128 if a.order < b.order then
85 return true; 129 return true;
87 return false; 131 return false;
88 end 132 end
89 133
90 function createOrReplaceList (privacy_lists, origin, stanza, name, entries, roster) 134 function createOrReplaceList (privacy_lists, origin, stanza, name, entries, roster)
91 module:log("info", "User requests to create / replace list named %s, item count: %d", name, #entries); 135 module:log("info", "User requests to create / replace list named %s, item count: %d", name, #entries);
92 local ret = true;
93 local idx = findNamedList(privacy_lists, name); 136 local idx = findNamedList(privacy_lists, name);
94 local bare_jid = origin.username.."@"..origin.host; 137 local bare_jid = origin.username.."@"..origin.host;
95 138
96 if privacy_lists.lists == nil then 139 if privacy_lists.lists == nil then
97 privacy_lists.lists = {}; 140 privacy_lists.lists = {};
106 list.name = name; 149 list.name = name;
107 list.items = {}; 150 list.items = {};
108 151
109 for _,item in ipairs(entries) do 152 for _,item in ipairs(entries) do
110 if to_number(item.attr.order) == nil or to_number(item.attr.order) < 0 or orderCheck[item.attr.order] ~= nil then 153 if to_number(item.attr.order) == nil or to_number(item.attr.order) < 0 or orderCheck[item.attr.order] ~= nil then
111 return "bad-request"; 154 return {"modify", "bad-request", "Order attribute not valid."};
112 end 155 end
156
157 if item.attr.type ~= nil and item.attr.type ~= "jid" and item.attr.type ~= "subscription" and item.attr.type ~= "group" then
158 return {"modify", "bad-request", "Type attribute not valid."};
159 end
160
113 local tmp = {}; 161 local tmp = {};
114 orderCheck[item.attr.order] = true; 162 orderCheck[item.attr.order] = true;
115 163
116 tmp["type"] = item.attr.type; 164 tmp["type"] = item.attr.type;
117 tmp["value"] = item.attr.value; 165 tmp["value"] = item.attr.value;
131 if tmp.type == "group" then 179 if tmp.type == "group" then
132 local found = false; 180 local found = false;
133 local roster = load_roster(origin.username, origin.host); 181 local roster = load_roster(origin.username, origin.host);
134 local groups = roster.groups; 182 local groups = roster.groups;
135 if groups == nil then 183 if groups == nil then
136 return "item-not-found"; 184 return {"cancel", "item-not-found", "Specifed roster group not existing."};
137 end 185 end
138 for _,group in ipairs(groups) do 186 for _,group in ipairs(groups) do
139 if group == tmp.value then 187 if group == tmp.value then
140 found = true; 188 found = true;
141 end 189 end
142 end 190 end
143 if found == false then 191 if found == false then
144 return "item-not-found"; 192 return {"cancel", "item-not-found", "Specifed roster group not existing."};
145 end 193 end
146 elseif tmp.type == "subscription" then 194 elseif tmp.type == "subscription" then
147 if tmp.value ~= "both" and 195 if tmp.value ~= "both" and
148 tmp.value ~= "to" and 196 tmp.value ~= "to" and
149 tmp.value ~= "from" and 197 tmp.value ~= "from" and
150 tmp.value ~= "none" then 198 tmp.value ~= "none" then
151 return "bad-request"; 199 return {"cancel", "bad-request", "Subscription value must be both, to, from or none."};
152 end 200 end
153 end 201 end
154 202
155 if tmp.action ~= "deny" and tmp.action ~= "allow" then 203 if tmp.action ~= "deny" and tmp.action ~= "allow" then
156 return "bad-request"; 204 return {"cancel", "bad-request", "Action must be either deny or allow."};
157 end 205 end
158 206
159 list.items[#list.items + 1] = tmp; 207 list.items[#list.items + 1] = tmp;
160 end 208 end
161 209
170 iq:up(); 218 iq:up();
171 for resource, session in pairs(bare_sessions[bare_jid].sessions) do 219 for resource, session in pairs(bare_sessions[bare_jid].sessions) do
172 iq.attr.to = bare_jid.."/"..resource 220 iq.attr.to = bare_jid.."/"..resource
173 session.send(iq); 221 session.send(iq);
174 end 222 end
223 else
224 return {"cancel", "bad-request", "internal error."};
175 end 225 end
176 return true; 226 return true;
177 end 227 end
178 228
179 function getList(privacy_lists, origin, stanza, name) 229 function getList(privacy_lists, origin, stanza, name)
180 module:log("info", "User requests list named: %s", name or "nil"); 230 module:log("info", "User requests list named: %s", name or "nil");
181 local ret = false;
182 local reply = st.reply(stanza); 231 local reply = st.reply(stanza);
183 reply:tag("query", {xmlns="jabber:iq:privacy"}); 232 reply:tag("query", {xmlns="jabber:iq:privacy"});
184 233
185 if name == nil then 234 if name == nil then
186 reply:tag("active", {name=origin.activePrivacyList or ""}):up(); 235 reply:tag("active", {name=origin.activePrivacyList or ""}):up();
188 if privacy_lists.lists then 237 if privacy_lists.lists then
189 for _,list in ipairs(privacy_lists.lists) do 238 for _,list in ipairs(privacy_lists.lists) do
190 reply:tag("list", {name=list.name}):up(); 239 reply:tag("list", {name=list.name}):up();
191 end 240 end
192 end 241 end
193 ret = true;
194 else 242 else
195 local idx = findNamedList(privacy_lists, name); 243 local idx = findNamedList(privacy_lists, name);
196 module:log("debug", "list idx: %d", idx or -1); 244 module:log("debug", "list idx: %d", idx or -1);
197 if idx ~= nil then 245 if idx ~= nil then
198 list = privacy_lists.lists[idx]; 246 list = privacy_lists.lists[idx];
203 if item["iq"] then reply:tag("iq"):up(); end 251 if item["iq"] then reply:tag("iq"):up(); end
204 if item["presence-in"] then reply:tag("presence-in"):up(); end 252 if item["presence-in"] then reply:tag("presence-in"):up(); end
205 if item["presence-out"] then reply:tag("presence-out"):up(); end 253 if item["presence-out"] then reply:tag("presence-out"):up(); end
206 reply:up(); 254 reply:up();
207 end 255 end
208 ret = true; 256 else
209 end 257 return {"cancel", "item-not-found", "Unknown list specified."};
210 end 258 end
211 259 end
212 if ret then 260
213 origin.send(reply); 261 origin.send(reply);
214 end 262 return true;
215 return ret;
216 end 263 end
217 264
218 module:hook("iq/bare/jabber:iq:privacy:query", function(data) 265 module:hook("iq/bare/jabber:iq:privacy:query", function(data)
219 local origin, stanza = data.origin, data.stanza; 266 local origin, stanza = data.origin, data.stanza;
220 267
221 if stanza.attr.to == nil then -- only service requests to own bare JID 268 if stanza.attr.to == nil then -- only service requests to own bare JID
222 local err_reply = nil;
223 local query = stanza.tags[1]; -- the query element 269 local query = stanza.tags[1]; -- the query element
224 local valid = false; 270 local valid = false;
225 local privacy_lists = datamanager.load(origin.username, origin.host, "privacy") or {}; 271 local privacy_lists = datamanager.load(origin.username, origin.host, "privacy") or {};
226 272
227 if stanza.attr.type == "set" then 273 if stanza.attr.type == "set" then
230 if tag.name == "active" or tag.name == "default" then 276 if tag.name == "active" or tag.name == "default" then
231 if tag.attr.name == nil then -- Client declines the use of active / default list 277 if tag.attr.name == nil then -- Client declines the use of active / default list
232 valid = declineList(privacy_lists, origin, stanza, tag.name); 278 valid = declineList(privacy_lists, origin, stanza, tag.name);
233 else -- Client requests change of active / default list 279 else -- Client requests change of active / default list
234 valid = activateList(privacy_lists, origin, stanza, tag.name, tag.attr.name); 280 valid = activateList(privacy_lists, origin, stanza, tag.name, tag.attr.name);
235 if valid ~= true and valid ~= false then
236 err_reply = st.error_reply(stanza, "cancel", valid);
237 valid = false;
238 end
239 end 281 end
240 elseif tag.name == "list" and tag.attr.name then -- Client adds / edits a privacy list 282 elseif tag.name == "list" and tag.attr.name then -- Client adds / edits a privacy list
241 if #tag.tags == 0 then -- Client removes a privacy list 283 if #tag.tags == 0 then -- Client removes a privacy list
242 valid = deleteList(privacy_lists, origin, stanza, tag.attr.name); 284 valid = deleteList(privacy_lists, origin, stanza, tag.attr.name);
243 else -- Client edits a privacy list 285 else -- Client edits a privacy list
244 valid = createOrReplaceList(privacy_lists, origin, stanza, tag.attr.name, tag.tags); -- TODO check if used! 286 valid = createOrReplaceList(privacy_lists, origin, stanza, tag.attr.name, tag.tags); -- TODO check if used!
245 if valid ~= true and valid ~= false then
246 err_reply = st.error_reply(stanza, "cancel", valid);
247 valid = false;
248 end
249 end 287 end
250 end 288 end
251 end 289 end
252 end 290 end
253 elseif stanza.attr.type == "get" then 291 elseif stanza.attr.type == "get" then
261 end 299 end
262 end 300 end
263 end 301 end
264 if listsToRetrieve == 0 or listsToRetrieve == 1 then 302 if listsToRetrieve == 0 or listsToRetrieve == 1 then
265 valid = getList(privacy_lists, origin, stanza, name); 303 valid = getList(privacy_lists, origin, stanza, name);
266 err_reply = st.error_reply(stanza, "cancel", "item-not-found"); 304 end
267 end 305 end
268 end 306
269 307 if valid ~= true then
270 if valid == false then 308 if valid[0] == nil then
271 if err_reply == nil then 309 valid[0] = "cancel";
272 err_reply = st.error_reply(stanza, "modify", "bad-request"); 310 end
273 end 311 if valid[1] == nil then
274 origin.send(err_reply); 312 valid[1] = "bad-request";
313 end
314 origin.send(st.error_reply(stanza, valid[0], valid[1], valid[2]));
275 else 315 else
276 datamanager.store(origin.username, origin.host, "privacy", privacy_lists); 316 datamanager.store(origin.username, origin.host, "privacy", privacy_lists);
277 end 317 end
278 return true; 318 return true;
279 end 319 end