From: pk910 Date: Mon, 12 Sep 2011 19:40:27 +0000 (+0200) Subject: implemented event logger X-Git-Tag: v5.3~425 X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=a10a047c4b8414ecc8d20ee8e48854e3e9e4c5f7;p=NeonServV5.git implemented event logger --- diff --git a/DATABASE.txt b/DATABASE.txt index 77ba154..1448119 100644 --- a/DATABASE.txt +++ b/DATABASE.txt @@ -36,4 +36,9 @@ ALTER TABLE `bans` CHANGE `ban_owner` `ban_owner` INT( 11 ) NOT NULL; ALTER TABLE `channels` ADD `channel_exttopic` TINYINT( 1 ) NOT NULL AFTER `channel_topicmask` , ADD `channel_exttopic_topic` VARCHAR( 512 ) NOT NULL AFTER `channel_exttopic`; -ALTER TABLE `bots` ADD `max_channels` INT( 5 ) NOT NULL ; \ No newline at end of file +ALTER TABLE `bots` ADD `max_channels` INT( 5 ) NOT NULL ; + +ALTER TABLE `bot_binds` CHANGE `botid` `botclass` INT( 11 ) NOT NULL; +ALTER TABLE `bots` DROP `whoisbot` ; +ALTER TABLE `bots` DROP `bindFrom` ; + diff --git a/EventLogger.c b/EventLogger.c new file mode 100644 index 0000000..6980dab --- /dev/null +++ b/EventLogger.c @@ -0,0 +1,60 @@ + +#include "EventLogger.h" + +static struct Event *first_event = NULL, *last_event = NULL; + +struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags) { + struct Event *event = malloc(sizeof(*event)); + if (!event) + { + perror("malloc() failed"); + return NULL; + } + event->client = client; + event->user = user; + event->chan = chan; + event->event_time = time(0); + event->command = strdup(command); + char arguments[MAXLEN]; + int argpos = 0; + int i; + for(i = 0; i < argc; i++) + argpos += sprintf(arguments + argpos, "%s ", args[i]); + arguments[(argpos ? argpos-1 : 0)] = '\0'; + event->arguments = strdup(arguments); + event->flags = flags; + event->next = NULL; + if(last_event) { + last_event->next = event; + last_event = event; + } else { + last_event = event; + first_event = event; + } + return event; +} + +void logEvent(struct Event *event) { + //log! +} + +static void destroyEvent(struct Event *event) { + if(event == first_event) + first_event = event->next; + if(event == last_event) { + struct Event *last; + for(last = first_event; last; last = last->next) + if(last->next == NULL) break; + last_event = last; + } + free(event->command); + free(event->arguments); + free(event); +} + +void destroyEvents() { + time_t now = time(0); + while(first_event && now - first_event->event_time >= 60) { + destroyEvent(first_event); + } +} diff --git a/EventLogger.h b/EventLogger.h new file mode 100644 index 0000000..71da262 --- /dev/null +++ b/EventLogger.h @@ -0,0 +1,25 @@ +#ifndef _EventLogger_h +#define _EventLogger_h + +#include "main.h" +struct ClientSocket; +struct UserNode; +struct ChanNode; + +struct Event { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + time_t event_time; + char *command; + char *arguments; + unsigned int flags; /* defined in modcmd.h */ + + struct Event *next; +}; + +struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char **args, int argc, int flags); +void logEvent(struct Event *event); +void destroyEvents(); + +#endif \ No newline at end of file diff --git a/Makefile b/Makefile index 7ec8de1..0cd3b08 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ all: gcc -g -O2 ${LIBS} -c tools.c -o tools.o ${CFLAGS} gcc -g -O2 ${LIBS} -c timeq.c -o timeq.o ${CFLAGS} gcc -g -O2 ${LIBS} -c DBHelper.c -o DBHelper.o ${CFLAGS} + gcc -g -O2 ${LIBS} -c EventLogger.c -o EventLogger.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bots.c -o bots.o ${CFLAGS} gcc -g -O2 ${LIBS} -c bot_NeonServ.c -o bot_NeonServ.o ${CFLAGS} diff --git a/bot_NeonServ.c b/bot_NeonServ.c index b95cf6d..e3c990e 100644 --- a/bot_NeonServ.c +++ b/bot_NeonServ.c @@ -16,6 +16,7 @@ #include "tools.h" #include "timeq.h" #include "version.h" +#include "EventLogger.h" #define BOTID 1 @@ -62,6 +63,7 @@ static const struct default_language_entry msgtab[] = { {"NS_USERS_COUNT_MATCH", "There are \002%d\002 users in %s. (\002%d\002 matching your request)"}, {"NS_USERS_COUNT_MATCH_1", "There is \002%d\002 user in %s. (\002%d\002 matching your request)"}, {"NS_USERS_SEEN_HERE", "Here"}, + {"NS_USERS_SEEN_INVISIBLE", "Here (invisible)"}, {"NS_USERS_SEEN_NEVER", "Never"}, {"NS_USERS_STATE_SUSPENDED", "Suspended"}, {"NS_USERS_STATE_NORMAL", "Normal"}, @@ -294,7 +296,7 @@ static void start_bots() { client->botid = BOTID; client->clientid = atoi(row[7]); connect_socket(client); - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botid` = '%d'", client->clientid); + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '%d'", client->botid); res2 = mysql_use(); while ((row = mysql_fetch_row(res2)) != NULL) { if(bind_cmd_to_command(BOTID, row[0], row[1])) { diff --git a/cmd_neonserv_addban.c b/cmd_neonserv_addban.c index ca0d692..91da9f8 100644 --- a/cmd_neonserv_addban.c +++ b/cmd_neonserv_addban.c @@ -4,11 +4,12 @@ * argv[1-*] reason */ static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup); -static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *mas, char *reason); +static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mas, char *reason); struct neonserv_cmd_addban_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *mask; char *reason; }; @@ -22,6 +23,7 @@ static CMD_BIND(neonserv_cmd_addban) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->mask = strdup(argv[0]); if(argc > 1) { cache->reason = strdup(merge_argv(argv, 1, argc)); @@ -32,14 +34,14 @@ static CMD_BIND(neonserv_cmd_addban) { static USERLIST_CALLBACK(neonserv_cmd_addban_userlist_lookup) { struct neonserv_cmd_addban_cache *cache = data; - neonserv_cmd_addban_async1(cache->client, cache->textclient, cache->user, chan, cache->mask, (cache->reason ? cache->reason : "Bye.")); + neonserv_cmd_addban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, (cache->reason ? cache->reason : "Bye.")); free(cache->mask); if(cache->reason) free(cache->reason); free(cache); } -static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *mask, char *reason) { +static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, char *reason) { int match_count = 0; char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; char usermask[NICKLEN+USERLEN+HOSTLEN+3]; @@ -100,4 +102,5 @@ static void neonserv_cmd_addban_async1(struct ClientSocket *client, struct Clien } } reply(textclient, user, "NS_ADDBAN_DONE", mask, chan->name, match_count); + logEvent(event); } diff --git a/cmd_neonserv_adduser.c b/cmd_neonserv_adduser.c index ceab6cd..ffd2224 100644 --- a/cmd_neonserv_adduser.c +++ b/cmd_neonserv_adduser.c @@ -5,12 +5,13 @@ */ static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup); static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup); -static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int access); +static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int access); struct neonserv_cmd_adduser_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; int access; char *nick; }; @@ -24,9 +25,13 @@ static CMD_BIND(neonserv_cmd_adduser) { reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); return; } - if(caccess >= getChannelAccess(user, chan, 1)) { - reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); - return; + if(caccess >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } } //check own access if(argv[0][0] == '*') { @@ -35,7 +40,7 @@ static CMD_BIND(neonserv_cmd_adduser) { printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0])); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, argv[0], row[0], caccess); + neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], row[0], caccess); } else { //we need to create a new user... //but first lookup the auth to check if it really exists @@ -48,6 +53,7 @@ static CMD_BIND(neonserv_cmd_adduser) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->access = caccess; cache->nick = strdup(argv[0]); lookup_authname(argv[0], neonserv_cmd_adduser_auth_lookup, cache); @@ -59,7 +65,7 @@ static CMD_BIND(neonserv_cmd_adduser) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, caccess); + neonserv_cmd_adduser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess); } else { struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -70,6 +76,7 @@ static CMD_BIND(neonserv_cmd_adduser) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->access = caccess; cache->nick = strdup(argv[0]); get_userauth(cuser, neonserv_cmd_adduser_nick_lookup, cache); @@ -83,7 +90,7 @@ static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup) { //AUTH_DOES_NOT_EXIST reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); } else - neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->nick, auth, cache->access); + neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->nick, auth, cache->access); free(cache->nick); free(cache); } @@ -99,12 +106,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->access); + neonserv_cmd_adduser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access); free(cache->nick); free(cache); } -static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int caccess) { +static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -126,4 +133,5 @@ static void neonserv_cmd_adduser_async1(struct ClientSocket *client, struct Clie } printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chan->channel_id, userid, caccess); reply(textclient, user, "NS_ADDUSER_DONE", nick, chan->name, caccess); + logEvent(event); } diff --git a/cmd_neonserv_ban.c b/cmd_neonserv_ban.c index 50db4c4..ee43f21 100644 --- a/cmd_neonserv_ban.c +++ b/cmd_neonserv_ban.c @@ -3,11 +3,12 @@ * argv[0-*] nick[,*auth[,*!*@mask[...]]] */ static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup); -static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *masks); +static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks); struct neonserv_cmd_ban_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *masks; }; @@ -20,18 +21,19 @@ static CMD_BIND(neonserv_cmd_ban) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->masks = strdup(merge_argv_char(argv, 0, argc, ',')); - get_userlist(chan, neonserv_cmd_ban_userlist_lookup, cache); + get_userlist_with_invisible(chan, neonserv_cmd_ban_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_ban_userlist_lookup) { struct neonserv_cmd_ban_cache *cache = data; - neonserv_cmd_ban_async1(cache->client, cache->textclient, cache->user, chan, cache->masks); + neonserv_cmd_ban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->masks); free(cache->masks); free(cache); } -static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *masks) { +static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *masks) { int done_masks = 0, provided_masks = 0, skip, match_count, total_match; char *mask, *nextmask; char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; @@ -92,4 +94,6 @@ static void neonserv_cmd_ban_async1(struct ClientSocket *client, struct ClientSo reply(getTextBot(), user, "NS_BAN_DONE", done_masks, chan->name, total_match); else reply(getTextBot(), user, "NS_BAN_FAIL", client->user->nick); + if(done_masks) + logEvent(event); } diff --git a/cmd_neonserv_chanservsync.c b/cmd_neonserv_chanservsync.c index 67123df..31548f9 100644 --- a/cmd_neonserv_chanservsync.c +++ b/cmd_neonserv_chanservsync.c @@ -90,6 +90,7 @@ static CMD_BIND(neonserv_cmd_chanservsync) { putsock(client, "PRIVMSG %s :users %s", botnick, chan->name); bind_privnotice(neonserv_cmd_chanservsync_notice_listener); reply(getTextBot(), user, "NS_CHANSERVSYNC_SYNCHRONIZING", chan->name, botnick); + logEvent(event); } static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message) { diff --git a/cmd_neonserv_clvl.c b/cmd_neonserv_clvl.c index 51bab6a..328b454 100644 --- a/cmd_neonserv_clvl.c +++ b/cmd_neonserv_clvl.c @@ -4,12 +4,13 @@ * argv[1] - access */ static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup); -static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int caccess); +static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess); struct neonserv_cmd_clvl_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; int access; }; @@ -21,14 +22,18 @@ static CMD_BIND(neonserv_cmd_clvl) { reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); return; } - if(caccess >= getChannelAccess(user, chan, 1)) { - reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); - return; + if(caccess >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } } if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, argv[0], argv[0], caccess); + neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], caccess); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -36,7 +41,7 @@ static CMD_BIND(neonserv_cmd_clvl) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, caccess); + neonserv_cmd_clvl_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, caccess); } else { struct neonserv_cmd_clvl_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -47,6 +52,7 @@ static CMD_BIND(neonserv_cmd_clvl) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); cache->access = caccess; get_userauth(cuser, neonserv_cmd_clvl_nick_lookup, cache); @@ -65,12 +71,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_clvl_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->access); + neonserv_cmd_clvl_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->access); free(cache->nick); free(cache); } -static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, int caccess) { +static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, int caccess) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -90,6 +96,7 @@ static void neonserv_cmd_clvl_async1(struct ClientSocket *client, struct ClientS } printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]); reply(textclient, user, "NS_CLVL_DONE", nick, caccess, chan->name); + logEvent(event); return; } } diff --git a/cmd_neonserv_delban.c b/cmd_neonserv_delban.c index b211a11..2bd5699 100644 --- a/cmd_neonserv_delban.c +++ b/cmd_neonserv_delban.c @@ -28,6 +28,7 @@ static CMD_BIND(neonserv_cmd_delban) { if(matching_bans) { putsock(client, "MODE %s -b %s", chan->name, mask); reply(getTextBot(), user, "NS_DELBAN_DONE", mask, chan->name); + logEvent(event); } else reply(getTextBot(), user, "NS_DELBAN_FAIL", mask); } diff --git a/cmd_neonserv_delme.c b/cmd_neonserv_delme.c index 13d288f..e487f1b 100644 --- a/cmd_neonserv_delme.c +++ b/cmd_neonserv_delme.c @@ -31,6 +31,7 @@ static CMD_BIND(neonserv_cmd_delme) { //delete printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]); reply(getTextBot(), user, "NS_DELME_DONE", atoi(row[0]), chan->name); + logEvent(event); return; } } diff --git a/cmd_neonserv_deluser.c b/cmd_neonserv_deluser.c index e7928f9..a90862a 100644 --- a/cmd_neonserv_deluser.c +++ b/cmd_neonserv_deluser.c @@ -3,12 +3,13 @@ * argv[0] - nick / *auth */ static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup); -static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth); +static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); struct neonserv_cmd_deluser_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; }; @@ -16,7 +17,7 @@ static CMD_BIND(neonserv_cmd_deluser) { if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, argv[0], argv[0]); + neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -24,7 +25,7 @@ static CMD_BIND(neonserv_cmd_deluser) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, argv[0], cuser->auth); + neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); } else { struct neonserv_cmd_deluser_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -35,6 +36,7 @@ static CMD_BIND(neonserv_cmd_deluser) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); get_userauth(cuser, neonserv_cmd_deluser_nick_lookup, cache); } @@ -52,12 +54,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_deluser_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth); + neonserv_cmd_deluser_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth); free(cache->nick); free(cache); } -static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth) { +static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -70,13 +72,18 @@ static void neonserv_cmd_deluser_async1(struct ClientSocket *client, struct Clie printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; + if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } } //delete printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]); reply(textclient, user, "NS_DELUSER_DONE", nick, atoi(row[0]), chan->name); + logEvent(event); return; } } diff --git a/cmd_neonserv_deop.c b/cmd_neonserv_deop.c index a0e7d0e..526cf1b 100644 --- a/cmd_neonserv_deop.c +++ b/cmd_neonserv_deop.c @@ -3,11 +3,12 @@ * argv[0-*] nicks */ static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup); -static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char **argv, int argc); +static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); struct neonserv_cmd_deop_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char **argv; int argc; }; @@ -21,6 +22,7 @@ static CMD_BIND(neonserv_cmd_deop) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->argv = calloc(argc, sizeof(char*)); int i; for(i = 0; i < argc; i++) { @@ -32,7 +34,7 @@ static CMD_BIND(neonserv_cmd_deop) { static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup) { struct neonserv_cmd_deop_cache *cache = data; - neonserv_cmd_deop_async1(cache->client, cache->textclient, cache->user, chan, cache->argv, cache->argc); + neonserv_cmd_deop_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc); int i; for(i = 0; i < cache->argc; i++) { free(cache->argv[i]); @@ -40,7 +42,7 @@ static USERLIST_CALLBACK(neonserv_cmd_deop_userlist_lookup) { free(cache); } -static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char **argv, int argc) { +static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) { int i, done_users = 0; struct UserNode *cuser; struct ChanUser *chanuser; @@ -68,4 +70,6 @@ static void neonserv_cmd_deop_async1(struct ClientSocket *client, struct ClientS reply(textclient, user, "NS_DEOP_DONE", chan->name); else reply(textclient, user, "NS_DEOP_FAIL", client->user->nick); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_deopall.c b/cmd_neonserv_deopall.c index 92d5b2f..7f04595 100644 --- a/cmd_neonserv_deopall.c +++ b/cmd_neonserv_deopall.c @@ -3,11 +3,12 @@ * argv[0] (optional) nick mask */ static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup); -static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char **argv, int argc); +static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); struct neonserv_cmd_deopall_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char **argv; int argc; }; @@ -21,6 +22,7 @@ static CMD_BIND(neonserv_cmd_deopall) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->argv = calloc(argc, sizeof(char*)); int i; for(i = 0; i < argc; i++) { @@ -32,7 +34,7 @@ static CMD_BIND(neonserv_cmd_deopall) { static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup) { struct neonserv_cmd_deopall_cache *cache = data; - neonserv_cmd_deopall_async1(cache->client, cache->textclient, cache->user, chan, cache->argv, cache->argc); + neonserv_cmd_deopall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->argv, cache->argc); int i; for(i = 0; i < cache->argc; i++) { free(cache->argv[i]); @@ -40,15 +42,11 @@ static USERLIST_CALLBACK(neonserv_cmd_deopall_userlist_lookup) { free(cache); } -static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char **argv, int argc) { +static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) { int issuer_access, victim_access, done_users = 0; char *nickmask = NULL; struct ChanUser *chanuser; struct ModeBuffer *modeBuf; - if(!checkChannelAccess(user, chan, "channel_canop", 1, 0)) { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; - } if(argc > 0) nickmask = argv[0]; modeBuf = initModeBuffer(client, chan); @@ -63,4 +61,6 @@ static void neonserv_cmd_deopall_async1(struct ClientSocket *client, struct Clie } freeModeBuffer(modeBuf); reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_devoice.c b/cmd_neonserv_devoice.c index d1720a8..998dd9f 100644 --- a/cmd_neonserv_devoice.c +++ b/cmd_neonserv_devoice.c @@ -27,4 +27,6 @@ static CMD_BIND(neonserv_cmd_devoice) { reply(getTextBot(), user, "NS_DEVOICE_DONE", chan->name); else reply(getTextBot(), user, "NS_DEVOICE_FAIL", client->user->nick); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_devoiceall.c b/cmd_neonserv_devoiceall.c index a2a7a5f..bc3112d 100644 --- a/cmd_neonserv_devoiceall.c +++ b/cmd_neonserv_devoiceall.c @@ -27,4 +27,6 @@ static CMD_BIND(neonserv_cmd_devoiceall) { } freeModeBuffer(modeBuf); reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_down.c b/cmd_neonserv_down.c index 1eff93f..eb81b08 100644 --- a/cmd_neonserv_down.c +++ b/cmd_neonserv_down.c @@ -11,8 +11,10 @@ static CMD_BIND(neonserv_cmd_down) { } if((chanuser->flags & CHANUSERFLAG_OPPED)) { putsock(client, "MODE %s -ov %s %s", chan->name, user->nick, user->nick); + logEvent(event); } else if((chanuser->flags & CHANUSERFLAG_VOICED)) { putsock(client, "MODE %s -v %s", chan->name, user->nick); + logEvent(event); } else reply(getTextBot(), user, "NS_DOWN_ALREADY", chan->name); } diff --git a/cmd_neonserv_downall.c b/cmd_neonserv_downall.c index 6a23db8..643d1ae 100644 --- a/cmd_neonserv_downall.c +++ b/cmd_neonserv_downall.c @@ -11,9 +11,19 @@ static CMD_BIND(neonserv_cmd_downall) { if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) continue; printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid); if (mysql_fetch_row(mysql_use()) == NULL) continue; - if((chanuser->flags & CHANUSERFLAG_OPPED)) + int done = 0; + if((chanuser->flags & CHANUSERFLAG_OPPED)) { putsock(client, "MODE %s -o %s", chan->name, user->nick); - if((chanuser->flags & CHANUSERFLAG_VOICED)) + done = 1; + } + if((chanuser->flags & CHANUSERFLAG_VOICED)) { putsock(client, "MODE %s -v %s", chan->name, user->nick); + done = 1; + } + if(done) { + //event hack + event->chan = chan; + logEvent(event); + } } } diff --git a/cmd_neonserv_giveowner.c b/cmd_neonserv_giveowner.c index bea8de0..450d634 100644 --- a/cmd_neonserv_giveowner.c +++ b/cmd_neonserv_giveowner.c @@ -7,21 +7,18 @@ #define GIVEOWNER_TIMEOUT 86400 /* 60*60*24 = 86400 */ static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup); -static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *key); +static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key); struct neonserv_cmd_giveowner_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; char *key; }; static CMD_BIND(neonserv_cmd_giveowner) { - if(getChannelAccess(user, chan, 0) != 500) { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; - } MYSQL_RES *res; MYSQL_ROW row; printf_mysql_query("SELECT `channel_lastgiveowner` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); @@ -35,7 +32,7 @@ static CMD_BIND(neonserv_cmd_giveowner) { if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, argv[0], argv[0], (argc != 1 ? argv[1] : NULL)); + neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], argv[0], (argc != 1 ? argv[1] : NULL)); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -43,7 +40,7 @@ static CMD_BIND(neonserv_cmd_giveowner) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, (argc != 1 ? argv[1] : NULL)); + neonserv_cmd_giveowner_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth, (argc != 1 ? argv[1] : NULL)); } else { struct neonserv_cmd_giveowner_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -54,6 +51,7 @@ static CMD_BIND(neonserv_cmd_giveowner) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); cache->key = (argc != 1 ? strdup(argv[1]) : NULL); get_userauth(cuser, neonserv_cmd_giveowner_nick_lookup, cache); @@ -72,14 +70,14 @@ static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_giveowner_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->key); + neonserv_cmd_giveowner_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth, cache->key); free(cache->nick); if(cache->key) free(cache->key); free(cache); } -static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *key) { +static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth, char *key) { //we've got a valid auth now... if(!stricmp(user->auth, auth)) { reply(textclient, user, "NS_GIVEOWNER_SELF"); @@ -110,6 +108,7 @@ static void neonserv_cmd_giveowner_async1(struct ClientSocket *client, struct Cl printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '499' WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = (SELECT `user_id` FROM `users` WHERE `user_user` = '%s')", chan->channel_id, escape_string(user->auth)); printf_mysql_query("INSERT INTO `owner_history` (`owner_history_cid`, `owner_history_uid`, `owner_history_time`) VALUE ('%d', '%d', UNIX_TIMESTAMP())", chan->channel_id, userid); reply(textclient, user, "NS_GIVEOWNER_DONE", chan->name, auth); + logEvent(event); } else { reply(textclient, user, "NS_GIVEOWNER_CONFIRM", auth, giveownerkey); } diff --git a/cmd_neonserv_kick.c b/cmd_neonserv_kick.c index 2c12457..0a97087 100644 --- a/cmd_neonserv_kick.c +++ b/cmd_neonserv_kick.c @@ -4,11 +4,12 @@ * argv[1-*] reason */ static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup); -static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason); +static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason); struct neonserv_cmd_kick_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nicks; char *reason; }; @@ -22,6 +23,7 @@ static CMD_BIND(neonserv_cmd_kick) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->nicks = strdup(argv[0]); if(argc > 1) { cache->reason = strdup(merge_argv(argv, 1, argc)); @@ -32,14 +34,14 @@ static CMD_BIND(neonserv_cmd_kick) { static USERLIST_CALLBACK(neonserv_cmd_kick_userlist_lookup) { struct neonserv_cmd_kick_cache *cache = data; - neonserv_cmd_kick_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks, (cache->reason ? cache->reason : "Bye.")); + neonserv_cmd_kick_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye.")); free(cache->nicks); if(cache->reason) free(cache->reason); free(cache); } -static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason) { +static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) { int i, kicked_users = 0, provided_nicks = 0; char *nick, *nextnick; struct UserNode *cuser; @@ -130,4 +132,6 @@ static void neonserv_cmd_kick_async1(struct ClientSocket *client, struct ClientS reply(getTextBot(), user, "NS_KICK_DONE", kicked_users, chan->name); else reply(getTextBot(), user, "NS_KICK_FAIL", client->user->nick); + if(kicked_users) + logEvent(event); } diff --git a/cmd_neonserv_kickban.c b/cmd_neonserv_kickban.c index ae59941..3d0081f 100644 --- a/cmd_neonserv_kickban.c +++ b/cmd_neonserv_kickban.c @@ -4,11 +4,12 @@ * argv[1-*] reason */ static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup); -static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason); +static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason); struct neonserv_cmd_kickban_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nicks; char *reason; }; @@ -22,24 +23,25 @@ static CMD_BIND(neonserv_cmd_kickban) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->nicks = strdup(argv[0]); if(argc > 1) { cache->reason = strdup(merge_argv(argv, 1, argc)); } else cache->reason = NULL; - get_userlist(chan, neonserv_cmd_kickban_userlist_lookup, cache); + get_userlist_with_invisible(chan, neonserv_cmd_kickban_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_kickban_userlist_lookup) { struct neonserv_cmd_kickban_cache *cache = data; - neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks, (cache->reason ? cache->reason : "Bye.")); + neonserv_cmd_kickban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks, (cache->reason ? cache->reason : "Bye.")); free(cache->nicks); if(cache->reason) free(cache->reason); free(cache); } -static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks, char *reason) { +static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks, char *reason) { int i, kicked_users = 0, provided_nicks = 0; char *nick, *nextnick; struct UserNode *cuser; @@ -132,4 +134,6 @@ static void neonserv_cmd_kickban_async1(struct ClientSocket *client, struct Clie reply(getTextBot(), user, "NS_KICKBAN_DONE", kicked_users, chan->name); else reply(getTextBot(), user, "NS_KICKBAN_FAIL", client->user->nick); + if(kicked_users) + logEvent(event); } diff --git a/cmd_neonserv_mdeluser.c b/cmd_neonserv_mdeluser.c index 6608066..5ca9727 100644 --- a/cmd_neonserv_mdeluser.c +++ b/cmd_neonserv_mdeluser.c @@ -40,5 +40,7 @@ static CMD_BIND(neonserv_cmd_mdeluser) { } } reply(getTextBot(), user, "NS_MDELUSER_DONE", del_count, argv[1], min_access, max_access, chan->name); + if(del_count) + logEvent(event); } diff --git a/cmd_neonserv_op.c b/cmd_neonserv_op.c index 0510fe8..6e6d0d8 100644 --- a/cmd_neonserv_op.c +++ b/cmd_neonserv_op.c @@ -3,11 +3,12 @@ * argv[0-*] nicks */ static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup); -static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks); +static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks); struct neonserv_cmd_op_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nicks; }; @@ -20,18 +21,19 @@ static CMD_BIND(neonserv_cmd_op) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->nicks = strdup(merge_argv(argv, 0, argc)); get_userlist_with_invisible(chan, neonserv_cmd_op_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_op_userlist_lookup) { struct neonserv_cmd_op_cache *cache = data; - neonserv_cmd_op_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks); + neonserv_cmd_op_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks); free(cache->nicks); free(cache); } -static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks) { +static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) { int total_users = 0, done_users = 0; struct UserNode *cuser; struct ChanUser *chanuser; @@ -68,4 +70,6 @@ static void neonserv_cmd_op_async1(struct ClientSocket *client, struct ClientSoc reply(textclient, user, "NS_OP_DONE", chan->name); else reply(textclient, user, "NS_OP_FAIL", client->user->nick); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_opall.c b/cmd_neonserv_opall.c index b9128ca..dfd6eef 100644 --- a/cmd_neonserv_opall.c +++ b/cmd_neonserv_opall.c @@ -4,11 +4,12 @@ * argv[1] (optional) nick mask */ static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup); -static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nickmask); +static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask); struct neonserv_cmd_opall_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nickmask; }; @@ -25,6 +26,7 @@ static CMD_BIND(neonserv_cmd_opall) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; if(argc > 1) { cache->nickmask = strdup(argv[1]); } else @@ -34,13 +36,13 @@ static CMD_BIND(neonserv_cmd_opall) { static USERLIST_CALLBACK(neonserv_cmd_opall_userlist_lookup) { struct neonserv_cmd_opall_cache *cache = data; - neonserv_cmd_opall_async1(cache->client, cache->textclient, cache->user, chan, cache->nickmask); + neonserv_cmd_opall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask); if(cache->nickmask) free(cache->nickmask); free(cache); } -static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nickmask) { +static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) { int done_users = 0; struct ChanUser *chanuser; struct ModeBuffer *modeBuf; @@ -53,4 +55,6 @@ static void neonserv_cmd_opall_async1(struct ClientSocket *client, struct Client } freeModeBuffer(modeBuf); reply(textclient, user, "NS_OPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_recover.c b/cmd_neonserv_recover.c index 7cdd323..544112a 100644 --- a/cmd_neonserv_recover.c +++ b/cmd_neonserv_recover.c @@ -54,4 +54,5 @@ static CMD_BIND(neonserv_cmd_recover) { reply(getTextBot(), user, "NS_REGISTER_DISCONNECTED"); printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', '%s')", botid, chanid, bottrigger); reply(getTextBot(), user, "NS_RECOVER_DONE", channel); + logEvent(event); } diff --git a/cmd_neonserv_register.c b/cmd_neonserv_register.c index 9486ec9..4d57ac0 100644 --- a/cmd_neonserv_register.c +++ b/cmd_neonserv_register.c @@ -5,12 +5,13 @@ */ static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup); static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup); -static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *channel, char *auth); +static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth); struct neonserv_cmd_register_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; char *channel; }; @@ -36,7 +37,7 @@ static CMD_BIND(neonserv_cmd_register) { printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[0])); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - neonserv_cmd_register_async1(client, getTextBot(), user, chan, channel, row[0]); + neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, row[0]); } else { //we need to create a new user... //but first lookup the auth to check if it really exists @@ -49,6 +50,7 @@ static CMD_BIND(neonserv_cmd_register) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[1]); cache->channel = strdup(channel); lookup_authname(argv[1], neonserv_cmd_register_auth_lookup, cache); @@ -60,7 +62,7 @@ static CMD_BIND(neonserv_cmd_register) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_register_async1(client, getTextBot(), user, chan, channel, cuser->auth); + neonserv_cmd_register_async1(client, getTextBot(), user, chan, event, channel, cuser->auth); } else { struct neonserv_cmd_register_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -71,6 +73,7 @@ static CMD_BIND(neonserv_cmd_register) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[1]); cache->channel = strdup(channel); get_userauth(cuser, neonserv_cmd_register_nick_lookup, cache); @@ -84,7 +87,7 @@ static AUTHLOOKUP_CALLBACK(neonserv_cmd_register_auth_lookup) { //AUTH_DOES_NOT_EXIST reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); } else - neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->channel, auth); + neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, auth); free(cache->channel); free(cache->nick); free(cache); @@ -101,13 +104,13 @@ static USERAUTH_CALLBACK(neonserv_cmd_register_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->channel, user->auth); + neonserv_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, user->auth); free(cache->channel); free(cache->nick); free(cache); } -static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *channel, char *auth) { +static void neonserv_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row, row2; @@ -167,4 +170,5 @@ static void neonserv_cmd_register_async1(struct ClientSocket *client, struct Cli printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid); printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chanid, userid, 500); reply(textclient, user, "NS_REGISTER_DONE", channel, auth); + logEvent(event); } diff --git a/cmd_neonserv_set.c b/cmd_neonserv_set.c index c87acdc..28dab07 100644 --- a/cmd_neonserv_set.c +++ b/cmd_neonserv_set.c @@ -1,10 +1,10 @@ -typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument); -static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int setting, char *argument); -static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument); -static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument); -static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument); -static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument); +typedef char* neonserv_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument); +static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *argument); +static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument); +static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument); +static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument); +static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument); #define NS_VALID_FUNCTION 0x01 #define NS_VALID_STRING 0x02 @@ -67,10 +67,14 @@ static CMD_BIND(neonserv_cmd_set) { int i, j; if(argc && !strcmp(argv[0], "defaults")) { //reset channel settings - int uaccess = getChannelAccess(user, chan, 1); + int uaccess = getChannelAccess(user, chan, 0); if(uaccess < 500) { - reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); - return; + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); + return; + } } int seed = 0; char *tmp; @@ -94,6 +98,7 @@ static CMD_BIND(neonserv_cmd_set) { } printf_mysql_query("UPDATE `channels` SET %s WHERE `channel_id` = '%d'", query, chan->channel_id); reply(getTextBot(), user, "NS_SET_DEFAULTS_DONE", chan->name); + logEvent(event); } else { reply(getTextBot(), user, "NS_SET_DEFAULTS_CODE", chan->name, defaultskey); } @@ -107,9 +112,9 @@ static CMD_BIND(neonserv_cmd_set) { //setting found if(channel_settings[i].valid & NS_VALID_FUNCTION) { neonserv_cmd_set_function *func = channel_settings[i].parameter; - func(client, user, chan, channel_settings[i].setting, args); + func(client, user, chan, event, channel_settings[i].setting, args); } else { - neonserv_cmd_set_setting(client, user, chan, i, args); + neonserv_cmd_set_setting(client, user, chan, event, i, args); } j = 1; break; @@ -150,7 +155,7 @@ static CMD_BIND(neonserv_cmd_set) { org_value = (row[j] ? row[j] : defaults[j]); } else if(channel_settings[i].valid & NS_VALID_FUNCTION) { neonserv_cmd_set_function *func = channel_settings[i].parameter; - org_value = func(client, user, chan, NULL, NULL); + org_value = func(client, user, chan, event, NULL, NULL); } else org_value = "0"; value = org_value; @@ -189,7 +194,7 @@ static CMD_BIND(neonserv_cmd_set) { } } -static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int setting, char *args) { +static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int setting, char *args) { char *value; char nameBuf[64]; //get current value @@ -220,15 +225,23 @@ static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNod reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); return; } - int uaccess = getChannelAccess(user, chan, 1); + int uaccess = getChannelAccess(user, chan, 0); if(uaccess == 500) uaccess++; if(atoi(value) > uaccess) { - reply(getTextBot(), user, "NS_SET_CANNOT_SET"); - return; + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_CANNOT_SET"); + return; + } } if(caccess > uaccess) { - reply(getTextBot(), user, "NS_SET_BADLEVEL"); - return; + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_BADLEVEL"); + return; + } } sprintf(nameBuf, "%d", caccess); args = nameBuf; @@ -274,6 +287,7 @@ static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNod //valid - set it value = args; printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, escape_string(value), chan->channel_id); + logEvent(event); } reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value); if(channel_settings[setting].valid & NS_HAS_HELP) { @@ -282,7 +296,7 @@ static void neonserv_cmd_set_setting(struct ClientSocket *client, struct UserNod } } -static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) { +static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) { char *trigger; //get current trigger MYSQL_RES *res; @@ -292,16 +306,21 @@ static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNo row = mysql_fetch_row(res); trigger = row[0]; if(argument) { - int uaccess = getChannelAccess(user, chan, 1); + int uaccess = getChannelAccess(user, chan, 0); if(uaccess < 500) { - reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name); - return NULL; + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_TRIGGER_OWNER", chan->name); + return NULL; + } } if(strlen(argument) > 15) argument[15] = '\0'; printf_mysql_query("UPDATE `bot_channels` SET `trigger` = '%s' WHERE `chanid` = '%d' AND `botid` = '%d'", escape_string(argument), chan->channel_id, client->clientid); trigger = argument; changeChannelTrigger(client->botid, chan, trigger); + logEvent(event); } if(setting) { reply(getTextBot(), user, "\002%s\002 %s", setting, trigger); @@ -309,7 +328,7 @@ static char* neonserv_cmd_set_trigger(struct ClientSocket *client, struct UserNo return trigger; } -static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) { +static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) { char *value; //get current value MYSQL_RES *res; @@ -333,7 +352,7 @@ static char* neonserv_cmd_set_modes(struct ClientSocket *client, struct UserNode return value; } -static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) { +static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) { char *value; char tmp[64]; //get current value @@ -357,6 +376,7 @@ static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserN putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument))); else if(isModeSet(chan, 'l')) putsock(client, "MODE %s -l", chan->name); + logEvent(event); } if(setting) { reply(getTextBot(), user, "\002%s\002 %s", setting, value); @@ -364,7 +384,7 @@ static char* neonserv_cmd_set_dynlimit(struct ClientSocket *client, struct UserN return value; } -static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *setting, char *argument) { +static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, const char *setting, char *argument) { char *value; //get current value MYSQL_RES *res; @@ -389,6 +409,8 @@ static char* neonserv_cmd_set_nodelete(struct ClientSocket *client, struct UserN return NULL; } printf_mysql_query("UPDATE `channels` SET `channel_nodelete` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id); + event->flags |= CMDFLAG_OPLOG; + logEvent(event); } if(setting) { reply(getTextBot(), user, "\002%s\002 %s", setting, value); diff --git a/cmd_neonserv_suspend.c b/cmd_neonserv_suspend.c index 867b74b..48c88c5 100644 --- a/cmd_neonserv_suspend.c +++ b/cmd_neonserv_suspend.c @@ -3,12 +3,13 @@ * argv[0] - nick / *auth */ static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup); -static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth); +static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); struct neonserv_cmd_suspend_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; }; @@ -16,7 +17,7 @@ static CMD_BIND(neonserv_cmd_suspend) { if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, argv[0], argv[0]); + neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -24,7 +25,7 @@ static CMD_BIND(neonserv_cmd_suspend) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, argv[0], cuser->auth); + neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); } else { struct neonserv_cmd_suspend_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -35,6 +36,7 @@ static CMD_BIND(neonserv_cmd_suspend) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); get_userauth(cuser, neonserv_cmd_suspend_nick_lookup, cache); } @@ -52,12 +54,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_suspend_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth); + neonserv_cmd_suspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth); free(cache->nick); free(cache); } -static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth) { +static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -70,9 +72,13 @@ static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct Clie printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; + if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } } //suspend cflags = atoi(row[2]); @@ -83,6 +89,7 @@ static void neonserv_cmd_suspend_async1(struct ClientSocket *client, struct Clie cflags |= DB_CHANUSER_SUSPENDED; printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]); reply(textclient, user, "NS_SUSPEND_DONE", nick, chan->name); + logEvent(event); return; } } diff --git a/cmd_neonserv_topic.c b/cmd_neonserv_topic.c index ab214b0..69f5a91 100644 --- a/cmd_neonserv_topic.c +++ b/cmd_neonserv_topic.c @@ -33,9 +33,10 @@ static CMD_BIND(neonserv_cmd_topic) { //default topic! putsock(client, "TOPIC %s :%s", chan->name, row[5]); reply(getTextBot(), user, "NS_TOPIC_DONE", row[5]); + logEvent(event); return; } - int uaccess = getChannelAccess(user, chan, 1); + int uaccess = getChannelAccess(user, chan, 0); if(uaccess >= atoi((row[3] ? row[3] : default_row[1]))) { //just set the topic newtopic = merge_argv(argv, 0, argc); @@ -45,6 +46,7 @@ static CMD_BIND(neonserv_cmd_topic) { } putsock(client, "TOPIC %s :%s", chan->name, newtopic); reply(getTextBot(), user, "NS_TOPIC_DONE", newtopic); + logEvent(event); return; } if(advanced_topic) { @@ -102,6 +104,7 @@ static CMD_BIND(neonserv_cmd_topic) { topiclist[MAXLEN] = '\0'; putsock(client, "TOPIC %s :%s", chan->name, topiclist); reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist); + logEvent(event); } else { newtopic = merge_argv(argv, 0, argc); char topiclist[MAXLEN*2]; @@ -118,6 +121,7 @@ static CMD_BIND(neonserv_cmd_topic) { topiclist[MAXLEN] = '\0'; putsock(client, "TOPIC %s :%s", chan->name, topiclist); reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist); + logEvent(event); } } diff --git a/cmd_neonserv_trim.c b/cmd_neonserv_trim.c index 9679195..345a9e2 100644 --- a/cmd_neonserv_trim.c +++ b/cmd_neonserv_trim.c @@ -4,29 +4,38 @@ * argv[1] duration */ static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup); -static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int min_access, int max_access, int duration); +static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration); struct neonserv_cmd_trim_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; int min_access; int max_access; int duration; }; static CMD_BIND(neonserv_cmd_trim) { - if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 1, 0)) { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; + if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 0, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } } int min_access, max_access; if(!stricmp(argv[0], "users")) { min_access = 1; max_access = getChannelAccess(user, chan, 0) - 1; } else if(!stricmp(argv[0], "bans")) { - if(!checkChannelAccess(user, chan, "channel_staticban", 1, 0)) { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; + if(!checkChannelAccess(user, chan, "channel_staticban", 0, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } } //TODO: TRIM BANS return; @@ -45,9 +54,13 @@ static CMD_BIND(neonserv_cmd_trim) { min_access = atoi(argv[0]); max_access = min_access; } - if(max_access >= getChannelAccess(user, chan, 1)) { - reply(getTextBot(), user, "NS_NO_ACCESS"); - return; + if(max_access >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_NO_ACCESS"); + return; + } } } //parse duration... @@ -64,20 +77,21 @@ static CMD_BIND(neonserv_cmd_trim) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->min_access = min_access; cache->max_access = max_access; cache->duration = duration; - get_userlist(chan, neonserv_cmd_trim_userlist_lookup, cache); + get_userlist_with_invisible(chan, neonserv_cmd_trim_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_trim_userlist_lookup) { struct neonserv_cmd_trim_cache *cache = data; //got userlist - neonserv_cmd_trim_async1(cache->client, cache->textclient, cache->user, chan, cache->min_access, cache->max_access, cache->duration); + neonserv_cmd_trim_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->min_access, cache->max_access, cache->duration); free(cache); } -static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int min_access, int max_access, int duration) { +static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, int min_access, int max_access, int duration) { MYSQL_RES *res; MYSQL_ROW row; int trim_count = 0, is_here; @@ -103,4 +117,6 @@ static void neonserv_cmd_trim_async1(struct ClientSocket *client, struct ClientS } char timeBuf[MAXLEN]; reply(getTextBot(), user, "NS_TRIM_DONE", trim_count, min_access, max_access, chan->name, timeToStr(user, duration, 3, timeBuf)); + if(trim_count) + logEvent(event); } diff --git a/cmd_neonserv_unregister.c b/cmd_neonserv_unregister.c index 2137403..ce8df75 100644 --- a/cmd_neonserv_unregister.c +++ b/cmd_neonserv_unregister.c @@ -36,4 +36,5 @@ static CMD_BIND(neonserv_cmd_unregister) { } printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]); reply(getTextBot(), user, "NS_UNREGISTER_DONE", channel); + logEvent(event); } diff --git a/cmd_neonserv_unsuspend.c b/cmd_neonserv_unsuspend.c index 58fdee5..e295595 100644 --- a/cmd_neonserv_unsuspend.c +++ b/cmd_neonserv_unsuspend.c @@ -3,12 +3,13 @@ * argv[0] - nick / *auth */ static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup); -static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth); +static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); struct neonserv_cmd_unsuspend_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; }; @@ -16,7 +17,7 @@ static CMD_BIND(neonserv_cmd_unsuspend) { if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, argv[0], argv[0]); + neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -24,7 +25,7 @@ static CMD_BIND(neonserv_cmd_unsuspend) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, argv[0], cuser->auth); + neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); } else { struct neonserv_cmd_unsuspend_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -35,6 +36,7 @@ static CMD_BIND(neonserv_cmd_unsuspend) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); get_userauth(cuser, neonserv_cmd_unsuspend_nick_lookup, cache); } @@ -52,12 +54,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_unsuspend_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth); + neonserv_cmd_unsuspend_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth); free(cache->nick); free(cache); } -static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth) { +static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -70,9 +72,13 @@ static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct Cl printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_flags` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; + if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } } //unsuspend cflags = atoi(row[2]); @@ -83,6 +89,7 @@ static void neonserv_cmd_unsuspend_async1(struct ClientSocket *client, struct Cl cflags &= ~DB_CHANUSER_SUSPENDED; printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", cflags, row[1]); reply(textclient, user, "NS_SUSPEND_RESTORED", nick, chan->name); + logEvent(event); return; } } diff --git a/cmd_neonserv_up.c b/cmd_neonserv_up.c index e5f8fed..991a9b3 100644 --- a/cmd_neonserv_up.c +++ b/cmd_neonserv_up.c @@ -31,11 +31,13 @@ static CMD_BIND(neonserv_cmd_up) { if(caccess >= chan_getop) { if(!(chanuser->flags & CHANUSERFLAG_OPPED)) { putsock(client, "MODE %s +o %s", chan->name, user->nick); + logEvent(event); } else reply(getTextBot(), user, "NS_UP_ALREADY_OP", chan->name); } else if(caccess >= chan_getvoice) { if(!(chanuser->flags & CHANUSERFLAG_VOICED)) { putsock(client, "MODE %s +v %s", chan->name, user->nick); + logEvent(event); } else reply(getTextBot(), user, "NS_UP_ALREADY_VOICE", chan->name); } else diff --git a/cmd_neonserv_upall.c b/cmd_neonserv_upall.c index 6324c11..9459acf 100644 --- a/cmd_neonserv_upall.c +++ b/cmd_neonserv_upall.c @@ -32,12 +32,21 @@ static CMD_BIND(neonserv_cmd_upall) { chan_getvoice = atoi(row[2]); } caccess = atoi(row[0]); + int done = 0; if(caccess >= chan_getop) { - if(!(chanuser->flags & CHANUSERFLAG_OPPED)) + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) { putsock(client, "MODE %s +o %s", chan->name, user->nick); + done = 1; + } } else if(caccess >= chan_getvoice) { - if(!(chanuser->flags & CHANUSERFLAG_VOICED)) + if(!(chanuser->flags & CHANUSERFLAG_VOICED)) { putsock(client, "MODE %s +v %s", chan->name, user->nick); + done = 1; + } + } + if(done) { + event->chan = chan; + logEvent(event); } } } diff --git a/cmd_neonserv_users.c b/cmd_neonserv_users.c index f9a7173..0ef88b6 100644 --- a/cmd_neonserv_users.c +++ b/cmd_neonserv_users.c @@ -35,7 +35,7 @@ static CMD_BIND(neonserv_cmd_users) { cache->usermask = (usermask ? strdup(usermask) : NULL); cache->min_access = min_access; cache->max_access = max_access; - get_userlist(chan, neonserv_cmd_users_userlist_lookup, cache); + get_userlist_with_invisible(chan, neonserv_cmd_users_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) { @@ -74,12 +74,16 @@ static void neonserv_cmd_users_async1(struct ClientSocket *client, struct Client is_here = 0; for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { if((chanuser->user->flags & USERFLAG_ISAUTHED) && !strcmp(chanuser->user->auth, row[1])) { - is_here = 1; - break; + if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) + is_here = 2; + else { + is_here = 1; + break; + } } } if(is_here) { - content[2] = get_language_string(user, "NS_USERS_SEEN_HERE"); + content[2] = get_language_string(user, (is_here == 2 ? "NS_USERS_SEEN_INVISIBLE" : "NS_USERS_SEEN_HERE")); } else if(!strcmp(row[2], "0")) { content[2] = get_language_string(user, "NS_USERS_SEEN_NEVER"); } else { diff --git a/cmd_neonserv_voice.c b/cmd_neonserv_voice.c index d4e385d..611c352 100644 --- a/cmd_neonserv_voice.c +++ b/cmd_neonserv_voice.c @@ -3,11 +3,12 @@ * argv[0-*] nicks */ static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup); -static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks); +static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks); struct neonserv_cmd_voice_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nicks; }; @@ -20,18 +21,19 @@ static CMD_BIND(neonserv_cmd_voice) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; cache->nicks = strdup(merge_argv(argv, 0, argc)); get_userlist_with_invisible(chan, neonserv_cmd_voice_userlist_lookup, cache); } static USERLIST_CALLBACK(neonserv_cmd_voice_userlist_lookup) { struct neonserv_cmd_voice_cache *cache = data; - neonserv_cmd_voice_async1(cache->client, cache->textclient, cache->user, chan, cache->nicks); + neonserv_cmd_voice_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks); free(cache->nicks); free(cache); } -static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nicks) { +static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks) { int total_users = 0, done_users = 0; struct UserNode *cuser; struct ChanUser *chanuser; @@ -68,4 +70,6 @@ static void neonserv_cmd_voice_async1(struct ClientSocket *client, struct Client reply(textclient, user, "NS_VOICE_DONE", chan->name); else reply(textclient, user, "NS_VOICE_FAIL", client->user->nick); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_voiceall.c b/cmd_neonserv_voiceall.c index 7cb01de..0377310 100644 --- a/cmd_neonserv_voiceall.c +++ b/cmd_neonserv_voiceall.c @@ -3,11 +3,12 @@ * argv[0] (optional) nick mask */ static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup); -static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nickmask); +static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask); struct neonserv_cmd_voiceall_cache { struct ClientSocket *client, *textclient; struct UserNode *user; + struct Event *event; char *nickmask; }; @@ -20,6 +21,7 @@ static CMD_BIND(neonserv_cmd_voiceall) { cache->client = client; cache->textclient = getTextBot(); cache->user = user; + cache->event = event; if(argc > 0) { cache->nickmask = strdup(argv[0]); } else @@ -29,13 +31,13 @@ static CMD_BIND(neonserv_cmd_voiceall) { static USERLIST_CALLBACK(neonserv_cmd_voiceall_userlist_lookup) { struct neonserv_cmd_voiceall_cache *cache = data; - neonserv_cmd_voiceall_async1(cache->client, cache->textclient, cache->user, chan, cache->nickmask); + neonserv_cmd_voiceall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask); if(cache->nickmask) free(cache->nickmask); free(cache); } -static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nickmask) { +static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask) { int done_users = 0; struct ChanUser *chanuser; struct ModeBuffer *modeBuf; @@ -48,4 +50,6 @@ static void neonserv_cmd_voiceall_async1(struct ClientSocket *client, struct Cli } freeModeBuffer(modeBuf); reply(textclient, user, "NS_VOICEALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); } diff --git a/cmd_neonserv_wipeinfo.c b/cmd_neonserv_wipeinfo.c index 71a7160..8fc1514 100644 --- a/cmd_neonserv_wipeinfo.c +++ b/cmd_neonserv_wipeinfo.c @@ -3,12 +3,13 @@ * argv[0] - nick / *auth */ static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup); -static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth); +static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); struct neonserv_cmd_wipeinfo_cache { struct ClientSocket *client, *textclient; struct UserNode *user; struct ChanNode *chan; + struct Event *event; char *nick; }; @@ -16,7 +17,7 @@ static CMD_BIND(neonserv_cmd_wipeinfo) { if(argv[0][0] == '*') { //we've got an auth argv[0]++; - neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, argv[0], argv[0]); + neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); } else { struct UserNode *cuser = getUserByNick(argv[0]); if(!cuser) { @@ -24,7 +25,7 @@ static CMD_BIND(neonserv_cmd_wipeinfo) { cuser->flags |= USERFLAG_ISTMPUSER; } if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, argv[0], cuser->auth); + neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); } else { struct neonserv_cmd_wipeinfo_cache *cache = malloc(sizeof(*cache)); if (!cache) { @@ -35,6 +36,7 @@ static CMD_BIND(neonserv_cmd_wipeinfo) { cache->textclient = getTextBot(); cache->user = user; cache->chan = chan; + cache->event = event; cache->nick = strdup(argv[0]); get_userauth(cuser, neonserv_cmd_wipeinfo_nick_lookup, cache); } @@ -52,12 +54,12 @@ static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup) { reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); } else - neonserv_cmd_wipeinfo_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth); + neonserv_cmd_wipeinfo_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, user->auth); free(cache->nick); free(cache); } -static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth) { +static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { //we've got a valid auth now... MYSQL_RES *res; MYSQL_ROW row; @@ -70,13 +72,18 @@ static void neonserv_cmd_wipeinfo_async1(struct ClientSocket *client, struct Cli printf_mysql_query("SELECT `chanuser_access`, `chanuser_id` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); res = mysql_use(); if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[0]) >= getChannelAccess(user, chan, 1)) { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; + if(atoi(row[0]) >= getChannelAccess(user, chan, 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } } //delete printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '' WHERE `chanuser_id` = '%s'", row[1]); reply(textclient, user, "NS_WIPEINFO_DONE", nick, chan->name); + logEvent(event); return; } } diff --git a/main.c b/main.c index c6814a1..5872b80 100644 --- a/main.c +++ b/main.c @@ -13,6 +13,7 @@ #include "lang.h" #include "tools.h" #include "timeq.h" +#include "EventLogger.h" time_t start_time; @@ -54,6 +55,7 @@ int main(void) timeq_tick(); loop_bots(); clearTempUsers(); + destroyEvents(); } } diff --git a/modcmd.c b/modcmd.c index 32011f2..c3868ea 100644 --- a/modcmd.c +++ b/modcmd.c @@ -10,6 +10,7 @@ #include "lang.h" #include "mysqlConn.h" #include "DBHelper.h" +#include "EventLogger.h" struct trigger_callback { int botid; @@ -224,6 +225,7 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u MYSQL_RES *res; MYSQL_ROW row; int uaccess; + int eventflags = (cbind->func->flags & (CMDFLAG_LOG | CMDFLAG_OPLOG)); if((cbind->func->flags & CMDFLAG_REQUIRE_AUTH) && !(user->flags & USERFLAG_ISAUTHED)) { reply(tmp_text_client, user, "MODCMD_AUTH_REQUIRED"); return; @@ -293,8 +295,10 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u chan->flags |= CHANFLAG_CHAN_REGISTERED; chan->channel_id = atoi(row[0]); if((sent_chan && sent_chan == chan) || access_count || minaccess) { - uaccess = getChannelAccess(user, chan, 1); - if(uaccess < minaccess) { + uaccess = getChannelAccess(user, chan, 0); + if(uaccess < minaccess && isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else if(uaccess < minaccess) { //ACCESS DENIED reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); return; @@ -304,9 +308,13 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u defaults = mysql_fetch_row(mysql_use()); } if(sent_chan && (sent_chan == chan) && uaccess < (row[1] ? atoi(row[1]) : atoi(defaults[1]))) { - //PUBCMD - reply(tmp_text_client, user, "MODCMD_PUBCMD", chan->name); - return; + if(isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else { + //PUBCMD + reply(tmp_text_client, user, "MODCMD_PUBCMD", chan->name); + return; + } } int i; for(i = 0; i < access_count; i++) { @@ -315,8 +323,12 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u defaults = mysql_fetch_row(mysql_use()); } if(uaccess < (row[2+i] ? atoi(row[2+i]) : atoi(defaults[2+i]))) { - reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); - return; + if(isGodMode(user)) { + eventflags |= CMDFLAG_OPLOG; + } else { + reply(tmp_text_client, user, "MODCMD_ACCESS_DENIED"); + return; + } } } } @@ -338,7 +350,8 @@ static void handle_command_async(struct ClientSocket *client, struct UserNode *u reply(tmp_text_client, user, "MODCMD_PRIVILEGED", cbind->cmd); return; } - cbind->func->func(client, user, chan, argv, argc); + struct Event *event = createEvent(client, user, chan, cbind->func->name, argv, argc, eventflags); + cbind->func->func(client, user, chan, argv, argc, event); } static void got_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { diff --git a/modcmd.h b/modcmd.h index fd313b0..4b5218c 100644 --- a/modcmd.h +++ b/modcmd.h @@ -2,21 +2,24 @@ #define _modcmd_h #include "main.h" -#define CMDFLAG_REQUIRE_CHAN 0x01 -#define CMDFLAG_REQUIRE_AUTH 0x02 -#define CMDFLAG_REQUIRE_GOD 0x04 -#define CMDFLAG_CHECK_AUTH 0x08 -#define CMDFLAG_REGISTERED_CHAN 0x10 -#define CMDFLAG_OVERRIDE_GLOBAL_ACCESS 0x20 -#define CMDFLAG_OVERRIDE_CHANNEL_ACCESS 0x40 -#define CMDFLAG_CHAN_PARAM 0x80 +#define CMDFLAG_REQUIRE_CHAN 0x0001 +#define CMDFLAG_REQUIRE_AUTH 0x0002 +#define CMDFLAG_REQUIRE_GOD 0x0004 +#define CMDFLAG_CHECK_AUTH 0x0008 +#define CMDFLAG_REGISTERED_CHAN 0x0010 +#define CMDFLAG_OVERRIDE_GLOBAL_ACCESS 0x0020 +#define CMDFLAG_OVERRIDE_CHANNEL_ACCESS 0x0040 +#define CMDFLAG_CHAN_PARAM 0x0080 +#define CMDFLAG_LOG 0x0100 +#define CMDFLAG_OPLOG 0x0200 struct ClientSocket; struct UserNode; struct ChanNode; +struct Event; -#define CMD_BIND(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(char **argv), UNUSED_ARG(char argc)) -typedef void cmd_bind_t(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char **argv, char argc); +#define CMD_BIND(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(struct ChanNode *chan), UNUSED_ARG(char **argv), UNUSED_ARG(char argc), UNUSED_ARG(struct Event *event)) +typedef void cmd_bind_t(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char **argv, char argc, struct Event *event); typedef void trigger_callback_t(struct ChanNode *chan, char *trigger); struct cmd_function {