summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-04-25 16:51:06 -0400
committerAdam <Adam@anope.org>2014-04-25 16:51:06 -0400
commit6a03eb69ebbe773f1d4139ff88d74ecdb2b0af4b (patch)
treed370fbc4a1dd55b72dbcda9f2aff24678d5626f3 /src
parent4fa2a00bd595eb120e6acde5eb167759c2018e33 (diff)
Add "virtual mode" support
This allows fully tracking extbans and other modes set by a different underlying mode, such as InspIRCd's namedmodes Add two configuration options to cs_ban to configure which mode is set and whether or not to kick banned users. Add default "mute" fantasy command to botserv.example.conf
Diffstat (limited to 'src')
-rw-r--r--src/channels.cpp38
-rw-r--r--src/config.cpp15
-rw-r--r--src/modes.cpp160
3 files changed, 163 insertions, 50 deletions
diff --git a/src/channels.cpp b/src/channels.cpp
index 37d04c44e..b705c8584 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -248,11 +248,14 @@ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::Get
return std::make_pair(it, it_end);
}
-void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
+void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
{
- if (!cm)
+ if (!ocm)
return;
+ Anope::string param = oparam;
+ ChannelMode *cm = ocm->Unwrap(param);
+
EventReturn MOD_RESULT;
/* Setting v/h/o/a/q etc */
@@ -315,11 +318,14 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anop
this->CheckModes();
}
-void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string &param, bool enforce_mlock)
+void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
{
- if (!cm)
+ if (!ocm)
return;
+ Anope::string param = oparam;
+ ChannelMode *cm = ocm->Unwrap(param);
+
EventReturn MOD_RESULT;
/* Setting v/h/o/a/q etc */
@@ -433,9 +439,12 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param,
this->chanserv_modecount++;
}
- ModeManager::StackerAdd(bi, this, cm, true, param);
+ Anope::string wparam = param;
+ ChannelMode *wcm = cm->Wrap(wparam);
+
+ ModeManager::StackerAdd(bi, this, wcm, true, wparam);
MessageSource ms(bi);
- SetModeInternal(ms, cm, param, enforce_mlock);
+ SetModeInternal(ms, wcm, wparam, enforce_mlock);
}
void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
@@ -484,9 +493,12 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &para
this->chanserv_modecount++;
}
- ModeManager::StackerAdd(bi, this, cm, false, realparam);
+ Anope::string wparam = realparam;
+ ChannelMode *wcm = cm->Wrap(wparam);
+
+ ModeManager::StackerAdd(bi, this, wcm, false, wparam);
MessageSource ms(bi);
- RemoveModeInternal(ms, cm, realparam, enforce_mlock);
+ RemoveModeInternal(ms, wcm, wparam, enforce_mlock);
}
void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string &param, bool enforce_mlock)
@@ -849,21 +861,21 @@ void Channel::SetCorrectModes(User *user, bool give_modes)
}
}
-bool Channel::Unban(User *u, bool full)
+bool Channel::Unban(User *u, const Anope::string &mode, bool full)
{
- if (!this->HasMode("BAN"))
+ if (!this->HasMode(mode))
return false;
bool ret = false;
- std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList("BAN");
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList(mode);
for (; bans.first != bans.second;)
{
- Entry ban("BAN", bans.first->second);
+ Entry ban(mode, bans.first->second);
++bans.first;
if (ban.Matches(u, full))
{
- this->RemoveMode(NULL, "BAN", ban.GetMask());
+ this->RemoveMode(NULL, mode, ban.GetMask());
ret = true;
}
}
diff --git a/src/config.cpp b/src/config.cpp
index e402080db..110045786 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -620,6 +620,21 @@ BotInfo *Conf::GetClient(const Anope::string &cname)
return GetClient(cname);
}
+Block *Conf::GetCommand(CommandSource &source)
+{
+ const Anope::string &block_name = source.c ? "fantasy" : "command";
+
+ for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range(block_name); iters.first != iters.second; ++iters.first)
+ {
+ Block *b = &iters.first->second;
+
+ if (b->Get<Anope::string>("name") == source.command)
+ return b;
+ }
+
+ return NULL;
+}
+
File::File(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL)
{
}
diff --git a/src/modes.cpp b/src/modes.cpp
index 13cda797f..891dcf6a8 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -21,9 +21,15 @@ struct StackerInfo;
static std::map<User *, StackerInfo *> UserStackerObjects;
static std::map<Channel *, StackerInfo *> ChannelStackerObjects;
-/* List of all modes Anope knows about */
-std::vector<ChannelMode *> ModeManager::ChannelModes;
-std::vector<UserMode *> ModeManager::UserModes;
+/* Array of all modes Anope knows about.*/
+static std::vector<ChannelMode *> ChannelModes;
+static std::vector<UserMode *> UserModes;
+
+/* Modes are in this array are at position
+ * modechar. Additionally, status modes are in this array (again) at statuschar.
+ */
+static std::vector<ChannelMode *> ChannelModesIdx;
+static std::vector<UserMode *> UserModesIdx;
static std::map<Anope::string, ChannelMode *> ChannelModesByName;
static std::map<Anope::string, UserMode *> UserModesByName;
@@ -142,6 +148,28 @@ bool ChannelMode::CanSet(User *u) const
return MOD_RESULT != EVENT_STOP;
}
+ChannelMode *ChannelMode::Wrap(Anope::string &param)
+{
+ return this;
+}
+
+ChannelMode *ChannelMode::Unwrap(Anope::string &param)
+{
+ for (unsigned i = 0; i < listeners.size(); ++i)
+ {
+ ChannelMode *cm = listeners[i]->Unwrap(this, param);
+ if (cm != this)
+ return cm;
+ }
+
+ return this;
+}
+
+ChannelMode *ChannelMode::Unwrap(ChannelMode *, Anope::string &param)
+{
+ throw CoreException("Unwrap in channel mode");
+}
+
ChannelModeList::ChannelModeList(const Anope::string &cm, char mch) : ChannelMode(cm, mch)
{
this->type = MODE_LIST;
@@ -157,6 +185,42 @@ ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar,
this->type = MODE_STATUS;
}
+template<typename T>
+ChannelModeVirtual<T>::ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename) : T(mname, 0)
+ , base(basename)
+{
+ basech = ModeManager::FindChannelModeByName(base);
+ if (basech)
+ basech->listeners.push_back(this);
+}
+
+template<typename T>
+ChannelModeVirtual<T>::~ChannelModeVirtual()
+{
+ if (basech)
+ {
+ std::vector<ChannelMode *>::iterator it = std::find(basech->listeners.begin(), basech->listeners.end(), this);
+ if (it != basech->listeners.end())
+ basech->listeners.erase(it);
+ }
+}
+
+template<typename T>
+ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string &param)
+{
+ if (basech == NULL)
+ {
+ basech = ModeManager::FindChannelModeByName(base);
+ if (basech)
+ basech->listeners.push_back(this);
+ }
+
+ return basech;
+}
+
+template class ChannelModeVirtual<ChannelMode>;
+template class ChannelModeVirtual<ChannelModeList>;
+
bool UserModeOperOnly::CanSet(User *u) const
{
return u && u->HasMode("OPER");
@@ -321,6 +385,8 @@ bool ModeManager::AddUserMode(UserMode *um)
{
if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
return false;
+ if (ModeManager::FindUserModeByName(um->name) != NULL)
+ return false;
if (um->name.empty())
{
@@ -329,12 +395,14 @@ bool ModeManager::AddUserMode(UserMode *um)
}
unsigned want = um->mchar;
- if (want >= ModeManager::UserModes.size())
- ModeManager::UserModes.resize(want + 1);
- ModeManager::UserModes[want] = um;
+ if (want >= UserModesIdx.size())
+ UserModesIdx.resize(want + 1);
+ UserModesIdx[want] = um;
UserModesByName[um->name] = um;
+ UserModes.push_back(um);
+
FOREACH_MOD(OnUserModeAdd, (um));
return true;
@@ -342,7 +410,9 @@ bool ModeManager::AddUserMode(UserMode *um)
bool ModeManager::AddChannelMode(ChannelMode *cm)
{
- if (ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
+ if (cm->mchar && ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
+ return false;
+ if (ModeManager::FindChannelModeByName(cm->name) != NULL)
return false;
if (cm->name.empty())
@@ -351,24 +421,29 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
}
- unsigned want = cm->mchar;
- if (want >= ModeManager::ChannelModes.size())
- ModeManager::ChannelModes.resize(want + 1);
- ModeManager::ChannelModes[want] = cm;
+ if (cm->mchar)
+ {
+ unsigned want = cm->mchar;
+ if (want >= ChannelModesIdx.size())
+ ChannelModesIdx.resize(want + 1);
+ ChannelModesIdx[want] = cm;
+ }
if (cm->type == MODE_STATUS)
{
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
- want = cms->symbol;
- if (want >= ModeManager::ChannelModes.size())
- ModeManager::ChannelModes.resize(want + 1);
- ModeManager::ChannelModes[want] = cms;
+ unsigned want = cms->symbol;
+ if (want >= ChannelModesIdx.size())
+ ChannelModesIdx.resize(want + 1);
+ ChannelModesIdx[want] = cms;
RebuildStatusModes();
}
ChannelModesByName[cm->name] = cm;
+ ChannelModes.push_back(cm);
+
FOREACH_MOD(OnChannelModeAdd, (cm));
return true;
@@ -378,18 +453,22 @@ void ModeManager::RemoveUserMode(UserMode *um)
{
if (!um)
return;
-
+
unsigned want = um->mchar;
- if (want >= ModeManager::UserModes.size())
+ if (want >= UserModesIdx.size())
return;
- if (ModeManager::UserModes[want] != um)
+ if (UserModesIdx[want] != um)
return;
- ModeManager::UserModes[want] = NULL;
+ UserModesIdx[want] = NULL;
UserModesByName.erase(um->name);
+ std::vector<UserMode *>::iterator it = std::find(UserModes.begin(), UserModes.end(), um);
+ if (it != UserModes.end())
+ UserModes.erase(it);
+
StackerDel(um);
}
@@ -397,53 +476,60 @@ void ModeManager::RemoveChannelMode(ChannelMode *cm)
{
if (!cm)
return;
+
+ if (cm->mchar)
+ {
+ unsigned want = cm->mchar;
+ if (want >= ChannelModesIdx.size())
+ return;
- unsigned want = cm->mchar;
- if (want >= ModeManager::ChannelModes.size())
- return;
-
- if (ModeManager::ChannelModes[want] != cm)
- return;
+ if (ChannelModesIdx[want] != cm)
+ return;
- ModeManager::ChannelModes[want] = NULL;
+ ChannelModesIdx[want] = NULL;
+ }
if (cm->type == MODE_STATUS)
{
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
- want = cms->symbol;
+ unsigned want = cms->symbol;
- if (want >= ModeManager::ChannelModes.size())
+ if (want >= ChannelModesIdx.size())
return;
- if (ModeManager::ChannelModes[want] != cm)
+ if (ChannelModesIdx[want] != cm)
return;
- ModeManager::ChannelModes[want] = NULL;
+ ChannelModesIdx[want] = NULL;
RebuildStatusModes();
}
ChannelModesByName.erase(cm->name);
+ std::vector<ChannelMode *>::iterator it = std::find(ChannelModes.begin(), ChannelModes.end(), cm);
+ if (it != ChannelModes.end())
+ ChannelModes.erase(it);
+
StackerDel(cm);
}
ChannelMode *ModeManager::FindChannelModeByChar(char mode)
{
unsigned want = mode;
- if (want >= ModeManager::ChannelModes.size())
+ if (want >= ChannelModesIdx.size())
return NULL;
- return ModeManager::ChannelModes[want];
+ return ChannelModesIdx[want];
}
UserMode *ModeManager::FindUserModeByChar(char mode)
{
unsigned want = mode;
- if (want >= ModeManager::UserModes.size())
+ if (want >= UserModesIdx.size())
return NULL;
- return ModeManager::UserModes[want];
+ return UserModesIdx[want];
}
ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name)
@@ -465,10 +551,10 @@ UserMode *ModeManager::FindUserModeByName(const Anope::string &name)
char ModeManager::GetStatusChar(char value)
{
unsigned want = value;
- if (want >= ModeManager::ChannelModes.size())
+ if (want >= ChannelModesIdx.size())
return 0;
- ChannelMode *cm = ModeManager::ChannelModes[want];
+ ChannelMode *cm = ChannelModesIdx[want];
if (cm == NULL || cm->type != MODE_STATUS || cm->mchar == value)
return 0;
@@ -505,7 +591,7 @@ void ModeManager::RebuildStatusModes()
{
ChannelMode *cm = ModeManager::GetChannelModes()[j];
- if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
+ if (cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm));
}
std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp);