CmdResult HandleUserTarget(User* source, const Params& parameters) { User* target; if (IS_LOCAL(source)) { // Local sources can specify either a nick or a nick@server mask as the target. const char* targetserver = strchr(parameters[0].c_str(), '@'); if (targetserver) { // The target is a user on a specific server (e.g. [email protected]). target = ServerInstance->FindNickOnly(parameters[0].substr(0, targetserver - parameters[0].c_str())); if (target && strcasecmp(target->server->GetName().c_str(), targetserver + 1)) target = NULL; } else { // If the source is a local user then we only look up the target by nick. target = ServerInstance->FindNickOnly(parameters[0]); } } else { // Remote users can only specify a nick or UUID as the target. target = ServerInstance->FindNick(parameters[0]); } if (!target || target->registered != REG_ALL) { // The target user does not exist or is not fully registered. source->WriteNumeric(Numerics::NoSuchNick(parameters[0])); return CMD_FAILURE; } // Fire the pre-message events. MessageTarget msgtarget(target); CTCTags::TagMessageDetails msgdetails(parameters.GetTags()); if (!FirePreEvents(source, msgtarget, msgdetails)) return CMD_FAILURE; LocalUser* const localtarget = IS_LOCAL(target); if (localtarget && cap.get(localtarget)) { // Send to the target if they have the capability and are a local user. CTCTags::TagMessage message(source, localtarget, parameters.GetTags()); localtarget->Send(msgevprov, message); } // Fire the post-message event. return FirePostEvent(source, msgtarget, msgdetails); }
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); }