CmdResult HandleServerTarget(User* source, const Params& parameters) { // If the source isn't allowed to mass message users then reject // the attempt to mass-message users. if (!source->HasPrivPermission("users/mass-message")) return CMD_FAILURE; // Extract the server glob match from the target parameter. std::string servername(parameters[0], 1); // Fire the pre-message events. MessageTarget msgtarget(&servername); CTCTags::TagMessageDetails msgdetails(parameters.GetTags()); if (!FirePreEvents(source, msgtarget, msgdetails)) return CMD_FAILURE; // If the current server name matches the server name glob then send // the message out to the local users. if (InspIRCd::Match(ServerInstance->Config->ServerName, servername)) { CTCTags::TagMessage message(source, "$*", parameters.GetTags()); const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers(); for (UserManager::LocalList::const_iterator iter = list.begin(); iter != list.end(); ++iter) { LocalUser* luser = IS_LOCAL(*iter); // Don't send to unregistered users or the user who is the source. if (luser->registered != REG_ALL || luser == source) continue; // Don't send to exempt users. if (msgdetails.exemptions.count(luser)) continue; // Send to users if they have the capability. if (cap.get(luser)) luser->Send(msgevprov, message); } } // Fire the post-message event. return FirePostEvent(source, msgtarget, msgdetails); }
CmdResult HandleChannelTarget(User* source, const Params& parameters, const char* target, PrefixMode* pm) { Channel* chan = ServerInstance->FindChan(target); if (!chan) { // The target channel does not exist. source->WriteNumeric(Numerics::NoSuchChannel(parameters[0])); return CMD_FAILURE; } if (IS_LOCAL(source)) { if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(source)) { // The noextmsg mode is set and the source is not in the channel. source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (no external messages)"); return CMD_FAILURE; } bool no_chan_priv = chan->GetPrefixValue(source) < VOICE_VALUE; if (no_chan_priv && chan->IsModeSet(moderatedmode)) { // The moderated mode is set and the source has no status rank. source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (+m)"); return CMD_FAILURE; } if (no_chan_priv && ServerInstance->Config->RestrictBannedUsers != ServerConfig::BUT_NORMAL && chan->IsBanned(source)) { // The source is banned in the channel and restrictbannedusers is enabled. if (ServerInstance->Config->RestrictBannedUsers == ServerConfig::BUT_RESTRICT_NOTIFY) source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're banned)"); return CMD_FAILURE; } } // Fire the pre-message events. MessageTarget msgtarget(chan, pm ? pm->GetPrefix() : 0); CTCTags::TagMessageDetails msgdetails(parameters.GetTags()); if (!FirePreEvents(source, msgtarget, msgdetails)) return CMD_FAILURE; unsigned int minrank = pm ? pm->GetPrefixRank() : 0; CTCTags::TagMessage message(source, chan, parameters.GetTags()); const Channel::MemberMap& userlist = chan->GetUsers(); for (Channel::MemberMap::const_iterator iter = userlist.begin(); iter != userlist.end(); ++iter) { LocalUser* luser = IS_LOCAL(iter->first); // Don't send to remote users or the user who is the source. if (!luser || luser == source) continue; // Don't send to unprivileged or exempt users. if (iter->second->getRank() < minrank || msgdetails.exemptions.count(luser)) continue; // Send to users if they have the capability. if (cap.get(luser)) luser->Send(msgevprov, message); } return FirePostEvent(source, msgtarget, msgdetails); }