]> jfr.im git - irc/quakenet/newserv.git/blob - lua/luacommands.c
lua: Export nickmatchban, nickistrusted, nickbanned to the lua module and use the...
[irc/quakenet/newserv.git] / lua / luacommands.c
1 /* Copyright (C) Chris Porter 2005-2007 */
2 /* ALL RIGHTS RESERVED. */
3 /* Don't put this into the SVN repo. */
4
5 /*
6 @todo
7 - Write a nick printf type thing for pcalled functions.
8 - Make commands register as apposed to blinding calling.
9 - Use numerics instead of huge structures, and add lookup functions.
10 */
11
12 #include "../channel/channel.h"
13 #include "../control/control.h"
14 #include "../nick/nick.h"
15 #include "../localuser/localuser.h"
16 #include "../localuser/localuserchannel.h"
17 #include "../lib/irc_string.h"
18 #include "../lib/flags.h"
19 #include "../authext/authext.h"
20 #include "../glines/glines.h"
21 #include "../trusts/trusts.h"
22 #include "../bans/bans.h"
23 #include "../core/modules.h"
24
25 #include "lua.h"
26 #include "luabot.h"
27
28 #include <stdarg.h>
29 #include <stddef.h>
30
31 #define MAX_PUSHER 50
32
33 static int lua_smsg(lua_State *ps);
34 static int lua_skill(lua_State *ps);
35
36 typedef struct lua_pusher {
37 short argtype;
38 short offset;
39 const char *structname;
40 } lua_pusher;
41
42 struct lua_pusher nickpusher[MAX_PUSHER];
43 struct lua_pusher chanpusher[MAX_PUSHER];
44 int nickpushercount, chanpushercount;
45
46 void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount);
47 int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np);
48
49 void lua_initnickpusher(void);
50 void lua_initchanpusher(void);
51
52 #define lua_setupnickpusher(L2, I2, P2, M2) lua_setuppusher(&nickpusher[0], L2, I2, P2, M2, nickpushercount)
53 #define lua_setupchanpusher(L2, I2, P2, M2) lua_setuppusher(&chanpusher[0], L2, I2, P2, M2, chanpushercount)
54
55 int lua_cmsg(char *channell, char *message, ...) __attribute__ ((format (printf, 2, 3)));
56
57 int lua_cmsg(char *channell, char *message, ...) {
58 char buf[512];
59 va_list va;
60 channel *cp;
61
62 va_start(va, message);
63 vsnprintf(buf, sizeof(buf), message, va);
64 va_end(va);
65
66 cp = findchannel(channell);
67 if(!cp)
68 return LUA_FAIL;
69
70 if(!lua_lineok(buf))
71 return LUA_FAIL;
72
73 lua_channelmessage(cp, "%s", buf);
74
75 return LUA_OK;
76 }
77
78 static int lua_chanmsg(lua_State *ps) {
79 if(!lua_isstring(ps, 1))
80 LUA_RETURN(ps, LUA_FAIL);
81
82 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua: %s", lua_tostring(ps, 1)));
83 }
84
85 static int lua_ctcp(lua_State *ps) {
86 const char *n, *msg;
87 nick *np;
88
89 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
90 LUA_RETURN(ps, LUA_FAIL);
91
92 n = lua_tostring(ps, 1);
93 msg = lua_tostring(ps, 2);
94
95 np = getnickbynick(n);
96 if(!np || !lua_lineok(msg))
97 LUA_RETURN(ps, LUA_FAIL);
98
99 lua_message(np, "\001%s\001", msg);
100
101 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-ctcp: %s (%s)", np->nick, msg));
102 }
103
104 static int lua_noticecmd(lua_State *ps) {
105 const char *n, *msg;
106 nick *np;
107
108 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
109 LUA_RETURN(ps, LUA_FAIL);
110
111 n = lua_tostring(ps, 1);
112 msg = lua_tostring(ps, 2);
113
114 np = getnickbynick(n);
115 if(!np || !lua_lineok(msg))
116 LUA_RETURN(ps, LUA_FAIL);
117
118 lua_notice(np, "%s", msg);
119
120 LUA_RETURN(ps, LUA_OK);
121 }
122
123 static int lua_privmsgcmd(lua_State *ps) {
124 const char *n, *msg;
125 nick *np;
126
127 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
128 LUA_RETURN(ps, LUA_FAIL);
129
130 n = lua_tostring(ps, 1);
131 msg = lua_tostring(ps, 2);
132
133 np = getnickbynick(n);
134 if(!np || !lua_lineok(msg))
135 LUA_RETURN(ps, LUA_FAIL);
136
137 lua_message(np, "%s", msg);
138
139 LUA_RETURN(ps, LUA_OK);
140 }
141
142 static int lua_kill(lua_State *ps) {
143 const char *n, *msg;
144 nick *np;
145
146 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
147 LUA_RETURN(ps, LUA_FAIL);
148
149 n = lua_tostring(ps, 1);
150 msg = lua_tostring(ps, 2);
151
152 np = getnickbynick(n);
153 if(!np)
154 LUA_RETURN(ps, LUA_FAIL);
155
156 if(IsOper(np) || IsService(np) || IsXOper(np))
157 LUA_RETURN(ps, LUA_FAIL);
158
159 if(!lua_lineok(msg))
160 LUA_RETURN(ps, LUA_FAIL);
161
162 killuser(lua_nick, np, "%s", msg);
163
164 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-KILL: %s (%s)", np->nick, msg));
165 }
166
167 static int lua_kick(lua_State *ps) {
168 const char *n, *msg, *chan;
169 nick *np;
170 channel *cp;
171 int dochecks = 1;
172
173 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
174 LUA_RETURN(ps, LUA_FAIL);
175
176 chan = lua_tostring(ps, 1);
177 n = lua_tostring(ps, 2);
178 msg = lua_tostring(ps, 3);
179
180 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
181 dochecks = 0;
182
183 np = getnickbynick(n);
184 if(!np)
185 LUA_RETURN(ps, LUA_FAIL);
186
187 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
188 LUA_RETURN(ps, LUA_FAIL);
189
190 cp = findchannel((char *)chan);
191 if(!cp)
192 LUA_RETURN(ps, LUA_FAIL);
193
194 if(!lua_lineok(msg))
195 LUA_RETURN(ps, LUA_FAIL);
196
197 localkickuser(lua_nick, cp, np, msg);
198
199 LUA_RETURN(ps, LUA_OK);
200 }
201
202 static int lua_invite(lua_State *ps) {
203 nick *np;
204 channel *cp;
205
206 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
207 LUA_RETURN(ps, LUA_FAIL);
208
209 np = getnickbynick((char *)lua_tostring(ps, 1));
210 if(!np)
211 LUA_RETURN(ps, LUA_FAIL);
212
213 cp = findchannel((char *)lua_tostring(ps, 2));
214 if(!cp)
215 LUA_RETURN(ps, LUA_FAIL);
216
217 localinvite(lua_nick, cp->index, np);
218
219 LUA_RETURN(ps, LUA_OK);
220 }
221
222 static int lua_gline(lua_State *ps) {
223 glineinfo *info;
224 const char *reason;
225 nick *target;
226 int duration;
227
228 if(!lua_isstring(ps, 1) || !lua_isint(ps, 2) || !lua_isstring(ps, 3))
229 LUA_RETURN(ps, LUA_FAIL);
230
231 duration = lua_toint(ps, 2);
232 if((duration < 1) || (duration > 31 * 86400))
233 LUA_RETURN(ps, LUA_FAIL);
234
235 reason = lua_tostring(ps, 3);
236 if(!lua_lineok(reason) || !reason)
237 LUA_RETURN(ps, LUA_FAIL);
238
239 target = getnickbynick(lua_tostring(ps, 1));
240 if(!target || (IsOper(target) || IsXOper(target) || IsService(target)))
241 LUA_RETURN(ps, LUA_FAIL);
242
243 if(glinebynick(target, duration, reason, GLINE_SIMULATE, "lua") > 50)
244 LUA_RETURN(ps, LUA_FAIL);
245
246 info = glinebynickex(target, duration, reason, 0, "lua");
247 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", info->mask, info->hits, duration, reason));
248 }
249
250 static int lua_fastgetchaninfo(lua_State *ps) {
251 static struct lua_pusher *ourpusher[MAX_PUSHER];
252 channel *cp;
253
254 if(!lua_isstring(ps, 1))
255 return 0;
256
257 cp = findchannel((char *)lua_tostring(ps, 1));
258 if(!cp || cp->index->channel != cp)
259 return 0;
260
261 lua_setupchanpusher(ps, 2, ourpusher, MAX_PUSHER);
262 return lua_usepusher(ps, ourpusher, cp->index);
263 }
264
265 static int lua_opchan(lua_State *ps) {
266 channel *cp;
267 nick *np;
268
269 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
270 LUA_RETURN(ps, LUA_FAIL);
271
272 cp = findchannel((char *)lua_tostring(ps, 1));
273 if(!cp)
274 LUA_RETURN(ps, LUA_FAIL);
275
276 np = getnickbynick((char *)lua_tostring(ps, 2));
277 if(!np)
278 LUA_RETURN(ps, LUA_FAIL);
279
280 localsetmodes(lua_nick, cp, np, MC_OP);
281 LUA_RETURN(ps, LUA_OK);
282 }
283
284 static int lua_deopchan(lua_State *ps) {
285 channel *cp;
286 nick *np;
287
288 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
289 LUA_RETURN(ps, LUA_FAIL);
290
291 cp = findchannel((char *)lua_tostring(ps, 1));
292 if(!cp)
293 LUA_RETURN(ps, LUA_FAIL);
294
295 np = getnickbynick((char *)lua_tostring(ps, 2));
296 if(!np)
297 LUA_RETURN(ps, LUA_FAIL);
298
299 localsetmodes(lua_nick, cp, np, MC_DEOP);
300 LUA_RETURN(ps, LUA_OK);
301 }
302
303 static int lua_voicechan(lua_State *ps) {
304 channel *cp;
305 nick *np;
306
307 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
308 LUA_RETURN(ps, LUA_FAIL);
309
310 cp = findchannel((char *)lua_tostring(ps, 1));
311 if(!cp)
312 LUA_RETURN(ps, LUA_FAIL);
313
314 np = getnickbynick((char *)lua_tostring(ps, 2));
315 if(!np)
316 LUA_RETURN(ps, LUA_FAIL);
317
318 localsetmodes(lua_nick, cp, np, MC_VOICE);
319 LUA_RETURN(ps, LUA_OK);
320 }
321
322 static int lua_counthost(lua_State *ps) {
323 long numeric;
324 nick *np;
325
326 if(!lua_islong(ps, 1))
327 return 0;
328
329 numeric = lua_tolong(ps, 1);
330
331 np = getnickbynumeric(numeric);
332 if(!np)
333 return 0;
334
335 lua_pushint(ps, np->host->clonecount);
336 return 1;
337 }
338
339 static int lua_versioninfo(lua_State *ps) {
340 lua_pushstring(ps, LUA_VERSION);
341 lua_pushstring(ps, LUA_BOTVERSION);
342 lua_pushstring(ps, __DATE__);
343 lua_pushstring(ps, __TIME__);
344
345 lua_pushstring(ps, LUA_AUXVERSION);
346
347 return 5;
348 }
349
350 static int lua_nickmatchban(lua_State *ps) {
351 const char *chanban_str, *nick_str;
352 chanban *cb;
353 nick *np;
354
355 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
356 return 0;
357
358 nick_str = lua_tostring(ps, 1);
359 chanban_str = lua_tostring(ps, 2);
360
361 np = getnickbynick(nick_str);
362 if(!np)
363 return 0;
364
365 cb = makeban(chanban_str);
366 if(!cb)
367 return 0;
368
369 lua_pushboolean(ps, nickmatchban(np, cb, 1));
370
371 freechanban(cb);
372
373 return 1;
374 }
375
376 static int lua_nickbanned(lua_State *ps) {
377 const char *channel_str, *nick_str;
378 channel *cp;
379 nick *np;
380
381 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
382 return 0;
383
384 nick_str = lua_tostring(ps, 1);
385 channel_str = lua_tostring(ps, 2);
386
387 np = getnickbynick(nick_str);
388 if(!np)
389 return 0;
390
391 cp = findchannel((char *)channel_str);
392 if(!cp)
393 return 0;
394
395 lua_pushboolean(ps, nickbanned(np, cp, 1));
396
397 return 1;
398 }
399
400 static int lua_suggestbanmask(lua_State *ps) {
401 const char *nick_str;
402 nick *np;
403 glinebuf gb;
404 gline *gl;
405 int i = 1;
406
407 if (!lua_isstring(ps, 1))
408 return 0;
409
410 nick_str = lua_tostring(ps, 1);
411 np = getnickbynick(nick_str);
412 if (!np)
413 return 0;
414
415 glinebufinit(&gb, 0);
416 glinebufaddbynick(&gb, np, 0, "Auto", "None", time(NULL), time(NULL), time(NULL));
417
418 lua_newtable(ps);
419
420 for (gl = gb.glines; gl; gl = gl->next) {
421 if (gl->host && gl->host->content) {
422 char *mask = glinetostring(gl);
423 LUA_APUSHSTRING(ps, i, mask);
424 i++;
425 }
426 }
427
428 glinebufabort(&gb);
429
430 return 1;
431 }
432
433 static int lua_nickistrusted(lua_State *ps) {
434 const char *nick_str;
435 nick *np;
436
437 if(!lua_isstring(ps, 1))
438 return 0;
439
440 nick_str = lua_tostring(ps, 1);
441
442 np = getnickbynick(nick_str);
443 if(!np)
444 return 0;
445
446 lua_pushboolean(ps, istrusted(np));
447
448 return 1;
449 }
450
451 static int lua_basepath(lua_State *ps) {
452 lua_pushfstring(ps, "%s/", cpath->content);
453
454 return 1;
455 }
456
457 static int lua_botnick(lua_State *ps) {
458 lua_pushstring(ps, luabotnick->content);
459
460 return 1;
461 }
462
463 static int lua_numerictobase64(lua_State *ps) {
464 if(!lua_islong(ps, 1))
465 return 0;
466
467 lua_pushstring(ps, longtonumeric(lua_tolong(ps, 1), 5));
468 return 1;
469 }
470
471 static int lua_match(lua_State *ps) {
472 const char *mask, *string;
473
474 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
475 return 0;
476
477 mask = lua_tostring(ps, 1);
478 string = lua_tostring(ps, 2);
479
480 if (!mask || !mask[0] || !string || !string[0])
481 return 0;
482
483 lua_pushboolean(ps, match2strings(mask, string));
484 return 1;
485 }
486
487 static int lua_getuserbyauth(lua_State *l) {
488 nick *np;
489 int found = 0;
490 authname *au;
491
492 if(!lua_isstring(l, 1))
493 return 0;
494
495 au = getauthbyname(lua_tostring(l, 1));
496 if(!au)
497 return 0;
498
499 for(np=au->nicks;np;np=np->nextbyauthname) {
500 lua_pushnumeric(l, np->numeric);
501 found++;
502 }
503
504 return found;
505 }
506
507 static int lua_getnickchans(lua_State *l) {
508 nick *np;
509 int i;
510 channel **channels;
511
512 if(!lua_islong(l, 1))
513 return 0;
514
515 np = getnickbynumeric(lua_tolong(l, 1));
516 if(!np)
517 return 0;
518
519 channels = (channel **)np->channels->content;
520 for(i=0;i<np->channels->cursi;i++)
521 lua_pushstring(l, channels[i]->index->name->content);
522
523 return np->channels->cursi;
524 }
525
526 static int lua_getnickchanindex(lua_State *l) {
527 nick *np;
528 int offset;
529
530 if(!lua_islong(l, 1) || !lua_isint(l, 2))
531 return 0;
532
533 np = getnickbynumeric(lua_tolong(l, 1));
534 if(!np)
535 return 0;
536
537 offset = lua_toint(l, 2);
538 if((offset < 0) || (offset >= np->channels->cursi))
539 return 0;
540
541 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
542
543 return 1;
544 }
545
546 int hashindex;
547 nick *lasthashnick;
548 static int geoipext;
549
550 struct lua_pusher *nickhashpusher[MAX_PUSHER];
551
552 static int lua_getnextnick(lua_State *l) {
553 if(!lasthashnick && (hashindex != -1))
554 return 0;
555
556 do {
557 if(!lasthashnick) {
558 hashindex++;
559 if(hashindex >= NICKHASHSIZE)
560 return 0;
561 lasthashnick = nicktable[hashindex];
562 } else {
563 lasthashnick = lasthashnick->next;
564 }
565 } while(!lasthashnick);
566
567 return lua_usepusher(l, nickhashpusher, lasthashnick);
568 }
569
570 static int lua_getfirstnick(lua_State *l) {
571 hashindex = -1;
572 lasthashnick = NULL;
573
574 lua_setupnickpusher(l, 1, nickhashpusher, MAX_PUSHER);
575 geoipext = findnickext("geoip");
576
577 return lua_getnextnick(l);
578 }
579
580 int chanhashindex;
581 chanindex *lasthashchan;
582
583 struct lua_pusher *chanhashpusher[MAX_PUSHER];
584
585 static int lua_getnextchan(lua_State *l) {
586 if(!lasthashchan && (chanhashindex != -1))
587 return 0;
588
589 do {
590 if(!lasthashchan) {
591 chanhashindex++;
592 if(chanhashindex >= CHANNELHASHSIZE)
593 return 0;
594 lasthashchan = chantable[chanhashindex];
595 } else {
596 lasthashchan = lasthashchan->next;
597 }
598 } while(!lasthashchan || !lasthashchan->channel);
599
600 return lua_usepusher(l, chanhashpusher, lasthashchan);
601 }
602
603 static int lua_getfirstchan(lua_State *l) {
604 chanhashindex = -1;
605 lasthashchan = NULL;
606
607 lua_setupchanpusher(l, 1, chanhashpusher, MAX_PUSHER);
608
609 return lua_getnextchan(l);
610 }
611
612 static int lua_getnickchancount(lua_State *l) {
613 nick *np;
614
615 if(!lua_islong(l, 1))
616 return 0;
617
618 np = getnickbynumeric(lua_tolong(l, 1));
619 if(!np)
620 return 0;
621
622 lua_pushint(l, np->channels->cursi);
623
624 return 1;
625 }
626
627 static int lua_gethostusers(lua_State *l) {
628 nick *np;
629 int count;
630
631 if(!lua_islong(l, 1))
632 return 0;
633
634 np = getnickbynumeric(lua_tolong(l, 1));
635 if(!np || !np->host || !np->host->nicks)
636 return 0;
637
638 np = np->host->nicks;
639 count = np->host->clonecount;
640
641 do {
642 lua_pushnumeric(l, np->numeric);
643 np = np->nextbyhost;
644 } while(np);
645
646 return count;
647 }
648
649 static int lua_getnickcountry(lua_State *l) {
650 nick *np;
651 int ext;
652
653 ext = findnickext("geoip");
654 if(ext == -1)
655 return 0;
656
657 if(!lua_islong(l, 1))
658 return 0;
659
660 np = getnickbynumeric(lua_tolong(l, 1));
661 if(!np)
662 return 0;
663
664 lua_pushint(l, (long)np->exts[ext]);
665 return 1;
666 }
667
668 static int lua_chanfix(lua_State *ps) {
669 channel *cp;
670 nick *np;
671
672 if(!lua_isstring(ps, 1))
673 LUA_RETURN(ps, LUA_FAIL);
674
675 cp = findchannel((char *)lua_tostring(ps, 1));
676 if(!cp || !cp->index)
677 LUA_RETURN(ps, LUA_FAIL);
678
679 np = getnickbynick(LUA_CHANFIXBOT);
680 if(!np)
681 LUA_RETURN(ps, LUA_FAIL);
682
683 lua_message(np, "chanfix %s", cp->index->name->content);
684
685 LUA_RETURN(ps, LUA_OK);
686 }
687
688 static int lua_clearmode(lua_State *ps) {
689 channel *cp;
690 int i;
691 nick *np;
692 unsigned long *lp;
693 modechanges changes;
694
695 if(!lua_isstring(ps, 1))
696 LUA_RETURN(ps, LUA_FAIL);
697
698 cp = findchannel((char *)lua_tostring(ps, 1));
699 if(!cp || !cp->users)
700 LUA_RETURN(ps, LUA_FAIL);
701
702 localsetmodeinit(&changes, cp, lua_nick);
703
704 localdosetmode_key(&changes, NULL, MCB_DEL);
705 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
706
707 while(cp->bans)
708 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
709
710 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
711 if((*lp != nouser) && (*lp & CUMODE_OP)) {
712 np = getnickbynumeric(*lp);
713 if(np && !IsService(np))
714 localdosetmode_nick(&changes, np, MC_DEOP);
715 }
716
717 localsetmodeflush(&changes, 1);
718
719 LUA_RETURN(ps, LUA_OK);
720 }
721
722 static int lua_ban(lua_State *ps) {
723 channel *cp;
724 const char *mask;
725 modechanges changes;
726 int dir = MCB_ADD;
727
728 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
729 LUA_RETURN(ps, LUA_FAIL);
730
731 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
732 dir = MCB_DEL;
733
734 cp = findchannel((char *)lua_tostring(ps, 1));
735 if(!cp)
736 LUA_RETURN(ps, LUA_FAIL);
737
738 mask = lua_tostring(ps, 2);
739 if(!mask || !mask[0] || !lua_lineok(mask))
740 LUA_RETURN(ps, LUA_FAIL);
741
742 localsetmodeinit(&changes, cp, lua_nick);
743 localdosetmode_ban(&changes, mask, dir);
744 localsetmodeflush(&changes, 1);
745
746 LUA_RETURN(ps, LUA_OK);
747 }
748
749 static int lua_topic(lua_State *ps) {
750 channel *cp;
751 char *topic;
752
753 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
754 LUA_RETURN(ps, LUA_FAIL);
755
756 cp = findchannel((char *)lua_tostring(ps, 1));
757 if(!cp)
758 LUA_RETURN(ps, LUA_FAIL);
759
760 topic = (char *)lua_tostring(ps, 2);
761 if(!topic || !lua_lineok(topic))
762 LUA_RETURN(ps, LUA_FAIL);
763
764 localsettopic(lua_nick, cp, topic);
765
766 LUA_RETURN(ps, LUA_OK);
767 }
768
769 static int lua_getuserchanmodes(lua_State *l) {
770 nick *np;
771 channel *cp;
772 unsigned long *lp;
773
774 if(!lua_islong(l, 1) || !lua_isstring(l, 2))
775 return 0;
776
777 np = getnickbynumeric(lua_tolong(l, 1));
778 if(!np)
779 return 0;
780
781 cp = findchannel((char *)lua_tostring(l, 2));
782 if(!cp || !cp->users)
783 return 0;
784
785 lp = getnumerichandlefromchanhash(cp->users, np->numeric);
786 if(!lp)
787 return 0;
788
789 LUA_PUSHNICKCHANMODES(l, lp);
790 return 1;
791 }
792
793 static int lua_getusermodes(lua_State *l) {
794 nick *np;
795
796 if(!lua_islong(l, 1))
797 return 0;
798
799 np = getnickbynumeric(lua_tolong(l, 1));
800 if(!np)
801 return 0;
802
803 lua_pushstring(l, printflags(np->umodes, umodeflags));
804 return 1;
805 }
806
807 static int lua_fastgetnickbynumeric(lua_State *l) {
808 static struct lua_pusher *ourpusher[MAX_PUSHER];
809 nick *np;
810
811 if(!lua_islong(l, 1))
812 return 0;
813
814 np = getnickbynumeric(lua_tolong(l, 1));
815 if(!np)
816 return 0;
817
818 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
819 return lua_usepusher(l, ourpusher, np);
820 }
821
822 static int lua_fastgetnickbynick(lua_State *l) {
823 static struct lua_pusher *ourpusher[MAX_PUSHER];
824 nick *np;
825
826 if(!lua_isstring(l, 1))
827 return 0;
828
829 np = getnickbynick((char *)lua_tostring(l, 1));
830 if(!np)
831 return 0;
832
833 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
834 return lua_usepusher(l, ourpusher, np);
835 }
836
837 int channelnicklistindex, channelnicklistcount = -1;
838 channel *channelnicklist;
839
840 struct lua_pusher *channelnickpusher[MAX_PUSHER];
841
842 static int lua_getnextchannick(lua_State *l) {
843 nick *np;
844
845 do {
846 channelnicklistindex++;
847
848 if(channelnicklistindex >= channelnicklistcount)
849 return 0;
850 } while((channelnicklist->users->content[channelnicklistindex] == nouser) || !(np = getnickbynumeric(channelnicklist->users->content[channelnicklistindex])));
851
852 return lua_usepusher(l, channelnickpusher, np);
853 }
854
855 static int lua_getfirstchannick(lua_State *l) {
856 if(!lua_isstring(l, 1))
857 return 0;
858
859 channelnicklist = findchannel((char *)lua_tostring(l, 1));
860 if(!channelnicklist|| !channelnicklist->users)
861 return 0;
862
863 channelnicklistindex = -1;
864 channelnicklistcount = channelnicklist->users->hashsize;
865
866 lua_setupnickpusher(l, 2, channelnickpusher, MAX_PUSHER);
867
868 return lua_getnextchannick(l);
869 }
870
871 static int lua_nickonchan(lua_State *l) {
872 int success = 0;
873 if(lua_islong(l, 1) && lua_isstring(l, 2)) {
874 channel *cp = findchannel((char *)lua_tostring(l, 2));
875 if(cp && cp->users) {
876 unsigned long *lp = getnumerichandlefromchanhash(cp->users, lua_tolong(l, 1));
877 if(lp)
878 success = 1;
879 }
880 }
881
882 lua_pushboolean(l, success);
883 return 1;
884 }
885
886 static int lua_simplechanmode(lua_State *ps) {
887 channel *cp;
888 char *modes;
889 flag_t add = 0, del = ~add;
890 flag_t permitted = CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT | CHANMODE_SECRET | CHANMODE_PRIVATE | CHANMODE_INVITEONLY | CHANMODE_MODERATE | CHANMODE_NOCOLOUR | CHANMODE_NOCTCP | CHANMODE_REGONLY | CHANMODE_DELJOINS | CHANMODE_NOQUITMSG | CHANMODE_NONOTICE | CHANMODE_MODNOAUTH | CHANMODE_SINGLETARG;
891 modechanges changes;
892
893 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
894 LUA_RETURN(ps, LUA_FAIL);
895
896 cp = findchannel((char *)lua_tostring(ps, 1));
897 if(!cp)
898 LUA_RETURN(ps, LUA_FAIL);
899
900 modes = (char *)lua_tostring(ps, 2);
901 if(!modes)
902 LUA_RETURN(ps, LUA_FAIL);
903
904 if(setflags(&add, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
905 LUA_RETURN(ps, LUA_FAIL);
906
907 if(setflags(&del, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
908 LUA_RETURN(ps, LUA_FAIL);
909
910 localsetmodeinit(&changes, cp, lua_nick);
911 localdosetmode_simple(&changes, add, ~del);
912 localsetmodeflush(&changes, 1);
913
914 LUA_RETURN(ps, LUA_OK);
915 }
916
917 static int lua_sethost(lua_State *ps) {
918 char *ident, *host;
919 nick *np;
920
921 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
922 LUA_RETURN(ps, LUA_FAIL);
923
924 np = getnickbynumeric(lua_tolong(ps, 1));
925 if(!np)
926 LUA_RETURN(ps, LUA_FAIL);
927
928 ident = (char *)lua_tostring(ps, 2);
929 host = (char *)lua_tostring(ps, 3);
930 if(!lua_lineok(ident) || !lua_lineok(host))
931 LUA_RETURN(ps, LUA_FAIL);
932
933 sethostuser(np, ident, host);
934
935 LUA_RETURN(ps, LUA_OK);
936 }
937
938 static int lua_getvisiblehostmask(lua_State *l) {
939 nick *np;
940 char buf[HOSTLEN+USERLEN+NICKLEN+REALLEN+10];
941
942 if(!lua_islong(l, 1))
943 return 0;
944
945 np = getnickbynumeric(lua_tolong(l, 1));
946 if(!np)
947 return 0;
948
949 lua_pushstring(l, visiblehostmask(np, buf));
950 return 1;
951 }
952
953 void lua_registercommands(lua_State *l) {
954 lua_register(l, "irc_smsg", lua_smsg);
955 lua_register(l, "irc_skill", lua_skill);
956
957 lua_register(l, "chanmsg", lua_chanmsg);
958 lua_register(l, "versioninfo", lua_versioninfo);
959 lua_register(l, "basepath", lua_basepath);
960 lua_register(l, "botnick", lua_botnick);
961
962 lua_register(l, "irc_report", lua_chanmsg);
963 lua_register(l, "irc_ctcp", lua_ctcp);
964 lua_register(l, "irc_kill", lua_kill);
965 lua_register(l, "irc_kick", lua_kick);
966 lua_register(l, "irc_invite", lua_invite);
967 lua_register(l, "irc_gline", lua_gline);
968 lua_register(l, "irc_counthost", lua_counthost);
969 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
970 lua_register(l, "irc_notice", lua_noticecmd);
971 lua_register(l, "irc_privmsg", lua_privmsgcmd);
972 lua_register(l, "irc_opchan", lua_opchan);
973 lua_register(l, "irc_voicechan", lua_voicechan);
974 lua_register(l, "irc_chanfix", lua_chanfix);
975 lua_register(l, "irc_clearmode", lua_clearmode);
976 lua_register(l, "irc_ban", lua_ban);
977 lua_register(l, "irc_deopchan", lua_deopchan);
978 lua_register(l, "irc_topic", lua_topic);
979
980 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
981 lua_register(l, "irc_getnextnick", lua_getnextnick);
982
983 lua_register(l, "irc_getnickchans", lua_getnickchans);
984 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
985 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
986
987 lua_register(l, "irc_getuserchanmodes", lua_getuserchanmodes);
988
989 lua_register(l, "irc_getfirstchannick", lua_getfirstchannick);
990 lua_register(l, "irc_getnextchannick", lua_getnextchannick);
991
992 lua_register(l, "irc_gethostusers", lua_gethostusers);
993 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
994
995 lua_register(l, "irc_getfirstchan", lua_getfirstchan);
996 lua_register(l, "irc_getnextchan", lua_getnextchan);
997 lua_register(l, "irc_getusermodes", lua_getusermodes);
998 lua_register(l, "irc_nickonchan", lua_nickonchan);
999
1000 lua_register(l, "irc_fastgetnickbynumeric", lua_fastgetnickbynumeric);
1001 lua_register(l, "irc_fastgetnickbynick", lua_fastgetnickbynick);
1002 lua_register(l, "irc_fastgetchaninfo", lua_fastgetchaninfo);
1003
1004 lua_register(l, "irc_getvisiblehostmask", lua_getvisiblehostmask);
1005
1006 lua_register(l, "irc_simplechanmode", lua_simplechanmode);
1007 lua_register(l, "irc_sethost", lua_sethost);
1008
1009 lua_register(l, "irc_numerictobase64", lua_numerictobase64);
1010 lua_register(l, "ircmatch", lua_match);
1011
1012 lua_register(l, "irc_nickmatchban", lua_nickmatchban);
1013 lua_register(l, "irc_nickistrusted", lua_nickistrusted);
1014 lua_register(l, "irc_nickbanned", lua_nickbanned);
1015 lua_register(l, "irc_suggestbanmask", lua_suggestbanmask);
1016 }
1017
1018 /* --- */
1019
1020 static int lua_smsg(lua_State *ps) {
1021 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
1022 LUA_RETURN(ps, LUA_FAIL);
1023
1024 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
1025 }
1026
1027 static int lua_skill(lua_State *ps) {
1028 const char *n, *msg;
1029 nick *np;
1030
1031 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
1032 LUA_RETURN(ps, LUA_FAIL);
1033
1034 n = lua_tostring(ps, 1);
1035 msg = lua_tostring(ps, 2);
1036
1037 np = getnickbynick(n);
1038 if(!np)
1039 LUA_RETURN(ps, LUA_FAIL);
1040
1041 if(IsOper(np) || IsService(np) || IsXOper(np))
1042 LUA_RETURN(ps, LUA_FAIL);
1043
1044 if(!lua_lineok(msg))
1045 LUA_RETURN(ps, LUA_FAIL);
1046
1047 killuser(lua_nick, np, "%s", msg);
1048
1049 LUA_RETURN(ps, LUA_OK);
1050 }
1051
1052 #define PUSHER_STRING 1
1053 #define PUSHER_REALNAME 2
1054 #define PUSHER_IP 3
1055 #define PUSHER_LONG 4
1056 #define PUSHER_HOSTNAME 5
1057 #define PUSHER_SSTRING 6
1058 #define PUSHER_TOTALUSERS 7
1059 #define PUSHER_TOPIC 8
1060 #define PUSHER_UMODES 9
1061 #define PUSHER_COUNTRY 10
1062 #define PUSHER_REALUSERS 11
1063 #define PUSHER_CHANMODES 12
1064 #define PUSHER_TIMESTAMP 13
1065 #define PUSHER_STRING_INDIRECT 14
1066 #define PUSHER_ACC_ID 15
1067 #define PUSHER_SERVER_NAME 16
1068 #define PUSHER_SERVER_NUMERIC 17
1069 #define PUSHER_IS_SERVICE 18
1070
1071 void lua_initnickpusher(void) {
1072 int i = 0;
1073
1074 #define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
1075 #define PUSH_NICKPUSHER_CUSTOM(F2, custom) nickpusher[i].argtype = F2; nickpusher[i].structname = custom; nickpusher[i].offset = 0; i++;
1076
1077 PUSH_NICKPUSHER(PUSHER_STRING, nick);
1078 PUSH_NICKPUSHER(PUSHER_STRING, ident);
1079 PUSH_NICKPUSHER(PUSHER_HOSTNAME, host);
1080 PUSH_NICKPUSHER(PUSHER_REALNAME, realname);
1081 PUSH_NICKPUSHER(PUSHER_STRING_INDIRECT, authname);
1082 PUSH_NICKPUSHER(PUSHER_IP, ipnode);
1083 PUSH_NICKPUSHER(PUSHER_LONG, numeric);
1084 PUSH_NICKPUSHER(PUSHER_LONG, timestamp);
1085 PUSH_NICKPUSHER(PUSHER_LONG, accountts);
1086 PUSH_NICKPUSHER(PUSHER_UMODES, umodes);
1087 PUSH_NICKPUSHER_CUSTOM(PUSHER_COUNTRY, "country");
1088 PUSH_NICKPUSHER_CUSTOM(PUSHER_ACC_ID, "accountid");
1089 PUSH_NICKPUSHER_CUSTOM(PUSHER_SERVER_NAME, "servername");
1090 PUSH_NICKPUSHER_CUSTOM(PUSHER_SERVER_NUMERIC, "servernumeric");
1091 PUSH_NICKPUSHER_CUSTOM(PUSHER_IS_SERVICE, "isservice");
1092
1093 nickpushercount = i;
1094 nickpusher[i].argtype = 0;
1095 }
1096
1097 void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount) {
1098 int current = 0;
1099
1100 if(max > 0)
1101 lp[0] = NULL;
1102
1103 if(!lua_istable(l, index) || (max < 2))
1104 return;
1105
1106 lua_pushnil(l);
1107
1108 max--;
1109
1110 while(lua_next(l, index)) {
1111 if(lua_isint(l, -1)) {
1112 int index = lua_toint(l, -1);
1113 if((index >= 0) && (index < pcount))
1114 lp[current++] = &pusherlist[index];
1115 }
1116
1117 lua_pop(l, 1);
1118
1119 if(current == max)
1120 break;
1121 }
1122
1123 lp[current] = NULL;
1124 }
1125
1126 int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np) {
1127 int i = 0;
1128
1129 while(*lp) {
1130 void *offset = (void *)np + (*lp)->offset;
1131
1132 switch((*lp)->argtype) {
1133 case PUSHER_STRING:
1134 lua_pushstring(l, (char *)offset);
1135 break;
1136 case PUSHER_STRING_INDIRECT:
1137 lua_pushstring(l, *(char **)offset);
1138 break;
1139 case PUSHER_HOSTNAME:
1140 lua_pushstring(l, (*(host **)offset)->name->content);
1141 break;
1142 case PUSHER_REALNAME:
1143 lua_pushstring(l, (*(realname **)offset)->name->content);
1144 break;
1145 case PUSHER_SSTRING:
1146 lua_pushstring(l, (*((sstring **)offset))->content);
1147 break;
1148 case PUSHER_LONG:
1149 lua_pushlong(l, *((long *)offset));
1150 break;
1151 case PUSHER_TIMESTAMP:
1152 lua_pushlong(l, (*((channel **)offset))->timestamp);
1153 break;
1154 case PUSHER_IP:
1155 lua_pushstring(l, IPtostr((*((patricia_node_t **)offset))->prefix->sin));
1156 break;
1157 case PUSHER_TOTALUSERS:
1158 lua_pushint(l, (*((channel **)offset))->users->totalusers);
1159 break;
1160 case PUSHER_CHANMODES:
1161 lua_pushstring(l, printallmodes(*((channel **)offset)));
1162 break;
1163 case PUSHER_ACC_ID:
1164 {
1165 nick *tnp = (nick *)np;
1166 if(IsAccount(tnp) && tnp->auth) {
1167 lua_pushlong(l, tnp->auth->userid);
1168 } else {
1169 lua_pushnil(l);
1170 }
1171 break;
1172 }
1173 case PUSHER_REALUSERS:
1174 {
1175 channel *cp = *((channel **)offset);
1176 nick *np2;
1177 int i, currentusers = countuniquehosts(cp);
1178 for(i=0;i<cp->users->hashsize;i++) {
1179 if(cp->users->content[i]==nouser)
1180 continue;
1181
1182 if((np2=getnickbynumeric(cp->users->content[i]))==NULL) {
1183 Error("lua", ERR_ERROR, "Found unknown numeric %lu on channel %s", cp->users->content[i], cp->index->name->content);
1184 continue;
1185 }
1186
1187 if (IsXOper(np2) || IsService(np2))
1188 currentusers--;
1189 }
1190 lua_pushint(l, currentusers);
1191 }
1192 break;
1193 case PUSHER_UMODES:
1194 lua_pushstring(l, printflags(*((flag_t *)offset), umodeflags));
1195 break;
1196 case PUSHER_TOPIC:
1197 if((*((channel **)offset))->topic) {
1198 lua_pushstring(l, (*((channel **)offset))->topic->content);
1199 } else {
1200 lua_pushnil(l);
1201 }
1202 break;
1203 case PUSHER_COUNTRY:
1204 if(geoipext < 0) {
1205 lua_pushint(l, -1);
1206 } else {
1207 lua_pushint(l, (long)((nick *)offset)->exts[geoipext]);
1208 }
1209 break;
1210 case PUSHER_SERVER_NAME:
1211 lua_pushstring(l, serverlist[homeserver(((nick *)offset)->numeric)].name->content);
1212 break;
1213 case PUSHER_SERVER_NUMERIC:
1214 lua_pushint(l, homeserver(((nick *)offset)->numeric));
1215 break;
1216 case PUSHER_IS_SERVICE:
1217 lua_pushboolean(l, NickOnServiceServer((nick *)offset));
1218 break;
1219 }
1220
1221 i++;
1222 lp++;
1223 }
1224
1225 return i;
1226 }
1227
1228 void lua_initchanpusher(void) {
1229 int i = 0;
1230
1231 #define PUSH_CHANPUSHER(F2, O2, N2) chanpusher[i].argtype = F2; chanpusher[i].structname = N2; chanpusher[i].offset = offsetof(chanindex, O2); i++;
1232
1233 PUSH_CHANPUSHER(PUSHER_SSTRING, name, "name");
1234 PUSH_CHANPUSHER(PUSHER_TOTALUSERS, channel, "totalusers");
1235 PUSH_CHANPUSHER(PUSHER_TOPIC, channel, "topic");
1236 PUSH_CHANPUSHER(PUSHER_REALUSERS, channel, "realusers");
1237 PUSH_CHANPUSHER(PUSHER_TIMESTAMP, channel, "timestamp");
1238 PUSH_CHANPUSHER(PUSHER_CHANMODES, channel, "modes");
1239
1240 chanpushercount = i;
1241 chanpusher[i].argtype = 0;
1242 }
1243