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