From 7e0cb6d8ef283d83fcabee131f88ebe85e2ba44f Mon Sep 17 00:00:00 2001 From: Zach Bloomquist Date: Fri, 2 Jan 2015 21:09:05 -0500 Subject: cs_entrymsg to use SET permission, not isFounder Correcting syntax error (i don't actually know c++) --- modules/commands/cs_entrymsg.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp index 6df6918da..89b66a977 100644 --- a/modules/commands/cs_entrymsg.cpp +++ b/modules/commands/cs_entrymsg.cpp @@ -143,7 +143,7 @@ class CommandEntryMessage : public Command else { (*messages)->push_back(new EntryMsgImpl(ci, source.GetNick(), 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%s\002"), ci->name.c_str()); } } @@ -166,7 +166,7 @@ class CommandEntryMessage : public Command delete (*messages)->at(i - 1); if ((*messages)->empty()) ci->Shrink("entrymsg"); - Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message"; + Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message"; source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str()); } else @@ -183,7 +183,7 @@ class CommandEntryMessage : public Command { ci->Shrink("entrymsg"); - 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%s\002 have been cleared."), ci->name.c_str()); } @@ -212,7 +212,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); return; @@ -253,6 +253,9 @@ class CommandEntryMessage : public Command source.Reply(_("The \002ENTRYMSG CLEAR\002 command clears all entries from\n" "the list of messages shown to users when they join\n" "the channel, effectively disabling entry messages.")); + source.Reply(" "); + source.Reply(_("Adding, deleting, or clearing entry messages requires the\n" + "SET permission.")); return true; } }; -- cgit From d324e9152012500c7a811d7adda6ad2c6fbcd26f Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 26 Jan 2015 13:16:25 -0500 Subject: Fix negatively locking param modes in default mlock --- modules/commands/cs_mode.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index d5c356fa4..8a30f102c 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -958,16 +958,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) + { + ChannelModeParam *cmp = anope_dynamic_static_cast(cm); + if (add || !cmp->minus_no_arg) + { + sep.GetToken(param); + if (param.empty() || !cmp->IsValid(param)) + continue; + } + } + else if (cm->type != MODE_REGULAR) { - ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]); - Anope::string param; - if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param))) - ml->SetMLock(cm, add, param); + sep.GetToken(param); + if (param.empty()) + continue; } + + ml->SetMLock(cm, add, param); } } ml->Check(); -- cgit From 845ca576b4c5a94f0a3ec12a4dd524a7d017155e Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 28 Jan 2015 22:57:15 -0500 Subject: More properly track topic change sources and allow users with access to change topics through topiclock --- modules/commands/cs_topic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp index 1506bcc9c..353cf83a3 100644 --- a/modules/commands/cs_topic.cpp +++ b/modules/commands/cs_topic.cpp @@ -227,7 +227,7 @@ class CSTopic : public Module } } - void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override + void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override { if (!c->ci) return; @@ -237,7 +237,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->last_topic != c->topic) + if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic && (!source || !c->ci->AccessFor(source).HasPriv("TOPIC"))) { c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time); } -- cgit From 9834518b28e3bb6ec62000c26be4e5927ca92979 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 5 Feb 2015 20:16:36 -0500 Subject: Fix os_mode to handle channels going away due to mode changes, and maybe cs_mode --- modules/commands/cs_mode.cpp | 2 +- modules/commands/os_mode.cpp | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'modules/commands') 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/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 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); } } -- cgit From 61a8dd57f7984194dc453ef56b5b05c957aedd8b Mon Sep 17 00:00:00 2001 From: H7-25 Date: Thu, 5 Feb 2015 19:45:27 +0100 Subject: Added kickcheck override for users with protected privs --- modules/commands/cs_set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index afd2c3547..3c7a0f32c 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1252,7 +1252,7 @@ class CSSet : public Module EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override { - if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT")) + if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT") || u->IsProtected()) return EVENT_CONTINUE; if (c->ci->AccessFor(u).empty() && (!c->ci->GetFounder() || u->Account() != c->ci->GetFounder())) -- cgit From c3cc5804c32f423d4017a825300d926895ef64ed Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Mar 2015 11:26:12 -0400 Subject: Normalize masks given to cs_ban, use entry to match them against users --- modules/commands/cs_ban.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'modules/commands') 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()); } } -- cgit From 3f093d708f198c105e9ac528436a78d4246b8273 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Mar 2015 12:13:08 -0400 Subject: Normalize masks given to cs_kick, use entry to match them against users --- modules/commands/cs_kick.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'modules/commands') 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()); -- cgit From 78bff86dab32dc484164e5da8a535b3ec24c5c03 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Mar 2015 14:19:38 -0400 Subject: Make cs_clone behave closer to how the help describes it --- modules/commands/cs_clone.cpp | 161 +++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 65 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index 8365091cf..a7dcdd9ec 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -14,6 +14,88 @@ class CommandCSClone : public Command { + void CopySetting(ChannelInfo *ci, ChannelInfo *target_ci, const Anope::string &setting) + { + if (ci->HasExt(setting)) + target_ci->Extend(setting); + } + + void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci) + { + std::set masks; + unsigned access_max = Config->GetModule("chanserv")->Get("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 = ci->Require("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()); + } + public: CommandCSClone(Module *creator) : Command(creator, "chanserv/clone", 2, 3) { @@ -100,82 +182,31 @@ 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); + 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 masks; - unsigned access_max = Config->GetModule("chanserv")->Get("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 = ci->Require("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 { -- cgit From 310e95a92e64a9546247fe57d4643328fa4ebe9b Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Mar 2015 14:36:56 -0400 Subject: Allow cs clone to clone levels too --- modules/commands/cs_clone.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index a7dcdd9ec..cbf53e892 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -96,6 +96,18 @@ class CommandCSClone : public Command 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 &cilevels = ci->GetLevelEntries(); + + for (Anope::map::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) { @@ -191,6 +203,7 @@ public: 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)); @@ -208,6 +221,10 @@ public: { CopyBadwords(source, ci, target_ci); } + else if (what.equals_ci("LEVELS")) + { + CopyLevels(source, ci, target_ci); + } else { this->OnSyntaxError(source, ""); @@ -222,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; } -- cgit From bf727285bcf7c7c95c2b2b43faa3d1fa13bad6fb Mon Sep 17 00:00:00 2001 From: Peter Tseng Date: Sun, 1 Feb 2015 13:43:42 +0000 Subject: SendConfirmMail: Replace %E with new email The old mailer message said the user is changing email "to %e", which is changing TO the OLD email. But instead, the user is actually changing the email to the new email. We could change %e to be the new email, but maybe some users of Anope have already configured their messages to assume %e is the old email. So instead, add a new %E that is replaced with the new email. --- modules/commands/ns_set.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'modules/commands') diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp index 03ebae85c..fdf2a5e38 100644 --- a/modules/commands/ns_set.cpp +++ b/modules/commands/ns_set.cpp @@ -414,10 +414,12 @@ class CommandNSSetEmail : public Command message = Config->GetBlock("mail")->Get("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("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("networkname")); message = message.replace_all_cs("%c", code); -- cgit From 92920f5a1c8866c8e26e1608f0feb3e3e54c8dd2 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 11 Mar 2015 14:49:03 -0400 Subject: Only matches sqlines against channels if they begin with a # --- modules/commands/os_sxline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'modules/commands') 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" -- cgit From c5ff7c686837afbb854aa6546ade3aa8c86a1cd1 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 12 Mar 2015 08:00:12 -0400 Subject: Show passlen in PASSWORD_TOO_LONG --- modules/commands/ns_register.cpp | 6 ++++-- modules/commands/ns_set.cpp | 15 ++++++++++----- 2 files changed, 14 insertions(+), 7 deletions(-) (limited to 'modules/commands') 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("passlen", "32"); + if (Config->GetModule("nickserv")->Get("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("strictpasswords") && pass.length() < 5)) source.Reply(MORE_OBSCURE_PASSWORD); - else if (pass.length() > Config->GetModule("nickserv")->Get("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 fdf2a5e38..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("passlen", "32")) + + unsigned int passlen = Config->GetModule("nickserv")->Get("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("strictpasswords") && len < 5)) + + if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get("strictpasswords") && len < 5)) { source.Reply(MORE_OBSCURE_PASSWORD); return; } - else if (len > Config->GetModule("nickserv")->Get("passlen", "32")) + + unsigned int passlen = Config->GetModule("nickserv")->Get("passlen", "32"); + if (len > passlen) { - source.Reply(PASSWORD_TOO_LONG); + source.Reply(PASSWORD_TOO_LONG, passlen); return; } -- cgit From 41a24afa4f613e86802a95d90d866f51492ae3d9 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 12 Mar 2015 13:29:50 -0400 Subject: Revert "Added kickcheck override for users with protected privs" --- modules/commands/cs_set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 3c7a0f32c..afd2c3547 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1252,7 +1252,7 @@ class CSSet : public Module EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override { - if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT") || u->IsProtected()) + if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT")) return EVENT_CONTINUE; if (c->ci->AccessFor(u).empty() && (!c->ci->GetFounder() || u->Account() != c->ci->GetFounder())) -- cgit From 303e652a3563c50d8836996851341840b1ad4277 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 12 Mar 2015 13:44:05 -0400 Subject: Only apply keepmodes on channel sync Not sure why this was this way originally, it interfears with the chanserv +r check to determine how new the channel is because it restores +r. This seems to still work okay, though. --- modules/commands/cs_set.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index afd2c3547..73bdb5a0c 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1235,7 +1235,7 @@ class CSSet : public Module ci->bantype = Config->GetModule(this)->Get("defbantype", "2"); } - void OnChannelCreate(Channel *c) anope_override + void OnChannelSync(Channel *c) anope_override { if (c->ci && keep_modes.HasExt(c->ci)) { @@ -1245,11 +1245,6 @@ class CSSet : public Module } } - void OnChannelSync(Channel *c) anope_override - { - OnChannelCreate(c); - } - EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override { if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT")) -- cgit From 5df4ac9a98b11518af41a449bb6b89c3bf6290d9 Mon Sep 17 00:00:00 2001 From: Robby- Date: Sun, 1 Feb 2015 16:56:29 +0100 Subject: Make the signed kick/ban message format configurable. --- modules/commands/cs_ban.cpp | 14 ++++++++++++-- modules/commands/cs_kick.cpp | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp index be15df66c..de6a4f40e 100644 --- a/modules/commands/cs_ban.cpp +++ b/modules/commands/cs_ban.cpp @@ -101,6 +101,9 @@ class CommandCSBan : public Command if (reason.length() > reasonmax) reason = reason.substr(0, reasonmax); + Anope::string signkickformat = Config->GetModule("chanserv")->Get("signkickformat", "%m (%n)"); + signkickformat = signkickformat.replace_all_cs("%n", source.GetNick()); + User *u = source.GetUser(); User *u2 = User::Find(target, true); @@ -146,7 +149,10 @@ class CommandCSBan : public Command if (block->Get("kick", "yes")) { if (ci->HasExt("SIGNKICK") || (ci->HasExt("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()); } @@ -197,7 +203,11 @@ 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(), mask.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(), mask.c_str()); } diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp index a3505d254..5b28b5f18 100644 --- a/modules/commands/cs_kick.cpp +++ b/modules/commands/cs_kick.cpp @@ -47,6 +47,9 @@ class CommandCSKick : public Command if (reason.length() > reasonmax) reason = reason.substr(0, reasonmax); + Anope::string signkickformat = Config->GetModule("chanserv")->Get("signkickformat", "%m (%n)"); + signkickformat = signkickformat.replace_all_cs("%n", source.GetNick()); + AccessGroup u_access = source.AccessFor(ci); if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick")) @@ -66,7 +69,10 @@ class CommandCSKick : public Command Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; if (ci->HasExt("SIGNKICK") || (ci->HasExt("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()); } @@ -96,7 +102,11 @@ 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(), mask.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(), mask.c_str()); } -- cgit From 57b614ae59603b6628012ef9ba86912dbb240f8e Mon Sep 17 00:00:00 2001 From: Thomas Fargeix Date: Sun, 14 Jun 2015 19:28:51 +0200 Subject: Allow opers with chanserv/access/list to view the levels list --- modules/commands/cs_access.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 7fef5bfc5..2fc245690 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -758,12 +758,20 @@ 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. */ if (cmd.equals_ci("SET") ? s.empty() : (cmd.substr(0, 3).equals_ci("DIS") ? (what.empty() || !s.empty()) : !what.empty())) this->OnSyntaxError(source, cmd); - else if (!source.AccessFor(ci).HasPriv("FOUNDER") && !source.HasPriv("chanserv/access/modify")) + else if (!has_access) source.Reply(ACCESS_DENIED); else if (Anope::ReadOnly && !cmd.equals_ci("LIST")) source.Reply(READ_ONLY_MODE); -- cgit From 444976e64f5e5eb261f9ac25585535ca593a24f9 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 20 Jun 2015 17:32:33 -0400 Subject: Update host on hs off too Protocol modules which don't trigger this by causing a mode change currently desync --- modules/commands/hs_off.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'modules/commands') diff --git a/modules/commands/hs_off.cpp b/modules/commands/hs_off.cpp index 96d5fccca..c3b5e8b50 100644 --- a/modules/commands/hs_off.cpp +++ b/modules/commands/hs_off.cpp @@ -30,6 +30,7 @@ class CommandHSOff : public Command else { IRCD->SendVhostDel(u); + u->UpdateHost(); Log(LOG_COMMAND, source, this) << "to disable their vhost"; source.Reply(_("Your vhost was removed and the normal cloaking restored.")); } -- cgit From bb5c4906cc09df213c782342f96db00570aa8194 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 21 Jun 2015 10:42:49 -0400 Subject: Also clear vhost on hs_off so the proto mods don't have to --- modules/commands/hs_off.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'modules/commands') diff --git a/modules/commands/hs_off.cpp b/modules/commands/hs_off.cpp index c3b5e8b50..75e6bc966 100644 --- a/modules/commands/hs_off.cpp +++ b/modules/commands/hs_off.cpp @@ -29,6 +29,7 @@ class CommandHSOff : public Command source.Reply(HOST_NOT_ASSIGNED); else { + u->vhost.clear(); IRCD->SendVhostDel(u); u->UpdateHost(); Log(LOG_COMMAND, source, this) << "to disable their vhost"; -- cgit From 3e3312db259b3126e84ad2c1730c23c6f5ee8284 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 29 Jun 2015 08:42:29 -0400 Subject: Don't allow adding or changing bots to collide with users --- modules/commands/bs_bot.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp index d066a49a8..6a4f0344a 100644 --- a/modules/commands/bs_bot.cpp +++ b/modules/commands/bs_bot.cpp @@ -75,6 +75,13 @@ class CommandBSBot : public Command return; } + User *u = User::Find(nick, true); + if (u) + { + source.Reply(_("User \2%s\2 is already in use."), u->nick.c_str()); + return; + } + BotInfo *bi = new BotInfo(nick, user, host, real); Log(LOG_ADMIN, source, this) << "ADD " << bi->GetMask() << " " << bi->realname; @@ -161,10 +168,19 @@ class CommandBSBot : public Command return; } - if (!nick.equals_ci(bi->nick) && BotInfo::Find(nick, true)) + if (!nick.equals_ci(bi->nick)) { - source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); - return; + if (BotInfo::Find(nick, true)) + { + source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); + return; + } + + if (User::Find(nick, true)) + { + source.Reply(_("User \2%s\2 is already in use."), nick.c_str()); + return; + } } if (!nick.equals_ci(bi->nick)) -- cgit From 8eb46772e6e9244575851ceaa86b39e57a1db060 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 29 Jun 2015 08:58:31 -0400 Subject: Don't allow loading hostserv mods if there can be no hostserv --- modules/commands/hs_del.cpp | 3 ++- modules/commands/hs_group.cpp | 2 ++ modules/commands/hs_list.cpp | 2 ++ modules/commands/hs_off.cpp | 3 ++- modules/commands/hs_on.cpp | 3 ++- modules/commands/hs_request.cpp | 1 - modules/commands/hs_set.cpp | 3 ++- 7 files changed, 12 insertions(+), 5 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/hs_del.cpp b/modules/commands/hs_del.cpp index c27dc89d0..e103b8250 100644 --- a/modules/commands/hs_del.cpp +++ b/modules/commands/hs_del.cpp @@ -105,7 +105,8 @@ class HSDel : public Module HSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandhsdel(this), commandhsdelall(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 a238c3f99..232b2bef3 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(NickAlias *na) anope_override diff --git a/modules/commands/hs_list.cpp b/modules/commands/hs_list.cpp index cbdbb25ae..db63c5cd4 100644 --- a/modules/commands/hs_list.cpp +++ b/modules/commands/hs_list.cpp @@ -152,6 +152,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 75e6bc966..603b863c1 100644 --- a/modules/commands/hs_off.cpp +++ b/modules/commands/hs_off.cpp @@ -58,7 +58,8 @@ class HSOff : public Module HSOff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandhsoff(this) { - + if (!IRCD || !IRCD->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); } }; diff --git a/modules/commands/hs_on.cpp b/modules/commands/hs_on.cpp index d6897283a..d59206e27 100644 --- a/modules/commands/hs_on.cpp +++ b/modules/commands/hs_on.cpp @@ -65,7 +65,8 @@ class HSOn : public Module HSOn(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandhson(this) { - + if (!IRCD || !IRCD->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); } }; diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp index 616b2e772..313057d25 100644 --- a/modules/commands/hs_request.cpp +++ b/modules/commands/hs_request.cpp @@ -362,7 +362,6 @@ class HSRequest : public Module commandhsrequest(this), commandhsactive(this), commandhsreject(this), commandhswaiting(this), hostrequest(this, "hostrequest"), request_type("HostRequest", HostRequest::Unserialize) { - if (!IRCD || !IRCD->CanSetVHost) throw ModuleException("Your IRCd does not support vhosts"); } diff --git a/modules/commands/hs_set.cpp b/modules/commands/hs_set.cpp index 2940227aa..72e331e88 100644 --- a/modules/commands/hs_set.cpp +++ b/modules/commands/hs_set.cpp @@ -221,7 +221,8 @@ class HSSet : public Module public: HSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandhsset(this), commandhssetall(this) { - + if (!IRCD || !IRCD->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); } }; -- cgit From 510a746f8d7cd373bfae4efc98a1ef9b13f2b4e9 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 29 Jun 2015 09:37:09 -0400 Subject: Add ns_identify:maxlogins to limit the max number of concurrent logins per account --- modules/commands/ns_identify.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/ns_identify.cpp b/modules/commands/ns_identify.cpp index ce564321c..4aa361a0a 100644 --- a/modules/commands/ns_identify.cpp +++ b/modules/commands/ns_identify.cpp @@ -77,16 +77,27 @@ class CommandNSIdentify : public Command NickAlias *na = NickAlias::Find(nick); if (na && na->nc->HasExt("NS_SUSPENDED")) + { source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); - else if (u->Account() && na && u->Account() == na->nc) + return; + } + + if (u->Account() && na && u->Account() == na->nc) + { source.Reply(_("You are already identified.")); - else + return; + } + + unsigned int maxlogins = Config->GetModule(this->owner)->Get("maxlogins"); + if (na && maxlogins && na->nc->users.size() >= maxlogins) { - NSIdentifyRequest *req = new NSIdentifyRequest(owner, source, this, na ? na->nc->display : nick, pass); - FOREACH_MOD(OnCheckAuthentication, (u, req)); - req->Dispatch(); + source.Reply(_("Account \2%s\2 has exceeeded the maximum number of simultaneous logins (%u)."), na->nc->display.c_str(), maxlogins); + return; } - return; + + NSIdentifyRequest *req = new NSIdentifyRequest(owner, source, this, na ? na->nc->display : nick, pass); + FOREACH_MOD(OnCheckAuthentication, (u, req)); + req->Dispatch(); } bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override -- cgit From de023bab0a9edd7b0621ee6479447b2ea2492573 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 29 Jun 2015 13:47:50 -0400 Subject: Don't allow registering service nicks --- modules/commands/ns_register.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'modules/commands') diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp index 75ef5a9fb..5fe70437a 100644 --- a/modules/commands/ns_register.cpp +++ b/modules/commands/ns_register.cpp @@ -158,6 +158,12 @@ class CommandNSRegister : public Command return; } + if (BotInfo::Find(u_nick, true)) + { + source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); + return; + } + if (Config->GetModule("nickserv")->Get("restrictopernicks")) for (unsigned i = 0; i < Oper::opers.size(); ++i) { -- cgit From 02ed9a9725c40b57df965c4a13579bafebef2af3 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 29 Jun 2015 19:35:57 -0400 Subject: #1649 don't update keepmodes during inhbait --- modules/commands/cs_set.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 73bdb5a0c..cfff16377 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1207,6 +1207,8 @@ class CSSet : public Module CommandCSSetSuccessor commandcssetsuccessor; CommandCSSetNoexpire commandcssetnoexpire; + ExtensibleRef inhabit; + bool persist_lower_ts; public: @@ -1221,7 +1223,9 @@ class CSSet : public Module commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this), commandcssetpeace(this), commandcssetpersist(this), commandcssetrestricted(this), commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this), - commandcssetsuccessor(this), commandcssetnoexpire(this) + commandcssetsuccessor(this), commandcssetnoexpire(this), + + inhabit("inhabit") { } @@ -1271,7 +1275,7 @@ class CSSet : public Module if (mode->name == "PERM") persist.Set(c->ci, true); - if (mode->type != MODE_STATUS && !c->syncing && Me->IsSynced()) + if (mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && (!inhabit || !inhabit->HasExt(c))) c->ci->last_modes = c->GetModes(); } @@ -1286,7 +1290,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))) c->ci->last_modes = c->GetModes(); return EVENT_CONTINUE; -- cgit From 4362f53cc38177039d6f6b86565e73800e7b5390 Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 1 Jul 2015 20:16:59 -0400 Subject: Fix unused variable warning in cs_clone --- modules/commands/cs_clone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp index cbf53e892..282ff9afc 100644 --- a/modules/commands/cs_clone.cpp +++ b/modules/commands/cs_clone.cpp @@ -128,12 +128,12 @@ public: } User *u = source.GetUser(); - ChannelInfo *ci = ChannelInfo::Find(params[0]); + ChannelInfo *ci = ChannelInfo::Find(channel); bool override = false; if (ci == NULL) { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); + source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); return; } -- cgit From 1666b1a8d8d629fd4ea89b083863dc217154eee9 Mon Sep 17 00:00:00 2001 From: Peter Powell Date: Wed, 8 Jul 2015 10:55:44 +0100 Subject: Fix a ton of typos. --- modules/commands/cs_access.cpp | 2 +- modules/commands/cs_ban.cpp | 2 +- modules/commands/cs_mode.cpp | 2 +- modules/commands/cs_set.cpp | 2 +- modules/commands/cs_updown.cpp | 4 ++-- modules/commands/ms_check.cpp | 2 +- modules/commands/ms_read.cpp | 4 ++-- modules/commands/ms_set.cpp | 2 +- modules/commands/ns_logout.cpp | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 2fc245690..2fba96a9a 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -666,7 +666,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.")); diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp index de6a4f40e..2fd5cb8d1 100644 --- a/modules/commands/cs_ban.cpp +++ b/modules/commands/cs_ban.cpp @@ -118,7 +118,7 @@ class CommandCSBan : public Command if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick")) source.Reply(ACCESS_DENIED); /* - * 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. */ else if (c->MatchesList(u2, "EXCEPT")) diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index b11bc8862..0b36b989b 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -921,7 +921,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->set) { Anope::string param; diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index cfff16377..2559ae301 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -616,7 +616,7 @@ class CommandCSSetPersist : public Command " \n" "If your IRCd has a permanent (persistent) channel mode\n" "and it is set or unset (for any reason, including MODE LOCK),\n" - "persist is automatically set and unset for the channel aswell.\n" + "persist is automatically set and unset for the channel as well.\n" "Additionally, services will set or unset this mode when you\n" "set persist on or off."), BotServ ? BotServ->nick.c_str() : "BotServ", ChanServ ? ChanServ->nick.c_str() : "ChanServ"); diff --git a/modules/commands/cs_updown.cpp b/modules/commands/cs_updown.cpp index 4524a9831..96cab5b5f 100644 --- a/modules/commands/cs_updown.cpp +++ b/modules/commands/cs_updown.cpp @@ -124,7 +124,7 @@ class CommandCSUp : public Command this->SendSyntax(source); source.Reply(" "); source.Reply(_("Updates a selected nicks status modes on a channel. If \037nick\037 is\n" - "ommited then your status is updated. If \037channel\037 is ommited then\n" + "omitted then your status is updated. If \037channel\037 is omitted then\n" "your channel status is updated on every channel you are in.")); return true; } @@ -221,7 +221,7 @@ class CommandCSDown : public Command this->SendSyntax(source); source.Reply(" "); source.Reply(_("Removes a selected nicks status modes on a channel. If \037nick\037 is\n" - "ommited then your status is removed. If \037channel\037 is ommited then\n" + "omitted then your status is removed. If \037channel\037 is omitted then\n" "your channel status is removed on every channel you are in.")); return true; } diff --git a/modules/commands/ms_check.cpp b/modules/commands/ms_check.cpp index 6fab8919a..f789d785d 100644 --- a/modules/commands/ms_check.cpp +++ b/modules/commands/ms_check.cpp @@ -36,7 +36,7 @@ class CommandMSCheck : public Command MemoInfo *mi = &na->nc->memos; - /* Okay, I know this looks strange but we wanna get the LAST memo, so we + /* Okay, I know this looks strange but we want to get the LAST memo, so we have to loop backwards */ for (unsigned i = mi->memos->size(); i > 0; --i) diff --git a/modules/commands/ms_read.cpp b/modules/commands/ms_read.cpp index 82a3831ff..8dab9200e 100644 --- a/modules/commands/ms_read.cpp +++ b/modules/commands/ms_read.cpp @@ -30,14 +30,14 @@ static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Ano if (!nc) return; - /* Text of the memo varies if the recepient was a + /* Text of the memo varies if the recipient was a nick or channel */ Anope::string text = Anope::printf(Language::Translate(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")), targ.c_str()); /* Send notification */ MemoServService->Send(source.GetNick(), m->sender, text, true); - /* Notify recepient of the memo that a notification has + /* Notify recipient of the memo that a notification has been sent to the sender */ source.Reply(_("A notification memo has been sent to %s informing him/her you have\n" "read his/her memo."), nc->display.c_str()); diff --git a/modules/commands/ms_set.cpp b/modules/commands/ms_set.cpp index c3394f14d..63ffe383a 100644 --- a/modules/commands/ms_set.cpp +++ b/modules/commands/ms_set.cpp @@ -254,7 +254,7 @@ class CommandMSSet : public Command " on or when you unset /AWAY.\n" " NEW You will only be notified of memos when they\n" " are sent to you.\n" - " MAIL You will be notified of memos by email aswell as\n" + " MAIL You will be notified of memos by email as well as\n" " any other settings you have.\n" " NOMAIL You will not be notified of memos by email.\n" " OFF You will not receive any notification of memos.\n" diff --git a/modules/commands/ns_logout.cpp b/modules/commands/ns_logout.cpp index d8f7b2486..2ddff2185 100644 --- a/modules/commands/ns_logout.cpp +++ b/modules/commands/ns_logout.cpp @@ -40,7 +40,7 @@ class CommandNSLogout : public Command if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE") && NickServService) NickServService->Validate(u2); - u2->super_admin = false; /* Dont let people logout and remain a SuperAdmin */ + u2->super_admin = false; /* Don't let people logout and remain a SuperAdmin */ Log(LOG_COMMAND, source, this) << "to logout " << u2->nick; /* Remove founder status from this user in all channels */ -- cgit From a86162f2877d6576b2a4accec00372f246629869 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 13 Jul 2015 18:02:44 -0400 Subject: Fix incorrect iteration when destructing modelockimpls --- modules/commands/cs_mode.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index b11bc8862..e801b3959 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -44,10 +44,11 @@ struct ModeLocksImpl : ModeLocks ~ModeLocksImpl() { - for (ModeList::iterator it = this->mlocks->begin(); it != this->mlocks->end();) + ModeList modelist; + mlocks->swap(modelist); + for (ModeList::iterator it = modelist.begin(); it != modelist.end(); ++it) { ModeLock *ml = *it; - ++it; delete ml; } } -- cgit From 4e8cc4f786cd13cc3df2e9efea46e822fc03bd88 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 30 Jul 2015 19:47:00 -0400 Subject: Make secureops help less weird --- modules/commands/cs_set.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index cfff16377..d08806d98 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -870,8 +870,8 @@ class CommandCSSetSecureOps : public Command this->SendSyntax(source); source.Reply(" "); source.Reply(_("Enables or disables the \002secure ops\002 option for a channel.\n" - "When \002secure ops\002 is set, users who are not on the userlist\n" - "will not be allowed chanop status.")); + "When \002secure ops\002 is set, users who are not on the access list\n" + "will not be allowed channel operator status.")); return true; } }; -- cgit From 3b647b07407472abd4aca513a30f67f36969bd8f Mon Sep 17 00:00:00 2001 From: Robby Date: Wed, 2 Sep 2015 20:36:24 +0200 Subject: When toggling NOEXPIRE for a nickname, show the actual nickname in addition to the account name. --- modules/commands/ns_set.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp index e8e7c335c..589529d61 100644 --- a/modules/commands/ns_set.cpp +++ b/modules/commands/ns_set.cpp @@ -1107,13 +1107,13 @@ class CommandNSSASetNoexpire : public Command if (param.equals_ci("ON")) { - Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nc->display; + Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nick << " (" << na->nc->display << ")"; na->Extend("NS_NO_EXPIRE"); source.Reply(_("Nick %s \002will not\002 expire."), na->nick.c_str()); } else if (param.equals_ci("OFF")) { - Log(LOG_ADMIN, source, this) << "to disable noexpire for " << na->nc->display; + Log(LOG_ADMIN, source, this) << "to disable noexpire for " << na->nick << " (" << na->nc->display << ")"; na->Shrink("NS_NO_EXPIRE"); source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str()); } -- cgit From 94f781726ec14db780fdd376195ed81aa1f70464 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 11 Sep 2015 14:54:48 -0400 Subject: Don't assign bots when persist is set if we aren't synced sinec we might not know of all modes --- modules/commands/cs_set.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 106adf507..84541a2a9 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1170,7 +1170,8 @@ class CSSet : public Module { c->SetMode(NULL, cm); } - else + /* on startup we might not know mode availibity here */ + else if (Me && Me->IsSynced()) { if (!ci->bi) { -- cgit From 2f5e880e57be3d4881c47da991334c516e76ffaf Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 14 Sep 2015 12:24:13 -0400 Subject: Don't update channel last used time from ns alist access check --- modules/commands/ns_alist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/ns_alist.cpp b/modules/commands/ns_alist.cpp index 46981dc95..23389de22 100644 --- a/modules/commands/ns_alist.cpp +++ b/modules/commands/ns_alist.cpp @@ -78,7 +78,7 @@ class CommandNSAList : public Command continue; } - AccessGroup access = ci->AccessFor(nc); + AccessGroup access = ci->AccessFor(nc, false); if (access.empty()) continue; -- cgit From 8c4eec2b6e3bcc620258e2b928c2ea0b6351c327 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 14 Sep 2015 12:39:59 -0400 Subject: Update topic lock help to reflect how it works --- modules/commands/cs_topic.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp index 353cf83a3..968fe9942 100644 --- a/modules/commands/cs_topic.cpp +++ b/modules/commands/cs_topic.cpp @@ -196,7 +196,8 @@ class CommandCSTopic : public Command "the given topic to the existing topic.\n" " \n" "\002LOCK\002 and \002UNLOCK\002 may be used to enable and disable topic lock. When\n" - "topic lock is set, the channel topic will be unchangeable except via this command.")); + "topic lock is set, the channel topic will be unchangeable by users who do not have\n" + "the \002TOPIC\002 privilege.")); return true; } }; -- cgit From 8d13a355cd9b851b5cf9f6012c77b2af68a039f1 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 14 Sep 2015 13:43:14 -0400 Subject: Remove associated oper blocks in os_oper when accounts are deleted --- modules/commands/os_oper.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'modules/commands') diff --git a/modules/commands/os_oper.cpp b/modules/commands/os_oper.cpp index a99e770a7..7b74af5ea 100644 --- a/modules/commands/os_oper.cpp +++ b/modules/commands/os_oper.cpp @@ -277,6 +277,15 @@ class OSOper : public Module } } } + + void OnDelCore(NickCore *nc) anope_override + { + if (nc->o && dynamic_cast(nc->o)) + { + delete nc->o; + nc->o = NULL; + } + } }; MODULE_INIT(OSOper) -- cgit From 5692abb316647e4780e91c82bfe09007efd50243 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 17 Sep 2015 20:35:46 -0400 Subject: Don't prevent channel destruction because persist is set. Perm mode/a bot should be assigned anyway which will prevent it. Fixes deleting bots out of perm channels causing desyncs --- modules/commands/cs_set.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index 84541a2a9..663aa1b37 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1297,13 +1297,6 @@ class CSSet : public Module return EVENT_CONTINUE; } - EventReturn OnCheckDelete(Channel *c) anope_override - { - if (c->ci && persist.HasExt(c->ci)) - return EVENT_STOP; - return EVENT_CONTINUE; - } - void OnJoinChannel(User *u, Channel *c) anope_override { if (persist_lower_ts && c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->time_registered) -- cgit From 9810da9829e03aa7501b2afe183ff25da83679e8 Mon Sep 17 00:00:00 2001 From: Robby Date: Fri, 18 Sep 2015 04:53:49 +0200 Subject: Fix some sentences to be more correct. --- modules/commands/bs_bot.cpp | 4 ++-- modules/commands/ns_identify.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'modules/commands') diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp index 6a4f0344a..fc5f84863 100644 --- a/modules/commands/bs_bot.cpp +++ b/modules/commands/bs_bot.cpp @@ -78,7 +78,7 @@ class CommandBSBot : public Command User *u = User::Find(nick, true); if (u) { - source.Reply(_("User \2%s\2 is already in use."), u->nick.c_str()); + source.Reply(_("Nick \2%s\2 is currently in use."), u->nick.c_str()); return; } @@ -178,7 +178,7 @@ class CommandBSBot : public Command if (User::Find(nick, true)) { - source.Reply(_("User \2%s\2 is already in use."), nick.c_str()); + source.Reply(_("Nick \2%s\2 is currently in use."), nick.c_str()); return; } } diff --git a/modules/commands/ns_identify.cpp b/modules/commands/ns_iden