X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/ba436ecf7343064507ea0a06fa8df5ae4984a472..211567363bd8bfbd70cef81e4208ea02d49ebb55:/lua/lualocal.c diff --git a/lua/lualocal.c b/lua/lualocal.c index 83204f16..2d519e55 100644 --- a/lua/lualocal.c +++ b/lua/lualocal.c @@ -13,14 +13,14 @@ void lua_localnickhandler(nick *target, int type, void **args); void lua_reconnectlocal(void *arg); -static int lua_registerlocaluser(lua_State *ps) { - nick *np; +static int lua_registerlocaluserid(lua_State *ps) { lua_list *l; lua_localnick *ln; char *nickname, *ident, *hostname, *realname, *account; flag_t modes = 0; + long userid; - if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4) || !lua_isstring(ps, 5) || !lua_isstring(ps, 6) || !lua_isfunction(ps, 7)) + if(!lua_isstring(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4) || !lua_isstring(ps, 5) || !lua_isstring(ps, 7) || !lua_isfunction(ps, 8)) return 0; nickname = (char *)lua_tostring(ps, 1); @@ -28,8 +28,13 @@ static int lua_registerlocaluser(lua_State *ps) { hostname = (char *)lua_tostring(ps, 3); realname = (char *)lua_tostring(ps, 4); account = (char *)lua_tostring(ps, 5); + if(lua_islong(ps, 6)) { + userid = lua_tolong(ps, 6); + } else { + userid = 0; + } - setflags(&modes, UMODE_ALL, (char *)lua_tostring(ps, 6), umodeflags, REJECT_NONE); + setflags(&modes, UMODE_ALL, (char *)lua_tostring(ps, 7), umodeflags, REJECT_NONE); if(!lua_lineok(nickname) || !lua_lineok(ident) || !lua_lineok(hostname) || !lua_lineok(realname) || !lua_lineok(account)) return 0; @@ -38,15 +43,15 @@ static int lua_registerlocaluser(lua_State *ps) { if(!l) return 0; - ln = (lua_localnick *)malloc(sizeof(lua_localnick)); + ln = (lua_localnick *)luamalloc(sizeof(lua_localnick)); if(!ln) return 0; ln->reconnect = NULL; - ln->nick = registerlocaluser(nickname, ident, hostname, realname, account, modes, &lua_localnickhandler); + ln->nick = registerlocaluserflags(nickname, ident, hostname, realname, account, userid, 0, modes, &lua_localnickhandler); if(!ln->nick) { - free(ln); + luafree(ln); return 0; } @@ -55,7 +60,7 @@ static int lua_registerlocaluser(lua_State *ps) { ln->next = l->nicks; l->nicks = ln; - lua_pushlong(ps, np->numeric); + lua_pushlong(ps, ln->nick->numeric); return 1; } @@ -68,7 +73,7 @@ void lua_freelocalnick(lua_State *ps, lua_localnick *l, char *quitm) { luaL_unref(ps, LUA_REGISTRYINDEX, l->handler); - free(l); + luafree(l); } int lua_getlocalnickbynick(nick *np, lua_list **rl, lua_localnick **rln) { @@ -95,13 +100,20 @@ static int lua_deregisterlocaluser(lua_State *ps) { if(!lua_islong(ps, 1)) LUA_RETURN(ps, LUA_FAIL); + numeric = lua_tolong(ps, 1); + quitm = lua_isstring(ps, 2)?(char *)lua_tostring(ps, 2):"localuser unregistered."; l = lua_listfromstate(ps); for(l2=l->nicks;l2;lp=l2,l2=l2->next) { - if(l2->nick->numeric == numeric) { - lp->next = l2->next; + if(l2->nick && l2->nick->numeric == numeric) { + if(lp) { + lp->next = l2->next; + } else { + l->nicks = l2->next; + } + lua_freelocalnick(ps, l2, quitm); LUA_RETURN(ps, LUA_OK); } @@ -113,7 +125,9 @@ static int lua_deregisterlocaluser(lua_State *ps) { void lua_deregisternicks(lua_list *l) { struct lua_localnick *ln, *pn; - for(ln=l->nicks;ln;ln=pn) { + ln = l->nicks; + l->nicks = NULL; + for(;ln;ln=pn) { pn = ln->next; lua_freelocalnick(l->l, ln, "Script unloaded."); @@ -145,6 +159,17 @@ void lua_localnickhandler(nick *target, int type, void **args) { break; + case LU_PRIVNOTICE: + np = (nick *)args[0]; + p = (char *)args[1]; + + if(!np || !p) + return; + + lua_vlpcall(l, ln, "irc_onnotice", "Ns", np, p); + + break; + case LU_CHANMSG: np = (nick *)args[0]; c = (channel *)args[1]; @@ -170,6 +195,16 @@ void lua_localnickhandler(nick *target, int type, void **args) { ln->reconnect = scheduleoneshot(time(NULL) + 1, &lua_reconnectlocal, ln); + break; + case LU_INVITE: + /* we were invited, check if someone invited us to PUBLICCHAN */ + np = (nick *)args[0]; + c = (channel *)args[1]; + + if(!c || !np || !c->index || !c->index->name) + return; + + lua_vlpcall(l, ln, "irc_oninvite", "Ns", np, c->index->name->content); break; } } @@ -203,6 +238,8 @@ static int lua_localjoin(lua_State *ps) { LUA_RETURN(ps, LUA_FAIL); chan = (char *)lua_tostring(ps, 2); + if(chan[0] != '#') + LUA_RETURN(ps, LUA_FAIL); if(!lua_lineok(chan)) LUA_RETURN(ps, LUA_FAIL); @@ -220,7 +257,7 @@ static int lua_localjoin(lua_State *ps) { static int lua_localpart(lua_State *ps) { nick *source; channel *target; - char *chan; + char *chan, *reason; if(!lua_islong(ps, 1) || !lua_isstring(ps, 2)) LUA_RETURN(ps, LUA_FAIL); @@ -233,10 +270,18 @@ static int lua_localpart(lua_State *ps) { if(!lua_lineok(chan)) LUA_RETURN(ps, LUA_FAIL); - + + if(lua_isstring(ps, 3)) { + reason = (char *)lua_tostring(ps, 3); + if(!lua_lineok(reason)) + LUA_RETURN(ps, LUA_FAIL); + } else { + reason = NULL; + } + target = findchannel(chan); if(target) { - localpartchannel(source, target); + localpartchannel(source, target, reason); } else { LUA_RETURN(ps, LUA_FAIL); } @@ -296,56 +341,332 @@ static int lua_localnotice(lua_State *ps) { LUA_RETURN(ps, LUA_OK); } -static int lua_localovmode(lua_State *ps) { - char *mode; - nick *source, *target; - channel *chan; - int add, realmode; +static int lua_localprivmsg(lua_State *ps) { + char *msg; + nick *source; + nick *target; - if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isboolean(ps, 3) || !lua_isstring(ps, 4) || !lua_islong(ps, 5)) + if(!lua_islong(ps, 1) || !lua_islong(ps, 2) || !lua_isstring(ps, 3)) LUA_RETURN(ps, LUA_FAIL); source = getnickbynumeric(lua_tolong(ps, 1)); if(!source) LUA_RETURN(ps, LUA_FAIL); - chan = findchannel((char *)lua_tostring(ps, 2)); + target = getnickbynumeric(lua_tolong(ps, 2)); + if(!target) + LUA_RETURN(ps, LUA_FAIL); + + msg = (char *)lua_tostring(ps, 3); + + if(!lua_lineok(msg)) + LUA_RETURN(ps, LUA_FAIL); + + sendmessagetouser(source, target, "%s", msg); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localovmode(lua_State *l) { + nick *source; + channel *chan; + int state = 0, add = 0, realmode = 0, ignoring = 0; + modechanges changes; + + if(!lua_islong(l, 1) || !lua_isstring(l, 2) || !lua_istable(l, 3)) + LUA_RETURN(l, LUA_FAIL); + + source = getnickbynumeric(lua_tolong(l, 1)); + if(!source) + LUA_RETURN(l, LUA_FAIL); + + chan = findchannel((char *)lua_tostring(l, 2)); if(!chan) + LUA_RETURN(l, LUA_FAIL); + + localsetmodeinit(&changes, chan, source); + + lua_pushnil(l); + + while(lua_next(l, 3)) { + if(state == 0) { + ignoring = 0; + + if(!lua_isboolean(l, -1)) { + ignoring = 1; + } else { + add = (int)lua_toboolean(l, -1); + } + } else if((state == 1) && !ignoring) { + if(!lua_isstring(l, -1)) { + ignoring = 1; + } else { + char *mode = (char *)lua_tostring(l, -1); + if((*mode == 'o') && add) { + realmode = MC_OP; + } else if (*mode == 'o') { + realmode = MC_DEOP; + } else if((*mode == 'v') && add) { + realmode = MC_VOICE; + } else if (*mode == 'v') { + realmode = MC_DEVOICE; + } else { + ignoring = 1; + } + } + } else if((state == 2) && !ignoring) { + if(lua_islong(l, -1)) { + nick *target = getnickbynumeric(lua_tolong(l, -1)); + if(target) + localdosetmode_nick(&changes, target, realmode); + } + } + + lua_pop(l, 1); + + state = (state + 1) % 3; + } + + localsetmodeflush(&changes, 1); + + LUA_RETURN(l, LUA_OK); +} + +static int lua_localumodes(lua_State *ps) { + nick *np; + char *modes; + flag_t newmodes = 0; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2)) LUA_RETURN(ps, LUA_FAIL); - add = (int)lua_toboolean(ps, 3); - mode = (char *)lua_tostring(ps, 4); + np = getnickbynumeric(lua_tolong(ps, 1)); + if(!np) + LUA_RETURN(ps, LUA_FAIL); - target = getnickbynumeric(lua_tolong(ps, 5)); - if(!target) + modes = (char *)lua_tostring(ps, 2); + + setflags(&newmodes, UMODE_ALL, modes, umodeflags, REJECT_NONE); + + localusersetumodes(np, newmodes); + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localtopic(lua_State *ps) { + nick *np; + channel *cp; + char *topic; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3)) LUA_RETURN(ps, LUA_FAIL); - if((*mode == 'o') && add) { - realmode = MC_OP; - } else if (*mode == 'o') { - realmode = MC_DEOP; - } else if((*mode == 'v') && add) { - realmode = MC_VOICE; - } else if (*mode == 'o') { - realmode = MC_DEVOICE; - } else { + np = getnickbynumeric(lua_tolong(ps, 1)); + if(!np) LUA_RETURN(ps, LUA_FAIL); - } - localsetmodes(source, chan, target, realmode); + cp = findchannel((char *)lua_tostring(ps, 2)); + if(!cp) + LUA_RETURN(ps, LUA_FAIL); + + topic = (char *)lua_tostring(ps, 3); + if(!topic || !lua_lineok(topic)) + LUA_RETURN(ps, LUA_FAIL); + + localsettopic(np, cp, topic); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localban(lua_State *ps) { + channel *cp; + const char *mask; + modechanges changes; + nick *source; + + int dir = MCB_ADD; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3)) + LUA_RETURN(ps, LUA_FAIL); + + if(lua_isboolean(ps, 4) && lua_toboolean(ps, 4)) + dir = MCB_DEL; + + source = getnickbynumeric(lua_tolong(ps, 1)); + + cp = findchannel((char *)lua_tostring(ps, 2)); + if(!cp) + LUA_RETURN(ps, LUA_FAIL); + + mask = lua_tostring(ps, 3); + if(!mask || !mask[0] || !lua_lineok(mask)) + LUA_RETURN(ps, LUA_FAIL); + + localsetmodeinit(&changes, cp, source); + localdosetmode_ban(&changes, mask, dir); + localsetmodeflush(&changes, 1); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localkick(lua_State *ps) { + const char *n, *msg, *chan; + nick *source, *np; + channel *cp; + int dochecks = 1; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3) || !lua_isstring(ps, 4)) + LUA_RETURN(ps, LUA_FAIL); + + source = getnickbynumeric(lua_tolong(ps, 1)); + chan = lua_tostring(ps, 2); + n = lua_tostring(ps, 3); + msg = lua_tostring(ps, 4); + if(!source) + LUA_RETURN(ps, LUA_FAIL); + + if(lua_isboolean(ps, 4) && !lua_toboolean(ps, 4)) + dochecks = 0; + + np = getnickbynick(n); + if(!np) + LUA_RETURN(ps, LUA_FAIL); + + if(dochecks && (IsOper(np) || IsXOper(np) || IsService(np))) + LUA_RETURN(ps, LUA_FAIL); + + cp = findchannel((char *)chan); + if(!cp) + LUA_RETURN(ps, LUA_FAIL); + + if(!lua_lineok(msg)) + LUA_RETURN(ps, LUA_FAIL); + + localkickuser(source, cp, np, msg); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localrename(lua_State *ps) { + nick *np; + char *changeto; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) ) + LUA_RETURN(ps, LUA_FAIL); + + np = getnickbynumeric(lua_tolong(ps, 1)); + changeto = (char *)lua_tostring(ps, 2); + + if(!lua_lineok(changeto)) + LUA_RETURN(ps, LUA_FAIL); + + renamelocaluser(np, changeto); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localwallusers(lua_State *ps) { + char *msg; + nick *source; + char senderstr[6]; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2)) + LUA_RETURN(ps, LUA_FAIL); + + source = getnickbynumeric(lua_tolong(ps, 1)); + if(!source) + LUA_RETURN(ps, LUA_FAIL); + + msg = (char *)lua_tostring(ps, 2); + + if(!lua_lineok(msg)) + LUA_RETURN(ps, LUA_FAIL); + + longtonumeric2(source->numeric,5,senderstr); + irc_send("%s WU :%s", senderstr, msg); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localwallops(lua_State *ps) { + char *msg; + nick *source; + char senderstr[6]; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2)) + LUA_RETURN(ps, LUA_FAIL); + + source = getnickbynumeric(lua_tolong(ps, 1)); + if(!source) + LUA_RETURN(ps, LUA_FAIL); + + msg = (char *)lua_tostring(ps, 2); + + if(!lua_lineok(msg)) + LUA_RETURN(ps, LUA_FAIL); + + longtonumeric2(source->numeric,5,senderstr); + irc_send("%s WA :%s", senderstr, msg); + + LUA_RETURN(ps, LUA_OK); +} + +static int lua_localsimplechanmode(lua_State *ps) { + nick *source; + channel *cp; + char *modes; + flag_t add = 0, del = ~add; + 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; + modechanges changes; + + if(!lua_islong(ps, 1) || !lua_isstring(ps, 2) || !lua_isstring(ps, 3)) + LUA_RETURN(ps, LUA_FAIL); + + source = getnickbynumeric(lua_tolong(ps, 1)); + if(!source) + LUA_RETURN(ps, LUA_FAIL); + + cp = findchannel((char *)lua_tostring(ps, 2)); + if(!cp) + LUA_RETURN(ps, LUA_FAIL); + + modes = (char *)lua_tostring(ps, 3); + if(!modes) + LUA_RETURN(ps, LUA_FAIL); + + if(setflags(&add, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE) + LUA_RETURN(ps, LUA_FAIL); + + if(setflags(&del, permitted, modes, cmodeflags, REJECT_DISALLOWED|REJECT_UNKNOWN) != REJECT_NONE) + LUA_RETURN(ps, LUA_FAIL); + + localsetmodeinit(&changes, cp, source); + localdosetmode_simple(&changes, add, ~del); + localsetmodeflush(&changes, 1); LUA_RETURN(ps, LUA_OK); } void lua_registerlocalcommands(lua_State *l) { - lua_register(l, "irc_localregisteruser", lua_registerlocaluser); + lua_register(l, "irc_localregisteruserid", lua_registerlocaluserid); lua_register(l, "irc_localderegisteruser", lua_deregisterlocaluser); lua_register(l, "irc_localjoin", lua_localjoin); lua_register(l, "irc_localpart", lua_localpart); lua_register(l, "irc_localchanmsg", lua_localchanmsg); lua_register(l, "irc_localnotice", lua_localnotice); + lua_register(l, "irc_localprivmsg", lua_localprivmsg); lua_register(l, "irc_localovmode", lua_localovmode); + lua_register(l, "irc_localtopic", lua_localtopic); + + lua_register(l, "irc_localban", lua_localban); + lua_register(l, "irc_localkick", lua_localkick); + lua_register(l, "irc_localumodes", lua_localumodes); + + lua_register(l, "irc_localrename", lua_localrename); + + lua_register(l, "irc_localwallusers", lua_localwallusers); + lua_register(l, "irc_localwallops", lua_localwallops); + lua_register(l, "irc_localsimplechanmode", lua_localsimplechanmode); }