From 14e50ceae9029e33cec145cbd07a79c6e1aa463b Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 8 Sep 2011 05:02:27 +0200 Subject: [PATCH] added cmd_addban & simple time queue system --- DATABASE.txt | 2 ++ Makefile | 1 + bot_NeonServ.c | 5 ++- cmd_neonserv_addban.c | 81 +++++++++++++++++++++++++++++++++++++++++++ cmd_neonserv_ban.c | 3 +- main.c | 2 ++ timeq.c | 62 +++++++++++++++++++++++++++++++++ timeq.h | 21 +++++++++++ 8 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 cmd_neonserv_addban.c create mode 100644 timeq.c create mode 100644 timeq.h diff --git a/DATABASE.txt b/DATABASE.txt index 09ca9c4..c2688f0 100644 --- a/DATABASE.txt +++ b/DATABASE.txt @@ -29,3 +29,5 @@ ALTER TABLE `chanusers` ADD INDEX ( `chanuser_uid` ) ; ALTER TABLE `bot_binds` ADD `chan_access` VARCHAR( 256 ) NULL DEFAULT NULL AFTER `parameters` ALTER TABLE `bot_binds` CHANGE `global_access` `global_access` INT( 3 ) NULL + +ALTER TABLE `bans` CHANGE `ban_owner` `ban_owner` INT( 11 ) NOT NULL diff --git a/Makefile b/Makefile index bd3f3c8..0f5bdbd 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ all: gcc -g -O2 ${LIBS} -c lang.c -o lang.o ${CFLAGS} gcc -g -O2 ${LIBS} -c HandleInfoHandler.c -o HandleInfoHandler.o ${CFLAGS} gcc -g -O2 ${LIBS} -c tools.c -o tools.o ${CFLAGS} + gcc -g -O2 ${LIBS} -c timeq.c -o timeq.o ${CFLAGS} gcc -g -O2 ${LIBS} -c DBHelper.c -o DBHelper.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bots.c -o bots.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bot_NeonServ.c -o bot_NeonServ.o ${CFLAGS} diff --git a/bot_NeonServ.c b/bot_NeonServ.c index ec6615a..7a0a772 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -13,6 +13,7 @@ #include "WHOHandler.h" #include "DBHelper.h" #include "tools.h" +#include "timeq.h" #define BOTID 1 @@ -119,6 +120,7 @@ static const struct default_language_entry msgtab[] = { {"NS_WIPEINFO_DONE", "Removed \002%s\002's infoline in \002%s\002."}, {"NS_TRACE_HEADER", "The following users were found:"}, {"NS_TRACE_FOUND", "Found \002%d\002 matches."}, + {"NS_ADDBAN_DONE", "\002%s\002 permantly added to the %s ban list. (matching %d users)"}, {NULL, NULL} }; @@ -158,7 +160,7 @@ INCLUDE ALL CMD's HERE #include "cmd_neonserv_suspend.c" #include "cmd_neonserv_unsuspend.c" #include "cmd_neonserv_wipeinfo.c" -//#include "cmd_neonserv_addban.c" +#include "cmd_neonserv_addban.c" //#include "cmd_neonserv_addtimeban.c" //#include "cmd_neonserv_delban.c" //#include "cmd_neonserv_banlist.c" @@ -300,6 +302,7 @@ void init_NeonServ() { register_command(BOTID, "kickban", neonserv_cmd_kickban, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_cankick,#channel_canban", 0); register_command(BOTID, "ban", neonserv_cmd_ban, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canban", 0); register_command(BOTID, "wipeinfo", neonserv_cmd_wipeinfo, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_wipeinfo", 0); + register_command(BOTID, "addban", neonserv_cmd_addban, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_staticban", 0); register_command(BOTID, "trace", neonserv_cmd_trace, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, NULL, 400); diff --git a/cmd_neonserv_addban.c b/cmd_neonserv_addban.c new file mode 100644 index 0000000..91202d9 --- /dev/null +++ b/cmd_neonserv_addban.c @@ -0,0 +1,81 @@ + +/* +* argv[0] nick|*auth|*!*@mask +* argv[1-*] reason +*/ +static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup); +static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *mas, char *reason); + +struct neonserv_cmd_addban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + char *mask; + char *reason; +}; + +static CMD_BIND(neonserv_cmd_addban) { + struct neonserv_cmd_addban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->mask = strdup(argv[0]); + if(argc > 1) { + cache->reason = strdup(merge_argv(argv, 1, argc)); + } else + cache->reason = NULL; + get_userlist(chan, neonserv_cmd_addban_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup) { + struct neonserv_cmd_addban_cache *cache = data; + neonserv_cmd_addban_async1(cache->client, cache->textclient, cache->user, chan, cache->mask, (cache->reason ? cache->reason : "Bye.")); + free(cache->mask); + if(cache->reason) + free(cache->reason); + free(cache); +} + +static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *mask, char *reason) { + int match_count = 0; + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct UserNode *cuser; + struct ChanUser *chanuser; + check_mysql(); + mask = make_banmask(mask, hostmask_buffer); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + return; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + return; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + reply(textclient, user, "NS_LAME_MASK", mask); + return; + } + } + } + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + int userid; + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) + userid = atoi(row[0]); + else + return; + //add the ban + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', '%u', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned int) time(0), userid, escape_string(reason)); + reply(getTextBot(), user, "NS_ADDBAN_DONE", mask, chan->name, match_count); +} diff --git a/cmd_neonserv_ban.c b/cmd_neonserv_ban.c index b329131..e51934d 100644 --- a/cmd_neonserv_ban.c +++ b/cmd_neonserv_ban.c @@ -1,7 +1,6 @@ /* -* argv[0] nick[,*auth[,*!*@mask[...]]] -* argv[1-*] reason +* argv[0-*] nick[,*auth[,*!*@mask[...]]] */ static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup); static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *masks); diff --git a/main.c b/main.c index 56305fc..bcf2fb2 100644 --- a/main.c +++ b/main.c @@ -12,6 +12,7 @@ #include "HandleInfoHandler.h" #include "lang.h" #include "tools.h" +#include "timeq.h" void cleanup() { free_sockets(); @@ -46,6 +47,7 @@ int main(void) do { socket_loop(SOCKET_SELECT_TIME); } while(time(0) < socket_wait); + timeq_tick(); clearTempUsers(); } } diff --git a/timeq.c b/timeq.c new file mode 100644 index 0000000..60d92f7 --- /dev/null +++ b/timeq.c @@ -0,0 +1,62 @@ + +#include "timeq.h" + +static struct timeq_entry *timeq_events; + +void timeq_tick() { + struct timeq_entry *entry, *next; + time_t now = time(0); + for(entry = timeq_events; entry; entry = next) { + if(entry->execute <= now) { + entry->callback(entry->data); + next = entry->next; + free(entry); + } else + break; + } +} + +struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data) { + time_t now = time(0); + struct timeq_entry *entry = malloc(sizeof(*entry)); + if (!entry) + { + perror("malloc() failed"); + return NULL; + } + entry->execute = now + seconds; + entry->callback = callback; + entry->data = data; + struct timeq_entry *next, *prev = NULL; + for(next = timeq_events; next; next = next->next) { + if(next->execute >= entry->execute) + break; + else + prev = next; + } + if(prev == NULL) { + entry->next = timeq_events; + timeq_events = entry; + } else { + entry->next = next; + prev->next = entry; + } + return entry; +} + +int timeq_del(struct timeq_entry* entry) { + struct timeq_entry *centry, *last = NULL; + for(centry = timeq_events; centry; centry = centry->next) { + if(centry == entry) { + if(last) + last->next = centry->next; + else + timeq_events = centry->next; + free(centry); + return 1; + } else { + last = centry; + } + } + return 0; +} diff --git a/timeq.h b/timeq.h new file mode 100644 index 0000000..d683c9a --- /dev/null +++ b/timeq.h @@ -0,0 +1,21 @@ +#ifndef _timeq_h +#define _timeq_h + +#include "main.h" + +#define TIMEQ_CALLBACK(NAME) int NAME(UNUSED_ARG(void *data)) +typedef TIMEQ_CALLBACK(timeq_callback_t); + +struct timeq_entry { + time_t execute; + timeq_callback_t *callback; + void *data; + + struct timeq_entry *next; +}; + +void timeq_tick(); +struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data); +int timeq_del(struct timeq_entry* entry); + +#endif \ No newline at end of file -- 2.20.1