Merge 0.9->0.10
authorMatthew Wild <mwild1@gmail.com>
Tue, 21 Jan 2014 03:24:40 +0000 (03:24 +0000)
committerMatthew Wild <mwild1@gmail.com>
Tue, 21 Jan 2014 03:24:40 +0000 (03:24 +0000)
1  2 
plugins/muc/mod_muc.lua
tools/ejabberd2prosody.lua

diff --combined plugins/muc/mod_muc.lua
index 7bb1d8b2df918a98247507f60ce54e31dcbd5a57,6e86ab730d0451c6369995edc1ecee78543f8619..c514bafd375b36e810ba3d9887e460f19984abee
@@@ -1,12 -1,11 +1,12 @@@
  -- Prosody IM
  -- Copyright (C) 2008-2010 Matthew Wild
  -- Copyright (C) 2008-2010 Waqas Hussain
 --- 
 +--
  -- This project is MIT/X11 licensed. Please see the
  -- COPYING file in the source package for more information.
  --
  
 +local array = require "util.array";
  
  if module:get_host_type() ~= "component" then
        error("MUC should be loaded as a component, please see http://prosody.im/doc/components", 0);
@@@ -17,15 -16,12 +17,15 @@@ local muc_name = module:get_option("nam
  if type(muc_name) ~= "string" then muc_name = "Prosody Chatrooms"; end
  local restrict_room_creation = module:get_option("restrict_room_creation");
  if restrict_room_creation then
 -      if restrict_room_creation == true then 
 +      if restrict_room_creation == true then
                restrict_room_creation = "admin";
        elseif restrict_room_creation ~= "admin" and restrict_room_creation ~= "local" then
                restrict_room_creation = nil;
        end
  end
 +local lock_rooms = module:get_option_boolean("muc_room_locking", false);
 +local lock_room_timeout = module:get_option_number("muc_room_lock_timeout", 300);
 +
  local muclib = module:require "muc";
  local muc_new_room = muclib.new_room;
  local jid_split = require "util.jid".split;
@@@ -44,17 -40,12 +44,17 @@@ local room_configs = module:open_store(
  -- Configurable options
  muclib.set_max_history_length(module:get_option_number("max_history_messages"));
  
 +module:depends("disco");
 +module:add_identity("conference", "text", muc_name);
 +module:add_feature("http://jabber.org/protocol/muc");
 +
  local function is_admin(jid)
        return um_is_admin(jid, module.host);
  end
  
 -local _set_affiliation = muc_new_room.room_mt.set_affiliation;
 -local _get_affiliation = muc_new_room.room_mt.get_affiliation;
 +room_mt = muclib.room_mt; -- Yes, global.
 +local _set_affiliation = room_mt.set_affiliation;
 +local _get_affiliation = room_mt.get_affiliation;
  function muclib.room_mt:get_affiliation(jid)
        if is_admin(jid) then return "owner"; end
        return _get_affiliation(self, jid);
@@@ -92,16 -83,6 +92,16 @@@ function create_room(jid
        room.route_stanza = room_route_stanza;
        room.save = room_save;
        rooms[jid] = room;
 +      if lock_rooms then
 +              room.locked = true;
 +              if lock_room_timeout and lock_room_timeout > 0 then
 +                      module:add_timer(lock_room_timeout, function ()
 +                              if room.locked then
 +                                      room:destroy(); -- Not unlocked in time
 +                              end
 +                      end);
 +              end
 +      end
        module:fire_event("muc-room-created", { room = room });
        return room;
  end
@@@ -126,15 -107,20 +126,15 @@@ local host_room = muc_new_room(muc_host
  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")
 -              :tag("identity", {category='conference', type='text', name=muc_name}):up()
 -              :tag("feature", {var="http://jabber.org/protocol/muc"}); -- TODO cache disco reply
 -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");
 +module:hook("host-disco-items", function(event)
 +      local reply = event.reply;
 +      module:log("debug", "host-disco-items called");
        for jid, room in pairs(rooms) do
 -              if not room:is_hidden() then
 +              if not room:get_hidden() then
                        reply:tag("item", {jid=jid, name=room:get_name()}):up();
                end
        end
 -      return reply; -- TODO cache disco reply
 -end
 +end);
  
  local function handle_to_domain(event)
        local origin, stanza = event.origin, event.stanza;
        if stanza.name == "iq" and type == "get" then
                local xmlns = stanza.tags[1].attr.xmlns;
                local node = stanza.tags[1].attr.node;
 -              if xmlns == "http://jabber.org/protocol/disco#info" and not node then
 -                      origin.send(get_disco_info(stanza));
 -              elseif xmlns == "http://jabber.org/protocol/disco#items" and not node then
 -                      origin.send(get_disco_items(stanza));
 -              elseif xmlns == "http://jabber.org/protocol/muc#unique" then
 +              if xmlns == "http://jabber.org/protocol/muc#unique" then
                        origin.send(st.reply(stanza):tag("unique", {xmlns = xmlns}):text(uuid_gen())); -- FIXME Random UUIDs can theoretically have collisions
                else
                        origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); -- TODO disco/etc
@@@ -173,6 -163,7 +173,7 @@@ function stanza_handler(event
        if room then
                room:handle_stanza(origin, stanza);
                if not next(room._occupants) and not persistent_rooms[room.jid] then -- empty, non-persistent room
+                       module:fire_event("muc-room-destroyed", { room = room });
                        rooms[bare] = nil; -- discard room
                end
        else
@@@ -229,8 -220,7 +230,8 @@@ function shutdown_component(
        if not saved then
                local stanza = st.presence({type = "unavailable"})
                        :tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
 -                              :tag("item", { affiliation='none', role='none' }):up();
 +                              :tag("item", { affiliation='none', role='none' }):up()
 +                              :tag("status", { code = "332"}):up();
                for roomjid, room in pairs(rooms) do
                        shutdown_room(room, stanza);
                end
  end
  module.unload = shutdown_component;
  module:hook_global("server-stopping", shutdown_component);
 +
 +-- Ad-hoc commands
 +module:depends("adhoc")
 +local t_concat = table.concat;
 +local keys = require "util.iterators".keys;
 +local adhoc_new = module:require "adhoc".new;
 +local adhoc_initial = require "util.adhoc".new_initial_data_form;
 +local dataforms_new = require "util.dataforms".new;
 +
 +local destroy_rooms_layout = dataforms_new {
 +      title = "Destroy rooms";
 +      instructions = "Select the rooms to destroy";
 +
 +      { name = "FORM_TYPE", type = "hidden", value = "http://prosody.im/protocol/muc#destroy" };
 +      { name = "rooms", type = "list-multi", required = true, label = "Rooms to destroy:"};
 +};
 +
 +local destroy_rooms_handler = adhoc_initial(destroy_rooms_layout, function()
 +      return { rooms = array.collect(keys(rooms)):sort() };
 +end, function(fields, errors)
 +      if errors then
 +              local errmsg = {};
 +              for name, err in pairs(errors) do
 +                      errmsg[#errmsg + 1] = name .. ": " .. err;
 +              end
 +              return { status = "completed", error = { message = t_concat(errmsg, "\n") } };
 +      end
 +      for _, room in ipairs(fields.rooms) do
 +              rooms[room]:destroy();
 +              rooms[room] = nil;
 +      end
 +      return { status = "completed", info = "The following rooms were destroyed:\n"..t_concat(fields.rooms, "\n") };
 +end);
 +local destroy_rooms_desc = adhoc_new("Destroy Rooms", "http://prosody.im/protocol/muc#destroy", destroy_rooms_handler, "admin");
 +
 +module:provides("adhoc", destroy_rooms_desc);
index 4bc15eb7bb8d6a04d2242b5d791aa73970d7ddbc,bc916fb874eba3625158b5f1c5615b4d9cc4789f..8297278fa7f5522c6bd03af9cc70210e24ee4c71
@@@ -2,7 -2,7 +2,7 @@@
  -- Prosody IM
  -- Copyright (C) 2008-2010 Matthew Wild
  -- Copyright (C) 2008-2010 Waqas Hussain
 --- 
 +--
  -- This project is MIT/X11 licensed. Please see the
  -- COPYING file in the source package for more information.
  --
@@@ -30,7 -30,7 +30,7 @@@ dm.set_data_path("data")
  
  function build_stanza(tuple, stanza)
        assert(type(tuple) == "table", "XML node is of unexpected type: "..type(tuple));
-       if tuple[1] == "xmlelement" then
+       if tuple[1] == "xmlelement" or tuple[1] == "xmlel" then
                assert(type(tuple[2]) == "string", "element name has type: "..type(tuple[2]));
                assert(type(tuple[3]) == "table", "element attribute array has type: "..type(tuple[3]));
                assert(type(tuple[4]) == "table", "element children array has type: "..type(tuple[4]));
@@@ -247,7 -247,7 +247,7 @@@ local filters = 
                end
                muc_room(tuple[2][1], tuple[2][2], properties);
        end;
-       config = function(tuple)
+       --[=[config = function(tuple)
                if tuple[2] == "hosts" then
                        local output = io.output(); io.output("prosody.cfg.lua");
                        io.write("-- Configuration imported from ejabberd --\n");
                        io.output(output);
                        print("prosody.cfg.lua created");
                end
-       end;
+       end;]=]
  };
  
  local arg = ...;