X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/8dfe8ec62620bb511aa85b51ea05af4820070cf6..8855bb48b449ed06cfd3ce528b3c0a77c37cb24b:/glines/glines_commands.c diff --git a/glines/glines_commands.c b/glines/glines_commands.c index e769e0a8..68f93ed6 100644 --- a/glines/glines_commands.c +++ b/glines/glines_commands.c @@ -18,92 +18,122 @@ 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 *coff) { + const char *pos; + + *coff = 0; + *overridesanity = 0; + *overridelimit = 0; + *simulate = 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; + default: + controlreply(sender, "Invalid flag specified: %c", *pos); + return 0; + } + } + } + + return 1; +} + static int glines_cmdblock(void *source, int cargc, char **cargv) { nick *sender = source; nick *target; - int hits, duration; + int hits, duration, id; + int coff, overridesanity, overridelimit, simulate; 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, &coff)) + return CMD_ERROR; + + if (cargc < 3 + coff) return CMD_USAGE; - target = getnickbynick(cargv[0]); + target = getnickbynick(cargv[coff]); if (!target) { controlreply(sender, "Sorry, couldn't find that user."); 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; - } + 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); + glinebufaddbynick(&gbuf, target, 0, creator, reason, getnettime() + duration, getnettime(), getnettime() + duration); - reason = cargv[2]; + glinebufspew(&gbuf, sender); - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); + if (!glinebufchecksane(&gbuf, sender, overridesanity, overridelimit)) { + glinebufabort(&gbuf); + 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); + 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); - controlreply(sender, "Done."); + 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, &coff)) + return CMD_ERROR; if (cargc < 3 + coff) return CMD_USAGE; @@ -117,19 +147,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 +162,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); - controlreply(sender, "G-Line on '%s' would hit %d users/%d channels.", mask, users, channels); + 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. G-Line transaction ID: %d", id); return CMD_OK; } @@ -221,39 +210,37 @@ 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; - origmask = cargv[0]; - - if (origmask[0] == '#' || origmask[0] == '&') { - controlreply(sender, "Please use \"gline\" for badchans and regex glines."); + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff)) return CMD_ERROR; - } - duration = durationtolong(cargv[1]); + if (cargc < 3 + coff) + return CMD_USAGE; - if (duration <= 0) { - controlreply(sender, "Invalid duration specified."); - return CMD_ERROR; - } + origmask = cargv[coff]; - if (duration > MAXUSERGLINEDURATION) { - controlreply(sender, "Sorry, glines may not last longer than %s.", longtoduration(MAXUSERGLINEDURATION, 0)); + if (origmask[0] == '#' || origmask[0] == '&' || origmask[0] == '$') { + controlreply(sender, "Please use \"gline\" for badchan or realname glines."); return CMD_ERROR; } - reason = cargv[2]; + duration = durationtolong(cargv[coff + 1]); - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); + if (duration <= 0) { + controlreply(sender, "Invalid duration specified."); return CMD_ERROR; } + rejoinline(cargv[coff + 2], cargc - coff - 2); + reason = cargv[coff + 2]; + strncpy(mask, origmask, sizeof(mask)); if (strchr(mask, '!')) { @@ -282,17 +269,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; } @@ -325,60 +331,87 @@ static int glines_cmdungline(void *source, int cargc, char **cargv) { return CMD_OK; } +static int glines_cmddestroygline(void *source, int cargc, char **cargv) { + nick *sender = source; + gline *gl; + + if (cargc < 1) + return CMD_USAGE; + + gl = findgline(cargv[0]); + + if (!gl) { + controlreply(sender, "No such G-Line."); + return CMD_ERROR; + } + + gline_destroy(gl, 0, 1); + + controlwall(NO_OPER, NL_GLINES, "%s DESTROYGLINE'd mask '%s'", controlid(sender), cargv[0]); + + controlreply(sender, "G-Line destroyed."); + + return CMD_OK; +} + static int glines_cmdclearchan(void *source, int cargc, char **cargv) { nick *sender = source; 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; - cp = findchannel(cargv[0]); + if (!parse_gline_flags(sender, cargv[0], &overridesanity, &overridelimit, &simulate, &coff)) + return CMD_ERROR; + + if (cargc < 2 + coff) + return CMD_USAGE; + + 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 *)); @@ -402,19 +435,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)) @@ -428,19 +473,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; } @@ -450,51 +513,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, &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]; - - if (strlen(reason) < MINUSERGLINEREASON) { - controlreply(sender, "Please specify a proper gline reason."); - return CMD_ERROR; - } + rejoinline(cargv[coff + 3], cargc - coff - 3); + reason = cargv[coff + 3]; - 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; } @@ -520,7 +604,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); @@ -595,7 +679,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] "); @@ -610,8 +694,6 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { return CMD_ERROR; } - mask = cargv[0]; - if (cargc > 1) { char* ch = cargv[0]; @@ -663,7 +745,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); @@ -687,13 +769,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) @@ -704,28 +787,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; - } } } } @@ -736,11 +820,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 : ""); } @@ -751,29 +837,74 @@ static int glines_cmdglist(void *source, int cargc, char **cargv) { return CMD_OK; } -static int glines_cmdcleanupglines(void *source, int cargc, char **cargv) { +static int glines_cmdglinelog(void *source, int cargc, char **cargv) { nick *sender = source; - gline **pnext, *gl; - int count; + glinebuf *gbl; + gline *gl; + int i, id, count; + char timebuf[30]; - count = 0; + id = 0; - for (pnext = &glinelist; *pnext; pnext = &((*pnext)->next)) { - gl = *pnext; + if (cargc > 0) { + id = atoi(cargv[0]); - if (!(gl->flags & GLINE_ACTIVE)) { - gline_destroy(gl, 0, 1); - count++; + 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 (!*pnext) - break; + 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; + } } - controlwall(NO_OPER, NL_GLINES, "%s CLEANUPGLINES'd %d G-Lines.", - controlid(sender), count); + 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; - controlreply(sender, "Done."); + 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; } @@ -798,31 +929,35 @@ static int glines_cmdsyncglines(void *source, int cargc, char **cargv) { return CMD_OK; } -static int glines_cmdsaveglines(void *source, int cargc, char **cargv) { - nick *sender = source; - int count; - - count = glstore_save(); - - if (count < 0) - controlreply(sender, "An error occured while saving G-Lines."); - else - controlreply(sender, "Saved %d G-Line%s.", count, (count == 1) ? "" : "s"); - - return CMD_OK; -} - -static int glines_cmdloadglines(void *source, int cargc, char **cargv) { +static int glines_cmdcleanupglines(void *source, int cargc, char **cargv) { nick *sender = source; + gline **pnext, *gl; int count; - - count = glstore_load(); - - if (count < 0) - controlreply(sender, "An error occured while loading the G-Lines file."); - else - controlreply(sender, "Loaded %d G-Line%s.", count, (count == 1) ? "" : "s"); - + 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; } @@ -833,20 +968,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"); + 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("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("destroygline", NO_DEVELOPER, 1, glines_cmddestroygline, "Usage: destroygline \nDestroys a gline."); + 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("cleanupglines", NO_OPER, 0, glines_cmdcleanupglines, "Usage: cleanupglines\nDestroys all deactivated G-Lines."); + 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("loadglines", NO_DEVELOPER, 0, glines_cmdloadglines, "Usage: loadglines\nForce load of glines."); - registercontrolhelpcmd("saveglines", NO_DEVELOPER, 0, glines_cmdsaveglines, "Usage: saveglines\nForce save of glines."); + registercontrolhelpcmd("cleanupglines", NO_DEVELOPER, 0, glines_cmdcleanupglines, "Usage: cleanupglines\nDestroys all deactivated G-Lines."); } static void deregistercommands(int hooknum, void *arg) { @@ -856,18 +991,18 @@ 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); deregistercontrolcmd("clearchan", glines_cmdclearchan); deregistercontrolcmd("trustgline", glines_cmdtrustgline); deregistercontrolcmd("trustungline", glines_cmdtrustungline); deregistercontrolcmd("glstats", glines_cmdglstats); deregistercontrolcmd("glist", glines_cmdglist); - deregistercontrolcmd("cleanupglines", glines_cmdcleanupglines); + deregistercontrolcmd("glinelog", glines_cmdglinelog); + deregistercontrolcmd("glineundo", glines_cmdglineundo); deregistercontrolcmd("syncglines", glines_cmdsyncglines); - deregistercontrolcmd("loadglines", glines_cmdloadglines); - deregistercontrolcmd("saveglines", glines_cmdsaveglines); + deregistercontrolcmd("cleanupglines", glines_cmdcleanupglines); } void _init(void) {