added sort function to cmd_nicklist
authorpk910 <philipp@zoelle1.de>
Wed, 15 Aug 2012 23:48:30 +0000 (01:48 +0200)
committerpk910 <philipp@zoelle1.de>
Wed, 15 Aug 2012 23:51:49 +0000 (01:51 +0200)
src/modules/NeonServ.mod/cmd_neonserv_nicklist.c

index 3e858d0f2a49ad43820e77feaba587c272c76fb3..c978247e8d30302deff963b81c9ab29f16d756f0 100644 (file)
@@ -80,25 +80,62 @@ static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup) {
     free(cache);
 }
 
+static int neonserv_cmd_nicklist_sort_flags[] = { 
+    CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED,
+    CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED,
+    CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED,
+    CHANUSERFLAG_OPPED,
+    CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED,
+    CHANUSERFLAG_HALFOPPED,
+    CHANUSERFLAG_VOICED,
+    CHANUSERFLAG_INVISIBLE,
+    0
+};
+
+static int neonserv_cmd_nicklist_sort(const void *a, const void *b) {
+    const struct ChanUser *chanuser_a = *((struct ChanUser * const *) a);
+    const struct ChanUser *chanuser_b = *((struct ChanUser * const *) b); 
+    int i_a = 0, i_b = 0;
+    while((chanuser_a->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != neonserv_cmd_nicklist_sort_flags[i_a] && neonserv_cmd_nicklist_sort_flags[i_a])
+        i_a++;
+    while((chanuser_b->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != neonserv_cmd_nicklist_sort_flags[i_b] && neonserv_cmd_nicklist_sort_flags[i_b])
+        i_b++;
+    if(i_a == i_b) {
+        return stricmp(chanuser_a->user->nick, chanuser_b->user->nick);
+    } else
+        return i_a - i_b;
+}
+
 static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers) {
     MYSQL_RES *res;
     MYSQL_ROW row, defaults = NULL;
     struct Table *table;
-    table = table_init(3, chan->usercount + 1, 0);
     char *content[3];
+    int userlistlen, i, j;
+    int db_enfops, db_enfvoice;
+    int caccess, synced_user;
+    struct ChanUser *chanusers[chan->usercount];
+    struct ChanUser *chanuser;
+    int chanuser_count;
+    char statebuf[5];
+    char accessbuf[9];
+    int uaccess;
+    
+    table = table_init(3, chan->usercount + 1, 0);
     content[0] = get_language_string(user, "NS_NICKLIST_NICK");
     content[1] = get_language_string(user, "NS_NICKLIST_STATE");
     content[2] = get_language_string(user, "NS_NICKLIST_ACCESS");
     table_add(table, content);
+    
     printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d'", chan->channel_id);
     res = mysql_use();
-    int userlistlen = mysql_num_rows(res);
-    int i = 0;
+    userlistlen = mysql_num_rows(res);
+    i = 0;
     MYSQL_ROW userlist[userlistlen];
     while ((row = mysql_fetch_row(res)) != NULL) {
         userlist[i++] = row;
     }
-    int db_enfops, db_enfvoice;
+    
     printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
     row = mysql_fetch_row(mysql_use());
     if(row[0] == NULL || row[1] == NULL) {
@@ -107,106 +144,96 @@ static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct Cli
     }
     db_enfops = atoi((row[0] ? row[0] : defaults[0]));
     db_enfvoice = atoi((row[1] ? row[1] : defaults[1]));
-    int caccess = getChannelAccess(user, chan);
-    int synced_user = 0;
-    struct ChanUser *chanuser;
-    int sort_nicklist[] = { 
-            CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED,
-            CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED,
-            CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED,
-            CHANUSERFLAG_OPPED,
-            CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED,
-            CHANUSERFLAG_HALFOPPED,
-            CHANUSERFLAG_VOICED,
-            CHANUSERFLAG_INVISIBLE,
-            0
-        };
-    int *sort_pos = sort_nicklist;
-    int sort_flags;
-    do {
-        sort_flags = *(sort_pos++);
-        char statebuf[5];
-        char accessbuf[9];
-        int uaccess;
-        int stateset = 0;
-        for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
-            if((chanuser->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != sort_flags) continue;
-            if(nickmask && match(nickmask, chanuser->user->nick)) continue;
-            if(!stateset) {
-                if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[stateset++] = '<';
-                if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[stateset++] = '@';
-                if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[stateset++] = '%';
-                if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[stateset++] = '+';
-                statebuf[stateset++] = '\0';
-            }
-            content[0] = chanuser->user->nick;
-            content[1] = statebuf;
-            uaccess = 0;
-            if(chanuser->user->flags & USERFLAG_ISAUTHED) {
-                for(i = 0; i < userlistlen; i++) {
-                    if(!stricmp(chanuser->user->auth, userlist[i][1])) {
-                        uaccess = atoi(userlist[i][0]);
-                        if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) {
-                            if(syncusers) {
-                                if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) {
-                                    if(db_enfops >= caccess)
-                                        event->flags |= CMDFLAG_OPLOG;
-                                    uaccess = db_enfops;
-                                } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) {
-                                    if(db_enfvoice >= caccess)
-                                        event->flags |= CMDFLAG_OPLOG;
-                                    uaccess = db_enfvoice;
-                                } else {
-                                    //fail...
-                                    sprintf(accessbuf, "\00307%d\003", uaccess);
-                                    break;
-                                }
-                                neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess);
-                                sprintf(accessbuf, "\00309%d\003", uaccess);
-                                synced_user = 1;
+    
+    chanuser_count = 0;
+    for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
+        if(nickmask && match(nickmask, chanuser->user->nick)) continue;
+        chanusers[chanuser_count++] = chanuser;
+    }
+    qsort(chanusers, chanuser_count, sizeof(struct ChanUser *), neonserv_cmd_nicklist_sort);
+    
+    caccess = getChannelAccess(user, chan);
+    synced_user = 0;
+    for(i = 0; i < chanuser_count; i++) {
+        chanuser = chanusers[i];
+        
+        content[0] = chanuser->user->nick;
+        
+        j = 0;
+        if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[j++] = '<';
+        if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[j++] = '@';
+        if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[j++] = '%';
+        if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[j++] = '+';
+        statebuf[j++] = '\0';
+        content[1] = statebuf;
+        
+        uaccess = 0;
+        if(chanuser->user->flags & USERFLAG_ISAUTHED) {
+            for(j = 0; j < userlistlen; j++) {
+                if(!stricmp(chanuser->user->auth, userlist[j][1])) {
+                    uaccess = atoi(userlist[j][0]);
+                    if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) {
+                        if(syncusers) {
+                            if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) {
+                                if(db_enfops >= caccess)
+                                    event->flags |= CMDFLAG_OPLOG;
+                                uaccess = db_enfops;
+                            } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) {
+                                if(db_enfvoice >= caccess)
+                                    event->flags |= CMDFLAG_OPLOG;
+                                uaccess = db_enfvoice;
                             } else {
-                                synced_user = 1;
+                                //fail...
                                 sprintf(accessbuf, "\00307%d\003", uaccess);
+                                break;
                             }
-                        } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED)))
-                            sprintf(accessbuf, "\00303%d\003", uaccess);
-                        else
-                            sprintf(accessbuf, "%d", uaccess);
-                        break;
-                    }
+                            neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess);
+                            sprintf(accessbuf, "\00309%d\003", uaccess);
+                            synced_user = 1;
+                        } else {
+                            synced_user = 1;
+                            sprintf(accessbuf, "\00307%d\003", uaccess);
+                        }
+                    } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED)))
+                        sprintf(accessbuf, "\00303%d\003", uaccess);
+                    else
+                        sprintf(accessbuf, "%d", uaccess);
+                    break;
                 }
             }
