]> jfr.im git - irc/quakenet/newserv.git/blob - newsearch/newsearch.c
Initial Import
[irc/quakenet/newserv.git] / newsearch / newsearch.c
1
2 #include <stdio.h>
3 #include "newsearch.h"
4
5 #include "../irc/irc_config.h"
6 #include "../nick/nick.h"
7 #include "../lib/irc_string.h"
8 #include "../parser/parser.h"
9 #include "../control/control.h"
10 #include "../lib/splitline.h"
11
12 CommandTree *searchTree;
13
14 int do_nicksearch(void *source, int cargc, char **cargv);
15 struct searchNode *search_parse(int type, char *input);
16
17 void registersearchterm(char *term, parseFunc parsefunc);
18 void deregistersearchterm(char *term, parseFunc parsefunc);
19
20 void *trueval(int type);
21 void *falseval(int type);
22
23 const char *parseError;
24
25 void _init() {
26 searchTree=newcommandtree();
27
28 /* Boolean operations */
29 registersearchterm("and",and_parse);
30 registersearchterm("not",not_parse);
31 registersearchterm("or",or_parse);
32
33 registersearchterm("eq",eq_parse);
34
35 /* String operations */
36 registersearchterm("match",match_parse);
37 registersearchterm("regex",regex_parse);
38
39 /* Nickname operations */
40 registersearchterm("hostmask",hostmask_parse);
41 registersearchterm("realname",realname_parse);
42 registersearchterm("nick",nick_parse);
43 registersearchterm("ident",ident_parse);
44 registersearchterm("host",host_parse);
45 registersearchterm("channel",channel_parse);
46
47 /* Nickname / channel operations */
48 registersearchterm("modes",modes_parse);
49
50 registercontrolcmd("nicksearch",10,4,do_nicksearch);
51 }
52
53 void _fini() {
54 destroycommandtree(searchTree);
55 deregistercontrolcmd("nicksearch", do_nicksearch);
56 }
57
58 void registersearchterm(char *term, parseFunc parsefunc) {
59 addcommandtotree(searchTree, term, 0, 0, (CommandHandler) parsefunc);
60 }
61
62 void deregistersearchterm(char *term, parseFunc parsefunc) {
63 deletecommandfromtree(searchTree, term, (CommandHandler) parsefunc);
64 }
65
66 void printnick(nick *sender, nick *np) {
67 char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
68
69 controlreply(sender,"%s [%s] (%s) (%s)",visiblehostmask(np,hostbuf),
70 IPtostr(np->ipaddress), printflags(np->umodes, umodeflags), np->realname->name->content);
71 }
72
73 int do_nicksearch(void *source, int cargc, char **cargv) {
74 nick *sender=source, *np;
75 int i;
76 struct searchNode *search;
77 int limit=500,matches=0;
78 char *ch;
79 int arg=0;
80
81 if (cargc<1) {
82 controlreply(sender,"Usage: nicksearch (criteria)");
83 return CMD_ERROR;
84 }
85
86 if (*cargv[0] == '-') {
87 /* options */
88 arg++;
89
90 for (ch=cargv[0]+1;*ch;ch++) {
91 switch(*ch) {
92 case 'l':
93 if (cargc<arg) {
94 controlreply(sender,"Error: -l switch requires an argument");
95 return CMD_ERROR;
96 }
97 limit=strtoul(cargv[arg++],NULL,10);
98 break;
99
100 default:
101 controlreply(sender,"Unrecognised flag -%c.",*ch);
102 }
103 }
104 }
105
106 if (arg>=cargc) {
107 controlreply(sender,"No search terms - aborting.");
108 return CMD_ERROR;
109 }
110
111 if (arg<(cargc-1)) {
112 rejoinline(cargv[arg],cargc-arg);
113 }
114
115 if (!(search = search_parse(SEARCHTYPE_NICK, cargv[arg]))) {
116 controlreply(sender,"Parse error: %s",parseError);
117 return CMD_ERROR;
118 }
119
120 for (i=0;i<NICKHASHSIZE;i++) {
121 for (np=nicktable[i];np;np=np->next) {
122 if ((search->exe)(search, RETURNTYPE_BOOL, np)) {
123 if (matches<limit)
124 printnick(sender, np);
125 if (matches==limit)
126 controlreply(sender, "--- More than %d matches, skipping the rest",limit);
127 matches++;
128 }
129 }
130 }
131
132 (search->free)(search);
133
134 controlreply(sender,"--- End of list: %d matches", matches);
135
136 return CMD_OK;
137 }
138
139 void *trueval(int type) {
140 switch(type) {
141 default:
142 case RETURNTYPE_INT:
143 case RETURNTYPE_BOOL:
144 return (void *)1;
145
146 case RETURNTYPE_STRING:
147 return "1";
148 }
149 }
150
151 void *falseval(int type) {
152 switch (type) {
153 default:
154 case RETURNTYPE_INT:
155 case RETURNTYPE_BOOL:
156 return NULL;
157
158 case RETURNTYPE_STRING:
159 return "";
160 }
161 }
162
163
164 /*
165 * LITERAL node type: used by the top level parse function
166 */
167
168 struct literal_localdata {
169 int intval;
170 int boolval;
171 sstring *stringval;
172 };
173
174 void literal_free(struct searchNode *thenode);
175 void *literal_exe(struct searchNode *thenode, int type, void *theinput);
176
177 /* search_parse:
178 * Given an input string, return a searchNode.
179 */
180
181 struct searchNode *search_parse(int type, char *input) {
182 /* OK, we need to split the input into chunks on spaces and brackets.. */
183 char *argvector[100];
184 int i,j;
185 char *ch;
186 struct Command *cmd;
187 struct searchNode *thenode;
188 struct literal_localdata *localdata;
189
190 /* If it starts with a bracket, it's a function call.. */
191 if (*input=='(') {
192 /* Skip past string */
193 for (ch=input;*ch;ch++);
194 if (*(ch-1) != ')') {
195 parseError = "Bracket mismatch!";
196 return NULL;
197 }
198 input++;
199 *(ch-1)='\0';
200
201 /* Split further args */
202 i=-1; /* i = -1 BoW, 0 = inword, 1 = bracket nest depth */
203 j=0; /* j = current arg */
204 for (ch=input;*ch;ch++) {
205 if (i==-1) {
206 argvector[j]=ch;
207 if (*ch=='(') {
208 i=1;
209 } else if (*ch != ' ') {
210 i=0;
211 }
212 } else if (i==0) {
213 if (*ch==' ') {
214 *ch='\0';
215 j++;
216 i=-1;
217 }
218 } else {
219 if (*ch=='(') {
220 i++;
221 } else if (*ch==')') {
222 i--;
223 }
224 }
225 }
226
227 if (i>0) {
228 parseError = "Bracket mismatch!";
229 return NULL;
230 }
231
232 if (!(cmd=findcommandintree(searchTree,argvector[0],1))) {
233 parseError = "Unknown command";
234 return NULL;
235 } else {
236 return ((parseFunc)cmd->handler)(type, j, argvector+1);
237 }
238 } else {
239 /* Literal */
240 thenode=(struct searchNode *)malloc(sizeof(struct searchNode));
241 localdata=(struct literal_localdata *)malloc(sizeof (struct literal_localdata));
242
243 localdata->stringval=getsstring(input,512);
244 localdata->intval=strtol(input,NULL,10);
245 if (input==NULL || *input=='\0') {
246 localdata->boolval = 0;
247 } else {
248 localdata->boolval = 1;
249 }
250
251 thenode->localdata = localdata;
252 thenode->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING;
253 thenode->exe = literal_exe;
254 thenode->free = literal_free;
255
256 return thenode;
257 }
258 }
259
260 void *literal_exe(struct searchNode *thenode, int type, void *theinput) {
261 struct literal_localdata *localdata;
262
263 localdata=thenode->localdata;
264
265 switch (type) {
266 case RETURNTYPE_STRING:
267 return (void *)(localdata->stringval->content);
268
269 default:
270 case RETURNTYPE_BOOL:
271 return (void *)(localdata->boolval);
272
273 case RETURNTYPE_INT:
274 return (void *)(localdata->intval);
275 }
276 }
277
278 void literal_free(struct searchNode *thenode) {
279 struct literal_localdata *localdata;
280
281 localdata=thenode->localdata;
282
283 freesstring(localdata->stringval);
284 free(localdata);
285 free(thenode);
286 }