Merge 0.10->trunk
[prosody.git] / plugins / muc / muc.lib.lua
index 75caa233938f49d627df9aefae1c84d2d67935f7..8fec0ffca557ba63a0ede668a67a9db4640ab1c4 100644 (file)
@@ -187,15 +187,15 @@ end
 -- Takes the x element that goes into the stanzas
 function room_mt:publicise_occupant_status(occupant, base_x, nick, actor, reason)
        -- Build real jid and (optionally) occupant jid template presences
-       local base_presence;
-       if occupant.role ~= nil then
+       local base_presence do
                -- Try to use main jid's presence
                local pr = occupant:get_presence();
-               if pr ~= nil then
+               if pr and (pr.attr.type ~= "unavailable" or occupant.role == nil) then
                        base_presence = st.clone(pr);
+               else -- user is leaving but didn't send a leave presence. make one for them
+                       base_presence = st.presence {from = occupant.nick; type = "unavailable";};
                end
        end
-       base_presence = base_presence or st.presence {from = occupant.nick; type = "unavailable";};
 
        -- Fire event (before full_p and anon_p are created)
        local event = {
@@ -546,7 +546,7 @@ function room_mt:handle_iq_to_occupant(origin, stanza)
        if (type == "error" or type == "result") then
                do -- deconstruct_stanza_id
                        if not occupant then return nil; end
-                       local from_jid, id, to_jid_hash = (base64.decode(stanza.attr.id) or ""):match("^(.+)%z(.*)%z(.+)$");
+                       local from_jid, id, to_jid_hash = (base64.decode(stanza.attr.id) or ""):match("^(%Z+)%z(%Z*)%z(.+)$");
                        if not(from == from_jid or from == jid_bare(from_jid)) then return nil; end
                        local from_occupant_jid = self:get_occupant_jid(from_jid);
                        if from_occupant_jid == nil then return nil; end
@@ -644,11 +644,11 @@ function room_mt:process_form(origin, stanza)
        if form.attr.type == "cancel" then
                origin.send(st.reply(stanza));
        elseif form.attr.type == "submit" then
-               local fields;
+               local fields, errors, present;
                if form.tags[1] == nil then -- Instant room
-                       fields = {};
+                       fields, present = {}, {};
                else
-                       fields = self:get_form_layout(stanza.attr.from):data(form);
+                       fields, errors, present = self:get_form_layout(stanza.attr.from):data(form);
                        if fields.FORM_TYPE ~= "http://jabber.org/protocol/muc#roomconfig" then
                                origin.send(st.error_reply(stanza, "cancel", "bad-request", "Form is not of type room configuration"));
                                return true;
@@ -666,6 +666,11 @@ function room_mt:process_form(origin, stanza)
                        return true;
                end
                module:fire_event("muc-config-submitted", event);
+               for submitted_field in pairs(present) do
+                       event.field, event.value = submitted_field, fields[submitted_field];
+                       module:fire_event("muc-config-submitted/"..submitted_field, event);
+               end
+               event.field, event.value = nil, nil;
 
                if self.save then self:save(true); end
                origin.send(st.reply(stanza));
@@ -723,6 +728,9 @@ end
 
 function room_mt:handle_admin_query_set_command(origin, stanza)
        local item = stanza.tags[1].tags[1];
+       if not item then
+               origin.send(st.error_reply(stanza, "cancel", "bad-request"));
+       end
        if item.attr.jid then -- Validate provided JID
                item.attr.jid = jid_prep(item.attr.jid);
                if not item.attr.jid then
@@ -747,8 +755,11 @@ function room_mt:handle_admin_query_set_command(origin, stanza)
        else
                success, errtype, err = nil, "cancel", "bad-request";
        end
-       if not success then origin.send(st.error_reply(stanza, errtype, err)); end
-       origin.send(st.reply(stanza));
+       if not success then
+               origin.send(st.error_reply(stanza, errtype, err));
+       else
+               origin.send(st.reply(stanza));
+       end
        return true;
 end
 
@@ -762,7 +773,7 @@ function room_mt:handle_admin_query_get_command(origin, stanza)
        if _aff and _aff_rank and not _rol then
                -- You need to be at least an admin, and be requesting info about your affifiliation or lower
                -- e.g. an admin can't ask for a list of owners
-               local affiliation_rank = valid_affiliations[affiliation];
+               local affiliation_rank = valid_affiliations[affiliation or "none"];
                if affiliation_rank >= valid_affiliations.admin and affiliation_rank >= _aff_rank then
                        local reply = st.reply(stanza):query("http://jabber.org/protocol/muc#admin");
                        for jid in self:each_affiliation(_aff or "none") do
@@ -1146,7 +1157,7 @@ function room_mt:set_role(actor, occupant_jid, role, reason)
        else
                -- Can't do anything to other owners or admins
                local occupant_affiliation = self:get_affiliation(occupant.bare_jid);
-               if occupant_affiliation == "owner" and occupant_affiliation == "admin" then
+               if occupant_affiliation == "owner" or occupant_affiliation == "admin" then
                        return nil, "cancel", "not-allowed";
                end
 
@@ -1178,58 +1189,10 @@ function room_mt:set_role(actor, occupant_jid, role, reason)
        return true;
 end
 
-local affiliation_notify = module:require "muc/affiliation_notify";
-
-local name = module:require "muc/name";
-room_mt.get_name = name.get;
-room_mt.set_name = name.set;
-
-local description = module:require "muc/description";
-room_mt.get_description = description.get;
-room_mt.set_description = description.set;
-
-local hidden = module:require "muc/hidden";
-room_mt.get_hidden = hidden.get;
-room_mt.set_hidden = hidden.set;
-function room_mt:get_public()
-       return not self:get_hidden();
-end
-function room_mt:set_public(public)
-       return self:set_hidden(not public);
-end
-
-local password = module:require "muc/password";
-room_mt.get_password = password.get;
-room_mt.set_password = password.set;
-
 local whois = module:require "muc/whois";
 room_mt.get_whois = whois.get;
 room_mt.set_whois = whois.set;
 
-local members_only = module:require "muc/members_only";
-room_mt.get_members_only = members_only.get;
-room_mt.set_members_only = members_only.set;
-
-local moderated = module:require "muc/moderated";
-room_mt.get_moderated = moderated.get;
-room_mt.set_moderated = moderated.set;
-
-local persistent = module:require "muc/persistent";
-room_mt.get_persistent = persistent.get;
-room_mt.set_persistent = persistent.set;
-
-local subject = module:require "muc/subject";
-room_mt.get_changesubject = subject.get_changesubject;
-room_mt.set_changesubject = subject.set_changesubject;
-room_mt.get_subject = subject.get;
-room_mt.set_subject = subject.set;
-room_mt.send_subject = subject.send;
-
-local history = module:require "muc/history";
-room_mt.send_history = history.send;
-room_mt.get_historylength = history.get_length;
-room_mt.set_historylength = history.set_length;
-
 local _M = {}; -- module "muc"
 
 function _M.new_room(jid, config)