diff options
Diffstat (limited to 'src/botserv.cpp')
-rw-r--r-- | src/botserv.cpp | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/src/botserv.cpp b/src/botserv.cpp index 119264c1d..45d30b395 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -14,351 +14,6 @@ #include "services.h" #include "modules.h" -static UserData *get_user_data(Channel *c, User *u); - -E void moduleAddBotServCmds(); - -/*************************************************************************/ - -void moduleAddBotServCmds() -{ - ModuleManager::LoadModuleList(Config->BotServCoreModules); -} - -/*************************************************************************/ -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_botserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - - for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - ++count; - mem += sizeof(*bi); - mem += bi->nick.length() + 1; - mem += bi->GetIdent().length() + 1; - mem += bi->host.length() + 1; - mem += bi->realname.length() + 1; - } - - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* BotServ initialization. */ - -void bs_init() -{ - if (!Config->s_BotServ.empty()) - moduleAddBotServCmds(); -} - -/*************************************************************************/ - -/* Handles all messages that are sent to registered channels where a - * bot is on. - */ - -void botchanmsgs(User *u, ChannelInfo *ci, const Anope::string &buf) -{ - if (!u || !ci || !ci->c || buf.empty()) - return; - - /* Answer to ping if needed */ - if (buf.substr(0, 6).equals_ci("\1PING ") && buf[buf.length() - 1] == '\1') - { - Anope::string ctcp = buf; - ctcp.erase(ctcp.begin()); - ctcp.erase(ctcp.length() - 1); - ircdproto->SendCTCP(ci->bi, u->nick, "%s", ctcp.c_str()); - } - - bool was_action = false; - Anope::string realbuf = buf; - - /* 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); - was_action = true; - } - - if (realbuf.empty()) - return; - - /* 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. - */ - - bool Allow = true; - if (check_access(u, ci, CA_NOKICK)) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (ci->c->HasUserStatus(u, CMODE_HALFOP) || ci->c->HasUserStatus(u, CMODE_OP) || ci->c->HasUserStatus(u, CMODE_PROTECT) || ci->c->HasUserStatus(u, CMODE_OWNER))) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE)) - Allow = false; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPrivmsg, OnPrivmsg(u, ci, realbuf, Allow)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (Allow) - { - /* Bolds kicker */ - if (ci->botflags.HasFlag(BS_KICK_BOLDS) && realbuf.find(2) != Anope::string::npos) - { - check_ban(ci, u, TTB_BOLDS); - bot_kick(ci, u, _("Don't use bolds on this channel!")); - return; - } - - /* Color kicker */ - if (ci->botflags.HasFlag(BS_KICK_COLORS) && realbuf.find(3) != Anope::string::npos) - { - check_ban(ci, u, TTB_COLORS); - bot_kick(ci, u, _("Don't use colors on this channel!")); - return; - } - - /* Reverses kicker */ - if (ci->botflags.HasFlag(BS_KICK_REVERSES) && realbuf.find(22) != Anope::string::npos) - { - check_ban(ci, u, TTB_REVERSES); - bot_kick(ci, u, _("Don't use reverses on this channel!")); - return; - } - - /* Italics kicker */ - if (ci->botflags.HasFlag(BS_KICK_ITALICS) && realbuf.find(29) != Anope::string::npos) - { - check_ban(ci, u, TTB_ITALICS); - bot_kick(ci, u, _("Don't use italics on this channel!")); - return; - } - - /* Underlines kicker */ - if (ci->botflags.HasFlag(BS_KICK_UNDERLINES) && realbuf.find(31) != Anope::string::npos) - { - check_ban(ci, u, TTB_UNDERLINES); - bot_kick(ci, u, _("Don't use underlines on this channel!")); - return; - } - - /* Caps kicker */ - if (ci->botflags.HasFlag(BS_KICK_CAPS) && realbuf.length() >= ci->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 >= ci->capsmin && i * 100 / (i + l) >= ci->capspercent) - { - check_ban(ci, u, TTB_CAPS); - bot_kick(ci, u, _("Turn caps lock OFF!")); - return; - } - } - - /* Bad words kicker */ - if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) - { - bool mustkick = false; - - /* Normalize the buffer */ - Anope::string nbuf = normalizeBuffer(realbuf); - - for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i) - { - BadWord *bw = ci->GetBadWord(i); - - if (bw->type == BW_ANY && ((Config->BSCaseSensitive && nbuf.find(bw->word) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) != Anope::string::npos))) - mustkick = true; - else if (bw->type == BW_SINGLE) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf))) - mustkick = true; - else if (nbuf.find(' ') == len && ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf)))) - mustkick = true; - else - { - if (nbuf.rfind(' ') == nbuf.length() - len - 1 && ((Config->BSCaseSensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) == nbuf.length() - len))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - } - else if (bw->type == BW_START) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(0, len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - else if (bw->type == BW_END) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - - if (mustkick) - { - check_ban(ci, u, TTB_BADWORDS); - if (Config->BSGentleBWReason) - 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; - } - } - } - - /* Flood kicker */ - if (ci->botflags.HasFlag(BS_KICK_FLOOD)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (Anope::CurTime - ud->last_start > ci->floodsecs) - { - ud->last_start = Anope::CurTime; - ud->lines = 0; - } - - ++ud->lines; - if (ud->lines >= ci->floodlines) - { - check_ban(ci, u, TTB_FLOOD); - bot_kick(ci, u, _("Stop flooding!")); - return; - } - } - - /* Repeat kicker */ - if (ci->botflags.HasFlag(BS_KICK_REPEAT)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (!ud->lastline.empty() && !ud->lastline.equals_ci(buf)) - { - ud->lastline = buf; - ud->times = 0; - } - else - { - if (ud->lastline.empty()) - ud->lastline = buf; - ++ud->times; - } - - if (ud->times >= ci->repeattimes) - { - check_ban(ci, u, TTB_REPEAT); - bot_kick(ci, u, _("Stop repeating yourself!")); - return; - } - } - } - - /* Fantaisist commands */ - if (ci->botflags.HasFlag(BS_FANTASY) && buf[0] == Config->BSFantasyCharacter[0] && !was_action) - { - Anope::string message = buf; - /* Strip off the fantasy character */ - message.erase(message.begin()); - - size_t space = message.find(' '); - Anope::string command, rest; - if (space == Anope::string::npos) - command = message; - else - { - command = message.substr(0, space); - rest = message.substr(space + 1); - } - - if (check_access(u, ci, CA_FANTASIA)) - { - - Command *cmd = FindCommand(ChanServ, command); - - /* Command exists and can be called by fantasy */ - if (cmd && !cmd->HasFlag(CFLAG_DISABLE_FANTASY)) - { - Anope::string params = rest; - /* Some commands don't need the channel name added.. eg !help */ - if (!cmd->HasFlag(CFLAG_STRIP_CHANNEL)) - params = ci->name + " " + params; - params = command + " " + params; - - mod_run_cmd(ChanServ, u, ci, params); - } - - FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, ci, rest)); - } - else - { - FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, ci, rest)); - } - } -} - -/*************************************************************************/ - BotInfo *findbot(const Anope::string &nick) { BotInfo *bi = NULL; @@ -380,138 +35,6 @@ BotInfo *findbot(const Anope::string &nick) return bi; } -/*************************************************************************/ - -/* Returns ban data associated with a user if it exists, allocates it - otherwise. */ - -static BanData *get_ban_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - Anope::string mask = u->GetIdent() + "@" + u->GetDisplayedHost(); - /* XXX This should really be on some sort of timer/garbage collector, and use std::map */ - for (std::list<BanData *>::iterator it = c->bd.begin(), it_end = c->bd.end(), it_next; it != it_end; it = it_next) - { - it_next = it; - ++it_next; - - if (Anope::CurTime - (*it)->last_use > Config->BSKeepData) - { - delete *it; - c->bd.erase(it); - continue; - } - if ((*it)->mask.equals_ci(mask)) - { - (*it)->last_use = Anope::CurTime; - return *it; - } - } - - /* If we fall here it is that we haven't found the record */ - BanData *bd = new BanData(); - bd->mask = mask; - bd->last_use = Anope::CurTime; - for (int x = 0; x < TTB_SIZE; ++x) - bd->ttb[x] = 0; - - c->bd.push_front(bd); - - return bd; -} - -/*************************************************************************/ - -/* Returns BotServ data associated with a user on a given channel. - * Allocates it if necessary. - */ - -static UserData *get_user_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - UserContainer *uc = *it; - - if (uc->user == u) - { - /* Checks whether data is obsolete */ - if (Anope::CurTime - uc->ud.last_use > Config->BSKeepData) - { - /* We should not free and realloc, but reset to 0 - instead. */ - uc->ud.Clear(); - uc->ud.last_use = Anope::CurTime; - } - - return &uc->ud; - } - } - - return NULL; -} - -/*************************************************************************/ - -/** Check if a user should be banned by botserv - * @param ci The channel the user is on - * @param u The user - * @param ttbtype The type of bot kicker the user should be checked against - */ -void check_ban(ChannelInfo *ci, User *u, int ttbtype) -{ - BanData *bd = get_ban_data(ci->c, u); - - if (!bd) - return; - - /* Don't ban ulines */ - if (u->server->IsULined()) - return; - - ++bd->ttb[ttbtype]; - if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) - { - /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->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 */ - Anope::string mask; - - bd->ttb[ttbtype] = 0; - - get_idealban(ci, u, mask); - - if (ci->c) - ci->c->SetMode(NULL, CMODE_BAN, mask); - FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask)); - } -} - -/*************************************************************************/ - -/* This makes a bot kick a user. Works somewhat like notice_lang in fact ;) */ - -void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) -{ - va_list args; - char buf[1024]; - - if (!ci || !ci->bi || !ci->c || !u) - return; - - Anope::string fmt = GetString(u->Account(), message); - va_start(args, message); - if (fmt.empty()) - return; - vsnprintf(buf, sizeof(buf), fmt.c_str(), args); - va_end(args); - - ci->c->Kick(ci->bi, u, "%s", buf); -} /*************************************************************************/ @@ -585,80 +108,3 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); } -/*************************************************************************/ - -/** - * Normalize buffer stripping control characters and colors - * @param A string to be parsed for control and color codes - * @return A string stripped of control and color codes - */ -Anope::string normalizeBuffer(const Anope::string &buf) -{ - Anope::string newbuf; - - for (unsigned i = 0, end = buf.length(); i < end; ++i) - { - switch (buf[i]) - { - /* ctrl char */ - case 1: - break; - /* Bold ctrl char */ - case 2: - break; - /* Color ctrl char */ - case 3: - /* If the next character is a digit, its also removed */ - if (isdigit(buf[i + 1])) - { - ++i; - - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - - /* Check for background color code - * and remove it as well - */ - if (buf[i + 1] == ',') - { - ++i; - - if (isdigit(buf[i + 1])) - ++i; - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - } - } - - break; - /* line feed char */ - case 10: - break; - /* carriage returns char */ - case 13: - break; - /* Reverse ctrl char */ - case 22: - break; - /* Underline ctrl char */ - case 31: - break; - /* Italic ctrl char */ - case 29: - break; - /* A valid char gets copied into the new buffer */ - default: - newbuf += buf[i]; - } - } - - return newbuf; -} |