Software /
code /
prosody
Comparison
plugins/muc/muc.lib.lua @ 8842:463505cc75d5
MUC: Revert unstable MUC commits since 0.10.1
These have caused too many issue reports to be included in
the stable branch at this time.
Affected issues: #345, #397
Reverted commits:
dcd53a565c01
6d4b0895f76d
1b10802a770e
564e897f0790
a7221ada9368
aaff40ec7001
05a3275b6873
c2b99fa134b3
8da11142fabf
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 30 May 2018 21:33:53 +0100 |
parent | 8839:dcd53a565c01 |
child | 8843:041ddc670934 |
child | 8887:c47f220580fd |
comparison
equal
deleted
inserted
replaced
8841:bc8558bbc797 | 8842:463505cc75d5 |
---|---|
169 | 169 |
170 local maxchars = history_tag and tonumber(history_tag.attr.maxchars); | 170 local maxchars = history_tag and tonumber(history_tag.attr.maxchars); |
171 if maxchars then maxchars = math.floor(maxchars); end | 171 if maxchars then maxchars = math.floor(maxchars); end |
172 | 172 |
173 local maxstanzas = math.floor(history_tag and tonumber(history_tag.attr.maxstanzas) or #history); | 173 local maxstanzas = math.floor(history_tag and tonumber(history_tag.attr.maxstanzas) or #history); |
174 if not history_tag then maxstanzas = self._data.default_history_messages; end | 174 if not history_tag then maxstanzas = 20; end |
175 | 175 |
176 local seconds = history_tag and tonumber(history_tag.attr.seconds); | 176 local seconds = history_tag and tonumber(history_tag.attr.seconds); |
177 if seconds then seconds = datetime.datetime(os.time() - math.floor(seconds)); end | 177 if seconds then seconds = datetime.datetime(os.time() - math.floor(seconds)); end |
178 | 178 |
179 local since = history_tag and history_tag.attr.since; | 179 local since = history_tag and history_tag.attr.since; |
356 if length == default_history_length then | 356 if length == default_history_length then |
357 length = nil; | 357 length = nil; |
358 end | 358 end |
359 self._data.history_length = length; | 359 self._data.history_length = length; |
360 end | 360 end |
361 | |
362 -- Fix for clients who don't support XEP-0045 correctly | |
363 -- Default number of history messages the room returns | |
364 function room_mt:get_defaulthistorymessages() | |
365 return self._data.default_history_messages or default_history_length; | |
366 end | |
367 function room_mt:set_defaulthistorymessages(number) | |
368 number = math.min(tonumber(number) or default_history_length, self._data.history_length or default_history_length); | |
369 if number == default_history_length then | |
370 number = nil; | |
371 end | |
372 self._data.default_history_messages = number; | |
373 end | |
374 | |
375 | 361 |
376 | 362 |
377 local valid_whois = { moderators = true, anyone = true }; | 363 local valid_whois = { moderators = true, anyone = true }; |
378 | 364 |
379 function room_mt:set_whois(whois) | 365 function room_mt:set_whois(whois) |
710 { | 696 { |
711 name = 'muc#roomconfig_historylength', | 697 name = 'muc#roomconfig_historylength', |
712 type = 'text-single', | 698 type = 'text-single', |
713 label = 'Maximum Number of History Messages Returned by Room', | 699 label = 'Maximum Number of History Messages Returned by Room', |
714 value = tostring(self:get_historylength()) | 700 value = tostring(self:get_historylength()) |
715 }, | |
716 { | |
717 name = 'muc#roomconfig_defaulthistorymessages', | |
718 type = 'text-single', | |
719 label = 'Default Number of History Messages Returned by Room', | |
720 value = tostring(self:get_defaulthistorymessages()) | |
721 } | 701 } |
722 }); | 702 }); |
723 return module:fire_event("muc-config-form", { room = self, actor = actor, form = form }) or form; | 703 return module:fire_event("muc-config-form", { room = self, actor = actor, form = form }) or form; |
724 end | 704 end |
725 | 705 |
764 handle_option("moderated", "muc#roomconfig_moderatedroom"); | 744 handle_option("moderated", "muc#roomconfig_moderatedroom"); |
765 handle_option("members_only", "muc#roomconfig_membersonly"); | 745 handle_option("members_only", "muc#roomconfig_membersonly"); |
766 handle_option("public", "muc#roomconfig_publicroom"); | 746 handle_option("public", "muc#roomconfig_publicroom"); |
767 handle_option("changesubject", "muc#roomconfig_changesubject"); | 747 handle_option("changesubject", "muc#roomconfig_changesubject"); |
768 handle_option("historylength", "muc#roomconfig_historylength"); | 748 handle_option("historylength", "muc#roomconfig_historylength"); |
769 handle_option("defaulthistorymessages", "muc#roomconfig_defaulthistorymessages"); | |
770 handle_option("whois", "muc#roomconfig_whois", valid_whois); | 749 handle_option("whois", "muc#roomconfig_whois", valid_whois); |
771 handle_option("password", "muc#roomconfig_roomsecret"); | 750 handle_option("password", "muc#roomconfig_roomsecret"); |
772 | 751 |
773 if self.save then self:save(true); end | 752 if self.save then self:save(true); end |
774 if self.locked then | 753 if self.locked then |
821 elseif xmlns == "http://jabber.org/protocol/muc#admin" then | 800 elseif xmlns == "http://jabber.org/protocol/muc#admin" then |
822 local actor = stanza.attr.from; | 801 local actor = stanza.attr.from; |
823 local affiliation = self:get_affiliation(actor); | 802 local affiliation = self:get_affiliation(actor); |
824 local current_nick = self._jid_nick[actor]; | 803 local current_nick = self._jid_nick[actor]; |
825 local role = current_nick and self._occupants[current_nick].role or self:get_default_role(affiliation); | 804 local role = current_nick and self._occupants[current_nick].role or self:get_default_role(affiliation); |
826 if type == "set" then | 805 local item = stanza.tags[1].tags[1]; |
827 local at_least_one_item_provided = false; | 806 if item and item.name == "item" then |
828 local callback = function() origin.send(st.reply(stanza)); end | 807 if type == "set" then |
829 | 808 local callback = function() origin.send(st.reply(stanza)); end |
830 -- Gather all changes to affiliations and roles | |
831 local jid_affiliation = {}; | |
832 local jidnick_role = {}; | |
833 for item in stanza.tags[1]:childtags("item") do | |
834 at_least_one_item_provided = true; | |
835 | |
836 if item.attr.jid then -- Validate provided JID | 809 if item.attr.jid then -- Validate provided JID |
837 item.attr.jid = jid_prep(item.attr.jid); | 810 item.attr.jid = jid_prep(item.attr.jid); |
838 if not item.attr.jid then | 811 if not item.attr.jid then |
839 origin.send(st.error_reply(stanza, "modify", "jid-malformed")); | 812 origin.send(st.error_reply(stanza, "modify", "jid-malformed")); |
840 return; | 813 return; |
845 if occupant then item.attr.jid = occupant.jid; end | 818 if occupant then item.attr.jid = occupant.jid; end |
846 elseif not item.attr.nick and item.attr.jid then | 819 elseif not item.attr.nick and item.attr.jid then |
847 local nick = self._jid_nick[item.attr.jid]; | 820 local nick = self._jid_nick[item.attr.jid]; |
848 if nick then item.attr.nick = select(3, jid_split(nick)); end | 821 if nick then item.attr.nick = select(3, jid_split(nick)); end |
849 end | 822 end |
850 | |
851 local reason = item.tags[1] and item.tags[1].name == "reason" and #item.tags[1] == 1 and item.tags[1][1]; | 823 local reason = item.tags[1] and item.tags[1].name == "reason" and #item.tags[1] == 1 and item.tags[1][1]; |
852 if item.attr.affiliation and item.attr.jid and not item.attr.role then | 824 if item.attr.affiliation and item.attr.jid and not item.attr.role then |
853 jid_affiliation[item.attr.jid] = { ["affiliation"] = item.attr.affiliation, ["reason"] = reason }; | 825 local success, errtype, err = self:set_affiliation(actor, item.attr.jid, item.attr.affiliation, callback, reason); |
826 if not success then origin.send(st.error_reply(stanza, errtype, err)); end | |
854 elseif item.attr.role and item.attr.nick and not item.attr.affiliation then | 827 elseif item.attr.role and item.attr.nick and not item.attr.affiliation then |
855 jidnick_role[self.jid.."/"..item.attr.nick] = { ["role"] = item.attr.role, ["reason"] = reason }; | 828 local success, errtype, err = self:set_role(actor, self.jid.."/"..item.attr.nick, item.attr.role, callback, reason); |
829 if not success then origin.send(st.error_reply(stanza, errtype, err)); end | |
856 else | 830 else |
857 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | 831 origin.send(st.error_reply(stanza, "cancel", "bad-request")); |
858 return; | |
859 end | 832 end |
860 end | 833 elseif type == "get" then |
861 | |
862 if not at_least_one_item_provided then | |
863 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | |
864 return; | |
865 else | |
866 local can_set_affiliations, errtype_aff, err_aff = self:can_set_affiliations(actor, jid_affiliation) | |
867 local can_set_roles, errtype_role, err_role = self:can_set_roles(actor, jidnick_role) | |
868 | |
869 if can_set_affiliations and can_set_roles then | |
870 local nb_affiliation_changes = 0; | |
871 for _ in pairs(jid_affiliation) do nb_affiliation_changes = nb_affiliation_changes + 1; end | |
872 local nb_role_changes = 0; | |
873 for _ in pairs(jidnick_role) do nb_role_changes = nb_role_changes + 1; end | |
874 | |
875 if nb_affiliation_changes > 0 and nb_role_changes > 0 then | |
876 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | |
877 end | |
878 if nb_affiliation_changes > 0 then | |
879 self:set_affiliations(actor, jid_affiliation, callback); | |
880 end | |
881 if nb_role_changes > 0 then | |
882 self:set_roles(actor, jidnick_role, callback); | |
883 end | |
884 else | |
885 if not can_set_affiliations then | |
886 origin.send(st.error_reply(stanza, errtype_aff, err_aff)); | |
887 elseif not can_set_roles then | |
888 origin.send(st.error_reply(stanza, errtype_role, err_role)); | |
889 else | |
890 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | |
891 end | |
892 | |
893 return; | |
894 end | |
895 end | |
896 elseif type == "get" then | |
897 local item = stanza.tags[1].tags[1]; | |
898 if item and item.name == "item" then | |
899 local _aff = item.attr.affiliation; | 834 local _aff = item.attr.affiliation; |
900 local _rol = item.attr.role; | 835 local _rol = item.attr.role; |
901 if _aff and not _rol then | 836 if _aff and not _rol then |
902 if affiliation == "owner" or (affiliation == "admin" and _aff ~= "owner" and _aff ~= "admin") | 837 if affiliation == "owner" or (affiliation == "admin" and _aff ~= "owner" and _aff ~= "admin") |
903 or (affiliation and affiliation ~= "outcast" and self:get_members_only() and self:get_whois() == "anyone") then | 838 or (affiliation and affiliation ~= "outcast" and self:get_members_only() and self:get_whois() == "anyone") then |
931 origin.send(st.error_reply(stanza, "auth", "forbidden")); | 866 origin.send(st.error_reply(stanza, "auth", "forbidden")); |
932 end | 867 end |
933 else | 868 else |
934 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | 869 origin.send(st.error_reply(stanza, "cancel", "bad-request")); |
935 end | 870 end |
936 else | 871 end |
937 origin.send(st.error_reply(stanza, "cancel", "bad-request")); | 872 elseif type == "set" or type == "get" then |
938 end | 873 origin.send(st.error_reply(stanza, "cancel", "bad-request")); |
939 end | 874 end |
940 elseif xmlns == "http://jabber.org/protocol/muc#owner" and (type == "get" or type == "set") and stanza.tags[1].name == "query" then | 875 elseif xmlns == "http://jabber.org/protocol/muc#owner" and (type == "get" or type == "set") and stanza.tags[1].name == "query" then |
941 if self:get_affiliation(stanza.attr.from) ~= "owner" then | 876 if self:get_affiliation(stanza.attr.from) ~= "owner" then |
942 origin.send(st.error_reply(stanza, "auth", "forbidden", "Only owners can configure rooms")); | 877 origin.send(st.error_reply(stanza, "auth", "forbidden", "Only owners can configure rooms")); |
943 elseif stanza.attr.type == "get" then | 878 elseif stanza.attr.type == "get" then |
1061 local bare = node and node.."@"..host or host; | 996 local bare = node and node.."@"..host or host; |
1062 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID. | 997 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID. |
1063 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned | 998 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned |
1064 return result; | 999 return result; |
1065 end | 1000 end |
1066 --- Checks whether the given affiliation changes in jid_affiliation can be applied by actor. | 1001 function room_mt:set_affiliation(actor, jid, affiliation, callback, reason) |
1067 -- Note: Empty tables can always be applied and won't have any effect. | 1002 jid = jid_bare(jid); |
1068 function room_mt:can_set_affiliations(actor, jid_affiliation) | 1003 if affiliation == "none" then affiliation = nil; end |
1069 local actor_affiliation; | 1004 if affiliation and affiliation ~= "outcast" and affiliation ~= "owner" and affiliation ~= "admin" and affiliation ~= "member" then |
1005 return nil, "modify", "not-acceptable"; | |
1006 end | |
1070 if actor ~= true then | 1007 if actor ~= true then |
1071 actor_affiliation = self:get_affiliation(actor); | 1008 local actor_affiliation = self:get_affiliation(actor); |
1072 end | |
1073 | |
1074 -- First let's see if there are any problems with the affiliations given | |
1075 -- in jid_affiliation | |
1076 for jid, value in pairs(jid_affiliation) do | |
1077 local affiliation = value["affiliation"]; | |
1078 | |
1079 if jid ~= jid_bare(jid) then | |
1080 return false, "modify", "not-acceptable"; | |
1081 end | |
1082 jid = jid_bare(jid); | |
1083 if affiliation == "none" then affiliation = nil; end | |
1084 if affiliation and affiliation ~= "outcast" and affiliation ~= "owner" and affiliation ~= "admin" and affiliation ~= "member" then | |
1085 return false, "modify", "not-acceptable"; | |
1086 end | |
1087 | |
1088 local target_affiliation = self:get_affiliation(jid); | 1009 local target_affiliation = self:get_affiliation(jid); |
1089 if target_affiliation == affiliation then | 1010 if target_affiliation == affiliation then -- no change, shortcut |
1090 -- no change, no error checking necessary | 1011 if callback then callback(); end |
1012 return true; | |
1013 end | |
1014 if actor_affiliation ~= "owner" then | |
1015 if affiliation == "owner" or affiliation == "admin" or actor_affiliation ~= "admin" or target_affiliation == "owner" or target_affiliation == "admin" then | |
1016 return nil, "cancel", "not-allowed"; | |
1017 end | |
1018 elseif target_affiliation == "owner" and jid_bare(actor) == jid then -- self change | |
1019 local is_last = true; | |
1020 for j, aff in pairs(self._affiliations) do if j ~= jid and aff == "owner" then is_last = false; break; end end | |
1021 if is_last then | |
1022 return nil, "cancel", "conflict"; | |
1023 end | |
1024 end | |
1025 end | |
1026 self._affiliations[jid] = affiliation; | |
1027 local role = self:get_default_role(affiliation); | |
1028 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}) | |
1029 :tag("item", {affiliation=affiliation or "none", role=role or "none"}) | |
1030 :tag("reason"):text(reason or ""):up() | |
1031 :up(); | |
1032 local presence_type = nil; | |
1033 if not role then -- getting kicked | |
1034 presence_type = "unavailable"; | |
1035 if affiliation == "outcast" then | |
1036 x:tag("status", {code="301"}):up(); -- banned | |
1091 else | 1037 else |
1092 if actor ~= true and actor_affiliation ~= "owner" then | 1038 x:tag("status", {code="321"}):up(); -- affiliation change |
1093 if affiliation == "owner" or affiliation == "admin" or actor_affiliation ~= "admin" or target_affiliation == "owner" or target_affiliation == "admin" then | 1039 end |
1094 return false, "cancel", "not-allowed"; | |
1095 end | |
1096 elseif target_affiliation == "owner" and jid_bare(actor) == jid then -- self change | |
1097 local is_last = true; | |
1098 for j, aff in pairs(self._affiliations) do if j ~= jid and aff == "owner" then is_last = false; break; end end | |
1099 if is_last then | |
1100 return false, "cancel", "conflict"; | |
1101 end | |
1102 end | |
1103 end | |
1104 end | |
1105 | |
1106 return true; | |
1107 end | |
1108 --- Updates the room affiliations by applying the ones given here. | |
1109 -- Takes the affiliations given in jid_affiliation and applies them to | |
1110 -- the room, overwriting a potentially existing affiliation for any given | |
1111 -- jid. | |
1112 -- @param jid_affiliation A table associating a jid with a table consisting | |
1113 -- of two subkeys: `affilation` and `reason`. The jids | |
1114 -- within must not be malformed. | |
1115 function room_mt:set_affiliations(actor, jid_affiliation, callback) | |
1116 local can_set, err_type, err_condition = self:can_set_affiliations(actor, jid_affiliation) | |
1117 | |
1118 if not can_set then | |
1119 return false, err_type, err_condition; | |
1120 end | 1040 end |
1121 -- Your own presence should have status 110 | 1041 -- Your own presence should have status 110 |
1042 local self_x = st.clone(x); | |
1043 self_x:tag("status", {code="110"}); | |
1122 local modified_nicks = {}; | 1044 local modified_nicks = {}; |
1123 local nb_modified_nicks = 0; | 1045 for nick, occupant in pairs(self._occupants) do |
1124 -- Now we can be sure that jid_affiliation causes no problems | 1046 if jid_bare(occupant.jid) == jid then |
1125 -- We can actually set them | 1047 if not role then -- getting kicked |
1126 for jid, value in pairs(jid_affiliation) do | 1048 self._occupants[nick] = nil; |
1127 local affiliation = value["affiliation"]; | |
1128 local reason = value["reason"]; | |
1129 | |
1130 self._affiliations[jid] = affiliation; | |
1131 local role = self:get_default_role(affiliation); | |
1132 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}) | |
1133 :tag("item", {affiliation=affiliation or "none", role=role or "none"}) | |
1134 :tag("reason"):text(reason or ""):up() | |
1135 :up(); | |
1136 local self_x = st.clone(x); | |
1137 self_x:tag("status", {code="110"}):up(); | |
1138 local presence_type = nil; | |
1139 if not role then -- getting kicked | |
1140 presence_type = "unavailable"; | |
1141 if affiliation == "outcast" then | |
1142 -- banned | |
1143 x:tag("status", {code="301"}):up(); | |
1144 self_x:tag("status", {code="301"}):up(); | |
1145 else | 1049 else |
1146 -- affiliation change | 1050 occupant.affiliation, occupant.role = affiliation, role; |
1147 x:tag("status", {code="321"}):up(); | 1051 end |
1148 self_x:tag("status", {code="321"}):up(); | 1052 for jid,pres in pairs(occupant.sessions) do -- remove for all sessions of the nick |
1149 end | 1053 if not role then self._jid_nick[jid] = nil; end |
1150 end | 1054 local p = st.clone(pres); |
1151 for nick, occupant in pairs(self._occupants) do | 1055 p.attr.from = nick; |
1152 if jid_bare(occupant.jid) == jid then | 1056 p.attr.type = presence_type; |
1153 if not role then -- getting kicked | 1057 p.attr.to = jid; |
1154 self._occupants[nick] = nil; | 1058 if occupant.jid == jid then |
1155 else | |
1156 occupant.affiliation, occupant.role = affiliation, role; | |
1157 end | |
1158 for jid,pres in pairs(occupant.sessions) do -- remove for all sessions of the nick | |
1159 if not role then self._jid_nick[jid] = nil; end | |
1160 local p = st.clone(pres); | |
1161 p.attr.from = nick; | |
1162 p.attr.type = presence_type; | |
1163 p.attr.to = jid; | |
1164 self:_route_stanza(p); | |
1165 if occupant.jid == jid then | |
1166 -- Broadcast this presence to everyone else later, with the public <x> variant | 1059 -- Broadcast this presence to everyone else later, with the public <x> variant |
1167 local bp = st.clone(p); | 1060 local bp = st.clone(p); |
1168 bp:add_child(x); | 1061 bp:add_child(x); |
1169 modified_nicks[nick] = bp; | 1062 modified_nicks[nick] = bp; |
1170 nb_modified_nicks = nb_modified_nicks + 1; | 1063 end |
1171 end | 1064 p:add_child(self_x); |
1172 p:add_child(self_x); | 1065 self:_route_stanza(p); |
1173 self:_route_stanza(p); | 1066 end |
1174 end | 1067 end |
1175 end | 1068 end |
1176 end | 1069 if self.save then self:save(); end |
1177 end | 1070 if callback then callback(); end |
1178 | |
1179 if nb_modified_nicks > 0 then | |
1180 if self.save then self:save(); end | |
1181 if callback then callback(); end | |
1182 end | |
1183 for nick,p in pairs(modified_nicks) do | 1071 for nick,p in pairs(modified_nicks) do |
1184 p.attr.from = nick; | 1072 p.attr.from = nick; |
1185 self:broadcast_except_nick(p, nick); | 1073 self:broadcast_except_nick(p, nick); |
1186 end | 1074 end |
1187 return true; | 1075 return true; |
1188 end | |
1189 function room_mt:set_affiliation(actor, jid, affiliation, callback, reason) | |
1190 return self.set_affiliations(actor, { [jid] = { ["affiliation"] = affiliation, ["reason"] = reason } }, callback) | |
1191 end | 1076 end |
1192 | 1077 |
1193 function room_mt:get_role(nick) | 1078 function room_mt:get_role(nick) |
1194 local session = self._occupants[nick]; | 1079 local session = self._occupants[nick]; |
1195 return session and session.role or nil; | 1080 return session and session.role or nil; |
1210 end | 1095 end |
1211 end | 1096 end |
1212 end | 1097 end |
1213 return nil, "cancel", "not-allowed"; | 1098 return nil, "cancel", "not-allowed"; |
1214 end | 1099 end |
1215 | 1100 function room_mt:set_role(actor, occupant_jid, role, callback, reason) |
1216 --- Checks whether the given role changes in jidnick_role can be applied by actor. | 1101 if role == "none" then role = nil; end |
1217 -- Note: Empty tables can always be applied and won't have any effect. | 1102 if role and role ~= "moderator" and role ~= "participant" and role ~= "visitor" then return nil, "modify", "not-acceptable"; end |
1218 function room_mt:can_set_roles(actor, jidnick_role) | 1103 local allowed, err_type, err_condition = self:can_set_role(actor, occupant_jid, role); |
1219 for jidnick, role_info in pairs(jidnick_role) do | |
1220 local role = role_info["role"]; | |
1221 if role == "none" then role = nil; end | |
1222 if role and role ~= "moderator" and role ~= "participant" and role ~= "visitor" then return false, "modify", "not-acceptable"; end | |
1223 local can_set, err_type, err_condition = self:can_set_role(actor, jidnick, role) | |
1224 if not can_set then | |
1225 return false, err_type, err_condition; | |
1226 end | |
1227 end | |
1228 | |
1229 return true; | |
1230 end | |
1231 | |
1232 --- Updates the room roles by applying the ones given here. | |
1233 -- Takes the roles given in jidnick_role and applies them to | |
1234 -- the room, overwriting a potentially existing role for any given | |
1235 -- jid. | |
1236 -- @param jidnick_role A table associating a jid/nick with a table consisting | |
1237 -- of two subkeys: `role` and `reason`. The jids within | |
1238 -- must not be malformed. | |
1239 function room_mt:set_roles(actor, jidnick_role, callback) | |
1240 local allowed, err_type, err_condition = self:can_set_roles(actor, jidnick_role); | |
1241 if not allowed then return allowed, err_type, err_condition; end | 1104 if not allowed then return allowed, err_type, err_condition; end |
1242 | 1105 local occupant = self._occupants[occupant_jid]; |
1243 local modified_nicks = {}; | 1106 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}) |
1244 local nb_modified_nicks = 0; | 1107 :tag("item", {affiliation=occupant.affiliation or "none", nick=select(3, jid_split(occupant_jid)), role=role or "none"}) |
1245 for jidnick, value in pairs(jidnick_role) do | 1108 :tag("reason"):text(reason or ""):up() |
1246 local occupant_jid = jidnick; | 1109 :up(); |
1247 local role = value["role"]; | 1110 local presence_type = nil; |
1248 local reason = value["reason"]; | 1111 if not role then -- kick |
1249 | 1112 presence_type = "unavailable"; |
1250 local occupant = self._occupants[occupant_jid]; | 1113 self._occupants[occupant_jid] = nil; |
1251 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}) | 1114 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick |
1252 :tag("item", {affiliation=occupant.affiliation or "none", nick=select(3, jid_split(occupant_jid)), role=role or "none"}) | 1115 self._jid_nick[jid] = nil; |
1253 :tag("reason"):text(reason or ""):up() | 1116 end |
1254 :up(); | 1117 x:tag("status", {code = "307"}):up(); |
1255 local presence_type = nil; | 1118 else |
1256 if not role or role == "none" then -- kick | 1119 occupant.role = role; |
1257 presence_type = "unavailable"; | 1120 end |
1258 self._occupants[occupant_jid] = nil; | 1121 local self_x = st.clone(x); |
1259 for jid in pairs(occupant.sessions) do -- remove for all sessions of the nick | 1122 self_x:tag("status", {code = "110"}):up(); |
1260 self._jid_nick[jid] = nil; | 1123 local bp; |
1261 end | 1124 for jid,pres in pairs(occupant.sessions) do -- send to all sessions of the nick |
1262 x:tag("status", {code = "307"}):up(); | 1125 local p = st.clone(pres); |
1263 else | 1126 p.attr.from = occupant_jid; |
1264 occupant.role = role; | 1127 p.attr.type = presence_type; |
1265 end | 1128 p.attr.to = jid; |
1266 local self_x = st.clone(x); | 1129 if occupant.jid == jid then |
1267 self_x:tag("status", {code = "110"}):up(); | 1130 bp = st.clone(p); |
1268 local bp; | 1131 bp:add_child(x); |
1269 for jid,pres in pairs(occupant.sessions) do -- send to all sessions of the nick | 1132 end |
1270 local p = st.clone(pres); | 1133 p:add_child(self_x); |
1271 p.attr.from = occupant_jid; | 1134 self:_route_stanza(p); |
1272 p.attr.type = presence_type; | 1135 end |
1273 p.attr.to = jid; | 1136 if callback then callback(); end |
1274 self:_route_stanza(p); | 1137 if bp then |
1275 if occupant.jid == jid then | 1138 self:broadcast_except_nick(bp, occupant_jid); |
1276 bp = st.clone(p); | |
1277 bp:add_child(x); | |
1278 modified_nicks[occupant_jid] = bp; | |
1279 nb_modified_nicks = nb_modified_nicks + 1; | |
1280 end | |
1281 p:add_child(self_x); | |
1282 self:route_stanza(p); | |
1283 end | |
1284 end | |
1285 | |
1286 if nb_modified_nicks > 0 then | |
1287 if callback then callback(); end | |
1288 end | |
1289 for nick,p in pairs(modified_nicks) do | |
1290 self:broadcast_except_nick(p, nick); | |
1291 end | 1139 end |
1292 return true; | 1140 return true; |
1293 end | 1141 end |
1294 | 1142 |
1295 function room_mt:_route_stanza(stanza) | 1143 function room_mt:_route_stanza(stanza) |
1309 end | 1157 end |
1310 if muc_child then | 1158 if muc_child then |
1311 for _, item in pairs(muc_child.tags) do | 1159 for _, item in pairs(muc_child.tags) do |
1312 if item.name == "item" then | 1160 if item.name == "item" then |
1313 if from_occupant == to_occupant then | 1161 if from_occupant == to_occupant then |
1314 item.attr.jid = jid_bare(stanza.attr.to); | 1162 item.attr.jid = stanza.attr.to; |
1315 else | 1163 else |
1316 item.attr.jid = jid_bare(from_occupant.jid); | 1164 item.attr.jid = from_occupant.jid; |
1317 end | 1165 end |
1318 end | 1166 end |
1319 end | 1167 end |
1320 end | 1168 end |
1321 self:route_stanza(stanza); | 1169 self:route_stanza(stanza); |