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);