From: pk910 Date: Sun, 28 Aug 2011 09:52:16 +0000 (+0200) Subject: added cmd_ban and all functions depending on X-Git-Tag: v5.3~471 X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=5a3c45f1d0ea75d7e3bcdf91340ba6b8a538731d added cmd_ban and all functions depending on --- diff --git a/UserNode.c b/UserNode.c index e857cb7..a20fb1e 100644 --- a/UserNode.c +++ b/UserNode.c @@ -1,5 +1,6 @@ #include "UserNode.h" #include "ChanUser.h" +#include "tools.h" static struct UserNode **userList; @@ -114,6 +115,19 @@ int countUsersWithHost(char *host) { return count; } +char *getAuthFakehost(char *auth) { + int i; + struct UserNode *user; + for(i = 0; i < VALID_NICK_CHARS_FIRST_LEN+1; i++) { + for(user = userList[i]; user; user = user->next) { + if((user->flags & USERFLAG_ISAUTHED) && !strcmp(user->auth, auth) && isFakeHost(user->host)) { + return user->host; + } + } + } + return NULL; +} + struct UserNode* addUser(const char *nick) { int userListIndex = get_nicklist_entry(*nick); if(userListIndex == -1 || !is_valid_nick(nick)) diff --git a/UserNode.h b/UserNode.h index b98c063..4aebb54 100644 --- a/UserNode.h +++ b/UserNode.h @@ -12,6 +12,9 @@ #define USERFLAG_REPLY_PRIVMSG 0x0080 #define USERFLAG_GOD_MODE 0x0100 +#define USERFLAG_SCRIPTFLAG1 0x40000000 +#define USERFLAG_SCRIPTFLAG2 0x80000000 + struct ChanUser; struct language; @@ -37,6 +40,7 @@ int is_valid_nick(const char *nick); struct UserNode* getUserByNick(const char *nick); struct UserNode* getUserByMask(const char *mask); int countUsersWithHost(char *host); +char *getAuthFakehost(char *auth); struct UserNode* searchUserByNick(const char *nick); struct UserNode* addUser(const char *nick); struct UserNode* addUserMask(const char *mask); diff --git a/bot_NeonServ.c b/bot_NeonServ.c index 54fae6f..884d002 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -101,6 +101,8 @@ static const struct default_language_entry msgtab[] = { {"NS_KICK_FAIL", "\002%s\002 could not kick some of the nicks you provided."}, {"NS_KICKBAN_DONE", "KickBanned \002%d\002 users from %s"}, {"NS_KICKBAN_FAIL", "\002%s\002 could not kickban some of the nicks you provided."}, + {"NS_BAN_DONE", "\002%d\002 masks added to the %s ban list. (matching %d users)"}, + {"NS_BAN_FAIL", "\002%s\002 could not kickban some of the nicks you provided."}, {"NS_LAME_MASK", "\002%s\002 is a little too general. Try making it more specific."}, {NULL, NULL} }; @@ -134,7 +136,7 @@ INCLUDE ALL CMD's HERE //#include "cmd_neonserv_uset.c" #include "cmd_neonserv_kick.c" #include "cmd_neonserv_kickban.c" -//#include "cmd_neonserv_ban.c" +#include "cmd_neonserv_ban.c" //#include "cmd_neonserv_unban.c" //#include "cmd_neonserv_unbanall.c" //#include "cmd_neonserv_unbanme.c" @@ -281,6 +283,7 @@ void init_NeonServ() { register_command(BOTID, "set", neonserv_cmd_set, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_setters", 0); register_command(BOTID, "kick", neonserv_cmd_kick, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH, "#channel_cankick", 0); 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); start_bots(); bind_bot_ready(neonserv_bot_ready); diff --git a/cmd_neonserv_ban.c b/cmd_neonserv_ban.c new file mode 100644 index 0000000..b329131 --- /dev/null +++ b/cmd_neonserv_ban.c @@ -0,0 +1,97 @@ + +/* +* argv[0] nick[,*auth[,*!*@mask[...]]] +* argv[1-*] reason +*/ +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); + +struct neonserv_cmd_ban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + char *masks; +}; + +static CMD_BIND(neonserv_cmd_ban) { + struct neonserv_cmd_ban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->masks = strdup(merge_argv_char(argv, 0, argc, ',')); + get_userlist(chan, neonserv_cmd_ban_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup) { + struct neonserv_cmd_ban_cache *cache = data; + neonserv_cmd_ban_async1(cache->client, cache->textclient, cache->user, chan, cache->masks); + free(cache->masks); + free(cache); +} + +static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *masks) { + int done_masks = 0, provided_masks = 0, skip, match_count, total_match; + char *mask, *nextmask; + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + nextmask = masks; + check_mysql(); + while((mask = nextmask)) { + nextmask = strstr(mask, ","); + if(nextmask) { + *nextmask = '\0'; + nextmask++; + } + provided_masks++; + skip = 0; + match_count = 0; + 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)) { + cuser->flags |= USERFLAG_SCRIPTFLAG1; //we mark the user as 'matching' + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + skip = 1; + break; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + skip = 1; + break; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + skip = 1; + reply(textclient, user, "NS_LAME_MASK", mask); + break; + } + } + } + if(!skip) { + done_masks++; + modeBufferBan(modeBuf, mask); + } + } + total_match = 0; // count all users marked as 'matching' + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + if(cuser->flags & USERFLAG_SCRIPTFLAG1) { + cuser->flags &= ~USERFLAG_SCRIPTFLAG1; + total_match++; + } + } + freeModeBuffer(modeBuf); + if(done_masks == provided_masks) + reply(getTextBot(), user, "NS_BAN_DONE", done_masks, chan->name, total_match); + else + reply(getTextBot(), user, "NS_BAN_FAIL", client->user->nick); +} diff --git a/tools.c b/tools.c index 938bf79..93fbd32 100644 --- a/tools.c +++ b/tools.c @@ -386,16 +386,8 @@ int is_ircmask(const char *text) { char* generate_banmask(struct UserNode *user, char *buffer) { char *userhost = user->host; - char *p1, *p2 = userhost; - //find the last dot to identify if the hostmask is a hidden host - while((p1 = strstr(userhost, "."))) { - p2 = p1; - } - //TLD database: http://www.iana.org/domains/root/db/ - //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D) - //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain - if(strlen(p2+1) > 4) { + if(isFakeHost(user->host)) { sprintf(buffer, "*!*@%s", userhost); return buffer; } @@ -410,6 +402,57 @@ char* generate_banmask(struct UserNode *user, char *buffer) { } } +char* make_banmask(char *input, char* buffer) { + char *nick = NULL, *ident = NULL, *host = NULL; + char tmp[HOSTLEN]; + char *p; + if((p = strstr(input, "!"))) { + nick = input; + *p = '\0'; + ident = p+1; + if((p = strstr(ident, "@"))) { + *p = '\0'; + host = p+1; + } + } else if((p = strstr(input, "@"))) { + ident = input; + *p = '\0'; + host = p+1; + } else if((p = strstr(input, "."))) { + host = input; + } else if(*input == '*' && !strstr(input+1, "*")) { + //AUTH MASK + p = getAuthFakehost(input+1); + if(p) + host = p; + else { + sprintf(tmp, "%s.*", input+1); + host = tmp; + } + } else { + struct UserNode *user = searchUserByNick(input); + if(user) + return generate_banmask(user, buffer); + else + nick = input; + } + sprintf(buffer, "%s!%s@%s", (nick ? nick : "*"), (ident ? ident : "*"), (host ? host : "*")); + return buffer; +} + +int isFakeHost(char *host) { + char *p1, *p2 = host; + + //find the last dot to identify if the hostmask is a fake host + while((p1 = strstr(p2, "."))) { + p2 = p1 + 1; + } + //TLD database: http://www.iana.org/domains/root/db/ + //the longest TLD i found was 6 chars long (ignoring the stange exotic ones :D) + //but we even ignore '.museum' and '.travel' so we can say that the TLD of our mask needs to be less than 4 chars to be a real domain + return (strlen(p2+1) > 4); +} + void init_tools() { register_default_language_table(msgtab); } diff --git a/tools.h b/tools.h index 03bdb64..a311004 100644 --- a/tools.h +++ b/tools.h @@ -59,6 +59,8 @@ void freeModeBuffer(struct ModeBuffer *modeBuf); int is_ircmask(const char *text); char* generate_banmask(struct UserNode *user, char *buffer); +char* make_banmask(char *input, char* buffer); +int isFakeHost(char *host); void init_tools();