-            if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) {
-                if(syncusers) {
-                    if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) {
-                        if(db_enfops >= caccess)
-                            event->flags |= CMDFLAG_OPLOG;
-                        uaccess = db_enfops;
-                    } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) {
-                        if(db_enfvoice >= caccess)
-                            event->flags |= CMDFLAG_OPLOG;
-                        uaccess = db_enfvoice;
-                    } else {
-                        uaccess = 0;
-                        sprintf(accessbuf, "\003040\003");
-                    }
-                    if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) {
-                        neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess);
-                        sprintf(accessbuf, "\00309%d\003", uaccess);
-                        synced_user = 1;
-                    } else if(uaccess) {
-                        sprintf(accessbuf, "\003040\003");
-                    }
+        }
+        if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) {
+            if(syncusers) {
+                if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) {
+                    if(db_enfops >= caccess)
+                        event->flags |= CMDFLAG_OPLOG;
+                    uaccess = db_enfops;
+                } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) {
+                    if(db_enfvoice >= caccess)
+                        event->flags |= CMDFLAG_OPLOG;
+                    uaccess = db_enfvoice;
                 } else {
+                    uaccess = 0;
+                    sprintf(accessbuf, "\003040\003");
+                }
+                if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) {
+                    neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess);
+                    sprintf(accessbuf, "\00309%d\003", uaccess);
                     synced_user = 1;
+                } else if(uaccess) {
                     sprintf(accessbuf, "\003040\003");
                 }
-            } else if(!uaccess)
-                sprintf(accessbuf, "0");
-            content[2] = accessbuf;
-            table_add(table, content);
-        }
-    } while(sort_flags != 0);
+            } else {
+                synced_user = 1;
+                sprintf(accessbuf, "\003040\003");
+            }
+        } else if(!uaccess)
+            sprintf(accessbuf, "0");
+        content[2] = accessbuf;
+        
+        table_add(table, content);
+    }
+    
     //send the table
     char **table_lines = table_end(table);
     for(i = 0; i < table->entrys; i++) {