diff options
author | Adam <Adam@Anope.org> | 2010-05-25 00:57:25 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2010-06-18 21:04:07 -0400 |
commit | 4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch) | |
tree | e4af4e59fd29352138db0fb0ff614d50233850b8 /src/core/bs_bot.cpp | |
parent | 2fba686904e6f78ebab35df171c5757afeebf05d (diff) |
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/core/bs_bot.cpp')
-rw-r--r-- | src/core/bs_bot.cpp | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/src/core/bs_bot.cpp b/src/core/bs_bot.cpp new file mode 100644 index 000000000..2c5888554 --- /dev/null +++ b/src/core/bs_bot.cpp @@ -0,0 +1,432 @@ +/* BotServ core functions + * + * (C) 2003-2010 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: + CommandReturn DoAdd(User *u, const std::vector<ci::string> ¶ms) + { + const char *nick = params[1].c_str(); + const char *user = params[2].c_str(); + const char *host = params[3].c_str(); + const char *real = params[4].c_str(); + const char *ch = NULL; + BotInfo *bi; + + if (findbot(nick)) + { + notice_lang(Config.s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + return MOD_CONT; + } + + if (strlen(nick) > Config.NickLen) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + if (strlen(user) > Config.UserLen) + { + notice_lang(Config.s_BotServ, u, BOT_LONG_IDENT, Config.UserLen); + return MOD_CONT; + } + + if (strlen(user) > Config.HostLen) + { + notice_lang(Config.s_BotServ, u, BOT_LONG_HOST, Config.HostLen); + return MOD_CONT; + } + + /* Check the nick is valid re RFC 2812 */ + if (isdigit(nick[0]) || nick[0] == '-') + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + for (ch = nick; *ch && (ch - nick) < Config.NickLen; ch++) + { + if (!isvalidnick(*ch)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + + /* check for hardcored ircd forbidden nicks */ + if (!ircdproto->IsNickValid(nick)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + /* Check the host is valid re RFC 2812 */ + if (!isValidHost(host, 3)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + + for (ch = user; *ch && (ch - user) < Config.UserLen; ch++) + { + if (!isalnum(*ch)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_IDENT, Config.UserLen); + return MOD_CONT; + } + } + + + /* 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 (findnick(nick)) + { + notice_lang(Config.s_BotServ, u, NICK_ALREADY_REGISTERED, nick); + return MOD_CONT; + } + + if (!(bi = new BotInfo(nick, user, host, real))) + { + notice_lang(Config.s_BotServ, u, BOT_BOT_CREATION_FAILED); + return MOD_CONT; + } + + /* We check whether user with this nick is online, and kill it if so */ + EnforceQlinedNick(nick, Config.s_BotServ); + + notice_lang(Config.s_BotServ, u, BOT_BOT_ADDED, bi->nick.c_str(), bi->user.c_str(), bi->host.c_str(), bi->real.c_str()); + + FOREACH_MOD(I_OnBotCreate, OnBotCreate(bi)); + return MOD_CONT; + } + + CommandReturn DoChange(User *u, const std::vector<ci::string> ¶ms) + { + const char *oldnick = params[1].c_str(); + const char *nick = params.size() > 2 ? params[2].c_str() : NULL; + const char *user = params.size() > 3 ? params[3].c_str() : NULL; + const char *host = params.size() > 4 ? params[4].c_str() : NULL; + const char *real = params.size() > 5 ? params[5].c_str() : NULL; + const char *ch = NULL; + BotInfo *bi; + + if (!oldnick || !nick) + { + this->OnSyntaxError(u, "CHANGE"); + return MOD_CONT; + } + + if (!(bi = findbot(oldnick))) + { + notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); + return MOD_CONT; + } + + if (stricmp(oldnick, nick) && nickIsServices(oldnick, 0)) + { + notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); + return MOD_CONT; + } + + if (strlen(nick) > Config.NickLen) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + if (user && strlen(user) > Config.UserLen) + { + notice_lang(Config.s_BotServ, u, BOT_LONG_IDENT, Config.UserLen); + return MOD_CONT; + } + + if (host && strlen(host) > Config.HostLen) + { + notice_lang(Config.s_BotServ, u, BOT_LONG_HOST, Config.HostLen); + return MOD_CONT; + } + + if (stricmp(oldnick, nick) && nickIsServices(nick, 0)) + { + notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); + return MOD_CONT; + } + + /* 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 (bi->nick == nick && (user ? bi->user == user : 1) && (host ? bi->host == host : 1) && (real ? bi->real == real : 1)) + { + notice_lang(Config.s_BotServ, u, BOT_BOT_ANY_CHANGES); + return MOD_CONT; + } + + /* Check the nick is valid re RFC 2812 */ + if (isdigit(nick[0]) || nick[0] == '-') + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + for (ch = nick; *ch && (ch - nick) < Config.NickLen; ch++) + { + if (!isvalidnick(*ch)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + } + + /* check for hardcored ircd forbidden nicks */ + if (!ircdproto->IsNickValid(nick)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_NICK); + return MOD_CONT; + } + + if (host && !isValidHost(host, 3)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_HOST); + return MOD_CONT; + } + + if (user) + { + for (ch = user; *ch && (ch - user) < Config.UserLen; ch++) + { + if (!isalnum(*ch)) + { + notice_lang(Config.s_BotServ, u, BOT_BAD_IDENT, Config.UserLen); + return MOD_CONT; + } + } + } + + ci::string ci_bi_nick(bi->nick.c_str()); + if (ci_bi_nick != nick && findbot(nick)) + { + notice_lang(Config.s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); + return MOD_CONT; + } + + if (ci_bi_nick != 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 (findnick(nick)) + { + notice_lang(Config.s_BotServ, u, NICK_ALREADY_REGISTERED, nick); + return MOD_CONT; + } + + /* The new nick is really different, so we remove the Q line for + the old nick. */ + if (ircd->sqline) + { + XLine x(bi->nick.c_str()); + ircdproto->SendSQLineDel(&x); + } + + /* We check whether user with this nick is online, and kill it if so */ + EnforceQlinedNick(nick, Config.s_BotServ); + } + + if (user) + ircdproto->SendQuit(bi, "Quit: Be right back"); + else + { + ircdproto->SendChangeBotNick(bi, nick); + XLine x(bi->nick.c_str(), "Reserved for services"); + ircdproto->SendSQLine(&x); + } + + if (bi->nick != nick) + bi->ChangeNick(nick); + + if (user && bi->user != user) + bi->user = user; + if (host && bi->host != host) + bi->host = host; + if (real && bi->real != real) + bi->real = real; + + if (user) + { + if (ircd->ts6) { + // This isn't the nicest way to do this, unfortunately. + bi->uid = ts6_uid_retrieve(); + } + ircdproto->SendClientIntroduction(bi->nick, bi->user, bi->host, bi->real, ircd->pseudoclient_mode, bi->uid); + XLine x(bi->nick.c_str(), "Reserved for services"); + ircdproto->SendSQLine(&x); + bi->RejoinAll(); + } + + notice_lang(Config.s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick.c_str(), bi->user.c_str(), bi->host.c_str(), bi->real.c_str()); + + FOREACH_MOD(I_OnBotChange, OnBotChange(bi)); + return MOD_CONT; + } + + CommandReturn DoDel(User *u, const std::vector<ci::string> ¶ms) + { + const char *nick = params[1].c_str(); + BotInfo *bi; + + if (!nick) + { + this->OnSyntaxError(u, "DEL"); + return MOD_CONT; + } + + if (!(bi = findbot(nick))) + { + notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + return MOD_CONT; + } + + if (nickIsServices(nick, 0)) + { + notice_lang(Config.s_BotServ, u, BOT_DOES_NOT_EXIST, nick); + return MOD_CONT; + } + + FOREACH_MOD(I_OnBotDelete, OnBotDelete(bi)); + + ircdproto->SendQuit(bi, "Quit: Help! I'm being deleted by %s!", u->nick.c_str()); + XLine x(bi->nick.c_str()); + ircdproto->SendSQLineDel(&x); + + delete bi; + notice_lang(Config.s_BotServ, u, BOT_BOT_DELETED, nick); + return MOD_CONT; + } + public: + CommandBSBot() : Command("BOT", 1, 6) + { + this->SetFlag(CFLAG_STRIP_CHANNEL); + } + + CommandReturn Execute(User *u, const std::vector<ci::string> ¶ms) + { + ci::string cmd = params[0]; + + if (readonly) + { + notice_lang(Config.s_BotServ, u, BOT_BOT_READONLY); + return MOD_CONT; + } + + if (cmd == "ADD") + { + // ADD nick user host real - 5 + if (!u->Account()->HasCommand("botserv/bot/add")) + { + notice_lang(Config.s_BotServ, u, ACCESS_DENIED); + return MOD_CONT; + } + + if (params.size() < 5) + { + this->OnSyntaxError(u, "ADD"); + return MOD_CONT; + } + + std::vector<ci::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(u, tempparams); + } + else if (cmd == "CHANGE") + { + // CHANGE oldn newn user host real - 6 + // but only oldn and newn are required + if (!u->Account()->HasCommand("botserv/bot/change")) + { + notice_lang(Config.s_BotServ, u, ACCESS_DENIED); + return MOD_CONT; + } + + if (params.size() < 3) + { + this->OnSyntaxError(u, "CHANGE"); + return MOD_CONT; + } + + return this->DoChange(u, params); + } + else if (cmd == "DEL") + { + // DEL nick + if (!u->Account()->HasCommand("botserv/bot/del")) + { + notice_lang(Config.s_BotServ, u, ACCESS_DENIED); + return MOD_CONT; + } + + if (params.size() < 1) + { + this->OnSyntaxError(u, "DEL"); + return MOD_CONT; + } + + return this->DoDel(u, params); + } + else + this->OnSyntaxError(u, ""); + + return MOD_CONT; + } + + bool OnHelp(User *u, const ci::string &subcommand) + { + notice_lang(Config.s_BotServ, u, BOT_SERVADMIN_HELP_BOT); + return true; + } + + void OnSyntaxError(User *u, const ci::string &subcommand) + { + syntax_error(Config.s_BotServ, u, "BOT", BOT_BOT_SYNTAX); + } +}; + +class BSBot : public Module +{ + public: + BSBot(const std::string &modname, const std::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetVersion(VERSION_STRING); + this->SetType(CORE); + this->AddCommand(BotServ, new CommandBSBot()); + + ModuleManager::Attach(I_OnBotServHelp, this); + } + void OnBotServHelp(User *u) + { + notice_lang(Config.s_BotServ, u, BOT_HELP_CMD_BOT); + } +}; + +MODULE_INIT(BSBot) |