diff options
author | Adam <Adam@anope.org> | 2012-02-26 23:23:15 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-02-26 23:23:15 -0500 |
commit | a5b9e235ae240439608aa743c9ebb3bf6e7d342a (patch) | |
tree | 9c3040b865ace191c224a94ef525ab60581c6ba5 | |
parent | a78790eac4da788a8432d0b83fa72de7853dd697 (diff) |
Added chanserv:require config option to set which modes must be on all registered channels. Prevents the core from always enforcing +r on every channel, even if chanserv is not loaded.
-rw-r--r-- | data/chanserv.example.conf | 20 | ||||
-rw-r--r-- | data/example.conf | 12 | ||||
-rw-r--r-- | include/channels.h | 4 | ||||
-rw-r--r-- | include/config.h | 2 | ||||
-rw-r--r-- | include/modules.h | 9 | ||||
-rw-r--r-- | include/regchannel.h | 2 | ||||
-rw-r--r-- | modules/commands/cs_clone.cpp | 2 | ||||
-rw-r--r-- | modules/commands/cs_drop.cpp | 7 | ||||
-rw-r--r-- | modules/commands/cs_mode.cpp | 2 | ||||
-rw-r--r-- | modules/commands/cs_register.cpp | 12 | ||||
-rw-r--r-- | modules/commands/cs_set_persist.cpp | 7 | ||||
-rw-r--r-- | modules/protocol/inspircd-ts6.h | 3 | ||||
-rw-r--r-- | modules/pseudoclients/chanserv.cpp | 13 | ||||
-rw-r--r-- | src/channels.cpp | 124 | ||||
-rw-r--r-- | src/chanserv.cpp | 83 | ||||
-rw-r--r-- | src/config.cpp | 5 | ||||
-rw-r--r-- | src/modes.cpp | 2 | ||||
-rw-r--r-- | src/servers.cpp | 2 |
18 files changed, 139 insertions, 172 deletions
diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index f3310b745..312b10dca 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -171,6 +171,26 @@ chanserv * This directive is optional. */ #opersonly = yes + + /* + * Default modes for mode lock, these are set on newly registered channels. + * + * If not set, the default is +nrt. + */ + mlock = "+nrt" + + /* + * Modes that will not be allowed to be locked. Oper only modes such as +O + * are always restricted from regular users and are not affected by this. + * Comment out for no restrictions. + */ + #nomlock = "P" + + /* + * Modes that are required to be set and only set on all registered channels. + * These modes can not be locked or unlocked. + */ + require = "r" } /* diff --git a/data/example.conf b/data/example.conf index a746051c0..5744265f0 100644 --- a/data/example.conf +++ b/data/example.conf @@ -465,18 +465,6 @@ options #ulineservers = "stats.your.network" /* - * Default modes for mode lock, these are set on newly registered channels. - */ - mlock = "+nrt" - - /* - * Modes that will not be allowed to be locked. Oper only modes such as +O - * are always restricted from regular users and are not affected by this. - * Comment out for no restrictions. - */ - nomlock = "z" - - /* * Modes to set on service bots when they join channels, comment this out for no modes * * This directive is optional. diff --git a/include/channels.h b/include/channels.h index a4803fe00..eadde3df5 100644 --- a/include/channels.h +++ b/include/channels.h @@ -86,6 +86,10 @@ class CoreExport Channel : public Base, public Extensible, public Flags<ChannelF */ void Sync(); + /** Check if a channels modes are correct. + */ + void CheckModes(); + /** Join a user internally to the channel * @param u The user */ diff --git a/include/config.h b/include/config.h index 99d116daa..9daa56022 100644 --- a/include/config.h +++ b/include/config.h @@ -446,6 +446,8 @@ class CoreExport ServerConfig Anope::string MLock; /* Unmlockable modes */ Anope::string NoMLock; + /* Modes that are required to be on registered channels */ + Anope::string CSRequire; /* Default botmodes on channels, defaults to ao */ Anope::string BotModes; /* THe actual modes */ diff --git a/include/modules.h b/include/modules.h index ce6bbba51..29e6c0881 100644 --- a/include/modules.h +++ b/include/modules.h @@ -938,6 +938,13 @@ class CoreExport Module : public Extensible * @param l The log message */ virtual void OnLog(Log *l) { } + + /** Called when a channels modes are being checked to see if they are allowed, + * mostly to ensure mlock/+r are set. + * @param c The channel + * @return EVENT_STOP to stop checking modes + */ + virtual EventReturn OnCheckModes(Channel *c) { return EVENT_CONTINUE; } }; /** Implementation-specific flags which may be set in ModuleManager::Attach() @@ -957,7 +964,7 @@ enum Implementation /* ChanServ */ I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, I_OnAccessDel, I_OnAccessClear, I_OnLevelChange, I_OnChanRegistered, I_OnChanUnsuspend, I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, - I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick, + I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick, I_OnCheckModes, I_OnChanInfo, I_OnFindChan, I_OnCheckPriv, I_OnGroupCheckPriv, /* BotServ */ diff --git a/include/regchannel.h b/include/regchannel.h index 93a242a28..d7c6a8492 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -437,8 +437,6 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag, void ClearLevels(); }; -extern void check_modes(Channel *c); - extern ChannelInfo *cs_findchan(const Anope::string &chan); extern bool IsFounder(User *user, ChannelInfo *ci); extern void update_cs_lastseen(User *user, ChannelInfo *ci); diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index 8205b723c..1676c70f6 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -67,7 +67,7 @@ public: { target_ci->c->ci = target_ci; - check_modes(target_ci->c); + target_ci->c->CheckModes(); ChannelMode *cm; if (u->FindChannel(target_ci->c) != NULL) diff --git a/modules/commands/cs_drop.cpp b/modules/commands/cs_drop.cpp index e9736851a..abdbed17e 100644 --- a/modules/commands/cs_drop.cpp +++ b/modules/commands/cs_drop.cpp @@ -53,16 +53,17 @@ class CommandCSDrop : public Command return; } - if (ci->c && ModeManager::FindChannelModeByName(CMODE_REGISTERED)) - ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); - bool override = (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !ci->AccessFor(u).HasPriv("FOUNDER")); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "(founder was: " << (ci->GetFounder() ? ci->GetFounder()->display : "none") << ")"; + Channel *c = ci->c; delete ci; source.Reply(_("Channel \002%s\002 has been dropped."), chan.c_str()); + if (c) + c->CheckModes(); + FOREACH_MOD(I_OnChanDrop, OnChanDrop(chan)); return; diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index c2b9c7de4..c9d7c112a 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -96,7 +96,7 @@ class CommandCSMode : public Command } if (ci->c) - check_modes(ci->c); + ci->c->CheckModes(); } else if (subcommand.equals_ci("DEL") && !param.empty()) { diff --git a/modules/commands/cs_register.cpp b/modules/commands/cs_register.cpp index 633364d31..570fd8125 100644 --- a/modules/commands/cs_register.cpp +++ b/modules/commands/cs_register.cpp @@ -76,7 +76,7 @@ class CommandCSRegister : public Command /* Implement new mode lock */ if (c) { - check_modes(c); + c->CheckModes(); ChannelMode *cm; if (u->FindChannel(c) != NULL) @@ -138,16 +138,6 @@ class CSRegister : public Module commandcsregister(this) { this->SetAuthor("Anope"); - - ModuleManager::Attach(I_OnDelChan, this); - } - - void OnDelChan(ChannelInfo *ci) anope_override - { - if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) - ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); - if (ci->c && ci->HasFlag(CI_PERSIST)) - ci->c->RemoveMode(NULL, CMODE_PERM, "", false); } }; diff --git a/modules/commands/cs_set_persist.cpp b/modules/commands/cs_set_persist.cpp index 4a1d676dd..b9d4d2c35 100644 --- a/modules/commands/cs_set_persist.cpp +++ b/modules/commands/cs_set_persist.cpp @@ -172,6 +172,13 @@ class CSSetPersist : public Module { this->SetAuthor("Anope"); + ModuleManager::Attach(I_OnDelChan, this); + } + + void OnDelChan(ChannelInfo *ci) anope_override + { + if (ci->c && ci->HasFlag(CI_PERSIST)) + ci->c->RemoveMode(NULL, CMODE_PERM, "", false); } }; diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index a079d54ce..964232080 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -411,9 +411,6 @@ class InspircdIRCdMessage : public IRCdMessage { c->creation_time = ts; c->Reset(); - - /* Reset mlock */ - check_modes(c); } /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ else if (ts > c->creation_time) diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index b5deaf284..f1ad3ec6a 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -65,7 +65,7 @@ class ChanServCore : public Module if (ChanServ == NULL) throw ModuleException("No bot named " + Config->ChanServ); - Implementation i[] = { I_OnBotPrivmsg, I_OnDelCore, I_OnPreHelp, I_OnPostHelp }; + Implementation i[] = { I_OnBotPrivmsg, I_OnDelCore, I_OnPreHelp, I_OnPostHelp, I_OnCheckModes }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); } @@ -179,6 +179,17 @@ class ChanServCore : public Module "any channel, view (and modify) the access, levels and akick\n" "lists and settings for any channel.")); } + + EventReturn OnCheckModes(Channel *c) anope_override + { + if (!Config->CSRequire.empty()) + if (c->ci) + c->SetModes(NULL, false, "+%s", Config->CSRequire.c_str()); + else + c->SetModes(NULL, false, "-%s", Config->CSRequire.c_str()); + + return EVENT_CONTINUE; + } }; MODULE_INIT(ChanServCore) diff --git a/src/channels.cpp b/src/channels.cpp index a04abff52..92bf9b7e3 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -91,7 +91,8 @@ void Channel::Reset() } } - check_modes(this); + this->CheckModes(); + for (CUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) chan_set_correct_modes((*it)->user, this, 1); @@ -107,13 +108,81 @@ void Channel::Sync() } if (this->ci) { - check_modes(this); + this->CheckModes(); if (Me && Me->IsSynced()) this->ci->RestoreTopic(); } } +void Channel::CheckModes() +{ + if (this->bouncy_modes) + return; + + /* Check for mode bouncing */ + if (this->server_modecount >= 3 && this->chanserv_modecount >= 3) + { + Log() << "Warning: unable to set modes on channel " << this->name << ". Are your servers' U:lines configured correctly?"; + this->bouncy_modes = 1; + return; + } + + if (this->chanserv_modetime != Anope::CurTime) + { + this->chanserv_modecount = 0; + this->chanserv_modetime = Anope::CurTime; + } + this->chanserv_modecount++; + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnCheckModes, OnCheckModes(this)); + if (MOD_RESULT == EVENT_STOP) + return; + + if (this->ci) + for (std::multimap<ChannelModeName, ModeLock>::const_iterator it = this->ci->GetMLock().begin(), it_end = this->ci->GetMLock().end(); it != it_end; ++it) + { + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm) + continue; + + if (cm->Type == MODE_REGULAR) + { + if (!this->HasMode(cm->Name) && ml.set) + this->SetMode(NULL, cm); + else if (this->HasMode(cm->Name) && !ml.set) + this->RemoveMode(NULL, cm); + } + else if (cm->Type == MODE_PARAM) + { + /* If the channel doesnt have the mode, or it does and it isn't set correctly */ + if (ml.set) + { + Anope::string param; + this->GetParam(cm->Name, param); + + if (!this->HasMode(cm->Name) || (!param.empty() && !ml.param.empty() && !param.equals_cs(ml.param))) + this->SetMode(NULL, cm, ml.param); + } + else + { + if (this->HasMode(cm->Name)) + this->RemoveMode(NULL, cm); + } + + } + else if (cm->Type == MODE_LIST) + { + if (ml.set) + this->SetMode(NULL, cm, ml.param); + else + this->RemoveMode(NULL, cm, ml.param); + } + } +} + void Channel::JoinUser(User *user) { Log(user, this, "join"); @@ -333,43 +402,7 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool if (!EnforceMLock || MOD_RESULT == EVENT_STOP) return; - /* Non registered channels can not be +r */ - if (!ci && HasMode(CMODE_REGISTERED)) - RemoveMode(NULL, CMODE_REGISTERED); - - /* Non registered channel has no mlock */ - if (!ci) - return; - - ModeLock *ml = ci->GetMLock(cm->Name, cm->Type == MODE_PARAM ? "" : param); - if (ml) - { - if (ml->set && cm->Type == MODE_PARAM) - { - Anope::string cparam; - this->GetParam(cm->Name, cparam); - - /* We have the wrong param set */ - if (cparam.empty() || ml->param.empty() || !cparam.equals_cs(ml->param)) - /* Reset the mode with the correct param */ - this->SetMode(NULL, cm, ml->param); - } - else if (!ml->set) - { - if (cm->Type == MODE_REGULAR) - this->RemoveMode(NULL, cm); - else if (cm->Type == MODE_PARAM) - { - Anope::string cparam; - this->GetParam(cm->Name, cparam); - this->RemoveMode(NULL, cm, cparam); - } - else if (cm->Type == MODE_LIST) - { - this->RemoveMode(NULL, cm, param); - } - } - } + this->CheckModes(); } /** Remove a mode internally on a channel, this is not sent out to the IRCd @@ -459,19 +492,10 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string ¶m, bo /* Check for mlock */ - /* Non registered channel, no mlock */ - if (!ci || !EnforceMLock || MOD_RESULT == EVENT_STOP) + if (!EnforceMLock || MOD_RESULT == EVENT_STOP) return; - ModeLock *ml = ci->GetMLock(cm->Name, param); - /* This channel has this the mode locked on */ - if (ml && ml->set) - { - if (cm->Type == MODE_REGULAR) - this->SetMode(NULL, cm); - else if (cm->Type == MODE_PARAM || cm->Type == MODE_LIST) - this->SetMode(NULL, cm, ml->param); - } + this->CheckModes(); } /** Set a mode on a channel diff --git a/src/chanserv.cpp b/src/chanserv.cpp index f18c919cc..fd7fb88f9 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -22,89 +22,6 @@ registered_channel_map RegisteredChannelList; /*************************************************************************/ -/* Check the current modes on a channel; if they conflict with a mode lock, - * fix them. - */ - -void check_modes(Channel *c) -{ - if (!c) - { - Log() << "check_modes called with NULL values"; - return; - } - - if (c->bouncy_modes) - return; - - /* Check for mode bouncing */ - if (c->server_modecount >= 3 && c->chanserv_modecount >= 3) - { - Log() << "Warning: unable to set modes on channel " << c->name << ". Are your servers' U:lines configured correctly?"; - c->bouncy_modes = 1; - return; - } - - if (c->chanserv_modetime != Anope::CurTime) - { - c->chanserv_modecount = 0; - c->chanserv_modetime = Anope::CurTime; - } - c->chanserv_modecount++; - - /* Check if the channel is registered; if not remove mode -r */ - ChannelInfo *ci = c->ci; - if (!ci) - { - if (c->HasMode(CMODE_REGISTERED)) - c->RemoveMode(NULL, CMODE_REGISTERED); - return; - } - - for (std::multimap<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) - { - const ModeLock &ml = it->second; - ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); - if (!cm) - continue; - - if (cm->Type == MODE_REGULAR) - { - if (!c->HasMode(cm->Name) && ml.set) - c->SetMode(NULL, cm); - else if (c->HasMode(cm->Name) && !ml.set) - c->RemoveMode(NULL, cm); - } - else if (cm->Type == MODE_PARAM) - { - Anope::string param; - c->GetParam(cm->Name, param); - - /* If the channel doesnt have the mode, or it does and it isn't set correctly */ - if (ml.set) - { - if (!c->HasMode(cm->Name) || (!param.empty() && !ml.param.empty() && !param.equals_cs(ml.param))) - c->SetMode(NULL, cm, ml.param); - } - else - { - if (c->HasMode(cm->Name)) - c->RemoveMode(NULL, cm); - } - - } - else if (cm->Type == MODE_LIST) - { - if (ml.set) - c->SetMode(NULL, cm, ml.param); - else - c->RemoveMode(NULL, cm, ml.param); - } - } -} - -/*************************************************************************/ - ChannelInfo *cs_findchan(const Anope::string &chan) { FOREACH_MOD(I_OnFindChan, OnFindChan(chan)); diff --git a/src/config.cpp b/src/config.cpp index 524e669fa..5093e9963 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1153,8 +1153,6 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"options", "restrictopernicks", "no", new ValueContainerBool(&conf->RestrictOperNicks), DT_BOOLEAN, NoValidation}, {"options", "newscount", "3", new ValueContainerUInt(&conf->NewsCount), DT_UINTEGER, NoValidation}, {"options", "ulineservers", "", new ValueContainerString(&UlineServers), DT_STRING, NoValidation}, - {"options", "mlock", "+nrt", new ValueContainerString(&conf->MLock), DT_STRING, NoValidation}, - {"options", "nomlock", "", new ValueContainerString(&conf->NoMLock), DT_STRING, NoValidation}, {"options", "botmodes", "", new ValueContainerString(&conf->BotModes), DT_STRING, NoValidation}, {"options", "retrywait", "60", new ValueContainerInt(&conf->RetryWait), DT_INTEGER, ValidateNotZero}, {"options", "hideprivilegedcommands", "no", new ValueContainerBool(&conf->HidePrivilegedCommands), DT_BOOLEAN, NoValidation}, @@ -1217,6 +1215,9 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"chanserv", "inhabit", "0", new ValueContainerTime(&conf->CSInhabit), DT_TIME, ValidateChanServ}, {"chanserv", "listmax", "0", new ValueContainerUInt(&conf->CSListMax), DT_UINTEGER, ValidateChanServ}, {"chanserv", "opersonly", "no", new ValueContainerBool(&conf->CSOpersOnly), DT_BOOLEAN, ValidateChanServ}, + {"chanserv", "mlock", "+nrt", new ValueContainerString(&conf->MLock), DT_STRING | DT_ALLOW_EMPTY, NoValidation}, + {"chanserv", "nomlock", "", new ValueContainerString(&conf->NoMLock), DT_STRING, NoValidation}, + {"chanserv", "require", "", new ValueContainerString(&conf->CSRequire), DT_STRING, NoValidation}, {"memoserv", "name", "", new ValueContainerString(&conf->MemoServ), DT_STRING, NoValidation}, {"memoserv", "maxmemos", "0", new ValueContainerUInt(&conf->MSMaxMemos), DT_UINTEGER, NoValidation}, {"memoserv", "senddelay", "0", new ValueContainerTime(&conf->MSSendDelay), DT_TIME, NoValidation}, diff --git a/src/modes.cpp b/src/modes.cpp index 580c9f2d7..cbfdc093b 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -178,7 +178,7 @@ ChannelMode::~ChannelMode() */ bool ChannelMode::CanSet(User *u) const { - if (Config->NoMLock.find(this->ModeChar) != Anope::string::npos) + if (Config->NoMLock.find(this->ModeChar) != Anope::string::npos || Config->CSRequire.find(this->ModeChar) != Anope::string::npos) return false; return true; } diff --git a/src/servers.cpp b/src/servers.cpp index 944285c42..51b47f6c7 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -313,7 +313,7 @@ void Server::Sync(bool SyncLinks) for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) { Channel *c = it->second; - check_modes(c); + c->CheckModes(); if (c->ci) c->ci->RestoreTopic(); } |