From d77d32bc8815f956ec519b946b8ae563b527b599 Mon Sep 17 00:00:00 2001 From: Francois Fleuret Date: Sun, 6 Oct 2013 11:15:55 +0200 Subject: [PATCH] Update to version 2.9.2d --- README.txt | 34 ++- objects.cc | 33 ++- objects.h | 10 + secure.cc | 278 +++++++++++++++++++++++ secure.h | 13 ++ tblib.cc | 154 +++++-------- tblib.h | 8 +- tropbot.cc | 643 +++++++++++++++++++++++++++++++++++++++++++++-------- 8 files changed, 959 insertions(+), 214 deletions(-) create mode 100644 secure.cc create mode 100644 secure.h diff --git a/README.txt b/README.txt index 55b7d7f..5bff2f7 100644 --- a/README.txt +++ b/README.txt @@ -1,5 +1,5 @@ ------------------------------------------------------------------------------- - TropBot v2.5 + TropBot v2.9 Documentation written by Francois Fleuret Contact for comments & bug reports Check http://www.eleves.ens.fr:8080/home/fleuret for latest version @@ -20,7 +20,8 @@ EFNet. After few months, TropBot became a real bot, with many features. He's still a fast and small bot, but he can defend a channel by himself. The version 2.2.0 was so stable that I have run one on #france for longer than one month with no reboot (when I finally -killed it it was just to run a newer version). +killed it it was just to run a newer version). The last version +(2.9.0) runs under Purify(tm) with no error. ------------------------------------------------------------------------------- II - TROPBOT CAPABILITIES ----------------------------------------------------- @@ -82,6 +83,18 @@ of the net, there are no flood detection and you won't loose the connection even if the bots send you a lot of datas, etc. This kind of connection is great for commands like "who" "help" "shitlist" etc. +Since v2.8.0, TropBot has new features to handle big channels. First, +it has in memory a list of 'restricted' sites. The bot will detect and +kick/ban any group of users who are on the same machine. The main idea +is to protect the channel from clone bots. The second important +feature is the 'cop-mode'. When this mode is switch ON, the bot will +detect any graphical effect (caps, reverse, mIrc colors, beeps, +art-chars, repeated chars, etc.), wil also ban any user who is kicked +3 times or more in less than 10 minutes, and will ban all site where +more than 3 people are banned. + +The v2.9.0 is a more stable version, debugged using Purify(tm) + ------------------------------------------------------------------------------- II - HOW TO INSTALL TROPBOT --------------------------------------------------- ------------------------------------------------------------------------------- @@ -181,6 +194,12 @@ FRIEND 2 *!*@*.fr trululu will make all people from France able to execute functions with a level 2 if they use the password trululu. +You can also specify a list of restricted sites. For example, if you +want to avoid to have more than one personne on a same adress +containing "ppp", just put + +RESTRICTED *!*@*ppp* + ------------------------------------------------------------------------------- V - TROPBOT FUNCTIONS --------------------------------------------------------- ------------------------------------------------------------------------------- @@ -212,6 +231,8 @@ usefull against clone bots. anti-flood system for the given duration. This feature is interesting when the bot lagged because of network troubles. +"cop" switch the cop-mode on/off + "deban { list of patterns }" (alias "db") remove from the ban-list all the entries who match one of the pattern @@ -315,7 +336,8 @@ VI - CONCLUSION/BUGS ---------------------------------------------------------- A bot is a complex program. This one, even if it's not very long has to deal with many buffers and strings operations. Such kind of program can't be 100% safe. I hope current version is stable, but I fear some -buggs are still creeping somewhere. +buggs are still creeping somewhere. The last version was checked with +Purify and is supposed to be kinda stable. ------------------------------------------------------------------------------- - AUTHOR ---------------------------------------------------------------------- @@ -330,12 +352,6 @@ I really DON'T appreciate questions about compilation, and I HATE questions whose answers are in this file. I appreciate suggestions and bug reports :P -Snail mail : - - Francois Fleuret - 16 Rue Pasteur - 78330 Fontenay le Fleury, FRANCE - ------------------------------------------------------------------------------- - ACKNOWLEDGEMENT ------------------------------------------------------------- ------------------------------------------------------------------------------- diff --git a/objects.cc b/objects.cc index 7b305fc..14765d2 100644 --- a/objects.cc +++ b/objects.cc @@ -7,6 +7,19 @@ extern int current_time; //----------------------------------------------------------------------------- +WaitPing::WaitPing(char *n, char *v, int t) +{ + nick = strdup(n); + value = strdup(v); + time_max = t; +}; + +WaitPing::~WaitPing() +{ + delete[] nick; + delete[] value; +}; + WaitInfos::WaitInfos(char *n, char *c, DCCChat *ch, char *u, int m, int d) { nick = strdup(n); @@ -19,9 +32,9 @@ WaitInfos::WaitInfos(char *n, char *c, DCCChat *ch, char *u, int m, int d) WaitInfos::~WaitInfos() { - delete nick; - delete comment; - delete user; + delete[] nick; + delete[] comment; + delete[] user; }; Welcome::Welcome(char *p, char *c, int time) @@ -33,8 +46,8 @@ Welcome::Welcome(char *p, char *c, int time) Welcome::~Welcome() { - delete pattern; - delete comment; + delete[] pattern; + delete[] comment; }; //----------------------------------------------------------------------------- @@ -49,9 +62,9 @@ DelayModeChange::DelayModeChange(char *w, char *m, char *p, int delay) DelayModeChange::~DelayModeChange() { - delete where; - delete mode; - delete parameter; + delete[] where; + delete[] mode; + delete[] parameter; }; //----------------------------------------------------------------------------- @@ -65,7 +78,7 @@ Person::Person(char *p, int l, char *pwd) Person::~Person() { - delete pattern; + delete[] pattern; }; //----------------------------------------------------------------------------- @@ -79,7 +92,7 @@ DCCChat::DCCChat(char *p, int s, int l) DCCChat::~DCCChat() { - delete prefix; + delete[] prefix; }; //----------------------------------------------------------------------------- diff --git a/objects.h b/objects.h index 48a92a8..fbfa6ff 100644 --- a/objects.h +++ b/objects.h @@ -35,6 +35,16 @@ public: ~DCCChat(); }; +class WaitPing +{ +public: + char *nick, *value; + int time_max; +public: + WaitPing(char *n, char *v, int t); + ~WaitPing(); +}; + class WaitInfos { public: diff --git a/secure.cc b/secure.cc new file mode 100644 index 0000000..ee181a5 --- /dev/null +++ b/secure.cc @@ -0,0 +1,278 @@ + +#include "secure.h" + +/*****************************************************************/ + +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +typedef unsigned long word32; +typedef unsigned char byte; + +struct xMD5Context { + word32 buf[4]; + word32 bytes[2]; + word32 in[16]; +}; + +void xMD5Init(struct xMD5Context *context); +void xMD5Update(struct xMD5Context *context, byte const *buf, int len); +void xMD5Final(byte digest[16], struct xMD5Context *context); +void xMD5Transform(word32 buf[4], word32 const in[16]); + + +/* + * Shuffle the bytes into little-endian order within words, as per the + * MD5 spec. Note: this code works regardless of the byte order. + */ +void +byteSwap(word32 *buf, unsigned words) +{ + byte *p = (byte *)buf; + + do { + *buf++ = (word32)((unsigned)p[3] << 8 | p[2]) << 16 | + ((unsigned)p[1] << 8 | p[0]); + p += 4; + } while (--words); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +xMD5Init(struct xMD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bytes[0] = 0; + ctx->bytes[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +xMD5Update(struct xMD5Context *ctx, byte const *buf, int len) +{ + word32 t; + + /* Update byte count */ + + t = ctx->bytes[0]; + if ((ctx->bytes[0] = t + len) < t) + ctx->bytes[1]++; /* Carry from low to high */ + + t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ + if ((unsigned)t > len) { + bcopy(buf, (byte *)ctx->in + 64 - (unsigned)t, len); + return; + } + /* First chunk is an odd size */ + bcopy(buf,(byte *)ctx->in + 64 - (unsigned)t, (unsigned)t); + byteSwap(ctx->in, 16); + xMD5Transform(ctx->buf, ctx->in); + buf += (unsigned)t; + len -= (unsigned)t; + + /* Process data in 64-byte chunks */ + while (len >= 64) { + bcopy(buf, ctx->in, 64); + byteSwap(ctx->in, 16); + xMD5Transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + bcopy(buf, ctx->in, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +xMD5Final(byte digest[16], struct xMD5Context *ctx) +{ + int count = (int)(ctx->bytes[0] & 0x3f); /* Bytes in ctx->in */ + byte *p = (byte *)ctx->in + count; /* First unused byte */ + + /* Set the first char of padding to 0x80. There is always room. */ + *p++ = 0x80; + + /* Bytes of padding needed to make 56 bytes (-8..55) */ + count = 56 - 1 - count; + + if (count < 0) { /* Padding forces an extra block */ + bzero(p, count+8); + byteSwap(ctx->in, 16); + xMD5Transform(ctx->buf, ctx->in); + p = (byte *)ctx->in; + count = 56; + } + bzero(p, count+8); + byteSwap(ctx->in, 14); + + /* Append length in bits and transform */ + ctx->in[14] = ctx->bytes[0] << 3; + ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; + xMD5Transform(ctx->buf, ctx->in); + + byteSwap(ctx->buf, 4); + bcopy(ctx->buf, digest, 16); + bzero(ctx,sizeof(ctx)); +} + + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f,w,x,y,z,in,s) \ + (w += f(x,y,z) + in, w = (w<>(32-s)) + x) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +xMD5Transform(word32 buf[4], word32 const in[16]) +{ + register word32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + + +void MD5(void *dest, void *orig, int len) +{ + struct xMD5Context context; + + xMD5Init(&context); + xMD5Update(&context, orig, len); + xMD5Final(dest, &context); +} + +void secure_nick(char *result, char *user, char *host, char *key, int time) +{ + int k; + char *s, *t; + char *code = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + char src[SECURE_BUFFER_SIZE], dst[16]; + + sprintf(src, "%s%s%s%d", user, host, key, time); + MD5(dst, src, strlen(src)); + + s = dst; t = result; + for(k=0; k"<"<"<"< +#include +#include + +#define SECURE_BUFFER_SIZE 1024 +#define NICK_LENGTH 9 + +void secure_nick(char *result, char *user, char *host, char *key, int time); + +#endif diff --git a/tblib.cc b/tblib.cc index b396fe9..4347aa5 100644 --- a/tblib.cc +++ b/tblib.cc @@ -421,31 +421,6 @@ int call_socket(char *hostname, unsigned short portnum) sa.sin_port = (unsigned short) htons(portnum); - - -/* - if(is_numeric(hostname)) - { -// if ((hp = gethostbyaddr(hostname)) == NULL) - cerr<<"*** Can't use numeric IP ***\n"; - return -1; - } - else - { - if ((hp = gethostbyname(hostname)) == NULL) - return -1; - }; - - cout<<"HP->H_ADDR >"; - for(int k=0; kh_length; k++) cout<<"["<h_addr[k]<<"]"; - cout<<"<\n"; - - memset(&sa,0,sizeof(sa)); - memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); - sa.sin_family= hp->h_addrtype; - sa.sin_port= htons((u_short)portnum); -*/ - if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0) /* get socket */ return(-1); @@ -477,7 +452,7 @@ int establish(unsigned short portnum) if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */ return(-1); - if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) + if (bind(s,(struct sockaddr *) &sa,sizeof(struct sockaddr_in)) < 0) { close(s); return(-1); /* bind address to socket */ @@ -511,92 +486,76 @@ int slice_buffer(char *&src, char *endsrc, char *s; - s = src; - while((*s != '\r') && (*s != '\n') && (s *node; - for(node = first; node != NULL; node = node->next) - cout<body<<"\n"; + return 0; }; +//----------------------------------------------------------------------------- + void ListChar::Clear() { NodeList *node, *next; @@ -604,7 +563,7 @@ void ListChar::Clear() while(node != NULL) { next = node->next; - delete node->body; + delete[] node->body; delete node; node = next; }; @@ -628,14 +587,17 @@ void ListChar::Remove(char *s) while(node != NULL) { next = node->next; + if(strcmp(node->body, s) == 0) { if(pred == NULL) first = next; else pred->next = next; - delete node->body; + + delete[] node->body; delete node; } else pred = node; + node = next; }; }; diff --git a/tblib.h b/tblib.h index c5c1de7..37ba7e3 100644 --- a/tblib.h +++ b/tblib.h @@ -15,7 +15,12 @@ #include #ifdef _AIX +#include +#include #include +#include +#include +#include #endif #include @@ -88,7 +93,7 @@ int are_same_site(char *u1, char *u2); //----------------------------------------------------------------------------- void concat_pattern_from_host(char *result, char *host); -char *patter_from_prefix(char *prefix, int site_ban, char *&pattern); +char *pattern_from_prefix(char *prefix, int site_ban); //----------------------------------------------------------------------------- @@ -140,7 +145,6 @@ int slice_buffer(char *&src, char *endsrc, class ListChar : public List { public: - void Print(); void Clear(); void Add(char *s); void Remove(char *s); diff --git a/tropbot.cc b/tropbot.cc index 13b85b2..f3f2161 100644 --- a/tropbot.cc +++ b/tropbot.cc @@ -1,12 +1,12 @@ /*----------------------------------------------------------------------------- - TropBot, a small IRC bot, v2.6 Dec 95 - Oct 96 + TropBot, a small IRC bot, v2.9 Dec 95 - Oct 96 Witten by Francois Fleuret. Contact for comments & bug reports Check http://www.eleves.ens.fr:8080/home/fleuret for latest version -----------------------------------------------------------------------------*/ -#define VERSION "v2.6.3a" -#define OPTIONS " + patch for mode -ko stuff" +#define VERSION "v2.9.2d" +#define OPTIONS "" #include #include @@ -21,6 +21,10 @@ //----------------------------------------------------------------------------- #define SCREEN_OUTPUT +#define ERROR_OUTPUT + +//#define ANTI_SPOOF +#define ANTI_SPOOF_MAX_TIME 300 //----------------------------------------------------------------------------- @@ -70,7 +74,17 @@ #define HISTORY_SIZE 3 -enum { FL_NOTICE, FL_PUBLIC, FL_CTCP, FL_NICK, FL_PART, FL_JOIN }; +enum { FL_NOTICE, FL_PUBLIC, FL_CTCP, FL_NICK, FL_PART, FL_JOIN, FL_KICK }; + +//----------------------------------------------------------------------------- + +// More than 3 kicks in 5 minutes -> 30 mins shit + +#define COP_NB_KICKS 3 +#define COP_NB_BANS 3 +#define COP_DELAY 300 +#define COP_DURATION 1800 +#define COP_DELAY_BEETWEEN_KICKS 2 //----------------------------------------------------------------------------- @@ -98,6 +112,8 @@ int op_delay = DEFAULT_OP_DELAY; int deban_delay = DEFAULT_DEBAN_DELAY; char control_char = DEFAULT_CONTROL_CHAR; +int cop_mode; + int delay; timeval delay_pause; time_t current_time, time_killed, time_last_datas, last_answer_time, @@ -118,6 +134,7 @@ template class List; template class List; template class List; template class List; +template class List; template class List; template class List; @@ -125,6 +142,7 @@ List dcc_chat_list; List level_list; List shit_list; List wait_list; +List wait_ping; List mode_change_list; ListChar present_people, banid_list, restricted_list, history; @@ -338,8 +356,10 @@ void write_irc(char *stuff) // I'd like to know why do I have to do such a cast ?!?! if((int) write(socket_irc, stuff, strlen(stuff)) < 0) { +#ifdef ERROR_OUTPUT cerr<<"KILLING CONNECTION : write_irc error\n"; cerr.flush(); +#endif kill_connection(); } else @@ -481,7 +501,7 @@ void smart_shit(DCCChat *chat, char *nick, sprintf(IRC_buffer, "Shit %s for %s (%s)\n", pattern, string_duration, comment); tell(chat, nick, IRC_buffer); - delete string_duration; + delete[] string_duration; } } else if((nick != NULL) || (chat != NULL)) @@ -621,17 +641,24 @@ void synch(char *channel) { nick = cut_nick_from_prefix(node->body); add_mode(channel, "+o", nick); - delete nick; + delete[] nick; } } //----------------------------------------------------------------------------- +ListChar already_kicked; + void filter_kick(char *where, char *pattern, char *comment) { NodeList *node; char *nick; - for(node = present_people.first; node != NULL; node = node->next) + + if(already_kicked.Contains(pattern)) return; + + already_kicked.Add(pattern); + for(node = present_people.first; node != NULL; + node = node->next) { if(match_pattern(pattern, node->body)) if(level_person(node->body, NULL) == 0) @@ -639,7 +666,7 @@ void filter_kick(char *where, char *pattern, char *comment) nick = cut_nick_from_prefix(node->body); sprintf(IRC_buffer, "KICK %s %s :%s\n", where, nick, comment); write_irc(IRC_buffer); - delete nick; + delete[] nick; } } } @@ -684,13 +711,13 @@ public: weigth = w; } - ~FloodLine() { delete prefix; } + ~FloodLine() { delete[] prefix; } void Reset() { individual = 0; site = 0; } }; template class List; -List flood_list; +List flood_list, kick_list; //----------------------------------------------------------------------------- @@ -748,7 +775,7 @@ void alert(char *where, DCCChat *chat, char *nick) { duration = DEFAULT_SHIT_TIME; r = pattern; - *r++ = '*'; *r++ = '!'; *r++ = '*'; *r++ = '@'; + concat(r, "*!*@"); concat_pattern_from_host(r, guilty_site); add_mode(where, "+m", NULL); smart_shit(NULL, NULL, pattern, "Alert", duration); @@ -804,15 +831,15 @@ void check_one_flood(NodeList *node) mode_change_list.Insert(new DelayModeChange(current_channel, "-b", banid, BAN_FLOOD_DELAY)); - delete banid; - delete pattern; + delete[] banid; + delete[] pattern; } #endif nick = cut_nick_from_prefix(node->body->prefix); sprintf(IRC_buffer, "KICK %s %s :%s\n", current_channel, nick, "Flood"); write_irc(IRC_buffer); - delete nick; + delete[] nick; for(son = flood_list.first; son != NULL; son = son->next) { @@ -834,7 +861,7 @@ void check_flood() while(node != NULL) { next = node->next; - if(node->body->time >= current_time - FLOOD_DELAY) + if(current_time <= node->body->time + FLOOD_DELAY) { nb_lines += node->body->weigth; if((node->body->kind == FL_CTCP) && !node->body->alreadykicked) @@ -886,6 +913,143 @@ inline void add_flood_line(char *prefix, int kind, int weigth) flood_list.Insert(new FloodLine(prefix, kind, weigth)); } +int bad_line(char *line, char *comment) +{ + int length, nb_art_chars, longest_word, nb_caps, nb_letters, nb_ctrl; + int l, bad; + unsigned char *s; + char *t; + + nb_ctrl = 0; + nb_art_chars = 0; + nb_caps = 0; + nb_letters = 0; + length = 0; + l = 0; + longest_word = 0; + + for(s=(unsigned char *)line; *s != '\0'; s++) + { + if((*s >= 'A') && (*s <= 'Z')) nb_caps++; + if(((*s >= 'A') && (*s <= 'Z')) || + ((*s >= 'a') && (*s <= 'z'))) nb_letters++; + if((*s > 2) && (*s < 31)) nb_ctrl++; + if((*s != ' ') && (*s != '?') && (*s != '!') && + (((*s >= 32) && (*s <= 47)) || + ((*s >= 58) && (*s <= 63)) || + ((*s >= 91) && (*s <= 96)) || + (*s >= 123))) nb_art_chars++; + + if(s > (unsigned char *) line) + { + if(*s == *(s-1)) l++; + else + { + if(l > longest_word) longest_word = l; + l = 0; + } + } + + length++; + } + if(l > longest_word) longest_word = l; + + t = comment; + + bad = 0; + if(longest_word > 60) + { + bad = 1; + concat(t, "repeated chars"); + } + + if(nb_ctrl > 0) + { + if(bad) concat(t, " + "); + concat(t, "control chars"); + bad = 1; + } + + if((nb_art_chars > nb_letters) && (nb_art_chars >= 20)) + { + if(bad) concat(t, " + "); + concat(t, "art chars"); + bad = 1; + } + + if((nb_caps*4 > nb_letters*3) && (nb_caps >= 10)) + { + if(bad) concat(t, " + "); + concat(t, "caps"); + bad = 1; + } + + *t = '\0'; + + return bad; +} + +void test_kick(char *prefix) +{ + int nb_kicks; + int last_kick_time; + NodeList *node, *next, *pred; + char *pattern, *banid, *loginathost; + + loginathost = reach_loginathost(prefix); + + nb_kicks = 0; + last_kick_time = current_time + COP_DELAY_BEETWEEN_KICKS + 1; + pred = NULL; + node = kick_list.first; + while(node != NULL) + { + next = node->next; + if(current_time <= node->body->time + COP_DELAY) + { + if(strcmp(loginathost, reach_loginathost(node->body->prefix)) == 0) + { + if(node->body->time < last_kick_time - COP_DELAY_BEETWEEN_KICKS) + { + nb_kicks += node->body->weigth; + last_kick_time = node->body->time; + } + } + pred = node; + } + else + { + if(pred == NULL) kick_list.first = next; + else pred->next = next; + delete node->body; + delete node; + } + node = next; + } + + if(nb_kicks >= COP_NB_KICKS) + { + pattern = pattern_from_prefix(prefix, 0); + banid = clean_banid(pattern); + + smart_shit(NULL, NULL, + pattern, "cop : too many kicks", COP_DURATION + deban_delay); + smart_ban(current_channel, pattern); + send_mode(current_channel); + filter_kick(current_channel, pattern, "cop : too many kicks"); + + delete[] banid; + delete[] pattern; + } +} + +inline void add_kick(char *prefix) +{ + if(level_person(prefix, NULL) >= LEVEL_FRIEND) return; + kick_list.Insert(new FloodLine(prefix, FL_KICK, 1)); + test_kick(prefix); +} + //----------------------------------------------------------------------------- // This function is called for all mode changes @@ -896,6 +1060,10 @@ void IRC_ONE_MODE(char *where, char *who, int signe, char mode, char *param) { char *c, *banid; char buffer[3]; + int check_ban, nb_bans, ok; + NodeList *node; + char pattern[SMALL_BUFFER_SIZE]; + char *adr_param; if(signe < 0) buffer[0] = '-'; else buffer[0] = '+'; buffer[1] = mode; @@ -937,10 +1105,51 @@ void IRC_ONE_MODE(char *where, char *who, int signe, char mode, char *param) if(signe > 0) { + check_ban = 1; banid_list.Add(param); - banid = clean_banid(param); - if(strcmp(banid, param) != 0) smart_ban(where, banid); - delete banid; + + if(cop_mode && !is_hostname(who)) + { + adr_param = adr_beginning(param); + nb_bans = 0; + + for(node = banid_list.first; node != NULL; node = node->next) + if(are_same_site(adr_param, adr_beginning(node->body))) + nb_bans++; + + if(nb_bans >= COP_NB_BANS) + { + check_ban = 0; + c = pattern; + concat(c, "*!*@"); + concat(c, adr_param); + *c++ = '\0'; + + ok = 1; + + for(node = present_people.first; + (node != NULL) && ok; node = node->next) + if(match_pattern(pattern, node->body)) + if(level_person(node->body, NULL) >= LEVEL_FRIEND) + ok = 0; + + if(ok) + { + smart_shit(NULL, NULL, + pattern, + "cop : too many bans on one site", + COP_DURATION + deban_delay); + smart_ban(where, pattern); + } + } + } + + if(check_ban) + { + banid = clean_banid(param); + if(strcmp(banid, param) != 0) smart_ban(where, banid); + delete[] banid; + } } else banid_list.Remove(param); break; @@ -963,7 +1172,7 @@ void IRC_ONE_MODE(char *where, char *who, int signe, char mode, char *param) c = cut_nick_from_prefix(who); add_mode(where, "-o", c); add_mode(where, "+o", param); - delete c; + delete[] c; } break; @@ -1000,7 +1209,7 @@ void IRC_ONE_MODE(char *where, char *who, int signe, char mode, char *param) else add_mode(where, "+m", NULL); c = cut_nick_from_prefix(who); add_mode(where, "-o", c); - delete c; + delete[] c; } } break; @@ -1073,7 +1282,9 @@ void get_one_line(ifstream *s, char *buffer, int buffer_size) *c = '\0'; } -int LoadConfigFile(char *name) +#define MAX_INCLUDE_RECURSE 3 + +int LoadConfigFile(char *name, int recurse) { ifstream *file; int duration, level, error; @@ -1093,7 +1304,23 @@ int LoadConfigFile(char *name) { r = IRC_buffer; r = next_word(buffer, r, SMALL_BUFFER_SIZE); - if(strcmp(buffer, "FRIEND") == 0) + + if(strcmp(buffer, "INCLUDE") == 0) + { + if(r != NULL) + { + if(recurse < MAX_INCLUDE_RECURSE) + { + r = next_word(buffer, r, SMALL_BUFFER_SIZE); + LoadConfigFile(buffer, recurse+1); + } +#ifdef ERROR_OUTPUT + else cerr<<"Can't include " + <"<"<"<body<<"\n"; - if((pattern == NULL) || match_pattern(pattern, node1->body)) { c = adr_beginning(node1->body); @@ -1317,7 +1542,7 @@ void notice_list_by_sites(DCCChat *chat, char *nick, char *pattern) nb_person[LEVEL_MASTER]); tell(chat, nick, IRC_buffer); - delete ok; + delete[] ok; } //----------------------------------------------------------------------------- @@ -1345,7 +1570,7 @@ void notice_shit_list(DCCChat *chat, char *nick, char *pattern, int matched) string_duration, node->body->comment); tell(chat, nick, IRC_buffer); - delete string_duration; + delete[] string_duration; } if(n == 0) tell(chat, nick, "\002No corresponding shits\002\n"); @@ -1378,7 +1603,7 @@ void add_in_history(char *prefix, char *action) { if(pred == NULL) history.first = next; else pred->next = next; - delete node->body; + delete[] node->body; delete node; } else pred = node; @@ -1423,7 +1648,7 @@ void msg_users(DCCChat *chat, char *nick, char *pattern, char *msg) sprintf(IRC_buffer, "PRIVMSG %s :\002[msg to %s]\002 %s\n", nick_user, pattern, msg); write_irc(IRC_buffer); - delete nick_user; + delete[] nick_user; } } @@ -1474,6 +1699,18 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) { if(dont_flood_server()) notice_shit_list(chat, nick, prefix, 0); } + else if(eq("write", buffer) || eq("wr", buffer)) + { + if(level >= LEVEL_MASTER) + { + if(r != NULL) + { + sprintf(IRC_buffer, "PRIVMSG %s :%s\n", current_channel, r); + write_irc(IRC_buffer); + } + } + else no_authorized = 1; + } else if(eq("sl", buffer) || eq("shitlist", buffer)) { if(level >= LEVEL_FRIEND) @@ -1483,7 +1720,8 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) r = next_word(buffer, r, SMALL_BUFFER_SIZE); uncap(buffer); - if(is_pattern(buffer)) notice_shit_list(chat, nick, buffer, 1); + if(is_pattern(buffer)) + notice_shit_list(chat, nick, buffer, 1); else { wait_list.Insert(new WaitInfos(buffer, NULL, chat, nick, @@ -1493,7 +1731,27 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) write_irc(IRC_buffer); } } - else notice_shit_list(chat, nick, "*", 1); + else + { + int s1, s2, s3, s4, d; + NodeList *node; + s1 = 0; s2 = 0; s3 = 0; s4 = 0; + for(node=shit_list.first; node != NULL; node=node->next) + { + d = node->body->time_max - current_time; + if(d < 1800) s1++; + else if(d < 4*3600) s2++; + else if(d < 24*3600) s3++; + else s4++; + } + + sprintf(IRC_buffer, + "%d entries " + "\002%d\002 < 30min < \002%d\002 < " + "4h < \002%d\002 < 24h < \002%d\002\n", + s1+s2+s3+s4, s1, s2, s3, s4); + tell(chat, nick, IRC_buffer); + } } else no_authorized = 1; } @@ -1511,15 +1769,6 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) else while(r != NULL) { r = next_word(buffer, r, SMALL_BUFFER_SIZE); - /* - if(!is_pattern(buffer)) - { - s = buffer; - while(*s != '\0') s++; - concat(s, "!*"); - *s++ == '\0'; - } - */ uncap(buffer); notice_list_by_sites(chat, nick, buffer); } @@ -1528,23 +1777,27 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) } else if(eq("ao", buffer) || eq("antifloodoff", buffer)) { - if(r != NULL) - { - r = next_word(buffer_time, r, SMALL_BUFFER_SIZE); - duration = string_to_seconds(buffer_time); - anti_flood_off_until = current_time + duration; - } - if(anti_flood_off_until > current_time) + if(level >= LEVEL_OP) { - string_duration = seconds_to_string(anti_flood_off_until - - current_time); - sprintf(IRC_buffer, "Anti-flood off for %s\n", - string_duration); - delete string_duration; - - tell(chat, nick, IRC_buffer); + if(r != NULL) + { + r = next_word(buffer_time, r, SMALL_BUFFER_SIZE); + duration = string_to_seconds(buffer_time); + anti_flood_off_until = current_time + duration; + } + if(anti_flood_off_until > current_time) + { + string_duration = seconds_to_string(anti_flood_off_until - + current_time); + sprintf(IRC_buffer, "Anti-flood off for %s\n", + string_duration); + delete[] string_duration; + + tell(chat, nick, IRC_buffer); + } + else tell(chat, nick, "Anti-flood on\n"); } - else tell(chat, nick, "Anti-flood on\n"); + else no_authorized = 1; } else if(eq("msg", buffer) || eq("message", buffer)) { @@ -1599,29 +1852,36 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) } else no_authorized = 1; } - else if(eq("help", buffer)) + else if(eq("mode", buffer)) { if(dont_flood_server() || (level >= LEVEL_FRIEND)) { + char *a; + if(cop_mode) a = "ON"; else a = "OFF"; if(father) { sprintf(IRC_buffer, - "control_char '%c' op_delay %ds deban_delay %ds" + "control_char '%c' op_delay %ds deban_delay %ds " + "cop-mode %s" " your level is %d. I am a father with %d sons.\n", - control_char, op_delay, deban_delay, + control_char, op_delay, deban_delay, a, level, nb_sons); tell(chat, nick, IRC_buffer); } else { sprintf(IRC_buffer, - "control_char '%c' op_delay %ds deban_delay %ds" + "control_char '%c' op_delay %ds deban_delay %ds " + "cop-mode %s" " your level is %d. I'm a clone.\n", - control_char, op_delay, deban_delay, level); + control_char, op_delay, deban_delay, a, + level); tell(chat, nick, IRC_buffer); } } - + } + else if(eq("help", buffer)) + { if(level >= LEVEL_FRIEND) { tell(chat, nick, "\002help\002 \002www\002 \002\037s\037\002hit\037l\037\002ist\002 [!] \002level\002 [] \002\037w\037\002ho\002 \002\037m\037\002y\037s\037\002hit\002\n"); @@ -1629,7 +1889,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) if(level >= LEVEL_OP) { - tell(chat, nick, "\002\037a\037\002ntiflood\037o\037\002ff\002 [] \002\037a\037\002lert\002 \002home\002 \002op\002 [{ list}] \002join\002 <#channel> \002nick\002 \002\037p\037\002rune\037b\037\002an\002 \002\037d\037\002e\037b\037\002an\002 { list} \002\037f\037\002ilter\037k\037\002ick\002 ! [] \002\037s\037\002hit/\037s\037\002hit\037s\037\002ite/\037s\037\002hit\037h\037\002ost\002 ! [ []] \002\037u\037\002n\037s\037\002hit\002 {! list} \002\037pu\037\002n\037s\037\002hit\002 { list} \002\037b\037\002an/\037s\037\002ite\037b\037\002an\002 ! \002synch\002 \002\037h\037\002istory\002\n \002\037m\037\002es\037s\037\002a\037g\037\002e\002 ! \n"); + tell(chat, nick, "\002\037a\037\002ntiflood\037o\037\002ff\002 [] \002\037a\037\002lert\002 \002home\002 \002cop\002 \002op\002 [{ list}] \002join\002 <#channel> \002nick\002 \002\037p\037\002rune\037b\037\002an\002 \002\037d\037\002e\037b\037\002an\002 { list} \002\037f\037\002ilter\037k\037\002ick\002 ! [] \002\037s\037\002hit/\037s\037\002hit\037s\037\002ite/\037s\037\002hit\037h\037\002ost\002 ! [ []] \002\037u\037\002n\037s\037\002hit\002 {! list} \002\037pu\037\002n\037s\037\002hit\002 { list} \002\037b\037\002an/\037s\037\002ite\037b\037\002an\002 ! \002synch\002 \002\037h\037\002istory\002\n \002\037m\037\002es\037s\037\002a\037g\037\002e\002 ! \n"); } if(level >= LEVEL_MASTER) @@ -1695,7 +1955,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) } else if(eq("db", buffer) || eq("deban", buffer)) { - if(level >= LEVEL_FRIEND) + if(level >= LEVEL_OP) { while(r != NULL) { @@ -1730,7 +1990,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) { banid = clean_banid(buffer); smart_ban(current_channel, banid); - delete banid; + delete[] banid; } else { @@ -1779,6 +2039,16 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) if(level >= LEVEL_OP) synch(current_channel); else no_authorized = 1; } + else if(eq("cop", buffer)) + { + if(level >= LEVEL_OP) + { + cop_mode = !cop_mode; + if(cop_mode) tell(chat, nick, "cop mode ON\n"); + else tell(chat, nick, "cop mode OFF\n"); + } + else no_authorized = 1; + } else if(eq("s", buffer) || eq("shit", buffer)) { if(level >= LEVEL_OP) @@ -1801,7 +2071,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) uncap(buffer); banid = clean_banid(buffer); smart_shit(chat, nick, banid, r, duration); - delete banid; + delete[] banid; } else { @@ -2033,7 +2303,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) if((od>=0) && (od <= 60)) { op_delay = od; - sprintf(IRC_buffer,"Oping delay set to %ds\n", op_delay); + sprintf(IRC_buffer,"Op delay set to %ds\n", op_delay); tell(chat, nick, IRC_buffer); } } @@ -2108,8 +2378,10 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) sprintf(IRC_buffer, "QUIT :Changing server\n"); write_irc(IRC_buffer); +#ifdef ERROR_OUTPUT cerr<<"KILLING CONNECTION : Changing server\n"; cerr.flush(); +#endif kill_connection(); } } @@ -2162,7 +2434,7 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) if(level >= LEVEL_MASTER) { if(r != NULL) r = next_word(config_file, r, SMALL_BUFFER_SIZE); - if(LoadConfigFile(config_file)) + if(LoadConfigFile(config_file, 0)) { sprintf(IRC_buffer, "Can't load the %s configuration file\n", @@ -2184,8 +2456,10 @@ void tropbot_cmd(DCCChat *chat, char *prefix, char *nick, char *msg) { sprintf(IRC_buffer, "QUIT :reset command sent by %s\n", nick); write_irc(IRC_buffer); +#ifdef ERROR_OUTPUT cerr<<"KILLING CONNECTION : Die\n"; cerr.flush(); +#endif kill_connection(); } else no_authorized = 1; @@ -2284,45 +2558,146 @@ int accepting_dcc_chat(char *prefix, char *nick, int level, char *r) //----------------------------------------------------------------------------- -// This function is called after a NOTICE +void pong_reply(char *nick, char *value) +{ + NodeList *node, *next, *pred; + + cout<<"pong_reply : nick >"<"<next; + if(current_time > node->body->time_max) + { + if(pred == NULL) wait_ping.first = next; + else pred->next = next; + delete node->body; + delete node; + } + if(strcmp(nick, node->body->nick) == 0) + { + if(strcmp(value, node->body->value) == 0) + add_mode(current_channel, "+o", nick); + if(pred == NULL) wait_ping.first = next; + else pred->next = next; + delete node->body; + delete node; + } + else pred = node; + node = next; + } +} + +// This function is called after a NOTICE void IRC_NOTICE(char *prefix, char *who, char *msg, char **slice_ctcp, int n_ctcp) { + int k; + char word[SMALL_BUFFER_SIZE], *r, *nick; uncap(who); if(strcmp(who, current_channel) == 0) add_flood_line(prefix, FL_NOTICE, 1); +#ifdef ANTI_SPOOF + else if(strcmp(who, real_nick) == 0) + for(k=0; k"< 0) add_flood_line(prefix, FL_CTCP, n_ctcp); - } + if(n_ctcp > 0) + { + add_flood_line(prefix, FL_CTCP, n_ctcp); + + if((cop_mode) && (level < LEVEL_FRIEND)) + { + ctcp = 0; + for(k = 0; (k0) { if(msg[0] == control_char) tropbot_cmd(NULL, prefix, nick, msg+1); - else if(strcmp(who, real_nick) == 0) tropbot_cmd(NULL, prefix, nick, msg); + else if(strcmp(who, real_nick) == 0) + tropbot_cmd(NULL, prefix, nick, msg); } - - version = 0; ping = 0; for(k=0; k" + "Contact THX-1138 on IRCNet, or " "\001\n", nick); write_irc(IRC_buffer); @@ -2355,7 +2730,6 @@ void IRC_PRIVMSG(char *prefix, // DCC (chat) else if(eq("DCC", buffer)) { - level = level_person(prefix, NULL); if(level >= LEVEL_OP) { if(r != NULL) @@ -2387,7 +2761,7 @@ void IRC_PRIVMSG(char *prefix, } } } - delete nick; + delete[] nick; } //----------------------------------------------------------------------------- @@ -2441,7 +2815,7 @@ void IRC_PART(char *prefix, char *where) present_people.Clear(); in_channel = 0; } - delete nick; + delete[] nick; } //----------------------------------------------------------------------------- @@ -2450,7 +2824,7 @@ void IRC_PART(char *prefix, char *where) void IRC_KICK(char *prefix, char *where, char *victim_nick) { - char *c; + char *c, *d; uncap(victim_nick); if(strcmp(victim_nick, real_nick) == 0) @@ -2461,17 +2835,23 @@ void IRC_KICK(char *prefix, char *where, char *victim_nick) write_irc(IRC_buffer); } + c = strdup(prefix_from_nick(victim_nick)); + if((level_person(prefix, NULL) < level_person(prefix_from_nick(victim_nick), NULL)) && (level_person(prefix_from_nick(victim_nick), NULL) > 0)) { - c = cut_nick_from_prefix(prefix); - add_mode(where, "-o", c); - delete c; + d = cut_nick_from_prefix(prefix); + add_mode(where, "-o", d); + delete[] d; } + else if(cop_mode && (c != NULL)) add_kick(c); - c = prefix_from_nick(victim_nick); if(c != NULL) present_people.Remove(c); +#ifdef ERROR_OUTPUT else cerr<<"** ERROR : non present person has been kicked out **\n"; +#endif + + delete[] c; } //----------------------------------------------------------------------------- @@ -2500,7 +2880,7 @@ int check_restricted(char *where, char *prefix) concat(s, "*!*@"); concat(s, p); *s++ = '\0'; - duration = DEFAULT_RESTRICTED_TIME; + duration = DEFAULT_RESTRICTED_TIME + deban_delay; smart_shit(NULL, NULL, pattern, "Restricted site : no clones", duration); smart_ban(where, pattern); send_mode(where); @@ -2515,8 +2895,9 @@ int check_restricted(char *where, char *prefix) void IRC_JOIN(char *prefix, char *where) { char *nick; - int l, restricted; + int k, l, restricted; NodeList *node; + char buffer[SMALL_BUFFER_SIZE]; nick = cut_nick_from_prefix(prefix); @@ -2536,20 +2917,35 @@ void IRC_JOIN(char *prefix, char *where) uncap(where); present_people.Add(prefix); - if(restricted_list.Matches(prefix)) + l = level_person(prefix, NULL); + + if((l < LEVEL_FRIEND) && (restricted_list.Matches(prefix))) restricted = check_restricted(where, prefix); else restricted = 0; if(!restricted) { - l = level_person(prefix, NULL); - +#ifdef ANTI_SPOOF + if(l >= LEVEL_FRIEND) + { + for(k=0; k<10; k++) buffer[k] = 'a'+int(rand()%26); + buffer[10] = '\0'; + wait_ping.Insert(new WaitPing(nick, buffer, + current_time+ANTI_SPOOF_MAX_TIME)); + sprintf(IRC_buffer, "PRIVMSG %s :\001PING %s\001\n", + nick, buffer); + write_irc(IRC_buffer); + } +#endif + if(l >= LEVEL_OP) { +#ifndef ANTI_SPOOF if(l >= LEVEL_DEFENCE) add_mode(where, "+o", nick); else mode_change_list.Insert(new DelayModeChange(where, "+o", nick, op_delay)); +#endif } else { @@ -2576,7 +2972,7 @@ void IRC_JOIN(char *prefix, char *where) } } - delete nick; + delete[] nick; } //----------------------------------------------------------------------------- @@ -2775,7 +3171,7 @@ void IRC_RPL_WHOISUSER(char *prefix, } - delete banid; + delete[] banid; if(pred == NULL) wait_list.first = next; else pred->next = next; @@ -2811,7 +3207,9 @@ void IRC_RPL_WHOREPLY(char *prefix, *s++ = '\0'; present_people.Add(IRC_buffer); } +#ifdef ERROR_OUTPUT else cerr< 0) for(k=0; k"; cout<<"\n"; + for(k=0; k 0) for(k=0; k"; + cout<<"\n"; #endif if(prefix != NULL) uncap(prefix); @@ -2891,7 +3293,7 @@ void get_command(char *prefix, { if(n_cmd > 0) if(eq("PING", cmd)) { - if(n_cmd > 2) sprintf(IRC_buffer, "PONG :%s\n", slice_cmd[1]); + if(n_cmd >= 2) sprintf(IRC_buffer, "PONG :%s\n", slice_cmd[1]); else sprintf(IRC_buffer, "PONG\n"); write_irc(IRC_buffer); } @@ -2958,13 +3360,17 @@ void get_options(int argc, char **argv) { n++; if(n=1) socket_delay = d; +#ifdef ERROR_OUTPUT else cerr<<"*** Delay error ***\n"; +#endif } +#ifdef ERROR_OUTPUT else cerr<<"*** No delay parameter ***\n"; +#endif } else if(eq("-od", argv[n])) { @@ -3018,9 +3442,13 @@ void get_options(int argc, char **argv) { d = atoi(argv[n]); if(d>=1) op_delay = d; +#ifdef ERROR_OUTPUT else cerr<<"*** Op delay error ***\n"; +#endif } +#ifdef ERROR_OUTPUT else cerr<<"*** No delay parameter ***\n"; +#endif } else if(eq("-dd", argv[n])) { @@ -3029,19 +3457,26 @@ void get_options(int argc, char **argv) { d = atoi(argv[n]); if(d>=1) deban_delay = d; +#ifdef ERROR_OUTPUT else cerr<<"*** Deban delay error ***\n"; +#endif } +#ifdef ERROR_OUTPUT else cerr<<"*** No delay parameter ***\n"; +#endif } else if(eq("-?", argv[n])) help = 1; else { +#ifdef ERROR_OUTPUT cerr<<"*** Unknown option "<.\n"; @@ -3059,6 +3494,7 @@ void get_options(int argc, char **argv) cout<<"-p sets the server port\n"; cout<<"-? shows this help\n"; exit(0); +#endif } n++; @@ -3104,8 +3540,10 @@ void try_reconnect() } strncpy(wanted_server, default_server, MAXHOSTNAME+1); wanted_port = default_port; +#ifdef ERROR_OUTPUT cerr<<"*** Can't contact IRC server ***\n"; cerr<<"*** Next try in "<= buffer+BUFFER_SIZE) { +#ifdef ERROR_OUTPUT cerr<<"*** Buffer full, erase it ***\n"; +#endif endsrc = buffer; } @@ -3146,8 +3586,10 @@ void got_datas_from_server() if(s <= 0) { +#ifdef ERROR_OUTPUT cerr<<"KILLING CONNECTION : Read error\n"; cerr.flush(); +#endif kill_connection(); } else @@ -3256,8 +3698,10 @@ int main(int argc, char **argv) level_list.Insert(new Person("*!*jolibot@*.ens.fr", LEVEL_DEFENCE, NULL)); level_list.Insert(new Person("*!*jolibot@*.curie.fr", LEVEL_DEFENCE, NULL)); +#ifdef SCREEN_OUTPUT cout<<"TropBot, written by Francois Fleuret," " contact \n"; +#endif get_options(argc, argv); @@ -3272,7 +3716,8 @@ int main(int argc, char **argv) global_state = STATE_WAIT; in_channel = 0; mode_protect_on = DEFAULT_MODE_PROTECT; - + cop_mode = 0; + FD_ZERO(&ready); alive = 1; @@ -3287,6 +3732,7 @@ int main(int argc, char **argv) delay = socket_delay; struct sigaction action; + memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; // We'll ignore the SIGPIPE signal, which will be catch somewhere else @@ -3336,8 +3782,10 @@ int main(int argc, char **argv) { if(current_time > time_last_datas+DELAY_DEAD_SERVER) { +#ifdef ERROR_OUTPUT cerr<<"KILLING CONNECTION : Quiet server\n"; cerr.flush(); +#endif kill_connection(); } else if(!in_channel) if(global_state == STATE_WAIT) @@ -3348,6 +3796,7 @@ int main(int argc, char **argv) } if(IRC_connected) check_stuffs(); + already_kicked.Clear(); } #ifdef SCREEN_OUTPUT -- 2.39.5