added basic halfop support
[NeonServV5.git] / src / WHOHandler.c
index f2e872190f09b8d89b953453e9668a3811e95fb6..a21f560414ec7ad962a2fb75e76ff43f01ee95cb 100644 (file)
@@ -1,4 +1,4 @@
-/* WHOHandler.c - NeonServ v5.1
+/* WHOHandler.c - NeonServ v5.2
  * Copyright (C) 2011  Philipp Kreil (pk910)
  * 
  * This program is free software: you can redistribute it and/or modify
 
 struct WHOQueueEntry {
     char type;
-    struct ClientSocket *client;
     struct ChanNode *chan;
     struct UserNode *user;
     struct WHOQueueEntry *next;
     void *callback[MAXCALLBACKS];
     void *data[MAXCALLBACKS];
 };
-
-static struct WHOQueueEntry *first_entry = NULL, *last_entry = NULL;
-
 static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
     struct WHOQueueEntry *entry = malloc(sizeof(*entry));
     if (!entry)
@@ -50,38 +46,37 @@ static struct WHOQueueEntry* addWHOQueueEntry(struct ClientSocket *client) {
         return NULL;
     }
     entry->next = NULL;
-    entry->client = client;
-    if(last_entry) {
-        last_entry->next = entry;
-        last_entry = entry;
+    if(client->whoqueue_last) {
+        client->whoqueue_last->next = entry;
     } else {
-        last_entry = entry;
-        first_entry = entry;
+        client->whoqueue_first = entry;
     }
+    client->whoqueue_last = entry;
     return entry;
 }
 
 static struct WHOQueueEntry* getNextWHOQueueEntry(struct ClientSocket *client, int freeEntry) {
-    if(!first_entry) return NULL;
-    struct WHOQueueEntry *entry;
-    for(entry = first_entry; entry; entry = entry->next) {
-        if(entry->client == client)
-            break;
-    }
-    if(entry == NULL) return NULL;
+    if(!client->whoqueue_first) return NULL;
+    struct WHOQueueEntry *entry = client->whoqueue_first;
     if(freeEntry) {
-        if(entry == first_entry)
-            first_entry = entry->next;
-        if(entry == last_entry) {
-            struct WHOQueueEntry *last = NULL;
-            for(last = first_entry; last; last = last->next)
-                if(last->next == NULL) break;
-            last_entry = last;
+        client->whoqueue_first = entry->next;
+        if(entry == client->whoqueue_last) {
+            client->whoqueue_last = NULL;
         }
     }
     return entry;
 }
 
+void clear_whoqueue(struct ClientSocket *client) {
+    if(!client->whoqueue_first) return;
+    struct WHOQueueEntry *entry, *next;
+    for(entry = client->whoqueue_first; entry; entry = next) {
+        next = entry->next;
+        free(entry);
+    }
+    client->whoqueue_last = NULL;
+}
+
 void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) {
     struct ClientSocket *bot;
     for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
@@ -153,24 +148,25 @@ void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t cal
 
 void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data) {
     //check if we have already an active WHO for this user
+    struct ClientSocket *bot, *whobot = NULL;
     struct WHOQueueEntry *entry;
-    for(entry = first_entry; entry; entry = entry->next) {
-        if((entry->type & WHOQUEUETYPE_USERAUTH) && entry->user == user) {
-            int i = 0;
-            for(i = 1; i < MAXCALLBACKS; i++) {
-                if(!entry->callback[i]) {
-                    entry->callback[i] = callback;
-                    entry->data[i] = data;
-                    return;
+    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
+        for(entry = bot->whoqueue_first; entry; entry = entry->next) {
+            if((entry->type & WHOQUEUETYPE_USERAUTH) && entry->user == user) {
+                int i = 0;
+                for(i = 1; i < MAXCALLBACKS; i++) {
+                    if(!entry->callback[i]) {
+                        entry->callback[i] = callback;
+                        entry->data[i] = data;
+                        return;
+                    }
                 }
             }
         }
-    }
-    struct ClientSocket *bot;
-    for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) {
         if(bot->flags & SOCKET_FLAG_PREFERRED)
-            break;
+            whobot = bot;
     }
+    bot = whobot;
     if(bot == NULL) bot = getBots(SOCKET_FLAG_READY, NULL);
     //check if we really need to who the user
     if((user->flags & (USERFLAG_ISAUTHED | USERFLAG_ISIRCOP | USERFLAG_ISBOT | USERFLAG_ISSERVER)) || (time(0) - user->last_who) <= REWHO_TIMEOUT) {
@@ -212,6 +208,9 @@ void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int
                 case '@':
                     chanuserflags |= CHANUSERFLAG_OPPED;
                     break;
+                case '%':
+                    chanuserflags |= CHANUSERFLAG_HALFOPPED;
+                    break;
                 case '+':
                     chanuserflags |= CHANUSERFLAG_VOICED;
                     break;
@@ -226,22 +225,22 @@ void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int
             }
         }
         
-        struct UserNode *user;
-        if(chanuserflags & CHANUSERFLAG_INVISIBLE) {
+        struct UserNode *user = getUserByNick(argv[4]);
+        struct ChanUser *chanuser;
+        if((chanuserflags & CHANUSERFLAG_INVISIBLE) && (!user || !isBot(user))) {
             user = createTempUser(argv[4]);
             user->flags |= USERFLAG_ISTMPUSER;
             chan->flags |= CHANFLAG_HAVE_INVISIBLES;
-            struct ChanUser *chanuser = addInvisibleChanUser(chan, user);
+            chanuser = addInvisibleChanUser(chan, user);
             chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
         } else {
-            user = getUserByNick(argv[4]);
             if(user == NULL) {
                 user = addUser(argv[4]);
             }
-            if(!isUserOnChan(user, chan)) {
-                struct ChanUser *chanuser = addChanUser(chan, user);
-                chanuser->flags = (chanuser->flags & ~CHANUSERFLAG_OPPED_OR_VOICED) | chanuserflags;
+            if(!(chanuser = getChanUser(user, chan))) {
+                chanuser = addChanUser(chan, user);
             }
+            chanuser->flags = (chanuser->flags & ~(CHANUSERFLAG_OPPED_OR_VOICED | CHANUSERFLAG_INVISIBLE)) | chanuserflags;
         }
         user->flags = (user->flags & ~USERFLAG_ISIRCOP) | userflags;
         user->last_who = time(0);
@@ -293,7 +292,7 @@ void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int
             struct ChanUser *chanuser, *next;
             for(chanuser = getChannelUsers(entry->chan, NULL); chanuser; chanuser = next) {
                 next = getChannelUsers(entry->chan, chanuser);
-                if(chanuser->flags & CHANUSERFLAG_INVISIBLE) {
+                if((chanuser->flags & CHANUSERFLAG_INVISIBLE) && !isBot(chanuser->user)) {
                     delChanUser(chanuser, 1);
                 }
             }
@@ -313,11 +312,5 @@ void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int
 }
 
 void free_whoqueue() {
-    struct WHOQueueEntry *entry, *next;
-    for(entry = first_entry; entry; entry = next) {
-        next = entry->next;
-        free(entry);
-    }
-    first_entry = NULL;
-    last_entry = NULL;
+    
 }