+void rg_setdelay(nick *np, rg_struct *reason, short punish) {
+ rg_delay *delay;
+ delay = (rg_delay *)malloc(sizeof(rg_delay));
+
+ /* Just incase */
+ if(!delay) {
+ killuser(NULL, np, "%s (ID: %08lx)", reason->reason->content, reason->glineid);
+ return;
+ }
+
+ delay->np = np;
+ delay->reason = reason;
+ delay->punish = punish;
+ delay->next = rg_delays;
+ rg_delays = delay;
+
+ delay->sch = scheduleoneshot(time(NULL) + (RG_MINIMUM_DELAY_TIME + (rand() % RG_MAXIMUM_RAND_TIME)), rg_dodelay, delay);
+}
+
+static void rg_shadowserver(nick *np, struct rg_struct *reason, int type) {
+ char buf[1024];
+
+ if(reason->class != classes[0]) /* drone */
+ return;
+
+ snprintf(buf, sizeof(buf), "regex-ban %lu %s!%s@%s %s %s", time(NULL), np->nick, np->ident, np->host->name->content, reason->mask->content, serverlist[homeserver(np->numeric)].name->content);
+
+ triggerhook(HOOK_SHADOW_SERVER, (void *)buf);
+}
+
+void rg_deletedelay(rg_delay *delay) {
+ rg_delay *temp, *prev;
+ prev = NULL;
+ for (temp=rg_delays;temp;temp=temp->next) {
+ if (temp==delay) {
+ if (temp==rg_delays)
+ rg_delays = temp->next;
+ else
+ prev->next = temp->next;
+
+ free(temp);
+ return;
+ }
+
+ prev = temp;
+ }
+}
+
+void rg_dodelay(void *arg) {
+ rg_delay *delay = (rg_delay *)arg;
+ char hostname[RG_MASKLEN];
+ int hostlen, usercount = 0;
+
+ /* User or regex gline no longer exists */
+ if((!delay->np) || (!delay->reason)) {
+ rg_deletedelay(delay);
+ return;
+ }
+
+ hostlen = RGBuildHostname(hostname, delay->np);
+
+ /* User has wisely changed nicknames */
+ if(pcre_exec(delay->reason->regex, delay->reason->hint, hostname, hostlen, 0, 0, NULL, 0) < 0) {
+ rg_deletedelay(delay);
+ return;
+ }
+
+ if (delay->reason->type == DELAYED_HOST_GLINE) {
+ usercount = delay->np->host->clonecount;
+ snprintf(hostname, sizeof(hostname), "*@%s", IPtostr(delay->np->p_ipaddr));
+ }
+
+ if((delay->reason->type == DELAYED_IDENT_GLINE) || (usercount > rg_max_per_gline)) {
+ nick *tnp;
+
+ for(usercount=0,tnp=delay->np->host->nicks;tnp;tnp=tnp->nextbyhost)
+ if(!ircd_strcmp(delay->np->ident, tnp->ident))
+ usercount++;
+
+ snprintf(hostname, sizeof(hostname), "%s@%s", delay->np->ident, IPtostr(delay->np->p_ipaddr));
+ }
+
+ if ((delay->reason->type == DELAYED_KILL) || (usercount > rg_max_per_gline)) {
+ if (IsAccount(delay->np)) {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s/%s matched delayed kill regex %08lx (class: %s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->np->authname, delay->reason->glineid, delay->reason->class);
+ } else {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s matched delayed kill regex %08lx (class: %s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->reason->glineid, delay->reason->class);
+ }
+
+ rg_shadowserver(delay->np, delay->reason, DELAYED_KILL);
+ killuser(NULL, delay->np, "%s (ID: %08lx)", delay->reason->reason->content, delay->reason->glineid);
+ return;
+ }
+
+ if (delay->reason->type == DELAYED_IDENT_GLINE) {
+ if (IsAccount(delay->np)) {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s/%s matched delayed user@host gline regex %08lx (class: %s, hit %d user%s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->np->authname, delay->reason->glineid, delay->reason->class, usercount, (usercount!=1)?"s":"");
+ } else {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s matched delayed user@host gline regex %08lx (class: %s, hit %d user%s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->reason->glineid, delay->reason->class, usercount, (usercount!=1)?"s":"");
+ }
+ } else if (delay->reason->type == DELAYED_HOST_GLINE) {
+ if (IsAccount(delay->np)) {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s/%s matched delayed *@host gline regex %08lx (class: %s, hit %d user%s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->np->authname, delay->reason->glineid, delay->reason->class, usercount, (usercount!=1)?"s":"");
+ } else {
+ controlwall(NO_OPER, NL_HITS, "%s!%s@%s matched delayed *@host gline regex %08lx (class: %s, hit %d user%s)", delay->np->nick, delay->np->ident, delay->np->host->name->content, delay->reason->glineid, delay->reason->class, usercount, (usercount!=1)?"s":"");
+ }
+ } else {
+ return;
+ }
+
+ rg_shadowserver(delay->np, delay->reason, delay->reason->type);
+ irc_send("%s GL * +%s %d %jd :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, (intmax_t)time(NULL), delay->reason->reason->content, delay->reason->glineid);
+ rg_deletedelay(delay);
+}
+