- 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;
- }
- }
- return discrim;
-
- fail:
- free(discrim);
- return NULL;
-}
-
-typedef int (*dnr_search_func)(struct do_not_register *match, void *extra);
-
-static unsigned int
-dnr_search(struct dnr_search *discrim, dnr_search_func dsf, void *data)
-{
- struct do_not_register *dnr;
- dict_iterator_t next;
- dict_iterator_t it;
- unsigned int count;
- int target_fixed;
-
- /* Initialize local variables. */
- count = 0;
- target_fixed = 0;
- if(discrim->chan_mask)
- {
- int shift = (discrim->chan_mask[0] == '\\' && discrim->chan_mask[1] == '*') ? 2 : 0;
- if('\0' == discrim->chan_mask[shift + strcspn(discrim->chan_mask+shift, "*?")])
- target_fixed = 1;
- }
-
- if(target_fixed && discrim->chan_mask[0] == '\\' && discrim->chan_mask[1] == '*')
- {
- /* Check against account-based DNRs. */
- dnr = dict_find(handle_dnrs, discrim->chan_mask + 2, NULL);
- if(dnr && dnr_search_matches(dnr, discrim) && (count++ < discrim->limit))
- dsf(dnr, data);
- }
- else if(target_fixed)
- {
- /* Check against channel-based DNRs. */
- dnr = dict_find(plain_dnrs, discrim->chan_mask, NULL);
- if(dnr && dnr_search_matches(dnr, discrim) && (count++ < discrim->limit))
- dsf(dnr, data);
- }
- else
- {
- /* Exhaustively search account DNRs. */
- for(it = dict_first(handle_dnrs); it; it = next)
- {
- next = iter_next(it);
- dnr = iter_data(it);
- if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
- break;
- }
- /* Do the same for channel DNRs. */
- for(it = dict_first(plain_dnrs); it; it = next)
- {
- next = iter_next(it);
- dnr = iter_data(it);
- if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
- break;
- }
-
- /* Do the same for wildcarded channel DNRs. */
- for(it = dict_first(mask_dnrs); it; it = next)
- {
- next = iter_next(it);
- dnr = iter_data(it);
- if(dnr_search_matches(dnr, discrim) && (count++ < discrim->limit) && dsf(dnr, data))
- break;
- }
- }
- return count;
-}
-
-static int
-dnr_remove_func(struct do_not_register *match, void *extra)
-{
- struct userNode *user;
- char *chan_name;
-
- chan_name = alloca(strlen(match->chan_name) + 1);
- strcpy(chan_name, match->chan_name);
- user = extra;
- if(((chan_name[0] == '*') && dict_remove(handle_dnrs, chan_name+1))
- || dict_remove(plain_dnrs, chan_name)
- || dict_remove(mask_dnrs, chan_name))
- {
- send_message(user, chanserv, "CSMSG_DNR_REMOVED", chan_name);