Software / code / prosody
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; |