summaryrefslogtreecommitdiff
path: root/modules/commands
diff options
context:
space:
mode:
Diffstat (limited to 'modules/commands')
-rw-r--r--modules/commands/cs_ban.cpp24
-rw-r--r--modules/commands/cs_clone.cpp182
-rw-r--r--modules/commands/cs_kick.cpp15
-rw-r--r--modules/commands/cs_mode.cpp2
-rw-r--r--modules/commands/ns_register.cpp6
-rw-r--r--modules/commands/ns_set.cpp17
-rw-r--r--modules/commands/os_mode.cpp14
-rw-r--r--modules/commands/os_sxline.cpp4
8 files changed, 168 insertions, 96 deletions
diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp
index 648e379e3..be15df66c 100644
--- a/modules/commands/cs_ban.cpp
+++ b/modules/commands/cs_ban.cpp
@@ -156,15 +156,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%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
+ new TempBan(ban_time, c, mask, mode);
+ source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
}
}
@@ -174,7 +177,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;
@@ -193,17 +197,17 @@ class CommandCSBan : public Command
{
++kicked;
if (ci->HasExt("SIGNKICK") || (ci->HasExt("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());
+ c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), mask.c_str(), source.GetNick().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 %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
+ source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
else
- source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
+ source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
}
}
diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp
index 8365091cf..cbf53e892 100644
--- a/modules/commands/cs_clone.cpp
+++ b/modules/commands/cs_clone.cpp
@@ -14,6 +14,100 @@
class CommandCSClone : public Command
{
+ void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting)
+ {
+ if (ci->HasExt(setting))
+ target_ci->Extend<bool>(setting);
+ }
+
+ void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ {
+ std::set<Anope::string> masks;
+ unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
+ unsigned count = 0;
+
+ for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
+ masks.insert(target_ci->GetAccess(i)->Mask());
+
+ for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
+ {
+ const ChanAccess *taccess = ci->GetAccess(i);
+ AccessProvider *provider = taccess->provider;
+
+ if (access_max && target_ci->GetDeepAccessCount() >= access_max)
+ break;
+
+ if (masks.count(taccess->Mask()))
+ continue;
+ masks.insert(taccess->Mask());
+
+ ChanAccess *newaccess = provider->Create();
+ newaccess->SetMask(taccess->Mask(), target_ci);
+ newaccess->creator = taccess->creator;
+ newaccess->last_seen = taccess->last_seen;
+ newaccess->created = taccess->created;
+ newaccess->AccessUnserialize(taccess->AccessSerialize());
+
+ target_ci->AddAccess(newaccess);
+
+ ++count;
+ }
+
+ source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, ci->name.c_str(), target_ci->name.c_str());
+ }
+
+ void CopyAkick(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ {
+ target_ci->ClearAkick();
+ for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
+ {
+ const AutoKick *akick = ci->GetAkick(i);
+ if (akick->nc)
+ target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
+ else
+ target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
+ }
+
+ source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
+ }
+
+ void CopyBadwords(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
+ {
+ BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
+ *badwords = ci->Require<BadWords>("badwords");
+
+ if (!target_badwords || !badwords)
+ {
+ source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
+ return;
+ }
+
+ target_badwords->ClearBadWords();
+
+ for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
+ {
+ const BadWord *bw = badwords->GetBadWord(i);
+ target_badwords->AddBadWord(bw->word, bw->type);
+ }
+
+ badwords->Check();
+ target_badwords->Check();
+
+ source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
+ }
+
+ 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());
+ }
+
public:
CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3)
{
@@ -100,82 +194,36 @@ public:
else
target_ci->last_topic_setter = source.service->nick;
+ const Anope::string settings[] = { "NOAUTOOP", "CS_KEEP_MODES", "PEACE", "PERSIST", "RESTRICTED",
+ "CS_SECURE", "SECUREFOUNDER", "SECUREOPS", "SIGNKICK", "SIGNKICK_LEVEL", "CS_NO_EXPIRE" };
+
+ for (unsigned int i = 0; i < sizeof(settings) / sizeof(Anope::string); ++i)
+ CopySetting(ci, target_ci, settings[i]);
+
+ CopyAccess(source, ci, target_ci);
+ CopyAkick(source, ci, target_ci);
+ CopyBadwords(source, ci, target_ci);
+ CopyLevels(source, ci, target_ci);
+
FOREACH_MOD(OnChanRegistered, (target_ci));
- source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
+ source.Reply(_("All settings from \002%s\002 have been cloned to \002%s\002."), ci->name.c_str(), target_ci->name.c_str());
}
else if (what.equals_ci("ACCESS"))
{
- std::set<Anope::string> masks;
- unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
- unsigned count = 0;
-
- for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
- masks.insert(target_ci->GetAccess(i)->Mask());
-
- for (unsigned i = 0; i < ci->GetAccessCount(); ++i)
- {
- const ChanAccess *taccess = ci->GetAccess(i);
- AccessProvider *provider = taccess->provider;
-
- if (access_max && target_ci->GetDeepAccessCount() >= access_max)
- break;
-
- if (masks.count(taccess->Mask()))
- continue;
- masks.insert(taccess->Mask());
-
- ChanAccess *newaccess = provider->Create();
- newaccess->SetMask(taccess->Mask(), target_ci);
- newaccess->creator = taccess->creator;
- newaccess->last_seen = taccess->last_seen;
- newaccess->created = taccess->created;
- newaccess->AccessUnserialize(taccess->AccessSerialize());
-
- target_ci->AddAccess(newaccess);
-
- ++count;
- }
-
- source.Reply(_("%d access entries from \002%s\002 have been cloned to \002%s\002."), count, channel.c_str(), target.c_str());
+ CopyAccess(source, ci, target_ci);
}
else if (what.equals_ci("AKICK"))
{
- target_ci->ClearAkick();
- for (unsigned i = 0; i < ci->GetAkickCount(); ++i)
- {
- const AutoKick *akick = ci->GetAkick(i);
- if (akick->nc)
- target_ci->AddAkick(akick->creator, akick->nc, akick->reason, akick->addtime, akick->last_used);
- else
- target_ci->AddAkick(akick->creator, akick->mask, akick->reason, akick->addtime, akick->last_used);
- }
-
- source.Reply(_("All akick entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
+ CopyAkick(source, ci, target_ci);
}
else if (what.equals_ci("BADWORDS"))
{
- BadWords *target_badwords = target_ci->Require<BadWords>("badwords"),
- *badwords = ci->Require<BadWords>("badwords");
-
- if (!target_badwords || !badwords)
- {
- source.Reply(ACCESS_DENIED); // BotServ doesn't exist/badwords isn't loaded
- return;
- }
-
- target_badwords->ClearBadWords();
-
- for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
- {
- const BadWord *bw = badwords->GetBadWord(i);
- target_badwords->AddBadWord(bw->word, bw->type);
- }
-
- badwords->Check();
- target_badwords->Check();
-
- source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
+ CopyBadwords(source, ci, target_ci);
+ }
+ else if (what.equals_ci("LEVELS"))
+ {
+ CopyLevels(source, ci, target_ci);
}
else
{
@@ -191,8 +239,8 @@ public:
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_("Copies all settings, access, akicks, etc from \002channel\002 to the\n"
- "\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, or \002BADWORDS\002\n"
- "then only the respective settings are cloned.\n"
+ "\002target\002 channel. If \037what\037 is \002ACCESS\002, \002AKICK\002, \002BADWORDS\002,\n"
+ "or \002LEVELS\002 then only the respective settings are cloned.\n"
"You must be the founder of \037channel\037 and \037target\037."));
return true;
}
diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp
index c95445557..a3505d254 100644
--- a/modules/commands/cs_kick.cpp
+++ b/modules/commands/cs_kick.cpp
@@ -73,7 +73,9 @@ class CommandCSKick : public Command
}
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;)
@@ -81,7 +83,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;
@@ -93,16 +96,16 @@ class CommandCSKick : public Command
++kicked;
if (ci->HasExt("SIGNKICK") || (ci->HasExt("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());
+ c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), mask.c_str(), source.GetNick().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 %d/%d users matching %s from %s."), kicked, matched, target.c_str(), c->name.c_str());
+ source.Reply(_("Kicked %d/%d users matching %s from %s."), kicked, matched, mask.c_str(), c->name.c_str());
else
- source.Reply(_("No users on %s match %s."), c->name.c_str(), target.c_str());
+ source.Reply(_("No users on %s match %s."), c->name.c_str(), mask.c_str());
}
else
source.Reply(NICK_X_NOT_IN_USE, target.c_str());
diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp
index 8a30f102c..b11bc8862 100644
--- a/modules/commands/cs_mode.cpp
+++ b/modules/commands/cs_mode.cpp
@@ -487,7 +487,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];
diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp
index 4793b2269..75ef5a9fb 100644
--- a/modules/commands/ns_register.cpp
+++ b/modules/commands/ns_register.cpp
@@ -170,6 +170,8 @@ class CommandNSRegister : public Command
}
}
+ unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
+
if (Config->GetModule("nickserv")->Get<bool>("forceemail", "yes") && email.empty())
this->OnSyntaxError(source, "");
else if (u && Anope::CurTime < u->lastnickreg + reg_delay)
@@ -178,8 +180,8 @@ class CommandNSRegister : public Command
source.Reply(NICK_ALREADY_REGISTERED, u_nick.c_str());
else if (pass.equals_ci(u_nick) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && pass.length() < 5))
source.Reply(MORE_OBSCURE_PASSWORD);
- else if (pass.length() > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
- source.Reply(PASSWORD_TOO_LONG);
+ else if (pass.length() > passlen)
+ source.Reply(PASSWORD_TOO_LONG, passlen);
else if (!email.empty() && !Mail::Validate(email))
source.Reply(MAIL_X_INVALID, email.c_str());
else
diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp
index 03ebae85c..e8e7c335c 100644
--- a/modules/commands/ns_set.cpp
+++ b/modules/commands/ns_set.cpp
@@ -133,9 +133,11 @@ class CommandNSSetPassword : public Command
source.Reply(MORE_OBSCURE_PASSWORD);
return;
}
- else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
+
+ unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
+ if (len > passlen)
{
- source.Reply(PASSWORD_TOO_LONG);
+ source.Reply(PASSWORD_TOO_LONG, passlen);
return;
}
@@ -191,14 +193,17 @@ class CommandNSSASetPassword : public Command
source.Reply(_("You may not change the password of other Services Operators."));
return;
}
- else if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
+
+ if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5))
{
source.Reply(MORE_OBSCURE_PASSWORD);
return;
}
- else if (len > Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"))
+
+ unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32");
+ if (len > passlen)
{
- source.Reply(PASSWORD_TOO_LONG);
+ source.Reply(PASSWORD_TOO_LONG, passlen);
return;
}
@@ -414,10 +419,12 @@ class CommandNSSetEmail : public Command
message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
subject = subject.replace_all_cs("%e", u->Account()->email);
+ subject = subject.replace_all_cs("%E", new_email);
subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
subject = subject.replace_all_cs("%c", code);
message = message.replace_all_cs("%e", u->Account()->email);
+ message = message.replace_all_cs("%E", new_email);
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
message = message.replace_all_cs("%c", code);
diff --git a/modules/commands/os_mode.cpp b/modules/commands/os_mode.cpp
index 379879844..b6f26c7b3 100644
--- a/modules/commands/os_mode.cpp
+++ b/modules/commands/os_mode.cpp
@@ -26,7 +26,7 @@ class CommandOSMode : public Command
const Anope::string &target = params[0];
const Anope::string &modes = params[1];
- Channel *c = Channel::Find(target);
+ Reference<Channel> c = Channel::Find(target);
if (!c)
source.Reply(CHAN_X_NOT_IN_USE, target.c_str());
else if (c->bouncy_modes)
@@ -36,9 +36,15 @@ class CommandOSMode : public Command
bool all = params.size() > 2 && params[2].equals_ci("ALL");
const Channel::ModeList chmodes = c->GetModes();
- for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end; ++it)
+ for (Channel::ModeList::const_iterator it = chmodes.begin(), it_end = chmodes.end(); it != it_end && c; ++it)
c->RemoveMode(c->ci->WhoSends(), it->first, it->second, false);
+ if (!c)
+ {
+ source.Reply(_("Modes cleared on %s and the channel destroyed."), target.c_str());
+ return;
+ }
+
if (all)
{
for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
@@ -65,7 +71,7 @@ class CommandOSMode : public Command
Anope::string log_modes, log_params;
sep.GetToken(mode);
- for (unsigned i = 0; i < mode.length(); ++i)
+ for (unsigned i = 0; i < mode.length() && c; ++i)
{
char ch = mode[i];
@@ -116,7 +122,7 @@ class CommandOSMode : public Command
}
if (!log_modes.replace_all_cs("+", "").replace_all_cs("-", "").empty())
- Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << c->name;
+ Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << (c ? c->name : target);
}
}
diff --git a/modules/commands/os_sxline.cpp b/modules/commands/os_sxline.cpp
index 80b7c5586..3fde89871 100644
--- a/modules/commands/os_sxline.cpp
+++ b/modules/commands/os_sxline.cpp
@@ -664,7 +664,9 @@ class CommandOSSQLine : public CommandOSSXLineBase
"connect, Services will not allow it to pursue his IRC\n"
"session.\n"
"If the first character of the mask is #, services will\n"
- "prevent the use of matching channels."));
+ "prevent the use of matching channels. If the mask is a\n"
+ "regular expression, the expression will be matched against\n"
+ "channels too."));
source.Reply(_(" \n"
"\002SQLINE ADD\002 adds the given (nick's) mask to the SQLINE\n"
"list for the given reason (which \002must\002 be given).\n"