Comparison

plugins/muc/muc.lib.lua @ 6095:7900ebc544ce

plugins/muc/muc.lib: Split out the room iq handler into functions
author daurnimator <quae@daurnimator.com>
date Fri, 21 Feb 2014 15:48:26 -0500
parent 6094:db2faeb151b6
child 6096:84f9123637d4
comparison
equal deleted inserted replaced
6094:db2faeb151b6 6095:7900ebc544ce
852 end 852 end
853 self:set_persistent(false); 853 self:set_persistent(false);
854 module:fire_event("muc-room-destroyed", { room = self }); 854 module:fire_event("muc-room-destroyed", { room = self });
855 end 855 end
856 856
857 function room_mt:handle_admin_item_set_command(origin, stanza)
858 local item = stanza.tags[1].tags[1];
859 if item.attr.jid then -- Validate provided JID
860 item.attr.jid = jid_prep(item.attr.jid);
861 if not item.attr.jid then
862 origin.send(st.error_reply(stanza, "modify", "jid-malformed"));
863 return true;
864 end
865 end
866 if not item.attr.jid and item.attr.nick then -- COMPAT Workaround for Miranda sending 'nick' instead of 'jid' when changing affiliation
867 local occupant = self._occupants[self.jid.."/"..item.attr.nick];
868 if occupant then item.attr.jid = occupant.jid; end
869 elseif not item.attr.nick and item.attr.jid then
870 local nick = self._jid_nick[item.attr.jid];
871 if nick then item.attr.nick = select(3, jid_split(nick)); end
872 end
873 local actor = stanza.attr.from;
874 local callback = function() origin.send(st.reply(stanza)); end
875 local reason = item.tags[1] and item.tags[1].name == "reason" and #item.tags[1] == 1 and item.tags[1][1];
876 if item.attr.affiliation and item.attr.jid and not item.attr.role then
877 local success, errtype, err = self:set_affiliation(actor, item.attr.jid, item.attr.affiliation, callback, reason);
878 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
879 return true;
880 elseif item.attr.role and item.attr.nick and not item.attr.affiliation then
881 local success, errtype, err = self:set_role(actor, self.jid.."/"..item.attr.nick, item.attr.role, callback, reason);
882 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
883 return true;
884 else
885 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
886 return true;
887 end
888 end
889
890 function room_mt:handle_admin_item_get_command(origin, stanza)
891 local actor = stanza.attr.from;
892 local affiliation = self:get_affiliation(actor);
893 local current_nick = self._jid_nick[actor];
894 local role = current_nick and self._occupants[current_nick].role or self:get_default_role(affiliation);
895 local item = stanza.tags[1].tags[1];
896 local _aff = item.attr.affiliation;
897 local _rol = item.attr.role;
898 if _aff and not _rol then
899 if affiliation == "owner" or (affiliation == "admin" and _aff ~= "owner" and _aff ~= "admin") then
900 local reply = st.reply(stanza):query("http://jabber.org/protocol/muc#admin");
901 for jid, affiliation in pairs(self._affiliations) do
902 if affiliation == _aff then
903 reply:tag("item", {affiliation = _aff, jid = jid}):up();
904 end
905 end
906 origin.send(reply);
907 return true;
908 else
909 origin.send(st.error_reply(stanza, "auth", "forbidden"));
910 return true;
911 end
912 elseif _rol and not _aff then
913 if role == "moderator" then
914 -- TODO allow admins and owners not in room? Provide read-only access to everyone who can see the participants anyway?
915 if _rol == "none" then _rol = nil; end
916 local reply = st.reply(stanza):query("http://jabber.org/protocol/muc#admin");
917 for occupant_jid, occupant in pairs(self._occupants) do
918 if occupant.role == _rol then
919 reply:tag("item", {
920 nick = select(3, jid_split(occupant_jid)),
921 role = _rol or "none",
922 affiliation = occupant.affiliation or "none",
923 jid = occupant.jid
924 }):up();
925 end
926 end
927 origin.send(reply);
928 return true;
929 else
930 origin.send(st.error_reply(stanza, "auth", "forbidden"));
931 return true;
932 end
933 else
934 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
935 return true;
936 end
937 end
938
939 function room_mt:handle_owner_query_get_to_room(origin, stanza)
940 if self:get_affiliation(stanza.attr.from) ~= "owner" then
941 origin.send(st.error_reply(stanza, "auth", "forbidden", "Only owners can configure rooms"));
942 return true;
943 end
944
945 self:send_form(origin, stanza);
946 return true;
947 end
948 function room_mt:handle_owner_query_set_to_room(origin, stanza)
949 if self:get_affiliation(stanza.attr.from) ~= "owner" then
950 origin.send(st.error_reply(stanza, "auth", "forbidden", "Only owners can configure rooms"));
951 return true;
952 end
953
954 local child = stanza.tags[1].tags[1];
955 if not child then
956 origin.send(st.error_reply(stanza, "modify", "bad-request"));
957 return true;
958 elseif child.name == "destroy" then
959 local newjid = child.attr.jid;
960 local reason, password;
961 for _,tag in ipairs(child.tags) do
962 if tag.name == "reason" then
963 reason = #tag.tags == 0 and tag[1];
964 elseif tag.name == "password" then
965 password = #tag.tags == 0 and tag[1];
966 end
967 end
968 self:destroy(newjid, reason, password);
969 origin.send(st.reply(stanza));
970 return true;
971 else
972 self:process_form(origin, stanza);
973 return true;
974 end
975 end
976
857 function room_mt:handle_iq_to_room(origin, stanza) 977 function room_mt:handle_iq_to_room(origin, stanza)
858 local type = stanza.attr.type; 978 local type = stanza.attr.type;
859 local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns; 979 local xmlns = stanza.tags[1] and stanza.tags[1].attr.xmlns;
860 if xmlns == "http://jabber.org/protocol/disco#info" and type == "get" and not stanza.tags[1].attr.node then 980 if xmlns == "http://jabber.org/protocol/disco#info" and type == "get" and not stanza.tags[1].attr.node then
861 origin.send(self:get_disco_info(stanza)); 981 origin.send(self:get_disco_info(stanza));
982 return true;
862 elseif xmlns == "http://jabber.org/protocol/disco#items" and type == "get" and not stanza.tags[1].attr.node then 983 elseif xmlns == "http://jabber.org/protocol/disco#items" and type == "get" and not stanza.tags[1].attr.node then
863 origin.send(self:get_disco_items(stanza)); 984 origin.send(self:get_disco_items(stanza));
985 return true;
864 elseif xmlns == "http://jabber.org/protocol/muc#admin" then 986 elseif xmlns == "http://jabber.org/protocol/muc#admin" then
865 local actor = stanza.attr.from;
866 local affiliation = self:get_affiliation(actor);
867 local current_nick = self._jid_nick[actor];
868 local role = current_nick and self._occupants[current_nick].role or self:get_default_role(affiliation);
869 local item = stanza.tags[1].tags[1]; 987 local item = stanza.tags[1].tags[1];
870 if item and item.name == "item" then 988 if item and item.name == "item" then
871 if type == "set" then 989 if type == "set" then
872 local callback = function() origin.send(st.reply(stanza)); end 990 return self:handle_admin_item_set_command(origin, stanza)
873 if item.attr.jid then -- Validate provided JID
874 item.attr.jid = jid_prep(item.attr.jid);
875 if not item.attr.jid then
876 origin.send(st.error_reply(stanza, "modify", "jid-malformed"));
877 return;
878 end
879 end
880 if not item.attr.jid and item.attr.nick then -- COMPAT Workaround for Miranda sending 'nick' instead of 'jid' when changing affiliation
881 local occupant = self._occupants[self.jid.."/"..item.attr.nick];
882 if occupant then item.attr.jid = occupant.jid; end
883 elseif not item.attr.nick and item.attr.jid then
884 local nick = self._jid_nick[item.attr.jid];
885 if nick then item.attr.nick = select(3, jid_split(nick)); end
886 end
887 local reason = item.tags[1] and item.tags[1].name == "reason" and #item.tags[1] == 1 and item.tags[1][1];
888 if item.attr.affiliation and item.attr.jid and not item.attr.role then
889 local success, errtype, err = self:set_affiliation(actor, item.attr.jid, item.attr.affiliation, callback, reason);
890 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
891 elseif item.attr.role and item.attr.nick and not item.attr.affiliation then
892 local success, errtype, err = self:set_role(actor, self.jid.."/"..item.attr.nick, item.attr.role, callback, reason);
893 if not success then origin.send(st.error_reply(stanza, errtype, err)); end
894 else
895 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
896 end
897 elseif type == "get" then 991 elseif type == "get" then
898 local _aff = item.attr.affiliation; 992 return self:handle_admin_item_get_command(origin, stanza)
899 local _rol = item.attr.role;
900 if _aff and not _rol then
901 if affiliation == "owner" or (affiliation == "admin" and _aff ~= "owner" and _aff ~= "admin") then
902 local reply = st.reply(stanza):query("http://jabber.org/protocol/muc#admin");
903 for jid, affiliation in pairs(self._affiliations) do
904 if affiliation == _aff then
905 reply:tag("item", {affiliation = _aff, jid = jid}):up();
906 end
907 end
908 origin.send(reply);
909 else
910 origin.send(st.error_reply(stanza, "auth", "forbidden"));
911 end
912 elseif _rol and not _aff then
913 if role == "moderator" then
914 -- TODO allow admins and owners not in room? Provide read-only access to everyone who can see the participants anyway?
915 if _rol == "none" then _rol = nil; end
916 local reply = st.reply(stanza):query("http://jabber.org/protocol/muc#admin");
917 for occupant_jid, occupant in pairs(self._occupants) do
918 if occupant.role == _rol then
919 reply:tag("item", {
920 nick = select(3, jid_split(occupant_jid)),
921 role = _rol or "none",
922 affiliation = occupant.affiliation or "none",
923 jid = occupant.jid
924 }):up();
925 end
926 end
927 origin.send(reply);
928 else
929 origin.send(st.error_reply(stanza, "auth", "forbidden"));
930 end
931 else
932 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
933 end
934 end 993 end
935 elseif type == "set" or type == "get" then 994 elseif type == "set" or type == "get" then
936 origin.send(st.error_reply(stanza, "cancel", "bad-request")); 995 origin.send(st.error_reply(stanza, "cancel", "bad-request"));
996 return true;
937 end 997 end
938 elseif xmlns == "http://jabber.org/protocol/muc#owner" and (type == "get" or type == "set") and stanza.tags[1].name == "query" then 998 elseif xmlns == "http://jabber.org/protocol/muc#owner" and (type == "get" or type == "set") and stanza.tags[1].name == "query" then
939 if self:get_affiliation(stanza.attr.from) ~= "owner" then 999 if stanza.attr.type == "get" then
940 origin.send(st.error_reply(stanza, "auth", "forbidden", "Only owners can configure rooms")); 1000 return self:handle_owner_query_get_to_room(origin, stanza)
941 elseif stanza.attr.type == "get" then
942 self:send_form(origin, stanza);
943 elseif stanza.attr.type == "set" then 1001 elseif stanza.attr.type == "set" then
944 local child = stanza.tags[1].tags[1]; 1002 return self:handle_owner_query_set_to_room(origin, stanza)
945 if not child then
946 origin.send(st.error_reply(stanza, "modify", "bad-request"));
947 elseif child.name == "destroy" then
948 local newjid = child.attr.jid;
949 local reason, password;
950 for _,tag in ipairs(child.tags) do
951 if tag.name == "reason" then
952 reason = #tag.tags == 0 and tag[1];
953 elseif tag.name == "password" then
954 password = #tag.tags == 0 and tag[1];
955 end
956 end
957 self:destroy(newjid, reason, password);
958 origin.send(st.reply(stanza));
959 else
960 self:process_form(origin, stanza);
961 end
962 end 1003 end
963 elseif type == "set" or type == "get" then 1004 elseif type == "set" or type == "get" then
964 origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); 1005 origin.send(st.error_reply(stanza, "cancel", "service-unavailable"));
1006 return true;
965 end 1007 end
966 end 1008 end
967 1009
968 function room_mt:handle_groupchat_to_room(origin, stanza) 1010 function room_mt:handle_groupchat_to_room(origin, stanza)
969 local from = stanza.attr.from; 1011 local from = stanza.attr.from;