summaryrefslogtreecommitdiff
path: root/src/modes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modes.cpp')
-rw-r--r--src/modes.cpp194
1 files changed, 148 insertions, 46 deletions
diff --git a/src/modes.cpp b/src/modes.cpp
index cecab9d11..c0bd79cc7 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -23,9 +23,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;
@@ -144,11 +150,40 @@ 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;
}
+bool ChannelModeList::IsValid(Anope::string &mask) const
+{
+ if (name == "BAN" || name == "EXCEPT" || name == "INVITEOVERRIDE")
+ mask = IRCD->NormalizeMask(mask);
+ return true;
+}
+
ChannelModeParam::ChannelModeParam(const Anope::string &cm, char mch, bool ma) : ChannelMode(cm, mch), minus_no_arg(ma)
{
this->type = MODE_PARAM;
@@ -159,6 +194,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");
@@ -169,7 +240,7 @@ bool UserModeNoone::CanSet(User *u) const
return false;
}
-bool ChannelModeKey::IsValid(const Anope::string &value) const
+bool ChannelModeKey::IsValid(Anope::string &value) const
{
if (!value.empty() && value.find(':') == Anope::string::npos && value.find(',') == Anope::string::npos)
return true;
@@ -324,6 +395,9 @@ 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())
{
um->name = stringify(++GenericUserModes);
@@ -331,12 +405,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);
+
Event::OnUserModeAdd(&Event::UserModeAdd::OnUserModeAdd, um);
return true;
@@ -344,7 +420,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())
@@ -353,24 +431,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);
+
Event::OnChannelModeAdd(&Event::ChannelModeAdd::OnChannelModeAdd, cm);
return true;
@@ -382,16 +465,20 @@ void ModeManager::RemoveUserMode(UserMode *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);
}
@@ -400,52 +487,59 @@ void ModeManager::RemoveChannelMode(ChannelMode *cm)
if (!cm)
return;
- unsigned want = cm->mchar;
- if (want >= ModeManager::ChannelModes.size())
- return;
-
- if (ModeManager::ChannelModes[want] != cm)
- return;
-
- ModeManager::ChannelModes[want] = NULL;
+ if (cm->mchar)
+ {
+ unsigned want = cm->mchar;
+ if (want >= ChannelModesIdx.size())
+ return;
+
+ if (ChannelModesIdx[want] != cm)
+ return;
+
+ 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)
@@ -467,10 +561,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;
@@ -503,9 +597,9 @@ static struct StatusSort
void ModeManager::RebuildStatusModes()
{
ChannelModesByStatus.clear();
- for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j)
+ for (unsigned j = 0; j < ChannelModesIdx.size(); ++j)
{
- ChannelMode *cm = ModeManager::GetChannelModes()[j];
+ ChannelMode *cm = ChannelModesIdx[j];
if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm));
@@ -712,7 +806,7 @@ Entry::Entry(const Anope::string &m, const Anope::string &fh) : name(m), mask(fh
this->host = cidr_ip;
- Log(LOG_DEBUG) << "Ban " << this->mask << " has cidr " << this->cidr_len;
+ Log(LOG_DEBUG) << "Ban " << m << " has cidr " << this->cidr_len;
}
}
catch (const ConvertException &) { }
@@ -728,6 +822,14 @@ const Anope::string Entry::GetMask() const
return this->mask;
}
+const Anope::string Entry::GetNUHMask() const
+{
+ Anope::string n = nick.empty() ? "*" : nick,
+ u = user.empty() ? "*" : user,
+ h = host.empty() ? "*" : host;
+ return n + "!" + u + "@" + h;
+}
+
bool Entry::Matches(User *u, bool full) const
{
/* First check if this mode has defined any matches (usually for extbans). */
@@ -768,7 +870,7 @@ bool Entry::Matches(User *u, bool full) const
}
}
else if (!this->host.empty() && !Anope::Match(u->GetDisplayedHost(), this->host) && !Anope::Match(u->GetCloakedHost(), this->host) &&
- (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip, this->host))))
+ (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->ip.addr(), this->host))))
ret = false;
if (!this->real.empty() && !Anope::Match(u->realname, this->real))