+ return 1;
+ }
+ reply("CSMSG_NO_SUCH_DNR", chan_name);
+ return 0;
+}
+
+struct dnr_search {
+ struct userNode *source;
+ char *chan_mask;
+ char *setter_mask;
+ char *reason_mask;
+ time_t min_set, max_set;
+ time_t min_expires, max_expires;
+ unsigned int limit;
+};
+
+static int
+dnr_search_matches(const struct do_not_register *dnr, const struct dnr_search *search)
+{
+ return !((dnr->set < search->min_set)
+ || (dnr->set > search->max_set)
+ || (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
+ && !match_ircglob(dnr->setter, search->setter_mask))
+ || (search->reason_mask
+ && !match_ircglob(dnr->reason, search->reason_mask)));
+}
+
+static struct dnr_search *
+dnr_search_create(struct userNode *user, struct svccmd *cmd, unsigned int argc, char *argv[])
+{
+ struct dnr_search *discrim;
+ unsigned int ii;
+
+ discrim = calloc(1, sizeof(*discrim));
+ discrim->source = user;
+ discrim->chan_mask = NULL;
+ discrim->setter_mask = NULL;
+ discrim->reason_mask = NULL;
+ discrim->max_set = INT_MAX;
+ discrim->limit = 50;
+
+ for(ii=0; ii<argc; ++ii)
+ {
+ if(ii == argc - 1)
+ {
+ reply("MSG_MISSING_PARAMS", argv[ii]);
+ goto fail;
+ }
+ else if(0 == irccasecmp(argv[ii], "channel"))
+ {
+ discrim->chan_mask = argv[++ii];
+ }
+ else if(0 == irccasecmp(argv[ii], "setter"))
+ {
+ discrim->setter_mask = argv[++ii];
+ }
+ else if(0 == irccasecmp(argv[ii], "reason"))
+ {
+ discrim->reason_mask = argv[++ii];
+ }
+ else if(0 == irccasecmp(argv[ii], "limit"))
+ {
+ discrim->limit = strtoul(argv[++ii], NULL, 0);
+ }
+ else if(0 == irccasecmp(argv[ii], "set"))
+ {
+ const char *cmp = argv[++ii];
+ if(cmp[0] == '<') {
+ if(cmp[1] == '=')
+ discrim->min_set = now - ParseInterval(cmp + 2);
+ else
+ discrim->min_set = now - (ParseInterval(cmp + 1) - 1);
+ } else if(cmp[0] == '=') {
+ discrim->min_set = discrim->max_set = now - ParseInterval(cmp + 1);
+ } else if(cmp[0] == '>') {
+ if(cmp[1] == '=')
+ discrim->max_set = now - ParseInterval(cmp + 2);
+ else
+ discrim->max_set = now - (ParseInterval(cmp + 1) - 1);
+ } else {
+ discrim->max_set = now - (ParseInterval(cmp) - 1);
+ }
+ }
+ else if(0 == irccasecmp(argv[ii], "expires"))
+ {
+ const char *cmp = argv[++ii];
+ if(cmp[0] == '<') {
+ if(cmp[1] == '=')
+ discrim->max_expires = now + ParseInterval(cmp + 2);
+ else
+ discrim->max_expires = now + (ParseInterval(cmp + 1) - 1);
+ } else if(cmp[0] == '=') {
+ discrim->min_expires = discrim->max_expires = now + ParseInterval(cmp + 1);
+ } else if(cmp[0] == '>') {
+ if(cmp[1] == '=')
+ discrim->min_expires = now + ParseInterval(cmp + 2);
+ else
+ discrim->min_expires = now + (ParseInterval(cmp + 1) - 1);
+ } else {
+ discrim->min_expires = now + (ParseInterval(cmp) - 1);
+ }
+ }
+ else
+ {
+ reply("MSG_INVALID_CRITERIA", argv[ii]);
+ goto fail;
+ }