]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/tools.c
Fix for a couple of crash bugs
[irc/evilnet/x3.git] / src / tools.c
index 01c8578947e720214fed733fdbe7a6264b0ac96e..357c1c7c3f6eb35a6c66d4957988947115c932f6 100644 (file)
@@ -367,6 +367,10 @@ irc_strtolower(char *str) {
 
 int
 irccasecmp(const char *stra, const char *strb) {
+    if (!stra)
+      return -1;
+    if (!strb)
+      return 1;
     while (*stra && (tolower(*stra) == tolower(*strb)))
         stra++, strb++;
     return tolower(*stra) - tolower(*strb);
@@ -602,18 +606,145 @@ int is_overmask(char *mask)
 }
 
 int
-user_matches_glob(struct userNode *user, const char *orig_glob, int flags)
+user_matches_glob(struct userNode *user, const char *orig_glob, int flags, int shared)
 {
-    char *glob, *marker;
+    char *tmpglob, *glob, *marker;
+    char exttype = 0;
+    int extreverse = 0, is_extended = 0, match = 0, banned = 0;
+    unsigned int count, n;
+    struct modeNode *mn;
+    struct chanNode *channel;
+    struct banNode *ban;
 
     /* Make a writable copy of the glob */
     glob = alloca(strlen(orig_glob)+1);
     strcpy(glob, orig_glob);
+
+    /* Extended bans */
+    tmpglob = alloca(strlen(orig_glob)+1);
+    tmpglob = strdup(orig_glob);
+
+    if (*tmpglob == '~') {
+        tmpglob++; /* get rid of the ~ */
+
+        if (*tmpglob == '!') {
+            extreverse = 1;
+            tmpglob++; /* get rid of the ! */
+        }
+
+        exttype = *tmpglob;
+        tmpglob++; /* get rid of the type */
+
+        if (*tmpglob == ':') {
+            is_extended = 1;
+            tmpglob++; /* get rid of the : */
+            glob = strdup(tmpglob);
+        }
+    }
+
+    if (is_extended) {
+        log_module(MAIN_LOG, LOG_DEBUG, "Extended ban. T (%c) R (%d) M (%s)", exttype, extreverse, glob);
+        switch (exttype) {
+            case 'a':
+                if (user->handle_info) {
+                    if (extreverse) {
+                        if (0 != strcasecmp(glob, user->handle_info->handle))
+                            return 1;
+                    } else {
+                        if (0 == strcasecmp(glob, user->handle_info->handle))
+                            return 1;
+                    }
+                } else {
+                    if (extreverse)
+                        return 1;
+                }
+                return match_ircglob(user->hostname, glob);
+            case 'c':
+                if (!strstr(glob, "#"))
+                    return -1;
+
+                if (extreverse) {
+                    for (n=count=0; n<user->channels.used; n++) {
+                        mn = user->channels.list[n];
+                        match = 0;
+
+                        if (*glob == '#') {
+                            if (0 == strcasecmp(glob, mn->channel->name))
+                                match = 1;
+                        } else {
+                            if (0 == strcasecmp(glob+1, mn->channel->name)) {
+                                if ((*glob == '@') && (mn->modes & MODE_CHANOP))
+                                    match = 1;
+                                else if ((*glob == '%') && (mn->modes & MODE_HALFOP))
+                                    match = 1;
+                                else if ((*glob == '+') && (mn->modes & MODE_VOICE))
+                                    match = 1;
+                             }
+                        }
+
+                        if (match == 0)
+                            banned = 1;
+                        else {
+                            banned = 0;
+                            break;
+                        }
+                    }
+                } else {
+                    for (n=count=0; n<user->channels.used; n++) {
+                        mn = user->channels.list[n];
+                        match = 0;
+
+                        if (*glob == '#') {
+                            if (0 == strcasecmp(glob, mn->channel->name))
+                                match = 1;
+                        } else {
+                            if (0 == strcasecmp(glob+1, mn->channel->name)) {
+                                if ((*glob == '@') && (mn->modes & MODE_CHANOP))
+                                    match = 1;
+                                else if ((*glob == '%') && (mn->modes & MODE_HALFOP))
+                                    match = 1;
+                                else if ((*glob == '+') && (mn->modes & MODE_VOICE))
+                                    match = 1;
+                             }
+                        }
+
+                        if (match == 1)
+                            banned = 1;
+                    }
+                }
+
+                if (banned)
+                    return 1;
+                else
+                    return match_ircglob(user->hostname, glob);
+            case 'j':
+                 if (shared == 0) {
+                     if (*glob != '#')
+                         return -1;
+                     if ((channel = GetChannel(glob))) {
+                         for (n = 0; n < channel->banlist.used; n++) {
+                             ban = channel->banlist.list[n];
+                             if (user_matches_glob(user, ban->ban, flags, 1))
+                                 return 1;
+                         }
+                     }
+                 }
+                 return match_ircglob(user->hostname, glob);
+            case 'n': /* this is handled ircd side */
+                return match_ircglob(user->hostname, glob);
+            case 'q': /* this is handled ircd side */
+                return match_ircglob(user->hostname, glob);
+            case 't': /* this is handled ircd side */
+                return match_ircglob(user->hostname, glob);
+            case 'R': /* this is handled ircd side */
+                return match_ircglob(user->hostname, glob);
+            default:
+                return -1;
+        }
+    }
+
     /* Check the nick, if it's present */
     if (flags & MATCH_USENICK) {
-        if (*glob == '~') /* small hack for extended bans */
-            return match_ircglob(user->hostname, glob);
-
         if (!(marker = strchr(glob, '!'))) {
             log_module(MAIN_LOG, LOG_ERROR, "user_matches_glob(\"%s\", \"%s\", %d) called, and glob doesn't include a '!'", user->nick, orig_glob, flags);
             return 0;