]> jfr.im git - irc/quakenet/newserv.git/blame - lua/luacommands.c
trusts changes
[irc/quakenet/newserv.git] / lua / luacommands.c
CommitLineData
8e965b0c 1/* Copyright (C) Chris Porter 2005-2007 */
2da56f0d
CP
2/* ALL RIGHTS RESERVED. */
3/* Don't put this into the SVN repo. */
4
d0d1e2a3
CP
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
2da56f0d
CP
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"
8e965b0c 18#include "../lib/flags.h"
2da56f0d
CP
19
20#include "lua.h"
21#include "luabot.h"
22
23#include <stdarg.h>
30a59b87 24#include <stddef.h>
2da56f0d 25
ec91b2e4
CP
26#define MAX_PUSHER 50
27
2da56f0d
CP
28static int lua_smsg(lua_State *ps);
29static int lua_skill(lua_State *ps);
30
ec91b2e4 31typedef struct lua_pusher {
30a59b87
CP
32 short argtype;
33 short offset;
34 const char *structname;
ec91b2e4
CP
35} lua_pusher;
36
37struct lua_pusher nickpusher[MAX_PUSHER];
38struct lua_pusher chanpusher[MAX_PUSHER];
ebdfcaa9 39int nickpushercount, chanpushercount;
ec91b2e4 40
4f556cb0
CP
41void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount);
42int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np);
ec91b2e4 43
ebdfcaa9 44void lua_initnickpusher(void);
ec91b2e4 45void lua_initchanpusher(void);
ec91b2e4 46
ebdfcaa9
CP
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)
30a59b87 49
bb4b25ee
CP
50int lua_cmsg(char *channell, char *message, ...) __attribute__ ((format (printf, 2, 3)));
51
2da56f0d
CP
52int 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
73static 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
2da56f0d
CP
80static 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
99static 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
47990928
CP
118static 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
2da56f0d
CP
137static 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
511316a4
CP
162static int lua_kick(lua_State *ps) {
163 const char *n, *msg, *chan;
164 nick *np;
165 channel *cp;
46751959 166 int dochecks = 1;
511316a4
CP
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
46751959
CP
175 if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4))
176 dochecks = 0;
177
511316a4
CP
178 np = getnickbynick(n);
179 if(!np)
180 LUA_RETURN(ps, LUA_FAIL);
181
46751959
CP
182 if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np)))
183 LUA_RETURN(ps, LUA_FAIL);
184
511316a4
CP
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
197static 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
2da56f0d
CP
217static 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);
79e512d7 228 if((duration < 1) || (duration > 31 * 86400))
2da56f0d
CP
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
526e7c1d 258 snprintf(mask, sizeof(mask), "*%s@%s", target->ident, IPtostr(target->p_ipaddr));
2da56f0d 259 } else {
526e7c1d 260 snprintf(mask, sizeof(mask), "*@%s", IPtostr(target->p_ipaddr));
2da56f0d
CP
261 }
262
fb3697bf 263 irc_send("%s GL * +%s %d %jd :%s", mynumeric->content, mask, duration, (intmax_t)getnettime(), reason);
2da56f0d
CP
264 LUA_RETURN(ps, lua_cmsg(LUA_PUKECHAN, "lua-GLINE: %s (%d users, %d seconds -- %s)", mask, usercount, duration, reason));
265}
266
8566a7ed
CP
267static int lua_fastgetchaninfo(lua_State *ps) {
268 static struct lua_pusher *ourpusher[MAX_PUSHER];
2da56f0d
CP
269 channel *cp;
270
271 if(!lua_isstring(ps, 1))
272 return 0;
273
274 cp = findchannel((char *)lua_tostring(ps, 1));
989bcbf5 275 if(!cp || cp->index->channel != cp)
2da56f0d
CP
276 return 0;
277
8566a7ed 278 lua_setupchanpusher(ps, 2, ourpusher, MAX_PUSHER);
0bb2fe5e 279 return lua_usepusher(ps, ourpusher, cp->index);
2da56f0d
CP
280}
281
282static 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
d6998bd1
CP
301static 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
2da56f0d
CP
320static 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
339static 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
356static 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
0225bed3 362 lua_pushstring(ps, LUA_AUXVERSION);
6269435f
CP
363
364 return 5;
365}
366
367static int lua_basepath(lua_State *ps) {
368 lua_pushfstring(ps, "%s/", cpath->content);
369
370 return 1;
2da56f0d
CP
371}
372
d324e17b
CP
373static int lua_botnick(lua_State *ps) {
374 lua_pushstring(ps, luabotnick->content);
375
376 return 1;
377}
378
2da56f0d
CP
379/* O(n) */
380static int lua_getuserbyauth(lua_State *l) {
381 const char *acc;
382 nick *np;
383 int i, found = 0;
384
385 if(!lua_isstring(l, 1))
386 return 0;
387
1fbb1306
CP
388 acc = lua_tostring(l, 1);
389
2da56f0d
CP
390 for(i=0;i<NICKHASHSIZE;i++) {
391 for(np=nicktable[i];np;np=np->next) {
e0a5b7b5 392 if(np && np->authname[0] && !ircd_strcmp(np->authname, acc)) {
0bb2fe5e 393 lua_pushnumeric(l, np->numeric);
2da56f0d
CP
394 found++;
395 }
396 }
397 }
398
399 return found;
400}
401
402static int lua_getnickchans(lua_State *l) {
403 nick *np;
404 int i;
405 channel **channels;
406
407 if(!lua_islong(l, 1))
408 return 0;
409
410 np = getnickbynumeric(lua_tolong(l, 1));
411 if(!np)
412 return 0;
413
414 channels = (channel **)np->channels->content;
415 for(i=0;i<np->channels->cursi;i++)
416 lua_pushstring(l, channels[i]->index->name->content);
417
418 return np->channels->cursi;
419}
420
4561a594
CP
421static int lua_getnickchanindex(lua_State *l) {
422 nick *np;
423 int offset;
424
425 if(!lua_islong(l, 1) || !lua_isint(l, 2))
426 return 0;
427
428 np = getnickbynumeric(lua_tolong(l, 1));
429 if(!np)
430 return 0;
431
432 offset = lua_toint(l, 2);
433 if((offset < 0) || (offset >= np->channels->cursi))
434 return 0;
435
436 lua_pushstring(l, ((channel **)np->channels->content)[offset]->index->name->content);
437
438 return 1;
439}
440
c5706d5b
CP
441int hashindex;
442nick *lasthashnick;
f6a3d1f7 443static int geoipext;
c5706d5b 444
ec91b2e4 445struct lua_pusher *nickhashpusher[MAX_PUSHER];
30a59b87 446
c5706d5b
CP
447static int lua_getnextnick(lua_State *l) {
448 if(!lasthashnick && (hashindex != -1))
449 return 0;
450
451 do {
452 if(!lasthashnick) {
453 hashindex++;
454 if(hashindex >= NICKHASHSIZE)
455 return 0;
456 lasthashnick = nicktable[hashindex];
457 } else {
458 lasthashnick = lasthashnick->next;
459 }
460 } while(!lasthashnick);
461
ec91b2e4 462 return lua_usepusher(l, nickhashpusher, lasthashnick);
c5706d5b
CP
463}
464
465static int lua_getfirstnick(lua_State *l) {
c5706d5b
CP
466 hashindex = -1;
467 lasthashnick = NULL;
468
ec91b2e4 469 lua_setupnickpusher(l, 1, nickhashpusher, MAX_PUSHER);
f6a3d1f7 470 geoipext = findnickext("geoip");
30a59b87 471
c5706d5b
CP
472 return lua_getnextnick(l);
473}
474
ec91b2e4
CP
475int chanhashindex;
476chanindex *lasthashchan;
477
478struct lua_pusher *chanhashpusher[MAX_PUSHER];
479
480static int lua_getnextchan(lua_State *l) {
481 if(!lasthashchan && (chanhashindex != -1))
482 return 0;
483
484 do {
485 if(!lasthashchan) {
486 chanhashindex++;
487 if(chanhashindex >= CHANNELHASHSIZE)
488 return 0;
489 lasthashchan = chantable[chanhashindex];
490 } else {
491 lasthashchan = lasthashchan->next;
492 }
493 } while(!lasthashchan || !lasthashchan->channel);
494
495 return lua_usepusher(l, chanhashpusher, lasthashchan);
496}
497
498static int lua_getfirstchan(lua_State *l) {
499 chanhashindex = -1;
500 lasthashchan = NULL;
501
502 lua_setupchanpusher(l, 1, chanhashpusher, MAX_PUSHER);
503
504 return lua_getnextchan(l);
505}
506
8ac8cd09
CP
507static int lua_getnickchancount(lua_State *l) {
508 nick *np;
509
510 if(!lua_islong(l, 1))
511 return 0;
512
513 np = getnickbynumeric(lua_tolong(l, 1));
514 if(!np)
515 return 0;
516
517 lua_pushint(l, np->channels->cursi);
518
519 return 1;
520}
521
2da56f0d
CP
522static int lua_gethostusers(lua_State *l) {
523 nick *np;
524 int count;
525
526 if(!lua_islong(l, 1))
527 return 0;
528
529 np = getnickbynumeric(lua_tolong(l, 1));
530 if(!np || !np->host || !np->host->nicks)
531 return 0;
532
533 np = np->host->nicks;
534 count = np->host->clonecount;
535
536 do {
0bb2fe5e 537 lua_pushnumeric(l, np->numeric);
2da56f0d
CP
538 np = np->nextbyhost;
539 } while(np);
540
541 return count;
542}
543
46751959
CP
544static int lua_getnickcountry(lua_State *l) {
545 nick *np;
546 int ext;
547
548 ext = findnickext("geoip");
549 if(ext == -1)
550 return 0;
551
552 if(!lua_islong(l, 1))
553 return 0;
554
555 np = getnickbynumeric(lua_tolong(l, 1));
556 if(!np)
557 return 0;
558
abc75f54 559 lua_pushint(l, (long)np->exts[ext]);
46751959
CP
560 return 1;
561}
562
ebe20bb8
CP
563static int lua_chanfix(lua_State *ps) {
564 channel *cp;
565 nick *np;
566
567 if(!lua_isstring(ps, 1))
568 LUA_RETURN(ps, LUA_FAIL);
569
570 cp = findchannel((char *)lua_tostring(ps, 1));
1f57d0e2 571 if(!cp || !cp->index)
ebe20bb8
CP
572 LUA_RETURN(ps, LUA_FAIL);
573
574 np = getnickbynick(LUA_CHANFIXBOT);
575 if(!np)
576 LUA_RETURN(ps, LUA_FAIL);
577
578 lua_message(np, "chanfix %s", cp->index->name->content);
579
580 LUA_RETURN(ps, LUA_OK);
581}
582
583static int lua_clearmode(lua_State *ps) {
584 channel *cp;
585 int i;
586 nick *np;
587 unsigned long *lp;
588 modechanges changes;
589
590 if(!lua_isstring(ps, 1))
591 LUA_RETURN(ps, LUA_FAIL);
592
593 cp = findchannel((char *)lua_tostring(ps, 1));
1f57d0e2 594 if(!cp || !cp->users)
ebe20bb8
CP
595 LUA_RETURN(ps, LUA_FAIL);
596
597 localsetmodeinit(&changes, cp, lua_nick);
598
599 localdosetmode_key(&changes, NULL, MCB_DEL);
600 localdosetmode_simple(&changes, 0, CHANMODE_INVITEONLY | CHANMODE_LIMIT);
601
602 while(cp->bans)
603 localdosetmode_ban(&changes, bantostring(cp->bans), MCB_DEL);
604
605 for(i=0,lp=cp->users->content;i<cp->users->hashsize;i++,lp++)
606 if((*lp != nouser) && (*lp & CUMODE_OP)) {
607 np = getnickbynumeric(*lp);
608 if(np && !IsService(np))
609 localdosetmode_nick(&changes, np, MC_DEOP);
610 }
611
612 localsetmodeflush(&changes, 1);
613
614 LUA_RETURN(ps, LUA_OK);
615}
616
46751959
CP
617static int lua_ban(lua_State *ps) {
618 channel *cp;
619 const char *mask;
620 modechanges changes;
621 int dir = MCB_ADD;
622
623 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
624 LUA_RETURN(ps, LUA_FAIL);
625
626 if(lua_isboolean(ps, 3) && lua_toboolean(ps, 3))
627 dir = MCB_DEL;
628
629 cp = findchannel((char *)lua_tostring(ps, 1));
630 if(!cp)
631 LUA_RETURN(ps, LUA_FAIL);
632
633 mask = lua_tostring(ps, 2);
634 if(!mask || !mask[0] || !lua_lineok(mask))
635 LUA_RETURN(ps, LUA_FAIL);
636
637 localsetmodeinit(&changes, cp, lua_nick);
638 localdosetmode_ban(&changes, mask, dir);
639 localsetmodeflush(&changes, 1);
640
641 LUA_RETURN(ps, LUA_OK);
642}
643
d0d1e2a3
CP
644static int lua_topic(lua_State *ps) {
645 channel *cp;
646 char *topic;
647
648 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
649 LUA_RETURN(ps, LUA_FAIL);
650
651 cp = findchannel((char *)lua_tostring(ps, 1));
652 if(!cp)
653 LUA_RETURN(ps, LUA_FAIL);
654
655 topic = (char *)lua_tostring(ps, 2);
656 if(!topic || !lua_lineok(topic))
657 LUA_RETURN(ps, LUA_FAIL);
658
659 localsettopic(lua_nick, cp, topic);
660
661 LUA_RETURN(ps, LUA_OK);
662}
663
664static int lua_getuserchanmodes(lua_State *l) {
665 nick *np;
666 channel *cp;
667 unsigned long *lp;
668
669 if(!lua_islong(l, 1) || !lua_isstring(l, 2))
670 return 0;
671
672 np = getnickbynumeric(lua_tolong(l, 1));
673 if(!np)
674 return 0;
675
676 cp = findchannel((char *)lua_tostring(l, 2));
1f57d0e2 677 if(!cp || !cp->users)
d0d1e2a3
CP
678 return 0;
679
680 lp = getnumerichandlefromchanhash(cp->users, np->numeric);
681 if(!lp)
682 return 0;
683
684 LUA_PUSHNICKCHANMODES(l, lp);
685 return 1;
686}
687
c0d574fa
CP
688static int lua_getusermodes(lua_State *l) {
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_pushstring(l, printflags(np->umodes, umodeflags));
699 return 1;
700}
701
8566a7ed
CP
702static int lua_fastgetnickbynumeric(lua_State *l) {
703 static struct lua_pusher *ourpusher[MAX_PUSHER];
d4aef858
CP
704 nick *np;
705
706 if(!lua_islong(l, 1))
707 return 0;
708
709 np = getnickbynumeric(lua_tolong(l, 1));
710 if(!np)
711 return 0;
712
8566a7ed
CP
713 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
714 return lua_usepusher(l, ourpusher, np);
d4aef858
CP
715}
716
8566a7ed 717static int lua_fastgetnickbynick(lua_State *l) {
1f57d0e2
CP
718 static struct lua_pusher *ourpusher[MAX_PUSHER];
719 nick *np;
720
8566a7ed 721 if(!lua_isstring(l, 1))
1f57d0e2
CP
722 return 0;
723
8566a7ed 724 np = getnickbynick((char *)lua_tostring(l, 1));
1f57d0e2
CP
725 if(!np)
726 return 0;
727
728 lua_setupnickpusher(l, 2, ourpusher, MAX_PUSHER);
729 return lua_usepusher(l, ourpusher, np);
730}
731
c0e81f9a
CP
732int channelnicklistindex, channelnicklistcount = -1;
733channel *channelnicklist;
734
735struct lua_pusher *channelnickpusher[MAX_PUSHER];
736
737static int lua_getnextchannick(lua_State *l) {
738 nick *np;
739
740 do {
741 channelnicklistindex++;
742
743 if(channelnicklistindex >= channelnicklistcount)
744 return 0;
745 } while((channelnicklist->users->content[channelnicklistindex] == nouser) || !(np = getnickbynumeric(channelnicklist->users->content[channelnicklistindex])));
746
747 return lua_usepusher(l, channelnickpusher, np);
748}
749
750static int lua_getfirstchannick(lua_State *l) {
751 if(!lua_isstring(l, 1))
752 return 0;
753
754 channelnicklist = findchannel((char *)lua_tostring(l, 1));
755 if(!channelnicklist|| !channelnicklist->users)
756 return 0;
757
758 channelnicklistindex = -1;
759 channelnicklistcount = channelnicklist->users->hashsize;
760
761 lua_setupnickpusher(l, 2, channelnickpusher, MAX_PUSHER);
762
763 return lua_getnextchannick(l);
764}
765
1f57d0e2
CP
766static int lua_nickonchan(lua_State *l) {
767 int success = 0;
768 if(lua_islong(l, 1) && lua_isstring(l, 2)) {
769 channel *cp = findchannel((char *)lua_tostring(l, 2));
770 if(cp && cp->users) {
771 unsigned long *lp = getnumerichandlefromchanhash(cp->users, lua_tolong(l, 1));
772 if(lp)
773 success = 1;
774 }
775 }
776
777 lua_pushboolean(l, success);
778 return 1;
779}
780
8e965b0c
CP
781static int lua_simplechanmode(lua_State *ps) {
782 channel *cp;
783 char *modes;
784 flag_t add = 0, del = ~add;
95c92529 785 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;
8e965b0c
CP
786 modechanges changes;
787
788 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
789 LUA_RETURN(ps, LUA_FAIL);
790
791 cp = findchannel((char *)lua_tostring(ps, 1));
792 if(!cp)
793 LUA_RETURN(ps, LUA_FAIL);
794
795 modes = (char *)lua_tostring(ps, 2);
796 if(!modes)
797 LUA_RETURN(ps, LUA_FAIL);
798
799 if(setflags(&add, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
800 LUA_RETURN(ps, LUA_FAIL);
801
802 if(setflags(&del, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE)
803 LUA_RETURN(ps, LUA_FAIL);
804
805 localsetmodeinit(&changes, cp, lua_nick);
806 localdosetmode_simple(&changes, add, ~del);
807 localsetmodeflush(&changes, 1);
808
809 LUA_RETURN(ps, LUA_OK);
810}
811
524fb1bd
CP
812static int lua_sethost(lua_State *ps) {
813 char *ident, *host;
814 nick *np;
815
816 if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3))
817 LUA_RETURN(ps, LUA_FAIL);
818
819 np = getnickbynumeric(lua_tolong(ps, 1));
820 if(!np)
821 LUA_RETURN(ps, LUA_FAIL);
822
823 ident = (char *)lua_tostring(ps, 2);
824 host = (char *)lua_tostring(ps, 3);
825 if(!lua_lineok(ident) || !lua_lineok(host))
826 LUA_RETURN(ps, LUA_FAIL);
827
828 sethostuser(np, ident, host);
829
830 LUA_RETURN(ps, LUA_OK);
831}
832
8e8b814d
CP
833static int lua_getvisiblehostmask(lua_State *l) {
834 nick *np;
835 char buf[HOSTLEN+USERLEN+NICKLEN+REALLEN+10];
836
837 if(!lua_islong(l, 1))
838 return 0;
839
840 np = getnickbynumeric(lua_tolong(l, 1));
841 if(!np)
842 return 0;
843
844 lua_pushstring(l, visiblehostmask(np, buf));
845 return 1;
846}
847
2da56f0d
CP
848void lua_registercommands(lua_State *l) {
849 lua_register(l, "irc_smsg", lua_smsg);
850 lua_register(l, "irc_skill", lua_skill);
851
852 lua_register(l, "chanmsg", lua_chanmsg);
2da56f0d 853 lua_register(l, "versioninfo", lua_versioninfo);
6269435f 854 lua_register(l, "basepath", lua_basepath);
d324e17b 855 lua_register(l, "botnick", lua_botnick);
2da56f0d
CP
856
857 lua_register(l, "irc_report", lua_chanmsg);
858 lua_register(l, "irc_ctcp", lua_ctcp);
859 lua_register(l, "irc_kill", lua_kill);
511316a4
CP
860 lua_register(l, "irc_kick", lua_kick);
861 lua_register(l, "irc_invite", lua_invite);
2da56f0d 862 lua_register(l, "irc_gline", lua_gline);
2da56f0d
CP
863 lua_register(l, "irc_counthost", lua_counthost);
864 lua_register(l, "irc_getuserbyauth", lua_getuserbyauth);
865 lua_register(l, "irc_notice", lua_noticecmd);
47990928 866 lua_register(l, "irc_privmsg", lua_privmsgcmd);
2da56f0d
CP
867 lua_register(l, "irc_opchan", lua_opchan);
868 lua_register(l, "irc_voicechan", lua_voicechan);
ebe20bb8
CP
869 lua_register(l, "irc_chanfix", lua_chanfix);
870 lua_register(l, "irc_clearmode", lua_clearmode);
46751959 871 lua_register(l, "irc_ban", lua_ban);
d6998bd1 872 lua_register(l, "irc_deopchan", lua_deopchan);
d0d1e2a3
CP
873 lua_register(l, "irc_topic", lua_topic);
874
d0d1e2a3
CP
875 lua_register(l, "irc_getfirstnick", lua_getfirstnick);
876 lua_register(l, "irc_getnextnick", lua_getnextnick);
2da56f0d
CP
877
878 lua_register(l, "irc_getnickchans", lua_getnickchans);
4561a594 879 lua_register(l, "irc_getnickchanindex", lua_getnickchanindex);
8ac8cd09 880 lua_register(l, "irc_getnickchancount", lua_getnickchancount);
c5706d5b 881
d0d1e2a3
CP
882 lua_register(l, "irc_getuserchanmodes", lua_getuserchanmodes);
883
c0e81f9a
CP
884 lua_register(l, "irc_getfirstchannick", lua_getfirstchannick);
885 lua_register(l, "irc_getnextchannick", lua_getnextchannick);
c5706d5b 886
2da56f0d 887 lua_register(l, "irc_gethostusers", lua_gethostusers);
46751959 888 lua_register(l, "irc_getnickcountry", lua_getnickcountry);
ec91b2e4
CP
889
890 lua_register(l, "irc_getfirstchan", lua_getfirstchan);
891 lua_register(l, "irc_getnextchan", lua_getnextchan);
c0d574fa 892 lua_register(l, "irc_getusermodes", lua_getusermodes);
1f57d0e2
CP
893 lua_register(l, "irc_nickonchan", lua_nickonchan);
894
895 lua_register(l, "irc_fastgetnickbynumeric", lua_fastgetnickbynumeric);
8566a7ed
CP
896 lua_register(l, "irc_fastgetnickbynick", lua_fastgetnickbynick);
897 lua_register(l, "irc_fastgetchaninfo", lua_fastgetchaninfo);
8e965b0c 898
8e8b814d
CP
899 lua_register(l, "irc_getvisiblehostmask", lua_getvisiblehostmask);
900
8e965b0c 901 lua_register(l, "irc_simplechanmode", lua_simplechanmode);
524fb1bd 902 lua_register(l, "irc_sethost", lua_sethost);
2da56f0d
CP
903}
904
905/* --- */
906
907static int lua_smsg(lua_State *ps) {
908 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
909 LUA_RETURN(ps, LUA_FAIL);
910
911 LUA_RETURN(ps, lua_cmsg((char *)lua_tostring(ps, 2), "%s", lua_tostring(ps, 1)));
912}
913
914static int lua_skill(lua_State *ps) {
915 const char *n, *msg;
916 nick *np;
917
918 if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2))
919 LUA_RETURN(ps, LUA_FAIL);
920
921 n = lua_tostring(ps, 1);
922 msg = lua_tostring(ps, 2);
923
924 np = getnickbynick(n);
925 if(!np)
926 LUA_RETURN(ps, LUA_FAIL);
927
928 if(IsOper(np) || IsService(np) || IsXOper(np))
929 LUA_RETURN(ps, LUA_FAIL);
930
931 if(!lua_lineok(msg))
932 LUA_RETURN(ps, LUA_FAIL);
933
934 killuser(lua_nick, np, "%s", msg);
935
936 LUA_RETURN(ps, LUA_OK);
937}
938
30a59b87 939#define PUSHER_STRING 1
eebdff1f 940#define PUSHER_REALNAME 2
30a59b87
CP
941#define PUSHER_IP 3
942#define PUSHER_LONG 4
eebdff1f
CP
943#define PUSHER_HOSTNAME 5
944#define PUSHER_SSTRING 6
ec91b2e4
CP
945#define PUSHER_TOTALUSERS 7
946#define PUSHER_TOPIC 8
de2bb012 947#define PUSHER_UMODES 9
f6a3d1f7 948#define PUSHER_COUNTRY 10
8566a7ed
CP
949#define PUSHER_REALUSERS 11
950#define PUSHER_CHANMODES 12
951#define PUSHER_TIMESTAMP 13
e0a5b7b5 952#define PUSHER_STRING_INDIRECT 14
30a59b87
CP
953
954void lua_initnickpusher(void) {
955 int i = 0;
956
957#define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
f6a3d1f7 958#define PUSH_NICKPUSHER_CUSTOM(F2, custom) nickpusher[i].argtype = F2; nickpusher[i].structname = custom; nickpusher[i].offset = 0; i++;
30a59b87
CP
959
960 PUSH_NICKPUSHER(PUSHER_STRING, nick);
961 PUSH_NICKPUSHER(PUSHER_STRING, ident);
eebdff1f
CP
962 PUSH_NICKPUSHER(PUSHER_HOSTNAME, host);
963 PUSH_NICKPUSHER(PUSHER_REALNAME, realname);
e0a5b7b5 964 PUSH_NICKPUSHER(PUSHER_STRING_INDIRECT, authname);
526e7c1d 965 PUSH_NICKPUSHER(PUSHER_IP, ipnode);
30a59b87 966 PUSH_NICKPUSHER(PUSHER_LONG, numeric);
de2bb012
CP
967 PUSH_NICKPUSHER(PUSHER_LONG, timestamp);
968 PUSH_NICKPUSHER(PUSHER_LONG, accountts);
969 PUSH_NICKPUSHER(PUSHER_UMODES, umodes);
f6a3d1f7 970 PUSH_NICKPUSHER_CUSTOM(PUSHER_COUNTRY, "country");
30a59b87 971
ebdfcaa9 972 nickpushercount = i;
30a59b87
CP
973 nickpusher[i].argtype = 0;
974}
975
4f556cb0 976void lua_setuppusher(struct lua_pusher *pusherlist, lua_State *l, int index, struct lua_pusher **lp, int max, int pcount) {
30a59b87 977 int current = 0;
30a59b87
CP
978
979 if(max > 0)
980 lp[0] = NULL;
981
533af02d 982 if(!lua_istable(l, index) || (max < 2))
30a59b87
CP
983 return;
984
985 lua_pushnil(l);
986
987 max--;
988
533af02d 989 while(lua_next(l, index)) {
ebdfcaa9
CP
990 if(lua_isint(l, -1)) {
991 int index = lua_toint(l, -1);
992 if((index >= 0) && (index < pcount))
993 lp[current++] = &pusherlist[index];
30a59b87
CP
994 }
995
996 lua_pop(l, 1);
997
998 if(current == max)
999 break;
1000 }
1001
1002 lp[current] = NULL;
1003}
1004
4f556cb0 1005int lua_usepusher(lua_State *l, struct lua_pusher **lp, void *np) {
1f38b1d7
CP
1006 int i = 0;
1007
30a59b87
CP
1008 while(*lp) {
1009 void *offset = (void *)np + (*lp)->offset;
1010
30a59b87
CP
1011 switch((*lp)->argtype) {
1012 case PUSHER_STRING:
1013 lua_pushstring(l, (char *)offset);
1014 break;
e0a5b7b5
CP
1015 case PUSHER_STRING_INDIRECT:
1016 lua_pushstring(l, *(char **)offset);
1017 break;
eebdff1f
CP
1018 case PUSHER_HOSTNAME:
1019 lua_pushstring(l, (*(host **)offset)->name->content);
1020 break;
1021 case PUSHER_REALNAME:
1022 lua_pushstring(l, (*(realname **)offset)->name->content);
1023 break;
30a59b87 1024 case PUSHER_SSTRING:
ec91b2e4 1025 lua_pushstring(l, (*((sstring **)offset))->content);
30a59b87
CP
1026 break;
1027 case PUSHER_LONG:
1028 lua_pushlong(l, *((long *)offset));
1029 break;
8566a7ed
CP
1030 case PUSHER_TIMESTAMP:
1031 lua_pushlong(l, (*((channel **)offset))->timestamp);
1032 break;
30a59b87 1033 case PUSHER_IP:
1c7f0e03 1034 lua_pushstring(l, IPtostr((*((patricia_node_t **)offset))->prefix->sin));
30a59b87 1035 break;
ec91b2e4
CP
1036 case PUSHER_TOTALUSERS:
1037 lua_pushint(l, (*((channel **)offset))->users->totalusers);
1038 break;
8566a7ed
CP
1039 case PUSHER_CHANMODES:
1040 lua_pushstring(l, printallmodes(*((channel **)offset)));
1041 break;
1042 case PUSHER_REALUSERS:
1043 {
1044 channel *cp = *((channel **)offset);
1045 nick *np2;
1046 int i, currentusers = countuniquehosts(cp);
1047 for(i=0;i<cp->users->hashsize;i++) {
1048 if(cp->users->content[i]==nouser)
1049 continue;
1050
1051 if((np2=getnickbynumeric(cp->users->content[i]))==NULL) {
16739dbe 1052 Error("lua", ERR_ERROR, "Found unknown numeric %lu on channel %s", cp->users->content[i], cp->index->name->content);
8566a7ed
CP
1053 continue;
1054 }
1055
1056 if (IsXOper(np2) || IsService(np2))
1057 currentusers--;
1058 }
1059 lua_pushint(l, currentusers);
1060 }
1061 break;
de2bb012
CP
1062 case PUSHER_UMODES:
1063 lua_pushstring(l, printflags(*((flag_t *)offset), umodeflags));
1064 break;
ec91b2e4
CP
1065 case PUSHER_TOPIC:
1066 if((*((channel **)offset))->topic) {
1067 lua_pushstring(l, (*((channel **)offset))->topic->content);
1068 } else {
1069 lua_pushnil(l);
1070 }
1071 break;
f6a3d1f7
CP
1072 case PUSHER_COUNTRY:
1073 if(geoipext < 0) {
1074 lua_pushint(l, -1);
1075 } else {
1076 lua_pushint(l, (long)((nick *)offset)->exts[geoipext]);
1077 }
1078 break;
30a59b87
CP
1079 }
1080
1f38b1d7 1081 i++;
30a59b87
CP
1082 lp++;
1083 }
1f38b1d7
CP
1084
1085 return i;
30a59b87 1086}
24da5817 1087
ec91b2e4
CP
1088void lua_initchanpusher(void) {
1089 int i = 0;
1090
1091#define PUSH_CHANPUSHER(F2, O2, N2) chanpusher[i].argtype = F2; chanpusher[i].structname = N2; chanpusher[i].offset = offsetof(chanindex, O2); i++;
1092
1093 PUSH_CHANPUSHER(PUSHER_SSTRING, name, "name");
1094 PUSH_CHANPUSHER(PUSHER_TOTALUSERS, channel, "totalusers");
1095 PUSH_CHANPUSHER(PUSHER_TOPIC, channel, "topic");
8566a7ed
CP
1096 PUSH_CHANPUSHER(PUSHER_REALUSERS, channel, "realusers");
1097 PUSH_CHANPUSHER(PUSHER_TIMESTAMP, channel, "timestamp");
1098 PUSH_CHANPUSHER(PUSHER_CHANMODES, channel, "modes");
ec91b2e4 1099
ebdfcaa9 1100 chanpushercount = i;
ec91b2e4
CP
1101 chanpusher[i].argtype = 0;
1102}