added some code & compiler information to cmd_netinfo
[NeonServV5.git] / cmd_neonserv_kick.c
1
2 /*
3 * argv[0]    nick[,*auth[,*!*@mask[...]]]
4 * argv[1-*]  reason
5 */
6 static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup);
7 static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason);
8
9 struct neonserv_cmd_kick_cache {
10     struct ClientSocket *client, *textclient;
11     struct UserNode *user;
12     char *nicks;
13     char *reason;
14 };
15
16 static CMD_BIND(neonserv_cmd_kick) {
17     struct neonserv_cmd_kick_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_kick_userlist_lookup, cache);
31 }
32
33 static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup) {
34     struct neonserv_cmd_kick_cache *cache = data;
35     neonserv_cmd_kick_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_kick_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     nextnick = nicks;
48     check_mysql();
49     while((nick = nextnick)) {
50         nextnick = strstr(nick, ",");
51         if(nextnick) {
52             *nextnick = '\0';
53             nextnick++;
54         }
55         if(!*nick) continue;
56         if(is_ircmask(nick)) {
57             //KICK HOSTMASK
58             char usermask[NICKLEN+USERLEN+HOSTLEN+3];
59             struct ChanUser *kick_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                     kick_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                 kicked_users++;
84                 putsock(client, "KICK %s %s :%s", chan->name, kick_chanuser[i]->user->nick, reason);
85             }
86         } else if(*nick == '*') {
87             //KICK AUTH
88             nick++;
89             cuser = NULL;
90             for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
91                 if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) {
92                     provided_nicks++;
93                     if(isNetworkService(chanuser->user)) {
94                         reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick);
95                         continue;
96                     }
97                     if(!cuser) {
98                         //check if the user is protected
99                         if(isUserProtected(chan, chanuser->user, user)) {
100                             reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick);
101                             break; //all other users are also protected...
102                         }
103                         cuser = chanuser->user;
104                     }
105                     kicked_users++;
106                     putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
107                 }
108             }
109         } else {
110             provided_nicks++;
111             cuser = searchUserByNick(nick);
112             if(!cuser) continue;
113             chanuser = getChanUser(cuser, chan);
114             if(!chanuser) continue;
115             if(isNetworkService(cuser)) {
116                 reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
117                 continue;
118             }
119             if(isUserProtected(chan, cuser, user)) {
120                 reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
121                 continue;
122             }
123             kicked_users++;
124             putsock(client, "KICK %s %s :%s", chan->name, cuser->nick, reason);
125         }
126     }
127     if(kicked_users == provided_nicks)
128         reply(getTextBot(), user, "NS_KICK_DONE", kicked_users, chan->name);
129     else
130         reply(getTextBot(), user, "NS_KICK_FAIL", client->user->nick);
131 }