diff --git a/include/modules.h b/include/modules.h index cfa639d08..df917581d 100644 --- a/include/modules.h +++ b/include/modules.h @@ -967,6 +967,20 @@ class CoreExport Module */ virtual void OnUserModeAdd(UserMode *um) { } + /** Called when a mode is about to be mlocked + * @param Name The mode being mlocked + * @param status true if its being mlocked +, false for - + * @param param The param, if there is one and if status is true + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock. + */ + virtual EventReturn OnMLock(ChannelModeName Name, bool status, const std::string ¶m) { return EVENT_CONTINUE; } + + /** Called when a mode is about to be unlocked + * @param Name The mode being mlocked + * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock. + */ + virtual EventReturn OnUnMLock(ChannelModeName Name) { return EVENT_CONTINUE; } + }; @@ -1009,6 +1023,7 @@ enum Implementation I_OnServerQuit, I_OnTopicUpdated, I_OnEncrypt, I_OnEncryptInPlace, I_OnEncryptCheckLen, I_OnDecrypt, I_OnCheckPassword, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, + I_OnMLock, I_OnUnMLock, I_END }; diff --git a/include/regchannel.h b/include/regchannel.h index eda83a1b7..8a906c818 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -62,7 +62,7 @@ enum ChannelInfoFlag class CoreExport ChannelInfo : public Extensible, public Flags { private: - std::map Params; /* Map of parameters by mode name */ + std::map Params; /* Map of parameters by mode name for mlock */ std::vector access; /* List of authorized users */ std::vector akick; /* List of users to kickban */ std::vector badwords; /* List of badwords */ @@ -253,14 +253,16 @@ class CoreExport ChannelInfo : public Extensible, public Flags /** Set a mlock * @param Name The mode * @param status True for mlock on, false for mlock off + * @param param An optional param arg for + mlocked modes + * @return true on success, false on failure (module blocking) */ - void SetMLock(ChannelModeName Name, bool status); + bool SetMLock(ChannelModeName Name, bool status, const std::string param = ""); /** Remove a mlock * @param Name The mode - * @param status True for mlock on, false for mlock off + * @return true on success, false on failure (module blcoking) */ - void RemoveMLock(ChannelModeName Name, bool status); + bool RemoveMLock(ChannelModeName Name); /** Clear all mlocks on the channel */ @@ -272,18 +274,6 @@ class CoreExport ChannelInfo : public Extensible, public Flags */ const size_t GetMLockCount(bool status) const; - /** Set a channel mode param on the channel - * @param Name The mode - * @param param The param - * @param true on success - */ - bool SetParam(ChannelModeName Name, std::string Value); - - /** Unset a param from the channel - * @param Name The mode - */ - void UnsetParam(ChannelModeName Name); - /** Get a param from the channel * @param Name The mode * @param Target a string to put the param into diff --git a/include/services.h b/include/services.h index 5a8e84ee0..f8e48aa8a 100644 --- a/include/services.h +++ b/include/services.h @@ -989,14 +989,16 @@ class CoreExport Channel : public Extensible /** * Set a mode on a channel * @param Name The mode name + * @param param Optional param arg for the mode */ - void SetMode(ChannelModeName Name); + void SetMode(ChannelModeName Name, const std::string param = ""); /** * Set a mode on a channel * @param Mode The mode + * @param param Optional param arg for the mode */ - void SetMode(char Mode); + void SetMode(char Mode, const std::string param = ""); /** * Remove a mode from a channel @@ -1030,18 +1032,6 @@ class CoreExport Channel : public Extensible */ void ClearInvites(char *client = NULL); - /** Set a channel mode param on the channel - * @param Name The mode - * @param param The param - * @param true on success - */ - bool SetParam(ChannelModeName Name, std::string ¶m); - - /** Unset a param from the channel - * @param Name The mode - */ - void UnsetParam(ChannelModeName Name); - /** Get a param from the channel * @param Name The mode * @param Target a string to put the param into diff --git a/src/channels.c b/src/channels.c index ef5e225f6..e6ee45430 100644 --- a/src/channels.c +++ b/src/channels.c @@ -137,7 +137,7 @@ bool Channel::HasMode(ChannelModeName Name) * Set a mode on a channel * @param Name The mode name */ -void Channel::SetMode(ChannelModeName Name) +void Channel::SetMode(ChannelModeName Name, const std::string param) { modes[Name] = true; @@ -147,6 +147,18 @@ void Channel::SetMode(ChannelModeName Name) ci->SetFlag(CI_PERSIST); } + if (!param.empty()) + { + /* They could be resetting the mode to change its params */ + std::map::iterator it = Params.find(Name); + if (it != Params.end()) + { + Params.erase(it); + } + + Params.insert(std::make_pair(Name, param)); + } + FOREACH_MOD(I_OnChannelModeSet, OnChannelModeSet(this, Name)); } @@ -154,13 +166,13 @@ void Channel::SetMode(ChannelModeName Name) * Set a mode on a channel * @param Mode The mode */ -void Channel::SetMode(char Mode) +void Channel::SetMode(char Mode, const std::string param) { ChannelMode *cm; if ((cm = ModeManager::FindChannelModeByChar(Mode))) { - SetMode(cm->Name); + SetMode(cm->Name, param); } } @@ -181,6 +193,12 @@ void Channel::RemoveMode(ChannelModeName Name) delete this; } + std::map::iterator it = Params.find(Name); + if (it != Params.end()) + { + Params.erase(it); + } + FOREACH_MOD(I_OnChannelModeUnset, OnChannelModeUnset(this, Name)); } @@ -198,29 +216,6 @@ void Channel::RemoveMode(char Mode) } } -/** Set a channel mode param on the channel - * @param Name The mode - * @param param The param - * @param true on success - */ -bool Channel::SetParam(ChannelModeName Name, std::string &Value) -{ - return Params.insert(std::make_pair(Name, Value)).second; -} - -/** Unset a param from the channel - * @param Name The mode - */ -void Channel::UnsetParam(ChannelModeName Name) -{ - std::map::iterator it = Params.find(Name); - - if (it != Params.end()) - { - Params.erase(it); - } -} - /** Get a param from the channel * @param Name The mode * @param Target a string to put the param into @@ -677,14 +672,6 @@ void chan_set_modes(const char *source, Channel *chan, int ac, const char **av, } else { - if (check >= 0) - { - if (add) - chan->SetMode(mode); - else - chan->RemoveMode(mode); - } - if (cm->Type == MODE_PARAM) { cmp = static_cast(cm); @@ -701,18 +688,19 @@ void chan_set_modes(const char *source, Channel *chan, int ac, const char **av, av++; } - if (*av && !cmp->IsValid(*av)) + if (!cmp->IsValid(*av)) continue; if (add) { std::string Param = *av; - chan->SetParam(cmp->Name, Param); + chan->SetMode(mode, Param); } else - chan->UnsetParam(cmp->Name); + { + chan->RemoveMode(mode); + } } - - if (check < 0) + else { if (add) chan->SetMode(mode); diff --git a/src/chanserv.c b/src/chanserv.c index 6413e468b..19ab774f1 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -483,27 +483,27 @@ void load_cs_dbase() { std::ostringstream limit; limit << tmp32; - ci->SetParam(CMODE_LIMIT, limit.str()); + ci->SetMLock(CMODE_LIMIT, true, limit.str()); } SAFE(read_string(&s, f)); if (s) { - ci->SetParam(CMODE_KEY, std::string(s)); + ci->SetMLock(CMODE_KEY, true, std::string(s)); delete [] s; } SAFE(read_string(&s, f)); if (s) { - ci->SetParam(CMODE_FLOOD, std::string(s)); + ci->SetMLock(CMODE_FLOOD, true, std::string(s)); delete [] s; } SAFE(read_string(&s, f)); if (s) { - ci->SetParam(CMODE_REDIRECT, std::string(s)); + ci->SetMLock(CMODE_REDIRECT, true, std::string(s)); delete [] s; } @@ -836,7 +836,7 @@ void check_modes(Channel * c) cm = it->second; /* If this channel does not have the mode and the mode is mlocked */ - if (!c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true)) + if (cm->Type == MODE_REGULAR && !c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true)) { modebuf += it->first; c->SetMode(cm->Name); @@ -853,18 +853,19 @@ void check_modes(Channel * c) } } } - /* If this is a param mode and its mlocked and is set negative */ - else if (cm->Type == MODE_PARAM && c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true)) + /* If this is a param mode and its mlocked, check to ensure it is set and set to the correct value */ + else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true)) { cmp = static_cast(cm); c->GetParam(cmp->Name, ¶m); ci->GetParam(cmp->Name, &ciparam); - if (!param.empty() && !ciparam.empty() && param != ciparam) + /* If the channel doesnt have the mode, or it does and it isn't set correctly */ + if (!c->HasMode(cm->Name) || (!param.empty() && !ciparam.empty() && param != ciparam)) { modebuf += it->first; - c->SetParam(cmp->Name, ciparam); + c->SetMode(cmp->Name, ciparam); argbuf += " " + ciparam; } diff --git a/src/core/cs_set.c b/src/core/cs_set.c index b70a528f3..54c397c52 100644 --- a/src/core/cs_set.c +++ b/src/core/cs_set.c @@ -208,6 +208,8 @@ class CommandCSSet : public Command } else if (add) { + ci->RemoveMLock(cm->Name); + if (cm->Type == MODE_PARAM) { cmp = static_cast(cm); @@ -218,27 +220,16 @@ class CommandCSSet : public Command if (!cmp->IsValid(param.c_str())) continue; - ci->SetParam(cmp->Name, param); + ci->SetMLock(cmp->Name, true, param); + } + else + { + ci->SetMLock(cm->Name, true); } - - ci->SetMLock(cm->Name, true); - ci->RemoveMLock(cm->Name, false); } else { ci->SetMLock(cm->Name, false); - - if (ci->HasMLock(cm->Name, true)) - { - ci->RemoveMLock(cm->Name, true); - - if (cm->Type == MODE_PARAM) - { - cmp = static_cast(cm); - - ci->UnsetParam(cmp->Name); - } - } } } else @@ -249,8 +240,7 @@ class CommandCSSet : public Command /* We can't mlock +L if +l is not mlocked as well. */ if (ci->HasMLock(CMODE_REDIRECT, true) && !ci->HasMLock(CMODE_LIMIT, true)) { - ci->RemoveMLock(CMODE_REDIRECT, true); - ci->UnsetParam(CMODE_REDIRECT); + ci->RemoveMLock(CMODE_REDIRECT); notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_L_REQUIRED); } } @@ -260,7 +250,7 @@ class CommandCSSet : public Command if (ModeManager::FindChannelModeByName(CMODE_NOKNOCK) && ircd->knock_needs_i) { if (ci->HasMLock(CMODE_NOKNOCK, true) && !ci->HasMLock(CMODE_INVITE, true)) { - ci->RemoveMLock(CMODE_NOKNOCK, true); + ci->RemoveMLock(CMODE_NOKNOCK); notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_K_REQUIRED); } } diff --git a/src/core/os_defcon.c b/src/core/os_defcon.c index fdcecc525..044eb54ac 100644 --- a/src/core/os_defcon.c +++ b/src/core/os_defcon.c @@ -200,14 +200,15 @@ class OSDEFCON : public Module std::string param; GetDefConParam(Name, ¶m); - c->SetMode(Name); - std::string buf = "+" + std::string(&cm->ModeChar); if (!param.empty()) { buf += " " + param; - c->SetParam(Name, param); + c->SetMode(Name, param); } + else + c->SetMode(Name); + ircdproto->SendMode(findbot(s_OperServ), c->name, buf.c_str()); } } @@ -496,7 +497,6 @@ void defconParseModeString(const char *str) { DefConModesOn.UnsetFlag(CMODE_REDIRECT); - //DefConModesCI.UnsetParam(CMODE_REDIRECT); alog("DefConChanModes must lock mode +l as well to lock mode +L"); } } diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 6bf2c64fe..4d1e1cf7d 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -416,29 +416,67 @@ const bool ChannelInfo::HasMLock(ChannelModeName Name, bool status) /** Set a mlock * @param Name The mode * @param status True for mlock on, false for mlock off + * @param param The param to use for this mode, if required + * @return true on success, false on failure (module blocking) */ -void ChannelInfo::SetMLock(ChannelModeName Name, bool status) +bool ChannelInfo::SetMLock(ChannelModeName Name, bool status, const std::string param) { size_t value = Name; + if (!status && !param.empty()) + throw CoreException("Was told to mlock a mode negatively with a param?"); + + EventReturn MOD_RESULT; + FOREACH_MOD(I_OnMLock, OnMLock(Name, status, param)); + if (MOD_RESULT == EVENT_STOP) + return false; + + /* First, remove this everywhere */ + mlock_on[value] = false; + mlock_off[value] = false; + + std::map::iterator it = Params.find(Name); + if (it != Params.end()) + { + Params.erase(it); + } + if (status) mlock_on[value] = true; else mlock_off[value] = true; + + if (status && !param.empty()) + { + Params.insert(std::make_pair(Name, param)); + } + + return true; } /** Remove a mlock * @param Name The mode - * @param status True for mlock on, false for mlock off + * @return true on success, false on failure (module blocking) */ -void ChannelInfo::RemoveMLock(ChannelModeName Name, bool status) +bool ChannelInfo::RemoveMLock(ChannelModeName Name) { size_t value = Name; - if (status) - mlock_on[value] = false; - else - mlock_off[value] = false; + EventReturn MOD_RESULT; + FOREACH_MOD(I_OnUnMLock, OnUnMLock(Name)); + if (MOD_RESULT == EVENT_STOP) + return false; + + mlock_on[value] = false; + mlock_off[value] = false; + + std::map::iterator it = Params.find(Name); + if (it != Params.end()) + { + Params.erase(it); + } + + return true; } /** Clear all mlocks on the channel @@ -461,29 +499,6 @@ const size_t ChannelInfo::GetMLockCount(bool status) const return mlock_off.count(); } -/** Set a channel mode param on the channel - * @param Name The mode - * @param param The param - * @param true on success - */ -bool ChannelInfo::SetParam(ChannelModeName Name, std::string Value) -{ - return Params.insert(std::make_pair(Name, Value)).second; -} - -/** Unset a param from the channel - * @param Name The mode - */ -void ChannelInfo::UnsetParam(ChannelModeName Name) -{ - std::map::iterator it = Params.find(Name); - - if (it != Params.end()) - { - Params.erase(it); - } -} - /** Get a param from the channel * @param Name The mode * @param Target a string to put the param into