X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/057503e20fa17411a54cbacc16ca8e1c4fba34b2..9d4541acd3fa4962bd0a17ff8b09c0373c465e1d:/glines/glines_commands.c?ds=sidebyside diff --git a/glines/glines_commands.c b/glines/glines_commands.c index 99ed4d0a..0941887f 100644 --- a/glines/glines_commands.c +++ b/glines/glines_commands.c @@ -18,92 +18,164 @@ MODULE_VERSION(""); static void registercommands(int, void *); static void deregistercommands(int, void *); +static int parse_gline_flags(nick *sender, const char *flagparam, int *overridesanity, int *overridelimit, int *simulate, int *chase, int *coff) { + const char *pos; + + *coff = 0; + *overridesanity = 0; + *overridelimit = 0; + *simulate = 0; + + if (chase) + *chase = 0; + + if (flagparam[0] == '-') { + *coff = 1; + + for (pos = flagparam + 1; *pos; pos++) { + switch (*pos) { + case 'f': + *overridesanity = 1; + break; + case 'l': + *overridelimit = 1; + break; + case 'S': + *simulate = 1; + break; + case 'c': + if (!chase) + goto invalid; + + *chase = 1; + break; + default: + goto invalid; + } + } + } + + return 1; + +invalid: + controlreply(sender, "Invalid flag specified: %c", *pos); + return 0; +} + static int glines_cmdblock(void *source, int cargc, char **cargv) { nick *sender = source; - nick *target; - int hits, duration; + nick *target, *wnp; + whowas *ww; + int hits, duration, id; + int coff, overridesanity, overridelimit, simulate, chase; char *reason; - char creator[32]; + char creator[128]; glinebuf gbuf; + int ownww; - if (cargc < 3) + if (cargc < 1) return CMD_USAGE; - target = getnickbynick(cargv[0]); - - if (!target) { - controlreply(sender, "Sorry, couldn't find that user."); + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &chase, &coff)) return CMD_ERROR; - } - duration = durationtolong(cargv[1]); + if (cargc < 3 + coff) + return CMD_USAGE; + + duration = durationtolong(cargv[coff + 1]); if (duration <= 0) { controlreply(sender, "Invalid duration specified."); return CMD_ERROR; } - if (duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); + target = getnickbynick(cargv[coff]); + + if (!target) { + ww = whowas_chase(cargv[coff], 1800); + + if (!ww) { + controlreply(sender, "Sorry, couldn't find that user."); + return CMD_ERROR; + } + + ownww = 0; + + controlreply(sender, "Found matching whowas record:"); + controlreply(sender, "%s", whowas_format(ww)); + } else { + ww = whowas_fromnick(target, 1); + ownww = 1; + } + + wnp = &ww->nick; + + if (sender != target && (IsService(wnp) || IsOper(wnp) || NickOnServiceServer(wnp))) { + controlreply(sender, "Target user '%s' is an oper or a service. Not setting G-Lines.", wnp->nick); return CMD_ERROR; } - reason = cargv[2]; + rejoinline(cargv[coff + 2], cargc - coff - 2); + reason = cargv[coff + 2]; + + if (sender->auth) + snprintf(creator, sizeof(creator), "#%s", sender->authname); + else + strncpy(creator, controlid(sender), sizeof(creator)); + + glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "BLOCK", cargc + coff - 1, cargv); + glinebufaddbywhowas(&gbuf, ww, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); + + glinebufspew(&gbuf, sender); - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + if (ownww) + whowas_free(ww); + controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines."); return CMD_ERROR; } - snprintf(creator, sizeof(creator), "#%s", sender->authname); + if (simulate) { + glinebufabort(&gbuf); + if (ownww) + whowas_free(ww); + controlreply(sender, "Simulation complete. Not setting G-Lines."); + return CMD_ERROR; + } - glinebufinit(&gbuf, 1); - glinebufaddbynick(&gbuf, target, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); glinebufcounthits(&gbuf, &hits, NULL); - glinebufflush(&gbuf, 1); + id = glinebufcommit(&gbuf, 1); - controlwall(NO_OPER, NL_GLINES, "%s BLOCK'ed user '%s!%s@%s' for %s with reason '%s' (%d hits)", controlid(sender), target->nick, target->ident, target->host->name->content, longtoduration(duration, 0), reason, hits); + controlwall(NO_OPER, NL_GLINES, "%s BLOCK'ed user '%s!%s@%s' for %s with reason '%s' (%d hits)", controlid(sender), + wnp->nick, wnp->ident, wnp->host->name->content, + longtoduration(duration, 0), reason, hits); - controlreply(sender, "Done."); + if (ownww) + whowas_free(ww); + + controlreply(sender, "Done. G-Line transaction ID: %d", id); return CMD_OK; } static int glines_cmdgline(void *source, int cargc, char **cargv) { nick *sender = source; - int duration, users, channels; - char *mask, *reason, *pos; - char creator[32]; - int coff, sanitychecks, operlimit; + int duration, users, channels, id; + char *mask, *reason; + char creator[128]; + int coff, overridesanity, overridelimit, simulate; glinebuf gbuf; #if SNIRCD_VERSION < 140 gline *gl; -#endif +#endif /* SNIRCD_VERSION */ if (cargc < 1) return CMD_USAGE; - coff = 0; - sanitychecks = 1; - operlimit = 1; - - if (cargv[0][0] == '-') { - coff = 1; - - for (pos = &(cargv[0][1]); *pos; pos++) { - switch (*pos) { - case 'S': - sanitychecks = 0; - break; - case 'l': - operlimit = 0; - break; - default: - controlreply(sender, "Invalid flag specified: %c", *pos); - return CMD_ERROR; - } - } - } + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff)) + return CMD_ERROR; if (cargc < 3 + coff) return CMD_USAGE; @@ -117,19 +189,9 @@ static int glines_cmdgline(void *source, int cargc, char **cargv) { return CMD_ERROR; } - if (duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); - return CMD_ERROR; - } - rejoinline(cargv[coff + 2], cargc - coff - 2); reason = cargv[coff + 2]; - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); - return CMD_ERROR; - } - #if SNIRCD_VERSION < 140 gl = findgline(mask); @@ -142,73 +204,42 @@ static int glines_cmdgline(void *source, int cargc, char **cargv) { controlreply(sender, "Reactivating existing gline on %s", mask); } -#endif +#endif /* SNIRCD_VERSION */ - snprintf(creator, sizeof(creator), "#%s", sender->authname); + if (sender->auth) + snprintf(creator, sizeof(creator), "#%s", sender->authname); + else + strncpy(creator, controlid(sender), sizeof(creator)); - glinebufinit(&gbuf, 1); + glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "GLINE", cargc + coff - 1, cargv); if (!glinebufadd(&gbuf, mask, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration)) { controlreply(sender, "Invalid G-Line mask."); return CMD_ERROR; } - glinebufcounthits(&gbuf, &users, &channels); - - if (operlimit) { - if (channels > MAXUSERGLINECHANNELHITS) { - glinebufabandon(&gbuf); - controlreply(sender, "G-Line on '%s' would hit %d channels. Limit is %d. Not setting G-Line.", mask, channels, MAXUSERGLINECHANNELHITS); - return CMD_ERROR; - } else if (users > MAXUSERGLINEUSERHITS) { - glinebufabandon(&gbuf); - controlreply(sender, "G-Line on '%s' would hit %d users. Limit is %d. Not setting G-Line.", mask, users, MAXUSERGLINEUSERHITS); - return CMD_ERROR; - } - } + glinebufspew(&gbuf, sender); - if (sanitychecks && glinebufsanitize(&gbuf) > 0) { - glinebufabandon(&gbuf); - controlreply(sender, "G-Line failed sanity checks. Not setting G-Line."); + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines."); return CMD_ERROR; } - - glinebufflush(&gbuf, 1); - - controlwall(NO_OPER, NL_GLINES, "%s GLINE'd mask '%s' for %s with reason '%s' (hits %d users/%d channels)", - controlid(sender), mask, longtoduration(duration, 0), reason, users, channels); - - controlreply(sender, "Done."); - - return CMD_OK; -} - -static int glines_cmdglinesimulate(void *source, int cargc, char **cargv) { - nick *sender = source; - char *mask; - glinebuf gbuf; - int users, channels; - char creator[32]; - - if (cargc < 1) - return CMD_USAGE; - - mask = cargv[0]; - - snprintf(creator, sizeof(creator), "#%s", sender->authname); - glinebufinit(&gbuf, 0); - - if (!glinebufadd(&gbuf, mask, creator, "Simulate", getnettime(), getnettime(), getnettime())) { - glinebufabandon(&gbuf); - controlreply(sender, "Invalid G-Line mask."); + if (simulate) { + glinebufabort(&gbuf); + controlreply(sender, "Simulation complete. Not setting G-Lines."); return CMD_ERROR; } glinebufcounthits(&gbuf, &users, &channels); - glinebufabandon(&gbuf); + id = glinebufcommit(&gbuf, 1); + + controlwall(NO_OPER, NL_GLINES, "%s GLINE'd mask '%s' for %s with reason '%s' (hits %d users/%d channels)", + controlid(sender), mask, longtoduration(duration, 0), reason, users, channels); - controlreply(sender, "G-Line on '%s' would hit %d users/%d channels.", mask, users, channels); + controlreply(sender, "Done. G-Line transaction ID: %d", id); return CMD_OK; } @@ -221,38 +252,36 @@ static int glines_cmdsmartgline(void *source, int cargc, char **cargv) { struct irc_in_addr ip; unsigned char bits; int hits, duration; + int coff, overridesanity, overridelimit, simulate, id; char *reason; - char creator[32]; + char creator[128]; glinebuf gbuf; - if (cargc < 3) + if (cargc < 1) + return CMD_USAGE; + + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff)) + return CMD_ERROR; + + if (cargc < 3 + coff) return CMD_USAGE; - origmask = cargv[0]; + origmask = cargv[coff]; if (origmask[0] == '#' || origmask[0] == '&' || origmask[0] == '$') { controlreply(sender, "Please use \"gline\" for badchan or realname glines."); return CMD_ERROR; } - duration = durationtolong(cargv[1]); + duration = durationtolong(cargv[coff + 1]); if (duration <= 0) { controlreply(sender, "Invalid duration specified."); return CMD_ERROR; } - if (duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); - return CMD_ERROR; - } - - reason = cargv[2]; - - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); - return CMD_ERROR; - } + rejoinline(cargv[coff + 2], cargc - coff - 2); + reason = cargv[coff + 2]; strncpy(mask, origmask, sizeof(mask)); @@ -282,17 +311,36 @@ static int glines_cmdsmartgline(void *source, int cargc, char **cargv) { return CMD_ERROR; } - snprintf(creator, sizeof(creator), "#%s", sender->authname); + if (sender->auth) + snprintf(creator, sizeof(creator), "#%s", sender->authname); + else + strncpy(creator, controlid(sender), sizeof(creator)); - glinebufinit(&gbuf, 1); + glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "SMARTGLINE", cargc + coff - 1, cargv); glinebufaddbyip(&gbuf, user, &ip, 128, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); + + glinebufspew(&gbuf, sender); + + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + controlreply(sender, "G-Lines failed sanity checks. Not setting G-Lines."); + return CMD_ERROR; + } + + if (simulate) { + glinebufabort(&gbuf); + controlreply(sender, "Simulation complete. Not setting G-Lines."); + return CMD_ERROR; + } + glinebufcounthits(&gbuf, &hits, NULL); - glinebufflush(&gbuf, 1); + id = glinebufcommit(&gbuf, 1); - controlwall(NO_OPER, NL_GLINES, "%s GLINE'd mask '%s' for %s with reason '%s' (%d hits)", + controlwall(NO_OPER, NL_GLINES, "%s SMARTGLINE'd mask '%s' for %s with reason '%s' (%d hits)", controlid(sender), cargv[0], longtoduration(duration, 0), reason, hits); - controlreply(sender, "Done."); + controlreply(sender, "Done. G-Line transaction ID: %d", id); return CMD_OK; } @@ -353,55 +401,59 @@ static int glines_cmdclearchan(void *source, int cargc, char **cargv) { channel *cp; nick *np; char *reason = "Clearing channel."; - int mode, duration, i, slot, hits; + int mode, duration, i, slot, hits, id; + int coff, overridesanity, overridelimit, simulate; array victims; - char creator[32]; + char creator[128]; glinebuf gbuf; - if (cargc < 2) + if (cargc < 1) + return CMD_USAGE; + + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff)) + return CMD_ERROR; + + if (cargc < 2 + coff) return CMD_USAGE; - cp = findchannel(cargv[0]); + cp = findchannel(cargv[coff]); if (!cp) { controlreply(sender, "Couldn't find that channel."); return CMD_ERROR; } - if (strcmp(cargv[1], "kick") == 0) + if (strcmp(cargv[coff + 1], "kick") == 0) mode = 0; - else if (strcmp(cargv[1], "kill") == 0) + else if (strcmp(cargv[coff + 1], "kill") == 0) mode = 1; - else if (strcmp(cargv[1], "gline") == 0) + else if (strcmp(cargv[coff + 1], "gline") == 0) mode = 2; - else if (strcmp(cargv[1], "glineall") == 0) + else if (strcmp(cargv[coff + 1], "glineall") == 0) mode = 3; else return CMD_USAGE; if (mode == 0 || mode == 1) { if (cargc >= 3) { - rejoinline(cargv[2], cargc - 2); - reason = cargv[2]; + rejoinline(cargv[coff + 2], cargc - coff - 2); + reason = cargv[coff + 2]; } } else { - if (cargc < 3) + if (cargc < 3 + coff) return CMD_USAGE; - duration = durationtolong(cargv[2]); + duration = durationtolong(cargv[coff + 2]); if (duration <= 0) { controlreply(sender, "Invalid duration specified."); return CMD_ERROR; } - if (duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); - return CMD_ERROR; + if (cargc >= 4 + coff) { + rejoinline(cargv[coff + 3], cargc - coff - 3); + reason = cargv[coff + 3]; } - - if (cargc >= 4) - reason = cargv[3]; } array_init(&victims, sizeof(nick *)); @@ -425,19 +477,31 @@ static int glines_cmdclearchan(void *source, int cargc, char **cargv) { (((nick **)victims.content)[slot]) = np; } - snprintf(creator, sizeof(creator), "#%s", sender->authname); + if (sender->auth) + snprintf(creator, sizeof(creator), "#%s", sender->authname); + else + strncpy(creator, controlid(sender), sizeof(creator)); - glinebufinit(&gbuf, 1); + glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "CLEARCHAN", cargc + coff - 1, cargv); for (i = 0; i < victims.cursi; i++) { np = ((nick **)victims.content)[i]; switch (mode) { case 0: - localkickuser(NULL, cp, np, reason); + if (simulate) + controlreply(sender, "user: %s!%s@%s r(%s)", np->nick, np->ident, np->host->name->content, np->realname->name->content); + else + localkickuser(NULL, cp, np, reason); + break; case 1: - killuser(NULL, np, "%s", reason); + if (simulate) + controlreply(sender, "user: %s!%s@%s r(%s)", np->nick, np->ident, np->host->name->content, np->realname->name->content); + else + killuser(NULL, np, "%s", reason); + break; case 2: if (IsAccount(np)) @@ -451,19 +515,37 @@ static int glines_cmdclearchan(void *source, int cargc, char **cargv) { } } + if (mode != 0 && mode != 1) { + glinebufspew(&gbuf, sender); + + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + controlreply(sender, "G-Line failed sanity checks. Not setting G-Line."); + return CMD_ERROR; + } + } + + if (simulate) { + glinebufabort(&gbuf); + controlreply(sender, "Simulation complete. Not clearing channel."); + return CMD_ERROR; + } + + glinebufmerge(&gbuf); glinebufcounthits(&gbuf, &hits, NULL); - glinebufflush(&gbuf, 1); + id = glinebufcommit(&gbuf, 1); array_free(&victims); - if (mode == 0 || mode == 1) + if (mode == 0 || mode == 1) { controlwall(NO_OPER, NL_GLINES, "%s CLEARCHAN'd channel '%s' with mode '%s' and reason '%s'", controlid(sender), cp->index->name->content, cargv[1], reason); - else + controlreply(sender, "Done."); + } else { controlwall(NO_OPER, NL_GLINES, "%s CLEARCHAN'd channel '%s' with mode '%s', duration %s and reason '%s' (%d hits)", controlid(sender), cp->index->name->content, cargv[1], longtoduration(duration, 0), reason, hits); - - controlreply(sender, "Done."); + controlreply(sender, "Done. G-Line transaction ID: %d", id); + } return CMD_OK; } @@ -473,51 +555,72 @@ static int glines_cmdtrustgline(void *source, int cargc, char **cargv) { trustgroup *tg; trusthost *th; int duration, hits; + int coff, overridesanity, overridelimit, simulate, id; char *reason; char mask[512]; - char creator[32]; + char creator[128]; glinebuf gbuf; - if (cargc < 4) + if (cargc < 1) return CMD_USAGE; - tg = tg_strtotg(cargv[0]); + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, NULL, &coff)) + return CMD_ERROR; + + if (cargc < 4 + coff) + return CMD_USAGE; + + tg = tg_strtotg(cargv[coff]); if (!(tg->flags & TRUST_RELIABLE_USERNAME)) { controlreply(sender, "Sorry, that trust group does not have the \"reliable username\" flag."); return CMD_ERROR; } - duration = durationtolong(cargv[2]); + duration = durationtolong(cargv[coff + 2]); - if (duration <= 0 || duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); + if (duration <= 0) { + controlreply(sender, "Invalid duration specified."); return CMD_ERROR; } - reason = cargv[3]; + rejoinline(cargv[coff + 3], cargc - coff - 3); + reason = cargv[coff + 3]; - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); - return CMD_ERROR; - } - - snprintf(creator, sizeof(creator), "#%s", sender->authname); + if (sender->auth) + snprintf(creator, sizeof(creator), "#%s", sender->authname); + else + strncpy(creator, controlid(sender), sizeof(creator)); glinebufinit(&gbuf, 0); + glinebufcommentv(&gbuf, "TRUSTGLINE", cargc + coff - 1, cargv); for(th = tg->hosts; th; th = th->next) { - snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], trusts_cidr2str(&th->ip, th->bits)); + snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], CIDRtostr(th->ip, th->bits)); glinebufadd(&gbuf, mask, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); } + glinebufspew(&gbuf, sender); + + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + controlreply(sender, "G-Line failed sanity checks. Not setting G-Line."); + return CMD_ERROR; + } + + if (simulate) { + glinebufabort(&gbuf); + controlreply(sender, "Simulation complete. Not setting G-Lines."); + return CMD_ERROR; + } + glinebufcounthits(&gbuf, &hits, NULL); - glinebufflush(&gbuf, 1); + id = glinebufcommit(&gbuf, 1); controlwall(NO_OPER, NL_GLINES, "%s TRUSTGLINE'd user '%s' on trust group '%s' for %s with reason '%s' (%d hits)", controlid(sender), cargv[1], tg->name->content, longtoduration(duration, 0), reason, hits); - controlreply(sender, "Done."); + controlreply(sender, "Done. G-Line transaction ID: %d", id); return CMD_OK; } @@ -543,7 +646,7 @@ static int glines_cmdtrustungline(void *source, int cargc, char **cargv) { count = 0; for (th = tg->hosts; th; th = th->next) { - snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], trusts_cidr2str(&th->ip, th->bits)); + snprintf(mask, sizeof(mask), "*!%s@%s", cargv[1], CIDRtostr(th->ip, th->bits)); gl = findgline(mask); @@ -618,7 +721,7 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { char *mask; int count = 0; int limit = 500; - char tmp[250]; + char expirestr[250], idstr[250]; if (cargc < 1 || (cargc == 1 && cargv[0][0] == '-')) { controlreply(sender, "Syntax: glist [-flags] "); @@ -633,8 +736,6 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { return CMD_ERROR; } - mask = cargv[0]; - if (cargc > 1) { char* ch = cargv[0]; @@ -686,7 +787,7 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { } if (!(flags & GLIST_COUNT)) - controlreply(sender, "%-50s %-19s %-25s %s", "Mask:", "Expires in:", "Creator:", "Reason:"); + controlreply(sender, "%-50s %-19s %-15s %-25s %s", "Mask:", "Expires in:", "Transaction ID:", "Creator:", "Reason:"); gline *searchgl = makegline(mask); @@ -710,13 +811,14 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { if (!(gl->flags & GLINE_REALNAME)) continue; if (flags & GLIST_EXACT) { - if (!glineequal(searchgl, gl)) { + if (!glineequal(searchgl, gl)) continue; - } } else if (flags & GLIST_FIND) { - if (!gline_match_mask(searchgl, gl)) { + if (!gline_match_mask(gl, searchgl)) + continue; + } else { + if (!match2strings(mask, glinetostring(gl))) continue; - } } } else { if (gl->flags & GLINE_REALNAME) @@ -727,28 +829,29 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { if (!gl->reason || ircd_strcmp(mask, gl->reason->content) != 0) continue; } else if (flags & GLIST_FIND) { - if (!gl->reason || match(gl->reason->content, mask)) + if (!gl->reason || !match2strings(gl->reason->content, mask)) continue; - } else if (!gl->reason || match(mask, gl->reason->content)) + } else if (!gl->reason || !match2strings(mask, gl->reason->content)) continue; } else if (flags & GLIST_OWNER) { if (flags & GLIST_EXACT) { if (!gl->creator || ircd_strcmp(mask, gl->creator->content) != 0) continue; } else if (flags & GLIST_FIND) { - if (!gl->creator || match(gl->creator->content, mask)) + if (!gl->creator || !match2strings(gl->creator->content, mask)) continue; - } else if (!gl->creator || match(mask, gl->creator->content)) + } else if (!gl->creator || !match2strings(mask, gl->creator->content)) continue; } else { if (flags & GLIST_EXACT) { - if (!glineequal(searchgl, gl)) { + if (!glineequal(searchgl, gl)) continue; - } } else if (flags & GLIST_FIND) { - if (!gline_match_mask(searchgl, gl)) { + if (!gline_match_mask(gl, searchgl)) + continue; + } else { + if (!match2strings(mask, glinetostring(gl))) continue; - } } } } @@ -759,11 +862,13 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { count++; if (!(flags & GLIST_COUNT) && count < limit) { - snprintf(tmp, 249, "%s", glinetostring(gl)); - controlreply(sender, "%s%-49s %-19s %-25s %s", + snprintf(expirestr, sizeof(expirestr), "%s", glinetostring(gl)); + snprintf(idstr, sizeof(idstr), "%d", gl->glinebufid); + controlreply(sender, "%s%-49s %-19s %-15s %-25s %s", (gl->flags & GLINE_ACTIVE) ? "+" : "-", - tmp, + expirestr, (gl->flags & GLINE_ACTIVE) ? (char*)longtoduration(gl->expire - curtime, 0) : "", + gl->glinebufid ? idstr : "", gl->creator ? gl->creator->content : "", gl->reason ? gl->reason->content : ""); } @@ -774,6 +879,130 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { return CMD_OK; } +static int glines_cmdglinelog(void *source, int cargc, char **cargv) { + nick *sender = source; + glinebuf *gbl; + gline *gl; + int i, id, count; + char timebuf[30]; + + id = 0; + + if (cargc > 0) { + id = atoi(cargv[0]); + + if (id == 0) { + controlreply(sender, "Invalid log ID."); + return CMD_ERROR; + } + } + + controlreply(sender, "Time ID G-Lines User Hits Channel Hits Comment"); + + for (i = 0; i < MAXGLINELOG; i++) { + gbl = glinebuflog[(i + glinebuflogoffset + 1) % MAXGLINELOG]; + + if (!gbl) + continue; + + if (id == 0 || gbl->id == id) { + count = 0; + + for (gl = gbl->glines; gl; gl = gl->next) + count++; + + strftime(timebuf, sizeof(timebuf), "%d/%m/%y %H:%M:%S", localtime((gbl->amend) ? &gbl->amend : &gbl->commit)); + strncat(timebuf, (gbl->amend) ? "*" : " ", sizeof(timebuf)); + controlreply(sender, "%-20s %-10d %-10d %-15d %-15d %s", timebuf, gbl->id, count, gbl->userhits, gbl->channelhits, gbl->comment ? gbl->comment->content : "(no comment)"); + } + + if (id != 0 && gbl->id == id) { + glinebufspew(gbl, sender); + controlreply(sender, "Done."); + return CMD_OK; + } + } + + if (id == 0) { + controlreply(sender, "Done."); + } else { + controlreply(sender, "Log entry for ID %d not found.", id); + } + + return CMD_OK; +} + +static int glines_cmdglineundo(void *source, int cargc, char **cargv) { + nick *sender = source; + int id; + + if (cargc < 1) + return CMD_USAGE; + + id = atoi(cargv[0]); + + if (id == 0 || !glinebufundo(id)) { + controlreply(sender, "Invalid log ID."); + return CMD_ERROR; + } + + controlreply(sender, "Done."); + + return CMD_OK; +} + +static int glines_cmdsyncglines(void *source, int cargc, char **cargv) { + nick *sender = source; + gline *gl; + int count; + + count = 0; + + for (gl = glinelist; gl; gl = gl->next) { + gline_propagate(gl); + count++; + } + + controlwall(NO_OPER, NL_GLINES, "%s SYNCGLINE'd %d G-Lines.", + controlid(sender), count); + + controlreply(sender, "Done."); + + return CMD_OK; +} + +static int glines_cmdcleanupglines(void *source, int cargc, char **cargv) { + nick *sender = source; + gline **pnext, *gl; + int count; + time_t now; + + count = 0; + time(&now); + + for (pnext = &glinelist; *pnext;) { + gl = *pnext; + + /* Remove inactivate glines that have been last changed more than a week ago */ + if (!(gl->flags & GLINE_ACTIVE) && gl->lastmod < now - 7 * 24 * 60 * 60) { + gline_destroy(gl, 0, 1); + count++; + } else { + pnext = &((*pnext)->next); + } + + if (!*pnext) + break; + } + + controlwall(NO_OPER, NL_GLINES, "%s CLEANUPGLINES'd %d G-Lines.", + controlid(sender), count); + + controlreply(sender, "Done."); + + return CMD_OK; +} + static int commandsregistered; static void registercommands(int hooknum, void *arg) { @@ -781,17 +1010,20 @@ static void registercommands(int hooknum, void *arg) { return; commandsregistered = 1; - registercontrolhelpcmd("block", NO_OPER, 3, glines_cmdblock, "Usage: block \nSets a gline using an appropriate mask given the user's nickname."); - registercontrolhelpcmd("gline", NO_OPER, 4, glines_cmdgline, "Usage: gline ?flags? \nSets a gline. Flags can be one or more of:\n-S - bypass sanity checks\n-l - bypass hit limits"); - registercontrolhelpcmd("glinesimulate", NO_OPER, 1, glines_cmdglinesimulate, "Usage: glinesimulate \nSimulates what happens when a gline is set."); - registercontrolhelpcmd("smartgline", NO_OPER, 3, glines_cmdsmartgline, "Usage: smartgline \nSets a gline. Automatically adjusts the mask depending on whether the specified mask is trusted."); + registercontrolhelpcmd("block", NO_OPER, 4, glines_cmdblock, "Usage: block ?flags? \nSets a gline using an appropriate mask given the user's nickname.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit\n-c - chase nick across quits/kills/nick changes"); + registercontrolhelpcmd("gline", NO_OPER, 4, glines_cmdgline, "Usage: gline ?flags? \nSets a gline.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit"); + registercontrolhelpcmd("smartgline", NO_OPER, 4, glines_cmdsmartgline, "Usage: smartgline ?flags? \nSets a gline. Automatically adjusts the mask depending on whether the specified mask is trusted.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit"); registercontrolhelpcmd("ungline", NO_OPER, 1, glines_cmdungline, "Usage: ungline \nDeactivates a gline."); registercontrolhelpcmd("destroygline", NO_DEVELOPER, 1, glines_cmddestroygline, "Usage: destroygline \nDestroys a gline."); - registercontrolhelpcmd("clearchan", NO_OPER, 4, glines_cmdclearchan, "Usage: clearchan <#channel> ?reason?\nClears a channel.\nhow can be one of:\nkick - Kicks users.\nkill - Kills users.\ngline - Glines non-authed users (using an appropriate mask).\nglineall - Glines users.\nDuration is only valid when glining users. Reason defaults to \"Clearing channel.\"."); - registercontrolhelpcmd("trustgline", NO_OPER, 4, glines_cmdtrustgline, "Usage: trustgline <#id|name> \nSets a gline on the specified username for each host in the specified trust group. The username may contain wildcards."); + registercontrolhelpcmd("clearchan", NO_OPER, 5, glines_cmdclearchan, "Usage: clearchan ?flags? <#channel> ?reason?\nClears a channel.\nhow can be one of:\nkick - Kicks users.\nkill - Kills users.\ngline - Glines non-authed users (using an appropriate mask).\nglineall - Glines users.\nDuration is only valid when glining users. Reason defaults to \"Clearing channel.\".\nFlags (for glines) can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit"); + registercontrolhelpcmd("trustgline", NO_OPER, 5, glines_cmdtrustgline, "Usage: trustgline ?flags? <#id|name> \nSets a gline on the specified username for each host in the specified trust group. The username may contain wildcards.\nFlags can be one or more of:\n-f - bypass sanity checks\n-l - bypass hit limits\n-S - simulate who the glines would hit"); registercontrolhelpcmd("trustungline", NO_OPER, 2, glines_cmdtrustungline, "Usage: trustungline <#id|name> \nRemoves a gline that was previously set with trustgline."); registercontrolhelpcmd("glstats", NO_OPER, 0, glines_cmdglstats, "Usage: glstat\nShows statistics about G-Lines."); registercontrolhelpcmd("glist", NO_OPER, 2, glines_cmdglist, "Usage: glist [-flags] \nLists matching G-Lines.\nValid flags are:\n-c: Count G-Lines.\n-f: Find G-Lines active on .\n-x: Find G-Lines matching exactly.\n-R: Find G-lines on realnames.\n-o: Search for glines by owner.\n-r: Search for glines by reason.\n-i: Include inactive glines."); + registercontrolhelpcmd("glinelog", NO_OPER, 1, glines_cmdglinelog, "Usage: glinelog ?id?\nShows information about previous gline transactions."); + registercontrolhelpcmd("glineundo", NO_OPER, 1, glines_cmdglineundo, "Usage: glineundo ?id?\nUndoes a gline transaction."); + registercontrolhelpcmd("syncglines", NO_DEVELOPER, 0, glines_cmdsyncglines, "Usage: syncglines\nSends all G-Lines to all other servers."); + registercontrolhelpcmd("cleanupglines", NO_DEVELOPER, 0, glines_cmdcleanupglines, "Usage: cleanupglines\nDestroys all deactivated G-Lines."); } static void deregistercommands(int hooknum, void *arg) { @@ -801,7 +1033,6 @@ static void deregistercommands(int hooknum, void *arg) { deregistercontrolcmd("block", glines_cmdblock); deregistercontrolcmd("gline", glines_cmdgline); - deregistercontrolcmd("glinesimulate", glines_cmdglinesimulate); deregistercontrolcmd("smartgline", glines_cmdsmartgline); deregistercontrolcmd("ungline", glines_cmdungline); deregistercontrolcmd("destroygline", glines_cmddestroygline); @@ -810,6 +1041,10 @@ static void deregistercommands(int hooknum, void *arg) { deregistercontrolcmd("trustungline", glines_cmdtrustungline); deregistercontrolcmd("glstats", glines_cmdglstats); deregistercontrolcmd("glist", glines_cmdglist); + deregistercontrolcmd("glinelog", glines_cmdglinelog); + deregistercontrolcmd("glineundo", glines_cmdglineundo); + deregistercontrolcmd("syncglines", glines_cmdsyncglines); + deregistercontrolcmd("cleanupglines", glines_cmdcleanupglines); } void _init(void) {