*** VERSION 5.2.0 ***
[NeonServV5.git] / src / cmd_neonserv_unban.c
1 /* cmd_neonserv_unban.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 /*
21 * argv[0-*]    nick[,*auth[,*!*@mask[...]]]
22 */
23 struct neonserv_cmd_unban_cache {
24     struct ClientSocket *client, *textclient;
25     struct UserNode *user;
26     struct ChanNode *chan;
27     struct Event *event;
28     struct ModeBuffer *modeBuf;
29     int provided_masks, done_masks, pending_whos, unbanned_masks;
30 };
31
32 static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup);
33 static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user);
34 static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask);
35 static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache);
36
37 CMD_BIND(neonserv_cmd_unban) {
38     char *mask, *nextmask;
39     struct ModeBuffer *modeBuf;
40     modeBuf = initModeBuffer(client, chan);
41     nextmask = merge_argv_char(argv, 0, argc, ',');
42     struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache));
43     if (!cache) {
44         perror("malloc() failed");
45         return;
46     }
47     cache->client = client;
48     cache->textclient = getTextBot();
49     cache->user = user;
50     cache->chan = chan;
51     cache->event = event;
52     cache->modeBuf = modeBuf;
53     cache->done_masks = 0;
54     cache->provided_masks = 0;
55     cache->unbanned_masks = 0;
56     while((mask = nextmask)) {
57         nextmask = strstr(mask, ",");
58         if(nextmask) {
59             *nextmask = '\0';
60             nextmask++;
61         }
62         cache->provided_masks++;
63         if(is_valid_nick(mask)) {
64             struct UserNode *cuser = getUserByNick(mask);
65             if(!cuser) {
66                 cuser = createTempUser(mask);
67                 cuser->flags |= USERFLAG_ISTMPUSER;
68                 get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache);
69                 cache->pending_whos++;
70             } else {
71                 neonserv_cmd_unban_nick(cache, cuser);
72             }
73         } else {
74             neonserv_cmd_unban_mask(cache, mask);
75         }
76     }
77     if(!cache->pending_whos)
78         neonserv_cmd_unban_finish(cache);
79 }
80
81 static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) {
82     struct neonserv_cmd_unban_cache *cache = data;
83     cache->pending_whos--;
84     if(user)
85         neonserv_cmd_unban_nick(cache, user);
86     else
87         neonserv_cmd_unban_mask(cache, user_nick);
88     if(!cache->pending_whos)
89         neonserv_cmd_unban_finish(cache);
90 }
91
92 static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) {
93     int matches = 0;
94     struct BanNode *ban;
95     char usermask[NICKLEN+USERLEN+HOSTLEN+3];
96     sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
97     for(ban = cache->chan->bans; ban; ban = ban->next) {
98         if(!match(ban->mask, usermask)) {
99             modeBufferUnban(cache->modeBuf, ban->mask);
100             cache->unbanned_masks++;
101             matches++;
102         }
103     }
104     if(matches)
105         cache->done_masks++;
106 }
107
108 static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) {
109     char banmask[NICKLEN+USERLEN+HOSTLEN+3];
110     int matches = 0;
111     struct BanNode *ban;
112     mask = make_banmask(mask, banmask);
113     for(ban = cache->chan->bans; ban; ban = ban->next) {
114         if(!match(mask, ban->mask)) {
115             modeBufferUnban(cache->modeBuf, ban->mask);
116             cache->unbanned_masks++;
117             matches++;
118         }
119     }
120     if(matches)
121         cache->done_masks++;
122     else {
123         for(ban = cache->chan->bans; ban; ban = ban->next) {
124             if(!match(ban->mask, mask)) {
125                 reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask);
126                 break;
127             }
128         }
129     }
130 }
131
132 static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) {
133     freeModeBuffer(cache->modeBuf);
134     if(cache->done_masks == cache->provided_masks)
135         reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name);
136     else
137         reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick);
138     if(cache->done_masks)
139         logEvent(cache->event);
140     free(cache);
141 }
142