mod_storage_sql: Initial commit of new SQL data driver.
[prosody.git] / plugins / muc / muc.lib.lua
index d89f3efe0464974efdd11f09c178dc4e401ff6d8..f3e2dd5285385e4482da16b0e0bd2ba5f800fae0 100644 (file)
@@ -613,12 +613,12 @@ function room_mt:process_form(origin, stanza)
        local dirty = false
 
        local name = fields['muc#roomconfig_roomname'];
-       if name then
+       if name ~= self:get_name() then
                self:set_name(name);
        end
 
        local description = fields['muc#roomconfig_roomdesc'];
-       if description then
+       if description ~= self:get_description() then
                self:set_description(description);
        end
 
@@ -911,15 +911,13 @@ function room_mt:set_affiliation(actor, jid, affiliation, callback, reason)
        if jid_bare(actor) == jid then return nil, "cancel", "not-allowed"; end
        self._affiliations[jid] = affiliation;
        local role = self:get_default_role(affiliation);
-       local p = st.presence()
-               :tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
+       local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"})
                        :tag("item", {affiliation=affiliation or "none", role=role or "none"})
                                :tag("reason"):text(reason or ""):up()
                        :up();
-       local x = p.tags[1];
-       local item = x.tags[1];
+       local presence_type = nil;
        if not role then -- getting kicked
-               p.attr.type = "unavailable";
+               presence_type = "unavailable";
                if affiliation == "outcast" then
                        x:tag("status", {code="301"}):up(); -- banned
                else
@@ -929,23 +927,28 @@ function room_mt:set_affiliation(actor, jid, affiliation, callback, reason)
        local modified_nicks = {};
        for nick, occupant in pairs(self._occupants) do
                if jid_bare(occupant.jid) == jid then
-                       t_insert(modified_nicks, nick);
                        if not role then -- getting kicked
                                self._occupants[nick] = nil;
                        else
                                occupant.affiliation, occupant.role = affiliation, role;
                        end
-                       p.attr.from = nick;
-                       for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick
+                       for jid,pres in pairs(occupant.sessions) do -- remove for all sessions of the nick
                                if not role then self._jid_nick[jid] = nil; end
+                               local p = st.clone(pres);
+                               p.attr.from = nick;
+                               p.attr.type = presence_type;
                                p.attr.to = jid;
+                               p:add_child(x);
                                self:_route_stanza(p);
+                               if occupant.jid == jid then
+                                       modified_nicks[nick] = p;
+                               end
                        end
                end
        end
        if self.save then self:save(); end
        if callback then callback(); end
-       for _, nick in ipairs(modified_nicks) do
+       for nick,p in pairs(modified_nicks) do
                p.attr.from = nick;
                self:broadcast_except_nick(p, nick);
        end
@@ -979,27 +982,37 @@ function room_mt:set_role(actor, occupant_jid, role, callback, reason)
        local allowed, err_type, err_condition = self:can_set_role(actor, occupant_jid, role);
        if not allowed then return allowed, err_type, err_condition; end
        local occupant = self._occupants[occupant_jid];
-       local p = st.presence({from = occupant_jid})
-               :tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
+       local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"})
                        :tag("item", {affiliation=occupant.affiliation or "none", nick=select(3, jid_split(occupant_jid)), role=role or "none"})
                                :tag("reason"):text(reason or ""):up()
                        :up();
+       local presence_type = nil;
        if not role then -- kick
-               p.attr.type = "unavailable";
+               presence_type = "unavailable";
                self._occupants[occupant_jid] = nil;
                for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick
                        self._jid_nick[jid] = nil;
                end
-               p:tag("status", {code = "307"}):up();
+               x:tag("status", {code = "307"}):up();
        else
                occupant.role = role;
        end
-       for jid in pairs(occupant.sessions) do -- send to all sessions of the nick
+       local bp;
+       for jid,pres in pairs(occupant.sessions) do -- send to all sessions of the nick
+               local p = st.clone(pres);
+               p.attr.from = occupant_jid;
+               p.attr.type = presence_type;
                p.attr.to = jid;
+               p:add_child(x);
                self:_route_stanza(p);
+               if occupant.jid == jid then
+                       bp = p;
+               end
        end
        if callback then callback(); end
-       self:broadcast_except_nick(p, occupant_jid);
+       if bp then
+               self:broadcast_except_nick(bp, occupant_jid);
+       end
        return true;
 end