bool ModeParser::DelMode(ModeHandler* mh) { if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) return false; ModeHandlerMap& mhmap = modehandlersbyname[mh->GetModeType()]; ModeHandlerMap::iterator mhmapit = mhmap.find(mh->name); if ((mhmapit == mhmap.end()) || (mhmapit->second != mh)) return false; ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65]; if (slot != mh) return false; /* Note: We can't stack here, as we have modes potentially being removed across many different channels. * To stack here we have to make the algorithm slower. Discuss. */ switch (mh->GetModeType()) { case MODETYPE_USER: { const user_hash& users = ServerInstance->Users->GetUsers(); for (user_hash::const_iterator i = users.begin(); i != users.end(); ) { User* user = i->second; ++i; mh->RemoveMode(user); } } break; case MODETYPE_CHANNEL: { const chan_hash& chans = ServerInstance->GetChans(); for (chan_hash::const_iterator i = chans.begin(); i != chans.end(); ) { // The channel may not be in the hash after RemoveMode(), see m_permchannels Channel* chan = i->second; ++i; Modes::ChangeList changelist; mh->RemoveMode(chan, changelist); this->Process(ServerInstance->FakeClient, chan, NULL, changelist, MODE_LOCALONLY); } } break; } mhmap.erase(mhmapit); if (mh->GetId() != MODEID_MAX) modehandlersbyid[mh->GetModeType()][mh->GetId()] = NULL; slot = NULL; if (mh->IsPrefixMode()) mhlist.prefix.erase(std::find(mhlist.prefix.begin(), mhlist.prefix.end(), mh->IsPrefixMode())); else if (mh->IsListModeBase()) mhlist.list.erase(std::find(mhlist.list.begin(), mhlist.list.end(), mh->IsListModeBase())); RecreateModeListFor004Numeric(); return true; }
bool ModeParser::DelMode(ModeHandler* mh) { unsigned char mask = 0; unsigned char pos = 0; if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) return false; mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; pos = (mh->GetModeChar()-65) | mask; if (modehandlers[pos] != mh) return false; /* Note: We can't stack here, as we have modes potentially being removed across many different channels. * To stack here we have to make the algorithm slower. Discuss. */ switch (mh->GetModeType()) { case MODETYPE_USER: for (user_hash::iterator i = ServerInstance->Users->clientlist->begin(); i != ServerInstance->Users->clientlist->end(); ) { User* user = i->second; ++i; mh->RemoveMode(user); } break; case MODETYPE_CHANNEL: for (chan_hash::iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); ) { // The channel may not be in the hash after RemoveMode(), see m_permchannels Channel* chan = i->second; ++i; irc::modestacker stack(false); mh->RemoveMode(chan, stack); std::vector<std::string> stackresult; stackresult.push_back(chan->name); while (stack.GetStackedLine(stackresult)) { this->Process(stackresult, ServerInstance->FakeClient, MODE_LOCALONLY); stackresult.erase(stackresult.begin() + 1, stackresult.end()); } } break; } modehandlers[pos] = NULL; if (mh->IsPrefixMode()) mhlist.prefix.erase(std::find(mhlist.prefix.begin(), mhlist.prefix.end(), mh->IsPrefixMode())); else if (mh->IsListModeBase()) mhlist.list.erase(std::find(mhlist.list.begin(), mhlist.list.end(), mh->IsListModeBase())); RecreateModeListFor004Numeric(); return true; }
void ModeParser::AddMode(ModeHandler* mh) { /* Yes, i know, this might let people declare modes like '_' or '^'. * If they do that, thats their problem, and if i ever EVER see an * official InspIRCd developer do that, i'll beat them with a paddle! */ if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) throw ModuleException("Invalid letter for mode " + mh->name); /* A mode prefix of ',' is not acceptable, it would f**k up server to server. * A mode prefix of ':' will f**k up both server to server, and client to server. * A mode prefix of '#' will mess up /whois and /privmsg */ PrefixMode* pm = mh->IsPrefixMode(); if (pm) { if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#')) throw ModuleException("Invalid prefix for mode " + mh->name); if (FindPrefix(pm->GetPrefix())) throw ModuleException("Prefix already exists for mode " + mh->name); } ModeHandler*& slot = modehandlers[mh->GetModeType()][mh->GetModeChar()-65]; if (slot) throw ModuleException("Letter is already in use for mode " + mh->name); // The mode needs an id if it is either a user mode, a simple mode (flag) or a parameter mode. // Otherwise (for listmodes and prefix modes) the id remains MODEID_MAX, which is invalid. ModeHandler::Id modeid = MODEID_MAX; if ((mh->GetModeType() == MODETYPE_USER) || (mh->IsParameterMode()) || (!mh->IsListMode())) modeid = AllocateModeId(mh->GetModeType()); if (!modehandlersbyname[mh->GetModeType()].insert(std::make_pair(mh->name, mh)).second) throw ModuleException("Mode name already in use: " + mh->name); // Everything is fine, add the mode // If we allocated an id for this mode then save it and put the mode handler into the slot if (modeid != MODEID_MAX) { mh->modeid = modeid; modehandlersbyid[mh->GetModeType()][modeid] = mh; } slot = mh; if (pm) mhlist.prefix.push_back(pm); else if (mh->IsListModeBase()) mhlist.list.push_back(mh->IsListModeBase()); RecreateModeListFor004Numeric(); }
bool ModeParser::AddMode(ModeHandler* mh) { unsigned char mask = 0; unsigned char pos = 0; /* Yes, i know, this might let people declare modes like '_' or '^'. * If they do that, thats their problem, and if i ever EVER see an * official InspIRCd developer do that, i'll beat them with a paddle! */ if ((mh->GetModeChar() < 'A') || (mh->GetModeChar() > 'z')) return false; /* A mode prefix of ',' is not acceptable, it would f**k up server to server. * A mode prefix of ':' will f**k up both server to server, and client to server. * A mode prefix of '#' will mess up /whois and /privmsg */ PrefixMode* pm = mh->IsPrefixMode(); if (pm) { if ((pm->GetPrefix() > 126) || (pm->GetPrefix() == ',') || (pm->GetPrefix() == ':') || (pm->GetPrefix() == '#')) return false; if (FindPrefix(pm->GetPrefix())) return false; } mh->GetModeType() == MODETYPE_USER ? mask = MASK_USER : mask = MASK_CHANNEL; pos = (mh->GetModeChar()-65) | mask; if (modehandlers[pos]) return false; // Everything is fine, add the mode modehandlers[pos] = mh; if (pm) mhlist.prefix.push_back(pm); else if (mh->IsListModeBase()) mhlist.list.push_back(mh->IsListModeBase()); RecreateModeListFor004Numeric(); return true; }