summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bots.cpp25
-rw-r--r--src/channels.cpp12
-rw-r--r--src/config.cpp189
-rw-r--r--src/init.cpp2
-rw-r--r--src/modes.cpp102
-rw-r--r--src/servers.cpp143
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 &param)
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 &param)
{
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;