diff options
author | Adam <Adam@anope.org> | 2014-04-25 16:51:06 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2014-04-25 16:51:06 -0400 |
commit | 6a03eb69ebbe773f1d4139ff88d74ecdb2b0af4b (patch) | |
tree | d370fbc4a1dd55b72dbcda9f2aff24678d5626f3 /src/modes.cpp | |
parent | 4fa2a00bd595eb120e6acde5eb167759c2018e33 (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/modes.cpp')
-rw-r--r-- | src/modes.cpp | 160 |
1 files changed, 123 insertions, 37 deletions
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 ¶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; @@ -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 ¶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"); @@ -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); |