diff options
Diffstat (limited to 'src/modes.cpp')
-rw-r--r-- | src/modes.cpp | 194 |
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 ¶m) +{ + return this; +} + +ChannelMode *ChannelMode::Unwrap(Anope::string ¶m) +{ + 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 ¶m) +{ + 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 ¶m) +{ + 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)) |