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