added some code & compiler information to cmd_netinfo
[NeonServV5.git] / cmd_neonserv_kickban.c
1
2 /*
3 * argv[0]    nick[,*auth[,*!*@mask[...]]]
4 * argv[1-*]  reason
5 */
6 static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup);
7 static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason);
8
9 struct neonserv_cmd_kickban_cache {
10     struct ClientSocket *client, *textclient;
11     struct UserNode *user;
12     char *nicks;
13     char *reason;
14 };
15
16 static CMD_BIND(neonserv_cmd_kickban) {
17     struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache));
18     if (!cache) {
19         perror("malloc() failed");
20         return;
21     }
22     cache->client = client;
23     cache->textclient = getTextBot();
24     cache->user = user;
25     cache->nicks = strdup(argv[0]);
26     if(argc > 1) {
27         cache->reason = strdup(merge_argv(argv, 1, argc));
28     } else
29         cache->reason = NULL;
30     get_userlist(chan, neonserv_cmd_kickban_userlist_lookup, cache);
31 }
32
33 static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup) {
34     struct neonserv_cmd_kickban_cache *cache = data;
35     neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks, (cache->reason ? cache->reason : "Bye."));
36     free(cache->nicks);
37     if(cache->reason)
38         free(cache->reason);
39     free(cache);
40 }
41
42 static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason) {
43     int i, kicked_users = 0, provided_nicks = 0;
44     char *nick, *nextnick;
45     struct UserNode *cuser;
46     struct ChanUser *chanuser;
47     char usermask[NICKLEN+USERLEN+HOSTLEN+3];
48     nextnick = nicks;
49     check_mysql();
50     while((nick = nextnick)) {
51         nextnick = strstr(nick, ",");
52         if(nextnick) {
53             *nextnick = '\0';
54             nextnick++;
55         }
56         if(!*nick) continue;
57         if(is_ircmask(nick)) {
58             //KICK HOSTMASK
59             struct ChanUser *kickban_chanuser[chan->usercount];
60             int kick_chanuser_pos = 0;
61             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
62                 cuser = chanuser->user;
63                 sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host);
64                 if(!match(nick, usermask)) {
65                     provided_nicks++;
66                     if(isNetworkService(chanuser->user)) {
67                         reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
68                         continue;
69                     }
70                     if(isUserProtected(chan, cuser, user)) {
71                         reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
72                         continue;
73                     }
74                     kickban_chanuser[kick_chanuser_pos++] = chanuser;
75                     if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) {
76                         kick_chanuser_pos = 0;
77                         reply(textclient, user, "NS_LAME_MASK", nick);
78                         break;
79                     }
80                 }
81             }
82             for(i = 0; i < kick_chanuser_pos; i++) {
83                 if(i == 0) {
84                     putsock(client, "MODE %s +b %s", chan->name, nick);
85                 }
86                 kicked_users++;
87                 putsock(client, "KICK %s %s :%s", chan->name, kickban_chanuser[i]->user->nick, reason);
88             }
89         } else if(*nick == '*') {
90             //KICK AUTH
91             nick++;
92             cuser = NULL;
93             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
94                 if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
95                     provided_nicks++;
96                     if(isNetworkService(chanuser->user)) {
97                         reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
98                         continue;
99                     }
100                     if(!cuser) {
101                         //check if the user is protected
102                         if(isUserProtected(chan, chanuser->user, user)) {
103                             reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
104                             break; //all other users are also protected...
105                         }
106                         cuser = chanuser->user;
107                     }
108                     kicked_users++;
109                     putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
110                     putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
111                 }
112             }
113         } else {
114             provided_nicks++;
115             cuser = searchUserByNick(nick);
116             if(!cuser) continue;
117             chanuser = getChanUser(cuser, chan);
118             if(!chanuser) continue;
119             if(isNetworkService(cuser)) {
120                 reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
121                 continue;
122             }
123             if(isUserProtected(chan, cuser, user)) {
124                 reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
125                 continue;
126             }
127             kicked_users++;
128             putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask));
129             putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
130         }
131     }
132     if(kicked_users == provided_nicks)
133         reply(getTextBot(), user, "NS_KICKBAN_DONE", kicked_users, chan->name);
134     else
135         reply(getTextBot(), user, "NS_KICKBAN_FAIL", client->user->nick);
136 }