fix possible crash on user deletion
[srvx.git] / src / hash.c
index 5a8df93dd53c23f75145ef77976000b67315a230..a55ad9ba92568bc06f6e3b031953a41bce38f273 100644 (file)
@@ -382,6 +382,7 @@ AddChannel(const char *name, unsigned long time_, const char *modes, char *banli
         strcpy(cNode->name, name);
         banList_init(&cNode->banlist);
         modeList_init(&cNode->members);
+        userList_init(&cNode->invited);
         mod_chanmode(NULL, cNode, argv, nn, MCP_FROM_SERVER);
         dict_insert(channels, cNode->name, cNode);
         cNode->timestamp = time_;
@@ -469,6 +470,7 @@ DelChannel(struct chanNode *channel)
 
     modeList_clean(&channel->members);
     banList_clean(&channel->banlist);
+    userList_clean(&channel->invited);
     free(channel);
 }
 
@@ -517,6 +519,33 @@ AddChannelUser(struct userNode *user, struct chanNode* channel)
         return mNode;
 }
 
+/* Return negative if *(struct modeNode**)pa is "less than" pb,
+ * positive if pa is "larger than" pb.  Comparison is based on sorting
+ * so that non-voiced/non-opped users are first, voiced-only users are
+ * next, and the "strongest" oplevels are before "weaker" oplevels.
+ * Within those sets, ordering is arbitrary.
+ */
+int
+modeNode_sort(const void *pa, const void *pb)
+{
+        struct modeNode *a = *(struct modeNode**)pa;
+        struct modeNode *b = *(struct modeNode**)pb;
+
+        if (a->modes & MODE_CHANOP) {
+            if (!(b->modes & MODE_CHANOP))
+                return -1;
+            else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+                return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+            else if (a->oplevel != b->oplevel)
+                return a->oplevel - b->oplevel;
+        } else if (b->modes & MODE_CHANOP)
+            return 1;
+        else if ((b->modes & MODE_VOICE) != (a->modes & MODE_VOICE))
+            return (b->modes & MODE_VOICE) - (a->modes & MODE_VOICE);
+
+        return irccasecmp(a->user->nick, b->user->nick);
+}
+
 static part_func_t *pf_list;
 static unsigned int pf_size = 0, pf_used = 0;
 
@@ -636,9 +665,9 @@ ChannelUserKicked(struct userNode* kicker, struct userNode* victim, struct chanN
     unsigned int n;
     struct modeNode *mn;
 
-    if (!victim || !channel || IsService(victim) || !GetUserMode(channel, victim))
+    if (!victim || !channel || !GetUserMode(channel, victim))
         return;
-
+    
     /* Update the kicker's idle time (kicker may be null if it was a server) */
     if (kicker && (mn = GetUserMode(channel, kicker)))
         mn->idle_since = now;