From 4d025dde856cb5de5047eee1a2d39c5c5eb728af Mon Sep 17 00:00:00 2001 From: Aaron Blakely Date: Fri, 23 Feb 2024 19:57:59 -0600 Subject: [PATCH] current --- lib/channel.h | 6 +++ lib/events.h | 1 + lib/irc.h | 10 ++-- lib/module.h | 2 + lib/timers.h | 2 + mods/chanop/Makefile | 7 +++ mods/chanop/chanop.c | 108 +++++++++++++++++++++++++++++++++++++++++++ mods/uptime/uptime.c | 10 ++-- src/channel.c | 71 ++++++++++++++++++++++++++++ src/events.c | 15 ++---- src/irc.c | 42 +++++++++++++++-- src/main.c | 20 ++++---- src/timers.c | 2 +- xbot.cfg | 4 +- 14 files changed, 263 insertions(+), 37 deletions(-) create mode 100755 mods/chanop/Makefile create mode 100755 mods/chanop/chanop.c diff --git a/lib/channel.h b/lib/channel.h index d177845..b630d65 100755 --- a/lib/channel.h +++ b/lib/channel.h @@ -50,6 +50,8 @@ struct channel struct user *users; }; +extern struct channel *channels[60]; + void add_channel(char *name); void remove_channel(char *name); void add_user_to_channel(char *user, char *host, char *chan); @@ -61,6 +63,10 @@ void update_server(char *nick, char *server); void update_realname(char *nick, char *real_name); void user_quit(char *nick); void set_realname(char *nick, char *real_name); +struct user *get_user(char *nick); + +MY_API char *get_user_host(char *nick); +MY_API char *get_user_user(char *nick); #ifdef _WIN32 MY_API BOOL is_op(char *chan, char *nick); diff --git a/lib/events.h b/lib/events.h index 1e9df58..6d03bc0 100755 --- a/lib/events.h +++ b/lib/events.h @@ -34,6 +34,7 @@ struct handler struct ev_handler *evhands; }; +extern struct handler *handlers[512]; void init_events(); MY_API int add_handler(char *type, void *handler); diff --git a/lib/irc.h b/lib/irc.h index f00368b..7a2989a 100755 --- a/lib/irc.h +++ b/lib/irc.h @@ -13,6 +13,8 @@ #include #endif +#define OUTBUF_SIZE 60000 +#define INBUF_SIZE 60000 struct irc_conn { @@ -29,8 +31,8 @@ struct irc_conn char real_name[512]; // I/O Buffers - char out[4096]; - char in[4096]; + char *out; + char *in; }; typedef struct handler event_handler; @@ -53,7 +55,9 @@ MY_API void irc_privmsg(struct irc_conn *bot, char *to, char *fmt, ...); MY_API void irc_raw(struct irc_conn *bot, char *fmt, ...); MY_API void irc_join(struct irc_conn *bot, char *channel); MY_API void irc_part(struct irc_conn *bot, char *channel, char *reason); - +MY_API void irc_ban(struct irc_conn *bot, char *channel, char *nick); +MY_API void irc_kick(struct irc_conn *bot, char *channel, char *user, char *reason); +MY_API void irc_mode(struct irc_conn *bot, char *channel, char *mode); void irc_parse_raw(struct irc_conn *bot, char *raw); diff --git a/lib/module.h b/lib/module.h index 37e0825..e3a114a 100755 --- a/lib/module.h +++ b/lib/module.h @@ -32,6 +32,8 @@ struct mods { struct module *modules; }; +extern struct mods *mods; + void init_mods(); void load_module(struct irc_conn *bot, char *where, char *stype, char *file); void unload_module(struct irc_conn *bot, char *where, char *file); diff --git a/lib/timers.h b/lib/timers.h index 60288d2..7aac79f 100755 --- a/lib/timers.h +++ b/lib/timers.h @@ -37,6 +37,8 @@ struct timers struct timer *timers; }; +extern struct timers *timers;; + void init_timers(); MY_API int add_timer(struct irc_conn *bot, int interval, int repeat, void *handler, void *data); diff --git a/mods/chanop/Makefile b/mods/chanop/Makefile new file mode 100755 index 0000000..6838bd9 --- /dev/null +++ b/mods/chanop/Makefile @@ -0,0 +1,7 @@ +CC=gcc +CFLAGS=-fPIC -I../../lib +OBJ=../chanop.so + +main: + $(CC) -shared -o $(OBJ) $(CFLAGS) ./chanop.c + @echo "All Done!" diff --git a/mods/chanop/chanop.c b/mods/chanop/chanop.c new file mode 100755 index 0000000..6b3b03e --- /dev/null +++ b/mods/chanop/chanop.c @@ -0,0 +1,108 @@ +#include "channel.h" +#define MY_DLL_EXPORTS 1 + +#include "util.h" +#include "irc.h" +#include "events.h" +#include "module.h" +#include +#include +#include + +#ifdef _WIN32 +#include +BOOL hasAccess(char *user, char *chan) +{ + if (is_op(chan, user) || is_halfop(chan, user)) + { + return TRUE; + } + else + { + return FALSE; + } +} +#else +#include +bool hasAccess(char *user, char *chan) +{ + if (is_op(chan, user) || is_halfop(chan, user)) + { + return true; + } + else + { + return false; + } +} +#endif + +MY_API void chanop_privmsg_handler(struct irc_conn *bot, char *user, char *host, char *chan, const char *text) +{ + char *nick; + char *buf = (char *)malloc(sizeof(char *) * 500); + int sn = 1; + + if (strstr(text, "!kb") != NULL) + { + if (!hasAccess(user, chan)) + goto NO_ACCESS; + + nick = skip((char *)text, ' '); + sprintf(buf, "Requested by %s", user); + + irc_ban(bot, chan, nick); + irc_kick(bot, chan, nick, buf); + } + else if (strstr(text, "!op") != NULL) + { + if (!hasAccess(user, chan)) + goto NO_ACCESS; + + nick = skip((char *)text, ' '); + irc_raw(bot, "MODE %s +o %s", chan, nick); + } + else if (strstr(text, "!deop") != NULL) + { + if (!hasAccess(user, chan)) + goto NO_ACCESS; + + nick = skip((char *)text, ' '); + irc_raw(bot, "MODE %s -o %s", chan, nick); + } + else if (strstr(text, "!voice") != NULL) + { + if (!hasAccess(user, chan)) + goto NO_ACCESS; + + nick = skip((char *)text, ' '); + irc_raw(bot, "MODE %s +v %s", chan, nick); + } + else if (strstr(text, "!devoice") != NULL) + { + if (!hasAccess(user, chan)) + goto NO_ACCESS; + + nick = skip((char *)text, ' '); + irc_raw(bot, "MODE %s -v %s", chan, nick); + } + + sn = 0; + +NO_ACCESS: + if (sn) + irc_notice(bot, user, "You do not have access to use that command in %s", chan); + free(buf); +} + +MY_API void mod_init() +{ + register_module("chanop", "Aaron Blakely", "v0.1", "Channel Operator module"); + add_handler(PRIVMSG_CHAN, chanop_privmsg_handler); +} + +MY_API void mod_unload() +{ + unregister_module("chanop"); + del_handler(PRIVMSG_CHAN, chanop_privmsg_handler); +} diff --git a/mods/uptime/uptime.c b/mods/uptime/uptime.c index 784c032..d57977d 100755 --- a/mods/uptime/uptime.c +++ b/mods/uptime/uptime.c @@ -10,7 +10,6 @@ #ifdef _WIN32 #define BUFFER_SIZE 512 #include -DWORD startTick; void parseUptime(const char *output, struct irc_conn *bot, const char *where) { const char *keyword = "Statistics since "; @@ -140,12 +139,13 @@ char *executeCommand(const char *command) MY_API void up(struct irc_conn *bot, char *user, char *host, char *chan, char *text) { #ifdef _WIN32 - const char *command = "net statistics server"; - char *output = executeCommand(command); + char *output; if (!strcmp(text, "!uptime")) { + output = executeCommand("net statistics server"); parseUptime(output, bot, chan); + free(output); } #else @@ -165,10 +165,6 @@ MY_API void up(struct irc_conn *bot, char *user, char *host, char *chan, char *t MY_API void mod_init() { -#ifdef _WIN32 - startTick = GetTickCount(); -#endif - register_module("uptime", "Aaron Blakely", "v0.1", "Uptime module"); printf("installing up handler\n"); add_handler(PRIVMSG_CHAN, up); diff --git a/src/channel.c b/src/channel.c index 0727bd1..8f2efe1 100755 --- a/src/channel.c +++ b/src/channel.c @@ -49,9 +49,28 @@ void remove_channel(char *name) } } +struct user *get_user(char *nick) +{ + int i, j; + + for (i = 0; i < chan_count; i++) + { + for (j = 0; j < channels[i]->user_count; j++) + { + if (!strcmp(channels[i]->users[j].nick, nick)) + { + return &channels[i]->users[j]; + } + } + } + + return NULL; +} + void add_user_to_channel(char *user, char *host, char *chan) { int i; + struct user *u, *uc; #ifdef _WIN32 BOOL is_op, is_voice, is_halfop, is_owner, is_admin; @@ -107,6 +126,21 @@ void add_user_to_channel(char *user, char *host, char *chan) { if (!strcmp(channels[i]->name, chan)) { + if (get_user(user) != NULL) + { + u = get_user(user); + u->is_op = is_op | is_owner | is_admin; + u->is_voice = is_voice | is_halfop | is_op | is_owner | is_admin; + u->is_halfop = is_halfop; + u->is_owner = is_owner; + u->is_admin = is_admin; + + channels[i]->users[channels[i]->user_count] = *u; + channels[i]->user_count++; + + return; + } + strlcpy(channels[i]->users[channels[i]->user_count].nick, user, 50); strlcpy(channels[i]->users[channels[i]->user_count].host, host, 256); @@ -267,6 +301,43 @@ void set_realname(char *nick, char *real_name) } } + +MY_API char *get_user_host(char *nick) +{ + int i, j; + + for (i = 0; i < chan_count; i++) + { + for (j = 0; j < channels[i]->user_count; j++) + { + if (!strcmp(channels[i]->users[j].nick, nick)) + { + return channels[i]->users[j].host; + } + } + } + + return NULL; +} + +char *get_user_user(char *nick) +{ + int i, j; + + for (i = 0; i < chan_count; i++) + { + for (j = 0; j < channels[i]->user_count; j++) + { + if (!strcmp(channels[i]->users[j].nick, nick)) + { + return channels[i]->users[j].user; + } + } + } + + return NULL; +} + #ifdef _WIN32 MY_API BOOL is_op(char *chan, char *nick) #else diff --git a/src/events.c b/src/events.c index 745dc4e..2e31abd 100755 --- a/src/events.c +++ b/src/events.c @@ -11,13 +11,8 @@ #include #endif -struct handler *privmsg_self; -struct handler *privmsg_chan; -struct handler *chan_join; -struct handler *irc_connected; - -int handlers_count = 0; struct handler *handlers[512]; +int handlers_count = 0; void init_event_type(char *type) { @@ -94,10 +89,10 @@ MY_API void del_handler(char *type, void *handler) void fire_handler(struct irc_conn *bot, char *type, ...) { va_list args; - char *usr = calloc(1, 64); - char *host = calloc(1, 512); - char *chan = calloc(1, 64); - char *text = calloc(1, 512); + char *usr; + char *host; + char *chan; + char *text; int i, j; void (*handler)(); char *cmd, *arg, *modpath; diff --git a/src/irc.c b/src/irc.c index de77489..2ae708c 100755 --- a/src/irc.c +++ b/src/irc.c @@ -68,6 +68,9 @@ void irc_connect(struct irc_conn *bot) struct addrinfo hints; struct addrinfo *res, *r; + bot->in = calloc(60000, sizeof(char)); + bot->out = calloc(60000, sizeof(char)); + memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; @@ -142,9 +145,10 @@ void irc_raw(struct irc_conn *bot, char *fmt, ...) { va_list ap; char outbuf[4096]; + char *p; va_start(ap, fmt); - vsnprintf(bot->out, sizeof bot->out, fmt, ap); + vsnprintf(bot->out, OUTBUF_SIZE, fmt, ap); va_end(ap); sprintf(outbuf, "%s\r\n", bot->out); @@ -175,6 +179,29 @@ void irc_part(struct irc_conn *bot, char *chan, char *reason) irc_raw(bot, "PART %s :%s", chan, reason); } +void irc_ban(struct irc_conn *bot, char *channel, char *user) +{ + char *host = get_user_host(user); + char *un = get_user_user(user); + + irc_raw(bot, "MODE %s +b *!%s@%s", channel, un, host); +} + +void irc_kick(struct irc_conn *bot, char *channel, char *user, char *reason) +{ + if (!reason) + { + reason = ""; + } + + irc_raw(bot, "KICK %s %s :%s", channel, user, reason); +} + +void irc_mode(struct irc_conn *bot, char *channel, char *mode) +{ + irc_raw(bot, "MODE %s %s", channel, mode); +} + void irc_ctcp(struct irc_conn *bot, char *to, char *fmt, ...) { char msg_[4096]; @@ -192,8 +219,6 @@ void irc_parse_raw(struct irc_conn *bot, char *raw) char *user, *host, *par, *text, *chan, *nick, *nicks, *tmp; user = bot->host; - text = calloc(1, strlen(raw) + 1); - if (!raw || !*raw) { return; @@ -334,14 +359,20 @@ void irc_parse_raw(struct irc_conn *bot, char *raw) while (nick) { - add_user_to_channel(nick, "", chan); - tmp = nick; if (nick[0] == '@' || nick[0] == '+' || nick[0] == '%' || nick[0] == '~' || nick[0] == '&') { tmp++; } + if (get_user(tmp)) + { + nick = strtok(NULL, " "); + continue; + } + + add_user_to_channel(nick, "", chan); + irc_raw(bot, "WHO %s", tmp); nick = strtok(NULL, " "); } @@ -376,4 +407,5 @@ void irc_parse_raw(struct irc_conn *bot, char *raw) fire_handler(bot, NICK_MYSELF, user, text); } } + } diff --git a/src/main.c b/src/main.c index 762b439..d20fc16 100755 --- a/src/main.c +++ b/src/main.c @@ -23,7 +23,6 @@ #include #endif - static time_t trespond; int main() @@ -32,15 +31,15 @@ int main() fd_set rd; struct irc_conn bot; struct timeval tv; - struct timeval last_ping; - char *p; - int bytesRecv; - + + bot.in = calloc(INBUF_SIZE, sizeof(char)); + bot.out = calloc(OUTBUF_SIZE, sizeof(char)); + last_ping.tv_sec = time(NULL); init_events(); @@ -54,6 +53,8 @@ int main() printf("Connecting to %s...\n", bot.host); irc_connect(&bot); + trespond = time(NULL); + irc_auth(&bot); for (;;) @@ -84,7 +85,7 @@ int main() } #else n = select(fileno(bot.srv_fd) + 1, &rd, 0, 0, &tv); - if (n < 0) + if (n < 0) { if (errno == EINTR) continue; @@ -112,7 +113,7 @@ int main() #ifdef _WIN32 if (FD_ISSET(bot.srv_fd, &rd)) { - bytesRecv = recv(bot.srv_fd, bot.in, sizeof(bot.in), 0); + bytesRecv = recv(bot.srv_fd, bot.in, INBUF_SIZE, 0); if (bytesRecv == SOCKET_ERROR) { eprint("Error receiving data: %d\n", WSAGetLastError()); @@ -134,7 +135,6 @@ int main() // split bot.in into lines by \r\n and parse each one - while (1) { // remove \r @@ -147,10 +147,12 @@ int main() irc_parse_raw(&bot, bot.in); memmove(bot.in, p + 1, strlen(p + 1) + 1); } + + free(p); #else if (FD_ISSET(fileno(bot.srv_fd), &rd)) { - if (fgets(bot.in, sizeof bot.in, bot.srv_fd) == NULL) + if (fgets(bot.in, INBUF_SIZE, bot.srv_fd) == NULL) { eprint("xbot: remote host closed connection\n"); return 0; diff --git a/src/timers.c b/src/timers.c index d26aebe..8ff149a 100755 --- a/src/timers.c +++ b/src/timers.c @@ -6,7 +6,7 @@ #include "util.h" #include "irc.h" -struct timers *timers;; +struct timers *timers; int delete_queue[512]; void init_timers() diff --git a/xbot.cfg b/xbot.cfg index 12326e5..c4c9945 100755 --- a/xbot.cfg +++ b/xbot.cfg @@ -3,7 +3,7 @@ bot: { verbose = 1; - nick = "X"; + nick = "_"; user = "xbot"; admin = "ab3800"; }; @@ -16,7 +16,7 @@ server: mods: { - autoload = ("autojoin", "hello", "uptime"); + autoload = ("chanop", "autojoin", "hello", "uptime"); blacklist = (); # config option for mods/autojoin.so