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