summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2015-10-27 18:57:37 -0400
committerAdam <Adam@anope.org>2015-10-27 18:58:48 -0400
commit64dac60071fab652745a6e7a06cf6b7bdbbd3625 (patch)
treef8f30161150451672b381f6370a8fdcab654bbb8 /modules
parent162fdbe5815bbdf187f549fefac94ff476d72e62 (diff)
parent830361e97d03c74e54cb1cf1bbf329dffdeb66f7 (diff)
Merge branch '2.0' into 2.1
Diffstat (limited to 'modules')
-rw-r--r--modules/commands/bs_bot.cpp12
-rw-r--r--modules/commands/cs_access.cpp12
-rw-r--r--modules/commands/cs_ban.cpp39
-rw-r--r--modules/commands/cs_clone.cpp16
-rw-r--r--modules/commands/cs_entrymsg.cpp12
-rw-r--r--modules/commands/cs_kick.cpp28
-rw-r--r--modules/commands/cs_mode.cpp40
-rw-r--r--modules/commands/cs_set.cpp26
-rw-r--r--modules/commands/cs_topic.cpp6
-rw-r--r--modules/commands/hs_del.cpp3
-rw-r--r--modules/commands/hs_group.cpp2
-rw-r--r--modules/commands/hs_list.cpp2
-rw-r--r--modules/commands/hs_off.cpp4
-rw-r--r--modules/commands/hs_on.cpp3
-rw-r--r--modules/commands/hs_set.cpp3
-rw-r--r--modules/commands/ms_read.cpp4
-rw-r--r--modules/commands/ms_set.cpp2
-rw-r--r--modules/commands/ns_alist.cpp2
-rw-r--r--modules/commands/ns_identify.cpp8
-rw-r--r--modules/commands/ns_logout.cpp2
-rw-r--r--modules/commands/ns_register.cpp8
-rw-r--r--modules/commands/ns_set.cpp2
-rw-r--r--modules/commands/os_mode.cpp14
-rw-r--r--modules/database/db_flatfile.cpp2
-rw-r--r--modules/database/db_old.cpp2
-rw-r--r--modules/extra/m_ldap.cpp665
-rw-r--r--modules/extra/m_ldap_authentication.cpp152
-rw-r--r--modules/extra/m_ldap_oper.cpp43
-rw-r--r--modules/extra/m_ssl_openssl.cpp18
-rw-r--r--modules/extra/stats/irc2sql/irc2sql.cpp11
-rw-r--r--modules/extra/stats/irc2sql/irc2sql.h3
-rw-r--r--modules/extra/stats/m_chanstats.cpp9
-rw-r--r--modules/fantasy.cpp28
-rw-r--r--modules/m_dns.cpp16
-rw-r--r--modules/m_xmlrpc.cpp50
-rw-r--r--modules/protocol/bahamut.cpp8
-rw-r--r--modules/protocol/charybdis.cpp4
-rw-r--r--modules/protocol/hybrid.cpp27
-rw-r--r--modules/protocol/inspircd20.cpp58
-rw-r--r--modules/protocol/ngircd.cpp14
-rw-r--r--modules/protocol/ratbox.cpp4
-rw-r--r--modules/protocol/unreal.cpp10
-rw-r--r--modules/pseudoclients/botserv/botserv.cpp6
-rw-r--r--modules/pseudoclients/chanserv/channel.cpp17
-rw-r--r--modules/pseudoclients/chanserv/channel.h4
-rw-r--r--modules/pseudoclients/nickserv/nickserv.cpp44
-rw-r--r--modules/pseudoclients/operserv.cpp8
-rw-r--r--modules/webcpanel/pages/index.cpp6
48 files changed, 846 insertions, 613 deletions
diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp
index 1ba22531e..726c02ab2 100644
--- a/modules/commands/bs_bot.cpp
+++ b/modules/commands/bs_bot.cpp
@@ -82,7 +82,10 @@ class CommandBSBot : public Command
User *targ = User::Find(nick, true);
if (targ)
- targ->Kill(Me, "Nickname is reserved for services");
+ {
+ source.Reply(_("\002{0}\002 is currently in use."), targ->nick);
+ return;
+ }
ServiceBot *bi = new ServiceBot(nick, user, host, real);
@@ -179,6 +182,13 @@ class CommandBSBot : public Command
return;
}
+ User *target = User::Find(nick, true);
+ if (target)
+ {
+ source.Reply(_("\002{0}\002 is currently in use."), target->nick);
+ return;
+ }
+
if (!nick.equals_ci(bi->nick))
{
/* We check whether the nick is registered, and inform the user
diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp
index 982d5763f..f8ecc6c38 100644
--- a/modules/commands/cs_access.cpp
+++ b/modules/commands/cs_access.cpp
@@ -704,7 +704,7 @@ class CommandCSLevels : public Command
{
const Anope::string &what = params[2];
- /* Don't allow disabling of the founder level. It would be hard to change it back if you dont have access to use this command */
+ /* Don't allow disabling of the founder level. It would be hard to change it back if you don't have access to use this command */
if (what.equals_ci("FOUNDER"))
{
source.Reply(_("You can not disable the founder privilege because it would be impossible to reenable it at a later time."));
@@ -804,6 +804,14 @@ class CommandCSLevels : public Command
return;
}
+ bool has_access = false;
+ if (source.HasPriv("chanserv/access/modify"))
+ has_access = true;
+ else if (cmd.equals_ci("LIST") && source.HasPriv("chanserv/access/list"))
+ has_access = true;
+ else if (source.AccessFor(ci).HasPriv("FOUNDER"))
+ has_access = true;
+
/* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only
* one; else, we want none.
*/
@@ -813,7 +821,7 @@ class CommandCSLevels : public Command
return;
}
- if (!source.AccessFor(ci).HasPriv("FOUNDER") && !source.HasPriv("chanserv/access/modify"))
+ if (!has_access)
{
source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "FOUNDER", ci->GetName());
return;
diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp
index a17ae48a0..f797eda0f 100644
--- a/modules/commands/cs_ban.cpp
+++ b/modules/commands/cs_ban.cpp
@@ -102,6 +102,9 @@ class CommandCSBan : public Command
if (reason.length() > reasonmax)
reason = reason.substr(0, reasonmax);
+ Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
+ signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
+
User *u = source.GetUser();
User *u2 = User::Find(target, true);
@@ -124,7 +127,7 @@ class CommandCSBan : public Command
}
/*
- * Dont ban/kick the user on channels where he is excepted
+ * Don't ban/kick the user on channels where he is excepted
* to prevent services <-> server wars.
*/
if (c->MatchesList(u2, "EXCEPT"))
@@ -161,7 +164,10 @@ class CommandCSBan : public Command
if (block->Get<bool>("kick", "yes"))
{
if (ci->HasFieldS("SIGNKICK") || (ci->HasFieldS("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
- c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
+ {
+ signkickformat = signkickformat.replace_all_cs("%m", reason);
+ c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
+ }
else
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
}
@@ -170,15 +176,18 @@ class CommandCSBan : public Command
{
bool founder = u_access.HasPriv("FOUNDER");
bool override = !founder && !u_access.HasPriv("BAN");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << target;
- if (!c->HasMode(mode, target))
+ Anope::string mask = IRCD->NormalizeMask(target);
+
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
+
+ if (!c->HasMode(mode, mask))
{
- c->SetMode(NULL, mode, target);
+ c->SetMode(NULL, mode, mask);
if (ban_time)
{
- new TempBan(ban_time, c, target, mode);
- source.Reply(_("Ban on \002{0}\002 expires in \002{1}\002."), target, Anope::Duration(ban_time, source.GetAccount()));
+ new TempBan(ban_time, c, mask, mode);
+ source.Reply(_("Ban on \002{0}\002 expires in \002{1}\002."), mask, Anope::Duration(ban_time, source.GetAccount()));
}
}
@@ -188,7 +197,8 @@ class CommandCSBan : public Command
ChanUserContainer *uc = it->second;
++it;
- if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
+ Entry e(mode, mask);
+ if (e.Matches(uc->user))
{
++matched;
@@ -206,18 +216,23 @@ class CommandCSBan : public Command
if (block->Get<bool>("kick", "yes"))
{
++kicked;
+
if (ci->HasFieldS("SIGNKICK") || (ci->HasFieldS("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
- c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
+ {
+ reason += " (Matches " + mask + ")";
+ signkickformat = signkickformat.replace_all_cs("%m", reason);
+ c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
+ }
else
- c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
+ c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
}
}
}
if (matched)
- source.Reply(_("Kicked \002{0}/{1}\002 users matching \002{2}\002 from \002{3}\002."), kicked, matched, target, c->name);
+ source.Reply(_("Kicked \002{0}/{1}\002 users matching \002{2}\002 from \002{3}\002."), kicked, matched, mask, c->name);
else
- source.Reply(_("No users on \002{0}\002 match \002{1}\002."), c->name, target);
+ source.Reply(_("No users on \002{0}\002 match \002{1}\002."), c->name, mask);
}
}
diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp
index 69dc70bea..256446bd1 100644
--- a/modules/commands/cs_clone.cpp
+++ b/modules/commands/cs_clone.cpp
@@ -15,6 +15,20 @@
class CommandCSClone : public Command
{
+#if 0
+ void CopyLevels(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ {
+ const Anope::map<int16_t> &cilevels = ci->GetLevelEntries();
+
+ for (Anope::map<int16_t>::const_iterator it = cilevels.begin(); it != cilevels.end(); ++it)
+ {
+ target_ci->SetLevel(it->first, it->second);
+ }
+
+ source.Reply(_("All level entries from \002%s\002 have been cloned into \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
+ }
+#endif
+
public:
CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3)
{
@@ -73,7 +87,7 @@ public:
if (what.empty())
{
- delete target_ci;
+ target_ci->Delete();
target_ci = ChanServ::channel.Create();
target_ci->SetName(target);
ChanServ::registered_channel_map& map = ChanServ::service->GetChannels();
diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp
index 4a646b3b3..31253599e 100644
--- a/modules/commands/cs_entrymsg.cpp
+++ b/modules/commands/cs_entrymsg.cpp
@@ -138,7 +138,7 @@ class CommandEntryMessage : public Command
msg->SetChannel(ci);
msg->SetCreator(source.GetNick());
msg->SetMessage(message);
- Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to add a message";
source.Reply(_("Entry message added to \002{0}\002"), ci->GetName());
}
@@ -157,8 +157,8 @@ class CommandEntryMessage : public Command
unsigned i = convertTo<unsigned>(message);
if (i > 0 && i <= messages.size())
{
- delete messages[i - 1];
- Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
+ messages[i - 1]->Delete();
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
source.Reply(_("Entry message \002{0}\002 for \002{1]\002 deleted."), i, ci->GetName());
}
else
@@ -176,7 +176,7 @@ class CommandEntryMessage : public Command
for (EntryMsg *e : ci->GetRefs<EntryMsg *>(entrymsg))
delete e;
- Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
source.Reply(_("Entry messages for \002{0}\002 have been cleared."), ci->GetName());
}
@@ -207,7 +207,7 @@ class CommandEntryMessage : public Command
return;
}
- if (!source.IsFounder(ci) && !source.HasPriv("chanserv/administration"))
+ if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration"))
{
source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "FOUNDER", ci->GetName());
return;
@@ -240,7 +240,7 @@ class CommandEntryMessage : public Command
"\n"
"The \002{0} CLEAR\002 command clears the entry message list.\n"
"\n"
- "Use of this command requires being the founder of \037channel\037."),
+ "Use of this command requires the \002SET\002 privilege on \037channel\037."),
source.command);
return true;
}
diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp
index 679ccfe06..89536df7f 100644
--- a/modules/commands/cs_kick.cpp
+++ b/modules/commands/cs_kick.cpp
@@ -50,6 +50,9 @@ class CommandCSKick : public Command
ChanServ::AccessGroup u_access = source.AccessFor(ci);
+ Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
+ signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
+
if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick"))
{
source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "KICK", ci->GetName());
@@ -71,14 +74,19 @@ class CommandCSKick : public Command
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick;
if (ci->HasFieldS("SIGNKICK") || (ci->HasFieldS("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
- c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
+ {
+ signkickformat = signkickformat.replace_all_cs("%m", reason);
+ c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str());
+ }
else
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
}
}
else if (u_access.HasPriv("FOUNDER"))
{
- Log(LOG_COMMAND, source, this, ci) << "for " << target;
+ Anope::string mask = IRCD->NormalizeMask(target);
+
+ Log(LOG_COMMAND, source, this, ci) << "for " << mask;
int matched = 0, kicked = 0;
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;)
@@ -86,7 +94,8 @@ class CommandCSKick : public Command
ChanUserContainer *uc = it->second;
++it;
- if (Anope::Match(uc->user->nick, target) || Anope::Match(uc->user->GetDisplayedMask(), target))
+ Entry e("", mask);
+ if (e.Matches(uc->user))
{
++matched;
@@ -97,17 +106,22 @@ class CommandCSKick : public Command
continue;
++kicked;
+
if (ci->HasFieldS("SIGNKICK") || (ci->HasFieldS("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
- c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
+ {
+ reason += " (Matches " + mask + ")";
+ signkickformat = signkickformat.replace_all_cs("%m", reason);
+ c->Kick(ci->WhoSends(), uc->user, "%s", signkickformat.c_str());
+ }
else
- c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
+ c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), mask.c_str());
}
}
if (matched)
- source.Reply(_("Kicked \002{0}/{1}\002 users matching \002{2}\002 from \002{3}\002."), kicked, matched, target, c->name);
+ source.Reply(_("Kicked \002{0}/{1}\002 users matching \002{2}\002 from \002{3}\002."), kicked, matched, mask, c->name);
else
- source.Reply(_("No users on\002{0}\002 match \002{1}\002."), c->name, target);
+ source.Reply(_("No users on\002{0}\002 match \002{1}\002."), c->name, mask);
}
else
source.Reply(_("\002{0}\002 isn't currently in use."), target);
diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp
index 67d1e5faa..121179a58 100644
--- a/modules/commands/cs_mode.cpp
+++ b/modules/commands/cs_mode.cpp
@@ -479,7 +479,7 @@ class CommandCSMode : public Command
case '*':
if (adding == -1 || !has_access)
break;
- for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j)
+ for (unsigned j = 0; j < ModeManager::GetChannelModes().size() && ci->c; ++j)
{
ChannelMode *cm = ModeManager::GetChannelModes()[j];
@@ -912,7 +912,7 @@ class CSMode : public Module
}
else if (cm->type == MODE_PARAM)
{
- /* If the channel doesnt have the mode, or it does and it isn't set correctly */
+ /* If the channel doesn't have the mode, or it does and it isn't set correctly */
if (ml->GetSet())
{
Anope::string param;
@@ -947,16 +947,40 @@ class CSMode : public Module
for (unsigned i = 0; i < mlock.length(); ++i)
{
if (mlock[i] == '+')
+ {
add = true;
- else if (mlock[i] == '-')
+ continue;
+ }
+
+ if (mlock[i] == '-')
+ {
add = false;
- else
+ continue;
+ }
+
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
+ if (!cm)
+ continue;
+
+ Anope::string param;
+ if (cm->type == MODE_PARAM)
{
- ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]);
- Anope::string param;
- if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
- mlocks->SetMLock(ci, cm, add, param);
+ ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm);
+ if (add || !cmp->minus_no_arg)
+ {
+ sep.GetToken(param);
+ if (param.empty() || !cmp->IsValid(param))
+ continue;
+ }
}
+ else if (cm->type != MODE_REGULAR)
+ {
+ sep.GetToken(param);
+ if (param.empty())
+ continue;
+ }
+
+ mlocks->SetMLock(ci, cm, add, param);
}
}
}
diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp
index f7ee80050..06c996f52 100644
--- a/modules/commands/cs_set.cpp
+++ b/modules/commands/cs_set.cpp
@@ -850,7 +850,7 @@ class CommandCSSetSecureOps : public Command
bool OnHelp(CommandSource &source, const Anope::string &) override
{
source.Reply(_("Enables or disables the \002secure ops\002 option for \037channel\037."
- " When \002secure ops\002 is set, users will not be allowed to have channel operator status if they do not have the privileges to have it."));
+ " When \002secure ops\002 is set, users will not be allowed to have channel operator status if they do not have the privileges for it."));
return true;
}
};
@@ -1066,13 +1066,11 @@ class CommandCSSetNoexpire : public Command
class CSSet : public Module
, public EventHook<Event::CreateChan>
- , public EventHook<Event::ChannelCreate>
, public EventHook<Event::ChannelSync>
, public EventHook<Event::CheckKick>
, public EventHook<Event::DelChan>
, public EventHook<Event::ChannelModeSet>
, public EventHook<Event::ChannelModeUnset>
- , public EventHook<Event::CheckDelete>
, public EventHook<Event::JoinChannel>
, public EventHook<Event::SetCorrectModes>
, public EventHook<ChanServ::Event::PreChanExpire>
@@ -1097,6 +1095,8 @@ class CSSet : public Module
CommandCSSetSuccessor commandcssetsuccessor;
CommandCSSetNoexpire commandcssetnoexpire;
+ ExtensibleRef<bool> inhabit;
+
bool persist_lower_ts;
public:
@@ -1129,6 +1129,8 @@ class CSSet : public Module
, commandcssetsignkick(this)
, commandcssetsuccessor(this)
, commandcssetnoexpire(this)
+
+ , inhabit("inhabit")
{
}
@@ -1142,18 +1144,13 @@ class CSSet : public Module
ci->SetBanType(Config->GetModule(this)->Get<int>("defbantype", "2"));
}
- void OnChannelCreate(Channel *c) override
+ void OnChannelSync(Channel *c) override
{
if (c->ci && keep_modes.HasExt(c->ci))
for (ChanServ::Mode *m : c->ci->GetRefs<ChanServ::Mode *>(ChanServ::mode))
c->SetMode(c->ci->WhoSends(), m->GetMode(), m->GetParam());
}
- void OnChannelSync(Channel *c) override
- {
- OnChannelCreate(c);
- }
-
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT"))
@@ -1180,7 +1177,7 @@ class CSSet : public Module
if (mode->name == "PERM")
persist.Set(c->ci, true);
- if (mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && ChanServ::mode)
+ if (mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && ChanServ::mode && (!inhabit || !inhabit->HasExt(c)))
{
ChanServ::Mode *m = ChanServ::mode.Create();
m->SetChannel(c->ci);
@@ -1200,7 +1197,7 @@ class CSSet : public Module
persist.Unset(c->ci);
}
- if (c->ci && mode->type != MODE_STATUS && !c->syncing && Me->IsSynced())
+ if (c->ci && mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && (!inhabit || !inhabit->HasExt(c)))
for (ChanServ::Mode *m : c->ci->GetRefs<ChanServ::Mode *>(ChanServ::mode))
if (m->GetMode() == mode->name && m->GetParam().equals_ci(param))
m->Delete();
@@ -1208,13 +1205,6 @@ class CSSet : public Module
return EVENT_CONTINUE;
}
- EventReturn OnCheckDelete(Channel *c) override
- {
- if (c->ci && persist.HasExt(c->ci))
- return EVENT_STOP;
- return EVENT_CONTINUE;
- }
-
void OnJoinChannel(User *u, Channel *c) override
{
if (persist_lower_ts && c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->GetTimeRegistered())
diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp
index 9e8b3764a..a132900a6 100644
--- a/modules/commands/cs_topic.cpp
+++ b/modules/commands/cs_topic.cpp
@@ -195,7 +195,7 @@ class CommandCSTopic : public Command
" The \002APPEND\002 command appends the given topic to the existing topic.\n"
"\n"
"\002LOCK\002 and \002UNLOCK\002 may be used to enable and disable topic lock."
- " When topic lock is set, the channel topic will be unchangeable except via this command.\n"
+ " When topic lock is set, the channel topic will be unchangeable by users who do not have the \002TOPIC\002 privilege.\n"
"\n"
"Use of this command requires the \002{0}\002 privilege on \037channel\037."),
"TOPIC");
@@ -235,7 +235,7 @@ class CSTopic : public Module
}
}
- void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) override
+ void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) override
{
if (!c->ci)
return;
@@ -245,7 +245,7 @@ class CSTopic : public Module
* This desyncs what is really set with what we have stored, and we end up resetting the topic often when
* it is not required
*/
- if (topiclock.HasExt(c->ci) && c->ci->GetLastTopic() != c->topic)
+ if (topiclock.HasExt(c->ci) && c->ci->GetLastTopic() != c->topic && (!source || !c->ci->AccessFor(source).HasPriv("TOPIC")))
{
c->ChangeTopic(c->ci->GetLastTopicSetter(), c->ci->GetLastTopic(), c->ci->GetLastTopicTime());
}
diff --git a/modules/commands/hs_del.cpp b/modules/commands/hs_del.cpp
index 4d7e7aac9..b45c10a61 100644
--- a/modules/commands/hs_del.cpp
+++ b/modules/commands/hs_del.cpp
@@ -101,7 +101,8 @@ class HSDel : public Module
, commandhsdelall(this, ondeletevhost)
, ondeletevhost(this)
{
-
+ if (!IRCD || !IRCD->CanSetVHost)
+ throw ModuleException("Your IRCd does not support vhosts");
}
};
diff --git a/modules/commands/hs_group.cpp b/modules/commands/hs_group.cpp
index 8a7a208a6..c3971fdea 100644
--- a/modules/commands/hs_group.cpp
+++ b/modules/commands/hs_group.cpp
@@ -86,6 +86,8 @@ class HSGroup : public Module
HSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
, commandhsgroup(this)
{
+ if (!IRCD || !IRCD->CanSetVHost)
+ throw ModuleException("Your IRCd does not support vhosts");
}
void OnSetVhost(NickServ::Nick *na) override
diff --git a/modules/commands/hs_list.cpp b/modules/commands/hs_list.cpp
index f363c81f7..738f9f1bd 100644
--- a/modules/commands/hs_list.cpp
+++ b/modules/commands/hs_list.cpp
@@ -151,6 +151,8 @@ class HSList : public Module
HSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR)
, commandhslist(this)
{
+ if (!IRCD || !IRCD->CanSetVHost)
+ throw ModuleException("Your IRCd does not support vhosts");
}
};
diff --git a/modules/commands/hs_off.cpp b/modules/commands/hs_off.cpp
index 6f88de67e..8f3c7e3da 100644
--- a/