added cmd_ban and all functions depending on
authorpk910 <philipp@zoelle1.de>
Sun, 28 Aug 2011 09:52:16 +0000 (11:52 +0200)
committerpk910 <philipp@zoelle1.de>
Sun, 28 Aug 2011 10:40:30 +0000 (12:40 +0200)
UserNode.c
UserNode.h
bot_NeonServ.c
cmd_neonserv_ban.c [new file with mode: 0644]
tools.c
tools.h

index e857cb7f46785bf4597f6d97e876751f7986e1b7..a20fb1e49b9ee1dd4627f24f4079e0f091663d72 100644 (file)
@@ -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))
index b98c06334922c21f479c16fd16365662aa1ba8d8..4aebb54efabde07e4479edb1d5b7a334012a1227 100644 (file)
@@ -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);
index 54fae6ff4d396246d8e08bb23243268397d29832..884d002abb2a75b935cfd7d9aded2478fe430fbe 100644 (file)
@@ -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 (file)
index 0000000..b329131
--- /dev/null
@@ -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 938bf790247cc9ffa215d5dba234c2d0d524d083..93fbd323e2c42d56e6c4455711e6628a6034f326 100644 (file)
--- 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 03bdb64399281efbf3f72c57d51849258dab4461..a3110040629030345517cb71bb0a7aec62bdeec9 100644 (file)
--- 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();