d4f9dc631d108b0c74071875fa8b8d672c272635
[NeonServV5.git] / cmd_neonserv_unban.c
1
2 /*
3 * argv[0-*]    nick[,*auth[,*!*@mask[...]]]
4 */
5 struct neonserv_cmd_unban_cache {
6     struct ClientSocket *client, *textclient;
7     struct UserNode *user;
8     struct ChanNode *chan;
9     struct Event *event;
10     struct ModeBuffer *modeBuf;
11     int provided_masks, done_masks, pending_whos, unbanned_masks;
12 };
13
14 static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup);
15 static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user);
16 static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask);
17 static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache);
18
19 static CMD_BIND(neonserv_cmd_unban) {
20     char *mask, *nextmask;
21     struct ModeBuffer *modeBuf;
22     modeBuf = initModeBuffer(client, chan);
23     nextmask = merge_argv_char(argv, 0, argc, ',');
24     struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache));
25     if (!cache) {
26         perror("malloc() failed");
27         return;
28     }
29     cache->client = client;
30     cache->textclient = getTextBot();
31     cache->user = user;
32     cache->chan = chan;
33     cache->event = event;
34     cache->modeBuf = modeBuf;
35     cache->done_masks = 0;
36     cache->provided_masks = 0;
37     cache->unbanned_masks = 0;
38     while((mask = nextmask)) {
39         nextmask = strstr(mask, ",");
40         if(nextmask) {
41             *nextmask = '\0';
42             nextmask++;
43         }
44         cache->provided_masks++;
45         if(is_valid_nick(mask)) {
46             struct UserNode *cuser = getUserByNick(mask);
47             if(!cuser) {
48                 cuser = createTempUser(mask);
49                 cuser->flags |= USERFLAG_ISTMPUSER;
50                 get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache);
51                 cache->pending_whos++;
52             } else {
53                 neonserv_cmd_unban_nick(cache, cuser);
54             }
55         } else {
56             neonserv_cmd_unban_mask(cache, mask);
57         }
58     }
59     if(!cache->pending_whos)
60         neonserv_cmd_unban_finish(cache);
61 }
62
63 static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) {
64     struct neonserv_cmd_unban_cache *cache = data;
65     cache->pending_whos--;
66     if(user)
67         neonserv_cmd_unban_nick(cache, user);
68     else
69         neonserv_cmd_unban_mask(cache, user_nick);
70     if(!cache->pending_whos)
71         neonserv_cmd_unban_finish(cache);
72 }
73
74 static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) {
75     int matches = 0;
76     struct BanNode *ban;
77     char usermask[NICKLEN+USERLEN+HOSTLEN+3];
78     sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
79     for(ban = cache->chan->bans; ban; ban = ban->next) {
80         if(!match(ban->mask, usermask)) {
81             modeBufferUnban(cache->modeBuf, ban->mask);
82             cache->unbanned_masks++;
83             matches++;
84         }
85     }
86     if(matches)
87         cache->done_masks++;
88 }
89
90 static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) {
91     char banmask[NICKLEN+USERLEN+HOSTLEN+3];
92     int matches = 0;
93     struct BanNode *ban;
94     mask = make_banmask(mask, banmask);
95     for(ban = cache->chan->bans; ban; ban = ban->next) {
96         if(!match(mask, ban->mask)) {
97             modeBufferUnban(cache->modeBuf, ban->mask);
98             cache->unbanned_masks++;
99             matches++;
100         }
101     }
102     if(matches)
103         cache->done_masks++;
104     else {
105         for(ban = cache->chan->bans; ban; ban = ban->next) {
106             if(!match(ban->mask, mask)) {
107                 reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask);
108                 break;
109             }
110         }
111     }
112 }
113
114 static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) {
115     freeModeBuffer(cache->modeBuf);
116     if(cache->done_masks == cache->provided_masks)
117         reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name);
118     else
119         reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick);
120     if(cache->done_masks)
121         logEvent(cache->event);
122     free(cache);
123 }
124