.PHONY: all
all: chanserv_newsearch.so
-chanserv_newsearch.so: chanserv_newsearch.o formats.o csns-qusers.o interface.o
+chanserv_newsearch.so: chanserv_newsearch.o formats.o csns-qusers.o interface.o csns-qlasthost.o csns-qemail.o csns-qsuspendreason.o csns-qusername.o
-#include "../../newsearch/newsearch.h"
#include "../chanserv.h"
-
-/* formats.c */
-void printnick_auth(searchCtx *, nick *, nick *);
-void printnick_authchans(searchCtx *, nick *, nick *);
-void printchannel_qusers(searchCtx *, nick *, chanindex *);
-
-struct searchNode *qusers_parse(searchCtx *, int type, int argc, char **argv);
+#include "chanserv_newsearch.h"
int cs_donicksearch(void *source, int cargc, char **cargv);
int cs_dochansearch(void *source, int cargc, char **cargv);
+int cs_dousersearch(void *source, int cargc, char **cargv);
+int cs_dospewemailtwo(void *source, int cargc, char **cargv);
+int cs_dospewdbtwo(void *source, int cargc, char **cargv);
+
+UserDisplayFunc previousdefault;
void _init() {
regnickdisp("auth", printnick_auth);
regnickdisp("authchans", printnick_authchans);
regchandisp("qusers", printchannel_qusers);
+ reguserdisp("auth", printauth);
+
registersearchterm("qusers", qusers_parse);
+ registersearchterm("qlasthost", qlasthost_parse);
+ registersearchterm("qemail", qemail_parse);
+ registersearchterm("qsuspendreason", qsuspendreason_parse);
+ registersearchterm("qusername", qusername_parse);
chanservaddcommand("nicksearch", QCMD_OPER, 5, cs_donicksearch, "Wrapper for standard newserv nicksearch command.", "");
chanservaddcommand("chansearch", QCMD_OPER, 5, cs_dochansearch, "Wrapper for standard newserv chansearch command.", "");
+ chanservaddcommand("usersearch", QCMD_OPER, 5, cs_dousersearch, "Wrapper for standard newserv usersearch command.", "");
+ chanservaddcommand("spewemailtwo", QCMD_OPER, 1, cs_dospewemailtwo, "Spews email...", "");
+ chanservaddcommand("spewdbtwo", QCMD_OPER, 1, cs_dospewdbtwo, "Spews db...", "");
+
+ previousdefault = defaultuserfn;
+ defaultuserfn = printauth;
}
void _fini() {
unregnickdisp("auth", printnick_auth);
unregnickdisp("authchans", printnick_authchans);
unregchandisp("qusers", printchannel_qusers);
+ unreguserdisp("auth", printauth);
+
deregistersearchterm("qusers", qusers_parse);
+ deregistersearchterm("qlasthost", qlasthost_parse);
+ deregistersearchterm("qemail", qemail_parse);
+ deregistersearchterm("qsuspendreason", qsuspendreason_parse);
+ deregistersearchterm("qusername", qusername_parse);
chanservremovecommand("nicksearch", cs_donicksearch);
chanservremovecommand("chansearch", cs_dochansearch);
+ chanservremovecommand("usersearch", cs_dousersearch);
+ chanservremovecommand("spewemailtwo", cs_dospewemailtwo);
+ chanservremovecommand("spewdbtwo", cs_dospewdbtwo);
+
+ defaultuserfn = previousdefault;
}
--- /dev/null
+#ifndef __CHANSERV_NEWSEARCH_H
+#define __CHANSERV_NEWSEARCH_H
+
+#include "../../newsearch/newsearch.h"
+
+void printnick_auth(searchCtx *, nick *, nick *);
+void printnick_authchans(searchCtx *, nick *, nick *);
+void printchannel_qusers(searchCtx *, nick *, chanindex *);
+void printauth(searchCtx *, nick *, authname *);
+
+struct searchNode *qusers_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qlasthost_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qemail_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qsuspendreason_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qusername_parse(searchCtx *, int type, int argc, char **argv);
+
+#endif
--- /dev/null
+/*
+ * qemail functionality
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qemail_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qemail_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qemail_parse(searchCtx *ctx, int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_USER) {
+ parseError = "qemail: this function is only valid for user searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_STRING;
+ thenode->exe = qemail_exe;
+ thenode->free = qemail_free;
+
+ return thenode;
+}
+
+void *qemail_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+ authname *ap = (authname *)theinput;
+ reguser *rup = ap->exts[chanservext];
+ if(!rup || !rup->email)
+ return "";
+
+ return rup->email->content;
+}
+
+void qemail_free(searchCtx *ctx, struct searchNode *thenode) {
+ free(thenode);
+}
+
--- /dev/null
+/*
+ * qlasthost functionality
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qlasthost_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qlasthost_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qlasthost_parse(searchCtx *ctx, int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_USER) {
+ parseError = "qlasthost: this function is only valid for user searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_STRING;
+ thenode->exe = qlasthost_exe;
+ thenode->free = qlasthost_free;
+
+ return thenode;
+}
+
+void *qlasthost_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+ authname *ap = (authname *)theinput;
+ reguser *rup = ap->exts[chanservext];
+ if(!rup || !rup->lastuserhost)
+ return "";
+
+ return rup->lastuserhost->content;
+}
+
+void qlasthost_free(searchCtx *ctx, struct searchNode *thenode) {
+ free(thenode);
+}
--- /dev/null
+/*
+ * qsuspendreason functionality
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qsuspendreason_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qsuspendreason_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qsuspendreason_parse(searchCtx *ctx, int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_USER) {
+ parseError = "qsuspendreason: this function is only valid for user searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_STRING;
+ thenode->exe = qsuspendreason_exe;
+ thenode->free = qsuspendreason_free;
+
+ return thenode;
+}
+
+void *qsuspendreason_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+ authname *ap = (authname *)theinput;
+ reguser *rup = ap->exts[chanservext];
+ if(!rup || !UHasSuspension(rup) || !rup->suspendreason)
+ return "";
+
+ return rup->suspendreason->content;
+}
+
+void qsuspendreason_free(searchCtx *ctx, struct searchNode *thenode) {
+ free(thenode);
+}
+
--- /dev/null
+/*
+ * qusername functionality
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qusername_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qusername_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qusername_parse(searchCtx *ctx, int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_USER) {
+ parseError = "qusername: this function is only valid for user searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_STRING;
+ thenode->exe = qusername_exe;
+ thenode->free = qusername_free;
+
+ return thenode;
+}
+
+void *qusername_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+ authname *ap = (authname *)theinput;
+ reguser *rup = ap->exts[chanservext];
+ if(!rup)
+ return "";
+
+ return rup->username;
+}
+
+void qusername_free(searchCtx *ctx, struct searchNode *thenode) {
+ free(thenode);
+}
+
#include "../chanserv.h"
#include "../../newsearch/newsearch.h"
#include "../../control/control.h"
+#include "../../lib/stringbuf.h"
void printchannel_qusers(searchCtx *ctx, nick *sender, chanindex *cip) {
regchanuser *rcup;
ctx->reply(sender," %s", thebuf);
}
}
+
+void printauth(searchCtx *ctx, nick *sender, authname *anp) {
+ reguser *rup;
+ StringBuf b;
+ char output[1024];
+ nick *tnp;
+ int space = 0;
+
+ if (!(rup=anp->exts[chanservaext]))
+ return;
+
+ output[0] = '\0';
+
+ b.capacity = sizeof(output);
+ b.len = 0;
+ b.buf = output;
+
+ for(tnp=anp->nicks;tnp;tnp=tnp->next) {
+ if(space)
+ sbaddchar(&b, ' ');
+ space = 1;
+ sbaddstr(&b, tnp->nick);
+ }
+ sbterminate(&b);
+
+ ctx->reply(sender, " %s%s%s%s", rup->username, *output?" (":"", output, *output?")":"");
+ ctx->reply(sender, " %-10s %-30s %s", UHasSuspension(rup)?"yes":"no", rup->email?rup->email->content:"(no email)", rup->lastuserhost?rup->lastuserhost->content:"(no last host)");
+}
#include "../chanserv.h"
-#include "../../newsearch/newsearch.h"
+#include "chanserv_newsearch.h"
#include <stdio.h>
#include <stdarg.h>
return CMD_OK;
}
+int cs_dousersearch(void *source, int cargc, char **cargv) {
+ nick *sender=source;
+
+ if (cargc < 1) {
+ chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "usersearch");
+ return CMD_ERROR;
+ }
+
+ do_usersearch_real(chanservmessagewrapper, chanservwallwrapper, source, cargc, cargv);
+
+ chanservstdmessage(sender, QM_DONE);
+ return CMD_OK;
+}
+
+int cs_dospewemailtwo(void *source, int cargc, char **cargv) {
+ searchASTExpr *tree;
+
+ if(cargc < 1)
+ return CMD_USAGE;
+
+ tree = NSASTNode(match_parse, NSASTNode(qemail_parse), NSASTLiteral(cargv[0]));
+ return ast_usersearch(tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, 500);
+}
+
+int cs_dospewdbtwo(void *source, int cargc, char **cargv) {
+ searchASTExpr *tree;
+
+ if(cargc < 1)
+ return CMD_USAGE;
+
+ tree =
+ NSASTNode(or_parse,
+ NSASTNode(match_parse, NSASTNode(qusername_parse), NSASTLiteral(cargv[0])),
+ NSASTNode(match_parse, NSASTNode(qsuspendreason_parse), NSASTLiteral(cargv[0])),
+ 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, 500);
+}
+
#include <stdarg.h>
#include <string.h>
#include "../lib/sstring.h"
+#include "../lib/stringbuf.h"
#include "../core/error.h"
#define MAXARGS 10
#define CONVBUF 512
-struct bufs {
- char *buf;
- int capacity;
- int len;
-};
-
-static int addchar(struct bufs *buf, char c) {
- if(buf->len >= buf->capacity - 1)
- return 0;
-
- buf->buf[buf->len++] = c;
-
- return 1;
-}
-
-static int addstr(struct bufs *buf, char *c) {
- int remaining = buf->capacity - buf->len - 1;
- char *p;
-
- for(p=c;*p;p++) {
- if(remaining-- <= 0)
- return 0;
-
- buf->buf[buf->len++] = *p;
- }
-
- return 1;
-}
-
void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, va_list ap) {
- struct bufs b;
+ StringBuf b;
const char *p;
char *c;
char convbuf[MAXARGS][CONVBUF];
for(p=format;*p;p++) {
if(*p != '$') {
- if(!addchar(&b, *p))
+ if(!sbaddchar(&b, *p))
break;
continue;
}
if(*p == '\0')
break;
if(*p == '$') {
- if(!addchar(&b, *p))
+ if(!sbaddchar(&b, *p))
break;
continue;
}
c = "(bad format specifier)";
}
if(c)
- if(!addstr(&b, c))
+ if(!sbaddstr(&b, c))
break;
}
- buf[b.len] = '\0';
+ sbterminate(&b);
/* not required */
/*
controlnotice(np, "%s", broadcast);
}
+void controlnswall(int noticelevel, char *format, ...) {
+ char broadcast[512];
+ va_list va;
+
+ va_start(va, format);
+ vsnprintf(broadcast, sizeof(broadcast), format, va);
+ va_end(va);
+
+ controlwall(NO_OPER, noticelevel, "%s", broadcast);
+}
+
void controlspecialrmmod(void *arg);
void controlspecialreloadmod(void *arg);
void controlhelp(nick *np, Command *cmd);
+void controlnswall(int noticelevel, char *format, ...);
#define registercontrolcmd(a, b, c, d) registercontrolhelpcmd(a, b, c, d, NULL)
@include@ @includel@../build.mk@includel@
.PHONY: all
-all: sstring.o array.o splitline.o base64.o flags.o irc_string.o strlfunc.o sha1.o irc_ipv6.o patricia.o rijndael.o sha2.o hmac.o prng.o md5.o
+all: sstring.o array.o splitline.o base64.o flags.o irc_string.o strlfunc.o sha1.o irc_ipv6.o patricia.o rijndael.o sha2.o hmac.o prng.o md5.o stringbuf.o
--- /dev/null
+#include "stringbuf.h"
+
+int sbaddchar(StringBuf *buf, char c) {
+ if(buf->len >= buf->capacity - 1)
+ return 0;
+
+ buf->buf[buf->len++] = c;
+
+ return 1;
+}
+
+int sbaddstr(StringBuf *buf, char *c) {
+ int remaining = buf->capacity - buf->len - 1;
+ char *p;
+
+ for(p=c;*p;p++) {
+ if(remaining <= 0)
+ return 0;
+
+ remaining--;
+
+ buf->buf[buf->len++] = *p;
+ }
+
+ return 1;
+}
+
+int sbterminate(StringBuf *buf) {
+ if(buf->capacity - buf->len > 0) {
+ buf->buf[buf->len] = '\0';
+ return 1;
+ }
+ return 0;
+}
--- /dev/null
+#ifndef __STRINGBUF_H
+#define __STRINGBUF_H
+
+typedef struct StringBuf {
+ char *buf;
+ int capacity;
+ int len;
+} StringBuf;
+
+int sbaddchar(StringBuf *buf, char c);
+int sbaddstr(StringBuf *buf, char *c);
+int sbterminate(StringBuf *buf);
+
+#endif
.PHONY: all
all: newsearch.so
-newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o
+newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o newsearch_ast.o
}
}
+void printuser(searchCtx *ctx, nick *sender, authname *aup) {
+ ctx->reply(sender,"%d", aup->userid);
+}
+
#include "../control/control.h"
#include "../lib/splitline.h"
#include "../lib/version.h"
+#include "../lib/stringbuf.h"
MODULE_VERSION("");
CommandTree *searchTree;
CommandTree *chanOutputTree;
CommandTree *nickOutputTree;
+CommandTree *userOutputTree;
int do_nicksearch(void *source, int cargc, char **cargv);
int do_chansearch(void *source, int cargc, char **cargv);
+int do_usersearch(void *source, int cargc, char **cargv);
void printnick_channels(searchCtx *, nick *, nick *);
void printchannel(searchCtx *, nick *, chanindex *);
void printchannel_topic(searchCtx *, nick *, chanindex *);
void printchannel_services(searchCtx *, nick *, chanindex *);
+UserDisplayFunc defaultuserfn = printuser;
+NickDisplayFunc defaultnickfn = printnick;
+ChanDisplayFunc defaultchanfn = printchannel;
+
void registersearchterm(char *term, parseFunc parsefunc);
void deregistersearchterm(char *term, parseFunc parsefunc);
deletecommandfromtree(nickOutputTree, name, (CommandHandler)handler);
}
+void reguserdisp(const char *name, UserDisplayFunc handler) {
+ addcommandtotree(userOutputTree, name, 0, 0, (CommandHandler)handler);
+}
+
+void unreguserdisp(const char *name, UserDisplayFunc handler) {
+ deletecommandfromtree(userOutputTree, name, (CommandHandler)handler);
+}
+
const char *parseError;
/* used for *_free functions that need to warn users of certain things
i.e. hitting too many users in a (kill) or (gline) */
searchTree=newcommandtree();
chanOutputTree=newcommandtree();
nickOutputTree=newcommandtree();
+ userOutputTree=newcommandtree();
/* Boolean operations */
registersearchterm("and",and_parse);
regchandisp("topic",printchannel_topic);
regchandisp("services",printchannel_services);
+ /* Nick output filters */
+ reguserdisp("default",printuser);
+
registercontrolhelpcmd("nicksearch",NO_OPER,4,do_nicksearch, "Usage: nicksearch <criteria>\nSearches for nicknames with the given criteria.");
registercontrolhelpcmd("chansearch",NO_OPER,4,do_chansearch, "Usage: chansearch <criteria>\nSearches for channels with the given criteria.");
+ registercontrolhelpcmd("usersearch",NO_OPER,4,do_usersearch, "Usage: usersearch <criteria>\nSearches for users with the given criteria.");
}
void _fini() {
destroycommandtree(searchTree);
destroycommandtree(chanOutputTree);
destroycommandtree(nickOutputTree);
+ destroycommandtree(userOutputTree);
deregistercontrolcmd("nicksearch", do_nicksearch);
deregistercontrolcmd("chansearch", do_chansearch);
+ deregistercontrolcmd("usersearch", do_usersearch);
}
void registersearchterm(char *term, parseFunc parsefunc) {
va_end(ap);
}
-int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
- nick *sender = senderNSExtern = source;
- struct searchNode *search;
- int limit=500;
+static int parseopts(int cargc, char **cargv, int *arg, int *limit, void **display, CommandTree *tree, replyFunc reply, void *sender) {
char *ch;
- int arg=0;
struct Command *cmd;
- NickDisplayFunc display=printnick;
- searchCtx ctx;
- if (cargc<1)
- return CMD_USAGE;
-
if (*cargv[0] == '-') {
/* options */
- arg++;
+ (*arg)++;
for (ch=cargv[0]+1;*ch;ch++) {
switch(*ch) {
case 'l':
- if (cargc<arg) {
+ if (cargc<*arg) {
reply(sender,"Error: -l switch requires an argument");
return CMD_USAGE;
}
- limit=strtoul(cargv[arg++],NULL,10);
+ *limit=strtoul(cargv[(*arg)++],NULL,10);
break;
case 'd':
- if (cargc<arg) {
+ if (cargc<*arg) {
reply(sender,"Error: -d switch requires an argument");
return CMD_USAGE;
}
- cmd=findcommandintree(nickOutputTree, cargv[arg], 1);
+ cmd=findcommandintree(tree, cargv[*arg], 1);
if (!cmd) {
- reply(sender,"Error: unknown output format %s",cargv[arg]);
+ reply(sender,"Error: unknown output format %s",cargv[*arg]);
return CMD_USAGE;
}
- display=(NickDisplayFunc)cmd->handler;
- arg++;
+ *display=(void *)cmd->handler;
+ (*arg)++;
break;
default:
}
}
+ return CMD_OK;
+}
+
+int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
+ nick *sender = senderNSExtern = source;
+ struct searchNode *search;
+ int limit=500;
+ int arg=0;
+ NickDisplayFunc display=defaultnickfn;
+ searchCtx ctx;
+ int ret;
+
+ if (cargc<1)
+ return CMD_USAGE;
+
+ ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, nickOutputTree, reply, sender);
+ if(ret != CMD_OK)
+ return ret;
+
if (arg>=cargc) {
reply(sender,"No search terms - aborting.");
return CMD_ERROR;
nick *sender = senderNSExtern = source;
struct searchNode *search;
int limit=500;
- char *ch;
int arg=0;
- struct Command *cmd;
- ChanDisplayFunc display=printchannel;
+ ChanDisplayFunc display=defaultchanfn;
searchCtx ctx;
+ int ret;
if (cargc<1)
return CMD_USAGE;
- if (*cargv[0] == '-') {
- /* options */
- arg++;
-
- for (ch=cargv[0]+1;*ch;ch++) {
- switch(*ch) {
- case 'l':
- if (cargc<arg) {
- reply(sender,"Error: -l switch requires an argument");
- return CMD_USAGE;
- }
- limit=strtoul(cargv[arg++],NULL,10);
- break;
-
- case 'd':
- if (cargc<arg) {
- reply(sender,"Error: -d switch requires an argument");
- return CMD_USAGE;
- }
- cmd=findcommandintree(chanOutputTree, cargv[arg], 1);
- if (!cmd) {
- reply(sender,"Error: unknown output format %s",cargv[arg]);
- return CMD_USAGE;
- }
- display=(ChanDisplayFunc)cmd->handler;
- arg++;
- break;
-
- default:
- reply(sender,"Unrecognised flag -%c.",*ch);
- }
- }
- }
+ ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, chanOutputTree, reply, sender);
+ if(ret != CMD_OK)
+ return ret;
if (arg>=cargc) {
reply(sender,"No search terms - aborting.");
ctx->reply(sender,"--- End of list: %d matches", matches);
}
+int do_usersearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
+ nick *sender = senderNSExtern = source;
+ struct searchNode *search;
+ int limit=500;
+ int arg=0;
+ UserDisplayFunc display=defaultuserfn;
+ searchCtx ctx;
+ int ret;
+
+ if (cargc<1)
+ return CMD_USAGE;
+
+ ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, userOutputTree, reply, sender);
+ if(ret != CMD_OK)
+ return ret;
+
+ if (arg>=cargc) {
+ reply(sender,"No search terms - aborting.");
+ return CMD_ERROR;
+ }
+
+ if (arg<(cargc-1)) {
+ rejoinline(cargv[arg],cargc-arg);
+ }
+
+ ctx.parser = search_parse;
+ ctx.reply = reply;
+ ctx.wall = wall;
+
+ if (!(search = ctx.parser(&ctx, SEARCHTYPE_USER, cargv[arg]))) {
+ reply(sender,"Parse error: %s",parseError);
+ return CMD_ERROR;
+ }
+
+ usersearch_exe(search, &ctx, sender, display, limit);
+
+ (search->free)(&ctx, search);
+
+ return CMD_OK;
+}
+
+int do_usersearch(void *source, int cargc, char **cargv) {
+ return do_usersearch_real(controlreply, controlwallwrapper, source, cargc, cargv);
+}
+
+void usersearch_exe(struct searchNode *search, searchCtx *ctx, nick *sender, UserDisplayFunc display, int limit) {
+ int i;
+ authname *aup;
+ int matches = 0;
+
+ search=coerceNode(ctx, search, RETURNTYPE_BOOL);
+
+ for (i=0;i<AUTHNAMEHASHSIZE;i++) {
+ for (aup=authnametable[i];aup;aup=aup->next) {
+ if ((search->exe)(ctx, search, aup)) {
+ if (matches<limit)
+ display(ctx, sender, aup);
+ if (matches==limit)
+ ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
+ matches++;
+ }
+ }
+ }
+
+ ctx->reply(sender,"--- End of list: %d matches", matches);
+}
+
struct coercedata {
struct searchNode *child;
union {
}
}
-struct bufs {
- char *buf;
- int capacity;
- int len;
-};
-
-static int addchar(struct bufs *buf, char c) {
- if(buf->len >= buf->capacity - 1)
- return 0;
-
- buf->buf[buf->len++] = c;
-
- return 1;
-}
-
-static int addstr(struct bufs *buf, char *c) {
- int remaining = buf->capacity - buf->len - 1;
- char *p;
-
- for(p=c;*p;p++) {
- if(remaining-- <= 0)
- return 0;
-
- buf->buf[buf->len++] = *p;
- }
-
- return 1;
-}
-
void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
- struct bufs b;
+ StringBuf b;
const char *p;
char *c;
char hostbuf[512];
for(p=format;*p;p++) {
if(*p != '%') {
- if(!addchar(&b, *p))
+ if(!sbaddchar(&b, *p))
break;
continue;
}
if(*p == '\0')
break;
if(*p == '%') {
- if(!addchar(&b, *p))
+ if(!sbaddchar(&b, *p))
break;
continue;
}
c = "(bad format specifier)";
}
if(c)
- if(!addstr(&b, c))
+ if(!sbaddstr(&b, c))
break;
}
- buf[b.len] = '\0';
+ sbterminate(&b);
/* not required */
/*
#include "../parser/parser.h"
#include "../channel/channel.h"
#include "../lib/flags.h"
+#include "../authext/authext.h"
#define SEARCHTYPE_CHANNEL 1
#define SEARCHTYPE_NICK 2
+#define SEARCHTYPE_USER 3
#define NSMAX_KILL_LIMIT 500
searchParseFunc parser;
replyFunc reply;
wallFunc wall;
+ void *arg;
} searchCtx;
typedef struct searchNode *(*parseFunc)(searchCtx *, int, int, char **);
typedef void *(*exeFunc)(searchCtx *, struct searchNode *, void *);
typedef void (*ChanDisplayFunc)(searchCtx *, nick *, chanindex *);
typedef void (*NickDisplayFunc)(searchCtx *, nick *, nick *);
+typedef void (*UserDisplayFunc)(searchCtx *, nick *, authname *);
/* Core functions */
/* Logical (BOOL -> BOOL)*/
void unregchandisp(const char *name, ChanDisplayFunc handler);
void regnickdisp(const char *name, NickDisplayFunc handler);
void unregnickdisp(const char *name, NickDisplayFunc handler);
+void reguserdisp(const char *name, UserDisplayFunc handler);
+void unreguserdisp(const char *name, UserDisplayFunc handler);
/* Special nick* printf */
void nssnprintf(char *, size_t, const char *, nick *);
extern const char *parseError;
void printnick(searchCtx *, nick *, nick *);
+void printuser(searchCtx *, nick *, authname *);
void nicksearch_exe(struct searchNode *search, searchCtx *sctx, nick *sender, NickDisplayFunc display, int limit);
void chansearch_exe(struct searchNode *search, searchCtx *sctx, nick *sender, ChanDisplayFunc display, int limit);
+void usersearch_exe(struct searchNode *search, searchCtx *ctx, nick *sender, UserDisplayFunc display, int limit);
int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
int do_chansearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
+int do_usersearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
+
+void *literal_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void literal_free(searchCtx *ctx, struct searchNode *thenode);
+
+/* AST functions */
+
+struct searchASTNode;
+
+#define AST_NODE_CHILD 1
+#define AST_NODE_LITERAL 2
+
+/* items to store in the ast lookup cache */
+#define AST_RECENT 10
+
+typedef struct searchASTExpr {
+ int type;
+ union {
+ char *literal;
+ struct searchASTNode *child;
+ } u;
+} searchASTExpr;
+
+typedef struct searchASTNode {
+ parseFunc fn;
+ int argc;
+ struct searchASTExpr **argv;
+} searchASTNode;
+
+/*
+ *
+ * FEAR THE COMPOUND LITERALS
+ * MUHAHAHHAHAHAHAHAHAAH
+ *
+ */
+#define __NSASTExpr(x, y, ...) &(searchASTExpr){.type = x, .u.y = __VA_ARGS__}
+#define __NSASTList(...) (searchASTExpr *[]){__VA_ARGS__}
+#define __NSASTNode(x, ...) &(searchASTNode){.fn = x, .argc = sizeof(__NSASTList(__VA_ARGS__)) / sizeof(__NSASTList(__VA_ARGS__)[0]), .argv = __NSASTList(__VA_ARGS__)}
+#define __NSASTChild(...) __NSASTExpr(AST_NODE_CHILD, child, __VA_ARGS__)
+
+#define NSASTLiteral(data) __NSASTExpr(AST_NODE_LITERAL, literal, data)
+#define NSASTNode(fn, ...) __NSASTChild(__NSASTNode(fn, __VA_ARGS__))
+
+searchNode *search_astparse(searchCtx *, int, char *);
+
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, int limit);
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, int limit);
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, int limit);
+
+char *ast_printtree(char *buf, size_t bufsize, searchASTExpr *expr);
+
+/* erk */
+extern CommandTree *searchTree;
+
+extern UserDisplayFunc defaultuserfn;
+extern NickDisplayFunc defaultnickfn;
+extern ChanDisplayFunc defaultchanfn;
+
--- /dev/null
+#include "newsearch.h"
+#include "../lib/sstring.h"
+#include "../lib/strlfunc.h"
+#include "../lib/stringbuf.h"
+#include <stdarg.h>
+#include <string.h>
+
+/* at least we have some type safety... */
+typedef union exprunion {
+ searchASTExpr *expr;
+ char *literal;
+} exprunion;
+
+typedef struct searchASTCache {
+ searchASTExpr *tree;
+ searchASTExpr *cache[AST_RECENT];
+ int nextpos;
+} searchASTCache;
+
+/* comares either a string and a string or an expression and an expression */
+static searchASTExpr *compareloc(searchASTExpr *expr, exprunion *loc) {
+ if(expr->type == AST_NODE_LITERAL) {
+ if(expr->u.literal == loc->literal)
+ return expr;
+ } else if(expr->type == AST_NODE_CHILD) {
+ if(expr == loc->expr)
+ return expr;
+ } else {
+ parseError = "static_parse_compare: bad node type";
+ return NULL;
+ }
+ return NULL;
+}
+
+/* searches the abstract syntax tree for the supplied expression/string */
+static searchASTExpr *treesearch(searchASTExpr *expr, exprunion *loc) {
+ searchASTExpr *ret = compareloc(expr, loc);
+ if(ret)
+ return ret;
+
+ if(expr->type == AST_NODE_CHILD) {
+ int i;
+ for(i=0;i<expr->u.child->argc;i++) {
+ searchASTExpr *d = treesearch(expr->u.child->argv[i], loc);
+ if(d)
+ return d;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * searches the AST cache, if this fails it goes and searches the tree.
+ * the cache is hit most of the time and I guess makes it nearly O(1) amortised...
+ */
+searchASTExpr *cachesearch(searchASTCache *cache, exprunion *loc) {
+ searchASTExpr *ret = compareloc(cache->tree, loc);
+ int i;
+ if(ret)
+ return ret;
+
+ for(i=0;i<AST_RECENT;i++) {
+ if(!cache->cache[i])
+ continue;
+ ret = compareloc(cache->cache[i], loc);
+ if(ret)
+ return ret;
+ }
+
+ return treesearch(cache->tree, loc);
+}
+
+/* pushes an item into the cache */
+static void cachepush(searchASTCache *cache, searchASTExpr *expr) {
+ cache->cache[cache->nextpos] = expr;
+ cache->nextpos = (cache->nextpos + 1) % AST_RECENT;
+}
+
+/* ast parser, the way we pass context around is very very hacky... */
+searchNode *search_astparse(searchCtx *ctx, int type, char *loc) {
+ searchASTCache *cache = ctx->arg;
+ searchASTExpr *expr = cachesearch(cache, (exprunion *)&loc);
+ searchNode *node;
+ char **v;
+ int i;
+
+ if(!expr) {
+ parseError = "WARNING: AST parsing failed";
+ return NULL;
+ }
+
+ switch(expr->type) {
+ case AST_NODE_LITERAL:
+ if (!(node=(searchNode *)malloc(sizeof(searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+ node->localdata = getsstring(expr->u.literal,512);
+ node->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING;
+ node->exe = literal_exe;
+ node->free = literal_free;
+ return node;
+ case AST_NODE_CHILD:
+ v = (char **)malloc(expr->u.child->argc * sizeof(char *));
+ if(!v) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+ for(i=0;i<expr->u.child->argc;i++) {
+ searchASTExpr *child = expr->u.child->argv[i];
+
+ cachepush(cache, child);
+ switch(child->type) {
+ case AST_NODE_LITERAL:
+ v[i] = child->u.literal;
+ break;
+ case AST_NODE_CHILD:
+ v[i] = (char *)child;
+ break;
+ default:
+ parseError = "static_parse: bad child node type";
+ free(v);
+ return NULL;
+ }
+ }
+
+ node = expr->u.child->fn(ctx, type, expr->u.child->argc, v);
+ free(v);
+ return node;
+ default:
+ parseError = "static_parse: bad node type";
+ return NULL;
+ }
+}
+
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, int limit) {
+ searchCtx ctx;
+ searchASTCache cache;
+ searchNode *search;
+ char buf[1024];
+
+ memset(&cache, 0, sizeof(cache));
+ cache.tree = tree;
+
+ ctx.reply = reply;
+ ctx.wall = wall;
+ ctx.parser = search_astparse;
+ ctx.arg = (void *)&cache;
+
+ buf[0] = '\0';
+ reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+ search = ctx.parser(&ctx, SEARCHTYPE_NICK, (char *)tree);
+ if(!search) {
+ reply(sender, "Parse error: %s", parseError);
+ return CMD_ERROR;
+ }
+
+ reply(sender, "Executing...");
+ nicksearch_exe(search, &ctx, sender, display, limit);
+
+ (search->free)(&ctx, search);
+
+ return CMD_OK;
+}
+
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, int limit) {
+ searchCtx ctx;
+ searchASTCache cache;
+ searchNode *search;
+ char buf[1024];
+
+ ctx.reply = reply;
+ ctx.wall = wall;
+ ctx.parser = search_astparse;
+ ctx.arg = (void *)&cache;
+
+ buf[0] = '\0';
+ reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+ search = ctx.parser(&ctx, SEARCHTYPE_CHANNEL, (char *)tree);
+ if(!search) {
+ reply(sender, "Parse error: %s", parseError);
+ return CMD_ERROR;
+ }
+
+ reply(sender, "Executing...");
+ chansearch_exe(search, &ctx, sender, display, limit);
+
+ (search->free)(&ctx, search);
+
+ return CMD_OK;
+}
+
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, int limit) {
+ searchCtx ctx;
+ searchASTCache cache;
+ searchNode *search;
+ char buf[1024];
+
+ memset(&cache, 0, sizeof(cache));
+ cache.tree = tree;
+
+ ctx.reply = reply;
+ ctx.wall = wall;
+ ctx.parser = search_astparse;
+ ctx.arg = (void *)&cache;
+
+ buf[0] = '\0';
+ reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+ search = ctx.parser(&ctx, SEARCHTYPE_USER, (char *)tree);
+ if(!search) {
+ reply(sender, "Parse error: %s", parseError);
+ return CMD_ERROR;
+ }
+
+ reply(sender, "Executing...");
+ usersearch_exe(search, &ctx, sender, display, limit);
+
+ (search->free)(&ctx, search);
+
+ return CMD_OK;
+}
+
+
+/* horribly inefficient -- don't call me very often! */
+static char *ast_printtree_real(StringBuf *buf, searchASTExpr *expr) {
+ char lbuf[256];
+ if(expr->type == AST_NODE_CHILD) {
+ int i;
+ sstring *command = getcommandname(searchTree, (void *)expr->u.child->fn);
+
+ if(command) {
+ snprintf(lbuf, sizeof(lbuf), "(%s", command->content);
+ } else {
+ snprintf(lbuf, sizeof(lbuf), "(%p", expr->u.child->fn);
+ }
+ sbaddstr(buf, lbuf);
+
+ for(i=0;i<expr->u.child->argc;i++) {
+ sbaddchar(buf, ' ');
+ ast_printtree_real(buf, expr->u.child->argv[i]);
+ }
+ sbaddchar(buf, ')');
+
+ } else if(expr->type == AST_NODE_LITERAL) {
+ sbaddstr(buf, expr->u.literal);
+ } else {
+ sbaddstr(buf, "???");
+ }
+
+ return buf->buf;
+}
+
+char *ast_printtree(char *buf, size_t bufsize, searchASTExpr *expr) {
+ StringBuf b;
+ char *p;
+
+ b.capacity = bufsize;
+ b.len = 0;
+ b.buf = buf;
+
+ p = ast_printtree_real(&b, expr);
+
+ sbterminate(&b);
+ return p;
+}
#include "../control/control.h"
#include "../nick/nick.h"
+#include "../newsearch/newsearch.h"
#include "../lib/irc_string.h"
#include "../lib/strlfunc.h"
#include "../localuser/localuserchannel.h"
registercontrolhelpcmd("spewchan", NO_OPER, 1, &controlspewchan, "Usage: spewchan <pattern>\nShows all channels which are matched by the given pattern");
-/* registercontrolhelpcmd("spew", NO_OPER, 1, &controlspew, "Usage: spewchan <pattern>\nShows all userss which are matched by the given pattern"); */
+ registercontrolhelpcmd("spew", NO_OPER, 1, &controlspew, "Usage: spewchan <pattern>\nShows all userss which are matched by the given pattern");
registercontrolhelpcmd("resync", NO_OPER, 1, &controlresync, "Usage: resync <channel>\nResyncs a desynched channel");
deregistercontrolcmd("broadcast", controlbroadcast);
deregistercontrolcmd("resync", controlresync);
-/* deregistercontrolcmd("spew", controlspew); */
+ deregistercontrolcmd("spew", controlspew);
deregistercontrolcmd("spewchan", controlspewchan);
/* deregistercontrolcmd("kill", controlkill); */
}
int controlspew(void *sender, int cargc, char **cargv) {
-/* nick *np = (nick *)sender; */
+ searchASTExpr *tree;
- return CMD_OK;
+ if(cargc < 1)
+ return CMD_USAGE;
+
+ tree = NSASTNode(match_parse, NSASTNode(hostmask_parse), NSASTLiteral(cargv[0]));
+ return ast_nicksearch(tree, controlreply, sender, controlnswall, printnick, 500);
}
+/* this function is the definition of horrible */
int controlspewchan(void *sender, int cargc, char **cargv) {
nick *np = (nick*)sender;
nick *np2;
return count;
}
+
+/* Returns the command name given a handler */
+sstring *getcommandname(CommandTree *ct, CommandHandler handler) {
+ int i;
+ sstring *s;
+
+ if(ct->cmd && ct->cmd->handler == handler) {
+ return ct->cmd->command;
+ }
+
+ for (i=0;i<26;i++) {
+ if(ct->next[i]) {
+ s=getcommandname(ct->next[i], handler);
+ if(s)
+ return s;
+ }
+ }
+
+ return NULL;
+}
int deletecommandfromtree(CommandTree *ct, const char *cmdname, CommandHandler handler);
Command *findcommandintree(CommandTree *ct, const char *cmdname, int strictcheck);
int getcommandlist(CommandTree *ct, Command **commandlist, int maxcommands);
+sstring *getcommandname(CommandTree *ct, CommandHandler handler);
#define addcommandtotree(a, b, c, d, e) addcommandhelptotree(a, b, c, d, e, NULL)
irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, phrase->id, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
- trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency);
+ trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d%s%s", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
}
}