summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2012-02-26 23:23:15 -0500
committerAdam <Adam@anope.org>2012-02-26 23:23:15 -0500
commita5b9e235ae240439608aa743c9ebb3bf6e7d342a (patch)
tree9c3040b865ace191c224a94ef525ab60581c6ba5
parenta78790eac4da788a8432d0b83fa72de7853dd697 (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.conf20
-rw-r--r--data/example.conf12
-rw-r--r--include/channels.h4
-rw-r--r--include/config.h2
-rw-r--r--include/modules.h9
-rw-r--r--include/regchannel.h2
-rw-r--r--modules/commands/cs_clone.cpp2
-rw-r--r--modules/commands/cs_drop.cpp7
-rw-r--r--modules/commands/cs_mode.cpp2
-rw-r--r--modules/commands/cs_register.cpp12
-rw-r--r--modules/commands/cs_set_persist.cpp7
-rw-r--r--modules/protocol/inspircd-ts6.h3
-rw-r--r--modules/pseudoclients/chanserv.cpp13
-rw-r--r--src/channels.cpp124
-rw-r--r--src/chanserv.cpp83
-rw-r--r--src/config.cpp5
-rw-r--r--src/modes.cpp2
-rw-r--r--src/servers.cpp2
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 &param, 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 &param, 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();
}