3 local function log(type, message)
4 mainlog(type, "rostermanager", message);
7 local setmetatable = setmetatable;
8 local format = string.format;
9 local loadfile, setfenv, pcall = loadfile, setfenv, pcall;
10 local pairs, ipairs = pairs, ipairs;
14 require "util.datamanager"
16 local datamanager = datamanager;
17 local st = require "util.stanza";
19 module "rostermanager"
21 function add_to_roster(session, jid, item)
22 if session.roster then
23 local old_item = session.roster[jid];
24 session.roster[jid] = item;
25 if save_roster(session.username, session.host) then
28 session.roster[jid] = old_item;
29 return nil, "wait", "internal-server-error", "Unable to save roster";
32 return nil, "auth", "not-authorized", "Session's roster not loaded";
36 function remove_from_roster(session, jid)
37 if session.roster then
38 local old_item = session.roster[jid];
39 session.roster[jid] = nil;
40 if save_roster(session.username, session.host) then
43 session.roster[jid] = old_item;
44 return nil, "wait", "internal-server-error", "Unable to save roster";
47 return nil, "auth", "not-authorized", "Session's roster not loaded";
51 function roster_push(username, host, jid)
52 if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
53 local item = hosts[host].sessions[username].roster[jid];
54 local stanza = st.iq({type="set"});
55 stanza:tag("query", {xmlns = "jabber:iq:roster"});
57 stanza:tag("item", {jid = jid, subscription = item.subscription, name = item.name, ask = item.ask});
58 for group in pairs(item.groups) do
59 stanza:tag("group"):text(group):up();
62 stanza:tag("item", {jid = jid, subscription = "remove"});
67 for _, session in pairs(hosts[host].sessions[username].sessions) do
68 if session.interested then
69 -- FIXME do we need to set stanza.attr.to?
76 function load_roster(username, host)
77 if hosts[host] and hosts[host].sessions[username] then
78 local roster = hosts[host].sessions[username].roster;
80 roster = datamanager.load(username, host, "roster") or {};
81 hosts[host].sessions[username].roster = roster;
85 -- Attempt to load roster for non-loaded user
86 return datamanager.load(username, host, "roster") or {};
89 function save_roster(username, host)
90 if hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster then
91 return datamanager.store(username, host, "roster", hosts[host].sessions[username].roster);
96 function process_inbound_subscription_approval(username, host, jid)
97 local roster = load_roster(username, host);
98 local item = roster[jid];
99 if item and item.ask and (item.subscription == "none" or item.subscription == "from") then
100 if item.subscription == "none" then
101 item.subscription = "to";
103 item.subscription = "both";
106 return datamanager.store(username, host, "roster", roster);
110 function process_inbound_subscription_cancellation(username, host, jid)
111 local roster = load_roster(username, host);
112 local item = roster[jid];
113 if item and (item.subscription == "to" or item.subscription == "both") then
114 if item.subscription == "to" then
115 item.subscription = "none";
117 item.subscription = "from";
119 -- FIXME do we need to item.ask = nil;?
120 return datamanager.store(username, host, "roster", roster);
124 function process_inbound_unsubscribe(username, host, jid)
125 local roster = load_roster(username, host);
126 local item = roster[jid];
127 if item and (item.subscription == "from" or item.subscription == "both") then
128 if item.subscription == "from" then
129 item.subscription = "none";
131 item.subscription = "to";
134 return datamanager.store(username, host, "roster", roster);
138 function is_contact_subscribed(username, host, jid)
139 local roster = load_roster(username, host);
140 local item = roster[jid];
141 return item and (item.subscription == "from" or item.subscription == "both");