diff options
Diffstat (limited to 'modules/commands')
-rw-r--r-- | modules/commands/cs_ban.cpp | 24 | ||||
-rw-r--r-- | modules/commands/cs_clone.cpp | 182 | ||||
-rw-r--r-- | modules/commands/cs_kick.cpp | 15 | ||||
-rw-r--r-- | modules/commands/ns_register.cpp | 6 | ||||
-rw-r--r-- | modules/commands/ns_set.cpp | 17 | ||||
-rw-r--r-- | modules/commands/os_sxline.cpp | 4 |
6 files changed, 157 insertions, 91 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/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_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" |