void ModeParser::ModeParamsToChangeList(User* user, ModeType type, const std::vector<std::string>& parameters, Modes::ChangeList& changelist, unsigned int beginindex, unsigned int endindex) { if (endindex > parameters.size()) endindex = parameters.size(); const std::string& mode_sequence = parameters[beginindex]; bool adding = true; unsigned int param_at = beginindex+1; for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) { unsigned char modechar = *letter; if (modechar == '+' || modechar == '-') { adding = (modechar == '+'); continue; } ModeHandler *mh = this->FindMode(modechar, type); if (!mh) { /* No mode handler? Unknown mode character then. */ user->WriteNumeric(type == MODETYPE_CHANNEL ? ERR_UNKNOWNMODE : ERR_UNKNOWNSNOMASK, "%c :is unknown mode char to me", modechar); continue; } std::string parameter; if (mh->GetNumParams(adding) && param_at < endindex) parameter = parameters[param_at++]; changelist.push(mh, adding, parameter); } }
void Channel::SetDefaultModes() { ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "SetDefaultModes %s", ServerInstance->Config->DefaultModes.c_str()); irc::spacesepstream list(ServerInstance->Config->DefaultModes); std::string modeseq; std::string parameter; list.GetToken(modeseq); for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n) { ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL); if (mode) { if (mode->IsPrefixMode()) continue; if (mode->GetNumParams(true)) list.GetToken(parameter); else parameter.clear(); mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true); } } }
void User::UnOper() { if (!IS_OPER(this)) return; /* * unset their oper type (what IS_OPER checks). * note, order is important - this must come before modes as -o attempts * to call UnOper. -- w00t */ oper = NULL; /* Remove all oper only modes from the user when the deoper - Bug #466*/ std::string moderemove("-"); for (unsigned char letter = 'A'; letter <= 'z'; letter++) { ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_USER); if (mh && mh->NeedsOper()) moderemove += letter; } std::vector<std::string> parameters; parameters.push_back(this->nick); parameters.push_back(moderemove); ServerInstance->Parser->CallHandler("MODE", parameters, this); /* remove the user from the oper list. Will remove multiple entries as a safeguard against bug #404 */ ServerInstance->Users->all_opers.remove(this); this->modes[UM_OPERATOR] = 0; }
ModResult AccessCheck(User* source, Channel* channel, std::string ¶meter, bool adding) { std::string::size_type pos = parameter.find(':'); if (pos == 0 || pos == std::string::npos) return adding ? MOD_RES_DENY : MOD_RES_PASSTHRU; unsigned int mylevel = channel->GetPrefixValue(source); std::string mid = parameter.substr(0, pos); ModeHandler* mh = FindMode(mid); if (adding && (!mh || !mh->GetPrefixRank())) { source->WriteNumeric(415, "%s %s :Cannot find prefix mode '%s' for autoop", source->nick.c_str(), mid.c_str(), mid.c_str()); return MOD_RES_DENY; } else if (!mh) return MOD_RES_PASSTHRU; std::string dummy; if (mh->AccessCheck(source, channel, dummy, true) == MOD_RES_DENY) return MOD_RES_DENY; if (mh->GetLevelRequired() > mylevel) { source->WriteNumeric(482, "%s %s :You must be able to set mode '%s' to include it in an autoop", source->nick.c_str(), channel->name.c_str(), mid.c_str()); return MOD_RES_DENY; } return MOD_RES_PASSTHRU; }
void ModeParser::DisplayCurrentModes(User *user, User* targetuser, Channel* targetchannel, const char* text) { if (targetchannel) { /* Display channel's current mode string */ user->WriteNumeric(RPL_CHANNELMODEIS, "%s +%s", targetchannel->name.c_str(), targetchannel->ChanModes(targetchannel->HasUser(user))); user->WriteNumeric(RPL_CHANNELCREATED, "%s %lu", targetchannel->name.c_str(), (unsigned long)targetchannel->age); return; } else { if (targetuser == user || user->HasPrivPermission("users/auspex")) { /* Display user's current mode string */ user->WriteNumeric(RPL_UMODEIS, ":+%s", targetuser->FormatModes()); if ((targetuser->IsOper())) { ModeHandler* snomask = FindMode('s', MODETYPE_USER); user->WriteNumeric(RPL_SNOMASKIS, "%s :Server notice mask", snomask->GetUserParameter(user).c_str()); } return; } else { user->WriteNumeric(ERR_USERSDONTMATCH, ":Can't view modes for other users"); return; } } }
void ModeParser::DisplayListModes(User* user, Channel* chan, std::string &mode_sequence) { seq++; for (std::string::const_iterator letter = mode_sequence.begin(); letter != mode_sequence.end(); letter++) { unsigned char mletter = *letter; if (mletter == '+') continue; /* Ensure the user doesnt request the same mode twice, * so they cant flood themselves off out of idiocy. */ if (sent[mletter] == seq) continue; sent[mletter] = seq; ModeHandler *mh = this->FindMode(mletter, MODETYPE_CHANNEL); if (!mh || !mh->IsListMode()) return; ModResult MOD_RESULT; FIRST_MOD_RESULT(OnRawMode, MOD_RESULT, (user, chan, mletter, "", true, 0)); if (MOD_RESULT == MOD_RES_DENY) continue; bool display = true; if (!user->HasPrivPermission("channels/auspex") && ServerInstance->Config->HideModeLists[mletter] && (chan->GetPrefixValue(user) < HALFOP_VALUE)) { user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You do not have access to view the +%c list", user->nick.c_str(), chan->name.c_str(), mletter); display = false; } // Ask mode watchers whether it's OK to show the list std::pair<ModeWatchIter, ModeWatchIter> itpair = modewatchermap.equal_range(mh->name); for (ModeWatchIter i = itpair.first; i != itpair.second; ++i) { ModeWatcher* mw = i->second; if (mw->GetModeType() == MODETYPE_CHANNEL) { std::string dummyparam; if (!mw->BeforeMode(user, NULL, chan, dummyparam, true)) { // A mode watcher doesn't want us to show the list display = false; break; } } } if (display) mh->DisplayList(user, chan); else mh->DisplayEmptyList(user, chan); } }
ModResult OnCheckBan(User *user, Channel *c, const std::string& mask) { if ((mask.length() > 2) && (mask[0] == 'j') && (mask[1] == ':')) { std::string rm = mask.substr(2); char status = 0; ModeHandler* mh = ServerInstance->Modes->FindPrefix(rm[0]); if (mh) { rm = mask.substr(3); status = mh->GetModeChar(); } for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) { if (InspIRCd::Match((**i).name, rm)) { if (status) { Membership* memb = (**i).GetUser(user); if (memb && memb->hasMode(status)) return MOD_RES_DENY; } else return MOD_RES_DENY; } } } return MOD_RES_PASSTHRU; }
PrefixMode* ModeParser::FindPrefixMode(unsigned char modeletter) { ModeHandler* mh = FindMode(modeletter, MODETYPE_CHANNEL); if (!mh) return NULL; return mh->IsPrefixMode(); }
void CommandMode::DisplayCurrentModes(User* user, User* targetuser, Channel* targetchannel) { if (targetchannel) { // Display channel's current mode string user->WriteNumeric(RPL_CHANNELMODEIS, targetchannel->name, (std::string("+") + targetchannel->ChanModes(targetchannel->HasUser(user)))); user->WriteNumeric(RPL_CHANNELCREATED, targetchannel->name, (unsigned long)targetchannel->age); } else { if (targetuser == user || user->HasPrivPermission("users/auspex")) { // Display user's current mode string // XXX: Use WriteServ() because WriteNumeric() assumes the target (i.e. next word after the number) // is 'user' and puts his nick there which is not what we want user->WriteServ("%03d %s :+%s", RPL_UMODEIS, targetuser->nick.c_str(), targetuser->FormatModes()); if (targetuser->IsOper()) { ModeHandler* snomask = ServerInstance->Modes->FindMode('s', MODETYPE_USER); std::string snomaskstr = snomask->GetUserParameter(user); // snomaskstr is empty if the snomask mode isn't set, otherwise it begins with a '+'. // In the former case output a "+", not an empty string. user->WriteServ("%03d %s %s%s :Server notice mask", RPL_SNOMASKIS, targetuser->nick.c_str(), (snomaskstr.empty() ? "+" : ""), snomaskstr.c_str()); } } else { user->WriteNumeric(ERR_USERSDONTMATCH, "Can't view modes for other users"); } } }
void DataKeeper::DoSaveUsers() { ModesExts currdata; const user_hash& users = ServerInstance->Users->GetUsers(); for (user_hash::const_iterator i = users.begin(); i != users.end(); ++i) { User* const user = i->second; // Serialize user modes for (size_t j = 0; j < handledmodes[MODETYPE_USER].size(); j++) { ModeHandler* mh = handledmodes[MODETYPE_USER][j].mh; if (user->IsModeSet(mh)) currdata.modelist.push_back(InstanceData(j, mh->GetUserParameter(user))); } // Serialize all extensions attached to the User SaveExtensions(user, currdata.extlist); // Add to list if the user has any modes or extensions set that we are interested in, otherwise we don't // have to do anything with this user when restoring if (!currdata.empty()) { userdatalist.push_back(UserData(user->uuid)); userdatalist.back().swap(currdata); } } }
void DataKeeper::SaveMemberData(Channel* chan, std::vector<OwnedModesExts>& memberdatalist) { ModesExts currdata; const Channel::MemberMap& users = chan->GetUsers(); for (Channel::MemberMap::const_iterator i = users.begin(); i != users.end(); ++i) { Membership* const memb = i->second; for (size_t j = 0; j < handledmodes[MODETYPE_CHANNEL].size(); j++) { ModeHandler* mh = handledmodes[MODETYPE_CHANNEL][j].mh; if ((mh->IsPrefixMode()) && (memb->hasMode(mh->GetModeChar()))) currdata.modelist.push_back(InstanceData(j, memb->user->uuid)); // Need to pass the user's uuid to the mode parser to set the mode later } SaveExtensions(memb, currdata.extlist); // Same logic as in DoSaveUsers() if (!currdata.empty()) { memberdatalist.push_back(OwnedModesExts(memb->user->uuid)); memberdatalist.back().swap(currdata); } } }
ModResult Call(User* user, Channel* chan, const std::string& restriction) { unsigned int mypfx = chan->GetPrefixValue(user); std::string minmode; modelist* list = ec.extItem.get(chan); if (list) { for (modelist::iterator i = list->begin(); i != list->end(); ++i) { std::string::size_type pos = (*i).mask.find(':'); if (pos == std::string::npos) continue; if ((*i).mask.substr(0,pos) == restriction) minmode = (*i).mask.substr(pos + 1); } } ModeHandler* mh = FindMode(minmode); if (mh && mypfx >= mh->GetPrefixRank()) return MOD_RES_ALLOW; if (mh || minmode == "*") return MOD_RES_DENY; return ServerInstance->HandleOnCheckExemption.Call(user, chan, restriction); }
void Channel::SetDefaultModes() { ServerInstance->Logs->Log("CHANNELS", LOG_DEBUG, "SetDefaultModes %s", ServerInstance->Config->DefaultModes.c_str()); irc::spacesepstream list(ServerInstance->Config->DefaultModes); std::string modeseq; std::string parameter; list.GetToken(modeseq); for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n) { ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL); if (mode) { if (mode->IsPrefixMode()) continue; if (mode->NeedsParam(true)) { list.GetToken(parameter); // If the parameter begins with a ':' then it's invalid if (parameter.c_str()[0] == ':') continue; } else parameter.clear(); if ((mode->NeedsParam(true)) && (parameter.empty())) continue; mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, this, parameter, true); } } }
void User::UnOper() { if (!this->IsOper()) return; /* * unset their oper type (what IS_OPER checks). * note, order is important - this must come before modes as -o attempts * to call UnOper. -- w00t */ oper = NULL; /* Remove all oper only modes from the user when the deoper - Bug #466*/ Modes::ChangeList changelist; const ModeParser::ModeHandlerMap& usermodes = ServerInstance->Modes->GetModes(MODETYPE_USER); for (ModeParser::ModeHandlerMap::const_iterator i = usermodes.begin(); i != usermodes.end(); ++i) { ModeHandler* mh = i->second; if (mh->NeedsOper()) changelist.push_remove(mh); } ServerInstance->Modes->Process(this, NULL, this, changelist); // Remove the user from the oper list stdalgo::vector::swaperase(ServerInstance->Users->all_opers, this); ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER); this->SetMode(opermh, false); }
/* returns a list of DIRECT servernames for a specific channel */ void SpanningTreeUtilities::GetListOfServersForChannel(Channel* c, TreeSocketSet& list, char status, const CUList& exempt_list) { unsigned int minrank = 0; if (status) { ModeHandler* mh = ServerInstance->Modes->FindPrefix(status); if (mh) minrank = mh->GetPrefixRank(); } const UserMembList *ulist = c->GetUsers(); for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++) { if (IS_LOCAL(i->first)) continue; if (minrank && i->second->getRank() < minrank) continue; if (exempt_list.find(i->first) == exempt_list.end()) { TreeServer* best = this->BestRouteTo(i->first->server); if (best) list.insert(best->GetSocket()); } } return; }
void OnPostJoin(Membership *memb) { if (!IS_LOCAL(memb->user)) return; modelist* list = mh.extItem.get(memb->chan); if (list) { std::string modeline("+"); std::vector<std::string> modechange; modechange.push_back(memb->chan->name); for (modelist::iterator it = list->begin(); it != list->end(); it++) { std::string::size_type colon = it->mask.find(':'); if (colon == std::string::npos) continue; if (memb->chan->CheckBan(memb->user, it->mask.substr(colon+1))) { ModeHandler* given = mh.FindMode(it->mask.substr(0, colon)); if (given && given->GetPrefixRank()) modeline.push_back(given->GetModeChar()); } } modechange.push_back(modeline); for(std::string::size_type i = modeline.length(); i > 1; --i) // we use "i > 1" instead of "i" so we skip the + modechange.push_back(memb->user->nick); if(modechange.size() >= 3) ServerInstance->SendGlobalMode(modechange, ServerInstance->FakeClient); } }
PrefixMode* FindMode(const std::string& mid) { if (mid.length() == 1) return ServerInstance->Modes->FindPrefixMode(mid[0]); ModeHandler* mh = ServerInstance->Modes->FindMode(mid, MODETYPE_CHANNEL); return mh ? mh->IsPrefixMode() : NULL; }
// Returns true if we should apply a merged mode, false if we should skip it static bool ShouldApplyMergedMode(Channel* chan, Modes::Change& item) { ModeHandler* mh = item.mh; if ((!chan) || (!chan->IsModeSet(mh)) || (mh->IsListMode())) // Mode not set here or merge is not applicable, apply the incoming mode return true; // Mode handler decides std::string ours = chan->GetModeParameter(mh); return mh->ResolveModeConflict(item.param, ours, chan); }
void init() override { ConfigTagList tags = ServerInstance->Config->ConfTags("customprefix"); for (ConfigIter iter = tags.first; iter != tags.second; ++iter) { ConfigTag* tag = iter->second; const std::string name = tag->getString("name"); if (name.empty()) throw ModuleException("<customprefix:name> must be specified at " + tag->getTagLocation()); if (tag->getBool("change")) { ModeHandler* mh = ServerInstance->Modes.FindMode(name, MODETYPE_CHANNEL); if (!mh) throw ModuleException("<customprefix:change> specified for a non-existent mode at " + tag->getTagLocation()); PrefixMode* pm = mh->IsPrefixMode(); if (!pm) throw ModuleException("<customprefix:change> specified for a non-prefix mode at " + tag->getTagLocation()); unsigned long rank = tag->getUInt("rank", pm->GetPrefixRank(), 0, UINT_MAX); unsigned long setrank = tag->getUInt("ranktoset", pm->GetLevelRequired(true), rank, UINT_MAX); unsigned long unsetrank = tag->getUInt("ranktounset", pm->GetLevelRequired(false), setrank, UINT_MAX); bool depriv = tag->getBool("depriv", pm->CanSelfRemove()); pm->Update(rank, setrank, unsetrank, depriv); ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Changed the %s prefix: depriv=%u rank=%u ranktoset=%u ranktounset=%u", pm->name.c_str(), pm->CanSelfRemove(), pm->GetPrefixRank(), pm->GetLevelRequired(true), pm->GetLevelRequired(false)); continue; } const std::string letter = tag->getString("letter"); if (letter.length() != 1) throw ModuleException("<customprefix:letter> must be set to a mode character at " + tag->getTagLocation()); const std::string prefix = tag->getString("prefix"); if (prefix.length() != 1) throw ModuleException("<customprefix:prefix> must be set to a mode prefix at " + tag->getTagLocation()); try { CustomPrefixMode* mh = new CustomPrefixMode(this, name, letter[0], prefix[0], tag); modes.push_back(mh); ServerInstance->Modules.AddService(*mh); } catch (ModuleException& e) { throw ModuleException(e.GetReason() + " (while creating mode from " + tag->getTagLocation() + ")"); } } }
std::string ModeParser::CreateModeList(ModeType mt, bool needparam) { std::string modestr; for (unsigned char mode = 'A'; mode <= 'z'; mode++) { ModeHandler* mh = modehandlers[mt][mode-65]; if ((mh) && ((!needparam) || (mh->GetNumParams(true)))) modestr.push_back(mode); } return modestr; }
void CommandFJoin::RemoveStatus(Channel* c) { Modes::ChangeList changelist; const ModeParser::ModeHandlerMap& mhs = ServerInstance->Modes.GetModes(MODETYPE_CHANNEL); for (ModeParser::ModeHandlerMap::const_iterator i = mhs.begin(); i != mhs.end(); ++i) { ModeHandler* mh = i->second; // Add the removal of this mode to the changelist. This handles all kinds of modes, including prefix modes. mh->RemoveMode(c, changelist); } ServerInstance->Modes.Process(ServerInstance->FakeClient, c, NULL, changelist, ModeParser::MODE_LOCALONLY); }
void CommandFJoin::RemoveStatus(Channel* c) { irc::modestacker stack(false); for (char modeletter = 'A'; modeletter <= 'z'; ++modeletter) { ModeHandler* mh = ServerInstance->Modes->FindMode(modeletter, MODETYPE_CHANNEL); /* Passing a pointer to a modestacker here causes the mode to be put onto the mode stack, * rather than applied immediately. Module unloads require this to be done immediately, * for this function we require tidyness instead. Fixes bug #493 */ if (mh) mh->RemoveMode(c, &stack); } ApplyModeStack(ServerInstance->FakeClient, c, stack); }
static void DisplayList(User* user, Channel* channel) { std::stringstream items; for(char letter = 'A'; letter <= 'z'; letter++) { ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL); if (!mh || mh->IsListMode()) continue; if (!channel->IsModeSet(mh)) continue; items << " +" << mh->name; if (mh->GetNumParams(true)) items << " " << channel->GetModeParameter(mh); } const std::string line = ":" + ServerInstance->Config->ServerName + " 961 " + user->nick + " " + channel->name; user->SendText(line, items); user->WriteNumeric(960, "%s %s :End of mode list", user->nick.c_str(), channel->name.c_str()); }
std::string ModeParser::GiveModeList(ModeType mt) { std::string type1; /* Listmodes EXCEPT those with a prefix */ std::string type2; /* Modes that take a param when adding or removing */ std::string type3; /* Modes that only take a param when adding */ std::string type4; /* Modes that dont take a param */ for (unsigned char mode = 'A'; mode <= 'z'; mode++) { ModeHandler* mh = modehandlers[mt][mode-65]; /* One parameter when adding */ if (mh) { if (mh->GetNumParams(true)) { PrefixMode* pm = mh->IsPrefixMode(); if ((mh->IsListMode()) && ((!pm) || (pm->GetPrefix() == 0))) { type1 += mh->GetModeChar(); } else { /* ... and one parameter when removing */ if (mh->GetNumParams(false)) { /* But not a list mode */ if (!pm) { type2 += mh->GetModeChar(); } } else { /* No parameters when removing */ type3 += mh->GetModeChar(); } } } else { type4 += mh->GetModeChar(); } } } return type1 + "," + type2 + "," + type3 + "," + type4; }
void ModuleManager::AddService(ServiceProvider& item) { switch (item.service) { case SERVICE_COMMAND: if (!ServerInstance->Parser->AddCommand(static_cast<Command*>(&item))) throw ModuleException("Command "+std::string(item.name)+" already exists."); return; case SERVICE_MODE: { ModeHandler* mh = static_cast<ModeHandler*>(&item); if (!ServerInstance->Modes->AddMode(mh)) throw ModuleException("Mode "+std::string(item.name)+" already exists."); DataProviders.insert(std::make_pair((mh->GetModeType() == MODETYPE_CHANNEL ? "mode/" : "umode/") + item.name, &item)); dynamic_reference_base::reset_all(); return; } case SERVICE_METADATA: if (!ServerInstance->Extensions.Register(static_cast<ExtensionItem*>(&item))) throw ModuleException("Extension " + std::string(item.name) + " already exists."); return; case SERVICE_DATA: case SERVICE_IOHOOK: { if ((item.name.substr(0, 5) == "mode/") || (item.name.substr(0, 6) == "umode/")) throw ModuleException("The \"mode/\" and the \"umode\" service name prefixes are reserved."); DataProviders.insert(std::make_pair(item.name, &item)); std::string::size_type slash = item.name.find('/'); if (slash != std::string::npos) { DataProviders.insert(std::make_pair(item.name.substr(0, slash), &item)); DataProviders.insert(std::make_pair(item.name.substr(slash + 1), &item)); } dynamic_reference_base::reset_all(); return; } default: throw ModuleException("Cannot add unknown service type"); } }
static std::string BuildModeList(ModeType type) { std::vector<std::string> modes; for(char c='A'; c <= 'z'; c++) { ModeHandler* mh = ServerInstance->Modes->FindMode(c, type); if (mh) { std::string mdesc = mh->name; mdesc.push_back('='); if (mh->GetPrefix()) mdesc.push_back(mh->GetPrefix()); if (mh->GetModeChar()) mdesc.push_back(mh->GetModeChar()); modes.push_back(mdesc); } } sort(modes.begin(), modes.end()); irc::stringjoiner line(" ", modes, 0, modes.size() - 1); return line.GetJoined(); }
CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* src) { Channel* const chan = ServerInstance->FindChan(parameters[0]); if (!chan) { src->WriteNumeric(Numerics::NoSuchNick(parameters[0])); return CMD_FAILURE; } if (parameters.size() == 1) { DisplayList(src, chan); return CMD_SUCCESS; } unsigned int i = 1; Modes::ChangeList modes; while (i < parameters.size()) { std::string prop = parameters[i++]; if (prop.empty()) continue; bool plus = prop[0] != '-'; if (prop[0] == '+' || prop[0] == '-') prop.erase(prop.begin()); ModeHandler* mh = ServerInstance->Modes->FindMode(prop, MODETYPE_CHANNEL); if (mh) { if (mh->NeedsParam(plus)) { if (i != parameters.size()) modes.push(mh, plus, parameters[i++]); } else modes.push(mh, plus); } } ServerInstance->Modes->ProcessSingle(src, chan, NULL, modes, ModeParser::MODE_CHECKACCESS); return CMD_SUCCESS; }
static void DisplayList(LocalUser* user, Channel* channel) { Numeric::ParamBuilder<1> numeric(user, 961); numeric.AddStatic(channel->name); const ModeParser::ModeHandlerMap& mhs = ServerInstance->Modes->GetModes(MODETYPE_CHANNEL); for (ModeParser::ModeHandlerMap::const_iterator i = mhs.begin(); i != mhs.end(); ++i) { ModeHandler* mh = i->second; if (!channel->IsModeSet(mh)) continue; numeric.Add("+" + mh->name); if (mh->NeedsParam(true)) { if ((mh->name == "key") && (!channel->HasUser(user)) && (!user->HasPrivPermission("channels/auspex"))) numeric.Add("<key>"); else numeric.Add(channel->GetModeParameter(mh)); } } numeric.Flush(); user->WriteNumeric(960, channel->name, "End of mode list"); }
const char* User::FormatModes(bool showparameters) { static std::string data; std::string params; data.clear(); for (unsigned char n = 0; n < 64; n++) { ModeHandler* mh = ServerInstance->Modes->FindMode(n + 65, MODETYPE_USER); if (mh && IsModeSet(mh)) { data.push_back(n + 65); if (showparameters && mh->GetNumParams(true)) { std::string p = mh->GetUserParameter(this); if (p.length()) params.append(" ").append(p); } } } data += params; return data.c_str(); }
CmdResult Handle(const std::vector<std::string> ¶meters, User *src) { if (parameters.size() == 1) { Channel* chan = ServerInstance->FindChan(parameters[0]); if (chan) DisplayList(src, chan); return CMD_SUCCESS; } unsigned int i = 1; std::vector<std::string> modes; modes.push_back(parameters[0]); modes.push_back(""); while (i < parameters.size()) { std::string prop = parameters[i++]; bool plus = prop[0] != '-'; if (prop[0] == '+' || prop[0] == '-') prop.erase(prop.begin()); for(char letter = 'A'; letter <= 'z'; letter++) { ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL); if (mh && mh->name == prop) { modes[1].append((plus ? "+" : "-") + std::string(1, letter)); if (mh->GetNumParams(plus)) { if (i != parameters.size()) modes.push_back(parameters[i++]); } } } } ServerInstance->Modes->Process(modes, src); return CMD_SUCCESS; }