aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWaqas Hussain <waqas20@gmail.com>2009-09-07 20:51:59 +0500
committerWaqas Hussain <waqas20@gmail.com>2009-09-07 20:51:59 +0500
commit4db96d1b1f410f99994962c41e0ab1428f7b9027 (patch)
tree673146402c7e5bf16e129cfc54db28f60ce4fef0
parentb1fb12f87d545c8438753e0867fb6172b0050e31 (diff)
downloadprosody-4db96d1b1f410f99994962c41e0ab1428f7b9027.tar.gz
prosody-4db96d1b1f410f99994962c41e0ab1428f7b9027.zip
MUC: Added support for room configuration forms, persistence and hidden rooms.
-rw-r--r--plugins/muc/mod_muc.lua51
-rw-r--r--plugins/muc/muc.lib.lua53
2 files changed, 100 insertions, 4 deletions
diff --git a/plugins/muc/mod_muc.lua b/plugins/muc/mod_muc.lua
index c61ac238..41c8a749 100644
--- a/plugins/muc/mod_muc.lua
+++ b/plugins/muc/mod_muc.lua
@@ -21,11 +21,50 @@ local deregister_component = require "core.componentmanager".deregister_componen
local jid_split = require "util.jid".split;
local st = require "util.stanza";
local uuid_gen = require "util.uuid".generate;
+local datamanager = require "util.datamanager";
local rooms = {};
+local persistent_rooms = datamanager.load(nil, muc_host, "persistent") or {};
local component;
+
+local function room_route_stanza(room, stanza) core_post_stanza(component, stanza); end
+local function room_save(room, forced)
+ local node = jid_split(room.jid);
+ persistent_rooms[room.jid] = room._data.persistent;
+ module:log("debug", "1, %s, %s", room.jid, tostring(room._data.persistent));
+ if room._data.persistent then
+ module:log("debug", "2");
+ local history = room._data.history;
+ room._data.history = nil;
+ local data = {
+ jid = room.jid;
+ _data = room._data;
+ _affiliations = room._affiliations;
+ };
+ datamanager.store(node, muc_host, "config", data);
+ room._data.history = history;
+ elseif forced then
+ module:log("debug", "3");
+ datamanager.store(node, muc_host, "config", nil);
+ end
+ module:log("debug", "4");
+ if forced then datamanager.store(nil, muc_host, "persistent", persistent_rooms); end
+end
+
+for jid in pairs(persistent_rooms) do
+ local node = jid_split(jid);
+ local data = datamanager.load(node, muc_host, "config") or {};
+ local room = muc_new_room(jid);
+ room._data = data._data;
+ room._affiliations = data._affiliations;
+ room.route_stanza = room_route_stanza;
+ room.save = room_save;
+ rooms[jid] = room;
+end
+
local host_room = muc_new_room(muc_host);
-host_room.route_stanza = function(room, stanza) core_post_stanza(component, stanza); end;
+host_room.route_stanza = room_route_stanza;
+host_room.save = room_save;
local function get_disco_info(stanza)
return st.iq({type='result', id=stanza.attr.id, from=muc_host, to=stanza.attr.from}):query("http://jabber.org/protocol/disco#info")
@@ -35,7 +74,9 @@ end
local function get_disco_items(stanza)
local reply = st.iq({type='result', id=stanza.attr.id, from=muc_host, to=stanza.attr.from}):query("http://jabber.org/protocol/disco#items");
for jid, room in pairs(rooms) do
- reply:tag("item", {jid=jid, name=jid}):up();
+ if not room._data.hidden then
+ reply:tag("item", {jid=jid, name=jid}):up();
+ end
end
return reply; -- TODO cache disco reply
end
@@ -68,7 +109,8 @@ component = register_component(muc_host, function(origin, stanza)
local room = rooms[bare];
if not room then
room = muc_new_room(bare);
- room.route_stanza = function(room, stanza) core_post_stanza(component, stanza); end;
+ room.route_stanza = room_route_stanza;
+ room.save = room_save;
rooms[bare] = room;
end
room:handle_stanza(origin, stanza);
@@ -95,7 +137,8 @@ module.restore = function(data)
room._occupants = oldroom._occupants;
room._data = oldroom._data;
room._affiliations = oldroom._affiliations;
- room.route_stanza = function(room, stanza) core_post_stanza(component, stanza); end;
+ room.route_stanza = room_route_stanza;
+ room.save = room_save;
rooms[jid] = room;
end
prosody.hosts[module:get_host()].muc = { rooms = rooms };
diff --git a/plugins/muc/muc.lib.lua b/plugins/muc/muc.lib.lua
index b0d2b73d..0d7e2581 100644
--- a/plugins/muc/muc.lib.lua
+++ b/plugins/muc/muc.lib.lua
@@ -190,6 +190,7 @@ function room_mt:set_subject(current_nick, subject)
-- TODO check nick's authority
if subject == "" then subject = nil; end
self._data['subject'] = subject;
+ if self.save then self:save(); end
local msg = st.message({type='groupchat', from=current_nick})
:tag('subject'):text(subject):up();
self:broadcast_message(msg, false);
@@ -307,6 +308,53 @@ function room_mt:handle_to_occupant(origin, stanza) -- PM, vCards, etc
end
end
+function room_mt:handle_form(origin, stanza)
+ if self:get_affiliation(stanza.attr.from) ~= "owner" then origin.send(st.error_reply(nil, "auth", "forbidden")); return; end
+ if stanza.attr.type == "get" then
+ local title = "Configuration for "..self.jid;
+ origin.send(st.reply(stanza):query("http://jabber.org/protocol/muc#owner")
+ :tag("x", {xmlns='jabber:x:data', type='form'})
+ :tag("title"):text(title):up()
+ :tag("instructions"):text(title):up()
+ :tag("field", {type='hidden', var='FORM_TYPE'}):tag("value"):text("http://jabber.org/protocol/muc#roomconfig"):up():up()
+ :tag("field", {type='boolean', label='Make Room Persistent?', var='muc#roomconfig_persistentroom'})
+ :tag("value"):text(self._data.persistent and "1" or "0"):up()
+ :up()
+ :tag("field", {type='boolean', label='Make Room Publicly Searchable?', var='muc#roomconfig_publicroom'})
+ :tag("value"):text(self._data.hidden and "0" or "1"):up()
+ :up()
+ );
+ elseif stanza.attr.type == "set" then
+ local query = stanza.tags[1];
+ local form;
+ for _, tag in ipairs(query.tags) do if tag.name == "x" and tag.attr.xmlns == "jabber:x:data" then form = tag; break; end end
+ if not form then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); return; end
+ if form.attr.type == "cancel" then origin.send(st.reply(stanza)); return; end
+ if form.attr.type ~= "submit" then origin.send(st.error_reply(stanza, "cancel", "bad-request")); return; end
+ local fields = {};
+ for _, field in pairs(form.tags) do
+ if field.name == "field" and field.attr.var and field.tags[1].name == "value" and #field.tags[1].tags == 0 then
+ fields[field.attr.var] = field.tags[1][1] or "";
+ end
+ end
+ if fields.FORM_TYPE ~= "http://jabber.org/protocol/muc#roomconfig" then origin.send(st.error_reply(stanza, "cancel", "bad-request")); return; end
+
+ local persistent = fields['muc#roomconfig_persistentroom'];
+ if persistent == "0" or persistent == "false" then persistent = nil; elseif persistent == "1" or persistent == "true" then persistent = true;
+ else origin.send(st.error_reply(stanza, "cancel", "bad-request")); return; end
+ self._data.persistent = persistent;
+ module:log("debug", "persistent=%s", tostring(persistent));
+
+ local public = fields['muc#roomconfig_publicroom'];
+ if public == "0" or public == "false" then public = nil; elseif public == "1" or public == "true" then public = true;
+ else origin.send(st.error_reply(stanza, "cancel", "bad-request")); return; end
+ self._data.hidden = not public and true or nil;
+
+ if self.save then self:save(true); end
+ origin.send(st.reply(stanza));
+ end
+end
+
function room_mt:handle_to_room(origin, stanza) -- presence changes and groupchat messages, along with disco/etc
local type = stanza.attr.type;
local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns;
@@ -373,6 +421,10 @@ function room_mt:handle_to_room(origin, stanza) -- presence changes and groupcha
elseif type == "set" or type == "get" then
origin.send(st.error_reply(stanza, "cancel", "bad-request"));
end
+ elseif xmlns == "http://jabber.org/protocol/muc#owner" and (type == "get" or type == "set") and stanza.tags[1].name == "query" then
+ self:handle_form(origin, stanza);
+ elseif type == "set" or type == "get" then
+ origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
end
elseif stanza.name == "message" and type == "groupchat" then
local from, to = stanza.attr.from, stanza.attr.to;
@@ -474,6 +526,7 @@ function room_mt:set_affiliation(actor, jid, affiliation, callback)
end
end
end
+ if room.save then room:save(); end
if callback then callback(); end
for _, nick in ipairs(modified_nicks) do
p.attr.from = nick;