Fix DNR expiration and expiration-based DNR searches.
[srvx.git] / src / chanserv.c
index 4f391c544eea03db7bfa64f9ef538b67452d69fa..ec6a364e7aacd6e663b3dcb918593ceab9dd5804 100644 (file)
@@ -1397,29 +1397,29 @@ expire_channels(UNUSED_ARG(void *data))
 static void
 expire_dnrs(UNUSED_ARG(void *data))
 {
-    dict_iterator_t it;
+    dict_iterator_t it, next;
     struct do_not_register *dnr;
 
-    for(it = dict_first(handle_dnrs); it; it = iter_next(it))
+    for(it = dict_first(handle_dnrs); it; it = next)
     {
         dnr = iter_data(it);
-        if(!dnr->expires || dnr->expires > now)
-            continue;
-        dict_remove(handle_dnrs, dnr->chan_name + 1);
+        next = iter_next(it);
+        if(dnr->expires && dnr->expires <= now)
+            dict_remove(handle_dnrs, dnr->chan_name + 1);
     }
-    for(it = dict_first(plain_dnrs); it; it = iter_next(it))
+    for(it = dict_first(plain_dnrs); it; it = next)
     {
         dnr = iter_data(it);
-        if(!dnr->expires || dnr->expires > now)
-            continue;
-        dict_remove(plain_dnrs, dnr->chan_name);
+        next = iter_next(it);
+        if(dnr->expires && dnr->expires <= now)
+            dict_remove(plain_dnrs, dnr->chan_name + 1);
     }
-    for(it = dict_first(mask_dnrs); it; it = iter_next(it))
+    for(it = dict_first(mask_dnrs); it; it = next)
     {
         dnr = iter_data(it);
-        if(!dnr->expires || dnr->expires > now)
-            continue;
-        dict_remove(mask_dnrs, dnr->chan_name);
+        next = iter_next(it);
+        if(dnr->expires && dnr->expires <= now)
+            dict_remove(mask_dnrs, dnr->chan_name + 1);
     }
 
     if(chanserv_conf.dnr_expire_frequency)
@@ -1734,8 +1734,10 @@ dnr_search_matches(const struct do_not_register *dnr, const struct dnr_search *s
 {
     return !((dnr->set < search->min_set)
              || (dnr->set > search->max_set)
-             || (dnr->expires && ((dnr->expires < search->min_expires)
-                                  || (dnr->expires > search->max_expires)))
+             || (dnr->expires < search->min_expires)
+             || (search->max_expires
+                 && ((dnr->expires == 0)
+                     || (dnr->expires > search->max_expires)))
              || (search->chan_mask
                  && !match_ircglob(dnr->chan_name, search->chan_mask))
              || (search->setter_mask
@@ -1756,7 +1758,6 @@ dnr_search_create(struct userNode *user, struct svccmd *cmd, unsigned int argc,
     discrim->setter_mask = NULL;
     discrim->reason_mask = NULL;
     discrim->max_set = INT_MAX;
-    discrim->max_expires = INT_MAX;
     discrim->limit = 50;
 
     for(ii=0; ii<argc; ++ii)
@@ -3122,6 +3123,35 @@ eject_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c
         ban = generate_hostmask(victim, GENMASK_STRICT_HOST|GENMASK_ANY_IDENT);
         name = victim->nick;
     }
+    else if(!is_ircmask(argv[1]) && (*argv[1] == '*'))
+    {
+        struct handle_info *hi;
+        char banmask[NICKLEN + USERLEN + HOSTLEN + 3];
+        const char *accountname = argv[1] + 1;
+
+        if(!(hi = get_handle_info(accountname)))
+        {
+            reply("MSG_HANDLE_UNKNOWN", accountname);
+            return 0;
+        }
+
+        snprintf(banmask, sizeof(banmask), "*!*@%s.*", hi->handle);
+        victims = alloca(sizeof(victims[0]) * channel->members.used);
+
+        if(bad_channel_ban(channel, user, banmask, &victimCount, victims))
+        {
+            reply("CSMSG_MASK_PROTECTED", banmask);
+            return 0;
+        }
+
+        if((action == ACTION_KICK) && (victimCount == 0))
+        {
+            reply("CSMSG_NO_MATCHING_USERS", channel->name, banmask);
+            return 0;
+        }
+
+        name = ban = strdup(banmask);
+    }
     else
     {
         if(!is_ircmask(argv[1]))
@@ -3437,13 +3467,23 @@ unban_user(struct userNode *user, struct chanNode *channel, unsigned int argc, c
     /* may want to allow a comma delimited list of users... */
     if(!(actee = GetUserH(argv[1])))
     {
-        if(!is_ircmask(argv[1]))
+        if(!is_ircmask(argv[1]) && *argv[1] == '*')
+        {
+            char banmask[NICKLEN + USERLEN + HOSTLEN + 3];
+            const char *accountname = argv[1] + 1;
+
+            snprintf(banmask, sizeof(banmask), "*!*@%s.*", accountname);
+            mask = strdup(banmask);
+        }
+        else if(!is_ircmask(argv[1]))
         {
             reply("MSG_NICK_UNKNOWN", argv[1]);
             return 0;
         }
-
-        mask = strdup(argv[1]);
+        else
+        {
+            mask = strdup(argv[1]);
+        }
     }
 
     /* We don't sanitize the mask here because ircu