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