summaryrefslogtreecommitdiff
path: root/src/botserv.c
diff options
context:
space:
mode:
authorAdam <Adam@Anope.org>2010-05-25 00:57:25 -0500
committerAdam <Adam@anope.org>2010-06-18 21:04:07 -0400
commit4a2b9ebcf38d6c0a2860b966421b3af125438488 (patch)
treee4af4e59fd29352138db0fb0ff614d50233850b8 /src/botserv.c
parent2fba686904e6f78ebab35df171c5757afeebf05d (diff)
Renamed all of source files from .c to .cpp
Diffstat (limited to 'src/botserv.c')
-rw-r--r--src/botserv.c853
1 files changed, 0 insertions, 853 deletions
diff --git a/src/botserv.c b/src/botserv.c
deleted file mode 100644
index aefe37b08..000000000
--- a/src/botserv.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/* BotServ 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 "services.h"
-#include "modules.h"
-#include "language.h"
-
-static UserData *get_user_data(Channel * c, User * u);
-
-static void check_ban(ChannelInfo * ci, User * u, int ttbtype);
-static void bot_kick(ChannelInfo * ci, User * u, int message, ...);
-
-E void moduleAddBotServCmds();
-
-/*************************************************************************/
-/* *INDENT-OFF* */
-void moduleAddBotServCmds() {
- ModuleManager::LoadModuleList(Config.BotServCoreModules);
-}
-/* *INDENT-ON* */
-/*************************************************************************/
-/*************************************************************************/
-
-/* Return information on memory use. Assumes pointers are valid. */
-
-void get_botserv_stats(long *nrec, long *memuse)
-{
- long count = 0, mem = 0;
-
- for (botinfo_map::const_iterator it = BotList.begin(); it != BotList.end(); ++it)
- {
- BotInfo *bi = it->second;
-
- count++;
- mem += sizeof(*bi);
- mem += bi->nick.size() + 1;
- mem += bi->user.size() + 1;
- mem += bi->host.size() + 1;
- mem += bi->real.size() + 1;
- }
-
- *nrec = count;
- *memuse = mem;
-}
-
-/*************************************************************************/
-/*************************************************************************/
-
-/* BotServ initialization. */
-
-void bs_init()
-{
- if (Config.s_BotServ) {
- moduleAddBotServCmds();
- }
-}
-
-/*************************************************************************/
-
-/* Main BotServ routine. */
-
-void botserv(User * u, char *buf)
-{
- char *cmd, *s;
-
- cmd = strtok(buf, " ");
-
- if (!cmd) {
- return;
- } else if (stricmp(cmd, "\1PING") == 0) {
- if (!(s = strtok(NULL, ""))) {
- *s = 0;
- }
- ircdproto->SendCTCP(BotServ, u->nick.c_str(), "PING %s", s);
- } else {
- mod_run_cmd(BotServ, u, cmd);
- }
-
-}
-
-/*************************************************************************/
-
-/* Handles all messages sent to bots. (Currently only answers to pings ;) */
-
-void botmsgs(User * u, BotInfo * bi, char *buf)
-{
- char *cmd = strtok(buf, " ");
- char *s;
-
- if (!cmd || !u || !bi)
- return;
-
- if (!stricmp(cmd, "\1PING")) {
- if (!(s = strtok(NULL, ""))) {
- *s = 0;
- }
- ircdproto->SendCTCP(bi, u->nick.c_str(), "PING %s", s);
- }
- else if (cmd && !bi->Commands.empty())
- {
- mod_run_cmd(bi, u, cmd);
- }
-}
-
-/*************************************************************************/
-
-/* Handles all messages that are sent to registered channels where a
- * bot is on.
- *
- */
-
-void botchanmsgs(User * u, ChannelInfo * ci, char *buf)
-{
- int c;
- char *cmd;
- UserData *ud;
- bool was_action = false;
- std::string bbuf;
-
- if (!u || !buf || !ci || !ci->c)
- return;
-
- /* Answer to ping if needed, without breaking the buffer. */
- if (!strnicmp(buf, "\1PING", 5)) {
- ircdproto->SendCTCP(ci->bi, u->nick.c_str(), "PING %s", buf);
- }
-
- /* If it's a /me, cut the CTCP part at the beginning (not
- * at the end, because one character just doesn't matter,
- * but the ACTION may create strange behaviours with the
- * caps or badwords kickers */
- if (!strnicmp(buf, "\1ACTION ", 8))
- {
- buf += 8;
- was_action = true;
- }
-
- /* 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 an user is kicked before
- * the last kicker check.
- *
- * But FIRST we check whether the user is protected in any
- * way.
- */
-
- bool Allow = false;
- if (!ci->botflags.HasFlag(BS_DONTKICKOPS) && !ci->botflags.HasFlag(BS_DONTKICKVOICES))
- Allow = true;
- 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 = true;
- else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE))
- Allow = true;
-
- if (buf && !check_access(u, ci, CA_NOKICK) && Allow)
- {
- /* Bolds kicker */
- if (ci->botflags.HasFlag(BS_KICK_BOLDS) && strchr(buf, 2)) {
- check_ban(ci, u, TTB_BOLDS);
- bot_kick(ci, u, BOT_REASON_BOLD);
- return;
- }
-
- /* Color kicker */
- if (ci->botflags.HasFlag(BS_KICK_COLORS) && strchr(buf, 3)) {
- check_ban(ci, u, TTB_COLORS);
- bot_kick(ci, u, BOT_REASON_COLOR);
- return;
- }
-
- /* Reverses kicker */
- if (ci->botflags.HasFlag(BS_KICK_REVERSES) && strchr(buf, 22)) {
- check_ban(ci, u, TTB_REVERSES);
- bot_kick(ci, u, BOT_REASON_REVERSE);
- return;
- }
-
- /* Underlines kicker */
- if (ci->botflags.HasFlag(BS_KICK_UNDERLINES) && strchr(buf, 31)) {
- check_ban(ci, u, TTB_UNDERLINES);
- bot_kick(ci, u, BOT_REASON_UNDERLINE);
- return;
- }
-
- /* Caps kicker */
- if (ci->botflags.HasFlag(BS_KICK_CAPS)
- && ((c = strlen(buf)) >= ci->capsmin)) {
- int i = 0;
- int l = 0;
- char *s = buf;
-
- do {
- if (isupper(*s))
- i++;
- else if (islower(*s))
- l++;
- } while (*s++);
-
- /* 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, BOT_REASON_CAPS);
- return;
- }
- }
-
- /* Bad words kicker */
- if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) {
- int mustkick = 0;
- char *nbuf;
- BadWord *bw;
-
- /* Normalize the buffer */
- nbuf = normalizeBuffer(buf);
-
- for (unsigned i = 0; i < ci->GetBadWordCount(); ++i)
- {
- bw = ci->GetBadWord(i);
-
- if (bw->type == BW_ANY
- && ((Config.BSCaseSensitive && strstr(nbuf, bw->word.c_str()))
- || (!Config.BSCaseSensitive && stristr(nbuf, bw->word.c_str())))) {
- mustkick = 1;
- } else if (bw->type == BW_SINGLE) {
- int len = bw->word.length();
-
- if ((Config.BSCaseSensitive && nbuf == bw->word)
- || (!Config.BSCaseSensitive
- && (!stricmp(nbuf, bw->word.c_str())))) {
- mustkick = 1;
- /* two next if are quite odd isn't it? =) */
- } else if ((strchr(nbuf, ' ') == nbuf + len)
- &&
- ((Config.BSCaseSensitive && nbuf == bw->word)
- || (!Config.BSCaseSensitive
- && (stristr(nbuf, bw->word.c_str()) ==
- nbuf)))) {
- mustkick = 1;
- } else {
- if ((strrchr(nbuf, ' ') ==
- nbuf + strlen(nbuf) - len - 1)
- &&
- ((Config.BSCaseSensitive
- && (strstr(nbuf, bw->word.c_str()) ==
- nbuf + strlen(nbuf) - len))
- || (!Config.BSCaseSensitive
- && (stristr(nbuf, bw->word.c_str()) ==
- nbuf + strlen(nbuf) - len)))) {
- mustkick = 1;
- } else {
- char *wordbuf = new char[len + 3];
-
- wordbuf[0] = ' ';
- wordbuf[len + 1] = ' ';
- wordbuf[len + 2] = '\0';
- memcpy(wordbuf + 1, bw->word.c_str(), len);
-
- if ((Config.BSCaseSensitive
- && (strstr(nbuf, wordbuf)))
- || (!Config.BSCaseSensitive
- && (stristr(nbuf, wordbuf)))) {
- mustkick = 1;
- }
-
- /* free previous (sc)allocated memory (#850) */
- delete [] wordbuf;
- }
- }
- } else if (bw->type == BW_START) {
- int len = bw->word.length();
-
- if ((Config.BSCaseSensitive
- && (!strncmp(nbuf, bw->word.c_str(), len)))
- || (!Config.BSCaseSensitive
- && (!strnicmp(nbuf, bw->word.c_str(), len)))) {
- mustkick = 1;
- } else {
- char *wordbuf = new char[len + 2];
-
- memcpy(wordbuf + 1, bw->word.c_str(), len);
- wordbuf[0] = ' ';
- wordbuf[len + 1] = '\0';
-
- if ((Config.BSCaseSensitive && (strstr(nbuf, wordbuf)))
- || (!Config.BSCaseSensitive
- && (stristr(nbuf, wordbuf))))
- mustkick = 1;
-
- delete [] wordbuf;
- }
- } else if (bw->type == BW_END) {
- int len = bw->word.length();
-
- if ((Config.BSCaseSensitive
- &&
- (!strncmp
- (nbuf + strlen(nbuf) - len, bw->word.c_str(), len)))
- || (!Config.BSCaseSensitive
- &&
- (!strnicmp
- (nbuf + strlen(nbuf) - len, bw->word.c_str(),
- len)))) {
- mustkick = 1;
- } else {
- char *wordbuf = new char[len + 2];
-
- memcpy(wordbuf, bw->word.c_str(), len);
- wordbuf[len] = ' ';
- wordbuf[len + 1] = '\0';
-
- if ((Config.BSCaseSensitive && (strstr(nbuf, wordbuf)))
- || (!Config.BSCaseSensitive
- && (stristr(nbuf, wordbuf))))
- mustkick = 1;
-
- delete [] wordbuf;
- }
- }
-
- if (mustkick) {
- check_ban(ci, u, TTB_BADWORDS);
- if (Config.BSGentleBWReason)
- bot_kick(ci, u, BOT_REASON_BADWORD_GENTLE);
- else
- bot_kick(ci, u, BOT_REASON_BADWORD, bw->word.c_str());
-
- /* free the normalized buffer before return (#850) */
- delete [] nbuf;
-
- return;
- }
- }
-
- /* Free the normalized buffer */
- delete [] nbuf;
- }
-
- /* Flood kicker */
- if (ci->botflags.HasFlag(BS_KICK_FLOOD)) {
- time_t now = time(NULL);
-
- ud = get_user_data(ci->c, u);
- if (!ud) {
- return;
- }
-
- if (now - ud->last_start > ci->floodsecs) {
- ud->last_start = time(NULL);
- ud->lines = 0;
- }
-
- ud->lines++;
- if (ud->lines >= ci->floodlines) {
- check_ban(ci, u, TTB_FLOOD);
- bot_kick(ci, u, BOT_REASON_FLOOD);
- return;
- }
- }
-
- /* Repeat kicker */
- if (ci->botflags.HasFlag(BS_KICK_REPEAT)) {
- ud = get_user_data(ci->c, u);
- if (!ud) {
- return;
- }
- if (ud->lastline && stricmp(ud->lastline, buf)) {
- delete [] ud->lastline;
- ud->lastline = sstrdup(buf);
- ud->times = 0;
- } else {
- if (!ud->lastline)
- ud->lastline = sstrdup(buf);
- ud->times++;
- }
-
- if (ud->times >= ci->repeattimes) {
- check_ban(ci, u, TTB_REPEAT);
- bot_kick(ci, u, BOT_REASON_REPEAT);
- return;
- }
- }
- }
-
-
- /* return if the user is on the ignore list */
- if (get_ignore(u->nick.c_str()) != NULL) {
- return;
- }
-
- /* Fantaisist commands */
-
- if (buf && ci->botflags.HasFlag(BS_FANTASY) && *buf == *Config.BSFantasyCharacter && !was_action) {
- cmd = strtok(buf, " ");
-
- if (cmd && (cmd[0] == *Config.BSFantasyCharacter)) {
- char *params = strtok(NULL, "");
-
- /* Strip off the fantasy character */
- cmd++;
-
- if (check_access(u, ci, CA_FANTASIA))
- {
- Command *command = FindCommand(ChanServ, cmd);
-
- /* Command exists and can not be called by fantasy */
- if (command && !command->HasFlag(CFLAG_DISABLE_FANTASY))
- {
- bbuf = std::string(cmd);
-
- /* Some commands don't need the channel name added.. eg !help */
- if (!command->HasFlag(CFLAG_STRIP_CHANNEL))
- {
- bbuf += " ";
- bbuf += ci->name;
- }
-
- if (params)
- {
- bbuf += " ";
- bbuf += params;
- }
-
- chanserv(u, const_cast<char *>(bbuf.c_str())); // XXX Unsafe cast, this needs reviewing -- CyberBotX
- }
-
- FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(cmd, u, ci, params));
- }
- else
- {
- FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(cmd, u, ci, params));
- }
- }
- }
-}
-
-/*************************************************************************/
-
-BotInfo *findbot(const char *nick)
-{
- return findbot(ci::string(nick));
-}
-
-BotInfo *findbot(const std::string &nick)
-{
- return findbot(ci::string(nick.c_str()));
-}
-
-BotInfo *findbot(const ci::string &nick)
-{
- botinfo_map::const_iterator it = BotList.find(nick);
-
- if (it != BotList.end())
- return it->second;
- return NULL;
-}
-
-
-/*************************************************************************/
-
-/* Returns ban data associated with an user if it exists, allocates it
- otherwise. */
-
-static BanData *get_ban_data(Channel * c, User * u)
-{
- char mask[BUFSIZE];
- BanData *bd, *next;
- time_t now = time(NULL);
-
- if (!c || !u)
- return NULL;
-
- snprintf(mask, sizeof(mask), "%s@%s", u->GetIdent().c_str(),
- u->GetDisplayedHost().c_str());
-
- for (bd = c->bd; bd; bd = next) {
- if (now - bd->last_use > Config.BSKeepData) {
- if (bd->next)
- bd->next->prev = bd->prev;
- if (bd->prev)
- bd->prev->next = bd->next;
- else
- c->bd = bd->next;
- if (bd->mask)
- delete [] bd->mask;
- next = bd->next;
- delete bd;
- continue;
- }
- if (!stricmp(bd->mask, mask)) {
- bd->last_use = now;
- return bd;
- }
- next = bd->next;
- }
-
- /* If we fall here it is that we haven't found the record */
- bd = new BanData;
- bd->mask = sstrdup(mask);
- bd->last_use = now;
- for (int x = 0; x < TTB_SIZE; ++x)
- bd->ttb[x] = 0;
-
- bd->prev = NULL;
- bd->next = c->bd;
- if (bd->next)
- bd->next->prev = bd;
- c->bd = bd;
-
- return bd;
-}
-
-/*************************************************************************/
-
-/* Returns BotServ data associated with an 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 != c->users.end(); ++it)
- {
- UserContainer *uc = *it;
-
- if (uc->user == u)
- {
- time_t now = time(NULL);
-
- /* Checks whether data is obsolete */
- if (now - uc->ud.last_use > Config.BSKeepData)
- {
- if (uc->ud.lastline)
- delete [] uc->ud.lastline;
- /* We should not free and realloc, but reset to 0
- instead. */
- memset(&uc->ud, 0, sizeof(UserData));
- uc->ud.last_use = now;
- }
-
- return &uc->ud;
- }
- }
-
- return NULL;
-}
-
-/*************************************************************************/
-
-/* Makes the bot join a channel and op himself. */
-
-void bot_join(ChannelInfo * ci)
-{
- if (!ci || !ci->c || !ci->bi)
- return;
-
- if (Config.BSSmartJoin)
- {
- /* We check for bans */
- if (ci->c->bans && ci->c->bans->count)
- {
- Entry *ban, *next;
-
- for (ban = ci->c->bans->entries; ban; ban = next)
- {
- next = ban->next;
-
- if (entry_match(ban, ci->bi->nick.c_str(), ci->bi->user.c_str(), ci->bi->host.c_str(), 0))
- {
- ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask);
- }
- }
- }
-
- std::string Limit;
- int limit = 0;
- if (ci->c->GetParam(CMODE_LIMIT, Limit))
- {
- limit = atoi(Limit.c_str());
- }
-
- /* Should we be invited? */
- if (ci->c->HasMode(CMODE_INVITE)
- || (limit && ci->c->users.size() >= limit))
- ircdproto->SendNoticeChanops(ci->bi, ci->c,
- "%s invited %s into the channel.",
- ci->bi->nick.c_str(), ci->bi->nick.c_str());
- }
- ircdproto->SendJoin(ci->bi, ci->c->name.c_str(), ci->c->creation_time);
- for (std::list<ChannelModeStatus *>::iterator it = BotModes.begin(); it != BotModes.end(); ++it)
- {
- ci->c->SetMode(ci->bi, *it, ci->bi->nick, false);
- }
- FOREACH_MOD(I_OnBotJoin, OnBotJoin(ci, ci->bi));
-}
-
-/*************************************************************************/
-
-/** 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
- */
-static 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 */
- char mask[BUFSIZE];
-
- bd->ttb[ttbtype] = 0;
-
- get_idealban(ci, u, mask, sizeof(mask));
-
- if (ci->c)
- ci->c->SetMode(NULL, CMODE_BAN, mask);
- FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask));
- }
-}
-
-/*************************************************************************/
-
-/* This makes a bot kick an user. Works somewhat like notice_lang in fact ;) */
-
-static void bot_kick(ChannelInfo * ci, User * u, int message, ...)
-{
- va_list args;
- char buf[1024];
- const char *fmt;
-
- if (!ci || !ci->bi || !ci->c || !u)
- return;
-
- va_start(args, message);
- fmt = getstring(u, message);
- if (!fmt)
- return;
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
-
- ci->c->Kick(ci->bi, u, "%s", buf);
-}
-
-/*************************************************************************/
-
-/* Makes a simple ban and kicks the target */
-
-void bot_raw_ban(User * requester, ChannelInfo * ci, char *nick, const char *reason)
-{
- char mask[BUFSIZE];
- User *u = finduser(nick);
-
- if (!u)
- return;
-
- if ((ModeManager::FindUserModeByName(UMODE_PROTECTED)))
- {
- if (u->IsProtected() && (requester != u)) {
- ircdproto->SendPrivmsg(ci->bi, ci->name.c_str(), "%s", getstring(ACCESS_DENIED));
- return;
- }
- }
-
- if (ci->HasFlag(CI_PEACE) && stricmp(requester->nick.c_str(), nick) && (get_access(u, ci) >= get_access(requester, ci)))
- return;
-
- if (ModeManager::FindChannelModeByName(CMODE_EXCEPT))
- {
- if (is_excepted(ci, u) == 1) {
- ircdproto->SendPrivmsg(ci->bi, ci->name.c_str(), "%s", getstring(BOT_EXCEPT));
- return;
- }
- }
-
- get_idealban(ci, u, mask, sizeof(mask));
-
- ci->c->SetMode(NULL, CMODE_BAN, mask);
-
- /* Check if we need to do a signkick or not -GD */
- if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK)))
- ci->c->Kick(ci->bi, u, "%s (%s)", reason ? reason : ci->bi->nick.c_str(), requester->nick.c_str());
- else
- ci->c->Kick(ci->bi, u, "%s", reason ? reason : ci->bi->nick.c_str());
-}
-
-/*************************************************************************/
-
-/* Makes a kick with a "dynamic" reason ;) */
-
-void bot_raw_kick(User * requester, ChannelInfo * ci, char *nick, const char *reason)
-{
- User *u = finduser(nick);
-
- if (!u || !ci->c->FindUser(u))
- return;
-
- if ((ModeManager::FindUserModeByName(UMODE_PROTECTED)))
- {
- if (u->IsProtected() && (requester != u)) {
- ircdproto->SendPrivmsg(ci->bi, ci->name.c_str(), "%s", getstring(ACCESS_DENIED));
- return;
- }
- }
-
- if (ci->HasFlag(CI_PEACE) && stricmp(requester->nick.c_str(), nick) && (get_access(u, ci) >= get_access(requester, ci)))
- return;
-
- if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(requester, ci, CA_SIGNKICK)))
- ci->c->Kick(ci->bi, u, "%s (%s)", reason ? reason : ci->bi->nick.c_str(), requester->nick.c_str());
- else
- ci->c->Kick(ci->bi, u, "%s", reason ? reason : ci->bi->nick.c_str());
-}
-
-/*************************************************************************/
-
-/* Makes a mode operation on a channel for a nick */
-
-void bot_raw_mode(User * requester, ChannelInfo * ci, const char *mode, char *nick)
-{
- char buf[BUFSIZE];
- User *u;
-
- *buf = '\0';
- u = finduser(nick);
-
- if (!u || !ci->c->FindUser(u))
- return;
-
- snprintf(buf, BUFSIZE - 1, "%ld", static_cast<long>(time(NULL)));
-
- if ((ModeManager::FindUserModeByName(UMODE_PROTECTED))) {
- if (u->IsProtected() && *mode == '-' && (requester != u)) {
- ircdproto->SendPrivmsg(ci->bi, ci->name.c_str(), "%s", getstring(ACCESS_DENIED));
- return;
- }
- }
-
- if (*mode == '-' && ci->HasFlag(CI_PEACE)
- && stricmp(requester->nick.c_str(), nick) && (get_access(u, ci) >= get_access(requester, ci)))
- return;
-
- ci->c->SetModes(NULL, "%s %s", mode, nick);
-}
-
-/*************************************************************************/
-/**
- * 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
- */
-char *normalizeBuffer(const char *buf)
-{
- char *newbuf;
- int i, len, j = 0;
-
- len = strlen(buf);
- newbuf = new char[len + 1];
-
- for (i = 0; i < len; 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;
- /* A valid char gets copied into the new buffer */
- default:
- newbuf[j] = buf[i];
- j++;
- }
- }
-
- /* Terminate the string */
- newbuf[j] = 0;
-
- return (newbuf);
-}