cs_log(source, "SPEWEMAIL %s", cargv[0]);
tree = NSASTNode(match_parse, NSASTNode(qemail_parse), NSASTLiteral(cargv[0]));
- return ast_usersearch(&tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, showheader, (void *)QM_SPEWHEADER, 2000);
+ return ast_usersearch(&tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, showheader, (void *)QM_SPEWHEADER, 2000, NULL);
}
int cs_dospewdb(void *source, int cargc, char **cargv) {
NSASTNode(match_parse, NSASTNode(qemail_parse), NSASTLiteral(cargv[0])),
NSASTNode(match_parse, NSASTNode(qlasthost_parse), NSASTLiteral(cargv[0])),
);
- return ast_usersearch(&tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, showheader, (void *)QM_SPEWHEADER, 2000);
+ return ast_usersearch(&tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, showheader, (void *)QM_SPEWHEADER, 2000, NULL);
}
return CMD_OK;
}
-void newsearch_ctxinit(searchCtx *ctx, searchParseFunc searchfn, replyFunc replyfn, wallFunc wallfn, void *arg, searchCmd *cmd, nick *np, void *displayfn, int limit) {
+void newsearch_ctxinit(searchCtx *ctx, searchParseFunc searchfn, replyFunc replyfn, wallFunc wallfn, void *arg, searchCmd *cmd, nick *np, void *displayfn, int limit, void *target) {
memset(ctx, 0, sizeof(searchCtx));
ctx->reply = replyfn;
ctx->searchcmd = cmd;
ctx->sender = np;
ctx->limit = limit;
+ ctx->target = target;
ctx->displayfn = displayfn;
}
return CMD_ERROR;
}
- ast_nicksearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+ ast_nicksearch(tree->root, reply, sender, wall, display, NULL, NULL, limit, NULL);
parse_free(tree);
search=coerceNode(ctx, search, RETURNTYPE_BOOL);
for (i=0;i<NICKHASHSIZE;i++) {
- for (np=nicktable[i];np;np=np->next) {
+ for (np=ctx->target ? ctx->target : nicktable[i];np;np=np->next) {
if ((search->exe)(ctx, search, np)) {
/* Add total channels */
tchans += np->channels->cursi;
ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
}
+
+ if (ctx->target)
+ goto done;
}
}
+done:
ctx->reply(sender,"--- End of list: %d matches; users were on %u channels (%u unique, %.1f average clones)",
matches, tchans, uchans, (float)tchans/uchans);
}
return CMD_ERROR;
}
- ast_whowassearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+ ast_whowassearch(tree->root, reply, sender, wall, display, NULL, NULL, limit, NULL);
parse_free(tree);
search=coerceNode(ctx, search, RETURNTYPE_BOOL);
for (i = whowasoffset; i < whowasoffset + WW_MAXENTRIES; i++) {
- ww = &whowasrecs[i % WW_MAXENTRIES];
+ if (ctx->target) {
+ ww = ctx->target;
+ } else {
+ ww = &whowasrecs[i % WW_MAXENTRIES];
- if (ww->type == WHOWAS_UNUSED)
- continue;
+ if (ww->type == WHOWAS_UNUSED)
+ continue;
+ }
/* Note: We're passing the nick to the filter function. The original
* whowas record is in the nick's ->next field. */
ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
}
+
+ if (ctx->target)
+ break;
}
ctx->reply(sender,"--- End of list: %d matches", matches);
return CMD_ERROR;
}
- ast_chansearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+ ast_chansearch(tree->root, reply, sender, wall, display, NULL, NULL, limit, NULL);
parse_free(tree);
search=coerceNode(ctx, search, RETURNTYPE_BOOL);
for (i=0;i<CHANNELHASHSIZE;i++) {
- for (cip=chantable[i];cip;cip=cip->next) {
+ for (cip=ctx->target ? ctx->target : chantable[i];cip;cip=cip->next) {
if ((search->exe)(ctx, search, cip)) {
if (matches<limit)
display(ctx, sender, cip);
if (matches==limit)
ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
+
+ if (ctx->target)
+ goto done;
}
}
}
+done:
ctx->reply(sender,"--- End of list: %d matches", matches);
}
return CMD_ERROR;
}
- ast_usersearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+ ast_usersearch(tree->root, reply, sender, wall, display, NULL, NULL, limit, NULL);
parse_free(tree);
search=coerceNode(ctx, search, RETURNTYPE_BOOL);
for (i=0;i<AUTHNAMEHASHSIZE;i++) {
- for (aup=authnametable[i];aup;aup=aup->next) {
+ for (aup=ctx->target ? ctx->target : authnametable[i];aup;aup=aup->next) {
if ((search->exe)(ctx, search, aup)) {
if (matches<limit)
display(ctx, sender, aup);
ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
}
+
+ if (ctx->target)
+ goto done;
}
}
+done:
ctx->reply(sender,"--- End of list: %d matches", matches);
}
struct searchCmd *searchcmd;
nick *sender;
int limit;
+ void *target;
void *displayfn;
} searchCtx;
searchNode *var_get(searchCtx *ctx, char *arg);
void var_setstr(struct searchVariable *v, char *data);
-void newsearch_ctxinit(searchCtx *ctx, searchParseFunc searchfn, replyFunc replyfn, wallFunc wallfn, void *arg, searchCmd *cmd, nick *sender, void *displayfn, int limit);
+void newsearch_ctxinit(searchCtx *ctx, searchParseFunc searchfn, replyFunc replyfn, wallFunc wallfn, void *arg, searchCmd *cmd, nick *sender, void *displayfn, int limit, void *target);
/* AST functions */
searchNode *search_astparse(searchCtx *, char *);
-int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, HeaderFunc header, void *headerarg, int limit);
-int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, HeaderFunc header, void *headerarg, int limit);
-int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, HeaderFunc header, void *headerarg, int limit);
-int ast_whowassearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, WhowasDisplayFunc display, HeaderFunc header, void *headerarg, int limit);
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, HeaderFunc header, void *headerarg, int limit, nick *);
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, HeaderFunc header, void *headerarg, int limit, chanindex *);
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, HeaderFunc header, void *headerarg, int limit, authname *);
+int ast_whowassearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, WhowasDisplayFunc display, HeaderFunc header, void *headerarg, int limit, whowas *);
char *ast_printtree(char *buf, size_t bufsize, searchASTExpr *expr, searchCmd *cmd);
int parseopts(int cargc, char **cargv, int *arg, int *limit, void **subset, void *display, CommandTree *sl, replyFunc reply, void *sender);
-typedef int (*ASTFunc)(searchASTExpr *, replyFunc, void *, wallFunc, void *, HeaderFunc, void *, int limit);
+typedef int (*ASTFunc)(searchASTExpr *, replyFunc, void *, wallFunc, void *, HeaderFunc, void *, int limit, void *target);
/* erk */
extern searchList *globalterms;
}
}
-int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, HeaderFunc header, void *headerarg, int limit) {
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, HeaderFunc header, void *headerarg, int limit, nick *target) {
searchCtx ctx;
searchASTCache cache;
searchNode *search;
memset(&cache, 0, sizeof(cache));
cache.tree = tree;
- newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_nicksearch, sender, display, limit);
+ newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_nicksearch, sender, display, limit, target);
buf[0] = '\0';
reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree, reg_nicksearch));
return CMD_OK;
}
-int ast_whowassearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, WhowasDisplayFunc display, HeaderFunc header, void *headerarg, int limit) {
+int ast_whowassearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, WhowasDisplayFunc display, HeaderFunc header, void *headerarg, int limit, whowas *target) {
searchCtx ctx;
searchASTCache cache;
searchNode *search;
memset(&cache, 0, sizeof(cache));
cache.tree = tree;
- newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_whowassearch, sender, display, limit);
+ newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_whowassearch, sender, display, limit, target);
buf[0] = '\0';
reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree, reg_whowassearch));
return CMD_OK;
}
-int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, HeaderFunc header, void *headerarg, int limit) {
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, HeaderFunc header, void *headerarg, int limit, chanindex *target) {
searchCtx ctx;
searchASTCache cache;
searchNode *search;
char buf[1024];
- newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_chansearch, sender, display, limit);
+ newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_chansearch, sender, display, limit, target);
memset(&cache, 0, sizeof(cache));
cache.tree = tree;
return CMD_OK;
}
-int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, HeaderFunc header, void *headerarg, int limit) {
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, HeaderFunc header, void *headerarg, int limit, authname *target) {
searchCtx ctx;
searchASTCache cache;
searchNode *search;
memset(&cache, 0, sizeof(cache));
cache.tree = tree;
- newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_usersearch, sender, display, limit);
+ newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_usersearch, sender, display, limit, target);
buf[0] = '\0';
reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree, reg_usersearch));
--- /dev/null
+include ../build.mk
+.PHONY: all
+all: nickwatch.so
+
+nickwatch.so: nickwatch.o
--- /dev/null
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "../core/schedule.h"
+#include "../control/control.h"
+#include "../newsearch/newsearch.h"
+#include "../newsearch/parser.h"
+
+typedef struct nickwatch {
+ int id;
+
+ char term[512];
+ parsertree *tree;
+
+ struct nickwatch *next;
+} nickwatch;
+
+typedef struct nickwatchevent {
+ char description[128];
+ long numeric;
+} nickwatchevent;
+
+static nickwatch *nickwatches;
+static int nextnickwatch = 1;
+
+static void nw_dummyreply(nick *np, char *format, ...) { }
+
+static void nw_dummywall(int level, char *format, ...) { }
+
+static int nw_currentid;
+static nickwatchevent *nw_currentevent;
+
+static void nw_printnick(searchCtx *ctx, nick *sender, nick *np) {
+ char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
+
+ controlwall(NO_OPER, NL_HITS, "nickwatch(#%d, %s): %s [%s] (%s) (%s)", nw_currentid, nw_currentevent->description, visiblehostmask(np,hostbuf),
+ IPtostr(np->ipaddress), printflags(np->umodes, umodeflags), np->realname->name->content);
+}
+
+static nickwatchevent *nwe_new(nick *np, const char *format, ...) {
+ nickwatchevent *nwe;
+ va_list va;
+
+ nwe = malloc(sizeof(nickwatchevent));
+ nwe->numeric = np->numeric;
+
+ va_start(va, format);
+ vsnprintf(nwe->description, sizeof(nwe->description), format, va);
+ va_end(va);
+
+ return nwe;
+}
+
+static void nwe_free(nickwatchevent *nwe) {
+ free(nwe);
+}
+
+static void nw_sched_processevent(void *arg) {
+ nickwatchevent *nwe = arg;
+ nick *np;
+ nickwatch *nw;
+
+ np = getnickbynumeric(nwe->numeric);
+
+ if (!np) {
+ nwe_free(nwe);
+ return;
+ }
+ nw_currentevent = nwe;
+
+ for (nw = nickwatches; nw; nw = nw->next) {
+ nw_currentid = nw->id;
+ ast_nicksearch(nw->tree->root, &nw_dummyreply, mynick, &nw_dummywall, &nw_printnick, NULL, NULL, 10, np);
+ }
+
+ nwe_free(nwe);
+}
+
+static void nw_hook_newnick(int hooknum, void *arg) {
+ nick *np = arg;
+ nickwatchevent *nwe = nwe_new(np, "new user");
+ scheduleoneshot(0, nw_sched_processevent, nwe);
+}
+
+static void nw_hook_joinchannel(int hooknum, void *arg) {
+ void **args = arg;
+ channel *cp = args[0];
+ nick *np = args[1];
+ nickwatchevent *nwe = nwe_new(np, "join channel %s", cp->index->name->content);
+ scheduleoneshot(0, nw_sched_processevent, nwe);
+}
+
+static int nw_cmd_nickwatch(void *source, int cargc, char **cargv) {
+ nick *sender = source;
+ nickwatch *nw;
+ parsertree *tree;
+
+ if (cargc < 1)
+ return CMD_USAGE;
+
+ tree = parse_string(reg_nicksearch, cargv[0]);
+ if (!tree) {
+ displaystrerror(controlreply, sender, cargv[0]);
+ return CMD_ERROR;
+ }
+
+ nw = malloc(sizeof(nickwatch));
+ nw->id = nextnickwatch++;
+ strncpy(nw->term, cargv[0], sizeof(nw->term));
+ nw->tree = parse_string(reg_nicksearch, cargv[0]);
+ nw->next = nickwatches;
+ nickwatches = nw;
+
+ controlreply(sender, "Done.");
+
+ return CMD_OK;
+}
+
+static int nw_cmd_nickunwatch(void *source, int cargc, char **cargv) {
+ nick *sender = source;
+ nickwatch **pnext, *nw;
+ int id;
+
+ if (cargc < 1)
+ return CMD_USAGE;
+
+ id = atoi(cargv[0]);
+
+ for (pnext = &nickwatches; *pnext; pnext = &((*pnext)->next)) {
+ nw = *pnext;
+
+ if (nw->id == id) {
+ parse_free(nw->tree);
+ *pnext = nw->next;
+ free(nw);
+
+ controlreply(sender, "Done.");
+ return CMD_OK;
+ }
+ }
+
+ controlreply(sender, "Nickwatch #%d not found.", id);
+
+ return CMD_ERROR;
+}
+
+static int nw_cmd_nickwatches(void *source, int cargc, char **cargv) {
+ nick *sender = source;
+ nickwatch *nw;
+
+ controlreply(sender, "ID Term");
+
+ for (nw = nickwatches; nw; nw = nw->next)
+ controlreply(sender, "%-5d %s", nw->id, nw->term);
+
+ controlreply(sender, "--- End of nickwatches.");
+
+ return CMD_OK;
+}
+
+void _init(void) {
+ registercontrolhelpcmd("nickwatch", NO_OPER, 1, &nw_cmd_nickwatch, "Usage: nickwatch <nicksearch term>\nAdds a nickwatch entry.");
+ registercontrolhelpcmd("nickunwatch", NO_OPER, 1, &nw_cmd_nickunwatch, "Usage: nickunwatch <#id>\nRemoves a nickwatch entry.");
+ registercontrolhelpcmd("nickwatches", NO_OPER, 0, &nw_cmd_nickwatches, "Usage: nickwatches\nLists nickwatches.");
+
+ registerhook(HOOK_NICK_NEWNICK, &nw_hook_newnick);
+ registerhook(HOOK_CHANNEL_CREATE, &nw_hook_joinchannel);
+ registerhook(HOOK_CHANNEL_JOIN, &nw_hook_joinchannel);
+}
+
+void _fini(void) {
+ nickwatch *nw, *next;
+
+ deregistercontrolcmd("nickwatch", &nw_cmd_nickwatch);
+ deregistercontrolcmd("nickunwatch", &nw_cmd_nickunwatch);
+ deregistercontrolcmd("nickwatches", &nw_cmd_nickwatches);
+
+ deregisterhook(HOOK_NICK_NEWNICK, &nw_hook_newnick);
+ deregisterhook(HOOK_CHANNEL_CREATE, &nw_hook_joinchannel);
+ deregisterhook(HOOK_CHANNEL_JOIN, &nw_hook_joinchannel);
+
+ for (nw = nickwatches; nw; nw = next) {
+ next = nw->next;
+
+ parse_free(nw->tree);
+ free(nw);
+ }
+}
return CMD_USAGE;
tree = NSASTNode(match_parse, NSASTNode(hostmask_parse), NSASTLiteral(cargv[0]));
- return ast_nicksearch(&tree, controlreply, sender, controlnswall, printnick, NULL, NULL, 500);
+ return ast_nicksearch(&tree, controlreply, sender, controlnswall, printnick, NULL, NULL, 500, NULL);
}
int controlspewchan(void *sender, int cargc, char **cargv) {
return CMD_USAGE;
tree = NSASTNode(match_parse, NSASTNode(name_parse), NSASTLiteral(cargv[0]));
- return ast_chansearch(&tree, controlreply, sender, controlnswall, printchannel, NULL, NULL, 500);
+ return ast_chansearch(&tree, controlreply, sender, controlnswall, printchannel, NULL, NULL, 500, NULL);
}
int controlcompare(void *sender, int cargc, char **cargv) {
}
tree = NSASTManualNode(and_parse, cargc, nodes);
- return (execfn)(&tree, controlreply, sender, controlnswall, displayfn, NULL, NULL, 500);
+ return (execfn)(&tree, controlreply, sender, controlnswall, displayfn, NULL, NULL, 500, NULL);
}
int controlbroadcast(void *sender, int cargc, char **cargv) {
snprintf(message, sizeof(message), "(oBroadcast) %s", cargv[0]);
tree = NSASTNode(and_parse, NSASTNode(modes_parse, NSASTLiteral("+o")), NSASTNode(notice_parse, NSASTLiteral(message)));
- if((ret=ast_nicksearch(&tree, controlreply, sender, controlnswall, NULL, NULL, NULL, -1)) == CMD_OK) {
+ if((ret=ast_nicksearch(&tree, controlreply, sender, controlnswall, NULL, NULL, NULL, -1, NULL)) == CMD_OK) {
controlwall(NO_OPER, NL_BROADCASTS, "%s/%s sent an obroadcast: %s", np->nick, np->authname, cargv[0]);
controlreply(np, "Message obroadcasted.");
} else {
snprintf(message, sizeof(message), "(cBroadcast) %s", cargv[1]);
tree = NSASTNode(and_parse, NSASTNode(country_parse, NSASTLiteral(cargv[0])), NSASTNode(notice_parse, NSASTLiteral(message)));
- if((ret=ast_nicksearch(&tree, controlreply, sender, controlnswall, NULL, NULL, NULL, -1)) == CMD_OK) {
+ if((ret=ast_nicksearch(&tree, controlreply, sender, controlnswall, NULL, NULL, NULL, -1, NULL)) == CMD_OK) {
controlwall(NO_OPER, NL_BROADCASTS, "%s/%s sent a cbroadcast %s: %s", np->nick, np->authname, cargv[0], cargv[1]);
controlreply(np, "Message cbroadcasted.");
} else {
#include <string.h>
#include "patriciasearch.h"
-int ast_nodesearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NodeDisplayFunc display, HeaderFunc header, void *headerarg, int limit) {
+int ast_nodesearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NodeDisplayFunc display, HeaderFunc header, void *headerarg, int limit, patricia_node_t *target) {
searchCtx ctx;
searchASTCache cache;
searchNode *search;
char buf[1024];
- newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_nodesearch, sender, display, limit);
+ newsearch_ctxinit(&ctx, search_astparse, reply, wall, &cache, reg_nodesearch, sender, display, limit, target);
memset(&cache, 0, sizeof(cache));
cache.tree = tree;
return CMD_ERROR;
}
- ast_nodesearch(tree->root, reply, sender, wall, display, NULL, NULL, limit);
+ ast_nodesearch(tree->root, reply, sender, wall, display, NULL, NULL, limit, NULL);
parse_free(tree);
int do_pnodesearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
-int ast_nodesearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NodeDisplayFunc display, HeaderFunc header, void *headerarg, int limit);
+int ast_nodesearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NodeDisplayFunc display, HeaderFunc header, void *headerarg, int limit, patricia_node_t *target);
void regpnodedisp(const char *name, NodeDisplayFunc handler);
void unregpnodedisp(const char *name, NodeDisplayFunc handler);
return CMD_USAGE;
tree = NSASTNode(tgroup_parse, NSASTLiteral(cargv[0]));
- return ast_nicksearch(&tree, controlreply, sender, NULL, printnick_channels, NULL, NULL, 2000);
+ return ast_nicksearch(&tree, controlreply, sender, NULL, printnick_channels, NULL, NULL, 2000, NULL);
}
static int commandsregistered;