From: pk910 Date: Wed, 14 Sep 2011 22:59:57 +0000 (+0200) Subject: modified time-queue system and added cmd_addtimeban X-Git-Tag: v5.3~419 X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=c656ce0a3fd442055e09b67b3a714e8b73e880a1;p=NeonServV5.git modified time-queue system and added cmd_addtimeban --- diff --git a/bot_NeonServ.c b/bot_NeonServ.c index 502d7cb..24441fb 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -167,9 +167,14 @@ static const struct default_language_entry msgtab[] = { {"NS_UNREGISTER_DONE", "\002%s\002 unregistered."}, {"NS_RECOVER_DONE", "\002%s\002 has been recovered."}, {"NS_RESYNC_DONE", "Synchronized users in \002%s\002 with the userlist."}, + {"NS_TIMEBAN_DURATION_TOO_SHORT", "You must specify a ban duration of at least %d seconds."}, + {"NS_TIMEBAN_DONE", "Banned \002%s\002 from %s for %s. (matching %d users)"}, {NULL, NULL} }; +//define some usefull functions :D +static TIMEQ_CALLBACK(channel_ban_timeout); + /* INCLUDE ALL CMD's HERE */ @@ -207,7 +212,7 @@ INCLUDE ALL CMD's HERE #include "cmd_neonserv_unsuspend.c" #include "cmd_neonserv_wipeinfo.c" #include "cmd_neonserv_addban.c" -//#include "cmd_neonserv_addtimeban.c" +#include "cmd_neonserv_addtimeban.c" #include "cmd_neonserv_delban.c" #include "cmd_neonserv_bans.c" //#include "cmd_neonserv_open.c" @@ -313,6 +318,33 @@ static void start_bots() { } } } + + //load all timed bans + printf_mysql_query("SELECT `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_timeout` > 0"); + res = mysql_use(); + char nameBuf[20]; + while ((row = mysql_fetch_row(res)) != NULL) { + if(atol(row[1]) - time(0) > 0) { + sprintf(nameBuf, "ban_%s", row[0]); + timeq_add_name(nameBuf, atol(row[1]) - time(0), channel_ban_timeout, strdup(row[0])); + } else { + //timed out + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[0]); + } + } +} + +static TIMEQ_CALLBACK(channel_ban_timeout) { + char *str_banid = data; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `ban_mask` FROM `bans` WHERE `ban_id` = '%s'", str_banid); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + //TODO: unban if mask is still banned + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", str_banid); + } + free(str_banid); } void init_NeonServ() { @@ -354,6 +386,7 @@ void init_NeonServ() { register_command(BOTID, "topic", neonserv_cmd_topic, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_changetopic", 0); register_command(BOTID, "chanservsync", neonserv_cmd_chanservsync, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH,"500", 0); register_command(BOTID, "resync", neonserv_cmd_resync, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_canresync", 0); + register_command(BOTID, "addtimeban", neonserv_cmd_addtimeban,2, 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); register_command(BOTID, "register", neonserv_cmd_register, 2, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG, NULL, 100); diff --git a/cmd_neonserv_addtimeban.c b/cmd_neonserv_addtimeban.c new file mode 100644 index 0000000..b21a834 --- /dev/null +++ b/cmd_neonserv_addtimeban.c @@ -0,0 +1,120 @@ + +/* +* argv[0] nick|*auth|*!*@mask +* argv[1] time +* argv[2-*] reason +*/ +static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup); +static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason); + +struct neonserv_cmd_addtimeban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *mask; + int duration; + char *reason; +}; + +static CMD_BIND(neonserv_cmd_addtimeban) { + int duration = strToTime(user, argv[1]); + if(duration < 30) { + reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30); + return; + } + struct neonserv_cmd_addtimeban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->mask = strdup(argv[0]); + cache->duration = duration; + if(argc > 2) { + cache->reason = strdup(merge_argv(argv, 2, argc)); + } else + cache->reason = NULL; + get_userlist(chan, neonserv_cmd_addtimeban_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup) { + struct neonserv_cmd_addtimeban_cache *cache = data; + neonserv_cmd_addtimeban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, cache->duration, (cache->reason ? cache->reason : "Bye.")); + free(cache->mask); + if(cache->reason) + free(cache->reason); + free(cache); +} + +static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, 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; + 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; + //check if the provided mask is already banned by another ban + char *ban = getBanAffectingMask(chan, mask); + if(ban != NULL) { + reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name); + return; + } + //check if the provided mask affects any existing bans + printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!match(mask, row[0])) { + //remove the ban + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); + } + } + 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_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned long) (time(0) + duration), userid, escape_string(reason)); + int banid = (int) mysql_insert_id(mysql_conn); + putsock(client, "MODE %s +b %s", chan->name, mask); + 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)) { + putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason); + } + } + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); + reply(textclient, user, "NS_ADDTIMEBAN_DONE", mask, chan->name, timeToStr(user, duration, 2, nameBuf), match_count); + logEvent(event); +} diff --git a/cmd_neonserv_delban.c b/cmd_neonserv_delban.c index 2bd5699..016008b 100644 --- a/cmd_neonserv_delban.c +++ b/cmd_neonserv_delban.c @@ -16,11 +16,16 @@ static CMD_BIND(neonserv_cmd_delban) { return; } //check if the provided mask affects any existing bans - printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + char nameBuf[20]; + printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); res = mysql_use(); while ((row = mysql_fetch_row(res)) != NULL) { if(!match(mask, row[0])) { //remove the ban + if(strcmp(row[2], "0")) { + sprintf(nameBuf, "ban_%s", row[1]); + timeq_del_name(nameBuf); + } printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); matching_bans++; } diff --git a/timeq.c b/timeq.c index 60d92f7..c300cd4 100644 --- a/timeq.c +++ b/timeq.c @@ -27,6 +27,7 @@ struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *dat entry->execute = now + seconds; entry->callback = callback; entry->data = data; + entry->name = NULL; struct timeq_entry *next, *prev = NULL; for(next = timeq_events; next; next = next->next) { if(next->execute >= entry->execute) @@ -44,6 +45,12 @@ struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *dat return entry; } +struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data) { + struct timeq_entry *entry = timeq_add(seconds, callback, data); + entry->name = strdup(name); + return entry; +} + int timeq_del(struct timeq_entry* entry) { struct timeq_entry *centry, *last = NULL; for(centry = timeq_events; centry; centry = centry->next) { @@ -52,6 +59,26 @@ int timeq_del(struct timeq_entry* entry) { last->next = centry->next; else timeq_events = centry->next; + if(centry->name) + free(centry->name); + free(centry); + return 1; + } else { + last = centry; + } + } + return 0; +} + +int timeq_del_name(char *name) { + struct timeq_entry *centry, *last = NULL; + for(centry = timeq_events; centry; centry = centry->next) { + if(centry->name && !stricmp(centry->name, name)) { + if(last) + last->next = centry->next; + else + timeq_events = centry->next; + free(centry->name); free(centry); return 1; } else { diff --git a/timeq.h b/timeq.h index d683c9a..334eb70 100644 --- a/timeq.h +++ b/timeq.h @@ -3,10 +3,11 @@ #include "main.h" -#define TIMEQ_CALLBACK(NAME) int NAME(UNUSED_ARG(void *data)) +#define TIMEQ_CALLBACK(NAME) void NAME(UNUSED_ARG(void *data)) typedef TIMEQ_CALLBACK(timeq_callback_t); struct timeq_entry { + char *name; time_t execute; timeq_callback_t *callback; void *data; @@ -16,6 +17,8 @@ struct timeq_entry { void timeq_tick(); struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data); +struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data); int timeq_del(struct timeq_entry* entry); +int timeq_del_name(char *name); #endif \ No newline at end of file