X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/6970c535bc99c3a693d0b798775f2de0832d7d36..0d6366b6a61a69b26dc0cde44eb85e3293c6659d:/newsearch/ns-kill.c diff --git a/newsearch/ns-kill.c b/newsearch/ns-kill.c index 4929bb1c..f0cb2dea 100644 --- a/newsearch/ns-kill.c +++ b/newsearch/ns-kill.c @@ -7,49 +7,58 @@ #include #include -#include "../control/control.h" /* controlreply() */ +#include "../control/control.h" #include "../localuser/localuser.h" /* killuser() */ #include "../lib/irc_string.h" /* IPtostr() */ +#include "../lib/strlfunc.h" /* used for *_free functions that need to warn users of certain things i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */ extern nick *senderNSExtern; -void *kill_exe(struct searchNode *thenode, void *theinput); -void kill_free(struct searchNode *thenode); +void *kill_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput); +void kill_free(searchCtx *ctx, struct searchNode *thenode); +static const char *defaultreason = "You (%n) have been disconnected for violating our terms of service"; struct kill_localdata { unsigned int marker; int count; - int type; char reason[NSMAX_REASON_LEN]; }; -struct searchNode *kill_parse(int type, int argc, char **argv) { +struct searchNode *kill_parse(searchCtx *ctx, int argc, char **argv) { struct kill_localdata *localdata; struct searchNode *thenode; - int len; if (!(localdata = (struct kill_localdata *) malloc(sizeof(struct kill_localdata)))) { parseError = "malloc: could not allocate memory for this search."; return NULL; } localdata->count = 0; - localdata->type = type; - if (type == SEARCHTYPE_CHANNEL) + if (ctx->searchcmd == reg_chansearch) localdata->marker = nextchanmarker(); - else + else if (ctx->searchcmd == reg_nicksearch) localdata->marker = nextnickmarker(); + else { + free(localdata); + parseError = "kill: invalid search type"; + return NULL; + } if (argc==1) { - len = snprintf(localdata->reason, NSMAX_REASON_LEN, ":%s", argv[0]); - /* strip leading and trailing '"'s */ - localdata->reason[1] = ' '; - localdata->reason[len-1] = '\0'; + struct searchNode *reasonstr; + char *p; + if (!(reasonstr=argtoconststr("kill", ctx, argv[0], &p))) { + free(localdata); + return NULL; + } + + strlcpy(localdata->reason, p, sizeof(localdata->reason)); + reasonstr->free(ctx, reasonstr); + } else { + strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason)); } - else - snprintf(localdata->reason, NSMAX_REASON_LEN, "."); - + if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) { /* couldn't malloc() memory for thenode, so free localdata to avoid leakage */ parseError = "malloc: could not allocate memory for this search."; @@ -65,19 +74,18 @@ struct searchNode *kill_parse(int type, int argc, char **argv) { return thenode; } -void *kill_exe(struct searchNode *thenode, void *theinput) { +void *kill_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) { struct kill_localdata *localdata; nick *np; chanindex *cip; localdata = thenode->localdata; - if (localdata->type == SEARCHTYPE_CHANNEL) { + if (ctx->searchcmd == reg_chansearch) { cip = (chanindex *)theinput; cip->marker = localdata->marker; localdata->count += cip->channel->users->totalusers; - } - else { + } else { np = (nick *)theinput; np->marker = localdata->marker; localdata->count++; @@ -86,64 +94,70 @@ void *kill_exe(struct searchNode *thenode, void *theinput) { return (void *)1; } -void kill_free(struct searchNode *thenode) { +void kill_free(searchCtx *ctx, struct searchNode *thenode) { struct kill_localdata *localdata; nick *np, *nnp; - chanindex *cip, *ncip; + chanindex *cip; int i, j, safe=0; + unsigned int nickmarker; + char msgbuf[512]; localdata = thenode->localdata; if (localdata->count > NSMAX_KILL_LIMIT) { /* need to warn the user that they have just tried to twat half the network ... */ - controlreply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count); + ctx->reply(senderNSExtern, "Warning: your pattern matches too many users (%d) - nothing done.", localdata->count); free(localdata); free(thenode); return; } - if (localdata->type == SEARCHTYPE_CHANNEL) { + /* For channel searches, mark up all the nicks in the relevant channels first */ + if (ctx->searchcmd == reg_chansearch) { + nickmarker=nextnickmarker(); for (i=0;inext; - if (cip != NULL && cip->channel != NULL && cip->marker == localdata->marker) { - for (j=0;jchannel->users->hashsize;j++) { - if (cip->channel->users->content[j]==nouser) - continue; - - if ((np=getnickbynumeric(cip->channel->users->content[j]))) { - if (!IsOper(np) && !IsService(np) && !IsXOper(np)) { - killuser(NULL, np, "You (%s!%s@%s) have been disconnected for violating our terms of service%s", np->nick, - np->ident, IPtostr(np->p_ipaddr), localdata->reason); - } - else - safe++; - } - } + for (cip=chantable[i];cip;cip=cip->next) { + /* Skip empty and non-matching channels */ + if (!cip->channel || cip->marker != localdata->marker) + continue; + + for (j=0;jchannel->users->hashsize;j++) { + if (cip->channel->users->content[j]==nouser) + continue; + + if ((np=getnickbynumeric(cip->channel->users->content[j]))) + np->marker=nickmarker; } } } + } else { + /* For nick searches they're already marked, pick up the saved value */ + nickmarker=localdata->marker; } - else { - for (i=0;inext; - if (np->marker == localdata->marker) { - if (!IsOper(np) && !IsService(np) && !IsXOper(np)) { - killuser(NULL, np, "You (%s!%s@%s) have been disconnected for violating our terms of service%s", np->nick, - np->ident, IPtostr(np->p_ipaddr), localdata->reason); - } - else - safe++; - } + + /* Now do the actual kills */ + for (i=0;inext; + + if (np->marker != nickmarker) + continue; + + if (IsOper(np) || IsService(np) || IsXOper(np)) { + safe++; + continue; } + + nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np); + killuser(NULL, np, "%s", msgbuf); } } + if (safe) - controlreply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe); + ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe); /* notify opers of the action */ - controlwall(NO_OPER, NL_KICKKILLS, "%s/%s killed %d %s via %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), - (localdata->count - safe) != 1 ? "users" : "user", (localdata->type == SEARCHTYPE_CHANNEL) ? "chansearch" : "nicksearch", safe); + ctx->wall(NL_KICKKILLS, "%s/%s killed %d %s via %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), + (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", safe); free(localdata); free(thenode); }