tried to reorder the program structure and build process
[NeonServV5.git] / src / cmd_neonserv_unban.c
diff --git a/src/cmd_neonserv_unban.c b/src/cmd_neonserv_unban.c
new file mode 100644 (file)
index 0000000..073bf50
--- /dev/null
@@ -0,0 +1,126 @@
+
+#include "cmd_neonserv.h"
+
+/*
+* argv[0-*]    nick[,*auth[,*!*@mask[...]]]
+*/
+struct neonserv_cmd_unban_cache {
+    struct ClientSocket *client, *textclient;
+    struct UserNode *user;
+    struct ChanNode *chan;
+    struct Event *event;
+    struct ModeBuffer *modeBuf;
+    int provided_masks, done_masks, pending_whos, unbanned_masks;
+};
+
+static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup);
+static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user);
+static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask);
+static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache);
+
+CMD_BIND(neonserv_cmd_unban) {
+    char *mask, *nextmask;
+    struct ModeBuffer *modeBuf;
+    modeBuf = initModeBuffer(client, chan);
+    nextmask = merge_argv_char(argv, 0, argc, ',');
+    struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache));
+    if (!cache) {
+        perror("malloc() failed");
+        return;
+    }
+    cache->client = client;
+    cache->textclient = getTextBot();
+    cache->user = user;
+    cache->chan = chan;
+    cache->event = event;
+    cache->modeBuf = modeBuf;
+    cache->done_masks = 0;
+    cache->provided_masks = 0;
+    cache->unbanned_masks = 0;
+    while((mask = nextmask)) {
+        nextmask = strstr(mask, ",");
+        if(nextmask) {
+            *nextmask = '\0';
+            nextmask++;
+        }
+        cache->provided_masks++;
+        if(is_valid_nick(mask)) {
+            struct UserNode *cuser = getUserByNick(mask);
+            if(!cuser) {
+                cuser = createTempUser(mask);
+                cuser->flags |= USERFLAG_ISTMPUSER;
+                get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache);
+                cache->pending_whos++;
+            } else {
+                neonserv_cmd_unban_nick(cache, cuser);
+            }
+        } else {
+            neonserv_cmd_unban_mask(cache, mask);
+        }
+    }
+    if(!cache->pending_whos)
+        neonserv_cmd_unban_finish(cache);
+}
+
+static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) {
+    struct neonserv_cmd_unban_cache *cache = data;
+    cache->pending_whos--;
+    if(user)
+        neonserv_cmd_unban_nick(cache, user);
+    else
+        neonserv_cmd_unban_mask(cache, user_nick);
+    if(!cache->pending_whos)
+        neonserv_cmd_unban_finish(cache);
+}
+
+static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) {
+    int matches = 0;
+    struct BanNode *ban;
+    char usermask[NICKLEN+USERLEN+HOSTLEN+3];
+    sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host);
+    for(ban = cache->chan->bans; ban; ban = ban->next) {
+        if(!match(ban->mask, usermask)) {
+            modeBufferUnban(cache->modeBuf, ban->mask);
+            cache->unbanned_masks++;
+            matches++;
+        }
+    }
+    if(matches)
+        cache->done_masks++;
+}
+
+static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) {
+    char banmask[NICKLEN+USERLEN+HOSTLEN+3];
+    int matches = 0;
+    struct BanNode *ban;
+    mask = make_banmask(mask, banmask);
+    for(ban = cache->chan->bans; ban; ban = ban->next) {
+        if(!match(mask, ban->mask)) {
+            modeBufferUnban(cache->modeBuf, ban->mask);
+            cache->unbanned_masks++;
+            matches++;
+        }
+    }
+    if(matches)
+        cache->done_masks++;
+    else {
+        for(ban = cache->chan->bans; ban; ban = ban->next) {
+            if(!match(ban->mask, mask)) {
+                reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask);
+                break;
+            }
+        }
+    }
+}
+
+static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) {
+    freeModeBuffer(cache->modeBuf);
+    if(cache->done_masks == cache->provided_masks)
+        reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name);
+    else
+        reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick);
+    if(cache->done_masks)
+        logEvent(cache->event);
+    free(cache);
+}
+