diff options
Diffstat (limited to 'modules/commands')
105 files changed, 0 insertions, 29438 deletions
diff --git a/modules/commands/bs_assign.cpp b/modules/commands/bs_assign.cpp deleted file mode 100644 index 0d1989fe9..000000000 --- a/modules/commands/bs_assign.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSAssign : public Command -{ - public: - CommandBSAssign(Module *creator) : Command(creator, "botserv/assign", 2, 2) - { - this->SetDesc(_("Assigns a bot to a channel")); - this->SetSyntax(_("\037channel\037 \037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &nick = params[1]; - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot assignment is temporarily disabled.")); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - BotInfo *bi = BotInfo::Find(nick, true); - if (!bi) - { - source.Reply(BOT_DOES_NOT_EXIST, nick.c_str()); - return; - } - - AccessGroup access = source.AccessFor(ci); - if (ci->HasExt("BS_NOBOT") || (!access.HasPriv("ASSIGN") && !source.HasPriv("botserv/administration"))) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (bi->oper_only && !source.HasPriv("botserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (ci->bi == bi) - { - source.Reply(_("Bot \002%s\002 is already assigned to channel \002%s\002."), ci->bi->nick.c_str(), chan.c_str()); - return; - } - - bool override = !access.HasPriv("ASSIGN"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << bi->nick; - - bi->Assign(source.GetUser(), ci); - source.Reply(_("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), ci->name.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Assigns the specified bot to a channel. You\n" - "can then configure the bot for the channel so it fits\n" - "your needs.")); - return true; - } -}; - -class CommandBSUnassign : public Command -{ - public: - CommandBSUnassign(Module *creator) : Command(creator, "botserv/unassign", 1, 1) - { - this->SetDesc(_("Unassigns a bot from a channel")); - this->SetSyntax(_("\037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot assignment is temporarily disabled.")); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - AccessGroup access = source.AccessFor(ci); - if (!source.HasPriv("botserv/administration") && !access.HasPriv("ASSIGN")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (!ci->bi) - { - source.Reply(BOT_NOT_ASSIGNED); - return; - } - - if (ci->HasExt("PERSIST") && !ModeManager::FindChannelModeByName("PERM")) - { - source.Reply(_("You cannot unassign bots while persist is set on the channel.")); - return; - } - - bool override = !access.HasPriv("ASSIGN"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << ci->bi->nick; - - ci->bi->UnAssign(source.GetUser(), ci); - source.Reply(_("There is no bot assigned to %s anymore."), ci->name.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Unassigns a bot from a channel. When you use this command,\n" - "the bot won't join the channel anymore. However, bot\n" - "configuration for the channel is kept, so you will always\n" - "be able to reassign a bot later without having to reconfigure\n" - "it entirely.")); - return true; - } -}; - -class CommandBSSetNoBot : public Command -{ - public: - CommandBSSetNoBot(Module *creator, const Anope::string &sname = "botserv/set/nobot") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("Prevent a bot from being assigned to a channel")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - const Anope::string &value = params[1]; - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot modification is temporarily disabled.")); - return; - } - - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (value.equals_ci("ON")) - { - Log(LOG_ADMIN, source, this, ci) << "to enable nobot"; - - ci->Extend<bool>("BS_NOBOT"); - if (ci->bi) - ci->bi->UnAssign(source.GetUser(), ci); - source.Reply(_("No-bot mode is now \002on\002 on channel %s."), ci->name.c_str()); - } - else if (value.equals_ci("OFF")) - { - Log(LOG_ADMIN, source, this, ci) << "to disable nobot"; - - ci->Shrink<bool>("BS_NOBOT"); - source.Reply(_("No-bot mode is now \002off\002 on channel %s."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, source.command); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "This option makes a channel unassignable. If a bot\n" - "is already assigned to the channel, it is unassigned\n" - "automatically when you enable it.")); - return true; - } -}; - -class BSAssign : public Module -{ - ExtensibleItem<bool> nobot; - - CommandBSAssign commandbsassign; - CommandBSUnassign commandbsunassign; - CommandBSSetNoBot commandbssetnobot; - - public: - BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - nobot(this, "BS_NOBOT"), - commandbsassign(this), commandbsunassign(this), commandbssetnobot(this) - { - } - - void OnInvite(User *source, Channel *c, User *targ) anope_override - { - BotInfo *bi; - if (Anope::ReadOnly || !c->ci || targ->server != Me || !(bi = dynamic_cast<BotInfo *>(targ))) - return; - - AccessGroup access = c->ci->AccessFor(source); - if (nobot.HasExt(c->ci) || (!access.HasPriv("ASSIGN") && !source->HasPriv("botserv/administration"))) - { - targ->SendMessage(bi, ACCESS_DENIED); - return; - } - - if (bi->oper_only && !source->HasPriv("botserv/administration")) - { - targ->SendMessage(bi, ACCESS_DENIED); - return; - } - - if (c->ci->bi == bi) - { - targ->SendMessage(bi, _("Bot \002%s\002 is already assigned to channel \002%s\002."), c->ci->bi->nick.c_str(), c->name.c_str()); - return; - } - - bi->Assign(source, c->ci); - targ->SendMessage(bi, _("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), c->name.c_str()); - } - - void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override - { - if (nobot.HasExt(ci)) - info.AddOption(_("No bot")); - } -}; - -MODULE_INIT(BSAssign) diff --git a/modules/commands/bs_badwords.cpp b/modules/commands/bs_badwords.cpp deleted file mode 100644 index 57731b168..000000000 --- a/modules/commands/bs_badwords.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/bs_badwords.h" - -struct BadWordImpl : BadWord, Serializable -{ - BadWordImpl() : Serializable("BadWord") { } - ~BadWordImpl(); - - void Serialize(Serialize::Data &data) const anope_override - { - data["ci"] << this->chan; - data["word"] << this->word; - data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &); -}; - -struct BadWordsImpl : BadWords -{ - Serialize::Reference<ChannelInfo> ci; - typedef std::vector<BadWordImpl *> list; - Serialize::Checker<list> badwords; - - BadWordsImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), badwords("BadWord") { } - - ~BadWordsImpl(); - - BadWord* AddBadWord(const Anope::string &word, BadWordType type) anope_override - { - BadWordImpl *bw = new BadWordImpl(); - bw->chan = ci->name; - bw->word = word; - bw->type = type; - - this->badwords->push_back(bw); - - FOREACH_MOD(OnBadWordAdd, (ci, bw)); - - return bw; - } - - BadWord* GetBadWord(unsigned index) const anope_override - { - if (this->badwords->empty() || index >= this->badwords->size()) - return NULL; - - BadWordImpl *bw = (*this->badwords)[index]; - bw->QueueUpdate(); - return bw; - } - - unsigned GetBadWordCount() const anope_override - { - return this->badwords->size(); - } - - void EraseBadWord(unsigned index) anope_override - { - if (this->badwords->empty() || index >= this->badwords->size()) - return; - - FOREACH_MOD(OnBadWordDel, (ci, (*this->badwords)[index])); - - delete this->badwords->at(index); - } - - void ClearBadWords() anope_override - { - while (!this->badwords->empty()) - delete this->badwords->back(); - } - - void Check() anope_override - { - if (this->badwords->empty()) - ci->Shrink<BadWords>("badwords"); - } -}; - -BadWordsImpl::~BadWordsImpl() -{ - for (list::iterator it = badwords->begin(); it != badwords->end();) - { - BadWord *bw = *it; - ++it; - delete bw; - } -} - -BadWordImpl::~BadWordImpl() -{ - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci) - { - BadWordsImpl *badwords = ci->GetExt<BadWordsImpl>("badwords"); - if (badwords) - { - BadWordsImpl::list::iterator it = std::find(badwords->badwords->begin(), badwords->badwords->end(), this); - if (it != badwords->badwords->end()) - badwords->badwords->erase(it); - } - } -} - -Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data) -{ - Anope::string sci, sword; - - data["ci"] >> sci; - data["word"] >> sword; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (!ci) - return NULL; - - unsigned int n; - data["type"] >> n; - - BadWordImpl *bw; - if (obj) - bw = anope_dynamic_static_cast<BadWordImpl *>(obj); - else - bw = new BadWordImpl(); - bw->chan = sci; - bw->word = sword; - bw->type = static_cast<BadWordType>(n); - - BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords"); - if (!obj) - bws->badwords->push_back(bw); - - return bw; -} - -class BadwordsDelCallback : public NumberList -{ - CommandSource &source; - ChannelInfo *ci; - BadWords *bw; - Command *c; - unsigned deleted; - bool override; - public: - BadwordsDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), deleted(0), override(false) - { - if (!source.AccessFor(ci).HasPriv("BADWORDS") && source.HasPriv("botserv/administration")) - this->override = true; - bw = ci->Require<BadWords>("badwords"); - } - - ~BadwordsDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str()); - else if (deleted == 1) - source.Reply(_("Deleted 1 entry from %s bad words list."), ci->name.c_str()); - else - source.Reply(_("Deleted %d entries from %s bad words list."), deleted, ci->name.c_str()); - } - - void HandleNumber(unsigned Number) anope_override - { - if (!bw || !Number || Number > bw->GetBadWordCount()) - return; - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << bw->GetBadWord(Number - 1)->word; - ++deleted; - bw->EraseBadWord(Number - 1); - } -}; - -class CommandBSBadwords : public Command -{ - private: - void DoList(CommandSource &source, ChannelInfo *ci, const Anope::string &word) - { - bool override = !source.AccessFor(ci).HasPriv("BADWORDS"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "LIST"; - ListFormatter list(source.GetAccount()); - BadWords *bw = ci->GetExt<BadWords>("badwords"); - - list.AddColumn(_("Number")).AddColumn(_("Word")).AddColumn(_("Type")); - - if (!bw || !bw->GetBadWordCount()) - { - source.Reply(_("%s bad words list is empty."), ci->name.c_str()); - return; - } - else if (!word.empty() && word.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class BadwordsListCallback : public NumberList - { - ListFormatter &list; - BadWords *bw; - public: - BadwordsListCallback(ListFormatter &_list, BadWords *_bw, const Anope::string &numlist) : NumberList(numlist, false), list(_list), bw(_bw) - { - } - - void HandleNumber(unsigned Number) anope_override - { - if (!Number || Number > bw->GetBadWordCount()) - return; - - const BadWord *b = bw->GetBadWord(Number - 1); - ListFormatter::ListEntry entry; - entry["Number"] = stringify(Number); - entry["Word"] = b->word; - entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : "")); - this->list.AddEntry(entry); - } - } - nl_list(list, bw, word); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = bw->GetBadWordCount(); i < end; ++i) - { - const BadWord *b = bw->GetBadWord(i); - - if (!word.empty() && !Anope::Match(b->word, word)) - continue; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Word"] = b->word; - entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : "")); - list.AddEntry(entry); - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str()); - else - { - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("Bad words list for %s:"), ci->name.c_str()); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of bad words list.")); - } - } - - void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &word) - { - size_t pos = word.rfind(' '); - BadWordType bwtype = BW_ANY; - Anope::string realword = word; - BadWords *badwords = ci->Require<BadWords>("badwords"); - - if (pos != Anope::string::npos) - { - Anope::string opt = word.substr(pos + 1); - if (!opt.empty()) - { - if (opt.equals_ci("SINGLE")) - bwtype = BW_SINGLE; - else if (opt.equals_ci("START")) - bwtype = BW_START; - else if (opt.equals_ci("END")) - bwtype = BW_END; - } - realword = word.substr(0, pos); - } - - unsigned badwordsmax = Config->GetModule(this->module)->Get<unsigned>("badwordsmax"); - if (badwords->GetBadWordCount() >= badwordsmax) - { - source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), badwordsmax); - return; - } - - bool casesensitive = Config->GetModule(this->module)->Get<bool>("casesensitive"); - - for (unsigned i = 0, end = badwords->GetBadWordCount(); i < end; ++i) - { - const BadWord *bw = badwords->GetBadWord(i); - - if ((casesensitive && realword.equals_cs(bw->word)) || (!casesensitive && realword.equals_ci(bw->word))) - { - source.Reply(_("\002%s\002 already exists in %s bad words list."), bw->word.c_str(), ci->name.c_str()); - return; - } - } - - bool override = !source.AccessFor(ci).HasPriv("BADWORDS"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ADD " << realword; - badwords->AddBadWord(realword, bwtype); - - source.Reply(_("\002%s\002 added to %s bad words list."), realword.c_str(), ci->name.c_str()); - } - - void DoDelete(CommandSource &source, ChannelInfo *ci, const Anope::string &word) - { - BadWords *badwords = ci->GetExt<BadWords>("badwords"); - - if (!badwords || !badwords->GetBadWordCount()) - { - source.Reply(_("%s bad words list is empty."), ci->name.c_str()); - return; - } - - /* Special case: is it a number/list? Only do search if it isn't. */ - if (!word.empty() && isdigit(word[0]) && word.find_first_not_of("1234567890,-") == Anope::string::npos) - { - BadwordsDelCallback list(source, ci, this, word); - list.Process(); - } - else - { - unsigned i, end; - const BadWord *badword; - - for (i = 0, end = badwords->GetBadWordCount(); i < end; ++i) - { - badword = badwords->GetBadWord(i); - - if (word.equals_ci(badword->word)) - break; - } - - if (i == end) - { - source.Reply(_("\002%s\002 not found on %s bad words list."), word.c_str(), ci->name.c_str()); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("BADWORDS"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "DEL " << badword->word; - - source.Reply(_("\002%s\002 deleted from %s bad words list."), badword->word.c_str(), ci->name.c_str()); - - badwords->EraseBadWord(i); - } - - badwords->Check(); - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("BADWORDS"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "CLEAR"; - - BadWords *badwords = ci->GetExt<BadWords>("badwords"); - if (badwords) - badwords->ClearBadWords(); - source.Reply(_("Bad words list is now empty.")); - } - - public: - CommandBSBadwords(Module *creator) : Command(creator, "botserv/badwords", 2, 3) - { - this->SetDesc(_("Maintains the bad words list")); - this->SetSyntax(_("\037channel\037 ADD \037word\037 [\037SINGLE\037 | \037START\037 | \037END\037]")); - this->SetSyntax(_("\037channel\037 DEL {\037word\037 | \037entry-num\037 | \037list\037}")); - this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[1]; - const Anope::string &word = params.size() > 2 ? params[2] : ""; - bool need_args = cmd.equals_ci("LIST") || cmd.equals_ci("CLEAR"); - - if (!need_args && word.empty()) - { - this->OnSyntaxError(source, cmd); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("BADWORDS") && (!need_args || !source.HasPriv("botserv/administration"))) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bad words list modification is temporarily disabled.")); - return; - } - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, ci, word); - else if (cmd.equals_ci("DEL")) - return this->DoDelete(source, ci, word); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, ci, word); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source, ci); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002bad words list\002 for a channel. The bad\n" - "words list determines which words are to be kicked\n" - "when the bad words kicker is enabled. For more information,\n" - "type \002%s%s HELP KICK %s\002.\n" - " \n" - "The \002ADD\002 command adds the given word to the\n" - "bad words list. If SINGLE is specified, a kick will be\n" - "done only if a user says the entire word. If START is\n" - "specified, a kick will be done if a user says a word\n" - "that starts with \037word\037. If END is specified, a kick\n" - "will be done if a user says a word that ends with\n" - "\037word\037. If you don't specify anything, a kick will\n" - "be issued every time \037word\037 is said by a user.\n" - " \n"), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str()); - source.Reply(_("The \002DEL\002 command removes the given word from the\n" - "bad words list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002LIST\002 command displays the bad words list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002#channel LIST 2-5,7-9\002\n" - " Lists bad words entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002CLEAR\002 command clears all entries from the\n" - "bad words list.")); - return true; - } -}; - -class BSBadwords : public Module -{ - CommandBSBadwords commandbsbadwords; - ExtensibleItem<BadWordsImpl> badwords; - Serialize::Type badword_type; - - public: - BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize) - { - } -}; - -MODULE_INIT(BSBadwords) diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp deleted file mode 100644 index 6a152937a..000000000 --- a/modules/commands/bs_bot.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSBot : public Command -{ - private: - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &nick = params[1]; - const Anope::string &user = params[2]; - const Anope::string &host = params[3]; - const Anope::string &real = params[4]; - - if (BotInfo::Find(nick, true)) - { - source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); - return; - } - - Configuration::Block *networkinfo = Config->GetBlock("networkinfo"); - - if (nick.length() > networkinfo->Get<unsigned>("nicklen")) - { - source.Reply(_("Bot nicks may only be %d characters long."), networkinfo->Get<unsigned>("nicklen")); - return; - } - - if (user.length() > networkinfo->Get<unsigned>("userlen")) - { - source.Reply(_("Bot idents may only be %d characters long."), networkinfo->Get<unsigned>("userlen")); - return; - } - - if (host.length() > networkinfo->Get<unsigned>("hostlen")) - { - source.Reply(_("Bot hosts may only be %d characters long."), networkinfo->Get<unsigned>("hostlen")); - return; - } - - if (!IRCD->IsNickValid(nick)) - { - source.Reply(_("Bot nicks may only contain valid nick characters.")); - return; - } - - if (!IRCD->IsIdentValid(user)) - { - source.Reply(_("Bot idents may only contain valid ident characters.")); - return; - } - - if (!IRCD->IsHostValid(host)) - { - source.Reply(_("Bot hosts may only contain valid host characters.")); - return; - } - - /* We check whether the nick is registered, and inform the user - * if so. You need to drop the nick manually before you can use - * it as a bot nick from now on -GD - */ - if (NickAlias::Find(nick)) - { - source.Reply(NICK_ALREADY_REGISTERED, nick.c_str()); - return; - } - - User *u = User::Find(nick, true); - if (u) - { - source.Reply(_("Nick \002%s\002 is currently 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; - - source.Reply(_("%s!%s@%s (%s) added to the bot list."), bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); - - FOREACH_MOD(OnBotCreate, (bi)); - return; - } - - void DoChange(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &oldnick = params[1]; - const Anope::string &nick = params.size() > 2 ? params[2] : ""; - const Anope::string &user = params.size() > 3 ? params[3] : ""; - const Anope::string &host = params.size() > 4 ? params[4] : ""; - const Anope::string &real = params.size() > 5 ? params[5] : ""; - - if (oldnick.empty() || nick.empty()) - { - this->OnSyntaxError(source, "CHANGE"); - return; - } - - BotInfo *bi = BotInfo::Find(oldnick, true); - if (!bi) - { - source.Reply(BOT_DOES_NOT_EXIST, oldnick.c_str()); - return; - } - - if (bi->conf) - { - source.Reply(_("Bot %s is not changeable."), bi->nick.c_str()); - return; - } - - Configuration::Block *networkinfo = Config->GetBlock("networkinfo"); - - if (nick.length() > networkinfo->Get<unsigned>("nicklen")) - { - source.Reply(_("Bot nicks may only be %d characters long."), networkinfo->Get<unsigned>("nicklen")); - return; - } - - if (user.length() > networkinfo->Get<unsigned>("userlen")) - { - source.Reply(_("Bot idents may only be %d characters long."), networkinfo->Get<unsigned>("userlen")); - return; - } - - if (host.length() > networkinfo->Get<unsigned>("hostlen")) - { - source.Reply(_("Bot hosts may only be %d characters long."), networkinfo->Get<unsigned>("hostlen")); - return; - } - - /* Checks whether there *are* changes. - * Case sensitive because we may want to change just the case. - * And we must finally check that the nick is not already - * taken by another bot. - */ - if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1)) - { - source.Reply(_("The old information is the same as the new information specified.")); - return; - } - - if (!IRCD->IsNickValid(nick)) - { - source.Reply(_("Bot nicks may only contain valid nick characters.")); - return; - } - - if (!user.empty() && !IRCD->IsIdentValid(user)) - { - source.Reply(_("Bot idents may only contain valid ident characters.")); - return; - } - - if (!host.empty() && !IRCD->IsHostValid(host)) - { - source.Reply(_("Bot hosts may only contain valid host characters.")); - return; - } - - if (!nick.equals_ci(bi->nick)) - { - if (BotInfo::Find(nick, true)) - { - source.Reply(_("Bot \002%s\002 already exists."), nick.c_str()); - return; - } - - if (User::Find(nick, true)) - { - source.Reply(_("Nick \002%s\002 is currently in use."), nick.c_str()); - return; - } - } - - if (!nick.equals_ci(bi->nick)) - { - /* We check whether the nick is registered, and inform the user - * if so. You need to drop the nick manually before you can use - * it as a bot nick from now on -GD - */ - if (NickAlias::Find(nick)) - { - source.Reply(NICK_ALREADY_REGISTERED, nick.c_str()); - return; - } - - /* The new nick is really different, so we remove the Q line for the old nick. */ - XLine x_del(bi->nick); - IRCD->SendSQLineDel(&x_del); - - /* Add a Q line for the new nick */ - XLine x(nick, "Reserved for services"); - IRCD->SendSQLine(NULL, &x); - } - - if (!user.empty()) - { - IRCD->SendQuit(bi, "Quit: Be right back"); - bi->introduced = false; - } - else - IRCD->SendNickChange(bi, nick); - - if (!nick.equals_cs(bi->nick)) - bi->SetNewNick(nick); - - if (!user.empty() && !user.equals_cs(bi->GetIdent())) - bi->SetIdent(user); - if (!host.empty() && !host.equals_cs(bi->host)) - bi->host = host; - if (!real.empty() && !real.equals_cs(bi->realname)) - bi->realname = real; - - if (!user.empty()) - bi->OnKill(); - - source.Reply(_("Bot \002%s\002 has been changed to %s!%s@%s (%s)."), oldnick.c_str(), bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); - Log(LOG_ADMIN, source, this) << "CHANGE " << oldnick << " to " << bi->GetMask() << " " << bi->realname; - - FOREACH_MOD(OnBotChange, (bi)); - return; - } - - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &nick = params[1]; - - if (nick.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - BotInfo *bi = BotInfo::Find(nick, true); - if (!bi) - { - source.Reply(BOT_DOES_NOT_EXIST, nick.c_str()); - return; - } - - if (bi->conf) - { - source.Reply(_("Bot %s is not deletable."), bi->nick.c_str()); - return; - } - - FOREACH_MOD(OnBotDelete, (bi)); - - Log(LOG_ADMIN, source, this) << "DEL " << bi->nick; - - source.Reply(_("Bot \002%s\002 has been deleted."), nick.c_str()); - delete bi; - return; - } - public: - CommandBSBot(Module *creator) : Command(creator, "botserv/bot", 1, 6) - { - this->SetDesc(_("Maintains network bot list")); - this->SetSyntax(_("\002ADD \037nick\037 \037user\037 \037host\037 \037real\037\002")); - this->SetSyntax(_("\002CHANGE \037oldnick\037 \037newnick\037 [\037user\037 [\037host\037 [\037real\037]]]\002")); - this->SetSyntax(_("\002DEL \037nick\037\002")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot modification is temporarily disabled.")); - return; - } - - if (cmd.equals_ci("ADD")) - { - // ADD nick user host real - 5 - if (!source.HasCommand("botserv/bot/add")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params.size() < 5) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - std::vector<Anope::string> tempparams = params; - // ADD takes less params than CHANGE, so we need to take 6 if given and append it with a space to 5. - if (tempparams.size() >= 6) - tempparams[4] = tempparams[4] + " " + tempparams[5]; - - return this->DoAdd(source, tempparams); - } - else if (cmd.equals_ci("CHANGE")) - { - // CHANGE oldn newn user host real - 6 - // but only oldn and newn are required - if (!source.HasCommand("botserv/bot/change")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params.size() < 3) - { - this->OnSyntaxError(source, "CHANGE"); - return; - } - - return this->DoChange(source, params); - } - else if (cmd.equals_ci("DEL")) - { - // DEL nick - if (!source.HasCommand("botserv/bot/del")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params.size() < 1) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - return this->DoDel(source, params); - } - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to create, modify, and delete\n" - "bots that users will be able to use on their own\n" - "channels.\n" - " \n" - "\002BOT ADD\002 adds a bot with the given nickname, username,\n" - "hostname and realname. Since no integrity checks are done\n" - "for these settings, be really careful.\n" - " \n" - "\002BOT CHANGE\002 allows you to change the nickname, username, hostname\n" - "or realname of a bot without deleting it (and\n" - "all the data associated with it).\n" - " \n" - "\002BOT DEL\002 removes the given bot from the bot list.\n" - " \n" - "\002Note\002: You cannot create a bot with a nick that is\n" - "currently registered. If an unregistered user is currently\n" - "using the nick, they will be killed.")); - return true; - } -}; - -class BSBot : public Module -{ - CommandBSBot commandbsbot; - - public: - BSBot(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbsbot(this) - { - - } -}; - -MODULE_INIT(BSBot) diff --git a/modules/commands/bs_botlist.cpp b/modules/commands/bs_botlist.cpp deleted file mode 100644 index 089c2894d..000000000 --- a/modules/commands/bs_botlist.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSBotList : public Command -{ - public: - CommandBSBotList(Module *creator) : Command(creator, "botserv/botlist", 0, 0) - { - this->SetDesc(_("Lists available bots")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - unsigned count = 0; - ListFormatter list(source.GetAccount()); - - list.AddColumn(_("Nick")).AddColumn(_("Mask")); - - for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - if (source.HasPriv("botserv/administration") || !bi->oper_only) - { - ++count; - ListFormatter::ListEntry entry; - entry["Nick"] = (bi->oper_only ? "* " : "") + bi->nick; - entry["Mask"] = bi->GetIdent() + "@" + bi->host; - list.AddEntry(entry); - } - } - - std::vector<Anope::string> replies; - list.Process(replies); - - if (!count) - source.Reply(_("There are no bots available at this time.\n" - "Ask a Services Operator to create one!")); - else - { - source.Reply(_("Bot list:")); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("%d bots available."), count); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all available bots on this network.\n" - "Bots prefixed by a * are reserved for IRC Operators.")); - return true; - } -}; - -class BSBotList : public Module -{ - CommandBSBotList commandbsbotlist; - - public: - BSBotList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbsbotlist(this) - { - - } -}; - -MODULE_INIT(BSBotList) diff --git a/modules/commands/bs_control.cpp b/modules/commands/bs_control.cpp deleted file mode 100644 index bdacf8dd1..000000000 --- a/modules/commands/bs_control.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSSay : public Command -{ - public: - CommandBSSay(Module *creator) : Command(creator, "botserv/say", 2, 2) - { - this->SetDesc(_("Makes the bot say the specified text on the specified channel")); - this->SetSyntax(_("\037channel\037 \037text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &text = params[1]; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("SAY") && !source.HasPriv("botserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (!ci->bi) - { - source.Reply(BOT_NOT_ASSIGNED); - return; - } - - if (!ci->c || !ci->c->FindUser(ci->bi)) - { - source.Reply(BOT_NOT_ON_CHANNEL, ci->name.c_str()); - return; - } - - if (text[0] == '\001') - { - this->OnSyntaxError(source, ""); - return; - } - - IRCD->SendPrivmsg(*ci->bi, ci->name, "%s", text.c_str()); - ci->bi->lastmsg = Anope::CurTime; - - bool override = !source.AccessFor(ci).HasPriv("SAY"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to say: " << text; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Makes the bot say the specified text on the specified channel.")); - return true; - } -}; - -class CommandBSAct : public Command -{ - public: - CommandBSAct(Module *creator) : Command(creator, "botserv/act", 2, 2) - { - this->SetDesc(_("Makes the bot do the equivalent of a \"/me\" command")); - this->SetSyntax(_("\037channel\037 \037text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Anope::string message = params[1]; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("SAY") && !source.HasPriv("botserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (!ci->bi) - { - source.Reply(BOT_NOT_ASSIGNED); - return; - } - - if (!ci->c || !ci->c->FindUser(ci->bi)) - { - source.Reply(BOT_NOT_ON_CHANNEL, ci->name.c_str()); - return; - } - - message = message.replace_all_cs("\1", ""); - if (message.empty()) - return; - - IRCD->SendAction(*ci->bi, ci->name, "%s", message.c_str()); - ci->bi->lastmsg = Anope::CurTime; - - bool override = !source.AccessFor(ci).HasPriv("SAY"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to say: " << message; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Makes the bot do the equivalent of a \"/me\" command\n" - "on the specified channel using the specified text.")); - return true; - } -}; - -class BSControl : public Module -{ - CommandBSSay commandbssay; - CommandBSAct commandbsact; - - public: - BSControl(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbssay(this), commandbsact(this) - { - - } -}; - -MODULE_INIT(BSControl) diff --git a/modules/commands/bs_info.cpp b/modules/commands/bs_info.cpp deleted file mode 100644 index 76dcfa4f4..000000000 --- a/modules/commands/bs_info.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSInfo : public Command -{ - private: - void send_bot_channels(std::vector<Anope::string> &buffers, const BotInfo *bi) - { - Anope::string buf; - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) - { - const ChannelInfo *ci = it->second; - - if (ci->bi == bi) - { - buf += " " + ci->name + " "; - if (buf.length() > 300) - { - buffers.push_back(buf); - buf.clear(); - } - } - } - if (!buf.empty()) - buffers.push_back(buf); - } - - public: - CommandBSInfo(Module *creator) : Command(creator, "botserv/info", 1, 1) - { - this->SetSyntax(_("{\037channel\037 | \037nickname\037}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &query = params[0]; - - BotInfo *bi = BotInfo::Find(query, true); - ChannelInfo *ci = ChannelInfo::Find(query); - InfoFormatter info(source.nc); - - if (bi) - { - source.Reply(_("Information for bot \002%s\002:"), bi->nick.c_str()); - info[_("Mask")] = bi->GetIdent() + "@" + bi->host; - info[_("Real name")] = bi->realname; - info[_("Created")] = Anope::strftime(bi->created, source.GetAccount()); - info[_("Options")] = bi->oper_only ? _("Private") : _("None"); - info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)"; - - FOREACH_MOD(OnBotInfo, (source, bi, ci, info)); - - std::vector<Anope::string> replies; - info.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - if (source.HasPriv("botserv/administration")) - { - std::vector<Anope::string> buf; - this->send_bot_channels(buf, bi); - for (unsigned i = 0; i < buf.size(); ++i) - source.Reply(buf[i]); - } - - } - else if (ci) - { - if (!source.AccessFor(ci).HasPriv("INFO") && !source.HasPriv("botserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - source.Reply(CHAN_INFO_HEADER, ci->name.c_str()); - info[_("Bot nick")] = ci->bi ? ci->bi->nick : _("not assigned yet"); - - Anope::string enabled = Language::Translate(source.nc, _("Enabled")); - Anope::string disabled = Language::Translate(source.nc, _("Disabled")); - - FOREACH_MOD(OnBotInfo, (source, bi, ci, info)); - - std::vector<Anope::string> replies; - info.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - else - source.Reply(_("\002%s\002 is not a valid bot or registered channel."), query.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to see %s information about a channel or a bot.\n" - "If the parameter is a channel, then you'll get information\n" - "such as enabled kickers. If the parameter is a nick,\n" - "you'll get information about a bot, such as creation\n" - "time or number of channels it is on."), source.service->nick.c_str()); - return true; - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - return Anope::printf(Language::Translate(source.GetAccount(), _("Allows you to see %s information about a channel or a bot")), source.service->nick.c_str()); - } -}; - -class BSInfo : public Module -{ - CommandBSInfo commandbsinfo; - - public: - BSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbsinfo(this) - { - - } -}; - -MODULE_INIT(BSInfo) diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp deleted file mode 100644 index 1897bc5e6..000000000 --- a/modules/commands/bs_kick.cpp +++ /dev/null @@ -1,1474 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/bs_kick.h" -#include "modules/bs_badwords.h" - -static Module *me; - -struct KickerDataImpl : KickerData -{ - KickerDataImpl(Extensible *obj) - { - amsgs = badwords = bolds = caps = colors = flood = italics = repeat = reverses = underlines = false; - for (int16_t i = 0; i < TTB_SIZE; ++i) - ttb[i] = 0; - capsmin = capspercent = 0; - floodlines = floodsecs = 0; - repeattimes = 0; - - dontkickops = dontkickvoices = false; - } - - void Check(ChannelInfo *ci) anope_override - { - if (amsgs || badwords || bolds || caps || colors || flood || italics || repeat || reverses || underlines) - return; - - ci->Shrink<KickerData>("kickerdata"); - } - - struct ExtensibleItem : ::ExtensibleItem<KickerDataImpl> - { - ExtensibleItem(Module *m, const Anope::string &ename) : ::ExtensibleItem<KickerDataImpl>(m, ename) { } - - void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override - { - if (s->GetSerializableType()->GetName() != "ChannelInfo") - return; - - const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e); - KickerData *kd = this->Get(ci); - if (kd == NULL) - return; - - data["kickerdata:amsgs"] << kd->amsgs; - data["kickerdata:badwords"] << kd->badwords; - data["kickerdata:bolds"] << kd->bolds; - data["kickerdata:caps"] << kd->caps; - data["kickerdata:colors"] << kd->colors; - data["kickerdata:flood"] << kd->flood; - data["kickerdata:italics"] << kd->italics; - data["kickerdata:repeat"] << kd->repeat; - data["kickerdata:reverses"] << kd->reverses; - data["kickerdata:underlines"] << kd->underlines; - - data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin; - data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent; - data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines; - data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs; - data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes; - for (int16_t i = 0; i < TTB_SIZE; ++i) - data["ttb"] << kd->ttb[i] << " "; - } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override - { - if (s->GetSerializableType()->GetName() != "ChannelInfo") - return; - - ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e); - KickerData *kd = ci->Require<KickerData>("kickerdata"); - - data["kickerdata:amsgs"] >> kd->amsgs; - data["kickerdata:badwords"] >> kd->badwords; - data["kickerdata:bolds"] >> kd->bolds; - data["kickerdata:caps"] >> kd->caps; - data["kickerdata:colors"] >> kd->colors; - data["kickerdata:flood"] >> kd->flood; - data["kickerdata:italics"] >> kd->italics; - data["kickerdata:repeat"] >> kd->repeat; - data["kickerdata:reverses"] >> kd->reverses; - data["kickerdata:underlines"] >> kd->underlines; - - data["capsmin"] >> kd->capsmin; - data["capspercent"] >> kd->capspercent; - data["floodlines"] >> kd->floodlines; - data["floodsecs"] >> kd->floodsecs; - data["repeattimes"] >> kd->repeattimes; - - Anope::string ttb, tok; - data["ttb"] >> ttb; - spacesepstream sep(ttb); - for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i) - try - { - kd->ttb[i] = convertTo<int16_t>(tok); - } - catch (const ConvertException &) { } - - kd->Check(ci); - } - }; -}; - -class CommandBSKick : public Command -{ - public: - CommandBSKick(Module *creator) : Command(creator, "botserv/kick", 0) - { - this->SetDesc(_("Configures kickers")); - this->SetSyntax(_("\037option\037 \037channel\037 {\037ON|OFF\037} [\037settings\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Configures bot kickers. \037option\037 can be one of:")); - - Anope::string this_name = source.command; - for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - - if (c_name.find_ci(this_name + " ") == 0) - { - ServiceReference<Command> command("Command", info.name); - if (command) - { - source.command = c_name; - command->OnServHelp(source); - } - } - } - - source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option.\n" - " \n" - "Note: access to this command is controlled by the\n" - "level SET."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); - - return true; - } -}; - -class CommandBSKickBase : public Command -{ - public: - CommandBSKickBase(Module *creator, const Anope::string &cname, int minarg, int maxarg) : Command(creator, cname, minarg, maxarg) - { - } - - virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override = 0; - - virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override = 0; - - protected: - bool CheckArguments(CommandSource &source, const std::vector<Anope::string> ¶ms, ChannelInfo* &ci) - { - const Anope::string &chan = params[0]; - const Anope::string &option = params[1]; - - ci = ChannelInfo::Find(chan); - - if (Anope::ReadOnly) - source.Reply(_("Sorry, kicker configuration is temporarily disabled.")); - else if (ci == NULL) - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - else if (option.empty()) - this->OnSyntaxError(source, ""); - else if (!option.equals_ci("ON") && !option.equals_ci("OFF")) - this->OnSyntaxError(source, ""); - else if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("botserv/administration")) - source.Reply(ACCESS_DENIED); - else if (!ci->bi) - source.Reply(BOT_NOT_ASSIGNED); - else - return true; - - return false; - } - - void Process(CommandSource &source, ChannelInfo *ci, const Anope::string ¶m, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, KickerData *kd, bool &val) - { - if (param.equals_ci("ON")) - { - if (!ttb.empty()) - { - int16_t i; - - try - { - i = convertTo<int16_t>(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return; - } - - kd->ttb[ttb_idx] = i; - } - else - kd->ttb[ttb_idx] = 0; - - val = true; - if (kd->ttb[ttb_idx]) - source.Reply(_("Bot will now kick for \002%s\002, and will place a ban\n" - "after %d kicks for the same user."), optname.c_str(), kd->ttb[ttb_idx]); - else - source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str()); - - bool override = !source.AccessFor(ci).HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable the " << optname << " kicker"; - } - else if (param.equals_ci("OFF")) - { - bool override = !source.AccessFor(ci).HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << " kicker"; - - val = false; - source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str()); - } - else - this->OnSyntaxError(source, ""); - } -}; - -class CommandBSKickAMSG : public CommandBSKickBase -{ - public: - CommandBSKickAMSG(Module *creator) : CommandBSKickBase(creator, "botserv/kick/amsg", 2, 3) - { - this->SetDesc(_("Configures AMSG kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", kd, kd->amsgs); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - BotInfo *bi = Config->GetClient("BotServ"); - source.Reply(_("Sets the AMSG kicker on or off. When enabled, the bot will\n" - "kick users who send the same message to multiple channels\n" - "where %s bots are.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before they get banned. Don't give ttb to disable\n" - "the ban system once activated."), bi ? bi->nick.c_str() : "BotServ"); - return true; - } -}; - -class CommandBSKickBadwords : public CommandBSKickBase -{ - public: - CommandBSKickBadwords(Module *creator) : CommandBSKickBase(creator, "botserv/kick/badwords", 2, 3) - { - this->SetDesc(_("Configures badwords kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", kd, kd->badwords); - kd->Check(ci); - } - - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the bad words kicker on or off. When enabled, this\n" - "option tells the bot to kick users who say certain words\n" - "on the channels.\n" - "You can define bad words for your channel using the\n" - "\002BADWORDS\002 command. Type \002%s%s HELP BADWORDS\002 for\n" - "more information.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class CommandBSKickBolds : public CommandBSKickBase -{ - public: - CommandBSKickBolds(Module *creator) : CommandBSKickBase(creator, "botserv/kick/bolds", 2, 3) - { - this->SetDesc(_("Configures bolds kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BOLDS, "bolds", kd, kd->bolds); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the bolds kicker on or off. When enabled, this\n" - "option tells the bot to kick users who use bolds.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickCaps : public CommandBSKickBase -{ - public: - CommandBSKickCaps(Module *creator) : CommandBSKickBase(creator, "botserv/kick/caps", 2, 5) - { - this->SetDesc(_("Configures caps kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037min\037 [\037percent\037]]]\002")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (!CheckArguments(source, params, ci)) - return; - - KickerData *kd = ci->Require<KickerData>("kickerdata"); - - if (params[1].equals_ci("ON")) - { - const Anope::string &ttb = params.size() > 2 ? params[2] : "", - &min = params.size() > 3 ? params[3] : "", - &percent = params.size() > 4 ? params[4] : ""; - - if (!ttb.empty()) - { - try - { - kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb); - if (kd->ttb[TTB_CAPS] < 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - kd->ttb[TTB_CAPS] = 0; - source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return; - } - } - else - kd->ttb[TTB_CAPS] = 0; - - kd->capsmin = 10; - try - { - kd->capsmin = convertTo<int16_t>(min); - } - catch (const ConvertException &) { } - if (kd->capsmin < 1) - kd->capsmin = 10; - - kd->capspercent = 25; - try - { - kd->capspercent = convertTo<int16_t>(percent); - } - catch (const ConvertException &) { } - if (kd->capspercent < 1 || kd->capspercent > 100) - kd->capspercent = 25; - - kd->caps = true; - if (kd->ttb[TTB_CAPS]) - source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n" - "%d characters and %d%% of the entire message), and will\n" - "place a ban after %d kicks for the same user."), kd->capsmin, kd->capspercent, kd->ttb[TTB_CAPS]); - else - source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n" - "%d characters and %d%% of the entire message)."), kd->capsmin, kd->capspercent); - } - else - { - kd->caps = false; - source.Reply(_("Bot won't kick for \002caps\002 anymore.")); - } - - kd->Check(ci); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the caps kicker on or off. When enabled, this\n" - "option tells the bot to kick users who are talking in\n" - "CAPS.\n" - "The bot kicks only if there are at least \002min\002 caps\n" - "and they constitute at least \002percent\002%% of the total\n" - "text line (if not given, it defaults to 10 characters\n" - "and 25%%).\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickColors : public CommandBSKickBase -{ - public: - CommandBSKickColors(Module *creator) : CommandBSKickBase(creator, "botserv/kick/colors", 2, 3) - { - this->SetDesc(_("Configures color kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_COLORS, "colors", kd, kd->colors); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the colors kicker on or off. When enabled, this\n" - "option tells the bot to kick users who use colors.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickFlood : public CommandBSKickBase -{ - public: - CommandBSKickFlood(Module *creator) : CommandBSKickBase(creator, "botserv/kick/flood", 2, 5) - { - this->SetDesc(_("Configures flood kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037ln\037 [\037secs\037]]]\002")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (!CheckArguments(source, params, ci)) - return; - - KickerData *kd = ci->Require<KickerData>("kickerdata"); - - if (params[1].equals_ci("ON")) - { - const Anope::string &ttb = params.size() > 2 ? params[2] : "", - &lines = params.size() > 3 ? params[3] : "", - &secs = params.size() > 4 ? params[4] : ""; - - if (!ttb.empty()) - { - int16_t i; - - try - { - i = convertTo<int16_t>(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return; - } - - kd->ttb[TTB_FLOOD] = i; - } - else - kd->ttb[TTB_FLOOD] = 0; - - kd->floodlines = 6; - try - { - kd->floodlines = convertTo<int16_t>(lines); - } - catch (const ConvertException &) { } - if (kd->floodlines < 2) - kd->floodlines = 6; - - kd->floodsecs = 10; - try - { - kd->floodsecs = convertTo<int16_t>(secs); - } - catch (const ConvertException &) { } - if (kd->floodsecs < 1) - kd->floodsecs = 10; - if (kd->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata")) - kd->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata"); - - kd->flood = true; - if (kd->ttb[TTB_FLOOD]) - source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds\n" - "and will place a ban after %d kicks for the same user."), kd->floodlines, kd->floodsecs, kd->ttb[TTB_FLOOD]); - else - source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds)."), kd->floodlines, kd->floodsecs); - } - else if (params[1].equals_ci("OFF")) - { - kd->flood = false; - source.Reply(_("Bot won't kick for \002flood\002 anymore.")); - } - else - this->OnSyntaxError(source, params[1]); - - kd->Check(ci); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the flood kicker on or off. When enabled, this\n" - "option tells the bot to kick users who are flooding\n" - "the channel using at least \002ln\002 lines in \002secs\002 seconds\n" - "(if not given, it defaults to 6 lines in 10 seconds).\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickItalics : public CommandBSKickBase -{ - public: - CommandBSKickItalics(Module *creator) : CommandBSKickBase(creator, "botserv/kick/italics", 2, 3) - { - this->SetDesc(_("Configures italics kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", kd, kd->italics); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the italics kicker on or off. When enabled, this\n" - "option tells the bot to kick users who use italics.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickRepeat : public CommandBSKickBase -{ - public: - CommandBSKickRepeat(Module *creator) : CommandBSKickBase(creator, "botserv/kick/repeat", 2, 4) - { - this->SetDesc(_("Configures repeat kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037 [\037num\037]]\002")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (!CheckArguments(source, params, ci)) - return; - - KickerData *kd = ci->Require<KickerData>("kickerdata"); - - if (params[1].equals_ci("ON")) - { - const Anope::string &ttb = params.size() > 2 ? params[2] : "", - × = params.size() > 3 ? params[3] : ""; - - if (!ttb.empty()) - { - int16_t i; - - try - { - i = convertTo<int16_t>(ttb); - if (i < 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str()); - return; - } - - kd->ttb[TTB_REPEAT] = i; - } - else - kd->ttb[TTB_REPEAT] = 0; - - kd->repeattimes = 3; - try - { - kd->repeattimes = convertTo<int16_t>(times); - } - catch (const ConvertException &) { } - if (kd->repeattimes < 1) - kd->repeattimes = 3; - - kd->repeat = true; - if (kd->ttb[TTB_REPEAT]) - { - if (kd->repeattimes != 1) - source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n" - "same message %d times), and will place a ban after %d\n" - "kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]); - else - source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n" - "same message %d time), and will place a ban after %d\n" - "kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]); - } - else - { - if (kd->repeattimes != 1) - source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n" - "same message %d times)."), kd->repeattimes); - else - source.Reply(_("Bot will now kick for \002repeats\002 (users that repeat the\n" - "same message %d time)."), kd->repeattimes); - } - } - else if (params[1].equals_ci("OFF")) - { - kd->repeat = false; - source.Reply(_("Bot won't kick for \002repeats\002 anymore.")); - } - else - this->OnSyntaxError(source, params[1]); - - kd->Check(ci); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the repeat kicker on or off. When enabled, this\n" - "option tells the bot to kick users who are repeating\n" - "themselves \002num\002 times (if num is not given, it\n" - "defaults to 3).\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickReverses : public CommandBSKickBase -{ - public: - CommandBSKickReverses(Module *creator) : CommandBSKickBase(creator, "botserv/kick/reverses", 2, 3) - { - this->SetDesc(_("Configures reverses kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_REVERSES, "reverses", kd, kd->reverses); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the reverses kicker on or off. When enabled, this\n" - "option tells the bot to kick users who use reverses.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSKickUnderlines : public CommandBSKickBase -{ - public: - CommandBSKickUnderlines(Module *creator) : CommandBSKickBase(creator, "botserv/kick/underlines", 2, 3) - { - this->SetDesc(_("Configures underlines kicker")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci; - if (CheckArguments(source, params, ci)) - { - KickerData *kd = ci->Require<KickerData>("kickerdata"); - Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_UNDERLINES, "underlines", kd, kd->underlines); - kd->Check(ci); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the underlines kicker on or off. When enabled, this\n" - "option tells the bot to kick users who use underlines.\n" - " \n" - "\037ttb\037 is the number of times a user can be kicked\n" - "before it gets banned. Don't give ttb to disable\n" - "the ban system once activated.")); - return true; - } -}; - -class CommandBSSetDontKickOps : public Command -{ - public: - CommandBSSetDontKickOps(Module *creator, const Anope::string &sname = "botserv/set/dontkickops") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("To protect ops against bot kicks")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - AccessGroup access = source.AccessFor(ci); - if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot option setting is temporarily disabled.")); - return; - } - - KickerData *kd = ci->Require<KickerData>("kickerdata"); - if (params[1].equals_ci("ON")) - { - bool override = !access.HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickops"; - - kd->dontkickops = true; - source.Reply(_("Bot \002won't kick ops\002 on channel %s."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - bool override = !access.HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickops"; - - kd->dontkickops = false; - source.Reply(_("Bot \002will kick ops\002 on channel %s."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, source.command); - - kd->Check(ci); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "Enables or disables \002ops protection\002 mode on a channel.\n" - "When it is enabled, ops won't be kicked by the bot\n" - "even if they don't match the NOKICK level.")); - return true; - } -}; - -class CommandBSSetDontKickVoices : public Command -{ - public: - CommandBSSetDontKickVoices(Module *creator, const Anope::string &sname = "botserv/set/dontkickvoices") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("To protect voices against bot kicks")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - AccessGroup access = source.AccessFor(ci); - if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, bot option setting is temporarily disabled.")); - return; - } - - KickerData *kd = ci->Require<KickerData>("kickerdata"); - if (params[1].equals_ci("ON")) - { - bool override = !access.HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickvoices"; - - kd->dontkickvoices = true; - source.Reply(_("Bot \002won't kick voices\002 on channel %s."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - bool override = !access.HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickvoices"; - - kd->dontkickvoices = false; - source.Reply(_("Bot \002will kick voices\002 on channel %s."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, source.command); - - kd->Check(ci); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "Enables or disables \002voices protection\002 mode on a channel.\n" - "When it is enabled, voices won't be kicked by the bot\n" - "even if they don't match the NOKICK level.")); - return true; - } -}; - -struct BanData -{ - struct Data - { - Anope::string mask; - time_t last_use; - int16_t ttb[TTB_SIZE]; - - Data() - { - last_use = 0; - for (int i = 0; i < TTB_SIZE; ++i) - this->ttb[i] = 0; - } - }; - - private: - typedef Anope::map<Data> data_type; - data_type data_map; - - public: - BanData(Extensible *) { } - - Data &get(const Anope::string &key) - { - return this->data_map[key]; - } - - bool empty() const - { - return this->data_map.empty(); - } - - void purge() - { - time_t keepdata = Config->GetModule(me)->Get<time_t>("keepdata"); - for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;) - { - const Anope::string &user = it->first; - Data &bd = it->second; - ++it; - - if (Anope::CurTime - bd.last_use > keepdata) - data_map.erase(user); - } - } -}; - -struct UserData -{ - UserData(Extensible *) - { - last_use = last_start = Anope::CurTime; - lines = times = 0; - lastline.clear(); - } - - /* Data validity */ - time_t last_use; - - /* for flood kicker */ - int16_t lines; - time_t last_start; - - /* for repeat kicker */ - Anope::string lasttarget; - int16_t times; - - Anope::string lastline; -}; - -class BanDataPurger : public Timer -{ - public: - BanDataPurger(Module *o) : Timer(o, 300, Anope::CurTime, true) { } - - void Tick(time_t) anope_override - { - Log(LOG_DEBUG) << "bs_main: Running bandata purger"; - - for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - { - Channel *c = it->second; - - BanData *bd = c->GetExt<BanData>("bandata"); - if (bd != NULL) - { - bd->purge(); - if (bd->empty()) - c->Shrink<BanData>("bandata"); - } - } - } -}; - -class BSKick : public Module -{ - ExtensibleItem<BanData> bandata; - ExtensibleItem<UserData> userdata; - KickerDataImpl::ExtensibleItem kickerdata; - - CommandBSKick commandbskick; - CommandBSKickAMSG commandbskickamsg; - CommandBSKickBadwords commandbskickbadwords; - CommandBSKickBolds commandbskickbolds; - CommandBSKickCaps commandbskickcaps; - CommandBSKickColors commandbskickcolors; - CommandBSKickFlood commandbskickflood; - CommandBSKickItalics commandbskickitalics; - CommandBSKickRepeat commandbskickrepeat; - CommandBSKickReverses commandbskickreverse; - CommandBSKickUnderlines commandbskickunderlines; - - CommandBSSetDontKickOps commandbssetdontkickops; - CommandBSSetDontKickVoices commandbssetdontkickvoices; - - BanDataPurger purger; - - BanData::Data &GetBanData(User *u, Channel *c) - { - BanData *bd = bandata.Require(c); - return bd->get(u->GetMask()); - } - - UserData *GetUserData(User *u, Channel *c) - { - ChanUserContainer *uc = c->FindUser(u); - if (uc == NULL) - return NULL; - - UserData *ud = userdata.Require(uc); - return ud; - } - - void check_ban(ChannelInfo *ci, User *u, KickerData *kd, int ttbtype) - { - /* Don't ban ulines or protected users */ - if (u->IsProtected()) - return; - - BanData::Data &bd = this->GetBanData(u, ci->c); - - ++bd.ttb[ttbtype]; - if (kd->ttb[ttbtype] && bd.ttb[ttbtype] >= kd->ttb[ttbtype]) - { - /* Should not use == here because bd.ttb[ttbtype] could possibly be > kd->ttb[ttbtype] - * if the TTB was changed after it was not set (0) before and the user had already been - * kicked a few times. Bug #1056 - Adam */ - - bd.ttb[ttbtype] = 0; - - Anope::string mask = ci->GetIdealBan(u); - - ci->c->SetMode(NULL, "BAN", mask); - FOREACH_MOD(OnBotBan, (u, ci, mask)); - } - } - - void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) - { - va_list args; - char buf[1024]; - - if (!ci || !ci->bi || !ci->c || !u || u->IsProtected() || !ci->c->FindUser(u)) - return; - - Anope::string fmt = Language::Translate(u, message); - va_start(args, message); - vsnprintf(buf, sizeof(buf), fmt.c_str(), args); - va_end(args); - - ci->c->Kick(ci->bi, u, "%s", buf); - } - - public: - BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - bandata(this, "bandata"), - userdata(this, "userdata"), - kickerdata(this, "kickerdata"), - - commandbskick(this), - commandbskickamsg(this), commandbskickbadwords(this), commandbskickbolds(this), commandbskickcaps(this), - commandbskickcolors(this), commandbskickflood(this), commandbskickitalics(this), commandbskickrepeat(this), - commandbskickreverse(this), commandbskickunderlines(this), - - commandbssetdontkickops(this), commandbssetdontkickvoices(this), - - purger(this) - { - me = this; - - } - - void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override - { - if (!ci) - return; - - Anope::string enabled = Language::Translate(source.nc, _("Enabled")); - Anope::string disabled = Language::Translate(source.nc, _("Disabled")); - KickerData *kd = kickerdata.Get(ci); - - if (kd && kd->badwords) - { - if (kd->ttb[TTB_BADWORDS]) - info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]); - else - info[_("Bad words kicker")] = enabled; - } - else - info[_("Bad words kicker")] = disabled; - - if (kd && kd->bolds) - { - if (kd->ttb[TTB_BOLDS]) - info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]); - else - info[_("Bolds kicker")] = enabled; - } - else - info[_("Bolds kicker")] = disabled; - - if (kd && kd->caps) - { - if (kd->ttb[TTB_CAPS]) - info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%)"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent); - else - info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent); - } - else - info[_("Caps kicker")] = disabled; - - if (kd && kd->colors) - { - if (kd->ttb[TTB_COLORS]) - info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]); - else - info[_("Colors kicker")] = enabled; - } - else - info[_("Colors kicker")] = disabled; - - if (kd && kd->flood) - { - if (kd->ttb[TTB_FLOOD]) - info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds)"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs); - else - info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs); - } - else - info[_("Flood kicker")] = disabled; - - if (kd && kd->repeat) - { - if (kd->ttb[TTB_REPEAT]) - info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes); - else - info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes); - } - else - info[_("Repeat kicker")] = disabled; - - if (kd && kd->reverses) - { - if (kd->ttb[TTB_REVERSES]) - info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]); - else - info[_("Reverses kicker")] = enabled; - } - else - info[_("Reverses kicker")] = disabled; - - if (kd && kd->underlines) - { - if (kd->ttb[TTB_UNDERLINES]) - info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]); - else - info[_("Underlines kicker")] = enabled; - } - else - info[_("Underlines kicker")] = disabled; - - if (kd && kd->italics) - { - if (kd->ttb[TTB_ITALICS]) - info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]); - else - info[_("Italics kicker")] = enabled; - } - else - info[_("Italics kicker")] = disabled; - - if (kd && kd->amsgs) - { - if (kd->ttb[TTB_AMSGS]) - info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]); - else - info[_("AMSG kicker")] = enabled; - } - else - info[_("AMSG kicker")] = disabled; - - if (kd && kd->dontkickops) - info.AddOption(_("Ops protection")); - if (kd && kd->dontkickvoices) - info.AddOption(_("Voices protection")); - } - - void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override - { - /* Now we can make kicker stuff. We try to order the checks - * from the fastest one to the slowest one, since there's - * no need to process other kickers if a user is kicked before - * the last kicker check. - * - * But FIRST we check whether the user is protected in any - * way. - */ - ChannelInfo *ci = c->ci; - if (ci == NULL) - return; - KickerData *kd = kickerdata.Get(ci); - if (kd == NULL) - return; - - if (ci->AccessFor(u).HasPriv("NOKICK")) - return; - else if (kd->dontkickops && (c->HasUserStatus(u, "HALFOP") || c->HasUserStatus(u, "OP") || c->HasUserStatus(u, "PROTECT") || c->HasUserStatus(u, "OWNER"))) - return; - else if (kd->dontkickvoices && c->HasUserStatus(u, "VOICE")) - return; - - Anope::string realbuf = msg; - - /* If it's a /me, cut the CTCP part because the ACTION will cause - * problems with the caps or badwords kicker - */ - if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1') - { - realbuf.erase(0, 8); - realbuf.erase(realbuf.length() - 1); - } - - if (realbuf.empty()) - return; - - /* Bolds kicker */ - if (kd->bolds && realbuf.find(2) != Anope::string::npos) - { - check_ban(ci, u, kd, TTB_BOLDS); - bot_kick(ci, u, _("Don't use bolds on this channel!")); - return; - } - - /* Color kicker */ - if (kd->colors && realbuf.find(3) != Anope::string::npos) - { - check_ban(ci, u, kd, TTB_COLORS); - bot_kick(ci, u, _("Don't use colors on this channel!")); - return; - } - - /* Reverses kicker */ - if (kd->reverses && realbuf.find(22) != Anope::string::npos) - { - check_ban(ci, u, kd, TTB_REVERSES); - bot_kick(ci, u, _("Don't use reverses on this channel!")); - return; - } - - /* Italics kicker */ - if (kd->italics && realbuf.find(29) != Anope::string::npos) - { - check_ban(ci, u, kd, TTB_ITALICS); - bot_kick(ci, u, _("Don't use italics on this channel!")); - return; - } - - /* Underlines kicker */ - if (kd->underlines && realbuf.find(31) != Anope::string::npos) - { - check_ban(ci, u, kd, TTB_UNDERLINES); - bot_kick(ci, u, _("Don't use underlines on this channel!")); - return; - } - - /* Caps kicker */ - if (kd->caps && realbuf.length() >= static_cast<unsigned>(kd->capsmin)) - { - int i = 0, l = 0; - - for (unsigned j = 0, end = realbuf.length(); j < end; ++j) - { - if (isupper(realbuf[j])) - ++i; - else if (islower(realbuf[j])) - ++l; - } - - /* i counts uppercase chars, l counts lowercase chars. Only - * alphabetic chars (so islower || isupper) qualify for the - * percentage of caps to kick for; the rest is ignored. -GD - */ - - if ((i || l) && i >= kd->capsmin && i * 100 / (i + l) >= kd->capspercent) - { - check_ban(ci, u, kd, TTB_CAPS); - bot_kick(ci, u, _("Turn caps lock OFF!")); - return; - } - } - - /* Bad words kicker */ - if (kd->badwords) - { - bool mustkick = false; - BadWords *badwords = ci->GetExt<BadWords>("badwords"); - - /* Normalize the buffer */ - Anope::string nbuf = Anope::NormalizeBuffer(realbuf); - bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive"); - - /* Normalize can return an empty string if this only conains control codes etc */ - if (badwords && !nbuf.empty()) - for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i) - { - const BadWord *bw = badwords->GetBadWord(i); - - if (bw->word.empty()) - continue; // Shouldn't happen - - if (bw->word.length() > nbuf.length()) - continue; // This can't ever match - - if (bw->type == BW_ANY && ((casesensitive && nbuf.find(bw->word) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(bw->word) != Anope::string::npos))) - mustkick = true; - else if (bw->type == BW_SINGLE) - { - size_t len = bw->word.length(); - - if ((casesensitive && bw->word.equals_cs(nbuf)) || (!casesensitive && bw->word.equals_ci(nbuf))) - mustkick = true; - else if (nbuf.find(' ') == len && ((casesensitive && bw->word.equals_cs(nbuf.substr(0, len))) || (!casesensitive && bw->word.equals_ci(nbuf.substr(0, len))))) - mustkick = true; - else - { - if (len < nbuf.length() && nbuf.rfind(' ') == nbuf.length() - len - 1 && ((casesensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!casesensitive && nbuf.find_ci(bw->word) == nbuf.length() - len))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word + " "; - - if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - } - else if (bw->type == BW_START) - { - size_t len = bw->word.length(); - - if ((casesensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!casesensitive && nbuf.substr(0, len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word; - - if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - else if (bw->type == BW_END) - { - size_t len = bw->word.length(); - - if ((casesensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!casesensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = bw->word + " "; - - if ((casesensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - - if (mustkick) - { - check_ban(ci, u, kd, TTB_BADWORDS); - if (Config->GetModule(me)->Get<bool>("gentlebadwordreason")) - bot_kick(ci, u, _("Watch your language!")); - else - bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str()); - - return; - } - } /* for */ - } /* if badwords */ - - UserData *ud = GetUserData(u, c); - - if (ud) - { - /* Flood kicker */ - if (kd->flood) - { - if (Anope::CurTime - ud->last_start > kd->floodsecs) - { - ud->last_start = Anope::CurTime; - ud->lines = 0; - } - - ++ud->lines; - if (ud->lines >= kd->floodlines) - { - check_ban(ci, u, kd, TTB_FLOOD); - bot_kick(ci, u, _("Stop flooding!")); - return; - } - } - - /* Repeat kicker */ - if (kd->repeat) - { - if (!ud->lastline.equals_ci(realbuf)) - ud->times = 0; - else - ++ud->times; - - if (ud->times >= kd->repeattimes) - { - check_ban(ci, u, kd, TTB_REPEAT); - bot_kick(ci, u, _("Stop repeating yourself!")); - return; - } - } - - if (ud->lastline.equals_ci(realbuf) && !ud->lasttarget.empty() && !ud->lasttarget.equals_ci(ci->name)) - { - for (User::ChanUserList::iterator it = u->chans.begin(); it != u->chans.end();) - { - Channel *chan = it->second->chan; - ++it; - - if (chan->ci && kd->amsgs && !chan->ci->AccessFor(u).HasPriv("NOKICK")) - { - check_ban(chan->ci, u, kd, TTB_AMSGS); - bot_kick(chan->ci, u, _("Don't use AMSGs!")); - } - } - } - - ud->lasttarget = ci->name; - ud->lastline = realbuf; - } - } -}; - -MODULE_INIT(BSKick) diff --git a/modules/commands/bs_set.cpp b/modules/commands/bs_set.cpp deleted file mode 100644 index 9e0bac56a..000000000 --- a/modules/commands/bs_set.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* BotServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSSet : public Command -{ - public: - CommandBSSet(Module *creator) : Command(creator, "botserv/set", 3, 3) - { - this->SetDesc(_("Configures bot options")); - this->SetSyntax(_("\037option\037 \037(channel | bot)\037 \037settings\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Configures bot options.\n" - " \n" - "Available options:")); - bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), - hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); - Anope::string this_name = source.command; - for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - if (c_name.find_ci(this_name + " ") == 0) - { - ServiceReference<Command> command("Command", info.name); - if (command) - { - // XXX dup - if (hide_registered_commands && !command->AllowUnregistered() && !source.GetAccount()) - continue; - - if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) - continue; - - source.command = it->first; - command->OnServHelp(source); - } - } - } - source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n" - "particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); - - return true; - } -}; - -class CommandBSSetBanExpire : public Command -{ - public: - class UnbanTimer : public Timer - { - Anope::string chname; - Anope::string mask; - - public: - UnbanTimer(Module *creator, const Anope::string &ch, const Anope::string &bmask, time_t t) : Timer(creator, t), chname(ch), mask(bmask) { } - - void Tick(time_t) anope_override - { - Channel *c = Channel::Find(chname); - if (c) - c->RemoveMode(NULL, "BAN", mask); - } - }; - - CommandBSSetBanExpire(Module *creator, const Anope::string &sname = "botserv/set/banexpire") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("Configures the time bot bans expire in")); - this->SetSyntax(_("\037channel\037 \037time\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &arg = params[1]; - - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - AccessGroup access = source.AccessFor(ci); - if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, changing bot options is temporarily disabled.")); - return; - } - - time_t t = Anope::DoTime(arg); - if (t == -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - - /* cap at 1 day */ - if (t > 86400) - { - source.Reply(_("Ban expiry may not be longer than 1 day.")); - return; - } - - ci->banexpire = t; - - bool override = !access.HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to change banexpire to " << ci->banexpire; - - if (!ci->banexpire) - source.Reply(_("Bot bans will no longer automatically expire.")); - else - source.Reply(_("Bot bans will automatically expire after %s."), Anope::Duration(ci->banexpire, source.GetAccount()).c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "Sets the time bot bans expire in. If enabled, any bans placed by\n" - "bots, such as flood kicker, badwords kicker, etc. will automatically\n" - "be removed after the given time. Set to 0 to disable bans from\n" - "automatically expiring.")); - return true; - } -}; - -class CommandBSSetPrivate : public Command -{ - public: - CommandBSSetPrivate(Module *creator, const Anope::string &sname = "botserv/set/private") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("Prevent a bot from being assigned by non IRC operators")); - this->SetSyntax(_("\037botname\037 {\037ON|OFF\037}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - BotInfo *bi = BotInfo::Find(params[0], true); - const Anope::string &value = params[1]; - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (bi == NULL) - { - source.Reply(BOT_DOES_NOT_EXIST, params[0].c_str()); - return; - } - - if (value.equals_ci("ON")) - { - bi->oper_only = true; - source.Reply(_("Private mode of bot %s is now \002on\002."), bi->nick.c_str()); - } - else if (value.equals_ci("OFF")) - { - bi->oper_only = false; - source.Reply(_("Private mode of bot %s is now \002off\002."), bi->nick.c_str()); - } - else - this->OnSyntaxError(source, source.command); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "This option prevents a bot from being assigned to a\n" - "channel by users that aren't IRC Operators.")); - return true; - } -}; - -class BSSet : public Module -{ - CommandBSSet commandbsset; - CommandBSSetBanExpire commandbssetbanexpire; - CommandBSSetPrivate commandbssetprivate; - - public: - BSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandbsset(this), commandbssetbanexpire(this), - commandbssetprivate(this) - { - } - - void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) anope_override - { - if (!ci->banexpire) - return; - - new CommandBSSetBanExpire::UnbanTimer(this, ci->name, mask, ci->banexpire); - } -}; - -MODULE_INIT(BSSet) diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp deleted file mode 100644 index 6e9b79c6a..000000000 --- a/modules/commands/cs_access.cpp +++ /dev/null @@ -1,904 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static std::map<Anope::string, int16_t, ci::less> defaultLevels; - -static inline void reset_levels(ChannelInfo *ci) -{ - ci->ClearLevels(); - for (std::map<Anope::string, int16_t, ci::less>::iterator it = defaultLevels.begin(), it_end = defaultLevels.end(); it != it_end; ++it) - ci->SetLevel(it->first, it->second); -} - -class AccessChanAccess : public ChanAccess -{ - public: - int level; - - AccessChanAccess(AccessProvider *p) : ChanAccess(p), level(0) - { - } - - bool HasPriv(const Anope::string &name) const anope_override - { - return this->ci->GetLevel(name) != ACCESS_INVALID && this->level >= this->ci->GetLevel(name); - } - - Anope::string AccessSerialize() const - { - return stringify(this->level); - } - - void AccessUnserialize(const Anope::string &data) anope_override - { - try - { - this->level = convertTo<int>(data); - } - catch (const ConvertException &) - { - } - } - - bool operator>(const ChanAccess &other) const anope_override - { - if (this->provider != other.provider) - return ChanAccess::operator>(other); - else - return this->level > anope_dynamic_static_cast<const AccessChanAccess *>(&other)->level; - } - - bool operator<(const ChanAccess &other) const anope_override - { - if (this->provider != other.provider) - return ChanAccess::operator<(other); - else - return this->level < anope_dynamic_static_cast<const AccessChanAccess *>(&other)->level; - } -}; - -class AccessAccessProvider : public AccessProvider -{ - public: - static AccessAccessProvider *me; - - AccessAccessProvider(Module *o) : AccessProvider(o, "access/access") - { - me = this; - } - - ChanAccess *Create() anope_override - { - return new AccessChanAccess(this); - } -}; -AccessAccessProvider* AccessAccessProvider::me; - -class CommandCSAccess : public Command -{ - void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - Anope::string mask = params[2]; - Privilege *p = NULL; - int level = ACCESS_INVALID; - - try - { - level = convertTo<int>(params[3]); - } - catch (const ConvertException &) - { - p = PrivilegeManager::FindPrivilege(params[3]); - if (p != NULL && defaultLevels[p->name]) - level = defaultLevels[p->name]; - } - - if (!level) - { - source.Reply(_("Access level must be non-zero.")); - return; - } - else if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) - { - source.Reply(CHAN_ACCESS_LEVEL_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); - return; - } - - AccessGroup u_access = source.AccessFor(ci); - const ChanAccess *highest = u_access.Highest(); - - AccessChanAccess tmp_access(AccessAccessProvider::me); - tmp_access.ci = ci; - tmp_access.level = level; - - bool override = false; - const NickAlias *na = NULL; - - if ((!highest || *highest <= tmp_access) && !u_access.founder) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - - if (IRCD->IsChannelValid(mask)) - { - if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access")) - { - source.Reply(_("Channels may not be on access lists.")); - return; - } - - ChannelInfo *targ_ci = ChannelInfo::Find(mask); - if (targ_ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, mask.c_str()); - return; - } - else if (ci == targ_ci) - { - source.Reply(_("You can't add a channel to its own access list.")); - return; - } - - mask = targ_ci->name; - } - else - { - na = NickAlias::Find(mask); - - if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access")) - { - source.Reply(_("Masks and unregistered users may not be on access lists.")); - return; - } - else if (mask.find_first_of("!*@") == Anope::string::npos && !na) - { - User *targ = User::Find(mask, true); - if (targ != NULL) - mask = "*!*@" + targ->GetDisplayedHost(); - else - { - source.Reply(NICK_X_NOT_REGISTERED, mask.c_str()); - return; - } - } - - if (na) - mask = na->nick; - } - - for (unsigned i = ci->GetAccessCount(); i > 0; --i) - { - const ChanAccess *access = ci->GetAccess(i - 1); - if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask())) - { - /* Don't allow lowering from a level >= u_level */ - if ((!highest || *access >= *highest) && !u_access.founder && !source.HasPriv("chanserv/access/modify")) - { - source.Reply(ACCESS_DENIED); - return; - } - delete ci->EraseAccess(i - 1); - break; - } - } - - unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024"); - if (access_max && ci->GetDeepAccessCount() >= access_max) - { - source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max); - return; - } - - ServiceReference<AccessProvider> provider("AccessProvider", "access/access"); - if (!provider) - return; - AccessChanAccess *access = anope_dynamic_static_cast<AccessChanAccess *>(provider->Create()); - access->SetMask(mask, ci); - access->creator = source.GetNick(); - access->level = level; - access->last_seen = 0; - access->created = Anope::CurTime; - ci->AddAccess(access); - - FOREACH_MOD(OnAccessAdd, (ci, source, access)); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to add " << mask << " with level " << level; - if (p != NULL) - source.Reply(_("\002%s\002 added to %s access list at privilege %s (level %d)"), access->Mask().c_str(), ci->name.c_str(), p->name.c_str(), level); - else - source.Reply(_("\002%s\002 added to %s access list at level \002%d\002."), access->Mask().c_str(), ci->name.c_str(), level); - } - - void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - Anope::string mask = params[2]; - - if (!isdigit(mask[0]) && mask.find_first_of("#!*@") == Anope::string::npos && !NickAlias::Find(mask)) - { - User *targ = User::Find(mask, true); - if (targ != NULL) - mask = "*!*@" + targ->GetDisplayedHost(); - else - { - source.Reply(NICK_X_NOT_REGISTERED, mask.c_str()); - return; - } - } - - if (!ci->GetAccessCount()) - source.Reply(_("%s access list is empty."), ci->name.c_str()); - else if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class AccessDelCallback : public NumberList - { - CommandSource &source; - ChannelInfo *ci; - Command *c; - unsigned deleted; - Anope::string Nicks; - bool denied; - bool override; - public: - AccessDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), denied(false), override(false) - { - if (!source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && source.HasPriv("chanserv/access/modify")) - this->override = true; - } - - ~AccessDelCallback() - { - if (denied && !deleted) - source.Reply(ACCESS_DENIED); - else if (!deleted) - source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); - else - { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << Nicks; - - if (deleted == 1) - source.Reply(_("Deleted 1 entry from %s access list."), ci->name.c_str()); - else - source.Reply(_("Deleted %d entries from %s access list."), deleted, ci->name.c_str()); - } - } - - void HandleNumber(unsigned Number) anope_override - { - if (!Number || Number > ci->GetAccessCount()) - return; - - ChanAccess *access = ci->GetAccess(Number - 1); - - AccessGroup ag = source.AccessFor(ci); - const ChanAccess *u_highest = ag.Highest(); - - if ((!u_highest || *u_highest <= *access) && !ag.founder && !this->override && access->GetAccount() != source.nc) - { - denied = true; - return; - } - - ++deleted; - if (!Nicks.empty()) - Nicks += ", " + access->Mask(); - else - Nicks = access->Mask(); - - ci->EraseAccess(Number - 1); - - FOREACH_MOD(OnAccessDel, (ci, source, access)); - delete access; - } - } - delcallback(source, ci, this, mask); - delcallback.Process(); - } - else - { - AccessGroup u_access = source.AccessFor(ci); - const ChanAccess *highest = u_access.Highest(); - - for (unsigned i = ci->GetAccessCount(); i > 0; --i) - { - ChanAccess *access = ci->GetAccess(i - 1); - if (mask.equals_ci(access->Mask())) - { - if (access->GetAccount() != source.nc && !u_access.founder && (!highest || *highest <= *access) && !source.HasPriv("chanserv/access/modify")) - source.Reply(ACCESS_DENIED); - else - { - source.Reply(_("\002%s\002 deleted from %s access list."), access->Mask().c_str(), ci->name.c_str()); - bool override = !u_access.founder && !u_access.HasPriv("ACCESS_CHANGE") && access->GetAccount() != source.nc; - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << access->Mask(); - - ci->EraseAccess(i - 1); - FOREACH_MOD(OnAccessDel, (ci, source, access)); - delete access; - } - return; - } - } - - source.Reply(_("\002%s\002 not found on %s access list."), mask.c_str(), ci->name.c_str()); - } - - return; - } - - void ProcessList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, ListFormatter &list) - { - const Anope::string &nick = params.size() > 2 ? params[2] : ""; - - if (!ci->GetAccessCount()) - source.Reply(_("%s access list is empty."), ci->name.c_str()); - else if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class AccessListCallback : public NumberList - { - ListFormatter &list; - ChannelInfo *ci; - - public: - AccessListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > ci->GetAccessCount()) - return; - - const ChanAccess *access = ci->GetAccess(number - 1); - - Anope::string timebuf; - if (ci->c) - for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit) - { - ChannelInfo *p; - if (access->Matches(cit->second->user, cit->second->user->Account(), p)) - timebuf = "Now"; - } - if (timebuf.empty()) - { - if (access->last_seen == 0) - timebuf = "Never"; - else - timebuf = Anope::strftime(access->last_seen, NULL, true); - } - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); - entry["Level"] = access->AccessSerialize(); - entry["Mask"] = access->Mask(); - entry["By"] = access->creator; - entry["Last seen"] = timebuf; - this->list.AddEntry(entry); - } - } - nl_list(list, ci, nick); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i) - { - const ChanAccess *access = ci->GetAccess(i); - - if (!nick.empty() && !Anope::Match(access->Mask(), nick)) - continue; - - Anope::string timebuf; - if (ci->c) - for (Channel::ChanUserList::const_iterator cit = ci->c->users.begin(), cit_end = ci->c->users.end(); cit != cit_end; ++cit) - { - ChannelInfo *p; - if (access->Matches(cit->second->user, cit->second->user->Account(), p)) - timebuf = "Now"; - } - if (timebuf.empty()) - { - if (access->last_seen == 0) - timebuf = "Never"; - else - timebuf = Anope::strftime(access->last_seen, NULL, true); - } - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Level"] = access->AccessSerialize(); - entry["Mask"] = access->Mask(); - entry["By"] = access->creator; - entry["Last seen"] = timebuf; - list.AddEntry(entry); - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); - else - { - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("Access list for %s:"), ci->name.c_str()); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of access list")); - } - - return; - } - - void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (!ci->GetAccessCount()) - { - source.Reply(_("%s access list is empty."), ci->name.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")); - this->ProcessList(source, ci, params, list); - } - - void DoView(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (!ci->GetAccessCount()) - { - source.Reply(_("%s access list is empty."), ci->name.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Level")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Last seen")); - this->ProcessList(source, ci, params, list); - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - if (!source.IsFounder(ci) && !source.HasPriv("chanserv/access/modify")) - source.Reply(ACCESS_DENIED); - else - { - FOREACH_MOD(OnAccessClear, (ci, source)); - - ci->ClearAccess(); - - source.Reply(_("Channel %s access list has been cleared."), ci->name.c_str()); - - bool override = !source.IsFounder(ci); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list"; - } - - return; - } - - public: - CommandCSAccess(Module *creator) : Command(creator, "chanserv/access", 2, 4) - { - this->SetDesc(_("Modify the list of privileged users")); - this->SetSyntax(_("\037channel\037 ADD \037mask\037 \037level\037")); - this->SetSyntax(_("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); - this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 VIEW [\037mask\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[1]; - const Anope::string &nick = params.size() > 2 ? params[2] : ""; - const Anope::string &s = params.size() > 3 ? params[3] : ""; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - bool is_list = cmd.equals_ci("LIST") || cmd.equals_ci("VIEW"); - bool is_clear = cmd.equals_ci("CLEAR"); - bool is_del = cmd.equals_ci("DEL"); - - bool has_access = false; - if (source.HasPriv("chanserv/access/modify")) - has_access = true; - else if (is_list && source.HasPriv("chanserv/access/list")) - has_access = true; - else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST")) - has_access = true; - else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE")) - has_access = true; - else if (is_del) - { - const NickAlias *na = NickAlias::Find(nick); - if (na && na->nc == source.GetAccount()) - has_access = true; - } - - /* If LIST, we don't *require* any parameters, but we can take any. - * If DEL, we require a nick and no level. - * Else (ADD), we require a level (which implies a nick). */ - if (is_list || is_clear ? 0 : (cmd.equals_ci("DEL") ? (nick.empty() || !s.empty()) : s.empty())) - this->OnSyntaxError(source, cmd); - else if (!has_access) - source.Reply(ACCESS_DENIED); - else if (Anope::ReadOnly && !is_list) - source.Reply(_("Sorry, channel access list modification is temporarily disabled.")); - else if (cmd.equals_ci("ADD")) - this->DoAdd(source, ci, params); - else if (cmd.equals_ci("DEL")) - this->DoDel(source, ci, params); - else if (cmd.equals_ci("LIST")) - this->DoList(source, ci, params); - else if (cmd.equals_ci("VIEW")) - this->DoView(source, ci, params); - else if (cmd.equals_ci("CLEAR")) - this->DoClear(source, ci); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002access list\002 for a channel. The access\n" - "list specifies which users are allowed chanop status or\n" - "access to %s commands on the channel. Different\n" - "user levels allow for access to different subsets of\n" - "privileges. Any registered user not on the access list has\n" - "a user level of 0, and any unregistered user has a user level\n" - "of -1."), source.service->nick.c_str()); - source.Reply(" "); - source.Reply(_("The \002ACCESS ADD\002 command adds the given mask to the\n" - "access list with the given user level; if the mask is\n" - "already present on the list, its access level is changed to\n" - "the level specified in the command. The \037level\037 specified\n" - "may be a numerical level or the name of a privilege (eg AUTOOP).\n" - "When a user joins the channel the access they receive is from the\n" - "highest level entry in the access list.")); - if (!Config->GetModule("chanserv")->Get<bool>("disallow_channel_access")) - source.Reply(_("The given mask may also be a channel, which will use the\n" - "access list from the other channel up to the given \037level\037.")); - source.Reply(" "); - source.Reply(_("The \002ACCESS DEL\002 command removes the given nick from the\n" - "access list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - "You may remove yourself from an access list, even if you\n" - "do not have access to modify that list otherwise.")); - source.Reply(" "); - source.Reply(_("The \002ACCESS LIST\002 command displays the access list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002ACCESS #channel LIST 2-5,7-9\002\n" - " Lists access entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002ACCESS VIEW\002 command displays the access list similar\n" - "to \002ACCESS LIST\002 but shows the creator and last used time.\n" - " \n" - "The \002ACCESS CLEAR\002 command clears all entries of the\n" - "access list.")); - source.Reply(" "); - - BotInfo *bi; - Anope::string cmd; - if (Command::FindCommandFromService("chanserv/levels", bi, cmd)) - source.Reply(_("\002User access levels\002 can be seen by using the\n" - "\002%s\002 command; type \002%s%s HELP LEVELS\002 for\n" - "information."), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str()); - return true; - } -}; - -class CommandCSLevels : public Command -{ - void DoSet(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string &what = params[2]; - const Anope::string &lev = params[3]; - - int level; - - if (lev.equals_ci("FOUNDER")) - level = ACCESS_FOUNDER; - else - { - try - { - level = convertTo<int>(lev); - } - catch (const ConvertException &) - { - this->OnSyntaxError(source, "SET"); - return; - } - } - - if (level <= ACCESS_INVALID || level > ACCESS_FOUNDER) - source.Reply(_("Level must be between %d and %d inclusive."), ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); - else - { - Privilege *p = PrivilegeManager::FindPrivilege(what); - if (p == NULL) - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str()); - else - { - bool override = !source.AccessFor(ci).HasPriv("FOUNDER"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to set " << p->name << " to level " << level; - - ci->SetLevel(p->name, level); - FOREACH_MOD(OnLevelChange, (source, ci, p->name, level)); - - if (level == ACCESS_FOUNDER) - source.Reply(_("Level for %s on channel %s changed to founder only."), p->name.c_str(), ci->name.c_str()); - else - source.Reply(_("Level for \002%s\002 on channel %s changed to \002%d\002."), p->name.c_str(), ci->name.c_str(), level); - } - } - } - - void DoDisable(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string &what = params[2]; - - /* 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.")); - return; - } - - Privilege *p = PrivilegeManager::FindPrivilege(what); - if (p != NULL) - { - bool override = !source.AccessFor(ci).HasPriv("FOUNDER"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable " << p->name; - - ci->SetLevel(p->name, ACCESS_INVALID); - FOREACH_MOD(OnLevelChange, (source, ci, p->name, ACCESS_INVALID)); - - source.Reply(_("\002%s\002 disabled on channel %s."), p->name.c_str(), ci->name.c_str()); - return; - } - - source.Reply(_("Setting \002%s\002 not known. Type \002%s%s HELP LEVELS\002 for a list of valid settings."), what.c_str(), Config->StrictPrivmsg.c_str(), source.service->nick.c_str()); - } - - void DoList(CommandSource &source, ChannelInfo *ci) - { - source.Reply(_("Access level settings for channel %s:"), ci->name.c_str()); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Name")).AddColumn(_("Level")); - - const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); - - for (unsigned i = 0; i < privs.size(); ++i) - { - const Privilege &p = privs[i]; - int16_t j = ci->GetLevel(p.name); - - ListFormatter::ListEntry entry; - entry["Name"] = p.name; - - if (j == ACCESS_INVALID) - entry["Level"] = Language::Translate(source.GetAccount(), _("(disabled)")); - else if (j == ACCESS_FOUNDER) - entry["Level"] = Language::Translate(source.GetAccount(), _("(founder only)")); - else - entry["Level"] = stringify(j); - - list.AddEntry(entry); - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - - void DoReset(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("FOUNDER"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to reset all levels"; - - reset_levels(ci); - FOREACH_MOD(OnLevelChange, (source, ci, "ALL", 0)); - - source.Reply(_("Access levels for \002%s\002 reset to defaults."), ci->name.c_str()); - return; - } - - public: - CommandCSLevels(Module *creator) : Command(creator, "chanserv/levels", 2, 4) - { - this->SetDesc(_("Redefine the meanings of access levels")); - this->SetSyntax(_("\037channel\037 SET \037type\037 \037level\037")); - this->SetSyntax(_("\037channel\037 {DIS | DISABLE} \037type\037")); - this->SetSyntax(_("\037channel\037 LIST")); - this->SetSyntax(_("\037channel\037 RESET")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[1]; - const Anope::string &what = params.size() > 2 ? params[2] : ""; - const Anope::string &s = params.size() > 3 ? params[3] : ""; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - 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 (!has_access) - source.Reply(ACCESS_DENIED); - else if (Anope::ReadOnly && !cmd.equals_ci("LIST")) - source.Reply(READ_ONLY_MODE); - else if (cmd.equals_ci("SET")) - this->DoSet(source, ci, params); - else if (cmd.equals_ci("DIS") || cmd.equals_ci("DISABLE")) - this->DoDisable(source, ci, params); - else if (cmd.equals_ci("LIST")) - this->DoList(source, ci); - else if (cmd.equals_ci("RESET")) - this->DoReset(source, ci); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (subcommand.equals_ci("DESC")) - { - source.Reply(_("The following feature/function names are available:")); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Name")).AddColumn(_("Description")); - - const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges(); - for (unsigned i = 0; i < privs.size(); ++i) - { - const Privilege &p = privs[i]; - ListFormatter::ListEntry entry; - entry["Name"] = p.name; - entry["Description"] = Language::Translate(source.nc, p.desc.c_str()); - list.AddEntry(entry); - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - else - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("The \002LEVELS\002 command allows fine control over the meaning of\n" - "the numeric access levels used for channels. With this\n" - "command, you can define the access level required for most\n" - "of %s's functions. (The \002SET FOUNDER\002 and this command\n" - "are always restricted to the channel founder.)\n" - " \n" - "\002LEVELS SET\002 allows the access level for a function or group of\n" - "functions to be changed. \002LEVELS DISABLE\002 (or \002DIS\002 for short)\n" - "disables an automatic feature or disallows access to a\n" - "function by anyone, INCLUDING the founder (although, the founder\n" - "can always reenable it). Use \002LEVELS SET founder\002 to make a level\n" - "founder only.\n" - " \n" - "\002LEVELS LIST\002 shows the current levels for each function or\n" - "group of functions. \002LEVELS RESET\002 resets the levels to the\n" - "default levels of a newly-created channel.\n" - " \n" - "For a list of the features and functions whose levels can be\n" - "set, see \002HELP LEVELS DESC\002."), source.service->nick.c_str()); - } - return true; - } -}; - -class CSAccess : public Module -{ - AccessAccessProvider accessprovider; - CommandCSAccess commandcsaccess; - CommandCSLevels commandcslevels; - - public: - CSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - accessprovider(this), commandcsaccess(this), commandcslevels(this) - { - this->SetPermanent(true); - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - defaultLevels.clear(); - - for (int i = 0; i < conf->CountBlock("privilege"); ++i) - { - Configuration::Block *priv = conf->GetBlock("privilege", i); - - const Anope::string &pname = priv->Get<const Anope::string>("name"); - - Privilege *p = PrivilegeManager::FindPrivilege(pname); - if (p == NULL) - continue; - - const Anope::string &value = priv->Get<const Anope::string>("level"); - if (value.empty()) - continue; - else if (value.equals_ci("founder")) - defaultLevels[p->name] = ACCESS_FOUNDER; - else if (value.equals_ci("disabled")) - defaultLevels[p->name] = ACCESS_INVALID; - else - defaultLevels[p->name] = priv->Get<int16_t>("level"); - } - } - - void OnCreateChan(ChannelInfo *ci) anope_override - { - reset_levels(ci); - } - - EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) anope_override - { - if (group->ci == NULL) - return EVENT_CONTINUE; - /* Special case. Allows a level of -1 to match anyone, and a level of 0 to match anyone identified. */ - int16_t level = group->ci->GetLevel(priv); - if (level == -1) - return EVENT_ALLOW; - else if (level == 0 && group->nc) - return EVENT_ALLOW; - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(CSAccess) diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp deleted file mode 100644 index cb0a49ccb..000000000 --- a/modules/commands/cs_akick.cpp +++ /dev/null @@ -1,572 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSAKick : public Command -{ - void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - Anope::string mask = params[2]; - Anope::string reason = params.size() > 3 ? params[3] : ""; - const NickAlias *na = NickAlias::Find(mask); - NickCore *nc = NULL; - const AutoKick *akick; - unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200"); - - if (reason.length() > reasonmax) - reason = reason.substr(0, reasonmax); - - if (IRCD->IsExtbanValid(mask)) - ; /* If this is an extban don't try to complete the mask */ - else if (IRCD->IsChannelValid(mask)) - { - /* Also don't try to complete the mask if this is a channel */ - - if (mask.equals_ci(ci->name) && ci->HasExt("PEACE")) - { - source.Reply(ACCESS_DENIED); - return; - } - } - else if (!na) - { - /* If the mask contains a realname the reason must be prepended with a : */ - if (mask.find('#') != Anope::string::npos) - { - size_t r = reason.find(':'); - if (r != Anope::string::npos) - { - mask += " " + reason.substr(0, r); - mask.trim(); - reason = reason.substr(r + 1); - reason.trim(); - } - else - { - mask = mask + " " + reason; - reason.clear(); - } - } - - Entry e("", mask); - - mask = (e.nick.empty() ? "*" : e.nick) + "!" - + (e.user.empty() ? "*" : e.user) + "@" - + (e.host.empty() ? "*" : e.host); - if (!e.real.empty()) - mask += "#" + e.real; - } - else - nc = na->nc; - - /* Check excepts BEFORE we get this far */ - if (ci->c) - { - std::vector<Anope::string> modes = ci->c->GetModeList("EXCEPT"); - for (unsigned int i = 0; i < modes.size(); ++i) - { - if (Anope::Match(modes[i], mask)) - { - source.Reply(CHAN_EXCEPTED, mask.c_str(), ci->name.c_str()); - return; - } - } - } - - bool override = !source.AccessFor(ci).HasPriv("AKICK"); - /* Opers overriding get to bypass PEACE */ - if (override) - ; - /* These peace checks are only for masks */ - else if (IRCD->IsChannelValid(mask)) - ; - /* Check whether target nick has equal/higher access - * or whether the mask matches a user with higher/equal access - Viper */ - else if (ci->HasExt("PEACE") && nc) - { - AccessGroup nc_access = ci->AccessFor(nc), u_access = source.AccessFor(ci); - if (nc == ci->GetFounder() || nc_access >= u_access) - { - source.Reply(ACCESS_DENIED); - return; - } - } - else if (ci->HasExt("PEACE")) - { - /* Match against all currently online users with equal or - * higher access. - Viper */ - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u2 = it->second; - - AccessGroup nc_access = ci->AccessFor(nc), u_access = source.AccessFor(ci); - Entry entry_mask("", mask); - - if ((ci->AccessFor(u2).HasPriv("FOUNDER") || nc_access >= u_access) && entry_mask.Matches(u2)) - { - source.Reply(ACCESS_DENIED); - return; - } - } - - /* Match against the lastusermask of all nickalias's with equal - * or higher access. - Viper */ - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it) - { - na = it->second; - - AccessGroup nc_access = ci->AccessFor(na->nc), u_access = source.AccessFor(ci); - if (na->nc && (na->nc == ci->GetFounder() || nc_access >= u_access)) - { - Anope::string buf = na->nick + "!" + na->last_usermask; - if (Anope::Match(buf, mask)) - { - source.Reply(ACCESS_DENIED); - return; - } - } - } - } - - for (unsigned j = 0, end = ci->GetAkickCount(); j < end; ++j) - { - akick = ci->GetAkick(j); - if (akick->nc ? akick->nc == nc : mask.equals_ci(akick->mask)) - { - source.Reply(_("\002%s\002 already exists on %s autokick list."), akick->nc ? akick->nc->display.c_str() : akick->mask.c_str(), ci->name.c_str()); - return; - } - } - - if (ci->GetAkickCount() >= Config->GetModule(this->owner)->Get<unsigned>("autokickmax")) - { - source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner)->Get<unsigned>("autokickmax")); - return; - } - - if (nc) - akick = ci->AddAkick(source.GetNick(), nc, reason); - else - akick = ci->AddAkick(source.GetNick(), mask, reason); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to add " << mask << (reason == "" ? "" : ": ") << reason; - - FOREACH_MOD(OnAkickAdd, (source, ci, akick)); - - source.Reply(_("\002%s\002 added to %s autokick list."), mask.c_str(), ci->name.c_str()); - - this->DoEnforce(source, ci); - } - - void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string &mask = params[2]; - unsigned i, end; - - if (!ci->GetAkickCount()) - { - source.Reply(_("%s autokick list is empty."), ci->name.c_str()); - return; - } - - /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class AkickDelCallback : public NumberList - { - CommandSource &source; - ChannelInfo *ci; - Command *c; - unsigned deleted; - AccessGroup ag; - public: - AkickDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), c(_c), deleted(0), ag(source.AccessFor(ci)) - { - } - - ~AkickDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str()); - else if (deleted == 1) - source.Reply(_("Deleted 1 entry from %s autokick list."), ci->name.c_str()); - else - source.Reply(_("Deleted %d entries from %s autokick list."), deleted, ci->name.c_str()); - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > ci->GetAkickCount()) - return; - - const AutoKick *akick = ci->GetAkick(number - 1); - - FOREACH_MOD(OnAkickDel, (source, ci, akick)); - - bool override = !ag.HasPriv("AKICK"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << (akick->nc ? akick->nc->display : akick->mask); - - ++deleted; - ci->EraseAkick(number - 1); - } - } - delcallback(source, ci, this, mask); - delcallback.Process(); - } - else - { - const NickAlias *na = NickAlias::Find(mask); - const NickCore *nc = na ? *na->nc : NULL; - - for (i = 0, end = ci->GetAkickCount(); i < end; ++i) - { - const AutoKick *akick = ci->GetAkick(i); - - if (akick->nc ? akick->nc == nc : mask.equals_ci(akick->mask)) - break; - } - - if (i == ci->GetAkickCount()) - { - source.Reply(_("\002%s\002 not found on %s autokick list."), mask.c_str(), ci->name.c_str()); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("AKICK"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << mask; - - FOREACH_MOD(OnAkickDel, (source, ci, ci->GetAkick(i))); - - ci->EraseAkick(i); - - source.Reply(_("\002%s\002 deleted from %s autokick list."), mask.c_str(), ci->name.c_str()); - } - } - - void ProcessList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms, ListFormatter &list) - { - const Anope::string &mask = params.size() > 2 ? params[2] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class AkickListCallback : public NumberList - { - ListFormatter &list; - ChannelInfo *ci; - - public: - AkickListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > ci->GetAkickCount()) - return; - - const AutoKick *akick = ci->GetAkick(number - 1); - - Anope::string timebuf, lastused; - if (akick->addtime) - timebuf = Anope::strftime(akick->addtime, NULL, true); - else - timebuf = UNKNOWN; - if (akick->last_used) - lastused = Anope::strftime(akick->last_used, NULL, true); - else - lastused = UNKNOWN; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); - if (akick->nc) - entry["Mask"] = akick->nc->display; - else - entry["Mask"] = akick->mask; - entry["Creator"] = akick->creator; - entry["Created"] = timebuf; - entry["Last used"] = lastused; - entry["Reason"] = akick->reason; - this->list.AddEntry(entry); - } - } - nl_list(list, ci, mask); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = ci->GetAkickCount(); i < end; ++i) - { - const AutoKick *akick = ci->GetAkick(i); - - if (!mask.empty()) - { - if (!akick->nc && !Anope::Match(akick->mask, mask)) - continue; - if (akick->nc && !Anope::Match(akick->nc->display, mask)) - continue; - } - - Anope::string timebuf, lastused; - if (akick->addtime) - timebuf = Anope::strftime(akick->addtime, NULL, true); - else - timebuf = UNKNOWN; - if (akick->last_used) - lastused = Anope::strftime(akick->last_used, NULL, true); - else - lastused = UNKNOWN; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - if (akick->nc) - entry["Mask"] = akick->nc->display; - else - entry["Mask"] = akick->mask; - entry["Creator"] = akick->creator; - entry["Created"] = timebuf; - entry["Last used"] = lastused; - entry["Reason"] = akick->reason; - list.AddEntry(entry); - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str()); - else - { - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("Autokick list for %s:"), ci->name.c_str()); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of autokick list")); - } - } - - void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (!ci->GetAkickCount()) - { - source.Reply(_("%s autokick list is empty."), ci->name.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason")); - this->ProcessList(source, ci, params, list); - } - - void DoView(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (!ci->GetAkickCount()) - { - source.Reply(_("%s autokick list is empty."), ci->name.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Last used")).AddColumn(_("Reason")); - this->ProcessList(source, ci, params, list); - } - - void DoEnforce(CommandSource &source, ChannelInfo *ci) - { - Channel *c = ci->c; - int count = 0; - - if (!c) - { - source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - return; - } - - for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) - { - ChanUserContainer *uc = it->second; - ++it; - - if (c->CheckKick(uc->user)) - ++count; - } - - bool override = !source.AccessFor(ci).HasPriv("AKICK"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ENFORCE, affects " << count << " users"; - - source.Reply(_("AKICK ENFORCE for \002%s\002 complete; \002%d\002 users were affected."), ci->name.c_str(), count); - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the akick list"; - - ci->ClearAkick(); - source.Reply(_("Channel %s akick list has been cleared."), ci->name.c_str()); - } - - public: - CommandCSAKick(Module *creator) : Command(creator, "chanserv/akick", 2, 4) - { - this->SetDesc(_("Maintain the AutoKick list")); - this->SetSyntax(_("\037channel\037 ADD {\037nick\037 | \037mask\037} [\037reason\037]")); - this->SetSyntax(_("\037channel\037 DEL {\037nick\037 | \037mask\037 | \037entry-num\037 | \037list\037}")); - this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037entry-num\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 VIEW [\037mask\037 | \037entry-num\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 ENFORCE")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Anope::string chan = params[0]; - Anope::string cmd = params[1]; - Anope::string mask = params.size() > 2 ? params[2] : ""; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - bool is_list = cmd.equals_ci("LIST") || cmd.equals_ci("VIEW"); - - bool has_access = false; - if (source.AccessFor(ci).HasPriv("AKICK") || source.HasPriv("chanserv/access/modify")) - has_access = true; - else if (is_list && source.HasPriv("chanserv/access/list")) - has_access = true; - - if (mask.empty() && (cmd.equals_ci("ADD") || cmd.equals_ci("DEL"))) - this->OnSyntaxError(source, cmd); - else if (!has_access) - source.Reply(ACCESS_DENIED); - else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && Anope::ReadOnly) - source.Reply(_("Sorry, channel autokick list modification is temporarily disabled.")); - else if (cmd.equals_ci("ADD")) - this->DoAdd(source, ci, params); - else if (cmd.equals_ci("DEL")) - this->DoDel(source, ci, params); - else if (cmd.equals_ci("LIST")) - this->DoList(source, ci, params); - else if (cmd.equals_ci("VIEW")) - this->DoView(source, ci, params); - else if (cmd.equals_ci("ENFORCE")) - this->DoEnforce(source, ci); - else if (cmd.equals_ci("CLEAR")) - this->DoClear(source, ci); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - BotInfo *bi = Config->GetClient("NickServ"); - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002AutoKick list\002 for a channel. If a user\n" - "on the AutoKick list attempts to join the channel,\n" - "%s will ban that user from the channel, then kick\n" - "the user.\n" - " \n" - "The \002AKICK ADD\002 command adds the given nick or usermask\n" - "to the AutoKick list. If a \037reason\037 is given with\n" - "the command, that reason will be used when the user is\n" - "kicked; if not, the default reason is \"User has been\n" - "banned from the channel\".\n" - "When akicking a \037registered nick\037 the %s account\n" - "will be added to the akick list instead of the mask.\n" - "All users within that nickgroup will then be akicked.\n"), - source.service->nick.c_str(), bi ? bi->nick.c_str() : "NickServ"); - source.Reply(_( - " \n" - "The \002AKICK DEL\002 command removes the given nick or mask\n" - "from the AutoKick list. It does not, however, remove any\n" - "bans placed by an AutoKick; those must be removed\n" - "manually.\n" - " \n" - "The \002AKICK LIST\002 command displays the AutoKick list, or\n" - "optionally only those AutoKick entries which match the\n" - "given mask.\n" - " \n" - "The \002AKICK VIEW\002 command is a more verbose version of the\n" - "\002AKICK LIST\002 command.\n" - " \n" - "The \002AKICK ENFORCE\002 command causes %s to enforce the\n" - "current AKICK list by removing those users who match an\n" - "AKICK mask.\n" - " \n" - "The \002AKICK CLEAR\002 command clears all entries of the\n" - "akick list."), source.service->nick.c_str()); - return true; - } -}; - -class CSAKick : public Module -{ - CommandCSAKick commandcsakick; - - public: - CSAKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsakick(this) - { - } - - EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override - { - if (!c->ci || c->MatchesList(u, "EXCEPT")) - return EVENT_CONTINUE; - - for (unsigned j = 0, end = c->ci->GetAkickCount(); j < end; ++j) - { - AutoKick *autokick = c->ci->GetAkick(j); - bool kick = false; - - if (autokick->nc) - kick = autokick->nc == u->Account(); - else if (IRCD->IsChannelValid(autokick->mask)) - { - Channel *chan = Channel::Find(autokick->mask); - kick = chan != NULL && chan->FindUser(u); - } - else - kick = Entry("BAN", autokick->mask).Matches(u); - - if (kick) - { - Log(LOG_DEBUG_2) << u->nick << " matched akick " << (autokick->nc ? autokick->nc->display : autokick->mask); - autokick->last_used = Anope::CurTime; - if (!autokick->nc && autokick->mask.find('#') == Anope::string::npos) - mask = autokick->mask; - reason = autokick->reason; - if (reason.empty()) - { - reason = Language::Translate(u, Config->GetModule(this)->Get<const Anope::string>("autokickreason").c_str()); - reason = reason.replace_all_cs("%n", u->nick) - .replace_all_cs("%c", c->name); - } - if (reason.empty()) - reason = Language::Translate(u, _("User has been banned from the channel")); - return EVENT_STOP; - } - } - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(CSAKick) diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp deleted file mode 100644 index 1cf316b88..000000000 --- a/modules/commands/cs_ban.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static Module *me; - -class TempBan : public Timer -{ - private: - Anope::string channel; - Anope::string mask; - Anope::string mode; - - public: - TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod) : Timer(me, seconds), channel(c->name), mask(banmask), mode(mod) { } - - void Tick(time_t ctime) anope_override - { - Channel *c = Channel::Find(this->channel); - if (c) - c->RemoveMode(NULL, mode, this->mask); - } -}; - -class CommandCSBan : public Command -{ - public: - CommandCSBan(Module *creator) : Command(creator, "chanserv/ban", 2, 4) - { - this->SetDesc(_("Bans a given nick or mask on a channel")); - this->SetSyntax(_("\037channel\037 [+\037expiry\037] {\037nick\037 | \037mask\037} [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - Configuration::Block *block = Config->GetCommand(source); - const Anope::string &mode = block->Get<Anope::string>("mode", "BAN"); - - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - Channel *c = ci->c; - if (c == NULL) - { - source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); - return; - } - else if (IRCD->GetMaxListFor(c) && c->HasMode(mode) >= IRCD->GetMaxListFor(c)) - { - source.Reply(_("The %s list for %s is full."), mode.lower().c_str(), c->name.c_str()); - return; - } - - Anope::string expiry, target, reason; - time_t ban_time; - if (params[1][0] == '+') - { - ban_time = Anope::DoTime(params[1]); - if (ban_time == -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - if (params.size() < 3) - { - this->SendSyntax(source); - return; - } - target = params[2]; - reason = "Requested"; - if (params.size() > 3) - reason = params[3]; - } - else - { - ban_time = 0; - target = params[1]; - reason = "Requested"; - if (params.size() > 2) - reason = params[2]; - if (params.size() > 3) - reason += " " + params[3]; - } - - unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200"); - if (reason.length() > reasonmax) - reason = reason.substr(0, reasonmax); - - Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)"); - signkickformat = signkickformat.replace_all_cs("%n", source.GetNick()); - - User *u = source.GetUser(); - User *u2 = User::Find(target, true); - - AccessGroup u_access = source.AccessFor(ci); - - if (!u_access.HasPriv("BAN") && !source.HasPriv("chanserv/kick")) - source.Reply(ACCESS_DENIED); - else if (u2) - { - AccessGroup u2_access = ci->AccessFor(u2); - - if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick")) - source.Reply(ACCESS_DENIED); - /* - * Don't ban/kick the user on channels where he is excepted - * to prevent services <-> server wars. - */ - else if (c->MatchesList(u2, "EXCEPT")) - source.Reply(CHAN_EXCEPTED, u2->nick.c_str(), ci->name.c_str()); - else if (u2->IsProtected()) - source.Reply(ACCESS_DENIED); - else - { - Anope::string mask = ci->GetIdealBan(u2); - - bool override = !u_access.HasPriv("BAN") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask; - - if (!c->HasMode(mode, mask)) - { - c->SetMode(NULL, mode, mask); - if (ban_time) - { - 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()); - } - } - - /* We still allow host banning while not allowing to kick */ - if (!c->FindUser(u2)) - return; - - if (block->Get<bool>("kick", "yes")) - { - if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK"))) - { - signkickformat = signkickformat.replace_all_cs("%m", reason); - c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str()); - } - else - c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); - } - } - } - else - { - bool founder = u_access.HasPriv("FOUNDER"); - bool override = !founder && !u_access.HasPriv("BAN"); - - 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, mask); - if (ban_time) - { - 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()); - } - } - - int matched = 0, kicked = 0; - for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end;) - { - ChanUserContainer *uc = it->second; - ++it; - - Entry e(mode, mask); - if (e.Matches(uc->user)) - { - ++matched; - - AccessGroup u2_access = ci->AccessFor(uc->user); - - if (matched > 1 && !founder) - continue; - if (u != uc->user && ci->HasExt("PEACE") && u2_access >= u_access) - continue; - else if (ci->c->MatchesList(uc->user, "EXCEPT")) - continue; - else if (uc->user->IsProtected()) - continue; - - if (block->Get<bool>("kick", "yes")) - { - ++kicked; - if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK"))) - { - 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()); - } - } - } - - if (matched) - 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(), mask.c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Bans a given nick or mask on a channel. An optional expiry may\n" - "be given to cause services to remove the ban after a set amount\n" - "of time.\n" - " \n" - "By default, limited to AOPs or those with level 5 access\n" - "and above on the channel. Channel founders may ban masks.")); - return true; - } -}; - -class CSBan : public Module -{ - CommandCSBan commandcsban; - - public: - CSBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsban(this) - { - me = this; - } -}; - -MODULE_INIT(CSBan) diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp deleted file mode 100644 index a4ec31c1e..000000000 --- a/modules/commands/cs_clone.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/bs_badwords.h" - -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) - { - this->SetDesc(_("Copy all settings from one channel to another")); - this->SetSyntax(_("\037channel\037 \037target\037 [\037what\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &channel = params[0]; - const Anope::string &target = params[1]; - Anope::string what = params.size() > 2 ? params[2] : ""; - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - User *u = source.GetUser(); - ChannelInfo *ci = ChannelInfo::Find(channel); - bool override = false; - - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); - return; - } - - ChannelInfo *target_ci = ChannelInfo::Find(target); - if (!target_ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, target.c_str()); - return; - } - - if (ci == target_ci) - { - source.Reply(_("Cannot clone channel \002%s\002 to itself!"), target.c_str()); - return; - } - - if (!source.IsFounder(ci) || !source.IsFounder(target_ci)) - { - if (!source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - else - override = true; - } - - if (what.equals_ci("ALL")) - what.clear(); - - if (what.empty()) - { - delete target_ci; - target_ci = new ChannelInfo(*ci); - target_ci->name = target; - target_ci->time_registered = Anope::CurTime; - (*RegisteredChannelList)[target_ci->name] = target_ci; - target_ci->c = Channel::Find(target_ci->name); - - target_ci->bi = NULL; - if (ci->bi) - ci->bi->Assign(u, target_ci); - - if (target_ci->c) - { - target_ci->c->ci = target_ci; - - target_ci->c->CheckModes(); - - target_ci->c->SetCorrectModes(u, true); - } - - if (target_ci->c && !target_ci->c->topic.empty()) - { - target_ci->last_topic = target_ci->c->topic; - target_ci->last_topic_setter = target_ci->c->topic_setter; - target_ci->last_topic_time = target_ci->c->topic_time; - } - 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."), ci->name.c_str(), target_ci->name.c_str()); - } - else if (what.equals_ci("ACCESS")) - { - CopyAccess(source, ci, target_ci); - } - else if (what.equals_ci("AKICK")) - { - CopyAkick(source, ci, target_ci); - } - else if (what.equals_ci("BADWORDS")) - { - CopyBadwords(source, ci, target_ci); - } - else if (what.equals_ci("LEVELS")) - { - CopyLevels(source, ci, target_ci); - } - else - { - this->OnSyntaxError(source, ""); - return; - } - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clone " << (what.empty() ? "everything from it" : what) << " to " << target_ci->name; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - 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, \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; - } -}; - -class CSClone : public Module -{ - CommandCSClone commandcsclone; - - public: - CSClone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsclone(this) - { - - } -}; - -MODULE_INIT(CSClone) diff --git a/modules/commands/cs_drop.cpp b/modules/commands/cs_drop.cpp deleted file mode 100644 index 83299aee5..000000000 --- a/modules/commands/cs_drop.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSDrop : public Command -{ - public: - CommandCSDrop(Module *creator) : Command(creator, "chanserv/drop", 1, 2) - { - this->SetDesc(_("Cancel the registration of a channel")); - this->SetSyntax(_("\037channel\037 \037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - - if (Anope::ReadOnly && !source.HasPriv("chanserv/administration")) - { - source.Reply(_("Sorry, channel de-registration is temporarily disabled.")); // XXX: READ_ONLY_MODE? - return; - } - - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (params.size() < 2 || !chan.equals_ci(params[1])) - { - source.Reply(_("You must enter the channel name twice as a confirmation that you wish to drop \002%s\002."), chan.c_str()); - return; - } - - if ((ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && !source.HasCommand("chanserv/drop")) - { - source.Reply(ACCESS_DENIED); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnChanDrop, MOD_RESULT, (source, ci)); - if (MOD_RESULT == EVENT_STOP) - return; - - bool override = (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "(founder was: " << (ci->GetFounder() ? ci->GetFounder()->display : "none") << ")"; - - Reference<Channel> c = ci->c; - delete ci; - - source.Reply(_("Channel \002%s\002 has been dropped."), chan.c_str()); - - if (c) - c->CheckModes(); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - if (source.IsServicesOper()) - source.Reply(_("Unregisters the specified channel. Only \002Services Operators\002\n" - "can drop a channel of which they are not the founder of.")); - else - source.Reply(_("Unregisters the named channel. Can only be used by\n" - "the \002channel founder\002.")); - - return true; - } -}; - -class CSDrop : public Module -{ - CommandCSDrop commandcsdrop; - - public: - CSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsdrop(this) - { - - } -}; - -MODULE_INIT(CSDrop) diff --git a/modules/commands/cs_enforce.cpp b/modules/commands/cs_enforce.cpp deleted file mode 100644 index b9f700284..000000000 --- a/modules/commands/cs_enforce.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Original Coder: GeniusDex <geniusdex@anope.org> - * - * Please read COPYING and README for further details. - * - * Send any bug reports to the Anope Coder, as he will be able - * to deal with it best. - */ - -#include "module.h" - -class CommandCSEnforce : public Command -{ - private: - void DoSecureOps(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce secureops"; - - /* Dirty hack to allow Channel::SetCorrectModes to work ok. - * We pretend like SECUREOPS is on so it doesn't ignore that - * part of the code. This way we can enforce SECUREOPS even - * if it's off. - */ - bool hadsecureops = ci->HasExt("SECUREOPS"); - ci->Extend<bool>("SECUREOPS"); - - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - - ci->c->SetCorrectModes(uc->user, false); - } - - if (!hadsecureops) - ci->Shrink<bool>("SECUREOPS"); - - source.Reply(_("Secureops enforced on %s."), ci->name.c_str()); - } - - void DoRestricted(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce restricted"; - - std::vector<User *> users; - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (user->IsProtected()) - continue; - - if (ci->AccessFor(user).empty()) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - { - User *user = users[i]; - - Anope::string mask = ci->GetIdealBan(user); - Anope::string reason = Language::Translate(user, _("RESTRICTED enforced by ")) + source.GetNick(); - ci->c->SetMode(NULL, "BAN", mask); - ci->c->Kick(NULL, user, "%s", reason.c_str()); - } - - source.Reply(_("Restricted enforced on %s."), ci->name.c_str()); - } - - void DoRegOnly(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce registered only"; - - std::vector<User *> users; - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (user->IsProtected()) - continue; - - if (!user->IsIdentified()) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - { - User *user = users[i]; - - Anope::string mask = ci->GetIdealBan(user); - Anope::string reason = Language::Translate(user, _("REGONLY enforced by ")) + source.GetNick(); - if (!ci->c->HasMode("REGISTEREDONLY")) - ci->c->SetMode(NULL, "BAN", mask); - ci->c->Kick(NULL, user, "%s", reason.c_str()); - } - - source.Reply(_("Registered only enforced on %s."), ci->name.c_str()); - } - - void DoSSLOnly(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce SSL only"; - - std::vector<User *> users; - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (user->IsProtected()) - continue; - - if (!user->HasMode("SSL") && !user->HasExt("ssl")) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - { - User *user = users[i]; - - Anope::string mask = ci->GetIdealBan(user); - Anope::string reason = Language::Translate(user, _("SSLONLY enforced by ")) + source.GetNick(); - if (!ci->c->HasMode("SSL")) - ci->c->SetMode(NULL, "BAN", mask); - ci->c->Kick(NULL, user, "%s", reason.c_str()); - } - - source.Reply(_("SSL only enforced on %s."), ci->name.c_str()); - } - - void DoBans(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce bans"; - - std::vector<User *> users; - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (user->IsProtected()) - continue; - - if (ci->c->MatchesList(user, "BAN") && !ci->c->MatchesList(user, "EXCEPT")) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - { - User *user = users[i]; - - Anope::string reason = Language::Translate(user, _("BANS enforced by ")) + source.GetNick(); - ci->c->Kick(NULL, user, "%s", reason.c_str()); - } - - source.Reply(_("Bans enforced on %s."), ci->name.c_str()); - } - - void DoLimit(CommandSource &source, ChannelInfo *ci) - { - bool override = !source.AccessFor(ci).HasPriv("AKICK") && source.HasPriv("chanserv/access/modify"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enforce limit"; - - Anope::string l_str; - if (!ci->c->GetParam("LIMIT", l_str)) - { - source.Reply(_("No limit is set on %s."), ci->name.c_str()); - return; - } - - int l; - try - { - l = convertTo<int>(l_str); - if (l < 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("The limit on %s is not valid."), ci->name.c_str()); - return; - } - - std::vector<User *> users; - /* The newer users are at the end of the list, so kick users starting from the end */ - for (Channel::ChanUserList::reverse_iterator it = ci->c->users.rbegin(), it_end = ci->c->users.rend(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (user->IsProtected()) - continue; - - if (!ci->AccessFor(user).empty()) - continue; - - if (ci->c->users.size() - users.size() <= static_cast<unsigned>(l)) - continue; - - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - { - User *user = users[i]; - - Anope::string reason = Language::Translate(user, _("LIMIT enforced by ")) + source.GetNick(); - ci->c->Kick(NULL, user, "%s", reason.c_str()); - } - - source.Reply(_("LIMIT enforced on %s, %d users removed."), ci->name.c_str(), users.size()); - } - - public: - CommandCSEnforce(Module *creator) : Command(creator, "chanserv/enforce", 2, 2) - { - this->SetDesc(_("Enforce various channel modes and set options")); - this->SetSyntax(_("\037channel\037 \037what\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &what = params.size() > 1 ? params[1] : ""; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - - if (!ci) - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - else if (!ci->c) - source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - else if (!source.AccessFor(ci).HasPriv("AKICK") && !source.HasPriv("chanserv/access/modify")) - source.Reply(ACCESS_DENIED); - else if (what.equals_ci("SECUREOPS")) - this->DoSecureOps(source, ci); - else if (what.equals_ci("RESTRICTED")) - this->DoRestricted(source, ci); - else if (what.equals_ci("REGONLY")) - this->DoRegOnly(source, ci); - else if (what.equals_ci("SSLONLY")) - this->DoSSLOnly(source, ci); - else if (what.equals_ci("BANS")) - this->DoBans(source, ci); - else if (what.equals_ci("LIMIT")) - this->DoLimit(source, ci); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enforce various channel modes and set options. The \037channel\037\n" - "option indicates what channel to enforce the modes and options\n" - "on. The \037what\037 option indicates what modes and options to\n" - "enforce, and can be any of \002SECUREOPS\002, \002RESTRICTED\002, \002REGONLY\002, \002SSLONLY\002,\n" - "\002BANS\002, or \002LIMIT\002.\n" - " \n" - "Use \002SECUREOPS\002 to enforce the SECUREOPS option, even if it is not\n" - "enabled. Use \002RESTRICTED\002 to enfore the RESTRICTED option, also\n" - "if it's not enabled. Use \002REGONLY\002 to kick all unregistered users\n" - "from the channel. Use \002SSLONLY\002 to kick all users not using a secure\n" - "connection from the channel. \002BANS\002 will enforce bans on the channel by\n" - "kicking users affected by them, and \002LIMIT\002 will kick users until the\n" - "user count drops below the channel limit, if one is set.")); - return true; - } -}; - -class CSEnforce : public Module -{ - CommandCSEnforce commandcsenforce; - - public: - CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsenforce(this) - { - - } -}; - -MODULE_INIT(CSEnforce) diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp deleted file mode 100644 index 796aa5148..000000000 --- a/modules/commands/cs_entrymsg.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_entrymsg.h" - -struct EntryMsgImpl : EntryMsg, Serializable -{ - EntryMsgImpl() : Serializable("EntryMsg") - { - } - - EntryMsgImpl(ChannelInfo *c, const Anope::string &cname, const Anope::string &cmessage, time_t ct = Anope::CurTime) : Serializable("EntryMsg") - { - this->chan = c->name; - this->creator = cname; - this->message = cmessage; - this->when = ct; - } - - ~EntryMsgImpl(); - - void Serialize(Serialize::Data &data) const anope_override - { - data["ci"] << this->chan; - data["creator"] << this->creator; - data["message"] << this->message; - data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data); -}; - -struct EntryMessageListImpl : EntryMessageList -{ - EntryMessageListImpl(Extensible *) { } - - EntryMsg* Create() anope_override - { - return new EntryMsgImpl(); - } -}; - -EntryMsgImpl::~EntryMsgImpl() -{ - ChannelInfo *ci = ChannelInfo::Find(this->chan); - if (!ci) - return; - - EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg"); - if (!messages) - return; - - std::vector<EntryMsg *>::iterator it = std::find((*messages)->begin(), (*messages)->end(), this); - if (it != (*messages)->end()) - (*messages)->erase(it); -} - - -Serializable* EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data) -{ - Anope::string sci, screator, smessage; - time_t swhen; - - data["ci"] >> sci; - data["creator"] >> screator; - data["message"] >> smessage; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (!ci) - return NULL; - - if (obj) - { - EntryMsgImpl *msg = anope_dynamic_static_cast<EntryMsgImpl *>(obj); - msg->chan = ci->name; - data["creator"] >> msg->creator; - data["message"] >> msg->message; - data["when"] >> msg->when; - return msg; - } - - EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg"); - - data["when"] >> swhen; - - EntryMsgImpl *m = new EntryMsgImpl(ci, screator, smessage, swhen); - (*messages)->push_back(m); - return m; -} - -class CommandEntryMessage : public Command -{ - private: - void DoList(CommandSource &source, ChannelInfo *ci) - { - EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg"); - - if ((*messages)->empty()) - { - source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str()); - return; - } - - source.Reply(_("Entry message list for \002%s\002:"), ci->name.c_str()); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Message")); - for (unsigned i = 0; i < (*messages)->size(); ++i) - { - EntryMsg *msg = (*messages)->at(i); - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Creator"] = msg->creator; - entry["Created"] = Anope::strftime(msg->when, NULL, true); - entry["Message"] = msg->message; - list.AddEntry(entry); - } - - std::vector<Anope::string> replies; - list.Process(replies); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of entry message list.")); - } - - void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &message) - { - EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg"); - - if ((*messages)->size() >= Config->GetModule(this->owner)->Get<unsigned>("maxentries")) - source.Reply(_("The entry message list for \002%s\002 is full."), ci->name.c_str()); - else - { - (*messages)->push_back(new EntryMsgImpl(ci, source.GetNick(), 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()); - } - } - - void DoDel(CommandSource &source, ChannelInfo *ci, const Anope::string &message) - { - EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg"); - - if (!message.is_pos_number_only()) - source.Reply(("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str()); - else if ((*messages)->empty()) - source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str()); - else - { - try - { - unsigned i = convertTo<unsigned>(message); - if (i > 0 && i <= (*messages)->size()) - { - delete (*messages)->at(i - 1); - if ((*messages)->empty()) - ci->Shrink<EntryMessageList>("entrymsg"); - 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 - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str()); - } - } - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - ci->Shrink<EntryMessageList>("entrymsg"); - - 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()); - } - - public: - CommandEntryMessage(Module *creator) : Command(creator, "chanserv/entrymsg", 2, 3) - { - this->SetDesc(_("Manage the channel's entry messages")); - this->SetSyntax(_("\037channel\037 ADD \037message\037")); - this->SetSyntax(_("\037channel\037 DEL \037num\037")); - this->SetSyntax(_("\037channel\037 LIST")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (Anope::ReadOnly && !params[1].equals_ci("LIST")) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("LIST")) - this->DoList(source, ci); - else if (params[1].equals_ci("CLEAR")) - this->DoClear(source, ci); - else if (params.size() < 3) - this->OnSyntaxError(source, ""); - else if (params[1].equals_ci("ADD")) - this->DoAdd(source, ci, params[2]); - else if (params[1].equals_ci("DEL")) - this->DoDel(source, ci, params[2]); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Controls what messages will be sent to users when they join the channel.")); - source.Reply(" "); - source.Reply(_("The \002ENTRYMSG ADD\002 command adds the given message to\n" - "the list of messages shown to users when they join\n" - "the channel.")); - source.Reply(" "); - source.Reply(_("The \002ENTRYMSG DEL\002 command removes the specified message from\n" - "the list of messages shown to users when they join\n" - "the channel. You can remove a message by specifying its number\n" - "which you can get by listing the messages as explained below.")); - source.Reply(" "); - source.Reply(_("The \002ENTRYMSG LIST\002 command displays a listing of messages\n" - "shown to users when they join the channel.")); - source.Reply(" "); - 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; - } -}; - -class CSEntryMessage : public Module -{ - CommandEntryMessage commandentrymsg; - ExtensibleItem<EntryMessageListImpl> eml; - Serialize::Type entrymsg_type; - - public: - CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandentrymsg(this), - eml(this, "entrymsg"), entrymsg_type("EntryMsg", EntryMsgImpl::Unserialize) - { - } - - void OnJoinChannel(User *u, Channel *c) anope_override - { - if (u && c && c->ci && u->server->IsSynced()) - { - EntryMessageList *messages = c->ci->GetExt<EntryMessageList>("entrymsg"); - - if (messages != NULL) - for (unsigned i = 0; i < (*messages)->size(); ++i) - u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), (*messages)->at(i)->message.c_str()); - } - } -}; - -MODULE_INIT(CSEntryMessage) diff --git a/modules/commands/cs_flags.cpp b/modules/commands/cs_flags.cpp deleted file mode 100644 index 477cc2468..000000000 --- a/modules/commands/cs_flags.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static std::map<Anope::string, char> defaultFlags; - -class FlagsChanAccess : public ChanAccess -{ - public: - std::set<char> flags; - - FlagsChanAccess(AccessProvider *p) : ChanAccess(p) - { - } - - bool HasPriv(const Anope::string &priv) const anope_override - { - std::map<Anope::string, char>::iterator it = defaultFlags.find(priv); - if (it != defaultFlags.end() && this->flags.count(it->second) > 0) - return true; - return false; - } - - Anope::string AccessSerialize() const - { - return Anope::string(this->flags.begin(), this->flags.end()); - } - - void AccessUnserialize(const Anope::string &data) anope_override - { - for (unsigned i = data.length(); i > 0; --i) - this->flags.insert(data[i - 1]); - } - - static Anope::string DetermineFlags(const ChanAccess *access) - { - if (access->provider->name == "access/flags") - return access->AccessSerialize(); - - std::set<char> buffer; - - for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) - if (access->HasPriv(it->first)) - buffer.insert(it->second); - - if (buffer.empty()) - return "(none)"; - else - return Anope::string(buffer.begin(), buffer.end()); - } -}; - -class FlagsAccessProvider : public AccessProvider -{ - public: - static FlagsAccessProvider *ap; - - FlagsAccessProvider(Module *o) : AccessProvider(o, "access/flags") - { - ap = this; - } - - ChanAccess *Create() anope_override - { - return new FlagsChanAccess(this); - } -}; -FlagsAccessProvider* FlagsAccessProvider::ap; - -class CommandCSFlags : public Command -{ - void DoModify(CommandSource &source, ChannelInfo *ci, Anope::string mask, const Anope::string &flags) - { - if (flags.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - AccessGroup u_access = source.AccessFor(ci); - const ChanAccess *highest = u_access.Highest(); - const NickAlias *na = NULL; - - if (IRCD->IsChannelValid(mask)) - { - if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access")) - { - source.Reply(_("Channels may not be on access lists.")); - return; - } - - ChannelInfo *targ_ci = ChannelInfo::Find(mask); - if (targ_ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, mask.c_str()); - return; - } - else if (ci == targ_ci) - { - source.Reply(_("You can't add a channel to its own access list.")); - return; - } - - mask = targ_ci->name; - } - else - { - na = NickAlias::Find(mask); - if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access")) - { - source.Reply(_("Masks and unregistered users may not be on access lists.")); - return; - } - else if (mask.find_first_of("!*@") == Anope::string::npos && !na) - { - User *targ = User::Find(mask, true); - if (targ != NULL) - mask = "*!*@" + targ->GetDisplayedHost(); - else - { - source.Reply(NICK_X_NOT_REGISTERED, mask.c_str()); - return; - } - } - - if (na) - mask = na->nick; - } - - ChanAccess *current = NULL; - unsigned current_idx; - std::set<char> current_flags; - bool override = false; - for (current_idx = ci->GetAccessCount(); current_idx > 0; --current_idx) - { - ChanAccess *access = ci->GetAccess(current_idx - 1); - if ((na && na->nc == access->GetAccount()) || mask.equals_ci(access->Mask())) - { - // Flags allows removing others that have the same access as you, - // but no other access system does. - if (highest && highest->provider != FlagsAccessProvider::ap && !u_access.founder) - // operator<= on the non-me entry! - if (*highest <= *access) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - - current = access; - Anope::string cur_flags = FlagsChanAccess::DetermineFlags(access); - for (unsigned j = cur_flags.length(); j > 0; --j) - current_flags.insert(cur_flags[j - 1]); - break; - } - } - - unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024"); - if (access_max && ci->GetDeepAccessCount() >= access_max) - { - source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max); - return; - } - - Privilege *p = NULL; - bool add = true; - for (size_t i = 0; i < flags.length(); ++i) - { - char f = flags[i]; - switch (f) - { - case '+': - add = true; - break; - case '-': - add = false; - break; - case '*': - for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) - { - bool has = current_flags.count(it->second); - // If we are adding a flag they already have or removing one they don't have, don't bother - if (add == has) - continue; - - if (!u_access.HasPriv(it->first) && !u_access.founder) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - continue; - } - - if (add) - current_flags.insert(it->second); - else - current_flags.erase(it->second); - } - break; - default: - p = PrivilegeManager::FindPrivilege(flags.substr(i)); - if (p != NULL && defaultFlags[p->name]) - { - f = defaultFlags[p->name]; - i = flags.length(); - } - - for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) - { - if (f != it->second) - continue; - else if (!u_access.HasPriv(it->first) && !u_access.founder) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - { - source.Reply(_("You cannot set the \002%c\002 flag."), f); - break; - } - } - if (add) - current_flags.insert(f); - else - current_flags.erase(f); - break; - } - } - } - if (current_flags.empty()) - { - if (current != NULL) - { - ci->EraseAccess(current_idx - 1); - FOREACH_MOD(OnAccessDel, (ci, source, current)); - delete current; - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << mask; - source.Reply(_("\002%s\002 removed from the %s access list."), mask.c_str(), ci->name.c_str()); - } - else - { - source.Reply(_("\002%s\002 not found on %s access list."), mask.c_str(), ci->name.c_str()); - } - return; - } - - ServiceReference<AccessProvider> provider("AccessProvider", "access/flags"); - if (!provider) - return; - FlagsChanAccess *access = anope_dynamic_static_cast<FlagsChanAccess *>(provider->Create()); - access->SetMask(mask, ci); - access->creator = source.GetNick(); - access->last_seen = current ? current->last_seen : 0; - access->created = Anope::CurTime; - access->flags = current_flags; - - if (current != NULL) - delete current; - - ci->AddAccess(access); - - FOREACH_MOD(OnAccessAdd, (ci, source, access)); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to modify " << mask << "'s flags to " << access->AccessSerialize(); - if (p != NULL) - { - if (add) - source.Reply(_("Privilege \002%s\002 added to \002%s\002 on \002%s\002, new flags are +\002%s\002"), p->name.c_str(), access->Mask().c_str(), ci->name.c_str(), access->AccessSerialize().c_str()); - else - source.Reply(_("Privilege \002%s\002 removed from \002%s\002 on \002%s\002, new flags are +\002%s\002"), p->name.c_str(), access->Mask().c_str(), ci->name.c_str(), access->AccessSerialize().c_str()); - } - else - source.Reply(_("Flags for \002%s\002 on %s set to +\002%s\002"), access->Mask().c_str(), ci->name.c_str(), access->AccessSerialize().c_str()); - } - - void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string &arg = params.size() > 2 ? params[2] : ""; - - if (!ci->GetAccessCount()) - { - source.Reply(_("%s access list is empty."), ci->name.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Flags")).AddColumn(_("Creator")).AddColumn(_("Created")); - - unsigned count = 0; - for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i) - { - const ChanAccess *access = ci->GetAccess(i); - const Anope::string &flags = FlagsChanAccess::DetermineFlags(access); - - if (!arg.empty()) - { - if (arg[0] == '+') - { - bool pass = true; - for (size_t j = 1; j < arg.length(); ++j) - if (flags.find(arg[j]) == Anope::string::npos) - pass = false; - if (pass == false) - continue; - } - else if (!Anope::Match(access->Mask(), arg)) - continue; - } - - ListFormatter::ListEntry entry; - ++count; - entry["Number"] = stringify(i + 1); - entry["Mask"] = access->Mask(); - entry["Flags"] = flags; - entry["Creator"] = access->creator; - entry["Created"] = Anope::strftime(access->created, source.nc, true); - list.AddEntry(entry); - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); - else - { - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("Flags list for %s"), ci->name.c_str()); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - if (count == ci->GetAccessCount()) - source.Reply(_("End of access list.")); - else - source.Reply(_("End of access list - %d/%d entries shown."), count, ci->GetAccessCount()); - } - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - if (!source.IsFounder(ci) && !source.HasPriv("chanserv/access/modify")) - source.Reply(ACCESS_DENIED); - else - { - ci->ClearAccess(); - - FOREACH_MOD(OnAccessClear, (ci, source)); - - source.Reply(_("Channel %s access list has been cleared."), ci->name.c_str()); - - bool override = !source.IsFounder(ci); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list"; - } - - return; - } - - public: - CommandCSFlags(Module *creator) : Command(creator, "chanserv/flags", 1, 4) - { - this->SetDesc(_("Modify the list of privileged users")); - this->SetSyntax(_("\037channel\037 [MODIFY] \037mask\037 \037changes\037")); - this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | +\037flags\037]")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &cmd = params.size() > 1 ? params[1] : ""; - - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - bool is_list = cmd.empty() || cmd.equals_ci("LIST"); - bool has_access = false; - if (source.HasPriv("chanserv/access/modify")) - has_access = true; - else if (is_list && source.HasPriv("chanserv/access/list")) - has_access = true; - else if (is_list && source.AccessFor(ci).HasPriv("ACCESS_LIST")) - has_access = true; - else if (source.AccessFor(ci).HasPriv("ACCESS_CHANGE")) - has_access = true; - - if (!has_access) - source.Reply(ACCESS_DENIED); - else if (Anope::ReadOnly && !is_list) - source.Reply(_("Sorry, channel access list modification is temporarily disabled.")); - else if (is_list) - this->DoList(source, ci, params); - else if (cmd.equals_ci("CLEAR")) - this->DoClear(source, ci); - else - { - Anope::string mask, flags; - if (cmd.equals_ci("MODIFY")) - { - mask = params.size() > 2 ? params[2] : ""; - flags = params.size() > 3 ? params[3] : ""; - } - else - { - mask = cmd; - flags = params.size() > 2 ? params[2] : ""; - } - - this->DoModify(source, ci, mask, flags); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("%s is another way to modify the channel access list, similar to\n" - "the XOP and ACCESS methods."), source.command.c_str()); - source.Reply(" "); - source.Reply(_("The \002MODIFY\002 command allows you to modify the access list. If the mask is\n" - "not already on the access list it is added, then the changes are applied.\n" - "If the mask has no more flags, then the mask is removed from the access list.\n" - "Additionally, you may use +* or -* to add or remove all flags, respectively. You are\n" - "only able to modify the access list if you have the proper permission on the channel,\n" - "and even then you can only give other people access to the equivalent of what your access is.")); - source.Reply(" "); - source.Reply(_("The \002LIST\002 command allows you to list existing entries on the channel access list.\n" - "If a mask is given, the mask is wildcard matched against all existing entries on the\n" - "access list, and only those entries are returned. If a set of flags is given, only those\n" - "on the access list with the specified flags are returned.")); - source.Reply(" "); - source.Reply(_("The \002CLEAR\002 command clears the channel access list. This requires channel founder access.")); - source.Reply(" "); - source.Reply(_("The available flags are:")); - - typedef std::multimap<char, Anope::string, ci::less> reverse_map; - reverse_map reverse; - for (std::map<Anope::string, char>::iterator it = defaultFlags.begin(), it_end = defaultFlags.end(); it != it_end; ++it) - reverse.insert(std::make_pair(it->second, it->first)); - - for (reverse_map::iterator it = reverse.begin(), it_end = reverse.end(); it != it_end; ++it) - { - Privilege *p = PrivilegeManager::FindPrivilege(it->second); - if (p == NULL) - continue; - source.Reply(" %c - %s", it->first, Language::Translate(source.nc, p->desc.c_str())); - } - - return true; - } -}; - -class CSFlags : public Module -{ - FlagsAccessProvider accessprovider; - CommandCSFlags commandcsflags; - - public: - CSFlags(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - accessprovider(this), commandcsflags(this) - { - this->SetPermanent(true); - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - defaultFlags.clear(); - - for (int i = 0; i < conf->CountBlock("privilege"); ++i) - { - Configuration::Block *priv = conf->GetBlock("privilege", i); - - const Anope::string &pname = priv->Get<const Anope::string>("name"); - - Privilege *p = PrivilegeManager::FindPrivilege(pname); - if (p == NULL) - continue; - - const Anope::string &value = priv->Get<const Anope::string>("flag"); - if (value.empty()) - continue; - - defaultFlags[p->name] = value[0]; - } - } -}; - -MODULE_INIT(CSFlags) diff --git a/modules/commands/cs_getkey.cpp b/modules/commands/cs_getkey.cpp deleted file mode 100644 index b9d58393d..000000000 --- a/modules/commands/cs_getkey.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSGetKey : public Command -{ - public: - CommandCSGetKey(Module *creator) : Command(creator, "chanserv/getkey", 1, 1) - { - this->SetDesc(_("Returns the key of the given channel")); - this->SetSyntax(_("\037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("GETKEY") && !source.HasCommand("chanserv/getkey")) - { - source.Reply(ACCESS_DENIED); - return; - } - - Anope::string key; - if (!ci->c || !ci->c->GetParam("KEY", key)) - { - source.Reply(_("Channel \002%s\002 has no key."), chan.c_str()); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("GETKEY"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci); - - source.Reply(_("Key for channel \002%s\002 is \002%s\002."), chan.c_str(), key.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Returns the key of the given channel.")); - return true; - } -}; - -class CSGetKey : public Module -{ - CommandCSGetKey commandcsgetkey; - - public: - CSGetKey(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsgetkey(this) - { - - } -}; - -MODULE_INIT(CSGetKey) diff --git a/modules/commands/cs_info.cpp b/modules/commands/cs_info.cpp deleted file mode 100644 index 8ebcc8e40..000000000 --- a/modules/commands/cs_info.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSInfo : public Command -{ - public: - CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2) - { - this->SetDesc(_("Lists information about the specified registered channel")); - this->SetSyntax(_("\037channel\037")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - - NickCore *nc = source.nc; - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - bool has_auspex = source.HasPriv("chanserv/auspex"); - bool show_all = false; - - /* Should we show all fields? Only for sadmins and identified users */ - if (source.AccessFor(ci).HasPriv("INFO") || has_auspex) - show_all = true; - - InfoFormatter info(nc); - - source.Reply(CHAN_INFO_HEADER, chan.c_str()); - if (ci->GetFounder()) - info[_("Founder")] = ci->GetFounder()->display; - - if (show_all && ci->GetSuccessor()) - info[_("Successor")] = ci->GetSuccessor()->display; - - if (!ci->desc.empty()) - info[_("Description")] = ci->desc; - - info[_("Registered")] = Anope::strftime(ci->time_registered, source.GetAccount()); - info[_("Last used")] = Anope::strftime(ci->last_used, source.GetAccount()); - - if (show_all) - { - info[_("Ban type")] = stringify(ci->bantype); - } - - FOREACH_MOD(OnChanInfo, (source, ci, info, show_all)); - - std::vector<Anope::string> replies; - info.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists information about the specified registered channel,\n" - "including its founder, time of registration, last\n" - "time used, and description. If the user issuing the\n" - "command has the appropriate access for it, then the\n" - "successor, last topic set, settings and expiration\n" - "time will also be displayed when applicable.")); - return true; - } -}; - -class CSInfo : public Module -{ - CommandCSInfo commandcsinfo; - - public: - CSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsinfo(this) - { - - } -}; - -MODULE_INIT(CSInfo) diff --git a/modules/commands/cs_invite.cpp b/modules/commands/cs_invite.cpp deleted file mode 100644 index a95e25b30..000000000 --- a/modules/commands/cs_invite.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSInvite : public Command -{ - public: - CommandCSInvite(Module *creator) : Command(creator, "chanserv/invite", 1, 3) - { - this->SetDesc(_("Invites you or an optionally specified nick into a channel")); - this->SetSyntax(_("\037channel\037 [\037nick\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - - User *u = source.GetUser(); - Channel *c = Channel::Find(chan); - - if (!c) - { - source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); - return; - } - - ChannelInfo *ci = c->ci; - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("INVITE") && !source.HasCommand("chanserv/invite")) - { - source.Reply(ACCESS_DENIED); - return; - } - - User *u2; - if (params.size() == 1) - u2 = u; - else - u2 = User::Find(params[1], true); - - if (!u2) - { - source.Reply(NICK_X_NOT_IN_USE, params.size() > 1 ? params[1].c_str() : source.GetNick().c_str()); - return; - } - - if (c->FindUser(u2)) - { - if (u2 == u) - source.Reply(_("You are already in \002%s\002!"), c->name.c_str()); - else - source.Reply(_("\002%s\002 is already in \002%s\002!"), u2->nick.c_str(), c->name.c_str()); - } - else - { - bool override = !source.AccessFor(ci).HasPriv("INVITE"); - - IRCD->SendInvite(ci->WhoSends(), c, u2); - if (u2 != u) - { - source.Reply(_("\002%s\002 has been invited to \002%s\002."), u2->nick.c_str(), c->name.c_str()); - u2->SendMessage(ci->WhoSends(), _("You have been invited to \002%s\002 by \002%s\002."), c->name.c_str(), source.GetNick().c_str()); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; - } - else - { - u2->SendMessage(ci->WhoSends(), _("You have been invited to \002%s\002."), c->name.c_str()); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci); - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Tells %s to invite you or an optionally specified\n" - "nick into the given channel.\n" - " \n" - "By default, limited to AOPs or those with level 5 access and above\n" - "on the channel."), source.service->nick.c_str()); - return true; - } -}; - -class CSInvite : public Module -{ - CommandCSInvite commandcsinvite; - - public: - CSInvite(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsinvite(this) - { - - } -}; - -MODULE_INIT(CSInvite) diff --git a/modules/commands/cs_kick.cpp b/modules/commands/cs_kick.cpp deleted file mode 100644 index d552efb23..000000000 --- a/modules/commands/cs_kick.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSKick : public Command -{ - public: - CommandCSKick(Module *creator) : Command(creator, "chanserv/kick", 2, 3) - { - this->SetDesc(_("Kicks a specified nick from a channel")); - this->SetSyntax(_("\037channel\037 \037nick\037 [\037reason\037]")); - this->SetSyntax(_("\037channel\037 \037mask\037 [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &target = params[1]; - Anope::string reason = params.size() > 2 ? params[2] : "Requested"; - - User *u = source.GetUser(); - ChannelInfo *ci = ChannelInfo::Find(params[0]); - Channel *c = Channel::Find(params[0]); - User *u2 = User::Find(target, true); - - if (!c) - { - source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); - return; - } - else if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200"); - if (reason.length() > reasonmax) - reason = reason.substr(0, reasonmax); - - Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)"); - signkickformat = signkickformat.replace_all_cs("%n", source.GetNick()); - - AccessGroup u_access = source.AccessFor(ci); - - if (!u_access.HasPriv("KICK") && !source.HasPriv("chanserv/kick")) - source.Reply(ACCESS_DENIED); - else if (u2) - { - AccessGroup u2_access = ci->AccessFor(u2); - if (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access && !source.HasPriv("chanserv/kick")) - source.Reply(ACCESS_DENIED); - else if (u2->IsProtected()) - source.Reply(ACCESS_DENIED); - else if (!c->FindUser(u2)) - source.Reply(NICK_X_NOT_ON_CHAN, u2->nick.c_str(), c->name.c_str()); - else - { - bool override = !u_access.HasPriv("KICK") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << u2->nick; - - if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK"))) - { - signkickformat = signkickformat.replace_all_cs("%m", reason); - c->Kick(ci->WhoSends(), u2, "%s", signkickformat.c_str()); - } - else - c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); - } - } - else if (u_access.HasPriv("FOUNDER")) - { - 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;) - { - ChanUserContainer *uc = it->second; - ++it; - - Entry e("", mask); - if (e.Matches(uc->user)) - { - ++matched; - - AccessGroup u2_access = ci->AccessFor(uc->user); - if (u != uc->user && ci->HasExt("PEACE") && u2_access >= u_access) - continue; - else if (uc->user->IsProtected()) - continue; - - ++kicked; - if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK"))) - { - 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()); - } - } - - if (matched) - 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(), mask.c_str()); - } - else - source.Reply(NICK_X_NOT_IN_USE, target.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Kicks a specified nick from a channel.\n" - " \n" - "By default, limited to AOPs or those with level 5 access\n" - "and above on the channel. Channel founders can also specify masks.")); - return true; - } -}; - -class CSKick : public Module -{ - CommandCSKick commandcskick; - - public: - CSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcskick(this) - { - - } -}; - -MODULE_INIT(CSKick) diff --git a/modules/commands/cs_list.cpp b/modules/commands/cs_list.cpp deleted file mode 100644 index bb2fd854d..000000000 --- a/modules/commands/cs_list.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_mode.h" - -class CommandCSList : public Command -{ - public: - CommandCSList(Module *creator) : Command(creator, "chanserv/list", 1, 2) - { - this->SetDesc(_("Lists all registered channels matching the given pattern")); - this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Anope::string pattern = params[0]; - unsigned nchans; - bool is_servadmin = source.HasCommand("chanserv/list"); - int count = 0, from = 0, to = 0; - bool suspended = false, channoexpire = false; - - if (pattern[0] == '#') - { - Anope::string n1, n2; - sepstream(pattern.substr(1), '-').GetToken(n1, 0); - sepstream(pattern, '-').GetToken(n2, 1); - - try - { - from = convertTo<int>(n1); - to = convertTo<int>(n2); - } - catch (const ConvertException &) - { - source.Reply(LIST_INCORRECT_RANGE); - source.Reply(_("To search for channels starting with #, search for the channel\n" - "name without the #-sign prepended (\002anope\002 instead of \002#anope\002).")); - return; - } - - pattern = "*"; - } - - nchans = 0; - - if (is_servadmin && params.size() > 1) - { - Anope::string keyword; - spacesepstream keywords(params[1]); - while (keywords.GetToken(keyword)) - { - if (keyword.equals_ci("SUSPENDED")) - suspended = true; - if (keyword.equals_ci("NOEXPIRE")) - channoexpire = true; - } - } - - Anope::string spattern = "#" + pattern; - unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50"); - - source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str()); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Name")).AddColumn(_("Description")); - - Anope::map<ChannelInfo *> ordered_map; - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it) - ordered_map[it->first] = it->second; - - for (Anope::map<ChannelInfo *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it) - { - const ChannelInfo *ci = it->second; - - if (!is_servadmin) - { - if (ci->HasExt("CS_PRIVATE") || ci->HasExt("CS_SUSPENDED")) - continue; - if (ci->c && ci->c->HasMode("SECRET")) - continue; - - ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks"); - const ModeLock *secret = ml ? ml->GetMLock("SECRET") : NULL; - if (secret && secret->set) - continue; - } - - if (suspended && !ci->HasExt("CS_SUSPENDED")) - continue; - - if (channoexpire && !ci->HasExt("CS_NO_EXPIRE")) - continue; - - if (pattern.equals_ci(ci->name) || ci->name.equals_ci(spattern) || Anope::Match(ci->name, pattern, false, true) || Anope::Match(ci->name, spattern, false, true) || Anope::Match(ci->desc, pattern, false, true) || Anope::Match(ci->last_topic, pattern, false, true)) - { - if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nchans <= listmax) - { - bool isnoexpire = false; - if (is_servadmin && (ci->HasExt("CS_NO_EXPIRE"))) - isnoexpire = true; - - ListFormatter::ListEntry entry; - entry["Name"] = (isnoexpire ? "!" : "") + ci->name; - if (ci->HasExt("CS_SUSPENDED")) - entry["Description"] = Language::Translate(source.GetAccount(), _("[Suspended]")); - else - entry["Description"] = ci->desc; - list.AddEntry(entry); - } - ++count; - } - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of list - %d/%d matches shown."), nchans > listmax ? listmax : nchans, nchans); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all registered channels matching the given pattern.\n" - "Channels with the \002PRIVATE\002 option set will only be\n" - "displayed to Services Operators with the proper access.\n" - "Channels with the \002NOEXPIRE\002 option set will have\n" - "a \002!\002 prefixed to the channel for Services Operators to see.\n" - " \n" - "Note that a preceding '#' specifies a range, channel names\n" - "are to be written without '#'.\n" - " \n" - "If the SUSPENDED or NOEXPIRE options are given, only channels\n" - "which, respectively, are SUSPENDED or have the NOEXPIRE\n" - "flag set will be displayed. If multiple options are given,\n" - "all channels matching at least one option will be displayed.\n" - "Note that these options are limited to \037Services Operators\037.\n" - " \n" - "Examples:\n" - " \n" - " \002LIST *anope*\002\n" - " Lists all registered channels with \002anope\002 in their\n" - " names (case insensitive).\n" - " \n" - " \002LIST * NOEXPIRE\002\n" - " Lists all registered channels which have been set to not expire.\n" - " \n" - " \002LIST #51-100\002\n" - " Lists all registered channels within the given range (51-100).")); - - if (!Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), Config->GetBlock("options")->Get<const Anope::string>("regexengine").c_str()); - } - - return true; - } -}; - -class CommandCSSetPrivate : public Command -{ - public: - CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Hide channel from the LIST command")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable private"; - ci->Extend<bool>("CS_PRIVATE"); - source.Reply(_("Private option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable private"; - ci->Shrink<bool>("CS_PRIVATE"); - source.Reply(_("Private option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "PRIVATE"); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the \002private\002 option for a channel.")); - - BotInfo *bi; - Anope::string cmd; - if (Command::FindCommandFromService("chanserv/list", bi, cmd)) - source.Reply(_("When \002private\002 is set, the channel will not appear in\n" - "%s's %s command."), bi->nick.c_str(), cmd.c_str()); - return true; - } -}; - -class CSList : public Module -{ - CommandCSList commandcslist; - CommandCSSetPrivate commandcssetprivate; - - SerializableExtensibleItem<bool> priv; - - public: - CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcslist(this), commandcssetprivate(this), priv(this, "CS_PRIVATE") - { - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override - { - if (!show_all) - return; - - if (priv.HasExt(ci)) - info.AddOption(_("Private")); - } -}; - -MODULE_INIT(CSList) diff --git a/modules/commands/cs_log.cpp b/modules/commands/cs_log.cpp deleted file mode 100644 index 8fd996f27..000000000 --- a/modules/commands/cs_log.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_log.h" - -struct LogSettingImpl : LogSetting, Serializable -{ - LogSettingImpl() : Serializable("LogSetting") - { - } - - ~LogSettingImpl() - { - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci) - { - LogSettings *ls = ci->GetExt<LogSettings>("logsettings"); - if (ls) - { - LogSettings::iterator it = std::find((*ls)->begin(), (*ls)->end(), this); - if (it != (*ls)->end()) - (*ls)->erase(it); - } - } - } - - void Serialize(Serialize::Data &data) const anope_override - { - data["ci"] << chan; - data["service_name"] << service_name; - data["command_service"] << command_service; - data["command_name"] << command_name; - data["method"] << method; - data["extra"] << extra; - data["creator"] << creator; - data.SetType("created", Serialize::Data::DT_INT); data["created"] << created; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string sci; - data["ci"] >> sci; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (ci == NULL) - return NULL; - - LogSettingImpl *ls; - if (obj) - ls = anope_dynamic_static_cast<LogSettingImpl *>(obj); - else - { - LogSettings *lsettings = ci->Require<LogSettings>("logsettings"); - ls = new LogSettingImpl(); - (*lsettings)->push_back(ls); - } - - ls->chan = ci->name; - data["service_name"] >> ls->service_name; - data["command_service"] >> ls->command_service; - data["command_name"] >> ls->command_name; - data["method"] >> ls->method; - data["extra"] >> ls->extra; - data["creator"] >> ls->creator; - data["created"] >> ls->created; - - return ls; - } -}; - -struct LogSettingsImpl : LogSettings -{ - LogSettingsImpl(Extensible *) { } - - ~LogSettingsImpl() - { - for (iterator it = (*this)->begin(); it != (*this)->end();) - { - LogSetting *ls = *it; - ++it; - delete ls; - } - } - - LogSetting *Create() anope_override - { - return new LogSettingImpl(); - } -}; - -class CommandCSLog : public Command -{ -public: - CommandCSLog(Module *creator) : Command(creator, "chanserv/log", 1, 4) - { - this->SetDesc(_("Configures channel logging settings")); - this->SetSyntax(_("\037channel\037")); - this->SetSyntax(_("\037channel\037 \037command\037 \037method\037 [\037status\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &channel = params[0]; - - ChannelInfo *ci = ChannelInfo::Find(channel); - if (ci == NULL) - source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); - else if (!source.AccessFor(ci).HasPriv("SET") && !source.HasPriv("chanserv/administration")) - source.Reply(ACCESS_DENIED); - else if (params.size() == 1) - { - LogSettings *ls = ci->Require<LogSettings>("logsettings"); - if (!ls || (*ls)->empty()) - source.Reply(_("There currently are no logging configurations for %s."), ci->name.c_str()); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Service")).AddColumn(_("Command")).AddColumn(_("Method")).AddColumn(""); - - for (unsigned i = 0; i < (*ls)->size(); ++i) - { - const LogSetting *log = (*ls)->at(i); - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Service"] = log->command_service; - entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name; - entry["Method"] = log->method; - entry[""] = log->extra; - list.AddEntry(entry); - } - - source.Reply(_("Log list for %s:"), ci->name.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - else if (params.size() > 2) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - LogSettings *ls = ci->Require<LogSettings>("logsettings"); - const Anope::string &command = params[1]; - const Anope::string &method = params[2]; - const Anope::string &extra = params.size() > 3 ? params[3] : ""; - - size_t sl = command.find('/'); - if (sl == Anope::string::npos) - { - source.Reply(_("%s is not a valid command."), command.c_str()); - return; - } - - Anope::string service = command.substr(0, sl), - command_name = command.substr(sl + 1); - BotInfo *bi = BotInfo::Find(service, true); - - Anope::string service_name; - - /* Allow either a command name or a service name. */ - if (bi && bi->commands.count(command_name)) - { - /* Get service name from command */ - service_name = bi->commands[command_name].name; - } - else if (ServiceReference<Command>("Command", command.lower())) - { - /* This is the service name, don't use any specific command */ - service_name = command; - bi = NULL; - command_name.clear(); - } - else - { - source.Reply(_("%s is not a valid command."), command.c_str()); - return; - } - - if (!method.equals_ci("MESSAGE") && !method.equals_ci("NOTICE") && !method.equals_ci("MEMO")) - { - source.Reply(_("%s is not a valid logging method."), method.c_str()); - return; - } - - for (unsigned i = 0; i < extra.length(); ++i) - if (ModeManager::GetStatusChar(extra[i]) == 0) - { - source.Reply(_("%c is an unknown status mode."), extra[i]); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("SET"); - - for (unsigned i = (*ls)->size(); i > 0; --i) - { - LogSetting *log = (*ls)->at(i - 1); - - if (log->service_name == service_name && log->method.equals_ci(method) && command_name.equals_ci(log->command_name)) - { - if (log->extra == extra) - { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to remove logging for " << command << " with method " << method << (extra == "" ? "" : " ") << extra; - source.Reply(_("Logging for command %s on %s with log method %s%s%s has been removed."), !log->command_name.empty() ? log->command_name.c_str() : log->service_name.c_str(), !log->command_service.empty() ? log->command_service.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str()); - delete log; - } - else - { - log->extra = extra; - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to change logging for " << command << " to method " << method << (extra == "" ? "" : " ") << extra; - source.Reply(_("Logging changed for command %s on %s, now using log method %s%s%s."), !log->command_name.empty() ? log->command_name.c_str() : log->service_name.c_str(), !log->command_service.empty() ? log->command_service.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str()); - } - return; - } - } - - LogSetting *log = new LogSettingImpl(); - log->chan = ci->name; - log->service_name = service_name; - if (bi) - log->command_service = bi->nick; - log->command_name = command_name; - log->method = method; - log->extra = extra; - log->created = Anope::CurTime; - log->creator = source.GetNick(); - - (*ls)->push_back(log); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to log " << command << " with method " << method << (extra == "" ? "" : " ") << extra; - - source.Reply(_("Logging is now active for command %s on %s, using log method %s%s%s."), !command_name.empty() ? command_name.c_str() : service_name.c_str(), bi ? bi->nick.c_str() : "any service", method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str()); - } - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("The %s command allows users to configure logging settings\n" - "for their channel. If no parameters are given this command\n" - "lists the current logging methods in place for this channel.\n" - " \n" - "Otherwise, \037command\037 must be a command name, and \037method\037\n" - "is one of the following logging methods:\n" - " \n" - " MESSAGE [status], NOTICE [status], MEMO\n" - " \n" - "Which are used to message, notice, and memo the channel respectively.\n" - "With MESSAGE or NOTICE you must have a service bot assigned to and joined\n" - "to your channel. Status may be a channel status such as @ or +.\n" - " \n" - "To remove a logging method use the same syntax as you would to add it.\n" - " \n" - "Example:\n" - " %s #anope chanserv/access MESSAGE @\n" - " Would message any channel operators whenever someone used the\n" - " ACCESS command on ChanServ on the channel."), - source.command.upper().c_str(), source.command.upper().c_str()); - return true; - } -}; - -class CSLog : public Module -{ - ServiceReference<MemoServService> MSService; - CommandCSLog commandcslog; - ExtensibleItem<LogSettingsImpl> logsettings; - Serialize::Type logsetting_type; - - struct LogDefault - { - Anope::string service, command, method; - }; - - std::vector<LogDefault> defaults; - - public: - CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - MSService("MemoServService", "MemoServ"), commandcslog(this), - logsettings(this, "logsettings"), logsetting_type("LogSetting", LogSettingImpl::Unserialize) - { - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = conf->GetModule(this); - defaults.clear(); - - for (int i = 0; i < block->CountBlock("default"); ++i) - { - Configuration::Block *def = block->GetBlock("default", i); - - LogDefault ld; - - ld.service = def->Get<const Anope::string>("service"); - ld.command = def->Get<const Anope::string>("command"); - ld.method = def->Get<const Anope::string>("method"); - - defaults.push_back(ld); - } - } - - void OnChanRegistered(ChannelInfo *ci) anope_override - { - if (defaults.empty()) - return; - - LogSettings *ls = logsettings.Require(ci); - for (unsigned i = 0; i < defaults.size(); ++i) - { - LogDefault &d = defaults[i]; - - LogSetting *log = new LogSettingImpl(); - log->chan = ci->name; - - if (!d.service.empty()) - { - log->service_name = d.service.lower() + "/" + d.command.lower(); - log->command_service = d.service; - log->command_name = d.command; - } - else - log->service_name = d.command; - - spacesepstream sep(d.method); - sep.GetToken(log->method); - log->extra = sep.GetRemaining(); - - log->created = Anope::CurTime; - log->creator = ci->GetFounder() ? ci->GetFounder()->display : "(default)"; - - (*ls)->push_back(log); - } - } - - void OnLog(Log *l) anope_override - { - if (l->type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced()) - return; - - LogSettings *ls = logsettings.Get(l->ci); - if (ls) - for (unsigned i = 0; i < (*ls)->size(); ++i) - { - const LogSetting *log = (*ls)->at(i); - - /* wrong command */ - if (log->service_name != l->c->name) - continue; - - /* if a command name is given check the service and the command */ - if (!log->command_name.empty()) - { - /* wrong service (only check if not a fantasy command, though) */ - if (!l->source->c && log->command_service != l->source->service->nick) - continue; - - if (!log->command_name.equals_ci(l->source->command)) - continue; - } - - Anope::string buffer = l->u->nick + " used " + l->source->command.upper() + " " + l->buf.str(); - - if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL) - MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true); - else if (l->source->c) - /* Sending a channel message or notice in response to a fantasy command */; - else if (log->method.equals_ci("MESSAGE") && l->ci->c) - { - IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str()); - l->ci->WhoSends()->lastmsg = Anope::CurTime; - } - else if (log->method.equals_ci("NOTICE") && l->ci->c) - IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str()); - } - } -}; - -MODULE_INIT(CSLog) diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp deleted file mode 100644 index 2acef50f7..000000000 --- a/modules/commands/cs_mode.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_mode.h" - -struct ModeLockImpl : ModeLock, Serializable -{ - ModeLockImpl() : Serializable("ModeLock") - { - } - - ~ModeLockImpl() - { - ChannelInfo *chan = ChannelInfo::Find(ci); - if (chan) - { - ModeLocks *ml = chan->GetExt<ModeLocks>("modelocks"); - if (ml) - ml->RemoveMLock(this); - } - } - - void Serialize(Serialize::Data &data) const anope_override; - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data); -}; - -struct ModeLocksImpl : ModeLocks -{ - Serialize::Reference<ChannelInfo> ci; - Serialize::Checker<ModeList> mlocks; - - ModeLocksImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), mlocks("ModeLock") - { - } - - ~ModeLocksImpl() - { - ModeList modelist; - mlocks->swap(modelist); - for (ModeList::iterator it = modelist.begin(); it != modelist.end(); ++it) - { - ModeLock *ml = *it; - delete ml; - } - } - - bool HasMLock(ChannelMode *mode, const Anope::string ¶m, bool status) const anope_override - { - if (!mode) - return false; - - for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it) - { - const ModeLock *ml = *it; - - if (ml->name == mode->name && ml->set == status && ml->param == param) - return true; - } - - return false; - } - - bool SetMLock(ChannelMode *mode, bool status, const Anope::string ¶m, Anope::string setter, time_t created = Anope::CurTime) anope_override - { - if (!mode) - return false; - - RemoveMLock(mode, status, param); - - if (setter.empty()) - setter = ci->GetFounder() ? ci->GetFounder()->display : "Unknown"; - - ModeLock *ml = new ModeLockImpl(); - ml->ci = ci->name; - ml->set = status; - ml->name = mode->name; - ml->param = param; - ml->setter = setter; - ml->created = created; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnMLock, MOD_RESULT, (this->ci, ml)); - if (MOD_RESULT == EVENT_STOP) - { - delete ml; - return false; - } - - this->mlocks->push_back(ml); - return true; - } - - bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string ¶m = "") anope_override - { - if (!mode) - return false; - - for (ModeList::iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it) - { - ModeLock *m = *it; - - if (m->name == mode->name) - { - // For list or status modes, we must check the parameter - if (mode->type == MODE_LIST || mode->type == MODE_STATUS) - if (m->param != param) - continue; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnUnMLock, MOD_RESULT, (this->ci, m)); - if (MOD_RESULT == EVENT_STOP) - break; - - delete m; - return true; - } - } - - return false; - } - - void RemoveMLock(ModeLock *mlock) anope_override - { - ModeList::iterator it = std::find(this->mlocks->begin(), this->mlocks->end(), mlock); - if (it != this->mlocks->end()) - this->mlocks->erase(it); - } - - void ClearMLock() anope_override - { - ModeList ml; - this->mlocks->swap(ml); - for (unsigned i = 0; i < ml.size(); ++i) - delete ml[i]; - } - - const ModeList &GetMLock() const anope_override - { - return this->mlocks; - } - - std::list<ModeLock *> GetModeLockList(const Anope::string &name) anope_override - { - std::list<ModeLock *> mlist; - for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it) - { - ModeLock *m = *it; - if (m->name == name) - mlist.push_back(m); - } - return mlist; - } - - const ModeLock *GetMLock(const Anope::string &mname, const Anope::string ¶m = "") anope_override - { - for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it) - { - ModeLock *m = *it; - - if (m->name == mname && m->param == param) - return m; - } - - return NULL; - } - - Anope::string GetMLockAsString(bool complete) const anope_override - { - Anope::string pos = "+", neg = "-", params; - - for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it) - { - const ModeLock *ml = *it; - ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name); - - if (!cm || cm->type == MODE_LIST || cm->type == MODE_STATUS) - continue; - - if (ml->set) - pos += cm->mchar; - else - neg += cm->mchar; - - if (complete && ml->set && !ml->param.empty() && cm->type == MODE_PARAM) - params += " " + ml->param; - } - - if (pos.length() == 1) - pos.clear(); - if (neg.length() == 1) - neg.clear(); - - return pos + neg + params; - } - - void Check() anope_override - { - if (this->mlocks->empty()) - ci->Shrink<ModeLocks>("modelocks"); - } -}; - -void ModeLockImpl::Serialize(Serialize::Data &data) const -{ - data["ci"] << this->ci; - data["set"] << this->set; - data["name"] << this->name; - data["param"] << this->param; - data["setter"] << this->setter; - data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created; -} - -Serializable* ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data) -{ - Anope::string sci; - - data["ci"] >> sci; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (!ci) - return NULL; - - ModeLockImpl *ml; - if (obj) - ml = anope_dynamic_static_cast<ModeLockImpl *>(obj); - else - { - ml = new ModeLockImpl(); - ml->ci = ci->name; - } - - data["set"] >> ml->set; - data["created"] >> ml->created; - data["setter"] >> ml->setter; - data["name"] >> ml->name; - data["param"] >> ml->param; - - if (!obj) - ci->Require<ModeLocksImpl>("modelocks")->mlocks->push_back(ml); - - return ml; -} - -class CommandCSMode : public Command -{ - bool CanSet(CommandSource &source, ChannelInfo *ci, ChannelMode *cm, bool self) - { - if (!ci || !cm || cm->type != MODE_STATUS) - return false; - - return source.AccessFor(ci).HasPriv(cm->name + (self ? "ME" : "")); - } - - void DoLock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - User *u = source.GetUser(); - const Anope::string &subcommand = params[2]; - const Anope::string ¶m = params.size() > 3 ? params[3] : ""; - - bool override = !source.AccessFor(ci).HasPriv("MODE"); - ModeLocks *modelocks = ci->Require<ModeLocks>("modelocks"); - - if (Anope::ReadOnly && !subcommand.equals_ci("LIST")) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if ((subcommand.equals_ci("ADD") || subcommand.equals_ci("SET")) && !param.empty()) - { - /* If setting, remove the existing locks */ - if (subcommand.equals_ci("SET")) - { - const ModeLocks::ModeList mlocks = modelocks->GetMLock(); - for (ModeLocks::ModeList::const_iterator it = mlocks.begin(); it != mlocks.end(); ++it) - { - const ModeLock *ml = *it; - ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name); - if (cm && cm->CanSet(source.GetUser())) - modelocks->RemoveMLock(cm, ml->set, ml->param); - } - } - - spacesepstream sep(param); - Anope::string modes; - - sep.GetToken(modes); - - Anope::string pos = "+", neg = "-", pos_params, neg_params; - - int adding = 1; - bool needreply = true; - for (size_t i = 0; i < modes.length(); ++i) - { - switch (modes[i]) - { - case '+': - adding = 1; - break; - case '-': - adding = 0; - break; - default: - needreply = false; - ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); - if (!cm) - { - source.Reply(_("Unknown mode character %c ignored."), modes[i]); - break; - } - else if (u && !cm->CanSet(u)) - { - source.Reply(_("You may not (un)lock mode %c."), modes[i]); - break; - } - - Anope::string mode_param; - if (((cm->type == MODE_STATUS || cm->type == MODE_LIST) && !sep.GetToken(mode_param)) || (cm->type == MODE_PARAM && adding && !sep.GetToken(mode_param))) - source.Reply(_("Missing parameter for mode %c."), cm->mchar); - else if (cm->type == MODE_LIST && ci->c && IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) >= IRCD->GetMaxListFor(ci->c)) - source.Reply(_("List for mode %c is full."), cm->mchar); - else if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32")) - source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str()); - else - { - modelocks->SetMLock(cm, adding, mode_param, source.GetNick()); - - if (adding) - { - pos += cm->mchar; - if (!mode_param.empty()) - pos_params += " " + mode_param; - } - else - { - neg += cm->mchar; - if (!mode_param.empty()) - neg_params += " " + mode_param; - } - } - } - } - - if (pos == "+") - pos.clear(); - if (neg == "-") - neg.clear(); - Anope::string reply = pos + neg + pos_params + neg_params; - - if (!reply.empty()) - { - source.Reply(_("%s locked on %s."), reply.c_str(), ci->name.c_str()); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to lock " << reply; - } - else if (needreply) - source.Reply(_("Nothing to do.")); - - if (ci->c) - ci->c->CheckModes(); - } - else if (subcommand.equals_ci("DEL") && !param.empty()) - { - spacesepstream sep(param); - Anope::string modes; - - sep.GetToken(modes); - - int adding = 1; - bool needreply = true; - for (size_t i = 0; i < modes.length(); ++i) - { - switch (modes[i]) - { - case '+': - adding = 1; - break; - case '-': - adding = 0; - break; - default: - needreply = false; - ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); - if (!cm) - { - source.Reply(_("Unknown mode character %c ignored."), modes[i]); - break; - } - else if (u && !cm->CanSet(u)) - { - source.Reply(_("You may not (un)lock mode %c."), modes[i]); - break; - } - - Anope::string mode_param; - if (cm->type != MODE_REGULAR && !sep.GetToken(mode_param)) - source.Reply(_("Missing parameter for mode %c."), cm->mchar); - else - { - if (modelocks->RemoveMLock(cm, adding, mode_param)) - { - if (!mode_param.empty()) - mode_param = " " + mode_param; - source.Reply(_("%c%c%s has been unlocked from %s."), adding == 1 ? '+' : '-', cm->mchar, mode_param.c_str(), ci->name.c_str()); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to unlock " << (adding ? '+' : '-') << cm->mchar << mode_param; - } - else - source.Reply(_("%c%c is not locked on %s."), adding == 1 ? '+' : '-', cm->mchar, ci->name.c_str()); - } - } - } - - if (needreply) - source.Reply(_("Nothing to do.")); - } - else if (subcommand.equals_ci("LIST")) - { - const ModeLocks::ModeList mlocks = modelocks->GetMLock(); - if (mlocks.empty()) - { - source.Reply(_("Channel %s has no mode locks."), ci->name.c_str()); - } - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Mode")).AddColumn(_("Param")).AddColumn(_("Creator")).AddColumn(_("Created")); - - for (ModeLocks::ModeList::const_iterator it = mlocks.begin(), it_end = mlocks.end(); it != it_end; ++it) - { - const ModeLock *ml = *it; - ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name); - if (!cm) - continue; - - ListFormatter::ListEntry entry; - entry["Mode"] = Anope::printf("%c%c", ml->set ? '+' : '-', cm->mchar); - entry["Param"] = ml->param; - entry["Creator"] = ml->setter; - entry["Created"] = Anope::strftime(ml->created, NULL, true); - list.AddEntry(entry); - } - - source.Reply(_("Mode locks for %s:"), ci->name.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - else - this->OnSyntaxError(source, subcommand); - } - - void DoSet(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - User *u = source.GetUser(); - - bool has_access = source.AccessFor(ci).HasPriv("MODE") || source.HasPriv("chanserv/administration"); - bool can_override = source.HasPriv("chanserv/administration"); - - spacesepstream sep(params.size() > 3 ? params[3] : ""); - Anope::string modes = params[2], param; - - bool override = !source.AccessFor(ci).HasPriv("MODE") && source.HasPriv("chanserv/administration"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to set " << params[2] << (params.size() > 3 ? " " + params[3] : ""); - - int adding = -1; - for (size_t i = 0; i < modes.length(); ++i) - { - switch (modes[i]) - { - case '+': - adding = 1; - break; - case '-': - adding = 0; - break; - case '*': - if (adding == -1 || !has_access) - break; - for (unsigned j = 0; j < ModeManager::GetChannelModes().size() && ci->c; ++j) - { - ChannelMode *cm = ModeManager::GetChannelModes()[j]; - - if (!u || cm->CanSet(u) || can_override) - { - if (cm->type == MODE_REGULAR || (!adding && cm->type == MODE_PARAM)) - { - if (adding) - ci->c->SetMode(NULL, cm); - else - ci->c->RemoveMode(NULL, cm); - } - } - } - break; - default: - if (adding == -1) - break; - ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); - if (!cm || (u && !cm->CanSet(u) && !can_override)) - continue; - switch (cm->type) - { - case MODE_REGULAR: - if (!has_access) - break; - if (adding) - ci->c->SetMode(NULL, cm); - else - ci->c->RemoveMode(NULL, cm); - break; - case MODE_PARAM: - if (!has_access) - break; - if (adding && !sep.GetToken(param)) - break; - if (adding) - ci->c->SetMode(NULL, cm, param); - else - ci->c->RemoveMode(NULL, cm); - break; - case MODE_STATUS: - { - if (!sep.GetToken(param)) - param = source.GetNick(); - - AccessGroup u_access = source.AccessFor(ci); - - if (param.find_first_of("*?") != Anope::string::npos) - { - if (!this->CanSet(source, ci, cm, false) && !can_override) - { - source.Reply(_("You do not have access to set mode %c."), cm->mchar); - break; - } - - for (Channel::ChanUserList::const_iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end;) - { - ChanUserContainer *uc = it->second; - ++it; - - AccessGroup targ_access = ci->AccessFor(uc->user); - - if (uc->user->IsProtected() || (ci->HasExt("PEACE") && targ_access >= u_access && !can_override)) - { - source.Reply(_("You do not have the access to change %s's modes."), uc->user->nick.c_str()); - continue; - } - - if (Anope::Match(uc->user->GetMask(), param)) - { - if (adding) - ci->c->SetMode(NULL, cm, uc->user->GetUID()); - else - ci->c->RemoveMode(NULL, cm, uc->user->GetUID()); - } - } - } - else - { - User *target = User::Find(param, true); - if (target == NULL) - { - source.Reply(NICK_X_NOT_IN_USE, param.c_str()); - break; - } - - if (!this->CanSet(source, ci, cm, source.GetUser() == target) && !can_override) - { - source.Reply(_("You do not have access to set mode %c."), cm->mchar); - break; - } - - if (source.GetUser() != target) - { - AccessGroup targ_access = ci->AccessFor(target); - if (ci->HasExt("PEACE") && targ_access >= u_access && !can_override) - { - source.Reply(_("You do not have the access to change %s's modes."), target->nick.c_str()); - break; - } - else if (target->IsProtected()) - { - source.Reply(ACCESS_DENIED); - break; - } - } - - if (adding) - ci->c->SetMode(NULL, cm, target->GetUID()); - else - ci->c->RemoveMode(NULL, cm, target->GetUID()); - } - break; - } - case MODE_LIST: - if (!has_access) - break; - if (!sep.GetToken(param)) - break; - if (adding) - { - if (IRCD->GetMaxListFor(ci->c) && ci->c->HasMode(cm->name) < IRCD->GetMaxListFor(ci->c)) - ci->c->SetMode(NULL, cm, param); - } - else - { - std::vector<Anope::string> v = ci->c->GetModeList(cm->name); - for (unsigned j = 0; j < v.size(); ++j) - if (Anope::Match(v[j], param)) - ci->c->RemoveMode(NULL, cm, v[j]); - } - } - } - } - } - - void DoClear(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string ¶m = params.size() > 2 ? params[2] : ""; - - if (param.empty()) - { - std::vector<Anope::string> new_params; - new_params.push_back(params[0]); - new_params.push_back("SET"); - new_params.push_back("-*"); - this->DoSet(source, ci, new_params); - return; - } - - ChannelMode *cm; - if (param.length() == 1) - cm = ModeManager::FindChannelModeByChar(param[0]); - else - { - cm = ModeManager::FindChannelModeByName(param.upper()); - if (!cm) - cm = ModeManager::FindChannelModeByName(param.substr(0, param.length() - 1).upper()); - } - - if (!cm) - { - source.Reply(_("There is no such mode %s."), param.c_str()); - return; - } - - if (cm->type != MODE_STATUS && cm->type != MODE_LIST) - { - source.Reply(_("Mode %s is not a status or list mode."), param.c_str()); - return; - } - - std::vector<Anope::string> new_params; - new_params.push_back(params[0]); - new_params.push_back("SET"); - new_params.push_back("-" + stringify(cm->mchar)); - new_params.push_back("*"); - this->DoSet(source, ci, new_params); - } - - public: - CommandCSMode(Module *creator) : Command(creator, "chanserv/mode", 2, 4) - { - this->SetDesc(_("Control modes and mode locks on a channel")); - this->SetSyntax(_("\037channel\037 LOCK {ADD|DEL|SET|LIST} [\037what\037]")); - this->SetSyntax(_("\037channel\037 SET \037modes\037")); - this->SetSyntax(_("\037channel\037 CLEAR [\037what\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &subcommand = params[1]; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - - if (!ci) - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - else if (subcommand.equals_ci("LOCK") && params.size() > 2) - { - if (!source.AccessFor(ci).HasPriv("MODE") && !source.HasPriv("chanserv/administration")) - source.Reply(ACCESS_DENIED); - else - this->DoLock(source, ci, params); - } - else if (!ci->c) - source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); - else if (subcommand.equals_ci("SET") && params.size() > 2) - this->DoSet(source, ci, params); - else if (subcommand.equals_ci("CLEAR")) - { - if (!source.AccessFor(ci).HasPriv("MODE") && !source.HasPriv("chanserv/administration")) - source.Reply(ACCESS_DENIED); - else - this->DoClear(source, ci, params); - } - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Mainly controls mode locks and mode access (which is different from channel access)\n" - "on a channel.\n" - " \n" - "The \002%s LOCK\002 command allows you to add, delete, and view mode locks on a channel.\n" - "If a mode is locked on or off, services will not allow that mode to be changed. The \002SET\002\n" - "command will clear all existing mode locks and set the new one given, while \002ADD\002 and \002DEL\002\n" - "modify the existing mode lock.\n" - "Example:\n" - " \002MODE #channel LOCK ADD +bmnt *!*@*aol*\002\n" - " \n" - "The \002%s SET\002 command allows you to set modes through services. Wildcards * and ? may\n" - "be given as parameters for list and status modes.\n" - "Example:\n" - " \002MODE #channel SET +v *\002\n" - " Sets voice status to all users in the channel.\n" - " \n" - " \002MODE #channel SET -b ~c:*\n" - " Clears all extended bans that start with ~c:\n" - " \n" - "The \002%s CLEAR\002 command is an easy way to clear modes on a channel. \037what\037 may be\n" - "any mode name. Examples include bans, excepts, inviteoverrides, ops, halfops, and voices. If \037what\037\n" - "is not given then all basic modes are removed."), - source.command.upper().c_str(), source.command.upper().c_str(), source.command.upper().c_str()); - return true; - } -}; - -static Anope::map<std::pair<bool, Anope::string> > modes; - -class CommandCSModes : public Command -{ - public: - CommandCSModes(Module *creator) : Command(creator, "chanserv/modes", 1, 2) - { - this->SetSyntax(_("\037channel\037 [\037user\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(), - *targ = params.size() > 1 ? User::Find(params[1], true) : u; - ChannelInfo *ci = ChannelInfo::Find(params[0]); - - if (!targ) - { - if (params.size() > 1) - source.Reply(NICK_X_NOT_IN_USE, params[1].c_str()); - return; - } - - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - else if (!ci->c) - { - source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - return; - } - - AccessGroup u_access = source.AccessFor(ci), targ_access = ci->AccessFor(targ); - const std::pair<bool, Anope::string> &m = modes[source.command]; - - bool can_override = source.HasPriv("chanserv/administration"); - bool override = false; - - if (m.second.empty()) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (u == targ ? !u_access.HasPriv(m.second + "ME") : !u_access.HasPriv(m.second)) - { - if (!can_override) - { - source.Reply(ACCESS_DENIED); - return; - } - else - override = true; - } - - if (!override && !m.first && u != targ && (targ->IsProtected() || (ci->HasExt("PEACE") && targ_access >= u_access))) - { - if (!can_override) - { - source.Reply(ACCESS_DENIED); - return; - } - else - override = true; - } - - if (!ci->c->FindUser(targ)) - { - source.Reply(NICK_X_NOT_ON_CHAN, targ->nick.c_str(), ci->name.c_str()); - return; - } - - if (m.first) - ci->c->SetMode(NULL, m.second, targ->GetUID()); - else - ci->c->RemoveMode(NULL, m.second, targ->GetUID()); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "on " << targ->nick; - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - const std::pair<bool, Anope::string> &m = modes[source.command]; - if (!m.second.empty()) - { - if (m.first) - return Anope::printf(Language::Translate(source.GetAccount(), _("Gives you or the specified nick %s status on a channel")), m.second.c_str()); - else - return Anope::printf(Language::Translate(source.GetAccount(), _("Removes %s status from you or the specified nick on a channel")), m.second.c_str()); - } - else - return ""; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - const std::pair<bool, Anope::string> &m = modes[source.command]; - if (m.second.empty()) - return false; - - this->SendSyntax(source); - source.Reply(" "); - if (m.first) - source.Reply(_("Gives %s status to the selected nick on a channel. If \037nick\037 is\n" - "not given, it will %s you."), - m.second.upper().c_str(), m.second.lower().c_str()); - else - source.Reply(_("Removes %s status from the selected nick on a channel. If \037nick\037 is\n" - "not given, it will de%s you."), - m.second.upper().c_str(), m.second.lower().c_str()); - source.Reply(" "); - source.Reply(_("You must have the %s(ME) privilege on the channel to use this command."), m.second.upper().c_str()); - - return true; - } -}; - -class CSMode : public Module -{ - CommandCSMode commandcsmode; - CommandCSModes commandcsmodes; - ExtensibleItem<ModeLocksImpl> modelocks; - Serialize::Type modelocks_type; - - public: - CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsmode(this), commandcsmodes(this), - modelocks(this, "modelocks"), - modelocks_type("ModeLock", ModeLockImpl::Unserialize) - { - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - modes.clear(); - - for (int i = 0; i < conf->CountBlock("command"); ++i) - { - Configuration::Block *block = conf->GetBlock("command", i); - - const Anope::string &cname = block->Get<const Anope::string>("name"), - &cmd = block->Get<const Anope::string>("command"); - - if (cname.empty() || cmd != "chanserv/modes") - continue; - - const Anope::string &set = block->Get<const Anope::string>("set"), - &unset = block->Get<const Anope::string>("unset"); - - if (set.empty() && unset.empty()) - continue; - - modes[cname] = std::make_pair(!set.empty(), !set.empty() ? set : unset); - } - } - - void OnCheckModes(Reference<Channel> &c) anope_override - { - if (!c || !c->ci) - return; - - ModeLocks *locks = modelocks.Get(c->ci); - if (locks) - for (ModeLocks::ModeList::const_iterator it = locks->GetMLock().begin(), it_end = locks->GetMLock().end(); it != it_end; ++it) - { - const ModeLock *ml = *it; - ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name); - if (!cm) - continue; - - if (cm->type == MODE_REGULAR) - { - if (!c->HasMode(cm->name) && ml->set) - c->SetMode(NULL, cm, "", false); - else if (c->HasMode(cm->name) && !ml->set) - c->RemoveMode(NULL, cm, "", false); - } - else if (cm->type == MODE_PARAM) - { - /* If the channel doesn't have the mode, or it does and it isn't set correctly */ - if (ml->set) - { - Anope::string param; - c->GetParam(cm->name, param); - - if (!c->HasMode(cm->name) || (!param.empty() && !ml->param.empty() && !param.equals_cs(ml->param))) - c->SetMode(NULL, cm, ml->param, false); - } - else - { - if (c->HasMode(cm->name)) - c->RemoveMode(NULL, cm, "", false); - } - - } - else if (cm->type == MODE_LIST || cm->type == MODE_STATUS) - { - if (ml->set) - c->SetMode(NULL, cm, ml->param, false); - else - c->RemoveMode(NULL, cm, ml->param, false); - } - } - } - - void OnChanRegistered(ChannelInfo *ci) anope_override - { - ModeLocks *ml = modelocks.Require(ci); - Anope::string mlock; - spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("mlock", "+nt")); - if (sep.GetToken(mlock)) - { - bool add = true; - for (unsigned i = 0; i < mlock.length(); ++i) - { - if (mlock[i] == '+') - { - add = true; - continue; - } - - if (mlock[i] == '-') - { - add = false; - continue; - } - - ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock[i]); - if (!cm) - continue; - - Anope::string param; - if (cm->type == MODE_PARAM) - { - ChannelModeParam *cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); - if (add || !cmp->minus_no_arg) - { - sep.GetToken(param); - if (param.empty() || !cmp->IsValid(param)) - continue; - } - } - else if (cm->type != MODE_REGULAR) - { - sep.GetToken(param); - if (param.empty()) - continue; - } - - ml->SetMLock(cm, add, param); - } - } - ml->Check(); - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override - { - if (!show_hidden) - return; - - ModeLocks *ml = modelocks.Get(ci); - if (ml) - info[_("Mode lock")] = ml->GetMLockAsString(true); - } -}; - -MODULE_INIT(CSMode) diff --git a/modules/commands/cs_register.cpp b/modules/commands/cs_register.cpp deleted file mode 100644 index 8b73c9f06..000000000 --- a/modules/commands/cs_register.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSRegister : public Command -{ - public: - CommandCSRegister(Module *creator) : Command(creator, "chanserv/register", 1, 2) - { - this->SetDesc(_("Register a channel")); - this->SetSyntax(_("\037channel\037 [\037description\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &chdesc = params.size() > 1 ? params[1] : ""; - unsigned maxregistered = Config->GetModule("chanserv")->Get<unsigned>("maxregistered"); - - User *u = source.GetUser(); - NickCore *nc = source.nc; - Channel *c = Channel::Find(params[0]); - ChannelInfo *ci = ChannelInfo::Find(params[0]); - - if (Anope::ReadOnly) - source.Reply(_("Sorry, channel registration is temporarily disabled.")); - else if (nc->HasExt("UNCONFIRMED")) - source.Reply(_("You must confirm your account before you can register a channel.")); - else if (chan[0] == '&') - source.Reply(_("Local channels cannot be registered.")); - else if (chan[0] != '#') - source.Reply(CHAN_SYMBOL_REQUIRED); - else if (!IRCD->IsChannelValid(chan)) - source.Reply(CHAN_X_INVALID, chan.c_str()); - else if (!c && u) - source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); - else if (ci) - source.Reply(_("Channel \002%s\002 is already registered!"), chan.c_str()); - else if (c && u && !c->HasUserStatus(u, "OP")) - source.Reply(_("You must be a channel operator to register the channel.")); - else if (maxregistered && nc->channelcount >= maxregistered && !source.HasPriv("chanserv/no-register-limit")) - source.Reply(nc->channelcount > maxregistered ? CHAN_EXCEEDED_CHANNEL_LIMIT : CHAN_REACHED_CHANNEL_LIMIT, maxregistered); - else - { - ci = new ChannelInfo(chan); - ci->SetFounder(nc); - ci->desc = chdesc; - - if (c && !c->topic.empty()) - { - ci->last_topic = c->topic; - ci->last_topic_setter = c->topic_setter; - ci->last_topic_time = c->topic_time; - } - else - ci->last_topic_setter = source.service->nick; - - Log(LOG_COMMAND, source, this, ci); - source.Reply(_("Channel \002%s\002 registered under your account: %s"), chan.c_str(), nc->display.c_str()); - - FOREACH_MOD(OnChanRegistered, (ci)); - - /* Implement new mode lock */ - if (c) - { - c->CheckModes(); - if (u) - c->SetCorrectModes(u, true); - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Registers a channel in the %s database. In order\n" - "to use this command, you must first be a channel operator\n" - "on the channel you're trying to register.\n" - "The description, which is optional, is a\n" - "general description of the channel's purpose.\n" - " \n" - "When you register a channel, you are recorded as the\n" - "\"founder\" of the channel. The channel founder is allowed\n" - "to change all of the channel settings for the channel;\n" - "%s will also automatically give the founder\n" - "channel-operator privileges when s/he enters the channel."), - source.service->nick.c_str(), source.service->nick.c_str()); - BotInfo *bi; - Anope::string cmd; - if (Command::FindCommandFromService("chanserv/access", bi, cmd)) - source.Reply(_(" \n" - "See the \002%s\002 command (\002%s%s HELP ACCESS\002) for\n" - "information on giving a subset of these privileges to\n" - "other channel users.\n"), cmd.c_str(), Config->StrictPrivmsg.c_str(), bi->nick.c_str()); - source.Reply(_(" \n" - "NOTICE: In order to register a channel, you must have\n" - "first registered your nickname.")); - return true; - } -}; - - -class CSRegister : public Module -{ - CommandCSRegister commandcsregister; - - public: - CSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsregister(this) - { - } -}; - -MODULE_INIT(CSRegister) diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp deleted file mode 100644 index 80bc8e548..000000000 --- a/modules/commands/cs_seen.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/* cs_seen: provides a seen command by tracking all users - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -enum TypeInfo -{ - NEW, NICK_TO, NICK_FROM, JOIN, PART, QUIT, KICK -}; - -static bool simple; -struct SeenInfo; -static SeenInfo *FindInfo(const Anope::string &nick); -typedef Anope::hash_map<SeenInfo *> database_map; -database_map database; - -struct SeenInfo : Serializable -{ - Anope::string nick; - Anope::string vhost; - TypeInfo type; - Anope::string nick2; // for nickchanges and kicks - Anope::string channel; // for join/part/kick - Anope::string message; // for part/kick/quit - time_t last; // the time when the user was last seen - - SeenInfo() : Serializable("SeenInfo") - { - } - - ~SeenInfo() - { - database_map::iterator iter = database.find(nick); - if (iter != database.end() && iter->second == this) - database.erase(iter); - } - - void Serialize(Serialize::Data &data) const anope_override - { - data["nick"] << nick; - data["vhost"] << vhost; - data["type"] << type; - data["nick2"] << nick2; - data["channel"] << channel; - data["message"] << message; - data.SetType("last", Serialize::Data::DT_INT); data["last"] << last; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string snick; - - data["nick"] >> snick; - - SeenInfo *s; - if (obj) - s = anope_dynamic_static_cast<SeenInfo *>(obj); - else - { - SeenInfo* &info = database[snick]; - if (!info) - info = new SeenInfo(); - s = info; - } - - s->nick = snick; - data["vhost"] >> s->vhost; - unsigned int n; - data["type"] >> n; - s->type = static_cast<TypeInfo>(n); - data["nick2"] >> s->nick2; - data["channel"] >> s->channel; - data["message"] >> s->message; - data["last"] >> s->last; - - if (!obj) - database[s->nick] = s; - return s; - } -}; - -static SeenInfo *FindInfo(const Anope::string &nick) -{ - database_map::iterator iter = database.find(nick); - if (iter != database.end()) - return iter->second; - return NULL; -} - -static bool ShouldHide(const Anope::string &channel, User *u) -{ - Channel *targetchan = Channel::Find(channel); - const ChannelInfo *targetchan_ci = targetchan ? *targetchan->ci : ChannelInfo::Find(channel); - - if (targetchan && targetchan->HasMode("SECRET")) - return true; - else if (targetchan_ci && targetchan_ci->HasExt("CS_PRIVATE")) - return true; - else if (u && u->HasMode("PRIV")) - return true; - return false; -} - -class CommandOSSeen : public Command -{ - public: - CommandOSSeen(Module *creator) : Command(creator, "operserv/seen", 1, 2) - { - this->SetDesc(_("Statistics and maintenance for seen data")); - this->SetSyntax("STATS"); - this->SetSyntax(_("CLEAR \037time\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params[0].equals_ci("STATS")) - { - size_t mem_counter; - mem_counter = sizeof(database_map); - for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end; ++it) - { - mem_counter += (5 * sizeof(Anope::string)) + sizeof(TypeInfo) + sizeof(time_t); - mem_counter += it->first.capacity(); - mem_counter += it->second->vhost.capacity(); - mem_counter += it->second->nick2.capacity(); - mem_counter += it->second->channel.capacity(); - mem_counter += it->second->message.capacity(); - } - source.Reply(_("%lu nicks are stored in the database, using %.2Lf kB of memory."), database.size(), static_cast<long double>(mem_counter) / 1024); - } - else if (params[0].equals_ci("CLEAR")) - { - time_t time = 0; - if ((params.size() < 2) || (0 >= (time = Anope::DoTime(params[1])))) - { - this->OnSyntaxError(source, params[0]); - return; - } - time = Anope::CurTime - time; - database_map::iterator buf; - size_t counter = 0; - for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end;) - { - buf = it; - ++it; - if (time < buf->second->last) - { - Log(LOG_DEBUG) << buf->first << " was last seen " << Anope::strftime(buf->second->last) << ", deleting entry"; - delete buf->second; - counter++; - } - } - Log(LOG_ADMIN, source, this) << "CLEAR and removed " << counter << " nicks that were added after " << Anope::strftime(time, NULL, true); - source.Reply(_("Database cleared, removed %lu nicks that were added after %s."), counter, Anope::strftime(time, source.nc, true).c_str()); - } - else - this->SendSyntax(source); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("The \002STATS\002 command prints out statistics about stored nicks and memory usage.")); - source.Reply(_("The \002CLEAR\002 command lets you clean the database by removing all entries from the\n" - "database that were added within \037time\037.\n" - " \n" - "Example:\n" - " %s CLEAR 30m\n" - " Will remove all entries that were added within the last 30 minutes."), source.command.c_str()); - return true; - } -}; - -class CommandSeen : public Command -{ - void SimpleSeen(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (!source.c || !source.c->ci) - { - if (source.IsOper()) - source.Reply("Seen in simple mode is designed as a fantasy command only!"); - return; - } - - BotInfo *bi = BotInfo::Find(params[0], true); - if (bi) - { - if (bi == source.c->ci->bi) - source.Reply(_("You found me, %s!"), source.GetNick().c_str()); - else - source.Reply(_("%s is a network service."), bi->nick.c_str()); - return; - } - - NickAlias *na = NickAlias::Find(params[0]); - if (!na) - { - source.Reply(_("I don't know who %s is."), params[0].c_str()); - return; - } - - if (source.GetAccount() == na->nc) - { - source.Reply(_("Looking for yourself, eh %s?"), source.GetNick().c_str()); - return; - } - - User *target = User::Find(params[0], true); - - if (target && source.c->FindUser(target)) - { - source.Reply(_("%s is on the channel right now!"), target->nick.c_str()); - return; - } - - for (Channel::ChanUserList::const_iterator it = source.c->users.begin(), it_end = source.c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *u = uc->user; - - if (u->Account() == na->nc) - { - source.Reply(_("%s is on the channel right now (as %s)!"), params[0].c_str(), u->nick.c_str()); - return; - } - } - - AccessGroup ag = source.c->ci->AccessFor(na->nc); - time_t last = 0; - for (unsigned int i = 0; i < ag.paths.size(); ++i) - { - ChanAccess::Path &p = ag.paths[i]; - - if (p.empty()) - continue; - - ChanAccess *a = p[p.size() - 1]; - - if (a->GetAccount() == na->nc && a->last_seen > last) - last = a->last_seen; - } - - if (last > Anope::CurTime || !last) - source.Reply(_("I've never seen %s on this channel."), na->nick.c_str()); - else - source.Reply(_("%s was last seen here %s ago."), na->nick.c_str(), Anope::Duration(Anope::CurTime - last, source.GetAccount()).c_str()); - } - - public: - CommandSeen(Module *creator) : Command(creator, "chanserv/seen", 1, 2) - { - this->SetDesc(_("Tells you about the last time a user was seen")); - this->SetSyntax(_("\037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &target = params[0]; - - if (simple) - return this->SimpleSeen(source, params); - - if (target.length() > Config->GetBlock("networkinfo")->Get<unsigned>("nicklen")) - { - source.Reply(_("Nick too long, max length is %u characters."), Config->GetBlock("networkinfo")->Get<unsigned>("nicklen")); - return; - } - - if (BotInfo::Find(target, true) != NULL) - { - source.Reply(_("%s is a client on services."), target.c_str()); - return; - } - - if (target.equals_ci(source.GetNick())) - { - source.Reply(_("You might see yourself in the mirror, %s."), source.GetNick().c_str()); - return; - } - - SeenInfo *info = FindInfo(target); - if (!info) - { - source.Reply(_("Sorry, I have not seen %s."), target.c_str()); - return; - } - - User *u2 = User::Find(target, true); - Anope::string onlinestatus; - if (u2) - onlinestatus = "."; - else - onlinestatus = Anope::printf(_(" but %s mysteriously dematerialized."), target.c_str()); - - Anope::string timebuf = Anope::Duration(Anope::CurTime - info->last, source.nc); - Anope::string timebuf2 = Anope::strftime(info->last, source.nc, true); - - if (info->type == NEW) - { - source.Reply(_("%s (%s) was last seen connecting %s ago (%s)%s"), - target.c_str(), info->vhost.c_str(), timebuf.c_str(), timebuf2.c_str(), onlinestatus.c_str()); - } - else if (info->type == NICK_TO) - { - u2 = User::Find(info->nick2, true); - if (u2) - onlinestatus = Anope::printf( _(". %s is still online."), u2->nick.c_str()); - else - onlinestatus = Anope::printf(_(", but %s mysteriously dematerialized."), info->nick2.c_str()); - - source.Reply(_("%s (%s) was last seen changing nick to %s %s ago%s"), - target.c_str(), info->vhost.c_str(), info->nick2.c_str(), timebuf.c_str(), onlinestatus.c_str()); - } - else if (info->type == NICK_FROM) - { - source.Reply(_("%s (%s) was last seen changing nick from %s to %s %s ago%s"), - target.c_str(), info->vhost.c_str(), info->nick2.c_str(), target.c_str(), timebuf.c_str(), onlinestatus.c_str()); - } - else if (info->type == JOIN) - { - if (ShouldHide(info->channel, u2)) - source.Reply(_("%s (%s) was last seen joining a secret channel %s ago%s"), - target.c_str(), info->vhost.c_str(), timebuf.c_str(), onlinestatus.c_str()); - else - source.Reply(_("%s (%s) was last seen joining %s %s ago%s"), - target.c_str(), info->vhost.c_str(), info->channel.c_str(), timebuf.c_str(), onlinestatus.c_str()); - } - else if (info->type == PART) - { - if (ShouldHide(info->channel, u2)) - source.Reply(_("%s (%s) was last seen parting a secret channel %s ago%s"), - target.c_str(), info->vhost.c_str(), timebuf.c_str(), onlinestatus.c_str()); - else - source.Reply(_("%s (%s) was last seen parting %s %s ago%s"), - target.c_str(), info->vhost.c_str(), info->channel.c_str(), timebuf.c_str(), onlinestatus.c_str()); - } - else if (info->type == QUIT) - { - source.Reply(_("%s (%s) was last seen quitting (%s) %s ago (%s)."), - target.c_str(), info->vhost.c_str(), info->message.c_str(), timebuf.c_str(), timebuf2.c_str()); - } - else if (info->type == KICK) - { - if (ShouldHide(info->channel, u2)) - source.Reply(_("%s (%s) was kicked from a secret channel %s ago%s"), - target.c_str(), info->vhost.c_str(), timebuf.c_str(), onlinestatus.c_str()); - else - source.Reply(_("%s (%s) was kicked from %s (\"%s\") %s ago%s"), - target.c_str(), info->vhost.c_str(), info->channel.c_str(), info->message.c_str(), timebuf.c_str(), onlinestatus.c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Checks for the last time \037nick\037 was seen joining, leaving,\n" - "or changing nick on the network and tells you when and, depending\n" - "on channel or user settings, where it was.")); - return true; - } -}; - -class CSSeen : public Module -{ - Serialize::Type seeninfo_type; - CommandSeen commandseen; - CommandOSSeen commandosseen; - public: - CSSeen(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), seeninfo_type("SeenInfo", SeenInfo::Unserialize), commandseen(this), commandosseen(this) - { - } - - void OnReload(Configuration::Conf *conf) anope_override - { - simple = conf->GetModule(this)->Get<bool>("simple"); - } - - void OnExpireTick() anope_override - { - size_t previous_size = database.size(); - time_t purgetime = Config->GetModule(this)->Get<time_t>("purgetime"); - if (!purgetime) - purgetime = Anope::DoTime("30d"); - for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end;) - { - database_map::iterator cur = it; - ++it; - - if ((Anope::CurTime - cur->second->last) > purgetime) - { - Log(LOG_DEBUG) << cur->first << " was last seen " << Anope::strftime(cur->second->last) << ", purging entries"; - delete cur->second; - } - } - Log(LOG_DEBUG) << "cs_seen: Purged database, checked " << previous_size << " nicks and removed " << (previous_size - database.size()) << " old entries."; - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (!u->Quitting()) - UpdateUser(u, NEW, u->nick, "", "", ""); - } - - void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override - { - UpdateUser(u, NICK_TO, oldnick, u->nick, "", ""); - UpdateUser(u, NICK_FROM, u->nick, oldnick, "", ""); - } - - void OnUserQuit(User *u, const Anope::string &msg) anope_override - { - UpdateUser(u, QUIT, u->nick, "", "", msg); - } - - void OnJoinChannel(User *u, Channel *c) anope_override - { - UpdateUser(u, JOIN, u->nick, "", c->name, ""); - } - - void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) anope_override - { - UpdateUser(u, PART, u->nick, "", channel, msg); - } - - void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &msg) anope_override - { - UpdateUser(cu->user, KICK, cu->user->nick, source.GetSource(), cu->chan->name, msg); - } - - private: - void UpdateUser(const User *u, const TypeInfo Type, const Anope::string &nick, const Anope::string &nick2, const Anope::string &channel, const Anope::string &message) - { - if (simple || !u->server->IsSynced()) - return; - - SeenInfo* &info = database[nick]; - if (!info) - info = new SeenInfo(); - info->nick = nick; - info->vhost = u->GetVIdent() + "@" + u->GetDisplayedHost(); - info->type = Type; - info->last = Anope::CurTime; - info->nick2 = nick2; - info->channel = channel; - info->message = message; - } -}; - -MODULE_INIT(CSSeen) diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp deleted file mode 100644 index fb58f9efd..000000000 --- a/modules/commands/cs_set.cpp +++ /dev/null @@ -1,1356 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_mode.h" - -class CommandCSSet : public Command -{ - public: - CommandCSSet(Module *creator) : Command(creator, "chanserv/set", 2, 3) - { - this->SetDesc(_("Set channel options and information")); - this->SetSyntax(_("\037option\037 \037channel\037 \037parameters\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows the channel founder to set various channel options\n" - "and other information.\n" - " \n" - "Available options:")); - Anope::string this_name = source.command; - bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), - hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); - for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - if (c_name.find_ci(this_name + " ") == 0) - { - ServiceReference<Command> c("Command", info.name); - - // XXX dup - if (!c) - continue; - else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) - continue; - else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) - continue; - - source.command = it->first; - c->OnServHelp(source); - } - } - source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information on a\n" - "particular option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); - return true; - } -}; - -class CommandCSSetAutoOp : public Command -{ - public: - CommandCSSetAutoOp(Module *creator, const Anope::string &cname = "chanserv/set/autoop") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Should services automatically give status to users")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable autoop"; - ci->Shrink<bool>("NOAUTOOP"); - source.Reply(_("Services will now automatically give modes to users in \002%s\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable autoop"; - ci->Extend<bool>("NOAUTOOP"); - source.Reply(_("Services will no longer automatically give modes to users in \002%s\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "AUTOOP"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables %s's autoop feature for a\n" - "channel. When disabled, users who join the channel will\n" - "not automatically gain any status from %s."), source.service->nick.c_str(), - source.service->nick.c_str(), this->name.c_str()); - return true; - } -}; - -class CommandCSSetBanType : public Command -{ - public: - CommandCSSetBanType(Module *creator, const Anope::string &cname = "chanserv/set/bantype") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Set how Services make bans on the channel")); - this->SetSyntax(_("\037channel\037 \037bantype\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - try - { - int16_t new_type = convertTo<int16_t>(params[1]); - if (new_type < 0 || new_type > 3) - throw ConvertException("Invalid range"); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type; - ci->bantype = new_type; - source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype); - } - catch (const ConvertException &) - { - source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the ban type that will be used by services whenever\n" - "they need to ban someone from your channel.\n" - " \n" - "Bantype is a number between 0 and 3 that means:\n" - " \n" - "0: ban in the form *!user@host\n" - "1: ban in the form *!*user@host\n" - "2: ban in the form *!*@host\n" - "3: ban in the form *!*user@*.domain"), this->name.c_str()); - return true; - } -}; - -class CommandCSSetDescription : public Command -{ - public: - CommandCSSetDescription(Module *creator, const Anope::string &cname = "chanserv/set/description") : Command(creator, cname, 1, 2) - { - this->SetDesc(_("Set the channel description")); - this->SetSyntax(_("\037channel\037 [\037description\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - const Anope::string ¶m = params.size() > 1 ? params[1] : ""; - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (!param.empty()) - { - ci->desc = param; - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the description to " << ci->desc; - source.Reply(_("Description of %s changed to \002%s\002."), ci->name.c_str(), ci->desc.c_str()); - } - else - { - ci->desc.clear(); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to unset the description"; - source.Reply(_("Description of %s unset."), ci->name.c_str()); - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the description for the channel, which shows up with\n" - "the \002LIST\002 and \002INFO\002 commands."), this->name.c_str()); - return true; - } -}; - -class CommandCSSetFounder : public Command -{ - public: - CommandCSSetFounder(Module *creator, const Anope::string &cname = "chanserv/set/founder") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Set the founder of a channel")); - this->SetSyntax(_("\037channel\037 \037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - const NickAlias *na = NickAlias::Find(params[1]); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, params[1].c_str()); - return; - } - - NickCore *nc = na->nc; - unsigned max_reg = Config->GetModule("chanserv")->Get<unsigned>("maxregistered"); - if (max_reg && nc->channelcount >= max_reg && !source.HasPriv("chanserv/no-register-limit")) - { - source.Reply(_("\002%s\002 has too many channels registered."), na->nick.c_str()); - return; - } - - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the founder from " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << " to " << nc->display; - - ci->SetFounder(nc); - - source.Reply(_("Founder of \002%s\002 changed to \002%s\002."), ci->name.c_str(), na->nick.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the founder of a channel. The new nickname must\n" - "be a registered one."), this->name.c_str()); - return true; - } -}; - -class CommandCSSetKeepModes : public Command -{ - public: - CommandCSSetKeepModes(Module *creator, const Anope::string &cname = "chanserv/set/keepmodes") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Retain modes when channel is not in use")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable keep modes"; - ci->Extend<bool>("CS_KEEP_MODES"); - source.Reply(_("Keep modes for %s is now \002on\002."), ci->name.c_str()); - if (ci->c) - ci->last_modes = ci->c->GetModes(); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable keep modes"; - ci->Shrink<bool>("CS_KEEP_MODES"); - source.Reply(_("Keep modes for %s is now \002off\002."), ci->name.c_str()); - ci->last_modes.clear(); - } - else - this->OnSyntaxError(source, "KEEPMODES"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables keepmodes for the given channel. If keep\n" - "modes is enabled, services will remember modes set on the channel\n" - "and attempt to re-set them the next time the channel is created.")); - return true; - } -}; - -class CommandCSSetPeace : public Command -{ - public: - CommandCSSetPeace(Module *creator, const Anope::string &cname = "chanserv/set/peace") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Regulate the use of critical commands")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable peace"; - ci->Extend<bool>("PEACE"); - source.Reply(_("Peace option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable peace"; - ci->Shrink<bool>("PEACE"); - source.Reply(_("Peace option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "PEACE"); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the \002peace\002 option for a channel.\n" - "When \002peace\002 is set, a user won't be able to kick,\n" - "ban or remove a channel status of a user that has\n" - "a level superior or equal to his via %s commands."), source.service->nick.c_str()); - return true; - } -}; - -inline static Anope::string BotModes() -{ - return Config->GetModule("botserv")->Get<Anope::string>("botmodes", - Config->GetModule("chanserv")->Get<Anope::string>("botmodes", "o") - ); -} - -class CommandCSSetPersist : public Command -{ - public: - CommandCSSetPersist(Module *creator, const Anope::string &cname = "chanserv/set/persist") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Set the channel as permanent")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - ChannelMode *cm = ModeManager::FindChannelModeByName("PERM"); - - if (params[1].equals_ci("ON")) - { - if (!ci->HasExt("PERSIST")) - { - ci->Extend<bool>("PERSIST"); - - /* Channel doesn't exist, create it */ - if (!ci->c) - { - bool created; - Channel *c = Channel::FindOrCreate(ci->name, created); - if (ci->bi) - { - ChannelStatus status(BotModes()); - ci->bi->Join(c, &status); - } - if (created) - c->Sync(); - } - - /* Set the perm mode */ - if (cm) - { - if (ci->c && !ci->c->HasMode("PERM")) - ci->c->SetMode(NULL, cm); - /* Add it to the channels mlock */ - ModeLocks *ml = ci->Require<ModeLocks>("modelocks"); - if (ml) - ml->SetMLock(cm, true, "", source.GetNick()); - } - /* No botserv bot, no channel mode, give them ChanServ. - * Yes, this works fine with no BotServ. - */ - else if (!ci->bi) - { - BotInfo *ChanServ = Config->GetClient("ChanServ"); - if (!ChanServ) - { - source.Reply(_("ChanServ is required to enable persist on this network.")); - return; - } - - ChanServ->Assign(NULL, ci); - if (!ci->c->FindUser(ChanServ)) - { - ChannelStatus status(BotModes()); - ChanServ->Join(ci->c, &status); - } - } - } - - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable persist"; - source.Reply(_("Channel \002%s\002 is now persistent."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - if (ci->HasExt("PERSIST")) - { - ci->Shrink<bool>("PERSIST"); - - BotInfo *ChanServ = Config->GetClient("ChanServ"), - *BotServ = Config->GetClient("BotServ"); - - /* Unset perm mode */ - if (cm) - { - if (ci->c && ci->c->HasMode("PERM")) - ci->c->RemoveMode(NULL, cm); - /* Remove from mlock */ - ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks"); - if (ml) - ml->RemoveMLock(cm, true); - } - /* No channel mode, no BotServ, but using ChanServ as the botserv bot - * which was assigned when persist was set on - */ - else if (!cm && !BotServ && ci->bi) - { - if (!ChanServ) - { - source.Reply(_("ChanServ is required to enable persist on this network.")); - return; - } - - /* Unassign bot */ - ChanServ->UnAssign(NULL, ci); - } - } - - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable persist"; - source.Reply(_("Channel \002%s\002 is no longer persistent."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "PERSIST"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - BotInfo *BotServ = Config->GetClient("BotServ"); - BotInfo *ChanServ = Config->GetClient("ChanServ"); - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the persistent channel setting.\n" - "When persistent is set, the service bot will remain\n" - "in the channel when it has emptied of users.\n" - " \n" - "If your IRCd does not have a permanent (persistent) channel\n" - "mode you must have a service bot in your channel to\n" - "set persist on, and it can not be unassigned while persist\n" - "is on.\n" - " \n" - "If this network does not have %s enabled and does\n" - "not have a permanent channel mode, %s will\n" - "join your channel when you set persist on (and leave when\n" - "it has been set off).\n" - " \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 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"); - return true; - } -}; - -class CommandCSSetRestricted : public Command -{ - public: - CommandCSSetRestricted(Module *creator, const Anope::string &cname = "chanserv/set/restricted") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Restrict access to the channel")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable restricted"; - ci->Extend<bool>("RESTRICTED"); - source.Reply(_("Restricted access option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable restricted"; - ci->Shrink<bool>("RESTRICTED"); - source.Reply(_("Restricted access option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "RESTRICTED"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the \002restricted access\002 option for a\n" - "channel. When \002restricted access\002 is set, users not on the access list will\n" - "instead be kicked and banned from the channel.")); - return true; - } -}; - -class CommandCSSetSecure : public Command -{ - public: - CommandCSSetSecure(Module *creator, const Anope::string &cname = "chanserv/set/secure") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Activate security features")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure"; - ci->Extend<bool>("CS_SECURE"); - source.Reply(_("Secure option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure"; - ci->Shrink<bool>("CS_SECURE"); - source.Reply(_("Secure option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "SECURE"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables security features for a\n" - "channel. When \002SECURE\002 is set, only users who have\n" - "identified to services, and are not only recognized, will be\n" - "given access to channels from account-based access entries.")); - return true; - } -}; - -class CommandCSSetSecureFounder : public Command -{ - public: - CommandCSSetSecureFounder(Module *creator, const Anope::string &cname = "chanserv/set/securefounder") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Stricter control of channel founder status")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure founder"; - ci->Extend<bool>("SECUREFOUNDER"); - source.Reply(_("Secure founder option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure founder"; - ci->Shrink<bool>("SECUREFOUNDER"); - source.Reply(_("Secure founder option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "SECUREFOUNDER"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the \002secure founder\002 option for a channel.\n" - "When \002secure founder\002 is set, only the real founder will be\n" - "able to drop the channel, change its founder and its successor,\n" - "and not those who have founder level access through\n" - "the access/qop command.")); - return true; - } -}; - -class CommandCSSetSecureOps : public Command -{ - public: - CommandCSSetSecureOps(Module *creator, const Anope::string &cname = "chanserv/set/secureops") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Stricter control of chanop status")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure ops"; - ci->Extend<bool>("SECUREOPS"); - source.Reply(_("Secure ops option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure ops"; - ci->Shrink<bool>("SECUREOPS"); - source.Reply(_("Secure ops option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "SECUREOPS"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - 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 access list\n" - "will not be allowed channel operator status.")); - return true; - } -}; - -class CommandCSSetSignKick : public Command -{ - public: - CommandCSSetSignKick(Module *creator, const Anope::string &cname = "chanserv/set/signkick") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Sign kicks that are done with the KICK command")); - this->SetSyntax(_("\037channel\037 {ON | LEVEL | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - ci->Extend<bool>("SIGNKICK"); - ci->Shrink<bool>("SIGNKICK_LEVEL"); - source.Reply(_("Signed kick option for %s is now \002on\002."), ci->name.c_str()); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable sign kick"; - } - else if (params[1].equals_ci("LEVEL")) - { - ci->Extend<bool>("SIGNKICK_LEVEL"); - ci->Shrink<bool>("SIGNKICK"); - source.Reply(_("Signed kick option for %s is now \002on\002, but depends of the\n" - "level of the user that is using the command."), ci->name.c_str()); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable sign kick level"; - } - else if (params[1].equals_ci("OFF")) - { - ci->Shrink<bool>("SIGNKICK"); - ci->Shrink<bool>("SIGNKICK_LEVEL"); - source.Reply(_("Signed kick option for %s is now \002off\002."), ci->name.c_str()); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable sign kick"; - } - else - this->OnSyntaxError(source, "SIGNKICK"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables signed kicks for a\n" - "channel. When \002SIGNKICK\002 is set, kicks issued with\n" - "the \002KICK\002 command will have the nick that used the\n" - "command in their reason.\n" - " \n" - "If you use \002LEVEL\002, those who have a level that is superior\n" - "or equal to the SIGNKICK level on the channel won't have their\n" - "kicks signed.")); - return true; - } -}; - -class CommandCSSetSuccessor : public Command -{ - public: - CommandCSSetSuccessor(Module *creator, const Anope::string &cname = "chanserv/set/successor") : Command(creator, cname, 1, 2) - { - this->SetDesc(_("Set the successor for a channel")); - this->SetSyntax(_("\037channel\037 \037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - const Anope::string ¶m = params.size() > 1 ? params[1] : ""; - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - NickCore *nc; - - if (!param.empty()) - { - const NickAlias *na = NickAlias::Find(param); - - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, param.c_str()); - return; - } - if (na->nc == ci->GetFounder()) - { - source.Reply(_("%s cannot be the successor on channel %s as they are the founder."), na->nick.c_str(), ci->name.c_str()); - return; - } - nc = na->nc; - } - else - nc = NULL; - - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the successor from " << (ci->GetSuccessor() ? ci->GetSuccessor()->display : "(none)") << " to " << (nc ? nc->display : "(none)"); - - ci->SetSuccessor(nc); - - if (nc) - source.Reply(_("Successor for \002%s\002 changed to \002%s\002."), ci->name.c_str(), nc->display.c_str()); - else - source.Reply(_("Successor for \002%s\002 unset."), ci->name.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the successor of a channel. If the founder's\n" - "nickname expires or is dropped while the channel is still\n" - "registered, the successor will become the new founder of the\n" - "channel. The new nickname must be a registered one.")); - unsigned max_reg = Config->GetModule("chanserv")->Get<unsigned>("maxregistered"); - if (max_reg) - source.Reply(_("However, if the successor already has too many\n" - "channels registered (%d), the channel will be dropped\n" - "instead, just as if no successor had been set."), max_reg); - return true; - } -}; - -class CommandCSSetNoexpire : public Command -{ - public: - CommandCSSetNoexpire(Module *creator) : Command(creator, "chanserv/saset/noexpire", 2, 2) - { - this->SetDesc(_("Prevent the channel from expiring")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (source.permission.empty() && !source.AccessFor(ci).HasPriv("SET")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(LOG_ADMIN, source, this, ci) << "to enable noexpire"; - ci->Extend<bool>("CS_NO_EXPIRE"); - source.Reply(_("Channel %s \002will not\002 expire."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(LOG_ADMIN, source, this, ci) << "to disable noexpire"; - ci->Shrink<bool>("CS_NO_EXPIRE"); - source.Reply(_("Channel %s \002will\002 expire."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "NOEXPIRE"); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets whether the given channel will expire. Setting this\n" - "to ON prevents the channel from expiring.")); - return true; - } -}; - -class CSSet : public Module -{ - SerializableExtensibleItem<bool> noautoop, peace, securefounder, - restricted, secure, secureops, signkick, signkick_level, noexpire; - - struct KeepModes : SerializableExtensibleItem<bool> - { - KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { } - - void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override - { - SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data); - - if (s->GetSerializableType()->GetName() != "ChannelInfo") - return; - - const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(s); - Anope::string modes; - for (Channel::ModeList::const_iterator it = ci->last_modes.begin(); it != ci->last_modes.end(); ++it) - { - if (!modes.empty()) - modes += " "; - modes += it->first; - if (!it->second.empty()) - modes += "," + it->second; - } - data["last_modes"] << modes; - } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override - { - SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data); - - if (s->GetSerializableType()->GetName() != "ChannelInfo") - return; - - ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(s); - Anope::string modes; - data["last_modes"] >> modes; - for (spacesepstream sep(modes); sep.GetToken(modes);) - { - size_t c = modes.find(','); - if (c == Anope::string::npos) - ci->last_modes.insert(std::make_pair(modes, "")); - else - ci->last_modes.insert(std::make_pair(modes.substr(0, c), modes.substr(c + 1))); - } - } - } keep_modes; - - struct Persist : SerializableExtensibleItem<bool> - { - Persist(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override - { - SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data); - - if (s->GetSerializableType()->GetName() != "ChannelInfo" || !this->HasExt(e)) - return; - - ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(s); - if (ci->c) - return; - - bool created; - Channel *c = Channel::FindOrCreate(ci->name, created); - - ChannelMode *cm = ModeManager::FindChannelModeByName("PERM"); - if (cm) - { - c->SetMode(NULL, cm); - } - /* on startup we might not know mode availibity here */ - else if (Me && Me->IsSynced()) - { - if (!ci->bi) - { - BotInfo *ChanServ = Config->GetClient("ChanServ"); - if (ChanServ) - ChanServ->Assign(NULL, ci); - } - - if (ci->bi && !c->FindUser(ci->bi)) - { - ChannelStatus status(BotModes()); - ci->bi->Join(c, &status); - } - } - - if (created) - c->Sync(); - } - } persist; - - CommandCSSet commandcsset; - CommandCSSetAutoOp commandcssetautoop; - CommandCSSetBanType commandcssetbantype; - CommandCSSetDescription commandcssetdescription; - CommandCSSetFounder commandcssetfounder; - CommandCSSetKeepModes commandcssetkeepmodes; - CommandCSSetPeace commandcssetpeace; - CommandCSSetPersist commandcssetpersist; - CommandCSSetRestricted commandcssetrestricted; - CommandCSSetSecure commandcssetsecure; - CommandCSSetSecureFounder commandcssetsecurefounder; - CommandCSSetSecureOps commandcssetsecureops; - CommandCSSetSignKick commandcssetsignkick; - CommandCSSetSuccessor commandcssetsuccessor; - CommandCSSetNoexpire commandcssetnoexpire; - - ExtensibleRef<bool> inhabit; - - bool persist_lower_ts; - - public: - CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - noautoop(this, "NOAUTOOP"), peace(this, "PEACE"), - securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"), - secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"), - signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"), - keep_modes(this, "CS_KEEP_MODES"), persist(this, "PERSIST"), - - commandcsset(this), commandcssetautoop(this), commandcssetbantype(this), - commandcssetdescription(this), commandcssetfounder(this), commandcssetkeepmodes(this), - commandcssetpeace(this), commandcssetpersist(this), commandcssetrestricted(this), - commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this), - commandcssetsuccessor(this), commandcssetnoexpire(this), - - inhabit("inhabit") - { - } - - void OnReload(Configuration::Conf *conf) anope_override - { - persist_lower_ts = conf->GetModule(this)->Get<bool>("persist_lower_ts"); - } - - void OnCreateChan(ChannelInfo *ci) anope_override - { - ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2"); - } - - void OnChannelSync(Channel *c) anope_override - { - if (c->ci && keep_modes.HasExt(c->ci)) - { - Channel::ModeList ml = c->ci->last_modes; - for (Channel::ModeList::iterator it = ml.begin(); it != ml.end(); ++it) - c->SetMode(c->ci->WhoSends(), it->first, it->second); - } - } - - 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")) - return EVENT_CONTINUE; - - if (c->ci->AccessFor(u).empty() && (!c->ci->GetFounder() || u->Account() != c->ci->GetFounder())) - return EVENT_STOP; - - return EVENT_CONTINUE; - } - - void OnDelChan(ChannelInfo *ci) anope_override - { - if (ci->c && persist.HasExt(ci)) - ci->c->RemoveMode(ci->WhoSends(), "PERM", "", false); - persist.Unset(ci); - } - - EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) anope_override - { - if (c->ci) - { - /* Channel mode +P or so was set, mark this channel as persistent */ - if (mode->name == "PERM") - persist.Set(c->ci, true); - - if (mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && (!inhabit || !inhabit->HasExt(c))) - c->ci->last_modes = c->GetModes(); - } - - return EVENT_CONTINUE; - } - - EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string ¶m) anope_override - { - if (mode->name == "PERM") - { - if (c->ci) - persist.Unset(c->ci); - } - - if (c->ci && mode->type != MODE_STATUS && !c->syncing && Me->IsSynced() && (!inhabit || !inhabit->HasExt(c))) - c->ci->last_modes = c->GetModes(); - - 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) - { - Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered; - c->creation_time = c->ci->time_registered; - IRCD->SendChannel(c); - c->Reset(); - } - } - - void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override - { - if (chan->ci) - { - if (noautoop.HasExt(chan->ci)) - give_modes = false; - if (secureops.HasExt(chan->ci)) - // This overrides what chanserv does because it is loaded after chanserv - take_modes = true; - } - } - - void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override - { - if (noexpire.HasExt(ci)) - expire = false; - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override - { - if (!show_all) - return; - - if (peace.HasExt(ci)) - info.AddOption(_("Peace")); - if (restricted.HasExt(ci)) - info.AddOption(_("Restricted access")); - if (secure.HasExt(ci)) - info.AddOption(_("Security")); - if (securefounder.HasExt(ci)) - info.AddOption(_("Secure founder")); - if (secureops.HasExt(ci)) - info.AddOption(_("Secure ops")); - if (signkick.HasExt(ci) || signkick_level.HasExt(ci)) - info.AddOption(_("Signed kicks")); - if (persist.HasExt(ci)) - info.AddOption(_("Persistent")); - if (noexpire.HasExt(ci)) - info.AddOption(_("No expire")); - if (keep_modes.HasExt(ci)) - info.AddOption(_("Keep modes")); - if (noautoop.HasExt(ci)) - info.AddOption(_("No auto-op")); - } -}; - -MODULE_INIT(CSSet) diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp deleted file mode 100644 index 038bd7cb5..000000000 --- a/modules/commands/cs_set_misc.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/set_misc.h" - -static Module *me; - -static Anope::map<Anope::string> descriptions; - -struct CSMiscData; -static Anope::map<ExtensibleItem<CSMiscData> *> items; - -static ExtensibleItem<CSMiscData> *GetItem(const Anope::string &name) -{ - ExtensibleItem<CSMiscData>* &it = items[name]; - if (!it) - try - { - it = new ExtensibleItem<CSMiscData>(me, name); - } - catch (const ModuleException &) { } - return it; -} - -struct CSMiscData : MiscData, Serializable -{ - CSMiscData(Extensible *obj) : Serializable("CSMiscData") { } - - CSMiscData(ChannelInfo *c, const Anope::string &n, const Anope::string &d) : Serializable("CSMiscData") - { - object = c->name; - name = n; - data = d; - } - - void Serialize(Serialize::Data &sdata) const anope_override - { - sdata["ci"] << this->object; - sdata["name"] << this->name; - sdata["data"] << this->data; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string sci, sname, sdata; - - data["ci"] >> sci; - data["name"] >> sname; - data["data"] >> sdata; - - ChannelInfo *ci = ChannelInfo::Find(sci); - if (ci == NULL) - return NULL; - - CSMiscData *d = NULL; - if (obj) - { - d = anope_dynamic_static_cast<CSMiscData *>(obj); - d->object = ci->name; - data["name"] >> d->name; - data["data"] >> d->data; - } - else - { - ExtensibleItem<CSMiscData> *item = GetItem(sname); - if (item) - d = item->Set(ci, CSMiscData(ci, sname, sdata)); - } - - return d; - } -}; - -static Anope::string GetAttribute(const Anope::string &command) -{ - size_t sp = command.rfind(' '); - if (sp != Anope::string::npos) - return command.substr(sp + 1); - return command; -} - -class CommandCSSetMisc : public Command -{ - public: - CommandCSSetMisc(Module *creator, const Anope::string &cname = "chanserv/set/misc") : Command(creator, cname, 1, 2) - { - this->SetSyntax(_("\037channel\037 [\037parameters\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - const Anope::string ¶m = params.size() > 1 ? params[1] : ""; - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - Anope::string scommand = GetAttribute(source.command); - Anope::string key = "cs_set_misc:" + scommand; - ExtensibleItem<CSMiscData> *item = GetItem(key); - if (item == NULL) - return; - - if (!param.empty()) - { - item->Set(ci, CSMiscData(ci, key, param)); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change it to " << param; - source.Reply(CHAN_SETTING_CHANGED, scommand.c_str(), ci->name.c_str(), params[1].c_str()); - } - else - { - item->Unset(ci); - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to unset it"; - source.Reply(CHAN_SETTING_UNSET, scommand.c_str(), ci->name.c_str()); - } - } - - void OnServHelp(CommandSource &source) anope_override - { - if (descriptions.count(source.command)) - { - this->SetDesc(descriptions[source.command]); - Command::OnServHelp(source); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (descriptions.count(source.command)) - { - source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str())); - return true; - } - return false; - } -}; - -class CSSetMisc : public Module -{ - CommandCSSetMisc commandcssetmisc; - Serialize::Type csmiscdata_type; - - public: - CSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcssetmisc(this), csmiscdata_type("CSMiscData", CSMiscData::Unserialize) - { - me = this; - } - - ~CSSetMisc() - { - for (Anope::map<ExtensibleItem<CSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it) - delete it->second; - } - - void OnReload(Configuration::Conf *conf) anope_override - { - descriptions.clear(); - - for (int i = 0; i < conf->CountBlock("command"); ++i) - { - Configuration::Block *block = conf->GetBlock("command", i); - - if (block->Get<const Anope::string>("command") != "chanserv/set/misc") - continue; - - Anope::string cname = block->Get<const Anope::string>("name"); - Anope::string desc = block->Get<const Anope::string>("misc_description"); - - if (cname.empty() || desc.empty()) - continue; - - descriptions[cname] = desc; - } - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool) anope_override - { - for (Anope::map<ExtensibleItem<CSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it) - { - ExtensibleItem<CSMiscData> *e = it->second; - MiscData *data = e->Get(ci); - - if (data != NULL) - info[e->name.substr(12).replace_all_cs("_", " ")] = data->data; - } - } -}; - -MODULE_INIT(CSSetMisc) diff --git a/modules/commands/cs_status.cpp b/modules/commands/cs_status.cpp deleted file mode 100644 index b984d5952..000000000 --- a/modules/commands/cs_status.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSStatus : public Command -{ -public: - CommandCSStatus(Module *creator) : Command(creator, "chanserv/status", 1, 2) - { - this->SetDesc(_("Find a user's status on a channel")); - this->SetSyntax(_("\037channel\037 [\037user\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &channel = params[0]; - - ChannelInfo *ci = ChannelInfo::Find(channel); - if (ci == NULL) - source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); - else if (!source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && !source.HasPriv("chanserv/auspex")) - source.Reply(ACCESS_DENIED); - else - { - Anope::string nick = source.GetNick(); - if (params.size() > 1) - nick = params[1]; - - AccessGroup ag; - User *u = User::Find(nick, true); - NickAlias *na = NULL; - if (u != NULL) - ag = ci->AccessFor(u); - else - { - na = NickAlias::Find(nick); - if (na != NULL) - ag = ci->AccessFor(na->nc); - } - - if (ag.super_admin) - source.Reply(_("\002%s\002 is a super administrator."), nick.c_str()); - else if (ag.founder) - source.Reply(_("\002%s\002 is the founder of \002%s\002."), nick.c_str(), ci->name.c_str()); - else if (ag.empty()) - source.Reply(_("\002%s\002 has no access on \002%s\002."), nick.c_str(), ci->name.c_str()); - else - { - source.Reply(_("Access for \002%s\002 on \002%s\002:"), nick.c_str(), ci->name.c_str()); - - for (unsigned i = 0; i < ag.paths.size(); ++i) - { - ChanAccess::Path &p = ag.paths[i]; - - if (p.empty()) - continue; - - if (p.size() == 1) - { - ChanAccess *acc = p[0]; - - source.Reply(_("\002%s\002 matches access entry %s, which has privilege %s."), nick.c_str(), acc->Mask().c_str(), acc->AccessSerialize().c_str()); - } - else - { - ChanAccess *first = p[0]; - ChanAccess *acc = p[p.size() - 1]; - - source.Reply(_("\002%s\002 matches access entry %s (from entry %s), which has privilege %s."), nick.c_str(), acc->Mask().c_str(), first->Mask().c_str(), acc->AccessSerialize().c_str()); - } - } - } - - for (unsigned j = 0, end = ci->GetAkickCount(); j < end; ++j) - { - AutoKick *autokick = ci->GetAkick(j); - - if (autokick->nc) - { - if (na && *autokick->nc == na->nc) - source.Reply(_("\002%s\002 is on the auto kick list of \002%s\002 (%s)."), na->nc->display.c_str(), ci->name.c_str(), autokick->reason.c_str()); - } - else if (u != NULL) - { - Entry akick_mask("", autokick->mask); - if (akick_mask.Matches(u)) - source.Reply(_("\002%s\002 matches auto kick entry %s on \002%s\002 (%s)."), u->nick.c_str(), autokick->mask.c_str(), ci->name.c_str(), autokick->reason.c_str()); - } - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command tells you what a users access is on a channel\n" - "and what access entries, if any, they match. Additionally it\n" - "will tell you of any auto kick entries they match. Usage of\n" - "this command is limited to users who have the ability to modify\n" - "access entries on the channel.")); - return true; - } -}; - -class CSStatus : public Module -{ - CommandCSStatus commandcsstatus; - - public: - CSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcsstatus(this) - { - } -}; - -MODULE_INIT(CSStatus) diff --git a/modules/commands/cs_suspend.cpp b/modules/commands/cs_suspend.cpp deleted file mode 100644 index 6bab44207..000000000 --- a/modules/commands/cs_suspend.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/suspend.h" - -struct CSSuspendInfo : SuspendInfo, Serializable -{ - CSSuspendInfo(Extensible *) : Serializable("CSSuspendInfo") { } - - void Serialize(Serialize::Data &data) const anope_override - { - data["chan"] << what; - data["by"] << by; - data["reason"] << reason; - data["time"] << when; - data["expires"] << expires; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string schan; - data["chan"] >> schan; - - CSSuspendInfo *si; - if (obj) - si = anope_dynamic_static_cast<CSSuspendInfo *>(obj); - else - { - ChannelInfo *ci = ChannelInfo::Find(schan); - if (!ci) - return NULL; - si = ci->Extend<CSSuspendInfo>("CS_SUSPENDED"); - data["chan"] >> si->what; - } - - data["by"] >> si->by; - data["reason"] >> si->reason; - data["time"] >> si->when; - data["expires"] >> si->expires; - return si; - } -}; - -class CommandCSSuspend : public Command -{ - public: - CommandCSSuspend(Module *creator) : Command(creator, "chanserv/suspend", 2, 3) - { - this->SetDesc(_("Prevent a channel from being used preserving channel data and settings")); - this->SetSyntax(_("\037channel\037 [+\037expiry\037] [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - Anope::string expiry = params[1]; - Anope::string reason = params.size() > 2 ? params[2] : ""; - time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("expire"); - - if (!expiry.empty() && expiry[0] != '+') - { - reason = expiry + " " + reason; - reason.trim(); - expiry.clear(); - } - else - { - expiry_secs = Anope::DoTime(expiry); - if (expiry_secs == -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - ChannelInfo *ci = ChannelInfo::Find(chan); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - - if (ci->HasExt("CS_SUSPENDED")) - { - source.Reply(_("\002%s\002 is already suspended."), ci->name.c_str()); - return; - } - - CSSuspendInfo *si = ci->Extend<CSSuspendInfo>("CS_SUSPENDED"); - si->what = ci->name; - si->by = source.GetNick(); - si->reason = reason; - si->when = Anope::CurTime; - si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0; - - if (ci->c) - { - std::vector<User *> users; - - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - if (!user->HasMode("OPER") && user->server != Me) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - ci->c->Kick(NULL, users[i], "%s", !reason.empty() ? reason.c_str() : Language::Translate(users[i], _("This channel has been suspended."))); - } - - Log(LOG_ADMIN, source, this, ci) << "(" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); - source.Reply(_("Channel \002%s\002 is now suspended."), ci->name.c_str()); - - FOREACH_MOD(OnChanSuspend, (ci)); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Disallows anyone from using the given channel.\n" - "May be cancelled by using the \002UNSUSPEND\002\n" - "command to preserve all previous channel data/settings.\n" - "If an expiry is given the channel will be unsuspended after\n" - "that period of time, else the default expiry from the\n" - "configuration is used.\n" - " \n" - "Reason may be required on certain networks.")); - return true; - } -}; - -class CommandCSUnSuspend : public Command -{ - public: - CommandCSUnSuspend(Module *creator) : Command(creator, "chanserv/unsuspend", 1, 1) - { - this->SetDesc(_("Releases a suspended channel")); - this->SetSyntax(_("\037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - /* Only UNSUSPEND already suspended channels */ - CSSuspendInfo *si = ci->GetExt<CSSuspendInfo>("CS_SUSPENDED"); - if (!si) - { - source.Reply(_("Channel \002%s\002 isn't suspended."), ci->name.c_str()); - return; - } - - Log(LOG_ADMIN, source, this, ci) << "which was suspended by " << si->by << " for: " << (!si->reason.empty() ? si->reason : "No reason"); - - ci->Shrink<CSSuspendInfo>("CS_SUSPENDED"); - - source.Reply(_("Channel \002%s\002 is now released."), ci->name.c_str()); - - FOREACH_MOD(OnChanUnsuspend, (ci)); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Releases a suspended channel. All data and settings\n" - "are preserved from before the suspension.")); - return true; - } -}; - -class CSSuspend : public Module -{ - CommandCSSuspend commandcssuspend; - CommandCSUnSuspend commandcsunsuspend; - ExtensibleItem<CSSuspendInfo> suspend; - Serialize::Type suspend_type; - std::vector<Anope::string> show; - - struct trim - { - Anope::string operator()(Anope::string s) const - { - return s.trim(); - } - }; - - bool Show(CommandSource &source, const Anope::string &what) const - { - return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end(); - } - - public: - CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcssuspend(this), commandcsunsuspend(this), suspend(this, "CS_SUSPENDED"), - suspend_type("CSSuspendInfo", CSSuspendInfo::Unserialize) - { - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override - { - CSSuspendInfo *si = suspend.Get(ci); - if (!si) - return; - - if (show_hidden || Show(source, "suspended")) - info[_("Suspended")] = _("This channel is \002suspended\002."); - if (!si->by.empty() && (show_hidden || Show(source, "by"))) - info[_("Suspended by")] = si->by; - if (!si->reason.empty() && (show_hidden || Show(source, "reason"))) - info[_("Suspend reason")] = si->reason; - if (si->when && (show_hidden || Show(source, "on"))) - info[_("Suspended on")] = Anope::strftime(si->when, source.GetAccount()); - if (si->expires && (show_hidden || Show(source, "expires"))) - info[_("Suspension expires")] = Anope::strftime(si->expires, source.GetAccount()); - } - - void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override - { - CSSuspendInfo *si = suspend.Get(ci); - if (!si) - return; - - expire = false; - - if (!si->expires) - return; - - if (si->expires < Anope::CurTime) - { - ci->last_used = Anope::CurTime; - suspend.Unset(ci); - - Log(this) << "Expiring suspend for " << ci->name; - } - } - - EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override - { - if (u->HasMode("OPER") || !c->ci || !suspend.HasExt(c->ci)) - return EVENT_CONTINUE; - - reason = Language::Translate(u, _("This channel may not be used.")); - return EVENT_STOP; - } - - EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) anope_override - { - CSSuspendInfo *si = suspend.Get(ci); - if (si && !source.HasCommand("chanserv/drop")) - { - source.Reply(CHAN_X_SUSPENDED, ci->name.c_str()); - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(CSSuspend) diff --git a/modules/commands/cs_sync.cpp b/modules/commands/cs_sync.cpp deleted file mode 100644 index a60e24cab..000000000 --- a/modules/commands/cs_sync.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSSync : public Command -{ - public: - CommandCSSync(Module *creator) : Command(creator, "chanserv/sync", 1, 1) - { - this->SetDesc(_("Sync users channel modes")); - this->SetSyntax(_("\037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - - if (ci == NULL) - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - else if (ci->c == NULL) - source.Reply(CHAN_X_NOT_IN_USE, params[0].c_str()); - else if (!source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && !source.HasPriv("chanserv/administration")) - source.Reply(ACCESS_DENIED); - else - { - bool override = !source.AccessFor(ci).HasPriv("ACCESS_CHANGE") && source.HasPriv("chanserv/administration"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci); - - for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) - ci->c->SetCorrectModes(it->second->user, true); - - source.Reply(_("All user modes on \002%s\002 have been synced."), ci->name.c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string ¶ms) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Syncs all modes set on users on the channel with the modes\n" - "they should have based on their access.")); - return true; - } -}; - -class CSSync : public Module -{ - CommandCSSync commandcssync; - public: - CSSync(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcssync(this) - { - - } -}; - -MODULE_INIT(CSSync) diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp deleted file mode 100644 index 2db37a456..000000000 --- a/modules/commands/cs_topic.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/cs_mode.h" - -class CommandCSSetKeepTopic : public Command -{ - public: - CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic") : Command(creator, cname, 2, 2) - { - this->SetDesc(_("Retain topic when channel is not in use")); - this->SetSyntax(_("\037channel\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1])); - if (MOD_RESULT == EVENT_STOP) - return; - - if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (params[1].equals_ci("ON")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable keeptopic"; - ci->Extend<bool>("KEEPTOPIC"); - source.Reply(_("Topic retention option for %s is now \002on\002."), ci->name.c_str()); - } - else if (params[1].equals_ci("OFF")) - { - Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable keeptopic"; - ci->Shrink<bool>("KEEPTOPIC"); - source.Reply(_("Topic retention option for %s is now \002off\002."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, "KEEPTOPIC"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables the \002topic retention\002 option for a\n" - "channel. When \002%s\002 is set, the topic for the\n" - "channel will be remembered by %s even after the\n" - "last user leaves the channel, and will be restored the\n" - "next time the channel is created."), source.command.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class CommandCSTopic : public Command -{ - ExtensibleRef<bool> topiclock; - - void Lock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, "topiclock on")); - if (MOD_RESULT == EVENT_STOP) - return; - - topiclock->Set(ci, true); - source.Reply(_("Topic lock option for %s is now \002on\002."), ci->name.c_str()); - } - - void Unlock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, "topiclock off")); - if (MOD_RESULT == EVENT_STOP) - return; - - topiclock->Unset(ci); - source.Reply(_("Topic lock option for %s is now \002off\002."), ci->name.c_str()); - } - - void Set(CommandSource &source, ChannelInfo *ci, const Anope::string &topic) - { - bool has_topiclock = topiclock->HasExt(ci); - topiclock->Unset(ci); - ci->c->ChangeTopic(source.GetNick(), topic, Anope::CurTime); - if (has_topiclock) - topiclock->Set(ci); - - bool override = !source.AccessFor(ci).HasPriv("TOPIC"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << (!topic.empty() ? "to change the topic to: " : "to unset the topic") << (!topic.empty() ? topic : ""); - } - - void Append(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - const Anope::string &topic = params[2]; - - Anope::string new_topic; - if (!ci->c->topic.empty()) - { - new_topic = ci->c->topic + " " + topic; - ci->last_topic.clear(); - } - else - new_topic = topic; - - this->Set(source, ci, new_topic); - } - - public: - CommandCSTopic(Module *creator) : Command(creator, "chanserv/topic", 2, 3), - topiclock("TOPICLOCK") - { - this->SetDesc(_("Manipulate the topic of the specified channel")); - this->SetSyntax(_("\037channel\037 [SET] [\037topic\037]")); - this->SetSyntax(_("\037channel\037 APPEND \037topic\037")); - this->SetSyntax(_("\037channel\037 [UNLOCK|LOCK]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &subcmd = params[1]; - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - else if (!source.AccessFor(ci).HasPriv("TOPIC") && !source.HasCommand("chanserv/topic")) - source.Reply(ACCESS_DENIED); - else if (subcmd.equals_ci("LOCK")) - this->Lock(source, ci, params); - else if (subcmd.equals_ci("UNLOCK")) - this->Unlock(source, ci, params); - else if (!ci->c) - source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - else if (subcmd.equals_ci("APPEND") && params.size() > 2) - this->Append(source, ci, params); - else - { - Anope::string topic; - if (subcmd.equals_ci("SET")) - { - topic = params.size() > 2 ? params[2] : ""; - } - else - { - topic = subcmd; - if (params.size() > 2) - topic += " " + params[2]; - } - this->Set(source, ci, topic); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows manipulating the topic of the specified channel.\n" - "The \002SET\002 command changes the topic of the channel to the given topic\n" - "or unsets the topic if no topic is given. The \002APPEND\002 command appends\n" - "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 by users who do not have\n" - "the \002TOPIC\002 privilege.")); - return true; - } -}; - -class CSTopic : public Module -{ - CommandCSTopic commandcstopic; - CommandCSSetKeepTopic commandcssetkeeptopic; - - SerializableExtensibleItem<bool> topiclock, keeptopic; - - public: - CSTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcstopic(this), commandcssetkeeptopic(this), topiclock(this, "TOPICLOCK"), keeptopic(this, "KEEPTOPIC") - { - - } - - void OnChannelSync(Channel *c) anope_override - { - if (c->ci) - { - /* Update channel topic */ - if ((topiclock.HasExt(c->ci) || keeptopic.HasExt(c->ci)) && c->ci->last_topic != c->topic) - { - c->ChangeTopic(!c->ci->last_topic_setter.empty() ? c->ci->last_topic_setter : c->ci->WhoSends()->nick, c->ci->last_topic, c->ci->last_topic_time ? c->ci->last_topic_time : Anope::CurTime); - } - } - } - - void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) anope_override - { - if (!c->ci) - return; - - /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not - * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us. - * 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 && (!source || !c->ci->AccessFor(source).HasPriv("TOPIC"))) - { - c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time); - } - else - { - c->ci->last_topic = c->topic; - c->ci->last_topic_setter = c->topic_setter; - c->ci->last_topic_time = c->topic_ts; - } - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override - { - if (keeptopic.HasExt(ci)) - info.AddOption(_("Topic retention")); - if (topiclock.HasExt(ci)) - info.AddOption(_("Topic lock")); - - ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks"); - const ModeLock *secret = ml ? ml->GetMLock("SECRET") : NULL; - if (!ci->last_topic.empty() && (show_all || ((!secret || secret->set == false) && (!ci->c || !ci->c->HasMode("SECRET"))))) - { - info[_("Last topic")] = ci->last_topic; - info[_("Topic set by")] = ci->last_topic_setter; - } - } -}; - -MODULE_INIT(CSTopic) diff --git a/modules/commands/cs_unban.cpp b/modules/commands/cs_unban.cpp deleted file mode 100644 index 64ecc7151..000000000 --- a/modules/commands/cs_unban.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSUnban : public Command -{ - public: - CommandCSUnban(Module *creator) : Command(creator, "chanserv/unban", 0, 2) - { - this->SetDesc(_("Remove all bans preventing a user from entering a channel")); - this->SetSyntax(_("\037channel\037 [\037nick\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelMode *cm = ModeManager::FindChannelModeByName("BAN"); - if (!cm) - return; - - std::vector<ChannelMode *> modes = cm->listeners; - modes.push_back(cm); - - if (params.empty()) - { - if (!source.GetUser()) - return; - - std::deque<ChannelInfo *> queue; - source.GetAccount()->GetChannelReferences(queue); - - unsigned count = 0; - for (unsigned i = 0; i < queue.size(); ++i) - { - ChannelInfo *ci = queue[i]; - - if (!ci->c || !source.AccessFor(ci).HasPriv("UNBAN")) - continue; - - for (unsigned j = 0; j < modes.size(); ++j) - if (ci->c->Unban(source.GetUser(), modes[j]->name, true)) - ++count; - } - - Log(LOG_COMMAND, source, this, NULL) << "on all channels"; - source.Reply(_("You have been unbanned from %d channels."), count); - - return; - } - - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (ci->c == NULL) - { - source.Reply(CHAN_X_NOT_IN_USE, ci->name.c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("UNBAN") && !source.HasPriv("chanserv/kick")) - { - source.Reply(ACCESS_DENIED); - return; - } - - User *u2 = source.GetUser(); - if (params.size() > 1) - u2 = User::Find(params[1], true); - - if (!u2) - { - source.Reply(NICK_X_NOT_IN_USE, params[1].c_str()); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("UNBAN") && source.HasPriv("chanserv/kick"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to unban " << u2->nick; - - for (unsigned i = 0; i < modes.size(); ++i) - ci->c->Unban(u2, modes[i]->name, source.GetUser() == u2); - if (u2 == source.GetUser()) - source.Reply(_("You have been unbanned from \002%s\002."), ci->c->name.c_str()); - else - source.Reply(_("\002%s\002 has been unbanned from \002%s\002."), u2->nick.c_str(), ci->c->name.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Tells %s to remove all bans preventing you or the given\n" - "user from entering the given channel. If no channel is\n" - "given, all bans affecting you in channels you have access\n" - "in are removed.\n" - " \n" - "By default, limited to AOPs or those with level 5 access and above\n" - "on the channel."), source.service->nick.c_str()); - return true; - } -}; - -class CSUnban : public Module -{ - CommandCSUnban commandcsunban; - - public: - CSUnban(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsunban(this) - { - - } -}; - -MODULE_INIT(CSUnban) diff --git a/modules/commands/cs_updown.cpp b/modules/commands/cs_updown.cpp deleted file mode 100644 index ab3ab60ce..000000000 --- a/modules/commands/cs_updown.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandCSUp : public Command -{ - void SetModes(User *u, Channel *c) - { - if (!c->ci) - return; - - /* whether or not we are giving modes */ - bool giving = true; - /* whether or not we have given a mode */ - bool given = false; - AccessGroup u_access = c->ci->AccessFor(u); - - for (unsigned i = 0; i < ModeManager::GetStatusChannelModesByRank().size(); ++i) - { - ChannelModeStatus *cm = ModeManager::GetStatusChannelModesByRank()[i]; - bool has_priv = u_access.HasPriv("AUTO" + cm->name) || u_access.HasPriv(cm->name); - - if (has_priv) - { - /* Always give op. If we have already given one mode, don't give more until it has a symbol */ - if (cm->name == "OP" || !given || (giving && cm->symbol)) - { - c->SetMode(NULL, cm, u->GetUID(), false); - /* Now if this contains a symbol don't give any more modes, to prevent setting +qaohv etc on users */ - giving = !cm->symbol; - given = true; - } - } - } - } - public: - CommandCSUp(Module *creator) : Command(creator, "chanserv/up", 0, 2) - { - this->SetDesc(_("Updates a selected nicks status on a channel")); - this->SetSyntax(_("[\037channel\037 [\037nick\037]]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.empty()) - { - if (!source.GetUser()) - return; - for (User::ChanUserList::iterator it = source.GetUser()->chans.begin(); it != source.GetUser()->chans.end(); ++it) - { - Channel *c = it->second->chan; - SetModes(source.GetUser(), c); - } - Log(LOG_COMMAND, source, this, NULL) << "on all channels to update their status modes"; - } - else - { - const Anope::string &channel = params[0]; - const Anope::string &nick = params.size() > 1 ? params[1] : source.GetNick(); - - Channel *c = Channel::Find(channel); - - if (c == NULL) - { - source.Reply(CHAN_X_NOT_IN_USE, channel.c_str()); - return; - } - else if (!c->ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); - return; - } - - User *u = User::Find(nick, true); - User *srcu = source.GetUser(); - bool override = false; - - if (u == NULL) - { - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - return; - } - else if (srcu && !srcu->FindChannel(c)) - { - source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str()); - return; - } - else if (!u->FindChannel(c)) - { - source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str()); - return; - } - else if (source.GetUser() && u != source.GetUser() && c->ci->HasExt("PEACE")) - { - if (c->ci->AccessFor(u) >= c->ci->AccessFor(source.GetUser())) - { - if (source.HasPriv("chanserv/administration")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - } - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, c->ci) << "to update the status modes of " << u->nick; - SetModes(u, c); - } - - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Updates a selected nicks status modes on a channel. If \037nick\037 is\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; - } -}; - -class CommandCSDown : public Command -{ - void RemoveAll(User *u, Channel *c) - { - ChanUserContainer *cu = c->FindUser(u); - if (cu != NULL) - for (size_t i = cu->status.Modes().length(); i > 0;) - c->RemoveMode(NULL, ModeManager::FindChannelModeByChar(cu->status.Modes()[--i]), u->GetUID()); - } - - public: - CommandCSDown(Module *creator) : Command(creator, "chanserv/down", 0, 2) - { - this->SetDesc(_("Removes a selected nicks status from a channel")); - this->SetSyntax(_("[\037channel\037 [\037nick\037]]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.empty()) - { - if (!source.GetUser()) - return; - for (User::ChanUserList::iterator it = source.GetUser()->chans.begin(); it != source.GetUser()->chans.end(); ++it) - { - Channel *c = it->second->chan; - RemoveAll(source.GetUser(), c); - } - Log(LOG_COMMAND, source, this, NULL) << "on all channels to remove their status modes"; - } - else - { - const Anope::string &channel = params[0]; - const Anope::string &nick = params.size() > 1 ? params[1] : source.GetNick(); - - Channel *c = Channel::Find(channel); - - if (c == NULL) - { - source.Reply(CHAN_X_NOT_IN_USE, channel.c_str()); - return; - } - else if (!c->ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, channel.c_str()); - return; - } - - User *u = User::Find(nick, true); - User *srcu = source.GetUser(); - bool override = false; - - if (u == NULL) - { - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - return; - } - else if (srcu && !srcu->FindChannel(c)) - { - source.Reply(_("You must be in \002%s\002 to use this command."), c->name.c_str()); - return; - } - else if (!u->FindChannel(c)) - { - source.Reply(NICK_X_NOT_ON_CHAN, nick.c_str(), channel.c_str()); - return; - } - else if (source.GetUser() && u != source.GetUser() && c->ci->HasExt("PEACE")) - { - if (c->ci->AccessFor(u) >= c->ci->AccessFor(source.GetUser())) - { - if (source.HasPriv("chanserv/administration")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - } - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, c->ci) << "to remove the status modes from " << u->nick; - RemoveAll(u, c); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Removes a selected nicks status modes on a channel. If \037nick\037 is\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; - } -}; - -class CSUpDown : public Module -{ - CommandCSUp commandcsup; - CommandCSDown commandcsdown; - - public: - CSUpDown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandcsup(this), commandcsdown(this) - { - - } -}; - -MODULE_INIT(CSUpDown) diff --git a/modules/commands/cs_xop.cpp b/modules/commands/cs_xop.cpp deleted file mode 100644 index 3a6c4d484..000000000 --- a/modules/commands/cs_xop.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* ChanServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -namespace -{ - std::vector<Anope::string> order; - std::map<Anope::string, std::vector<Anope::string> > permissions; -} - -class XOPChanAccess : public ChanAccess -{ - public: - Anope::string type; - - XOPChanAccess(AccessProvider *p) : ChanAccess(p) - { - } - - bool HasPriv(const Anope::string &priv) const anope_override - { - for (std::vector<Anope::string>::iterator it = std::find(order.begin(), order.end(), this->type); it != order.end(); ++it) - { - const std::vector<Anope::string> &privs = permissions[*it]; - if (std::find(privs.begin(), privs.end(), priv) != privs.end()) - return true; - } - return false; - } - - Anope::string AccessSerialize() const - { - return this->type; - } - - void AccessUnserialize(const Anope::string &data) anope_override - { - this->type = data; - } - - static Anope::string DetermineLevel(const ChanAccess *access) - { - if (access->provider->name == "access/xop") - { - const XOPChanAccess *xaccess = anope_dynamic_static_cast<const XOPChanAccess *>(access); - return xaccess->type; - } - else - { - std::map<Anope::string, int> count; - - for (std::map<Anope::string, std::vector<Anope::string> >::const_iterator it = permissions.begin(), it_end = permissions.end(); it != it_end; ++it) - { - int &c = count[it->first]; - const std::vector<Anope::string> &perms = it->second; - for (unsigned i = 0; i < perms.size(); ++i) - if (access->HasPriv(perms[i])) - ++c; - } - - Anope::string max; - int maxn = 0; - for (std::map<Anope::string, int>::iterator it = count.begin(), it_end = count.end(); it != it_end; ++it) - if (it->second > maxn) - { - maxn = it->second; - max = it->first; - } - - return max; - } - } -}; - -class XOPAccessProvider : public AccessProvider -{ - public: - XOPAccessProvider(Module *o) : AccessProvider(o, "access/xop") - { - } - - ChanAccess *Create() anope_override - { - return new XOPChanAccess(this); - } -}; - -class CommandCSXOP : public Command -{ - private: - void DoAdd(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - Anope::string mask = params.size() > 2 ? params[2] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str()); - return; - } - - XOPChanAccess tmp_access(NULL); - tmp_access.ci = ci; - tmp_access.type = source.command.upper(); - - AccessGroup access = source.AccessFor(ci); - const ChanAccess *highest = access.Highest(); - bool override = false; - const NickAlias *na = NULL; - - std::vector<Anope::string>::iterator cmd_it = std::find(order.begin(), order.end(), source.command.upper()), - access_it = highest ? std::find(order.begin(), order.end(), XOPChanAccess::DetermineLevel(highest)) : order.end(); - - if (!access.founder && (!access.HasPriv("ACCESS_CHANGE") || cmd_it <= access_it)) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - - if (IRCD->IsChannelValid(mask)) - { - if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access")) - { - source.Reply(_("Channels may not be on access lists.")); - return; - } - - ChannelInfo *targ_ci = ChannelInfo::Find(mask); - if (targ_ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, mask.c_str()); - return; - } - else if (ci == targ_ci) - { - source.Reply(_("You can't add a channel to its own access list.")); - return; - } - - mask = targ_ci->name; - } - else - { - na = NickAlias::Find(mask); - if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access")) - { - source.Reply(_("Masks and unregistered users may not be on access lists.")); - return; - } - else if (mask.find_first_of("!*@") == Anope::string::npos && !na) - { - User *targ = User::Find(mask, true); - if (targ != NULL) - mask = "*!*@" + targ->GetDisplayedHost(); - else - { - source.Reply(NICK_X_NOT_REGISTERED, mask.c_str()); - return; - } - } - - if (na) - mask = na->nick; - } - - for (unsigned i = 0; i < ci->GetAccessCount(); ++i) - { - const ChanAccess *a = ci->GetAccess(i); - - if ((na && na->nc == a->GetAccount()) || mask.equals_ci(a->Mask())) - { - if ((!highest || *a >= *highest) && !access.founder && !source.HasPriv("chanserv/access/modify")) - { - source.Reply(ACCESS_DENIED); - return; - } - - delete ci->EraseAccess(i); - break; - } - } - - unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024"); - if (access_max && ci->GetDeepAccessCount() >= access_max) - { - source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max); - return; - } - - ServiceReference<AccessProvider> provider("AccessProvider", "access/xop"); - if (!provider) - return; - XOPChanAccess *acc = anope_dynamic_static_cast<XOPChanAccess *>(provider->Create()); - acc->SetMask(mask, ci); - acc->creator = source.GetNick(); - acc->type = source.command.upper(); - acc->last_seen = 0; - acc->created = Anope::CurTime; - ci->AddAccess(acc); - - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to add " << mask; - - FOREACH_MOD(OnAccessAdd, (ci, source, acc)); - source.Reply(_("\002%s\002 added to %s %s list."), acc->Mask().c_str(), ci->name.c_str(), source.command.c_str()); - } - - void DoDel(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - NickCore *nc = source.nc; - Anope::string mask = params.size() > 2 ? params[2] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str()); - return; - } - - if (!ci->GetAccessCount()) - { - source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str()); - return; - } - - XOPChanAccess tmp_access(NULL); - tmp_access.ci = ci; - tmp_access.type = source.command.upper(); - - AccessGroup access = source.AccessFor(ci); - const ChanAccess *highest = access.Highest(); - bool override = false; - - if (!isdigit(mask[0]) && mask.find_first_of("#!*@") == Anope::string::npos && !NickAlias::Find(mask)) - { - User *targ = User::Find(mask, true); - if (targ != NULL) - mask = "*!*@" + targ->GetDisplayedHost(); - else - { - source.Reply(NICK_X_NOT_REGISTERED, mask.c_str()); - return; - } - } - - std::vector<Anope::string>::iterator cmd_it = std::find(order.begin(), order.end(), source.command.upper()), - access_it = highest ? std::find(order.begin(), order.end(), XOPChanAccess::DetermineLevel(highest)) : order.end(); - - if (!mask.equals_ci(nc->display) && !access.founder && (!access.HasPriv("ACCESS_CHANGE") || cmd_it <= access_it)) - { - if (source.HasPriv("chanserv/access/modify")) - override = true; - else - { - source.Reply(ACCESS_DENIED); - return; - } - } - - /* Special case: is it a number/list? Only do search if it isn't. */ - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class XOPDelCallback : public NumberList - { - CommandSource &source; - ChannelInfo *ci; - Command *c; - unsigned deleted; - Anope::string nicks; - bool override; - public: - XOPDelCallback(CommandSource &_source, ChannelInfo *_ci, Command *_c, bool _override, const Anope::string &numlist) : NumberList(numlist, true), source(_source), ci(_ci), c(_c), deleted(0), override(_override) - { - } - - ~XOPDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on %s %s list."), ci->name.c_str(), source.command.c_str()); - else - { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << nicks; - - if (deleted == 1) - source.Reply(_("Deleted one entry from %s %s list."), ci->name.c_str(), source.command.c_str()); - else - source.Reply(_("Deleted %d entries from %s %s list."), deleted, ci->name.c_str(), source.command.c_str()); - } - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > ci->GetAccessCount()) - return; - - ChanAccess *caccess = ci->GetAccess(number - 1); - - if (caccess->provider->name != "access/xop" || this->source.command.upper() != caccess->AccessSerialize()) - return; - - ++deleted; - if (!nicks.empty()) - nicks += ", " + caccess->Mask(); - else - nicks = caccess->Mask(); - - ci->EraseAccess(number - 1); - FOREACH_MOD(OnAccessDel, (ci, source, caccess)); - delete caccess; - } - } - delcallback(source, ci, this, override, mask); - delcallback.Process(); - } - else - { - for (unsigned i = 0; i < ci->GetAccessCount(); ++i) - { - ChanAccess *a = ci->GetAccess(i); - - if (a->provider->name != "access/xop" || source.command.upper() != a->AccessSerialize()) - continue; - - if (a->Mask().equals_ci(mask)) - { - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to delete " << a->Mask(); - - source.Reply(_("\002%s\002 deleted from %s %s list."), a->Mask().c_str(), ci->name.c_str(), source.command.c_str()); - - ci->EraseAccess(i); - FOREACH_MOD(OnAccessDel, (ci, source, a)); - delete a; - - return; - } - } - - source.Reply(_("\002%s\002 not found on %s %s list."), mask.c_str(), ci->name.c_str(), source.command.c_str()); - } - } - - void DoList(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> ¶ms) - { - - const Anope::string &nick = params.size() > 2 ? params[2] : ""; - - AccessGroup access = source.AccessFor(ci); - - if (!access.HasPriv("ACCESS_LIST") && !source.HasPriv("chanserv/access/list")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (!ci->GetAccessCount()) - { - source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str()); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")); - - if (!nick.empty() && nick.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class XOPListCallback : public NumberList - { - ListFormatter &list; - ChannelInfo *ci; - CommandSource &source; - public: - XOPListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist, CommandSource &src) : NumberList(numlist, false), list(_list), ci(_ci), source(src) - { - } - - void HandleNumber(unsigned Number) anope_override - { - if (!Number || Number > ci->GetAccessCount()) - return; - - const ChanAccess *a = ci->GetAccess(Number - 1); - - if (a->provider->name != "access/xop" || this->source.command.upper() != a->AccessSerialize()) - return; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(Number); - entry["Mask"] = a->Mask(); - this->list.AddEntry(entry); - } - } nl_list(list, ci, nick, source); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = ci->GetAccessCount(); i < end; ++i) - { - const ChanAccess *a = ci->GetAccess(i); - - if (a->provider->name != "access/xop" || source.command.upper() != a->AccessSerialize()) - continue; - else if (!nick.empty() && !Anope::Match(a->Mask(), nick)) - continue; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Mask"] = a->Mask(); - list.AddEntry(entry); - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on %s access list."), ci->name.c_str()); - else - { - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("%s list for %s"), source.command.c_str(), ci->name.c_str()); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - void DoClear(CommandSource &source, ChannelInfo *ci) - { - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str()); - return; - } - - if (!ci->GetAccessCount()) - { - source.Reply(_("%s %s list is empty."), ci->name.c_str(), source.command.c_str()); - return; - } - - if (!source.AccessFor(ci).HasPriv("FOUNDER") && !source.HasPriv("chanserv/access/modify")) - { - source.Reply(ACCESS_DENIED); - return; - } - - bool override = !source.AccessFor(ci).HasPriv("FOUNDER"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to clear the access list"; - - for (unsigned i = ci->GetAccessCount(); i > 0; --i) - { - const ChanAccess *access = ci->GetAccess(i - 1); - - if (access->provider->name != "access/xop" || source.command.upper() != access->AccessSerialize()) - continue; - - delete ci->EraseAccess(i - 1); - } - - FOREACH_MOD(OnAccessClear, (ci, source)); - - source.Reply(_("Channel %s %s list has been cleared."), ci->name.c_str(), source.command.c_str()); - } - - public: - CommandCSXOP(Module *modname) : Command(modname, "chanserv/xop", 2, 4) - { - this->SetSyntax(_("\037channel\037 ADD \037mask\037")); - this->SetSyntax(_("\037channel\037 DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); - this->SetSyntax(_("\037channel\037 LIST [\037mask\037 | \037list\037]")); - this->SetSyntax(_("\037channel\037 CLEAR")); - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - return Anope::printf(Language::Translate(source.GetAccount(), _("Modify the list of %s users")), source.command.upper().c_str()); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - const Anope::string &cmd = params[1]; - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, ci, params); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, ci, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, ci, params); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source, ci); - else - this->OnSyntaxError(source, ""); - } - - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - const Anope::string &cmd = source.command.upper(); - - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Maintains the \002%s list\002 for a channel. Users who match an access entry\n" - "on the %s list receive the following privileges:\n" - " "), cmd.c_str(), cmd.c_str()); - - Anope::string buf; - for (unsigned i = 0; i < permissions[cmd].size(); ++i) - { - buf += ", " + permissions[cmd][i]; - if (buf.length() > 75) - { - source.Reply(" %s\n", buf.substr(2).c_str()); - buf.clear(); - } - } - if (!buf.empty()) - { - source.Reply(" %s\n", buf.substr(2).c_str()); - buf.clear(); - } - - source.Reply(_(" \n" - "The \002%s ADD\002 command adds the given nickname to the\n" - "%s list.\n" - " \n" - "The \002%s DEL\002 command removes the given nick from the\n" - "%s list. If a list of entry numbers is given, those\n" - "entries are deleted. (See the example for LIST below.)\n" - " \n" - "The \002%s LIST\002 command displays the %s list. If\n" - "a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002%s #channel LIST 2-5,7-9\002\n" - " Lists %s entries numbered 2 through 5 and\n" - " 7 through 9.\n" - " \n" - "The \002%s CLEAR\002 command clears all entries of the\n" - "%s list."), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), - cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str(), cmd.c_str()); - BotInfo *access_bi, *flags_bi; - Anope::string access_cmd, flags_cmd; - Command::FindCommandFromService("chanserv/access", access_bi, access_cmd); - Command::FindCommandFromService("chanserv/flags", flags_bi, access_cmd); - if (!access_cmd.empty() || !flags_cmd.empty()) - { - source.Reply(_("Alternative methods of modifying channel access lists are\n" - "available. ")); - if (!access_cmd.empty()) - source.Reply(_("See \002%s%s HELP %s\002 for more information\n" - "about the access list."), Config->StrictPrivmsg.c_str(), access_bi->nick.c_str(), access_cmd.c_str()); - if (!flags_cmd.empty()) - source.Reply(_("See \002%s%s HELP %s\002 for more information\n" - "about the flags system."), Config->StrictPrivmsg.c_str(), flags_bi->nick.c_str(), flags_cmd.c_str()); - } - return true; - } -}; - -class CSXOP : public Module -{ - XOPAccessProvider accessprovider; - CommandCSXOP commandcsxop; - - public: - CSXOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - accessprovider(this), commandcsxop(this) - { - this->SetPermanent(true); - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - order.clear(); - permissions.clear(); - - for (int i = 0; i < conf->CountBlock("privilege"); ++i) - { - Configuration::Block *block = conf->GetBlock("privilege", i); - const Anope::string &pname = block->Get<const Anope::string>("name"); - - Privilege *p = PrivilegeManager::FindPrivilege(pname); - if (p == NULL) - continue; - - const Anope::string &xop = block->Get<const Anope::string>("xop"); - if (pname.empty() || xop.empty()) - continue; - - permissions[xop].push_back(pname); - } - - for (int i = 0; i < conf->CountBlock("command"); ++i) - { - Configuration::Block *block = conf->GetBlock("command", i); - const Anope::string &cname = block->Get<const Anope::string>("name"), - &cserv = block->Get<const Anope::string>("command"); - if (cname.empty() || cserv != "chanserv/xop") - continue; - - order.push_back(cname); - } - } -}; - -MODULE_INIT(CSXOP) diff --git a/modules/commands/gl_global.cpp b/modules/commands/gl_global.cpp deleted file mode 100644 index dcc7c4780..000000000 --- a/modules/commands/gl_global.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* Global core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandGLGlobal : public Command -{ - ServiceReference<GlobalService> GService; - - public: - CommandGLGlobal(Module *creator) : Command(creator, "global/global", 1, 1), GService("GlobalService", "Global") - { - this->SetDesc(_("Send a message to all users")); - this->SetSyntax(_("\037message\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &msg = params[0]; - - if (!GService) - source.Reply("No global reference, is global loaded?"); - else - { - Log(LOG_ADMIN, source, this); - GService->SendGlobal(NULL, source.GetNick(), msg); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Administrators to send messages to all users on the\n" - "network. The message will be sent from the nick \002%s\002."), source.service->nick.c_str()); - return true; - } -}; - -class GLGlobal : public Module -{ - CommandGLGlobal commandglglobal; - - public: - GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandglglobal(this) - { - - } -}; - -MODULE_INIT(GLGlobal) diff --git a/modules/commands/greet.cpp b/modules/commands/greet.cpp deleted file mode 100644 index 0f61a1a6e..000000000 --- a/modules/commands/greet.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandBSSetGreet : public Command -{ - public: - CommandBSSetGreet(Module *creator, const Anope::string &sname = "botserv/set/greet") : Command(creator, sname, 2, 2) - { - this->SetDesc(_("Enable greet messages")); - this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - ChannelInfo *ci = ChannelInfo::Find(params[0]); - const Anope::string &value = params[1]; - - if (ci == NULL) - { - source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET")) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (value.equals_ci("ON")) - { - bool override = !source.AccessFor(ci).HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable greets"; - - ci->Extend<bool>("BS_GREET"); - source.Reply(_("Greet mode is now \002on\002 on channel %s."), ci->name.c_str()); - } - else if (value.equals_ci("OFF")) - { - bool override = !source.AccessFor(ci).HasPriv("SET"); - Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable greets"; - - ci->Shrink<bool>("BS_GREET"); - source.Reply(_("Greet mode is now \002off\002 on channel %s."), ci->name.c_str()); - } - else - this->OnSyntaxError(source, source.command); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(_(" \n" - "Enables or disables \002greet\002 mode on a channel.\n" - "When it is enabled, the bot will display greet\n" - "messages of users joining the channel, provided\n" - "they have enough access to the channel.")); - return true; - } -}; - -class CommandNSSetGreet : public Command -{ - public: - CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Associate a greet message with your nickname")); - this->SetSyntax(_("\037message\037")); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (!param.empty()) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the greet of " << nc->display; - nc->Extend<Anope::string>("greet", param); - source.Reply(_("Greet message for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str()); - } - else - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the greet of " << nc->display; - nc->Shrink<Anope::string>("greet"); - source.Reply(_("Greet message for \002%s\002 unset."), nc->display.c_str()); - } - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params.size() > 0 ? params[0] : ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Makes the given message the greet of your nickname, that\n" - "will be displayed when joining a channel that has GREET\n" - "option enabled, provided that you have the necessary\n" - "access on it.")); - return true; - } -}; - -class CommandNSSASetGreet : public CommandNSSetGreet -{ - public: - CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 \037message\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params.size() > 1 ? params[1] : ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Makes the given message the greet of the nickname, that\n" - "will be displayed when joining a channel that has GREET\n" - "option enabled, provided that the user has the necessary\n" - "access on it.")); - return true; - } -}; - -class Greet : public Module -{ - /* channel setting for whether or not greet should be shown */ - SerializableExtensibleItem<bool> bs_greet; - /* user greets */ - SerializableExtensibleItem<Anope::string> ns_greet; - - CommandBSSetGreet commandbssetgreet; - CommandNSSetGreet commandnssetgreet; - CommandNSSASetGreet commandnssasetgreet; - - public: - Greet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - bs_greet(this, "BS_GREET"), - ns_greet(this, "greet"), - commandbssetgreet(this), - commandnssetgreet(this), commandnssasetgreet(this) - { - } - - void OnJoinChannel(User *user, Channel *c) anope_override - { - /* Only display the greet if the main uplink we're connected - * to has synced, or we'll get greet-floods when the net - * recovers from a netsplit. -GD - */ - if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->Account()) - return; - - Anope::string *greet = ns_greet.Get(user->Account()); - if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET")) - { - IRCD->SendPrivmsg(*c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), greet->c_str()); - c->ci->bi->lastmsg = Anope::CurTime; - } - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override - { - Anope::string *greet = ns_greet.Get(na->nc); - if (greet != NULL) - info[_("Greet")] = *greet; - } - - void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override - { - if (bs_greet.HasExt(ci)) - info.AddOption(_("Greet")); - } -}; - -MODULE_INIT(Greet) diff --git a/modules/commands/help.cpp b/modules/commands/help.cpp deleted file mode 100644 index f6e459bde..000000000 --- a/modules/commands/help.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHelp : public Command -{ - static const unsigned help_wrap_len = 40; - - static CommandGroup *FindGroup(const Anope::string &name) - { - for (unsigned i = 0; i < Config->CommandGroups.size(); ++i) - { - CommandGroup &gr = Config->CommandGroups[i]; - if (gr.name == name) - return &gr; - } - - return NULL; - } - - public: - CommandHelp(Module *creator) : Command(creator, "generic/help", 0) - { - this->SetDesc(_("Displays this list and give information about commands")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - EventReturn MOD_RESULT; - FOREACH_RESULT(OnPreHelp, MOD_RESULT, (source, params)); - if (MOD_RESULT == EVENT_STOP) - return; - - Anope::string source_command = source.command; - const BotInfo *bi = source.service; - const CommandInfo::map &map = source.c ? Config->Fantasy : bi->commands; - bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), - hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); - - if (params.empty() || params[0].equals_ci("ALL")) - { - bool all = !params.empty() && params[0].equals_ci("ALL"); - typedef std::map<CommandGroup *, std::list<Anope::string> > GroupInfo; - GroupInfo groups; - - if (all) - source.Reply(_("All available commands for \002%s\002:"), source.service->nick.c_str()); - - for (CommandInfo::map::const_iterator it = map.begin(), it_end = map.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - - if (info.hide) - continue; - - // Smaller command exists - Anope::string cmd; - spacesepstream(c_name).GetToken(cmd, 0); - if (cmd != it->first && map.count(cmd)) - continue; - - ServiceReference<Command> c("Command", info.name); - if (!c) - continue; - - if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) - continue; - - if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) - continue; - - if (!info.group.empty() && !all) - { - CommandGroup *gr = FindGroup(info.group); - if (gr != NULL) - { - groups[gr].push_back(c_name); - continue; - } - } - - source.command = c_name; - c->OnServHelp(source); - - } - - for (GroupInfo::iterator it = groups.begin(), it_end = groups.end(); it != it_end; ++it) - { - CommandGroup *gr = it->first; - - source.Reply(" "); - source.Reply("%s", gr->description.c_str()); - - Anope::string buf; - for (std::list<Anope::string>::iterator it2 = it->second.begin(), it2_end = it->second.end(); it2 != it2_end; ++it2) - { - const Anope::string &c_name = *it2; - - buf += ", " + c_name; - - if (buf.length() > help_wrap_len) - { - source.Reply(" %s", buf.substr(2).c_str()); - buf.clear(); - } - } - if (buf.length() > 2) - { - source.Reply(" %s", buf.substr(2).c_str()); - buf.clear(); - } - } - if (!groups.empty()) - { - source.Reply(" "); - source.Reply(_("Use the \002%s ALL\002 command to list all commands and their descriptions."), source_command.c_str()); - } - } - else - { - bool helped = false; - for (unsigned max = params.size(); max > 0; --max) - { - Anope::string full_command; - for (unsigned i = 0; i < max; ++i) - full_command += " " + params[i]; - full_command.erase(full_command.begin()); - - CommandInfo::map::const_iterator it = map.find(full_command); - if (it == map.end()) - continue; - - const CommandInfo &info = it->second; - - ServiceReference<Command> c("Command", info.name); - if (!c) - continue; - - if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) - continue; - - // Allow unregistered users to see help for commands that they explicitly request help for - - const Anope::string &subcommand = params.size() > max ? params[max] : ""; - source.command = full_command; - if (!c->OnHelp(source, subcommand)) - continue; - - helped = true; - - /* Inform the user what permission is required to use the command */ - if (!info.permission.empty()) - { - source.Reply(" "); - source.Reply(_("Access to this command requires the permission \002%s\002 to be present in your opertype."), info.permission.c_str()); - } - if (!c->AllowUnregistered() && !source.nc) - { - if (info.permission.empty()) - source.Reply(" "); - source.Reply( _("You need to be identified to use this command.")); - } - /* User doesn't have the proper permission to use this command */ - else if (!info.permission.empty() && !source.HasCommand(info.permission)) - { - source.Reply(_("You cannot use this command.")); - } - - break; - } - - if (helped == false) - source.Reply(_("No help available for \002%s\002."), params[0].c_str()); - } - - FOREACH_MOD(OnPostHelp, (source, params)); - - return; - } -}; - -class Help : public Module -{ - CommandHelp commandhelp; - - public: - Help(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandhelp(this) - { - - } -}; - -MODULE_INIT(Help) diff --git a/modules/commands/hs_del.cpp b/modules/commands/hs_del.cpp deleted file mode 100644 index 02b2a1324..000000000 --- a/modules/commands/hs_del.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSDel : public Command -{ - public: - CommandHSDel(Module *creator) : Command(creator, "hostserv/del", 1, 1) - { - this->SetDesc(_("Delete the vhost of another user")); - this->SetSyntax(_("\037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nick = params[0]; - NickAlias *na = NickAlias::Find(nick); - if (na) - { - Log(LOG_ADMIN, source, this) << "for user " << na->nick; - FOREACH_MOD(OnDeleteVhost, (na)); - na->RemoveVhost(); - source.Reply(_("Vhost for \002%s\002 removed."), nick.c_str()); - } - else - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Deletes the vhost assigned to the given nick from the\n" - "database.")); - return true; - } -}; - -class CommandHSDelAll : public Command -{ - public: - CommandHSDelAll(Module *creator) : Command(creator, "hostserv/delall", 1, 1) - { - this->SetDesc(_("Deletes the vhost for all nicks in a group")); - this->SetSyntax(_("\037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nick = params[0]; - NickAlias *na = NickAlias::Find(nick); - if (na) - { - FOREACH_MOD(OnDeleteVhost, (na)); - const NickCore *nc = na->nc; - for (unsigned i = 0; i < nc->aliases->size(); ++i) - { - na = nc->aliases->at(i); - na->RemoveVhost(); - } - Log(LOG_ADMIN, source, this) << "for all nicks in group " << nc->display; - source.Reply(_("vhosts for group \002%s\002 have been removed."), nc->display.c_str()); - } - else - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Deletes the vhost for all nicks in the same group as\n" - "that of the given nick.")); - return true; - } -}; - -class HSDel : public Module -{ - CommandHSDel commandhsdel; - CommandHSDelAll commandhsdelall; - - public: - 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"); - } -}; - -MODULE_INIT(HSDel) diff --git a/modules/commands/hs_group.cpp b/modules/commands/hs_group.cpp deleted file mode 100644 index e6211b118..000000000 --- a/modules/commands/hs_group.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSGroup : public Command -{ - bool setting; - - public: - void Sync(const NickAlias *na) - { - if (setting) - return; - - if (!na || !na->HasVhost()) - return; - - setting = true; - for (unsigned i = 0; i < na->nc->aliases->size(); ++i) - { - NickAlias *nick = na->nc->aliases->at(i); - if (nick) - { - nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator()); - FOREACH_MOD(OnSetVhost, (nick)); - } - } - setting = false; - } - - CommandHSGroup(Module *creator) : Command(creator, "hostserv/group", 0, 0), setting(false) - { - this->SetDesc(_("Syncs the vhost for all nicks in a group")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - NickAlias *na = NickAlias::Find(source.GetNick()); - if (na && source.GetAccount() == na->nc && na->HasVhost()) - { - this->Sync(na); - if (!na->GetVhostIdent().empty()) - source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002@\002%s\002."), source.nc->display.c_str(), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str()); - else - source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002."), source.nc->display.c_str(), na->GetVhostHost().c_str()); - } - else - source.Reply(HOST_NOT_ASSIGNED); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command allows users to set the vhost of their\n" - "CURRENT nick to be the vhost for all nicks in the same\n" - "group.")); - return true; - } -}; - -class HSGroup : public Module -{ - CommandHSGroup commandhsgroup; - bool syncongroup; - bool synconset; - - public: - 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 - { - if (!synconset) - return; - - commandhsgroup.Sync(na); - } - - void OnNickGroup(User *u, NickAlias *na) anope_override - { - if (!syncongroup) - return; - - commandhsgroup.Sync(na); - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = conf->GetModule(this); - syncongroup = block->Get<bool>("syncongroup"); - synconset = block->Get<bool>("synconset"); - } -}; - -MODULE_INIT(HSGroup) diff --git a/modules/commands/hs_list.cpp b/modules/commands/hs_list.cpp deleted file mode 100644 index a5258b04c..000000000 --- a/modules/commands/hs_list.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSList : public Command -{ - public: - CommandHSList(Module *creator) : Command(creator, "hostserv/list", 0, 1) - { - this->SetDesc(_("Displays one or more vhost entries")); - this->SetSyntax(_("[\037key\037|\037#X-Y\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &key = !params.empty() ? params[0] : ""; - int from = 0, to = 0, counter = 1; - - /** - * Do a check for a range here, then in the next loop - * we'll only display what has been requested.. - **/ - if (!key.empty() && key[0] == '#') - { - size_t tmp = key.find('-'); - if (tmp == Anope::string::npos || tmp == key.length() || tmp == 1) - { - source.Reply(LIST_INCORRECT_RANGE); - return; - } - for (unsigned i = 1, end = key.length(); i < end; ++i) - { - if (!isdigit(key[i]) && i != tmp) - { - source.Reply(LIST_INCORRECT_RANGE); - return; - } - try - { - from = convertTo<int>(key.substr(1, tmp - 1)); - to = convertTo<int>(key.substr(tmp + 1)); - } - catch (const ConvertException &) { } - } - } - - unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50"); - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Creator")).AddColumn(_("Created")); - - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it) - { - const NickAlias *na = it->second; - - if (!na->HasVhost()) - continue; - - if (!key.empty() && key[0] != '#') - { - if ((Anope::Match(na->nick, key) || Anope::Match(na->GetVhostHost(), key)) && display_counter < listmax) - { - ++display_counter; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); - entry["Nick"] = na->nick; - if (!na->GetVhostIdent().empty()) - entry["Vhost"] = na->GetVhostIdent() + "@" + na->GetVhostHost(); - else - entry["Vhost"] = na->GetVhostHost(); - entry["Creator"] = na->GetVhostCreator(); - entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true); - list.AddEntry(entry); - } - } - else - { - /** - * List the host if its in the display range, and not more - * than NSListMax records have been displayed... - **/ - if (((counter >= from && counter <= to) || (!from && !to)) && display_counter < listmax) - { - ++display_counter; - ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); - entry["Nick"] = na->nick; - if (!na->GetVhostIdent().empty()) - entry["Vhost"] = na->GetVhostIdent() + "@" + na->GetVhostHost(); - else - entry["Vhost"] = na->GetVhostHost(); - entry["Creator"] = na->GetVhostCreator(); - entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true); - list.AddEntry(entry); - } - } - ++counter; - } - - if (!display_counter) - { - source.Reply(_("No records to display.")); - return; - } - - if (!key.empty()) - source.Reply(_("Displayed records matching key \002%s\002 (count: \002%d\002)."), key.c_str(), display_counter); - else - { - if (from) - source.Reply(_("Displayed records from \002%d\002 to \002%d\002."), from, to); - else - source.Reply(_("Displayed all records (count: \002%d\002)."), display_counter); - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command lists registered vhosts to the operator.\n" - "If a \037key\037 is specified, only entries whose nick or vhost match\n" - "the pattern given in \037key\037 are displayed e.g. Rob* for all\n" - "entries beginning with \"Rob\"\n" - "If a \037#X-Y\037 style is used, only entries between the range of \002X\002\n" - "and \002Y\002 will be displayed, e.g. \002#1-3\002 will display the first 3\n" - "nick/vhost entries.")); - return true; - } -}; - -class HSList : public Module -{ - CommandHSList commandhslist; - - public: - 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"); - } -}; - -MODULE_INIT(HSList) diff --git a/modules/commands/hs_off.cpp b/modules/commands/hs_off.cpp deleted file mode 100644 index 75c8cf62a..000000000 --- a/modules/commands/hs_off.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSOff : public Command -{ - public: - CommandHSOff(Module *creator) : Command(creator, "hostserv/off", 0, 0) - { - this->SetDesc(_("Deactivates your assigned vhost")); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - - const NickAlias *na = NickAlias::Find(u->nick); - if (!na || na->nc != u->Account() || !na->HasVhost()) - na = NickAlias::Find(u->Account()->display); - - if (!na || !na->HasVhost()) - source.Reply(HOST_NOT_ASSIGNED); - else - { - u->vhost.clear(); - 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.")); - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Deactivates the vhost currently assigned to the nick in use.\n" - "When you use this command any user who performs a /whois\n" - "on you will see your real host/IP address.")); - return true; - } -}; - -class HSOff : public Module -{ - CommandHSOff commandhsoff; - - public: - 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"); - } -}; - -MODULE_INIT(HSOff) diff --git a/modules/commands/hs_on.cpp b/modules/commands/hs_on.cpp deleted file mode 100644 index 5aa20380c..000000000 --- a/modules/commands/hs_on.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSOn : public Command -{ - public: - CommandHSOn(Module *creator) : Command(creator, "hostserv/on", 0, 0) - { - this->SetDesc(_("Activates your assigned vhost")); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!IRCD->CanSetVHost) - return; // HostServ wouldn't even be loaded at this point - - User *u = source.GetUser(); - const NickAlias *na = NickAlias::Find(u->nick); - if (!na || na->nc != u->Account() || !na->HasVhost()) - na = NickAlias::Find(u->Account()->display); - if (na && u->Account() == na->nc && na->HasVhost()) - { - if (!na->GetVhostIdent().empty()) - source.Reply(_("Your vhost of \002%s\002@\002%s\002 is now activated."), na->GetVhostIdent().c_str(), na->GetVhostHost().c_str()); - else - source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str()); - Log(LOG_COMMAND, source, this) << "to enable their vhost of " << (!na->GetVhostIdent().empty() ? na->GetVhostIdent() + "@" : "") << na->GetVhostHost(); - IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost()); - u->vhost = na->GetVhostHost(); - if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty()) - u->SetVIdent(na->GetVhostIdent()); - u->UpdateHost(); - } - else - source.Reply(HOST_NOT_ASSIGNED); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Activates the vhost currently assigned to the nick in use.\n" - "When you use this command any user who performs a /whois\n" - "on you will see the vhost instead of your real host/IP address.")); - return true; - } -}; - -class HSOn : public Module -{ - CommandHSOn commandhson; - - public: - 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"); - } -}; - -MODULE_INIT(HSOn) diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp deleted file mode 100644 index 12979e804..000000000 --- a/modules/commands/hs_request.cpp +++ /dev/null @@ -1,394 +0,0 @@ -/* hs_request.c - Add request and activate functionality to HostServ - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Based on the original module by Rob <rob@anope.org> - * Included in the Anope module pack since Anope 1.7.11 - * Anope Coder: GeniusDex <geniusdex@anope.org> - * - * Please read COPYING and README for further details. - * - * Send bug reports to the Anope Coder instead of the module - * author, because any changes since the inclusion into anope - * are not supported by the original author. - */ - -#include "module.h" - -static ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ"); - -static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost); - -struct HostRequest : Serializable -{ - Anope::string nick; - Anope::string ident; - Anope::string host; - time_t time; - - HostRequest(Extensible *) : Serializable("HostRequest") { } - - void Serialize(Serialize::Data &data) const anope_override - { - data["nick"] << this->nick; - data["ident"] << this->ident; - data["host"] << this->host; - data.SetType("time", Serialize::Data::DT_INT); data["time"] << this->time; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string snick; - data["nick"] >> snick; - - NickAlias *na = NickAlias::Find(snick); - if (na == NULL) - return NULL; - - HostRequest *req; - if (obj) - req = anope_dynamic_static_cast<HostRequest *>(obj); - else - req = na->Extend<HostRequest>("hostrequest"); - if (req) - { - req->nick = na->nick; - data["ident"] >> req->ident; - data["host"] >> req->host; - data["time"] >> req->time; - } - - return req; - } -}; - -class CommandHSRequest : public Command -{ - bool isvalidchar(char c) - { - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-') - return true; - return false; - } - - public: - CommandHSRequest(Module *creator) : Command(creator, "hostserv/request", 1, 1) - { - this->SetDesc(_("Request a vHost for your nick")); - this->SetSyntax(_("vhost")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - User *u = source.GetUser(); - NickAlias *na = NickAlias::Find(source.GetNick()); - if (!na || na->nc != source.GetAccount()) - { - source.Reply(ACCESS_DENIED); - return; - } - - if (source.GetAccount()->HasExt("UNCONFIRMED")) - { - source.Reply(_("You must confirm your account before you may request a vhost.")); - return; - } - - Anope::string rawhostmask = params[0]; - - Anope::string user, host; - size_t a = rawhostmask.find('@'); - - if (a == Anope::string::npos) - host = rawhostmask; - else - { - user = rawhostmask.substr(0, a); - host = rawhostmask.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - if (!user.empty()) - { - if (user.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen")) - { - source.Reply(HOST_SET_IDENTTOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("userlen")); - return; - } - else if (!IRCD->CanSetVIdent) - { - source.Reply(HOST_NO_VIDENT); - return; - } - for (Anope::string::iterator s = user.begin(), s_end = user.end(); s != s_end; ++s) - if (!isvalidchar(*s)) - { - source.Reply(HOST_SET_IDENT_ERROR); - return; - } - } - - if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")) - { - source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")); - return; - } - - if (!IRCD->IsHostValid(host)) - { - source.Reply(HOST_SET_ERROR); - return; - } - - time_t send_delay = Config->GetModule("memoserv")->Get<time_t>("senddelay"); - if (Config->GetModule(this->owner)->Get<bool>("memooper") && send_delay > 0 && u && u->lastmemosend + send_delay > Anope::CurTime) - { - source.Reply(_("Please wait %d seconds before requesting a new vHost."), send_delay); - u->lastmemosend = Anope::CurTime; - return; - } - - HostRequest req(na); - req.nick = source.GetNick(); - req.ident = user; - req.host = host; - req.time = Anope::CurTime; - na->Extend<HostRequest>("hostrequest", req); - - source.Reply(_("Your vHost has been requested.")); - req_send_memos(owner, source, user, host); - Log(LOG_COMMAND, source, this) << "to request new vhost " << (!user.empty() ? user + "@" : "") << host; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Request the given vHost to be activated for your nick by the\n" - "network administrators. Please be patient while your request\n" - "is being considered.")); - return true; - } -}; - -class CommandHSActivate : public Command -{ - public: - CommandHSActivate(Module *creator) : Command(creator, "hostserv/activate", 1, 1) - { - this->SetDesc(_("Approve the requested vHost of a user")); - this->SetSyntax(_("\037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nick = params[0]; - - NickAlias *na = NickAlias::Find(nick); - HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL; - if (req) - { - na->SetVhost(req->ident, req->host, source.GetNick(), req->time); - FOREACH_MOD(OnSetVhost, (na)); - - if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv) - memoserv->Send(source.service->nick, na->nick, _("[auto memo] Your requested vHost has been approved."), true); - - source.Reply(_("vHost for %s has been activated."), na->nick.c_str()); - Log(LOG_COMMAND, source, this) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host; - na->Shrink<HostRequest>("hostrequest"); - } - else - source.Reply(_("No request for nick %s found."), nick.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Activate the requested vHost for the given nick.")); - if (Config->GetModule(this->owner)->Get<bool>("memouser")) - source.Reply(_("A memo informing the user will also be sent.")); - - return true; - } -}; - -class CommandHSReject : public Command -{ - public: - CommandHSReject(Module *creator) : Command(creator, "hostserv/reject", 1, 2) - { - this->SetDesc(_("Reject the requested vHost of a user")); - this->SetSyntax(_("\037nick\037 [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nick = params[0]; - const Anope::string &reason = params.size() > 1 ? params[1] : ""; - - NickAlias *na = NickAlias::Find(nick); - HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL; - if (req) - { - na->Shrink<HostRequest>("hostrequest"); - - if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv) - { - Anope::string message; - if (!reason.empty()) - message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); - else - message = _("[auto memo] Your requested vHost has been rejected."); - - memoserv->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true); - } - - source.Reply(_("vHost for %s has been rejected."), nick.c_str()); - Log(LOG_COMMAND, source, this) << "to reject vhost for " << nick << " (" << (!reason.empty() ? reason : "no reason") << ")"; - } - else - source.Reply(_("No request for nick %s found."), nick.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Reject the requested vHost for the given nick.")); - if (Config->GetModule(this->owner)->Get<bool>("memouser")) - source.Reply(_("A memo informing the user will also be sent, which includes the reason for the rejection if supplied.")); - - return true; - } -}; - -class CommandHSWaiting : public Command -{ - public: - CommandHSWaiting(Module *creator) : Command(creator, "hostserv/waiting", 0, 0) - { - this->SetDesc(_("Retrieves the vhost requests")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - unsigned counter = 0; - unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax"); - ListFormatter list(source.GetAccount()); - - list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Created")); - - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it) - { - const NickAlias *na = it->second; - HostRequest *hr = na->GetExt<HostRequest>("hostrequest"); - if (!hr) - continue; - - if (!listmax || display_counter < listmax) - { - ++display_counter; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(display_counter); - entry["Nick"] = it->first; - if (!hr->ident.empty()) - entry["Vhost"] = hr->ident + "@" + hr->host; - else - entry["Vhost"] = hr->host; - entry["Created"] = Anope::strftime(hr->time, NULL, true); - list.AddEntry(entry); - } - ++counter; - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("Displayed \002%d\002 records (\002%d\002 total)."), display_counter, counter); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command retrieves the vhost requests.")); - - return true; - } -}; - -class HSRequest : public Module -{ - CommandHSRequest commandhsrequest; - CommandHSActivate commandhsactive; - CommandHSReject commandhsreject; - CommandHSWaiting commandhswaiting; - ExtensibleItem<HostRequest> hostrequest; - Serialize::Type request_type; - - public: - HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - 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"); - } -}; - -static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost) -{ - Anope::string host; - std::list<std::pair<Anope::string, Anope::string> >::iterator it, it_end; - - if (!vIdent.empty()) - host = vIdent + "@" + vHost; - else - host = vHost; - - if (Config->GetModule(me)->Get<bool>("memooper") && memoserv) - for (unsigned i = 0; i < Oper::opers.size(); ++i) - { - Oper *o = Oper::opers[i]; - - const NickAlias *na = NickAlias::Find(o->name); - if (!na) - continue; - - Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.GetNick().c_str()); - - memoserv->Send(source.service->nick, na->nick, message, true); - } -} - -MODULE_INIT(HSRequest) diff --git a/modules/commands/hs_set.cpp b/modules/commands/hs_set.cpp deleted file mode 100644 index 4c736a77d..000000000 --- a/modules/commands/hs_set.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* HostServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandHSSet : public Command -{ - public: - CommandHSSet(Module *creator) : Command(creator, "hostserv/set", 2, 2) - { - this->SetDesc(_("Set the vhost of another user")); - this->SetSyntax(_("\037nick\037 \037hostmask\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nick = params[0]; - - NickAlias *na = NickAlias::Find(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - - Anope::string rawhostmask = params[1]; - - Anope::string user, host; - size_t a = rawhostmask.find('@'); - - if (a == Anope::string::npos) - host = rawhostmask; - else - { - user = rawhostmask.substr(0, a); - host = rawhostmask.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - if (!user.empty()) - { - if (!IRCD->CanSetVIdent) - { - source.Reply(HOST_NO_VIDENT); - return; - } - else if (!IRCD->IsIdentValid(user)) - { - source.Reply(HOST_SET_IDENT_ERROR); - return; - } - } - - if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")) - { - source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")); - return; - } - - if (!IRCD->IsHostValid(host)) - { - source.Reply(HOST_SET_ERROR); - return; - } - - Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host; - - na->SetVhost(user, host, source.GetNick()); - FOREACH_MOD(OnSetVhost, (na)); - if (!user.empty()) - source.Reply(_("VHost for \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); - else - source.Reply(_("VHost for \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the vhost for the given nick to that of the given\n" - "hostmask. If your IRCD supports vIdents, then using\n" - "SET <nick> <ident>@<hostmask> set idents for users as\n" - "well as vhosts.")); - return true; - } -}; - -class CommandHSSetAll : public Command -{ - void Sync(const NickAlias *na) - { - if (!na || !na->HasVhost()) - return; - - for (unsigned i = 0; i < na->nc->aliases->size(); ++i) - { - NickAlias *nick = na->nc->aliases->at(i); - if (nick) - nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator()); - } - } - - public: - CommandHSSetAll(Module *creator) : Command(creator, "hostserv/setall", 2, 2) - { - this->SetDesc(_("Set the vhost for all nicks in a group")); - this->SetSyntax(_("\037nick\037 \037hostmask\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - Anope::string nick = params[0]; - - NickAlias *na = NickAlias::Find(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - - Anope::string rawhostmask = params[1]; - - Anope::string user, host; - size_t a = rawhostmask.find('@'); - - if (a == Anope::string::npos) - host = rawhostmask; - else - { - user = rawhostmask.substr(0, a); - host = rawhostmask.substr(a + 1); - } - - if (host.empty()) - { - this->OnSyntaxError(source, ""); - return; - } - - if (!user.empty()) - { - if (!IRCD->CanSetVIdent) - { - source.Reply(HOST_NO_VIDENT); - return; - } - else if (!IRCD->IsIdentValid(user)) - { - source.Reply(HOST_SET_IDENT_ERROR); - return; - } - } - - if (host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")) - { - source.Reply(HOST_SET_TOOLONG, Config->GetBlock("networkinfo")->Get<unsigned>("hostlen")); - return; - } - - if (!IRCD->IsHostValid(host)) - { - source.Reply(HOST_SET_ERROR); - return; - } - - Log(LOG_ADMIN, source, this) << "to set the vhost of " << na->nick << " to " << (!user.empty() ? user + "@" : "") << host; - - na->SetVhost(user, host, source.GetNick()); - this->Sync(na); - FOREACH_MOD(OnSetVhost, (na)); - if (!user.empty()) - source.Reply(_("VHost for group \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), user.c_str(), host.c_str()); - else - source.Reply(_("VHost for group \002%s\002 set to \002%s\002."), nick.c_str(), host.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets the vhost for all nicks in the same group as that\n" - "of the given nick. If your IRCD supports vIdents, then\n" - "using SETALL <nick> <ident>@<hostmask> will set idents\n" - "for users as well as vhosts.\n" - "* NOTE, this will not update the vhost for any nicks\n" - "added to the group after this command was used.")); - return true; - } -}; - -class HSSet : public Module -{ - CommandHSSet commandhsset; - CommandHSSetAll commandhssetall; - - 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"); - } -}; - -MODULE_INIT(HSSet) diff --git a/modules/commands/ms_cancel.cpp b/modules/commands/ms_cancel.cpp deleted file mode 100644 index 9e6f0ce63..000000000 --- a/modules/commands/ms_cancel.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSCancel : public Command -{ - public: - CommandMSCancel(Module *creator) : Command(creator, "memoserv/cancel", 1, 1) - { - this->SetDesc(_("Cancel the last memo you sent")); - this->SetSyntax(_("{\037nick\037 | \037channel\037}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const Anope::string &nname = params[0]; - - bool ischan; - MemoInfo *mi = MemoInfo::GetMemoInfo(nname, ischan); - - if (mi == NULL) - source.Reply(ischan ? CHAN_X_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), nname.c_str()); - else - { - ChannelInfo *ci = NULL; - NickAlias *na = NULL; - if (ischan) - ci = ChannelInfo::Find(nname); - else - na = NickAlias::Find(nname); - for (int i = mi->memos->size() - 1; i >= 0; --i) - if (mi->GetMemo(i)->unread && source.nc->display.equals_ci(mi->GetMemo(i)->sender)) - { - FOREACH_MOD(OnMemoDel, (ischan ? ci->name : na->nc->display, mi, mi->GetMemo(i))); - mi->Del(i); - source.Reply(_("Last memo to \002%s\002 has been cancelled."), nname.c_str()); - return; - } - - source.Reply(_("No memo was cancelable.")); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Cancels the last memo you sent to the given nick or channel,\n" - "provided it has not been read at the time you use the command.")); - return true; - } -}; - -class MSCancel : public Module -{ - CommandMSCancel commandmscancel; - - public: - MSCancel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmscancel(this) - { - } -}; - -MODULE_INIT(MSCancel) diff --git a/modules/commands/ms_check.cpp b/modules/commands/ms_check.cpp deleted file mode 100644 index 707da95cd..000000000 --- a/modules/commands/ms_check.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSCheck : public Command -{ - public: - CommandMSCheck(Module *creator) : Command(creator, "memoserv/check", 1, 1) - { - this->SetDesc(_("Checks if last memo to a nick was read")); - this->SetSyntax(_("\037nick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - const Anope::string &recipient = params[0]; - - bool found = false; - - const NickAlias *na = NickAlias::Find(recipient); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, recipient.c_str()); - return; - } - - MemoInfo *mi = &na->nc->memos; - - /* 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) - { - Memo *m = mi->GetMemo(i - 1); - NickAlias *na2 = NickAlias::Find(m->sender); - - if (na2 != NULL && na2->nc == source.GetAccount()) - { - found = true; /* Yes, we've found the memo */ - - if (m->unread) - source.Reply(_("The last memo you sent to %s (sent on %s) has not yet been read."), na->nick.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str()); - else - source.Reply(_("The last memo you sent to %s (sent on %s) has been read."), na->nick.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str()); - break; - } - } - - if (!found) - source.Reply(_("Nick %s doesn't have a memo from you."), na->nick.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Checks whether the _last_ memo you sent to \037nick\037 has been read\n" - "or not. Note that this only works with nicks, not with channels.")); - return true; - } -}; - -class MSCheck : public Module -{ - CommandMSCheck commandmscheck; - - public: - MSCheck(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmscheck(this) - { - - } -}; - -MODULE_INIT(MSCheck) diff --git a/modules/commands/ms_del.cpp b/modules/commands/ms_del.cpp deleted file mode 100644 index bc496d72e..000000000 --- a/modules/commands/ms_del.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class MemoDelCallback : public NumberList -{ - CommandSource &source; - ChannelInfo *ci; - MemoInfo *mi; - public: - MemoDelCallback(CommandSource &_source, ChannelInfo *_ci, MemoInfo *_mi, const Anope::string &list) : NumberList(list, true), source(_source), ci(_ci), mi(_mi) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > mi->memos->size()) - return; - - FOREACH_MOD(OnMemoDel, (ci ? ci->name : source.nc->display, mi, mi->GetMemo(number - 1))); - - mi->Del(number - 1); - source.Reply(_("Memo %d has been deleted."), number); - } -}; - -class CommandMSDel : public Command -{ - public: - CommandMSDel(Module *creator) : Command(creator, "memoserv/del", 0, 2) - { - this->SetDesc(_("Delete a memo or memos")); - this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | ALL}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - MemoInfo *mi; - ChannelInfo *ci = NULL; - Anope::string numstr = !params.empty() ? params[0] : "", chan; - - if (!numstr.empty() && numstr[0] == '#') - { - chan = numstr; - numstr = params.size() > 1 ? params[1] : ""; - - ci = ChannelInfo::Find(chan); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - else if (!source.AccessFor(ci).HasPriv("MEMO")) - { - source.Reply(ACCESS_DENIED); - return; - } - mi = &ci->memos; - } - else - mi = &source.nc->memos; - if (numstr.empty() || (!isdigit(numstr[0]) && !numstr.equals_ci("ALL") && !numstr.equals_ci("LAST"))) - this->OnSyntaxError(source, numstr); - else if (mi->memos->empty()) - { - if (!chan.empty()) - source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); - else - source.Reply(MEMO_HAVE_NO_MEMOS); - } - else - { - if (isdigit(numstr[0])) - { - MemoDelCallback list(source, ci, mi, numstr); - list.Process(); - } - else if (numstr.equals_ci("LAST")) - { - /* Delete last memo. */ - FOREACH_MOD(OnMemoDel, (ci ? ci->name : source.nc->display, mi, mi->GetMemo(mi->memos->size() - 1))); - mi->Del(mi->memos->size() - 1); - source.Reply(_("Memo %d has been deleted."), mi->memos->size() + 1); - } - else - { - /* Delete all memos. */ - for (unsigned i = mi->memos->size(); i > 0; --i) - { - FOREACH_MOD(OnMemoDel, (ci ? ci->name : source.nc->display, mi, mi->GetMemo(i))); - mi->Del(i - 1); - } - if (!chan.empty()) - source.Reply(_("All memos for channel %s have been deleted."), chan.c_str()); - else - source.Reply(_("All of your memos have been deleted.")); - } - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Deletes the specified memo or memos. You can supply\n" - "multiple memo numbers or ranges of numbers instead of a\n" - "single number, as in the second example below.\n" - " \n" - "If \002LAST\002 is given, the last memo will be deleted.\n" - "If \002ALL\002 is given, deletes all of your memos.\n" - " \n" - "Examples:\n" - " \n" - " \002DEL 1\002\n" - " Deletes your first memo.\n" - " \n" - " \002DEL 2-5,7-9\002\n" - " Deletes memos numbered 2 through 5 and 7 through 9.")); - return true; - } -}; - -class MSDel : public Module -{ - CommandMSDel commandmsdel; - - public: - MSDel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsdel(this) - { - - } -}; - -MODULE_INIT(MSDel) diff --git a/modules/commands/ms_ignore.cpp b/modules/commands/ms_ignore.cpp deleted file mode 100644 index 6a2fa01cf..000000000 --- a/modules/commands/ms_ignore.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSIgnore : public Command -{ - public: - CommandMSIgnore(Module *creator) : Command(creator, "memoserv/ignore", 1, 3) - { - this->SetDesc(_("Manage the memo ignore list")); - this->SetSyntax(_("[\037channel\037] ADD \037entry\037")); - this->SetSyntax(_("[\037channel\037] DEL \037entry\037")); - this->SetSyntax(_("[\037channel\037] LIST")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - Anope::string channel = params[0]; - Anope::string command = (params.size() > 1 ? params[1] : ""); - Anope::string param = (params.size() > 2 ? params[2] : ""); - - if (channel[0] != '#') - { - param = command; - command = channel; - channel = source.GetNick(); - } - - bool ischan; - MemoInfo *mi = MemoInfo::GetMemoInfo(channel, ischan); - ChannelInfo *ci = ChannelInfo::Find(channel); - if (!mi) - source.Reply(ischan ? CHAN_X_NOT_REGISTERED : _(NICK_X_NOT_REGISTERED), channel.c_str()); - else if (ischan && !source.AccessFor(ci).HasPriv("MEMO")) - source.Reply(ACCESS_DENIED); - else if (command.equals_ci("ADD") && !param.empty()) - { - if (mi->ignores.size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32")) - { - source.Reply(_("Sorry, the memo ignore list for \002%s\002 is full."), channel.c_str()); - return; - } - - if (std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()) == mi->ignores.end()) - { - mi->ignores.push_back(param.ci_str()); - source.Reply(_("\002%s\002 added to ignore list."), param.c_str()); - } - else - source.Reply(_("\002%s\002 is already on the ignore list."), param.c_str()); - } - else if (command.equals_ci("DEL") && !param.empty()) - { - std::vector<Anope::string>::iterator it = std::find(mi->ignores.begin(), mi->ignores.end(), param.ci_str()); - - if (it != mi->ignores.end()) - { - mi->ignores.erase(it); - source.Reply(_("\002%s\002 removed from the ignore list."), param.c_str()); - } - else - source.Reply(_("\002%s\002 is not on the ignore list."), param.c_str()); - } - else if (command.equals_ci("LIST")) - { - if (mi->ignores.empty()) - source.Reply(_("Memo ignore list is empty.")); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Mask")); - for (unsigned i = 0; i < mi->ignores.size(); ++i) - { - ListFormatter::ListEntry entry; - entry["Mask"] = mi->ignores[i]; - list.AddEntry(entry); - } - - source.Reply(_("Ignore list:")); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to ignore users by nick or host from memoing\n" - "you or a channel. If someone on the memo ignore list tries\n" - "to memo you or a channel, they will not be told that you have\n" - "them ignored.")); - return true; - } -}; - -class MSIgnore : public Module -{ - CommandMSIgnore commandmsignore; - - public: - MSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsignore(this) - { - } -}; - -MODULE_INIT(MSIgnore) diff --git a/modules/commands/ms_info.cpp b/modules/commands/ms_info.cpp deleted file mode 100644 index 8f99557bf..000000000 --- a/modules/commands/ms_info.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSInfo : public Command -{ - public: - CommandMSInfo(Module *creator) : Command(creator, "memoserv/info", 0, 1) - { - this->SetDesc(_("Displays information about your memos")); - this->SetSyntax(_("[\037nick\037 | \037channel\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - NickCore *nc = source.nc; - const MemoInfo *mi; - const NickAlias *na = NULL; - ChannelInfo *ci = NULL; - const Anope::string &nname = !params.empty() ? params[0] : ""; - bool hardmax; - - if (!nname.empty() && nname[0] != '#' && source.HasPriv("memoserv/info")) - { - na = NickAlias::Find(nname); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nname.c_str()); - return; - } - mi = &na->nc->memos; - hardmax = na->nc->HasExt("MEMO_HARDMAX"); - } - else if (!nname.empty() && nname[0] == '#') - { - ci = ChannelInfo::Find(nname); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, nname.c_str()); - return; - } - else if (!source.AccessFor(ci).HasPriv("MEMO")) - { - source.Reply(ACCESS_DENIED); - return; - } - mi = &ci->memos; - hardmax = ci->HasExt("MEMO_HARDMAX"); - } - else if (!nname.empty()) /* It's not a chan and we aren't services admin */ - { - source.Reply(ACCESS_DENIED); - return; - } - else - { - mi = &nc->memos; - hardmax = nc->HasExt("MEMO_HARDMAX"); - } - - if (!nname.empty() && (ci || na->nc != nc)) - { - if (mi->memos->empty()) - source.Reply(_("%s currently has no memos."), nname.c_str()); - else if (mi->memos->size() == 1) - { - if (mi->GetMemo(0)->unread) - source.Reply(_("%s currently has \0021\002 memo, and it has not yet been read."), nname.c_str()); - else - source.Reply(_("%s currently has \0021\002 memo."), nname.c_str()); - } - else - { - unsigned count = 0, i, end; - for (i = 0, end = mi->memos->size(); i < end; ++i) - if (mi->GetMemo(i)->unread) - ++count; - if (count == mi->memos->size()) - source.Reply(_("%s currently has \002%d\002 memos; all of them are unread."), nname.c_str(), count); - else if (!count) - source.Reply(_("%s currently has \002%d\002 memos."), nname.c_str(), mi->memos->size()); - else if (count == 1) - source.Reply(_("%s currently has \002%d\002 memos, of which \0021\002 is unread."), nname.c_str(), mi->memos->size()); - else - source.Reply(_("%s currently has \002%d\002 memos, of which \002%d\002 are unread."), nname.c_str(), mi->memos->size(), count); - } - if (!mi->memomax) - { - if (hardmax) - source.Reply(_("%s's memo limit is \002%d\002, and may not be changed."), nname.c_str(), mi->memomax); - else - source.Reply(_("%s's memo limit is \002%d\002."), nname.c_str(), mi->memomax); - } - else if (mi->memomax > 0) - { - if (hardmax) - source.Reply(_("%s's memo limit is \002%d\002, and may not be changed."), nname.c_str(), mi->memomax); - else - source.Reply(_("%s's memo limit is \002%d\002."), nname.c_str(), mi->memomax); - } - else - source.Reply(_("%s has no memo limit."), nname.c_str()); - - /* I ripped this code out of ircservices 4.4.5, since I didn't want - to rewrite the whole thing (it pisses me off). */ - if (na) - { - if (na->nc->HasExt("MEMO_RECEIVE") && na->nc->HasExt("MEMO_SIGNON")) - source.Reply(_("%s is notified of new memos at logon and when they arrive."), nname.c_str()); - else if (na->nc->HasExt("MEMO_RECEIVE")) - source.Reply(_("%s is notified when new memos arrive."), nname.c_str()); - else if (na->nc->HasExt("MEMO_SIGNON")) - source.Reply(_("%s is notified of news memos at logon."), nname.c_str()); - else - source.Reply(_("%s is not notified of new memos."), nname.c_str()); - } - } - else /* !nname || (!ci || na->nc == nc) */ - { - if (mi->memos->empty()) - source.Reply(_("You currently have no memos.")); - else if (mi->memos->size() == 1) - { - if (mi->GetMemo(0)->unread) - source.Reply(_("You currently have \0021\002 memo, and it has not yet been read.")); - else - source.Reply(_("You currently have \0021\002 memo.")); - } - else - { - unsigned count = 0, i, end; - for (i = 0, end = mi->memos->size(); i < end; ++i) - if (mi->GetMemo(i)->unread) - ++count; - if (count == mi->memos->size()) - source.Reply(_("You currently have \002%d\002 memos; all of them are unread."), count); - else if (!count) - source.Reply(_("You currently have \002%d\002 memos."), mi->memos->size()); - else if (count == 1) - source.Reply(_("You currently have \002%d\002 memos, of which \0021\002 is unread."), mi->memos->size()); - else - source.Reply(_("You currently have \002%d\002 memos, of which \002%d\002 are unread."), mi->memos->size(), count); - } - - if (!mi->memomax) - { - if (!source.IsServicesOper() && hardmax) - source.Reply(_("Your memo limit is \0020\002; you will not receive any new memos. You cannot change this limit.")); - else - source.Reply(_("Your memo limit is \0020\002; you will not receive any new memos.")); - } - else if (mi->memomax > 0) - { - if (!source.IsServicesOper() && hardmax) - source.Reply(_("Your memo limit is \002%d\002, and may not be changed."), mi->memomax); - else - source.Reply(_("Your memo limit is \002%d\002."), mi->memomax); - } - else - source.Reply(_("You have no limit on the number of memos you may keep.")); - - bool memo_mail = nc->HasExt("MEMO_MAIL"); - if (nc->HasExt("MEMO_RECEIVE") && nc->HasExt("MEMO_SIGNON")) - { - if (memo_mail) - source.Reply(_("You will be notified of new memos at logon and when they arrive, and by mail when they arrive.")); - else - source.Reply(_("You will be notified of new memos at logon and when they arrive.")); - } - else if (nc->HasExt("MEMO_RECEIVE")) - { - if (memo_mail) - source.Reply(_("You will be notified by message and by mail when new memos arrive.")); - else - source.Reply(_("You will be notified when new memos arrive.")); - } - else if (nc->HasExt("MEMO_SIGNON")) - { - if (memo_mail) - source.Reply(_("You will be notified of new memos at logon, and by mail when they arrive.")); - else - source.Reply(_("You will be notified of new memos at logon.")); - } - else - { - source.Reply(_("You will not be notified of new memos.")); - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Without a parameter, displays information on the number of\n" - "memos you have, how many of them are unread, and how many\n" - "total memos you can receive.\n" - " \n" - "With a channel parameter, displays the same information for\n" - "the given channel.\n" - " \n" - "With a nickname parameter, displays the same information\n" - "for the given nickname. This is limited to \002Services\002\n" - "\002Operators\002.")); - - return true; - } -}; - -class MSInfo : public Module -{ - CommandMSInfo commandmsinfo; - - public: - MSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsinfo(this) - { - - } -}; - -MODULE_INIT(MSInfo) diff --git a/modules/commands/ms_list.cpp b/modules/commands/ms_list.cpp deleted file mode 100644 index c386be81d..000000000 --- a/modules/commands/ms_list.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSList : public Command -{ - public: - CommandMSList(Module *creator) : Command(creator, "memoserv/list", 0, 2) - { - this->SetDesc(_("List your memos")); - this->SetSyntax(_("[\037channel\037] [\037list\037 | NEW]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - Anope::string param = !params.empty() ? params[0] : "", chan; - ChannelInfo *ci = NULL; - const MemoInfo *mi; - - if (!param.empty() && param[0] == '#') - { - chan = param; - param = params.size() > 1 ? params[1] : ""; - - ci = ChannelInfo::Find(chan); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - else if (!source.AccessFor(ci).HasPriv("MEMO")) - { - source.Reply(ACCESS_DENIED); - return; - } - mi = &ci->memos; - } - else - mi = &source.nc->memos; - - if (!param.empty() && !isdigit(param[0]) && !param.equals_ci("NEW")) - this->OnSyntaxError(source, param); - else if (!mi->memos->size()) - { - if (!chan.empty()) - source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); - else - source.Reply(MEMO_HAVE_NO_MEMOS); - } - else - { - ListFormatter list(source.GetAccount()); - - list.AddColumn(_("Number")).AddColumn(_("Sender")).AddColumn(_("Date/Time")); - - if (!param.empty() && isdigit(param[0])) - { - class MemoListCallback : public NumberList - { - ListFormatter &list; - CommandSource &source; - const MemoInfo *mi; - public: - MemoListCallback(ListFormatter &_list, CommandSource &_source, const MemoInfo *_mi, const Anope::string &numlist) : NumberList(numlist, false), list(_list), source(_source), mi(_mi) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > mi->memos->size()) - return; - - const Memo *m = mi->GetMemo(number - 1); - - ListFormatter::ListEntry entry; - entry["Number"] = (m->unread ? "* " : " ") + stringify(number); - entry["Sender"] = m->sender; - entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount()); - this->list.AddEntry(entry); - } - } - mlc(list, source, mi, param); - mlc.Process(); - } - else - { - if (!param.empty()) - { - unsigned i, end; - for (i = 0, end = mi->memos->size(); i < end; ++i) - if (mi->GetMemo(i)->unread) - break; - if (i == end) - { - if (!chan.empty()) - source.Reply(MEMO_X_HAS_NO_NEW_MEMOS, chan.c_str()); - else - source.Reply(MEMO_HAVE_NO_NEW_MEMOS); - return; - } - } - - for (unsigned i = 0, end = mi->memos->size(); i < end; ++i) - { - if (!param.empty() && !mi->GetMemo(i)->unread) - continue; - - const Memo *m = mi->GetMemo(i); - - ListFormatter::ListEntry entry; - entry["Number"] = (m->unread ? "* " : " ") + stringify(i + 1); - entry["Sender"] = m->sender; - entry["Date/Time"] = Anope::strftime(m->time, source.GetAccount()); - list.AddEntry(entry); - } - } - - std::vector<Anope::string> replies; - list.Process(replies); - - source.Reply(_("Memos for %s:"), ci ? ci->name.c_str() : source.GetNick().c_str()); - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists any memos you currently have. With \002NEW\002, lists only\n" - "new (unread) memos. Unread memos are marked with a \"*\"\n" - "to the left of the memo number. You can also specify a list\n" - "of numbers, as in the example below:\n" - " \002LIST 2-5,7-9\002\n" - " Lists memos numbered 2 through 5 and 7 through 9.")); - return true; - } -}; - -class MSList : public Module -{ - CommandMSList commandmslist; - - public: - MSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmslist(this) - { - - } -}; - -MODULE_INIT(MSList) diff --git a/modules/commands/ms_read.cpp b/modules/commands/ms_read.cpp deleted file mode 100644 index 96103d30b..000000000 --- a/modules/commands/ms_read.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static ServiceReference<MemoServService> MemoServService("MemoServService", "MemoServ"); - -static void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Anope::string &targ) -{ - /* Only send receipt if memos are allowed */ - if (MemoServService && !Anope::ReadOnly) - { - /* Get nick alias for sender */ - const NickAlias *na = NickAlias::Find(m->sender); - - if (!na) - return; - - /* Get nick core for sender */ - const NickCore *nc = na->nc; - - if (!nc) - return; - - /* 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 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()); - } - - /* Remove receipt flag from the original memo */ - m->receipt = false; -} - -class MemoListCallback : public NumberList -{ - CommandSource &source; - MemoInfo *mi; - const ChannelInfo *ci; - bool found; - public: - MemoListCallback(CommandSource &_source, MemoInfo *_mi, const ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), source(_source), mi(_mi), ci(_ci) - { - found = false; - } - - ~MemoListCallback() - { - if (!found) - source.Reply(_("No memos to display.")); - } - - void HandleNumber(unsigned number) anope_override - { - if (!number || number > mi->memos->size()) - return; - - MemoListCallback::DoRead(source, mi, ci, number - 1); - found = true; - } - - static void DoRead(CommandSource &source, MemoInfo *mi, const ChannelInfo *ci, unsigned index) - { - Memo *m = mi->GetMemo(index); - if (!m) - return; - - if (ci) - source.Reply(_("Memo %d from %s (%s)."), index + 1, m->sender.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str()); - else - source.Reply(_("Memo %d from %s (%s)."), index + 1, m->sender.c_str(), Anope::strftime(m->time, source.GetAccount()).c_str()); - - BotInfo *bi; - Anope::string cmd; - if (Command::FindCommandFromService("memoserv/del", bi, cmd)) - { - if (ci) - source.Reply(_("To delete, type: \002%s%s %s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), ci->name.c_str(), index + 1); - else - source.Reply(_("To delete, type: \002%s%s %s %d\002"), Config->StrictPrivmsg.c_str(), bi->nick.c_str(), cmd.c_str(), index + 1); - } - - source.Reply("%s", m->text.c_str()); - m->unread = false; - - /* Check if a receipt notification was requested */ - if (m->receipt) - rsend_notify(source, mi, m, ci ? ci->name : source.GetNick()); - } -}; - -class CommandMSRead : public Command -{ - public: - CommandMSRead(Module *creator) : Command(creator, "memoserv/read", 1, 2) - { - this->SetDesc(_("Read a memo or memos")); - this->SetSyntax(_("[\037channel\037] {\037num\037 | \037list\037 | LAST | NEW}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - MemoInfo *mi; - ChannelInfo *ci = NULL; - Anope::string numstr = params[0], chan; - - if (!numstr.empty() && numstr[0] == '#') - { - chan = numstr; - numstr = params.size() > 1 ? params[1] : ""; - - ci = ChannelInfo::Find(chan); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - else if (!source.AccessFor(ci).HasPriv("MEMO")) - { - source.Reply(ACCESS_DENIED); - return; - } - mi = &ci->memos; - } - else - mi = &source.nc->memos; - - if (numstr.empty() || (!numstr.equals_ci("LAST") && !numstr.equals_ci("NEW") && numstr.find_first_not_of("0123456789.,-") != Anope::string::npos)) - this->OnSyntaxError(source, numstr); - else if (mi->memos->empty()) - { - if (!chan.empty()) - source.Reply(MEMO_X_HAS_NO_MEMOS, chan.c_str()); - else - source.Reply(MEMO_HAVE_NO_MEMOS); - } - else - { - int i, end; - - if (numstr.equals_ci("NEW")) - { - int readcount = 0; - for (i = 0, end = mi->memos->size(); i < end; ++i) - if (mi->GetMemo(i)->unread) - { - MemoListCallback::DoRead(source, mi, ci, i); - ++readcount; - } - if (!readcount) - { - if (!chan.empty()) - source.Reply(MEMO_X_HAS_NO_NEW_MEMOS, chan.c_str()); - else - source.Reply(MEMO_HAVE_NO_NEW_MEMOS); - } - } - else if (numstr.equals_ci("LAST")) - { - for (i = 0, end = mi->memos->size() - 1; i < end; ++i); - MemoListCallback::DoRead(source, mi, ci, i); - } - else /* number[s] */ - { - MemoListCallback list(source, mi, ci, numstr); - list.Process(); - } - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends you the text of the memos specified. If LAST is\n" - "given, sends you the memo you most recently received. If\n" - "NEW is given, sends you all of your new memos. Otherwise,\n" - "sends you memo number \037num\037. You can also give a list of\n" - "numbers, as in this example:\n" - " \n" - " \002READ 2-5,7-9\002\n" - " Displays memos numbered 2 through 5 and 7 through 9.")); - return true; - } -}; - -class MSRead : public Module -{ - CommandMSRead commandmsread; - - public: - MSRead(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsread(this) - { - - } -}; - -MODULE_INIT(MSRead) diff --git a/modules/commands/ms_rsend.cpp b/modules/commands/ms_rsend.cpp deleted file mode 100644 index b7744131a..000000000 --- a/modules/commands/ms_rsend.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -namespace -{ - ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ"); -} - -class CommandMSRSend : public Command -{ - public: - CommandMSRSend(Module *creator) : Command(creator, "memoserv/rsend", 2, 2) - { - this->SetDesc(_("Sends a memo and requests a read receipt")); - this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!memoserv) - return; - - if (Anope::ReadOnly && !source.IsOper()) - { - source.Reply(MEMO_SEND_DISABLED); - return; - } - - const Anope::string &nick = params[0]; - const Anope::string &text = params[1]; - const NickAlias *na = NULL; - - /* prevent user from rsend to themselves */ - if ((na = NickAlias::Find(nick)) && na->nc == source.GetAccount()) - { - source.Reply(_("You can not request a receipt when sending a memo to yourself.")); - return; - } - - if (Config->GetModule(this->owner)->Get<bool>("operonly") && !source.IsServicesOper()) - source.Reply(ACCESS_DENIED); - else - { - MemoServService::MemoResult result = memoserv->Send(source.GetNick(), nick, text); - if (result == MemoServService::MEMO_INVALID_TARGET) - source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str()); - else if (result == MemoServService::MEMO_TOO_FAST) - source.Reply(_("Please wait %d seconds before using the %s command again."), Config->GetModule("memoserv")->Get<time_t>("senddelay"), source.command.c_str()); - else if (result == MemoServService::MEMO_TARGET_FULL) - source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str()); - else - { - source.Reply(_("Memo sent to \002%s\002."), nick.c_str()); - - bool ischan; - MemoInfo *mi = MemoInfo::GetMemoInfo(nick, ischan); - if (mi == NULL) - throw CoreException("NULL mi in ms_rsend"); - Memo *m = (mi->memos->size() ? mi->GetMemo(mi->memos->size() - 1) : NULL); - if (m != NULL) - m->receipt = true; - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends the named \037nick\037 or \037channel\037 a memo containing\n" - "\037memo-text\037. When sending to a nickname, the recipient will\n" - "receive a notice that he/she has a new memo. The target\n" - "nickname/channel must be registered.\n" - "Once the memo is read by its recipient, an automatic notification\n" - "memo will be sent to the sender informing him/her that the memo\n" - "has been read.")); - return true; - } -}; - -class MSRSend : public Module -{ - CommandMSRSend commandmsrsend; - - public: - MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsrsend(this) - { - if (!memoserv) - throw ModuleException("No MemoServ!"); - } -}; - -MODULE_INIT(MSRSend) diff --git a/modules/commands/ms_send.cpp b/modules/commands/ms_send.cpp deleted file mode 100644 index b028706d3..000000000 --- a/modules/commands/ms_send.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -namespace -{ - ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ"); -} - -class CommandMSSend : public Command -{ - public: - CommandMSSend(Module *creator) : Command(creator, "memoserv/send", 2, 2) - { - this->SetDesc(_("Send a memo to a nick or channel")); - this->SetSyntax(_("{\037nick\037 | \037channel\037} \037memo-text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!memoserv) - return; - - const Anope::string &nick = params[0]; - const Anope::string &text = params[1]; - - if (Anope::ReadOnly && !source.IsOper()) - { - source.Reply(MEMO_SEND_DISABLED); - return; - } - - if (source.GetAccount()->HasExt("UNCONFIRMED")) - { - source.Reply(_("You must confirm your account before you may send a memo.")); - return; - } - - MemoServService::MemoResult result = memoserv->Send(source.GetNick(), nick, text); - if (result == MemoServService::MEMO_SUCCESS) - { - source.Reply(_("Memo sent to \002%s\002."), nick.c_str()); - Log(LOG_COMMAND, source, this) << "to send a memo to " << nick; - } - else if (result == MemoServService::MEMO_INVALID_TARGET) - source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str()); - else if (result == MemoServService::MEMO_TOO_FAST) - source.Reply(_("Please wait %d seconds before using the %s command again."), Config->GetModule("memoserv")->Get<time_t>("senddelay"), source.command.c_str()); - else if (result == MemoServService::MEMO_TARGET_FULL) - source.Reply(_("Sorry, %s currently has too many memos and cannot receive more."), nick.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends the named \037nick\037 or \037channel\037 a memo containing\n" - "\037memo-text\037. When sending to a nickname, the recipient will\n" - "receive a notice that he/she has a new memo. The target\n" - "nickname/channel must be registered.")); - return true; - } -}; - -class MSSend : public Module -{ - CommandMSSend commandmssend; - - public: - MSSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmssend(this) - { - - if (!memoserv) - throw ModuleException("No MemoServ!"); - } -}; - -MODULE_INIT(MSSend) diff --git a/modules/commands/ms_sendall.cpp b/modules/commands/ms_sendall.cpp deleted file mode 100644 index 4cc0f350c..000000000 --- a/modules/commands/ms_sendall.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -namespace -{ - ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ"); -} - -class CommandMSSendAll : public Command -{ - public: - CommandMSSendAll(Module *creator) : Command(creator, "memoserv/sendall", 1, 1) - { - this->SetDesc(_("Send a memo to all registered users")); - this->SetSyntax(_("\037memo-text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!memoserv) - return; - - const Anope::string &text = params[0]; - - Log(LOG_ADMIN, source, this) << "to send " << text; - - for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it) - { - const NickCore *nc = it->second; - - if (nc != source.nc) - memoserv->Send(source.GetNick(), nc->display, text); - } - - source.Reply(_("A massmemo has been sent to all registered users.")); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends all registered users a memo containing \037memo-text\037.")); - return true; - } -}; - -class MSSendAll : public Module -{ - CommandMSSendAll commandmssendall; - - public: - MSSendAll(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmssendall(this) - { - if (!memoserv) - throw ModuleException("No MemoServ!"); - } -}; - -MODULE_INIT(MSSendAll) diff --git a/modules/commands/ms_set.cpp b/modules/commands/ms_set.cpp deleted file mode 100644 index d407132c7..000000000 --- a/modules/commands/ms_set.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandMSSet : public Command -{ - private: - void DoNotify(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) - { - const Anope::string ¶m = params[1]; - NickCore *nc = source.nc; - BotInfo *MemoServ = Config->GetClient("MemoServ"); - - if (!MemoServ) - return; - - if (param.equals_ci("ON")) - { - nc->Extend<bool>("MEMO_SIGNON"); - nc->Extend<bool>("MEMO_RECEIVE"); - source.Reply(_("%s will now notify you of memos when you log on and when they are sent to you."), MemoServ->nick.c_str()); - } - else if (param.equals_ci("LOGON")) - { - nc->Extend<bool>("MEMO_SIGNON"); - nc->Shrink<bool>("MEMO_RECEIVE"); - source.Reply(_("%s will now notify you of memos when you log on or unset /AWAY."), MemoServ->nick.c_str()); - } - else if (param.equals_ci("NEW")) - { - nc->Shrink<bool>("MEMO_SIGNON"); - nc->Extend<bool>("MEMO_RECEIVE"); - source.Reply(_("%s will now notify you of memos when they are sent to you."), MemoServ->nick.c_str()); - } - else if (param.equals_ci("MAIL")) - { - if (!nc->email.empty()) - { - nc->Extend<bool>("MEMO_MAIL"); - source.Reply(_("You will now be informed about new memos via email.")); - } - else - source.Reply(_("There's no email address set for your nick.")); - } - else if (param.equals_ci("NOMAIL")) - { - nc->Shrink<bool>("MEMO_MAIL"); - source.Reply(_("You will no longer be informed via email.")); - } - else if (param.equals_ci("OFF")) - { - nc->Shrink<bool>("MEMO_SIGNON"); - nc->Shrink<bool>("MEMO_RECEIVE"); - nc->Shrink<bool>("MEMO_MAIL"); - source.Reply(_("%s will not send you any notification of memos."), MemoServ->nick.c_str()); - } - else - this->OnSyntaxError(source, ""); - } - - void DoLimit(CommandSource &source, const std::vector<Anope::string> ¶ms, MemoInfo *mi) - { - - Anope::string p1 = params[1]; - Anope::string p2 = params.size() > 2 ? params[2] : ""; - Anope::string p3 = params.size() > 3 ? params[3] : ""; - Anope::string user, chan; - int16_t limit; - NickCore *nc = source.nc; - ChannelInfo *ci = NULL; - bool is_servadmin = source.HasPriv("memoserv/set-limit"); - - if (p1[0] == '#') - { - chan = p1; - p1 = p2; - p2 = p3; - p3 = params.size() > 4 ? params[4] : ""; - - ci = ChannelInfo::Find(chan); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, chan.c_str()); - return; - } - else if (!is_servadmin && !source.AccessFor(ci).HasPriv("MEMO")) - { - source.Reply(ACCESS_DENIED); - return; - } - mi = &ci->memos; - } - if (is_servadmin) - { - if (!p2.empty() && !p2.equals_ci("HARD") && chan.empty()) - { - const NickAlias *na; - if (!(na = NickAlias::Find(p1))) - { - source.Reply(NICK_X_NOT_REGISTERED, p1.c_str()); - return; - } - user = p1; - mi = &na->nc->memos; - nc = na->nc; - p1 = p2; - p2 = p3; - } - else if (p1.empty() || (!p1.is_pos_number_only() && !p1.equals_ci("NONE")) || (!p2.empty() && !p2.equals_ci("HARD"))) - { - this->OnSyntaxError(source, ""); - return; - } - if (!chan.empty()) - { - if (!p2.empty()) - ci->Extend<bool>("MEMO_HARDMAX"); - else - ci->Shrink<bool>("MEMO_HARDMAX"); - } - else - { - if (!p2.empty()) - nc->Extend<bool>("MEMO_HARDMAX"); - else - nc->Shrink<bool>("MEMO_HARDMAX"); - } - limit = -1; - try - { - limit = convertTo<int16_t>(p1); - } - catch (const ConvertException &) { } - } - else - { - if (p1.empty() || !p2.empty() || !isdigit(p1[0])) - { - this->OnSyntaxError(source, ""); - return; - } - if (!chan.empty() && ci->HasExt("MEMO_HARDMAX")) - { - source.Reply(_("The memo limit for %s may not be changed."), chan.c_str()); - return; - } - else if (chan.empty() && nc->HasExt("MEMO_HARDMAX")) - { - source.Reply(_("You are not permitted to change your memo limit.")); - return; - } - int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos"); - limit = -1; - try - { - limit = convertTo<int16_t>(p1); - } - catch (const ConvertException &) { } - /* The first character is a digit, but we could still go negative - * from overflow... watch out! */ - if (limit < 0 || (max_memos > 0 && limit > max_memos)) - { - if (!chan.empty()) - source.Reply(_("You cannot set the memo limit for %s higher than %d."), chan.c_str(), max_memos); - else - source.Reply(_("You cannot set your memo limit higher than %d."), max_memos); - return; - } - } - mi->memomax = limit; - if (limit > 0) - { - if (chan.empty() && nc == source.nc) - source.Reply(_("Your memo limit has been set to \002%d\002."), limit); - else - source.Reply(_("Memo limit for %s set to \002%d\002."), !chan.empty() ? chan.c_str() : user.c_str(), limit); - } - else if (!limit) - { - if (chan.empty() && nc == source.nc) - source.Reply(_("You will no longer be able to receive memos.")); - else - source.Reply(_("Memo limit for %s set to \0020\002."), !chan.empty() ? chan.c_str() : user.c_str()); - } - else - { - if (chan.empty() && nc == source.nc) - source.Reply(_("Your memo limit has been disabled.")); - else - source.Reply(_("Memo limit \002disabled\002 for %s."), !chan.empty() ? chan.c_str() : user.c_str()); - } - return; - } - public: - CommandMSSet(Module *creator) : Command(creator, "memoserv/set", 2, 5) - { - this->SetDesc(_("Set options related to memos")); - this->SetSyntax(_("\037option\037 \037parameters\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - MemoInfo *mi = &source.nc->memos; - - if (Anope::ReadOnly) - source.Reply(_("Sorry, memo option setting is temporarily disabled.")); - else if (cmd.equals_ci("NOTIFY")) - return this->DoNotify(source, params, mi); - else if (cmd.equals_ci("LIMIT")) - return this->DoLimit(source, params, mi); - else - { - this->OnSyntaxError(source, ""); - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (subcommand.empty()) - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets various memo options. \037option\037 can be one of:\n" - " \n" - " NOTIFY Changes when you will be notified about\n" - " new memos (only for nicknames)\n" - " LIMIT Sets the maximum number of memos you can\n" - " receive\n" - " \n" - "Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str()); - } - else if (subcommand.equals_ci("NOTIFY")) - source.Reply(_("Syntax: \002NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" - " \n" - "Changes when you will be notified about new memos:\n" - " \n" - " ON You will be notified of memos when you log on,\n" - " when you unset /AWAY, and when they are sent\n" - " to you.\n" - " LOGON You will only be notified of memos when you log\n" - " 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 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" - " \n" - "\002ON\002 is essentially \002LOGON\002 and \002NEW\002 combined.")); - else if (subcommand.equals_ci("LIMIT")) - { - int max_memos = Config->GetModule("memoserv")->Get<int>("maxmemos"); - if (source.IsServicesOper()) - source.Reply(_("Syntax: \002LIMIT [\037user\037 | \037channel\037] {\037limit\037 | NONE} [HARD]\002\n" - " \n" - "Sets the maximum number of memos a user or channel is\n" - "allowed to have. Setting the limit to 0 prevents the user\n" - "from receiving any memos; setting it to \002NONE\002 allows the\n" - "user to receive and keep as many memos as they want. If\n" - "you do not give a nickname or channel, your own limit is\n" - "set.\n" - " \n" - "Adding \002HARD\002 prevents the user from changing the limit. Not\n" - "adding \002HARD\002 has the opposite effect, allowing the user to\n" - "change the limit (even if a previous limit was set with\n" - "\002HARD\002).\n" - " \n" - "This use of the \002SET LIMIT\002 command is limited to \002Services\002\n" - "\002Operators\002. Other users may only enter a limit for themselves\n" - "or a channel on which they have such privileges, may not\n" - "remove their limit, may not set a limit above %d, and may\n" - "not set a hard limit."), max_memos); - else - source.Reply(_("Syntax: \002LIMIT [\037channel\037] \037limit\037\002\n" - " \n" - "Sets the maximum number of memos you (or the given channel)\n" - "are allowed to have. If you set this to 0, no one will be\n" - "able to send any memos to you. However, you cannot set\n" - "this any higher than %d."), max_memos); - } - else - return false; - - return true; - } -}; - -class MSSet : public Module -{ - CommandMSSet commandmsset; - SerializableExtensibleItem<bool> memo_signon, memo_receive, memo_mail, memo_hardmax; - - public: - MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsset(this), memo_signon(this, "MEMO_SIGNON"), memo_receive(this, "MEMO_RECEIVE"), memo_mail(this, "MEMO_MAIL"), - memo_hardmax(this, "MEMO_HARDMAX") - { - - } -}; - -MODULE_INIT(MSSet) diff --git a/modules/commands/ms_staff.cpp b/modules/commands/ms_staff.cpp deleted file mode 100644 index b3554fab8..000000000 --- a/modules/commands/ms_staff.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* MemoServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -namespace -{ - ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ"); -} - -class CommandMSStaff : public Command -{ - public: - CommandMSStaff(Module *creator) : Command(creator, "memoserv/staff", 1, 1) - { - this->SetDesc(_("Send a memo to all opers/admins")); - this->SetSyntax(_("\037memo-text\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!memoserv) - return; - - const Anope::string &text = params[0]; - - for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it) - { - const NickCore *nc = it->second; - - if (source.nc != nc && nc->IsServicesOper()) - memoserv->Send(source.GetNick(), nc->display, text, true); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends all services staff a memo containing \037memo-text\037.")); - - return true; - } -}; - -class MSStaff : public Module -{ - CommandMSStaff commandmsstaff; - - public: - MSStaff(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandmsstaff(this) - { - if (!memoserv) - throw ModuleException("No MemoServ!"); - } -}; - -MODULE_INIT(MSStaff) diff --git a/modules/commands/ns_access.cpp b/modules/commands/ns_access.cpp deleted file mode 100644 index e54252c65..000000000 --- a/modules/commands/ns_access.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSAccess : public Command -{ - private: - void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask) - { - if (mask.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (nc->access.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax", "32")) - { - source.Reply(_("Sorry, the maximum of %d access entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("accessmax")); - return; - } - - if (nc->FindAccess(mask)) - { - source.Reply(_("Mask \002%s\002 already present on %s's access list."), mask.c_str(), nc->display.c_str()); - return; - } - - nc->AddAccess(mask); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD mask " << mask << " to " << nc->display; - source.Reply(_("\002%s\002 added to %s's access list."), mask.c_str(), nc->display.c_str()); - - return; - } - - void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask) - { - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (!nc->FindAccess(mask)) - { - source.Reply(_("\002%s\002 not found on %s's access list."), mask.c_str(), nc->display.c_str()); - return; - } - - nc->EraseAccess(mask); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE mask " << mask << " from " << nc->display; - source.Reply(_("\002%s\002 deleted from %s's access list."), mask.c_str(), nc->display.c_str()); - - return; - } - - void DoList(CommandSource &source, NickCore *nc, const Anope::string &mask) - { - unsigned i, end; - - if (nc->access.empty()) - { - source.Reply(_("%s's access list is empty."), nc->display.c_str()); - return; - } - - source.Reply(_("Access list for %s:"), nc->display.c_str()); - for (i = 0, end = nc->access.size(); i < end; ++i) - { - Anope::string access = nc->GetAccess(i); - if (!mask.empty() && !Anope::Match(access, mask)) - continue; - source.Reply(" %s", access.c_str()); - } - - return; - } - public: - CommandNSAccess(Module *creator) : Command(creator, "nickserv/access", 1, 3) - { - this->SetDesc(_("Modify the list of authorized addresses")); - this->SetSyntax(_("ADD [\037nickname\037] \037mask\037")); - this->SetSyntax(_("DEL [\037nickname\037] \037mask\037")); - this->SetSyntax(_("LIST [\037nickname\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - Anope::string nick, mask; - - if (cmd.equals_ci("LIST")) - nick = params.size() > 1 ? params[1] : ""; - else - { - nick = params.size() == 3 ? params[1] : ""; - mask = params.size() > 1 ? params[params.size() - 1] : ""; - } - - NickCore *nc; - if (!nick.empty()) - { - const NickAlias *na = NickAlias::Find(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access")) - { - source.Reply(ACCESS_DENIED); - return; - } - else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->nc && na->nc->IsServicesOper() && !cmd.equals_ci("LIST")) - { - source.Reply(_("You may view but not modify the access list of other Services Operators.")); - return; - } - - nc = na->nc; - } - else - nc = source.nc; - - if (!mask.empty() && (mask.find('@') == Anope::string::npos || mask.find('!') != Anope::string::npos)) - { - source.Reply(BAD_USERHOST_MASK); - source.Reply(MORE_INFO, Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), source.command.c_str()); - } - else if (cmd.equals_ci("LIST")) - return this->DoList(source, nc, mask); - else if (nc->HasExt("NS_SUSPENDED")) - source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); - else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, nc, mask); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, nc, mask); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Modifies or displays the access list for your nick. This\n" - "is the list of addresses which will be automatically\n" - "recognized by %s as allowed to use the nick. If\n" - "you want to use the nick from a different address, you\n" - "need to send an \002IDENTIFY\002 command to make %s\n" - "recognize you. Services Operators may provide a nick\n" - "to modify other users' access lists.\n" - " \n" - "Examples:\n" - " \n" - " \002ACCESS ADD anyone@*.bepeg.com\002\n" - " Allows access to user \002anyone\002 from any machine in\n" - " the \002bepeg.com\002 domain.\n" - " \n" - " \002ACCESS DEL anyone@*.bepeg.com\002\n" - " Reverses the previous command.\n" - " \n" - " \002ACCESS LIST\002\n" - " Displays the current access list."), source.service->nick.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class NSAccess : public Module -{ - CommandNSAccess commandnsaccess; - - public: - NSAccess(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsaccess(this) - { - } - - void OnNickRegister(User *u, NickAlias *na, const Anope::string &) anope_override - { - if (u && Config->GetModule(this)->Get<bool>("addaccessonreg")) - na->nc->AddAccess(u->Mask()); - } -}; - -MODULE_INIT(NSAccess) diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp deleted file mode 100644 index b62029fad..000000000 --- a/modules/commands/ns_ajoin.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -struct AJoinEntry; - -struct AJoinList : Serialize::Checker<std::vector<AJoinEntry *> > -{ - AJoinList(Extensible *) : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { } - ~AJoinList(); -}; - -struct AJoinEntry : Serializable -{ - Serialize::Reference<NickCore> owner; - Anope::string channel; - Anope::string key; - - AJoinEntry(Extensible *) : Serializable("AJoinEntry") { } - - ~AJoinEntry() - { - AJoinList *channels = owner->GetExt<AJoinList>("ajoinlist"); - if (channels) - { - std::vector<AJoinEntry *>::iterator it = std::find((*channels)->begin(), (*channels)->end(), this); - if (it != (*channels)->end()) - (*channels)->erase(it); - } - } - - void Serialize(Serialize::Data &sd) const anope_override - { - if (!this->owner) - return; - - sd["owner"] << this->owner->display; - sd["channel"] << this->channel; - sd["key"] << this->key; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &sd) - { - Anope::string sowner; - - sd["owner"] >> sowner; - - NickCore *nc = NickCore::Find(sowner); - if (nc == NULL) - return NULL; - - AJoinEntry *aj; - if (obj) - aj = anope_dynamic_static_cast<AJoinEntry *>(obj); - else - { - aj = new AJoinEntry(nc); - aj->owner = nc; - } - - sd["channel"] >> aj->channel; - sd["key"] >> aj->key; - - if (!obj) - { - AJoinList *channels = nc->Require<AJoinList>("ajoinlist"); - (*channels)->push_back(aj); - } - - return aj; - } -}; - -AJoinList::~AJoinList() -{ - for (unsigned i = 0; i < (*this)->size(); ++i) - delete (*this)->at(i); -} - -class CommandNSAJoin : public Command -{ - void DoList(CommandSource &source, NickCore *nc) - { - AJoinList *channels = nc->Require<AJoinList>("ajoinlist"); - - if ((*channels)->empty()) - source.Reply(_("%s's auto join list is empty."), nc->display.c_str()); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Channel")).AddColumn(_("Key")); - for (unsigned i = 0; i < (*channels)->size(); ++i) - { - AJoinEntry *aj = (*channels)->at(i); - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Channel"] = aj->channel; - entry["Key"] = aj->key; - list.AddEntry(entry); - } - - source.Reply(_("%s's auto join list:"), nc->display.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &chans, const Anope::string &keys) - { - AJoinList *channels = nc->Require<AJoinList>("ajoinlist"); - - Anope::string addedchans; - Anope::string alreadyadded; - Anope::string invalidkey; - commasepstream ksep(keys, true); - commasepstream csep(chans); - for (Anope::string chan, key; csep.GetToken(chan);) - { - ksep.GetToken(key); - - unsigned i = 0; - for (; i < (*channels)->size(); ++i) - if ((*channels)->at(i)->channel.equals_ci(chan)) - break; - - if ((*channels)->size() >= Config->GetModule(this->owner)->Get<unsigned>("ajoinmax")) - { - source.Reply(_("Sorry, the maximum of %d auto join entries has been reached."), Config->GetModule(this->owner)->Get<unsigned>("ajoinmax")); - return; - } - else if (i != (*channels)->size()) - alreadyadded += chan + ", "; - else if (IRCD->IsChannelValid(chan) == false) - source.Reply(CHAN_X_INVALID, chan.c_str()); - else - { - Channel *c = Channel::Find(chan); - Anope::string k; - if (c && c->GetParam("KEY", k) && key != k) - { - invalidkey += chan + ", "; - continue; - } - - AJoinEntry *entry = new AJoinEntry(nc); - entry->owner = nc; - entry->channel = chan; - entry->key = key; - (*channels)->push_back(entry); - addedchans += chan + ", "; - } - } - - if (!alreadyadded.empty()) - { - alreadyadded = alreadyadded.substr(0, alreadyadded.length() - 2); - source.Reply(_("%s is already on %s's auto join list."), alreadyadded.c_str(), nc->display.c_str()); - } - - if (!invalidkey.empty()) - { - invalidkey = invalidkey.substr(0, invalidkey.length() - 2); - source.Reply(_("%s had an invalid key specified, and was thus ignored."), invalidkey.c_str()); - } - - if (addedchans.empty()) - return; - - addedchans = addedchans.substr(0, addedchans.length() - 2); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD channel " << addedchans << " to " << nc->display; - source.Reply(_("%s added to %s's auto join list."), addedchans.c_str(), nc->display.c_str()); - } - - void DoDel(CommandSource &source, NickCore *nc, const Anope::string &chans) - { - AJoinList *channels = nc->Require<AJoinList>("ajoinlist"); - Anope::string delchans; - Anope::string notfoundchans; - commasepstream sep(chans); - - for (Anope::string chan; sep.GetToken(chan);) - { - unsigned i = 0; - for (; i < (*channels)->size(); ++i) - if ((*channels)->at(i)->channel.equals_ci(chan)) - break; - - if (i == (*channels)->size()) - notfoundchans += chan + ", "; - else - { - delete (*channels)->at(i); - delchans += chan + ", "; - } - } - - if (!notfoundchans.empty()) - { - notfoundchans = notfoundchans.substr(0, notfoundchans.length() - 2); - source.Reply(_("%s was not found on %s's auto join list."), notfoundchans.c_str(), nc->display.c_str()); - } - - if (delchans.empty()) - return; - - delchans = delchans.substr(0, delchans.length() - 2); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE channel " << delchans << " from " << nc->display; - source.Reply(_("%s was removed from %s's auto join list."), delchans.c_str(), nc->display.c_str()); - - if ((*channels)->empty()) - nc->Shrink<AJoinList>("ajoinlist"); - } - - public: - CommandNSAJoin(Module *creator) : Command(creator, "nickserv/ajoin", 1, 4) - { - this->SetDesc(_("Manage your auto join list")); - this->SetSyntax(_("ADD [\037nickname\037] \037channel\037 [\037key\037]")); - this->SetSyntax(_("DEL [\037nickname\037] \037channel\037")); - this->SetSyntax(_("LIST [\037nickname\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - Anope::string nick, param, param2; - - if (cmd.equals_ci("LIST")) - nick = params.size() > 1 ? params[1] : ""; - else - nick = (params.size() > 2 && IRCD->IsChannelValid(params[2])) ? params[1] : ""; - - NickCore *nc; - if (!nick.empty()) - { - const NickAlias *na = NickAlias::Find(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - else if (na->nc != source.GetAccount() && !source.HasCommand("nickserv/ajoin")) - { - source.Reply(ACCESS_DENIED); - return; - } - - nc = na->nc; - param = params.size() > 2 ? params[2] : ""; - param2 = params.size() > 3 ? params[3] : ""; - } - else - { - nc = source.nc; - param = params.size() > 1 ? params[1] : ""; - param2 = params.size() > 2 ? params[2] : ""; - } - - if (cmd.equals_ci("LIST")) - return this->DoList(source, nc); - else if (nc->HasExt("NS_SUSPENDED")) - source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); - else if (param.empty()) - this->OnSyntaxError(source, ""); - else if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, nc, param, param2); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, nc, param); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command manages your auto join list. When you identify\n" - "you will automatically join the channels on your auto join list.\n" - "Services Operators may provide a nick to modify other users'\n" - "auto join lists.")); - return true; - } -}; - -class NSAJoin : public Module -{ - CommandNSAJoin commandnsajoin; - ExtensibleItem<AJoinList> ajoinlist; - Serialize::Type ajoinentry_type; - - public: - NSAJoin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsajoin(this), ajoinlist(this, "ajoinlist"), - ajoinentry_type("AJoinEntry", AJoinEntry::Unserialize) - { - - if (!IRCD || !IRCD->CanSVSJoin) - throw ModuleException("Your IRCd does not support SVSJOIN"); - - } - - void OnUserLogin(User *u) anope_override - { - BotInfo *NickServ = Config->GetClient("NickServ"); - if (!NickServ) - return; - - AJoinList *channels = u->Account()->GetExt<AJoinList>("ajoinlist"); - if (channels == NULL) - return; - - /* Set +r now, so we can ajoin users into +R channels */ - ModeManager::ProcessModes(); - - for (unsigned i = 0; i < (*channels)->size(); ++i) - { - AJoinEntry *entry = (*channels)->at(i); - Channel *c = Channel::Find(entry->channel); - ChannelInfo *ci; - - if (c) - ci = c->ci; - else - ci = ChannelInfo::Find(entry->channel); - - bool need_invite = false; - Anope::string key = entry->key; - AccessGroup u_access; - - if (ci != NULL) - { - if (ci->HasExt("CS_SUSPENDED")) - continue; - u_access = ci->AccessFor(u); - } - if (c != NULL) - { - if (c->FindUser(u) != NULL) - continue; - else if (c->HasMode("OPERONLY") && !u->HasMode("OPER")) - continue; - else if (c->HasMode("ADMINONLY") && !u->HasMode("ADMIN")) - continue; - else if (c->HasMode("SSL") && !(u->HasMode("SSL") || u->HasExt("ssl"))) - continue; - else if (c->MatchesList(u, "BAN") == true && c->MatchesList(u, "EXCEPT") == false) - need_invite = true; - else if (c->HasMode("INVITE") && c->MatchesList(u, "INVITEOVERRIDE") == false) - need_invite = true; - - if (c->HasMode("KEY")) - { - Anope::string k; - if (c->GetParam("KEY", k)) - { - if (u_access.HasPriv("GETKEY")) - key = k; - else if (key != k) - need_invite = true; - } - } - if (c->HasMode("LIMIT")) - { - Anope::string l; - if (c->GetParam("LIMIT", l)) - { - try - { - unsigned limit = convertTo<unsigned>(l); - if (c->users.size() >= limit) - need_invite = true; - } - catch (const ConvertException &) { } - } - } - } - - if (need_invite && c != NULL) - { - if (!u_access.HasPriv("INVITE")) - continue; - IRCD->SendInvite(NickServ, c, u); - } - - IRCD->SendSVSJoin(NickServ, u, entry->channel, key); - } - } -}; - -MODULE_INIT(NSAJoin) diff --git a/modules/commands/ns_alist.cpp b/modules/commands/ns_alist.cpp deleted file mode 100644 index 5f5efc7ea..000000000 --- a/modules/commands/ns_alist.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSAList : public Command -{ - static bool ChannelSort(ChannelInfo *ci1, ChannelInfo *ci2) - { - return ci::less()(ci1->name, ci2->name); - } - - public: - CommandNSAList(Module *creator) : Command(creator, "nickserv/alist", 0, 2) - { - this->SetDesc(_("List channels you have access on")); - this->SetSyntax(_("[\037nickname\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Anope::string nick = source.GetNick(); - NickCore *nc = source.nc; - - if (params.size() && source.HasPriv("nickserv/alist")) - { - nick = params[0]; - const NickAlias *na = NickAlias::Find(nick); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - nc = na->nc; - } - - ListFormatter list(source.GetAccount()); - int chan_count = 0; - - list.AddColumn(_("Number")).AddColumn(_("Channel")).AddColumn(_("Access")).AddColumn(_("Description")); - - std::deque<ChannelInfo *> queue; - nc->GetChannelReferences(queue); - std::sort(queue.begin(), queue.end(), ChannelSort); - - for (unsigned i = 0; i < queue.size(); ++i) - { - ChannelInfo *ci = queue[i]; - ListFormatter::ListEntry entry; - - if (ci->GetFounder() == nc) - { - ++chan_count; - entry["Number"] = stringify(chan_count); - entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; - entry["Access"] = Language::Translate(source.GetAccount(), _("Founder")); - entry["Description"] = ci->desc; - list.AddEntry(entry); - continue; - } - - if (ci->GetSuccessor() == nc) - { - ++chan_count; - entry["Number"] = stringify(chan_count); - entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; - entry["Access"] = Language::Translate(source.GetAccount(), _("Successor")); - entry["Description"] = ci->desc; - list.AddEntry(entry); - continue; - } - - AccessGroup access = ci->AccessFor(nc, false); - if (access.empty()) - continue; - - ++chan_count; - - entry["Number"] = stringify(chan_count); - entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name; - for (unsigned j = 0; j < access.paths.size(); ++j) - { - ChanAccess::Path &p = access.paths[j]; - - // not interested in indirect access - if (p.size() != 1) - continue; - - ChanAccess *a = p[0]; - entry["Access"] = entry["Access"] + ", " + a->AccessSerialize(); - } - entry["Access"] = entry["Access"].substr(2); - entry["Description"] = ci->desc; - list.AddEntry(entry); - } - - std::vector<Anope::string> replies; - list.Process(replies); - - if (!chan_count) - { - source.Reply(_("\002%s\002 has no access in any channels."), nc->display.c_str()); - } - else - { - source.Reply(_("Channels that \002%s\002 has access on:"), nc->display.c_str()); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of list - %d channels shown."), chan_count); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all channels you have access on.\n" - " \n" - "Channels that have the \037NOEXPIRE\037 option set will be\n" - "prefixed by an exclamation mark. The nickname parameter is\n" - "limited to Services Operators")); - - return true; - } -}; - -class NSAList : public Module -{ - CommandNSAList commandnsalist; - - public: - NSAList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsalist(this) - { - - } -}; - -MODULE_INIT(NSAList) diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp deleted file mode 100644 index 6fa5decab..000000000 --- a/modules/commands/ns_cert.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/ns_cert.h" - -static Anope::hash_map<NickCore *> certmap; - -struct CertServiceImpl : CertService -{ - CertServiceImpl(Module *o) : CertService(o) { } - - NickCore* FindAccountFromCert(const Anope::string &cert) anope_override - { - Anope::hash_map<NickCore *>::iterator it = certmap.find(cert); - if (it != certmap.end()) - return it->second; - return NULL; - } -}; - -struct NSCertListImpl : NSCertList -{ - Serialize::Reference<NickCore> nc; - std::vector<Anope::string> certs; - - public: - NSCertListImpl(Extensible *obj) : nc(anope_dynamic_static_cast<NickCore *>(obj)) { } - - ~NSCertListImpl() - { - ClearCert(); - } - - /** Add an entry to the nick's certificate list - * - * @param entry The fingerprint to add to the cert list - * - * Adds a new entry into the cert list. - */ - void AddCert(const Anope::string &entry) anope_override - { - this->certs.push_back(entry); - certmap[entry] = nc; - FOREACH_MOD(OnNickAddCert, (this->nc, entry)); - } - - /** Get an entry from the nick's cert list by index - * - * @param entry Index in the certificaate list vector to retrieve - * @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds - * - * Retrieves an entry from the certificate list corresponding to the given index. - */ - Anope::string GetCert(unsigned entry) const anope_override - { - if (entry >= this->certs.size()) - return ""; - return this->certs[entry]; - } - - unsigned GetCertCount() const anope_override - { - return this->certs.size(); - } - - /** Find an entry in the nick's cert list - * - * @param entry The fingerprint to search for - * @return True if the fingerprint is found in the cert list, false otherwise - * - * Search for an fingerprint within the cert list. - */ - bool FindCert(const Anope::string &entry) const anope_override - { - return std::find(this->certs.begin(), this->certs.end(), entry) != this->certs.end(); - } - - /** Erase a fingerprint from the nick's certificate list - * - * @param entry The fingerprint to remove - * - * Removes the specified fingerprint from the cert list. - */ - void EraseCert(const Anope::string &entry) anope_override - { - std::vector<Anope::string>::iterator it = std::find(this->certs.begin(), this->certs.end(), entry); - if (it != this->certs.end()) - { - FOREACH_MOD(OnNickEraseCert, (this->nc, entry)); - certmap.erase(entry); - this->certs.erase(it); - } - } - - /** Clears the entire nick's cert list - * - * Deletes all the memory allocated in the certificate list vector and then clears the vector. - */ - void ClearCert() anope_override - { - FOREACH_MOD(OnNickClearCert, (this->nc)); - for (unsigned i = 0; i < certs.size(); ++i) - certmap.erase(certs[i]); - this->certs.clear(); - } - - void Check() anope_override - { - if (this->certs.empty()) - nc->Shrink<NSCertList>("certificates"); - } - - struct ExtensibleItem : ::ExtensibleItem<NSCertListImpl> - { - ExtensibleItem(Module *m, const Anope::string &ename) : ::ExtensibleItem<NSCertListImpl>(m, ename) { } - - void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override - { - if (s->GetSerializableType()->GetName() != "NickCore") - return; - - const NickCore *n = anope_dynamic_static_cast<const NickCore *>(e); - NSCertList *c = this->Get(n); - if (c == NULL || !c->GetCertCount()) - return; - - for (unsigned i = 0; i < c->GetCertCount(); ++i) - data["cert"] << c->GetCert(i) << " "; - } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override - { - if (s->GetSerializableType()->GetName() != "NickCore") - return; - - NickCore *n = anope_dynamic_static_cast<NickCore *>(e); - NSCertListImpl *c = this->Require(n); - - Anope::string buf; - data["cert"] >> buf; - spacesepstream sep(buf); - for (unsigned i = 0; i < c->certs.size(); ++i) - certmap.erase(c->certs[i]); - c->certs.clear(); - while (sep.GetToken(buf)) - { - c->certs.push_back(buf); - certmap[buf] = n; - } - } - }; -}; - -class CommandNSCert : public Command -{ - private: - void DoAdd(CommandSource &source, NickCore *nc, Anope::string certfp) - { - NSCertList *cl = nc->Require<NSCertList>("certificates"); - unsigned max = Config->GetModule(this->owner)->Get<unsigned>("max", "5"); - - if (cl->GetCertCount() >= max) - { - source.Reply(_("Sorry, the maximum of %d certificate entries has been reached."), max); - return; - } - - if (source.GetAccount() == nc) - { - User *u = source.GetUser(); - - if (!u || u->fingerprint.empty()) - { - source.Reply(_("You are not using a client certificate.")); - return; - } - - certfp = u->fingerprint; - } - - if (cl->FindCert(certfp)) - { - source.Reply(_("Fingerprint \002%s\002 already present on %s's certificate list."), certfp.c_str(), nc->display.c_str()); - return; - } - - if (certmap.find(certfp) != certmap.end()) - { - source.Reply(_("Fingerprint \002%s\002 is already in use."), certfp.c_str()); - return; - } - - cl->AddCert(certfp); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to ADD certificate fingerprint " << certfp << " to " << nc->display; - source.Reply(_("\002%s\002 added to %s's certificate list."), certfp.c_str(), nc->display.c_str()); - } - - void DoDel(CommandSource &source, NickCore *nc, Anope::string certfp) - { - NSCertList *cl = nc->Require<NSCertList>("certificates"); - - if (certfp.empty()) - { - User *u = source.GetUser(); - if (u) - certfp = u->fingerprint; - } - - if (certfp.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (!cl->FindCert(certfp)) - { - source.Reply(_("\002%s\002 not found on %s's certificate list."), certfp.c_str(), nc->display.c_str()); - return; - } - - cl->EraseCert(certfp); - cl->Check(); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to DELETE certificate fingerprint " << certfp << " from " << nc->display; - source.Reply(_("\002%s\002 deleted from %s's certificate list."), certfp.c_str(), nc->display.c_str()); - } - - void DoList(CommandSource &source, const NickCore *nc) - { - NSCertList *cl = nc->GetExt<NSCertList>("certificates"); - - if (!cl || !cl->GetCertCount()) - { - source.Reply(_("%s's certificate list is empty."), nc->display.c_str()); - return; - } - - source.Reply(_("Certificate list for %s:"), nc->display.c_str()); - for (unsigned i = 0; i < cl->GetCertCount(); ++i) - { - Anope::string fingerprint = cl->GetCert(i); - source.Reply(" %s", fingerprint.c_str()); - } - } - - public: - CommandNSCert(Module *creator) : Command(creator, "nickserv/cert", 1, 3) - { - this->SetDesc(_("Modify the nickname client certificate list")); - this->SetSyntax(_("ADD [\037nickname\037] [\037fingerprint\037]")); - this->SetSyntax(_("DEL [\037nickname\037] \037fingerprint\037")); - this->SetSyntax(_("LIST [\037nickname\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - Anope::string nick, certfp; - - if (cmd.equals_ci("LIST")) - nick = params.size() > 1 ? params[1] : ""; - else - { - nick = params.size() == 3 ? params[1] : ""; - certfp = params.size() > 1 ? params[params.size() - 1] : ""; - } - - NickCore *nc; - if (!nick.empty()) - { - const NickAlias *na = NickAlias::Find(nick); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - else if (na->nc != source.GetAccount() && !source.HasPriv("nickserv/access")) - { - source.Reply(ACCESS_DENIED); - return; - } - else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.GetAccount() != na->nc && na->nc->IsServicesOper() && !cmd.equals_ci("LIST")) - { - source.Reply(_("You may view but not modify the certificate list of other Services Operators.")); - return; - } - - nc = na->nc; - } - else - nc = source.nc; - - if (cmd.equals_ci("LIST")) - return this->DoList(source, nc); - else if (nc->HasExt("NS_SUSPENDED")) - source.Reply(NICK_X_SUSPENDED, nc->display.c_str()); - else if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, nc, certfp); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, nc, certfp); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Modifies or displays the certificate list for your nick.\n" - "If you connect to IRC and provide a client certificate with a\n" - "matching fingerprint in the cert list, you will be\n" - "automatically identified to services. Services Operators\n" - "may provide a nick to modify other users' certificate lists.\n" - " \n")); - source.Reply(_("Examples:\n" - " \n" - " \002CERT ADD\002\n" - " Adds your current fingerprint to the certificate list and\n" - " automatically identifies you when you connect to IRC\n" - " using this fingerprint.\n" - " \n" - " \002CERT DEL <fingerprint>\002\n" - " Removes the fingerprint <fingerprint> from your certificate list.\n" - " \n" - " \002CERT LIST\002\n" - " Displays the current certificate list.")); - return true; - } -}; - -class NSCert : public Module -{ - CommandNSCert commandnscert; - NSCertListImpl::ExtensibleItem certs; - CertServiceImpl cs; - - public: - NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnscert(this), certs(this, "certificates"), cs(this) - { - if (!IRCD || !IRCD->CanCertFP) - throw ModuleException("Your IRCd does not support ssl client certificates"); - } - - void OnFingerprint(User *u) anope_override - { - BotInfo *NickServ = Config->GetClient("NickServ"); - if (!NickServ || u->IsIdentified()) - return; - - NickCore *nc = cs.FindAccountFromCert(u->fingerprint); - if (!nc || nc->HasExt("NS_SUSPENDED")) - return; - - unsigned int maxlogins = Config->GetModule("ns_identify")->Get<unsigned int>("maxlogins"); - if (maxlogins && nc->users.size() >= maxlogins) - { - u->SendMessage(NickServ, _("Account \002%s\002 has already reached the maximum number of simultaneous logins (%u)."), nc->display.c_str(), maxlogins); - return; - } - - NickAlias *na = NickAlias::Find(u->nick); - if (na && na->nc == nc) - u->Identify(na); - else - u->Login(nc); - - u->SendMessage(NickServ, _("SSL certificate fingerprint accepted, you are now identified to \002%s\002."), nc->display.c_str()); - Log(NickServ) << u->GetMask() << " automatically identified for account " << nc->display << " via SSL certificate fingerprint"; - } - - EventReturn OnNickValidate(User *u, NickAlias *na) anope_override - { - NSCertList *cl = certs.Get(na->nc); - if (!u->fingerprint.empty() && cl && cl->FindCert(u->fingerprint)) - { - BotInfo *NickServ = Config->GetClient("NickServ"); - - unsigned int maxlogins = Config->GetModule("ns_identify")->Get<unsigned int>("maxlogins"); - if (maxlogins && na->nc->users.size() >= maxlogins) - { - u->SendMessage(NickServ, _("Account \002%s\002 has already reached the maximum number of simultaneous logins (%u)."), na->nc->display.c_str(), maxlogins); - return EVENT_CONTINUE; - } - - u->Identify(na); - - u->SendMessage(NickServ, _("SSL certificate fingerprint accepted, you are now identified.")); - Log(NickServ) << u->GetMask() << " automatically identified for account " << na->nc->display << " via SSL certificate fingerprint"; - return EVENT_ALLOW; - } - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(NSCert) diff --git a/modules/commands/ns_drop.cpp b/modules/commands/ns_drop.cpp deleted file mode 100644 index df632fd24..000000000 --- a/modules/commands/ns_drop.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSDrop : public Command -{ - public: - CommandNSDrop(Module *creator) : Command(creator, "nickserv/drop", 1, 1) - { - this->SetSyntax(_("\037nickname\037")); - this->SetDesc(_("Cancel the registration of a nickname")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - - if (Anope::ReadOnly && !source.HasPriv("nickserv/drop")) - { - source.Reply(_("Sorry, nickname de-registration is temporarily disabled.")); - return; - } - - NickAlias *na = NickAlias::Find(nick); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - - bool is_mine = source.GetAccount() == na->nc; - - if (!is_mine && !source.HasPriv("nickserv/drop")) - source.Reply(ACCESS_DENIED); - else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && !is_mine && na->nc->IsServicesOper()) - source.Reply(_("You may not drop other Services Operators' nicknames.")); - else - { - FOREACH_MOD(OnNickDrop, (source, na)); - - Log(!is_mine ? LOG_ADMIN : LOG_COMMAND, source, this) << "to drop nickname " << na->nick << " (group: " << na->nc->display << ") (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")"; - delete na; - - source.Reply(_("Nickname \002%s\002 has been dropped."), nick.c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Drops the given nick from the database. Once your nickname\n" - "is dropped you may lose all of your access and channels that\n" - "you may own. Any other user will be able to gain control of\n" - "this nick.")); - if (!source.HasPriv("nickserv/drop")) - source.Reply(_("You may drop any nick within your group.")); - else - source.Reply(_("As a Services Operator, you may drop any nick.")); - - return true; - } -}; - -class NSDrop : public Module -{ - CommandNSDrop commandnsdrop; - - public: - NSDrop(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsdrop(this) - { - - } -}; - -MODULE_INIT(NSDrop) diff --git a/modules/commands/ns_getemail.cpp b/modules/commands/ns_getemail.cpp deleted file mode 100644 index 0e782938f..000000000 --- a/modules/commands/ns_getemail.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * A simple call to check for all emails that a user may have registered - * with. It returns the nicks that match the email you provide. Wild - * Cards are not excepted. Must use user@email-host. - */ - -#include "module.h" - -class CommandNSGetEMail : public Command -{ - public: - CommandNSGetEMail(Module *creator) : Command(creator, "nickserv/getemail", 1, 1) - { - this->SetDesc(_("Matches and returns all users that registered using given email")); - this->SetSyntax(_("\037email\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &email = params[0]; - int j = 0; - - Log(LOG_ADMIN, source, this) << "on " << email; - - for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it) - { - const NickCore *nc = it->second; - - if (!nc->email.empty() && Anope::Match(nc->email, email)) - { - ++j; - source.Reply(_("Email matched: \002%s\002 (\002%s\002) to \002%s\002."), nc->display.c_str(), nc->email.c_str(), email.c_str()); - } - } - - if (j <= 0) - { - source.Reply(_("No registrations matching \002%s\002 were found."), email.c_str()); - return; - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Returns the matching accounts that used given email.")); - return true; - } -}; - -class NSGetEMail : public Module -{ - CommandNSGetEMail commandnsgetemail; - public: - NSGetEMail(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsgetemail(this) - { - - } -}; - -MODULE_INIT(NSGetEMail) diff --git a/modules/commands/ns_getpass.cpp b/modules/commands/ns_getpass.cpp deleted file mode 100644 index ae32fc2ef..000000000 --- a/modules/commands/ns_getpass.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSGetPass : public Command -{ - public: - CommandNSGetPass(Module *creator) : Command(creator, "nickserv/getpass", 1, 1) - { - this->SetDesc(_("Retrieve the password for a nickname")); - this->SetSyntax(_("\037nickname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - Anope::string tmp_pass; - const NickAlias *na; - - if (!(na = NickAlias::Find(nick))) - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && na->nc->IsServicesOper()) - source.Reply(_("You may not get the password of other Services Operators.")); - else - { - if (Anope::Decrypt(na->nc->pass, tmp_pass) == 1) - { - Log(LOG_ADMIN, source, this) << "for " << nick; - source.Reply(_("Password for %s is \002%s\002."), nick.c_str(), tmp_pass.c_str()); - } - else - source.Reply(_("GETPASS command unavailable because encryption is in use.")); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Returns the password for the given nickname. \002Note\002 that\n" - "whenever this command is used, a message including the\n" - "person who issued the command and the nickname it was used\n" - "on will be logged and sent out as a WALLOPS/GLOBOPS.")); - return true; - } -}; - -class NSGetPass : public Module -{ - CommandNSGetPass commandnsgetpass; - - public: - NSGetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsgetpass(this) - { - - Anope::string tmp_pass = "plain:tmp"; - if (!Anope::Decrypt(tmp_pass, tmp_pass)) - throw ModuleException("Incompatible with the encryption module being used"); - - } -}; - -MODULE_INIT(NSGetPass) diff --git a/modules/commands/ns_group.cpp b/modules/commands/ns_group.cpp deleted file mode 100644 index 63d0dff10..000000000 --- a/modules/commands/ns_group.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/ns_cert.h" - -class NSGroupRequest : public IdentifyRequest -{ - CommandSource source; - Command *cmd; - Anope::string nick; - Reference<NickAlias> target; - - public: - NSGroupRequest(Module *o, CommandSource &src, Command *c, const Anope::string &n, NickAlias *targ, const Anope::string &pass) : IdentifyRequest(o, targ->nc->display, pass), source(src), cmd(c), nick(n), target(targ) { } - - void OnSuccess() anope_override - { - if (!source.GetUser() || source.GetUser()->nick != nick || !target || !target->nc) - return; - - User *u = source.GetUser(); - NickAlias *na = NickAlias::Find(nick); - /* If the nick is already registered, drop it. */ - if (na) - { - FOREACH_MOD(OnChangeCoreDisplay, (na->nc, u->nick)); - delete na; - } - - na = new NickAlias(nick, target->nc); - - Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_usermask = last_usermask; - na->last_realname = u->realname; - na->time_registered = na->last_seen = Anope::CurTime; - - u->Login(target->nc); - FOREACH_MOD(OnNickGroup, (u, target)); - - Log(LOG_COMMAND, source, cmd) << "to make " << nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")"; - source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str()); - - u->lastnickreg = Anope::CurTime; - - } - - void OnFail() anope_override - { - if (!source.GetUser()) - return; - - Log(LOG_COMMAND, source, cmd) << "and failed to group to " << target->nick; - if (NickAlias::Find(GetAccount()) != NULL) - { - source.Reply(PASSWORD_INCORRECT); - source.GetUser()->BadPassword(); - } - else - source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); - } -}; - -class CommandNSGroup : public Command -{ - public: - CommandNSGroup(Module *creator) : Command(creator, "nickserv/group", 0, 2) - { - this->SetDesc(_("Join a group")); - this->SetSyntax(_("\037[target]\037 \037[password]\037")); - this->AllowUnregistered(true); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - - Anope::string nick; - if (params.empty()) - { - NickCore* core = u->Account(); - if (core) - nick = core->display; - } - else - nick = params[0]; - - if (nick.empty()) - { - this->SendSyntax(source); - return; - } - - const Anope::string &pass = params.size() > 1 ? params[1] : ""; - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, nickname grouping is temporarily disabled.")); - return; - } - - if (!IRCD->IsNickValid(u->nick)) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); - return; - } - - if (Config->GetModule("nickserv")->Get<bool>("restrictopernicks")) - for (unsigned i = 0; i < Oper::opers.size(); ++i) - { - Oper *o = Oper::opers[i]; - - if (!u->HasMode("OPER") && u->nick.find_ci(o->name) != Anope::string::npos) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); - return; - } - } - - NickAlias *target, *na = NickAlias::Find(u->nick); - const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest"); - time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay"); - unsigned maxaliases = Config->GetModule(this->owner)->Get<unsigned>("maxaliases"); - if (!(target = NickAlias::Find(nick))) - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - else if (Anope::CurTime < u->lastnickreg + reg_delay) - source.Reply(_("Please wait %d seconds before using the GROUP command again."), (reg_delay + u->lastnickreg) - Anope::CurTime); - else if (target->nc->HasExt("NS_SUSPENDED")) - { - Log(LOG_COMMAND, source, this) << "and tried to group to SUSPENDED nick " << target->nick; - source.Reply(NICK_X_SUSPENDED, target->nick.c_str()); - } - else if (na && Config->GetModule(this->owner)->Get<bool>("nogroupchange")) - source.Reply(_("Your nick is already registered.")); - else if (na && *target->nc == *na->nc) - source.Reply(_("You are already a member of the group of \002%s\002."), target->nick.c_str()); - else if (na && na->nc != u->Account()) - source.Reply(NICK_IDENTIFY_REQUIRED); - else if (maxaliases && target->nc->aliases->size() >= maxaliases && !target->nc->IsServicesOper()) - source.Reply(_("There are too many nicks in your group.")); - else if (u->nick.length() <= guestnick.length() + 7 && - u->nick.length() >= guestnick.length() + 1 && - !u->nick.find_ci(guestnick) && !u->nick.substr(guestnick.length()).find_first_not_of("1234567890")) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); - } - else - { - bool ok = false; - if (!na && u->Account() == target->nc) - ok = true; - - NSCertList *cl = target->nc->GetExt<NSCertList>("certificates"); - if (!u->fingerprint.empty() && cl && cl->FindCert(u->fingerprint)) - ok = true; - - if (ok == false && !pass.empty()) - { - NSGroupRequest *req = new NSGroupRequest(owner, source, this, u->nick, target, pass); - FOREACH_MOD(OnCheckAuthentication, (source.GetUser(), req)); - req->Dispatch(); - } - else - { - NSGroupRequest req(owner, source, this, u->nick, target, pass); - - if (ok) - req.OnSuccess(); - else - req.OnFail(); - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command makes your nickname join the \037target\037 nickname's\n" - "group. \037password\037 is the password of the target nickname.\n" - " \n" - "Joining a group will allow you to share your configuration,\n" - "memos, and channel privileges with all the nicknames in the\n" - "group, and much more!\n" - " \n" - "A group exists as long as it is useful. This means that even\n" - "if a nick of the group is dropped, you won't lose the\n" - "shared things described above, as long as there is at\n" - "least one nick remaining in the group.\n" - " \n" - "You may be able to use this command even if you have not registered\n" - "your nick yet. If your nick is already registered, you'll\n" - "need to identify yourself before using this command.\n" - " \n" - "It is recommended to use this command with a non-registered\n" - "nick because it will be registered automatically when\n" - "using this command. You may use it with a registered nick (to\n" - "change your group) only if your network administrators allowed\n" - "it.\n" - " \n" - "You can only be in one group at a time. Group merging is\n" - "not possible.\n" - " \n" - "\037Note\037: all the nicknames of a group have the same password.")); - return true; - } -}; - -class CommandNSUngroup : public Command -{ - public: - CommandNSUngroup(Module *creator) : Command(creator, "nickserv/ungroup", 0, 1) - { - this->SetDesc(_("Remove a nick from a group")); - this->SetSyntax(_("[\037nick\037]")); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - Anope::string nick = !params.empty() ? params[0] : ""; - NickAlias *na = NickAlias::Find(!nick.empty() ? nick : u->nick); - - if (u->Account()->aliases->size() == 1) - source.Reply(_("Your nick is not grouped to anything, you can't ungroup it.")); - else if (!na) - source.Reply(NICK_X_NOT_REGISTERED, !nick.empty() ? nick.c_str() : u->nick.c_str()); - else if (na->nc != u->Account()) - source.Reply(_("Nick %s is not in your group."), na->nick.c_str()); - else - { - NickCore *oldcore = na->nc; - - std::vector<NickAlias *>::iterator it = std::find(oldcore->aliases->begin(), oldcore->aliases->end(), na); - if (it != oldcore->aliases->end()) - oldcore->aliases->erase(it); - - if (na->nick.equals_ci(oldcore->display)) - oldcore->SetDisplay(oldcore->aliases->front()); - - NickCore *nc = new NickCore(na->nick); - na->nc = nc; - nc->aliases->push_back(na); - - nc->pass = oldcore->pass; - if (!oldcore->email.empty()) - nc->email = oldcore->email; - nc->language = oldcore->language; - - source.Reply(_("Nick %s has been ungrouped from %s."), na->nick.c_str(), oldcore->display.c_str()); - - User *user = User::Find(na->nick, true); - if (user) - /* The user on the nick who was ungrouped may be identified to the old group, set -r */ - user->RemoveMode(source.service, "REGISTERED"); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command ungroups your nick, or if given, the specificed nick,\n" - "from the group it is in. The ungrouped nick keeps its registration\n" - "time, password, email, greet, language, and url. Everything else\n" - "is reset. You may not ungroup yourself if there is only one nick in\n" - "your group.")); - return true; - } -}; - -class CommandNSGList : public Command -{ - public: - CommandNSGList(Module *creator) : Command(creator, "nickserv/glist", 0, 1) - { - this->SetDesc(_("Lists all nicknames in your group")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = !params.empty() ? params[0] : ""; - const NickCore *nc; - - if (!nick.empty()) - { - const NickAlias *na = NickAlias::Find(nick); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - else if (na->nc != source.GetAccount() && !source.IsServicesOper()) - { - source.Reply(ACCESS_DENIED); - return; - } - - nc = na->nc; - } - else - nc = source.GetAccount(); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Nick")).AddColumn(_("Expires")); - time_t nickserv_expire = Config->GetModule("nickserv")->Get<time_t>("expire", "21d"), - unconfirmed_expire = Config->GetModule("nickserv")->Get<time_t>("unconfirmedexpire", "1d"); - for (unsigned i = 0; i < nc->aliases->size(); ++i) - { - const NickAlias *na2 = nc->aliases->at(i); - - Anope::string expires; - if (na2->HasExt("NS_NO_EXPIRE")) - expires = NO_EXPIRE; - else if (!nickserv_expire || Anope::NoExpire) - ; - else if (na2->nc->HasExt("UNCONFIRMED") && unconfirmed_expire) - expires = Anope::strftime(na2->time_registered + unconfirmed_expire, source.GetAccount()); - else - expires = Anope::strftime(na2->last_seen + nickserv_expire, source.GetAccount()); - - ListFormatter::ListEntry entry; - entry["Nick"] = na2->nick; - entry["Expires"] = expires; - list.AddEntry(entry); - } - - source.Reply(!nick.empty() ? _("List of nicknames in the group of \002%s\002:") : _("List of nicknames in your group:"), nc->display.c_str()); - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("%d nickname(s) in the group."), nc->aliases->size()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (source.IsServicesOper()) - source.Reply(_("Syntax: \002%s [\037nickname\037]\002\n" - " \n" - "Without a parameter, lists all nicknames that are in\n" - "your group.\n" - " \n" - "With a parameter, lists all nicknames that are in the\n" - "group of the given nick.\n" - "Specifying a nick is limited to \002Services Operators\002."), - source.command.c_str()); - else - source.Reply(_("Syntax: \002%s\002\n" - " \n" - "Lists all nicks in your group."), source.command.c_str()); - - return true; - } -}; - -class NSGroup : public Module -{ - CommandNSGroup commandnsgroup; - CommandNSUngroup commandnsungroup; - CommandNSGList commandnsglist; - - public: - NSGroup(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsgroup(this), commandnsungroup(this), commandnsglist(this) - { - if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) - throw ModuleException(modname + " can not be used with options:nonicknameownership enabled"); - } -}; - -MODULE_INIT(NSGroup) diff --git a/modules/commands/ns_identify.cpp b/modules/commands/ns_identify.cpp deleted file mode 100644 index a188b2ee8..000000000 --- a/modules/commands/ns_identify.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class NSIdentifyRequest : public IdentifyRequest -{ - CommandSource source; - Command *cmd; - - public: - NSIdentifyRequest(Module *o, CommandSource &s, Command *c, const Anope::string &acc, const Anope::string &pass) : IdentifyRequest(o, acc, pass), source(s), cmd(c) { } - - void OnSuccess() anope_override - { - if (!source.GetUser()) - return; - - User *u = source.GetUser(); - NickAlias *na = NickAlias::Find(GetAccount()); - - if (!na) - source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); - else - { - if (u->IsIdentified()) - Log(LOG_COMMAND, source, cmd) << "to log out of account " << u->Account()->display; - - Log(LOG_COMMAND, source, cmd) << "and identified for account " << na->nc->display; - source.Reply(_("Password accepted - you are now recognized.")); - u->Identify(na); - } - } - - void OnFail() anope_override - { - if (source.GetUser()) - { - bool accountexists = NickAlias::Find(GetAccount()) != NULL; - Log(LOG_COMMAND, source, cmd) << "and failed to identify to" << (accountexists ? " " : " nonexistent ") << "account " << GetAccount(); - if (accountexists) - { - source.Reply(PASSWORD_INCORRECT); - source.GetUser()->BadPassword(); - } - else - source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); - } - } -}; - -class CommandNSIdentify : public Command -{ - public: - CommandNSIdentify(Module *creator) : Command(creator, "nickserv/identify", 1, 2) - { - this->SetDesc(_("Identify yourself with your password")); - this->SetSyntax(_("[\037account\037] \037password\037")); - this->AllowUnregistered(true); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - - const Anope::string &nick = params.size() == 2 ? params[0] : u->nick; - Anope::string pass = params[params.size() - 1]; - - NickAlias *na = NickAlias::Find(nick); - if (na && na->nc->HasExt("NS_SUSPENDED")) - { - source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); - return; - } - - if (u->Account() && na && u->Account() == na->nc) - { - source.Reply(_("You are already identified.")); - return; - } - - unsigned int maxlogins = Config->GetModule(this->owner)->Get<unsigned int>("maxlogins"); - if (na && maxlogins && na->nc->users.size() >= maxlogins) - { - source.Reply(_("Account \002%s\002 has already reached the maximum number of simultaneous logins (%u)."), na->nc->display.c_str(), maxlogins); - 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 - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Tells %s that you are really the owner of this\n" - "nick. Many commands require you to authenticate yourself\n" - "with this command before you use them. The password\n" - "should be the same one you sent with the \002REGISTER\002\n" - "command."), source.service->nick.c_str()); - return true; - } -}; - -class NSIdentify : public Module -{ - CommandNSIdentify commandnsidentify; - - public: - NSIdentify(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsidentify(this) - { - - } -}; - -MODULE_INIT(NSIdentify) diff --git a/modules/commands/ns_info.cpp b/modules/commands/ns_info.cpp deleted file mode 100644 index a1cdfc897..000000000 --- a/modules/commands/ns_info.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSInfo : public Command -{ - public: - CommandNSInfo(Module *creator) : Command(creator, "nickserv/info", 0, 2) - { - this->SetDesc(_("Displays information about a given nickname")); - this->SetSyntax(_("[\037nickname\037]")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - const Anope::string &nick = params.size() ? params[0] : (source.nc ? source.nc->display : source.GetNick()); - NickAlias *na = NickAlias::Find(nick); - bool has_auspex = source.HasPriv("nickserv/auspex"); - - if (!na) - { - if (BotInfo::Find(nick, true)) - source.Reply(_("Nick \002%s\002 is part of this Network's Services."), nick.c_str()); - else - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - } - else - { - bool nick_online = false, show_hidden = false; - - /* Is the real owner of the nick we're looking up online? -TheShadow */ - User *u2 = User::Find(na->nick, true); - if (u2 && u2->Account() == na->nc) - { - nick_online = true; - na->last_seen = Anope::CurTime; - } - - if (has_auspex || na->nc == source.GetAccount()) - show_hidden = true; - - source.Reply(_("%s is %s"), na->nick.c_str(), na->last_realname.c_str()); - - if (na->nc->HasExt("UNCONFIRMED")) - source.Reply(_("%s is an unconfirmed nickname."), na->nick.c_str()); - - if (na->nc->IsServicesOper() && (show_hidden || !na->nc->HasExt("HIDE_STATUS"))) - source.Reply(_("%s is a Services Operator of type %s."), na->nick.c_str(), na->nc->o->ot->GetName().c_str()); - - InfoFormatter info(source.nc); - - if (nick_online) - { - bool shown = false; - if (show_hidden && !na->last_realhost.empty()) - { - info[_("Online from")] = na->last_realhost; - shown = true; - } - if ((show_hidden || !na->nc->HasExt("HIDE_MASK")) && (!shown || na->last_usermask != na->last_realhost)) - info[_("Online from")] = na->last_usermask; - else - source.Reply(_("%s is currently online."), na->nick.c_str()); - } - else - { - Anope::string shown; - if (show_hidden || !na->nc->HasExt("HIDE_MASK")) - { - info[_("Last seen address")] = na->last_usermask; - shown = na->last_usermask; - } - - if (show_hidden && !na->last_realhost.empty() && na->last_realhost != shown) - info[_("Last seen address")] = na->last_realhost; - } - - info[_("Registered")] = Anope::strftime(na->time_registered, source.GetAccount()); - - if (!nick_online) - info[_("Last seen")] = Anope::strftime(na->last_seen, source.GetAccount()); - - if (!na->last_quit.empty() && (show_hidden || !na->nc->HasExt("HIDE_QUIT"))) - info[_("Last quit message")] = na->last_quit; - - if (!na->nc->email.empty() && (show_hidden || !na->nc->HasExt("HIDE_EMAIL"))) - info[_("Email address")] = na->nc->email; - - if (show_hidden) - { - if (na->HasVhost()) - { - if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty()) - info[_("VHost")] = na->GetVhostIdent() + "@" + na->GetVhostHost(); - else - info[_("VHost")] = na->GetVhostHost(); - } - } - - FOREACH_MOD(OnNickInfo, (source, na, info, show_hidden)); - - std::vector<Anope::string> replies; - info.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Displays information about the given nickname, such as\n" - "the nick's owner, last seen address and time, and nick\n" - "options. If no nick is given, and you are identified,\n" - "your account name is used, else your current nickname is\n" - "used.")); - - return true; - } -}; - - -class CommandNSSetHide : public Command -{ - public: - CommandNSSetHide(Module *creator, const Anope::string &sname = "nickserv/set/hide", size_t min = 2) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Hide certain pieces of nickname information")); - this->SetSyntax("{EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m, const Anope::string &arg) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - Anope::string onmsg, offmsg, flag; - - if (param.equals_ci("EMAIL")) - { - flag = "HIDE_EMAIL"; - onmsg = _("The E-mail address of \002%s\002 will now be hidden from %s INFO displays."); - offmsg = _("The E-mail address of \002%s\002 will now be shown in %s INFO displays."); - } - else if (param.equals_ci("USERMASK")) - { - flag = "HIDE_MASK"; - onmsg = _("The last seen user@host mask of \002%s\002 will now be hidden from %s INFO displays."); - offmsg = _("The last seen user@host mask of \002%s\002 will now be shown in %s INFO displays."); - } - else if (param.equals_ci("STATUS")) - { - flag = "HIDE_STATUS"; - onmsg = _("The services access status of \002%s\002 will now be hidden from %s INFO displays."); - offmsg = _("The services access status of \002%s\002 will now be shown in %s INFO displays."); - } - else if (param.equals_ci("QUIT")) - { - flag = "HIDE_QUIT"; - onmsg = _("The last quit message of \002%s\002 will now be hidden from %s INFO displays."); - offmsg = _("The last quit message of \002%s\002 will now be shown in %s INFO displays."); - } - else - { - this->OnSyntaxError(source, "HIDE"); - return; - } - - if (arg.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param.upper() << " to " << arg.upper() << " for " << nc->display; - nc->Extend<bool>(flag); - source.Reply(onmsg.c_str(), nc->display.c_str(), source.service->nick.c_str()); - } - else if (arg.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param.upper() << " to " << arg.upper() << " for " << nc->display; - nc->Shrink<bool>(flag); - source.Reply(offmsg.c_str(), nc->display.c_str(), source.service->nick.c_str()); - } - else - this->OnSyntaxError(source, "HIDE"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to prevent certain pieces of information from\n" - "being displayed when someone does a %s \002INFO\002 on your\n" - "nick. You can hide your E-mail address (\002EMAIL\002), last seen\n" - "user@host mask (\002USERMASK\002), your services access status\n" - "(\002STATUS\002) and last quit message (\002QUIT\002).\n" - "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSASetHide : public CommandNSSetHide -{ - public: - CommandNSSASetHide(Module *creator) : CommandNSSetHide(creator, "nickserv/saset/hide", 3) - { - this->SetSyntax(_("\037nickname\037 {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->ClearSyntax(); - this->Run(source, params[0], params[1], params[2]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to prevent certain pieces of information from\n" - "being displayed when someone does a %s \002INFO\002 on the\n" - "nick. You can hide the E-mail address (\002EMAIL\002), last seen\n" - "user@host mask (\002USERMASK\002), the services access status\n" - "(\002STATUS\002) and last quit message (\002QUIT\002).\n" - "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str()); - return true; - } -}; - -class NSInfo : public Module -{ - CommandNSInfo commandnsinfo; - - CommandNSSetHide commandnssethide; - CommandNSSASetHide commandnssasethide; - - SerializableExtensibleItem<bool> hide_email, hide_usermask, hide_status, hide_quit; - - public: - NSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsinfo(this), commandnssethide(this), commandnssasethide(this), - hide_email(this, "HIDE_EMAIL"), hide_usermask(this, "HIDE_MASK"), hide_status(this, "HIDE_STATUS"), - hide_quit(this, "HIDE_QUIT") - { - - } -}; - -MODULE_INIT(NSInfo) diff --git a/modules/commands/ns_list.cpp b/modules/commands/ns_list.cpp deleted file mode 100644 index 43e8d3f13..000000000 --- a/modules/commands/ns_list.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSList : public Command -{ - public: - CommandNSList(Module *creator) : Command(creator, "nickserv/list", 1, 2) - { - this->SetDesc(_("List all registered nicknames that match a given pattern")); - this->SetSyntax(_("\037pattern\037 [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - Anope::string pattern = params[0]; - const NickCore *mync; - unsigned nnicks; - bool is_servadmin = source.HasCommand("nickserv/list"); - int count = 0, from = 0, to = 0; - bool suspended, nsnoexpire, unconfirmed; - unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50"); - - suspended = nsnoexpire = unconfirmed = false; - - if (pattern[0] == '#') - { - Anope::string n1, n2; - sepstream(pattern.substr(1), '-').GetToken(n1, 0); - sepstream(pattern, '-').GetToken(n2, 1); - try - { - from = convertTo<int>(n1); - to = convertTo<int>(n2); - } - catch (const ConvertException &) - { - source.Reply(LIST_INCORRECT_RANGE); - return; - } - - pattern = "*"; - } - - nnicks = 0; - - if (is_servadmin && params.size() > 1) - { - Anope::string keyword; - spacesepstream keywords(params[1]); - while (keywords.GetToken(keyword)) - { - if (keyword.equals_ci("NOEXPIRE")) - nsnoexpire = true; - if (keyword.equals_ci("SUSPENDED")) - suspended = true; - if (keyword.equals_ci("UNCONFIRMED")) - unconfirmed = true; - } - } - - mync = source.nc; - ListFormatter list(source.GetAccount()); - - list.AddColumn(_("Nick")).AddColumn(_("Last usermask")); - - Anope::map<NickAlias *> ordered_map; - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it) - ordered_map[it->first] = it->second; - - for (Anope::map<NickAlias *>::const_iterator it = ordered_map.begin(), it_end = ordered_map.end(); it != it_end; ++it) - { - const NickAlias *na = it->second; - - /* Don't show private nicks to non-services admins. */ - if (na->nc->HasExt("NS_PRIVATE") && !is_servadmin && na->nc != mync) - continue; - else if (nsnoexpire && !na->HasExt("NS_NO_EXPIRE")) - continue; - else if (suspended && !na->nc->HasExt("NS_SUSPENDED")) - continue; - else if (unconfirmed && !na->nc->HasExt("UNCONFIRMED")) - continue; - - /* We no longer compare the pattern against the output buffer. - * Instead we build a nice nick!user@host buffer to compare. - * The output is then generated separately. -TheShadow */ - Anope::string buf = Anope::printf("%s!%s", na->nick.c_str(), !na->last_usermask.empty() ? na->last_usermask.c_str() : "*@*"); - if (na->nick.equals_ci(pattern) || Anope::Match(buf, pattern, false, true)) - { - if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= listmax) - { - bool isnoexpire = false; - if (is_servadmin && na->HasExt("NS_NO_EXPIRE")) - isnoexpire = true; - - ListFormatter::ListEntry entry; - entry["Nick"] = (isnoexpire ? "!" : "") + na->nick; - if (na->nc->HasExt("HIDE_MASK") && !is_servadmin && na->nc != mync) - entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Hostname hidden]")); - else if (na->nc->HasExt("NS_SUSPENDED")) - entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Suspended]")); - else if (na->nc->HasExt("UNCONFIRMED")) - entry["Last usermask"] = Language::Translate(source.GetAccount(), _("[Unconfirmed]")); - else - entry["Last usermask"] = na->last_usermask; - list.AddEntry(entry); - } - ++count; - } - } - - source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of list - %d/%d matches shown."), nnicks > listmax ? listmax : nnicks, nnicks); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all registered nicknames which match the given\n" - "pattern, in \037nick!user@host\037 format. Nicks with the \002PRIVATE\002\n" - "option set will only be displayed to Services Operators with the\n" - "proper access. Nicks with the \002NOEXPIRE\002 option set will have\n" - "a \002!\002 prefixed to the nickname for Services Operators to see.\n" - " \n" - "Note that a preceding '#' specifies a range.\n" - " \n" - "If the SUSPENDED, UNCONFIRMED or NOEXPIRE options are given, only\n" - "nicks which, respectively, are SUSPENDED, UNCONFIRMED or have the\n" - "NOEXPIRE flag set will be displayed. If multiple options are\n" - "given, all nicks matching at least one option will be displayed.\n" - "Note that these options are limited to \037Services Operators\037.\n" - " \n" - "Examples:\n" - " \n" - " \002LIST *!joeuser@foo.com\002\n" - " Lists all registered nicks owned by joeuser@foo.com.\n" - " \n" - " \002LIST *Bot*!*@*\002\n" - " Lists all registered nicks with \002Bot\002 in their\n" - " names (case insensitive).\n" - " \n" - " \002LIST * NOEXPIRE\002\n" - " Lists all registered nicks which have been set to not expire.\n" - " \n" - " \002LIST #51-100\002\n" - " Lists all registered nicks within the given range (51-100).")); - - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), regexengine.c_str()); - } - - return true; - } -}; - - -class CommandNSSetPrivate : public Command -{ - public: - CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Prevent the nickname from appearing in the LIST command")); - this->SetSyntax("{ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable private for " << nc->display; - nc->Extend<bool>("NS_PRIVATE"); - source.Reply(_("Private option is now \002on\002 for \002%s\002."), nc->display.c_str()); - } - else if (param.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable private for " << nc->display; - nc->Shrink<bool>("NS_PRIVATE"); - source.Reply(_("Private option is now \002off\002 for \002%s\002."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, "PRIVATE"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns %s's privacy option on or off for your nick.\n" - "With \002PRIVATE\002 set, your nickname will not appear in\n" - "nickname lists generated with %s's \002LIST\002 command.\n" - "(However, anyone who knows your nickname can still get\n" - "information on it using the \002INFO\002 command.)"), - source.service->nick.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSASetPrivate : public CommandNSSetPrivate -{ - public: - CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns %s's privacy option on or off for the nick.\n" - "With \002PRIVATE\002 set, the nickname will not appear in\n" - "nickname lists generated with %s's \002LIST\002 command.\n" - "(However, anyone who knows the nickname can still get\n" - "information on it using the \002INFO\002 command.)"), - source.service->nick.c_str(), source.service->nick.c_str()); - return true; - } -}; - - -class NSList : public Module -{ - CommandNSList commandnslist; - - CommandNSSetPrivate commandnssetprivate; - CommandNSSASetPrivate commandnssasetprivate; - - SerializableExtensibleItem<bool> priv; - - public: - NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnslist(this), commandnssetprivate(this), commandnssasetprivate(this), - priv(this, "NS_PRIVATE") - { - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) anope_override - { - if (!show_all) - return; - - if (priv.HasExt(na->nc)) - info.AddOption(_("Private")); - } -}; - -MODULE_INIT(NSList) diff --git a/modules/commands/ns_logout.cpp b/modules/commands/ns_logout.cpp deleted file mode 100644 index 7567626e0..000000000 --- a/modules/commands/ns_logout.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static ServiceReference<NickServService> NickServService("NickServService", "NickServ"); - -class CommandNSLogout : public Command -{ - public: - CommandNSLogout(Module *creator) : Command(creator, "nickserv/logout", 0, 2) - { - this->SetDesc(_("Reverses the effect of the IDENTIFY command")); - this->SetSyntax(_("[\037nickname\037 [REVALIDATE]]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - const Anope::string &nick = !params.empty() ? params[0] : ""; - const Anope::string ¶m = params.size() > 1 ? params[1] : ""; - - User *u2; - if (!source.IsServicesOper() && !nick.empty()) - this->OnSyntaxError(source, ""); - else if (!(u2 = (!nick.empty() ? User::Find(nick, true) : source.GetUser()))) - source.Reply(NICK_X_NOT_IN_USE, !nick.empty() ? nick.c_str() : source.GetNick().c_str()); - else if (!nick.empty() && u2->IsServicesOper()) - source.Reply(_("You can't logout %s, they are a Services Operator."), nick.c_str()); - else - { - if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE") && NickServService) - NickServService->Validate(u2); - - 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 */ - if (!nick.empty()) - source.Reply(_("Nick %s has been logged out."), nick.c_str()); - else - source.Reply(_("Your nick has been logged out.")); - - IRCD->SendLogout(u2); - u2->RemoveMode(source.service, "REGISTERED"); - u2->Logout(); - - /* Send out an event */ - FOREACH_MOD(OnNickLogout, (u2)); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Without a parameter, reverses the effect of the \002IDENTIFY\002\n" - "command, i.e. make you not recognized as the real owner of the nick\n" - "anymore. Note, however, that you won't be asked to reidentify\n" - "yourself.\n" - " \n" - "With a parameter, does the same for the given nick. If you\n" - "specify \002REVALIDATE\002 as well, Services will ask the given nick\n" - "to re-identify. This is limited to \002Services Operators\002.")); - - return true; - } -}; - -class NSLogout : public Module -{ - CommandNSLogout commandnslogout; - - public: - NSLogout(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnslogout(this) - { - - } -}; - -MODULE_INIT(NSLogout) diff --git a/modules/commands/ns_recover.cpp b/modules/commands/ns_recover.cpp deleted file mode 100644 index f41a8d782..000000000 --- a/modules/commands/ns_recover.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/ns_cert.h" - -static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); - -typedef std::map<Anope::string, ChannelStatus> NSRecoverInfo; - -class NSRecoverSvsnick -{ - public: - Reference<User> from; - Anope::string to; -}; - -class NSRecoverRequest : public IdentifyRequest -{ - CommandSource source; - Command *cmd; - Anope::string user; - - public: - NSRecoverRequest(Module *o, CommandSource &src, Command *c, const Anope::string &nick, const Anope::string &pass) : IdentifyRequest(o, nick, pass), source(src), cmd(c), user(nick) { } - - void OnSuccess() anope_override - { - User *u = User::Find(user, true); - if (!source.GetUser() || !source.service) - return; - - NickAlias *na = NickAlias::Find(user); - if (!na) - return; - - Log(LOG_COMMAND, source, cmd) << "for " << na->nick; - - /* Nick is being held by us, release it */ - if (na->HasExt("HELD")) - { - nickserv->Release(na); - source.Reply(_("Service's hold on \002%s\002 has been released."), na->nick.c_str()); - } - else if (!u) - { - source.Reply(_("No one is using your nick, and services are not holding it.")); - } - // If the user being recovered is identified for the account of the nick then the user is the - // same person that is executing the command, so kill them off (old GHOST command). - else if (u->Account() == na->nc) - { - if (!source.GetAccount() && na->nc->HasExt("NS_SECURE")) - { - source.GetUser()->Login(u->Account()); - Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->display; - } - - if (Config->GetModule("ns_recover")->Get<bool>("restoreonrecover")) - { - if (!u->chans.empty()) - { - NSRecoverInfo *ei = source.GetUser()->Extend<NSRecoverInfo>("recover"); - for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) - (*ei)[it->first->name] = it->second->status; - } - } - - u->SendMessage(source.service, _("This nickname has been recovered by %s. If you did not do\n" - "this then %s may have your password, and you should change it."), - source.GetNick().c_str(), source.GetNick().c_str()); - - Anope::string buf = source.command.upper() + " command used by " + source.GetNick(); - u->Kill(*source.service, buf); - - source.Reply(_("Ghost with your nick has been killed.")); - - if (IRCD->CanSVSNick) - IRCD->SendForceNickChange(source.GetUser(), GetAccount(), Anope::CurTime); - } - /* User is not identified or not identified to the same account as the person using this command */ - else - { - if (!source.GetAccount() && na->nc->HasExt("NS_SECURE")) - { - source.GetUser()->Login(na->nc); // Identify the user using the command if they arent identified - Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->nick << " (" << na->nc->display << ")"; - source.Reply(_("You have been logged in as \002%s\002."), na->nc->display.c_str()); - } - - u->SendMessage(source.service, _("This nickname has been recovered by %s."), source.GetNick().c_str()); - - if (IRCD->CanSVSNick) - { - NSRecoverSvsnick *svs = u->Extend<NSRecoverSvsnick>("svsnick"); - svs->from = source.GetUser(); - svs->to = u->nick; - } - - if (nickserv) - nickserv->Collide(u, na); - - if (IRCD->CanSVSNick) - { - /* If we can svsnick then release our hold and svsnick the user using the command */ - if (nickserv) - nickserv->Release(na); - - source.Reply(_("You have regained control of \002%s\002."), u->nick.c_str()); - } - else - { - source.Reply(_("The user with your nick has been removed. Use this command again\n" - "to release services's hold on your nick.")); - } - } - } - - void OnFail() anope_override - { - if (NickAlias::Find(GetAccount()) != NULL) - { - source.Reply(ACCESS_DENIED); - if (!GetPassword().empty()) - { - Log(LOG_COMMAND, source, cmd) << "with an invalid password for " << GetAccount(); - if (source.GetUser()) - source.GetUser()->BadPassword(); - } - } - else - source.Reply(NICK_X_NOT_REGISTERED, GetAccount().c_str()); - } -}; - -class CommandNSRecover : public Command -{ - public: - CommandNSRecover(Module *creator) : Command(creator, "nickserv/recover", 1, 2) - { - this->SetDesc(_("Regains control of your nick")); - this->SetSyntax(_("\037nickname\037 [\037password\037]")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - const Anope::string &pass = params.size() > 1 ? params[1] : ""; - - User *user = User::Find(nick, true); - - if (user && source.GetUser() == user) - { - source.Reply(_("You can't %s yourself!"), source.command.lower().c_str()); - return; - } - - const NickAlias *na = NickAlias::Find(nick); - - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - else if (na->nc->HasExt("NS_SUSPENDED")) - { - source.Reply(NICK_X_SUSPENDED, na->nick.c_str()); - return; - } - - bool ok = false; - if (source.GetAccount() == na->nc) - ok = true; - else if (!na->nc->HasExt("NS_SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser())) - ok = true; - - NSCertList *cl = na->nc->GetExt<NSCertList>("certificates"); - if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl && cl->FindCert(source.GetUser()->fingerprint)) - ok = true; - - if (ok == false && !pass.empty()) - { - NSRecoverRequest *req = new NSRecoverRequest(owner, source, this, na->nick, pass); - FOREACH_MOD(OnCheckAuthentication, (source.GetUser(), req)); - req->Dispatch(); - } - else - { - NSRecoverRequest req(owner, source, this, na->nick, pass); - - if (ok) - req.OnSuccess(); - else - req.OnFail(); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Recovers your nick from another user or from services.\n" - "If services are currently holding your nick, the hold\n" - "will be released. If another user is holding your nick\n" - "and is identified they will be killed (similar to the old\n" - "GHOST command). If they are not identified they will be\n" - "forced off of the nick.")); - return true; - } -}; - -class NSRecover : public Module -{ - CommandNSRecover commandnsrecover; - PrimitiveExtensibleItem<NSRecoverInfo> recover; - PrimitiveExtensibleItem<NSRecoverSvsnick> svsnick; - - public: - NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsrecover(this), recover(this, "recover"), svsnick(this, "svsnick") - { - - if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) - throw ModuleException(modname + " can not be used with options:nonicknameownership enabled"); - - } - - void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override - { - if (Config->GetModule(this)->Get<bool>("restoreonrecover")) - { - NSRecoverInfo *ei = recover.Get(u); - BotInfo *NickServ = Config->GetClient("NickServ"); - - if (ei != NULL && NickServ != NULL) - for (NSRecoverInfo::iterator it = ei->begin(), it_end = ei->end(); it != it_end;) - { - Channel *c = Channel::Find(it->first); - const Anope::string &cname = it->first; - ++it; - - /* User might already be on the channel */ - if (u->FindChannel(c)) - this->OnJoinChannel(u, c); - else if (IRCD->CanSVSJoin) - IRCD->SendSVSJoin(NickServ, u, cname, ""); - } - } - - NSRecoverSvsnick *svs = svsnick.Get(u); - if (svs) - { - if (svs->from) - { - // svsnick from to to - IRCD->SendForceNickChange(svs->from, svs->to, Anope::CurTime); - } - - svsnick.Unset(u); - } - } - - void OnJoinChannel(User *u, Channel *c) anope_override - { - if (Config->GetModule(this)->Get<bool>("restoreonrecover")) - { - NSRecoverInfo *ei = recover.Get(u); - - if (ei != NULL) - { - NSRecoverInfo::iterator it = ei->find(c->name); - if (it != ei->end()) - { - for (size_t i = 0; i < it->second.Modes().length(); ++i) - c->SetMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(it->second.Modes()[i]), u->GetUID()); - - ei->erase(it); - if (ei->empty()) - recover.Unset(u); - } - } - } - } -}; - -MODULE_INIT(NSRecover) diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp deleted file mode 100644 index ce5dbc997..000000000 --- a/modules/commands/ns_register.cpp +++ /dev/null @@ -1,429 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi); - -class CommandNSConfirm : public Command -{ - public: - CommandNSConfirm(Module *creator) : Command(creator, "nickserv/confirm", 1, 2) - { - this->SetDesc(_("Confirm a passcode")); - this->SetSyntax(_("\037passcode\037")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &passcode = params[0]; - - if (source.nc && !source.nc->HasExt("UNCONFIRMED") && source.HasPriv("nickserv/confirm")) - { - NickAlias *na = NickAlias::Find(passcode); - if (na == NULL) - source.Reply(NICK_X_NOT_REGISTERED, passcode.c_str()); - else if (na->nc->HasExt("UNCONFIRMED") == false) - source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str()); - else - { - na->nc->Shrink<bool>("UNCONFIRMED"); - FOREACH_MOD(OnNickConfirm, (source.GetUser(), na->nc)); - Log(LOG_ADMIN, source, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")"; - source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str()); - - /* Login the users online already */ - for (std::list<User *>::iterator it = na->nc->users.begin(); it != na->nc->users.end(); ++it) - { - User *u = *it; - - IRCD->SendLogin(u, na); - - NickAlias *u_na = NickAlias::Find(u->nick); - - /* Set +r if they're on a nick in the group */ - if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && u_na && *u_na->nc == *na->nc) - u->SetMode(source.service, "REGISTERED"); - } - } - } - else if (source.nc) - { - Anope::string *code = source.nc->GetExt<Anope::string>("passcode"); - if (code != NULL && *code == passcode) - { - NickCore *nc = source.nc; - nc->Shrink<Anope::string>("passcode"); - Log(LOG_COMMAND, source, this) << "to confirm their email"; - source.Reply(_("Your email address of \002%s\002 has been confirmed."), source.nc->email.c_str()); - nc->Shrink<bool>("UNCONFIRMED"); - FOREACH_MOD(OnNickConfirm, (source.GetUser(), nc)); - - if (source.GetUser()) - { - NickAlias *na = NickAlias::Find(source.GetNick()); - if (na) - { - IRCD->SendLogin(source.GetUser(), na); - if (!Config->GetModule("nickserv")->Get<bool>("nonicknameownership") && na->nc == source.GetAccount() && !na->nc->HasExt("UNCONFIRMED")) - source.GetUser()->SetMode(source.service, "REGISTERED"); - } - } - } - else - source.Reply(_("Invalid passcode.")); - } - else - source.Reply(_("Invalid passcode.")); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command is used by several commands as a way to confirm\n" - "changes made to your account.\n" - " \n" - "This is most commonly used to confirm your email address once\n" - "you register or change it.\n" - " \n" - "This is also used after the RESETPASS command has been used to\n" - "force identify you to your nick so you may change your password.")); - if (source.HasPriv("nickserv/confirm")) - source.Reply(_("Additionally, Services Operators with the \037nickserv/confirm\037 permission can\n" - "replace \037passcode\037 with a users nick to force validate them.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) anope_override - { - source.Reply(NICK_CONFIRM_INVALID); - } -}; - -class CommandNSRegister : public Command -{ - public: - CommandNSRegister(Module *creator) : Command(creator, "nickserv/register", 1, 2) - { - this->SetDesc(_("Register a nickname")); - if (Config->GetModule("nickserv")->Get<bool>("forceemail", "yes")) - this->SetSyntax(_("\037password\037 \037email\037")); - else - this->SetSyntax(_("\037password\037 \037[email]\037")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - Anope::string u_nick = source.GetNick(); - size_t nicklen = u_nick.length(); - Anope::string pass = params[0]; - Anope::string email = params.size() > 1 ? params[1] : ""; - const Anope::string &nsregister = Config->GetModule(this->owner)->Get<const Anope::string>("registration"); - - if (Anope::ReadOnly) - { - source.Reply(_("Sorry, nickname registration is temporarily disabled.")); - return; - } - - if (nsregister.equals_ci("disable")) - { - source.Reply(_("Registration is currently disabled.")); - return; - } - - time_t nickregdelay = Config->GetModule(this->owner)->Get<time_t>("nickregdelay"); - time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay"); - if (u && !u->HasMode("OPER") && nickregdelay && Anope::CurTime - u->timestamp < nickregdelay) - { - source.Reply(_("You must have been using this nick for at least %d seconds to register."), nickregdelay); - return; - } - - /* Prevent "Guest" nicks from being registered. -TheShadow */ - - /* Guest nick can now have a series of between 1 and 7 digits. - * --lara - */ - const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest"); - if (nicklen <= guestnick.length() + 7 && nicklen >= guestnick.length() + 1 && !u_nick.find_ci(guestnick) && u_nick.substr(guestnick.length()).find_first_not_of("1234567890") == Anope::string::npos) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); - return; - } - - if (!IRCD->IsNickValid(u_nick)) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); - return; - } - - if (BotInfo::Find(u_nick, true)) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); - return; - } - - if (Config->GetModule("nickserv")->Get<bool>("restrictopernicks")) - for (unsigned i = 0; i < Oper::opers.size(); ++i) - { - Oper *o = Oper::opers[i]; - - if (!source.IsOper() && u_nick.find_ci(o->name) != Anope::string::npos) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); - return; - } - } - - 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) - source.Reply(_("Please wait %d seconds before using the REGISTER command again."), (u->lastnickreg + reg_delay) - Anope::CurTime); - else if (NickAlias::Find(u_nick) != NULL) - 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() > passlen) - source.Reply(PASSWORD_TOO_LONG, passlen); - else if (!email.empty() && !Mail::Validate(email)) - source.Reply(MAIL_X_INVALID, email.c_str()); - else - { - NickCore *nc = new NickCore(u_nick); - NickAlias *na = new NickAlias(u_nick, nc); - Anope::Encrypt(pass, nc->pass); - if (!email.empty()) - nc->email = email; - - if (u) - { - na->last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_realname = u->realname; - } - else - na->last_realname = source.GetNick(); - - Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")"; - - if (na->nc->GetAccessCount()) - source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str()); - else - source.Reply(_("Nickname \002%s\002 registered."), u_nick.c_str()); - - Anope::string tmp_pass; - if (Anope::Decrypt(na->nc->pass, tmp_pass) == 1) - source.Reply(_("Your password is \002%s\002 - remember this for later use."), tmp_pass.c_str()); - - if (nsregister.equals_ci("admin")) - { - nc->Extend<bool>("UNCONFIRMED"); - // User::Identify() called below will notify the user that their registration is pending - } - else if (nsregister.equals_ci("mail")) - { - if (!email.empty()) - { - nc->Extend<bool>("UNCONFIRMED"); - SendRegmail(NULL, na, source.service); - } - } - - FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass)); - - if (u) - { - u->Identify(na); - u->lastnickreg = Anope::CurTime; - } - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Registers your nickname in the %s database. Once\n" - "your nick is registered, you can use the \002SET\002 and \002ACCESS\002\n" - "commands to configure your nick's settings as you like\n" - "them. Make sure you remember the password you use when\n" - "registering - you'll need it to make changes to your nick\n" - "later. (Note that \002case matters!\002 \037ANOPE\037, \037Anope\037, and\n" - "\037anope\037 are all different passwords!)\n" - " \n" - "Guidelines on choosing passwords:\n" - " \n" - "Passwords should not be easily guessable. For example,\n" - "using your real name as a password is a bad idea. Using\n" - "your nickname as a password is a much worse idea ;) and,\n" - "in fact, %s will not allow it. Also, short\n" - "passwords are vulnerable to trial-and-error searches, so\n" - "you should choose a password at least 5 characters long.\n" - "Finally, the space character cannot be used in passwords."), - source.service->nick.c_str(), source.service->nick.c_str()); - - if (!Config->GetModule("nickserv")->Get<bool>("forceemail", "yes")) - { - source.Reply(" "); - source.Reply(_("The \037email\037 parameter is optional and will set the email\n" - "for your nick immediately.\n" - "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person. You may also wish to \002SET HIDE\002 it\n" - "after registering if it isn't the default setting already.")); - } - - source.Reply(" "); - source.Reply(_("This command also creates a new group for your nickname,\n" - "that will allow you to register other nicks later sharing\n" - "the same configuration, the same set of memos and the\n" - "same channel privileges.")); - return true; - } -}; - -class CommandNSResend : public Command -{ - public: - CommandNSResend(Module *creator) : Command(creator, "nickserv/resend", 0, 0) - { - this->SetDesc(_("Resend registration confirmation email")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail")) - { - source.Reply(ACCESS_DENIED); - return; - } - - const NickAlias *na = NickAlias::Find(source.GetNick()); - - if (na == NULL) - source.Reply(NICK_NOT_REGISTERED); - else if (na->nc != source.GetAccount() || !source.nc->HasExt("UNCONFIRMED")) - source.Reply(_("Your account is already confirmed.")); - else - { - if (Anope::CurTime < source.nc->lastmail + Config->GetModule(this->owner)->Get<time_t>("resenddelay")) - source.Reply(_("Cannot send mail now; please retry a little later.")); - else if (SendRegmail(source.GetUser(), na, source.service)) - { - na->nc->lastmail = Anope::CurTime; - source.Reply(_("Your passcode has been re-sent to %s."), na->nc->email.c_str()); - Log(LOG_COMMAND, source, this) << "to resend registration verification code"; - } - else - Log(this->owner) << "Unable to resend registration verification code for " << source.GetNick(); - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (!Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail")) - return false; - - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command will resend you the registration confirmation email.")); - return true; - } - - void OnServHelp(CommandSource &source) anope_override - { - if (Config->GetModule(this->owner)->Get<const Anope::string>("registration").equals_ci("mail")) - Command::OnServHelp(source); - } -}; - -class NSRegister : public Module -{ - CommandNSRegister commandnsregister; - CommandNSConfirm commandnsconfirm; - CommandNSResend commandnsrsend; - - SerializableExtensibleItem<bool> unconfirmed; - SerializableExtensibleItem<Anope::string> passcode; - - public: - NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsregister(this), commandnsconfirm(this), commandnsrsend(this), unconfirmed(this, "UNCONFIRMED"), - passcode(this, "passcode") - { - if (Config->GetModule(this)->Get<const Anope::string>("registration").equals_ci("disable")) - throw ModuleException("Module " + this->name + " will not load with registration disabled."); - } - - void OnNickIdentify(User *u) anope_override - { - BotInfo *NickServ; - if (unconfirmed.HasExt(u->Account()) && (NickServ = Config->GetClient("NickServ"))) - { - const Anope::string &nsregister = Config->GetModule(this)->Get<const Anope::string>("registration"); - if (nsregister.equals_ci("admin")) - u->SendMessage(NickServ, _("All new accounts must be validated by an administrator. Please wait for your registration to be confirmed.")); - else - u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you.")); - const NickAlias *this_na = NickAlias::Find(u->Account()->display); - time_t time_registered = Anope::CurTime - this_na->time_registered; - time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d"); - if (unconfirmed_expire > time_registered) - u->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s."), Anope::Duration(unconfirmed_expire - time_registered, u->Account()).c_str()); - } - } - - void OnPreNickExpire(NickAlias *na, bool &expire) anope_override - { - if (unconfirmed.HasExt(na->nc)) - { - time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d"); - if (unconfirmed_expire && Anope::CurTime - na->time_registered >= unconfirmed_expire) - expire = true; - } - } -}; - -static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi) -{ - NickCore *nc = na->nc; - - Anope::string *code = na->nc->GetExt<Anope::string>("passcode"); - if (code == NULL) - { - code = na->nc->Extend<Anope::string>("passcode"); - *code = Anope::Random(9); - } - - Anope::string subject = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("registration_subject").c_str()), - message = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("registration_message").c_str()); - - subject = subject.replace_all_cs("%n", na->nick); - 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("%n", na->nick); - message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); - message = message.replace_all_cs("%c", *code); - - return Mail::Send(u, nc, bi, subject, message); -} - -MODULE_INIT(NSRegister) diff --git a/modules/commands/ns_resetpass.cpp b/modules/commands/ns_resetpass.cpp deleted file mode 100644 index b1f835a01..000000000 --- a/modules/commands/ns_resetpass.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static bool SendResetEmail(User *u, const NickAlias *na, BotInfo *bi); - -class CommandNSResetPass : public Command -{ - public: - CommandNSResetPass(Module *creator) : Command(creator, "nickserv/resetpass", 2, 2) - { - this->SetDesc(_("Helps you reset lost passwords")); - this->SetSyntax(_("\037nickname\037 \037email\037")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const NickAlias *na; - - if (!(na = NickAlias::Find(params[0]))) - source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); - else if (!na->nc->email.equals_ci(params[1])) - source.Reply(_("Incorrect email address.")); - else - { - if (SendResetEmail(source.GetUser(), na, source.service)) - { - Log(LOG_COMMAND, source, this) << "for " << na->nick << " (group: " << na->nc->display << ")"; - source.Reply(_("Password reset email for \002%s\002 has been sent."), na->nick.c_str()); - } - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sends a passcode to the nickname with instructions on how to\n" - "reset their password. Email must be the email address associated\n" - "to the nickname.")); - return true; - } -}; - -struct ResetInfo -{ - Anope::string code; - time_t time; -}; - -class NSResetPass : public Module -{ - CommandNSResetPass commandnsresetpass; - PrimitiveExtensibleItem<ResetInfo> reset; - - public: - NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsresetpass(this), reset(this, "reset") - { - if (!Config->GetBlock("mail")->Get<bool>("usemail")) - throw ModuleException("Not using mail."); - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override - { - if (command->name == "nickserv/confirm" && params.size() > 1) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return EVENT_STOP; - } - - NickAlias *na = NickAlias::Find(params[0]); - - ResetInfo *ri = na ? reset.Get(na->nc) : NULL; - if (na && ri) - { - NickCore *nc = na->nc; - const Anope::string &passcode = params[1]; - if (ri->time < Anope::CurTime - 3600) - { - reset.Unset(nc); - source.Reply(_("Your password reset request has expired.")); - } - else if (passcode.equals_cs(ri->code)) - { - reset.Unset(nc); - nc->Shrink<bool>("UNCONFIRMED"); - - Log(LOG_COMMAND, source, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify as " << na->nick; - - if (source.GetUser()) - { - source.GetUser()->Identify(na); - source.Reply(_("You are now identified for your nick. Change your password now.")); - } - } - else - return EVENT_CONTINUE; - - return EVENT_STOP; - } - } - - return EVENT_CONTINUE; - } -}; - -static bool SendResetEmail(User *u, const NickAlias *na, BotInfo *bi) -{ - Anope::string subject = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("reset_subject").c_str()), - message = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("reset_message").c_str()), - passcode = Anope::Random(20); - - subject = subject.replace_all_cs("%n", na->nick); - subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); - subject = subject.replace_all_cs("%c", passcode); - - message = message.replace_all_cs("%n", na->nick); - message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname")); - message = message.replace_all_cs("%c", passcode); - - ResetInfo *ri = na->nc->Extend<ResetInfo>("reset"); - ri->code = passcode; - ri->time = Anope::CurTime; - - return Mail::Send(u, na->nc, bi, subject, message); -} - -MODULE_INIT(NSResetPass) diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp deleted file mode 100644 index f9351424e..000000000 --- a/modules/commands/ns_set.cpp +++ /dev/null @@ -1,1341 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSSet : public Command -{ - public: - CommandNSSet(Module *creator) : Command(creator, "nickserv/set", 1, 3) - { - this->SetDesc(_("Set options, including kill protection")); - this->SetSyntax(_("\037option\037 \037parameters\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->OnSyntaxError(source, ""); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); - - Anope::string this_name = source.command; - bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"), - hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands"); - for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - - if (c_name.find_ci(this_name + " ") == 0) - { - ServiceReference<Command> c("Command", info.name); - // XXX dup - if (!c) - continue; - else if (hide_registered_commands && !c->AllowUnregistered() && !source.GetAccount()) - continue; - else if (hide_privileged_commands && !info.permission.empty() && !source.HasCommand(info.permission)) - continue; - - source.command = c_name; - c->OnServHelp(source); - } - } - - source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); - - return true; - } -}; - -class CommandNSSASet : public Command -{ - public: - CommandNSSASet(Module *creator) : Command(creator, "nickserv/saset", 2, 4) - { - this->SetDesc(_("Set SET-options on another nickname")); - this->SetSyntax(_("\037option\037 \037nickname\037 \037parameters\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->OnSyntaxError(source, ""); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets various nickname options. \037option\037 can be one of:")); - - Anope::string this_name = source.command; - for (CommandInfo::map::const_iterator it = source.service->commands.begin(), it_end = source.service->commands.end(); it != it_end; ++it) - { - const Anope::string &c_name = it->first; - const CommandInfo &info = it->second; - - if (c_name.find_ci(this_name + " ") == 0) - { - ServiceReference<Command> command("Command", info.name); - if (command) - { - source.command = c_name; - command->OnServHelp(source); - } - } - } - - source.Reply(_("Type \002%s%s HELP %s \037option\037\002 for more information\n" - "on a specific option. The options will be set on the given\n" - "\037nickname\037."), Config->StrictPrivmsg.c_str(), source.service->nick.c_str(), this_name.c_str()); - return true; - } -}; - -class CommandNSSetPassword : public Command -{ - public: - CommandNSSetPassword(Module *creator) : Command(creator, "nickserv/set/password", 1) - { - this->SetDesc(_("Set your nickname password")); - this->SetSyntax(_("\037new-password\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string ¶m = params[0]; - unsigned len = param.length(); - - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (source.GetNick().equals_ci(param) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5)) - { - source.Reply(MORE_OBSCURE_PASSWORD); - return; - } - - unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"); - if (len > passlen) - { - source.Reply(PASSWORD_TOO_LONG, passlen); - return; - } - - Log(LOG_COMMAND, source, this) << "to change their password"; - - Anope::Encrypt(param, source.nc->pass); - Anope::string tmp_pass; - if (Anope::Decrypt(source.nc->pass, tmp_pass) == 1) - source.Reply(_("Password for \002%s\002 changed to \002%s\002."), source.nc->display.c_str(), tmp_pass.c_str()); - else - source.Reply(_("Password for \002%s\002 changed."), source.nc->display.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the password used to identify you as the nick's\n" - "owner.")); - return true; - } -}; - -class CommandNSSASetPassword : public Command -{ - public: - CommandNSSASetPassword(Module *creator) : Command(creator, "nickserv/saset/password", 2, 2) - { - this->SetDesc(_("Set the nickname password")); - this->SetSyntax(_("\037nickname\037 \037new-password\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *setter_na = NickAlias::Find(params[0]); - if (setter_na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); - return; - } - NickCore *nc = setter_na->nc; - - size_t len = params[1].length(); - - if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper()) - { - source.Reply(_("You may not change the password of other Services Operators.")); - return; - } - - if (nc->display.equals_ci(params[1]) || (Config->GetBlock("options")->Get<bool>("strictpasswords") && len < 5)) - { - source.Reply(MORE_OBSCURE_PASSWORD); - return; - } - - unsigned int passlen = Config->GetModule("nickserv")->Get<unsigned>("passlen", "32"); - if (len > passlen) - { - source.Reply(PASSWORD_TOO_LONG, passlen); - return; - } - - Log(LOG_ADMIN, source, this) << "to change the password of " << nc->display; - - Anope::Encrypt(params[1], nc->pass); - Anope::string tmp_pass; - if (Anope::Decrypt(nc->pass, tmp_pass) == 1) - source.Reply(_("Password for \002%s\002 changed to \002%s\002."), nc->display.c_str(), tmp_pass.c_str()); - else - source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the password used to identify as the nick's owner.")); - return true; - } -}; - -class CommandNSSetAutoOp : public Command -{ - public: - CommandNSSetAutoOp(Module *creator, const Anope::string &sname = "nickserv/set/autoop", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Sets whether services should set channel status modes on you automatically.")); - this->SetSyntax("{ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable autoop for " << na->nc->display; - nc->Extend<bool>("AUTOOP"); - source.Reply(_("Services will from now on set status modes on %s in channels."), nc->display.c_str()); - } - else if (param.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable autoop for " << na->nc->display; - nc->Shrink<bool>("AUTOOP"); - source.Reply(_("Services will no longer set status modes on %s in channels."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, "AUTOOP"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - BotInfo *bi = Config->GetClient("ChanServ"); - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets whether you will be given your channel status modes automatically.\n" - "Set to \002ON\002 to allow %s to set status modes on you automatically\n" - "when entering channels. Note that depending on channel settings some modes\n" - "may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ"); - return true; - } -}; - -class CommandNSSASetAutoOp : public CommandNSSetAutoOp -{ - public: - CommandNSSASetAutoOp(Module *creator) : CommandNSSetAutoOp(creator, "nickserv/saset/autoop", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - BotInfo *bi = Config->GetClient("ChanServ"); - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets whether the given nickname will be given its status modes\n" - "in channels automatically. Set to \002ON\002 to allow %s\n" - "to set status modes on the given nickname automatically when it\n" - "is entering channels. Note that depending on channel settings\n" - "some modes may not get set automatically."), bi ? bi->nick.c_str() : "ChanServ"); - return true; - } -}; - -class CommandNSSetDisplay : public Command -{ - public: - CommandNSSetDisplay(Module *creator, const Anope::string &sname = "nickserv/set/display", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Set the display of your group in Services")); - this->SetSyntax(_("\037new-display\037")); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param); - - if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) - { - source.Reply(_("This command may not be used on this network because nickname ownership is disabled.")); - return; - } - if (user_na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - else if (!na || *na->nc != *user_na->nc) - { - source.Reply(_("The new display MUST be a nickname of the nickname group %s."), user_na->nc->display.c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, user_na->nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick; - - user_na->nc->SetDisplay(na); - - /* Send updated account name */ - for (std::list<User *>::iterator it = user_na->nc->users.begin(); it != user_na->nc->users.end(); ++it) - { - User *u = *it; - IRCD->SendLogin(u, user_na); - } - - source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str()); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the display used to refer to your nickname group in\n" - "Services. The new display MUST be a nick of your group.")); - return true; - } -}; - -class CommandNSSASetDisplay : public CommandNSSetDisplay -{ - public: - CommandNSSASetDisplay(Module *creator) : CommandNSSetDisplay(creator, "nickserv/saset/display", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 \037new-display\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the display used to refer to the nickname group in\n" - "Services. The new display MUST be a nick of the group.")); - return true; - } -}; - -class CommandNSSetEmail : public Command -{ - static bool SendConfirmMail(User *u, BotInfo *bi, const Anope::string &new_email) - { - Anope::string code = Anope::Random(9); - - std::pair<Anope::string, Anope::string> *n = u->Account()->Extend<std::pair<Anope::string, Anope::string> >("ns_set_email"); - n->first = new_email; - n->second = code; - - Anope::string subject = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_subject"), - 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); - - Anope::string old = u->Account()->email; - u->Account()->email = new_email; - bool b = Mail::Send(u, u->Account(), bi, subject, message); - u->Account()->email = old; - return b; - } - - public: - CommandNSSetEmail(Module *creator, const Anope::string &cname = "nickserv/set/email", size_t min = 0) : Command(creator, cname, min, min + 1) - { - this->SetDesc(_("Associate an E-mail address with your nickname")); - this->SetSyntax(_("\037address\037")); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - if (nc->HasExt("UNCONFIRMED")) - { - source.Reply(_("You may not change the email of an unconfirmed account.")); - return; - } - - if (param.empty() && Config->GetModule("nickserv")->Get<bool>("forceemail", "yes")) - { - source.Reply(_("You cannot unset the e-mail on this network.")); - return; - } - else if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && source.nc != nc && nc->IsServicesOper()) - { - source.Reply(_("You may not change the e-mail of other Services Operators.")); - return; - } - else if (!param.empty() && !Mail::Validate(param)) - { - source.Reply(MAIL_X_INVALID, param.c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (!param.empty() && Config->GetModule("nickserv")->Get<bool>("confirmemailchanges") && !source.IsServicesOper()) - { - if (SendConfirmMail(source.GetUser(), source.service, param)) - source.Reply(_("A confirmation e-mail has been sent to \002%s\002. Follow the instructions in it to change your e-mail address."), param.c_str()); - } - else - { - if (!param.empty()) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the email of " << nc->display << " to " << param; - nc->email = param; - source.Reply(_("E-mail address for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str()); - } - else - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the email of " << nc->display; - nc->email.clear(); - source.Reply(_("E-mail address for \002%s\002 unset."), nc->display.c_str()); - } - } - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params.size() ? params[0] : ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Associates the given E-mail address with your nickname.\n" - "This address will be displayed whenever someone requests\n" - "information on the nickname with the \002INFO\002 command.")); - return true; - } -}; - -class CommandNSSASetEmail : public CommandNSSetEmail -{ - public: - CommandNSSASetEmail(Module *creator) : CommandNSSetEmail(creator, "nickserv/saset/email", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 \037address\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params.size() > 1 ? params[1] : ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Associates the given E-mail address with the nickname.")); - return true; - } -}; - -class CommandNSSetKeepModes : public Command -{ - public: - CommandNSSetKeepModes(Module *creator, const Anope::string &sname = "nickserv/set/keepmodes", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Enable or disable keep modes")); - this->SetSyntax("{ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable keepmodes for " << nc->display; - nc->Extend<bool>("NS_KEEP_MODES"); - source.Reply(_("Keep modes for %s is now \002on\002."), nc->display.c_str()); - } - else if (param.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable keepmodes for " << nc->display; - nc->Shrink<bool>("NS_KEEP_MODES"); - source.Reply(_("Keep modes for %s is now \002off\002."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, ""); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables keepmodes for your nick. If keep\n" - "modes is enabled, services will remember your usermodes\n" - "and attempt to re-set them the next time you authenticate.")); - return true; - } -}; - -class CommandNSSASetKeepModes : public CommandNSSetKeepModes -{ - public: - CommandNSSASetKeepModes(Module *creator) : CommandNSSetKeepModes(creator, "nickserv/saset/keepmodes", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Enables or disables keepmodes for the given nick. If keep\n" - "modes is enabled, services will remember users' usermodes\n" - "and attempt to re-set them the next time they authenticate.")); - return true; - } -}; - -class CommandNSSetKill : public Command -{ - public: - CommandNSSetKill(Module *creator, const Anope::string &sname = "nickserv/set/kill", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Turn protection on or off")); - this->SetSyntax("{ON | QUICK | IMMED | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - if (Config->GetModule("nickserv")->Get<bool>("nonicknameownership")) - { - source.Reply(_("This command may not be used on this network because nickname ownership is disabled.")); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - nc->Extend<bool>("KILLPROTECT"); - nc->Shrink<bool>("KILL_QUICK"); - nc->Shrink<bool>("KILL_IMMED"); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display; - source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str()); - } - else if (param.equals_ci("QUICK")) - { - nc->Extend<bool>("KILLPROTECT"); - nc->Extend<bool>("KILL_QUICK"); - nc->Shrink<bool>("KILL_IMMED"); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display; - source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str()); - } - else if (param.equals_ci("IMMED")) - { - if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed")) - { - nc->Extend<bool>("KILLPROTECT"); - nc->Shrink<bool>("KILL_QUICK"); - nc->Extend<bool>("KILL_IMMED"); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display; - source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str()); - } - else - source.Reply(_("The \002IMMED\002 option is not available on this network.")); - } - else if (param.equals_ci("OFF")) - { - nc->Shrink<bool>("KILLPROTECT"); - nc->Shrink<bool>("KILL_QUICK"); - nc->Shrink<bool>("KILL_IMMED"); - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display; - source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, "KILL"); - - return; - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns the automatic protection option for your nick\n" - "on or off. With protection on, if another user\n" - "tries to take your nick, they will be given one minute to\n" - "change to another nick, after which %s will forcibly change\n" - "their nick.\n" - " \n" - "If you select \002QUICK\002, the user will be given only 20 seconds\n" - "to change nicks instead of the usual 60. If you select\n" - "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" - "warned first or given a chance to change their nick; please\n" - "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSASetKill : public CommandNSSetKill -{ - public: - CommandNSSASetKill(Module *creator) : CommandNSSetKill(creator, "nickserv/saset/kill", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | QUICK | IMMED | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns the automatic protection option for the nick\n" - "on or off. With protection on, if another user\n" - "tries to take the nick, they will be given one minute to\n" - "change to another nick, after which %s will forcibly change\n" - "their nick.\n" - " \n" - "If you select \002QUICK\002, the user will be given only 20 seconds\n" - "to change nicks instead of the usual 60. If you select\n" - "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" - "warned first or given a chance to change their nick; please\n" - "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSetLanguage : public Command -{ - public: - CommandNSSetLanguage(Module *creator, const Anope::string &sname = "nickserv/set/language", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Set the language Services will use when messaging you")); - this->SetSyntax(_("\037language\037")); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param != "en_US") - for (unsigned j = 0; j < Language::Languages.size(); ++j) - { - if (Language::Languages[j] == param) - break; - else if (j + 1 == Language::Languages.size()) - { - this->OnSyntaxError(source, ""); - return; - } - } - - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the language of " << nc->display << " to " << param; - - nc->language = param; - if (source.GetAccount() == nc) - source.Reply(_("Language changed to \002English\002.")); - else - source.Reply(_("Language for \002%s\002 changed to \002%s\002."), nc->display.c_str(), Language::Translate(param.c_str(), _("English"))); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶m) anope_override - { - this->Run(source, source.nc->display, param[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the language Services uses when sending messages to\n" - "you (for example, when responding to a command you send).\n" - "\037language\037 should be chosen from the following list of\n" - "supported languages:")); - - source.Reply(" en_US (English)"); - for (unsigned j = 0; j < Language::Languages.size(); ++j) - { - const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English")); - if (langname == "English") - continue; - source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str()); - } - - return true; - } -}; - -class CommandNSSASetLanguage : public CommandNSSetLanguage -{ - public: - CommandNSSASetLanguage(Module *creator) : CommandNSSetLanguage(creator, "nickserv/saset/language", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 \037language\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Changes the language Services uses when sending messages to\n" - "the given user (for example, when responding to a command they send).\n" - "\037language\037 should be chosen from the following list of\n" - "supported languages:")); - source.Reply(" en (English)"); - for (unsigned j = 0; j < Language::Languages.size(); ++j) - { - const Anope::string &langname = Language::Translate(Language::Languages[j].c_str(), _("English")); - if (langname == "English") - continue; - source.Reply(" %s (%s)", Language::Languages[j].c_str(), langname.c_str()); - } - return true; - } -}; - -class CommandNSSetMessage : public Command -{ - public: - CommandNSSetMessage(Module *creator, const Anope::string &sname = "nickserv/set/message", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Change the communication method of Services")); - this->SetSyntax("{ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - if (!Config->GetBlock("options")->Get<bool>("useprivmsg")) - { - source.Reply(_("You cannot %s on this network."), source.command.c_str()); - return; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display; - nc->Extend<bool>("MSG"); - source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str()); - } - else if (param.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display; - nc->Shrink<bool>("MSG"); - source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, "MSG"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - Anope::string cmd = source.command; - size_t i = cmd.find_last_of(' '); - if (i != Anope::string::npos) - cmd = cmd.substr(i + 1); - - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to choose the way Services are communicating with\n" - "you. With \002%s\002 set, Services will use messages, else they'll\n" - "use notices."), cmd.upper().c_str()); - return true; - } - - void OnServHelp(CommandSource &source) anope_override - { - if (!Config->GetBlock("options")->Get<bool>("useprivmsg")) - Command::OnServHelp(source); - } -}; - -class CommandNSSASetMessage : public CommandNSSetMessage -{ - public: - CommandNSSASetMessage(Module *creator) : CommandNSSetMessage(creator, "nickserv/saset/message", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to choose the way Services are communicating with\n" - "the given user. With \002MSG\002 set, Services will use messages,\n" - "else they'll use notices.")); - return true; - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } -}; - -class CommandNSSetSecure : public Command -{ - public: - CommandNSSetSecure(Module *creator, const Anope::string &sname = "nickserv/set/secure", size_t min = 1) : Command(creator, sname, min, min + 1) - { - this->SetDesc(_("Turn nickname security on or off")); - this->SetSyntax("{ON | OFF}"); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (param.equals_ci("ON")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable secure for " << nc->display; - nc->Extend<bool>("NS_SECURE"); - source.Reply(_("Secure option is now \002on\002 for \002%s\002."), nc->display.c_str()); - } - else if (param.equals_ci("OFF")) - { - Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable secure for " << nc->display; - nc->Shrink<bool>("NS_SECURE"); - source.Reply(_("Secure option is now \002off\002 for \002%s\002."), nc->display.c_str()); - } - else - this->OnSyntaxError(source, "SECURE"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, params[0]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns %s's security features on or off for your\n" - "nick. With \002SECURE\002 set, you must enter your password\n" - "before you will be recognized as the owner of the nick,\n" - "regardless of whether your address is on the access\n" - "list. However, if you are on the access list, %s\n" - "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSASetSecure : public CommandNSSetSecure -{ - public: - CommandNSSASetSecure(Module *creator) : CommandNSSetSecure(creator, "nickserv/saset/secure", 2) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params[1]); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Turns %s's security features on or off for your\n" - "nick. With \002SECURE\002 set, you must enter your password\n" - "before you will be recognized as the owner of the nick,\n" - "regardless of whether your address is on the access\n" - "list. However, if you are on the access list, %s\n" - "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), source.service->nick.c_str(), source.service->nick.c_str()); - return true; - } -}; - -class CommandNSSASetNoexpire : public Command -{ - public: - CommandNSSASetNoexpire(Module *creator) : Command(creator, "nickserv/saset/noexpire", 1, 2) - { - this->SetDesc(_("Prevent the nickname from expiring")); - this->SetSyntax(_("\037nickname\037 {ON | OFF}")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - NickAlias *na = NickAlias::Find(params[0]); - if (na == NULL) - { - source.Reply(NICK_X_NOT_REGISTERED, params[0].c_str()); - return; - } - - Anope::string param = params.size() > 1 ? params[1] : ""; - - if (param.equals_ci("ON")) - { - Log(LOG_ADMIN, source, this) << "to enable noexpire for " << na->nick << " (" << na->nc->display << ")"; - na->Extend<bool>("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->nick << " (" << na->nc->display << ")"; - na->Shrink<bool>("NS_NO_EXPIRE"); - source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str()); - } - else - this->OnSyntaxError(source, "NOEXPIRE"); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets whether the given nickname will expire. Setting this\n" - "to \002ON\002 prevents the nickname from expiring.")); - return true; - } -}; - -class NSSet : public Module -{ - CommandNSSet commandnsset; - CommandNSSASet commandnssaset; - - CommandNSSetAutoOp commandnssetautoop; - CommandNSSASetAutoOp commandnssasetautoop; - - CommandNSSetDisplay commandnssetdisplay; - CommandNSSASetDisplay commandnssasetdisplay; - - CommandNSSetEmail commandnssetemail; - CommandNSSASetEmail commandnssasetemail; - - CommandNSSetKeepModes commandnssetkeepmodes; - CommandNSSASetKeepModes commandnssasetkeepmodes; - - CommandNSSetKill commandnssetkill; - CommandNSSASetKill commandnssasetkill; - - CommandNSSetLanguage commandnssetlanguage; - CommandNSSASetLanguage commandnssasetlanguage; - - CommandNSSetMessage commandnssetmessage; - CommandNSSASetMessage commandnssasetmessage; - - CommandNSSetPassword commandnssetpassword; - CommandNSSASetPassword commandnssasetpassword; - - CommandNSSetSecure commandnssetsecure; - CommandNSSASetSecure commandnssasetsecure; - - CommandNSSASetNoexpire commandnssasetnoexpire; - - SerializableExtensibleItem<bool> autoop, killprotect, kill_quick, kill_immed, - message, secure, noexpire; - - struct KeepModes : SerializableExtensibleItem<bool> - { - KeepModes(Module *m, const Anope::string &n) : SerializableExtensibleItem<bool>(m, n) { } - - void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override - { - SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data); - - if (s->GetSerializableType()->GetName() != "NickCore") - return; - - const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(s); - Anope::string modes; - for (User::ModeList::const_iterator it = nc->last_modes.begin(); it != nc->last_modes.end(); ++it) - { - if (!modes.empty()) - modes += " "; - modes += it->first; - if (!it->second.empty()) - modes += "," + it->second; - } - data["last_modes"] << modes; - } - - void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override - { - SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data); - - if (s->GetSerializableType()->GetName() != "NickCore") - return; - - NickCore *nc = anope_dynamic_static_cast<NickCore *>(s); - Anope::string modes; - data["last_modes"] >> modes; - for (spacesepstream sep(modes); sep.GetToken(modes);) - { - size_t c = modes.find(','); - if (c == Anope::string::npos) - nc->last_modes.insert(std::make_pair(modes, "")); - else - nc->last_modes.insert(std::make_pair(modes.substr(0, c), modes.substr(c + 1))); - } - } - } keep_modes; - - /* email, passcode */ - PrimitiveExtensibleItem<std::pair<Anope::string, Anope::string > > ns_set_email; - - public: - NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsset(this), commandnssaset(this), - commandnssetautoop(this), commandnssasetautoop(this), - commandnssetdisplay(this), commandnssasetdisplay(this), - commandnssetemail(this), commandnssasetemail(this), - commandnssetkeepmodes(this), commandnssasetkeepmodes(this), - commandnssetkill(this), commandnssasetkill(this), - commandnssetlanguage(this), commandnssasetlanguage(this), - commandnssetmessage(this), commandnssasetmessage(this), - commandnssetpassword(this), commandnssasetpassword(this), - commandnssetsecure(this), commandnssasetsecure(this), - commandnssasetnoexpire(this), - - autoop(this, "AUTOOP"), - killprotect(this, "KILLPROTECT"), kill_quick(this, "KILL_QUICK"), - kill_immed(this, "KILL_IMMED"), message(this, "MSG"), - secure(this, "NS_SECURE"), noexpire(this, "NS_NO_EXPIRE"), - - keep_modes(this, "NS_KEEP_MODES"), ns_set_email(this, "ns_set_email") - { - - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override - { - NickCore *uac = source.nc; - - if (command->name == "nickserv/confirm" && !params.empty() && uac) - { - std::pair<Anope::string, Anope::string> *n = ns_set_email.Get(uac); - if (n) - { - if (params[0] == n->second) - { - uac->email = n->first; - Log(LOG_COMMAND, source, command) << "to confirm their email address change to " << uac->email; - source.Reply(_("Your email address has been changed to \002%s\002."), uac->email.c_str()); - ns_set_email.Unset(uac); - return EVENT_STOP; - } - } - } - - return EVENT_CONTINUE; - } - - void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) anope_override - { - if (chan->ci) - { - /* Only give modes if autoop is set */ - give_modes &= !user->Account() || autoop.HasExt(user->Account()); - } - } - - void OnPreNickExpire(NickAlias *na, bool &expire) anope_override - { - if (noexpire.HasExt(na)) - expire = false; - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override - { - if (!show_hidden) - return; - - if (kill_immed.HasExt(na->nc)) - info.AddOption(_("Immediate protection")); - else if (kill_quick.HasExt(na->nc)) - info.AddOption(_("Quick protection")); - else if (killprotect.HasExt(na->nc)) - info.AddOption(_("Protection")); - if (secure.HasExt(na->nc)) - info.AddOption(_("Security")); - if (message.HasExt(na->nc)) - info.AddOption(_("Message mode")); - if (autoop.HasExt(na->nc)) - info.AddOption(_("Auto-op")); - if (noexpire.HasExt(na)) - info.AddOption(_("No expire")); - if (keep_modes.HasExt(na->nc)) - info.AddOption(_("Keep modes")); - } - - void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override - { - if (u->Account() && setter.GetUser() == u) - u->Account()->last_modes = u->GetModeList(); - } - - void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) anope_override - { - if (u->Account() && setter.GetUser() == u) - u->Account()->last_modes = u->GetModeList(); - } - - void OnUserLogin(User *u) anope_override - { - if (keep_modes.HasExt(u->Account())) - { - User::ModeList modes = u->Account()->last_modes; - for (User::ModeList::iterator it = modes.begin(); it != modes.end(); ++it) - { - UserMode *um = ModeManager::FindUserModeByName(it->first); - /* if the null user can set the mode, then it's probably safe */ - if (um && um->CanSet(NULL)) - u->SetMode(NULL, it->first, it->second); - } - } - } -}; - -MODULE_INIT(NSSet) diff --git a/modules/commands/ns_set_misc.cpp b/modules/commands/ns_set_misc.cpp deleted file mode 100644 index c145e386c..000000000 --- a/modules/commands/ns_set_misc.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/set_misc.h" - -static Module *me; - -static Anope::map<Anope::string> descriptions; - -struct NSMiscData; -static Anope::map<ExtensibleItem<NSMiscData> *> items; - -static ExtensibleItem<NSMiscData> *GetItem(const Anope::string &name) -{ - ExtensibleItem<NSMiscData>* &it = items[name]; - if (!it) - try - { - it = new ExtensibleItem<NSMiscData>(me, name); - } - catch (const ModuleException &) { } - return it; -} - -struct NSMiscData : MiscData, Serializable -{ - NSMiscData(Extensible *) : Serializable("NSMiscData") { } - - NSMiscData(NickCore *ncore, const Anope::string &n, const Anope::string &d) : Serializable("NSMiscData") - { - object = ncore->display; - name = n; - data = d; - } - - void Serialize(Serialize::Data &sdata) const anope_override - { - sdata["nc"] << this->object; - sdata["name"] << this->name; - sdata["data"] << this->data; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string snc, sname, sdata; - - data["nc"] >> snc; - data["name"] >> sname; - data["data"] >> sdata; - - NickCore *nc = NickCore::Find(snc); - if (nc == NULL) - return NULL; - - NSMiscData *d = NULL; - if (obj) - { - d = anope_dynamic_static_cast<NSMiscData *>(obj); - d->object = nc->display; - data["name"] >> d->name; - data["data"] >> d->data; - } - else - { - ExtensibleItem<NSMiscData> *item = GetItem(sname); - if (item) - d = item->Set(nc, NSMiscData(nc, sname, sdata)); - } - - return d; - } -}; - -static Anope::string GetAttribute(const Anope::string &command) -{ - size_t sp = command.rfind(' '); - if (sp != Anope::string::npos) - return command.substr(sp + 1); - return command; -} - -class CommandNSSetMisc : public Command -{ - public: - CommandNSSetMisc(Module *creator, const Anope::string &cname = "nickserv/set/misc", size_t min = 0) : Command(creator, cname, min, min + 1) - { - this->SetSyntax(_("[\037parameter\037]")); - } - - void Run(CommandSource &source, const Anope::string &user, const Anope::string ¶m) - { - if (Anope::ReadOnly) - { - source.Reply(READ_ONLY_MODE); - return; - } - - const NickAlias *na = NickAlias::Find(user); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, user.c_str()); - return; - } - NickCore *nc = na->nc; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param)); - if (MOD_RESULT == EVENT_STOP) - return; - - Anope::string scommand = GetAttribute(source.command); - Anope::string key = "ns_set_misc:" + scommand; - ExtensibleItem<NSMiscData> *item = GetItem(key); - if (item == NULL) - return; - - if (!param.empty()) - { - item->Set(nc, NSMiscData(nc, key, param)); - source.Reply(CHAN_SETTING_CHANGED, scommand.c_str(), nc->display.c_str(), param.c_str()); - } - else - { - item->Unset(nc); - source.Reply(CHAN_SETTING_UNSET, scommand.c_str(), nc->display.c_str()); - } - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, source.nc->display, !params.empty() ? params[0] : ""); - } - - void OnServHelp(CommandSource &source) anope_override - { - if (descriptions.count(source.command)) - { - this->SetDesc(descriptions[source.command]); - Command::OnServHelp(source); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (descriptions.count(source.command)) - { - source.Reply("%s", Language::Translate(source.nc, descriptions[source.command].c_str())); - return true; - } - return false; - } -}; - -class CommandNSSASetMisc : public CommandNSSetMisc -{ - public: - CommandNSSASetMisc(Module *creator) : CommandNSSetMisc(creator, "nickserv/saset/misc", 1) - { - this->ClearSyntax(); - this->SetSyntax(_("\037nickname\037 [\037parameter\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - this->Run(source, params[0], params.size() > 1 ? params[1] : ""); - } -}; - -class NSSetMisc : public Module -{ - CommandNSSetMisc commandnssetmisc; - CommandNSSASetMisc commandnssasetmisc; - Serialize::Type nsmiscdata_type; - - public: - NSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnssetmisc(this), commandnssasetmisc(this), nsmiscdata_type("NSMiscData", NSMiscData::Unserialize) - { - me = this; - } - - ~NSSetMisc() - { - for (Anope::map<ExtensibleItem<NSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it) - delete it->second; - } - - void OnReload(Configuration::Conf *conf) anope_override - { - descriptions.clear(); - - for (int i = 0; i < conf->CountBlock("command"); ++i) - { - Configuration::Block *block = conf->GetBlock("command", i); - - const Anope::string &cmd = block->Get<const Anope::string>("command"); - - if (cmd != "nickserv/set/misc" && cmd != "nickserv/saset/misc") - continue; - - Anope::string cname = block->Get<const Anope::string>("name"); - Anope::string desc = block->Get<const Anope::string>("misc_description"); - - if (cname.empty() || desc.empty()) - continue; - - descriptions[cname] = desc; - } - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool) anope_override - { - for (Anope::map<ExtensibleItem<NSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it) - { - ExtensibleItem<NSMiscData> *e = it->second; - NSMiscData *data = e->Get(na->nc); - - if (data != NULL) - info[e->name.substr(12).replace_all_cs("_", " ")] = data->data; - } - } -}; - -MODULE_INIT(NSSetMisc) diff --git a/modules/commands/ns_status.cpp b/modules/commands/ns_status.cpp deleted file mode 100644 index b06e51ec4..000000000 --- a/modules/commands/ns_status.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSStatus : public Command -{ - public: - CommandNSStatus(Module *creator) : Command(creator, "nickserv/status", 0, 16) - { - this->SetDesc(_("Returns the owner status of the given nickname")); - this->SetSyntax(_("[\037nickname\037]")); - this->AllowUnregistered(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = !params.empty() ? params[0] : source.GetNick(); - const NickAlias *na = NickAlias::Find(nick); - spacesepstream sep(nick); - Anope::string nickbuf; - - while (sep.GetToken(nickbuf)) - { - User *u2 = User::Find(nickbuf, true); - if (!u2) /* Nick is not online */ - source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, ""); - else if (u2->IsIdentified() && na && na->nc == u2->Account()) /* Nick is identified */ - source.Reply("STATUS %s %d %s", nickbuf.c_str(), 3, u2->Account()->display.c_str()); - else if (u2->IsRecognized()) /* Nick is recognised, but NOT identified */ - source.Reply("STATUS %s %d %s", nickbuf.c_str(), 2, u2->Account() ? u2->Account()->display.c_str() : ""); - else if (!na) /* Nick is online, but NOT a registered */ - source.Reply("STATUS %s %d %s", nickbuf.c_str(), 0, ""); - else - /* Nick is not identified for the nick, but they could be logged into an account, - * so we tell the user about it - */ - source.Reply("STATUS %s %d %s", nickbuf.c_str(), 1, u2->Account() ? u2->Account()->display.c_str() : ""); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Returns whether the user using the given nickname is\n" - "recognized as the owner of the nickname. The response has\n" - "this format:\n" - " \n" - " \037nickname\037 \037status-code\037 \037account\037\n" - " \n" - "where \037nickname\037 is the nickname sent with the command,\n" - "\037status-code\037 is one of the following, and \037account\037\n" - "is the account they are logged in as.\n" - " \n" - " 0 - no such user online \002or\002 nickname not registered\n" - " 1 - user not recognized as nickname's owner\n" - " 2 - user recognized as owner via access list only\n" - " 3 - user recognized as owner via password identification\n" - " \n" - "If no nickname is given, your status will be returned.")); - return true; - } -}; - -class NSStatus : public Module -{ - CommandNSStatus commandnsstatus; - - public: - NSStatus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsstatus(this) - { - - } -}; - -MODULE_INIT(NSStatus) diff --git a/modules/commands/ns_suspend.cpp b/modules/commands/ns_suspend.cpp deleted file mode 100644 index 76b79d1d1..000000000 --- a/modules/commands/ns_suspend.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/suspend.h" - -static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); - -struct NSSuspendInfo : SuspendInfo, Serializable -{ - NSSuspendInfo(Extensible *) : Serializable("NSSuspendInfo") { } - - void Serialize(Serialize::Data &data) const anope_override - { - data["nick"] << what; - data["by"] << by; - data["reason"] << reason; - data["time"] << when; - data["expires"] << expires; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string snick; - data["nick"] >> snick; - - NSSuspendInfo *si; - if (obj) - si = anope_dynamic_static_cast<NSSuspendInfo *>(obj); - else - { - NickAlias *na = NickAlias::Find(snick); - if (!na) - return NULL; - si = na->nc->Extend<NSSuspendInfo>("NS_SUSPENDED"); - data["nick"] >> si->what; - } - - data["by"] >> si->by; - data["reason"] >> si->reason; - data["time"] >> si->when; - data["expires"] >> si->expires; - return si; - } -}; - -class CommandNSSuspend : public Command -{ - public: - CommandNSSuspend(Module *creator) : Command(creator, "nickserv/suspend", 2, 3) - { - this->SetDesc(_("Suspend a given nick")); - this->SetSyntax(_("\037nickname\037 [+\037expiry\037] [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - - const Anope::string &nick = params[0]; - Anope::string expiry = params[1]; - Anope::string reason = params.size() > 2 ? params[2] : ""; - time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("suspendexpire"); - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - if (expiry[0] != '+') - { - reason = expiry + " " + reason; - reason.trim(); - expiry.clear(); - } - else - { - expiry_secs = Anope::DoTime(expiry); - if (expiry_secs == -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - } - - NickAlias *na = NickAlias::Find(nick); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - - if (Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && na->nc->IsServicesOper()) - { - source.Reply(_("You may not suspend other Services Operators' nicknames.")); - return; - } - - if (na->nc->HasExt("NS_SUSPENDED")) - { - source.Reply(_("\002%s\002 is already suspended."), na->nc->display.c_str()); - return; - } - - NickCore *nc = na->nc; - - NSSuspendInfo *si = nc->Extend<NSSuspendInfo>("NS_SUSPENDED"); - si->what = nc->display; - si->by = source.GetNick(); - si->reason = reason; - si->when = Anope::CurTime; - si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0; - - for (unsigned i = 0; i < nc->aliases->size(); ++i) - { - NickAlias *na2 = nc->aliases->at(i); - - if (na2 && *na2->nc == *na->nc) - { - na2->last_quit = reason; - - User *u2 = User::Find(na2->nick, true); - if (u2) - { - u2->Logout(); - if (nickserv) - nickserv->Collide(u2, na2); - } - } - } - - Log(LOG_ADMIN, source, this) << "for " << nick << " (" << (!reason.empty() ? reason : "No reason") << "), expires on " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never"); - source.Reply(_("Nick %s is now suspended."), nick.c_str()); - - FOREACH_MOD(OnNickSuspend, (na)); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Suspends a registered nickname, which prevents it from being used\n" - "while keeping all the data for that nick. If an expiry is given\n" - "the nick will be unsuspended after that period of time, else the\n" - "default expiry from the configuration is used.")); - return true; - } -}; - -class CommandNSUnSuspend : public Command -{ - public: - CommandNSUnSuspend(Module *creator) : Command(creator, "nickserv/unsuspend", 1, 1) - { - this->SetDesc(_("Unsuspend a given nick")); - this->SetSyntax(_("\037nickname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - NickAlias *na = NickAlias::Find(nick); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, nick.c_str()); - return; - } - - if (!na->nc->HasExt("NS_SUSPENDED")) - { - source.Reply(_("Nick %s is not suspended."), na->nick.c_str()); - return; - } - - NSSuspendInfo *si = na->nc->GetExt<NSSuspendInfo>("NS_SUSPENDED"); - - Log(LOG_ADMIN, source, this) << "for " << na->nick << " which was suspended by " << (!si->by.empty() ? si->by : "(none)") << " for: " << (!si->reason.empty() ? si->reason : "No reason"); - - na->nc->Shrink<NSSuspendInfo>("NS_SUSPENDED"); - - source.Reply(_("Nick %s is now released."), nick.c_str()); - - FOREACH_MOD(OnNickUnsuspended, (na)); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Unsuspends a nickname which allows it to be used again.")); - return true; - } -}; - -class NSSuspend : public Module -{ - CommandNSSuspend commandnssuspend; - CommandNSUnSuspend commandnsunsuspend; - ExtensibleItem<NSSuspendInfo> suspend; - Serialize::Type suspend_type; - std::vector<Anope::string> show; - - struct trim - { - Anope::string operator()(Anope::string s) const - { - return s.trim(); - } - }; - - bool Show(CommandSource &source, const Anope::string &what) const - { - return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end(); - } - - public: - NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnssuspend(this), commandnsunsuspend(this), suspend(this, "NS_SUSPENDED"), - suspend_type("NSSuspendInfo", NSSuspendInfo::Unserialize) - { - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Anope::string s = conf->GetModule(this)->Get<Anope::string>("show"); - commasepstream(s).GetTokens(show); - std::transform(show.begin(), show.end(), show.begin(), trim()); - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override - { - NSSuspendInfo *s = suspend.Get(na->nc); - if (!s) - return; - - if (show_hidden || Show(source, "suspended")) - info[_("Suspended")] = _("This nickname is \002suspended\002."); - if (!s->by.empty() && (show_hidden || Show(source, "by"))) - info[_("Suspended by")] = s->by; - if (!s->reason.empty() && (show_hidden || Show(source, "reason"))) - info[_("Suspend reason")] = s->reason; - if (s->when && (show_hidden || Show(source, "on"))) - info[_("Suspended on")] = Anope::strftime(s->when, source.GetAccount()); - if (s->expires && (show_hidden || Show(source, "expires"))) - info[_("Suspension expires")] = Anope::strftime(s->expires, source.GetAccount()); - } - - void OnPreNickExpire(NickAlias *na, bool &expire) anope_override - { - NSSuspendInfo *s = suspend.Get(na->nc); - if (!s) - return; - - expire = false; - - if (!s->expires) - return; - - if (s->expires < Anope::CurTime) - { - na->last_seen = Anope::CurTime; - suspend.Unset(na->nc); - - Log(LOG_NORMAL, "nickserv/expire", Config->GetClient("NickServ")) << "Expiring suspend for " << na->nick; - } - } - - EventReturn OnNickValidate(User *u, NickAlias *na) anope_override - { - NSSuspendInfo *s = suspend.Get(na->nc); - if (!s) - return EVENT_CONTINUE; - - u->SendMessage(Config->GetClient("NickServ"), NICK_X_SUSPENDED, u->nick.c_str()); - return EVENT_STOP; - } -}; - -MODULE_INIT(NSSuspend) diff --git a/modules/commands/ns_update.cpp b/modules/commands/ns_update.cpp deleted file mode 100644 index fcbe02f21..000000000 --- a/modules/commands/ns_update.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* NickServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandNSUpdate : public Command -{ - public: - CommandNSUpdate(Module *creator) : Command(creator, "nickserv/update", 0, 0) - { - this->SetDesc(_("Updates your current status, i.e. it checks for new memos")); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - NickAlias *na = NickAlias::Find(u->nick); - - if (na && na->nc == source.GetAccount()) - { - na->last_realname = u->realname; - na->last_seen = Anope::CurTime; - } - - FOREACH_MOD(OnNickUpdate, (u)); - - source.Reply(_("Status updated (memos, vhost, chmodes, flags).")); - } - - bool OnHelp(CommandSource &source, const Anope::string &) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Updates your current status, i.e. it checks for new memos,\n" - "sets needed channel modes and updates your vhost and\n" - "your userflags (lastseentime, etc).")); - return true; - } -}; - -class NSUpdate : public Module -{ - CommandNSUpdate commandnsupdate; - - public: - NSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandnsupdate(this) - { - - } -}; - -MODULE_INIT(NSUpdate) diff --git a/modules/commands/os_akill.cpp b/modules/commands/os_akill.cpp deleted file mode 100644 index 08bbc79ac..000000000 --- a/modules/commands/os_akill.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline"); - -class AkillDelCallback : public NumberList -{ - CommandSource &source; - unsigned deleted; - Command *cmd; - public: - AkillDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), deleted(0), cmd(c) - { - } - - ~AkillDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on the AKILL list.")); - else if (deleted == 1) - source.Reply(_("Deleted 1 entry from the AKILL list.")); - else - source.Reply(_("Deleted %d entries from the AKILL list."), deleted); - } - - void HandleNumber(unsigned number) anope_override - { - if (!number) - return; - - XLine *x = akills->GetEntry(number - 1); - - if (!x) - return; - - Log(LOG_ADMIN, source, cmd) << "to remove " << x->mask << " from the list"; - - ++deleted; - DoDel(source, x); - } - - static void DoDel(CommandSource &source, XLine *x) - { - akills->DelXLine(x); - } -}; - -class CommandOSAKill : public Command -{ - private: - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - Anope::string expiry, mask; - - if (params.size() < 2) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - spacesepstream sep(params[1]); - sep.GetToken(mask); - - if (mask[0] == '+') - { - expiry = mask; - sep.GetToken(mask); - } - - time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("autokillexpiry", "30d"); - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (sep.StreamEnd()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - Anope::string reason; - if (mask.find('#') != Anope::string::npos) - { - Anope::string remaining = sep.GetRemaining(); - - size_t co = remaining[0] == ':' ? 0 : remaining.rfind(" :"); - if (co == Anope::string::npos) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - if (co != 0) - ++co; - - reason = remaining.substr(co + 1); - mask += " " + remaining.substr(0, co); - mask.trim(); - } - else - reason = sep.GetRemaining(); - - if (mask[0] == '/' && mask[mask.length() - 1] == '/') - { - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - - if (regexengine.empty()) - { - source.Reply(_("Regex is disabled.")); - return; - } - - ServiceReference<RegexProvider> provider("Regex", regexengine); - if (!provider) - { - source.Reply(_("Unable to find regex engine %s."), regexengine.c_str()); - return; - } - - try - { - Anope::string stripped_mask = mask.substr(1, mask.length() - 2); - delete provider->Compile(stripped_mask); - } - catch (const RegexException &ex) - { - source.Reply("%s", ex.GetReason().c_str()); - return; - } - } - - User *targ = User::Find(mask, true); - if (targ) - mask = "*@" + targ->host; - - if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty()) - reason = "[" + source.GetNick() + "] " + reason; - - if (mask.find_first_not_of("/~@.*?") == Anope::string::npos) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - return; - } - else if (mask.find('@') == Anope::string::npos) - { - source.Reply(BAD_USERHOST_MASK); - return; - } - - XLine *x = new XLine(mask, source.GetNick(), expires, reason); - if (Config->GetModule("operserv")->Get<bool>("akillids")) - x->id = XLineManager::GenerateUID(); - - unsigned int affected = 0; - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (akills->Check(it->second, x)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - Log(LOG_ADMIN, source, this) << "tried to akill " << percent << "% of the network (" << affected << " users)"; - delete x; - return; - } - - if (!akills->CanAdd(source, mask, expires, reason)) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, akills)); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return; - } - - akills->AddXLine(x); - if (Config->GetModule("operserv")->Get<bool>("akillonadd")) - akills->Send(NULL, x); - - source.Reply(_("\002%s\002 added to the AKILL list."), mask.c_str()); - - Log(LOG_ADMIN, source, this) << "on " << mask << " (" << x->reason << "), expires in " << (expires ? Anope::Duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (akills->GetList().empty()) - { - source.Reply(_("AKILL list is empty.")); - return; - } - - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - AkillDelCallback list(source, mask, this); - list.Process(); - } - else - { - XLine *x = akills->HasEntry(mask); - - if (!x) - { - source.Reply(_("\002%s\002 not found on the AKILL list."), mask.c_str()); - return; - } - - do - { - FOREACH_MOD(OnDelXLine, (source, x, akills)); - - Log(LOG_ADMIN, source, this) << "to remove " << x->mask << " from the list"; - source.Reply(_("\002%s\002 deleted from the AKILL list."), x->mask.c_str()); - AkillDelCallback::DoDel(source, x); - } - while ((x = akills->HasEntry(mask))); - - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - return; - } - - void ProcessList(CommandSource &source, const std::vector<Anope::string> ¶ms, ListFormatter &list) - { - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class ListCallback : public NumberList - { - CommandSource &source; - ListFormatter &list; - public: - ListCallback(CommandSource &_source, ListFormatter &_list, const Anope::string &numstr) : NumberList(numstr, false), source(_source), list(_list) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number) - return; - - const XLine *x = akills->GetEntry(number - 1); - - if (!x) - return; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); - entry["Mask"] = x->mask; - entry["Creator"] = x->by; - entry["Created"] = Anope::strftime(x->created, NULL, true); - entry["Expires"] = Anope::Expires(x->expires, source.nc); - entry["ID"] = x->id; - entry["Reason"] = x->reason; - this->list.AddEntry(entry); - } - } - nl_list(source, list, mask); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = akills->GetCount(); i < end; ++i) - { - const XLine *x = akills->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true)) - { - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Mask"] = x->mask; - entry["Creator"] = x->by; - entry["Created"] = Anope::strftime(x->created, NULL, true); - entry["Expires"] = Anope::Expires(x->expires, source.nc); - entry["ID"] = x->id; - entry["Reason"] = x->reason; - list.AddEntry(entry); - } - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on the AKILL list.")); - else - { - source.Reply(_("Current AKILL list:")); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of AKILL list.")); - } - } - - void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (akills->GetList().empty()) - { - source.Reply(_("AKILL list is empty.")); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason")); - - this->ProcessList(source, params, list); - } - - void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (akills->GetList().empty()) - { - source.Reply(_("AKILL list is empty.")); - return; - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Expires")); - if (Config->GetModule("operserv")->Get<bool>("akillids")) - list.AddColumn(_("ID")); - list.AddColumn(_("Reason")); - - this->ProcessList(source, params, list); - } - - void DoClear(CommandSource &source) - { - - for (unsigned i = akills->GetCount(); i > 0; --i) - { - XLine *x = akills->GetEntry(i - 1); - FOREACH_MOD(OnDelXLine, (source, x, akills)); - akills->DelXLine(x); - } - - Log(LOG_ADMIN, source, this) << "to CLEAR the list"; - source.Reply(_("The AKILL list has been cleared.")); - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - public: - CommandOSAKill(Module *creator) : Command(creator, "operserv/akill", 1, 2) - { - this->SetDesc(_("Manipulate the AKILL list")); - this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037 \037reason\037")); - this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037 | \037id\037}")); - this->SetSyntax(_("LIST [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax(_("VIEW [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax("CLEAR"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - if (!akills) - return; - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->DoView(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to manipulate the AKILL list. If\n" - "a user matching an AKILL mask attempts to connect, Services\n" - "will issue a KILL for that user and, on supported server\n" - "types, will instruct all servers to add a ban for the mask\n" - "which the user matched.\n" - " \n" - "\002AKILL ADD\002 adds the given mask to the AKILL\n" - "list for the given reason, which \002must\002 be given.\n" - "Mask should be in the format of nick!user@host#real name,\n" - "though all that is required is user@host. If a real name is specified,\n" - "the reason must be prepended with a :.\n" - "\037expiry\037 is specified as an integer followed by one of \037d\037\n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as\n" - "\0371h30m\037) are not permitted. If a unit specifier is not\n" - "included, the default is days (so \037+30\037 by itself means 30\n" - "days). To add an AKILL which does not expire, use \037+0\037. If the\n" - "usermask to be added starts with a \037+\037, an expiry time must\n" - "be given, even if it is the same as the default. The\n" - "current AKILL default expiry time can be found with the\n" - "\002STATS AKILL\002 command.")); - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your mask in // if this is desired."), regexengine.c_str()); - } - source.Reply(_( - " \n" - "The \002AKILL DEL\002 command removes the given mask from the\n" - "AKILL list if it is present. If a list of entry numbers is\n" - "given, those entries are deleted. (See the example for LIST\n" - "below.)\n" - " \n" - "The \002AKILL LIST\002 command displays the AKILL list.\n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002AKILL LIST 2-5,7-9\002\n" - " Lists AKILL entries numbered 2 through 5 and 7\n" - " through 9.\n" - " \n" - "\002AKILL VIEW\002 is a more verbose version of \002AKILL LIST\002, and\n" - "will show who added an AKILL, the date it was added, and when\n" - "it expires, as well as the user@host/ip mask and reason.\n" - " \n" - "\002AKILL CLEAR\002 clears all entries of the AKILL list.")); - return true; - } -}; - -class OSAKill : public Module -{ - CommandOSAKill commandosakill; - - public: - OSAKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosakill(this) - { - - } -}; - -MODULE_INIT(OSAKill) diff --git a/modules/commands/os_chankill.cpp b/modules/commands/os_chankill.cpp deleted file mode 100644 index 56b5f6b33..000000000 --- a/modules/commands/os_chankill.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -static ServiceReference<XLineManager> akills("XLineManager", "xlinemanager/sgline"); - -class CommandOSChanKill : public Command -{ - public: - CommandOSChanKill(Module *creator) : Command(creator, "operserv/chankill", 2, 3) - { - this->SetDesc(_("AKILL all users on a specific channel")); - this->SetSyntax(_("[+\037expiry\037] \037channel\037 \037reason\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!akills) - return; - - Anope::string expiry, channel; - unsigned last_param = 1; - Channel *c; - - channel = params[0]; - if (!channel.empty() && channel[0] == '+') - { - expiry = channel; - channel = params[1]; - last_param = 2; - } - - time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("autokillexpiry", "30d"); - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - if (expires && expires < 60) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (params.size() <= last_param) - { - this->OnSyntaxError(source, ""); - return; - } - - Anope::string reason = params[last_param]; - if (params.size() > last_param + 1) - reason += params[last_param + 1]; - if (!reason.empty()) - { - Anope::string realreason; - if (Config->GetModule("operserv")->Get<bool>("addakiller") && !source.GetNick().empty()) - realreason = "[" + source.GetNick() + "] " + reason; - else - realreason = reason; - - if ((c = Channel::Find(channel))) - { - for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - - if (uc->user->server == Me || uc->user->HasMode("OPER")) - continue; - - Anope::string akillmask = "*@" + uc->user->host; - if (akills->HasEntry(akillmask)) - continue; - - XLine *x = new XLine(akillmask, source.GetNick(), expires, realreason, XLineManager::GenerateUID()); - akills->AddXLine(x); - akills->OnMatch(uc->user, x); - } - - Log(LOG_ADMIN, source, this) << "on " << c->name << " (" << realreason << ")"; - } - else - source.Reply(CHAN_X_NOT_IN_USE, channel.c_str()); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Puts an AKILL for every nick on the specified channel. It\n" - "uses the entire real ident@host for every nick, and\n" - "then enforces the AKILL.")); - return true; - } -}; - -class OSChanKill : public Module -{ - CommandOSChanKill commandoschankill; - - public: - OSChanKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoschankill(this) - { - - } -}; - -MODULE_INIT(OSChanKill) diff --git a/modules/commands/os_config.cpp b/modules/commands/os_config.cpp deleted file mode 100644 index a2e4f3272..000000000 --- a/modules/commands/os_config.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSConfig : public Command -{ - public: - CommandOSConfig(Module *creator) : Command(creator, "operserv/config", 1, 4) - { - this->SetDesc(_("View and change configuration file settings")); - this->SetSyntax(_("{\037MODIFY\037|\037VIEW\037} [\037block name\037 \037item name\037 \037item value\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &what = params[0]; - - if (what.equals_ci("MODIFY") && params.size() > 3) - { - if (!source.HasPriv("operserv/config")) - { - source.Reply(ACCESS_DENIED); - return; - } - - Configuration::Block *block = Config->GetBlock(params[1]); - if (!block) - block = Config->GetModule(params[1]); - - if (!block) - { - source.Reply(_("There is no such configuration block %s."), params[1].c_str()); - return; - } - - block->Set(params[2], params[3]); - - Log(LOG_ADMIN, source, this) << "to change the configuration value of " << params[1] << ":" << params[2] << " to " << params[3]; - source.Reply(_("Value of %s:%s changed to %s"), params[1].c_str(), params[2].c_str(), params[3].c_str()); - } - else if (what.equals_ci("VIEW")) - { - /* Blocks we should show */ - const Anope::string show_blocks[] = { "serverinfo", "networkinfo", "options", "" }; - - Log(LOG_ADMIN, source, this) << "VIEW"; - - for (unsigned i = 0; !show_blocks[i].empty(); ++i) - { - Configuration::Block *block = Config->GetBlock(show_blocks[i]); - const Configuration::Block::item_map *items = block->GetItems(); - - if (!items) - continue; - - ListFormatter lflist(source.GetAccount()); - lflist.AddColumn(_("Name")).AddColumn(_("Value")); - - for (Configuration::Block::item_map::const_iterator it = items->begin(), it_end = items->end(); it != it_end; ++it) - { - ListFormatter::ListEntry entry; - entry["Name"] = it->first; - entry["Value"] = it->second; - lflist.AddEntry(entry); - } - - std::vector<Anope::string> replies; - lflist.Process(replies); - - source.Reply(_("%s settings:"), block->GetName().c_str()); - - for (unsigned j = 0; j < replies.size(); ++j) - source.Reply(replies[j]); - - source.Reply(" "); - } - - ListFormatter lflist(source.GetAccount()); - lflist.AddColumn(_("Module Name")).AddColumn(_("Name")).AddColumn(_("Value")); - - for (int i = 0; i < Config->CountBlock("module"); ++i) - { - Configuration::Block *block = Config->GetBlock("module", i); - const Configuration::Block::item_map *items = block->GetItems(); - - if (!items || items->size() <= 1) - continue; - - ListFormatter::ListEntry entry; - entry["Module Name"] = block->Get<Anope::string>("name"); - - for (Configuration::Block::item_map::const_iterator it = items->begin(), it_end = items->end(); it != it_end; ++it) - { - entry["Name"] = it->first; - entry["Value"] = it->second; - lflist.AddEntry(entry); - } - } - - std::vector<Anope::string> replies; - lflist.Process(replies); - - source.Reply(_("Module settings:")); - - for (unsigned j = 0; j < replies.size(); ++j) - source.Reply(replies[j]); - - source.Reply(_("End of configuration.")); - } - else - this->OnSyntaxError(source, what); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to change and view configuration settings.\n" - "Settings changed by this command are temporary and will not be reflected\n" - "back into the configuration file, and will be lost if Anope is shut down,\n" - "restarted, or the configuration is reloaded.\n" - " \n" - "Example:\n" - " \002MODIFY nickserv forcemail no\002")); - return true; - } -}; - -class OSConfig : public Module -{ - CommandOSConfig commandosconfig; - - public: - OSConfig(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosconfig(this) - { - - } -}; - -MODULE_INIT(OSConfig) diff --git a/modules/commands/os_defcon.cpp b/modules/commands/os_defcon.cpp deleted file mode 100644 index fbccf2aae..000000000 --- a/modules/commands/os_defcon.cpp +++ /dev/null @@ -1,603 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_session.h" - -enum DefconLevel -{ - DEFCON_NO_NEW_CHANNELS, - DEFCON_NO_NEW_NICKS, - DEFCON_NO_MLOCK_CHANGE, - DEFCON_FORCE_CHAN_MODES, - DEFCON_REDUCE_SESSION, - DEFCON_NO_NEW_CLIENTS, - DEFCON_OPER_ONLY, - DEFCON_SILENT_OPER_ONLY, - DEFCON_AKILL_NEW_CLIENTS, - DEFCON_NO_NEW_MEMOS -}; - -bool DefConModesSet = false; - -struct DefconConfig -{ - std::vector<std::bitset<32> > DefCon; - std::set<Anope::string> DefConModesOn, DefConModesOff; - std::map<Anope::string, Anope::string> DefConModesOnParams; - - int defaultlevel, sessionlimit; - Anope::string chanmodes, message, offmessage, akillreason; - std::vector<Anope::string> defcons; - time_t akillexpire, timeout; - bool globalondefcon; - - unsigned max_session_kill; - time_t session_autokill_expiry; - Anope::string sle_reason, sle_detailsloc; - - DefconConfig() - { - this->DefCon.resize(6); - this->defcons.resize(5); - } - - bool Check(DefconLevel level) - { - return this->Check(this->defaultlevel, level); - } - - bool Check(int dlevel, DefconLevel level) - { - return this->DefCon[dlevel].test(level); - } - - void Add(int dlevel, DefconLevel level) - { - this->DefCon[dlevel][level] = true; - } - - void Del(int dlevel, DefconLevel level) - { - this->DefCon[dlevel][level] = false; - } - - bool SetDefConParam(const Anope::string &name, const Anope::string &buf) - { - return DefConModesOnParams.insert(std::make_pair(name, buf)).second; - } - - void UnsetDefConParam(const Anope::string &name) - { - DefConModesOnParams.erase(name); - } - - bool GetDefConParam(const Anope::string &name, Anope::string &buf) - { - std::map<Anope::string, Anope::string>::iterator it = DefConModesOnParams.find(name); - - buf.clear(); - - if (it != DefConModesOnParams.end()) - { - buf = it->second; - return true; - } - - return false; - } -}; - -static DefconConfig DConfig; - -static void runDefCon(); -static Anope::string defconReverseModes(const Anope::string &modes); - -static ServiceReference<GlobalService> GlobalService("GlobalService", "Global"); - -static Timer *timeout; - -class DefConTimeout : public Timer -{ - int level; - - public: - DefConTimeout(Module *mod, int newlevel) : Timer(mod, DConfig.timeout), level(newlevel) - { - timeout = this; - } - - ~DefConTimeout() - { - timeout = NULL; - } - - void Tick(time_t) anope_override - { - if (DConfig.defaultlevel != level) - { - DConfig.defaultlevel = level; - FOREACH_MOD(OnDefconLevel, (level)); - Log(Config->GetClient("OperServ"), "operserv/defcon") << "Defcon level timeout, returning to level " << level; - - if (DConfig.globalondefcon) - { - if (!DConfig.offmessage.empty()) - GlobalService->SendGlobal(NULL, "", DConfig.offmessage); - else - GlobalService->SendGlobal(NULL, "", Anope::printf(Language::Translate(_("The Defcon level is now at: \002%d\002")), DConfig.defaultlevel)); - - if (!DConfig.message.empty()) - GlobalService->SendGlobal(NULL, "", DConfig.message); - } - - runDefCon(); - } - } -}; - -class CommandOSDefcon : public Command -{ - void SendLevels(CommandSource &source) - { - if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) - source.Reply(_("* No new channel registrations")); - if (DConfig.Check(DEFCON_NO_NEW_NICKS)) - source.Reply(_("* No new nick registrations")); - if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) - source.Reply(_("* No mode lock changes")); - if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && !DConfig.chanmodes.empty()) - source.Reply(_("* Force channel modes (%s) to be set on all channels"), DConfig.chanmodes.c_str()); - if (DConfig.Check(DEFCON_REDUCE_SESSION)) - source.Reply(_("* Use the reduced session limit of %d"), DConfig.sessionlimit); - if (DConfig.Check(DEFCON_NO_NEW_CLIENTS)) - source.Reply(_("* Kill any new clients connecting")); - if (DConfig.Check(DEFCON_OPER_ONLY)) - source.Reply(_("* Ignore non-opers with a message")); - if (DConfig.Check(DEFCON_SILENT_OPER_ONLY)) - source.Reply(_("* Silently ignore non-opers")); - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) - source.Reply(_("* AKILL any new clients connecting")); - if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) - source.Reply(_("* No new memos sent")); - } - - public: - CommandOSDefcon(Module *creator) : Command(creator, "operserv/defcon", 1, 1) - { - this->SetDesc(_("Manipulate the DefCon system")); - this->SetSyntax(_("[\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &lvl = params[0]; - - if (lvl.empty()) - { - source.Reply(_("Services are now at DEFCON \002%d\002."), DConfig.defaultlevel); - this->SendLevels(source); - return; - } - - int newLevel = 0; - try - { - newLevel = convertTo<int>(lvl); - } - catch (const ConvertException &) { } - - if (newLevel < 1 || newLevel > 5) - { - this->OnSyntaxError(source, ""); - return; - } - - DConfig.defaultlevel = newLevel; - - FOREACH_MOD(OnDefconLevel, (newLevel)); - - delete timeout; - - if (DConfig.timeout) - timeout = new DefConTimeout(this->module, 5); - - source.Reply(_("Services are now at DEFCON \002%d\002."), DConfig.defaultlevel); - this->SendLevels(source); - Log(LOG_ADMIN, source, this) << "to change defcon level to " << newLevel; - - /* Global notice the user what is happening. Also any Message that - the Admin would like to add. Set in config file. */ - if (DConfig.globalondefcon) - { - if (DConfig.defaultlevel == 5 && !DConfig.offmessage.empty()) - GlobalService->SendGlobal(NULL, "", DConfig.offmessage); - else if (DConfig.defaultlevel != 5) - { - GlobalService->SendGlobal(NULL, "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); - if (!DConfig.message.empty()) - GlobalService->SendGlobal(NULL, "", DConfig.message); - } - } - - /* Run any defcon functions, e.g. FORCE CHAN MODE */ - runDefCon(); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("The defcon system can be used to implement a pre-defined\n" - "set of restrictions to services useful during an attempted\n" - "attack on the network.")); - return true; - } -}; - -class OSDefcon : public Module -{ - ServiceReference<SessionService> session_service; - ServiceReference<XLineManager> akills; - CommandOSDefcon commandosdefcon; - - void ParseModeString() - { - int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ - unsigned char mode; - ChannelMode *cm; - ChannelModeParam *cmp; - Anope::string modes, param; - - spacesepstream ss(DConfig.chanmodes); - - DConfig.DefConModesOn.clear(); - DConfig.DefConModesOff.clear(); - ss.GetToken(modes); - - /* Loop while there are modes to set */ - for (unsigned i = 0, end = modes.length(); i < end; ++i) - { - mode = modes[i]; - - switch (mode) - { - case '+': - add = 1; - continue; - case '-': - add = 0; - continue; - default: - if (add < 0) - continue; - } - - if ((cm = ModeManager::FindChannelModeByChar(mode))) - { - if (cm->type == MODE_STATUS || cm->type == MODE_LIST) - { - Log(this) << "DefConChanModes mode character '" << mode << "' cannot be locked"; - continue; - } - else if (add) - { - DConfig.DefConModesOn.insert(cm->name); - DConfig.DefConModesOff.erase(cm->name); - - if (cm->type == MODE_PARAM) - { - cmp = anope_dynamic_static_cast<ChannelModeParam *>(cm); - - if (!ss.GetToken(param)) - { - Log(this) << "DefConChanModes mode character '" << mode << "' has no parameter while one is expected"; - continue; - } - - if (!cmp->IsValid(param)) - continue; - - DConfig.SetDefConParam(cmp->name, param); - } - } - else if (DConfig.DefConModesOn.count(cm->name)) - { - DConfig.DefConModesOn.erase(cm->name); - - if (cm->type == MODE_PARAM) - DConfig.UnsetDefConParam(cm->name); - } - } - } - - /* We can't mlock +L if +l is not mlocked as well. */ - if ((cm = ModeManager::FindChannelModeByName("REDIRECT")) && DConfig.DefConModesOn.count(cm->name) && !DConfig.DefConModesOn.count("LIMIT")) - { - DConfig.DefConModesOn.erase("REDIRECT"); - - Log(this) << "DefConChanModes must lock mode +l as well to lock mode +L"; - } - } - - public: - OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), session_service("SessionService", "session"), akills("XLineManager", "xlinemanager/sgline"), commandosdefcon(this) - { - - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = conf->GetModule(this); - DefconConfig dconfig; - - dconfig.defaultlevel = block->Get<int>("defaultlevel"); - dconfig.defcons[4] = block->Get<const Anope::string>("level4"); - dconfig.defcons[3] = block->Get<const Anope::string>("level3"); - dconfig.defcons[2] = block->Get<const Anope::string>("level2"); - dconfig.defcons[1] = block->Get<const Anope::string>("level1"); - dconfig.sessionlimit = block->Get<int>("sessionlimit"); - dconfig.akillreason = block->Get<const Anope::string>("akillreason"); - dconfig.akillexpire = block->Get<time_t>("akillexpire"); - dconfig.chanmodes = block->Get<const Anope::string>("chanmodes"); - dconfig.timeout = block->Get<time_t>("timeout"); - dconfig.globalondefcon = block->Get<bool>("globalondefcon"); - dconfig.message = block->Get<const Anope::string>("message"); - dconfig.offmessage = block->Get<const Anope::string>("offmessage"); - - block = conf->GetModule("os_session"); - - dconfig.max_session_kill = block->Get<int>("maxsessionkill"); - dconfig.session_autokill_expiry = block->Get<time_t>("sessionautokillexpiry"); - dconfig.sle_reason = block->Get<const Anope::string>("sessionlimitexceeded"); - dconfig.sle_detailsloc = block->Get<const Anope::string>("sessionlimitdetailsloc"); - - if (dconfig.defaultlevel < 1 || dconfig.defaultlevel > 5) - throw ConfigException("The value for <defcon:defaultlevel> must be between 1 and 5"); - else if (dconfig.akillexpire <= 0) - throw ConfigException("The value for <defcon:akillexpire> must be greater than zero!"); - - for (unsigned level = 1; level < 5; ++level) - { - spacesepstream operations(dconfig.defcons[level]); - Anope::string operation; - while (operations.GetToken(operation)) - { - if (operation.equals_ci("nonewchannels")) - dconfig.Add(level, DEFCON_NO_NEW_CHANNELS); - else if (operation.equals_ci("nonewnicks")) - dconfig.Add(level, DEFCON_NO_NEW_NICKS); - else if (operation.equals_ci("nomlockchanges")) - dconfig.Add(level, DEFCON_NO_MLOCK_CHANGE); - else if (operation.equals_ci("forcechanmodes")) - dconfig.Add(level, DEFCON_FORCE_CHAN_MODES); - else if (operation.equals_ci("reducedsessions")) - dconfig.Add(level, DEFCON_REDUCE_SESSION); - else if (operation.equals_ci("nonewclients")) - dconfig.Add(level, DEFCON_NO_NEW_CLIENTS); - else if (operation.equals_ci("operonly")) - dconfig.Add(level, DEFCON_OPER_ONLY); - else if (operation.equals_ci("silentoperonly")) - dconfig.Add(level, DEFCON_SILENT_OPER_ONLY); - else if (operation.equals_ci("akillnewclients")) - dconfig.Add(level, DEFCON_AKILL_NEW_CLIENTS); - else if (operation.equals_ci("nonewmemos")) - dconfig.Add(level, DEFCON_NO_NEW_MEMOS); - } - - if (dconfig.Check(level, DEFCON_REDUCE_SESSION) && dconfig.sessionlimit <= 0) - throw ConfigException("The value for <defcon:sessionlimit> must be greater than zero!"); - else if (dconfig.Check(level, DEFCON_AKILL_NEW_CLIENTS) && dconfig.akillreason.empty()) - throw ConfigException("The value for <defcon:akillreason> must not be empty!"); - else if (dconfig.Check(level, DEFCON_FORCE_CHAN_MODES) && dconfig.chanmodes.empty()) - throw ConfigException("The value for <defcon:chanmodes> must not be empty!"); - } - - DConfig = dconfig; - this->ParseModeString(); - } - - EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) anope_override - { - if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOff.count(mode->name) && source.GetUser() && !source.GetBot()) - { - c->RemoveMode(Config->GetClient("OperServ"), mode, param); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnChannelModeUnset(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string &) anope_override - { - if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOn.count(mode->name) && source.GetUser() && !source.GetBot()) - { - Anope::string param; - - if (DConfig.GetDefConParam(mode->name, param)) - c->SetMode(Config->GetClient("OperServ"), mode, param); - else - c->SetMode(Config->GetClient("OperServ"), mode); - - return EVENT_STOP; - - } - - return EVENT_CONTINUE; - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override - { - if (DConfig.Check(DEFCON_OPER_ONLY) && !source.IsOper()) - { - source.Reply(_("Services are in DefCon mode, please try again later.")); - return EVENT_STOP; - } - else if (DConfig.Check(DEFCON_SILENT_OPER_ONLY) && !source.IsOper()) - { - return EVENT_STOP; - } - else if (command->name == "nickserv/register" || command->name == "nickserv/group") - { - if (DConfig.Check(DEFCON_NO_NEW_NICKS)) - { - source.Reply(_("Services are in DefCon mode, please try again later.")); - return EVENT_STOP; - } - } - else if (command->name == "chanserv/mode" && params.size() > 1 && params[1].equals_ci("LOCK")) - { - if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) - { - source.Reply(_("Services are in DefCon mode, please try again later.")); - return EVENT_STOP; - } - } - else if (command->name == "chanserv/register") - { - if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) - { - source.Reply(_("Services are in DefCon mode, please try again later.")); - return EVENT_STOP; - } - } - else if (command->name == "memoserv/send") - { - if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) - { - source.Reply(_("Services are in DefCon mode, please try again later.")); - return EVENT_STOP; - } - } - - return EVENT_CONTINUE; - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (exempt || u->Quitting() || !u->server->IsSynced() || u->server->IsULined()) - return; - - BotInfo *OperServ = Config->GetClient("OperServ"); - if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && akills) - { - Log(OperServ, "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; - XLine x("*@" + u->host, OperServ ? OperServ->nick : "defcon", Anope::CurTime + DConfig.akillexpire, DConfig.akillreason, XLineManager::GenerateUID()); - akills->Send(NULL, &x); - } - - if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) - { - u->Kill(OperServ, DConfig.akillreason); - return; - } - - if (DConfig.sessionlimit <= 0 || !session_service) - return; - - Session *session = session_service->FindSession(u->ip.addr()); - Exception *exception = session_service->FindException(u); - - if (DConfig.Check(DEFCON_REDUCE_SESSION) && !exception) - { - if (session && session->count > static_cast<unsigned>(DConfig.sessionlimit)) - { - if (!DConfig.sle_reason.empty()) - { - Anope::string message = DConfig.sle_reason.replace_all_cs("%IP%", u->ip.addr()); - u->SendMessage(OperServ, message); - } - if (!DConfig.sle_detailsloc.empty()) - u->SendMessage(OperServ, DConfig.sle_detailsloc); - - ++session->hits; - if (akills && DConfig.max_session_kill && session->hits >= DConfig.max_session_kill) - { - XLine x("*@" + session->addr.mask(), OperServ ? OperServ->nick : "", Anope::CurTime + DConfig.session_autokill_expiry, "Defcon session limit exceeded", XLineManager::GenerateUID()); - akills->Send(NULL, &x); - Log(OperServ, "akill/defcon") << "[DEFCON] Added a temporary AKILL for \002*@" << session->addr.mask() << "\002 due to excessive connections"; - } - else - { - u->Kill(OperServ, "Defcon session limit exceeded"); - } - } - } - } - - void OnChannelModeAdd(ChannelMode *cm) anope_override - { - if (DConfig.chanmodes.find(cm->mchar) != Anope::string::npos) - this->ParseModeString(); - } - - void OnChannelSync(Channel *c) anope_override - { - if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) - c->SetModes(Config->GetClient("OperServ"), false, "%s", DConfig.chanmodes.c_str()); - } -}; - -static void runDefCon() -{ - BotInfo *OperServ = Config->GetClient("OperServ"); - if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) - { - if (!DConfig.chanmodes.empty() && !DefConModesSet) - { - if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') - { - Log(OperServ, "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels"; - DefConModesSet = true; - for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - it->second->SetModes(OperServ, false, "%s", DConfig.chanmodes.c_str()); - } - } - } - else - { - if (!DConfig.chanmodes.empty() && DefConModesSet) - { - if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') - { - DefConModesSet = false; - Anope::string newmodes = defconReverseModes(DConfig.chanmodes); - if (!newmodes.empty()) - { - Log(OperServ, "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; - for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) - it->second->SetModes(OperServ, true, "%s", newmodes.c_str()); - } - } - } - } -} - -static Anope::string defconReverseModes(const Anope::string &modes) -{ - if (modes.empty()) - return ""; - Anope::string newmodes; - for (unsigned i = 0, end = modes.length(); i < end; ++i) - { - if (modes[i] == '+') - newmodes += '-'; - else if (modes[i] == '-') - newmodes += '+'; - else - newmodes += modes[i]; - } - return newmodes; -} - -MODULE_INIT(OSDefcon) diff --git a/modules/commands/os_dns.cpp b/modules/commands/os_dns.cpp deleted file mode 100644 index 687f44f4a..000000000 --- a/modules/commands/os_dns.cpp +++ /dev/null @@ -1,949 +0,0 @@ -/* - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -#include "module.h" -#include "modules/dns.h" - -static ServiceReference<DNS::Manager> dnsmanager("DNS::Manager", "dns/manager"); - -struct DNSZone; -class DNSServer; - -static Serialize::Checker<std::vector<DNSZone *> > zones("DNSZone"); -static Serialize::Checker<std::vector<DNSServer *> > dns_servers("DNSServer"); - -static std::map<Anope::string, std::list<time_t> > server_quit_times; - -struct DNSZone : Serializable -{ - Anope::string name; - std::set<Anope::string, ci::less> servers; - - DNSZone(const Anope::string &n) : Serializable("DNSZone"), name(n) - { - zones->push_back(this); - } - - ~DNSZone() - { - std::vector<DNSZone *>::iterator it = std::find(zones->begin(), zones->end(), this); - if (it != zones->end()) - zones->erase(it); - } - - void Serialize(Serialize::Data &data) const anope_override - { - data["name"] << name; - unsigned count = 0; - for (std::set<Anope::string, ci::less>::iterator it = servers.begin(), it_end = servers.end(); it != it_end; ++it) - data["server" + stringify(count++)] << *it; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - DNSZone *zone; - Anope::string zone_name; - - data["name"] >> zone_name; - - if (obj) - { - zone = anope_dynamic_static_cast<DNSZone *>(obj); - data["name"] >> zone->name; - } - else - zone = new DNSZone(zone_name); - - zone->servers.clear(); - for (unsigned count = 0; true; ++count) - { - Anope::string server_str; - data["server" + stringify(count)] >> server_str; - if (server_str.empty()) - break; - zone->servers.insert(server_str); - } - - return zone; - } - - static DNSZone *Find(const Anope::string &name) - { - for (unsigned i = 0; i < zones->size(); ++i) - if (zones->at(i)->name.equals_ci(name)) - { - DNSZone *z = zones->at(i); - z->QueueUpdate(); - return z; - } - return NULL; - } -}; - -class DNSServer : public Serializable -{ - Anope::string server_name; - std::vector<Anope::string> ips; - unsigned limit; - /* wants to be in the pool */ - bool pooled; - /* is actually in the pool */ - bool active; - - public: - std::set<Anope::string, ci::less> zones; - time_t repool; - - DNSServer(const Anope::string &sn) : Serializable("DNSServer"), server_name(sn), limit(0), pooled(false), active(false), repool(0) - { - dns_servers->push_back(this); - } - - ~DNSServer() - { - std::vector<DNSServer *>::iterator it = std::find(dns_servers->begin(), dns_servers->end(), this); - if (it != dns_servers->end()) - dns_servers->erase(it); - } - - const Anope::string &GetName() const { return server_name; } - std::vector<Anope::string> &GetIPs() { return ips; } - unsigned GetLimit() const { return limit; } - void SetLimit(unsigned l) { limit = l; } - - bool Pooled() const { return pooled; } - void Pool(bool p) - { - if (!p) - this->SetActive(p); - pooled = p; - } - - bool Active() const { return pooled && active; } - void SetActive(bool p) - { - if (p) - this->Pool(p); - active = p; - - if (dnsmanager) - { - dnsmanager->UpdateSerial(); - for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it) - dnsmanager->Notify(*it); - } - } - - void Serialize(Serialize::Data &data) const anope_override - { - data["server_name"] << server_name; - for (unsigned i = 0; i < ips.size(); ++i) - data["ip" + stringify(i)] << ips[i]; - data["limit"] << limit; - data["pooled"] << pooled; - unsigned count = 0; - for (std::set<Anope::string, ci::less>::iterator it = zones.begin(), it_end = zones.end(); it != it_end; ++it) - data["zone" + stringify(count++)] << *it; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - DNSServer *req; - Anope::string server_name; - - data["server_name"] >> server_name; - - if (obj) - { - req = anope_dynamic_static_cast<DNSServer *>(obj); - req->server_name = server_name; - } - else - req = new DNSServer(server_name); - - for (unsigned i = 0; true; ++i) - { - Anope::string ip_str; - data["ip" + stringify(i)] >> ip_str; - if (ip_str.empty()) - break; - req->ips.push_back(ip_str); - } - - data["limit"] >> req->limit; - data["pooled"] >> req->pooled; - - req->zones.clear(); - for (unsigned i = 0; true; ++i) - { - Anope::string zone_str; - data["zone" + stringify(i)] >> zone_str; - if (zone_str.empty()) - break; - req->zones.insert(zone_str); - } - - return req; - } - - static DNSServer *Find(const Anope::string &s) - { - for (unsigned i = 0; i < dns_servers->size(); ++i) - if (dns_servers->at(i)->GetName().equals_ci(s)) - { - DNSServer *serv = dns_servers->at(i); - serv->QueueUpdate(); - return serv; - } - return NULL; - } -}; - -class CommandOSDNS : public Command -{ - void DisplayPoolState(CommandSource &source) - { - if (dns_servers->empty()) - { - source.Reply(_("There are no configured servers.")); - return; - } - - ListFormatter lf(source.GetAccount()); - lf.AddColumn(_("Server")).AddColumn(_("IP")).AddColumn(_("Limit")).AddColumn(_("State")); - for (unsigned i = 0; i < dns_servers->size(); ++i) - { - DNSServer *s = dns_servers->at(i); - Server *srv = Server::Find(s->GetName(), true); - - ListFormatter::ListEntry entry; - entry["Server"] = s->GetName(); - entry["Limit"] = s->GetLimit() ? stringify(s->GetLimit()) : Language::Translate(source.GetAccount(), _("None")); - - Anope::string ip_str; - for (unsigned j = 0; j < s->GetIPs().size(); ++j) - ip_str += s->GetIPs()[j] + " "; - ip_str.trim(); - if (ip_str.empty()) - ip_str = "None"; - entry["IP"] = ip_str; - - if (s->Active()) - entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Active")); - else if (s->Pooled()) - entry["State"] = Language::Translate(source.GetAccount(), _("Pooled/Not Active")); - else - entry["State"] = Language::Translate(source.GetAccount(), _("Unpooled")); - - if (!srv) - entry["State"] += Anope::string(" ") + Language::Translate(source.GetAccount(), _("(Split)")); - - lf.AddEntry(entry); - } - - std::vector<Anope::string> replies; - lf.Process(replies); - - if (!zones->empty()) - { - ListFormatter lf2(source.GetAccount()); - lf2.AddColumn(_("Zone")).AddColumn(_("Servers")); - - for (unsigned i = 0; i < zones->size(); ++i) - { - const DNSZone *z = zones->at(i); - - ListFormatter::ListEntry entry; - entry["Zone"] = z->name; - - Anope::string server_str; - for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it) - server_str += *it + " "; - server_str.trim(); - - if (server_str.empty()) - server_str = "None"; - - entry["Servers"] = server_str; - - lf2.AddEntry(entry); - } - - lf2.Process(replies); - } - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - - void AddZone(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &zone = params[1]; - - if (DNSZone::Find(zone)) - { - source.Reply(_("Zone %s already exists."), zone.c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to add zone " << zone; - - new DNSZone(zone); - source.Reply(_("Added zone %s."), zone.c_str()); - } - - void DelZone(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &zone = params[1]; - - DNSZone *z = DNSZone::Find(zone); - if (!z) - { - source.Reply(_("Zone %s does not exist."), zone.c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to delete zone " << z->name; - - for (std::set<Anope::string, ci::less>::iterator it = z->servers.begin(), it_end = z->servers.end(); it != it_end; ++it) - { - DNSServer *s = DNSServer::Find(*it); - if (s) - s->zones.erase(z->name); - } - - if (dnsmanager) - { - dnsmanager->UpdateSerial(); - dnsmanager->Notify(z->name); - } - - source.Reply(_("Zone %s removed."), z->name.c_str()); - delete z; - } - - void AddServer(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - const Anope::string &zone = params.size() > 2 ? params[2] : ""; - - if (s) - { - if (zone.empty()) - { - source.Reply(_("Server %s already exists."), s->GetName().c_str()); - } - else - { - DNSZone *z = DNSZone::Find(zone); - if (!z) - { - source.Reply(_("Zone %s does not exist."), zone.c_str()); - return; - } - else if (z->servers.count(s->GetName())) - { - source.Reply(_("Server %s is already in zone %s."), s->GetName().c_str(), z->name.c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - z->servers.insert(s->GetName()); - s->zones.insert(zone); - - if (dnsmanager) - { - dnsmanager->UpdateSerial(); - dnsmanager->Notify(zone); - } - - Log(LOG_ADMIN, source, this) << "to add server " << s->GetName() << " to zone " << z->name; - - source.Reply(_("Server %s added to zone %s."), s->GetName().c_str(), z->name.c_str()); - } - - return; - } - - Server *serv = Server::Find(params[1], true); - if (!serv || serv == Me || serv->IsJuped()) - { - source.Reply(_("Server %s is not linked to the network."), params[1].c_str()); - return; - } - - s = new DNSServer(params[1]); - if (zone.empty()) - { - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to add server " << s->GetName(); - source.Reply(_("Added server %s."), s->GetName().c_str()); - } - else - { - DNSZone *z = DNSZone::Find(zone); - if (!z) - { - source.Reply(_("Zone %s does not exist."), zone.c_str()); - delete s; - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to add server " << s->GetName() << " to zone " << zone; - - z->servers.insert(s->GetName()); - s->zones.insert(z->name); - - if (dnsmanager) - { - dnsmanager->UpdateSerial(); - dnsmanager->Notify(z->name); - } - } - } - - void DelServer(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - const Anope::string &zone = params.size() > 2 ? params[2] : ""; - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - else if (!zone.empty()) - { - DNSZone *z = DNSZone::Find(zone); - if (!z) - { - source.Reply(_("Zone %s does not exist."), zone.c_str()); - return; - } - else if (!z->servers.count(s->GetName())) - { - source.Reply(_("Server %s is not in zone %s."), s->GetName().c_str(), z->name.c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to remove server " << s->GetName() << " from zone " << z->name; - - if (dnsmanager) - { - dnsmanager->UpdateSerial(); - dnsmanager->Notify(z->name); - } - - z->servers.erase(s->GetName()); - s->zones.erase(z->name); - source.Reply(_("Removed server %s from zone %s."), s->GetName().c_str(), z->name.c_str()); - return; - } - else if (Server::Find(s->GetName(), true)) - { - source.Reply(_("Server %s must be quit before it can be deleted."), s->GetName().c_str()); - return; - } - - for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it) - { - DNSZone *z = DNSZone::Find(*it); - if (z) - z->servers.erase(s->GetName()); - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - if (dnsmanager) - dnsmanager->UpdateSerial(); - - Log(LOG_ADMIN, source, this) << "to delete server " << s->GetName(); - source.Reply(_("Removed server %s."), s->GetName().c_str()); - delete s; - } - - void AddIP(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - - for (unsigned i = 0; i < s->GetIPs().size(); ++i) - if (params[2].equals_ci(s->GetIPs()[i])) - { - source.Reply(_("IP %s already exists for %s."), s->GetIPs()[i].c_str(), s->GetName().c_str()); - return; - } - - sockaddrs addr(params[2]); - if (!addr.valid()) - { - source.Reply(_("%s is not a valid IP address."), params[2].c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - s->GetIPs().push_back(params[2]); - source.Reply(_("Added IP %s to %s."), params[2].c_str(), s->GetName().c_str()); - Log(LOG_ADMIN, source, this) << "to add IP " << params[2] << " to " << s->GetName(); - - if (s->Active() && dnsmanager) - { - dnsmanager->UpdateSerial(); - for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it) - dnsmanager->Notify(*it); - } - } - - void DelIP(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - for (unsigned i = 0; i < s->GetIPs().size(); ++i) - if (params[2].equals_ci(s->GetIPs()[i])) - { - s->GetIPs().erase(s->GetIPs().begin() + i); - source.Reply(_("Removed IP %s from %s."), params[2].c_str(), s->GetName().c_str()); - Log(LOG_ADMIN, source, this) << "to remove IP " << params[2] << " from " << s->GetName(); - - if (s->GetIPs().empty()) - { - s->repool = 0; - s->Pool(false); - } - - if (s->Active() && dnsmanager) - { - dnsmanager->UpdateSerial(); - for (std::set<Anope::string, ci::less>::iterator it = s->zones.begin(), it_end = s->zones.end(); it != it_end; ++it) - dnsmanager->Notify(*it); - } - - return; - } - - source.Reply(_("IP %s does not exist for %s."), params[2].c_str(), s->GetName().c_str()); - } - - void OnSet(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - if (params[2].equals_ci("LIMIT")) - { - try - { - unsigned l = convertTo<unsigned>(params[3]); - s->SetLimit(l); - if (l) - source.Reply(_("User limit for %s set to %d."), s->GetName().c_str(), l); - else - source.Reply(_("User limit for %s removed."), s->GetName().c_str()); - } - catch (const ConvertException &ex) - { - source.Reply(_("Invalid value for LIMIT. Must be numerical.")); - } - } - else - source.Reply(_("Unknown SET option.")); - } - - void OnPool(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - else if (!Server::Find(s->GetName(), true)) - { - source.Reply(_("Server %s is not currently linked."), s->GetName().c_str()); - return; - } - else if (s->Pooled()) - { - source.Reply(_("Server %s is already pooled."), s->GetName().c_str()); - return; - } - else if (s->GetIPs().empty()) - { - source.Reply(_("Server %s has no configured IPs."), s->GetName().c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - s->SetActive(true); - - source.Reply(_("Pooled %s."), s->GetName().c_str()); - Log(LOG_ADMIN, source, this) << "to pool " << s->GetName(); - } - - - void OnDepool(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - DNSServer *s = DNSServer::Find(params[1]); - - if (!s) - { - source.Reply(_("Server %s does not exist."), params[1].c_str()); - return; - } - else if (!s->Pooled()) - { - source.Reply(_("Server %s is not pooled."), s->GetName().c_str()); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - s->Pool(false); - - source.Reply(_("Depooled %s."), s->GetName().c_str()); - Log(LOG_ADMIN, source, this) << "to depool " << s->GetName(); - } - - public: - CommandOSDNS(Module *creator) : Command(creator, "operserv/dns", 0, 4) - { - this->SetDesc(_("Manage DNS zones for this network")); - this->SetSyntax(_("ADDZONE \037zone.name\037")); - this->SetSyntax(_("DELZONE \037zone.name\037")); - this->SetSyntax(_("ADDSERVER \037server.name\037 [\037zone.name\037]")); - this->SetSyntax(_("DELSERVER \037server.name\037 [\037zone.name\037]")); - this->SetSyntax(_("ADDIP \037server.name\037 \037ip\037")); - this->SetSyntax(_("DELIP \037server.name\037 \037ip\037")); - this->SetSyntax(_("SET \037server.name\037 \037option\037 \037value\037")); - this->SetSyntax(_("POOL \037server.name\037")); - this->SetSyntax(_("DEPOOL \037server.name\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.empty()) - this->DisplayPoolState(source); - else if (params[0].equals_ci("ADDZONE") && params.size() > 1) - this->AddZone(source, params); - else if (params[0].equals_ci("DELZONE") && params.size() > 1) - this->DelZone(source, params); - else if (params[0].equals_ci("ADDSERVER") && params.size() > 1) - this->AddServer(source, params); - else if (params[0].equals_ci("DELSERVER") && params.size() > 1) - this->DelServer(source, params); - else if (params[0].equals_ci("ADDIP") && params.size() > 2) - this->AddIP(source, params); - else if (params[0].equals_ci("DELIP") && params.size() > 2) - this->DelIP(source, params); - else if (params[0].equals_ci("SET") && params.size() > 3) - this->OnSet(source, params); - else if (params[0].equals_ci("POOL") && params.size() > 1) - this->OnPool(source, params); - else if (params[0].equals_ci("DEPOOL") && params.size() > 1) - this->OnDepool(source, params); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command allows managing DNS zones used for controlling what servers users\n" - "are directed to when connecting. Omitting all parameters prints out the status of\n" - "the DNS zone.\n" - " \n" - "\002ADDZONE\002 adds a zone, eg us.yournetwork.tld. Servers can then be added to this\n" - "zone with the \002ADDSERVER\002 command.\n" - " \n" - "The \002ADDSERVER\002 command adds a server to the given zone. When a query is done, the\n" - "zone in question is served if it exists, else all servers in all zones are served.\n" - "A server may be in more than one zone.\n" - " \n" - "The \002ADDIP\002 command associates an IP with a server.\n" - " \n" - "The \002POOL\002 and \002DEPOOL\002 commands actually add and remove servers to their given zones.")); - return true; - } -}; - -class ModuleDNS : public Module -{ - Serialize::Type zone_type, dns_type; - CommandOSDNS commandosdns; - - time_t ttl; - int user_drop_mark; - time_t user_drop_time; - time_t user_drop_readd_time; - bool remove_split_servers; - bool readd_connected_servers; - - time_t last_warn; - - public: - ModuleDNS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR), - zone_type("DNSZone", DNSZone::Unserialize), dns_type("DNSServer", DNSServer::Unserialize), commandosdns(this), - last_warn(0) - { - - - for (unsigned j = 0; j < dns_servers->size(); ++j) - { - DNSServer *s = dns_servers->at(j); - if (s->Pooled() && Server::Find(s->GetName(), true)) - s->SetActive(true); - } - } - - ~ModuleDNS() - { - for (unsigned i = zones->size(); i > 0; --i) - delete zones->at(i - 1); - for (unsigned i = dns_servers->size(); i > 0; --i) - delete dns_servers->at(i - 1); - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = conf->GetModule(this); - this->ttl = block->Get<time_t>("ttl"); - this->user_drop_mark = block->Get<int>("user_drop_mark"); - this->user_drop_time = block->Get<time_t>("user_drop_time"); - this->user_drop_readd_time = block->Get<time_t>("user_drop_readd_time"); - this->remove_split_servers = block->Get<bool>("remove_split_servers"); - this->readd_connected_servers = block->Get<bool>("readd_connected_servers"); - } - - void OnNewServer(Server *s) anope_override - { - if (s == Me || s->IsJuped()) - return; - if (!Me->IsSynced() || this->readd_connected_servers) - { - DNSServer *dns = DNSServer::Find(s->GetName()); - if (dns && dns->Pooled() && !dns->Active() && !dns->GetIPs().empty()) - { - dns->SetActive(true); - Log(this) << "Pooling server " << s->GetName(); - } - } - } - - void OnServerQuit(Server *s) anope_override - { - DNSServer *dns = DNSServer::Find(s->GetName()); - if (remove_split_servers && dns && dns->Pooled() && dns->Active()) - { - if (readd_connected_servers) - dns->SetActive(false); // Will be reactivated when it comes back - else - dns->Pool(false); // Otherwise permanently pull this - Log(this) << "Depooling delinked server " << s->GetName(); - } - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (!u->Quitting() && u->server) - { - DNSServer *s = DNSServer::Find(u->server->GetName()); - /* Check for user limit reached */ - if (s && s->Pooled() && s->Active() && s->GetLimit() && u->server->users >= s->GetLimit()) - { - Log(this) << "Depooling full server " << s->GetName() << ": " << u->server->users << " users"; - s->SetActive(false); - } - } - } - - void OnPreUserLogoff(User *u) anope_override - { - if (u && u->server) - { - DNSServer *s = DNSServer::Find(u->server->GetName()); - if (!s || !s->Pooled()) - return; - - /* Check for dropping under userlimit */ - if (s->GetLimit() && !s->Active() && s->GetLimit() > u->server->users) - { - Log(this) << "Pooling server " << s->GetName(); - s->SetActive(true); - } - - if (this->user_drop_mark > 0) - { - std::list<time_t>& times = server_quit_times[u->server->GetName()]; - times.push_back(Anope::CurTime); - if (times.size() > static_cast<unsigned>(this->user_drop_mark)) - times.pop_front(); - - if (times.size() == static_cast<unsigned>(this->user_drop_mark)) - { - time_t diff = Anope::CurTime - *times.begin(); - - /* Check for very fast user drops */ - if (s->Active() && diff <= this->user_drop_time) - { - Log(this) << "Depooling server " << s->GetName() << ": dropped " << this->user_drop_mark << " users in " << diff << " seconds"; - s->repool = Anope::CurTime + this->user_drop_readd_time; - s->SetActive(false); - } - /* Check for needing to re-pool a server that dropped users */ - else if (!s->Active() && s->repool && s->repool <= Anope::CurTime) - { - s->SetActive(true); - s->repool = 0; - Log(this) << "Pooling server " << s->GetName(); - } - } - } - } - } - - void OnDnsRequest(DNS::Query &req, DNS::Query *packet) anope_override - { - if (req.questions.empty()) - return; - /* Currently we reply to any QR for A/AAAA */ - const DNS::Question& q = req.questions[0]; - if (q.type != DNS::QUERY_A && q.type != DNS::QUERY_AAAA && q.type != DNS::QUERY_AXFR && q.type != DNS::QUERY_ANY) - return; - - DNSZone *zone = DNSZone::Find(q.name); - size_t answer_size = packet->answers.size(); - if (zone) - { - for (std::set<Anope::string, ci::less>::iterator it = zone->servers.begin(), it_end = zone->servers.end(); it != it_end; ++it) - { - DNSServer *s = DNSServer::Find(*it); - if (!s || !s->Active()) - continue; - - for (unsigned j = 0; j < s->GetIPs().size(); ++j) - { - DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A; - - if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type) - { - DNS::ResourceRecord rr(q.name, q_type); - rr.ttl = this->ttl; - rr.rdata = s->GetIPs()[j]; - packet->answers.push_back(rr); - } - } - } - } - - if (packet->answers.size() == answer_size) - { - /* Default zone */ - for (unsigned i = 0; i < dns_servers->size(); ++i) - { - DNSServer *s = dns_servers->at(i); - if (!s->Active()) - continue; - - for (unsigned j = 0; j < s->GetIPs().size(); ++j) - { - DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A; - - if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type) - { - DNS::ResourceRecord rr(q.name, q_type); - rr.ttl = this->ttl; - rr.rdata = s->GetIPs()[j]; - packet->answers.push_back(rr); - } - } - } - } - - if (packet->answers.size() == answer_size) - { - if (last_warn + 60 < Anope::CurTime) - { - last_warn = Anope::CurTime; - Log(this) << "Warning! There are no pooled servers!"; - } - - /* Something messed up, just return them all and hope one is available */ - for (unsigned i = 0; i < dns_servers->size(); ++i) - { - DNSServer *s = dns_servers->at(i); - - for (unsigned j = 0; j < s->GetIPs().size(); ++j) - { - DNS::QueryType q_type = s->GetIPs()[j].find(':') != Anope::string::npos ? DNS::QUERY_AAAA : DNS::QUERY_A; - - if (q.type == DNS::QUERY_AXFR || q.type == DNS::QUERY_ANY || q_type == q.type) - { - DNS::ResourceRecord rr(q.name, q_type); - rr.ttl = this->ttl; - rr.rdata = s->GetIPs()[j]; - packet->answers.push_back(rr); - } - } - } - - if (packet->answers.size() == answer_size) - { - Log(this) << "Error! There are no servers with any IPs of type " << q.type; - /* Send back an empty answer anyway */ - } - } - } -}; - -MODULE_INIT(ModuleDNS) diff --git a/modules/commands/os_forbid.cpp b/modules/commands/os_forbid.cpp deleted file mode 100644 index 8c723b337..000000000 --- a/modules/commands/os_forbid.cpp +++ /dev/null @@ -1,559 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_forbid.h" - -static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); - -struct ForbidDataImpl : ForbidData, Serializable -{ - ForbidDataImpl() : Serializable("ForbidData") { } - void Serialize(Serialize::Data &data) const anope_override; - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data); -}; - -void ForbidDataImpl::Serialize(Serialize::Data &data) const -{ - data["mask"] << this->mask; - data["creator"] << this->creator; - data["reason"] << this->reason; - data["created"] << this->created; - data["expires"] << this->expires; - data["type"] << this->type; -} - -Serializable* ForbidDataImpl::Unserialize(Serializable *obj, Serialize::Data &data) -{ - if (!forbid_service) - return NULL; - - ForbidDataImpl *fb; - if (obj) - fb = anope_dynamic_static_cast<ForbidDataImpl *>(obj); - else - fb = new ForbidDataImpl(); - - data["mask"] >> fb->mask; - data["creator"] >> fb->creator; - data["reason"] >> fb->reason; - data["created"] >> fb->created; - data["expires"] >> fb->expires; - unsigned int t; - data["type"] >> t; - fb->type = static_cast<ForbidType>(t); - - if (t > FT_SIZE - 1) - return NULL; - - if (!obj) - forbid_service->AddForbid(fb); - return fb; -} - -class MyForbidService : public ForbidService -{ - Serialize::Checker<std::vector<ForbidData *>[FT_SIZE - 1]> forbid_data; - - inline std::vector<ForbidData *>& forbids(unsigned t) { return (*this->forbid_data)[t - 1]; } - - public: - MyForbidService(Module *m) : ForbidService(m), forbid_data("ForbidData") { } - - ~MyForbidService() - { - std::vector<ForbidData *> f = GetForbids(); - for (unsigned i = 0; i < f.size(); ++i) - delete f[i]; - } - - void AddForbid(ForbidData *d) anope_override - { - this->forbids(d->type).push_back(d); - } - - void RemoveForbid(ForbidData *d) anope_override - { - std::vector<ForbidData *>::iterator it = std::find(this->forbids(d->type).begin(), this->forbids(d->type).end(), d); - if (it != this->forbids(d->type).end()) - this->forbids(d->type).erase(it); - delete d; - } - - ForbidData *CreateForbid() anope_override - { - return new ForbidDataImpl(); - } - - ForbidData *FindForbid(const Anope::string &mask, ForbidType ftype) anope_override - { - for (unsigned i = this->forbids(ftype).size(); i > 0; --i) - { - ForbidData *d = this->forbids(ftype)[i - 1]; - - if (Anope::Match(mask, d->mask, false, true)) - return d; - } - return NULL; - } - - std::vector<ForbidData *> GetForbids() anope_override - { - std::vector<ForbidData *> f; - for (unsigned j = FT_NICK; j < FT_SIZE; ++j) - for (unsigned i = this->forbids(j).size(); i > 0; --i) - { - ForbidData *d = this->forbids(j).at(i - 1); - - if (d->expires && !Anope::NoExpire && Anope::CurTime >= d->expires) - { - Anope::string ftype = "none"; - if (d->type == FT_NICK) - ftype = "nick"; - else if (d->type == FT_CHAN) - ftype = "chan"; - else if (d->type == FT_EMAIL) - ftype = "email"; - - Log(LOG_NORMAL, "expire/forbid", Config->GetClient("OperServ")) << "Expiring forbid for " << d->mask << " type " << ftype; - this->forbids(j).erase(this->forbids(j).begin() + i - 1); - delete d; - } - else - f.push_back(d); - } - - return f; - } -}; - -class CommandOSForbid : public Command -{ - ServiceReference<ForbidService> fs; - public: - CommandOSForbid(Module *creator) : Command(creator, "operserv/forbid", 1, 5), fs("ForbidService", "forbid") - { - this->SetDesc(_("Forbid usage of nicknames, channels, and emails")); - this->SetSyntax(_("ADD {NICK|CHAN|EMAIL|REGISTER} [+\037expiry\037] \037entry\037 \037reason\037")); - this->SetSyntax(_("DEL {NICK|CHAN|EMAIL|REGISTER} \037entry\037")); - this->SetSyntax("LIST [NICK|CHAN|EMAIL|REGISTER]"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!this->fs) - return; - - const Anope::string &command = params[0]; - const Anope::string &subcommand = params.size() > 1 ? params[1] : ""; - - ForbidType ftype = FT_SIZE; - if (subcommand.equals_ci("NICK")) - ftype = FT_NICK; - else if (subcommand.equals_ci("CHAN")) - ftype = FT_CHAN; - else if (subcommand.equals_ci("EMAIL")) - ftype = FT_EMAIL; - else if (subcommand.equals_ci("REGISTER")) - ftype = FT_REGISTER; - - if (command.equals_ci("ADD") && params.size() > 3 && ftype != FT_SIZE) - { - const Anope::string &expiry = params[2][0] == '+' ? params[2] : ""; - const Anope::string &entry = !expiry.empty() ? params[3] : params[2]; - Anope::string reason; - if (expiry.empty()) - reason = params[3] + " "; - if (params.size() > 4) - reason += params[4]; - reason.trim(); - - if (entry.replace_all_cs("?*", "").empty()) - { - source.Reply(_("The mask must contain at least one non wildcard character.")); - return; - } - - time_t expiryt = 0; - - if (!expiry.empty()) - { - expiryt = Anope::DoTime(expiry); - if (expiryt == -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expiryt) - expiryt += Anope::CurTime; - } - - NickAlias *target = NickAlias::Find(entry); - if (target != NULL && Config->GetModule("nickserv")->Get<bool>("secureadmins", "yes") && target->nc->IsServicesOper()) - { - source.Reply(ACCESS_DENIED); - return; - } - - ForbidData *d = this->fs->FindForbid(entry, ftype); - bool created = false; - if (d == NULL) - { - d = new ForbidDataImpl(); - created = true; - } - - d->mask = entry; - d->creator = source.GetNick(); - d->reason = reason; - d->created = Anope::CurTime; - d->expires = expiryt; - d->type = ftype; - if (created) - this->fs->AddForbid(d); - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to add a forbid on " << entry << " of type " << subcommand; - source.Reply(_("Added a forbid on %s of type %s to expire on %s."), entry.c_str(), subcommand.lower().c_str(), d->expires ? Anope::strftime(d->expires, source.GetAccount()).c_str() : "never"); - - /* apply forbid */ - switch (ftype) - { - case FT_NICK: - { - int na_matches = 0; - - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - module->OnUserNickChange(it->second, ""); - - for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end;) - { - NickAlias *na = it->second; - ++it; - - d = this->fs->FindForbid(na->nick, FT_NICK); - if (d == NULL) - continue; - - ++na_matches; - - delete na; - } - - source.Reply(_("\002%d\002 nickname(s) dropped."), na_matches); - break; - } - case FT_CHAN: - { - int chan_matches = 0, ci_matches = 0; - - for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end;) - { - Channel *c = it->second; - ++it; - - d = this->fs->FindForbid(c->name, FT_CHAN); - if (d == NULL) - continue; - - ServiceReference<ChanServService> chanserv("ChanServService", "ChanServ"); - BotInfo *OperServ = Config->GetClient("OperServ"); - if (IRCD->CanSQLineChannel && OperServ) - { - time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s"); - XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->reason); - IRCD->SendSQLine(NULL, &x); - } - else if (chanserv) - { - chanserv->Hold(c); - } - - ++chan_matches; - - for (Channel::ChanUserList::const_iterator cit = c->users.begin(), cit_end = c->users.end(); cit != cit_end;) - { - User *u = cit->first; - ++cit; - - if (u->server == Me || u->HasMode("OPER")) - continue; - - reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); - - c->Kick(source.service, u, "%s", reason.c_str()); - } - } - - for (registered_channel_map::const_iterator it = RegisteredChannelList->begin(); it != RegisteredChannelList->end();) - { - ChannelInfo *ci = it->second; - ++it; - - d = this->fs->FindForbid(ci->name, FT_CHAN); - if (d == NULL) - continue; - - ++ci_matches; - - delete ci; - } - - source.Reply(_("\002%d\002 channel(s) cleared, and \002%d\002 channel(s) dropped."), chan_matches, ci_matches); - - break; - } - default: - break; - } - - } - else if (command.equals_ci("DEL") && params.size() > 2 && ftype != FT_SIZE) - { - const Anope::string &entry = params[2]; - - ForbidData *d = this->fs->FindForbid(entry, ftype); - if (d != NULL) - { - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to remove forbid on " << d->mask << " of type " << subcommand; - source.Reply(_("%s deleted from the %s forbid list."), d->mask.c_str(), subcommand.c_str()); - this->fs->RemoveForbid(d); - } - else - source.Reply(_("Forbid on %s was not found."), entry.c_str()); - } - else if (command.equals_ci("LIST")) - { - const std::vector<ForbidData *> &forbids = this->fs->GetForbids(); - if (forbids.empty()) - source.Reply(_("Forbid list is empty.")); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Mask")).AddColumn(_("Type")).AddColumn(_("Creator")).AddColumn(_("Expires")).AddColumn(_("Reason")); - - unsigned shown = 0; - for (unsigned i = 0; i < forbids.size(); ++i) - { - ForbidData *d = forbids[i]; - - if (ftype != FT_SIZE && ftype != d->type) - continue; - - Anope::string stype; - if (d->type == FT_NICK) - stype = "NICK"; - else if (d->type == FT_CHAN) - stype = "CHAN"; - else if (d->type == FT_EMAIL) - stype = "EMAIL"; - else if (d->type == FT_REGISTER) - stype = "REGISTER"; - else - continue; - - ListFormatter::ListEntry entry; - entry["Mask"] = d->mask; - entry["Type"] = stype; - entry["Creator"] = d->creator; - entry["Expires"] = d->expires ? Anope::strftime(d->expires, NULL, true).c_str() : Language::Translate(source.GetAccount(), _("Never")); - entry["Reason"] = d->reason; - list.AddEntry(entry); - ++shown; - } - - if (!shown) - { - source.Reply(_("There are no forbids of type %s."), subcommand.upper().c_str()); - } - else - { - source.Reply(_("Forbid list:")); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - if (shown >= forbids.size()) - source.Reply(_("End of forbid list.")); - else - source.Reply(_("End of forbid list - %d/%d entries shown."), shown, forbids.size()); - } - } - } - else - this->OnSyntaxError(source, command); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Forbid allows you to forbid usage of certain nicknames, channels,\n" - "and email addresses. Wildcards are accepted for all entries.")); - - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), regexengine.c_str()); - } - - return true; - } -}; - -class OSForbid : public Module -{ - MyForbidService forbidService; - Serialize::Type forbiddata_type; - CommandOSForbid commandosforbid; - - public: - OSForbid(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - forbidService(this), forbiddata_type("ForbidData", ForbidDataImpl::Unserialize), commandosforbid(this) - { - - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (u->Quitting() || exempt) - return; - - this->OnUserNickChange(u, ""); - } - - void OnUserNickChange(User *u, const Anope::string &) anope_override - { - if (u->HasMode("OPER")) - return; - - ForbidData *d = this->forbidService.FindForbid(u->nick, FT_NICK); - if (d != NULL) - { - BotInfo *bi = Config->GetClient("NickServ"); - if (!bi) - bi = Config->GetClient("OperServ"); - if (bi) - u->SendMessage(bi, _("This nickname has been forbidden: %s"), d->reason.c_str()); - if (nickserv) - nickserv->Collide(u, NULL); - } - } - - EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override - { - BotInfo *OperServ = Config->GetClient("OperServ"); - if (u->HasMode("OPER") || !OperServ) - return EVENT_CONTINUE; - - ForbidData *d = this->forbidService.FindForbid(c->name, FT_CHAN); - if (d != NULL) - { - ServiceReference<ChanServService> chanserv("ChanServService", "ChanServ"); - if (IRCD->CanSQLineChannel) - { - time_t inhabit = Config->GetModule("chanserv")->Get<time_t>("inhabit", "15s"); - XLine x(c->name, OperServ->nick, Anope::CurTime + inhabit, d->reason); - IRCD->SendSQLine(NULL, &x); - } - else if (chanserv) - { - chanserv->Hold(c); - } - - reason = Anope::printf(Language::Translate(u, _("This channel has been forbidden: %s")), d->reason.c_str()); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> ¶ms) anope_override - { - if (command->name == "nickserv/info" && params.size() > 0) - { - ForbidData *d = this->forbidService.FindForbid(params[0], FT_NICK); - if (d != NULL) - { - if (source.IsOper()) - source.Reply(_("Nick \002%s\002 is forbidden by %s: %s"), params[0].c_str(), d->creator.c_str(), d->reason.c_str()); - else - source.Reply(_("Nick \002%s\002 is forbidden."), params[0].c_str()); - return EVENT_STOP; - } - } - else if (command->name == "chanserv/info" && params.size() > 0) - { - ForbidData *d = this->forbidService.FindForbid(params[0], FT_CHAN); - if (d != NULL) - { - if (source.IsOper()) - source.Reply(_("Channel \002%s\002 is forbidden by %s: %s"), params[0].c_str(), d->creator.c_str(), d->reason.c_str()); - else - source.Reply(_("Channel \002%s\002 is forbidden."), params[0].c_str()); - return EVENT_STOP; - } - } - else if (source.IsOper()) - return EVENT_CONTINUE; - else if (command->name == "nickserv/register" && params.size() > 1) - { - ForbidData *d = this->forbidService.FindForbid(source.GetNick(), FT_REGISTER); - if (d != NULL) - { - source.Reply(NICK_CANNOT_BE_REGISTERED, source.GetNick().c_str()); - return EVENT_STOP; - } - - d = this->forbidService.FindForbid(params[1], FT_EMAIL); - if (d != NULL) - { - source.Reply(_("Your email address is not allowed, choose a different one.")); - return EVENT_STOP; - } - } - else if (command->name == "nickserv/set/email" && params.size() > 0) - { - ForbidData *d = this->forbidService.FindForbid(params[0], FT_EMAIL); - if (d != NULL) - { - source.Reply(_("Your email address is not allowed, choose a different one.")); - return EVENT_STOP; - } - } - else if (command->name == "chanserv/register" && !params.empty()) - { - ForbidData *d = this->forbidService.FindForbid(params[0], FT_REGISTER); - if (d != NULL) - { - source.Reply(CHAN_X_INVALID, params[0].c_str()); - return EVENT_STOP; - } - } - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(OSForbid) diff --git a/modules/commands/os_ignore.cpp b/modules/commands/os_ignore.cpp deleted file mode 100644 index 2f4fca3e2..000000000 --- a/modules/commands/os_ignore.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_ignore.h" - -struct IgnoreDataImpl : IgnoreData, Serializable -{ - IgnoreDataImpl() : Serializable("IgnoreData") { } - ~IgnoreDataImpl(); - void Serialize(Serialize::Data &data) const anope_override; - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data); -}; - -IgnoreDataImpl::~IgnoreDataImpl() -{ - if (ignore_service) - ignore_service->DelIgnore(this); -} - -void IgnoreDataImpl::Serialize(Serialize::Data &data) const -{ - data["mask"] << this->mask; - data["creator"] << this->creator; - data["reason"] << this->reason; - data["time"] << this->time; -} - -Serializable* IgnoreDataImpl::Unserialize(Serializable *obj, Serialize::Data &data) -{ - if (!ignore_service) - return NULL; - - IgnoreDataImpl *ign; - if (obj) - ign = anope_dynamic_static_cast<IgnoreDataImpl *>(obj); - else - { - ign = new IgnoreDataImpl(); - ignore_service->AddIgnore(ign); - } - - data["mask"] >> ign->mask; - data["creator"] >> ign->creator; - data["reason"] >> ign->reason; - data["time"] >> ign->time; - - return ign; -} - - -class OSIgnoreService : public IgnoreService -{ - Serialize::Checker<std::vector<IgnoreData *> > ignores; - - public: - OSIgnoreService(Module *o) : IgnoreService(o), ignores("IgnoreData") { } - - void AddIgnore(IgnoreData *ign) anope_override - { - ignores->push_back(ign); - } - - void DelIgnore(IgnoreData *ign) anope_override - { - std::vector<IgnoreData *>::iterator it = std::find(ignores->begin(), ignores->end(), ign); - if (it != ignores->end()) - ignores->erase(it); - } - - void ClearIgnores() anope_override - { - for (unsigned i = ignores->size(); i > 0; --i) - { - IgnoreData *ign = ignores->at(i - 1); - delete ign; - } - } - - IgnoreData *Create() anope_override - { - return new IgnoreDataImpl(); - } - - IgnoreData *Find(const Anope::string &mask) anope_override - { - User *u = User::Find(mask, true); - std::vector<IgnoreData *>::iterator ign = this->ignores->begin(), ign_end = this->ignores->end(); - - if (u) - { - for (; ign != ign_end; ++ign) - { - Entry ignore_mask("", (*ign)->mask); - if (ignore_mask.Matches(u, true)) - break; - } - } - else - { - size_t user, host; - Anope::string tmp; - /* We didn't get a user.. generate a valid mask. */ - if ((host = mask.find('@')) != Anope::string::npos) - { - if ((user = mask.find('!')) != Anope::string::npos) - { - /* this should never happen */ - if (user > host) - return NULL; - tmp = mask; - } - else - /* We have user@host. Add nick wildcard. */ - tmp = "*!" + mask; - } - /* We only got a nick.. */ - else - tmp = mask + "!*@*"; - - for (; ign != ign_end; ++ign) - if (Anope::Match(tmp, (*ign)->mask, false, true)) - break; - } - - /* Check whether the entry has timed out */ - if (ign != ign_end) - { - IgnoreData *id = *ign; - - if (id->time && !Anope::NoExpire && id->time <= Anope::CurTime) - { - Log(LOG_NORMAL, "expire/ignore", Config->GetClient("OperServ")) << "Expiring ignore entry " << id->mask; - delete id; - } - else - return id; - } - - return NULL; - } - - std::vector<IgnoreData *> &GetIgnores() anope_override - { - return *ignores; - } -}; - -class CommandOSIgnore : public Command -{ - private: - Anope::string RealMask(const Anope::string &mask) - { - /* If it s an existing user, we ignore the hostmask. */ - User *u = User::Find(mask, true); - if (u) - return "*!*@" + u->host; - - size_t host = mask.find('@'); - /* Determine whether we get a nick or a mask. */ - if (host != Anope::string::npos) - { - size_t user = mask.find('!'); - /* Check whether we have a nick too.. */ - if (user != Anope::string::npos) - { - if (user > host) - /* this should never happen */ - return ""; - else - return mask; - } - else - /* We have user@host. Add nick wildcard. */ - return "*!" + mask; - } - - /* We only got a nick.. */ - return mask + "!*@*"; - } - - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (!ignore_service) - return; - - const Anope::string &time = params.size() > 1 ? params[1] : ""; - const Anope::string &nick = params.size() > 2 ? params[2] : ""; - const Anope::string &reason = params.size() > 3 ? params[3] : ""; - - if (time.empty() || nick.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - else - { - time_t t = Anope::DoTime(time); - - if (t <= -1) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - - Anope::string mask = RealMask(nick); - if (mask.empty()) - { - source.Reply(BAD_USERHOST_MASK); - return; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - IgnoreData *ign = new IgnoreDataImpl(); - ign->mask = mask; - ign->creator = source.GetNick(); - ign->reason = reason; - ign->time = t ? Anope::CurTime + t : 0; - - ignore_service->AddIgnore(ign); - if (!t) - { - source.Reply(_("\002%s\002 will now permanently be ignored."), mask.c_str()); - Log(LOG_ADMIN, source, this) << "to add a permanent ignore for " << mask; - } - else - { - source.Reply(_("\002%s\002 will now be ignored for \002%s\002."), mask.c_str(), Anope::Duration(t, source.GetAccount()).c_str()); - Log(LOG_ADMIN, source, this) << "to add an ignore on " << mask << " for " << Anope::Duration(t); - } - } - } - - void DoList(CommandSource &source) - { - if (!ignore_service) - return; - - std::vector<IgnoreData *> &ignores = ignore_service->GetIgnores(); - for (unsigned i = ignores.size(); i > 0; --i) - { - IgnoreData *id = ignores[i - 1]; - - if (id->time && !Anope::NoExpire && id->time <= Anope::CurTime) - { - Log(LOG_NORMAL, "expire/ignore", Config->GetClient("OperServ")) << "Expiring ignore entry " << id->mask; - delete id; - } - } - - if (ignores.empty()) - source.Reply(_("Ignore list is empty.")); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Mask")).AddColumn(_("Creator")).AddColumn(_("Reason")).AddColumn(_("Expires")); - - for (unsigned i = ignores.size(); i > 0; --i) - { - const IgnoreData *ignore = ignores[i - 1]; - - ListFormatter::ListEntry entry; - entry["Mask"] = ignore->mask; - entry["Creator"] = ignore->creator; - entry["Reason"] = ignore->reason; - entry["Expires"] = Anope::Expires(ignore->time, source.GetAccount()); - list.AddEntry(entry); - } - - source.Reply(_("Services ignore list:")); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - if (!ignore_service) - return; - - const Anope::string nick = params.size() > 1 ? params[1] : ""; - if (nick.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - Anope::string mask = RealMask(nick); - if (mask.empty()) - { - source.Reply(BAD_USERHOST_MASK); - return; - } - - IgnoreData *ign = ignore_service->Find(mask); - if (ign) - { - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "to remove an ignore on " << mask; - source.Reply(_("\002%s\002 will no longer be ignored."), mask.c_str()); - delete ign; - } - else - source.Reply(_("\002%s\002 not found on ignore list."), mask.c_str()); - } - - void DoClear(CommandSource &source) - { - if (!ignore_service) - return; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - ignore_service->ClearIgnores(); - Log(LOG_ADMIN, source, this) << "to CLEAR the list"; - source.Reply(_("Ignore list has been cleared.")); - - return; - } - - public: - CommandOSIgnore(Module *creator) : Command(creator, "operserv/ignore", 1, 4) - { - this->SetDesc(_("Modify the Services ignore list")); - this->SetSyntax(_("ADD \037expiry\037 {\037nick\037|\037mask\037} [\037reason\037]")); - this->SetSyntax(_("DEL {\037nick\037|\037mask\037}")); - this->SetSyntax("LIST"); - this->SetSyntax("CLEAR"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->DoClear(source); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to make Services ignore a nick or mask\n" - "for a certain time or until the next restart. The default\n" - "time format is seconds. You can specify it by using units.\n" - "Valid units are: \037s\037 for seconds, \037m\037 for minutes,\n" - "\037h\037 for hours and \037d\037 for days.\n" - "Combinations of these units are not permitted.\n" - "To make Services permanently ignore the user, type 0 as time.\n" - "When adding a \037mask\037, it should be in the format nick!user@host,\n" - "everything else will be considered a nick. Wildcards are permitted.\n" - " \n" - "Ignores will not be enforced on IRC Operators.")); - - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), regexengine.c_str()); - } - - return true; - } -}; - -class OSIgnore : public Module -{ - Serialize::Type ignoredata_type; - OSIgnoreService osignoreservice; - CommandOSIgnore commandosignore; - - public: - OSIgnore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - ignoredata_type("IgnoreData", IgnoreDataImpl::Unserialize), osignoreservice(this), commandosignore(this) - { - - } - - EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message) anope_override - { - if (!u->HasMode("OPER") && this->osignoreservice.Find(u->nick)) - return EVENT_STOP; - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(OSIgnore) diff --git a/modules/commands/os_info.cpp b/modules/commands/os_info.cpp deleted file mode 100644 index 0965d5ea7..000000000 --- a/modules/commands/os_info.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - */ - -#include "module.h" - -struct OperInfo : Serializable -{ - Anope::string target; - Anope::string info; - Anope::string adder; - time_t created; - - OperInfo() : Serializable("OperInfo"), created(0) { } - OperInfo(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c) : - Serializable("OperInfo"), target(t), info(i), adder(a), created(c) { } - - ~OperInfo(); - - void Serialize(Serialize::Data &data) const anope_override - { - data["target"] << target; - data["info"] << info; - data["adder"] << adder; - data["created"] << created; - } - - static Serializable *Unserialize(Serializable *obj, Serialize::Data &data); -}; - -struct OperInfos : Serialize::Checker<std::vector<OperInfo *> > -{ - OperInfos(Extensible *) : Serialize::Checker<std::vector<OperInfo *> >("OperInfo") { } - - ~OperInfos() - { - for (unsigned i = (*this)->size(); i > 0; --i) - delete (*this)->at(i - 1); - } - - static Extensible *Find(const Anope::string &target) - { - NickAlias *na = NickAlias::Find(target); - if (na) - return na->nc; - return ChannelInfo::Find(target); - } -}; - -OperInfo::~OperInfo() -{ - Extensible *e = OperInfos::Find(target); - if (e) - { - OperInfos *op = e->GetExt<OperInfos>("operinfo"); - if (op) - { - std::vector<OperInfo *>::iterator it = std::find((*op)->begin(), (*op)->end(), this); - if (it != (*op)->end()) - (*op)->erase(it); - } - } -} - -Serializable *OperInfo::Unserialize(Serializable *obj, Serialize::Data &data) -{ - Anope::string starget; - data["target"] >> starget; - - Extensible *e = OperInfos::Find(starget); - if (!e) - return NULL; - - OperInfos *oi = e->Require<OperInfos>("operinfo"); - OperInfo *o; - if (obj) - o = anope_dynamic_static_cast<OperInfo *>(obj); - else - { - o = new OperInfo(); - o->target = starget; - } - data["info"] >> o->info; - data["adder"] >> o->adder; - data["created"] >> o->created; - - if (!obj) - (*oi)->push_back(o); - return o; -} - -class CommandOSInfo : public Command -{ - public: - CommandOSInfo(Module *creator) : Command(creator, "operserv/info", 2, 3) - { - this->SetDesc(_("Associate oper info with a nick or channel")); - this->SetSyntax(_("ADD \037target\037 \037info\037")); - this->SetSyntax(_("DEL \037target\037 \037info\037")); - this->SetSyntax(_("CLEAR \037target\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0], target = params[1], info = params.size() > 2 ? params[2] : ""; - - Extensible *e; - if (IRCD->IsChannelValid(target)) - { - ChannelInfo *ci = ChannelInfo::Find(target); - if (!ci) - { - source.Reply(CHAN_X_NOT_REGISTERED, target.c_str()); - return; - } - - e = ci; - } - else - { - NickAlias *na = NickAlias::Find(target); - if (!na) - { - source.Reply(NICK_X_NOT_REGISTERED, target.c_str()); - return; - } - - e = na->nc; - } - - if (cmd.equals_ci("ADD")) - { - if (info.empty()) - { - this->OnSyntaxError(source, cmd); - return; - } - - OperInfos *oi = e->Require<OperInfos>("operinfo"); - - if ((*oi)->size() >= Config->GetModule(this->module)->Get<unsigned>("max", "10")) - { - source.Reply(_("The oper info list for \002%s\002 is full."), target.c_str()); - return; - } - - for (unsigned i = 0; i < (*oi)->size(); ++i) - { - OperInfo *o = (*oi)->at(i); - - if (o->info.equals_ci(info)) - { - source.Reply(_("The oper info already exists on \002%s\002."), target.c_str()); - return; - } - } - - (*oi)->push_back(new OperInfo(target, info, source.GetNick(), Anope::CurTime)); - - source.Reply(_("Added info to \002%s\002."), target.c_str()); - Log(LOG_ADMIN, source, this) << "to add information to " << target; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - else if (cmd.equals_ci("DEL")) - { - if (info.empty()) - { - this->OnSyntaxError(source, cmd); - return; - } - - OperInfos *oi = e->GetExt<OperInfos>("operinfo"); - - if (!oi) - { - source.Reply(_("Oper info list for \002%s\002 is empty."), target.c_str()); - return; - } - - bool found = false; - for (unsigned i = (*oi)->size(); i > 0; --i) - { - OperInfo *o = (*oi)->at(i - 1); - - if (o->info.equals_ci(info)) - { - delete o; - found = true; - break; - } - } - - if (!found) - { - source.Reply(_("No such info \"%s\" on \002%s\002."), info.c_str(), target.c_str()); - } - else - { - if ((*oi)->empty()) - e->Shrink<OperInfos>("operinfo"); - - source.Reply(_("Deleted info from \002%s\002."), target.c_str()); - Log(LOG_ADMIN, source, this) << "to remove information from " << target; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - } - else if (cmd.equals_ci("CLEAR")) - { - OperInfos *oi = e->GetExt<OperInfos>("operinfo"); - - if (!oi) - { - source.Reply(_("Oper info list for \002%s\002 is empty."), target.c_str()); - return; - } - - e->Shrink<OperInfos>("operinfo"); - - source.Reply(_("Cleared info from \002%s\002."), target.c_str()); - Log(LOG_ADMIN, source, this) << "to clear information for " << target; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - else - { - this->OnSyntaxError(source, cmd); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Add or delete oper information for a given nick or channel.\n" - "This will show to opers in the respective info command for\n" - "the nick or channel.")); - return true; - } -}; - -class OSInfo : public Module -{ - CommandOSInfo commandosinfo; - ExtensibleItem<OperInfos> oinfo; - Serialize::Type oinfo_type; - - void OnInfo(CommandSource &source, Extensible *e, InfoFormatter &info) - { - if (!source.IsOper()) - return; - - OperInfos *oi = oinfo.Get(e); - if (!oi) - return; - - for (unsigned i = 0; i < (*oi)->size(); ++i) - { - OperInfo *o = (*oi)->at(i); - info[_("Oper Info")] = Anope::printf(_("(by %s on %s) %s"), o->adder.c_str(), Anope::strftime(o->created, source.GetAccount(), true).c_str(), o->info.c_str()); - } - } - - public: - OSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosinfo(this), oinfo(this, "operinfo"), oinfo_type("OperInfo", OperInfo::Unserialize) - { - - } - - void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override - { - OnInfo(source, na->nc, info); - } - - void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override - { - OnInfo(source, ci, info); - } -}; - -MODULE_INIT(OSInfo) diff --git a/modules/commands/os_jupe.cpp b/modules/commands/os_jupe.cpp deleted file mode 100644 index c586feee3..000000000 --- a/modules/commands/os_jupe.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSJupe : public Command -{ - public: - CommandOSJupe(Module *creator) : Command(creator, "operserv/jupe", 1, 2) - { - this->SetDesc(_("\"Jupiter\" a server")); - this->SetSyntax(_("\037server\037 [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &jserver = params[0]; - const Anope::string &reason = params.size() > 1 ? params[1] : ""; - Server *server = Server::Find(jserver, true); - - if (!IRCD->IsHostValid(jserver) || jserver.find('.') == Anope::string::npos) - source.Reply(_("Please use a valid server name when juping.")); - else if (server == Me || server == Servers::GetUplink()) - source.Reply(_("You can not jupe your Services' pseudoserver or your uplink server.")); - else if (server && server->IsJuped()) - source.Reply(_("You can not jupe an already juped server.")); - else - { - Anope::string rbuf = "Juped by " + source.GetNick() + (!reason.empty() ? ": " + reason : ""); - /* Generate the new sid before quitting the old server, so they can't collide */ - Anope::string sid = IRCD->SID_Retrieve(); - if (server) - { - IRCD->SendSquit(server, rbuf); - server->Delete(rbuf); - } - Server *juped_server = new Server(Me, jserver, 1, rbuf, sid, true); - IRCD->SendServer(juped_server); - - Log(LOG_ADMIN, source, this) << "on " << jserver << " (" << rbuf << ")"; - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Tells Services to jupiter a server -- that is, to create\n" - "a fake \"server\" connected to Services which prevents\n" - "the real server of that name from connecting. The jupe\n" - "may be removed using a standard \002SQUIT\002. If a reason is\n" - "given, it is placed in the server information field;\n" - "otherwise, the server information field will contain the\n" - "text \"Juped by <nick>\", showing the nickname of the\n" - "person who jupitered the server.")); - return true; - } -}; - -class OSJupe : public Module -{ - CommandOSJupe commandosjupe; - - public: - OSJupe(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosjupe(this) - { - - } -}; - -MODULE_INIT(OSJupe) diff --git a/modules/commands/os_kick.cpp b/modules/commands/os_kick.cpp deleted file mode 100644 index 5a3584240..000000000 --- a/modules/commands/os_kick.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSKick : public Command -{ - public: - CommandOSKick(Module *creator) : Command(creator, "operserv/kick", 3, 3) - { - this->SetDesc(_("Kick a user from a channel")); - this->SetSyntax(_("\037channel\037 \037user\037 \037reason\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &chan = params[0]; - const Anope::string &nick = params[1]; - const Anope::string &s = params[2]; - Channel *c; - User *u2; - - if (!(c = Channel::Find(chan))) - { - source.Reply(CHAN_X_NOT_IN_USE, chan.c_str()); - return; - } - - if (c->bouncy_modes) - { - source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); - return; - } - - if (!(u2 = User::Find(nick, true))) - { - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - return; - } - - if (!c->Kick(source.service, u2, "%s (%s)", source.GetNick().c_str(), s.c_str())) - { - source.Reply(ACCESS_DENIED); - return; - } - - Log(LOG_ADMIN, source, this) << "on " << u2->nick << " in " << c->name << " (" << s << ")"; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows staff to kick a user from any channel.\n" - "Parameters are the same as for the standard /KICK\n" - "command. The kick message will have the nickname of the\n" - "IRCop sending the KICK command prepended; for example:\n" - " \n" - "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), source.service->nick.c_str()); - return true; - } -}; - -class OSKick : public Module -{ - CommandOSKick commandoskick; - - public: - OSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoskick(this) - { - - } -}; - -MODULE_INIT(OSKick) diff --git a/modules/commands/os_kill.cpp b/modules/commands/os_kill.cpp deleted file mode 100644 index 12fcda99e..000000000 --- a/modules/commands/os_kill.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSKill : public Command -{ - public: - CommandOSKill(Module *creator) : Command(creator, "operserv/kill", 1, 2) - { - this->SetDesc(_("Kill a user")); - this->SetSyntax(_("\037user\037 [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - Anope::string reason = params.size() > 1 ? params[1] : ""; - - User *u2 = User::Find(nick, true); - if (u2 == NULL) - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - else if (u2->IsProtected() || u2->server == Me) - source.Reply(ACCESS_DENIED); - else - { - if (reason.empty()) - reason = "No reason specified"; - if (Config->GetModule("operserv")->Get<bool>("addakiller")) - reason = "(" + source.GetNick() + ") " + reason; - Log(LOG_ADMIN, source, this) << "on " << u2->nick << " for " << reason; - u2->Kill(*source.service, reason); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to kill a user from the network.\n" - "Parameters are the same as for the standard /KILL\n" - "command.")); - return true; - } -}; - -class OSKill : public Module -{ - CommandOSKill commandoskill; - - public: - OSKill(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoskill(this) - { - - } -}; - -MODULE_INIT(OSKill) diff --git a/modules/commands/os_list.cpp b/modules/commands/os_list.cpp deleted file mode 100644 index 27e02cb0a..000000000 --- a/modules/commands/os_list.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSChanList : public Command -{ - public: - CommandOSChanList(Module *creator) : Command(creator, "operserv/chanlist", 0, 2) - { - this->SetDesc(_("Lists all channel records")); - this->SetSyntax(_("[{\037pattern\037 | \037nick\037} [\037SECRET\037]]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &pattern = !params.empty() ? params[0] : ""; - const Anope::string &opt = params.size() > 1 ? params[1] : ""; - std::set<Anope::string> modes; - User *u2; - - if (!pattern.empty()) - Log(LOG_ADMIN, source, this) << "for " << pattern; - else - Log(LOG_ADMIN, source, this); - - if (!opt.empty() && opt.equals_ci("SECRET")) - { - modes.insert("SECRET"); - modes.insert("PRIVATE"); - } - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Name")).AddColumn(_("Users")).AddColumn(_("Modes")).AddColumn(_("Topic")); - - if (!pattern.empty() && (u2 = User::Find(pattern, true))) - { - source.Reply(_("\002%s\002 channel list:"), u2->nick.c_str()); - - for (User::ChanUserList::iterator uit = u2->chans.begin(), uit_end = u2->chans.end(); uit != uit_end; ++uit) - { - ChanUserContainer *cc = uit->second; - - if (!modes.empty()) - for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it) - if (!cc->chan->HasMode(*it)) - continue; - - ListFormatter::ListEntry entry; - entry["Name"] = cc->chan->name; - entry["Users"] = stringify(cc->chan->users.size()); - entry["Modes"] = cc->chan->GetModes(true, true); - entry["Topic"] = cc->chan->topic; - list.AddEntry(entry); - } - } - else - { - source.Reply(_("Channel list:")); - - for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) - { - Channel *c = cit->second; - - if (!pattern.empty() && !Anope::Match(c->name, pattern, false, true)) - continue; - if (!modes.empty()) - for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it) - if (!c->HasMode(*it)) - continue; - - ListFormatter::ListEntry entry; - entry["Name"] = c->name; - entry["Users"] = stringify(c->users.size()); - entry["Modes"] = c->GetModes(true, true); - entry["Topic"] = c->topic; - list.AddEntry(entry); - } - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of channel list.")); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all channels currently in use on the IRC network, whether they\n" - "are registered or not.\n" - " \n" - "If \002pattern\002 is given, lists only channels that match it. If a nickname\n" - "is given, lists only the channels the user using it is on. If SECRET is\n" - "specified, lists only channels matching \002pattern\002 that have the +s or\n" - "+p mode.")); - - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), regexengine.c_str()); - } - - return true; - } -}; - -class CommandOSUserList : public Command -{ - public: - CommandOSUserList(Module *creator) : Command(creator, "operserv/userlist", 0, 2) - { - this->SetDesc(_("Lists all user records")); - this->SetSyntax(_("[{\037pattern\037 | \037channel\037} [\037INVISIBLE\037]]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &pattern = !params.empty() ? params[0] : ""; - const Anope::string &opt = params.size() > 1 ? params[1] : ""; - Channel *c; - std::set<Anope::string> modes; - - if (!pattern.empty()) - Log(LOG_ADMIN, source, this) << "for " << pattern; - else - Log(LOG_ADMIN, source, this); - - if (!opt.empty() && opt.equals_ci("INVISIBLE")) - modes.insert("INVIS"); - - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Name")).AddColumn(_("Mask")); - - if (!pattern.empty() && (c = Channel::Find(pattern))) - { - source.Reply(_("\002%s\002 users list:"), pattern.c_str()); - - for (Channel::ChanUserList::iterator cuit = c->users.begin(), cuit_end = c->users.end(); cuit != cuit_end; ++cuit) - { - ChanUserContainer *uc = cuit->second; - - if (!modes.empty()) - for (std::set<Anope::string>::iterator it = modes.begin(), it_end = modes.end(); it != it_end; ++it) - if (!uc->user->HasMode(*it)) - continue; - - ListFormatter::ListEntry entry; - entry["Name"] = uc->user->nick; - entry["Mask"] = uc->user->GetIdent() + "@" + uc->user->GetDisplayedHost(); - list.AddEntry(entry); - } - } - else - { - /* Historically this has been ordered, so... */ - Anope::map<User *> ordered_map; - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - ordered_map[it->first] = it->second; - - source.Reply(_("Users list:")); - - for (Anope::map<User *>::const_iterator it = ordered_map.begin(); it != ordered_map.end(); ++it) - { - User *u2 = it->second; - - if (!pattern.empty()) - { - Anope::string mask = u2->nick + "!" + u2->GetIdent() + "@" + u2->GetDisplayedHost(), mask2 = u2->nick + "!" + u2->GetIdent() + "@" + u2->host, mask3 = u2->nick + "!" + u2->GetIdent() + "@" + u2->ip.addr(); - if (!Anope::Match(mask, pattern) && !Anope::Match(mask2, pattern) && !Anope::Match(mask3, pattern)) - continue; - if (!modes.empty()) - for (std::set<Anope::string>::iterator mit = modes.begin(), mit_end = modes.end(); mit != mit_end; ++mit) - if (!u2->HasMode(*mit)) - continue; - } - - ListFormatter::ListEntry entry; - entry["Name"] = u2->nick; - entry["Mask"] = u2->GetIdent() + "@" + u2->GetDisplayedHost(); - list.AddEntry(entry); - } - } - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of users list.")); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists all users currently online on the IRC network, whether their\n" - "nick is registered or not.\n" - " \n" - "If \002pattern\002 is given, lists only users that match it (it must be in\n" - "the format nick!user@host). If \002channel\002 is given, lists only users\n" - "that are on the given channel. If INVISIBLE is specified, only users\n" - "with the +i flag will be listed.")); - - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your pattern in // if this is desired."), regexengine.c_str()); - } - - return true; - } -}; - -class OSList : public Module -{ - CommandOSChanList commandoschanlist; - CommandOSUserList commandosuserlist; - - public: - OSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoschanlist(this), commandosuserlist(this) - { - - } -}; - -MODULE_INIT(OSList) diff --git a/modules/commands/os_login.cpp b/modules/commands/os_login.cpp deleted file mode 100644 index b18ffc633..000000000 --- a/modules/commands/os_login.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSLogin : public Command -{ - public: - CommandOSLogin(Module *creator) : Command(creator, "operserv/login", 1, 1) - { - this->SetSyntax(_("\037password\037")); - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &password = params[0]; - - User *u = source.GetUser(); - Oper *o = source.nc->o; - if (o == NULL) - source.Reply(_("No oper block for your nick.")); - else if (o->password.empty()) - source.Reply(_("Your oper block doesn't require logging in.")); - else if (u->HasExt("os_login")) - source.Reply(_("You are already identified.")); - else if (o->password != password) - { - source.Reply(PASSWORD_INCORRECT); - u->BadPassword(); - } - else - { - Log(LOG_ADMIN, source, this) << "and successfully identified to " << source.service->nick; - u->Extend<bool>("os_login"); - source.Reply(_("Password accepted.")); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Logs you in to %s so you gain Services Operator privileges.\n" - "This command may be unnecessary if your oper block is\n" - "configured without a password."), source.service->nick.c_str()); - return true; - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - return Anope::printf(Language::Translate(source.GetAccount(), _("Login to %s")), source.service->nick.c_str()); - } -}; - -class CommandOSLogout : public Command -{ - public: - CommandOSLogout(Module *creator) : Command(creator, "operserv/logout", 0, 0) - { - this->RequireUser(true); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - User *u = source.GetUser(); - Oper *o = source.nc->o; - if (o == NULL) - source.Reply(_("No oper block for your nick.")); - else if (o->password.empty()) - source.Reply(_("Your oper block doesn't require logging in.")); - else if (!u->HasExt("os_login")) - source.Reply(_("You are not identified.")); - else - { - Log(LOG_ADMIN, source, this); - u->Shrink<bool>("os_login"); - source.Reply(_("You have been logged out.")); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Logs you out from %s so you lose Services Operator privileges.\n" - "This command is only useful if your oper block is configured\n" - "with a password."), source.service->nick.c_str()); - return true; - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - return Anope::printf(Language::Translate(source.GetAccount(), _("Logout from %s")), source.service->nick.c_str()); - } -}; - -class OSLogin : public Module -{ - CommandOSLogin commandoslogin; - CommandOSLogout commandoslogout; - ExtensibleItem<bool> os_login; - - public: - OSLogin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoslogin(this), commandoslogout(this), os_login(this, "os_login") - { - - } - - EventReturn IsServicesOper(User *u) anope_override - { - if (!u->Account()->o->password.empty()) - { - if (os_login.HasExt(u)) - return EVENT_ALLOW; - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } -}; - -MODULE_INIT(OSLogin) diff --git a/modules/commands/os_logsearch.cpp b/modules/commands/os_logsearch.cpp deleted file mode 100644 index f8ee99d4e..000000000 --- a/modules/commands/os_logsearch.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSLogSearch : public Command -{ - static inline Anope::string CreateLogName(const Anope::string &file, time_t t = Anope::CurTime) - { - char timestamp[32]; - - tm *tm = localtime(&t); - - strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm); - - return Anope::LogDir + "/" + file + "." + timestamp; - } - - public: - CommandOSLogSearch(Module *creator) : Command(creator, "operserv/logsearch", 1, 3) - { - this->SetDesc(_("Searches logs for a matching pattern")); - this->SetSyntax(_("[+\037days\037d] [+\037limit\037l] \037pattern\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - int days = 7, replies = 50; - - unsigned i; - for (i = 0; i < params.size() && params[i][0] == '+'; ++i) - { - switch (params[i][params[i].length() - 1]) - { - case 'd': - if (params[i].length() > 2) - { - Anope::string dur = params[i].substr(1, params[i].length() - 2); - try - { - days = convertTo<int>(dur); - if (days <= 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("Invalid duration %s, using %d days."), dur.c_str(), days); - } - } - break; - case 'l': - if (params[i].length() > 2) - { - Anope::string dur = params[i].substr(1, params[i].length() - 2); - try - { - replies = convertTo<int>(dur); - if (replies <= 0) - throw ConvertException(); - } - catch (const ConvertException &) - { - source.Reply(_("Invalid limit %s, using %d."), dur.c_str(), replies); - } - } - break; - default: - source.Reply(_("Unknown parameter: %s"), params[i].c_str()); - } - } - - if (i >= params.size()) - { - this->OnSyntaxError(source, ""); - return; - } - - Anope::string search_string = params[i++]; - for (; i < params.size(); ++i) - search_string += " " + params[i]; - - Log(LOG_ADMIN, source, this) << "for " << search_string; - - const Anope::string &logfile_name = Config->GetModule(this->owner)->Get<const Anope::string>("logname"); - std::list<Anope::string> matches; - for (int d = days - 1; d >= 0; --d) - { - Anope::string lf_name = CreateLogName(logfile_name, Anope::CurTime - (d * 86400)); - Log(LOG_DEBUG) << "Searching " << lf_name; - std::fstream fd(lf_name.c_str(), std::ios_base::in); - if (!fd.is_open()) - continue; - - for (Anope::string buf, token; std::getline(fd, buf.str());) - if (Anope::Match(buf, "*" + search_string + "*")) - matches.push_back(buf); - - fd.close(); - } - - unsigned found = matches.size(); - if (!found) - { - source.Reply(_("No matches for \002%s\002 found."), search_string.c_str()); - return; - } - - while (matches.size() > static_cast<unsigned>(replies)) - matches.pop_front(); - - source.Reply(_("Matches for \002%s\002:"), search_string.c_str()); - unsigned count = 0; - for (std::list<Anope::string>::iterator it = matches.begin(), it_end = matches.end(); it != it_end; ++it) - source.Reply("#%d: %s", ++count, it->c_str()); - source.Reply(_("Showed %d/%d matches for \002%s\002."), matches.size(), found, search_string.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command searches the Services logfiles for messages\n" - "that match the given pattern. The day and limit argument\n" - "may be used to specify how many days of logs to search\n" - "and the number of replies to limit to. By default this\n" - "command searches one week of logs, and limits replies\n" - "to 50.\n" - " \n" - "For example:\n" - " \002LOGSEARCH +21d +500l Anope\002\n" - " Searches the last 21 days worth of logs for messages\n" - " containing Anope and lists the most recent 500 of them.")); - return true; - } -}; - -class OSLogSearch : public Module -{ - CommandOSLogSearch commandoslogsearch; - - public: - OSLogSearch(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandoslogsearch(this) - { - } -}; - -MODULE_INIT(OSLogSearch) diff --git a/modules/commands/os_mode.cpp b/modules/commands/os_mode.cpp deleted file mode 100644 index 378f6b082..000000000 --- a/modules/commands/os_mode.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSMode : public Command -{ - public: - CommandOSMode(Module *creator) : Command(creator, "operserv/mode", 2, 3) - { - this->SetDesc(_("Change channel modes")); - this->SetSyntax(_("\037channel\037 \037modes\037")); - this->SetSyntax(_("\037channel\037 CLEAR [ALL]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &target = params[0]; - const Anope::string &modes = params[1]; - - Reference<Channel> c = Channel::Find(target); - if (!c) - source.Reply(CHAN_X_NOT_IN_USE, target.c_str()); - else if (c->bouncy_modes) - source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); - else if (modes.equals_ci("CLEAR")) - { - 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 && 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) - { - ChanUserContainer *uc = it->second; - - if (uc->user->HasMode("OPER")) - continue; - - for (size_t i = uc->status.Modes().length(); i > 0; --i) - c->RemoveMode(c->ci->WhoSends(), ModeManager::FindChannelModeByChar(uc->status.Modes()[i - 1]), uc->user->GetUID(), false); - } - - source.Reply(_("All modes cleared on %s."), c->name.c_str()); - } - else - source.Reply(_("Non-status modes cleared on %s."), c->name.c_str()); - } - else - { - spacesepstream sep(modes + (params.size() > 2 ? " " + params[2] : "")); - Anope::string mode; - int add = 1; - Anope::string log_modes, log_params; - - sep.GetToken(mode); - for (unsigned i = 0; i < mode.length() && c; ++i) - { - char ch = mode[i]; - - if (ch == '+') - { - add = 1; - log_modes += "+"; - continue; - } - else if (ch == '-') - { - add = 0; - log_modes += "-"; - continue; - } - - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - continue; - - Anope::string param, param_log; - if (cm->type != MODE_REGULAR) - { - if (cm->type == MODE_PARAM && !add && anope_dynamic_static_cast<ChannelModeParam *>(cm)->minus_no_arg) - ; - else if (!sep.GetToken(param)) - continue; - - param_log = param; - - if (cm->type == MODE_STATUS) - { - User *targ = User::Find(param, true); - if (targ == NULL || c->FindUser(targ) == NULL) - continue; - param = targ->GetUID(); - } - } - - log_modes += cm->mchar; - if (!param.empty()) - log_params += " " + param_log; - - if (add) - c->SetMode(source.service, cm, param, false); - else - c->RemoveMode(source.service, cm, param, false); - } - - if (!log_modes.replace_all_cs("+", "").replace_all_cs("-", "").empty()) - Log(LOG_ADMIN, source, this) << log_modes << log_params << " on " << (c ? c->name : target); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to change modes for any channel.\n" - "Parameters are the same as for the standard /MODE command.\n" - "Alternatively, CLEAR may be given to clear all modes on the channel.\n" - "If CLEAR ALL is given then all modes, including user status, is removed.")); - return true; - } -}; - -class CommandOSUMode : public Command -{ - public: - CommandOSUMode(Module *creator) : Command(creator, "operserv/umode", 2, 2) - { - this->SetDesc(_("Change user modes")); - this->SetSyntax(_("\037user\037 \037modes\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &target = params[0]; - const Anope::string &modes = params[1]; - - User *u2 = User::Find(target, true); - if (!u2) - source.Reply(NICK_X_NOT_IN_USE, target.c_str()); - else - { - u2->SetModes(source.service, "%s", modes.c_str()); - source.Reply(_("Changed usermodes of \002%s\002 to %s."), u2->nick.c_str(), modes.c_str()); - - u2->SendMessage(source.service, _("\002%s\002 changed your usermodes to %s."), source.GetNick().c_str(), modes.c_str()); - - Log(LOG_ADMIN, source, this) << modes << " on " << target; - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to change modes for any user.\n" - "Parameters are the same as for the standard /MODE command.")); - return true; - } -}; - -class OSMode : public Module -{ - CommandOSMode commandosmode; - CommandOSUMode commandosumode; - - public: - OSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosmode(this), commandosumode(this) - { - - } -}; - -MODULE_INIT(OSMode) diff --git a/modules/commands/os_modinfo.cpp b/modules/commands/os_modinfo.cpp deleted file mode 100644 index b1f0c7470..000000000 --- a/modules/commands/os_modinfo.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSModInfo : public Command -{ - public: - CommandOSModInfo(Module *creator) : Command(creator, "operserv/modinfo", 1, 1) - { - this->SetDesc(_("Info about a loaded module")); - this->SetSyntax(_("\037modname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &file = params[0]; - - Log(LOG_ADMIN, source, this) << "on " << file; - - Module *m = ModuleManager::FindModule(file); - if (m) - { - source.Reply(_("Module: \002%s\002 Version: \002%s\002 Author: \002%s\002 Loaded: \002%s\002"), m->name.c_str(), !m->version.empty() ? m->version.c_str() : "?", !m->author.empty() ? m->author.c_str() : "Unknown", Anope::strftime(m->created, source.GetAccount()).c_str()); - if (Anope::Debug) - source.Reply(_(" Loaded at: %p"), m->handle); - - std::vector<Anope::string> servicekeys = Service::GetServiceKeys("Command"); - for (unsigned i = 0; i < servicekeys.size(); ++i) - { - ServiceReference<Command> c("Command", servicekeys[i]); - if (!c || c->owner != m) - continue; - - source.Reply(_(" Providing service: \002%s\002"), c->name.c_str()); - - for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) - { - const BotInfo *bi = it->second; - - for (CommandInfo::map::const_iterator cit = bi->commands.begin(), cit_end = bi->commands.end(); cit != cit_end; ++cit) - { - const Anope::string &c_name = cit->first; - const CommandInfo &info = cit->second; - if (info.name != c->name) - continue; - source.Reply(_(" Command \002%s\002 on \002%s\002 is linked to \002%s\002"), c_name.c_str(), bi->nick.c_str(), c->name.c_str()); - } - } - } - } - else - source.Reply(_("No information about module \002%s\002 is available."), file.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command lists information about the specified loaded module.")); - return true; - } -}; - -class CommandOSModList : public Command -{ - public: - CommandOSModList(Module *creator) : Command(creator, "operserv/modlist", 0, 1) - { - this->SetDesc(_("List loaded modules")); - this->SetSyntax("[all|third|vendor|extra|database|encryption|pseudoclient|protocol]"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string ¶m = !params.empty() ? params[0] : ""; - - if (!param.empty()) - Log(LOG_ADMIN, source, this) << "for " << param; - else - Log(LOG_ADMIN, source, this); - - bool third = false, vendor = false, extra = false, database = false, encryption = false, pseudoclient = false, protocol = false; - - if (param.equals_ci("all")) - third = vendor = extra = database = encryption = pseudoclient = protocol = true; - else if (param.equals_ci("third")) - third = true; - else if (param.equals_ci("vendor")) - vendor = true; - else if (param.equals_ci("extra")) - extra = true; - else if (param.equals_ci("database")) - database = true; - else if (param.equals_ci("encryption")) - encryption = true; - else if (param.equals_ci("pseudoclient")) - pseudoclient = true; - else if (param.equals_ci("protocol")) - protocol = true; - else - third = extra = database = encryption = protocol = true; - - Module *protomod = ModuleManager::FindFirstOf(PROTOCOL); - - source.Reply(_("Current module list:")); - - int count = 0; - for (std::list<Module *>::iterator it = ModuleManager::Modules.begin(), it_end = ModuleManager::Modules.end(); it != it_end; ++it) - { - Module *m = *it; - - bool show = false; - Anope::string mtype; - - if (m->type & PROTOCOL) - { - show |= protocol; - if (!mtype.empty()) - mtype += ", "; - mtype += "Protocol"; - } - if (m->type & PSEUDOCLIENT) - { - show |= pseudoclient; - if (!mtype.empty()) - mtype += ", "; - mtype += "Pseudoclient"; - } - if (m->type & ENCRYPTION) - { - show |= encryption; - if (!mtype.empty()) - mtype += ", "; - mtype += "Encryption"; - } - if (m->type & DATABASE) - { - show |= database; - if (!mtype.empty()) - mtype += ", "; - mtype += "Database"; - } - if (m->type & EXTRA) - { - show |= extra; - if (!mtype.empty()) - mtype += ", "; - mtype += "Extra"; - } - if (m->type & VENDOR) - { - show |= vendor; - if (!mtype.empty()) - mtype += ", "; - mtype += "Vendor"; - } - if (m->type & THIRD) - { - show |= third; - if (!mtype.empty()) - mtype += ", "; - mtype += "Third"; - } - - if (!show) - continue; - else if (m->type & PROTOCOL && param.empty() && m != protomod) - continue; - - ++count; - - source.Reply(_("Module: \002%s\002 [%s] [%s]"), m->name.c_str(), m->version.c_str(), mtype.c_str()); - } - - if (!count) - source.Reply(_("No modules currently loaded matching that criteria.")); - else - source.Reply(_("%d modules loaded."), count); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Lists currently loaded modules.")); - return true; - } -}; - -class OSModInfo : public Module -{ - CommandOSModInfo commandosmodinfo; - CommandOSModList commandosmodlist; - - public: - OSModInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosmodinfo(this), commandosmodlist(this) - { - - } -}; - -MODULE_INIT(OSModInfo) diff --git a/modules/commands/os_module.cpp b/modules/commands/os_module.cpp deleted file mode 100644 index f271ed2c9..000000000 --- a/modules/commands/os_module.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSModLoad : public Command -{ - public: - CommandOSModLoad(Module *creator) : Command(creator, "operserv/modload", 1, 1) - { - this->SetDesc(_("Load a module")); - this->SetSyntax(_("\037modname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &mname = params[0]; - - ModuleReturn status = ModuleManager::LoadModule(mname, source.GetUser()); - if (status == MOD_ERR_OK) - { - Log(LOG_ADMIN, source, this) << "to load module " << mname; - source.Reply(_("Module \002%s\002 loaded."), mname.c_str()); - } - else if (status == MOD_ERR_EXISTS) - source.Reply(_("Module \002%s\002 is already loaded."), mname.c_str()); - else - source.Reply(_("Unable to load module \002%s\002."), mname.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command loads the module named \037modname\037 from the modules\n" - "directory.")); - return true; - } -}; - -class CommandOSModReLoad : public Command -{ - public: - CommandOSModReLoad(Module *creator) : Command(creator, "operserv/modreload", 1, 1) - { - this->SetDesc(_("Reload a module")); - this->SetSyntax(_("\037modname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &mname = params[0]; - - Module *m = ModuleManager::FindModule(mname); - if (!m) - { - source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); - return; - } - - if (!m->handle || m->GetPermanent()) - { - source.Reply(_("Unable to remove module \002%s\002."), m->name.c_str()); - return; - } - - Module *protocol = ModuleManager::FindFirstOf(PROTOCOL); - if (m->type == PROTOCOL && m != protocol) - { - source.Reply(_("You can not reload this module directly, instead reload %s."), protocol ? protocol->name.c_str() : "(unknown)"); - return; - } - - /* Unrecoverable */ - bool fatal = m->type == PROTOCOL; - ModuleReturn status = ModuleManager::UnloadModule(m, source.GetUser()); - - if (status != MOD_ERR_OK) - { - source.Reply(_("Unable to remove module \002%s\002."), mname.c_str()); - return; - } - - status = ModuleManager::LoadModule(mname, source.GetUser()); - if (status == MOD_ERR_OK) - { - Log(LOG_ADMIN, source, this) << "to reload module " << mname; - source.Reply(_("Module \002%s\002 reloaded."), mname.c_str()); - } - else - { - if (fatal) - { - Anope::QuitReason = "Unable to reload module " + mname; - Anope::Quitting = true; - } - else - source.Reply(_("Unable to load module \002%s\002."), mname.c_str()); - } - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command reloads the module named \037modname\037.")); - return true; - } -}; - -class CommandOSModUnLoad : public Command -{ - public: - CommandOSModUnLoad(Module *creator) : Command(creator, "operserv/modunload", 1, 1) - { - this->SetDesc(_("Un-Load a module")); - this->SetSyntax(_("\037modname\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &mname = params[0]; - - Module *m = ModuleManager::FindModule(mname); - if (!m) - { - source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str()); - return; - } - - if (!m->handle || m->GetPermanent() || m->type == PROTOCOL) - { - source.Reply(_("Unable to remove module \002%s\002."), m->name.c_str()); - return; - } - - Log(this->owner) << "Trying to unload module [" << mname << "]"; - - ModuleReturn status = ModuleManager::UnloadModule(m, source.GetUser()); - - if (status == MOD_ERR_OK) - { - Log(LOG_ADMIN, source, this) << "to unload module " << mname; - source.Reply(_("Module \002%s\002 unloaded."), mname.c_str()); - } - else - source.Reply(_("Unable to remove module \002%s\002."), mname.c_str()); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("This command unloads the module named \037modname\037.")); - return true; - } -}; - -class OSModule : public Module -{ - CommandOSModLoad commandosmodload; - CommandOSModReLoad commandosmodreload; - CommandOSModUnLoad commandosmodunload; - - public: - OSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosmodload(this), commandosmodreload(this), commandosmodunload(this) - { - this->SetPermanent(true); - - } -}; - -MODULE_INIT(OSModule) diff --git a/modules/commands/os_news.cpp b/modules/commands/os_news.cpp deleted file mode 100644 index a35a74584..000000000 --- a/modules/commands/os_news.cpp +++ /dev/null @@ -1,464 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_news.h" - -/* List of messages for each news type. This simplifies message sending. */ - -enum -{ - MSG_SYNTAX, - MSG_LIST_HEADER, - MSG_LIST_NONE, - MSG_ADDED, - MSG_DEL_NOT_FOUND, - MSG_DELETED, - MSG_DEL_NONE, - MSG_DELETED_ALL -}; - -struct NewsMessages msgarray[] = { - {NEWS_LOGON, "LOGON", - {_("LOGONNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), - _("Logon news items:"), - _("There is no logon news."), - _("Added new logon news item."), - _("Logon news item #%s not found!"), - _("Logon news item #%d deleted."), - _("No logon news items to delete!"), - _("All logon news items deleted.")} - }, - {NEWS_OPER, "OPER", - {_("OPERNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), - _("Oper news items:"), - _("There is no oper news."), - _("Added new oper news item."), - _("Oper news item #%s not found!"), - _("Oper news item #%d deleted."), - _("No oper news items to delete!"), - _("All oper news items deleted.")} - }, - {NEWS_RANDOM, "RANDOM", - {_("RANDOMNEWS {ADD|DEL|LIST} [\037text\037|\037num\037]\002"), - _("Random news items:"), - _("There is no random news."), - _("Added new random news item."), - _("Random news item #%s not found!"), - _("Random news item #%d deleted."), - _("No random news items to delete!"), - _("All random news items deleted.")} - } -}; - -struct MyNewsItem : NewsItem -{ - void Serialize(Serialize::Data &data) const anope_override - { - data["type"] << this->type; - data["text"] << this->text; - data["who"] << this->who; - data["time"] << this->time; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - if (!news_service) - return NULL; - - NewsItem *ni; - if (obj) - ni = anope_dynamic_static_cast<NewsItem *>(obj); - else - ni = new MyNewsItem(); - - unsigned int t; - data["type"] >> t; - ni->type = static_cast<NewsType>(t); - data["text"] >> ni->text; - data["who"] >> ni->who; - data["time"] >> ni->time; - - if (!obj) - news_service->AddNewsItem(ni); - return ni; - } -}; - -class MyNewsService : public NewsService -{ - std::vector<NewsItem *> newsItems[3]; - public: - MyNewsService(Module *m) : NewsService(m) { } - - ~MyNewsService() - { - for (unsigned i = 0; i < 3; ++i) - for (unsigned j = 0; j < newsItems[i].size(); ++j) - delete newsItems[i][j]; - } - - NewsItem *CreateNewsItem() anope_override - { - return new MyNewsItem(); - } - - void AddNewsItem(NewsItem *n) - { - this->newsItems[n->type].push_back(n); - } - - void DelNewsItem(NewsItem *n) - { - std::vector<NewsItem *> &list = this->GetNewsList(n->type); - std::vector<NewsItem *>::iterator it = std::find(list.begin(), list.end(), n); - if (it != list.end()) - list.erase(it); - delete n; - } - - std::vector<NewsItem *> &GetNewsList(NewsType t) - { - return this->newsItems[t]; - } -}; - -#define lenof(a) (sizeof(a) / sizeof(*(a))) -static const char **findmsgs(NewsType type) -{ - for (unsigned i = 0; i < lenof(msgarray); ++i) - if (msgarray[i].type == type) - return msgarray[i].msgs; - return NULL; -} - -class NewsBase : public Command -{ - ServiceReference<NewsService> ns; - - protected: - void DoList(CommandSource &source, NewsType ntype, const char **msgs) - { - std::vector<NewsItem *> &list = this->ns->GetNewsList(ntype); - if (list.empty()) - source.Reply(msgs[MSG_LIST_NONE]); - else - { - ListFormatter lflist(source.GetAccount()); - lflist.AddColumn(_("Number")).AddColumn(_("Creator")).AddColumn(_("Created")).AddColumn(_("Text")); - - for (unsigned i = 0, end = list.size(); i < end; ++i) - { - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Creator"] = list[i]->who; - entry["Created"] = Anope::strftime(list[i]->time, NULL, true); - entry["Text"] = list[i]->text; - lflist.AddEntry(entry); - } - - source.Reply(msgs[MSG_LIST_HEADER]); - - std::vector<Anope::string> replies; - lflist.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - - source.Reply(_("End of news list.")); - } - - return; - } - - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType ntype, const char **msgs) - { - const Anope::string text = params.size() > 1 ? params[1] : ""; - - if (text.empty()) - this->OnSyntaxError(source, "ADD"); - else - { - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - NewsItem *news = new MyNewsItem(); - news->type = ntype; - news->text = text; - news->time = Anope::CurTime; - news->who = source.GetNick(); - - this->ns->AddNewsItem(news); - - source.Reply(msgs[MSG_ADDED]); - Log(LOG_ADMIN, source, this) << "to add a news item"; - } - - return; - } - - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType ntype, const char **msgs) - { - const Anope::string &text = params.size() > 1 ? params[1] : ""; - - if (text.empty()) - this->OnSyntaxError(source, "DEL"); - else - { - std::vector<NewsItem *> &list = this->ns->GetNewsList(ntype); - if (list.empty()) - source.Reply(msgs[MSG_LIST_NONE]); - else - { - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - if (!text.equals_ci("ALL")) - { - try - { - unsigned num = convertTo<unsigned>(text); - if (num > 0 && num <= list.size()) - { - this->ns->DelNewsItem(list[num - 1]); - source.Reply(msgs[MSG_DELETED], num); - Log(LOG_ADMIN, source, this) << "to delete a news item"; - return; - } - } - catch (const ConvertException &) { } - - source.Reply(msgs[MSG_DEL_NOT_FOUND], text.c_str()); - } - else - { - for (unsigned i = list.size(); i > 0; --i) - this->ns->DelNewsItem(list[i - 1]); - source.Reply(msgs[MSG_DELETED_ALL]); - Log(LOG_ADMIN, source, this) << "to delete all news items"; - } - } - } - - return; - } - - void DoNews(CommandSource &source, const std::vector<Anope::string> ¶ms, NewsType ntype) - { - if (!this->ns) - return; - - const Anope::string &cmd = params[0]; - - const char **msgs = findmsgs(ntype); - if (!msgs) - throw CoreException("news: Invalid type to do_news()"); - - if (cmd.equals_ci("LIST")) - return this->DoList(source, ntype, msgs); - else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params, ntype, msgs); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params, ntype, msgs); - else - this->OnSyntaxError(source, ""); - - return; - } - public: - NewsBase(Module *creator, const Anope::string &newstype) : Command(creator, newstype, 1, 2), ns("NewsService", "news") - { - this->SetSyntax(_("ADD \037text\037")); - this->SetSyntax(_("DEL {\037num\037 | ALL}")); - this->SetSyntax("LIST"); - } - - virtual ~NewsBase() - { - } - - virtual void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; - - virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; -}; - -class CommandOSLogonNews : public NewsBase -{ - public: - CommandOSLogonNews(Module *creator) : NewsBase(creator, "operserv/logonnews") - { - this->SetDesc(_("Define messages to be shown to users at logon")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoNews(source, params, NEWS_LOGON); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Edits or displays the list of logon news messages. When a\n" - "user connects to the network, these messages will be sent\n" - "to them. However, no more than \002%d\002 messages will be\n" - "sent in order to avoid flooding the user. If there are\n" - "more news messages, only the most recent will be sent."), - Config->GetModule(this->owner)->Get<unsigned>("newscount", "3")); - return true; - } -}; - -class CommandOSOperNews : public NewsBase -{ - public: - CommandOSOperNews(Module *creator) : NewsBase(creator, "operserv/opernews") - { - this->SetDesc(_("Define messages to be shown to users who oper")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoNews(source, params, NEWS_OPER); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Edits or displays the list of oper news messages. When a\n" - "user opers up (with the /OPER command), these messages will\n" - "be sent to them. However, no more than \002%d\002 messages will\n" - "be sent in order to avoid flooding the user. If there are\n" - "more news messages, only the most recent will be sent."), - Config->GetModule(this->owner)->Get<unsigned>("newscount", "3")); - return true; - } -}; - -class CommandOSRandomNews : public NewsBase -{ - public: - CommandOSRandomNews(Module *creator) : NewsBase(creator, "operserv/randomnews") - { - this->SetDesc(_("Define messages to be randomly shown to users at logon")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - return this->DoNews(source, params, NEWS_RANDOM); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Edits or displays the list of random news messages. When a\n" - "user connects to the network, one (and only one) of the\n" - "random news will be randomly chosen and sent to them.")); - return true; - } -}; - -static unsigned cur_rand_news = 0; - -class OSNews : public Module -{ - MyNewsService newsservice; - Serialize::Type newsitem_type; - - CommandOSLogonNews commandoslogonnews; - CommandOSOperNews commandosopernews; - CommandOSRandomNews commandosrandomnews; - - Anope::string oper_announcer, announcer; - unsigned news_count; - - void DisplayNews(User *u, NewsType Type) - { - std::vector<NewsItem *> &newsList = this->newsservice.GetNewsList(Type); - if (newsList.empty()) - return; - - BotInfo *bi = NULL; - if (Type == NEWS_OPER) - bi = BotInfo::Find(Config->GetModule(this)->Get<const Anope::string>("oper_announcer", "OperServ"), true); - else - bi = BotInfo::Find(Config->GetModule(this)->Get<const Anope::string>("announcer", "Global"), true); - if (bi == NULL) - return; - - Anope::string msg; - if (Type == NEWS_LOGON) - msg = _("[\002Logon News\002 - %s] %s"); - else if (Type == NEWS_OPER) - msg = _("[\002Oper News\002 - %s] %s"); - else if (Type == NEWS_RANDOM) - msg = _("[\002Random News\002 - %s] %s"); - - int start = 0; - - if (Type != NEWS_RANDOM) - { - start = newsList.size() - news_count; - if (start < 0) - start = 0; - } - - for (unsigned i = start, end = newsList.size(); i < end; ++i) - { - if (Type == NEWS_RANDOM && i != cur_rand_news) - continue; - - u->SendMessage(bi, msg.c_str(), Anope::strftime(newsList[i]->time, u->Account(), true).c_str(), newsList[i]->text.c_str()); - - if (Type == NEWS_RANDOM) - { - ++cur_rand_news; - break; - } - } - - /* Reset to head of list to get first random news value */ - if (Type == NEWS_RANDOM && cur_rand_news >= newsList.size()) - cur_rand_news = 0; - } - - public: - OSNews(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - newsservice(this), newsitem_type("NewsItem", MyNewsItem::Unserialize), - commandoslogonnews(this), commandosopernews(this), commandosrandomnews(this) - { - } - - void OnReload(Configuration::Conf *conf) anope_override - { - oper_announcer = conf->GetModule(this)->Get<const Anope::string>("oper_announcer", "OperServ"); - announcer = conf->GetModule(this)->Get<const Anope::string>("announcer", "Global"); - news_count = conf->GetModule(this)->Get<unsigned>("newscount", "3"); - } - - void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) anope_override - { - if (mname == "OPER") - DisplayNews(u, NEWS_OPER); - } - - void OnUserConnect(User *user, bool &) anope_override - { - if (user->Quitting() || !user->server->IsSynced()) - return; - - DisplayNews(user, NEWS_LOGON); - DisplayNews(user, NEWS_RANDOM); - } -}; - -MODULE_INIT(OSNews) diff --git a/modules/commands/os_noop.cpp b/modules/commands/os_noop.cpp deleted file mode 100644 index c0beb678a..000000000 --- a/modules/commands/os_noop.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSNOOP : public Command -{ - public: - CommandOSNOOP(Module *creator) : Command(creator, "operserv/noop", 2, 2) - { - this->SetDesc(_("Remove all operators from a server remotely")); - this->SetSyntax(_("SET \037server\037")); - this->SetSyntax(_("REVOKE \037server\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - const Anope::string &server = params[1]; - - Server *s = Server::Find(server, true); - if (s == NULL) - source.Reply(_("Server %s does not exist."), server.c_str()); - else if (s == Me || s->IsJuped()) - source.Reply(_("You can not NOOP Services.")); - else if (cmd.equals_ci("SET")) - { - /* Remove the O:lines */ - IRCD->SendSVSNOOP(s, true); - s->Extend<Anope::string>("noop", source.GetNick()); - - Log(LOG_ADMIN, source, this) << "SET on " << s->GetName(); - source.Reply(_("All operators from \002%s\002 have been removed."), s->GetName().c_str()); - - Anope::string reason = "NOOP command used by " + source.GetNick(); - /* Kill all the IRCops of the server */ - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u2 = it->second; - - if (u2->server == s && u2->HasMode("OPER")) - u2->Kill(*source.service, reason); - } - } - else if (cmd.equals_ci("REVOKE")) - { - s->Shrink<Anope::string>("noop"); - IRCD->SendSVSNOOP(s, false); - Log(LOG_ADMIN, source, this) << "REVOKE on " << s->GetName(); - source.Reply(_("All O:lines of \002%s\002 have been reset."), s->GetName().c_str()); - } - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("\002SET\002 kills all operators from the given\n" - "\002server\002 and prevents operators from opering\n" - "up on the given server. \002REVOKE\002 removes this\n" - "restriction.")); - return true; - } -}; - -class OSNOOP : public Module -{ - CommandOSNOOP commandosnoop; - PrimitiveExtensibleItem<Anope::string> noop; - - public: - OSNOOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosnoop(this), noop(this, "noop") - { - - } - - void OnUserModeSet(const MessageSource &, User *u, const Anope::string &mname) anope_override - { - Anope::string *setter; - if (mname == "OPER" && (setter = noop.Get(u->server))) - { - Anope::string reason = "NOOP command used by " + *setter; - BotInfo *OperServ = Config->GetClient("OperServ"); - u->Kill(OperServ, reason); - } - } -}; - -MODULE_INIT(OSNOOP) diff --git a/modules/commands/os_oline.cpp b/modules/commands/os_oline.cpp deleted file mode 100644 index 5270d3f78..000000000 --- a/modules/commands/os_oline.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSOLine : public Command -{ - public: - CommandOSOLine(Module *creator) : Command(creator, "operserv/oline", 2, 2) - { - this->SetDesc(_("Give Operflags to a certain user")); - this->SetSyntax(_("\037nick\037 \037flags\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - const Anope::string &flag = params[1]; - User *u2 = NULL; - - /* let's check whether the user is online */ - if (!(u2 = User::Find(nick, true))) - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - else if (u2 && flag[0] == '+') - { - IRCD->SendSVSO(source.service, nick, flag); - u2->SetMode(source.service, "OPER"); - u2->SendMessage(source.service, _("You are now an IRC Operator.")); - source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); - Log(LOG_ADMIN, source, this) << "for " << nick; - } - else if (u2 && flag[0] == '-') - { - IRCD->SendSVSO(source.service, nick, flag); - source.Reply(_("Operflags \002%s\002 have been removed from \002%s\002."), flag.c_str(), nick.c_str()); - Log(LOG_ADMIN, source, this) << "for " << nick; - } - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to give Operflags to any user.\n" - "Flags have to be prefixed with a \"+\" or a \"-\". To\n" - "remove all flags simply type a \"-\" instead of any flags.")); - return true; - } -}; - -class OSOLine : public Module -{ - CommandOSOLine commandosoline; - - public: - OSOLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosoline(this) - { - - if (!IRCD || !IRCD->CanSVSO) - throw ModuleException("Your IRCd does not support OMODE."); - - } -}; - -MODULE_INIT(OSOLine) diff --git a/modules/commands/os_oper.cpp b/modules/commands/os_oper.cpp deleted file mode 100644 index f5ac80160..000000000 --- a/modules/commands/os_oper.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -struct MyOper : Oper, Serializable -{ - MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { } - - void Serialize(Serialize::Data &data) const anope_override - { - data["name"] << this->name; - data["type"] << this->ot->GetName(); - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - Anope::string stype, sname; - - data["type"] >> stype; - data["name"] >> sname; - - OperType *ot = OperType::Find(stype); - if (ot == NULL) - return NULL; - NickCore *nc = NickCore::Find(sname); - if (nc == NULL) - return NULL; - - MyOper *myo; - if (obj) - myo = anope_dynamic_static_cast<MyOper *>(obj); - else - myo = new MyOper(nc->display, ot); - nc->o = myo; - Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName(); - return myo; - } -}; - -class CommandOSOper : public Command -{ - bool HasPrivs(CommandSource &source, OperType *ot) const - { - std::list<Anope::string> commands = ot->GetCommands(), privs = ot->GetPrivs(); - - for (std::list<Anope::string>::iterator it = commands.begin(); it != commands.end(); ++it) - if (!source.HasCommand(*it)) - return false; - - for (std::list<Anope::string>::iterator it = privs.begin(); it != privs.end(); ++it) - if (!source.HasPriv(*it)) - return false; - - return true; - } - - public: - CommandOSOper(Module *creator) : Command(creator, "operserv/oper", 1, 3) - { - this->SetDesc(_("View and change Services Operators")); - this->SetSyntax(_("ADD \037oper\037 \037type\037")); - this->SetSyntax(_("DEL \037oper\037")); - this->SetSyntax(_("INFO [\037type\037]")); - this->SetSyntax("LIST"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &subcommand = params[0]; - - if (subcommand.equals_ci("ADD") && params.size() > 2) - { - const Anope::string &oper = params[1]; - const Anope::string &otype = params[2]; - - if (!source.HasPriv("operserv/oper/modify")) - { - source.Reply(ACCESS_DENIED); - return; - } - - const NickAlias *na = NickAlias::Find(oper); - if (na == NULL) - source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); - else if (na->nc->o) - source.Reply(_("Nick \002%s\002 is already an operator."), na->nick.c_str()); - else - { - OperType *ot = OperType::Find(otype); - if (ot == NULL) - { - source.Reply(_("Oper type \002%s\002 has not been configured."), otype.c_str()); - return; - } - - if (!HasPrivs(source, ot)) - { - source.Reply(ACCESS_DENIED); - return; - } - - na->nc->o = new MyOper(na->nc->display, ot); - na->nc->o->require_oper = true; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "ADD " << na->nick << " as type " << ot->GetName(); - source.Reply("%s (%s) added to the \002%s\002 list.", na->nick.c_str(), na->nc->display.c_str(), ot->GetName().c_str()); - } - } - else if (subcommand.equals_ci("DEL") && params.size() > 1) - { - const Anope::string &oper = params[1]; - - if (!source.HasPriv("operserv/oper/modify")) - { - source.Reply(ACCESS_DENIED); - return; - } - - const NickAlias *na = NickAlias::Find(oper); - if (na == NULL) - source.Reply(NICK_X_NOT_REGISTERED, oper.c_str()); - else if (!na->nc || !na->nc->o) - source.Reply(_("Nick \002%s\002 is not a Services Operator."), oper.c_str()); - else if (!HasPrivs(source, na->nc->o->ot)) - source.Reply(ACCESS_DENIED); - else if (std::find(Config->Opers.begin(), Config->Opers.end(), na->nc->o) != Config->Opers.end()) - source.Reply(_("Oper \002%s\002 is configured in the configuration file(s) and can not be removed by this command."), na->nc->display.c_str()); - else - { - delete na->nc->o; - na->nc->o = NULL; - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - Log(LOG_ADMIN, source, this) << "DEL " << na->nick; - source.Reply(_("Oper privileges removed from %s (%s)."), na->nick.c_str(), na->nc->display.c_str()); - } - } - else if (subcommand.equals_ci("LIST")) - { - source.Reply(_("Name Type")); - for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it) - { - const NickCore *nc = it->second; - - if (!nc->o) - continue; - - source.Reply(_("%-8s %s"), nc->o->name.c_str(), nc->o->ot->GetName().c_str()); - if (std::find(Config->Opers.begin(), Config->Opers.end(), nc->o) != Config->Opers.end()) - source.Reply(_(" This oper is configured in the configuration file.")); - for (std::list<User *>::const_iterator uit = nc->users.begin(); uit != nc->users.end(); ++uit) - { - User *u = *uit; - source.Reply(_(" %s is online using this oper block."), u->nick.c_str()); - } - } - } - else if (subcommand.equals_ci("INFO")) - { - if (params.size() < 2) - { - source.Reply(_("Available opertypes:")); - for (unsigned i = 0; i < Config->MyOperTypes.size(); ++i) - { - OperType *ot = Config->MyOperTypes[i]; - source.Reply("%s", ot->GetName().c_str()); - } - return; - } - - Anope::string fulltype = params[1]; - if (params.size() > 2) - fulltype += " " + params[2]; - OperType *ot = OperType::Find(fulltype); - if (ot == NULL) - source.Reply(_("Oper type \002%s\002 has not been configured."), fulltype.c_str()); - else - { - if (ot->GetCommands().empty()) - source.Reply(_("Opertype \002%s\002 has no allowed commands."), ot->GetName().c_str()); - else - { - source.Reply(_("Available commands for \002%s\002:"), ot->GetName().c_str()); - Anope::string buf; - std::list<Anope::string> cmds = ot->GetCommands(); - for (std::list<Anope::string>::const_iterator it = cmds.begin(), it_end = cmds.end(); it != it_end; ++it) - { - buf += *it + " "; - if (buf.length() > 400) - { - source.Reply("%s", buf.c_str()); - buf.clear(); - } - } - if (!buf.empty()) - { - source.Reply("%s", buf.c_str()); - buf.clear(); - } - } - if (ot->GetPrivs().empty()) - source.Reply(_("Opertype \002%s\002 has no allowed privileges."), ot->GetName().c_str()); - else - { - source.Reply(_("Available privileges for \002%s\002:"), ot->GetName().c_str()); - Anope::string buf; - std::list<Anope::string> privs = ot->GetPrivs(); - for (std::list<Anope::string>::const_iterator it = privs.begin(), it_end = privs.end(); it != it_end; ++it) - { - buf += *it + " "; - if (buf.length() > 400) - { - source.Reply("%s", buf.c_str()); - buf.clear(); - } - } - if (!buf.empty()) - { - source.Reply("%s", buf.c_str()); - buf.clear(); - } - } - if (!ot->modes.empty()) - source.Reply(_("Opertype \002%s\002 receives modes \002%s\002 once identified."), ot->GetName().c_str(), ot->modes.c_str()); - } - } - else - this->OnSyntaxError(source, subcommand); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows you to change and view Services Operators.\n" - "Note that operators removed by this command but are still set in\n" - "the configuration file are not permanently affected by this.")); - return true; - } -}; - -class OSOper : public Module -{ - Serialize::Type myoper_type; - CommandOSOper commandosoper; - - public: - OSOper(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - myoper_type("Oper", MyOper::Unserialize), commandosoper(this) - { - } - - ~OSOper() - { - for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it) - { - NickCore *nc = it->second; - - if (nc->o && dynamic_cast<MyOper *>(nc->o)) - { - delete nc->o; - nc->o = NULL; - } - } - } - - void OnDelCore(NickCore *nc) anope_override - { - if (nc->o && dynamic_cast<MyOper *>(nc->o)) - { - delete nc->o; - nc->o = NULL; - } - } -}; - -MODULE_INIT(OSOper) diff --git a/modules/commands/os_reload.cpp b/modules/commands/os_reload.cpp deleted file mode 100644 index 1ab3c3c87..000000000 --- a/modules/commands/os_reload.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSReload : public Command -{ - public: - CommandOSReload(Module *creator) : Command(creator, "operserv/reload", 0, 0) - { - this->SetDesc(_("Reload services' configuration file")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - try - { - Log(LOG_ADMIN, source, this); - - Configuration::Conf *new_config = new Configuration::Conf(); - Configuration::Conf *old = Config; - Config = new_config; - Config->Post(old); - delete old; - - source.Reply(_("Services' configuration has been reloaded.")); - } - catch (const ConfigException &ex) - { - Log(this->owner) << "Error reloading configuration file: " << ex.GetReason(); - source.Reply(_("Error reloading configuration file: %s"), ex.GetReason().c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Causes Services to reload the configuration file. Note that\n" - "some directives still need the restart of the Services to\n" - "take effect (such as Services' nicknames, activation of the\n" - "session limitation, etc.).")); - return true; - } -}; - -class OSReload : public Module -{ - CommandOSReload commandosreload; - - public: - OSReload(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosreload(this) - { - - } -}; - -MODULE_INIT(OSReload) diff --git a/modules/commands/os_session.cpp b/modules/commands/os_session.cpp deleted file mode 100644 index e8f1e241a..000000000 --- a/modules/commands/os_session.cpp +++ /dev/null @@ -1,737 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_session.h" - -namespace -{ - /* The default session limit */ - unsigned session_limit; - /* How many times to kill before adding an AKILL */ - unsigned max_session_kill; - /* How long session akills should last */ - time_t session_autokill_expiry; - /* Reason to use for session kills */ - Anope::string sle_reason; - /* Optional second reason */ - Anope::string sle_detailsloc; - - /* Max limit that can be used for exceptions */ - unsigned max_exception_limit; - /* How long before exceptions expire by default */ - time_t exception_expiry; - - /* Number of bits to use when comparing session IPs */ - unsigned ipv4_cidr; - unsigned ipv6_cidr; -} - -class MySessionService : public SessionService -{ - SessionMap Sessions; - Serialize::Checker<ExceptionVector> Exceptions; - public: - MySessionService(Module *m) : SessionService(m), Exceptions("Exception") { } - - Exception *CreateException() anope_override - { - return new Exception(); - } - - void AddException(Exception *e) anope_override - { - this->Exceptions->push_back(e); - } - - void DelException(Exception *e) anope_override - { - ExceptionVector::iterator it = std::find(this->Exceptions->begin(), this->Exceptions->end(), e); - if (it != this->Exceptions->end()) - this->Exceptions->erase(it); - } - - Exception *FindException(User *u) anope_override - { - for (std::vector<Exception *>::const_iterator it = this->Exceptions->begin(), it_end = this->Exceptions->end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(u->host, e->mask) || Anope::Match(u->ip.addr(), e->mask)) - return e; - - if (cidr(e->mask).match(u->ip)) - return e; - } - return NULL; - } - - Exception *FindException(const Anope::string &host) anope_override - { - for (std::vector<Exception *>::const_iterator it = this->Exceptions->begin(), it_end = this->Exceptions->end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(host, e->mask)) - return e; - - if (cidr(e->mask).match(sockaddrs(host))) - return e; - } - - return NULL; - } - - ExceptionVector &GetExceptions() anope_override - { - return this->Exceptions; - } - - void DelSession(Session *s) - { - this->Sessions.erase(s->addr); - } - - Session *FindSession(const Anope::string &ip) anope_override - { - cidr c(ip, ip.find(':') != Anope::string::npos ? ipv6_cidr : ipv4_cidr); - if (!c.valid()) - return NULL; - SessionMap::iterator it = this->Sessions.find(c); - if (it != this->Sessions.end()) - return it->second; - return NULL; - } - - SessionMap::iterator FindSessionIterator(const sockaddrs &ip) - { - cidr c(ip, ip.ipv6() ? ipv6_cidr : ipv4_cidr); - if (!c.valid()) - return this->Sessions.end(); - return this->Sessions.find(c); - } - - Session* &FindOrCreateSession(const cidr &ip) - { - return this->Sessions[ip]; - } - - SessionMap &GetSessions() anope_override - { - return this->Sessions; - } -}; - -class ExceptionDelCallback : public NumberList -{ - protected: - CommandSource &source; - unsigned deleted; - Command *cmd; - public: - ExceptionDelCallback(CommandSource &_source, const Anope::string &numlist, Command *c) : NumberList(numlist, true), source(_source), deleted(0), cmd(c) - { - } - - ~ExceptionDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on session-limit exception list.")); - else if (deleted == 1) - source.Reply(_("Deleted 1 entry from session-limit exception list.")); - else - source.Reply(_("Deleted %d entries from session-limit exception list."), deleted); - } - - virtual void HandleNumber(unsigned number) anope_override - { - if (!number || number > session_service->GetExceptions().size()) - return; - - Log(LOG_ADMIN, source, cmd) << "to remove the session limit exception for " << session_service->GetExceptions()[number - 1]->mask; - - ++deleted; - DoDel(source, number - 1); - } - - static void DoDel(CommandSource &source, unsigned index) - { - Exception *e = session_service->GetExceptions()[index]; - FOREACH_MOD(OnExceptionDel, (source, e)); - - session_service->DelException(e); - delete e; - } -}; - -class CommandOSSession : public Command -{ - private: - void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - Anope::string param = params[1]; - - unsigned mincount = 0; - try - { - mincount = convertTo<unsigned>(param); - } - catch (const ConvertException &) { } - - if (mincount <= 1) - source.Reply(_("Invalid threshold value. It must be a valid integer greater than 1.")); - else - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Session")).AddColumn(_("Host")); - - for (SessionService::SessionMap::iterator it = session_service->GetSessions().begin(), it_end = session_service->GetSessions().end(); it != it_end; ++it) - { - Session *session = it->second; - - if (session->count >= mincount) - { - ListFormatter::ListEntry entry; - entry["Session"] = stringify(session->count); - entry["Host"] = session->addr.mask(); - list.AddEntry(entry); - } - } - - source.Reply(_("Hosts with at least \002%d\002 sessions:"), mincount); - - std::vector<Anope::string> replies; - list.Process(replies); - - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - - return; - } - - void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - Anope::string param = params[1]; - Session *session = session_service->FindSession(param); - - Exception *exception = session_service->FindException(param); - Anope::string entry = "no entry"; - unsigned limit = session_limit; - if (exception) - { - if (!exception->limit) - limit = 0; - else if (exception->limit > limit) - limit = exception->limit; - entry = exception->mask; - } - - if (!session) - source.Reply(_("\002%s\002 not found on session list, but has a limit of \002%d\002 because it matches entry: \002%s\002."), param.c_str(), limit, entry.c_str()); - else - source.Reply(_("The host \002%s\002 currently has \002%d\002 sessions with a limit of \002%d\002 because it matches entry: \002%s\002."), session->addr.mask().c_str(), session->count, limit, entry.c_str()); - } - public: - CommandOSSession(Module *creator) : Command(creator, "operserv/session", 2, 2) - { - this->SetDesc(_("View the list of host sessions")); - this->SetSyntax(_("LIST \037threshold\037")); - this->SetSyntax(_("VIEW \037host\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - Log(LOG_ADMIN, source, this) << cmd << " " << params[1]; - - if (!session_limit) - source.Reply(_("Session limiting is disabled.")); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->DoView(source, params); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to view the session list.\n" - " \n" - "\002SESSION LIST\002 lists hosts with at least \037threshold\037 sessions.\n" - "The threshold must be a number greater than 1. This is to\n" - "prevent accidental listing of the large number of single\n" - "session hosts.\n" - " \n" - "\002SESSION VIEW\002 displays detailed information about a specific\n" - "host - including the current session count and session limit.\n" - "The \037host\037 value may not include wildcards.\n" - " \n" - "See the \002EXCEPTION\002 help for more information about session\n" - "limiting and how to set session limits specific to certain\n" - "hosts and groups thereof.")); - return true; - } -}; - -class CommandOSException : public Command -{ - private: - void DoAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - Anope::string mask, expiry, limitstr; - unsigned last_param = 3; - - mask = params.size() > 1 ? params[1] : ""; - if (!mask.empty() && mask[0] == '+') - { - expiry = mask; - mask = params.size() > 2 ? params[2] : ""; - last_param = 4; - } - - limitstr = params.size() > last_param - 1 ? params[last_param - 1] : ""; - - if (params.size() <= last_param) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - Anope::string reason = params[last_param]; - if (last_param == 3 && params.size() > 4) - reason += " " + params[4]; - if (reason.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : exception_expiry; - if (expires < 0) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expires > 0) - expires += Anope::CurTime; - - unsigned limit = -1; - try - { - limit = convertTo<unsigned>(limitstr); - } - catch (const ConvertException &) { } - - if (limit > max_exception_limit) - { - source.Reply(_("Invalid session limit. It must be a valid integer greater than or equal to zero and less than \002%d\002."), max_exception_limit); - return; - } - else - { - if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) - { - source.Reply(_("Invalid hostmask. Only real hostmasks are valid, as exceptions are not matched against nicks or usernames.")); - return; - } - - for (std::vector<Exception *>::iterator it = session_service->GetExceptions().begin(), it_end = session_service->GetExceptions().end(); it != it_end; ++it) - { - Exception *e = *it; - if (e->mask.equals_ci(mask)) - { - if (e->limit != limit) - { - e->limit = limit; - source.Reply(_("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); - } - else - source.Reply(_("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); - return; - } - } - - Exception *exception = new Exception(); - exception->mask = mask; - exception->limit = limit; - exception->reason = reason; - exception->time = Anope::CurTime; - exception->who = source.GetNick(); - exception->expires = expires; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnExceptionAdd, MOD_RESULT, (exception)); - if (MOD_RESULT == EVENT_STOP) - delete exception; - else - { - Log(LOG_ADMIN, source, this) << "to set the session limit for " << mask << " to " << limit; - session_service->AddException(exception); - source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit); - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - } - - return; - } - - void DoDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - ExceptionDelCallback list(source, mask, this); - list.Process(); - } - else - { - unsigned i = 0, end = session_service->GetExceptions().size(); - for (; i < end; ++i) - if (mask.equals_ci(session_service->GetExceptions()[i]->mask)) - { - Log(LOG_ADMIN, source, this) << "to remove the session limit exception for " << mask; - ExceptionDelCallback::DoDel(source, i); - source.Reply(_("\002%s\002 deleted from session-limit exception list."), mask.c_str()); - break; - } - if (i == end) - source.Reply(_("\002%s\002 not found on session-limit exception list."), mask.c_str()); - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - return; - } - - void ProcessList(CommandSource &source, const std::vector<Anope::string> ¶ms, ListFormatter &list) - { - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (session_service->GetExceptions().empty()) - { - source.Reply(_("The session exception list is empty.")); - return; - } - - if (!mask.empty() && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class ExceptionListCallback : public NumberList - { - CommandSource &source; - ListFormatter &list; - public: - ExceptionListCallback(CommandSource &_source, ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), source(_source), list(_list) - { - } - - void HandleNumber(unsigned Number) anope_override - { - if (!Number || Number > session_service->GetExceptions().size()) - return; - - Exception *e = session_service->GetExceptions()[Number - 1]; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(Number); - entry["Mask"] = e->mask; - entry["By"] = e->who; - entry["Created"] = Anope::strftime(e->time, NULL, true); - entry["Expires"] = Anope::Expires(e->expires, source.GetAccount()); - entry["Limit"] = stringify(e->limit); - entry["Reason"] = e->reason; - this->list.AddEntry(entry); - } - } - nl_list(source, list, mask); - nl_list.Process(); - } - else - { - for (unsigned i = 0, end = session_service->GetExceptions().size(); i < end; ++i) - { - Exception *e = session_service->GetExceptions()[i]; - if (mask.empty() || Anope::Match(e->mask, mask)) - { - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Mask"] = e->mask; - entry["By"] = e->who; - entry["Created"] = Anope::strftime(e->time, NULL, true); - entry["Expires"] = Anope::Expires(e->expires, source.GetAccount()); - entry["Limit"] = stringify(e->limit); - entry["Reason"] = e->reason; - list.AddEntry(entry); - } - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on session-limit exception list.")); - else - { - source.Reply(_("Current Session Limit Exception list:")); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - void DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Limit")).AddColumn(_("Mask")); - - this->ProcessList(source, params, list); - } - - void DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Created")).AddColumn(_("Expires")).AddColumn(_("Limit")).AddColumn(_("Reason")); - - this->ProcessList(source, params, list); - } - - public: - CommandOSException(Module *creator) : Command(creator, "operserv/exception", 1, 5) - { - this->SetDesc(_("Modify the session-limit exception list")); - this->SetSyntax(_("ADD [\037+expiry\037] \037mask\037 \037limit\037 \037reason\037")); - this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037}")); - this->SetSyntax(_("LIST [\037mask\037 | \037list\037]")); - this->SetSyntax(_("VIEW [\037mask\037 | \037list\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - if (!session_limit) - source.Reply(_("Session limiting is disabled.")); - else if (cmd.equals_ci("ADD")) - return this->DoAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->DoDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->DoList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->DoView(source, params); - else - this->OnSyntaxError(source, ""); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to manipulate the list of hosts that\n" - "have specific session limits - allowing certain machines,\n" - "such as shell servers, to carry more than the default number\n" - "of clients at a time. Once a host reaches its session limit,\n" - "all clients attempting to connect from that host will be\n" - "killed. Before the user is killed, they are notified, of a\n" - "source of help regarding session limiting. The content of\n" - "this notice is a config setting.")); - source.Reply(" "); - source.Reply(_("\002EXCEPTION ADD\002 adds the given host mask to the exception list.\n" - "Note that \002nick!user@host\002 and \002user@host\002 masks are invalid!\n" - "Only real host masks, such as \002box.host.dom\002 and \002*.host.dom\002,\n" - "are allowed because sessions limiting does not take nick or\n" - "user names into account. \037limit\037 must be a number greater than\n" - "or equal to zero. This determines how many sessions this host\n" - "may carry at a time. A value of zero means the host has an\n" - "unlimited session limit. See the \002AKILL\002 help for details about\n" - "the format of the optional \037expiry\037 parameter.\n" - " \n" - "\002EXCEPTION DEL\002 removes the given mask from the exception list.\n" - " \n" - "\002EXCEPTION LIST\002 and \002EXCEPTION VIEW\002 show all current\n" - "sessions if the optional mask is given, the list is limited\n" - "to those sessions matching the mask. The difference is that\n" - "\002EXCEPTION VIEW\002 is more verbose, displaying the name of the\n" - "person who added the exception, its session limit, reason,\n" - "host mask and the expiry date and time.\n" - " \n" - "Note that a connecting client will \"use\" the first exception\n" - "their host matches.")); - return true; - } -}; - -class OSSession : public Module -{ - Serialize::Type exception_type; - MySessionService ss; - CommandOSSession commandossession; - CommandOSException commandosexception; - ServiceReference<XLineManager> akills; - - public: - OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - exception_type("Exception", Exception::Unserialize), ss(this), commandossession(this), commandosexception(this), akills("XLineManager", "xlinemanager/sgline") - { - this->SetPermanent(true); - } - - void Prioritize() anope_override - { - ModuleManager::SetPriority(this, PRIORITY_FIRST); - } - - void OnReload(Configuration::Conf *conf) anope_override - { - Configuration::Block *block = Config->GetModule(this); - - session_limit = block->Get<int>("defaultsessionlimit"); - max_session_kill = block->Get<int>("maxsessionkill"); - session_autokill_expiry = block->Get<time_t>("sessionautokillexpiry"); - sle_reason = block->Get<const Anope::string>("sessionlimitexceeded"); - sle_detailsloc = block->Get<const Anope::string>("sessionlimitdetailsloc"); - - max_exception_limit = block->Get<int>("maxsessionlimit"); - exception_expiry = block->Get<time_t>("exceptionexpiry"); - - ipv4_cidr = block->Get<unsigned>("session_ipv4_cidr", "32"); - ipv6_cidr = block->Get<unsigned>("session_ipv6_cidr", "128"); - - if (ipv4_cidr > 32 || ipv6_cidr > 128) - throw ConfigException(this->name + ": session CIDR value out of range"); - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (u->Quitting() || !session_limit || exempt || !u->server || u->server->IsULined()) - return; - - cidr u_ip(u->ip, u->ip.ipv6() ? ipv6_cidr : ipv4_cidr); - if (!u_ip.valid()) - return; - - Session* &session = this->ss.FindOrCreateSession(u_ip); - - if (session) - { - bool kill = false; - if (session->count >= session_limit) - { - kill = true; - Exception *exception = this->ss.FindException(u); - if (exception) - { - kill = false; - if (exception->limit && session->count >= exception->limit) - kill = true; - } - } - - /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was - * decremented in do_quit, which caused problems and fixed here - * - * Now, we create the user struture before calling this to fix some user tracking issues, - * so we must increment this here no matter what because it will either be - * decremented when the user is killed or quits - Adam - */ - ++session->count; - - if (kill && !exempt) - { - BotInfo *OperServ = Config->GetClient("OperServ"); - if (OperServ) - { - if (!sle_reason.empty()) - { - Anope::string message = sle_reason.replace_all_cs("%IP%", u->ip.addr()); - u->SendMessage(OperServ, message); - } - if (!sle_detailsloc.empty()) - u->SendMessage(OperServ, sle_detailsloc); - } - - ++session->hits; - - const Anope::string &akillmask = "*@" + session->addr.mask(); - if (max_session_kill && session->hits >= max_session_kill && akills && !akills->HasEntry(akillmask)) - { - XLine *x = new XLine(akillmask, OperServ ? OperServ->nick : "", Anope::CurTime + session_autokill_expiry, "Session limit exceeded", XLineManager::GenerateUID()); - akills->AddXLine(x); - akills->Send(NULL, x); - Log(OperServ, "akill/session") << "Added a temporary AKILL for \002" << akillmask << "\002 due to excessive connections"; - } - else - { - u->Kill(OperServ, "Session limit exceeded"); - } - } - } - else - { - session = new Session(u->ip, u->ip.ipv6() ? ipv6_cidr : ipv4_cidr); - } - } - - void OnUserQuit(User *u, const Anope::string &msg) anope_override - { - if (!session_limit || !u->server || u->server->IsULined()) - return; - - SessionService::SessionMap &sessions = this->ss.GetSessions(); - SessionService::SessionMap::iterator sit = this->ss.FindSessionIterator(u->ip); - - if (sit == sessions.end()) - return; - - Session *session = sit->second; - - if (session->count > 1) - { - --session->count; - return; - } - - delete session; - sessions.erase(sit); - } - - void OnExpireTick() anope_override - { - if (Anope::NoExpire) - return; - for (unsigned i = this->ss.GetExceptions().size(); i > 0; --i) - { - Exception *e = this->ss.GetExceptions()[i - 1]; - - if (!e->expires || e->expires > Anope::CurTime) - continue; - BotInfo *OperServ = Config->GetClient("OperServ"); - Log(OperServ, "expire/exception") << "Session exception for " << e->mask << " has expired."; - this->ss.DelException(e); - delete e; - } - } -}; - -MODULE_INIT(OSSession) diff --git a/modules/commands/os_set.cpp b/modules/commands/os_set.cpp deleted file mode 100644 index 5aca2f370..000000000 --- a/modules/commands/os_set.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSSet : public Command -{ - private: - void DoList(CommandSource &source) - { - Log(LOG_ADMIN, source, this) << "LIST"; - - Anope::string index; - - index = Anope::ReadOnly ? _("%s is enabled") : _("%s is disabled"); - source.Reply(index.c_str(), "READONLY"); - index = Anope::Debug ? _("%s is enabled") : _("%s is disabled"); - source.Reply(index.c_str(), "DEBUG"); - index = Anope::NoExpire ? _("%s is enabled") : _("%s is disabled"); - source.Reply(index.c_str(), "NOEXPIRE"); - - return; - } - - void DoSetReadOnly(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &setting = params.size() > 1 ? params[1] : ""; - - if (setting.empty()) - { - this->OnSyntaxError(source, "READONLY"); - return; - } - - if (setting.equals_ci("ON")) - { - Anope::ReadOnly = true; - Log(LOG_ADMIN, source, this) << "READONLY ON"; - source.Reply(_("Services are now in \002read-only\002 mode.")); - } - else if (setting.equals_ci("OFF")) - { - Anope::ReadOnly = false; - Log(LOG_ADMIN, source, this) << "READONLY OFF"; - source.Reply(_("Services are now in \002read-write\002 mode.")); - } - else - source.Reply(_("Setting for READONLY must be \002ON\002 or \002OFF\002.")); - - return; - } - - void DoSetSuperAdmin(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &setting = params.size() > 1 ? params[1] : ""; - - if (!source.GetUser()) - return; - - if (setting.empty()) - { - this->OnSyntaxError(source, "SUPERADMIN"); - return; - } - - /** - * Allow the user to turn super admin on/off - * - * Rob - **/ - bool super_admin = Config->GetModule(this->owner)->Get<bool>("superadmin"); - if (!super_admin) - source.Reply(_("Super admin can not be set because it is not enabled in the configuration.")); - else if (setting.equals_ci("ON")) - { - source.GetUser()->super_admin = true; - source.Reply(_("You are now a super admin.")); - Log(LOG_ADMIN, source, this) << "SUPERADMIN ON"; - } - else if (setting.equals_ci("OFF")) - { - source.GetUser()->super_admin = false; - source.Reply(_("You are no longer a super admin.")); - Log(LOG_ADMIN, source, this) << "SUPERADMIN OFF"; - } - else - source.Reply(_("Setting for super admin must be \002ON\002 or \002OFF\002.")); - - return; - } - - void DoSetDebug(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &setting = params.size() > 1 ? params[1] : ""; - - if (setting.empty()) - { - this->OnSyntaxError(source, "DEBUG"); - return; - } - - if (setting.equals_ci("ON")) - { - Anope::Debug = 1; - Log(LOG_ADMIN, source, this) << "DEBUG ON"; - source.Reply(_("Services are now in \002debug\002 mode.")); - } - else if (setting.equals_ci("OFF") || setting == "0") - { - Log(LOG_ADMIN, source, this) << "DEBUG OFF"; - Anope::Debug = 0; - source.Reply(_("Services are now in \002non-debug\002 mode.")); - } - else - { - try - { - Anope::Debug = convertTo<int>(setting); - Log(LOG_ADMIN, source, this) << "DEBUG " << Anope::Debug; - source.Reply(_("Services are now in \002debug\002 mode (level %d)."), Anope::Debug); - return; - } - catch (const ConvertException &) { } - - source.Reply(_("Setting for DEBUG must be \002ON\002, \002OFF\002, or a positive number.")); - } - - return; - } - - void DoSetNoExpire(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - const Anope::string &setting = params.size() > 1 ? params[1] : ""; - - if (setting.empty()) - { - this->OnSyntaxError(source, "NOEXPIRE"); - return; - } - - if (setting.equals_ci("ON")) - { - Anope::NoExpire = true; - Log(LOG_ADMIN, source, this) << "NOEXPIRE ON"; - source.Reply(_("Services are now in \002no expire\002 mode.")); - } - else if (setting.equals_ci("OFF")) - { - Anope::NoExpire = false; - Log(LOG_ADMIN, source, this) << "NOEXPIRE OFF"; - source.Reply(_("Services are now in \002expire\002 mode.")); - } - else - source.Reply(_("Setting for NOEXPIRE must be \002ON\002 or \002OFF\002.")); - - return; - } - public: - CommandOSSet(Module *creator) : Command(creator, "operserv/set", 1, 2) - { - this->SetDesc(_("Set various global Services options")); - this->SetSyntax(_("\037option\037 \037setting\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &option = params[0]; - - if (option.equals_ci("LIST")) - return this->DoList(source); - else if (option.equals_ci("READONLY")) - return this->DoSetReadOnly(source, params); - else if (option.equals_ci("DEBUG")) - return this->DoSetDebug(source, params); - else if (option.equals_ci("NOEXPIRE")) - return this->DoSetNoExpire(source, params); - else if (option.equals_ci("SUPERADMIN")) - return this->DoSetSuperAdmin(source, params); - else - this->OnSyntaxError(source, ""); - - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - if (subcommand.empty()) - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Sets various global Services options. Option names\n" - "currently defined are:\n" - " READONLY Set read-only or read-write mode\n" - " DEBUG Activate or deactivate debug mode\n" - " NOEXPIRE Activate or deactivate no expire mode\n" - " SUPERADMIN Activate or deactivate super admin mode\n" - " LIST List the options")); - } - else if (subcommand.equals_ci("LIST")) - source.Reply(_("Syntax: \002LIST\002\n" - " \n" - "Display the various %s settings."), source.service->nick.c_str()); - else if (subcommand.equals_ci("READONLY")) - source.Reply(_("Syntax: \002READONLY {ON | OFF}\002\n" - " \n" - "Sets read-only mode on or off. In read-only mode, normal\n" - "users will not be allowed to modify any Services data,\n" - "including channel and nickname access lists, etc. IRCops\n" - "with sufficient Services privileges will be able to modify\n" - "Services' AKILL, SQLINE, SNLINE and ignore lists, drop,\n" - "suspend or forbid nicknames and channels, and manage news,\n" - "oper info and DNS, but any such changes will not be saved\n" - "unless read-only mode is deactivated before Services are\n" - "terminated or restarted.\n" - " \n" - "This option is equivalent to the command-line option\n" - "\002--readonly\002.")); - else if (subcommand.equals_ci("DEBUG")) - source.Reply(_("Syntax: \002DEBUG {ON | OFF}\002\n" - " \n" - "Sets debug mode on or off.\n" - " \n" - "This option is equivalent to the command-line option\n" - "\002--debug\002.")); - else if (subcommand.equals_ci("NOEXPIRE")) - source.Reply(_("Syntax: \002NOEXPIRE {ON | OFF}\002\n" - " \n" - "Sets no expire mode on or off. In no expire mode, nicks,\n" - "channels, akills and exceptions won't expire until the\n" - "option is unset.\n" - " \n" - "This option is equivalent to the command-line option\n" - "\002--noexpire\002.")); - else if (subcommand.equals_ci("SUPERADMIN")) - source.Reply(_("Syntax: \002SUPERADMIN {ON | OFF}\002\n" - " \n" - "Setting this will grant you extra privileges such as the\n" - "ability to be \"founder\" on all channel's etc...\n" - " \n" - "This option is \002not\002 persistent, and should only be used when\n" - "needed, and set back to OFF when no longer needed.")); - else - return false; - return true; - } -}; - -class OSSet : public Module -{ - CommandOSSet commandosset; - - public: - OSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosset(this) - { - } -}; - -MODULE_INIT(OSSet) diff --git a/modules/commands/os_shutdown.cpp b/modules/commands/os_shutdown.cpp deleted file mode 100644 index 1142edbc0..000000000 --- a/modules/commands/os_shutdown.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSQuit : public Command -{ - public: - CommandOSQuit(Module *creator) : Command(creator, "operserv/quit", 0, 0) - { - this->SetDesc(_("Terminate Services WITHOUT saving")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Log(LOG_ADMIN, source, this); - Anope::QuitReason = source.command + " command received from " + source.GetNick(); - Anope::Quitting = true; - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Causes Services to do an immediate shutdown; databases are\n" - "\002not\002 saved. This command should not be used unless\n" - "damage to the in-memory copies of the databases is feared\n" - "and they should not be saved.")); - return true; - } -}; - -class CommandOSRestart : public Command -{ - public: - CommandOSRestart(Module *creator) : Command(creator, "operserv/restart", 0, 0) - { - this->SetDesc(_("Save databases and restart Services")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Log(LOG_ADMIN, source, this); - Anope::QuitReason = source.command + " command received from " + source.GetNick(); - Anope::Quitting = Anope::Restarting = true; - Anope::SaveDatabases(); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(_("Causes Services to save all databases and then restart\n" - "(i.e. exit and immediately re-run the executable).")); - return true; - } -}; - -class CommandOSShutdown : public Command -{ - public: - CommandOSShutdown(Module *creator) : Command(creator, "operserv/shutdown", 0, 0) - { - this->SetDesc(_("Terminate services with save")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Log(LOG_ADMIN, source, this); - Anope::QuitReason = source.command + " command received from " + source.GetNick(); - Anope::Quitting = true; - Anope::SaveDatabases(); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Causes Services to save all databases and then shut down.")); - return true; - } -}; - -class OSShutdown : public Module -{ - CommandOSQuit commandosquit; - CommandOSRestart commandosrestart; - CommandOSShutdown commandosshutdown; - - public: - OSShutdown(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosquit(this), commandosrestart(this), commandosshutdown(this) - { - - } -}; - -MODULE_INIT(OSShutdown) diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp deleted file mode 100644 index 306100cea..000000000 --- a/modules/commands/os_stats.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" -#include "modules/os_session.h" - -struct Stats : Serializable -{ - static Stats *me; - - Stats() : Serializable("Stats") - { - me = this; - } - - void Serialize(Serialize::Data &data) const anope_override - { - data["maxusercnt"] << MaxUserCount; - data["maxusertime"] << MaxUserTime; - } - - static Serializable* Unserialize(Serializable *obj, Serialize::Data &data) - { - data["maxusercnt"] >> MaxUserCount; - data["maxusertime"] >> MaxUserTime; - return me; - } -}; - -Stats *Stats::me; - -/** - * Count servers connected to server s - * @param s The server to start counting from - * @return Amount of servers connected to server s - **/ -static int stats_count_servers(Server *s) -{ - if (!s) - return 0; - - int count = 1; - - if (!s->GetLinks().empty()) - for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) - count += stats_count_servers(s->GetLinks()[i]); - - return count; -} - -class CommandOSStats : public Command -{ - ServiceReference<XLineManager> akills, snlines, sqlines; - private: - void DoStatsAkill(CommandSource &source) - { - int timeout; - if (akills) - { - /* AKILLs */ - source.Reply(_("Current number of AKILLs: \002%d\002"), akills->GetCount()); - timeout = Config->GetModule("operserv")->Get<time_t>("autokillexpiry", "30d") + 59; - if (timeout >= 172800) - source.Reply(_("Default AKILL expiry time: \002%d days\002"), timeout / 86400); - else if (timeout >= 86400) - source.Reply(_("Default AKILL expiry time: \0021 day\002")); - else if (timeout >= 7200) - source.Reply(_("Default AKILL expiry time: \002%d hours\002"), timeout / 3600); - else if (timeout >= 3600) - source.Reply(_("Default AKILL expiry time: \0021 hour\002")); - else if (timeout >= 120) - source.Reply(_("Default AKILL expiry time: \002%d minutes\002"), timeout / 60); - else if (timeout >= 60) - source.Reply(_("Default AKILL expiry time: \0021 minute\002")); - else - source.Reply(_("Default AKILL expiry time: \002No expiration\002")); - } - if (snlines) - { - /* SNLINEs */ - source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount()); - timeout = Config->GetModule("operserv")->Get<time_t>("snlineexpiry", "30d") + 59; - if (timeout >= 172800) - source.Reply(_("Default SNLINE expiry time: \002%d days\002"), timeout / 86400); - else if (timeout >= 86400) - source.Reply(_("Default SNLINE expiry time: \0021 day\002")); - else if (timeout >= 7200) - source.Reply(_("Default SNLINE expiry time: \002%d hours\002"), timeout / 3600); - else if (timeout >= 3600) - source.Reply(_("Default SNLINE expiry time: \0021 hour\002")); - else if (timeout >= 120) - source.Reply(_("Default SNLINE expiry time: \002%d minutes\002"), timeout / 60); - else if (timeout >= 60) - source.Reply(_("Default SNLINE expiry time: \0021 minute\002")); - else - source.Reply(_("Default SNLINE expiry time: \002No expiration\002")); - } - if (sqlines) - { - /* SQLINEs */ - source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount()); - timeout = Config->GetModule("operserv")->Get<time_t>("sglineexpiry", "30d") + 59; - if (timeout >= 172800) - source.Reply(_("Default SQLINE expiry time: \002%d days\002"), timeout / 86400); - else if (timeout >= 86400) - source.Reply(_("Default SQLINE expiry time: \0021 day\002")); - else if (timeout >= 7200) - source.Reply(_("Default SQLINE expiry time: \002%d hours\002"), timeout / 3600); - else if (timeout >= 3600) - source.Reply(_("Default SQLINE expiry time: \0021 hour\002")); - else if (timeout >= 120) - source.Reply(_("Default SQLINE expiry time: \002%d minutes\002"), timeout / 60); - else if (timeout >= 60) - source.Reply(_("Default SQLINE expiry time: \0021 minute\002")); - else - source.Reply(_("Default SQLINE expiry time: \002No expiration\002")); - } - } - - void DoStatsReset(CommandSource &source) - { - MaxUserCount = UserListByNick.size(); - source.Reply(_("Statistics reset.")); - return; - } - - void DoStatsUptime(CommandSource &source) - { - time_t uptime = Anope::CurTime - Anope::StartTime; - source.Reply(_("Current users: \002%d\002 (\002%d\002 ops)"), UserListByNick.size(), OperCount); - source.Reply(_("Maximum users: \002%d\002 (%s)"), MaxUserCount, Anope::strftime(MaxUserTime, source.GetAccount()).c_str()); - source.Reply(_("Services up %s."), Anope::Duration(uptime, source.GetAccount()).c_str()); - - return; - } - - void DoStatsUplink(CommandSource &source) - { - Anope::string buf; - for (std::set<Anope::string>::iterator it = Servers::Capab.begin(); it != Servers::Capab.end(); ++it) - buf += " " + *it; - if (!buf.empty()) - buf.erase(buf.begin()); - - source.Reply(_("Uplink server: %s"), Me->GetLinks().front()->GetName().c_str()); - source.Reply(_("Uplink capab: %s"), buf.c_str()); - source.Reply(_("Servers found: %d"), stats_count_servers(Me->GetLinks().front())); - return; - } - - template<typename T> void GetHashStats(const T& map, size_t& entries, size_t& buckets, size_t& max_chain) - { - entries = map.size(), buckets = map.bucket_count(), max_chain = 0; - for (size_t i = 0; i < buckets; ++i) - if (map.bucket_size(i) > max_chain) - max_chain = map.bucket_size(i); - } - - void DoStatsHash(CommandSource &source) - { - size_t entries, buckets, max_chain; - - GetHashStats(UserListByNick, entries, buckets, max_chain); - source.Reply(_("Users (nick): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - - if (!UserListByUID.empty()) - { - GetHashStats(UserListByUID, entries, buckets, max_chain); - source.Reply(_("Users (uid): %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - } - - GetHashStats(ChannelList, entries, buckets, max_chain); - source.Reply(_("Channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - - GetHashStats(*RegisteredChannelList, entries, buckets, max_chain); - source.Reply(_("Registered channels: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - - GetHashStats(*NickAliasList, entries, buckets, max_chain); - source.Reply(_("Registered nicknames: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - - GetHashStats(*NickCoreList, entries, buckets, max_chain); - source.Reply(_("Registered nick groups: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - - if (session_service) - { - GetHashStats(session_service->GetSessions(), entries, buckets, max_chain); - source.Reply(_("Sessions: %lu entries, %lu buckets, longest chain is %d"), entries, buckets, max_chain); - } - } - - public: - CommandOSStats(Module *creator) : Command(creator, "operserv/stats", 0, 1), - akills("XLineManager", "xlinemanager/sgline"), snlines("XLineManager", "xlinemanager/snline"), sqlines("XLineManager", "xlinemanager/sqline") - { - this->SetDesc(_("Show status of Services and network")); - this->SetSyntax("[AKILL | HASH | UPLINK | UPTIME | ALL | RESET]"); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Anope::string extra = !params.empty() ? params[0] : ""; - - Log(LOG_ADMIN, source, this) << extra; - - if (extra.equals_ci("RESET")) - return this->DoStatsReset(source); - - if (extra.equals_ci("ALL") || extra.equals_ci("AKILL")) - this->DoStatsAkill(source); - - if (extra.equals_ci("ALL") || extra.equals_ci("HASH")) - this->DoStatsHash(source); - - if (extra.equals_ci("ALL") || extra.equals_ci("UPLINK")) - this->DoStatsUplink(source); - - if (extra.empty() || extra.equals_ci("ALL") || extra.equals_ci("UPTIME")) - this->DoStatsUptime(source); - - if (!extra.empty() && !extra.equals_ci("ALL") && !extra.equals_ci("AKILL") && !extra.equals_ci("HASH") && !extra.equals_ci("UPLINK") && !extra.equals_ci("UPTIME")) - source.Reply(_("Unknown STATS option: \002%s\002"), extra.c_str()); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Without any option, shows the current number of users online,\n" - "and the highest number of users online since Services was\n" - "started, and the length of time Services has been running.\n" - " \n" - "With the \002AKILL\002 option, displays the current size of the\n" - "AKILL list and the current default expiry time.\n" - " \n" - "The \002RESET\002 option currently resets the maximum user count\n" - "to the number of users currently present on the network.\n" - " \n" - "The \002UPLINK\002 option displays information about the current\n" - "server Anope uses as an uplink to the network.\n" - " \n" - "The \002HASH\002 option displays information about the hash maps.\n" - " \n" - "The \002ALL\002 option displays all of the above statistics.")); - return true; - } -}; - -class OSStats : public Module -{ - CommandOSStats commandosstats; - Serialize::Type stats_type; - Stats stats_saver; - - public: - OSStats(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosstats(this), stats_type("Stats", Stats::Unserialize) - { - - } - - void OnUserConnect(User *u, bool &exempt) anope_override - { - if (UserListByNick.size() == MaxUserCount && Anope::CurTime == MaxUserTime) - stats_saver.QueueUpdate(); - } -}; - -MODULE_INIT(OSStats) diff --git a/modules/commands/os_svs.cpp b/modules/commands/os_svs.cpp deleted file mode 100644 index 769adb338..000000000 --- a/modules/commands/os_svs.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSSVSNick : public Command -{ - public: - CommandOSSVSNick(Module *creator) : Command(creator, "operserv/svsnick", 2, 2) - { - this->SetDesc(_("Forcefully change a user's nickname")); - this->SetSyntax(_("\037nick\037 \037newnick\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &nick = params[0]; - Anope::string newnick = params[1]; - User *u2; - - if (!IRCD->CanSVSNick) - { - source.Reply(_("Your IRCd does not support SVSNICK.")); - return; - } - - /* Truncate long nicknames to nicklen characters */ - unsigned nicklen = Config->GetBlock("networkinfo")->Get<unsigned>("nicklen"); - if (newnick.length() > nicklen) - { - source.Reply(_("Nick \002%s\002 was truncated to %d characters."), newnick.c_str(), nicklen, newnick.c_str()); - newnick = params[1].substr(0, nicklen); - } - - /* Check for valid characters */ - if (!IRCD->IsNickValid(newnick)) - { - source.Reply(_("Nick \002%s\002 is an illegal nickname and cannot be used."), newnick.c_str()); - return; - } - - /* Check for a nick in use or a forbidden/suspended nick */ - if (!(u2 = User::Find(nick, true))) - source.Reply(NICK_X_NOT_IN_USE, nick.c_str()); - else if (!nick.equals_ci(newnick) && User::Find(newnick)) - source.Reply(_("Nick \002%s\002 is currently in use."), newnick.c_str()); - else - { - source.Reply(_("The nick \002%s\002 is now being changed to \002%s\002."), nick.c_str(), newnick.c_str()); - Log(LOG_ADMIN, source, this) << "to change " << nick << " to " << newnick; - IRCD->SendForceNickChange(u2, newnick, Anope::CurTime); - } - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Forcefully changes a user's nickname from \037nick\037 to \037newnick\037.")); - return true; - } -}; - -class CommandOSSVSJoin : public Command -{ - public: - CommandOSSVSJoin(Module *creator) : Command(creator, "operserv/svsjoin", 2, 2) - { - this->SetDesc(_("Forcefully join a user to a channel")); - this->SetSyntax(_("\037nick\037 \037channel\037")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!IRCD->CanSVSJoin) - { - source.Reply(_("Your IRCd does not support SVSJOIN.")); - return; - } - - User *target = User::Find(params[0], true); - Channel *c = Channel::Find(params[1]); - if (target == NULL) - source.Reply(NICK_X_NOT_IN_USE, params[0].c_str()); - else if (source.GetUser() != target && (target->IsProtected() || target->server == Me)) - source.Reply(ACCESS_DENIED); - else if (!IRCD->IsChannelValid(params[1])) - source.Reply(CHAN_X_INVALID, params[1].c_str()); - else if (c && c->FindUser(target)) - source.Reply(_("\002%s\002 is already in \002%s\002."), target->nick.c_str(), c->name.c_str()); - else - { - IRCD->SendSVSJoin(*source.service, target, params[1], ""); - Log(LOG_ADMIN, source, this) << "to force " << target->nick << " to join " << params[1]; - source.Reply(_("\002%s\002 has been joined to \002%s\002."), target->nick.c_str(), params[1].c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Forcefully join a user to a channel.")); - return true; - } -}; - -class CommandOSSVSPart : public Command -{ - public: - CommandOSSVSPart(Module *creator) : Command(creator, "operserv/svspart", 2, 3) - { - this->SetDesc(_("Forcefully part a user from a channel")); - this->SetSyntax(_("\037nick\037 \037channel\037 [\037reason\037]")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!IRCD->CanSVSJoin) - { - source.Reply(_("Your IRCd does not support SVSPART.")); - return; - } - - User *target = User::Find(params[0], true); - Channel *c = Channel::Find(params[1]); - const Anope::string &reason = params.size() > 2 ? params[2] : ""; - if (target == NULL) - source.Reply(NICK_X_NOT_IN_USE, params[0].c_str()); - else if (source.GetUser() != target && (target->IsProtected() || target->server == Me)) - source.Reply(ACCESS_DENIED); - else if (!c) - source.Reply(CHAN_X_NOT_IN_USE, params[1].c_str()); - else if (!c->FindUser(target)) - source.Reply(_("\002%s\002 is not in \002%s\002."), target->nick.c_str(), c->name.c_str()); - else - { - IRCD->SendSVSPart(*source.service, target, params[1], reason); - if (!reason.empty()) - Log(LOG_ADMIN, source, this) << "to force " << target->nick << " to part " << c->name << " with reason " << reason; - else - Log(LOG_ADMIN, source, this) << "to force " << target->nick << " to part " << c->name; - source.Reply(_("\002%s\002 has been parted from \002%s\002."), target->nick.c_str(), c->name.c_str()); - } - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Forcefully part a user from a channel.")); - return true; - } -}; - -class OSSVS : public Module -{ - CommandOSSVSNick commandossvsnick; - CommandOSSVSJoin commandossvsjoin; - CommandOSSVSPart commandossvspart; - - public: - OSSVS(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandossvsnick(this), commandossvsjoin(this), commandossvspart(this) - { - } -}; - -MODULE_INIT(OSSVS) diff --git a/modules/commands/os_sxline.cpp b/modules/commands/os_sxline.cpp deleted file mode 100644 index 0de21ce02..000000000 --- a/modules/commands/os_sxline.cpp +++ /dev/null @@ -1,732 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class SXLineDelCallback : public NumberList -{ - XLineManager *xlm; - Command *command; - CommandSource &source; - unsigned deleted; - public: - SXLineDelCallback(XLineManager *x, Command *c, CommandSource &_source, const Anope::string &numlist) : NumberList(numlist, true), xlm(x), command(c), source(_source), deleted(0) - { - } - - ~SXLineDelCallback() - { - if (!deleted) - source.Reply(_("No matching entries on the %s list."), source.command.c_str()); - else if (deleted == 1) - source.Reply(_("Deleted 1 entry from the %s list."), source.command.c_str()); - else - source.Reply(_("Deleted %d entries from the %s list."), deleted, source.command.c_str()); - } - - void HandleNumber(unsigned number) anope_override - { - if (!number) - return; - - XLine *x = this->xlm->GetEntry(number - 1); - - if (!x) - return; - - Log(LOG_ADMIN, source, command) << "to remove " << x->mask << " from the list"; - - ++deleted; - DoDel(this->xlm, source, x); - } - - static void DoDel(XLineManager *xlm, CommandSource &source, XLine *x) - { - xlm->DelXLine(x); - } -}; - -class CommandOSSXLineBase : public Command -{ - private: - virtual XLineManager* xlm() = 0; - - virtual void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) = 0; - - void OnDel(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - - if (!this->xlm() || this->xlm()->GetList().empty()) - { - source.Reply(_("%s list is empty."), source.command.c_str()); - return; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (mask.empty()) - { - this->OnSyntaxError(source, "DEL"); - return; - } - - if (isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - SXLineDelCallback list(this->xlm(), this, source, mask); - list.Process(); - } - else - { - XLine *x = this->xlm()->HasEntry(mask); - - if (!x) - { - source.Reply(_("\002%s\002 not found on the %s list."), mask.c_str(), source.command.c_str()); - return; - } - - FOREACH_MOD(OnDelXLine, (source, x, this->xlm())); - - SXLineDelCallback::DoDel(this->xlm(), source, x); - source.Reply(_("\002%s\002 deleted from the %s list."), mask.c_str(), source.command.c_str()); - Log(LOG_ADMIN, source, this) << "to remove " << mask << " from the list"; - } - - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - return; - } - - void ProcessList(CommandSource &source, const std::vector<Anope::string> ¶ms, ListFormatter &list) - { - if (!this->xlm() || this->xlm()->GetList().empty()) - { - source.Reply(_("%s list is empty."), source.command.c_str()); - return; - } - - const Anope::string &mask = params.size() > 1 ? params[1] : ""; - - if (!mask.empty() && isdigit(mask[0]) && mask.find_first_not_of("1234567890,-") == Anope::string::npos) - { - class SXLineListCallback : public NumberList - { - XLineManager *xlm; - CommandSource &source; - ListFormatter &list; - public: - SXLineListCallback(XLineManager *x, CommandSource &_source, ListFormatter &_list, const Anope::string &numlist) : NumberList(numlist, false), xlm(x), source(_source), list(_list) - { - } - - void HandleNumber(unsigned number) anope_override - { - if (!number) - return; - - const XLine *x = this->xlm->GetEntry(number - 1); - - if (!x) - return; - - ListFormatter::ListEntry entry; - entry["Number"] = stringify(number); - entry["Mask"] = x->mask; - entry["By"] = x->by; - entry["Created"] = Anope::strftime(x->created, NULL, true); - entry["Expires"] = Anope::Expires(x->expires, source.nc); - entry["ID"] = x->id; - entry["Reason"] = x->reason; - list.AddEntry(entry); - } - } - sl_list(this->xlm(), source, list, mask); - sl_list.Process(); - } - else - { - for (unsigned i = 0, end = this->xlm()->GetCount(); i < end; ++i) - { - const XLine *x = this->xlm()->GetEntry(i); - - if (mask.empty() || mask.equals_ci(x->mask) || mask == x->id || Anope::Match(x->mask, mask, false, true)) - { - ListFormatter::ListEntry entry; - entry["Number"] = stringify(i + 1); - entry["Mask"] = x->mask; - entry["By"] = x->by; - entry["Created"] = Anope::strftime(x->created, NULL, true); - entry["Expires"] = Anope::Expires(x->expires, source.nc); - entry["ID"] = x->id; - entry["Reason"] = x->reason; - list.AddEntry(entry); - } - } - } - - if (list.IsEmpty()) - source.Reply(_("No matching entries on the %s list."), source.command.c_str()); - else - { - source.Reply(_("Current %s list:"), source.command.c_str()); - - std::vector<Anope::string> replies; - list.Process(replies); - - for (unsigned i = 0; i < replies.size(); ++i) - source.Reply(replies[i]); - } - } - - void OnList(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("Reason")); - - this->ProcessList(source, params, list); - } - - void OnView(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - ListFormatter list(source.GetAccount()); - list.AddColumn(_("Number")).AddColumn(_("Mask")).AddColumn(_("By")).AddColumn(_("Created")).AddColumn(_("Expires")); - if (Config->GetModule("operserv")->Get<bool>("akillids")) - list.AddColumn(_("ID")); - list.AddColumn(_("Reason")); - - this->ProcessList(source, params, list); - } - - void OnClear(CommandSource &source) - { - FOREACH_MOD(OnDelXLine, (source, NULL, this->xlm())); - - for (unsigned i = this->xlm()->GetCount(); i > 0; --i) - { - XLine *x = this->xlm()->GetEntry(i - 1); - this->xlm()->DelXLine(x); - } - - Log(LOG_ADMIN, source, this) << "to CLEAR the list"; - source.Reply(_("The %s list has been cleared."), source.command.c_str()); - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - - return; - } - public: - CommandOSSXLineBase(Module *creator, const Anope::string &cmd) : Command(creator, cmd, 1, 4) - { - } - - const Anope::string GetDesc(CommandSource &source) const anope_override - { - return Anope::printf(Language::Translate(source.GetAccount(), _("Manipulate the %s list")), source.command.upper().c_str()); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - const Anope::string &cmd = params[0]; - - if (cmd.equals_ci("ADD")) - return this->OnAdd(source, params); - else if (cmd.equals_ci("DEL")) - return this->OnDel(source, params); - else if (cmd.equals_ci("LIST")) - return this->OnList(source, params); - else if (cmd.equals_ci("VIEW")) - return this->OnView(source, params); - else if (cmd.equals_ci("CLEAR")) - return this->OnClear(source); - else - this->OnSyntaxError(source, ""); - - return; - } - - virtual bool OnHelp(CommandSource &source, const Anope::string &subcommand) = 0; -}; - -class CommandOSSNLine : public CommandOSSXLineBase -{ - XLineManager *xlm() - { - return this->snlines; - } - - void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!this->xlm()) - return; - - unsigned last_param = 2; - Anope::string param, expiry; - - param = params.size() > 1 ? params[1] : ""; - if (!param.empty() && param[0] == '+') - { - expiry = param; - param = params.size() > 2 ? params[2] : ""; - last_param = 3; - } - - time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("snlineexpiry", "30d"); - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (param.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - Anope::string rest = param; - if (params.size() > last_param) - rest += " " + params[last_param]; - - if (rest.find(':') == Anope::string::npos) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - sepstream sep(rest, ':'); - Anope::string mask; - sep.GetToken(mask); - Anope::string reason = sep.GetRemaining(); - - if (mask.empty() || reason.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - if (mask[0] == '/' && mask[mask.length() - 1] == '/') - { - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - - if (regexengine.empty()) - { - source.Reply(_("Regex is disabled.")); - return; - } - - ServiceReference<RegexProvider> provider("Regex", regexengine); - if (!provider) - { - source.Reply(_("Unable to find regex engine %s."), regexengine.c_str()); - return; - } - - try - { - Anope::string stripped_mask = mask.substr(1, mask.length() - 2); - delete provider->Compile(stripped_mask); - } - catch (const RegexException &ex) - { - source.Reply("%s", ex.GetReason().c_str()); - return; - } - } - - /* Clean up the last character of the mask if it is a space - * See bug #761 - */ - unsigned masklen = mask.length(); - if (mask[masklen - 1] == ' ') - mask.erase(masklen - 1); - - if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty()) - reason = "[" + source.GetNick() + "] " + reason; - - if (mask.find_first_not_of("/.*?") == Anope::string::npos) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - return; - } - - XLine *x = new XLine(mask, source.GetNick(), expires, reason); - if (Config->GetModule("operserv")->Get<bool>("akillids")) - x->id = XLineManager::GenerateUID(); - - unsigned int affected = 0; - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (this->xlm()->Check(it->second, x)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - Log(LOG_ADMIN, source, this) << "tried to " << source.command << " " << percent << "% of the network (" << affected << " users)"; - delete x; - return; - } - - if (!this->xlm()->CanAdd(source, mask, expires, reason)) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, this->xlm())); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return; - } - - this->xlm()->AddXLine(x); - - if (Config->GetModule("operserv")->Get<bool>("killonsnline", "yes")) - { - Anope::string rreason = "G-Lined: " + reason; - - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *user = it->second; - - if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x)) - user->Kill(Me, rreason); - } - - this->xlm()->Send(NULL, x); - } - - source.Reply(_("\002%s\002 added to the %s list."), mask.c_str(), source.command.c_str()); - Log(LOG_ADMIN, source, this) << "on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - - ServiceReference<XLineManager> snlines; - public: - CommandOSSNLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/snline"), snlines("XLineManager", "xlinemanager/snline") - { - this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037:\037reason\037")); - this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037 | \037id\037}")); - this->SetSyntax(_("LIST [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax(_("VIEW [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax("CLEAR"); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to manipulate the SNLINE list. If\n" - "a user with a realname matching an SNLINE mask attempts to\n" - "connect, Services will not allow it to pursue his IRC\n" - "session.")); - source.Reply(_(" \n" - "\002SNLINE ADD\002 adds the given realname mask to the SNLINE\n" - "list for the given reason (which \002must\002 be given).\n" - "\037expiry\037 is specified as an integer followed by one of \037d\037\n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as\n" - "\0371h30m\037) are not permitted. If a unit specifier is not\n" - "included, the default is days (so \037+30\037 by itself means 30\n" - "days). To add an SNLINE which does not expire, use \037+0\037. If the\n" - "realname mask to be added starts with a \037+\037, an expiry time must\n" - "be given, even if it is the same as the default. The\n" - "current SNLINE default expiry time can be found with the\n" - "\002STATS AKILL\002 command.\n" - " \n" - "\002Note\002: because the realname mask may contain spaces, the\n" - "separator between it and the reason is a colon.")); - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your mask in // if this is desired."), regexengine.c_str()); - } - source.Reply(_(" \n" - "The \002SNLINE DEL\002 command removes the given mask from the\n" - "SNLINE list if it is present. If a list of entry numbers is\n" - "given, those entries are deleted. (See the example for LIST\n" - "below.)\n" - " \n" - "The \002SNLINE LIST\002 command displays the SNLINE list.\n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SNLINE LIST 2-5,7-9\002\n" - " Lists SNLINE entries numbered 2 through 5 and 7\n" - " through 9.\n" - " \n" - "\002SNLINE VIEW\002 is a more verbose version of \002SNLINE LIST\002, and\n" - "will show who added an SNLINE, the date it was added, and when\n" - "it expires, as well as the realname mask and reason.\n" - " \n" - "\002SNLINE CLEAR\002 clears all entries of the SNLINE list.")); - return true; - } -}; - -class CommandOSSQLine : public CommandOSSXLineBase -{ - XLineManager *xlm() - { - return this->sqlines; - } - - void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (!this->xlm()) - return; - - unsigned last_param = 2; - Anope::string expiry, mask; - - mask = params.size() > 1 ? params[1] : ""; - if (!mask.empty() && mask[0] == '+') - { - expiry = mask; - mask = params.size() > 2 ? params[2] : ""; - last_param = 3; - } - - time_t expires = !expiry.empty() ? Anope::DoTime(expiry) : Config->GetModule("operserv")->Get<time_t>("sqlineexpiry", "30d"); - /* If the expiry given does not contain a final letter, it's in days, - * said the doc. Ah well. - */ - if (!expiry.empty() && isdigit(expiry[expiry.length() - 1])) - expires *= 86400; - /* Do not allow less than a minute expiry time */ - if (expires && expires < 60) - { - source.Reply(BAD_EXPIRY_TIME); - return; - } - else if (expires > 0) - expires += Anope::CurTime; - - if (params.size() <= last_param) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - Anope::string reason = params[last_param]; - if (last_param == 2 && params.size() > 3) - reason += " " + params[3]; - - if (mask.empty() || reason.empty()) - { - this->OnSyntaxError(source, "ADD"); - return; - } - - if (mask[0] == '/' && mask[mask.length() - 1] == '/') - { - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - - if (regexengine.empty()) - { - source.Reply(_("Regex is disabled.")); - return; - } - - ServiceReference<RegexProvider> provider("Regex", regexengine); - if (!provider) - { - source.Reply(_("Unable to find regex engine %s."), regexengine.c_str()); - return; - } - - try - { - Anope::string stripped_mask = mask.substr(1, mask.length() - 2); - delete provider->Compile(stripped_mask); - } - catch (const RegexException &ex) - { - source.Reply("%s", ex.GetReason().c_str()); - return; - } - } - - if (Config->GetModule("operserv")->Get<bool>("addakiller", "yes") && !source.GetNick().empty()) - reason = "[" + source.GetNick() + "] " + reason; - - if (mask.find_first_not_of("./?*") == Anope::string::npos) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - return; - } - - XLine *x = new XLine(mask, source.GetNick(), expires, reason); - if (Config->GetModule("operserv")->Get<bool>("akillids")) - x->id = XLineManager::GenerateUID(); - - unsigned int affected = 0; - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (this->xlm()->Check(it->second, x)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { - source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); - Log(LOG_ADMIN, source, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)"; - delete x; - return; - } - - if (!this->sqlines->CanAdd(source, mask, expires, reason)) - return; - - EventReturn MOD_RESULT; - FOREACH_RESULT(OnAddXLine, MOD_RESULT, (source, x, this->xlm())); - if (MOD_RESULT == EVENT_STOP) - { - delete x; - return; - } - - this->xlm()->AddXLine(x); - - if (Config->GetModule("operserv")->Get<bool>("killonsqline", "yes")) - { - Anope::string rreason = "Q-Lined: " + reason; - - if (mask[0] == '#') - { - for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit) - { - Channel *c = cit->second; - - if (!Anope::Match(c->name, mask, false, true)) - continue; - - std::vector<User *> users; - for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - ChanUserContainer *uc = it->second; - User *user = uc->user; - - if (!user->HasMode("OPER") && user->server != Me) - users.push_back(user); - } - - for (unsigned i = 0; i < users.size(); ++i) - c->Kick(NULL, users[i], "%s", reason.c_str()); - } - } - else - { - for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *user = it->second; - - if (!user->HasMode("OPER") && user->server != Me && this->xlm()->Check(user, x)) - user->Kill(Me, rreason); - } - } - - this->xlm()->Send(NULL, x); - } - - source.Reply(_("\002%s\002 added to the %s list."), mask.c_str(), source.command.c_str()); - Log(LOG_ADMIN, source, this) << "on " << mask << " (" << reason << "), expires in " << (expires ? Anope::Duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (Anope::ReadOnly) - source.Reply(READ_ONLY_MODE); - } - - ServiceReference<XLineManager> sqlines; - public: - CommandOSSQLine(Module *creator) : CommandOSSXLineBase(creator, "operserv/sqline"), sqlines("XLineManager", "xlinemanager/sqline") - { - this->SetSyntax(_("ADD [+\037expiry\037] \037mask\037 \037reason\037")); - this->SetSyntax(_("DEL {\037mask\037 | \037entry-num\037 | \037list\037 | \037id\037}")); - this->SetSyntax(_("LIST [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax(_("VIEW [\037mask\037 | \037list\037 | \037id\037]")); - this->SetSyntax("CLEAR"); - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Allows Services Operators to manipulate the SQLINE list. If\n" - "a user with a nick matching an SQLINE mask attempts to\n" - "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. 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" - "\037expiry\037 is specified as an integer followed by one of \037d\037\n" - "(days), \037h\037 (hours), or \037m\037 (minutes). Combinations (such as\n" - "\0371h30m\037) are not permitted. If a unit specifier is not\n" - "included, the default is days (so \037+30\037 by itself means 30\n" - "days). To add an SQLINE which does not expire, use \037+0\037.\n" - "If the mask to be added starts with a \037+\037, an expiry time\n" - "must be given, even if it is the same as the default. The\n" - "current SQLINE default expiry time can be found with the\n" - "\002STATS AKILL\002 command.")); - const Anope::string ®exengine = Config->GetBlock("options")->Get<const Anope::string>("regexengine"); - if (!regexengine.empty()) - { - source.Reply(" "); - source.Reply(_("Regex matches are also supported using the %s engine.\n" - "Enclose your mask in // if this is desired."), regexengine.c_str()); - } - source.Reply(_(" \n" - "The \002SQLINE DEL\002 command removes the given mask from the\n" - "SQLINE list if it is present. If a list of entry numbers is\n" - "given, those entries are deleted. (See the example for LIST\n" - "below.)\n" - " \n" - "The \002SQLINE LIST\002 command displays the SQLINE list.\n" - "If a wildcard mask is given, only those entries matching the\n" - "mask are displayed. If a list of entry numbers is given,\n" - "only those entries are shown; for example:\n" - " \002SQLINE LIST 2-5,7-9\002\n" - " Lists SQLINE entries numbered 2 through 5 and 7\n" - " through 9.\n" - " \n" - "\002SQLINE VIEW\002 is a more verbose version of \002SQLINE LIST\002, and\n" - "will show who added an SQLINE, the date it was added, and when\n" - "it expires, as well as the mask and reason.\n" - " \n" - "\002SQLINE CLEAR\002 clears all entries of the SQLINE list.")); - return true; - } -}; - -class OSSXLine : public Module -{ - CommandOSSNLine commandossnline; - CommandOSSQLine commandossqline; - - public: - OSSXLine(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandossnline(this), commandossqline(this) - { - } -}; - -MODULE_INIT(OSSXLine) diff --git a/modules/commands/os_update.cpp b/modules/commands/os_update.cpp deleted file mode 100644 index 5fac1b063..000000000 --- a/modules/commands/os_update.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2016 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -class CommandOSUpdate : public Command -{ - public: - CommandOSUpdate(Module *creator) : Command(creator, "operserv/update", 0, 0) - { - this->SetDesc(_("Force the Services databases to be updated immediately")); - } - - void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override - { - Log(LOG_ADMIN, source, this); - source.Reply(_("Updating databases.")); - Anope::SaveDatabases(); - return; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override - { - this->SendSyntax(source); - source.Reply(" "); - source.Reply(_("Causes Services to update all database files as soon as you\n" - "send the command.")); - return true; - } -}; - -class OSUpdate : public Module -{ - CommandOSUpdate commandosupdate; - - public: - OSUpdate(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - commandosupdate(this) - { - - } -}; - -MODULE_INIT(OSUpdate) |