diff options
| author | Adam <Adam@anope.org> | 2015-09-06 16:47:57 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2015-09-06 16:48:25 -0400 |
| commit | c6a92296d4175a2d2276c2d5a46894af3d9085f4 (patch) | |
| tree | 8e6dfe9fd21825f53a1e32641bc71e701e6c853e /src | |
| parent | 263dc290d296af2fcdf7f8a9f04735935e9c2580 (diff) | |
Allow configuring modes
Diffstat (limited to 'src')
| -rw-r--r-- | src/bots.cpp | 25 | ||||
| -rw-r--r-- | src/channels.cpp | 12 | ||||
| -rw-r--r-- | src/config.cpp | 189 | ||||
| -rw-r--r-- | src/init.cpp | 2 | ||||
| -rw-r--r-- | src/modes.cpp | 102 | ||||
| -rw-r--r-- | src/servers.cpp | 143 |
6 files changed, 259 insertions, 214 deletions
diff --git a/src/bots.cpp b/src/bots.cpp index 697115ea0..205b0841c 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -25,7 +25,15 @@ ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, c this->type = UserType::BOT; this->lastmsg = Anope::CurTime; this->introduced = false; - this->conf = false; + + bi = botinfo.Create(); + bi->bot = this; + + bi->SetNick(nnick); + bi->SetUser(nuser); + bi->SetHost(nhost); + bi->SetRealName(nreal); + bi->SetCreated(Anope::CurTime); Event::OnCreateBot(&Event::CreateBot::OnCreateBot, this); @@ -46,6 +54,9 @@ ServiceBot::ServiceBot(const Anope::string &nnick, const Anope::string &nuser, c ServiceBot::~ServiceBot() { + bi->bot = nullptr; + bi->Delete(); + Event::OnDelBot(&Event::DelBot::OnDelBot, this); // If we're synchronised with the uplink already, send the bot. @@ -219,6 +230,18 @@ ServiceBot* ServiceBot::Find(const Anope::string &nick, bool nick_only) return nullptr; } +void BotInfo::Delete() +{ + if (bot) + { + ServiceBot *b = bot; + bot = nullptr; + delete b; + } + + return Serialize::Object::Delete(); +} + void BotInfo::SetCreated(const time_t &t) { Set(&BotInfoType::created, t); diff --git a/src/channels.cpp b/src/channels.cpp index 7972dca6b..f77f1f4bc 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -306,12 +306,6 @@ void Channel::SetModeInternal(const MessageSource &setter, ChannelMode *ocm, con return; } - if (cm->type == MODE_LIST) - { - ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); - cml->OnAdd(this, param); - } - MOD_RESULT = Event::OnChannelModeSet(&Event::ChannelModeSet::OnChannelModeSet, this, setter, cm, param); /* Check if we should enforce mlock */ @@ -375,12 +369,6 @@ void Channel::RemoveModeInternal(const MessageSource &setter, ChannelMode *ocm, else this->modes.erase(cm->name); - if (cm->type == MODE_LIST) - { - ChannelModeList *cml = anope_dynamic_static_cast<ChannelModeList *>(cm); - cml->OnDel(this, param); - } - MOD_RESULT = Event::OnChannelModeUnset(&Event::ChannelModeUnset::OnChannelModeUnset, this, setter, cm, param); if (cm->name == "PERM") diff --git a/src/config.cpp b/src/config.cpp index 323a48519..47a9d8580 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -18,6 +18,8 @@ #include "event.h" #include "bots.h" #include "modules.h" +#include "servers.h" +#include "protocol.h" #include "modules/nickserv.h" using namespace Configuration; @@ -323,15 +325,8 @@ Conf::Conf() : Block("") o->SetVhost(vhost); } - for (std::pair<Anope::string, User *> p : UserListByNick) - { - User *u = p.second; - if (u->type != UserType::BOT) - continue; - - ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); - bi->conf = false; - } + for (BotInfo *bi : Serialize::GetObjects<BotInfo *>(botinfo)) + bi->conf = nullptr; for (int i = 0; i < this->CountBlock("service"); ++i) { Block *service = this->GetBlock("service", i); @@ -349,73 +344,19 @@ Conf::Conf() : Block("") ValidateNotEmpty("service", "gecos", gecos); ValidateNoSpaces("service", "channels", channels); - ServiceBot *bi = ServiceBot::Find(nick, true); - if (!bi) - bi = new ServiceBot(nick, user, host, gecos, modes); - bi->conf = true; - - std::vector<Anope::string> oldchannels = bi->botchannels; - bi->botchannels.clear(); - commasepstream sep(channels); - for (Anope::string token; sep.GetToken(token);) + if (User *u = User::Find(nick, true)) { - bi->botchannels.push_back(token); - size_t ch = token.find('#'); - Anope::string chname, want_modes; - if (ch == Anope::string::npos) - chname = token; - else + if (u->type != UserType::BOT) { - want_modes = token.substr(0, ch); - chname = token.substr(ch); - } - bi->Join(chname); - Channel *c = Channel::Find(chname); - if (!c) - continue; // Can't happen - - c->botchannel = true; - - /* Remove all existing modes */ - ChanUserContainer *cu = c->FindUser(bi); - if (cu != NULL) - for (size_t j = 0; j < cu->status.Modes().length(); ++j) - c->RemoveMode(bi, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->GetUID()); - /* Set the new modes */ - for (unsigned j = 0; j < want_modes.length(); ++j) - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]); - if (cm == NULL) - cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j])); - if (cm && cm->type == MODE_STATUS) - c->SetMode(bi, cm, bi->GetUID()); + u->Kill(Me, "Nickname required by services"); } } - for (unsigned k = 0; k < oldchannels.size(); ++k) - { - size_t ch = oldchannels[k].find('#'); - Anope::string chname = oldchannels[k].substr(ch != Anope::string::npos ? ch : 0); - - bool found = false; - for (unsigned j = 0; j < bi->botchannels.size(); ++j) - { - ch = bi->botchannels[j].find('#'); - Anope::string ochname = bi->botchannels[j].substr(ch != Anope::string::npos ? ch : 0); - if (chname.equals_ci(ochname)) - found = true; - } - - if (found) - continue; + ServiceBot *sb = ServiceBot::Find(nick, true); + if (!sb) + sb = new ServiceBot(nick, user, host, gecos, modes); - Channel *c = Channel::Find(chname); - if (c) - { - c->botchannel = false; - bi->Part(c); - } - } + sb->bi->conf = service; } for (int i = 0; i < this->CountBlock("log"); ++i) @@ -512,6 +453,72 @@ Conf::Conf() : Block("") this->CommandGroups.push_back(gr); } + for (int i = 0; i < this->CountBlock("usermode"); ++i) + { + Block *usermode = this->GetBlock("usermode", i); + + Anope::string nname = usermode->Get<Anope::string>("name"), + character = usermode->Get<Anope::string>("character"); + bool oper_only = usermode->Get<bool>("oper_only"), + setable = usermode->Get<bool>("setable"), + param = usermode->Get<bool>("param"); + + ValidateNotEmpty("usermode", "name", nname); + + if (character.length() != 1) + throw ConfigException("Usermode character length must be 1"); + + Usermode um; + um.name = nname; + um.character = character[0]; + um.param = param; + um.oper_only = oper_only; + um.setable = setable; + + this->Usermodes.push_back(um); + } + + for (int i = 0; i < this->CountBlock("channelmode"); ++i) + { + Block *channelmode = this->GetBlock("channelmode", i); + + Anope::string nname = channelmode->Get<Anope::string>("name"), + character = channelmode->Get<Anope::string>("character"), + status = channelmode->Get<Anope::string>("status"), + param_regex = channelmode->Get<Anope::string>("param_regex"); + bool oper_only = channelmode->Get<bool>("oper_only"), + setable = channelmode->Get<bool>("setable"), + list = channelmode->Get<bool>("list"), + param = channelmode->Get<bool>("param"), + param_unset = channelmode->Get<bool>("param_unset", "yes"); + int level = channelmode->Get<int>("level"); + + ValidateNotEmpty("usermode", "name", nname); + + if (character.length() != 1) + throw ConfigException("Channelmode character length must be 1"); + + if (status.length() > 1) + throw ConfigException("Channelmode status must be at most one character"); + + if (list || !param_regex.empty() || param_unset || !status.empty()) + param = true; + + Channelmode cm; + cm.name = nname; + cm.character = character[0]; + cm.status = !status.empty() ? status[0] : 0; + cm.param_regex = param_regex; + cm.oper_only = oper_only; + cm.setable = setable; + cm.list = list; + cm.param = param; + cm.param_unset = param_unset; + cm.level = level; + + this->Channelmodes.push_back(cm); + } + for (int i = 0; i < this->CountBlock("casemap"); ++i) { Block *casemap = this->GetBlock("casemap", i); @@ -602,6 +609,8 @@ void Conf::Post(Conf *old) if (std::find(old->ModulesAutoLoad.begin(), old->ModulesAutoLoad.end(), this->ModulesAutoLoad[i]) == old->ModulesAutoLoad.end()) ModuleManager::LoadModule(this->ModulesAutoLoad[i], NULL); + ModeManager::Apply(old); + /* Apply opertype changes, as non-conf opers still point to the old oper types */ for (Oper *o : Serialize::GetObjects<Oper *>(operblock)) { @@ -622,6 +631,46 @@ void Conf::Post(Conf *old) } } } + + for (BotInfo *bi : Serialize::GetObjects<BotInfo *>(botinfo)) + { + if (!bi->conf) + { + bi->Delete(); + continue; + } + + for (int i = 0; i < bi->conf->CountBlock("channel"); ++i) + { + Block *channel = bi->conf->GetBlock("channel", i); + + const Anope::string &chname = channel->Get<Anope::string>("name"), + &modes = channel->Get<Anope::string>("modes"); + + bi->bot->Join(chname); + + Channel *c = Channel::Find(chname); + if (!c) + continue; // Can't happen + + c->botchannel = true; + + /* Remove all existing modes */ + ChanUserContainer *cu = c->FindUser(bi->bot); + if (cu != NULL) + for (size_t j = 0; j < cu->status.Modes().length(); ++j) + c->RemoveMode(bi->bot, ModeManager::FindChannelModeByChar(cu->status.Modes()[j]), bi->bot->GetUID()); + /* Set the new modes */ + for (unsigned j = 0; j < modes.length(); ++j) + { + ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[j]); + if (cm == NULL) + cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(modes[j])); + if (cm && cm->type == MODE_STATUS) + c->SetMode(bi->bot, cm, bi->bot->GetUID()); + } + } + } } Block *Conf::GetModule(Module *m) diff --git a/src/init.cpp b/src/init.cpp index 7e29b43b0..d649a2f6e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -526,6 +526,8 @@ void Anope::Init(int ac, char **av) block = Config->GetBlock("options"); srand(block->Get<unsigned>("seed") ^ time(NULL)); + ModeManager::Apply(nullptr); + /* load modules */ Log() << "Loading modules..."; for (int i = 0; i < Config->CountBlock("module"); ++i) diff --git a/src/modes.cpp b/src/modes.cpp index c0bd79cc7..2ea11d3a3 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -39,9 +39,6 @@ static std::map<Anope::string, UserMode *> UserModesByName; /* Sorted by status */ static std::vector<ChannelModeStatus *> ChannelModesByStatus; -/* Number of generic modes we support */ -unsigned ModeManager::GenericChannelModes = 0, ModeManager::GenericUserModes = 0; - struct StackerInfo { /* Modes to be added */ @@ -127,6 +124,12 @@ Mode::~Mode() bool Mode::CanSet(User *u) const { + if (!setable) + return false; + + if (oper_only) + return u && u->HasMode("OPER"); + return true; } @@ -189,6 +192,11 @@ ChannelModeParam::ChannelModeParam(const Anope::string &cm, char mch, bool ma) : this->type = MODE_PARAM; } +bool ChannelModeParam::IsValid(Anope::string &value) const +{ + return std::regex_search(value.str(), param_validation); +} + ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar, char msymbol, short mlevel) : ChannelMode(mname, modeChar), symbol(msymbol), level(mlevel) { this->type = MODE_STATUS; @@ -230,34 +238,6 @@ ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string ¶m) template class ChannelModeVirtual<ChannelMode>; template class ChannelModeVirtual<ChannelModeList>; -bool UserModeOperOnly::CanSet(User *u) const -{ - return u && u->HasMode("OPER"); -} - -bool UserModeNoone::CanSet(User *u) const -{ - return false; -} - -bool ChannelModeKey::IsValid(Anope::string &value) const -{ - if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos) - return true; - - return false; -} - -bool ChannelModeOperOnly::CanSet(User *u) const -{ - return u && u->HasMode("OPER"); -} - -bool ChannelModeNoone::CanSet(User *u) const -{ - return false; -} - void StackerInfo::AddMode(Mode *mode, bool set, const Anope::string ¶m) { bool is_param = mode->type == MODE_PARAM; @@ -398,12 +378,6 @@ bool ModeManager::AddUserMode(UserMode *um) if (ModeManager::FindUserModeByName(um->name) != NULL) return false; - if (um->name.empty()) - { - um->name = stringify(++GenericUserModes); - Log() << "ModeManager: Added generic support for user mode " << um->mchar; - } - unsigned want = um->mchar; if (want >= UserModesIdx.size()) UserModesIdx.resize(want + 1); @@ -425,12 +399,6 @@ bool ModeManager::AddChannelMode(ChannelMode *cm) if (ModeManager::FindChannelModeByName(cm->name) != NULL) return false; - if (cm->name.empty()) - { - cm->name = stringify(++GenericChannelModes); - Log() << "ModeManager: Added generic support for channel mode " << cm->mchar; - } - if (cm->mchar) { unsigned want = cm->mchar; @@ -739,6 +707,54 @@ void ModeManager::StackerDel(Mode *m) } } +void ModeManager::Apply(Configuration::Conf *old) +{ + /* XXX remove old modes */ + + for (Configuration::Channelmode &cm : Config->Channelmodes) + { + ChannelMode *mode; + + if (cm.character) + Log(LOG_DEBUG) << "Creating channelmode " << cm.name << " (" << cm.character << ")"; + else + Log(LOG_DEBUG) << "Creating channelmode " << cm.name; + + if (cm.list) + mode = new ChannelModeList(cm.name, cm.character); + else if (cm.status) + mode = new ChannelModeStatus(cm.name, cm.character, cm.status, cm.level); + else if (cm.param) + mode = new ChannelModeParam(cm.name, cm.character, !cm.param_unset); + else + mode = new ChannelMode(cm.name, cm.character); + + mode->SetSetable(cm.setable); + mode->SetOperOnly(cm.oper_only); + + if (!AddChannelMode(mode)) + delete mode; + } + + for (Configuration::Usermode &um : Config->Usermodes) + { + UserMode *mode; + + Log(LOG_DEBUG) << "Creating usermode " << um.name << " (" << um.character << ")"; + + if (um.param) + mode = new UserModeParam(um.name, um.character); + else + mode = new UserMode(um.name, um.character); + + mode->SetSetable(um.setable); + mode->SetOperOnly(um.oper_only); + + if (!AddUserMode(mode)) + delete mode; + } +} + Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh), cidr_len(0) { Anope::string n, u, h; diff --git a/src/servers.cpp b/src/servers.cpp index 394d4d6e8..9f94bc78e 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -48,94 +48,7 @@ Server::Server(Server *up, const Anope::string &sname, unsigned shops, const Ano /* Check to be sure this isn't a juped server */ if (Me == this->uplink && !juped) - { - /* Now do mode related stuff as we know what modes exist .. */ - for (std::pair<Anope::string, User *> p : UserListByNick) - { - User *u = p.second; - if (u->type != UserType::BOT) - continue; - - ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u); - Anope::string modes = !bi->botmodes.empty() ? ("+" + bi->botmodes) : IRCD->DefaultPseudoclientModes; - - bi->SetModesInternal(bi, modes.c_str()); - for (unsigned i = 0; i < bi->botchannels.size(); ++i) - { - size_t h = bi->botchannels[i].find('#'); - if (h == Anope::string::npos) - continue; - Anope::string chname = bi->botchannels[i].substr(h); - Channel *c = Channel::Find(chname); - if (c && c->FindUser(bi)) - { - Anope::string want_modes = bi->botchannels[i].substr(0, h); - for (unsigned j = 0; j < want_modes.length(); ++j) - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(want_modes[j]); - if (cm == NULL) - cm = ModeManager::FindChannelModeByChar(ModeManager::GetStatusChar(want_modes[j])); - if (cm && cm->type == MODE_STATUS) - { - MessageSource ms = bi; - c->SetModeInternal(ms, cm, bi->nick); - } - } - } - } - } - - IRCD->SendBOB(); - - for (unsigned i = 0; i < Me->GetLinks().size(); ++i) - { - Server *s = Me->GetLinks()[i]; - - if (s->juped) - IRCD->SendServer(s); - } - - /* We make the bots go online */ - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u = it->second; - - ServiceBot *bi = ServiceBot::Find(u->GetUID()); - if (bi) - { - //XLine x(bi->nick, "Reserved for services"); - //IRCD->SendSQLine(NULL, &x); - } - - IRCD->SendClientIntroduction(u); - if (bi) - bi->introduced = true; - } - - for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - { - Channel *c = it->second; - - if (c->users.empty()) - IRCD->SendChannel(c); - else - for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit) - IRCD->SendJoin(cit->second->user, c, &cit->second->status); - - for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2) - { - ChannelMode *cm = ModeManager::FindChannelModeByName(it2->first); - if (!cm || cm->type != MODE_LIST) - continue; - ModeManager::StackerAdd(c->ci->WhoSends(), c, cm, true, it2->second); - } - - if (!c->topic.empty() && !c->topic_setter.empty()) - IRCD->SendTopic(c->ci->WhoSends(), c); - - c->syncing = true; - } - } + Burst(); } Event::OnNewServer(&Event::NewServer::OnNewServer, this); @@ -177,6 +90,60 @@ void Server::Delete(const Anope::string &reason) delete this; } +void Server::Burst() +{ + IRCD->SendBOB(); + + for (unsigned i = 0; i < Me->GetLinks().size(); ++i) + { + Server *s = Me->GetLinks()[i]; + + if (s->juped) + IRCD->SendServer(s); + } + + /* We make the bots go online */ + for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u = it->second; + + ServiceBot *bi = ServiceBot::Find(u->GetUID()); + if (bi) + { + //XLine x(bi->nick, "Reserved for services"); + //IRCD->SendSQLine(NULL, &x); + } + + IRCD->SendClientIntroduction(u); + if (bi) + bi->introduced = true; + } + + for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) + { + Channel *c = it->second; + + if (c->users.empty()) + IRCD->SendChannel(c); + else + for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end; ++cit) + IRCD->SendJoin(cit->second->user, c, &cit->second->status); + + for (Channel::ModeList::const_iterator it2 = c->GetModes().begin(); it2 != c->GetModes().end(); ++it2) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(it2->first); + if (!cm || cm->type != MODE_LIST) + continue; + ModeManager::StackerAdd(c->ci->WhoSends(), c, cm, true, it2->second); + } + + if (!c->topic.empty() && !c->topic_setter.empty()) + IRCD->SendTopic(c->ci->WhoSends(), c); + + c->syncing = true; + } +} + const Anope::string &Server::GetName() const { return this->name; |
