From: pk910 Date: Sat, 11 Feb 2012 21:21:50 +0000 (+0100) Subject: rearranged NeonServ code to be modular X-Git-Tag: v5.3~16 X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=commitdiff_plain;h=706e48b1e666054030c491d864f740071e390038 rearranged NeonServ code to be modular --- diff --git a/src/BanNode.h b/src/BanNode.h index 2367eb8..028b599 100644 --- a/src/BanNode.h +++ b/src/BanNode.h @@ -27,10 +27,12 @@ struct BanNode { struct BanNode *next; }; +#ifndef DND_FUNCTIONS struct BanNode* addChannelBan(struct ChanNode *chan, char *mask); -struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask); +/* MODULAR ACCESSIBLE */ struct BanNode* getMatchingChannelBan(struct ChanNode *chan, char *mask); void removeChannelBanMask(struct ChanNode *chan, char *mask); void removeChannelBan(struct BanNode *ban); void removeChannelBans(struct ChanNode *chan); +#endif #endif \ No newline at end of file diff --git a/src/ChanNode.h b/src/ChanNode.h index d0bb4a5..38a1d89 100644 --- a/src/ChanNode.h +++ b/src/ChanNode.h @@ -49,17 +49,18 @@ struct ChanNode { struct ChanNode *next; }; +#ifndef DND_FUNCTIONS void init_ChanNode(); void free_ChanNode(); -int is_valid_chan(const char *name); -struct ChanNode* getAllChans(struct ChanNode *last); -struct ChanNode* getChanByName(const char *name); +/* MODULAR ACCESSIBLE */ int is_valid_chan(const char *name); +/* MODULAR ACCESSIBLE */ struct ChanNode* getAllChans(struct ChanNode *last); +/* MODULAR ACCESSIBLE */ struct ChanNode* getChanByName(const char *name); struct ChanNode* addChannel(const char *chan); -int getChannelCount(); -int getChanUserCount(); -int getChanBanCount(); +/* MODULAR ACCESSIBLE */ int getChannelCount(); +/* MODULAR ACCESSIBLE */ int getChanUserCount(); +/* MODULAR ACCESSIBLE */ int getChanBanCount(); void delChannel(struct ChanNode* chan, int freeChan); void freeChanNode(struct ChanNode* chan); int checkChannelVisibility(struct ChanNode* chan); - +#endif #endif \ No newline at end of file diff --git a/src/ChanUser.h b/src/ChanUser.h index 00bfc97..3e5ca8a 100644 --- a/src/ChanUser.h +++ b/src/ChanUser.h @@ -43,14 +43,15 @@ struct ChanUser { struct ChanUser *next_chan; }; +#ifndef DND_FUNCTIONS struct ChanUser* addChanUser(struct ChanNode *chan, struct UserNode *user); struct ChanUser* addInvisibleChanUser(struct ChanNode *chan, struct UserNode *user); -int isUserOnChan(struct UserNode *user, struct ChanNode *chan); -struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan); -struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last); -struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last); +/* MODULAR ACCESSIBLE */ int isUserOnChan(struct UserNode *user, struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ struct ChanUser* getChanUser(struct UserNode *user, struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ struct ChanUser* getChannelUsers(struct ChanNode *chan, struct ChanUser *last); +/* MODULAR ACCESSIBLE */ struct ChanUser* getUserChannels(struct UserNode *user, struct ChanUser *last); void delChanUser(struct ChanUser *chanuser, int freeChanUser); void removeChanUserFromLists(struct ChanUser *chanuser, int remove_from_userlist, int remove_from_channellist, int freeChanUser); void freeChanUser(struct ChanUser *chanuser); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/ClientSocket.h b/src/ClientSocket.h index 78e207c..34db5d6 100644 --- a/src/ClientSocket.h +++ b/src/ClientSocket.h @@ -77,19 +77,20 @@ struct ClientSocket { struct ClientSocket *next; }; -struct ClientSocket* create_socket(char *host, int port, char *bindto, char *pass, char *nick, char *ident, char *realname); -int connect_socket(struct ClientSocket *client); -int close_socket(struct ClientSocket *client); -int disconnect_socket(struct ClientSocket *client); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ struct ClientSocket* create_socket(char *host, int port, char *bindto, char *pass, char *nick, char *ident, char *realname); +/* MODULAR ACCESSIBLE */ int connect_socket(struct ClientSocket *client); +/* MODULAR ACCESSIBLE */ int close_socket(struct ClientSocket *client); +/* MODULAR ACCESSIBLE */ int disconnect_socket(struct ClientSocket *client); int write_socket_force(struct ClientSocket *client, char* msg, int len); -int write_socket(struct ClientSocket *client, char* msg, int len); +/* MODULAR ACCESSIBLE */ int write_socket(struct ClientSocket *client, char* msg, int len); #ifdef HAVE_THREADS int clientsocket_parseorder_top(unsigned int tid); #endif int socket_loop(int timeout_seconds); -void putsock(struct ClientSocket *client, const char *text, ...) PRINTF_LIKE(2, 3); -struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot); +/* MODULAR ACCESSIBLE */ void putsock(struct ClientSocket *client, const char *text, ...) PRINTF_LIKE(2, 3); +/* MODULAR ACCESSIBLE */ struct ClientSocket* getBots(int flags, struct ClientSocket* last_bot); void init_sockets(); void free_sockets(); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 231871c..fb529da 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -19,9 +19,10 @@ #define _ConfigParser_h #include "main.h" +#ifndef DND_FUNCTIONS int loadConfig(const char *filename); -int get_int_field(char *field_path); -char *get_string_field(char *field_path); +/* MODULAR ACCESSIBLE */ int get_int_field(char *field_path); +/* MODULAR ACCESSIBLE */ char *get_string_field(char *field_path); void free_loaded_config(); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/DBHelper.h b/src/DBHelper.h index 01658f4..55c782c 100644 --- a/src/DBHelper.h +++ b/src/DBHelper.h @@ -25,21 +25,25 @@ struct ChanNode; #define DB_CHANUSER_AUTOINVITE 0x02 #define DB_CHANUSER_NOAUTOOP 0x04 -void _loadUserSettings(struct UserNode* user); #define loadUserSettings(USER) if((USER->flags & USERFLAG_ISAUTHED) && !(USER->flags & USERFLAG_LOADED_SETTINGS)) _loadUserSettings(USER) -int isGodMode(struct UserNode *user); -char *getChanDefault(char *channel_setting); -int getChannelAccess(struct UserNode *user, struct ChanNode *chan); -int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_501); -void _loadChannelSettings(struct ChanNode *chan); #define loadChannelSettings(CHAN) if(!(CHAN->flags & CHANFLAG_REQUESTED_CHANINFO)) _loadChannelSettings(CHAN) -int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer); -char *getBanAffectingMask(struct ChanNode *chan, char *mask); //returns bans that match a given mask eg. *!*@ab* if you pass *!*@abcdefg.* +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ void _loadUserSettings(struct UserNode* user); +/* MODULAR ACCESSIBLE */ int isGodMode(struct UserNode *user); +/* MODULAR ACCESSIBLE */ char *getChanDefault(char *channel_setting); +/* MODULAR ACCESSIBLE */ int getChannelAccess(struct UserNode *user, struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ int checkChannelAccess(struct UserNode *user, struct ChanNode *chan, char *channel_setting, int allow_501); +/* MODULAR ACCESSIBLE */ void _loadChannelSettings(struct ChanNode *chan); -int renameAccount(char *oldauth, char *newauth); +/* MODULAR ACCESSIBLE */ int isUserProtected(struct ChanNode *chan, struct UserNode *victim, struct UserNode *issuer); -void deleteUser(int userid); +/* MODULAR ACCESSIBLE */ char *getBanAffectingMask(struct ChanNode *chan, char *mask); //returns bans that match a given mask eg. *!*@ab* if you pass *!*@abcdefg.* + +/* MODULAR ACCESSIBLE */ int renameAccount(char *oldauth, char *newauth); + +/* MODULAR ACCESSIBLE */ void deleteUser(int userid); void init_DBHelper(); -#endif \ No newline at end of file +#endif +#endif diff --git a/src/EventLogger.h b/src/EventLogger.h index 4b8927c..312aa21 100644 --- a/src/EventLogger.h +++ b/src/EventLogger.h @@ -35,8 +35,9 @@ struct Event { struct Event *next; }; +#ifndef DND_FUNCTIONS struct Event *createEvent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct cmd_binding *command, char **args, int argc, int flags); -void logEvent(struct Event *event); +/* MODULAR ACCESSIBLE */ void logEvent(struct Event *event); void destroyEvents(); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/HandleInfoHandler.h b/src/HandleInfoHandler.h index d5bb9bd..c44b9a1 100644 --- a/src/HandleInfoHandler.h +++ b/src/HandleInfoHandler.h @@ -25,9 +25,10 @@ struct UserNode; #define AUTHLOOKUP_CALLBACK(NAME) void NAME(UNUSED_ARG(char *auth), UNUSED_ARG(int exists), UNUSED_ARG(time_t registered), UNUSED_ARG(void *data)) typedef AUTHLOOKUP_CALLBACK(authlookup_callback_t); +#ifndef DND_FUNCTIONS void clear_handleinfoqueue(struct ClientSocket *client); -void lookup_authname(char *auth, authlookup_callback_t callback, void *data); +/* MODULAR ACCESSIBLE */ void lookup_authname(char *auth, authlookup_callback_t callback, void *data); void init_handleinfohandler(); void free_handleinfohandler(); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/IRCEvents.c b/src/IRCEvents.c index eb29a09..9e0222b 100644 --- a/src/IRCEvents.c +++ b/src/IRCEvents.c @@ -24,6 +24,7 @@ struct binding { void *func; + int module_id; struct binding *next; }; @@ -66,6 +67,25 @@ void free_bind() { free(binds); } +void unregister_module_events(int module_id) { + struct binding *cbind, *next, *prev; + int i; + for(i = 0; i < TOTAL_BIND_TYPES; i++) { + prev = NULL; + for(cbind = binds[i]; cbind; cbind = next) { + next = cbind->next; + if(cbind->module_id == module_id) { + if(prev) + prev->next = next; + else + binds[i] = next; + free(cbind); + } else + prev = cbind; + } + } +} + static int is_bound(unsigned char type, void *func) { struct binding *cbind; for(cbind = binds[type]; cbind; cbind = cbind->next) { @@ -76,7 +96,7 @@ static int is_bound(unsigned char type, void *func) { } #define FUNC_BIND(NAME,FUNCTYPE,TYPE) \ -int bind_##NAME(FUNCTYPE *func) { \ +int bind_##NAME(FUNCTYPE *func, int module_id) { \ if(!is_bound(TYPE, func)) { \ struct binding *cbind = malloc(sizeof(*cbind)); \ if (!cbind) { \ @@ -84,6 +104,7 @@ int bind_##NAME(FUNCTYPE *func) { \ return 0; \ } \ cbind->func = func; \ + cbind->module_id = module_id \ cbind->next = binds[TYPE]; \ binds[TYPE] = cbind; \ return 1; \ diff --git a/src/IRCEvents.h b/src/IRCEvents.h index ceccd64..ff4b972 100644 --- a/src/IRCEvents.h +++ b/src/IRCEvents.h @@ -24,102 +24,143 @@ struct ChanNode; struct ChanUser; struct ClientSocket; +#ifndef DND_FUNCTIONS void init_bind(); void free_bind(); +void unregister_module_events(int module_id); +#endif typedef void join_func_t(struct ChanUser *chanuser); -int bind_join(join_func_t *func); -void unbind_join(join_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_join(join_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_join(join_func_t *func); int event_join(struct ChanUser *chanuser); +#endif typedef void nick_func_t(struct UserNode *user, char *new_nick); -int bind_nick(nick_func_t *func); -void unbind_nick(nick_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_nick(nick_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_nick(nick_func_t *func); int event_nick(struct UserNode *user, char *new_nick); +#endif typedef void part_func_t(struct ChanUser *chanuser, char *reason); -int bind_part(part_func_t *func); -void unbind_part(part_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_part(part_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_part(part_func_t *func); int event_part(struct ChanUser *chanuser, char *reason); +#endif typedef void quit_func_t(struct UserNode *user, char *reason); -int bind_quit(quit_func_t *func); -void unbind_quit(quit_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_quit(quit_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_quit(quit_func_t *func); int event_quit(struct UserNode *user, char *reason); +#endif typedef void kick_func_t(struct UserNode *user, struct ChanUser *target, char *reason); -int bind_kick(kick_func_t *func); -void unbind_kick(kick_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_kick(kick_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_kick(kick_func_t *func); int event_kick(struct UserNode *user, struct ChanUser *target, char *reason); +#endif typedef void topic_func_t(struct UserNode *user, struct ChanNode *chan, const char *new_topic); -int bind_topic(topic_func_t *func); -void unbind_topic(topic_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_topic(topic_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_topic(topic_func_t *func); int event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic); +#endif typedef void mode_func_t(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc); -int bind_mode(mode_func_t *func); -void unbind_mode(mode_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_mode(mode_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_mode(mode_func_t *func); int event_mode(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc); +#endif typedef void chanmsg_func_t(struct UserNode *user, struct ChanNode *chan, char *message); -int bind_chanmsg(chanmsg_func_t *func); -void unbind_chanmsg(chanmsg_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_chanmsg(chanmsg_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_chanmsg(chanmsg_func_t *func); int event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message); +#endif typedef void privmsg_func_t(struct UserNode *user, struct UserNode *target, char *message); -int bind_privmsg(privmsg_func_t *func); -void unbind_privmsg(privmsg_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_privmsg(privmsg_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_privmsg(privmsg_func_t *func); int event_privmsg(struct UserNode *user, struct UserNode *target, char *message); +#endif typedef void channotice_func_t(struct UserNode *user, struct ChanNode *chan, char *message); -int bind_channotice(channotice_func_t *func); -void unbind_channotice(channotice_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_channotice(channotice_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_channotice(channotice_func_t *func); int event_channotice(struct UserNode *user, struct ChanNode *chan, char *message); +#endif typedef void privnotice_func_t(struct UserNode *user, struct UserNode *target, char *message); -int bind_privnotice(privnotice_func_t *func); -void unbind_privnotice(privnotice_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_privnotice(privnotice_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_privnotice(privnotice_func_t *func); int event_privnotice(struct UserNode *user, struct UserNode *target, char *message); +#endif typedef void chanctcp_func_t(struct UserNode *user, struct ChanNode *chan, char *command, char *text); -int bind_chanctcp(chanctcp_func_t *func); -void unbind_chanctcp(chanctcp_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_chanctcp(chanctcp_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_chanctcp(chanctcp_func_t *func); int event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text); +#endif typedef void privctcp_func_t(struct UserNode *user, struct UserNode *target, char *command, char *text); -int bind_privctcp(privctcp_func_t *func); -void unbind_privctcp(privctcp_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_privctcp(privctcp_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_privctcp(privctcp_func_t *func); int event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text); +#endif typedef void invite_func_t(struct ClientSocket *client, struct UserNode *user, char *channel); -int bind_invite(invite_func_t *func); -void unbind_invite(invite_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_invite(invite_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_invite(invite_func_t *func); int event_invite(struct ClientSocket *client, struct UserNode *user, char *channel); +#endif typedef void raw_func_t(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc); -int bind_raw(raw_func_t *func); -void unbind_raw(raw_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_raw(raw_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_raw(raw_func_t *func); int event_raw(struct ClientSocket *client, char *from, char *cmd, char **argv, int argc); +#endif typedef void bot_ready_func_t(struct ClientSocket *client); -int bind_bot_ready(bot_ready_func_t *func); -void unbind_bot_ready(bot_ready_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_bot_ready(bot_ready_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_bot_ready(bot_ready_func_t *func); int event_bot_ready(struct ClientSocket *client); +#endif typedef int registered_func_t(struct UserNode *old_user, struct UserNode *new_user); -int bind_registered(registered_func_t *func); -void unbind_registered(registered_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_registered(registered_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_registered(registered_func_t *func); int event_registered(struct UserNode *old_user, struct UserNode *new_user); +#endif typedef int freeuser_func_t(struct UserNode *user); -int bind_freeuser(freeuser_func_t *func); -void unbind_freeuser(freeuser_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_freeuser(freeuser_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_freeuser(freeuser_func_t *func); int event_freeuser(struct UserNode *user); +#endif typedef int freechan_func_t(struct ChanNode *chan); -int bind_freechan(freechan_func_t *func); -void unbind_freechan(freechan_func_t *func); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int bind_freechan(freechan_func_t *func, int module_id); +/* MODULAR ACCESSIBLE */ void unbind_freechan(freechan_func_t *func); int event_freechan(struct ChanNode *chan); +#endif -#endif \ No newline at end of file +#endif diff --git a/src/IRCParser.h b/src/IRCParser.h index 7731cb7..cdf2714 100644 --- a/src/IRCParser.h +++ b/src/IRCParser.h @@ -31,6 +31,7 @@ struct irc_cmd { struct irc_cmd *next; }; +#ifndef DND_FUNCTIONS extern int statistics_privmsg; extern int statistics_network_users; extern int statistics_network_channels; @@ -39,8 +40,8 @@ int parse_lines(struct ClientSocket *client, char *lines, int len); void bot_disconnect(struct ClientSocket *client); void init_parser(); void free_parser(); -void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...); -char* merge_argv(char **argv, int start, int end); -char* merge_argv_char(char **argv, int start, int end, char seperator); - -#endif \ No newline at end of file +/* MODULAR ACCESSIBLE */ void reply(struct ClientSocket *client, struct UserNode *user, const char *text, ...); +/* MODULAR ACCESSIBLE */ char* merge_argv(char **argv, int start, int end); +/* MODULAR ACCESSIBLE */ char* merge_argv_char(char **argv, int start, int end, char seperator); +#endif +#endif diff --git a/src/ModeNode.h b/src/ModeNode.h index 29121c0..07f0257 100644 --- a/src/ModeNode.h +++ b/src/ModeNode.h @@ -44,19 +44,18 @@ struct ModeNode { int *mode_int_args; }; -extern unsigned int valid_modes[]; - +#ifndef DND_FUNCTIONS void init_ModeNode(); -struct ModeNode *createModeNode(struct ChanNode *chan); -void freeModeNode(struct ModeNode *modes); -int isModeSet(struct ModeNode* modes, char modeChar); -int isModeAffected(struct ModeNode* modes, char modeChar); -void* getModeValue(struct ModeNode* modes, char modeChar); -unsigned int getModeType(struct ModeNode* modes, char modeChar); -void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc); -void parseModeString(struct ModeNode* modes, char *modeStr); -int parseMode(struct ModeNode* modes, int add, char mode, char *param); -void getModeString(struct ModeNode* modes, char *modesStr); -void getFullModeString(struct ModeNode* modes, char *modesStr); - -#endif \ No newline at end of file +/* MODULAR ACCESSIBLE */ struct ModeNode *createModeNode(struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ void freeModeNode(struct ModeNode *modes); +/* MODULAR ACCESSIBLE */ int isModeSet(struct ModeNode* modes, char modeChar); +/* MODULAR ACCESSIBLE */ int isModeAffected(struct ModeNode* modes, char modeChar); +/* MODULAR ACCESSIBLE */ void* getModeValue(struct ModeNode* modes, char modeChar); +/* MODULAR ACCESSIBLE */ unsigned int getModeType(struct ModeNode* modes, char modeChar); +/* MODULAR ACCESSIBLE */ void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc); +/* MODULAR ACCESSIBLE */ void parseModeString(struct ModeNode* modes, char *modeStr); +/* MODULAR ACCESSIBLE */ int parseMode(struct ModeNode* modes, int add, char mode, char *param); +/* MODULAR ACCESSIBLE */ void getModeString(struct ModeNode* modes, char *modesStr); +/* MODULAR ACCESSIBLE */ void getFullModeString(struct ModeNode* modes, char *modesStr); +#endif +#endif diff --git a/src/UserNode.h b/src/UserNode.h index bf07e7e..fb1afc1 100644 --- a/src/UserNode.h +++ b/src/UserNode.h @@ -59,17 +59,18 @@ struct UserNode { #define isNetworkService(USER) (USER->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP | USERFLAG_ISSERVER)) #define isBot(USER) (USER->flags & (USERFLAG_ISBOT)) +#ifndef DND_FUNCTIONS void init_UserNode(); void free_UserNode(); -int is_valid_nick(const char *nick); -struct UserNode* getUserByNick(const char *nick); -struct UserNode* getUserByMask(const char *mask); -int countUsersWithHost(char *host); -char *getAuthFakehost(char *auth); -struct UserNode* searchUserByNick(const char *nick); -struct UserNode* getAllUsers(struct UserNode *last); -struct UserNode* getUsersWithAuth(const char *auth, struct UserNode *last); -int getUserCount(); +/* MODULAR ACCESSIBLE */ int is_valid_nick(const char *nick); +/* MODULAR ACCESSIBLE */ struct UserNode* getUserByNick(const char *nick); +/* MODULAR ACCESSIBLE */ struct UserNode* getUserByMask(const char *mask); +/* MODULAR ACCESSIBLE */ int countUsersWithHost(char *host); +/* MODULAR ACCESSIBLE */ char *getAuthFakehost(char *auth); +/* MODULAR ACCESSIBLE */ struct UserNode* searchUserByNick(const char *nick); +/* MODULAR ACCESSIBLE */ struct UserNode* getAllUsers(struct UserNode *last); +/* MODULAR ACCESSIBLE */ struct UserNode* getUsersWithAuth(const char *auth, struct UserNode *last); +/* MODULAR ACCESSIBLE */ int getUserCount(); struct UserNode* addUser(const char *nick); struct UserNode* addUserMask(const char *mask); struct UserNode* createTempUser(const char *nick); @@ -77,5 +78,5 @@ struct UserNode* createTempUserMask(const char *mask); int renameUser(struct UserNode* user, const char *new_nick); void delUser(struct UserNode* user, int freeUser); void clearTempUsers(); - +#endif #endif diff --git a/src/WHOHandler.c b/src/WHOHandler.c index 2854718..743896e 100644 --- a/src/WHOHandler.c +++ b/src/WHOHandler.c @@ -22,6 +22,7 @@ #include "ModeNode.h" #include "ClientSocket.h" #include "IPNode.h" +#include "modules.h" #define WHOQUEUETYPE_ISONQUEUE 0x01 #define WHOQUEUETYPE_USERLIST 0x02 @@ -38,6 +39,7 @@ struct WHOQueueEntry { struct UserNode *user; struct WHOQueueEntry *next; void *callback[MAXCALLBACKS]; + int module_id[MAXCALLBACKS]; void *data[MAXCALLBACKS]; }; @@ -114,7 +116,7 @@ void clear_whoqueue(struct ClientSocket *client) { DESYNCHRONIZE(whohandler_sync); } -void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data) { +void get_userlist(struct ChanNode *chan, int module_id, userlist_callback_t callback, void *data) { struct ClientSocket *bot; for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { if(isUserOnChan(bot->user, chan)) @@ -137,6 +139,7 @@ void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *dat entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST; entry->chan = chan; entry->callback[0] = callback; + entry->module_id[0] = module_id; int i; for(i = 1; i < MAXCALLBACKS; i++) entry->callback[i] = NULL; @@ -148,7 +151,7 @@ void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *dat callback(bot, chan, data); } -void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data, int force) { +void _get_userlist_with_invisible(struct ChanNode *chan, int module_id, userlist_callback_t callback, void *data, int force) { struct ClientSocket *bot; for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { if(isUserOnChan(bot->user, chan)) @@ -172,6 +175,7 @@ void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t cal entry->type = WHOQUEUETYPE_ISONQUEUE | WHOQUEUETYPE_USERLIST; entry->chan = chan; entry->callback[0] = callback; + entry->module_id[0] = module_id; int i; for(i = 1; i < MAXCALLBACKS; i++) entry->callback[i] = NULL; @@ -183,7 +187,7 @@ void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t cal callback(bot, chan, data); } -void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data) { +void get_userauth(struct UserNode *user, int module_id, userauth_callback_t callback, void *data) { //check if we have already an active WHO for this user struct ClientSocket *bot, *whobot = NULL; struct WHOQueueEntry *entry; @@ -194,6 +198,7 @@ void get_userauth(struct UserNode *user, userauth_callback_t callback, void *dat for(i = 1; i < MAXCALLBACKS; i++) { if(!entry->callback[i]) { entry->callback[i] = callback; + entry->module_id[i] = module_id; entry->data[i] = data; return; } @@ -219,6 +224,7 @@ void get_userauth(struct UserNode *user, userauth_callback_t callback, void *dat entry->user = user; user->flags |= USERFLAG_IS_ON_WHO_QUEUE; entry->callback[0] = callback; + entry->module_id[0] = module_id; int i; for(i = 1; i < MAXCALLBACKS; i++) entry->callback[i] = NULL; @@ -319,7 +325,8 @@ static void _recv_whohandler_354(struct ClientSocket *client, char **argv, unsig for(i = 0; i < MAXCALLBACKS; i++) { userauth_callback_t *callback = entry->callback[i]; if(!callback) break; - callback(client, entry->user->nick, entry->user, entry->data[i]); + if(!entry->module_id[i] || module_loaded(entry->module_id[i])) + callback(client, entry->user->nick, entry->user, entry->data[i]); } } } @@ -352,7 +359,8 @@ static void _recv_whohandler_315(struct ClientSocket *client, char **argv, unsig for(i = 0; i < MAXCALLBACKS; i++) { callback = entry->callback[i]; if(!callback) break; - callback(client, entry->chan, entry->data[i]); + if(!entry->module_id[i] || module_loaded(entry->module_id[i])) + callback(client, entry->chan, entry->data[i]); } if(entry->chan->flags & CHANFLAG_HAVE_INVISIBLES) { //remove all invisible users again @@ -371,7 +379,8 @@ static void _recv_whohandler_315(struct ClientSocket *client, char **argv, unsig for(i = 0; i < MAXCALLBACKS; i++) { callback = entry->callback[i]; if(!callback) break; - callback(client, entry->user->nick, NULL, entry->data[i]); + if(!entry->module_id[i] || module_loaded(entry->module_id[i])) + callback(client, entry->user->nick, NULL, entry->data[i]); } } entry->user->flags &= ~USERFLAG_IS_ON_WHO_QUEUE; diff --git a/src/WHOHandler.h b/src/WHOHandler.h index 68ad205..76b279b 100644 --- a/src/WHOHandler.h +++ b/src/WHOHandler.h @@ -29,14 +29,16 @@ typedef USERLIST_CALLBACK(userlist_callback_t); #define USERAUTH_CALLBACK(NAME) void NAME(UNUSED_ARG(struct ClientSocket *client), UNUSED_ARG(char *user_nick), UNUSED_ARG(struct UserNode *user), UNUSED_ARG(void *data)) typedef USERAUTH_CALLBACK(userauth_callback_t); +#define get_userlist_if_invisible(CHAN, MODID, CALLBACK, DATA) _get_userlist_with_invisible(CHAN, MODID, CALLBACK, DATA, 0) +#define get_userlist_with_invisible(CHAN, MODID, CALLBACK, DATA) _get_userlist_with_invisible(CHAN, MODID, CALLBACK, DATA, 1) + +#ifndef DND_FUNCTIONS void clear_whoqueue(struct ClientSocket *client); void recv_whohandler_354(struct ClientSocket *client, char **argv, unsigned int argc); void recv_whohandler_315(struct ClientSocket *client, char **argv, unsigned int argc); -void get_userlist(struct ChanNode *chan, userlist_callback_t callback, void *data); -#define get_userlist_if_invisible(CHAN, CALLBACK, DATA) _get_userlist_with_invisible(CHAN, CALLBACK, DATA, 0) -#define get_userlist_with_invisible(CHAN, CALLBACK, DATA) _get_userlist_with_invisible(CHAN, CALLBACK, DATA, 1) -void _get_userlist_with_invisible(struct ChanNode *chan, userlist_callback_t callback, void *data, int force); -void get_userauth(struct UserNode *user, userauth_callback_t callback, void *data); +/* MODULAR ACCESSIBLE */ void get_userlist(struct ChanNode *chan, int module_id, userlist_callback_t callback, void *data); +/* MODULAR ACCESSIBLE */ void _get_userlist_with_invisible(struct ChanNode *chan, int module_id, userlist_callback_t callback, void *data, int force); +/* MODULAR ACCESSIBLE */ void get_userauth(struct UserNode *user, int module_id, userauth_callback_t callback, void *data); void free_whoqueue(); - -#endif \ No newline at end of file +#endif +#endif diff --git a/src/bot_DummyServ.c b/src/bot_DummyServ.c deleted file mode 100644 index afcb637..0000000 --- a/src/bot_DummyServ.c +++ /dev/null @@ -1,126 +0,0 @@ -/* bot_DummyServ.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "bot_DummyServ.h" -#include "modcmd.h" -#include "IRCParser.h" -#include "IRCEvents.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "ModeNode.h" -#include "BanNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "version.h" -#include "EventLogger.h" -#include "bots.h" -#include "cmd_neonserv.h" -#include "cmd_neonspam.h" - -#define BOTID 3 -#define BOTALIAS "DummyServ" - -static void dummyserv_bot_ready(struct ClientSocket *client) { - MYSQL_RES *res; - MYSQL_ROW row; - - printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "MODE %s +%s", client->user->nick, row[0]); - } - - printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "JOIN %s %s", row[0], row[1]); - } -} - -static void dummyserv_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { - //this bot doesn't have a trigger - strcpy(trigger, ""); -} - -static void start_bots() { - struct ClientSocket *client; - MYSQL_RES *res, *res2; - MYSQL_ROW row; - - printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); - client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); - client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); - client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); - client->flags |= SOCKET_FLAG_SILENT; - client->botid = BOTID; - client->clientid = atoi(row[7]); - connect_socket(client); - } - - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); - res2 = mysql_use(); - while ((row = mysql_fetch_row(res2)) != NULL) { - if(bind_cmd_to_command(BOTID, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_set_parameters(BOTID, row[0], row[2]); - } - if(row[3]) { - bind_set_global_access(BOTID, row[0], atoi(row[3])); - } - if(row[4]) { - bind_set_channel_access(BOTID, row[0], row[4]); - } - if(strcmp(row[5], "0")) - bind_set_bind_flags(BOTID, row[0], atoi(row[5])); - } - } - bind_unbound_required_functions(BOTID); -} - -void init_DummyServ() { - - set_bot_alias(BOTID, BOTALIAS); - start_bots(); - - //register events - bind_bot_ready(dummyserv_bot_ready); - - set_trigger_callback(BOTID, dummyserv_trigger_callback); -} - -void loop_DummyServ() { - -} - -void free_DummyServ() { - -} - -#undef BOTID -#undef BOTALIAS diff --git a/src/bot_DummyServ.h b/src/bot_DummyServ.h deleted file mode 100644 index 79e6f4b..0000000 --- a/src/bot_DummyServ.h +++ /dev/null @@ -1,26 +0,0 @@ -/* bot_DummyServ.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _bot_DummyServ_h -#define _bot_DummyServ_h - -#include "main.h" - -void init_DummyServ(); -void loop_DummyServ(); -void free_DummyServ(); - -#endif \ No newline at end of file diff --git a/src/bot_NeonHelp.c b/src/bot_NeonHelp.c deleted file mode 100644 index 1922262..0000000 --- a/src/bot_NeonHelp.c +++ /dev/null @@ -1,538 +0,0 @@ -/* bot_NeonHelp.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "bot_NeonHelp.h" -#include "modcmd.h" -#include "cmd_neonhelp.h" -#include "lang.h" -#include "mysqlConn.h" -#include "ClientSocket.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "IRCEvents.h" -#include "IRCParser.h" -#include "bots.h" -#include "DBHelper.h" -#include "WHOHandler.h" - -#define BOTID 4 -#define BOTALIAS "NeonHelp" - -static const struct default_language_entry msgtab[] = { - {"NH_NOT_ON_CHAN_1", "You cannot open this request as you are not in %s."}, /* {ARGS: "#test"} */ - {"NH_NOT_ON_CHAN_2", "You cannot open this request as you are not in %s or %s."}, /* {ARGS: "test", "#test-support"} */ - {"NH_REQUEST_RECORDED", "Your message has been recorded and assigned request ID#%d A helper should contact you shortly."}, /* {ARGS: 5} */ - {"NH_REQUEST_OTHERS_0", "There are no other unhandled requests."}, - {"NH_REQUEST_OTHERS_1", "There is 1 other unhandled request."}, - {"NH_REQUEST_OTHERS_2", "There are %d other unhandled requests."}, /* {ARGS: 1337} */ - {"NH_REQUEST_FOOTER_1", "Everything you tell me until you are helped (or you leave %1$s) will be recorded. If you part %1$s, your request will be lost."}, /* {ARGS: "#test"} */ - {"NH_REQUEST_FOOTER_2", "Everything you tell me until you are helped (or you leave %1$s or %2$s) will be recorded. If you part %1$s or %2$s, your request will be lost."}, /* {ARGS: "#test", "#test-support"} */ - {"NH_NEW_REQUEST", "New request #%d by %s: %s"}, /* {ARGS: 5, "pk910", "Help, I've fallen and I can't get up!"} */ - {"NH_NEXT_NONE", "No more requests."}, - {"NH_NEXT_NOT_FOUND", "No request found."}, - {"NH_NEXT_HEADER", "$bNext request: #%d %s$b"}, /* {ARGS: 5, "pk910"} */ - {"NH_NEXT_HELPER", "Your helper for request ID#%d is %s (Current nick: %s)."}, /* {ARGS: 5, "pk910", "Skynet"} */ - {"NH_NEXT_JOIN", "Please /join %s now."}, /* {ARGS: "#test-support"} */ - {"NH_DELETED", "Your request ID#%d has been deleted."}, /* {ARGS: 5} */ - {"NH_DELETED_STAFF", "Request deleted: #%d (%s)"}, /* {ARGS: 5, "pk910"} */ - {"NH_REMIND_OPEN_REQUESTS_1", "There is %d unhandled request!"}, /* {ARGS: 1} */ - {"NH_REMIND_OPEN_REQUESTS_2", "There are %d unhandled requests!"}, /* {ARGS: 4} */ - {"NH_REQUESTS_HEADER_ID", "ID"}, - {"NH_REQUESTS_HEADER_STATUS", "State"}, - {"NH_REQUESTS_HEADER_NICK", "Nick"}, - {"NH_REQUESTS_HEADER_TIME", "Time"}, - {"NH_REQUESTS_HEADER_REQUEST", "Question"}, - {"NH_REQUESTS_STATE_ACTIVE", "active"}, - {"NH_REQUESTS_STATE_PENDING", "pending"}, - {"NH_REQUESTS_STATE_ERROR", "ERROR"}, - {"NH_STATS_HEADER_USER", "User"}, - {"NH_STATS_HEADER_LAST_24H", "last 24h"}, - {"NH_STATS_HEADER_LAST_7DAY", "last 7d"}, - {"NH_STATS_HEADER_LAST_30DAY", "last 30d"}, - {NULL, NULL} -}; - -static void neonhelp_bot_ready(struct ClientSocket *client) { - MYSQL_RES *res; - MYSQL_ROW row; - - printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "MODE %s +%s", client->user->nick, row[0]); - } - - printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "JOIN %s %s", row[0], row[1]); - } -} - -static void neonhelp_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { - MYSQL_RES *res; - MYSQL_ROW row; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { - strcpy(trigger, "!"); - return; - } - printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); - res = mysql_use(); - if(!(row = mysql_fetch_row(res))) { - strcpy(trigger, "!"); - return; - } - if(row[0] && *row[0]) - strcpy(trigger, row[0]); - else - strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "!")); -} - -static void start_bots() { - struct ClientSocket *client; - MYSQL_RES *res, *res2; - MYSQL_ROW row; - - printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); - client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); - client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); - client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); - client->flags |= SOCKET_FLAG_SILENT; - client->botid = BOTID; - client->clientid = atoi(row[7]); - connect_socket(client); - //close old, still opened requests - printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `botid` = '%d'", client->clientid); - } - - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); - res2 = mysql_use(); - while ((row = mysql_fetch_row(res2)) != NULL) { - if(bind_cmd_to_command(BOTID, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_set_parameters(BOTID, row[0], row[2]); - } - if(row[3]) { - bind_set_global_access(BOTID, row[0], atoi(row[3])); - } - if(row[4]) { - bind_set_channel_access(BOTID, row[0], row[4]); - } - if(strcmp(row[5], "0")) - bind_set_bind_flags(BOTID, row[0], atoi(row[5])); - } - } - bind_unbound_required_functions(BOTID); -} - -static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message); -static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup); -struct neonhelp_event_privmsg_cache { - struct ClientSocket *client; - struct UserNode *user, *target; - char *message; -}; - -static void neonhelp_event_privmsg(struct UserNode *user, struct UserNode *target, char *message) { - struct ClientSocket *client; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->user == target) { - if(client->botid != BOTID) return; - break; - } - } - if(!client) return; //we got the message but we have no client that could receive it??? - if(user->flags & USERFLAG_ISAUTHED) { - neonhelp_event_privmsg_async(client, user, target, message); - } else { - struct neonhelp_event_privmsg_cache *cache = malloc(sizeof(*cache)); - if(!cache) return; - cache->client = client; - cache->user = user; - cache->target = target; - cache->message = strdup(message); - get_userauth(user, neonhelp_event_privmsg_nick_lookup, cache); - } -} - -static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup) { - struct neonhelp_event_privmsg_cache *cache = data; - neonhelp_event_privmsg_async(cache->client, cache->user, cache->target, cache->message); - free(cache->message); - free(cache); -} - -static TIMEQ_CALLBACK(neonhelp_remind_open_requests); - -static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message) { - MYSQL_RES *res; - MYSQL_ROW row, row2; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern`, `helpserv_intern_announce` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) return; - //check if the user is a supporter (access in the support channel) - if((user->flags & USERFLAG_ISAUTHED)) { - int caccess = 0; - int userid; - if(user->flags & USERFLAG_HAS_USERID) - userid = user->user_id; - else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - userid = atoi(row2[0]); - user->user_id = userid; - user->flags |= USERFLAG_HAS_USERID; - } else - userid = 0; - } - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - int cflags = atoi(row2[1]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) - caccess = atoi(row2[0]); - } - if(caccess) return; //ignore messages from supporters - } - //check if the user is in one of the bot's channels - struct ChanUser *chanuser; - struct ChanNode *chan; - for(chanuser = getUserChannels(target, NULL); chanuser; chanuser = getUserChannels(target, chanuser)) { - chan = chanuser->chan; - if((!stricmp(chan->name, row[0]) || (row[1] && !stricmp(chan->name, row[1]))) && isUserOnChan(user, chan)) - break; - } - if(!chanuser) { - if(row[1]) - reply(client, user, "NH_NOT_ON_CHAN_2", row[0], row[1]); - else - reply(client, user, "NH_NOT_ON_CHAN_1", row[0]); - return; - } - //check if there is already a support request - int others = 0; - if(client->flags & SOCKET_HAVE_HELPNODE) { - struct NeonHelpNode *helpnode; - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->user == user) { - //simply append the message to the database - printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = %d", helpnode->suppid); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - char *old_msg = escape_string(row2[0]); - char *new_msg = escape_string(message); - printf_long_mysql_query(1024 + strlen(old_msg) + strlen(new_msg), "UPDATE `helpserv_requests` SET `text` = '%s\n%s' WHERE `id` = %d", old_msg, new_msg, helpnode->suppid); - } - return; - } - others++; - } - } - //add new request - struct NeonHelpNode *helpnode = malloc(sizeof(*helpnode)); - if(!helpnode) return; - helpnode->user = user; - helpnode->logchan = getChanByName(row[0]); - helpnode->status = 0; - helpnode->announce = (row[2] && strcmp(row[3], "0") ? 1 : 0); - if(helpnode->announce) { - char nameBuf[30]; - sprintf(nameBuf, "neonhelp_%d", client->clientid); - if(!timeq_name_exists(nameBuf)) { - int *cidptr = malloc(sizeof(int)); - *cidptr = client->clientid; - timeq_add_name(nameBuf, 300, neonhelp_remind_open_requests, cidptr); - } - } - printf_mysql_query("INSERT INTO `helpserv_requests` (`botid`, `host`, `hand`, `nick`, `status`, `supporter`, `time`, `text`) VALUES ('%d', '%s@%s', '%s', '%s', '0', '-1', UNIX_TIMESTAMP(), '%s')", client->clientid, escape_string(user->ident), escape_string(user->host), ((user->flags & USERFLAG_ISAUTHED) ? escape_string(user->auth) : "*"), escape_string(user->nick), escape_string(message)); - helpnode->suppid = (int) mysql_insert_id(get_mysql_conn()); - helpnode->log = NULL; - helpnode->next = ((client->flags & SOCKET_HAVE_HELPNODE) ? client->botclass_helpnode : NULL); - client->botclass_helpnode = helpnode; - client->flags |= SOCKET_HAVE_HELPNODE; - //build the user reply... - char user_reply[MAXLEN]; - int user_reply_pos = 0; - char reply_buff[MAXLEN]; - //1st part: NH_REQUEST_RECORDED - strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_RECORDED", helpnode->suppid)); - user_reply_pos += strlen(reply_buff); - //2nd part: NH_REQUEST_OTHERS_0 / NH_REQUEST_OTHERS_1 / NH_REQUEST_OTHERS_2 - user_reply[user_reply_pos++] = ' '; - if(others <= 1) - strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, (others ? "NH_REQUEST_OTHERS_1" : "NH_REQUEST_OTHERS_0"))); - else - strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_OTHERS_2", others)); - user_reply_pos += strlen(reply_buff); - //3th part: NH_REQUEST_FOOTER_1 / NH_REQUEST_FOOTER_2 - user_reply[user_reply_pos++] = ' '; - if(row[1]) - strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_2", row[0], row[1])); - else - strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_1", row[0])); - user_reply_pos += strlen(reply_buff); - reply(client, user, "%s", user_reply); - //sent a message to the internal channel / onotice to supp channel - build_language_string(user, reply_buff, "NH_NEW_REQUEST", helpnode->suppid, user->nick, message); - if(row[2]) { - putsock(client, "PRIVMSG %s :%s", row[2], reply_buff); - } else { - putsock(client, "NOTICE @%s :%s", row[0], reply_buff); - } -} - -static TIMEQ_CALLBACK(neonhelp_remind_open_requests) { - int clientid = *((int*)data); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern`, `helpserv_intern_announce` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res)) || !row[2]) { - free(data); - return; - } - struct ClientSocket *client; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->clientid == clientid) - break; - } - if(!client) { - free(data); - return; - } - //count open requests - int requests = 0; - struct NeonHelpNode *helpnode; - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->status == 0) { - requests++; - } - } - } - if(requests) { - char nameBuf[30]; - sprintf(nameBuf, "neonhelp_%d", client->clientid); - if(!timeq_name_exists(nameBuf)) { - timeq_add_name(nameBuf, 300, neonhelp_remind_open_requests, data); - } - char replybuf[MAXLEN]; - build_language_string(NULL, replybuf, (requests == 1 ? "NH_REMIND_OPEN_REQUESTS_1" : "NH_REMIND_OPEN_REQUESTS_2"), requests); - putsock(client, "PRIVMSG %s :%s", row[2], replybuf); - } else - free(data); -} - -static void neonhelp_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { - char logline[MAXLEN]; - sprintf(logline, "<%s> %s", user->nick, message); - struct ClientSocket *client; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->botid == BOTID) { - struct NeonHelpNode *helpnode; - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->logchan == chan && helpnode->status == 1) { - if(!helpnode->log) { - helpnode->log = calloc(LOGBUFFERLINES, sizeof(char*)); - if(!helpnode->log) return; - } - int i; - for(i = 0; i < LOGBUFFERLINES; i++) { - if(!helpnode->log[i]) { - helpnode->log[i] = strdup(logline); - break; - } - } - if(i == LOGBUFFERLINES) { - //write buffer to database - char logbuff[MAXLEN * LOGBUFFERLINES]; - int len = 0; - for(i = 0; i < LOGBUFFERLINES; i++) { - len += sprintf(logbuff + len, "%s\n", helpnode->log[i]); - free(helpnode->log[i]); - helpnode->log[i] = NULL; - } - printf_long_mysql_query(1024 + len, "UPDATE `helpserv_requests` SET `log` = CONCAT(`log`, '%s') WHERE `id` = %d", escape_string(logbuff), helpnode->suppid); - } - break; - } - } - } - } - } -} - -static void destroy_support_request(struct ClientSocket *client, struct NeonHelpNode *helpnode, int do_reply) { - //write buffer to database - char logbuff[MAXLEN * LOGBUFFERLINES]; - int len = 0; - int i; - if(helpnode->log) { - for(i = 0; i < LOGBUFFERLINES; i++) { - if(!helpnode->log[i]) break; - len += sprintf(logbuff + len, "%s\n", helpnode->log[i]); - free(helpnode->log[i]); - helpnode->log[i] = NULL; - } - free(helpnode->log); - } else - logbuff[0] = '\0'; - printf_long_mysql_query(1024 + len, "UPDATE `helpserv_requests` SET `status`='2', `log` = CONCAT(`log`, '%s') WHERE `id` = %d", escape_string(logbuff), helpnode->suppid); - if(do_reply) { - reply(client, helpnode->user, "NH_DELETED", helpnode->suppid); - } - free(helpnode); -} - -static void neonhelp_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { - struct ClientSocket *client; - MYSQL_RES *res; - MYSQL_ROW row; - struct ChanNode *support, *public; - int userHasRequest; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { - userHasRequest = 0; - struct NeonHelpNode *helpnode, *prev_helpnode = NULL; - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->user == target->user) { - userHasRequest = 1; - break; - } else - prev_helpnode = helpnode; - } - } - if(!userHasRequest) continue; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) continue; - support = getChanByName(row[0]); - public = (row[1] ? getChanByName(row[1]) : NULL); - if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { - //free the user's support request - if(prev_helpnode) - prev_helpnode->next = helpnode->next; - else - client->botclass_helpnode = helpnode->next; - destroy_support_request(client, helpnode, 1); - } - } - } -} - -static void neonhelp_event_part(struct ChanUser *target, char *reason) { - struct ClientSocket *client; - MYSQL_RES *res; - MYSQL_ROW row; - struct ChanNode *support, *public; - int userHasRequest; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { - userHasRequest = 0; - struct NeonHelpNode *helpnode, *prev_helpnode = NULL; - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->user == target->user) { - userHasRequest = 1; - break; - } else - prev_helpnode = helpnode; - } - } - if(!userHasRequest) continue; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) continue; - support = getChanByName(row[0]); - public = (row[1] ? getChanByName(row[1]) : NULL); - if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { - //free the user's support request - if(prev_helpnode) - prev_helpnode->next = helpnode->next; - else - client->botclass_helpnode = helpnode->next; - destroy_support_request(client, helpnode, 1); - } - } - } -} - -static void neonhelp_event_quit(struct UserNode *target, char *reason) { - struct ClientSocket *client; - int userHasRequest; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->botid == BOTID) { - userHasRequest = 0; - struct NeonHelpNode *helpnode, *prev_helpnode = NULL; - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->user == target) { - userHasRequest = 1; - break; - } else - prev_helpnode = helpnode; - } - } - if(!userHasRequest) continue; - //free the user's support request - if(prev_helpnode) - prev_helpnode->next = helpnode->next; - else - client->botclass_helpnode = helpnode->next; - destroy_support_request(client, helpnode, 0); - } - } -} - -void init_NeonHelp() { - - set_bot_alias(BOTID, BOTALIAS); - start_bots(); - - //register events - bind_bot_ready(neonhelp_bot_ready); - bind_privmsg(neonhelp_event_privmsg); - bind_chanmsg(neonhelp_event_chanmsg); - bind_part(neonhelp_event_part); - bind_kick(neonhelp_event_kick); - bind_quit(neonhelp_event_quit); - - set_trigger_callback(BOTID, neonhelp_trigger_callback); - - register_default_language_table(msgtab); -} - -void loop_NeonHelp() { - -} - -void free_NeonHelp() { - -} - -#undef BOTID -#undef BOTALIAS diff --git a/src/bot_NeonHelp.h b/src/bot_NeonHelp.h deleted file mode 100644 index 2cbf694..0000000 --- a/src/bot_NeonHelp.h +++ /dev/null @@ -1,45 +0,0 @@ -/* bot_NeonHelp.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _bot_NeonHelp_h -#define _bot_NeonHelp_h - -#include "main.h" - -/* definition for ClientSocket struct */ -#define botclass_helpnode botclassvalue1 -#define SOCKET_HAVE_HELPNODE SOCKET_HAVE_BOTCLASSVALUE1 - -#define LOGBUFFERLINES 20 - -struct UserNode; -struct ChanNode; - -struct NeonHelpNode { - struct UserNode *user; - int suppid; - char status:6; - char announce:2; - struct NeonHelpNode *next; - struct ChanNode *logchan; - char **log; -}; - -void init_NeonHelp(); -void loop_NeonHelp(); -void free_NeonHelp(); - -#endif \ No newline at end of file diff --git a/src/bot_NeonServ.c b/src/bot_NeonServ.c deleted file mode 100644 index 61d41d6..0000000 --- a/src/bot_NeonServ.c +++ /dev/null @@ -1,523 +0,0 @@ -/* bot_NeonServ.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "bot_NeonServ.h" -#include "modcmd.h" -#include "IRCEvents.h" -#include "IRCParser.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "BanNode.h" -#include "ModeNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "EventLogger.h" -#include "cmd_neonserv.h" -#include "ConfigParser.h" - -#define BOTID 1 -#define BOTALIAS "NeonServ" - -static const struct default_language_entry msgtab[] = { - {"NS_USER_UNKNOWN", "User with nick $b%s$b does not exist."}, /* {ARGS: "TestUser"} */ - {"NS_AUTH_UNKNOWN", "Account $b%s$b has not been registered."}, /* {ARGS: "TestAuth"} */ - {"NS_USER_NEED_AUTH", "%s must first authenticate with $bAuthServ$b."}, /* {ARGS: "TestUser"} */ - {"NS_YOU_NEED_AUTH", "You must first authenticate with $bAuthServ$b."}, - {"NS_INVALID_ACCESS", "$b%d$b is an invalid access level."}, /* {ARGS: 1337} */ - {"NS_ADDUSER_ALREADY_ADDED", "%s is already on the $b%s$b user list (with access %d)."}, /* {ARGS: "TestUser", "#TestChan", 123} */ - {"NS_ADDUSER_DONE", "Added %s to the %s user list with access %d."}, /* {ARGS: "TestUser", "#TestChan", 123} */ - {"NS_NOT_ON_USERLIST", "%s lacks access to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_NOT_ON_USERLIST_YOU", "You lack access to $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_NOT_ON_CHANNEL", "%s isn't currently in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_NOT_ON_CHANNEL_YOU", "You aren't currently in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DELUSER_DONE", "Deleted %s (with access %d) from the %s user list."}, /* {ARGS: "TestUser", 123, "#TestChan"} */ - {"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."}, - {"NS_USER_OUTRANKED", "$b%s$b outranks you (command has no effect)."}, /* {ARGS: "TestUser"} */ - {"NS_ACCESS_DENIED", "Access denied."}, - {"NS_NO_ACCESS", "You lack sufficient access to use this command."}, - {"NS_USER_PROTECTED", "Sorry, $b%s$b is protected."}, /* {ARGS: "TestUser"} */ - {"NS_SERVICE_IMMUNE", "$b%s$b may not be kicked, killed, banned, or deopped."}, /* {ARGS: "TestUser"} */ - {"NS_YOU_PROTECTED", "You may not kick or ban yourself."}, - {"NS_TABLE_NONE", " None"}, - {"NS_TABLE_COUNT", "Found $b%d$b matches."}, /* {ARGS: 5} */ - {"NS_BAN_ALREADY_ADDED", "$b%s$b is already banned in %s."}, /* {ARGS: "*!*@moeeep.*", "#TestChan"} */ - {"NS_INVALID_ACCESS_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)."}, /* {ARGS: 450, 400} */ - {"NS_CLVL_DONE", "%s now has access $b%d$b in %s."}, /* {ARGS: "TestUser", 123, "#TestChan"} */ - {"NS_A_LACKS_ACCESS_BUT_GOD_NICK", "%s lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "#TestChan"} */ - {"NS_A_LACKS_ACCESS_BUT_GOD_AUTH", "%s (%s) lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", "#TestChan"} */ - {"NS_A_ACCESS_NICK", "%s has access $b%d$b in %s."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */ - {"NS_A_ACCESS_AUTH", "%s (%s) has access $b%d$b in %s."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */ - {"NS_A_ACCESS_NICK_GOD", "%s has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */ - {"NS_A_ACCESS_AUTH_GOD", "%s (%s) has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */ - {"NS_A_SUSPENDED", "$b%s$b's access to %s has been suspended."}, /* {ARGS: "TestAuth", "#TestChan"} */ - {"NS_A_IS_IRCOP", "%s is an $bIRC operator$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_USERS_HEADER", "%s users from level %d to %d:"}, /* {ARGS: "#TestChan", 1, 500} */ - {"NS_USERS_HEADER_MATCH", "%s users from level %d to %d matching %s:"}, /* {ARGS: "#TestChan", 1, 500, "Test*"} */ - {"NS_USERS_HEADER_ACCESS", "Access"}, - {"NS_USERS_HEADER_ACCOUNT", "Accout"}, - {"NS_USERS_HEADER_SEEN", "Last Seen"}, - {"NS_USERS_HEADER_STATE", "Status"}, - {"NS_USERS_COUNT", "There are $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_USERS_COUNT_1", "There is $b%d$b user in %s."}, /* {ARGS: 1, "#TestChan"} */ - {"NS_USERS_COUNT_MATCH", "There are $b%d$b users in %s. ($b%d$b matching your request)"}, /* {ARGS: 20, "#TestChan", 5} */ - {"NS_USERS_COUNT_MATCH_1", "There is $b%d$b user in %s. ($b%d$b matching your request)"}, /* {ARGS: 1, "#TestChan", 1} */ - {"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"}, - {"NS_SUSPEND_ALREADY", "$b%s$b is already suspended." }, /* {ARGS: "TestUser"} */ - {"NS_SUSPEND_NOT", "$b%s$b is not suspended." }, /* {ARGS: "TestUser"} */ - {"NS_SUSPEND_DONE", "$b%s$b's access to $b%s$b has been suspended." }, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_SUSPEND_RESTORED", "$b%s$b's access to $b%s$b has been restored." }, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_DELME_OWNER", "You cannot delete your owner access in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DELME_KEY", "To really remove yourself, you must use 'deleteme %s'."}, /* {ARGS: "abc123"} */ - {"NS_DELME_DONE", "Your $b%d$b access has been deleted from $b%s$b."}, /* {ARGS: 123, "#TestChan"} */ - {"NS_MYACCESS_SELF_ONLY", "You may only see the list of infolines for yourself (by using $bmyaccess$b with no arguments)."}, - {"NS_MYACCESS_HEADER", "Showing all channel entries for account $b%s$b:"}, /* {ARGS: "TestAuth"} */ - {"NS_MYACCESS_HEADER_MATCH", "Showing all channel entries for account $b%s$b matching %s:"}, /* {ARGS: "TestAuth", "#Test*"} */ - {"NS_MYACCESS_HEADER_NAME", "Name"}, - {"NS_MYACCESS_HEADER_ACCESS", "Access"}, - {"NS_MYACCESS_HEADER_FLAGS", "Flags"}, - {"NS_MYACCESS_HEADER_INFO", "Info"}, - {"NS_MYACCESS_COUNT", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s)."}, /* {ARGS: "TestUser", 15, 5} */ - {"NS_MYACCESS_COUNT_MATCH", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s) ($b%d$b channels matching your request)."}, /* {ARGS: "TestUser", 15, 5, 7} */ - {"NS_UP_ALREADY_OP", "You are already opped in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_UP_ALREADY_VOICE", "You are already voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DOWN_ALREADY", "You are not opped or voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_MDELUSER_DONE", "Deleted $b%d$b account(s) matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list."}, /* {ARGS: 10, "Test*", 1, 200, "#TestChan"} */ - {"NS_TRIM_DURATION_TOO_SHORT", "You must include a minimum inactivity duration of at least %d seconds to trim."}, - {"NS_TRIM_DONE", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s."}, /* {ARGS: 10, 1, 100, "#TestChan", "10 days"} */ - {"NS_TRIM_BAN_DONE", "Trimmed $b%d bans$b from the %s ban list who were banned for at least %s."}, /* {ARGS: 5, "#TestChan", "1 day"} */ - {"NS_GIVEOWNER_SELF", "You cannot give ownership to your own account."}, - {"NS_GIVEOWNER_TIMEOUT", "You must wait %s before you can give ownership of $b%s$b to someone else."}, /* {ARGS: "5 hours", "#TestChan"} */ - {"NS_GIVEOWNER_CONFIRM", "To really give ownership to $b%1$s$b, you must use 'giveownership *%1$s %2$s'."}, /* {ARGS: "TestUser", "abc123"} */ - {"NS_GIVEOWNER_DONE", "Ownership of $b%s$b has been transferred to account $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */ - {"NS_OP_FAIL", "$b%s$b could not op some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_OP_DONE", "Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_HALFOP_FAIL", "$b%s$b could not halfop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_HALFOP_DONE", "Half-Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_VOICE_FAIL", "$b%s$b could not voice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_VOICE_DONE", "Voiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DEOP_FAIL", "$b%s$b could not deop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_DEOP_DONE", "Deopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DEHALFOP_FAIL", "$b%s$b could not dehalfop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_DEHALFOP_DONE", "Dehalfopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_DEVOICE_FAIL", "$b%s$b could not devoice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_DEVOICE_DONE", "Devoiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_OPALL_SECURITY", "$bWARNING$b: Opping all users on a channel is very insecure! If you still want do op all users on %s use: '$bopall FORCE$b [nick mask]'"}, - {"NS_OPALL_DONE", "Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_HALFOPALL_DONE", "Half-Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_VOICEALL_DONE", "Voiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_DEOPALL_DONE", "Deopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_DEHALFOPALL_DONE", "Dehalfopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_DEVOICEALL_DONE", "Devoiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ - {"NS_KICK_DONE", "Kicked $b%d$b users from %s"}, /* {ARGS: 20, "#TestChan"} */ - {"NS_KICK_FAIL", "$b%s$b could not kick some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_KICKBAN_DONE", "KickBanned $b%d$b users from %s"}, /* {ARGS: 10, "#TestChan"} */ - {"NS_KICKBAN_FAIL", "$b%s$b could not kickban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_BAN_DONE", "$b%d$b masks added to the %s ban list. (matching %d users)"}, /* {ARGS: 5, "#TestChan", 15} */ - {"NS_BAN_FAIL", "$b%s$b could not ban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_LAME_MASK", "$b%s$b is a little too general. Try making it more specific."}, /* {ARGS: "*!*@*"} */ - {"NS_LAME_MASK_WARNING", "$k4WARNING$k: $b%s$b is very general. (matches %d users)"}, - {"NS_SET_HEADER", "Channel Settings for %s:"}, /* {ARGS: "#TestChan"} */ - {"NS_SET_ON", "on"}, - {"NS_SET_OFF", "off"}, - {"NS_SET_UNKNOWN_SETTING", "$b%s$b is an unknown channel setting."}, /* {ARGS: "TestSetting"} */ - {"NS_SET_CANNOT_SET", "That setting is above your current level, so you cannot change it."}, - {"NS_SET_BADLEVEL", "You cannot change any setting to above your level."}, - {"NS_SET_INVALID_OPTION", "$b%d$b is not a valid choice. Choose one:"}, /* {ARGS: 5} */ - {"NS_SET_INVALID_BOOLEAN", "$b%s$b is an invalid binary value."}, /* {ARGS: 2} */ - {"NS_SET_DEFAULTS_OWNER", "You must have access 500 in %s to reset it to the default options."}, /* {ARGS: "#TestChan"} */ - {"NS_SET_DEFAULTS_CODE", "To reset %s's settings to the defaults, you must use 'set defaults %s'."}, /* {ARGS: "#TestChan", "abc123"} */ - {"NS_SET_DEFAULTS_DONE", "All settings for %s have been reset to default values."}, /* {ARGS: "#TestChan"} */ - {"NS_SET_TRIGGER_OWNER", "You must have access 500 in %s to change the channel trigger."}, /* {ARGS: "#TestChan"} */ - {"NS_SET_HELP_USERINFO","(access to set the userinfo)"}, - {"NS_SET_HELP_WIPEINFO","(access to clear the userinfo of other users)"}, - {"NS_SET_HELP_INVITEME","(access to get invited by the bot)"}, - {"NS_SET_HELP_ENFVOICE","(access to give voice to other users)"}, - {"NS_SET_HELP_ENFOPS","(access to give op to their users)"}, - {"NS_SET_HELP_GIVEOPS","(access to get op by the bot)"}, - {"NS_SET_HELP_GIVEVOICE","(access to get voice by the bot)"}, - {"NS_SET_HELP_KICK","(access to kick other users from the channel)"}, - {"NS_SET_HELP_BAN","(access to ban other users from the channel)"}, - {"NS_SET_HELP_STATICBAN","(access to add static bans to the channel banlist e.g. +addban)"}, - {"NS_SET_HELP_PUBCMD","(access to do public commands in the channel e.g. +users)"}, - {"NS_SET_HELP_ENFMODES","(access to override the modelock)"}, - {"NS_SET_HELP_ENFTOPIC","(access to override the topicmask)"}, - {"NS_SET_HELP_TOPICSNARF","(access to set the default topic by changing the topic with /TOPIC)"}, - {"NS_SET_HELP_CHANGETOPIC","(access to change the topic)"}, - {"NS_SET_HELP_SETTERS","(access to change this settings)"}, - {"NS_SET_HELP_ADDUSER","(access to add an user to the userlist)"}, - {"NS_SET_HELP_DELUSER","(access to delete an user from the userlist)"}, - {"NS_SET_HELP_CLVL","(access to change the access of an user in the userlist)"}, - {"NS_SET_HELP_RESYNC","(access to synchronize the channelrights (@,+) with the userlist)"}, - {"NS_SET_HELP_SUSPEND","(access to suspend an user on the userlist)"}, - {"NS_SET_OPTION_CTCPREACTION_0","Kick on disallowed CTCPs"}, - {"NS_SET_OPTION_CTCPREACTION_1","Kickban on disallowed CTCPs"}, - {"NS_SET_OPTION_CTCPREACTION_2","Short timed ban on disallowed CTCPs"}, - {"NS_SET_OPTION_CTCPREACTION_3","Long timed ban on disallowed CTCPs"}, - {"NS_SET_OPTION_NOTICEREACTION_0","Kick on disallowed NOTICEs"}, - {"NS_SET_OPTION_NOTICEREACTION_1","Kickban on disallowed NOTICEs"}, - {"NS_SET_OPTION_NOTICEREACTION_2","Short timed ban on disallowed NOTICEs"}, - {"NS_SET_OPTION_NOTICEREACTION_3","Long timed ban on disallowed NOTICEs"}, - {"NS_SET_OPTION_PROTECT_0","All users will be protected from users with equal or lower access."}, - {"NS_SET_OPTION_PROTECT_1","All users with access will be protected from users with equal or lower access."}, - {"NS_SET_OPTION_PROTECT_2","All users with access will be protected from user with lower access."}, - {"NS_SET_OPTION_PROTECT_3","Nobody will be protected."}, - {"NS_SET_OPTION_TOYS_0","Funcommands can't be used."}, - {"NS_SET_OPTION_TOYS_1","Funcommands are possible but the reply will be sent as a notice."}, - {"NS_SET_OPTION_TOYS_2","Funcommands are possible and the reply will be sent to the channel."}, - {"NS_SET_OPTION_DYNLIMIT_0","off"}, - {"NS_SET_OPTION_NODELETE_0","off (only bot masters)"}, - {"NS_SET_OPTION_NODELETE_1","on (only bot masters)"}, - {"NS_WIPEINFO_DONE", "Removed $b%s$b's infoline in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_TRACE_HEADER", "The following users were found:"}, - {"NS_ADDBAN_DONE", "$b%s$b permantly added to the %s ban list. (matching %d users)"}, /* {ARGS: "*!*@Test.*", "#TestChan", 4} */ - {"NS_BANS_HEADER_MASK", "Mask"}, - {"NS_BANS_HEADER_SETBY", "Set By"}, - {"NS_BANS_HEADER_TRIGGERED", "Triggered"}, - {"NS_BANS_HEADER_EXPIRES", "Expires"}, - {"NS_BANS_HEADER_REASON", "Reason"}, - {"NS_DELBAN_BANNED_BY", "%s is banned by %s."}, /* {ARGS: "*!*@bla*", "*!*@b*"} */ - {"NS_DELBAN_FAIL", "Sorry, no ban found for $b%s$b."}, /* {ARGS: "*!*@bla*"} */ - {"NS_DELBAN_DONE", "Removed $b%s$b from the %s ban list."}, /* {ARGS: "*!*@bla.*", "#TestChan"} */ - {"NS_NETINFO_HEADER", "$bNetwork information$b"}, - {"NS_NETINFO_BOTS", "Bots:"}, - {"NS_NETINFO_UPTIME", "Uptime:"}, - {"NS_NETINFO_TRAFFIC", "Traffic:"}, - {"NS_NETINFO_CACHE", "Cache:"}, - {"NS_NETINFO_DATABASE", "Database:"}, - {"NS_NETINFO_CHANNEL", " Channel:"}, - {"NS_NETINFO_CHANNEL_BAN", " Bans:"}, - {"NS_NETINFO_USER", " User:"}, - {"NS_NETINFO_CHANUSER", " Channel-User:"}, - {"NS_NETINFO_OTHER", " Other:"}, - {"NS_NETINFO_THREADS", "Threads:"}, - {"NS_NETINFO_VERSION", "Version:"}, - {"NS_NETINFO_CODE", "Code:"}, - {"NS_NETINFO_CODE_VALUE", "%s lines c code (view it at http://dev.pk910.de/NeonServ)"}, /* {ARGS: 20} */ - {"NS_NETINFO_COMPILER", "Compiler:"}, - {"NS_NETINFO_COMPILER_VALUE", "%s (%s)"}, /* {ARGS: "GCC 4.4.5", "Sun Sep 18 2011 at 05:21:33 CEST"} */ - {"NS_EXTTOPIC_INVALID_ID", "ADVANCEDTOPIC is enabled and $b%s$b is an invalid TOPIC ID. Valid topic id's are: 1-9"}, /* {ARGS: 10} */ - {"NS_EXTTOPIC_TOPICID", "Topic %d: %s"}, /* {ARGS: 5, "topic"} */ - {"NS_TOPIC_DONE", "Topic is now '%s'."}, /* {ARGS: "i like you :D"} */ - {"NS_CHANSERVSYNC_UNSUPPORTED", "\0034WARNING\003: the user list style of %s is not known. %s can try to synchronize the userlist, but there is no guarantee that it is successful!"}, /* {ARGS: "CowBot"} */ - {"NS_CHANSERVSYNC_KEY", "If you really want to synchronize the %s userlist with %s use: chanservsync %s %s"}, /* {ARGS: "#TestChan", "CowBot", "CowBot", "abc123"} */ - {"NS_CHANSERVSYNC_INUSE", "$bchanservsync$b is already in use by someone else. Please try again in a few seconds..."}, - {"NS_CHANSERVSYNC_SYNCHRONIZING", "Synchronizing userlist in %s with $b%s$b..."}, /* {ARGS: "#TestChan", "CowBot"} */ - {"NS_CHANSERVSYNC_SYNCHRONIZED", "Synchronized user $b%s$b: access $b%d$b"}, /* {ARGS: "TestUser", 123} */ - {"NS_REGISTER_ALREADY", "%s is already registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */ - {"NS_INVALID_CHANNEL_NAME", "%s is not a valid channel name."}, /* {ARGS: "#invalid"} */ - {"NS_REGISTER_FULL", "the bot can not join more channels."}, - {"NS_REGISTER_DISCONNECTED", "%s has been registered with a Bot, that is currently NOT connected. The Bot should join the channel, when it reconnects to the IRC-Network."}, /* {ARGS: "#TestChan"} */ - {"NS_REGISTER_DONE", "$b%s$b is now registered to $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */ - {"NS_REGISTER_DONE_NOAUTH", "$b%s$b is now registered."}, /* {ARGS: "#TestChan"} */ - {"NS_UNREGISTER_NOT_REGISTERED", "$b%s$b is not registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */ - {"NS_UNREGISTER_DONE", "$b%s$b unregistered."}, /* {ARGS: "#TestChan"} */ - {"NS_RECOVER_DONE", "$b%s$b has been recovered."}, /* {ARGS: "#TestChan"} */ - {"NS_RESYNC_DONE", "Synchronized users in $b%s$b with the userlist."}, /* {ARGS: "#TestChan"} */ - {"NS_TIMEBAN_DURATION_TOO_SHORT", "You must specify a ban duration of at least %d seconds."}, /* {ARGS: 30} */ - {"NS_TIMEBAN_DONE", "Banned $b%s$b from %s for %s. (matching %d users)"}, /* {ARGS: "*!*@bla*", "#TestChan", "2 hours", 5} */ - {"NS_MODE_INVALID", "$b%c$b is an invalid set of channel modes."}, /* {ARGS: "+xyz"} */ - {"NS_MODE_LOCKED", "Modes conflicting with $b%s$b are not allowed in %s."}, /* {ARGS: "+xyz", "#TestChan"} */ - {"NS_MODE_DONE", "Channel modes are now $b%s$b."}, /* {ARGS: "+xyz"} */ - {"NS_MODE_ENFOPS", "You may not op or deop users on $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_MODE_ENFVOICE", "You may not voice or devoice users on $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_MODE_CANBAN", "You may not ban or unban users on $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_GOD_ON", "Security override has been enabled."}, - {"NS_GOD_OFF", "Security override has been disabled."}, - {"NS_PEEK_HEADER", "$b%s$b Status:"}, /* {ARGS: "#TestChan"} */ - {"NS_PEEK_TOPIC", "Topic: %s"}, /* {ARGS: "TOPIC"} */ - {"NS_PEEK_MODES", "Modes: %s"}, /* {ARGS: "+xyz"} */ - {"NS_PEEK_USERS", "Total Users: %d (%d ops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 20, 4, 6, 8, 2} */ - {"NS_PEEK_USERS_HALFOP", "Total Users: %d (%d ops, %d halfops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 25, 5, 4, 6, 8, 2} */ - {"NS_PEEK_OPS", "Ops:"}, - {"NS_USET_GLOBAL", "$b--- Global ---$b"}, - {"NS_USET_CHANNEL", "$b--- User options (channel) ---$b"}, - {"NS_USET_NO_ACCESS", "no access"}, - {"NS_USET_UNKNOWN_SETTING", "$b%s$b is an unknown uset setting."}, /* {ARGS: "TestSetting"} */ - {"NS_RELOADLANG_UNKNOWN", "$b%s$b is an unknown language tag."}, /* {ARGS: "de"} */ - {"NS_RELOADLANG_DONE", "$b%s$b (%s) reloaded."}, /* {ARGS: "Deutsch", "de"} */ - {"NS_UNBAN_DONE", "$b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ - {"NS_UNBAN_FAIL", "$b%s$b could not unban some of the masks you provided."}, /* {ARGS: "NeonServ"} */ - {"NS_UNBANALL_DONE", "all $b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ - {"NS_UNBANALL_FAIL", "$b%s$b could not find any bans in %s."}, /* {ARGS: "NeonServ", "#TestChan"} */ - {"NS_UNBANME_DONE", "removed $b%d$b masks from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ - {"NS_UNBANME_FAIL", "$b%s$b could not find any bans matching %s."}, /* {ARGS: "NeonServ", "TestUser!TestIdent@TestUser.user.WebGamesNet"} */ - {"NS_INVITE_RESTRICTION", "%s doesn't want to be invited to %s."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_INVITE_TIMEOUT", "%s has already been invited to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_INVITE_ON_CHAN", "%s is already in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_INVITE_DONE_USER", "You have been invited to join $b%s$b by %s. (Do $b/msg %s %1$s uset noinvite 1$b if you don't want to be invited to %1$s anymore.)"}, /* {ARGS: "#TestChan", "TestUser", "NeonServ"} */ - {"NS_INVITE_DONE", "Invited $b%s$b to join %s."}, /* {ARGS: "TestUser", "#TestChan"} */ - {"NS_INVITEME_ON_CHAN", "You are already in $b%s$b."}, /* {ARGS: "#TestChan"} */ - {"NS_INVITEME_DONE", "You have been invited to join %s."}, /* {ARGS: "#TestChan"} */ - {"NS_HELP_TOPIC", "No help on that topic."}, - {"NS_CSUSPEND_ALREADY", "$b%s$b is already suspended."}, /* {ARGS: "#TestChan"} */ - {"NS_CSUSPEND_DONE", "Channel $b%s$b has been temporarily suspended."}, /* {ARGS: "#TestChan"} */ - {"NS_CUNSUSPEND_NOT", "$b%s$b is not suspended."}, /* {ARGS: "#TestChan"} */ - {"NS_CUNSUSPEND_DONE", "Channel $b%s$b has been restored."}, /* {ARGS: "#TestChan"} */ - {"NS_MOVE_SUSPENDED", "Moving cannot be performed if the source channel is suspended."}, - {"NS_MOVE_SELF", "Moving cannot be performed if the source and target channels are the same."}, - {"NS_MOVE_DONE", "Channel $b%s$b has been moved to $b%s$b."}, /* {ARGS: "#TestChan", "#NewTestChan"} */ - {"NS_BIND_ALREADY", "$b%s$b is already bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */ - {"NS_BIND_UNKNOWN", "$b%s$b is an undefined function."}, /* {ARGS: "TestFunction"} */ - {"NS_BIND_DONE", "New command $b%s$b bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */ - {"NS_UNBIND_NOT_FOUND", "There is no command called $b%s$b bound."}, /* {ARGS: "TestCommand"} */ - {"NS_UNBIND_DONE", "Unbound command $b%s$b."}, /* {ARGS: "TestCommand"} */ - {"NS_EVENTS_HEADER", "The following channel events were found:"}, - {"NS_OPLOG_HEADER", "The following oper events were found:"}, - {"NS_SEARCH_HEADER", "The following channels were found:"}, - {"NS_COMMAND_BINDING", "$b%s$b is a binding of %s %s"}, /* {ARGS: "TestCommand", "TestFunction", "TestParameters"} */ - {"NS_COMMAND_ACCESS", "You need at least %d channel access and %d oper access to execute this command."}, /* {ARGS: 500, 100} */ - {"NS_TOPIC_ACCESS", "You lack sufficient access in %s to change the topic."}, /* {ARGS: "#TestChan"} */ - {"NS_BOTWAR_DETECTED", "$b$k4BOTWAR DETECTED!$k Please check the channel configuration!$b"}, - {"NS_BOTWAR_REPORTED", "A supporter has been informed to help you preventing botwars in the future."}, - {"NS_BOTWAR_ALERT", "$b$k4BOTWAR ALERT:$k$b Botwar in $b%s$b detected. (opponent: $b%s$b) Please join and help them preventing Botwars."}, /* {ARGS: "#TestChan", "OtherBot"} */ - {"NS_INVITE_FAIL", "$b%s$b is not registered with %s or suspended."}, /* {ARGS: "#TestChan", "NeonServ"} */ - {"NS_SETACCESS_DONE", "$b%s$b has now %d global access."}, /* {ARGS: "TestUser", 1000} */ - {"NS_ADDRANK_EXISTS", "Another support ranking called '$b%s$b' already exists."}, /* {ARGS: "Supporter"} */ - {"NS_ADDRANK_DONE", "Support ranking '$b%s$b' created."}, /* {ARGS: "Supporter"} */ - {"NS_DELRANK_NOT_FOUND", "There is no support ranking called '$b%s$b'."}, /* {ARGS: "Supporter"} */ - {"NS_DELRANK_DELETED", "Support ranking called '$b%s$b' removed."}, /* {ARGS: "Supporter"} */ - {"NS_LISTRANK_ID", "Id"}, - {"NS_LISTRANK_NAME", "Name"}, - {"NS_LISTRANK_ASSIGNED", "Assigned to"}, - {"NS_LISTRANK_UNRANKED", "There are also %d unranked users with global access."}, /* {ARGS: 10} */ - {"NS_SETRANK_NOT_FOUND", "There is no support ranking with ID '$b%s$b'."}, /* {ARGS: 42} */ - {"NS_SETRANK_HEAD", "Support ranking settings for Id %s:"}, /* {ARGS: 42} */ - {"NS_SETRANK_UNKNOWN_SETTING", "$b%s$b is an unknown support rank setting."}, /* {ARGS: "moep"} */ - {"NS_SETRANK_ORDER_INVALID", "%d is an invalid numeric value. (valid: 1-99)"}, /* {ARGS: 100} */ - {"NS_ASSIGNRANK_DONE", "$b%s$b is now ranked as '$b%s$b'."}, /* {ARGS: "TestUser", "Supporter"} */ - {"NS_INFO_HEADER", "$b%s$b Information:"}, /* {ARGS: "#TestChan"} */ - {"NS_INFO_DEFAULTTOPIC", "Default Topic:"}, - {"NS_INFO_MODELOCK", "Mode Lock:"}, - {"NS_INFO_RECORD", "Record Visitors:"}, - {"NS_INFO_OWNER", "Owner:"}, - {"NS_INFO_USERS", "Total User Count:"}, - {"NS_INFO_BANS", "Ban Count:"}, - {"NS_INFO_VISITED", "Visited:"}, - {"NS_INFO_REGISTERED", "Registered:"}, - {"NS_INFO_REGISTRAR", "Registered by:"}, - {"NS_INFO_OWNERLOG", "Ownership transfer history for $b%s$b:"}, /* {ARGS: "#TestChan"} */ - {"NS_INFO_OWNERCHANGE", " from %s to %s on %s"}, - {"NS_RENAME_DONE", "Renamed $b%s$b to $b%s$b."}, /* {ARGS: "TestUser", "TestUser2"} */ - {"NS_RENAME_FAIL", "Failed renaming $b%s$b."}, /* {ARGS: "TestUser"} */ - {"NS_FUN_DISABLED", "Fun commands are disabled in %s."}, /* {ARGS: "#TestChan"} */ - {"NS_UNBIND_REQUIRED", "%1$s is a required function and there is no other command bound to %1$s. Bind another command to %1$s first."}, /* {ARGS: "bind"} */ - {"NS_COMMANDS_NAME", "Name"}, - {"NS_COMMANDS_ACCESS", "Access"}, - {"NS_COMMANDS_GACCESS", "GodAccess"}, - {"NS_COMMANDS_TRIGGERED", "Triggered"}, - {"NS_COMMANDS_FUNCTION", "Function"}, - {"NS_DNR_SET", "$b%s$b is do-not-register (by $b%s$b): %s" }, /* {ARGS: "#TestChan", "TestUser", "because of it is like it is"} */ - {"NS_DNR_SET_EXPIRES", "$b%s$b is do-not-register (by $b%s$b; expires %s): %s" }, /* {ARGS: "#TestChan", "TestUser", "1 day", "because of it is like it is"} */ - {"NS_DNR_SET_ANONYM", "$b%s$b is do-not-register. Please contact the support to get more information."}, /* {ARGS: "TestUser"} */ - {"NS_NOREGISTER_INVALID_DURATION", "$b%s$b is not a valid duration."}, /* {ARGS: "möp"} */ - {"NS_NOREGISTER_REGISTERED", "$b%s$b is currently registered and can't be added to the do-not-register list."}, /* {ARGS: "#TestChan"} */ - {"NS_NOREGISTER_DONE", "added $b%s$b to the do-not-register list."}, /* {ARGS: "#TestChan"} */ - {"NS_NOREGISTER_HEAD", "The following do-not-registers were found:"}, - {"NS_DNR_TARGET", "Target"}, - {"NS_DNR_USER", "Issuer"}, - {"NS_DNR_EXPIRES", "Expires"}, - {"NS_DNR_REASON", "Reason"}, - {"NS_STAFF_LOGGEDIN", "Logged in as"}, - {"NS_BOTS_ID", "Id"}, - {"NS_BOTS_NICK", "Nick"}, - {"NS_BOTS_SERVER", "Server:Port(:Pass)"}, - {"NS_BOTS_CLASS", "Bot Class"}, - {"NS_BOTS_FLAGS", "Flags"}, - {"NS_BOTS_CHANNELS", "Channels"}, - {"NS_BOTS_TRIGGER", "Trigger"}, - {"NS_NICKLIST_NICK", "Nick"}, - {"NS_NICKLIST_STATE", "State"}, - {"NS_NICKLIST_ACCESS", "Access"}, - {"NS_NICKLIST_SYNC", "use `nicklist sync` to fix all red and orange entrys in the list above (add opped users with %d and voiced with %d access)"}, - {"NS_SETBOT_UNKNOWN", "`%d` is an unknown botid."}, /* {ARGS: 50} */ - {"NS_SETBOT_HEADER", "$bSettings for botid `%d`:$b"}, /* {ARGS: 50} */ - {"NS_SETBOT_SETTING", "$b%s$b is an unknown bot setting."}, /* {ARGS: "strangeSetting"} */ - {"NS_SETBOT_NICK_INVALID", "`%s` is an invalid botnick."}, /* {ARGS: "-SuperMagicBananaBotWithManyFunctions"} */ - {"NS_SETBOT_NEED_RESTART", "You need to reconnect the bot to apply this setting."}, - {"NS_SETBOT_PORT_INVALID", "`%s` is an invalid port number."}, /* {ARGS: "-1"} */ - {"NS_SETBOT_INVALID_CLASS", "`%s` is an invalid botclass."}, /* {ARGS: "MistColaLeer"} */ - {"NS_SETBOT_MAXCHAN_INVALID", "`%s` is an invalid maxchan value."}, /* {ARGS: "-1"} */ - {"NS_SETBOT_PRIORITY_INVALID", "`%s` is an invalid priority value."}, /* {ARGS: "-1"} */ - {"NS_SETBOT_TRIGGER_INVALID", "`%s` is an invalid bot trigger."}, /* {ARGS: "tooLongTrigger"} */ - {"NS_SETBOT_TRIGGER_NOTE", "Please note: This Setting will only affect new channels."}, - {"NS_ADDBOT_EXISTING", "A bot with nick %s does already exist."}, /* {ARGS: "NeonServ"} */ - {"NS_ADDBOT_DONE", "Added %s with BotID $b%d$b."}, /* {ARGS: "NeonServ", 2} */ - {"NS_DELBOT_NOT_FOUND", "Bot with BotID / nick $b%s$b not found."}, /* {ARGS: "NeonServ"} */ - {"NS_DELBOT_DONE", "Bot deleted."}, - {"NS_RECONNECT_DONE", "Reconnected bot."}, - {"NS_MODCMD_SETTING", "$b%s$b is an unknown modcmd setting."}, /* {ARGS: "strangeSetting"} */ - {"NS_MODCMD_HEADER", "$bSettings for command %s:$b"}, /* {ARGS: "access"} */ - {"NS_MODCMD_OUTRANKED", "$b%s$b outranks you. (required access: %d)"}, /* {ARGS: "die", 1000} */ - {"NS_MODCMD_STATIC_FLAG", "This Flag is added statically. It can't be modified manually."}, - {"NS_MEMINFO_DISABLED", "Memory Debugger is disabled!"}, - {"NS_MEMINFO_NAME", "Name"}, - {"NS_MEMINFO_COUNT", "Count"}, - {"NS_MEMINFO_SIZE", "Size"}, - {"NS_MEMINFO_LINE", "Line"}, - {"NS_MEMINFO_TOTAL", "Total"}, - {NULL, NULL} -}; - -/* TODO: -cmd_neonserv_open.c -set modelock -cmd_neonserv_modcmd.c -cmd_neonserv_allowregister.c -cmd_neonserv_noregister.c -cmd_neonserv_expire.c -cmd_neonserv_unvisited.c -cmd_neonserv_merge.c -cmd_neonserv_dnrsearch.c -cmd_neonserv_iplocate.c -cmd_neonserv_calc.c -*/ -//EVENTS -#include "event_neonserv_join.c" -#include "event_neonserv_part.c" -#include "event_neonserv_quit.c" -#include "event_neonserv_kick.c" -#include "event_neonserv_mode.c" -#include "event_neonserv_ctcp.c" -#include "event_neonserv_notice.c" -#include "event_neonserv_invite.c" -#include "event_neonserv_topic.c" - - -struct ClientSocket *getBotForChannel(struct ChanNode *chan) { - return getChannelBot(chan, BOTID); -} - -static void neonserv_bot_ready(struct ClientSocket *client) { - MYSQL_RES *res; - MYSQL_ROW row; - - printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "MODE %s +%s", client->user->nick, row[0]); - } - - printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "JOIN %s %s", row[0], row[1]); - } -} - -static void neonserv_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { - MYSQL_RES *res; - MYSQL_ROW row; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { - strcpy(trigger, "+"); - return; - } - printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); - res = mysql_use(); - if(!(row = mysql_fetch_row(res))) { - strcpy(trigger, "+"); - return; - } - if(row[0] && *row[0]) - strcpy(trigger, row[0]); - else - strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "~")); -} - -static void start_bots() { - struct ClientSocket *client; - MYSQL_RES *res, *res2; - MYSQL_ROW row; - - printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); - client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); - client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); - client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); - client->botid = BOTID; - client->clientid = atoi(row[7]); - connect_socket(client); - } - - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); - res2 = mysql_use(); - while ((row = mysql_fetch_row(res2)) != NULL) { - if(bind_cmd_to_command(BOTID, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_set_parameters(BOTID, row[0], row[2]); - } - if(row[3]) { - bind_set_global_access(BOTID, row[0], atoi(row[3])); - } - if(row[4]) { - bind_set_channel_access(BOTID, row[0], row[4]); - } - if(strcmp(row[5], "0")) - bind_set_bind_flags(BOTID, row[0], atoi(row[5])); - } - } - bind_unbound_required_functions(BOTID); -} - -void init_NeonServ() { - - set_bot_alias(BOTID, BOTALIAS); - start_bots(); - - //register events - bind_bot_ready(neonserv_bot_ready); - bind_join(neonserv_event_join); - bind_part(neonserv_event_part); - bind_quit(neonserv_event_quit); - bind_chanctcp(neonserv_event_chanctcp); - bind_privctcp(general_event_privctcp); - bind_channotice(neonserv_event_channotice); - bind_topic(neonserv_event_topic); - bind_invite(neonserv_event_invite); - bind_mode(neonserv_event_mode); - bind_kick(neonserv_event_kick); - - set_trigger_callback(BOTID, neonserv_trigger_callback); - - register_default_language_table(msgtab); -} - -void loop_NeonServ() { - -} - -void free_NeonServ() { - -} - -#undef BOTID -#undef BOTALIAS diff --git a/src/bot_NeonServ.h b/src/bot_NeonServ.h deleted file mode 100644 index 397d34f..0000000 --- a/src/bot_NeonServ.h +++ /dev/null @@ -1,30 +0,0 @@ -/* bot_NeonServ.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _bot_NeonServ_h -#define _bot_NeonServ_h - -#include "main.h" - -struct ChanNode; - -void init_NeonServ(); -void loop_NeonServ(); -void free_NeonServ(); - -struct ClientSocket *getBotForChannel(struct ChanNode *chan); - -#endif \ No newline at end of file diff --git a/src/bot_NeonSpam.c b/src/bot_NeonSpam.c deleted file mode 100644 index 3c08748..0000000 --- a/src/bot_NeonSpam.c +++ /dev/null @@ -1,351 +0,0 @@ -/* bot_NeonSpam.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "bot_NeonSpam.h" -#include "modcmd.h" -#include "IRCParser.h" -#include "IRCEvents.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "ModeNode.h" -#include "BanNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "version.h" -#include "EventLogger.h" -#include "bots.h" -#include "cmd_neonserv.h" -#include "cmd_neonspam.h" - -#define BOTID 2 -#define BOTALIAS "NeonSpam" - -static const struct default_language_entry msgtab[] = { - {"SS_SET_PERCENT", "%u is an invalid percent value (valid: 0-100)"}, /* {ARGS: 120} */ - {"SS_SET_SENSIBILITY", "%s is an invalid sensibility format. (valid: amount:time e.g. 5:10)"}, /* {ARGS: "möp"} */ - {"SS_SET_SENSIBILITY_AMOUNT", "%d is an invalid amount value. (valid: %d-%d)"}, /* {ARGS: 120, 1, 5} */ - {"SS_SET_SENSIBILITY_TIME", "%d is an invalid time value. (valid: %d-%d)"}, /* {ARGS: 300, 15, 180} */ - {"SS_SET_SPAMLIMIT", "%d is an invalid spamlimit value. (valid: %d-%d)"}, /* {ARGS: 120, 2, 8} */ - {"SS_SET_OPTION_SpamReaction_0", "Kick"}, - {"SS_SET_OPTION_SpamReaction_1", "KickBan"}, - {"SS_SET_OPTION_SpamReaction_2", "Timed Ban"}, - {"SS_SET_OPTION_FloodReaction_0", "Kick"}, - {"SS_SET_OPTION_FloodReaction_1", "KickBan"}, - {"SS_SET_OPTION_FloodReaction_2", "Timed Ban"}, - {"SS_SET_OPTION_JoinReaction_0", "Kick"}, - {"SS_SET_OPTION_JoinReaction_1", "KickBan"}, - {"SS_SET_OPTION_JoinReaction_2", "Timed Ban"}, - {"SS_SET_OPTION_CapsReaction_0", "Kick"}, - {"SS_SET_OPTION_CapsReaction_1", "KickBan"}, - {"SS_SET_OPTION_CapsReaction_2", "Timed Ban"}, - {"SS_SET_OPTION_DigitReaction_0", "Kick"}, - {"SS_SET_OPTION_DigitReaction_1", "KickBan"}, - {"SS_SET_OPTION_DigitReaction_2", "Timed Ban"}, - {NULL, NULL} -}; - -static unsigned int convertNeonSpamSettingsToFlags(char *str); -static void createSpamNode(struct ChanUser *chanuser); -static void freeJoinNode(struct NeonSpamJoinNode *joinnode); -static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser); - -#define SPAMSERV_CHECK_IGNORE 0 -#define SPAMSERV_CHECK_WARN 1 -#define SPAMSERV_CHECK_PUNISH 2 -#define SPAMSERV_CHECK_DEAD 3 /* scanner has already killed the user */ - -#define SPAMSERV_MSG_SPAM "Spamming" -#define SPAMSERV_MSG_FLOOD "Flooding the channel/network" -#define SPAMSERV_MSG_ADV "Advertising" -#define SPAMSERV_MSG_JOINFLOOD "Join flooding the channel" -#define SPAMSERV_MSG_WARNING "%s is against the channel rules" -#define SPAMSERV_MSG_BOTNET "BotNet detected." -#define SPAMSERV_MSG_CAPS "Using too many chars in UPPER CASE" -#define SPAMSERV_MSG_DIGIT "Using too many numeric chars" - -//EVENTS -#include "event_neonspam_join.c" -#include "event_neonspam_chanmsg.c" - -static void neonspam_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { - struct ChanNode *chan = target->chan; - if(isBot(target->user)) { - struct ClientSocket *client = getChannelBot(chan, 0); - struct ClientSocket *bot = client; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->user == target->user) { - break; - } - } - if(!client) return; - if(bot && bot != client && (isModeSet(chan->modes, 'i') || isModeSet(chan->modes, 'a') || isModeSet(chan->modes, 'l'))) { - struct ChanUser *chanuser = getChanUser(bot->user, chan); - if(chanuser && chanuser->flags & CHANUSERFLAG_OPPED) - putsock(bot, "INVITE %s %s", target->user->nick, chan->name); - } - char *key = ""; - if(isModeSet(chan->modes, 'k')) { - key = getModeValue(chan->modes, 'k'); - } - putsock(client, "JOIN %s %s", chan->name, key); - return; - } -} - -static void neonspam_bot_ready(struct ClientSocket *client) { - MYSQL_RES *res; - MYSQL_ROW row; - - printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "MODE %s +%s", client->user->nick, row[0]); - } - - printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "JOIN %s %s", row[0], row[1]); - } -} - -static void neonspam_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { - MYSQL_RES *res; - MYSQL_ROW row; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { - strcpy(trigger, "~"); - return; - } - printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); - res = mysql_use(); - if(!(row = mysql_fetch_row(res))) { - strcpy(trigger, "~"); - return; - } - if(row[0] && *row[0]) - strcpy(trigger, row[0]); - else - strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "~")); -} - -static void start_bots() { - struct ClientSocket *client; - MYSQL_RES *res, *res2; - MYSQL_ROW row; - - printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); - res = mysql_use(); - - while ((row = mysql_fetch_row(res)) != NULL) { - client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); - client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); - client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); - client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); - client->botid = BOTID; - client->clientid = atoi(row[7]); - connect_socket(client); - } - - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); - res2 = mysql_use(); - while ((row = mysql_fetch_row(res2)) != NULL) { - if(bind_cmd_to_command(BOTID, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_set_parameters(BOTID, row[0], row[2]); - } - if(row[3]) { - bind_set_global_access(BOTID, row[0], atoi(row[3])); - } - if(row[4]) { - bind_set_channel_access(BOTID, row[0], row[4]); - } - if(strcmp(row[5], "0")) - bind_set_bind_flags(BOTID, row[0], atoi(row[5])); - } - } - bind_unbound_required_functions(BOTID); -} - -char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer) { - int pos = 0; - unsigned int i; - int j = 0; - char *chars = SPAMSETTINGS_CHARS; - for(i = 1; i <= SPAMSETTINGS_FLAGS; i = i << 1) { - if(flags & i) - buffer[pos++] = chars[j]; - j++; - } - buffer[pos] = '\0'; - return buffer; -} - -static unsigned int convertNeonSpamSettingsToFlags(char *str) { - unsigned int i = 1, flags = 0; - int j = 0; - char *chars = SPAMSETTINGS_CHARS; - while(*str) { - for(; i <= SPAMSETTINGS_FLAGS; i = i << 1) { - if(*str == chars[j]) { - flags |= i; - j++; - i = i << 1; - break; - } - j++; - } - str++; - } - return flags; -} - -int loadNeonSpamSettings(struct ChanNode *chan) { - if(chan->spam_settings) return 0; - struct NeonSpamSettings *settings = malloc(sizeof(*settings)); - if(!settings) { - perror("malloc() failed"); - return 0; - } - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - loadChannelSettings(chan); - printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5] || !row[6] || !row[7] || !row[8] || !row[9] || !row[10] || !row[11] || !row[12]) { - printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - settings->flags = convertNeonSpamSettingsToFlags(row[0] ? row[0] : defaults[0]); - settings->spam_amount = atoi(row[1] ? row[1] : defaults[1]); - settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] = atoi(row[2] ? row[2] : defaults[2]); - settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[3] ? row[3] : defaults[3]); - settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[4] ? row[4] : defaults[4]); - settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] = atoi(row[5] ? row[5] : defaults[5]); - settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX] = atoi(row[6] ? row[6] : defaults[6]); - settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX] = atoi(row[7] ? row[7] : defaults[7]); - settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] = atoi(row[8] ? row[8] : defaults[8]); - settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX] = atoi(row[9] ? row[9] : defaults[9]); - settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] = atoi(row[10] ? row[10] : defaults[10]); - settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX] = atoi(row[11] ? row[11] : defaults[11]); - settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] = atoi(row[12] ? row[12] : defaults[12]); - settings->join_nodes = NULL; - settings->lastmsg_time = 0; - int i; - for(i = 0; i < BOTNETSCAN_USERS; i++) - settings->botnicks[i] = NULL; - chan->spam_settings = settings; - return 1; -} - -void freeNeonSpamSettings(struct NeonSpamSettings *settings) { - struct NeonSpamJoinNode *joinnode, *nextjoinnode; - for(joinnode = settings->join_nodes; joinnode; joinnode = nextjoinnode) { - nextjoinnode = joinnode->next; - freeJoinNode(joinnode); - } - free(settings); -} - -static void freeJoinNode(struct NeonSpamJoinNode *joinnode) { - free(joinnode->ident); - free(joinnode->host); - free(joinnode); -} - -static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser) { - struct NeonSpamJoinNode *joinnode, *prevjoinnode = NULL, *nextjoinnode, *result = NULL; - for(joinnode = chanuser->chan->spam_settings->join_nodes; joinnode; joinnode = nextjoinnode) { - nextjoinnode = joinnode->next; - if(!stricmp(joinnode->ident, chanuser->user->ident) && !stricmp(joinnode->host, chanuser->user->host)) { - prevjoinnode = joinnode; - result = joinnode; - } else if(time(0) - joinnode->last_penalty_update > MAX_JOIN_TIME) { - freeJoinNode(joinnode); - if(prevjoinnode) - prevjoinnode->next = nextjoinnode; - else - chanuser->chan->spam_settings->join_nodes = nextjoinnode; - } else - prevjoinnode = joinnode; - } - if(result) - return result; - joinnode = malloc(sizeof(*joinnode)); - if(!joinnode) { - perror("malloc() failed"); - return NULL; - } - joinnode->ident = strdup(chanuser->user->ident); - joinnode->host = strdup(chanuser->user->host); - joinnode->last_penalty_update = time(0); - joinnode->joinpenalty = 0; - joinnode->next = chanuser->chan->spam_settings->join_nodes; - chanuser->chan->spam_settings->join_nodes = joinnode; - return joinnode; -} - -static void createSpamNode(struct ChanUser *chanuser) { - struct NeonSpamNode *spamnode = malloc(sizeof(*spamnode)); - if(!spamnode) { - perror("malloc() failed"); - return; - } - spamnode->lastmsg = 0; - spamnode->spamcount = 0; - spamnode->floodpenalty = 0; - spamnode->last_penalty_update = time(0); - chanuser->spamnode = spamnode; -} - -void init_NeonSpam() { - - set_bot_alias(BOTID, BOTALIAS); - start_bots(); - - //register events - bind_bot_ready(neonspam_bot_ready); - bind_join(neonspam_event_join); - bind_chanmsg(neonspam_event_chanmsg); - bind_privctcp(general_event_privctcp); - bind_kick(neonspam_event_kick); - - set_trigger_callback(BOTID, neonspam_trigger_callback); - - register_default_language_table(msgtab); -} - -void loop_NeonSpam() { - -} - -void free_NeonSpam() { - -} - -#undef BOTID -#undef BOTALIAS diff --git a/src/bot_NeonSpam.h b/src/bot_NeonSpam.h deleted file mode 100644 index a95f3bc..0000000 --- a/src/bot_NeonSpam.h +++ /dev/null @@ -1,150 +0,0 @@ -/* bot_NeonSpam.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _bot_NeonSpam_h -#define _bot_NeonSpam_h - -#include "main.h" - -struct ChanNode; - -//SPAMSCAN -#define SPAMSETTINGS_SPAMSCAN 0x000001 -#define SPAMSETTINGS_SPAMSCAN_OPS 0x000002 -#define SPAMSETTINGS_SPAMSCAN_VOICE 0x000004 -#define SPAMSETTINGS_SPAMCHARS "abc" -#define SPAMSETTINGS_SPAMEXCINDEX 0 - -//FLOODSCAN -#define SPAMSETTINGS_FLOODSCAN 0x000008 -#define SPAMSETTINGS_FLOODSCAN_OPS 0x000010 -#define SPAMSETTINGS_FLOODSCAN_VOICE 0x000020 -#define SPAMSETTINGS_FLOODCHARS "def" -#define SPAMSETTINGS_FLOODEXCINDEX 1 -#define SPAMSETTINGS_FLOODSENINDEX 0 - -//JOINSCAN -#define SPAMSETTINGS_JOINSCAN 0x000040 -#define SPAMSETTINGS_JOINSCAN_OPS 0x000080 -#define SPAMSETTINGS_JOINSCAN_VOICE 0x000100 -#define SPAMSETTINGS_JOINCHARS "ghi" -#define SPAMSETTINGS_JOINEXCINDEX 2 -#define SPAMSETTINGS_JOINSENINDEX 1 - -//BOTNET SCAN -#define SPAMSETTINGS_BOTNETSCAN 0x000200 -#define SPAMSETTINGS_BOTNETSCAN_OPS 0x000400 -#define SPAMSETTINGS_BOTNETSCAN_VOICE 0x000800 -#define SPAMSETTINGS_BOTNETSCAN_STRIPCC 0x001000 -#define SPAMSETTINGS_BOTNETCHARS "jklm" -#define SPAMSETTINGS_BOTNETEXCINDEX 3 - -//CAPSSCAN -#define SPAMSETTINGS_CAPSSCAN 0x002000 -#define SPAMSETTINGS_CAPSSCAN_OPS 0x004000 -#define SPAMSETTINGS_CAPSSCAN_VOICE 0x008000 -#define SPAMSETTINGS_CAPSCHARS "nop" -#define SPAMSETTINGS_CAPSEXCINDEX 4 -#define SPAMSETTINGS_CAPSPERCENTINDEX 0 - -//DIGITSCAN -#define SPAMSETTINGS_DIGITSCAN 0x010000 -#define SPAMSETTINGS_DIGITSCAN_OPS 0x020000 -#define SPAMSETTINGS_DIGITSCAN_VOICE 0x040000 -#define SPAMSETTINGS_DIGITCHARS "qrs" -#define SPAMSETTINGS_DIGITEXCINDEX 5 -#define SPAMSETTINGS_DIGITPERCENTINDEX 1 - - -#define SPAMSETTINGS_CHARS SPAMSETTINGS_SPAMCHARS SPAMSETTINGS_FLOODCHARS SPAMSETTINGS_JOINCHARS SPAMSETTINGS_BOTNETCHARS SPAMSETTINGS_CAPSCHARS SPAMSETTINGS_DIGITCHARS -#define SPAMSETTINGS_FLAGS 0x07ffff /* all flags that can be stored in the database */ -#define SPAMSETTINGS_EXCEPTINDEXES 6 -#define SPAMSETTINGS_SENSIBILITYINDEXES 2 -#define SPAMSETTINGS_PERCENTINDEXES 2 - -//SCRIPT FLAGS -#define SPAMSETTINGS_KICKEDBOTQUEUE 0x080000 -#define SPAMSETTINGS_ISTIMEBAN 0x100000 -#define SPAMSETTINGS_SETTIMEBAN 0x200000 - -#define MAX_FLOOD_AMOUNT 300 -#define MIN_FLOOD_AMOUNT 2 -#define MAX_FLOOD_TIME 200 - -#define MAX_JOIN_AMOUNT 300 -#define MIN_JOIN_AMOUNT 2 -#define MAX_JOIN_TIME 200 - -#define BOTNETSCAN_USERS 4 -#define BOTNETSCAN_TIME 2 - -struct NeonSpamSettings { - unsigned int flags; - unsigned char spam_amount; - unsigned char sensibility_amount[SPAMSETTINGS_SENSIBILITYINDEXES]; - unsigned char sensibility_time[SPAMSETTINGS_SENSIBILITYINDEXES]; - unsigned int exceptlevel[SPAMSETTINGS_EXCEPTINDEXES]; - unsigned char percent[SPAMSETTINGS_PERCENTINDEXES]; - - //joinflood - struct NeonSpamJoinNode *join_nodes; - - //botnet - unsigned long lastmsg; //crc32 hash - time_t lastmsg_time; - char *botnicks[BOTNETSCAN_USERS]; - - -}; -/* PENALTY SYSTEM -* user gets MAX_FLOOD_TIME points per message -* points get removed each loop -* pounts to be removed each second: -* MAX_FLOOD_TIME/flood_time -* -* the floodlimit is reached, if the penalty points -* are bigger than MAX_FLOOD_TIME * flood_amount -*/ - -#define NEONSPAMNODE_FLAG_CAPSSCAN_WARNED 0x01 -#define NEONSPAMNODE_FLAG_DIGITSCAN_WARNED 0x02 - -struct NeonSpamNode { - unsigned long lastmsg; //crc32 hash - unsigned char spamcount; - int floodpenalty; - time_t last_penalty_update; - unsigned char flags; -}; - -struct NeonSpamJoinNode { - char *ident; - char *host; - int joinpenalty; - time_t last_penalty_update; - struct NeonSpamJoinNode *next; -}; - -void init_NeonSpam(); -void loop_NeonSpam(); -void free_NeonSpam(); - -void freeNeonSpamSettings(struct NeonSpamSettings *settings); -char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer); -int loadNeonSpamSettings(struct ChanNode *chan); - -#endif \ No newline at end of file diff --git a/src/bots.c b/src/bots.c index c9b0616..994dbba 100644 --- a/src/bots.c +++ b/src/bots.c @@ -98,11 +98,6 @@ static void zero_bots_trigger_callback(int clientid, struct ChanNode *chan, char } void init_bots() { - init_NeonServ(); - init_NeonSpam(); - init_DummyServ(); - init_NeonHelp(); - set_bot_alias(0, "0"); start_zero_bots(); set_trigger_callback(0, zero_bots_trigger_callback); @@ -124,20 +119,6 @@ void init_bots() { } } -void loop_bots() { - loop_NeonServ(); - loop_NeonSpam(); - loop_DummyServ(); - loop_NeonHelp(); -} - -void free_bots() { - free_NeonServ(); - free_NeonSpam(); - free_DummyServ(); - free_NeonHelp(); -} - struct ClientSocket *getChannelBot(struct ChanNode *chan, int botid) { struct ClientSocket *bot, *use_bot = NULL, *second_bot = NULL, *third_bot = NULL; struct ChanUser *chanuser; diff --git a/src/bots.h b/src/bots.h index 578f509..3344d38 100644 --- a/src/bots.h +++ b/src/bots.h @@ -24,16 +24,15 @@ struct UserNode; struct ChanNode; struct ClientSocket; +#ifndef DND_FUNCTIONS void init_bots(); -void loop_bots(); -void free_bots(); - -struct ClientSocket *getChannelBot(struct ChanNode *chan, int botid); -void requestOp(struct UserNode *user, struct ChanNode *chan); -TIMEQ_CALLBACK(channel_ban_timeout); -void general_event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text); -void set_bot_alias(int botid, char *alias); -const char *resolve_botid(int botid); -int resolve_botalias(const char *alias); +/* MODULAR ACCESSIBLE */ struct ClientSocket *getChannelBot(struct ChanNode *chan, int botid); +/* MODULAR ACCESSIBLE */ void requestOp(struct UserNode *user, struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ TIMEQ_CALLBACK(channel_ban_timeout); +/* MODULAR ACCESSIBLE */ void general_event_privctcp(struct UserNode *user, struct UserNode *target, char *command, char *text); +/* MODULAR ACCESSIBLE */ void set_bot_alias(int botid, char *alias); +/* MODULAR ACCESSIBLE */ const char *resolve_botid(int botid); +/* MODULAR ACCESSIBLE */ int resolve_botalias(const char *alias); +#endif #endif \ No newline at end of file diff --git a/src/cmd_funcmds.c b/src/cmd_funcmds.c deleted file mode 100644 index 3f4095a..0000000 --- a/src/cmd_funcmds.c +++ /dev/null @@ -1,218 +0,0 @@ -/* cmd_funcmds.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_funcmds.h" -#include "modcmd.h" -#include "mysqlConn.h" -#include "IRCParser.h" -#include "ClientSocket.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "lang.h" -#include "tools.h" -#include "DBHelper.h" - -static const struct default_language_entry msgtab[] = { - {"FUN_DICE", "$b%s$b: A $b%d$b shows on the %d-sided die."}, /* {ARGS: "TestUser", 5, 6} */ - {"FUN_DICE_NUM", "I do not understand $b%s$b. Please use a single number above 1."}, /* {ARGS: "bla"} */ - {"FUN_8BALL", "$b%s$b: %s"}, /* {ARGS: "TestUser", "Not a chance."} */ - {"FUN_8BALL_REPLIES", "Not a chance.|In your dreams.|Absolutely!|Could be, could be.|No!"}, - {"FUN_COOKIE", "gives %1$s a very big chocolate cookie. %1$s has got %2$d cookies until now (%3$d in this channel)."}, /* {ARGS: "TestUser", 20, 50} */ - {NULL, NULL} -}; - -void init_funcmds() { - register_default_language_table(msgtab); - srand(time(NULL)); -} - -struct current_funcmd_header { - struct ClientSocket *client; - struct UserNode *user; - struct ChanNode *chan; - char send_notice; -}; - -static struct current_funcmd_header current_funcmd; - -#define FUNCMD_HEADER \ -current_funcmd.client = getTextBot(); \ -current_funcmd.user = user; \ -current_funcmd.chan = chan; \ -{\ - MYSQL_RES *res; \ - MYSQL_ROW row; \ - printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name)); \ - res = mysql_use(); \ - row = mysql_fetch_row(res); \ - if(!row || !strcmp(row[0], "0")) { \ - reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name); \ - return; \ - } else if(!strcmp(row[0], "1")) \ - current_funcmd.send_notice = 1; \ - else \ - current_funcmd.send_notice = 0; \ -} - -#define REPLYTYPE_NORMAL 0 -#define REPLYTYPE_ACTION 1 -static void funcmd_reply(const char *text, int type, ...) { - if (!(current_funcmd.client->flags & SOCKET_FLAG_CONNECTED)) return; - const char *reply_format = get_language_string(current_funcmd.user, text); - if(reply_format) - text = reply_format; - char formatBuf[MAXLEN]; - if(current_funcmd.send_notice) { - if(type == REPLYTYPE_ACTION) - sprintf(formatBuf, "NOTICE %s :%s %s", current_funcmd.user->nick, current_funcmd.client->user->nick, text); - else - sprintf(formatBuf, "NOTICE %s :%s", current_funcmd.user->nick, text); - } else { - if(type == REPLYTYPE_ACTION) - sprintf(formatBuf, "PRIVMSG %s :\001ACTION %s\001", current_funcmd.chan->name, text); - else - sprintf(formatBuf, "PRIVMSG %s :%s", current_funcmd.chan->name, text); - } - va_list arg_list; - char sendBuf[MAXLEN]; - int pos; - sendBuf[0] = '\0'; - va_start(arg_list, type); - pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list); - va_end(arg_list); - if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; - sendBuf[pos] = '\n'; - sendBuf[pos+1] = '\0'; - write_socket(current_funcmd.client, sendBuf, pos+1); -} - -static char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) { - char *uname = ""; - int cid = 0; - MYSQL_RES *res; - MYSQL_ROW row; - if(user) { - uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); - } - if(chan) { - loadChannelSettings(chan); - if(chan->flags & CHANFLAG_CHAN_REGISTERED) - cid = chan->channel_id; - } - printf_mysql_query("SELECT `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - return row[0]; - } else - return NULL; -} - -static void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value) { - char *uname = ""; - int cid = 0; - MYSQL_RES *res; - MYSQL_ROW row; - if(user) { - uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); - } - if(chan) { - loadChannelSettings(chan); - if(chan->flags & CHANFLAG_CHAN_REGISTERED) - cid = chan->channel_id; - } - printf_mysql_query("SELECT `id`, `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - if(strcmp(row[1], value)) - printf_mysql_query("UPDATE `fundata` SET `value` = '%s' WHERE `id` = '%s'", escape_string(value), row[0]); - } else - printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value)); -} - -CMD_BIND(funcmd_ping) { - FUNCMD_HEADER; - funcmd_reply("\002%s\002: Pong!", REPLYTYPE_NORMAL, user->nick); -} - -CMD_BIND(funcmd_pong) { - FUNCMD_HEADER; - funcmd_reply("\002%s\002: Ping!", REPLYTYPE_NORMAL, user->nick); -} - -CMD_BIND(funcmd_dice) { - FUNCMD_HEADER; - int max = atoi(argv[0]); - if(max > 1) { - int val = (rand() % max) + 1; - funcmd_reply("FUN_DICE", REPLYTYPE_NORMAL, user->nick, val, max); - } else - funcmd_reply("FUN_DICE_NUM", REPLYTYPE_NORMAL, argv[0]); -} - -CMD_BIND(funcmd_8ball) { - FUNCMD_HEADER; - char *message = merge_argv(argv, 0, argc); - const char *const_replies = get_language_string(current_funcmd.user, "FUN_8BALL_REPLIES"); - char replies[MAXLEN]; - int i, reply_count = 1; - for(i = 0; const_replies[i]; i++) { - if(const_replies[i] == '|') - reply_count++; - replies[i] = const_replies[i]; - } - replies[i] = '\0'; - unsigned int crc32_val = (crc32(message)) % reply_count; - char *creply = (crc32_val == 0 ? replies : NULL); - reply_count = 0; - for(i = 0; replies[i]; i++) { - if(replies[i] == '|') { - if(creply) { - replies[i] = '\0'; - break; - } else { - reply_count++; - if(reply_count == crc32_val) { - creply = &replies[i+1]; - } - } - } - } - if(creply) { - funcmd_reply("FUN_8BALL", REPLYTYPE_NORMAL, user->nick, creply); - } -} - -CMD_BIND(funcmd_cookie) { - FUNCMD_HEADER; - if(argc) { - if(!(user = getUserByNick(argv[0]))) { - reply(current_funcmd.client, current_funcmd.user, "NS_USER_UNKNOWN", argv[0]); - return; - } - } - char *tmp; - int user_count = ((tmp = getSetting(user, chan, "cookies")) ? atoi(tmp) : 0); - int total_count = ((tmp = getSetting(user, NULL, "cookies")) ? atoi(tmp) : 0); - user_count++; - total_count++; - char buf[10]; - sprintf(buf, "%d", user_count); - setSetting(user, chan, "cookies", buf); - sprintf(buf, "%d", total_count); - setSetting(user, NULL, "cookies", buf); - funcmd_reply("FUN_COOKIE", REPLYTYPE_ACTION, user->nick, total_count, user_count); -} diff --git a/src/cmd_funcmds.h b/src/cmd_funcmds.h deleted file mode 100644 index 37dc779..0000000 --- a/src/cmd_funcmds.h +++ /dev/null @@ -1,30 +0,0 @@ -/* cmd_funcmds.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _cmd_funcmds_h -#define _cmd_funcmds_h -#include "main.h" -#include "modcmd.h" - -void init_funcmds(); - -CMD_BIND(funcmd_ping); -CMD_BIND(funcmd_pong); -CMD_BIND(funcmd_dice); -CMD_BIND(funcmd_8ball); -CMD_BIND(funcmd_cookie); - -#endif \ No newline at end of file diff --git a/src/cmd_global.h b/src/cmd_global.h deleted file mode 100644 index 55bb5a7..0000000 --- a/src/cmd_global.h +++ /dev/null @@ -1,68 +0,0 @@ -/* cmd_global.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _cmd_global_h -#define _cmd_global_h -#include "main.h" -#include "modcmd.h" -#include "IRCParser.h" -#include "IRCEvents.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "ModeNode.h" -#include "BanNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "version.h" -#include "EventLogger.h" -#include "bots.h" - -CMD_BIND(global_cmd_addbot); -CMD_BIND(global_cmd_bind); -CMD_BIND(global_cmd_bots); -CMD_BIND(global_cmd_command); -CMD_BIND(global_cmd_commands); -CMD_BIND(global_cmd_delbot); -CMD_BIND(global_cmd_die); -CMD_BIND(global_cmd_emote); -CMD_BIND(global_cmd_god); -CMD_BIND(global_cmd_meminfo); -CMD_BIND(global_cmd_modcmd); -CMD_BIND(global_cmd_motd); -CMD_BIND(global_cmd_netinfo); -CMD_BIND(global_cmd_notice); -CMD_BIND(global_cmd_raw); -CMD_BIND(global_cmd_reconnect); -CMD_BIND(global_cmd_register); -CMD_BIND(global_cmd_reload); -CMD_BIND(global_cmd_restart); -CMD_BIND(global_cmd_reloadlang); -CMD_BIND(global_cmd_say); -CMD_BIND(global_cmd_setaccess); -CMD_BIND(global_cmd_setbot); -CMD_BIND(global_cmd_staff); -CMD_BIND(global_cmd_unbind); -CMD_BIND(global_cmd_unregister); -CMD_BIND(global_cmd_version); - -#endif \ No newline at end of file diff --git a/src/cmd_global_addbot.c b/src/cmd_global_addbot.c deleted file mode 100644 index 1783834..0000000 --- a/src/cmd_global_addbot.c +++ /dev/null @@ -1,43 +0,0 @@ -/* cmd_global_addbot.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] nick -* argv[1] class -*/ - -CMD_BIND(global_cmd_addbot) { - MYSQL_RES *res; - int botid; - if((botid = resolve_botalias(argv[1])) == -1) { - reply(getTextBot(), user, "NS_SETBOT_INVALID_CLASS", argv[1]); - return; - } - printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s'", escape_string(argv[0])); - res = mysql_use(); - if(mysql_fetch_row(res)) { - reply(getTextBot(), user, "NS_ADDBOT_EXISTING", argv[0]); - return; - } - printf_mysql_query("INSERT INTO `bots` (`nick`, `botclass`) VALUES ('%s', '%d')", escape_string(argv[0]), botid); - botid = (int) mysql_insert_id(get_mysql_conn()); - reply(getTextBot(), user, "NS_ADDBOT_DONE", argv[0], botid); - logEvent(event); -} - diff --git a/src/cmd_global_bind.c b/src/cmd_global_bind.c deleted file mode 100644 index 2842cf8..0000000 --- a/src/cmd_global_bind.c +++ /dev/null @@ -1,54 +0,0 @@ -/* cmd_global_bind.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] command name -* argv[1] command function -* argv[2-*] parameters (optional) -*/ - -CMD_BIND(global_cmd_bind) { - MYSQL_RES *res; - MYSQL_ROW row; - if(client->botid == 0) - printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `botid` = '%d' AND `command` = '%s'", client->botid, client->clientid, escape_string(argv[0])); - else - printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_BIND_ALREADY", argv[0], row[0]); - return; - } - char *params; - if(argc > 2) - params = merge_argv(argv, 2, argc); - else - params = ""; - struct cmd_function *function = find_cmd_function(client->botid, argv[1]); - if(!function) { - reply(getTextBot(), user, "NS_BIND_UNKNOWN", argv[1]); - return; - } - bind_botwise_cmd_to_function(client->botid, client->clientid, argv[0], function); - printf_mysql_query("INSERT INTO `bot_binds` (`botclass`, `botid`, `command`, `function`, `parameters`) VALUES ('%d', '%d', '%s', '%s', '%s')", client->botid, (client->botid == 0 ? client->clientid : 0), escape_string(argv[0]), escape_string(argv[1]), params); - if(*params) - bind_botwise_set_parameters(client->botid, client->clientid, argv[0], params); - reply(getTextBot(), user, "NS_BIND_DONE", argv[0], function->name); - logEvent(event); -} diff --git a/src/cmd_global_bots.c b/src/cmd_global_bots.c deleted file mode 100644 index 57ab153..0000000 --- a/src/cmd_global_bots.c +++ /dev/null @@ -1,73 +0,0 @@ -/* cmd_global_bots.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] (optional) class name -*/ - -CMD_BIND(global_cmd_bots) { - struct Table *table; - MYSQL_RES *res, *res2; - MYSQL_ROW row, row2; - printf_mysql_query("SELECT `active`, `nick`, `server`, `port`, `pass`, `botclass`, `textbot`, `queue`, `defaulttrigger`, `max_channels`, `register_priority`, `id` FROM `bots`"); - res = mysql_use(); - table = table_init(7, mysql_num_rows(res) + 1, 0); - char *content[7]; - content[0] = get_language_string(user, "NS_BOTS_ID"); - content[1] = get_language_string(user, "NS_BOTS_NICK"); - content[2] = get_language_string(user, "NS_BOTS_SERVER"); - content[3] = get_language_string(user, "NS_BOTS_CLASS"); - content[4] = get_language_string(user, "NS_BOTS_FLAGS"); - content[5] = get_language_string(user, "NS_BOTS_CHANNELS"); - content[6] = get_language_string(user, "NS_BOTS_TRIGGER"); - table_add(table, content); - char botnick[NICKLEN + 3]; - char botserver[MAXLEN]; - char botflags[10]; - int flagspos; - char botchans[20]; - while ((row = mysql_fetch_row(res)) != NULL) { - content[0] = row[11]; - sprintf(botnick, (strcmp(row[0], "0") ? "%s" : "!%s"), row[1]); - content[1] = botnick; - sprintf(botserver, (strcmp(row[4], "") ? "%s:%s:*" : "%s:%s"), row[2], row[3]); - content[2] = botserver; - content[3] = (char *) resolve_botid(atoi(row[5])); - flagspos = 0; - if(!strcmp(row[6], "1")) - botflags[flagspos++] = 't'; - if(!strcmp(row[7], "1")) - botflags[flagspos++] = 'q'; - botflags[flagspos] = '\0'; - content[4] = botflags; - printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[11]); - res2 = mysql_use(); - row2 = mysql_fetch_row(res2); - sprintf(botchans, "%s/%s", row2[0], row[9]); - content[5] = botchans; - content[6] = row[8]; - table_add(table, content); - } - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); -} \ No newline at end of file diff --git a/src/cmd_global_command.c b/src/cmd_global_command.c deleted file mode 100644 index 594ea1b..0000000 --- a/src/cmd_global_command.c +++ /dev/null @@ -1,179 +0,0 @@ -/* cmd_global_command.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0-1] command -*/ -static int global_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan); -static int global_cmd_command_operaccess(struct cmd_binding *cbind); - -CMD_BIND(global_cmd_command) { - char *ident; - MYSQL_RES *res; - MYSQL_ROW row; - struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); - if (!cbind) { - reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); - return; - } - ident = argv[0]; - char parameters[MAXLEN]; - if(cbind->paramcount) { - int i, parampos = 0; - for(i = 0; i < cbind->paramcount; i++) { - parampos += sprintf(parameters + parampos, (i ? " %s" : "%s"), cbind->parameters[i]); - } - } else - parameters[0] = '\0'; - reply(getTextBot(), user, "NS_COMMAND_BINDING", cbind->cmd, cbind->func->name, parameters); - if(chan) - reply(getTextBot(), user, "NS_COMMAND_ACCESS", global_cmd_command_chanaccess(cbind, chan), global_cmd_command_operaccess(cbind)); - printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - char *lang; - if ((row = mysql_fetch_row(res)) != NULL) - lang = row[0]; - else - lang = "en"; - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - if(stricmp(lang, "en")) { - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident)); - res = mysql_use(); - } - if ((row = mysql_fetch_row(res)) == NULL) { - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(cbind->func->name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - if(stricmp(lang, "en")) { - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(cbind->func->name)); - res = mysql_use(); - } - if ((row = mysql_fetch_row(res)) == NULL) { - return; - } - } - } - } - char sendBuf[MAXLEN]; - int sendBufPos = 0; - int i; - for(i = 0; i < strlen(row[0]); i++) { - switch(row[0][i]) { - case '\n': - if(sendBufPos) { - sendBuf[sendBufPos] = '\0'; - reply(getTextBot(), user, "%s", sendBuf); - sendBufPos = 0; - } - break; - case '$': - switch(row[0][i+1]) { - case 'b': - sendBuf[sendBufPos++] = '\002'; - i++; - break; - case 'k': - sendBuf[sendBufPos++] = '\003'; - i++; - break; - case 'u': - sendBuf[sendBufPos++] = '\031'; - i++; - break; - case 'C': - case 'S': - sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick); - i++; - break; - default: - sendBuf[sendBufPos++] = '$'; - break; - } - break; - default: - sendBuf[sendBufPos++] = row[0][i]; - break; - } - } - if(sendBufPos) { - sendBuf[sendBufPos] = '\0'; - reply(getTextBot(), user, "%s", sendBuf); - sendBufPos = 0; - } -} - -static int global_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) { - char access_list[256]; - int access_pos = 0; - int access_count = 0; - int minaccess = 0; - char *str_a, *str_b = cbind->func->channel_access, *str_c; - if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) - str_b = cbind->channel_access; - access_list[0] = '\0'; - if(str_b) { - str_c = strdup(str_b); - str_b = str_c; - while((str_a = str_b)) { - str_b = strstr(str_a, ","); - if(str_b) { - *str_b = '\0'; - str_b++; - } - if(*str_a == '@' || *str_a == '+') { - //privs can override this access requirement - str_a++; - } - if(*str_a == '#') { - str_a++; - access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a); - access_count++; - } else { - if(atoi(str_a) > minaccess) - minaccess = atoi(str_a); - } - } - free(str_c); - } - if(access_count) { - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - int i, caccess; - for(i = 0; i < access_count; i++) { - if(!row[i] && !defaults) { - printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); - defaults = mysql_fetch_row(mysql_use()); - } - caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i])); - if(caccess > minaccess) - minaccess = caccess; - } - } - } - return minaccess; -} - -static int global_cmd_command_operaccess(struct cmd_binding *cbind) { - return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); -} diff --git a/src/cmd_global_commands.c b/src/cmd_global_commands.c deleted file mode 100644 index caeac97..0000000 --- a/src/cmd_global_commands.c +++ /dev/null @@ -1,153 +0,0 @@ -/* cmd_global_commands.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] mask -*/ - -static int global_cmd_commands_sort(const void *a, const void *b); -static int global_cmd_commands_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan); -static int global_cmd_commands_operaccess(struct cmd_binding *cbind); - -CMD_BIND(global_cmd_commands) { - struct cmd_binding *cbind; - int bindcount = 0; - for(cbind = getAllBinds(NULL); cbind; cbind = getAllBinds(cbind)) { - if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && !(cbind->func->flags & CMDFLAG_FUNCMD)) - bindcount++; - } - struct cmd_binding *binds[bindcount]; - bindcount = 0; - for(cbind = getAllBinds(NULL); cbind; cbind = getAllBinds(cbind)) { - if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && !(cbind->func->flags & CMDFLAG_FUNCMD)) - binds[bindcount++] = cbind; - } - qsort(binds, bindcount, sizeof(struct cmd_binding *), global_cmd_commands_sort); - int i; - struct Table *table; - table = table_init(5, bindcount + 1, 0); - char *content[5]; - content[0] = get_language_string(user, "NS_COMMANDS_NAME"); - content[1] = get_language_string(user, "NS_COMMANDS_ACCESS"); - content[2] = get_language_string(user, "NS_COMMANDS_GACCESS"); - content[3] = get_language_string(user, "NS_COMMANDS_TRIGGERED"); - content[4] = get_language_string(user, "NS_COMMANDS_FUNCTION"); - table_add(table, content); - char caccess[5]; - char gaccess[5]; - char triggered[10]; - char funcname[MAXLEN]; - int funcpos; - for(i = 0; i < bindcount; i++) { - cbind = binds[i]; - content[0] = cbind->cmd; - sprintf(caccess, "%d", global_cmd_commands_chanaccess(cbind, chan)); - content[1] = caccess; - sprintf(gaccess, "%d", global_cmd_commands_operaccess(cbind)); - content[2] = gaccess; - sprintf(triggered, "%d", cbind->triggered); - content[3] = triggered; - funcpos = sprintf(funcname, "%s", cbind->func->name); - if(cbind->paramcount) { - int j; - for(j = 0; j < cbind->paramcount; j++) { - funcpos += sprintf(funcname + funcpos, " %s", cbind->parameters[j]); - } - } - content[4] = funcname; - table_add(table, content); - } - //send the table - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); -} - -static int global_cmd_commands_sort(const void *a, const void *b) { - const struct cmd_binding *bind_a = *((struct cmd_binding * const *) a); - const struct cmd_binding *bind_b = *((struct cmd_binding * const *) b); - int i = stricmp(bind_a->func->name, bind_b->func->name); - if(i == 0) { - return stricmp(bind_a->cmd, bind_b->cmd); - } else - return i; -} - -static int global_cmd_commands_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) { - char access_list[256]; - int access_pos = 0; - int access_count = 0; - int minaccess = 0; - char *str_a, *str_b = cbind->func->channel_access, *str_c; - if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) - str_b = cbind->channel_access; - access_list[0] = '\0'; - if(str_b) { - str_c = strdup(str_b); - str_b = str_c; - while((str_a = str_b)) { - str_b = strstr(str_a, ","); - if(str_b) { - *str_b = '\0'; - str_b++; - } - if(*str_a == '@' || *str_a == '+') { - //privs can override this access requirement - str_a++; - } - if(*str_a == '#') { - str_a++; - access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a); - access_count++; - } else { - if(atoi(str_a) > minaccess) - minaccess = atoi(str_a); - } - } - free(str_c); - } - if(access_count) { - if(!chan) { - return -1; - } - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - int i, caccess; - for(i = 0; i < access_count; i++) { - if(!row[i] && !defaults) { - printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); - defaults = mysql_fetch_row(mysql_use()); - } - caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i])); - if(caccess > minaccess) - minaccess = caccess; - } - } - } - return minaccess; -} - -static int global_cmd_commands_operaccess(struct cmd_binding *cbind) { - return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); -} diff --git a/src/cmd_global_delbot.c b/src/cmd_global_delbot.c deleted file mode 100644 index b017f12..0000000 --- a/src/cmd_global_delbot.c +++ /dev/null @@ -1,45 +0,0 @@ -/* cmd_global_delbot.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] nick/botid -*/ - -CMD_BIND(global_cmd_delbot) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s' OR `id` = '%s'", escape_string(argv[0]), escape_string(argv[0])); - res = mysql_use(); - if((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_DELBOT_NOT_FOUND", argv[0]); - return; - } - int botid = atoi(row[0]); - printf_mysql_query("DELETE FROM `bots` WHERE `id` = '%s'", row[0]); - printf_mysql_query("DELETE FROM `bot_binds` WHERE `botid` = '%s'", row[0]); - printf_mysql_query("DELETE FROM `bot_channels` WHERE `botid` = '%s'", row[0]); - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == botid) { - close_socket(client); - break; - } - } - reply(getTextBot(), user, "NS_DELBOT_DONE"); - logEvent(event); -} diff --git a/src/cmd_global_die.c b/src/cmd_global_die.c deleted file mode 100644 index c80b0b0..0000000 --- a/src/cmd_global_die.c +++ /dev/null @@ -1,27 +0,0 @@ -/* cmd_global_die.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* no args -*/ - -CMD_BIND(global_cmd_die) { - //hard work! :D - stop_bot(); -} diff --git a/src/cmd_global_emote.c b/src/cmd_global_emote.c deleted file mode 100644 index 494e5e3..0000000 --- a/src/cmd_global_emote.c +++ /dev/null @@ -1,28 +0,0 @@ -/* cmd_global_emote.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] target -* argv[1-*] message -*/ - -CMD_BIND(global_cmd_emote) { - char *message = merge_argv(argv, 1, argc); - putsock(client, "PRIVMSG %s :\001ACTION %s\001", argv[0], message); -} \ No newline at end of file diff --git a/src/cmd_global_god.c b/src/cmd_global_god.c deleted file mode 100644 index 3e54b7f..0000000 --- a/src/cmd_global_god.c +++ /dev/null @@ -1,53 +0,0 @@ -/* cmd_global_god.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] (optional) on/off -*/ - -CMD_BIND(global_cmd_god) { - if(argc > 0) { - if(!strcmp(argv[0], "0") || !stricmp(argv[0], "off") || !stricmp(argv[0], get_language_string(user, "NS_SET_OFF"))) { - if(isGodMode(user)) { - printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth)); - user->flags &= ~USERFLAG_GOD_MODE; - } - reply(getTextBot(), user, "NS_GOD_OFF"); - } else if(!strcmp(argv[0], "1") || !stricmp(argv[0], "on") || !stricmp(argv[0], get_language_string(user, "NS_SET_ON"))) { - if(!isGodMode(user)) { - printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth)); - user->flags |= USERFLAG_GOD_MODE; - } - reply(getTextBot(), user, "NS_GOD_ON"); - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[0]); - return; - } - } else { - if(isGodMode(user)) { - printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth)); - user->flags &= ~USERFLAG_GOD_MODE; - reply(getTextBot(), user, "NS_GOD_OFF"); - } else { - printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth)); - user->flags |= USERFLAG_GOD_MODE; - reply(getTextBot(), user, "NS_GOD_ON"); - } - } -} \ No newline at end of file diff --git a/src/cmd_global_meminfo.c b/src/cmd_global_meminfo.c deleted file mode 100644 index bdcf45a..0000000 --- a/src/cmd_global_meminfo.c +++ /dev/null @@ -1,118 +0,0 @@ -/* cmd_global_meminfo.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" -#include "memoryInfo.h" - -/* -* no arguments -*/ - -CMD_BIND(global_cmd_meminfo) { - #ifndef ENABLE_MEMORY_DEBUG - reply(getTextBot(), user, "NS_MEMINFO_DISABLED"); - #else - if(argc > 0) { - struct Table *table; - int elementcount = 0; - struct memoryInfoLines *element, *elements; - elements = getMemoryInfoLines(argv[0]); - for(element = elements; element; element = element->next) { - elementcount++; - } - table = table_init(4, elementcount+2, 0); - char *content[4]; - content[0] = get_language_string(user, "NS_MEMINFO_LINE"); - content[1] = get_language_string(user, "NS_MEMINFO_COUNT"); - content[2] = get_language_string(user, "NS_MEMINFO_SIZE"); - content[3] = get_language_string(user, "NS_MEMINFO_TOTAL"); - table_add(table, content); - char lineBuf[20]; - char countBuf[20]; - char sizeBuf[20]; - char totalBuf[50]; - unsigned int total_allocations = 0; - unsigned int total_allocated = 0; - for(element = elements; element; element = element->next) { - sprintf(lineBuf, "%u", element->line); - content[0] = lineBuf; - sprintf(countBuf, "%u", element->allocations); - total_allocations += element->allocations; - content[1] = countBuf; - sprintf(sizeBuf, "%uB", element->allocate); - content[2] = sizeBuf; - sprintf(totalBuf, "%u (%.2f kB)", (element->allocate * element->allocations), ((float)(element->allocate * element->allocations) / 1024)); - total_allocated += (element->allocate * element->allocations); - content[3] = totalBuf; - table_add(table, content); - } - content[0] = "Total"; - sprintf(countBuf, "%u", total_allocations); - content[1] = countBuf; - content[2] = "*"; - sprintf(sizeBuf, "%u (%.2f kB)", total_allocated, ((float)total_allocated / 1024)); - content[3] = sizeBuf; - table_add(table, content); - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); - } else { - struct Table *table; - int elementcount = 0; - struct memoryInfoFiles *element, *elements; - elements = getMemoryInfoFiles(); - for(element = elements; element; element = element->next) { - elementcount++; - } - table = table_init(3, elementcount+2, 0); - char *content[3]; - content[0] = get_language_string(user, "NS_MEMINFO_NAME"); - content[1] = get_language_string(user, "NS_MEMINFO_COUNT"); - content[2] = get_language_string(user, "NS_MEMINFO_SIZE"); - table_add(table, content); - char countBuf[20]; - char sizeBuf[50]; - unsigned int total_allocations = 0; - unsigned int total_allocated = 0; - for(element = elements; element; element = element->next) { - content[0] = element->filename; - sprintf(countBuf, "%u", element->allocations); - total_allocations += element->allocations; - content[1] = countBuf; - sprintf(sizeBuf, "%u (%.2f kB)", element->allocated, ((float)element->allocated / 1024)); - total_allocated += element->allocated; - content[2] = sizeBuf; - table_add(table, content); - } - content[0] = "Total"; - sprintf(countBuf, "%u", total_allocations); - content[1] = countBuf; - sprintf(sizeBuf, "%u (%.2f kB)", total_allocated, ((float)total_allocated / 1024)); - content[2] = sizeBuf; - table_add(table, content); - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); - } - #endif -} \ No newline at end of file diff --git a/src/cmd_global_modcmd.c b/src/cmd_global_modcmd.c deleted file mode 100644 index 1506a35..0000000 --- a/src/cmd_global_modcmd.c +++ /dev/null @@ -1,222 +0,0 @@ -/* cmd_global_modcmd.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] command -* argv[1] setting -* argv[2] value -*/ - -static int global_cmd_modcmd_params(struct UserNode *user, struct cmd_binding *cbind, char *value); -static int global_cmd_modcmd_flags(struct UserNode *user, struct cmd_binding *cbind, char *value); -static int global_cmd_modcmd_caccess(struct UserNode *user, struct cmd_binding *cbind, char *value); -static int global_cmd_modcmd_oaccess(struct UserNode *user, struct cmd_binding *cbind, char *value); - -CMD_BIND(global_cmd_modcmd) { - MYSQL_RES *res; - MYSQL_ROW row; - struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); - if (!cbind) { - reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); - return; - } - int uaccess = 0; - printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - uaccess = atoi(row[0]); - } - int gaccess = ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); - if(gaccess > uaccess) { - reply(getTextBot(), user, "NS_MODCMD_OUTRANKED", cbind->cmd, gaccess); - return; - } - if(argc > 1) { - char *value; - if(argc > 2) { - value = merge_argv(argv, 2, argc); - } else - value = NULL; - int log_event = 0; - if(!stricmp(argv[1], "caccess")) log_event = global_cmd_modcmd_caccess(user, cbind, value); - else if(!stricmp(argv[1], "oaccess")) log_event = global_cmd_modcmd_oaccess(user, cbind, value); - else if(!stricmp(argv[1], "parameters")) log_event = global_cmd_modcmd_params(user, cbind, value); - else if(!stricmp(argv[1], "flags")) log_event = global_cmd_modcmd_flags(user, cbind, value); - else { - reply(getTextBot(), user, "NS_MODCMD_SETTING", argv[1]); - } - if(log_event) { - logEvent(event); - } - } else { - reply(getTextBot(), user, "NS_MODCMD_HEADER", cbind->cmd); - global_cmd_modcmd_params(user, cbind, NULL); - global_cmd_modcmd_caccess(user, cbind, NULL); - global_cmd_modcmd_oaccess(user, cbind, NULL); - global_cmd_modcmd_flags(user, cbind, NULL); - } -} - -static int global_cmd_modcmd_params(struct UserNode *user, struct cmd_binding *cbind, char *value) { - char parameters[MAXLEN]; - int ret = 0; - if(cbind->paramcount) { - int i, parampos = 0; - for(i = 0; i < cbind->paramcount; i++) { - parampos += sprintf(parameters + parampos, (i ? " %s" : "%s"), cbind->parameters[i]); - } - } else - parameters[0] = '\0'; - if(value) { - if(!strcmp(value, "*")) - value = NULL; - bind_botwise_set_parameters(cbind->botid, cbind->clientid, cbind->cmd, value); - if(cbind->botid == 0) - printf_mysql_query("UPDATE `bot_binds` SET `parameters` = '%s' WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? escape_string(value) : ""), cbind->clientid, escape_string(cbind->cmd)); - else - printf_mysql_query("UPDATE `bot_binds` SET `parameters` = '%s' WHERE `botclass` = '%d' AND `command` = '%s'", (value ? escape_string(value) : ""), cbind->botid, escape_string(cbind->cmd)); - strcpy(parameters, (value ? value : "")); - ret = 1; - } - reply(getTextBot(), user, "\002PARAMETERS \002 %s", parameters); - return ret; -} - -static const struct { - const char *name; - unsigned int flag; -} global_cmd_modcmd_show_flags[] = { - {"REQUIRE_CHAN", CMDFLAG_REQUIRE_CHAN}, //The command requires a valid channel (at least one bot in it) - {"REQUIRE_AUTH", CMDFLAG_REQUIRE_AUTH}, //The command requires the user to be authenticated - {"REQUIRE_GOD", CMDFLAG_REQUIRE_GOD}, //The command requires the user to have security override enabled - {"REQUIRE_REGISTERED", CMDFLAG_REGISTERED_CHAN}, //The command requires the channel to be registered (database entry) - {"CHECK_AUTH", CMDFLAG_CHECK_AUTH}, //WHO the user if no auth is known, yet - {"CHANNEL_ARGS", CMDFLAG_CHAN_PARAM}, //don't interpret channel arguments as channel - just pass them as a string - {"LOG", CMDFLAG_LOG}, - {"OPLOG", CMDFLAG_OPLOG}, - {"FUNCMD", CMDFLAG_FUNCMD}, - {"ESCAPED_ARGS", CMDFLAG_ESCAPE_ARGS}, //allows arguments to be escaped ("a\ b" = "a b" as one argument) - {"NO_CROSSCHAN", CMDFLAG_NO_CROSSCHAN}, - {NULL, 0} -}; - -static int global_cmd_modcmd_flags(struct UserNode *user, struct cmd_binding *cbind, char *value) { - char flags[MAXLEN]; - int flagpos = 0; - int ret = 0; - unsigned int visible_flags = 0; - int i = 0; - while(global_cmd_modcmd_show_flags[i].name) { - if(cbind->func->flags & global_cmd_modcmd_show_flags[i].flag) { - flagpos += sprintf(flags + flagpos, (flagpos ? " %s" : "\00314%s"), global_cmd_modcmd_show_flags[i].name); - } - visible_flags |= global_cmd_modcmd_show_flags[i].flag; - i++; - } - if(flagpos) - flags[flagpos++] = '\003'; - if(value) { - int add = 1; - unsigned int current_flag = 0; - if(value[0] == '+') { - value++; - } else if(value[0] == '-') { - add = 0; - value++; - } - if(*value) { - i = 0; - while(global_cmd_modcmd_show_flags[i].name) { - if(!stricmp(global_cmd_modcmd_show_flags[i].name, value)) { - current_flag = global_cmd_modcmd_show_flags[i].flag; - break; - } - i++; - } - } - if(cbind->func->flags & current_flag) { - reply(getTextBot(), user, "NS_MODCMD_STATIC_FLAG"); - return 0; - } - if(add) - cbind->flags |= current_flag; - else - cbind->flags &= ~current_flag; - if(cbind->botid == 0) - printf_mysql_query("UPDATE `bot_binds` SET `flags` = '%u' WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (cbind->flags & visible_flags), cbind->clientid, escape_string(cbind->cmd)); - else - printf_mysql_query("UPDATE `bot_binds` SET `flags` = '%u' WHERE `botclass` = '%d' AND `command` = '%s'", (cbind->flags & visible_flags), cbind->botid, escape_string(cbind->cmd)); - ret = 1; - } - i = 0; - while(global_cmd_modcmd_show_flags[i].name) { - if(cbind->flags & global_cmd_modcmd_show_flags[i].flag) { - flagpos += sprintf(flags + flagpos, (flagpos ? " %s" : "%s"), global_cmd_modcmd_show_flags[i].name); - } - i++; - } - flags[flagpos] = '\0'; - reply(getTextBot(), user, "\002FLAGS \002 %s", flags); - return ret; -} - -static int global_cmd_modcmd_caccess(struct UserNode *user, struct cmd_binding *cbind, char *value) { - char caccess[MAXLEN]; - int ret = 0; - if(value) { - if(!strcmp(value, "*")) - value = NULL; - bind_botwise_set_channel_access(cbind->botid, cbind->clientid, cbind->cmd, value); - if(cbind->botid == 0) - printf_mysql_query("UPDATE `bot_binds` SET `chan_access` = %s%s%s WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->clientid, escape_string(cbind->cmd)); - else - printf_mysql_query("UPDATE `bot_binds` SET `chan_access` = %s%s%s WHERE `botclass` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->botid, escape_string(cbind->cmd)); - - ret = 1; - } - if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) - sprintf(caccess, "%s", cbind->channel_access); - else - sprintf(caccess, "\00314%s\003", (cbind->func->channel_access ? cbind->func->channel_access : "0")); - reply(getTextBot(), user, "\002CACCESS \002 %s", caccess); - return ret; -} - -static int global_cmd_modcmd_oaccess(struct UserNode *user, struct cmd_binding *cbind, char *value) { - char oaccess[MAXLEN]; - int ret = 0; - if(value) { - if(!strcmp(value, "*")) - value = NULL; - bind_botwise_set_global_access(cbind->botid, cbind->clientid, cbind->cmd, atoi(value)); - if(cbind->botid == 0) - printf_mysql_query("UPDATE `bot_binds` SET `global_access` = %s%s%s WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->clientid, escape_string(cbind->cmd)); - else - printf_mysql_query("UPDATE `bot_binds` SET `global_access` = %s%s%s WHERE `botclass` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->botid, escape_string(cbind->cmd)); - - ret = 1; - } - if(cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) - sprintf(oaccess, "%d", cbind->global_access); - else - sprintf(oaccess, "\00314%d\003", (cbind->func->global_access ? cbind->func->global_access : 0)); - reply(getTextBot(), user, "\002OACCESS \002 %s", oaccess); - return ret; -} - diff --git a/src/cmd_global_motd.c b/src/cmd_global_motd.c deleted file mode 100644 index 0340e47..0000000 --- a/src/cmd_global_motd.c +++ /dev/null @@ -1,36 +0,0 @@ -/* cmd_global_motd.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* no args -*/ - -CMD_BIND(global_cmd_motd) { - FILE *f; - f = fopen("motd.txt", "rb"); - if(!f) return; - char line[MAXLEN]; - char *a; - while (fgets(line, MAXLEN, f) != NULL) { - if((a = strchr(line, '\n'))) - *a = '\0'; - reply(getTextBot(), user, "%s", line); - } - fclose(f); -} \ No newline at end of file diff --git a/src/cmd_global_netinfo.c b/src/cmd_global_netinfo.c deleted file mode 100644 index 3d01c98..0000000 --- a/src/cmd_global_netinfo.c +++ /dev/null @@ -1,177 +0,0 @@ -/* cmd_global_netinfo.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* no args -*/ - -CMD_BIND(global_cmd_netinfo) { - reply(getTextBot(), user, "NS_NETINFO_HEADER"); - char tmp[MAXLEN]; - struct Table *table; - table = table_init(2, 19, 0); - char *content[2]; - - content[0] = get_language_string(user, "NS_NETINFO_UPTIME"); - content[1] = timeToStr(user, (time(0) - start_time), 3, tmp); - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_BOTS"); - struct ClientSocket *cclient; - int bot_count = 0, connected_bot_count = 0; - float traffic_in = 0, traffic_out = 0; - for(cclient = getBots(0, NULL); cclient; cclient = getBots(0, cclient)) { - bot_count++; - if(cclient->flags & SOCKET_FLAG_READY) - connected_bot_count++; - traffic_in += cclient->traffic_in; - traffic_out += cclient->traffic_out; - } - sprintf(tmp, "%d (%d connected)", bot_count, connected_bot_count); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_TRAFFIC"); - sprintf(tmp, "in: %.2f kb out: %.2f kb", traffic_in / 1024, traffic_out / 1024); - content[1] = tmp; - table_add(table, content); - - int channel_count = getChannelCount(); - float channel_memory = channel_count * sizeof(struct ChanNode); - int channel_ban_count = getChanBanCount(); - float channel_ban_memory = channel_ban_count * sizeof(struct BanNode); - int user_count = getUserCount(); - float user_memory = user_count * sizeof(struct UserNode); - int chanuser_count = getChanUserCount(); - float chanuser_memory = chanuser_count * sizeof(struct ChanUser); - float total_memory = channel_memory + channel_ban_memory + user_memory + chanuser_memory; - content[0] = get_language_string(user, "NS_NETINFO_CACHE"); - sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024); - content[1] = tmp; - table_add(table, content); - content[0] = get_language_string(user, "NS_NETINFO_CHANNEL"); - sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", channel_count, channel_memory / 1024, channel_count, (unsigned int) sizeof(struct ChanNode), channel_memory / 1024); - content[1] = tmp; - table_add(table, content); - content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN"); - sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", channel_ban_count, channel_ban_memory / 1024, channel_ban_count, (unsigned int) sizeof(struct BanNode), channel_ban_memory / 1024); - content[1] = tmp; - table_add(table, content); - content[0] = get_language_string(user, "NS_NETINFO_USER"); - sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", user_count, user_memory / 1024, user_count, (unsigned int) sizeof(struct UserNode), user_memory / 1024); - content[1] = tmp; - table_add(table, content); - content[0] = get_language_string(user, "NS_NETINFO_CHANUSER"); - sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", chanuser_count, chanuser_memory / 1024, chanuser_count, (unsigned int) sizeof(struct ChanUser), chanuser_memory / 1024); - content[1] = tmp; - table_add(table, content); - - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SHOW TABLE STATUS"); - res = mysql_use(); - int mysql_entrys[4]; - float mysql_length[5]; - total_memory = 0; - mysql_entrys[0] = 0; mysql_entrys[1] = 0; mysql_entrys[2] = 0; mysql_entrys[3] = 0; - mysql_length[0] = 0; mysql_length[1] = 0; mysql_length[2] = 0; mysql_length[3] = 0; mysql_length[4] = 0; - while ((row = mysql_fetch_row(res)) != NULL) { - if(!stricmp(row[0], "channels")) { - mysql_entrys[0] = atoi(row[4]); - mysql_length[0] = atof(row[6]); - total_memory += atof(row[6]); - } else if(!stricmp(row[0], "bans")) { - mysql_entrys[1] = atoi(row[4]); - mysql_length[1] = atof(row[6]); - total_memory += atof(row[6]); - } else if(!stricmp(row[0], "users")) { - mysql_entrys[2] = atoi(row[4]); - mysql_length[2] = atof(row[6]); - total_memory += atof(row[6]); - } else if(!stricmp(row[0], "chanusers")) { - mysql_entrys[3] = atoi(row[4]); - mysql_length[3] = atof(row[6]); - total_memory += atof(row[6]); - } else { - mysql_length[4] += atof(row[6]); - total_memory += atof(row[6]); - } - } - - content[0] = get_language_string(user, "NS_NETINFO_DATABASE"); - sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_CHANNEL"); - sprintf(tmp, "%d %.2f kB", mysql_entrys[0], mysql_length[0] / 1024); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN"); - sprintf(tmp, "%d %.2f kB", mysql_entrys[1], mysql_length[1] / 1024); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_USER"); - sprintf(tmp, "%d %.2f kB", mysql_entrys[2], mysql_length[2] / 1024); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_CHANUSER"); - sprintf(tmp, "%d %.2f kB", mysql_entrys[3], mysql_length[3] / 1024); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_OTHER"); - sprintf(tmp, "* %.2f kB", mysql_length[4] / 1024); - content[1] = tmp; - table_add(table, content); - - #ifdef HAVE_THREADS - content[0] = get_language_string(user, "NS_NETINFO_THREADS"); - sprintf(tmp, "%d (current thread: %i)", running_threads, getCurrentThreadID()); - content[1] = tmp; - table_add(table, content); - #endif - - if(strcmp(revision, "")) - sprintf(tmp, "%s.%d (%s)", NEONSERV_VERSION, patchlevel, revision); - else - sprintf(tmp, "%s.%d", NEONSERV_VERSION, patchlevel); - content[0] = get_language_string(user, "NS_NETINFO_VERSION"); - content[1] = tmp; - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_COMPILER"); - content[1] = build_language_string(user, tmp, "NS_NETINFO_COMPILER_VALUE", COMPILER, creation); - table_add(table, content); - - content[0] = get_language_string(user, "NS_NETINFO_CODE"); - content[1] = build_language_string(user, tmp, "NS_NETINFO_CODE_VALUE", codelines); - table_add(table, content); - - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); -} - diff --git a/src/cmd_global_notice.c b/src/cmd_global_notice.c deleted file mode 100644 index b42b1c3..0000000 --- a/src/cmd_global_notice.c +++ /dev/null @@ -1,28 +0,0 @@ -/* cmd_global_notice.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] target -* argv[1-*] message -*/ - -CMD_BIND(global_cmd_notice) { - char *message = merge_argv(argv, 1, argc); - putsock(client, "NOTICE %s :%s", argv[0], message); -} \ No newline at end of file diff --git a/src/cmd_global_raw.c b/src/cmd_global_raw.c deleted file mode 100644 index 1d8ce55..0000000 --- a/src/cmd_global_raw.c +++ /dev/null @@ -1,27 +0,0 @@ -/* cmd_global_raw.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0-*] raw -*/ - -CMD_BIND(global_cmd_raw) { - char *raw = merge_argv(argv, 0, argc); - putsock(client, "%s", raw); -} \ No newline at end of file diff --git a/src/cmd_global_reconnect.c b/src/cmd_global_reconnect.c deleted file mode 100644 index acf8c2e..0000000 --- a/src/cmd_global_reconnect.c +++ /dev/null @@ -1,49 +0,0 @@ -/* cmd_global_reconnect.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] nick/botid -*/ - -CMD_BIND(global_cmd_reconnect) { - int botid; - if(argc) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s' OR `id` = '%s'", escape_string(argv[0]), escape_string(argv[0])); - res = mysql_use(); - if((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_DELBOT_NOT_FOUND", argv[0]); - return; - } - botid = atoi(row[0]); - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == botid) { - disconnect_socket(client); - client->flags |= SOCKET_FLAG_FAST_JUMP; - break; - } - } - } else { - disconnect_socket(client); - connect_socket(client); - } - reply(getTextBot(), user, "NS_RECONNECT_DONE"); - logEvent(event); -} diff --git a/src/cmd_global_register.c b/src/cmd_global_register.c deleted file mode 100644 index 548860d..0000000 --- a/src/cmd_global_register.c +++ /dev/null @@ -1,266 +0,0 @@ -/* cmd_global_register.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] - channel -* argv[1] - nick / *auth -* argv[2] - (optional) bot nick -*/ -static AUTHLOOKUP_CALLBACK(global_cmd_register_auth_lookup); -static USERAUTH_CALLBACK(global_cmd_register_nick_lookup); -static void global_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth, int multibot, char *botname); - -struct global_cmd_register_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - struct Event *event; - char *nick; - char *channel; - char *botname; - int multibot; -}; - -CMD_BIND(global_cmd_register) { - MYSQL_RES *res; - MYSQL_ROW row; - char *channel = argv[0]; - char *botname = (argc > 2 ? argv[2] : NULL); - int multibot = 0; - if(!is_valid_chan(channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); - return; - } - printf_mysql_query("SELECT `botid`, `botclass` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[1]) == client->botid && (client->botid || client->clientid == atoi(row[0]))) { - reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick); - return; - } else - multibot = 1; - } - printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(channel)); - res = mysql_use(); - if((row = mysql_fetch_row(res)) != NULL) { - int expire_time = atoi(row[1]); - if(expire_time) { - if(expire_time - time(0) <= 0) { - printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); - } else { - char expireBuf[MAXLEN]; - reply(getTextBot(), user, "NS_DNR_SET_EXPIRES", channel, row[0], timeToStr(user, (expire_time - time(0)), 2, expireBuf), row[2]); - return; - } - } else { - reply(getTextBot(), user, "NS_DNR_SET", channel, row[0], row[2]); - return; - } - } - //if theres already another bot in the channel we don't need a owner parameter... - if(multibot && argc < 2) { - //skip all these owner check lines - multibot = 2; - global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, NULL, multibot, botname); - return; - } else if(argc < 2) { - global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, user->auth, multibot, botname); - return; - } - //check own access - if(argv[1][0] == '*') { - //we've got an auth - argv[1]++; - printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[1])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, row[0], multibot, botname); - } else { - //we need to create a new user... - //but first lookup the auth to check if it really exists - struct global_cmd_register_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->nick = strdup(argv[1]); - cache->channel = strdup(channel); - cache->multibot = multibot; - cache->botname = (botname ? strdup(botname) : NULL); - lookup_authname(argv[1], global_cmd_register_auth_lookup, cache); - } - } else { - struct UserNode *cuser = getUserByNick(argv[1]); - if(!cuser) { - cuser = createTempUser(argv[1]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[1]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, cuser->auth, multibot, botname); - } else { - struct global_cmd_register_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->nick = strdup(argv[1]); - cache->channel = strdup(channel); - cache->multibot = multibot; - cache->botname = (botname ? strdup(botname) : NULL); - get_userauth(cuser, global_cmd_register_nick_lookup, cache); - } - } -} - -static AUTHLOOKUP_CALLBACK(global_cmd_register_auth_lookup) { - struct global_cmd_register_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); - } else - global_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, auth, cache->multibot, cache->botname); - if(cache->botname) - free(cache->botname); - free(cache->channel); - free(cache->nick); - free(cache); -} - -static USERAUTH_CALLBACK(global_cmd_register_nick_lookup) { - struct global_cmd_register_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - global_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, user->auth, cache->multibot, cache->botname); - if(cache->botname) - free(cache->botname); - free(cache->channel); - free(cache->nick); - free(cache); -} - -static void global_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth, int multibot, char *botname) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row, row2; - int userid = 0, adminid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) - adminid = atoi(row[0]); - else - adminid = 0; - if(multibot != 2) { - printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(auth)); - res = mysql_use(); - if((row = mysql_fetch_row(res)) != NULL) { - int expire_time = atoi(row[1]); - if(expire_time) { - if(expire_time - time(0) <= 0) { - printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); - } else { - char expireBuf[MAXLEN]; - reply(getTextBot(), user, "NS_DNR_SET_EXPIRES", auth, row[0], timeToStr(user, (expire_time - time(0)), 2, expireBuf), row[2]); - return; - } - } else { - reply(getTextBot(), user, "NS_DNR_SET", auth, row[0], row[2]); - return; - } - } - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); - userid = (int) mysql_insert_id(get_mysql_conn()); - } - } - if(client->botid) - printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger`, `nick` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1' ORDER BY `register_priority` DESC", client->botid); - else - printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger`, `nick` FROM `bots` WHERE `id` = '%d' AND `active` = '1'", client->clientid); - res = mysql_use(); - int botid = 0; - while ((row = mysql_fetch_row(res)) != NULL) { - //check channel count - printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]); - row2 = mysql_fetch_row(mysql_use()); - if(atoi(row2[0]) < atoi(row[1]) && (!botname || !stricmp(botname, row[3]))) { - botid = atoi(row[0]); - break; - } - } - if(!botid) { - reply(textclient, user, "NS_REGISTER_FULL"); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - printf_mysql_query("UPDATE `channels` SET `channel_registered` = UNIX_TIMESTAMP(), `channel_registrator` = '%d' WHERE `channel_id` = '%d'", adminid, chanid); - } else { - printf_mysql_query("INSERT INTO `channels` (`channel_name`, `channel_registered`, `channel_registrator`) VALUES ('%s', UNIX_TIMESTAMP(), '%d')", escape_string(channel), adminid); - chanid = (int) mysql_insert_id(get_mysql_conn()); - } - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - putsock(bot, "JOIN %s", channel); - } else - reply(textclient, user, "NS_REGISTER_DISCONNECTED", channel); - printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', NULL)", botid, chanid); - if(multibot != 2) { - if(multibot) { - printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = 499 WHERE `chanuser_cid` = '%d' AND `chanuser_access` = '500'", chanid); - printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chanid, userid); - } else - 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); - } else - reply(textclient, user, "NS_REGISTER_DONE_NOAUTH", channel); - logEvent(event); -} diff --git a/src/cmd_global_reload.c b/src/cmd_global_reload.c deleted file mode 100644 index 883b3ed..0000000 --- a/src/cmd_global_reload.c +++ /dev/null @@ -1,27 +0,0 @@ -/* cmd_global_reload.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] soft (optional) -*/ - -CMD_BIND(global_cmd_reload) { - reload_config(); - reply(client, user, "reloaded."); -} diff --git a/src/cmd_global_reloadlang.c b/src/cmd_global_reloadlang.c deleted file mode 100644 index d99062e..0000000 --- a/src/cmd_global_reloadlang.c +++ /dev/null @@ -1,35 +0,0 @@ -/* cmd_global_reloadlang.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] language tag -*/ - -CMD_BIND(global_cmd_reloadlang) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `text`, `lang` FROM `language` WHERE `ident` = 'name' AND `lang` = '%s'", escape_string(argv[0])); - res = mysql_use(); - if((row = mysql_fetch_row(res)) != NULL) { - load_language(row[1], row[0]); - reply(getTextBot(), user, "NS_RELOADLANG_DONE", row[0], row[1]); - } else { - reply(getTextBot(), user, "NS_RELOADLANG_UNKNOWN", argv[0]); - } -} \ No newline at end of file diff --git a/src/cmd_global_restart.c b/src/cmd_global_restart.c deleted file mode 100644 index ad580cd..0000000 --- a/src/cmd_global_restart.c +++ /dev/null @@ -1,28 +0,0 @@ -/* cmd_global_restart.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] soft (optional) -*/ - -CMD_BIND(global_cmd_restart) { - int hard_restart = 1; - if(argc > 0 && !stricmp(argv[0], "soft")) hard_restart = 0; - restart_bot(hard_restart); -} diff --git a/src/cmd_global_say.c b/src/cmd_global_say.c deleted file mode 100644 index e81cfc4..0000000 --- a/src/cmd_global_say.c +++ /dev/null @@ -1,28 +0,0 @@ -/* cmd_global_say.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] target -* argv[1-*] message -*/ - -CMD_BIND(global_cmd_say) { - char *message = merge_argv(argv, 1, argc); - putsock(client, "PRIVMSG %s :%s", argv[0], message); -} \ No newline at end of file diff --git a/src/cmd_global_setaccess.c b/src/cmd_global_setaccess.c deleted file mode 100644 index 0458bd6..0000000 --- a/src/cmd_global_setaccess.c +++ /dev/null @@ -1,144 +0,0 @@ -/* cmd_global_setaccess.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] - nick / *auth -* argv[1] - global access -*/ -static AUTHLOOKUP_CALLBACK(global_cmd_setaccess_auth_lookup); -static USERAUTH_CALLBACK(global_cmd_setaccess_nick_lookup); -static void global_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int access); - -struct global_cmd_setaccess_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - int access; - char *nick; -}; - -CMD_BIND(global_cmd_setaccess) { - int caccess; - MYSQL_RES *res; - MYSQL_ROW row; - caccess = atoi(argv[1]); - if(caccess < 0 || caccess > 1000) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return; - } - printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL || atoi(row[0]) < caccess) { - reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); - return; - } - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - 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) { - global_cmd_setaccess_async1(client, getTextBot(), user, 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 - struct global_cmd_setaccess_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->access = caccess; - cache->nick = strdup(argv[0]); - lookup_authname(argv[0], global_cmd_setaccess_auth_lookup, cache); - } - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - global_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], cuser->auth, caccess); - } else { - struct global_cmd_setaccess_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->access = caccess; - cache->nick = strdup(argv[0]); - get_userauth(cuser, global_cmd_setaccess_nick_lookup, cache); - } - } -} - -static AUTHLOOKUP_CALLBACK(global_cmd_setaccess_auth_lookup) { - struct global_cmd_setaccess_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); - } else - global_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->access); - free(cache->nick); - free(cache); -} - -static USERAUTH_CALLBACK(global_cmd_setaccess_nick_lookup) { - struct global_cmd_setaccess_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - global_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->access); - free(cache->nick); - free(cache); -} - -static void global_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int caccess) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `user_id`, `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[1]) != caccess) - printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_id` = '%s'", caccess, row[0]); - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`) VALUES ('%s', '%d')", escape_string(auth), caccess); - } - reply(textclient, user, "NS_SETACCESS_DONE", auth, caccess); - logEvent(event); -} diff --git a/src/cmd_global_setbot.c b/src/cmd_global_setbot.c deleted file mode 100644 index e823a9e..0000000 --- a/src/cmd_global_setbot.c +++ /dev/null @@ -1,527 +0,0 @@ -/* cmd_global_setbot.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] botid -* argv[1] setting -* argv[2] value -*/ - -static int global_cmd_setbot_active(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_nick(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_ident(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_realname(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_server(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_port(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_bind(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_ssl(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_serverpass(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_class(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_queue(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_prefered(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_maxchan(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_priority(struct UserNode *user, MYSQL_ROW bot, char *value); -static int global_cmd_setbot_trigger(struct UserNode *user, MYSQL_ROW bot, char *value); - -CMD_BIND(global_cmd_setbot) { - MYSQL_RES *res; - MYSQL_ROW row; - int botid = atoi(argv[0]); - printf_mysql_query("SELECT `active`, `nick`, `server`, `port`, `pass`, `botclass`, `textbot`, `queue`, `defaulttrigger`, `max_channels`, `register_priority`, `bind`, `ident`, `realname`, `ssl`, `id` FROM `bots` WHERE `id` = '%d'", botid); - res = mysql_use(); - if(!(row = mysql_fetch_row(res))) { - reply(getTextBot(), user, "NS_SETBOT_UNKNOWN", botid); - return; - } - if(argc > 1) { - char *value; - if(argc > 2) { - value = merge_argv(argv, 2, argc); - } else - value = NULL; - int log_event = 0; - if(!stricmp(argv[1], "active")) log_event = global_cmd_setbot_active(user, row, value); - else if(!stricmp(argv[1], "nick")) log_event = global_cmd_setbot_nick(user, row, value); - else if(!stricmp(argv[1], "ident")) log_event = global_cmd_setbot_ident(user, row, value); - else if(!stricmp(argv[1], "realname")) log_event = global_cmd_setbot_realname(user, row, value); - else if(!stricmp(argv[1], "server")) log_event = global_cmd_setbot_server(user, row, value); - else if(!stricmp(argv[1], "port")) log_event = global_cmd_setbot_port(user, row, value); - else if(!stricmp(argv[1], "bind")) log_event = global_cmd_setbot_bind(user, row, value); - else if(!stricmp(argv[1], "ssl")) log_event = global_cmd_setbot_ssl(user, row, value); - else if(!stricmp(argv[1], "serverpass")) log_event = global_cmd_setbot_serverpass(user, row, value); - else if(!stricmp(argv[1], "botclass")) log_event = global_cmd_setbot_class(user, row, value); - else if(!stricmp(argv[1], "queue")) log_event = global_cmd_setbot_queue(user, row, value); - else if(!stricmp(argv[1], "prefered")) log_event = global_cmd_setbot_prefered(user, row, value); - else if(!stricmp(argv[1], "maxchan")) log_event = global_cmd_setbot_maxchan(user, row, value); - else if(!stricmp(argv[1], "priority")) log_event = global_cmd_setbot_priority(user, row, value); - else if(!stricmp(argv[1], "trigger")) log_event = global_cmd_setbot_trigger(user, row, value); - else { - reply(getTextBot(), user, "NS_SETBOT_SETTING", argv[1]); - } - if(log_event) { - if(!stricmp(argv[1], "serverpass") && value) { //censor server password - char cmd_args[MAXLEN]; - sprintf(cmd_args, "%d SERVERPASS ***", botid); - free(event->arguments); - event->arguments = strdup(cmd_args); - } - logEvent(event); - } - } else { - reply(getTextBot(), user, "NS_SETBOT_HEADER", botid); - global_cmd_setbot_active(user, row, NULL); - global_cmd_setbot_nick(user, row, NULL); - global_cmd_setbot_ident(user, row, NULL); - global_cmd_setbot_realname(user, row, NULL); - global_cmd_setbot_server(user, row, NULL); - global_cmd_setbot_port(user, row, NULL); - global_cmd_setbot_bind(user, row, NULL); - global_cmd_setbot_ssl(user, row, NULL); - global_cmd_setbot_serverpass(user, row, NULL); - global_cmd_setbot_class(user, row, NULL); - global_cmd_setbot_queue(user, row, NULL); - global_cmd_setbot_prefered(user, row, NULL); - global_cmd_setbot_maxchan(user, row, NULL); - global_cmd_setbot_priority(user, row, NULL); - global_cmd_setbot_trigger(user, row, NULL); - } -} - -static int global_cmd_setbot_active(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = ((bot[0] && !strcmp(bot[0], "1")) ? 1 : 0); - int ret = 0; - if(value) { - if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { - val = 0; - } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { - val = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); - return 0; - } - if(val != ((bot[0] && !strcmp(bot[0], "1")) ? 1 : 0)) { - if(val) { - //add the bot - struct ClientSocket *client; - client = create_socket(bot[2], atoi(bot[3]), bot[11], bot[4], bot[1], bot[12], bot[13]); - client->flags |= (strcmp(bot[6], "0") ? SOCKET_FLAG_PREFERRED : 0); - client->flags |= (strcmp(bot[7], "0") ? SOCKET_FLAG_USE_QUEUE : 0); - client->flags |= (strcmp(bot[14], "0") ? SOCKET_FLAG_SSL : 0); - client->botid = atoi(bot[5]); - client->clientid = atoi(bot[15]); - connect_socket(client); - if(client->botid == 0) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d'", client->clientid); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(bind_botwise_cmd_to_command(0, client->clientid, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_botwise_set_parameters(0, client->clientid, row[0], row[2]); - } - if(row[3]) { - bind_botwise_set_global_access(0, client->clientid, row[0], atoi(row[3])); - } - if(row[4]) { - bind_botwise_set_channel_access(0, client->clientid, row[0], row[4]); - } - } - } - bind_botwise_unbound_required_functions(0, client->clientid); - } - } else { - //remove the bot - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - unbind_botwise_allcmd(client->clientid); - close_socket(client); - break; - } - } - } - printf_mysql_query("UPDATE `bots` SET `active` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - } - reply(getTextBot(), user, "\002ACTIVE \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); - return ret; -} - -static int global_cmd_setbot_nick(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[1]; - int ret = 0; - if(value) { - if(!is_valid_nick(value)) { - reply(getTextBot(), user, "NS_SETBOT_NICK_INVALID", value); - return 0; - } - //rename the bot - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->nick) - free(client->nick); - client->nick = strdup(value); - if(client->flags & SOCKET_FLAG_READY) - putsock(client, "NICK %s", value); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `nick` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002NICK \002 %s", val); - return ret; -} - -static int global_cmd_setbot_ident(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[12]; - int ret = 0; - if(value) { - if(strlen(value) > 12) - value[12] = '\0'; - //rename the bot - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->ident) - free(client->ident); - client->ident = strdup(value); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `ident` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002IDENT \002 %s", val); - return ret; -} - -static int global_cmd_setbot_realname(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[13]; - int ret = 0; - if(value) { - if(strlen(value) > 255) - value[255] = '\0'; - //rename the bot - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->ident) - free(client->ident); - client->ident = strdup(value); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `realname` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002REALNAME \002 %s", val); - return ret; -} - -static int global_cmd_setbot_server(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[2]; - int ret = 0; - if(value) { - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->host) - free(client->host); - client->host = strdup(value); - if(client->flags & SOCKET_FLAG_READY) - reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `server` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002SERVER \002 %s", val); - return ret; -} - -static int global_cmd_setbot_port(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = atoi(bot[3]); - int ret = 0; - if(value) { - val = atoi(value); - if(val <= 0 || val > 65534) { - reply(getTextBot(), user, "NS_SETBOT_PORT_INVALID", value); - return 0; - } - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - client->port = val; - if(client->flags & SOCKET_FLAG_READY) - reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `port` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002PORT \002 %d", val); - return ret; -} - -static int global_cmd_setbot_bind(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[11]; - int ret = 0; - if(value) { - if(!strcmp(value, "*")) - value = NULL; - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->bind) - free(client->bind); - client->bind = (value ? strdup(value) : NULL); - if(client->flags & SOCKET_FLAG_READY) - reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); - break; - } - } - if(value) - printf_mysql_query("UPDATE `bots` SET `bind` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - else - printf_mysql_query("UPDATE `bots` SET `bind` = NULL WHERE `id` = '%s'", bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002BIND \002 %s", val); - return ret; -} - -static int global_cmd_setbot_ssl(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = (strcmp(bot[14], "0") ? 1 : 0); - int ret = 0; - if(value) { - if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { - val = 0; - } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { - val = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); - return 0; - } - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(val) - client->flags |= SOCKET_FLAG_SSL; - else - client->flags &= ~SOCKET_FLAG_SSL; - if(client->flags & SOCKET_FLAG_READY) - reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `ssl` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002SSL \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); - return ret; -} - -static int global_cmd_setbot_serverpass(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[4]; - int ret = 0; - if(value) { - if(!strcmp(value, "*")) - value = ""; - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(client->pass) - free(client->pass); - client->pass = (value ? strdup(value) : NULL); - if(client->flags & SOCKET_FLAG_READY) - reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); - break; - } - } - printf_mysql_query("UPDATE `bots` SET `pass` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002SERVERPASS \002 %s", val); - return ret; -} - -static int global_cmd_setbot_class(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = atoi(bot[5]); - int ret = 0; - if(value) { - if((val = resolve_botalias(value)) == -1) { - reply(getTextBot(), user, "NS_SETBOT_INVALID_CLASS", value); - return 0; - } - if(val != atoi(bot[5])) { - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - unbind_botwise_allcmd(client->clientid); - client->botid = val; - if(client->botid == 0) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d'", client->clientid); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(bind_botwise_cmd_to_command(client->botid, client->clientid, row[0], row[1])) { - if(row[2] && strcmp(row[2], "")) { - bind_botwise_set_parameters(client->botid, client->clientid, row[0], row[2]); - } - if(row[3]) { - bind_botwise_set_global_access(client->botid, client->clientid, row[0], atoi(row[3])); - } - if(row[4]) { - bind_botwise_set_channel_access(client->botid, client->clientid, row[0], row[4]); - } - } - } - bind_botwise_unbound_required_functions(client->botid, client->clientid); - } - break; - } - } - printf_mysql_query("UPDATE `bots` SET `botclass` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - } - reply(getTextBot(), user, "\002BOTCLASS \002 %s", resolve_botid(val)); - return ret; -} - -static int global_cmd_setbot_queue(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = (strcmp(bot[7], "0") ? 1 : 0); - int ret = 0; - if(value) { - if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { - val = 0; - } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { - val = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); - return 0; - } - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(val) - client->flags |= SOCKET_FLAG_USE_QUEUE; - else - client->flags &= ~SOCKET_FLAG_USE_QUEUE; - break; - } - } - printf_mysql_query("UPDATE `bots` SET `queue` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002QUEUE \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); - return ret; -} - -static int global_cmd_setbot_prefered(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = (strcmp(bot[6], "0") ? 1 : 0); - int ret = 0; - if(value) { - if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { - val = 0; - } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { - val = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); - return 0; - } - struct ClientSocket *client; - for(client = getBots(0, NULL); client; client = getBots(0, client)) { - if(client->clientid == atoi(bot[15])) { - if(val) - client->flags |= SOCKET_FLAG_PREFERRED; - else - client->flags &= ~SOCKET_FLAG_PREFERRED; - break; - } - } - printf_mysql_query("UPDATE `bots` SET `prefered` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002PREFERED \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); - return ret; -} - -static int global_cmd_setbot_maxchan(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = atoi(bot[9]); - int ret = 0; - if(value) { - val = atoi(value); - if(val < 0 || val > 99999) { - reply(getTextBot(), user, "NS_SETBOT_MAXCHAN_INVALID", value); - return 0; - } - printf_mysql_query("UPDATE `bots` SET `max_channels` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002MAXCHAN \002 %d", val); - return ret; -} - -static int global_cmd_setbot_priority(struct UserNode *user, MYSQL_ROW bot, char *value) { - int val = atoi(bot[10]); - int ret = 0; - if(value) { - val = atoi(value); - if(val < 0 || val > 99) { - reply(getTextBot(), user, "NS_SETBOT_PRIORITY_INVALID", value); - return 0; - } - printf_mysql_query("UPDATE `bots` SET `register_priority` = '%d' WHERE `id` = '%s'", val, bot[15]); - ret = 1; - } - reply(getTextBot(), user, "\002PRIORITY \002 %d", val); - return ret; -} - -static int global_cmd_setbot_trigger(struct UserNode *user, MYSQL_ROW bot, char *value) { - char *val = bot[8]; - int ret = 0; - if(value) { - if(!*value || strlen(value) > 10) { - reply(getTextBot(), user, "NS_SETBOT_TRIGGER_INVALID", value); - return 0; - } - printf_mysql_query("UPDATE `bots` SET `defaulttrigger` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); - flush_trigger_cache(atoi(bot[5]), atoi(bot[15])); - reply(getTextBot(), user, "NS_SETBOT_TRIGGER_NOTE"); - val = value; - ret = 1; - } - reply(getTextBot(), user, "\002TRIGGER \002 %s", val); - return ret; -} diff --git a/src/cmd_global_staff.c b/src/cmd_global_staff.c deleted file mode 100644 index 3f1989e..0000000 --- a/src/cmd_global_staff.c +++ /dev/null @@ -1,52 +0,0 @@ -/* cmd_global_staff.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* no arguments -*/ - -CMD_BIND(global_cmd_staff) { - MYSQL_RES *res, *res2; - MYSQL_ROW row, row2; - printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` ORDER BY `rank_order` ASC"); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - printf_mysql_query("SELECT `user_user`, `user_god` FROM `users` WHERE `user_rank` = '%s'", row[0]); - res2 = mysql_use(); - if(mysql_num_rows(res2)) { - reply(getTextBot(), user, "\002%s\002", row[1]); - while ((row2 = mysql_fetch_row(res2)) != NULL) { - if(strcmp(row2[1], "0")) { - //god enabled - show nicks - char loggedinBuf[MAXLEN]; - int loggedinPos = 0; - struct UserNode *cuser; - for(cuser = getUsersWithAuth(row2[0], NULL); cuser; cuser = getUsersWithAuth(row2[0], cuser)) { - loggedinPos += sprintf(loggedinBuf+loggedinPos, (loggedinPos ? ", %s" : "%s"), cuser->nick); - } - if(loggedinPos) - reply(getTextBot(), user, " %s (%s: %s)", row2[0], get_language_string(user, "NS_STAFF_LOGGEDIN"), loggedinBuf); - else - reply(getTextBot(), user, " %s", row2[0]); - } else - reply(getTextBot(), user, " %s", row2[0]); - } - } - } -} diff --git a/src/cmd_global_unbind.c b/src/cmd_global_unbind.c deleted file mode 100644 index 8cd8f45..0000000 --- a/src/cmd_global_unbind.c +++ /dev/null @@ -1,54 +0,0 @@ -/* cmd_global_unbind.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] command name -*/ - -CMD_BIND(global_cmd_unbind) { - MYSQL_RES *res; - MYSQL_ROW row; - struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); - if(client->botid == 0) - printf_mysql_query("SELECT `id`, `function` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", client->clientid, escape_string(argv[0])); - else - printf_mysql_query("SELECT `id`, `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL && (!cbind || !(cbind->flags & CMDFLAG_TEMPONARY_BIND))) { - reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); - return; - } - struct cmd_function *function = find_cmd_function(client->botid, cbind->func->name); - if(function && (function->flags & CMDFLAG_REQUIRED)) { - if(client->botid == 0) - printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d' AND `function` = '%s'", client->clientid, escape_string(function->name)); - else - printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '%d' AND `function` = '%s'", client->botid, escape_string(function->name)); - res = mysql_use(); - if (mysql_num_rows(res) <= 1) { - reply(getTextBot(), user, "NS_UNBIND_REQUIRED", function->name); - return; - } - } - unbind_botwise_cmd(client->botid, client->clientid, argv[0]); - if(!cbind || !(cbind->flags & CMDFLAG_TEMPONARY_BIND)) - printf_mysql_query("DELETE FROM `bot_binds` WHERE `id` = '%s'", row[0]); - reply(getTextBot(), user, "NS_UNBIND_DONE", argv[0]); - logEvent(event); -} diff --git a/src/cmd_global_unregister.c b/src/cmd_global_unregister.c deleted file mode 100644 index 206e763..0000000 --- a/src/cmd_global_unregister.c +++ /dev/null @@ -1,65 +0,0 @@ -/* cmd_global_unregister.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* argv[0] - channel -*/ -CMD_BIND(global_cmd_unregister) { - MYSQL_RES *res; - MYSQL_ROW row; - char *channel; - if(argc) - channel = argv[0]; - else - channel = (chan ? chan->name : ""); - if(!is_valid_chan(channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - } else { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - if(client->botid == 0) - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '0' AND `botid` = '%d'", chanid, client->clientid); - else - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - int botid = atoi(row[0]); - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]); - reply(getTextBot(), user, "NS_UNREGISTER_DONE", channel); - if(bot && strcmp(row[2], "1")) { - putsock(bot, "PART %s :Channel unregistered.", channel); - } - logEvent(event); -} diff --git a/src/cmd_global_version.c b/src/cmd_global_version.c deleted file mode 100644 index 307e34c..0000000 --- a/src/cmd_global_version.c +++ /dev/null @@ -1,37 +0,0 @@ -/* cmd_global_version.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" - -/* -* no args -*/ - -CMD_BIND(global_cmd_version) { - reply(getTextBot(), user, "\002NeonServ %s.%d\002 (%s), written by pk910", NEONSERV_VERSION, patchlevel, (strcmp(revision, "") ? revision : "-")); - reply(getTextBot(), user, "Build (#%s) %s (%s lines, " COMPILER ")", compilation, creation, codelines); - reply(getTextBot(), user, "NeonServ can be found on: http://dev.pk910.de/NeonServ"); - //helpers :D - reply(getTextBot(), user, "special thanks to:"); - reply(getTextBot(), user, " Zer0n, TeaTow, Phil (testing and ideas current version)"); - reply(getTextBot(), user, " Buschman, Zer0n, Neon (translating current version)"); - reply(getTextBot(), user, " Patschi95, DerGrinch, Darkfly, Zer0n, Buschman (testing and ideas older versions)"); - reply(getTextBot(), user, " Buschman, Georg, richard (translating older versions)"); - reply(getTextBot(), user, "and all the other users that reported all these nasty bugs :D"); - reply(getTextBot(), user, "\002If you found a bug or if you have a good idea report it on http://dev.pk910.de/BugTrack\002"); - -} \ No newline at end of file diff --git a/src/cmd_neonhelp.h b/src/cmd_neonhelp.h deleted file mode 100644 index 0fce87a..0000000 --- a/src/cmd_neonhelp.h +++ /dev/null @@ -1,37 +0,0 @@ -/* cmd_neonhelp.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _cmd_neonhelp_h -#define _cmd_neonhelp_h -#include "main.h" -#include "modcmd.h" -#include "mysqlConn.h" -#include "ClientSocket.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "DBHelper.h" -#include "IRCParser.h" -#include "bot_NeonHelp.h" -#include "lang.h" -#include "tools.h" - -CMD_BIND(neonhelp_cmd_delete); -CMD_BIND(neonhelp_cmd_next); -CMD_BIND(neonhelp_cmd_requests); -CMD_BIND(neonhelp_cmd_stats); - -#endif \ No newline at end of file diff --git a/src/cmd_neonhelp_delete.c b/src/cmd_neonhelp_delete.c deleted file mode 100644 index 43d5829..0000000 --- a/src/cmd_neonhelp_delete.c +++ /dev/null @@ -1,83 +0,0 @@ -/* cmd_neonhelp_delete.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonhelp.h" - -/* -* argv[0] suppid -*/ - -CMD_BIND(neonhelp_cmd_delete) { - //check permissions - MYSQL_RES *res; - MYSQL_ROW row, row2; - int caccess = 0; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) return; - //check if the user is a supporter (access in the support channel) - if((user->flags & USERFLAG_ISAUTHED)) { - int userid; - if(user->flags & USERFLAG_HAS_USERID) - userid = user->user_id; - else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - userid = atoi(row2[0]); - user->user_id = userid; - user->flags |= USERFLAG_HAS_USERID; - } else - userid = 0; - } - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - int cflags = atoi(row2[1]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) - caccess = atoi(row2[0]); - } - } - if(!caccess) { - reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); - return; - } - if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { - reply(getTextBot(), user, "NH_NEXT_NONE"); - return; - } - struct NeonHelpNode *helpnode, *next_helpnode = NULL, *prev_helpnode = NULL; - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(atoi(argv[0]) == helpnode->suppid) { - next_helpnode = helpnode; - break; - } else - prev_helpnode = helpnode; - } - if(!next_helpnode) { - reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); - return; - } - reply(client, next_helpnode->user, "NH_DELETED", next_helpnode->suppid); - printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `id` = '%d'", next_helpnode->suppid); - if(prev_helpnode) - prev_helpnode->next = next_helpnode->next; - else - client->botclass_helpnode = next_helpnode->next; - reply(getTextBot(), user, "NH_DELETED_STAFF", next_helpnode->suppid, next_helpnode->user->nick); - free(next_helpnode); -} diff --git a/src/cmd_neonhelp_next.c b/src/cmd_neonhelp_next.c deleted file mode 100644 index 2e2a2d1..0000000 --- a/src/cmd_neonhelp_next.c +++ /dev/null @@ -1,108 +0,0 @@ -/* cmd_neonhelp_next.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonhelp.h" - -/* -* argv[0] (optional) suppid -*/ - -CMD_BIND(neonhelp_cmd_next) { - //check permissions - MYSQL_RES *res; - MYSQL_ROW row, row2; - int caccess = 0; - int userid; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) return; - //check if the user is a supporter (access in the support channel) - if((user->flags & USERFLAG_ISAUTHED)) { - if(user->flags & USERFLAG_HAS_USERID) - userid = user->user_id; - else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - userid = atoi(row2[0]); - user->user_id = userid; - user->flags |= USERFLAG_HAS_USERID; - } else - userid = 0; - } - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - int cflags = atoi(row2[1]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) - caccess = atoi(row2[0]); - } - } - if(!caccess) { - reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); - return; - } - if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { - reply(getTextBot(), user, "NH_NEXT_NONE"); - return; - } - struct NeonHelpNode *helpnode, *next_helpnode = NULL; - int lowest_id = -1; - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->status == 0) { - if(argc) { - if(atoi(argv[0]) == helpnode->suppid) { - next_helpnode = helpnode; - break; - } - } else { - if(helpnode->suppid < lowest_id || lowest_id == -1) { - lowest_id = helpnode->suppid; - next_helpnode = helpnode; - } - } - } - } - if(!next_helpnode) { - reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); - return; - } - printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = '%d'", next_helpnode->suppid); - res = mysql_use(); - if (!(row2 = mysql_fetch_row(res))) return; - reply(getTextBot(), user, "NH_NEXT_HEADER", next_helpnode->suppid, next_helpnode->user->nick); - char *a, *b = row2[0]; - do { - a = strstr(b, "\n"); - if(a) *a = '\0'; - reply(getTextBot(), user, " %s", b); - if(a) { - *a = '\n'; - b = a+1; - } - } while(a); - if(row[1]) - putsock(client, "INVITE %s %s", next_helpnode->user->nick, row[0]); - else - putsock(client, "MODE %s +v %s", row[0], next_helpnode->user->nick); - char sendbuf1[MAXLEN]; - char sendbuf2[MAXLEN]; - char *join_now = (row[1] ? build_language_string(user, sendbuf2, "NH_NEXT_JOIN", row[0]) : ""); - putsock(client, "PRIVMSG %s :%s %s", next_helpnode->user->nick, build_language_string(user, sendbuf1, "NH_NEXT_HELPER", next_helpnode->suppid, user->auth, user->nick), join_now); - next_helpnode->status = 1; - printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '1', `supporter` = '%d' WHERE `id` = '%d'", userid, next_helpnode->suppid); -} diff --git a/src/cmd_neonhelp_requests.c b/src/cmd_neonhelp_requests.c deleted file mode 100644 index b95a4b4..0000000 --- a/src/cmd_neonhelp_requests.c +++ /dev/null @@ -1,108 +0,0 @@ -/* cmd_neonhelp_requests.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonhelp.h" - -/* -* no args -*/ - -CMD_BIND(neonhelp_cmd_requests) { - //check permissions - MYSQL_RES *res; - MYSQL_ROW row, row2; - int caccess = 0; - int userid; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) return; - //check if the user is a supporter (access in the support channel) - if((user->flags & USERFLAG_ISAUTHED)) { - if(user->flags & USERFLAG_HAS_USERID) - userid = user->user_id; - else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - userid = atoi(row2[0]); - user->user_id = userid; - user->flags |= USERFLAG_HAS_USERID; - } else - userid = 0; - } - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - int cflags = atoi(row2[1]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) - caccess = atoi(row2[0]); - } - } - if(!caccess) { - reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); - return; - } - struct Table *table; - printf_mysql_query("SELECT `id`, `time`, `text` FROM `helpserv_requests` WHERE `botid` = '%d' AND `status` != 2 ORDER BY `time` DESC", client->clientid); - res = mysql_use(); - table = table_init(5, mysql_num_rows(res) + 1, 0); - char *content[5]; - content[0] = get_language_string(user, "NH_REQUESTS_HEADER_ID"); - content[1] = get_language_string(user, "NH_REQUESTS_HEADER_STATUS"); - content[2] = get_language_string(user, "NH_REQUESTS_HEADER_NICK"); - content[3] = get_language_string(user, "NH_REQUESTS_HEADER_TIME"); - content[4] = get_language_string(user, "NH_REQUESTS_HEADER_REQUEST"); - table_add(table, content); - char timestr[MAXLEN]; - struct NeonHelpNode *helpnode; - int suppid; - while ((row = mysql_fetch_row(res)) != NULL) { - content[0] = row[0]; - suppid = atoi(row[0]); - if(client->flags & SOCKET_HAVE_HELPNODE) { - for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { - if(helpnode->suppid == suppid) { - if(helpnode->status) - content[1] = get_language_string(user, "NH_REQUESTS_STATE_ACTIVE"); - else - content[1] = get_language_string(user, "NH_REQUESTS_STATE_PENDING"); - content[2] = helpnode->user->nick; - break; - } - } - } else { - content[1] = get_language_string(user, "NH_REQUESTS_STATE_ERROR"); - content[2] = NULL; - } - timeToStr(user, (time(0) - atoi(row[1])), 2, timestr); - content[3] = timestr; - char *p; - if((p = strstr(row[2], "\n"))) - *p = '\0'; - content[4] = row[2]; - table_add(table, content); - } - //send the table - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - if(table->entrys == 1) - reply(getTextBot(), user, "NS_TABLE_NONE"); - table_free(table); -} diff --git a/src/cmd_neonhelp_stats.c b/src/cmd_neonhelp_stats.c deleted file mode 100644 index 0d1d9a4..0000000 --- a/src/cmd_neonhelp_stats.c +++ /dev/null @@ -1,88 +0,0 @@ -/* cmd_neonhelp_stats.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonhelp.h" - -/* -* argv[0] user -*/ - -CMD_BIND(neonhelp_cmd_stats) { - //check permissions - MYSQL_RES *res; - MYSQL_ROW row, row2; - int caccess = 0; - printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); - res = mysql_use(); - if (!(row = mysql_fetch_row(res))) return; - //check if the user is a supporter (access in the support channel) - if((user->flags & USERFLAG_ISAUTHED)) { - int userid; - if(user->flags & USERFLAG_HAS_USERID) - userid = user->user_id; - else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - userid = atoi(row2[0]); - user->user_id = userid; - user->flags |= USERFLAG_HAS_USERID; - } else - userid = 0; - } - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); - res = mysql_use(); - if ((row2 = mysql_fetch_row(res)) != NULL) { - int cflags = atoi(row2[1]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) - caccess = atoi(row2[0]); - } - } - if(!caccess) { - reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); - return; - } - if(argc > 0) { - //following - } else { - struct Table *table; - printf_mysql_query("SELECT DISTINCT a.`supporter`, `user_user`, (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24))), (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24*7))), (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24*7*4))) FROM `helpserv_requests` AS a LEFT JOIN `users` ON a.`supporter` = `user_id` WHERE a.`time` > (UNIX_TIMESTAMP()-(3600*24*7*4)) AND `botid` = '%d' ORDER BY `user_user` ASC", client->clientid); - res = mysql_use(); - table = table_init(4, mysql_num_rows(res) + 1, 0); - char *content[4]; - content[0] = get_language_string(user, "NH_STATS_HEADER_USER"); - content[1] = get_language_string(user, "NH_STATS_HEADER_LAST_24H"); - content[2] = get_language_string(user, "NH_STATS_HEADER_LAST_7DAY"); - content[3] = get_language_string(user, "NH_STATS_HEADER_LAST_30DAY"); - table_add(table, content); - while ((row = mysql_fetch_row(res)) != NULL) { - content[0] = (strcmp(row[0], "-1") ? row[1] : "-"); - content[1] = row[2]; - content[2] = row[3]; - content[3] = row[4]; - table_add(table, content); - } - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - if(table->entrys == 1) - reply(getTextBot(), user, "NS_TABLE_NONE"); - table_free(table); - } -} diff --git a/src/cmd_neonserv.h b/src/cmd_neonserv.h deleted file mode 100644 index 0df1a7b..0000000 --- a/src/cmd_neonserv.h +++ /dev/null @@ -1,111 +0,0 @@ -/* cmd_neonserv.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _cmd_neonserv_h -#define _cmd_neonserv_h -#include "main.h" -#include "modcmd.h" -#include "IRCParser.h" -#include "IRCEvents.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "ModeNode.h" -#include "BanNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "version.h" -#include "EventLogger.h" -#include "bots.h" -#include "bot_NeonServ.h" -#include "ConfigParser.h" - -CMD_BIND(neonserv_cmd_access); -CMD_BIND(neonserv_cmd_addban); -CMD_BIND(neonserv_cmd_addrank); -CMD_BIND(neonserv_cmd_addtimeban); -CMD_BIND(neonserv_cmd_adduser); -CMD_BIND(neonserv_cmd_assignrank); -CMD_BIND(neonserv_cmd_ban); -CMD_BIND(neonserv_cmd_bans); -CMD_BIND(neonserv_cmd_chanservsync); -CMD_BIND(neonserv_cmd_clvl); -CMD_BIND(neonserv_cmd_csuspend); -CMD_BIND(neonserv_cmd_cunsuspend); -CMD_BIND(neonserv_cmd_dehalfop); -CMD_BIND(neonserv_cmd_dehalfopall); -CMD_BIND(neonserv_cmd_delban); -CMD_BIND(neonserv_cmd_delme); -CMD_BIND(neonserv_cmd_delrank); -CMD_BIND(neonserv_cmd_deluser); -CMD_BIND(neonserv_cmd_deop); -CMD_BIND(neonserv_cmd_deopall); -CMD_BIND(neonserv_cmd_devoice); -CMD_BIND(neonserv_cmd_devoiceall); -CMD_BIND(neonserv_cmd_down); -CMD_BIND(neonserv_cmd_downall); -CMD_BIND(neonserv_cmd_events); -CMD_BIND(neonserv_cmd_extscript); -CMD_BIND(neonserv_cmd_giveowner); -CMD_BIND(neonserv_cmd_halfop); -CMD_BIND(neonserv_cmd_halfopall); -CMD_BIND(neonserv_cmd_help); -CMD_BIND(neonserv_cmd_info); -CMD_BIND(neonserv_cmd_invite); -CMD_BIND(neonserv_cmd_inviteme); -CMD_BIND(neonserv_cmd_kick); -CMD_BIND(neonserv_cmd_kickban); -CMD_BIND(neonserv_cmd_listrank); -CMD_BIND(neonserv_cmd_mdeluser); -CMD_BIND(neonserv_cmd_mode); -CMD_BIND(neonserv_cmd_move); -CMD_BIND(neonserv_cmd_myaccess); -CMD_BIND(neonserv_cmd_nicklist); -CMD_BIND(neonserv_cmd_noregister); -CMD_BIND(neonserv_cmd_op); -CMD_BIND(neonserv_cmd_opall); -CMD_BIND(neonserv_cmd_oplog); -CMD_BIND(neonserv_cmd_peek); -CMD_BIND(neonserv_cmd_recover); -CMD_BIND(neonserv_cmd_rename); -CMD_BIND(neonserv_cmd_resync); -CMD_BIND(neonserv_cmd_search); -CMD_BIND(neonserv_cmd_set); -CMD_BIND(neonserv_cmd_setrank); -CMD_BIND(neonserv_cmd_suspend); -CMD_BIND(neonserv_cmd_topic); -CMD_BIND(neonserv_cmd_trace); -CMD_BIND(neonserv_cmd_trim); -CMD_BIND(neonserv_cmd_unban); -CMD_BIND(neonserv_cmd_unbanall); -CMD_BIND(neonserv_cmd_unbanme); -CMD_BIND(neonserv_cmd_unsuspend); -CMD_BIND(neonserv_cmd_unvisited); -CMD_BIND(neonserv_cmd_up); -CMD_BIND(neonserv_cmd_upall); -CMD_BIND(neonserv_cmd_users); -CMD_BIND(neonserv_cmd_uset); -CMD_BIND(neonserv_cmd_voice); -CMD_BIND(neonserv_cmd_voiceall); -CMD_BIND(neonserv_cmd_wipeinfo); - -#endif \ No newline at end of file diff --git a/src/cmd_neonserv_access.c b/src/cmd_neonserv_access.c deleted file mode 100644 index 25b2501..0000000 --- a/src/cmd_neonserv_access.c +++ /dev/null @@ -1,173 +0,0 @@ -/* cmd_neonserv_access.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -*/ -static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup); -static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target); -static void neonserv_cmd_access_filter_ranking_info(char *info, char *buffer, char *nick, char *auth, char *rank_name); - -struct neonserv_cmd_access_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - char *nick; -}; - -CMD_BIND(neonserv_cmd_access) { - if(argc == 0) { - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->nick = strdup(user->nick); - get_userauth(user, neonserv_cmd_access_nick_lookup, cache); - } else - neonserv_cmd_access_async1(client, getTextBot(), user, chan, user->nick, user->auth, user); - } - else if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - neonserv_cmd_access_async1(client, getTextBot(), user, chan, NULL, argv[0], NULL); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_access_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, cuser); - } else { - struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->nick = strdup(argv[0]); - get_userauth(cuser, neonserv_cmd_access_nick_lookup, cache); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup) { - struct neonserv_cmd_access_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - if(!strcmp(cache->nick, cache->user->nick)) - reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH"); - else - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - neonserv_cmd_access_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, user); - free(cache->nick); - free(cache); -} - -static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW user_row, chanuser_row; - int userid; - printf_mysql_query("SELECT `user_id`, `user_access`, `user_god`, `user_rank`, `rank_info`, `rank_name` FROM `users` LEFT JOIN `support_ranks` ON `rank_id` = `user_rank` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((user_row = mysql_fetch_row(res)) != NULL) { - userid = atoi(user_row[0]); - //check if the user is already added - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); - res = mysql_use(); - if(strcmp(user_row[3], "0") && strcmp(user_row[4], "")) { - char rank_info[MAXLEN]; - neonserv_cmd_access_filter_ranking_info(user_row[4], rank_info, nick, auth, user_row[5]); - reply(textclient, user, "%s", rank_info); - } - if ((chanuser_row = mysql_fetch_row(res)) != NULL) { - //access output - if(nick) - reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_AUTH" : "NS_A_ACCESS_AUTH_GOD"), nick, auth, atoi(chanuser_row[0]), chan->name); - else - reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_NICK" : "NS_A_ACCESS_NICK_GOD"), auth, atoi(chanuser_row[0]), chan->name); - int cflags = atoi(chanuser_row[1]); - if(cflags & DB_CHANUSER_SUSPENDED) - reply(textclient, user, "NS_A_SUSPENDED", (nick ? nick : auth), chan->name); - if(chanuser_row[2] && strcmp(chanuser_row[2], "")) - reply(textclient, user, "[%s] %s", (nick ? nick : auth), chanuser_row[2]); - } else if(!strcmp(user_row[2], "1")) { - if(nick) - reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_AUTH", nick, auth, chan->name); - else - reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_NICK", auth, chan->name); - } else - reply(textclient, user, "NS_NOT_ON_USERLIST", (nick ? nick : auth), chan->name); - } else - reply(textclient, user, "NS_NOT_ON_USERLIST", (nick ? nick : auth), chan->name); - if(target && (target->flags & USERFLAG_ISIRCOP)) - reply(textclient, user, "NS_A_IS_IRCOP", nick); -} - -static void neonserv_cmd_access_filter_ranking_info(char *info, char *buffer, char *nick, char *auth, char *rank_name) { - int bufferPos = 0; - char *a, *b = info; - do { - if(!b) break; - a = strstr(b, "$"); - if(a) *a = '\0'; - bufferPos += sprintf(buffer + bufferPos, "%s", b); - if(!a) break; - switch(a[1]) { - case '\0': - a = NULL; - break; - case 'U': - bufferPos += sprintf(buffer + bufferPos, "%s", auth); - break; - case 'N': - bufferPos += sprintf(buffer + bufferPos, "%s", (nick ? nick : auth)); - break; - case 'R': - bufferPos += sprintf(buffer + bufferPos, "%s", rank_name); - break; - default: - buffer[bufferPos++] = '$'; - buffer[bufferPos++] = a[1]; - break; - } - if(a) - b = a+2; - } while(a); -} diff --git a/src/cmd_neonserv_addban.c b/src/cmd_neonserv_addban.c deleted file mode 100644 index fffadf5..0000000 --- a/src/cmd_neonserv_addban.c +++ /dev/null @@ -1,128 +0,0 @@ -/* cmd_neonserv_addban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] nick|*auth|*!*@mask -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_addban) { - struct neonserv_cmd_addban_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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)); - } else - cache->reason = NULL; - get_userlist(chan, neonserv_cmd_addban_userlist_lookup, cache); -} - -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->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, struct Event *event, char *mask, char *reason) { - int match_count = 0; - char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - struct UserNode *cuser; - struct ChanUser *chanuser; - mask = make_banmask(mask, hostmask_buffer); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(mask, usermask)) { - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - return; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - return; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - return; - } - match_count++; - if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { - reply(textclient, user, "NS_LAME_MASK", mask); - return; - } - } - } - MYSQL_RES *res; - MYSQL_ROW row; - //check if the provided mask is already banned by another ban - char *ban = getBanAffectingMask(chan, mask); - if(ban != NULL) { - reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name); - return; - } - //check if the provided mask affects any existing bans - printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(!match(mask, row[0])) { - //remove the ban - printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); - } - } - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - int userid; - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) - userid = atoi(row[0]); - else - return; - //add the ban - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%d', '%s')", chan->channel_id, escape_string(mask), userid, escape_string(reason)); - putsock(client, "MODE %s +b %s", chan->name, mask); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(mask, usermask)) { - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - reply(textclient, user, "NS_ADDBAN_DONE", mask, chan->name, match_count); - logEvent(event); -} diff --git a/src/cmd_neonserv_addrank.c b/src/cmd_neonserv_addrank.c deleted file mode 100644 index 6ade32d..0000000 --- a/src/cmd_neonserv_addrank.c +++ /dev/null @@ -1,36 +0,0 @@ -/* cmd_neonserv_addrank.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] rank name -*/ - -CMD_BIND(neonserv_cmd_addrank) { - char *name = merge_argv(argv, 0, argc); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_ADDRANK_EXISTS", row[0]); - return; - } - printf_mysql_query("INSERT INTO `support_ranks` (`rank_name`) VALUES ('%s')", escape_string(name)); - reply(getTextBot(), user, "NS_ADDRANK_DONE", name); -} diff --git a/src/cmd_neonserv_addtimeban.c b/src/cmd_neonserv_addtimeban.c deleted file mode 100644 index 837812e..0000000 --- a/src/cmd_neonserv_addtimeban.c +++ /dev/null @@ -1,138 +0,0 @@ -/* cmd_neonserv_addtimeban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] nick|*auth|*!*@mask -* argv[1] time -* argv[2-*] reason -*/ -static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup); -static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason); - -struct neonserv_cmd_addtimeban_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *mask; - int duration; - char *reason; -}; - -CMD_BIND(neonserv_cmd_addtimeban) { - int duration = strToTime(user, argv[1]); - if(duration < 5) { - reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 5); - return; - } - struct neonserv_cmd_addtimeban_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->mask = strdup(argv[0]); - cache->duration = duration; - if(argc > 2) { - cache->reason = strdup(merge_argv(argv, 2, argc)); - } else - cache->reason = NULL; - get_userlist(chan, neonserv_cmd_addtimeban_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup) { - struct neonserv_cmd_addtimeban_cache *cache = data; - neonserv_cmd_addtimeban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, cache->duration, (cache->reason ? cache->reason : "Bye.")); - free(cache->mask); - if(cache->reason) - free(cache->reason); - free(cache); -} - -static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason) { - int match_count = 0; - char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - struct UserNode *cuser; - struct ChanUser *chanuser; - mask = make_banmask(mask, hostmask_buffer); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(mask, usermask)) { - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - return; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - return; - } - match_count++; - if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { - reply(textclient, user, "NS_LAME_MASK", mask); - return; - } - } - } - MYSQL_RES *res; - MYSQL_ROW row; - //check if the provided mask is already banned by another ban - char *ban = getBanAffectingMask(chan, mask); - if(ban != NULL) { - reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name); - return; - } - //check if the provided mask affects any existing bans - printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(!match(mask, row[0])) { - //remove the ban - printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); - } - } - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - int userid; - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) - userid = atoi(row[0]); - else - return; - //add the ban - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned long) (time(0) + duration), userid, escape_string(reason)); - int banid = (int) mysql_insert_id(get_mysql_conn()); - putsock(client, "MODE %s +b %s", chan->name, mask); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(mask, usermask)) { - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - char nameBuf[MAXLEN]; - char banidBuf[20]; - sprintf(nameBuf, "ban_%d", banid); - sprintf(banidBuf, "%d", banid); - timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); - reply(textclient, user, "NS_TIMEBAN_DONE", mask, chan->name, timeToStr(user, duration, 2, nameBuf), match_count); - logEvent(event); -} diff --git a/src/cmd_neonserv_adduser.c b/src/cmd_neonserv_adduser.c deleted file mode 100644 index 0e8432b..0000000 --- a/src/cmd_neonserv_adduser.c +++ /dev/null @@ -1,159 +0,0 @@ -/* cmd_neonserv_adduser.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -* argv[1] - chan access -*/ -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, 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; -}; - -CMD_BIND(neonserv_cmd_adduser) { - int caccess; - MYSQL_RES *res; - MYSQL_ROW row; - caccess = atoi(argv[1]); - if(caccess <= 0 || caccess > 500) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return; - } - if(caccess >= getChannelAccess(user, chan)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); - return; - } - } - //check own access - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - 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, 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 - struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup) { - struct neonserv_cmd_adduser_cache *cache = data; - if(!exists) { - //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->event, cache->nick, auth, cache->access); - free(cache->nick); - free(cache); -} - -static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup) { - struct neonserv_cmd_adduser_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth, int caccess) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is already added - printf_mysql_query("SELECT `chanuser_access` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(textclient, user, "NS_ADDUSER_ALREADY_ADDED", nick, chan->name, atoi(row[0])); - return; - } - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); - userid = (int) mysql_insert_id(get_mysql_conn()); - } - 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/src/cmd_neonserv_assignrank.c b/src/cmd_neonserv_assignrank.c deleted file mode 100644 index 4fedaf8..0000000 --- a/src/cmd_neonserv_assignrank.c +++ /dev/null @@ -1,151 +0,0 @@ -/* cmd_neonserv_assignrank.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -* argv[1-*] - rank name -*/ -static AUTHLOOKUP_CALLBACK(neonserv_cmd_assignrank_auth_lookup); -static USERAUTH_CALLBACK(neonserv_cmd_assignrank_nick_lookup); -static void neonserv_cmd_assignrank_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int rank_id); - -struct neonserv_cmd_assignrank_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - int rank_id; - char *nick; -}; - -CMD_BIND(neonserv_cmd_assignrank) { - MYSQL_RES *res; - MYSQL_ROW row; - char *name = merge_argv(argv, 1, argc); - int rank_id = 0; - if(stricmp(name, "*") && stricmp(name, "user") && stricmp(name, "none")) { - printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_DELRANK_NOT_FOUND", name); - return; - } - rank_id = atoi(row[0]); - } - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - 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_assignrank_async1(client, getTextBot(), user, event, argv[0], row[0], rank_id); - } else { - //we need to create a new user... - //but first lookup the auth to check if it really exists - struct neonserv_cmd_assignrank_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->rank_id = rank_id; - cache->nick = strdup(argv[0]); - lookup_authname(argv[0], neonserv_cmd_assignrank_auth_lookup, cache); - } - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_assignrank_async1(client, getTextBot(), user, event, argv[0], cuser->auth, rank_id); - } else { - struct neonserv_cmd_assignrank_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->rank_id = rank_id; - cache->nick = strdup(argv[0]); - get_userauth(cuser, neonserv_cmd_assignrank_nick_lookup, cache); - } - } -} - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_assignrank_auth_lookup) { - struct neonserv_cmd_assignrank_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); - } else - neonserv_cmd_assignrank_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->rank_id); - free(cache->nick); - free(cache); -} - -static USERAUTH_CALLBACK(neonserv_cmd_assignrank_nick_lookup) { - struct neonserv_cmd_assignrank_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - neonserv_cmd_assignrank_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->rank_id); - free(cache->nick); - free(cache); -} - -static void neonserv_cmd_assignrank_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int rank_id) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row, rank = NULL; - int caccess = 0; - if(rank_id) { - printf_mysql_query("SELECT `rank_access`, `rank_name` FROM `support_ranks` WHERE `rank_id` = '%d'", rank_id); - res = mysql_use(); - rank = mysql_fetch_row(res); - caccess = atoi(rank[0]); - } - printf_mysql_query("SELECT `user_id`, `user_rank` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - if(atoi(row[1]) != rank_id) { - printf_mysql_query("UPDATE `users` SET `user_access` = '%d', `user_rank` = '%d' WHERE `user_id` = '%s'", caccess, rank_id, row[0]); - } - } else if(rank_id) { - printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`, `user_rank`) VALUES ('%s', '%d', '%d')", escape_string(auth), caccess, rank_id); - } - reply(textclient, user, "NS_ASSIGNRANK_DONE", auth, (rank_id ? rank[1] : "*")); - logEvent(event); -} diff --git a/src/cmd_neonserv_ban.c b/src/cmd_neonserv_ban.c deleted file mode 100644 index 84a497a..0000000 --- a/src/cmd_neonserv_ban.c +++ /dev/null @@ -1,122 +0,0 @@ -/* cmd_neonserv_ban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, struct Event *event, char *masks); - -struct neonserv_cmd_ban_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *masks; -}; - -CMD_BIND(neonserv_cmd_ban) { - struct neonserv_cmd_ban_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->masks = strdup(merge_argv_char(argv, 0, argc, ',')); - 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->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, 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]; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - struct UserNode *cuser; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - nextmask = masks; - while((mask = nextmask)) { - nextmask = strstr(mask, ","); - if(nextmask) { - *nextmask = '\0'; - nextmask++; - } - provided_masks++; - skip = 0; - match_count = 0; - mask = make_banmask(mask, hostmask_buffer); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(mask, usermask)) { - cuser->flags |= USERFLAG_SCRIPTFLAG1; //we mark the user as 'matching' - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - skip = 1; - break; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - skip = 1; - break; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - skip = 1; - break; - } - match_count++; - if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { - skip = 1; - reply(textclient, user, "NS_LAME_MASK", mask); - break; - } - } - } - if(!skip) { - done_masks++; - modeBufferBan(modeBuf, mask); - } - } - total_match = 0; // count all users marked as 'matching' - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - if(cuser->flags & USERFLAG_SCRIPTFLAG1) { - cuser->flags &= ~USERFLAG_SCRIPTFLAG1; - total_match++; - } - } - freeModeBuffer(modeBuf); - if(done_masks == provided_masks) - 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/src/cmd_neonserv_bans.c b/src/cmd_neonserv_bans.c deleted file mode 100644 index 7ad47e1..0000000 --- a/src/cmd_neonserv_bans.c +++ /dev/null @@ -1,75 +0,0 @@ -/* cmd_neonserv_bans.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] (optional) mask -*/ -CMD_BIND(neonserv_cmd_bans) { - MYSQL_RES *res; - MYSQL_ROW row; - //ban list - int i, with_expire = 0, cindex = 0; - char triggered_str[MAXLEN], expires_str[MAXLEN]; - struct Table *table; - printf_mysql_query("SELECT `ban_mask`, `user_user`, `ban_triggered`, `ban_timeout`, `ban_reason` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d'", chan->channel_id); - res = mysql_use(); - table = table_init(5, mysql_num_rows(res) + 1, 0); - char *content[5]; - //add a NULL row (we add values later) - content[0] = NULL; - content[1] = NULL; - content[2] = NULL; - content[3] = NULL; - content[4] = NULL; - table_add(table, content); - while ((row = mysql_fetch_row(res)) != NULL) { - if(argc > 0 && match(argv[0], row[0])) continue; - content[0] = row[0]; - content[1] = row[1]; - content[2] = (strcmp(row[2], "0") ? timeToStr(user, (time(0) - atoi(row[2])), 2, triggered_str) : get_language_string(user, "NS_USERS_SEEN_NEVER")); - if(strcmp(row[3], "0")) { - if(!with_expire) { - //we're using expire times now... - for(i = 0; i < cindex; i++) - table_change_field(table, i+1, 3, get_language_string(user, "NS_USERS_SEEN_NEVER")); - with_expire = 1; - } - content[3] = timeToStr(user, (atoi(row[3]) - time(0)), 2, expires_str); - } else - content[3] = (with_expire ? get_language_string(user, "NS_USERS_SEEN_NEVER") : NULL); - content[4] = row[4]; - cindex++; - table_add(table, content); - } - //now we add the table header - content[0] = get_language_string(user, "NS_BANS_HEADER_MASK"); - content[1] = get_language_string(user, "NS_BANS_HEADER_SETBY"); - content[2] = get_language_string(user, "NS_BANS_HEADER_TRIGGERED"); - content[3] = (with_expire ? get_language_string(user, "NS_BANS_HEADER_EXPIRES") : NULL); - content[4] = get_language_string(user, "NS_BANS_HEADER_REASON"); - table_change(table, 0, content); - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - if(!cindex) - reply(getTextBot(), user, "NS_TABLE_NONE"); - reply(getTextBot(), user, "NS_TABLE_COUNT", cindex); - table_free(table); -} diff --git a/src/cmd_neonserv_chanservsync.c b/src/cmd_neonserv_chanservsync.c deleted file mode 100644 index 8581cb2..0000000 --- a/src/cmd_neonserv_chanservsync.c +++ /dev/null @@ -1,270 +0,0 @@ -/* cmd_neonserv_chanservsync.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - botnick -* argv[1] - key -*/ -#define CHANSERVSYNC_END_TIMEOUT 5 - -static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message); -static void neonserv_cmd_chanservsync_free_cache(); -static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup); -static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new); - -struct neonserv_cmd_chanservsync_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - char *botnick; - time_t last_response; -}; - -struct neonserv_cmd_chanservsync_auth_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - int caccess; - time_t seen; - int flags; -}; - -struct neonserv_cmd_chanservsync_cache *neonserv_cmd_chanservsync_used = NULL; -const char* neonserv_cmd_chanservsync_supported[] = {"ChanServ", NULL}; - -CMD_BIND(neonserv_cmd_chanservsync) { - if(neonserv_cmd_chanservsync_used && time(0) - neonserv_cmd_chanservsync_used->last_response < CHANSERVSYNC_END_TIMEOUT) { - reply(getTextBot(), user, "NS_CHANSERVSYNC_INUSE"); - return; - } - if(neonserv_cmd_chanservsync_used) { - neonserv_cmd_chanservsync_free_cache(); - } - char *botnick = "ChanServ"; - char *key = ""; - if(argc) { - if(argv[0][0] == '!') { - key = argv[0]; - } else { - botnick = argv[0]; - if(argc > 1) - key = argv[1]; - } - } - int seed = 0; - char *tmp; - char synckey[18]; - for(tmp = user->auth; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = chan->name; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = botnick; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - sprintf(synckey, "!%08x!", seed); - if(strcmp(synckey, key)) { - int f = 0; - const char **supp = neonserv_cmd_chanservsync_supported; - while(*supp) { - if(!stricmp(*supp, botnick)) { - f = 1; - break; - } - supp++; - } - if(!f) { - reply(getTextBot(), user, "NS_CHANSERVSYNC_UNSUPPORTED", botnick, client->user->nick); - } - reply(getTextBot(), user, "NS_CHANSERVSYNC_KEY", client->user->nick, botnick, botnick, synckey); - return; - } - struct neonserv_cmd_chanservsync_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->botnick = strdup(botnick); - cache->last_response = time(0); - neonserv_cmd_chanservsync_used = cache; - 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) { - if(neonserv_cmd_chanservsync_used && neonserv_cmd_chanservsync_used->client->user == target && !stricmp(user->nick, neonserv_cmd_chanservsync_used->botnick)) { - //we've got a notice from our bot... - //let's try parsing it.... - char *p = message; - char *tokens[MAXLEN]; - int tokensPos = 0; - while(*p == ' ') //skip leading spaces (airb0t) - p++; - message = p; - char *q = p; - while(*q) { - if(*q < 32) *q = ' '; - q++; - } - while((q = strstr(p, " "))) { - *q = '\0'; - do { - q++; - } while(*q == ' ' || *q == '-'); - if(*p) { - tokens[tokensPos++] = p; - } - p = q; - } - if(*p) { - tokens[tokensPos++] = p; - } - int caccess; - char *username; - if(tokensPos == 1) { - //maybe a chip-like userlist - if(tokens[0][0] == '@') { - caccess = 200; - username = &tokens[0][1]; - } else if(tokens[0][0] == '+') { - caccess = 100; - username = &tokens[0][1]; - } else - return; - } else if(tokensPos >= 2) { - if(atoi(tokens[0]) > 0) { - caccess = atoi(tokens[0]); - username = tokens[1]; - } else { - caccess = atoi(tokens[1]); - username = tokens[0]; - } - } else - return; - if(caccess < 1 || caccess > 500) return; - int flags = 0; - time_t now = time(0); - time_t seen_time = now; //now - now = 0 (never) - neonserv_cmd_chanservsync_used->last_response = now; - if(strlen(username) < 3) return; - //ok we have access and username... maybe there is something else we can parse??? - char *seen = NULL; - char *status = NULL; - if(tokensPos > 2) { - if(!stricmp("normal", tokens[2]) || !stricmp("suspended", tokens[2]) || !stricmp("bot", tokens[2])) { - status = tokens[2]; - if (tokensPos > 3) { - seen = merge_argv(tokens, 3, tokensPos); - } - } else if (tokensPos > 3) { - if(!stricmp("normal", tokens[tokensPos-1]) || !stricmp("suspended", tokens[tokensPos-1]) || !stricmp("bot", tokens[tokensPos-1])) { - status = tokens[tokensPos-1]; - seen = merge_argv(tokens, 2, tokensPos-1); - } else { - seen = merge_argv(tokens, 2, tokensPos); - } - } else { - seen = merge_argv(tokens, 2, tokensPos); - } - } - if(status && !stricmp(status, "suspended")) { - flags |= DB_CHANUSER_SUSPENDED; - } - if(seen) { - if(!stricmp(seen, "here")) - seen_time = 0; - else if(stricmp(seen, "never")) - seen_time = strToTime(user, seen); - } - seen_time = now - seen_time; - //we've collected all information now. synchronize the user (use the higher access if the user is already added) - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(username)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 0); - } else if(!stricmp(user->nick, "chanserv")) { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(username)); - userid = (int) mysql_insert_id(get_mysql_conn()); - neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 1); - } else { - //lookup auth - struct neonserv_cmd_chanservsync_auth_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = neonserv_cmd_chanservsync_used->client; - cache->textclient = neonserv_cmd_chanservsync_used->textclient; - cache->user = neonserv_cmd_chanservsync_used->user; - cache->chan = neonserv_cmd_chanservsync_used->chan; - cache->caccess = caccess; - cache->seen = seen_time; - cache->flags = flags; - lookup_authname(username, neonserv_cmd_chanservsync_auth_lookup, cache); - } - } -} - -static void neonserv_cmd_chanservsync_free_cache() { - free(neonserv_cmd_chanservsync_used->botnick); - free(neonserv_cmd_chanservsync_used); - unbind_privnotice(neonserv_cmd_chanservsync_notice_listener); - neonserv_cmd_chanservsync_used = NULL; -} - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup) { - struct neonserv_cmd_chanservsync_auth_cache *cache = data; - if(exists) { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); - int userid = (int) mysql_insert_id(get_mysql_conn()); - neonserv_cmd_chanservsync_synchronize_user(cache->client, cache->textclient, cache->user, cache->chan, auth, userid, cache->caccess, cache->seen, cache->flags, 1); - } - free(cache); -} - -static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new) { - //just sync the user with the given userid with the providet information - if(caccess == 500) caccess = 499; - if(new) { - //just add - printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags); - } else { - MYSQL_RES *res; - MYSQL_ROW row; - //check if already added - printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - //clvl - if(atoi(row[0]) >= caccess) return; - if(atol(row[2]) > seen) seen = atol(row[2]); - printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d', `chanuser_seen` = '%lu' WHERE `chanuser_id` = '%s'", caccess, (unsigned long) seen, row[1]); - } else - printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags); - } - reply(textclient, user, "NS_CHANSERVSYNC_SYNCHRONIZED", username, caccess); -} diff --git a/src/cmd_neonserv_clvl.c b/src/cmd_neonserv_clvl.c deleted file mode 100644 index a541c3d..0000000 --- a/src/cmd_neonserv_clvl.c +++ /dev/null @@ -1,130 +0,0 @@ -/* cmd_neonserv_clvl.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_clvl) { - int caccess; - caccess = atoi(argv[1]); - if(caccess <= 0 || caccess > 500) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return; - } - if(caccess >= getChannelAccess(user, chan)) { - 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, event, argv[0], argv[0], caccess); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) { - struct neonserv_cmd_clvl_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth, int caccess) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is already added - 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) { - //clvl - if(atoi(row[0]) >= getChannelAccess(user, chan)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; - } - } - 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; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonserv_csuspend.c b/src/cmd_neonserv_csuspend.c deleted file mode 100644 index 9ff2fea..0000000 --- a/src/cmd_neonserv_csuspend.c +++ /dev/null @@ -1,62 +0,0 @@ -/* cmd_neonserv_csuspend.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - channel -*/ -CMD_BIND(neonserv_cmd_csuspend) { - MYSQL_RES *res; - MYSQL_ROW row; - char *channel = argv[0]; - if(!is_valid_chan(channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - } else { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - if(!strcmp(row[2], "1")) { - reply(getTextBot(), user, "NS_CSUSPEND_ALREADY", channel); - return; - } - int botid = atoi(row[0]); - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - putsock(bot, "PART %s :Channel suspended.", channel); - } - printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '1' WHERE `id` = '%s'", row[1]); - reply(getTextBot(), user, "NS_CSUSPEND_DONE", channel); - logEvent(event); -} diff --git a/src/cmd_neonserv_cunsuspend.c b/src/cmd_neonserv_cunsuspend.c deleted file mode 100644 index 53a997d..0000000 --- a/src/cmd_neonserv_cunsuspend.c +++ /dev/null @@ -1,62 +0,0 @@ -/* cmd_neonserv_cunsuspend.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - channel -*/ -CMD_BIND(neonserv_cmd_cunsuspend) { - MYSQL_RES *res; - MYSQL_ROW row; - char *channel = argv[0]; - if(!is_valid_chan(channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - } else { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - if(!strcmp(row[2], "0")) { - reply(getTextBot(), user, "NS_CUNSUSPEND_NOT", channel); - return; - } - int botid = atoi(row[0]); - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - putsock(bot, "JOIN %s", channel); - } - printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '0' WHERE `id` = '%s'", row[1]); - reply(getTextBot(), user, "NS_CUNSUSPEND_DONE", channel); - logEvent(event); -} diff --git a/src/cmd_neonserv_dehalfop.c b/src/cmd_neonserv_dehalfop.c deleted file mode 100644 index f995e0f..0000000 --- a/src/cmd_neonserv_dehalfop.c +++ /dev/null @@ -1,94 +0,0 @@ -/* cmd_neonserv_dehalfop.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nicks -*/ -static USERLIST_CALLBACK(neonserv_cmd_dehalfop_userlist_lookup); -static void neonserv_cmd_dehalfop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); - -struct neonserv_cmd_dehalfop_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char **argv; - int argc; -}; - -CMD_BIND(neonserv_cmd_dehalfop) { - struct neonserv_cmd_dehalfop_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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++) { - cache->argv[i] = strdup(argv[i]); - } - cache->argc = argc; - get_userlist(chan, neonserv_cmd_dehalfop_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_dehalfop_userlist_lookup) { - struct neonserv_cmd_dehalfop_cache *cache = data; - neonserv_cmd_dehalfop_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]); - } - free(cache->argv); - free(cache); -} - -static void neonserv_cmd_dehalfop_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; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(i = 0; i < argc; i++) { - cuser = searchUserByNick(argv[i]); - if(!cuser) continue; - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - if(isNetworkService(cuser)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - done_users++; - if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; - modeBufferDehalfop(modeBuf, argv[i]); - } - freeModeBuffer(modeBuf); - if(done_users == argc) - reply(textclient, user, "NS_DEHALFOP_DONE", chan->name); - else - reply(textclient, user, "NS_DEHALFOP_FAIL", client->user->nick); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_dehalfopall.c b/src/cmd_neonserv_dehalfopall.c deleted file mode 100644 index 1cb58d0..0000000 --- a/src/cmd_neonserv_dehalfopall.c +++ /dev/null @@ -1,85 +0,0 @@ -/* cmd_neonserv_dehalfopall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] (optional) nick mask -*/ -static USERLIST_CALLBACK(neonserv_cmd_dehalfopall_userlist_lookup); -static void neonserv_cmd_dehalfopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); - -struct neonserv_cmd_dehalfopall_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char **argv; - int argc; -}; - -CMD_BIND(neonserv_cmd_dehalfopall) { - struct neonserv_cmd_dehalfopall_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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++) { - cache->argv[i] = strdup(argv[i]); - } - cache->argc = argc; - get_userlist(chan, neonserv_cmd_dehalfopall_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_dehalfopall_userlist_lookup) { - struct neonserv_cmd_dehalfopall_cache *cache = data; - neonserv_cmd_dehalfopall_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]); - } - free(cache->argv); - free(cache); -} - -static void neonserv_cmd_dehalfopall_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(argc > 0) - nickmask = argv[0]; - modeBuf = initModeBuffer(client, chan); - issuer_access = getChannelAccess(user, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - victim_access = getChannelAccess(chanuser->user, chan); - if(victim_access >= issuer_access || isNetworkService(chanuser->user)) continue; - if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; - modeBufferDehalfop(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(getTextBot(), user, "NS_DEHALFOPALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_delban.c b/src/cmd_neonserv_delban.c deleted file mode 100644 index 3b4f9d8..0000000 --- a/src/cmd_neonserv_delban.c +++ /dev/null @@ -1,51 +0,0 @@ -/* cmd_neonserv_delban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] nick|*auth|*!*@mask -*/ - -CMD_BIND(neonserv_cmd_delban) { - char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; - char *mask = make_banmask(argv[0], hostmask_buffer); - int matching_bans = 0; - MYSQL_RES *res; - MYSQL_ROW row; - //check if the provided mask affects any existing bans - char nameBuf[20]; - printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(!match(mask, row[0])) { - //remove the ban - if(strcmp(row[2], "0")) { - sprintf(nameBuf, "ban_%s", row[1]); - timeq_del_name(nameBuf); - } - printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); - matching_bans++; - } - } - 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/src/cmd_neonserv_delme.c b/src/cmd_neonserv_delme.c deleted file mode 100644 index 256ca69..0000000 --- a/src/cmd_neonserv_delme.c +++ /dev/null @@ -1,62 +0,0 @@ -/* cmd_neonserv_delme.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - key -*/ - -CMD_BIND(neonserv_cmd_delme) { - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is added - 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]) == 500) { - reply(getTextBot(), user, "NS_DELME_OWNER", chan->name); - return; - } - //check key - int seed = 0; - char *tmp; - static char unregkey[16]; - for(tmp = user->auth; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = chan->name; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - sprintf(unregkey, "%08x", seed); - if(argc < 1 || strcmp(argv[0], unregkey)) { - reply(getTextBot(), user, "NS_DELME_KEY", unregkey); - return; - } else { - //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; - } - } - } - reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name); -} diff --git a/src/cmd_neonserv_delrank.c b/src/cmd_neonserv_delrank.c deleted file mode 100644 index 489b32a..0000000 --- a/src/cmd_neonserv_delrank.c +++ /dev/null @@ -1,37 +0,0 @@ -/* cmd_neonserv_delrank.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] rank name -*/ - -CMD_BIND(neonserv_cmd_delrank) { - char *name = merge_argv(argv, 0, argc); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_DELRANK_NOT_FOUND", name); - return; - } - printf_mysql_query("UPDATE `users` SET `user_rank` = '0', `user_access` = '0' WHERE `user_rank` = '%s'", row[0]); - printf_mysql_query("DELETE FROM `support_ranks` WHERE `rank_id` = '%s'", row[0]); - reply(getTextBot(), user, "NS_DELRANK_DELETED", row[1]); -} diff --git a/src/cmd_neonserv_deluser.c b/src/cmd_neonserv_deluser.c deleted file mode 100644 index 5188f01..0000000 --- a/src/cmd_neonserv_deluser.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cmd_neonserv_deluser.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_deluser) { - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) { - struct neonserv_cmd_deluser_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is already added - 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)) { - 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; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonserv_deop.c b/src/cmd_neonserv_deop.c deleted file mode 100644 index 20a4f44..0000000 --- a/src/cmd_neonserv_deop.c +++ /dev/null @@ -1,94 +0,0 @@ -/* cmd_neonserv_deop.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_deop) { - struct neonserv_cmd_deop_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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++) { - cache->argv[i] = strdup(argv[i]); - } - cache->argc = argc; - get_userlist(chan, neonserv_cmd_deop_userlist_lookup, cache); -} - -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->event, cache->argv, cache->argc); - int i; - for(i = 0; i < cache->argc; i++) { - free(cache->argv[i]); - } - free(cache->argv); - free(cache); -} - -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; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(i = 0; i < argc; i++) { - cuser = searchUserByNick(argv[i]); - if(!cuser) continue; - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - if(isNetworkService(cuser)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - done_users++; - if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; - modeBufferDeop(modeBuf, argv[i]); - } - freeModeBuffer(modeBuf); - if(done_users == argc) - 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/src/cmd_neonserv_deopall.c b/src/cmd_neonserv_deopall.c deleted file mode 100644 index 7b1cdb2..0000000 --- a/src/cmd_neonserv_deopall.c +++ /dev/null @@ -1,85 +0,0 @@ -/* cmd_neonserv_deopall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_deopall) { - struct neonserv_cmd_deopall_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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++) { - cache->argv[i] = strdup(argv[i]); - } - cache->argc = argc; - get_userlist(chan, neonserv_cmd_deopall_userlist_lookup, cache); -} - -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->event, cache->argv, cache->argc); - int i; - for(i = 0; i < cache->argc; i++) { - free(cache->argv[i]); - } - free(cache->argv); - free(cache); -} - -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(argc > 0) - nickmask = argv[0]; - modeBuf = initModeBuffer(client, chan); - issuer_access = getChannelAccess(user, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - victim_access = getChannelAccess(chanuser->user, chan); - if(victim_access >= issuer_access || isNetworkService(chanuser->user)) continue; - if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; - modeBufferDeop(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_devoice.c b/src/cmd_neonserv_devoice.c deleted file mode 100644 index e7ced34..0000000 --- a/src/cmd_neonserv_devoice.c +++ /dev/null @@ -1,50 +0,0 @@ -/* cmd_neonserv_devoice.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nicks -*/ - -CMD_BIND(neonserv_cmd_devoice) { - int i, done_users = 0; - struct UserNode *cuser; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(i = 0; i < argc; i++) { - cuser = searchUserByNick(argv[i]); - if(!cuser) continue; - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - if(isUserProtected(chan, cuser, user)) { - reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - done_users++; - if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; - modeBufferDevoice(modeBuf, argv[i]); - } - freeModeBuffer(modeBuf); - if(done_users == argc) - 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/src/cmd_neonserv_devoiceall.c b/src/cmd_neonserv_devoiceall.c deleted file mode 100644 index 9254e46..0000000 --- a/src/cmd_neonserv_devoiceall.c +++ /dev/null @@ -1,46 +0,0 @@ -/* cmd_neonserv_devoiceall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] (optional) nick mask -*/ - -CMD_BIND(neonserv_cmd_devoiceall) { - int issuer_access, victim_access, done_users = 0; - char *nickmask = NULL; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - check_mysql(); - if(argc > 0) - nickmask = argv[0]; - modeBuf = initModeBuffer(client, chan); - issuer_access = getChannelAccess(user, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - victim_access = getChannelAccess(chanuser->user, chan); - if(victim_access >= issuer_access) continue; - if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; - modeBufferDevoice(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_down.c b/src/cmd_neonserv_down.c deleted file mode 100644 index fd29475..0000000 --- a/src/cmd_neonserv_down.c +++ /dev/null @@ -1,38 +0,0 @@ -/* cmd_neonserv_down.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -CMD_BIND(neonserv_cmd_down) { - struct ChanUser *chanuser = getChanUser(user, chan); - if(!chanuser) { - reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name); - return; - } - 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/src/cmd_neonserv_downall.c b/src/cmd_neonserv_downall.c deleted file mode 100644 index a7add47..0000000 --- a/src/cmd_neonserv_downall.c +++ /dev/null @@ -1,50 +0,0 @@ -/* cmd_neonserv_downall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -CMD_BIND(neonserv_cmd_downall) { - struct ChanUser *chanuser; - int botid = client->botid; - for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) { - chan = chanuser->chan; - loadChannelSettings(chan); - 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; - int done = 0; - client = getChannelBot(chan, botid); - if(!client) continue; - if((chanuser->flags & CHANUSERFLAG_OPPED)) { - putsock(client, "MODE %s -o %s", chan->name, user->nick); - 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/src/cmd_neonserv_events.c b/src/cmd_neonserv_events.c deleted file mode 100644 index de4fd6c..0000000 --- a/src/cmd_neonserv_events.c +++ /dev/null @@ -1,57 +0,0 @@ -/* cmd_neonserv_events.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] time -* argv[1-*] match -*/ - -CMD_BIND(neonserv_cmd_events) { - char *str_match; - int duration = (argc ? strToTime(user, argv[0]) : 0); - if(argc > (duration ? 1 : 0)) - str_match = merge_argv(argv, (duration ? 1 : 0), argc); - else - str_match = ""; - if(!duration) duration = (60*60*24); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `time`, `auth`, `nick`, `command` FROM `events` WHERE `cid` = '%d' AND `time` > '%lu' ORDER BY `time` ASC", chan->channel_id, ((unsigned long) time(0) - duration)); - res = mysql_use(); - int skip = mysql_num_rows(res) - 100; - int count = 0; - char timeBuf[50]; - struct tm *timeinfo; - time_t event_time; - if(skip < 0) skip = 0; - reply(getTextBot(), user, "NS_EVENTS_HEADER"); - while ((row = mysql_fetch_row(res)) != NULL) { - if(skip) { - skip--; - continue; - } - if(*str_match && match(str_match, row[3])) continue; - count++; - event_time = (time_t) atol(row[0]); - timeinfo = localtime(&event_time); - strftime(timeBuf, 80, "%X %x", timeinfo); - reply(getTextBot(), user, "[%s] [%s:%s]: %s", timeBuf, row[2], row[1], row[3]); - } - reply(getTextBot(), user, "NS_TABLE_COUNT", count); -} diff --git a/src/cmd_neonserv_extscript.c b/src/cmd_neonserv_extscript.c deleted file mode 100644 index e4a4e2e..0000000 --- a/src/cmd_neonserv_extscript.c +++ /dev/null @@ -1,170 +0,0 @@ -/* cmd_neonserv_extscript.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" -#include - -/* -* argv[0] 'toys' if it's a toy command (check if toys are enabled) -* argv[0-*] script name & parameter patterns -* argv[argc-1] all arguments passed to the command -*/ - -static TIMEQ_CALLBACK(neonserv_cmd_extscript_callback); - -struct neonserv_cmd_extscript_cache { - struct ClientSocket *client, *textclient; - struct Event *event; - struct UserNode *user; - struct ChanNode *chan; - int answere_channel; - FILE *pipe; -}; - -CMD_BIND(neonserv_cmd_extscript) { - int i, j; - char *args[MAXNUMPARAMS]; - int argpos = 0; - char *next, *curr; - char command[1024]; - int commandpos = 0; - char part[MAXLEN]; - int partpos; - int escape_param; - int answere_channel = 0; - //check first arg - if(argc && !stricmp(argv[0], "toys")) { - if(!chan) return; //toys are not allowed via query - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name)); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row || !strcmp(row[0], "0")) { - //disabled - reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name); - return; - } else if(!strcmp(row[0], "2")) - answere_channel = 1; - argc--; - argv++; - } - //parse arguments - if(argc < 2) return; - curr = argv[argc-1]; - while(curr) { - next = strstr(curr, " "); - args[argpos++] = curr; - if(next) { - *next = '\0'; - curr = next+1; - } else - curr = NULL; - } - //parse command pattern and build command - commandpos = sprintf(command, "%s", argv[0]); - for(i = 1; i < argc-1; i++) { - partpos = 0; - escape_param = 1; - if(argv[i][0] == '$') { - argv[i]++; - if(argv[i][strlen(argv[i])-1] == '-') { - argv[i][strlen(argv[i])-1] = '\0'; - j = atoi(argv[i]); - if(j <= argpos) - partpos = sprintf(part, "%s", merge_argv(args, j-1, argpos)); - } else if((j = atoi(argv[i])) > 0) { - if(j <= argpos) - partpos = sprintf(part, "%s", args[j-1]); - } else if(!strcmp(argv[i], "c")) { - partpos = sprintf(part, "%s", (chan ? chan->name : "")); - } else if(!strcmp(argv[i], "n")) { - partpos = sprintf(part, "%s", user->nick); - } else if(!strcmp(argv[i], "a")) { - partpos = sprintf(part, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "")); - } else if(!strcmp(argv[i], "access")) { - if(chan) - partpos = sprintf(part, "%d", getChannelAccess(user, chan)); - } - } else { - partpos = sprintf(part, "%s", argv[i]); - escape_param = 0; - } - //escape shell argument - command[commandpos++] = ' '; - if(escape_param) { - command[commandpos++] = '\''; - for(j = 0; j < partpos; j++) { - if(part[j] == '\'') { - command[commandpos++] = '\''; - command[commandpos++] = '\\'; - command[commandpos++] = '\''; - command[commandpos++] = '\''; - } else - command[commandpos++] = part[j]; - } - command[commandpos++] = '\''; - } else - commandpos += sprintf(command + commandpos, " %s", part); - } - command[commandpos] = '\0'; - //we should now have a valid command - - struct neonserv_cmd_extscript_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->event = event; - cache->user = user; - cache->chan = chan; - cache->answere_channel = answere_channel; - cache->pipe = popen(command, "r"); - #ifndef WIN32 - fcntl(fileno(cache->pipe), F_SETFL, O_NONBLOCK); - #endif - timeq_uadd(200, neonserv_cmd_extscript_callback, cache); -} - -static TIMEQ_CALLBACK(neonserv_cmd_extscript_callback) { - struct neonserv_cmd_extscript_cache *cache = data; - char command[512]; - char *a; - if(feof(cache->pipe)) { - pclose(cache->pipe); - free(cache); - return; - } - while (fgets(command, 512, cache->pipe) != NULL) { - if((a = strchr(command, '\n'))) - *a = '\0'; - if(!stricmp(command, "/log")) { - logEvent(cache->event); - continue; - } - if(cache->answere_channel) - putsock(cache->client, "PRIVMSG %s :%s", cache->chan->name, command); - else - reply(cache->textclient, cache->user, "%s", command); - } - timeq_uadd(200, neonserv_cmd_extscript_callback, cache); -} - - - diff --git a/src/cmd_neonserv_giveowner.c b/src/cmd_neonserv_giveowner.c deleted file mode 100644 index 9cf5ae7..0000000 --- a/src/cmd_neonserv_giveowner.c +++ /dev/null @@ -1,157 +0,0 @@ -/* cmd_neonserv_giveowner.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -* argv[1] - key -*/ - -#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, 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; -}; - -CMD_BIND(neonserv_cmd_giveowner) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_lastgiveowner` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(strcmp(row[0], "0") && (atoi(row[0]) + GIVEOWNER_TIMEOUT) > time(0)) { - char timeBuf[MAXLEN]; - reply(getTextBot(), user, "NS_GIVEOWNER_TIMEOUT", timeToStr(user, (GIVEOWNER_TIMEOUT - (time(0) - atoi(row[0]))), 2, timeBuf), chan->name); - return; - } - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - 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) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup) { - struct neonserv_cmd_giveowner_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, 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"); - return; - } - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(auth)); - res = mysql_use(); - if((row = mysql_fetch_row(res)) != NULL) { - int expire_time = atoi(row[1]); - if(expire_time) { - if(expire_time - time(0) <= 0) { - printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); - } else { - reply(getTextBot(), user, "NS_DNR_SET_ANONYM", auth); - return; - } - } else { - reply(getTextBot(), user, "NS_DNR_SET_ANONYM", auth); - return; - } - } - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is already added - 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) { - int seed = 0; - char *tmp; - char giveownerkey[16]; - for(tmp = user->auth; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = chan->name; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - sprintf(giveownerkey, "%08x", seed); - if(key && !stricmp(giveownerkey, key)) { - //give ownership - printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '500' WHERE `chanuser_id` = '%s'", row[1]); - 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_from_uid`, `owner_history_to_uid`, `owner_history_time`) VALUE ('%d', (SELECT `user_id` FROM `users` WHERE `user_user` = '%s'), '%d', UNIX_TIMESTAMP())", chan->channel_id, escape_string(user->auth), userid); - reply(textclient, user, "NS_GIVEOWNER_DONE", chan->name, auth); - logEvent(event); - } else { - reply(textclient, user, "NS_GIVEOWNER_CONFIRM", auth, giveownerkey); - } - return; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonserv_halfop.c b/src/cmd_neonserv_halfop.c deleted file mode 100644 index ba684cb..0000000 --- a/src/cmd_neonserv_halfop.c +++ /dev/null @@ -1,93 +0,0 @@ -/* cmd_neonserv_halfop.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nicks -*/ -static USERLIST_CALLBACK(neonserv_cmd_halfop_userlist_lookup); -static void neonserv_cmd_halfop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks); - -struct neonserv_cmd_halfop_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nicks; -}; - -CMD_BIND(neonserv_cmd_halfop) { - struct neonserv_cmd_halfop_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->nicks = strdup(merge_argv(argv, 0, argc)); - get_userlist_if_invisible(chan, neonserv_cmd_halfop_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_halfop_userlist_lookup) { - struct neonserv_cmd_halfop_cache *cache = data; - neonserv_cmd_halfop_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks); - free(cache->nicks); - free(cache); -} - -static void neonserv_cmd_halfop_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; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - char *a, *b = nicks; - do { - a = strstr(b, " "); - if(a) *a = '\0'; - total_users++; - cuser = searchUserByNick(b); - if(!cuser) { - //check for an invisible user - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(!stricmp(chanuser->user->nick, b)) { - cuser = chanuser->user; - break; - } - } - if(!cuser) continue; - } else { - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - } - done_users++; - if(chanuser->flags & CHANUSERFLAG_OPPED) continue; - modeBufferHalfop(modeBuf, b); - if(a) { - b = a+1; - } - } while(a); - freeModeBuffer(modeBuf); - if(done_users == total_users) - reply(textclient, user, "NS_HALFOP_DONE", chan->name); - else - reply(textclient, user, "NS_HALFOP_FAIL", client->user->nick); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_halfopall.c b/src/cmd_neonserv_halfopall.c deleted file mode 100644 index a52ad6d..0000000 --- a/src/cmd_neonserv_halfopall.c +++ /dev/null @@ -1,74 +0,0 @@ -/* cmd_neonserv_halfopall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] "force" -* argv[1] (optional) nick mask -*/ -static USERLIST_CALLBACK(neonserv_cmd_halfopall_userlist_lookup); -static void neonserv_cmd_halfopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask); - -struct neonserv_cmd_halfopall_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nickmask; -}; - -CMD_BIND(neonserv_cmd_halfopall) { - struct neonserv_cmd_halfopall_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - if(argc) { - cache->nickmask = strdup(argv[0]); - } else - cache->nickmask = NULL; - get_userlist_if_invisible(chan, neonserv_cmd_halfopall_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_halfopall_userlist_lookup) { - struct neonserv_cmd_halfopall_cache *cache = data; - neonserv_cmd_halfopall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask); - if(cache->nickmask) - free(cache->nickmask); - free(cache); -} - -static void neonserv_cmd_halfopall_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; - modeBuf = initModeBuffer(client, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - if(chanuser->flags & CHANUSERFLAG_OPPED) continue; - modeBufferHalfop(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(textclient, user, "NS_HALFOPALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_help.c b/src/cmd_neonserv_help.c deleted file mode 100644 index 20ec2c2..0000000 --- a/src/cmd_neonserv_help.c +++ /dev/null @@ -1,97 +0,0 @@ -/* cmd_neonserv_help.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] index -*/ - -CMD_BIND(neonserv_cmd_help) { - char *ident; - if(argc) - ident = merge_argv(argv, 0, argc); - else - ident = "0"; - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - char *lang; - if ((row = mysql_fetch_row(res)) != NULL) - lang = row[0]; - else - lang = "en"; - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - if(stricmp(lang, "en")) { - printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident)); - res = mysql_use(); - } - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_HELP_TOPIC"); - return; - } - } - char sendBuf[MAXLEN]; - int sendBufPos = 0; - int i; - for(i = 0; i < strlen(row[0]); i++) { - switch(row[0][i]) { - case '\n': - if(sendBufPos) { - sendBuf[sendBufPos] = '\0'; - reply(getTextBot(), user, "%s", sendBuf); - sendBufPos = 0; - } - break; - case '$': - switch(row[0][i+1]) { - case 'b': - sendBuf[sendBufPos++] = 2; - i++; - break; - case 'k': - sendBuf[sendBufPos++] = 3; - i++; - break; - case 'u': - sendBuf[sendBufPos++] = 31; - i++; - break; - case 'C': - case 'S': - sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick); - i++; - break; - default: - sendBuf[sendBufPos++] = '$'; - break; - } - break; - default: - sendBuf[sendBufPos++] = row[0][i]; - break; - } - } - if(sendBufPos) { - sendBuf[sendBufPos] = '\0'; - reply(getTextBot(), user, "%s", sendBuf); - sendBufPos = 0; - } -} diff --git a/src/cmd_neonserv_info.c b/src/cmd_neonserv_info.c deleted file mode 100644 index 17a9df6..0000000 --- a/src/cmd_neonserv_info.c +++ /dev/null @@ -1,105 +0,0 @@ -/* cmd_neonserv_info.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no parameters -*/ - -CMD_BIND(neonserv_cmd_info) { - MYSQL_RES *res; - MYSQL_ROW row, row2; - struct Table *table; - printf_mysql_query("SELECT `channel_defaulttopic`, `channel_modes`, `channel_maxusers`, `channel_lastvisit`, `channel_registered`, `user_user` FROM `channels` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - table = table_init(2, 9, 0); - table_set_bold(table, 0, 1); - char *content[2]; - reply(getTextBot(), user, "NS_INFO_HEADER", chan->name); - content[0] = get_language_string(user, "NS_INFO_DEFAULTTOPIC"); - content[1] = row[0]; - table_add(table, content); - content[0] = get_language_string(user, "NS_INFO_MODELOCK"); - content[1] = row[1]; - table_add(table, content); - content[0] = get_language_string(user, "NS_INFO_RECORD"); - content[1] = row[2]; - table_add(table, content); - printf_mysql_query("SELECT `user_user`, `chanuser_access` FROM `chanusers` LEFT JOIN `users` ON `user_id` = `chanuser_uid` WHERE `chanuser_cid` = '%d'", chan->channel_id); - res = mysql_use(); - char ownerstr[MAXLEN]; - int ownerpos = 0, usercount = 0; - int userisowner = 0; - while((row2 = mysql_fetch_row(res))) { - if(!strcmp(row2[1], "500")) { - ownerpos += sprintf(ownerstr + ownerpos, (ownerpos ? ", %s" : "%s"), row2[0]); - if((user->flags & USERFLAG_ISAUTHED) && !stricmp(row2[0], user->auth)) - userisowner = 1; - } - usercount++; - } - content[0] = get_language_string(user, "NS_INFO_OWNER"); - content[1] = ownerstr; - table_add(table, content); - sprintf(ownerstr, "%d", usercount); - content[0] = get_language_string(user, "NS_INFO_USERS"); - content[1] = ownerstr; - table_add(table, content); - printf_mysql_query("SELECT COUNT(*) FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); - res = mysql_use(); - row2 = mysql_fetch_row(res); - content[0] = get_language_string(user, "NS_INFO_BANS"); - content[1] = row2[0]; - table_add(table, content); - content[0] = get_language_string(user, "NS_INFO_VISITED"); - content[1] = timeToStr(user, time(0) - atoi(row[3]), 2, ownerstr); - table_add(table, content); - if(strcmp(row[4], "0")) { - content[0] = get_language_string(user, "NS_INFO_REGISTERED"); - content[1] = timeToStr(user, time(0) - atoi(row[4]), 2, ownerstr); - table_add(table, content); - } - if(row[5] && isGodMode(user)) { - content[0] = get_language_string(user, "NS_INFO_REGISTRAR"); - content[1] = row[5]; - table_add(table, content); - } - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); - if(userisowner || isGodMode(user)) { - printf_mysql_query("SELECT `owner_history_time`, a.`user_user`, b.`user_user` FROM `owner_history` LEFT JOIN `users` a ON `owner_history_from_uid` = a.`user_id` LEFT JOIN `users` b ON `owner_history_to_uid` = b.`user_id` WHERE `owner_history_cid` = '%d'", chan->channel_id); - res = mysql_use(); - if(mysql_num_rows(res)) { - reply(getTextBot(), user, "NS_INFO_OWNERLOG", chan->name); - time_t rawtime; - struct tm *timeinfo; - char timeBuf[80]; - while((row = mysql_fetch_row(res))) { - rawtime = (time_t) atol(row[0]); - timeinfo = localtime(&rawtime); - strftime(timeBuf, 80, "%c", timeinfo); - reply(getTextBot(), user, "NS_INFO_OWNERCHANGE", row[1], row[2], timeBuf); - } - } - } -} diff --git a/src/cmd_neonserv_invite.c b/src/cmd_neonserv_invite.c deleted file mode 100644 index 60c00a2..0000000 --- a/src/cmd_neonserv_invite.c +++ /dev/null @@ -1,180 +0,0 @@ -/* cmd_neonserv_invite.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -*/ -static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup); -static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); -static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout); -static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan); -static int neonserv_cmd_invite_is_timeout(char *nick, char *chan); -static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout); - - -struct neonserv_cmd_invite_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - struct Event *event; - char *nick; -}; - -struct neonserv_cmd_invite_timeout { - char *nick; - char *chan; - - struct neonserv_cmd_invite_timeout *next; -}; - -static struct neonserv_cmd_invite_timeout *first_timeout = NULL, *last_timeout = NULL; - -CMD_BIND(neonserv_cmd_invite) { - if(neonserv_cmd_invite_is_timeout(argv[0], chan->name)) { - reply(getTextBot(), user, "NS_INVITE_TIMEOUT", argv[0], chan->name); - return; - } - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } else if(getChanUser(cuser, chan)) { - reply(getTextBot(), user, "NS_INVITE_ON_CHAN", cuser->nick, chan->name); - /* BUG - This check does not work if the user is invisible (CHMODE +D/+d) - to fix this we'd need to request the full userlist... - this is really senseless to invite a simple user so we simply mark this bug as unsolvable. - */ - return; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_invite_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); - } else { - struct neonserv_cmd_invite_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->nick = strdup(argv[0]); - get_userauth(cuser, neonserv_cmd_invite_nick_lookup, cache); - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup) { - struct neonserv_cmd_invite_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } else - neonserv_cmd_invite_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, ((user->flags & USERFLAG_ISAUTHED) ? user->auth : NULL)); - free(cache->nick); - free(cache); -} - -static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { - if(auth) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - //check if the user has set noinvite - printf_mysql_query("SELECT `id` FROM `noinvite` WHERE `uid` = '%s' AND `cid` = '%d'", row[0], chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(textclient, user, "NS_INVITE_RESTRICTION", nick, chan->name); - return; - } - } - } - struct neonserv_cmd_invite_timeout *timeout = neonserv_cmd_invite_add_timeout(nick, chan->name); - timeq_add(INVITE_TIMEOUT, neonserv_cmd_invite_timeout_timeout, timeout); - putsock(client, "INVITE %s %s", nick, chan->name); - struct UserNode *tmpu = getUserByNick(nick); - if(!tmpu) { - tmpu = createTempUser(nick); - tmpu->flags |= USERFLAG_ISTMPUSER | (auth ? USERFLAG_ISAUTHED : 0); - if(auth) - strcpy(tmpu->auth, auth); - } - reply(textclient, tmpu, "NS_INVITE_DONE_USER", chan->name, user->nick, client->user->nick); - reply(textclient, user, "NS_INVITE_DONE", nick, chan->name); -} - -static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout) { - struct neonserv_cmd_invite_timeout *entry = data; - neonserv_cmd_invite_del_timeout(entry); -} - -static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan) { - struct neonserv_cmd_invite_timeout *entry = malloc(sizeof(*entry)); - if (!entry) { - perror("malloc() failed"); - return NULL; - } - entry->next = NULL; - entry->nick = strdup(nick); - entry->chan = strdup(chan); - if(last_timeout) { - last_timeout->next = entry; - last_timeout = entry; - } else { - last_timeout = entry; - first_timeout = entry; - } - return entry; -} - -static int neonserv_cmd_invite_is_timeout(char *nick, char *chan) { - if(!first_timeout) return 0; - struct neonserv_cmd_invite_timeout *entry; - for(entry = first_timeout; entry; entry = entry->next) { - if(!stricmp(entry->nick, nick) && !stricmp(entry->chan, chan)) - return 1; - } - return 0; -} - -static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout) { - struct neonserv_cmd_invite_timeout *entry, *prev = NULL; - for(entry = first_timeout; entry; entry = entry->next) { - if(entry == timeout) { - if(prev) - prev->next = entry->next; - else - first_timeout = entry->next; - break; - } else - prev = entry; - } - if(last_timeout == timeout) - last_timeout = prev; - free(timeout->nick); - free(timeout->chan); - free(timeout); -} diff --git a/src/cmd_neonserv_inviteme.c b/src/cmd_neonserv_inviteme.c deleted file mode 100644 index 54c2dbf..0000000 --- a/src/cmd_neonserv_inviteme.c +++ /dev/null @@ -1,36 +0,0 @@ -/* cmd_neonserv_inviteme.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -CMD_BIND(neonserv_cmd_inviteme) { - if(getChanUser(user, chan)) { - reply(getTextBot(), user, "NS_INVITEME_ON_CHAN", chan->name); - /* BUG - This check does not work if the user is invisible (CHMODE +D/+d) - to fix this we'd need to request the full userlist... - this is really senseless to invite a simple user so we simply mark this bug as unsolvable. - */ - return; - } - putsock(client, "INVITE %s %s", user->nick, chan->name); - reply(getTextBot(), user, "NS_INVITEME_DONE", chan->name); -} diff --git a/src/cmd_neonserv_kick.c b/src/cmd_neonserv_kick.c deleted file mode 100644 index 7ffcf65..0000000 --- a/src/cmd_neonserv_kick.c +++ /dev/null @@ -1,167 +0,0 @@ -/* cmd_neonserv_kick.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] nick[,*auth[,*!*@mask[...]]] -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_kick) { - struct neonserv_cmd_kick_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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_with_invisible(chan, neonserv_cmd_kick_userlist_lookup, cache); -} - -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->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, struct Event *event, char *nicks, char *reason) { - int i, kicked_users = 0, provided_nicks = 0; - char *nick, *nextnick; - struct UserNode *cuser; - struct ChanUser *chanuser; - nextnick = nicks; - while((nick = nextnick)) { - nextnick = strstr(nick, ","); - if(nextnick) { - *nextnick = '\0'; - nextnick++; - } - if(!*nick) continue; - if(is_ircmask(nick)) { - //KICK HOSTMASK - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - struct ChanUser *kick_chanuser[chan->usercount]; - int kick_chanuser_pos = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(nick, usermask)) { - provided_nicks++; - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - continue; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - kick_chanuser[kick_chanuser_pos++] = chanuser; - if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) { - kick_chanuser_pos = 0; - reply(textclient, user, "NS_LAME_MASK", nick); - break; - } - } - } - for(i = 0; i < kick_chanuser_pos; i++) { - kicked_users++; - putsock(client, "KICK %s %s :(%s) %s", chan->name, kick_chanuser[i]->user->nick, user->nick, reason); - } - } else if(*nick == '*') { - //KICK AUTH - nick++; - cuser = NULL; - if(!stricmp(user->auth, nick)) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) { - provided_nicks++; - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - continue; - } - if(!cuser) { - //check if the user is protected - if(isUserProtected(chan, chanuser->user, user)) { - reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick); - break; //all other users are also protected... - } - cuser = chanuser->user; - } - kicked_users++; - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - } else { - provided_nicks++; - cuser = NULL; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(!stricmp(chanuser->user->nick, nick)) { - cuser = chanuser->user; - } - } - if(!cuser) continue; - if(isNetworkService(cuser)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - continue; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - kicked_users++; - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - if(kicked_users == provided_nicks) - 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/src/cmd_neonserv_kickban.c b/src/cmd_neonserv_kickban.c deleted file mode 100644 index 1123cd7..0000000 --- a/src/cmd_neonserv_kickban.c +++ /dev/null @@ -1,169 +0,0 @@ -/* cmd_neonserv_kickban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] nick[,*auth[,*!*@mask[...]]] -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_kickban) { - struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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_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->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, struct Event *event, char *nicks, char *reason) { - int i, kicked_users = 0, provided_nicks = 0; - char *nick, *nextnick; - struct UserNode *cuser; - struct ChanUser *chanuser; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - nextnick = nicks; - while((nick = nextnick)) { - nextnick = strstr(nick, ","); - if(nextnick) { - *nextnick = '\0'; - nextnick++; - } - if(!*nick) continue; - if(is_ircmask(nick)) { - //KICK HOSTMASK - struct ChanUser *kickban_chanuser[chan->usercount]; - int kick_chanuser_pos = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(nick, usermask)) { - provided_nicks++; - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - continue; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - kickban_chanuser[kick_chanuser_pos++] = chanuser; - if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) { - kick_chanuser_pos = 0; - reply(textclient, user, "NS_LAME_MASK", nick); - break; - } - } - } - for(i = 0; i < kick_chanuser_pos; i++) { - if(i == 0) { - putsock(client, "MODE %s +b %s", chan->name, nick); - } - kicked_users++; - putsock(client, "KICK %s %s :(%s) %s", chan->name, kickban_chanuser[i]->user->nick, user->nick, reason); - } - } else if(*nick == '*') { - //KICK AUTH - nick++; - cuser = NULL; - if(!stricmp(user->auth, nick)) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) { - provided_nicks++; - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - continue; - } - if(!cuser) { - //check if the user is protected - if(isUserProtected(chan, chanuser->user, user)) { - reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick); - break; //all other users are also protected... - } - cuser = chanuser->user; - } - kicked_users++; - putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask)); - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - } else { - provided_nicks++; - cuser = searchUserByNick(nick); - if(!cuser) continue; - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - if(isNetworkService(cuser)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - continue; - } - if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { - reply(textclient, user, "NS_YOU_PROTECTED"); - continue; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - continue; - } - kicked_users++; - putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask)); - putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); - } - } - if(kicked_users == provided_nicks) - 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/src/cmd_neonserv_listrank.c b/src/cmd_neonserv_listrank.c deleted file mode 100644 index 65d53cf..0000000 --- a/src/cmd_neonserv_listrank.c +++ /dev/null @@ -1,77 +0,0 @@ -/* cmd_neonserv_listrank.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -CMD_BIND(neonserv_cmd_listrank) { - MYSQL_RES *res, *res2; - MYSQL_ROW row, row2; - struct Table *table; - int ranks = 0; - printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` ORDER BY `rank_order` ASC"); - res = mysql_use(); - table = table_init(3, mysql_num_rows(res) + 1, 0); - char *content[3]; - content[0] = get_language_string(user, "NS_LISTRANK_ID"); - content[1] = get_language_string(user, "NS_LISTRANK_NAME"); - content[2] = get_language_string(user, "NS_LISTRANK_ASSIGNED"); - table_add(table, content); - char usersBuf[MAXLEN]; - int usersPos, userCount; - char assignedBuf[MAXLEN]; - while ((row = mysql_fetch_row(res)) != NULL) { - ranks++; - content[0] = row[0]; - content[1] = row[1]; - printf_mysql_query("SELECT `user_user`, `user_god` FROM `users` WHERE `user_rank` = '%s'", row[0]); - res2 = mysql_use(); - usersPos = 0; - userCount = 0; - while((row2 = mysql_fetch_row(res2)) != NULL) { - usersPos += sprintf(usersBuf+usersPos, (usersPos ? ", %s%s" : "%s%s"), (strcmp(row2[1], "0") ? "@" : ""), row2[0]); - userCount++; - } - sprintf(assignedBuf, (userCount ? "%d (%s)" : "%d"), userCount, usersBuf); - content[2] = assignedBuf; - table_add(table, content); - } - //send the table - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - if(!ranks) - reply(getTextBot(), user, "NS_TABLE_NONE"); - table_free(table); - printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_rank` = '0' AND `user_access` > 0"); - res2 = mysql_use(); - usersPos = 0; - userCount = 0; - while((row2 = mysql_fetch_row(res2)) != NULL) { - usersPos += sprintf(usersBuf+usersPos, (usersPos ? ", %s%s" : "%s%s"), (strcmp(row2[1], "0") ? "@" : ""), row2[0]); - userCount++; - } - reply(getTextBot(), user, "NS_LISTRANK_UNRANKED", userCount); - if(userCount) { - reply(getTextBot(), user, " %s", usersBuf); - } -} diff --git a/src/cmd_neonserv_mdeluser.c b/src/cmd_neonserv_mdeluser.c deleted file mode 100644 index 50090dd..0000000 --- a/src/cmd_neonserv_mdeluser.c +++ /dev/null @@ -1,64 +0,0 @@ -/* cmd_neonserv_mdeluser.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] access (format: minaccess-maxaccess) -* argv[1] pattern -*/ - -CMD_BIND(neonserv_cmd_mdeluser) { - int min_access, max_access; - char *seperator = strstr(argv[0], "-"); - if(seperator) { - *seperator = '\0'; - seperator++; - min_access = atoi(argv[0]); - max_access = atoi(seperator); - if(max_access < min_access) { - reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access); - return; - } - } else { - min_access = atoi(argv[0]); - max_access = min_access; - } - if(max_access >= getChannelAccess(user, chan)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_NO_ACCESS"); - return; - } - } - MYSQL_RES *res; - MYSQL_ROW row; - int del_count = 0; - printf_mysql_query("SELECT `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access); - res = mysql_use(); - while((row = mysql_fetch_row(res)) != NULL) { - if(!match(argv[1], row[0])) { - del_count++; - printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]); - } - } - reply(getTextBot(), user, "NS_MDELUSER_DONE", del_count, argv[1], min_access, max_access, chan->name); - if(del_count) - logEvent(event); -} - diff --git a/src/cmd_neonserv_mode.c b/src/cmd_neonserv_mode.c deleted file mode 100644 index 8a11e36..0000000 --- a/src/cmd_neonserv_mode.c +++ /dev/null @@ -1,297 +0,0 @@ -/* cmd_neonserv_mode.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - modes -* argv[1-*] - parameters -*/ -static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup); -static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode); - -struct neonserv_cmd_mode_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *mode; -}; - -CMD_BIND(neonserv_cmd_mode) { - struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->mode = strdup(merge_argv(argv, 0, argc)); - get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup) { - struct neonserv_cmd_mode_cache *cache = data; - neonserv_cmd_mode_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mode); - free(cache->mode); - free(cache); -} - -static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode) { - MYSQL_ROW row, defaults = NULL; - int i, arg, add = 1, skip = 0; - unsigned int modetype; - int db_canop, db_canvoice, db_canban, db_enfmodes; - struct ModeNode *modelock = createModeNode(NULL), *changemodes = createModeNode(NULL); - struct ModeBuffer *modeBuf; - struct UserNode *cuser; - struct ChanUser *chanuser; - modeBuf = initModeBuffer(client, chan); - printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - row = mysql_fetch_row(mysql_use()); - if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) { - printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'"); - defaults = mysql_fetch_row(mysql_use()); - } - db_canop = atoi((row[0] ? row[0] : defaults[0])); - db_canvoice = atoi((row[1] ? row[1] : defaults[1])); - db_canban = atoi((row[2] ? row[2] : defaults[2])); - db_enfmodes = atoi((row[3] ? row[3] : defaults[3])); - if(row[4]) - parseModeString(modelock, row[4]); - else if(defaults[4]) - parseModeString(modelock, defaults[4]); - int uaccess = getChannelAccess(user, chan); - char *a, *b = mode; - char *argv[MAXNUMPARAMS]; - char *carg; - char tmp[MAXLEN]; - int argc = 0; - do { - a = strstr(b, " "); - if(a) *a = '\0'; - argv[argc++] = b; - if(argc == MAXNUMPARAMS) break; - if(a) b = a+1; - } while(a); - arg = 0; - while(arg < argc) { - char *modeStr = argv[arg++]; - for(i = 0; i < strlen(modeStr); i++) { - switch(modeStr[i]) { - case '+': - add = 1; - break; - case '-': - add = 0; - break; - case 'o': - case 'v': - if(arg == argc) { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - carg = argv[arg++]; - if(modeStr[i] == 'o') { - if(uaccess < db_canop) { - reply(textclient, user, "NS_MODE_ENFOPS", chan->name); - db_canop = -1; - break; - } - if(db_canop == -1) break; - } else { - if(uaccess < db_canvoice) { - reply(textclient, user, "NS_MODE_ENFVOICE", chan->name); - db_canvoice = -1; - break; - } - if(db_canvoice == -1) break; - } - cuser = searchUserByNick(carg); - if(!cuser) { - //check for an invisible user - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(!stricmp(chanuser->user->nick, carg)) { - cuser = chanuser->user; - break; - } - } - if(!cuser) break; - } else { - chanuser = getChanUser(cuser, chan); - if(!chanuser) break; - } - if(!(add ^ (chanuser->flags & (modeStr[i] == 'o' ? CHANUSERFLAG_OPPED : CHANUSERFLAG_VOICED)))) break; - if(!add) { - //check protection - if(modeStr[i] == 'o' && isNetworkService(cuser)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - break; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - break; - } - } - modeBufferSet(modeBuf, add, modeStr[i], carg); - break; - case 'b': - if(arg == argc) { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - carg = argv[arg++]; - if(uaccess < db_canban) { - reply(textclient, user, "NS_MODE_CANBAN", chan->name); - db_canban = -1; - break; - } - if(db_canban == -1) break; - char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - struct BanNode *ban; - int match_count = 0; - carg = make_banmask(carg, hostmask_buffer); - if(add) { - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(carg, usermask)) { - if(isNetworkService(chanuser->user)) { - reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); - skip = 1; - break; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - skip = 1; - break; - } - match_count++; - if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { - skip = 1; - reply(textclient, user, "NS_LAME_MASK", carg); - break; - } - } - } - } else { - skip = 1; - for(ban = chan->bans; ban; ban = ban->next) { - if(!match(carg, ban->mask)) { - skip = 0; - break; - } - } - } - if(!skip) { - modeBufferSet(modeBuf, add, 'b', carg); - } - break; - default: - modetype = getModeType(modelock, modeStr[i]); - if(modetype == 0) { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) { - if(isGodMode(user)) - event->flags |= CMDFLAG_OPLOG; - else { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - return; - } - } - if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) { - if(arg == argc) { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - carg = argv[arg++]; - if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) { - char *modelock_val = getModeValue(modelock, modeStr[i]); - if(stricmp(carg, modelock_val)) { - if(isGodMode(user)) - event->flags |= CMDFLAG_OPLOG; - else { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - return; - } - } - } - if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) { - int *modelock_val = getModeValue(modelock, modeStr[i]); - if(atoi(carg) != *modelock_val) { - if(isGodMode(user)) - event->flags |= CMDFLAG_OPLOG; - else { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - return; - } - } - } - } else if(!add && (modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_B) { - if(arg == argc && !(modetype & CHANNEL_MODE_KEY)) { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - carg = (arg == argc ? NULL : argv[arg++]); - } else - carg = NULL; - if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add) - break; - if(!isModeAffected(changemodes, modeStr[i])) { - if(!add && (modetype & CHANNEL_MODE_KEY)) { - if(isModeSet(chan->modes, modeStr[i])) { - char *current_val = getModeValue(chan->modes, modeStr[i]); - carg = current_val; - } - } - if(parseMode(changemodes, add, modeStr[i], carg)) { - if(carg) { - if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) { - char *current_val = getModeValue(chan->modes, modeStr[i]); - modeBufferSet(modeBuf, 0, modeStr[i], current_val); - flushModeBuffer(modeBuf); - } - if(!add && !isModeSet(chan->modes, modeStr[i])) break; - modeBufferSet(modeBuf, add, modeStr[i], carg); - } else { - modeBufferSimpleMode(modeBuf, add, modeStr[i]); - } - } else { - reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); - return; - } - } - break; - } - } - } - getFullModeString(changemodes, tmp); - freeModeBuffer(modeBuf); - if(strcmp(tmp, "+")) - reply(textclient, user, "NS_MODE_DONE", tmp); - - logEvent(event); - freeModeNode(modelock); - freeModeNode(changemodes); -} diff --git a/src/cmd_neonserv_move.c b/src/cmd_neonserv_move.c deleted file mode 100644 index 211247e..0000000 --- a/src/cmd_neonserv_move.c +++ /dev/null @@ -1,91 +0,0 @@ -/* cmd_neonserv_move.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - channel -* argv[1] - new channel -*/ -CMD_BIND(neonserv_cmd_move) { - MYSQL_RES *res; - MYSQL_ROW row; - char *channel = argv[0]; - char *new_channel = argv[1]; - if(!is_valid_chan(new_channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", new_channel); - return; - } - if(!stricmp(channel, new_channel)) { - reply(getTextBot(), user, "NS_MOVE_SELF"); - return; - } - printf_mysql_query("SELECT `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `channel_id` = `chanid` WHERE `channel_name` = '%s'", escape_string(new_channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_REGISTER_ALREADY", new_channel, client->user->nick); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - } else { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - if(!strcmp(row[2], "1")) { - reply(getTextBot(), user, "NS_MOVE_SUSPENDED"); - return; - } - int botid = atoi(row[0]); - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - putsock(bot, "PART %s :Channel moved to %s.", channel, new_channel); - putsock(bot, "JOIN %s", new_channel); - } - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(new_channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid); - printf_mysql_query("DELETE FROM `bans` WHERE `ban_channel` = '%d'", chanid); - printf_mysql_query("DELETE FROM `events` WHERE `cid` = '%d'", chanid); - printf_mysql_query("DELETE FROM `noinvite` WHERE `cid` = '%d'", chanid); - printf_mysql_query("DELETE FROM `owner_history` WHERE `owner_history_cid` = '%d'", chanid); - printf_mysql_query("DELETE FROM `channels` WHERE `channel_id` = '%d'", chanid); - } - printf_mysql_query("UPDATE `channels` SET `channel_name` = '%s' WHERE `channel_name` = '%s'", escape_string(new_channel), escape_string(channel)); - struct ChanNode *channode = getChanByName(channel); - if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) { - channode->flags &= ~CHANFLAG_CHAN_REGISTERED; - channode->channel_id = 0; - } - reply(getTextBot(), user, "NS_MOVE_DONE", channel, new_channel); - logEvent(event); -} diff --git a/src/cmd_neonserv_myaccess.c b/src/cmd_neonserv_myaccess.c deleted file mode 100644 index b9f6581..0000000 --- a/src/cmd_neonserv_myaccess.c +++ /dev/null @@ -1,190 +0,0 @@ -/* cmd_neonserv_myaccess.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - nick / *auth -*/ -static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup); -static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch); - -struct neonserv_cmd_myaccess_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - char *nick; - char *chanmatch; -}; - -CMD_BIND(neonserv_cmd_myaccess) { - char *chanmatch = NULL; - if(argc == 0 || argv[0][0] == '#') { - if(argc != 0) { - chanmatch = argv[0]; - } - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->nick = strdup(argv[0]); - cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL); - get_userauth(user, neonserv_cmd_myaccess_nick_lookup, cache); - } else - neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, user->nick, user->auth, chanmatch); - } - else if(argv[0][0] == '*') { - //we've got an auth - if(argc > 1 && argv[1][0] == '#') { - chanmatch = argv[1]; - } - argv[0]++; - neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, NULL, argv[0], chanmatch); - } else { - if(argc > 1 && argv[1][0] == '#') { - chanmatch = argv[1]; - } - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, chanmatch); - } else { - struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->nick = strdup(argv[0]); - cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL); - get_userauth(cuser, neonserv_cmd_myaccess_nick_lookup, cache); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup) { - struct neonserv_cmd_myaccess_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - if(!strcmp(cache->nick, cache->user->nick)) - reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH"); - else - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - neonserv_cmd_myaccess_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->chanmatch); - if(cache->chanmatch) - free(cache->chanmatch); - free(cache->nick); - free(cache); -} - -static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch) { - //we've got a valid auth now... - if(stricmp(user->auth, auth) && !isGodMode(user)) { - reply(textclient, user, "NS_MYACCESS_SELF_ONLY"); - return; - } - MYSQL_RES *res, *default_res; - MYSQL_ROW user_row, chanuser_row, default_chan = NULL; - char flagBuf[5]; - int userid, cflags, caccess, flagPos; - int i, total_count = 0, match_count = 0, owner_count = 0; - struct Table *table = NULL; - printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - char *content[4]; - content[0] = get_language_string(user, "NS_MYACCESS_HEADER_NAME"); - content[1] = get_language_string(user, "NS_MYACCESS_HEADER_ACCESS"); - content[2] = get_language_string(user, "NS_MYACCESS_HEADER_FLAGS"); - content[3] = get_language_string(user, "NS_MYACCESS_HEADER_INFO"); - if(chanmatch) - reply(textclient, user, "NS_MYACCESS_HEADER_MATCH", auth, chanmatch); - else - reply(textclient, user, "NS_MYACCESS_HEADER", auth); - if ((user_row = mysql_fetch_row(res)) != NULL) { - userid = atoi(user_row[0]); - //check if the user is already added - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `channel_name`, `channel_getop`, `channel_getvoice`, `botid` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` LEFT JOIN `bot_channels` ON `chanuser_cid` = `chanid` LEFT JOIN `bots` ON `bots`.`id` = `botid` WHERE `chanuser_uid` = '%d' AND `botclass` = '%d' AND `active` = '1' ORDER BY `chanuser_access` DESC, `channel_name` ASC", userid, client->botid); - res = mysql_use(); - total_count = mysql_num_rows(res); - table = table_init(4, total_count + 1, 0); - table_add(table, content); - while ((chanuser_row = mysql_fetch_row(res)) != NULL) { - if(!strcmp(chanuser_row[0], "500")) owner_count++; - if(chanmatch && match(chanmatch, chanuser_row[0])) continue; - match_count++; - if((!chanuser_row[4] || !chanuser_row[5]) && !default_chan) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); - default_res = mysql_use(); - default_chan = mysql_fetch_row(default_res); - } - flagPos = 0; - content[0] = chanuser_row[3]; - content[1] = chanuser_row[0]; - cflags = atoi(chanuser_row[1]); - caccess = atoi(chanuser_row[0]); - if((cflags & DB_CHANUSER_SUSPENDED)) - flagPos += sprintf(flagBuf + flagPos, "s"); - if(caccess >= (chanuser_row[4] ? atoi(chanuser_row[4]) : atoi(default_chan[0]))) - flagPos += sprintf(flagBuf + flagPos, "o"); - if(caccess >= (chanuser_row[5] ? atoi(chanuser_row[5]) : atoi(default_chan[1]))) - flagPos += sprintf(flagBuf + flagPos, "v"); - if((cflags & DB_CHANUSER_AUTOINVITE)) - flagPos += sprintf(flagBuf + flagPos, "i"); - content[2] = (flagPos ? flagBuf : ""); - content[3] = chanuser_row[2]; - table_add(table, content); - } - } else { - table = table_init(4, 1, 0); - table_add(table, content); - } - //send the table - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(textclient, user, table_lines[i]); - } - if(!match_count) - reply(textclient, user, "NS_TABLE_NONE"); - if(chanmatch) { - reply(textclient, user, "NS_MYACCESS_COUNT_MATCH", auth, total_count, owner_count, match_count, chanmatch); - } else { - reply(textclient, user, "NS_MYACCESS_COUNT", auth, total_count, owner_count); - } - table_free(table); -} diff --git a/src/cmd_neonserv_nicklist.c b/src/cmd_neonserv_nicklist.c deleted file mode 100644 index 181923c..0000000 --- a/src/cmd_neonserv_nicklist.c +++ /dev/null @@ -1,249 +0,0 @@ -/* cmd_neonserv_nicklist.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] "force" -* argv[1] (optional) nick mask -*/ -static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup); -static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers); -static void neonserv_cmd_nicklist_synchronize_user(struct ChanNode *chan, struct UserNode *user, int access); - -struct neonserv_cmd_nicklist_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nickmask; - int syncusers; -}; - -CMD_BIND(neonserv_cmd_nicklist) { - int syncusers = 0; - if(argc && !stricmp(argv[0], "sync")) { - if(!checkChannelAccess(user, chan, "channel_canadd", 0)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; - } - } - argv++; - argc--; - syncusers = 1; - event->flags |= CMDFLAG_LOG; - } - if(argc && !stricmp(argv[0], "nowho") && isGodMode(user)) { - argv++; - argc--; - neonserv_cmd_nicklist_async1(client, getTextBot(), user, chan, event, (argc ? argv[0] : NULL), syncusers); - return; - } - struct neonserv_cmd_nicklist_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - if(argc) { - cache->nickmask = strdup(argv[0]); - } else - cache->nickmask = NULL; - cache->syncusers = syncusers; - get_userlist_with_invisible(chan, neonserv_cmd_nicklist_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup) { - struct neonserv_cmd_nicklist_cache *cache = data; - neonserv_cmd_nicklist_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask, cache->syncusers); - if(cache->nickmask) - free(cache->nickmask); - free(cache); -} - -static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers) { - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - struct Table *table; - table = table_init(3, chan->usercount + 1, 0); - char *content[3]; - content[0] = get_language_string(user, "NS_NICKLIST_NICK"); - content[1] = get_language_string(user, "NS_NICKLIST_STATE"); - content[2] = get_language_string(user, "NS_NICKLIST_ACCESS"); - table_add(table, content); - printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d'", chan->channel_id); - res = mysql_use(); - int userlistlen = mysql_num_rows(res); - int i = 0; - MYSQL_ROW userlist[userlistlen]; - while ((row = mysql_fetch_row(res)) != NULL) { - userlist[i++] = row; - } - int db_enfops, db_enfvoice; - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - row = mysql_fetch_row(mysql_use()); - if(row[0] == NULL || row[1] == NULL) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); - defaults = mysql_fetch_row(mysql_use()); - } - db_enfops = atoi((row[0] ? row[0] : defaults[0])); - db_enfvoice = atoi((row[1] ? row[1] : defaults[1])); - int caccess = getChannelAccess(user, chan); - int synced_user = 0; - struct ChanUser *chanuser; - int sort_nicklist[] = { - CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED, - CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_OPPED, - CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, - CHANUSERFLAG_HALFOPPED, - CHANUSERFLAG_VOICED, - CHANUSERFLAG_INVISIBLE, - 0 - }; - int *sort_pos = sort_nicklist; - int sort_flags; - do { - sort_flags = *(sort_pos++); - char statebuf[5]; - char accessbuf[9]; - int uaccess; - int stateset = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if((chanuser->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != sort_flags) continue; - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - if(!stateset) { - if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[stateset++] = '<'; - if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[stateset++] = '@'; - if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[stateset++] = '%'; - if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[stateset++] = '+'; - statebuf[stateset++] = '\0'; - } - content[0] = chanuser->user->nick; - content[1] = statebuf; - uaccess = 0; - if(chanuser->user->flags & USERFLAG_ISAUTHED) { - for(i = 0; i < userlistlen; i++) { - if(!stricmp(chanuser->user->auth, userlist[i][1])) { - uaccess = atoi(userlist[i][0]); - if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) { - if(syncusers) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { - if(db_enfops >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfops; - } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) { - if(db_enfvoice >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfvoice; - } else { - //fail... - sprintf(accessbuf, "\00307%d\003", uaccess); - break; - } - neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); - sprintf(accessbuf, "\00309%d\003", uaccess); - synced_user = 1; - } else { - synced_user = 1; - sprintf(accessbuf, "\00307%d\003", uaccess); - } - } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED))) - sprintf(accessbuf, "\00303%d\003", uaccess); - else - sprintf(accessbuf, "%d", uaccess); - break; - } - } - } - if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) { - if(syncusers) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { - if(db_enfops >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfops; - } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) { - if(db_enfvoice >= caccess) - event->flags |= CMDFLAG_OPLOG; - uaccess = db_enfvoice; - } else { - uaccess = 0; - sprintf(accessbuf, "\003040\003"); - } - if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) { - neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); - sprintf(accessbuf, "\00309%d\003", uaccess); - synced_user = 1; - } else if(uaccess) { - sprintf(accessbuf, "\003040\003"); - } - } else { - synced_user = 1; - sprintf(accessbuf, "\003040\003"); - } - } else if(!uaccess) - sprintf(accessbuf, "0"); - content[2] = accessbuf; - table_add(table, content); - } - } while(sort_flags != 0); - //send the table - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(textclient, user, table_lines[i]); - } - if(table->length == 1) - reply(textclient, user, "NS_TABLE_NONE"); - reply(textclient, user, "NS_TABLE_COUNT", table->length - 1); - table_free(table); - if(synced_user) { - if(!syncusers) - reply(textclient, user, "NS_NICKLIST_SYNC", db_enfops, db_enfvoice); - else - logEvent(event); - } -} - -static void neonserv_cmd_nicklist_synchronize_user(struct ChanNode *chan, struct UserNode *user, int caccess) { - if(!(user->flags & USERFLAG_ISAUTHED)) return; - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth)); - userid = (int) mysql_insert_id(get_mysql_conn()); - } - //check if already added - printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - //clvl - if(atoi(row[0]) >= caccess) return; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]); - } else - printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chan->channel_id, userid, caccess); -} diff --git a/src/cmd_neonserv_noregister.c b/src/cmd_neonserv_noregister.c deleted file mode 100644 index f0ba380..0000000 --- a/src/cmd_neonserv_noregister.c +++ /dev/null @@ -1,199 +0,0 @@ -/* cmd_neonserv_noregister.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] *auth/#channel -* argv[1] duration -* argv[2-*] reason -*/ - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_noregister_auth_lookup); -static USERAUTH_CALLBACK(neonserv_cmd_noregister_nick_lookup); -static void neonserv_cmd_noregister_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event,char *auth, int duration, char *reason); -static void neonserv_cmd_noregister_list(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); - -struct neonserv_cmd_noregister_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - struct Event *event; - int duration; - char *reason, *nick; -}; - -CMD_BIND(neonserv_cmd_noregister) { - if(argc < 3) { - neonserv_cmd_noregister_list(client, user, chan, event, argv, argc); - return; - } - int duration = strToTime(user, argv[1]); - if(duration == 0 && strcmp(argv[1], "0")) { - reply(getTextBot(), user, "NS_NOREGISTER_INVALID_DURATION", argv[1]); - return; - } - char *reason = merge_argv(argv, 2, argc); - MYSQL_RES *res; - MYSQL_ROW row; - if(argv[0][0] == '#') { - printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s'", escape_string(argv[0])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_NOREGISTER_REGISTERED", argv[0]); - return; - } - neonserv_cmd_noregister_async1(client, getTextBot(), user, chan, event, argv[0], duration, reason); - } else if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - 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_noregister_async1(client, getTextBot(), user, chan, event, row[0], duration, reason); - } else { - //we need to create a new user... - //but first lookup the auth to check if it really exists - struct neonserv_cmd_noregister_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->nick = strdup(argv[0]); - cache->duration = duration; - cache->reason = strdup(reason); - lookup_authname(argv[0], neonserv_cmd_noregister_auth_lookup, cache); - } - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - neonserv_cmd_noregister_async1(client, getTextBot(), user, chan, event, cuser->auth, duration, reason); - } else { - struct neonserv_cmd_noregister_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->nick = strdup(user->nick); - cache->duration = duration; - cache->reason = strdup(reason); - get_userauth(cuser, neonserv_cmd_noregister_nick_lookup, cache); - } - } -} - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_noregister_auth_lookup) { - struct neonserv_cmd_noregister_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); - } else - neonserv_cmd_noregister_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, auth, cache->duration, cache->reason); - free(cache->reason); - free(cache->nick); - free(cache); -} - -static USERAUTH_CALLBACK(neonserv_cmd_noregister_nick_lookup) { - struct neonserv_cmd_noregister_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - neonserv_cmd_noregister_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->auth, cache->duration, cache->reason); - free(cache->reason); - free(cache->nick); - free(cache); -} - -static void neonserv_cmd_noregister_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event,char *auth, int duration, char *reason) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `dnr_id` FROM `donotregister` WHERE `dnr_target` = '%s'", escape_string(auth)); - res = mysql_use(); - if((row = mysql_fetch_row(res)) != NULL) { - printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[0]); - } - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) - userid = atoi(row[0]); - else - userid = 0; - printf_mysql_query("INSERT INTO `donotregister` (`dnr_target`, `dnr_timeout`, `dnr_user`, `dnr_reason`) VALUES ('%s', '%lu', '%d', '%s')", escape_string(auth), (duration ? (time(0)+duration) : 0), userid, escape_string(reason)); - reply(getTextBot(), user, "NS_NOREGISTER_DONE", auth); -} - -static void neonserv_cmd_noregister_list(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) { - struct Table *table; - int entrys = 0; - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `dnr_target`, `dnr_timeout`, `user_user`, `dnr_reason` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` ORDER BY `dnr_target` ASC"); - res = mysql_use(); - table = table_init(4, mysql_num_rows(res) + 1, 0); - char *content[4]; - content[0] = get_language_string(user, "NS_DNR_TARGET"); - content[1] = get_language_string(user, "NS_DNR_USER"); - content[2] = get_language_string(user, "NS_DNR_EXPIRES"); - content[3] = get_language_string(user, "NS_DNR_REASON"); - table_add(table, content); - int duration; - char expires_str[MAXLEN]; - while ((row = mysql_fetch_row(res)) != NULL) { - entrys++; - content[0] = row[0]; - content[1] = row[2]; - duration = atoi(row[1]); - content[2] = (duration ? timeToStr(user, (duration - time(0)), 2, expires_str) : get_language_string(user, "NS_USERS_SEEN_NEVER")); - content[3] = row[3]; - table_add(table, content); - } - //send the table - char **table_lines = table_end(table); - int i; - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - if(!entrys) - reply(getTextBot(), user, "NS_TABLE_NONE"); - table_free(table); -} diff --git a/src/cmd_neonserv_op.c b/src/cmd_neonserv_op.c deleted file mode 100644 index 6bf3b28..0000000 --- a/src/cmd_neonserv_op.c +++ /dev/null @@ -1,93 +0,0 @@ -/* cmd_neonserv_op.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, struct Event *event, char *nicks); - -struct neonserv_cmd_op_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nicks; -}; - -CMD_BIND(neonserv_cmd_op) { - struct neonserv_cmd_op_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->nicks = strdup(merge_argv(argv, 0, argc)); - get_userlist_if_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->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, struct Event *event, char *nicks) { - int total_users = 0, done_users = 0; - struct UserNode *cuser; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - char *a, *b = nicks; - do { - a = strstr(b, " "); - if(a) *a = '\0'; - total_users++; - cuser = searchUserByNick(b); - if(!cuser) { - //check for an invisible user - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(!stricmp(chanuser->user->nick, b)) { - cuser = chanuser->user; - break; - } - } - if(!cuser) continue; - } else { - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - } - done_users++; - if(chanuser->flags & CHANUSERFLAG_OPPED) continue; - modeBufferOp(modeBuf, b); - if(a) { - b = a+1; - } - } while(a); - freeModeBuffer(modeBuf); - if(done_users == total_users) - 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/src/cmd_neonserv_opall.c b/src/cmd_neonserv_opall.c deleted file mode 100644 index b6bdacc..0000000 --- a/src/cmd_neonserv_opall.c +++ /dev/null @@ -1,78 +0,0 @@ -/* cmd_neonserv_opall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] "force" -* 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, struct Event *event, char *nickmask); - -struct neonserv_cmd_opall_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nickmask; -}; - -CMD_BIND(neonserv_cmd_opall) { - if(!argc || strcmp(argv[0], "FORCE")) { - reply(getTextBot(), user, "NS_OPALL_SECURITY", chan->name); - return; - } - struct neonserv_cmd_opall_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - if(argc > 1) { - cache->nickmask = strdup(argv[1]); - } else - cache->nickmask = NULL; - get_userlist_if_invisible(chan, neonserv_cmd_opall_userlist_lookup, cache); -} - -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->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, struct Event *event, char *nickmask) { - int done_users = 0; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - if(chanuser->flags & CHANUSERFLAG_OPPED) continue; - modeBufferOp(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(textclient, user, "NS_OPALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_oplog.c b/src/cmd_neonserv_oplog.c deleted file mode 100644 index 9cf412b..0000000 --- a/src/cmd_neonserv_oplog.c +++ /dev/null @@ -1,57 +0,0 @@ -/* cmd_neonserv_oplog.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] time -* argv[1-*] match -*/ - -CMD_BIND(neonserv_cmd_oplog) { - char *str_match; - int duration = (argc ? strToTime(user, argv[0]) : 0); - if(argc > (duration ? 1 : 0)) - str_match = merge_argv(argv, (duration ? 1 : 0), argc); - else - str_match = ""; - if(!duration) duration = (60*60*24); - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `godlog_time`, `user_user`, `channel_name`, `godlog_cmd` FROM `godlog` LEFT JOIN `channels` ON `godlog_cid` = `channel_id` LEFT JOIN `users` ON `godlog_uid` = `user_id` WHERE `godlog_time` > '%lu' ORDER BY `godlog_time` ASC", ((unsigned long) time(0) - duration)); - res = mysql_use(); - int skip = mysql_num_rows(res) - 100; - int count = 0; - char timeBuf[50]; - struct tm *timeinfo; - time_t event_time; - if(skip < 0) skip = 0; - reply(getTextBot(), user, "NS_EVENTS_HEADER"); - while ((row = mysql_fetch_row(res)) != NULL) { - if(skip) { - skip--; - continue; - } - if(*str_match && match(str_match, row[3])) continue; - count++; - event_time = (time_t) atol(row[0]); - timeinfo = localtime(&event_time); - strftime(timeBuf, 80, "%X %x", timeinfo); - reply(getTextBot(), user, "[%s] [%s%s%s]: %s", timeBuf, row[1], (row[2] ? ":" : ""), (row[2] ? row[2] : ""), row[3]); - } - reply(getTextBot(), user, "NS_TABLE_COUNT", count); -} diff --git a/src/cmd_neonserv_peek.c b/src/cmd_neonserv_peek.c deleted file mode 100644 index 51de508..0000000 --- a/src/cmd_neonserv_peek.c +++ /dev/null @@ -1,89 +0,0 @@ -/* cmd_neonserv_peek.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no parameters -*/ -static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup); -static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan); - -struct neonserv_cmd_peek_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; -}; - -CMD_BIND(neonserv_cmd_peek) { - struct neonserv_cmd_peek_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - get_userlist_if_invisible(chan, neonserv_cmd_peek_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup) { - struct neonserv_cmd_peek_cache *cache = data; - neonserv_cmd_peek_async1(cache->client, cache->textclient, cache->user, chan); - free(cache); -} - -static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan) { - reply(textclient, user, "NS_PEEK_HEADER", chan->name); - reply(textclient, user, "NS_PEEK_TOPIC", chan->topic); - char tmpStr[MAXLEN]; - getModeString(chan->modes, tmpStr); - reply(textclient, user, "NS_PEEK_MODES", tmpStr); - struct ChanUser *chanuser; - int with_halfops = get_int_field("General.have_halfop"); - int op_count = 0, halfop_count = 0, voice_count = 0, normal_count = 0, invi_count = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(chanuser->flags & CHANUSERFLAG_OPPED) - op_count++; - else if(with_halfops && (chanuser->flags & CHANUSERFLAG_HALFOPPED)) - halfop_count++; - else if(chanuser->flags & CHANUSERFLAG_VOICED) - voice_count++; - else if(chanuser->flags & CHANUSERFLAG_INVISIBLE) - invi_count++; - else - normal_count++; - } - if(with_halfops) - reply(textclient, user, "NS_PEEK_USERS_HALFOP", op_count+halfop_count+voice_count+invi_count+normal_count, op_count, halfop_count, voice_count, normal_count, invi_count); - else - reply(textclient, user, "NS_PEEK_USERS", op_count+voice_count+invi_count+normal_count, op_count, voice_count, normal_count, invi_count); - int tmpStrPos = 0; - int headerlen = 10 + strlen(user->nick); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(chanuser->flags & CHANUSERFLAG_OPPED) { - if(tmpStrPos + headerlen + strlen(chanuser->user->nick) + 2 >= 512) { - //clear buffer - reply(textclient, user, "%s", tmpStr); - tmpStrPos = 0; - } - tmpStrPos += sprintf(tmpStr + tmpStrPos, (tmpStrPos ? ", %s" : "%s"), chanuser->user->nick); - } - } - if(tmpStrPos) { - reply(textclient, user, "%s", tmpStr); - } -} diff --git a/src/cmd_neonserv_recover.c b/src/cmd_neonserv_recover.c deleted file mode 100644 index f48a8c5..0000000 --- a/src/cmd_neonserv_recover.c +++ /dev/null @@ -1,76 +0,0 @@ -/* cmd_neonserv_recover.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - channel -*/ -CMD_BIND(neonserv_cmd_recover) { - MYSQL_RES *res; - MYSQL_ROW row, row2; - char *channel = argv[0]; - if(!is_valid_chan(channel)) { - reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); - return; - } - printf_mysql_query("SELECT `botid`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick); - return; - } - int chanid; - printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - chanid = atoi(row[0]); - } else { - reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); - return; - } - printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid); - res = mysql_use(); - int botid = 0; - char *bottrigger; - while ((row = mysql_fetch_row(res)) != NULL) { - //check channel count - printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]); - row2 = mysql_fetch_row(mysql_use()); - if(atoi(row2[0]) < atoi(row[1])) { - botid = atoi(row[0]); - bottrigger = row[2]; - break; - } - } - if(!botid) { - reply(getTextBot(), user, "NS_REGISTER_FULL"); - return; - } - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - putsock(bot, "JOIN %s", channel); - } else - 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/src/cmd_neonserv_rename.c b/src/cmd_neonserv_rename.c deleted file mode 100644 index 9b87be4..0000000 --- a/src/cmd_neonserv_rename.c +++ /dev/null @@ -1,68 +0,0 @@ -/* cmd_neonserv_rename.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] old auth -* argv[1] new auth -*/ - -struct neonserv_cmd_rename_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *oldauth, *newauth; -}; - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_rename_auth_lookup); -static void neonserv_cmd_rename_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *oldauth, char *newauth); - -CMD_BIND(neonserv_cmd_rename) { - struct neonserv_cmd_rename_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->oldauth = strdup(argv[0]); - cache->newauth = strdup(argv[1]); - lookup_authname(argv[1], neonserv_cmd_rename_auth_lookup, cache); -} - -static AUTHLOOKUP_CALLBACK(neonserv_cmd_rename_auth_lookup) { - struct neonserv_cmd_rename_cache *cache = data; - if(!exists) { - //AUTH_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->newauth); - } else - neonserv_cmd_rename_async1(cache->client, cache->textclient, cache->user, cache->event, cache->oldauth, auth); - free(cache->oldauth); - free(cache->newauth); - free(cache); -} - -static void neonserv_cmd_rename_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *oldauth, char *newauth) { - if(renameAccount(oldauth, newauth)) { - reply(textclient, user, "NS_RENAME_DONE", oldauth, newauth); - } else { - reply(textclient, user, "NS_RENAME_FAIL", oldauth); - } -} diff --git a/src/cmd_neonserv_resync.c b/src/cmd_neonserv_resync.c deleted file mode 100644 index 7c60a6e..0000000 --- a/src/cmd_neonserv_resync.c +++ /dev/null @@ -1,167 +0,0 @@ -/* cmd_neonserv_resync.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - (optional) usermask -* argv[1] - (optional) min access -* argv[2] - (optional) max access -* argv[1/3] - (optional) FORCE (override NoAutoOp) -*/ -static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup); -static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop); - -struct neonserv_cmd_resync_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - char *usermask; - int min_access; - int max_access; - char override_noautoop; -}; - -CMD_BIND(neonserv_cmd_resync) { - int min_access = 0, max_access = 500; - char *usermask = NULL; - char override_noautoop = 0; - if(argc > 0) { - usermask = argv[0]; - if(argc > 2) { - min_access = atoi(argv[1]); - max_access = atoi(argv[2]); - if(argc > 3) - override_noautoop = (!stricmp(argv[3], "FORCE") ? 1 : 0); - } else if(argc > 1) - override_noautoop = (!stricmp(argv[1], "FORCE") ? 1 : 0); - } - struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->usermask = (usermask ? strdup(usermask) : NULL); - cache->min_access = min_access; - cache->max_access = max_access; - cache->override_noautoop = override_noautoop; - get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) { - struct neonserv_cmd_resync_cache *cache = data; - neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access, cache->override_noautoop); - if(cache->usermask) - free(cache->usermask); - free(cache); -} - -static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop) { - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - int i; - int resync_op = 1; - int with_halfop = get_int_field("General.have_halfop"); - int resync_halfop = with_halfop; - int resync_voice = 1; - if(usermask && usermask[0] == '@') { - resync_voice = 0; - resync_halfop = 0; - usermask++; - if(!*usermask) usermask = NULL; - } else if(usermask && with_halfop && usermask[0] == 'h') { - resync_op = 0; - resync_voice = 0; - usermask++; - if(!*usermask) usermask = NULL; - } else if(usermask && usermask[0] == '+') { - resync_op = 0; - resync_halfop = 0; - usermask++; - if(!*usermask) usermask = NULL; - } - struct ChanUser *chanuser; - int db_enfops, db_enfhalfop, db_enfvoice; - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_gethalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - row = mysql_fetch_row(mysql_use()); - if(row[0] == NULL || row[1] == NULL) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_gethalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); - defaults = mysql_fetch_row(mysql_use()); - } - db_enfops = atoi((row[0] ? row[0] : defaults[0])); - db_enfvoice = atoi((row[1] ? row[1] : defaults[1])); - db_enfhalfop = (with_halfop ? atoi((row[2] ? row[2] : defaults[2])) : 0); - printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id); - res = mysql_use(); - char *db_users[mysql_num_rows(res)]; - int db_access[mysql_num_rows(res)]; - int db_flags[mysql_num_rows(res)]; - int db_count = 0; - while ((row = mysql_fetch_row(res)) != NULL) { - db_users[db_count] = row[1]; - db_access[db_count] = atoi(row[0]); - db_flags[db_count] = atoi(row[2]); - db_count++; - } - int caccess, cflags; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - caccess = 0; - cflags = 0; - if((chanuser->user->flags & USERFLAG_ISAUTHED)) { - for(i = 0; i < db_count; i++) { - if(!stricmp(db_users[i], chanuser->user->auth)) { - caccess = db_access[i]; - cflags = db_flags[i]; - if(cflags & DB_CHANUSER_SUSPENDED) - caccess = 0; - break; - } - } - } - if((usermask && *usermask && match(usermask, chanuser->user->nick)) || caccess < min_access || caccess > max_access) continue; - if(caccess >= db_enfops) { - if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) - modeBufferOp(modeBuf, chanuser->user->nick); - } else if(with_halfop && caccess >= db_enfhalfop) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDeop(modeBuf, chanuser->user->nick); - if(!(chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) - modeBufferHalfop(modeBuf, chanuser->user->nick); - } else if(caccess >= db_enfvoice) { - if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDeop(modeBuf, chanuser->user->nick); - if((chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDehalfop(modeBuf, chanuser->user->nick); - if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) - modeBufferVoice(modeBuf, chanuser->user->nick); - } else { - if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDeop(modeBuf, chanuser->user->nick); - if((chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDehalfop(modeBuf, chanuser->user->nick); - if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) - modeBufferDevoice(modeBuf, chanuser->user->nick); - } - - } - freeModeBuffer(modeBuf); - reply(textclient, user, "NS_RESYNC_DONE", chan->name); -} diff --git a/src/cmd_neonserv_search.c b/src/cmd_neonserv_search.c deleted file mode 100644 index 2cefe55..0000000 --- a/src/cmd_neonserv_search.c +++ /dev/null @@ -1,175 +0,0 @@ -/* cmd_neonserv_search.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -#define CMD_SEARCH_FLAG_HAS_NODELETE 0x001 -#define CMD_SEARCH_FLAG_NOT_NODELETE 0x002 -#define CMD_SEARCH_FLAG_HAS_SUSPENDED 0x004 -#define CMD_SEARCH_FLAG_NOT_SUSPENDED 0x008 -#define CMD_SEARCH_FLAG_IS_JOINED 0x010 -#define CMD_SEARCH_FLAG_NOT_JOINED 0x020 -#define CMD_SEARCH_FLAG_IS_OPPED 0x040 -#define CMD_SEARCH_FLAG_NOT_OPPED 0x080 -#define CMD_SEARCH_FLAG_IS_VOICED 0x100 -#define CMD_SEARCH_FLAG_NOT_VOICED 0x200 -#define CMD_SEARCH_FLAG_STATES 0x3f0 - -struct neonserv_cmd_search_criteria { - char *name; - char *registrar; - char *onchan; - unsigned int flags : 16; - unsigned int unvisited; - unsigned int registered; - unsigned int limit : 16; -}; - -CMD_BIND(neonserv_cmd_search) { - //ok parse the criterias - struct neonserv_cmd_search_criteria criteria; - memset(&criteria, 0, sizeof(criteria)); - criteria.limit = 50; - int i, show_chans = 0, positive; - if(!stricmp(argv[0], "print")) { - show_chans = 1; - } - for(i = 1; i < argc; i += 2) { - if(argc <= i+1) { - reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT"); - return; - } - if(!stricmp(argv[i], "name")) criteria.name = argv[i+1]; - else if(!stricmp(argv[i], "registrar")) criteria.registrar = argv[i+1]; - else if(!stricmp(argv[i], "onchan")) criteria.onchan = argv[i+1]; - else if(!stricmp(argv[i], "unvisited")) criteria.unvisited = strToTime(user, argv[i+1]); - else if(!stricmp(argv[i], "registered")) criteria.registered = strToTime(user, argv[i+1]); - else if(!stricmp(argv[i], "flags")) { - if(argv[i+1][0] == '+') { - positive = 1; - argv[i+1]++; - } else if(argv[i+1][0] == '-') { - positive = 0; - argv[i+1]++; - } else - positive = 1; - if(!stricmp(argv[i+1], "nodelete")) { - if(positive) - criteria.flags |= CMD_SEARCH_FLAG_HAS_NODELETE; - else - criteria.flags |= CMD_SEARCH_FLAG_NOT_NODELETE; - } else if(!stricmp(argv[i+1], "suspended")) { - if(positive) - criteria.flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED; - else - criteria.flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED; - } - } - else if(!stricmp(argv[i], "state")) { - if(argv[i+1][0] == '+') { - positive = 1; - argv[i+1]++; - } else if(argv[i+1][0] == '-') { - positive = 0; - argv[i+1]++; - } else - positive = 1; - if(!stricmp(argv[i+1], "joined")) { - if(positive) - criteria.flags |= CMD_SEARCH_FLAG_IS_JOINED; - else - criteria.flags |= CMD_SEARCH_FLAG_NOT_JOINED; - } else if(!stricmp(argv[i+1], "opped")) { - if(positive) - criteria.flags |= CMD_SEARCH_FLAG_IS_OPPED; - else - criteria.flags |= CMD_SEARCH_FLAG_NOT_OPPED; - } else if(!stricmp(argv[i+1], "voiced")) { - if(positive) - criteria.flags |= CMD_SEARCH_FLAG_IS_VOICED; - else - criteria.flags |= CMD_SEARCH_FLAG_NOT_VOICED; - } - } - else if(!stricmp(argv[i], "limit")) { - criteria.limit = atoi(argv[i+1]); - } - } - int matches = 0; - reply(getTextBot(), user, "NS_SEARCH_HEADER"); - MYSQL_RES *res, *res2; - MYSQL_ROW row, row2; - printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `bots` ON `bots`.`id` = `botid` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botclass` = '%d' AND `active` = '1'", client->botid); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(show_chans && matches == criteria.limit) { - //too many - break; - } - if(criteria.name && match(criteria.name, row[0])) continue; - if(criteria.registrar && row[1] && match(criteria.registrar, row[1])) continue; - if(criteria.unvisited) { - printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]); - res2 = mysql_use(); - row2 = mysql_fetch_row(res2); - if(!row2) continue; - if((time(0) - atoi(row2[0])) < criteria.unvisited) continue; - } - if(criteria.registered && (time(0) - atoi(row[2])) < criteria.registered) continue; - - if((criteria.flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue; - if((criteria.flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue; - if((criteria.flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue; - if((criteria.flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue; - if((criteria.flags & CMD_SEARCH_FLAG_STATES) || criteria.onchan) { - struct ChanNode *channel = getChanByName(row[0]); - if(criteria.onchan) { - if(!channel) continue; - struct ChanUser *chanuser = NULL; - for(chanuser = getChannelUsers(channel, NULL); chanuser; chanuser = getChannelUsers(channel, chanuser)) { - if(!match(criteria.onchan, chanuser->user->nick)) break; - } - if(!chanuser) continue; - } - if((criteria.flags & CMD_SEARCH_FLAG_IS_JOINED) && !channel) continue; - if((criteria.flags & CMD_SEARCH_FLAG_NOT_JOINED) && channel) continue; - if(channel && (criteria.flags & (CMD_SEARCH_FLAG_IS_OPPED | CMD_SEARCH_FLAG_NOT_OPPED | CMD_SEARCH_FLAG_IS_VOICED | CMD_SEARCH_FLAG_NOT_VOICED))) { - int flags = 0; - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->botid == client->botid) { - struct ChanUser *chanuser = getChanUser(bot->user, channel); - if(chanuser) { - flags = chanuser->flags; - break; - } - } - } - if((criteria.flags & CMD_SEARCH_FLAG_IS_OPPED) && !(flags & CHANUSERFLAG_OPPED)) continue; - if((criteria.flags & CMD_SEARCH_FLAG_NOT_OPPED) && (flags & CHANUSERFLAG_OPPED)) continue; - if((criteria.flags & CMD_SEARCH_FLAG_IS_VOICED) && !(flags & CHANUSERFLAG_VOICED)) continue; - if((criteria.flags & CMD_SEARCH_FLAG_NOT_VOICED) && (flags & CHANUSERFLAG_VOICED)) continue; - } - } - matches++; - //output - if(show_chans) { - reply(getTextBot(), user, "%s", row[0]); - } - } - reply(getTextBot(), user, "NS_TABLE_COUNT", matches); -} diff --git a/src/cmd_neonserv_set.c b/src/cmd_neonserv_set.c deleted file mode 100644 index ec21e44..0000000 --- a/src/cmd_neonserv_set.c +++ /dev/null @@ -1,471 +0,0 @@ -/* cmd_neonserv_set.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -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 -#define NS_VALID_ACCESS 0x04 -#define NS_VALID_NO501 0x08 -#define NS_VALID_OPTIONS 0x10 -#define NS_VALID_NUMERIC 0x20 -#define NS_VALID_BOOLEAN 0x40 -#define NS_VALID_IF_HALFOP 0x80 - -#define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */ -#define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */ - -static const struct { - const char *setting; - const char *chanfield; - unsigned int valid; - void *parameter; -} channel_settings[] = { - {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger}, - {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL}, - {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL}, - {"ADVANCEDTOPIC", "channel_exttopic", NS_VALID_BOOLEAN | NS_HAS_OPT, NULL}, - {"GREETING", "channel_greeting", NS_VALID_STRING, NULL}, - {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL}, - {"USERINFO", "channel_userinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes}, - {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL}, - {"GIVEOPS", "channel_getop", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"GIVEHALFOPS", "channel_gethalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL}, - {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"ENFOPS", "channel_canop", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"ENFHALFOPS", "channel_canhalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL}, - {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"KICK", "channel_cankick", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"BAN", "channel_canban", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"STATICBAN", "channel_staticban", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL}, - {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL}, - {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL}, - {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL}, - {"ADDUSER", "channel_canadd", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"DELUSER", "channel_candel", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"CLVL", "channel_canclvl", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"RESYNC", "channel_canresync", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, - {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL}, - {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, - {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL}, - {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, - {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, - {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"}, - {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit}, - {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete}, - {NULL, NULL, 0, NULL} -}; - -#define MAX_QUERY_LEN 1024 -CMD_BIND(neonserv_cmd_set) { - int i, j; - if(argc && !strcmp(argv[0], "defaults")) { - //reset channel settings - int uaccess = getChannelAccess(user, chan); - if(uaccess < 500) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); - return; - } - } - int seed = 0; - char *tmp; - static char defaultskey[16]; - for(tmp = user->auth; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = chan->name; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - sprintf(defaultskey, "%08x", seed); - if(argc > 1 && !strcmp(argv[1], defaultskey)) { - char query[MAX_QUERY_LEN]; - int querypos = 0; - i = 0; - while(channel_settings[i].setting) { - if(channel_settings[i].chanfield) - querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield); - i++; - } - if(querypos) { - query[querypos-2] = '\0'; - } - 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); - } - } else if(argc && strcmp(argv[0], "help")) { - //find the correct command - i = 0; - j = 0; - char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL); - int with_halfops = get_int_field("General.have_halfop"); - while(channel_settings[i].setting) { - if(!stricmp(channel_settings[i].setting, argv[0]) && (!(channel_settings[i].valid & NS_VALID_IF_HALFOP) || with_halfops)) { - //setting found - if(channel_settings[i].valid & NS_VALID_FUNCTION) { - neonserv_cmd_set_function *func = channel_settings[i].parameter; - func(client, user, chan, event, channel_settings[i].setting, args); - } else { - neonserv_cmd_set_setting(client, user, chan, event, i, args); - } - j = 1; - break; - } - i++; - } - if(j == 0) { - //unknown setting - reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]); - } - } else { - char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64]; - int querypos = 0; - MYSQL_RES *res, *defaults_res; - MYSQL_ROW row, defaults; - struct Table *table; - char *content[2]; - int with_halfops = get_int_field("General.have_halfop"); - i = 0; - j = 0; - while(channel_settings[i].setting) { - if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) { - j++; - i++; - continue; - } - if(channel_settings[i].chanfield) - querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield); - i++; - } - table = table_init(2, i-j, 0); - table_set_bold(table, 0, 1); - printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query); - defaults_res = mysql_use(); - defaults = mysql_fetch_row(defaults_res); - printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - i = 0; - j = 0; - reply(getTextBot(), user, "NS_SET_HEADER", chan->name); - while(channel_settings[i].setting) { - if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) { - i++; - continue; - } - if(channel_settings[i].chanfield) { - j++; - 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, event, NULL, NULL); - } else - org_value = "0"; - value = org_value; - if(channel_settings[i].valid & NS_VALID_BOOLEAN) { - if(!strcmp(value, "0")) - value = get_language_string(user, "NS_SET_OFF"); - else - value = get_language_string(user, "NS_SET_ON"); - } - strcpy(query, value); - querypos = strlen(query); - if(channel_settings[i].valid & NS_HAS_OPT) { - sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value); - tmp = get_language_string(user, nameBuf); - if(tmp) { - querypos += sprintf(query+querypos, " - %s", tmp); - } - } - if(argc && channel_settings[i].valid & NS_HAS_HELP) { - sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting); - tmp = get_language_string(user, nameBuf); - if(tmp) { - querypos += sprintf(query+querypos, " - %s", tmp); - } - } - content[0] = (char*)channel_settings[i].setting; - content[1] = query; - table_add(table, content); - i++; - } - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); - } -} - -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 - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row[0] == NULL) { - printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield); - res = mysql_use(); - row = mysql_fetch_row(res); - } - value = row[0]; - if(args) { - //change the channel setting - //check the new argument - int valid = channel_settings[setting].valid; - if(valid & NS_VALID_STRING) { - if(!strcmp(args, "*")) { - args = ""; - } - } - if(valid & NS_VALID_ACCESS) { - int caccess = atoi(args); - int max = ((valid & NS_VALID_NO501) ? 500 : 501); - if(caccess < 0 || caccess > max) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return; - } - int uaccess = getChannelAccess(user, chan); - if(uaccess == 500) uaccess++; - if(atoi(value) > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_CANNOT_SET"); - return; - } - } - if(caccess > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_BADLEVEL"); - return; - } - } - sprintf(nameBuf, "%d", caccess); - args = nameBuf; - } - if(valid & NS_VALID_OPTIONS) { - int options = atoi((char *) channel_settings[setting].parameter); - int coption = atoi(args); - if(coption < 0 || coption >= options) { - reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption); - int i; - int nameBufPos = 0; - if(valid & NS_HAS_OPT) { - for(i = 0; i < options; i++) { - sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i); - reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf)); - } - } else { - for(i = 0; i < options; i++) { - nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i); - } - if(nameBufPos) { - nameBuf[nameBufPos-2] = '\0'; - reply(getTextBot(), user, nameBuf); - } - } - return; - } - } - if(valid & NS_VALID_NUMERIC) { - sprintf(nameBuf, "%d", atoi(args)); - args = nameBuf; - } - if(valid & NS_VALID_BOOLEAN) { - if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) { - args = "0"; - } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) { - args = "1"; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args); - return; - } - } - //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); - } - if(channel_settings[setting].valid & NS_HAS_OPT) { - sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[setting].setting, value); - char *tmp = get_language_string(user, nameBuf); - if(tmp) - reply(getTextBot(), user, "\002%s\002 %s - %s", channel_settings[setting].setting, value, tmp); - else - reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value); - } else - reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value); - if(channel_settings[setting].valid & NS_HAS_HELP) { - sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting); - reply(getTextBot(), user, " %s", get_language_string(user, nameBuf)); - } -} - -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; - MYSQL_ROW row; - printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid); - res = mysql_use(); - row = mysql_fetch_row(res); - trigger = (row[0] ? row[0] : row[1]); - if(argument) { - int uaccess = getChannelAccess(user, chan); - if(uaccess < 500) { - 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); - } - return trigger; -} - -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; - char valueBuf[MAXLEN]; - //get current value - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row[0] == NULL) { - printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - row = mysql_fetch_row(res); - } - value = row[0]; - if(argument) { - //change the channel setting - struct ModeNode *modenode = createModeNode(NULL); - parseModeString(modenode, argument); - getFullModeString(modenode, valueBuf); - value = valueBuf; - printf_mysql_query("UPDATE `channels` SET `channel_modes` = '%s' WHERE `channel_id` = '%d'", escape_string(value), chan->channel_id); - //TODO: set modelock - freeModeNode(modenode); - } - if(setting) { - reply(getTextBot(), user, "\002%s\002 %s", setting, value); - } - return value; -} - -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 - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row[0] == NULL) { - printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - row = mysql_fetch_row(res); - } - value = row[0]; - if(argument) { - //change the channel setting - sprintf(tmp, "%d", atoi(argument)); - argument = tmp; - printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id); - if(strcmp(argument, "0")) - putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument))); - else if(isModeSet(chan->modes, 'l')) - putsock(client, "MODE %s -l", chan->name); - value = argument; - logEvent(event); - } - if(setting) { - reply(getTextBot(), user, "\002%s\002 %s", setting, value); - } - return value; -} - -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; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row[0] == NULL) { - printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - row = mysql_fetch_row(res); - } - value = row[0]; - if(argument && isGodMode(user)) { - //change the channel setting - if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) { - argument = "0"; - } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) { - argument = "1"; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); - 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; - value = argument; - logEvent(event); - } - if(setting) { - reply(getTextBot(), user, "\002%s\002 %s", setting, value); - } - return value; -} - -#undef MAX_QUERY_LEN diff --git a/src/cmd_neonserv_setrank.c b/src/cmd_neonserv_setrank.c deleted file mode 100644 index f0c20f7..0000000 --- a/src/cmd_neonserv_setrank.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cmd_neonserv_setrank.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] rank id -* argv[1] setting -* argv[2-*] value -*/ - -static void neonserv_cmd_setrank_name(struct UserNode *user, int rank_id, char *current, char *value); -static void neonserv_cmd_setrank_info(struct UserNode *user, int rank_id, char *current, char *value); -static void neonserv_cmd_setrank_access(struct UserNode *user, int rank_id, char *current, char *value); -static void neonserv_cmd_setrank_order(struct UserNode *user, int rank_id, char *current, char *value); - -CMD_BIND(neonserv_cmd_setrank) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `rank_id`, `rank_name`, `rank_info`, `rank_access`, `rank_order` FROM `support_ranks` WHERE `rank_id` = '%s'", escape_string(argv[0])); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(getTextBot(), user, "NS_SETRANK_NOT_FOUND", argv[0]); - return; - } - if(argc < 2) { - reply(getTextBot(), user, "NS_SETRANK_HEAD", row[0]); - reply(getTextBot(), user, "\002NAME \002 %s", row[1]); - reply(getTextBot(), user, "\002INFO \002 %s", row[2]); - reply(getTextBot(), user, "\002ACCESS \002 %s", row[3]); - reply(getTextBot(), user, "\002ORDER \002 %s", row[4]); - } else { - char *value = NULL; - if(argc > 2) { - value = merge_argv(argv, 2, argc); - } - if(!stricmp(argv[1], "name")) - neonserv_cmd_setrank_name(user, atoi(row[0]), row[1], value); - else if(!stricmp(argv[1], "info")) - neonserv_cmd_setrank_info(user, atoi(row[0]), row[2], value); - else if(!stricmp(argv[1], "access")) - neonserv_cmd_setrank_access(user, atoi(row[0]), row[3], value); - else if(!stricmp(argv[1], "order")) - neonserv_cmd_setrank_order(user, atoi(row[0]), row[4], value); - else - reply(getTextBot(), user, "NS_SETRANK_UNKNOWN_SETTING", row[1]); - } -} - -static void neonserv_cmd_setrank_name(struct UserNode *user, int rank_id, char *current, char *value) { - if(value && stricmp(value, current)) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `rank_id` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(value)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - reply(getTextBot(), user, "NS_ADDRANK_EXISTS", value); - return; - } - printf_mysql_query("UPDATE `support_ranks` SET `rank_name` = '%s' WHERE `rank_id` = '%d'", escape_string(value), rank_id); - current = value; - } - reply(getTextBot(), user, "\002NAME\002 %s", current); -} - -static void neonserv_cmd_setrank_info(struct UserNode *user, int rank_id, char *current, char *value) { - if(value && stricmp(value, current)) { - printf_mysql_query("UPDATE `support_ranks` SET `rank_info` = '%s' WHERE `rank_id` = '%d'", escape_string(value), rank_id); - current = value; - } - reply(getTextBot(), user, "\002INFO\002 %s", current); -} - -static void neonserv_cmd_setrank_access(struct UserNode *user, int rank_id, char *current, char *value) { - if(value && stricmp(value, current)) { - int new_access = atoi(value); - if(new_access <= 0 || new_access > 1000) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", new_access); - return; - } - printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_rank` = '%d'", new_access, rank_id); - printf_mysql_query("UPDATE `support_ranks` SET `rank_access` = '%d' WHERE `rank_id` = '%d'", new_access, rank_id); - current = value; - } - reply(getTextBot(), user, "\002ACCESS\002 %s", current); -} - -static void neonserv_cmd_setrank_order(struct UserNode *user, int rank_id, char *current, char *value) { - if(value && stricmp(value, current)) { - int new_order = atoi(value); - if(new_order <= 0 || new_order > 99) { - reply(getTextBot(), user, "NS_SETRANK_ORDER_INVALID", new_order); - return; - } - printf_mysql_query("UPDATE `support_ranks` SET `rank_order` = '%d' WHERE `rank_id` = '%d'", new_order, rank_id); - current = value; - } - reply(getTextBot(), user, "\002ORDER\002 %s", current); -} diff --git a/src/cmd_neonserv_suspend.c b/src/cmd_neonserv_suspend.c deleted file mode 100644 index b6d18b4..0000000 --- a/src/cmd_neonserv_suspend.c +++ /dev/null @@ -1,119 +0,0 @@ -/* cmd_neonserv_suspend.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_suspend) { - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup) { - struct neonserv_cmd_suspend_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid, cflags; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is added - 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)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; - } - } - //suspend - cflags = atoi(row[2]); - if(cflags & DB_CHANUSER_SUSPENDED) { - reply(textclient, user, "NS_SUSPEND_ALREADY", nick); - return; - } - 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; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonserv_topic.c b/src/cmd_neonserv_topic.c deleted file mode 100644 index 76abea6..0000000 --- a/src/cmd_neonserv_topic.c +++ /dev/null @@ -1,157 +0,0 @@ -/* cmd_neonserv_topic.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* ADVANCEDTOPIC enabled -* argv[0] topic id -* argv[1-*] topic -* -* ADVANCEDTOPIC disabled -* argv[0-*] topic -*/ - -#define ADVANCEDTOPIC_MAXID 9 - -CMD_BIND(neonserv_cmd_topic) { - MYSQL_RES *res; - MYSQL_ROW row, default_row = NULL; - int advanced_topic, i; - char *newtopic; - char *a,*b; - - printf_mysql_query("SELECT `channel_exttopic`, `channel_exttopic_topic`, `channel_topicmask`, `channel_enftopic`, `channel_topicsnarf`, `channel_defaulttopic` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[3] || !row[4]) { - printf_mysql_query("SELECT `channel_exttopic`, `channel_enftopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'"); - default_row = mysql_fetch_row(mysql_use()); - } - - if(row[0] == NULL) { - advanced_topic = atoi(default_row[0]); - } else - advanced_topic = atoi(row[0]); - if(argc == 0) { - //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); - if(uaccess >= atoi((row[3] ? row[3] : default_row[1]))) { - //just set the topic - newtopic = merge_argv(argv, 0, argc); - if(uaccess >= atoi((row[4] ? row[4] : default_row[2]))) { - //set the default topic - printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(newtopic), chan->channel_id); - } - putsock(client, "TOPIC %s :%s", chan->name, newtopic); - reply(getTextBot(), user, "NS_TOPIC_DONE", newtopic); - logEvent(event); - return; - } - if(advanced_topic) { - char *advtopics[ADVANCEDTOPIC_MAXID]; - int topic_id = 0; - topic_id = atoi(argv[0]); - if(!topic_id || topic_id > ADVANCEDTOPIC_MAXID) { - reply(getTextBot(), user, "NS_EXTTOPIC_INVALID_ID", argv[0]); - return; - } - //parse topics - i = 0; - b = row[1]; - while((a = strstr(b, "\n")) != NULL) { - *a = '\0'; - if(i == ADVANCEDTOPIC_MAXID-1) break; - advtopics[i++] = b; - b = a+1; - } - advtopics[i++] = b; - for(;i < ADVANCEDTOPIC_MAXID;i++) - advtopics[i] = ""; - if(argc < 2) { - //just show the topic with this id - reply(getTextBot(), user, "NS_EXTTOPIC_TOPICID", topic_id, advtopics[topic_id-1]); - return; - } - newtopic = merge_argv(argv, 1, argc); - if(!strcmp(newtopic, "*")) - newtopic = ""; - advtopics[topic_id-1] = newtopic; - char topiclist[MAXLEN*2]; - topiclist[0] = '\0'; - int topiclistpos = 0; - for(i = 0; i < ADVANCEDTOPIC_MAXID; i++) { - if(topiclistpos + strlen(advtopics[i]) + 2 >= MAXLEN) break; - topiclistpos += sprintf(topiclist+topiclistpos, (i ? "\n%s" : "%s"), advtopics[i]); - } - printf_mysql_query("UPDATE `channels` SET `channel_exttopic_topic` = '%s' WHERE `channel_id` = '%d'", escape_string(topiclist), chan->channel_id); - //now build the new topic and set it... - topiclistpos = 0; - b = row[2]; - char *topicpart, *debugbb; - while((a = strstr(b, "%")) != NULL) { - *a = '\0'; - if(isdigit(a[1]) && a[1] - 48 > 0) { - topicpart = advtopics[a[1] - 49]; - if(isdigit(topicpart[0]) && isdigit(b[strlen(b)-1])) - debugbb = "\002\002"; //double bold to prevent following digits used as color code - else - debugbb = ""; - topiclistpos += sprintf(topiclist + topiclistpos, "%s%s%s", b, debugbb, topicpart); - b = a+2; - } else { - topiclistpos += sprintf(topiclist + topiclistpos, "%s%%", b); - b = a+1; - } - } - topiclistpos += sprintf(topiclist + topiclistpos, "%s", b); - if(topiclistpos > MAXLEN) - 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]; - topiclist[0] = '\0'; - int topiclistpos = 0; - b = row[2]; - char *debugbb; - while((a = strstr(b, "*")) != NULL) { - *a = '\0'; - if(isdigit(newtopic[0]) && isdigit(b[strlen(b)-1])) - debugbb = "\002\002"; //double bold to prevent following digits used as color code - else - debugbb = ""; - topiclistpos += sprintf(topiclist + topiclistpos, "%s%s%s", b, debugbb, newtopic); - b = a+1; - } - topiclistpos += sprintf(topiclist + topiclistpos, "%s", b); - if(topiclistpos > MAXLEN) - topiclist[MAXLEN] = '\0'; - putsock(client, "TOPIC %s :%s", chan->name, topiclist); - reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist); - logEvent(event); - } -} - -#undef ADVANCEDTOPIC_MAXID \ No newline at end of file diff --git a/src/cmd_neonserv_trace.c b/src/cmd_neonserv_trace.c deleted file mode 100644 index eacb67f..0000000 --- a/src/cmd_neonserv_trace.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cmd_neonserv_trace.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -#define NS_TRACE_CRITERIA_AUTHED 0x01 -#define NS_TRACE_CRITERIA_NUMCHAN 0x02 - -struct neonserv_cmd_trace_criteria { - char *mask; - char *nick; - char *ident; - char *host; - char *account; - unsigned int flags : 4; - unsigned int authed : 1; - unsigned int used_channel : 5; //32 max - char *channel[10]; - unsigned int numchannels; - unsigned int limit : 16; -}; - -CMD_BIND(neonserv_cmd_trace) { - //ok parse the criterias - struct neonserv_cmd_trace_criteria *criteria = malloc(sizeof(*criteria)); - if (!criteria) { - perror("malloc() failed"); - return; - } - memset(criteria, 0, sizeof(*criteria)); - criteria->limit = 50; - int i, show_user = 0; - if(!stricmp(argv[0], "print")) { - show_user = 1; - } - for(i = 1; i < argc; i += 2) { - if(argc <= i+1) { - reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT"); - return; - } - if(!stricmp(argv[i], "mask")) criteria->mask = argv[i+1]; - else if(!stricmp(argv[i], "nick")) criteria->nick = argv[i+1]; - else if(!stricmp(argv[i], "ident")) criteria->ident = argv[i+1]; - else if(!stricmp(argv[i], "host")) criteria->host = argv[i+1]; - else if(!stricmp(argv[i], "account")) criteria->account = argv[i+1]; - else if(!stricmp(argv[i], "authed")) { - if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) { - criteria->authed = 1; - } else if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) { - criteria->authed = 0; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[i+1]); - return; - } - criteria->flags |= NS_TRACE_CRITERIA_AUTHED; - } - else if(!stricmp(argv[i], "channel")) criteria->channel[criteria->used_channel++] = argv[i+1]; - else if(!stricmp(argv[i], "numchannels")) { - criteria->numchannels = atoi(argv[i+1]); - criteria->flags |= NS_TRACE_CRITERIA_NUMCHAN; - } - else if(!stricmp(argv[i], "limit")) { - criteria->limit = atoi(argv[i+1]); - } - } - char tmp[MAXLEN]; - int matches = 0; - struct UserNode *cuser; - reply(getTextBot(), user, "NS_TRACE_HEADER"); - for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) { - if(show_user && matches == criteria->limit) { - //too many - break; - } - if(criteria->mask) { - sprintf(tmp, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(match(criteria->mask, tmp)) continue; - } - if(criteria->nick && match(criteria->nick, cuser->nick)) continue; - if(criteria->ident && match(criteria->ident, cuser->ident)) continue; - if(criteria->host && match(criteria->host, cuser->host)) continue; - if(criteria->account && (!(cuser->flags & USERFLAG_ISAUTHED) || match(criteria->account, cuser->auth))) continue; - if((criteria->flags & NS_TRACE_CRITERIA_AUTHED) && (criteria->authed ^ (cuser->flags & USERFLAG_ISAUTHED))) continue; - if((criteria->flags & NS_TRACE_CRITERIA_NUMCHAN)) { - int ccount = 0; - struct ChanUser *chanuser; - for(chanuser = getUserChannels(cuser, NULL); chanuser; chanuser = getUserChannels(cuser, chanuser)) - ccount++; - if(ccount < criteria->numchannels) - continue; - } - matches++; - //output - if(show_user) { - reply(getTextBot(), user, "%s!%s@%s %s", cuser->nick, cuser->ident, cuser->host, ((cuser->flags & USERFLAG_ISAUTHED) ? cuser->auth : "*")); - } - } - reply(getTextBot(), user, "NS_TABLE_COUNT", matches); -} diff --git a/src/cmd_neonserv_trim.c b/src/cmd_neonserv_trim.c deleted file mode 100644 index 65a0e73..0000000 --- a/src/cmd_neonserv_trim.c +++ /dev/null @@ -1,158 +0,0 @@ -/* cmd_neonserv_trim.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] target (format: minaccess-maxaccess/users/bans) -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_trim) { - if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 0)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; - } - } - int min_access, max_access; - int duration = strToTime(user, argv[1]); - if(duration < 30) { - reply(getTextBot(), user, "NS_TRIM_DURATION_TOO_SHORT", 30); - return; - } - if(!stricmp(argv[0], "users")) { - min_access = 1; - max_access = getChannelAccess(user, chan) - 1; - } else if(!stricmp(argv[0], "bans")) { - if(!checkChannelAccess(user, chan, "channel_staticban", 0)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_ACCESS_DENIED"); - return; - } - } - MYSQL_RES *res; - MYSQL_ROW row; - char nameBuf[20]; - printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d' AND `ban_triggered` < %d", chan->channel_id, (int) (time(0) - duration)); - res = mysql_use(); - int bancount = mysql_num_rows(res); - struct ModeBuffer *modenode = initModeBuffer(client, chan); - while ((row = mysql_fetch_row(res)) != NULL) { - if(strcmp(row[2], "0")) { - sprintf(nameBuf, "ban_%s", row[1]); - timeq_del_name(nameBuf); - } - printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); - modeBufferUnban(modenode, row[0]); - } - freeModeBuffer(modenode); - char timeBuf[MAXLEN]; - reply(getTextBot(), user, "NS_TRIM_BAN_DONE", bancount, chan->name, timeToStr(user, duration, 3, timeBuf)); - if(bancount) - logEvent(event); - return; - } else { - char *seperator = strstr(argv[0], "-"); - if(seperator) { - *seperator = '\0'; - seperator++; - min_access = atoi(argv[0]); - max_access = atoi(seperator); - if(max_access < min_access) { - reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access); - return; - } - } else { - min_access = atoi(argv[0]); - max_access = min_access; - } - if(max_access >= getChannelAccess(user, chan)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_NO_ACCESS"); - return; - } - } - } - struct neonserv_cmd_trim_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - 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_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->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, struct Event *event, int min_access, int max_access, int duration) { - MYSQL_RES *res; - MYSQL_ROW row; - int trim_count = 0, is_here; - struct ChanUser *chanuser; - printf_mysql_query("SELECT `chanuser_seen`, `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(!strcmp(row[0], "0") || time(0) - atoi(row[0]) >= duration) { - //check if the user is currently in the channel - 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(!is_here) { - //delete the user - trim_count++; - printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[2]); - } - } - } - 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/src/cmd_neonserv_unban.c b/src/cmd_neonserv_unban.c deleted file mode 100644 index f88033b..0000000 --- a/src/cmd_neonserv_unban.c +++ /dev/null @@ -1,145 +0,0 @@ -/* cmd_neonserv_unban.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nick[,*auth[,*!*@mask[...]]] -*/ -struct neonserv_cmd_unban_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct ChanNode *chan; - struct Event *event; - struct ModeBuffer *modeBuf; - int provided_masks, done_masks, pending_whos, unbanned_masks; -}; - -static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup); -static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user); -static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask); -static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache); - -CMD_BIND(neonserv_cmd_unban) { - char *mask, *nextmask; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - nextmask = merge_argv_char(argv, 0, argc, ','); - struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->chan = chan; - cache->event = event; - cache->modeBuf = modeBuf; - cache->done_masks = 0; - cache->provided_masks = 0; - cache->unbanned_masks = 0; - while((mask = nextmask)) { - nextmask = strstr(mask, ","); - if(nextmask) { - *nextmask = '\0'; - nextmask++; - } - cache->provided_masks++; - if(is_valid_nick(mask)) { - struct UserNode *cuser = getUserByNick(mask); - if(!cuser) { - cuser = createTempUserMask(mask); - if(!cuser) { - break; //internal bot error - } - cuser->flags |= USERFLAG_ISTMPUSER; - get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache); - cache->pending_whos++; - } else { - neonserv_cmd_unban_nick(cache, cuser); - } - } else { - neonserv_cmd_unban_mask(cache, mask); - } - } - if(!cache->pending_whos) - neonserv_cmd_unban_finish(cache); -} - -static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) { - struct neonserv_cmd_unban_cache *cache = data; - cache->pending_whos--; - if(user) - neonserv_cmd_unban_nick(cache, user); - else - neonserv_cmd_unban_mask(cache, user_nick); - if(!cache->pending_whos) - neonserv_cmd_unban_finish(cache); -} - -static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) { - int matches = 0; - struct BanNode *ban; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); - for(ban = cache->chan->bans; ban; ban = ban->next) { - if(!match(ban->mask, usermask)) { - modeBufferUnban(cache->modeBuf, ban->mask); - cache->unbanned_masks++; - matches++; - } - } - if(matches) - cache->done_masks++; -} - -static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) { - char banmask[NICKLEN+USERLEN+HOSTLEN+3]; - int matches = 0; - struct BanNode *ban; - mask = make_banmask(mask, banmask); - for(ban = cache->chan->bans; ban; ban = ban->next) { - if(!match(mask, ban->mask)) { - modeBufferUnban(cache->modeBuf, ban->mask); - cache->unbanned_masks++; - matches++; - } - } - if(matches) - cache->done_masks++; - else { - for(ban = cache->chan->bans; ban; ban = ban->next) { - if(!match(ban->mask, mask)) { - reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask); - break; - } - } - } -} - -static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) { - freeModeBuffer(cache->modeBuf); - if(cache->done_masks == cache->provided_masks) - reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name); - else - reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick); - if(cache->done_masks) - logEvent(cache->event); - free(cache); -} - diff --git a/src/cmd_neonserv_unbanall.c b/src/cmd_neonserv_unbanall.c deleted file mode 100644 index cff9531..0000000 --- a/src/cmd_neonserv_unbanall.c +++ /dev/null @@ -1,39 +0,0 @@ -/* cmd_neonserv_unbanall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nothing -*/ - -CMD_BIND(neonserv_cmd_unbanall) { - struct ModeBuffer *modeBuf; - int bans = 0; - struct BanNode *ban; - modeBuf = initModeBuffer(client, chan); - for(ban = chan->bans; ban; ban = ban->next) { - modeBufferUnban(modeBuf, ban->mask); - bans++; - } - freeModeBuffer(modeBuf); - if(bans) { - reply(getTextBot(), user, "NS_UNBANALL_DONE", bans, chan->name); - logEvent(event); - } else - reply(getTextBot(), user, "NS_UNBANALL_FAIL", client->user->nick, chan->name); -} diff --git a/src/cmd_neonserv_unbanme.c b/src/cmd_neonserv_unbanme.c deleted file mode 100644 index ac1fa6c..0000000 --- a/src/cmd_neonserv_unbanme.c +++ /dev/null @@ -1,43 +0,0 @@ -/* cmd_neonserv_unbanme.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0-*] nothing -*/ - -CMD_BIND(neonserv_cmd_unbanme) { - struct ModeBuffer *modeBuf; - int bans = 0; - struct BanNode *ban; - modeBuf = initModeBuffer(client, chan); - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); - for(ban = chan->bans; ban; ban = ban->next) { - if(!match(ban->mask, usermask)) { - modeBufferUnban(modeBuf, ban->mask); - bans++; - } - } - freeModeBuffer(modeBuf); - if(bans) { - reply(getTextBot(), user, "NS_UNBANME_DONE", bans, chan->name); - logEvent(event); - } else - reply(getTextBot(), user, "NS_UNBANME_FAIL", client->user->nick, usermask); -} diff --git a/src/cmd_neonserv_unsuspend.c b/src/cmd_neonserv_unsuspend.c deleted file mode 100644 index 4053950..0000000 --- a/src/cmd_neonserv_unsuspend.c +++ /dev/null @@ -1,119 +0,0 @@ -/* cmd_neonserv_unsuspend.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_unsuspend) { - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup) { - struct neonserv_cmd_unsuspend_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid, cflags; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is added - 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)) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(textclient, user, "NS_USER_OUTRANKED", nick); - return; - } - } - //unsuspend - cflags = atoi(row[2]); - if(!(cflags & DB_CHANUSER_SUSPENDED)) { - reply(textclient, user, "NS_SUSPEND_NOT", nick); - return; - } - 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; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonserv_unvisited.c b/src/cmd_neonserv_unvisited.c deleted file mode 100644 index 9d7cda7..0000000 --- a/src/cmd_neonserv_unvisited.c +++ /dev/null @@ -1,108 +0,0 @@ -/* cmd_neonserv_unvisited.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -struct neonserv_cmd_unvisited_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - int duration; - int who_count, matches; -}; - -static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup); -static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration); -static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache); - -CMD_BIND(neonserv_cmd_unvisited) { - int duration = (argc ? strToTime(user, argv[0]) : 60*60*24*7*3); - reply(getTextBot(), user, "NS_SEARCH_HEADER"); - MYSQL_RES *res, *res2; - MYSQL_ROW row, row2; - struct ChanNode *channel; - struct neonserv_cmd_unvisited_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->duration = duration; - cache->who_count = 1; /* small fake to prevent the cache to be freed too early */ - cache->matches = 0; - printf_mysql_query("SELECT `channel_id`, `channel_name`, `channel_nodelete` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - if(!strcmp(row[2], "1")) continue; - printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' AND `chanuser_access` >= 300 ORDER BY `chanuser_seen` DESC LIMIT 1", row[0]); - res2 = mysql_use(); - row2 = mysql_fetch_row(res2); - if(row2 && atol(row2[0]) > (time(0) - duration)) continue; - channel = getChanByName(row[1]); - if(channel) { - cache->who_count++; - channel->channel_id = atoi(row[0]); - get_userlist_with_invisible(channel, neonserv_cmd_unvisited_userlist_lookup, cache); - } else { - reply(getTextBot(), user, "%s", row[1]); - cache->matches++; - } - } - cache->who_count--; //see fix on line 46 - if(cache->who_count == 0) { - neonserv_cmd_unvisited_async2(cache); - } -} - -static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup) { - struct neonserv_cmd_unvisited_cache *cache = data; - if(neonserv_cmd_unvisited_async1(cache->client, cache->textclient, cache->user, chan, cache->duration)) - cache->matches++; - cache->who_count--; - if(cache->who_count == 0) { - neonserv_cmd_unvisited_async2(cache); - } -} - -static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration) { - struct ChanUser *chanuser; - MYSQL_RES *res2; - MYSQL_ROW row2; - int active = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(isBot(chanuser->user)) continue; - if((chanuser->user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_id`, `chanuser_access` FROM `chanusers` LEFT JOIN `users` ON `user_id` = `chanuser_uid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(chanuser->user->auth)); - res2 = mysql_use(); - row2 = mysql_fetch_row(res2); - if(row2 && atoi(row2[1]) >= 300) { - printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", row2[0]); - active = 1; - } - } - } - if(!active) { - reply(textclient, user, "%s", chan->name); - } - return !active; -} - -static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache) { - reply(cache->textclient, cache->user, "NS_TABLE_COUNT", cache->matches); - free(cache); -} diff --git a/src/cmd_neonserv_up.c b/src/cmd_neonserv_up.c deleted file mode 100644 index 930df02..0000000 --- a/src/cmd_neonserv_up.c +++ /dev/null @@ -1,96 +0,0 @@ -/* cmd_neonserv_up.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -struct neonserv_cmd_up_cache { - struct ClientSocket *client; - struct ClientSocket *textclient; - struct UserNode *user; - struct Event *event; -}; - -static void neonserv_cmd_up_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event); -static USERLIST_CALLBACK(neonserv_cmd_up_userlist_lookup); - -CMD_BIND(neonserv_cmd_up) { - if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) { - struct neonserv_cmd_up_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - get_userlist_if_invisible(chan, neonserv_cmd_up_userlist_lookup, cache); - } else { - neonserv_cmd_up_async1(client, getTextBot(), user, chan, event); - } -} - -static USERLIST_CALLBACK(neonserv_cmd_up_userlist_lookup) { - struct neonserv_cmd_up_cache *cache = data; - neonserv_cmd_up_async1(cache->client, cache->textclient, cache->user, chan, cache->event); - free(cache); -} - -static void neonserv_cmd_up_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event) { - struct ChanUser *chanuser = getChanUser(user, chan); - if(!chanuser) { - reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name); - return; - } - check_mysql(); - loadChannelSettings(chan); - MYSQL_RES *res, *default_res; - MYSQL_ROW row, default_row; - int chan_getop, chan_getvoice, caccess; - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); - default_res = mysql_use(); - if ((default_row = mysql_fetch_row(default_res)) == NULL) return; - chan_getop = (row[0] ? atoi(row[0]) : atoi(default_row[0])); - chan_getvoice = (row[1] ? atoi(row[1]) : atoi(default_row[1])); - } else { - chan_getop = atoi(row[0]); - chan_getvoice = atoi(row[1]); - } - caccess = getChannelAccess(user, chan); - 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 - reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name); -} diff --git a/src/cmd_neonserv_upall.c b/src/cmd_neonserv_upall.c deleted file mode 100644 index 0f12379..0000000 --- a/src/cmd_neonserv_upall.c +++ /dev/null @@ -1,73 +0,0 @@ -/* cmd_neonserv_upall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* no arguments -*/ - -CMD_BIND(neonserv_cmd_upall) { - MYSQL_RES *res, *default_res; - MYSQL_ROW row, default_row; - struct ChanUser *chanuser; - int userid, chan_getop, chan_getvoice, caccess; - int botid = client->botid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", user->auth); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) - return; - userid = atoi(row[0]); - printf_mysql_query("SELECT `chanuser_access`, `channel_getop`, `channel_getvoice`, `channel_name`, `channel_id` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d'", userid); - res = mysql_use(); - while ((row = mysql_fetch_row(res)) != NULL) { - chan = getChanByName(row[3]); - if(!chan) continue; - printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%s' AND `botclass` = '%d'", row[4], client->botid); - if (mysql_fetch_row(mysql_use()) == NULL) continue; - if(!(chanuser = getChanUser(user, chan))) continue; - if(!row[1] || !row[2]) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); - default_res = mysql_use(); - if ((default_row = mysql_fetch_row(default_res)) == NULL) return; - chan_getop = (row[1] ? atoi(row[1]) : atoi(default_row[0])); - chan_getvoice = (row[2] ? atoi(row[2]) : atoi(default_row[1])); - } else { - chan_getop = atoi(row[1]); - chan_getvoice = atoi(row[2]); - } - caccess = atoi(row[0]); - int done = 0; - client = getChannelBot(chan, botid); - if(!client) continue; - if(caccess >= chan_getop) { - 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)) { - putsock(client, "MODE %s +v %s", chan->name, user->nick); - done = 1; - } - } - if(done) { - event->chan = chan; - logEvent(event); - } - } -} diff --git a/src/cmd_neonserv_users.c b/src/cmd_neonserv_users.c deleted file mode 100644 index cd8d375..0000000 --- a/src/cmd_neonserv_users.c +++ /dev/null @@ -1,132 +0,0 @@ -/* cmd_neonserv_users.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* argv[0] - usermask -* argv[1] - min access -* argv[2] - max access -*/ -static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup); -static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access); - -struct neonserv_cmd_users_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - char *usermask; - int min_access; - int max_access; -}; - -CMD_BIND(neonserv_cmd_users) { - int min_access = 1, max_access = 500; - char *usermask = NULL; - if(argc > 0) - usermask = argv[0]; - if(argc > 2) { - min_access = atoi(argv[1]); - max_access = atoi(argv[2]); - } - struct neonserv_cmd_users_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->usermask = (usermask ? strdup(usermask) : NULL); - cache->min_access = min_access; - cache->max_access = max_access; - get_userlist_with_invisible(chan, neonserv_cmd_users_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) { - struct neonserv_cmd_users_cache *cache = data; - neonserv_cmd_users_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access); - if(cache->usermask) - free(cache->usermask); - free(cache); -} - -static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) { - MYSQL_RES *res; - MYSQL_ROW row; - int content_count = 0, cflags, is_here, caccess, i; - char seenstr[MAXLEN]; - struct Table *table; - struct ChanUser *chanuser; - printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_seen`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id); - res = mysql_use(); - table = table_init(4, mysql_num_rows(res) + 1, 0); - if(usermask) - reply(textclient, user, "NS_USERS_HEADER_MATCH", chan->name, min_access, max_access, usermask); - else - reply(textclient, user, "NS_USERS_HEADER", chan->name, min_access, max_access); - char *content[4]; - content[0] = get_language_string(user, "NS_USERS_HEADER_ACCESS"); - content[1] = get_language_string(user, "NS_USERS_HEADER_ACCOUNT"); - content[2] = get_language_string(user, "NS_USERS_HEADER_SEEN"); - content[3] = get_language_string(user, "NS_USERS_HEADER_STATE"); - table_add(table, content); - while ((row = mysql_fetch_row(res)) != NULL) { - caccess = atoi(row[0]); - if((!usermask || !match(usermask, row[1])) && caccess >= min_access && caccess <= max_access) { - content[0] = row[0]; - content[1] = row[1]; - is_here = 0; - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, row[1])) { - if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) - is_here = 2; - else { - is_here = 1; - break; - } - } - } - if(is_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 { - timeToStr(user, (time(0) - atoi(row[2])), 2, seenstr); - content[2] = seenstr; //generate time - } - cflags = atoi(row[3]); - if(cflags & DB_CHANUSER_SUSPENDED) - content[3] = get_language_string(user, "NS_USERS_STATE_SUSPENDED"); - else - content[3] = get_language_string(user, "NS_USERS_STATE_NORMAL"); - content_count++; - table_add(table, content); - } - } - //send the table - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(textclient, user, table_lines[i]); - } - if(!content_count) - reply(textclient, user, "NS_TABLE_NONE"); - if(usermask || min_access != 1 || max_access != 500) - reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_MATCH_1" : "NS_USERS_COUNT_MATCH"), table->length - 1, chan->name, content_count); - else - reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_1" : "NS_USERS_COUNT"), table->length - 1, chan->name); - table_free(table); -} diff --git a/src/cmd_neonserv_uset.c b/src/cmd_neonserv_uset.c deleted file mode 100644 index 25a3118..0000000 --- a/src/cmd_neonserv_uset.c +++ /dev/null @@ -1,184 +0,0 @@ -/* cmd_neonserv_uset.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -CMD_BIND(neonserv_cmd_uset) { - MYSQL_RES *res; - MYSQL_ROW row; - loadUserSettings(user); - if(argc > 0) { - if(!stricmp(argv[0], "language")) { - struct language* lang; - if(argc > 1) { - if((lang = get_language_by_tag(argv[1])) == NULL && (lang = get_language_by_name(argv[1])) == NULL) { - lang = user->language; - } else { - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - printf_mysql_query("UPDATE `users` SET `user_lang` = '%s' WHERE `user_id` = '%s'", escape_string(lang->langtag), row[0]); - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`, `user_lang`) VALUES ('%s', '%s')", escape_string(user->auth), escape_string(lang->langtag)); - } - struct UserNode *cuser; - for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) { - if((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth)) - cuser->language = lang; - } - } - } else - lang = user->language; - reply(getTextBot(), user, "\002Language \002%s", lang->langname); - char tmp[MAXLEN]; - int tmppos = 0; - lang = get_default_language(); - tmppos = sprintf(tmp, "%s (%s)", lang->langname, lang->langtag); - printf_mysql_query("SELECT `lang`,`text` FROM `language` WHERE `ident` = 'name'"); - res = mysql_use(); - while((row = mysql_fetch_row(res)) != NULL) { - tmppos += sprintf(tmp + tmppos, ", %s (%s)", row[1], row[0]); - } - reply(getTextBot(), user, " %s", tmp); - } else if(!stricmp(argv[0], "noinvite") && chan) { - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { - reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED"); - return; - } - printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - row = mysql_fetch_row(res); - int noinvite = (row ? 1 : 0); - if(argc > 1) { - if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { - if(noinvite) { - printf_mysql_query("DELETE FROM `noinvite` WHERE `id` = '%s'", row[0]); - noinvite = 0; - } - } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { - if(!noinvite) { - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - } else { - printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth)); - userid = (int) mysql_insert_id(get_mysql_conn()); - } - printf_mysql_query("INSERT INTO `noinvite` (`uid`, `cid`) VALUES ('%d', '%d')", userid, chan->channel_id); - noinvite = 1; - } - } - } - reply(getTextBot(), user, "\002NoInvite \002%s", (noinvite ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - } else if((!stricmp(argv[0], "autoinvite") || !stricmp(argv[0], "noautoop") || !stricmp(argv[0], "info")) && chan) { - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { - reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED"); - return; - } - printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row) { - int flags = atoi(row[0]); - if(!stricmp(argv[0], "autoinvite")) { - int getInvite = 0; - if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite"))) - getInvite = 1; - else if(row[3] && atoi(row[2]) >= atoi(row[3])) - getInvite = 1; - if(getInvite && argc > 1) { - if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { - if(flags & DB_CHANUSER_AUTOINVITE) { - flags &= ~DB_CHANUSER_AUTOINVITE; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); - } - } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { - if(!(flags & DB_CHANUSER_AUTOINVITE)) { - flags |= DB_CHANUSER_AUTOINVITE; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); - } - } - } - if(getInvite) - reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - else - reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS")); - } else if(!stricmp(argv[0], "noautoop")) { - if(argc > 1) { - if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { - if(flags & DB_CHANUSER_NOAUTOOP) { - flags &= ~DB_CHANUSER_NOAUTOOP; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); - } - } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { - if(!(flags & DB_CHANUSER_NOAUTOOP)) { - flags |= DB_CHANUSER_NOAUTOOP; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); - } - } - } - reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - } else if(!stricmp(argv[0], "info")) { - char *infoline; - if(argc > 1) { - infoline = merge_argv(argv, 1, argc); - if(!strcmp(infoline, "*")) - infoline = ""; - printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '%s' WHERE `chanuser_id` = '%s'", escape_string(infoline), row[4]); - } else - infoline = row[1]; - reply(getTextBot(), user, "\002Info \002%s", infoline); - } - } else - reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan); - } else - reply(getTextBot(), user, "NS_USET_UNKNOWN_SETTING", argv[0]); - } else { - //view all options - reply(getTextBot(), user, "NS_USET_GLOBAL"); - reply(getTextBot(), user, "\002Language \002%s", user->language->langname); - if(!chan) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - reply(getTextBot(), user, "NS_USET_CHANNEL"); - printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - row = mysql_fetch_row(res); - reply(getTextBot(), user, "\002NoInvite \002%s", (row ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - row = mysql_fetch_row(res); - if(row) { - int flags = atoi(row[0]); - int getInvite = 0; - if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite"))) - getInvite = 1; - else if(row[3] && atoi(row[2]) >= atoi(row[3])) - getInvite = 1; - if(getInvite) - reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - else - reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS")); - reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); - reply(getTextBot(), user, "\002Info \002%s", row[1]); - } - } -} \ No newline at end of file diff --git a/src/cmd_neonserv_voice.c b/src/cmd_neonserv_voice.c deleted file mode 100644 index 49dfe6c..0000000 --- a/src/cmd_neonserv_voice.c +++ /dev/null @@ -1,93 +0,0 @@ -/* cmd_neonserv_voice.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, struct Event *event, char *nicks); - -struct neonserv_cmd_voice_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nicks; -}; - -CMD_BIND(neonserv_cmd_voice) { - struct neonserv_cmd_voice_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - cache->nicks = strdup(merge_argv(argv, 0, argc)); - get_userlist_if_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->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, struct Event *event, char *nicks) { - int total_users = 0, done_users = 0; - struct UserNode *cuser; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - char *a, *b = nicks; - do { - a = strstr(b, " "); - if(a) *a = '\0'; - total_users++; - cuser = searchUserByNick(b); - if(!cuser) { - //check for an invisible user - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(!stricmp(chanuser->user->nick, b)) { - cuser = chanuser->user; - break; - } - } - if(!cuser) continue; - } else { - chanuser = getChanUser(cuser, chan); - if(!chanuser) continue; - } - done_users++; - if(chanuser->flags & CHANUSERFLAG_VOICED) continue; - modeBufferVoice(modeBuf, b); - if(a) { - b = a+1; - } - } while(a); - freeModeBuffer(modeBuf); - if(done_users == total_users) - 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/src/cmd_neonserv_voiceall.c b/src/cmd_neonserv_voiceall.c deleted file mode 100644 index 779110c..0000000 --- a/src/cmd_neonserv_voiceall.c +++ /dev/null @@ -1,73 +0,0 @@ -/* cmd_neonserv_voiceall.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, struct Event *event, char *nickmask); - -struct neonserv_cmd_voiceall_cache { - struct ClientSocket *client, *textclient; - struct UserNode *user; - struct Event *event; - char *nickmask; -}; - -CMD_BIND(neonserv_cmd_voiceall) { - struct neonserv_cmd_voiceall_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->textclient = getTextBot(); - cache->user = user; - cache->event = event; - if(argc > 0) { - cache->nickmask = strdup(argv[0]); - } else - cache->nickmask = NULL; - get_userlist_if_invisible(chan, neonserv_cmd_voiceall_userlist_lookup, cache); -} - -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->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, struct Event *event, char *nickmask) { - int done_users = 0; - struct ChanUser *chanuser; - struct ModeBuffer *modeBuf; - modeBuf = initModeBuffer(client, chan); - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - if(nickmask && match(nickmask, chanuser->user->nick)) continue; - if(chanuser->flags & CHANUSERFLAG_VOICED) continue; - modeBufferVoice(modeBuf, chanuser->user->nick); - done_users++; - } - freeModeBuffer(modeBuf); - reply(textclient, user, "NS_VOICEALL_DONE", done_users, chan->name); - if(done_users) - logEvent(event); -} diff --git a/src/cmd_neonserv_wipeinfo.c b/src/cmd_neonserv_wipeinfo.c deleted file mode 100644 index 71a1cc8..0000000 --- a/src/cmd_neonserv_wipeinfo.c +++ /dev/null @@ -1,113 +0,0 @@ -/* cmd_neonserv_wipeinfo.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonserv.h" - -/* -* 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, 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; -}; - -CMD_BIND(neonserv_cmd_wipeinfo) { - if(argv[0][0] == '*') { - //we've got an auth - argv[0]++; - neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); - } else { - struct UserNode *cuser = getUserByNick(argv[0]); - if(!cuser) { - cuser = createTempUser(argv[0]); - if(!cuser) { - reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); - return; - } - cuser->flags |= USERFLAG_ISTMPUSER; - } - if(cuser->flags & USERFLAG_ISAUTHED) { - 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) { - perror("malloc() failed"); - return; - } - cache->client = client; - 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); - } - } -} - -static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup) { - struct neonserv_cmd_wipeinfo_cache *cache = data; - if(!user) { - //USER_DOES_NOT_EXIST - reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); - } - else if(!(user->flags & USERFLAG_ISAUTHED)) { - //USER_NOT_AUTHED - reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); - } - else - 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, struct Event *event, char *nick, char *auth) { - //we've got a valid auth now... - MYSQL_RES *res; - MYSQL_ROW row; - int userid; - printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - userid = atoi(row[0]); - //check if the user is already added - 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)) { - 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; - } - } - reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); -} diff --git a/src/cmd_neonspam.h b/src/cmd_neonspam.h deleted file mode 100644 index 9989192..0000000 --- a/src/cmd_neonspam.h +++ /dev/null @@ -1,43 +0,0 @@ -/* cmd_neonspam.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _cmd_neonspam_h -#define _cmd_neonspam_h -#include "main.h" -#include "modcmd.h" -#include "IRCParser.h" -#include "IRCEvents.h" -#include "UserNode.h" -#include "ChanNode.h" -#include "ChanUser.h" -#include "ModeNode.h" -#include "BanNode.h" -#include "ClientSocket.h" -#include "mysqlConn.h" -#include "lang.h" -#include "HandleInfoHandler.h" -#include "WHOHandler.h" -#include "DBHelper.h" -#include "tools.h" -#include "timeq.h" -#include "version.h" -#include "EventLogger.h" -#include "bots.h" -#include "bot_NeonSpam.h" - -CMD_BIND(neonspam_cmd_set); - -#endif \ No newline at end of file diff --git a/src/cmd_neonspam_set.c b/src/cmd_neonspam_set.c deleted file mode 100644 index efaee45..0000000 --- a/src/cmd_neonspam_set.c +++ /dev/null @@ -1,655 +0,0 @@ -/* cmd_neonspam_set.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_neonspam.h" - -typedef char* neonspam_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); -static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); - -static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults; -#define SPAMSERV_SETTINGS_QUERY "`channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_botnet_bantime`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_digit_reaction`, `channel_digit_reaction_duration`" -#define SPAMSERV_SETTINGS_RESET "\ -`channel_scanner` = NULL, \ -`channel_spam_limit` = NULL, \ -`channel_spam_reaction` = NULL, \ -`channel_spam_reaction_duration` = NULL, \ -`channel_spam_except` = NULL, \ -`channel_flood_limit` = NULL, \ -`channel_flood_time` = NULL, \ -`channel_flood_reaction` = NULL, \ -`channel_flood_reaction_duration` = NULL, \ -`channel_flood_except` = NULL, \ -`channel_join_limit` = NULL, \ -`channel_join_time` = NULL, \ -`channel_join_reaction` = NULL, \ -`channel_join_reaction_duration` = NULL, \ -`channel_join_except` = NULL, \ -`channel_botnet_bantime` = NULL, \ -`channel_botnet_except` = NULL, \ -`channel_caps_percent` = NULL, \ -`channel_caps_reaction` = NULL, \ -`channel_caps_reaction_duration` = NULL, \ -`channel_caps_except` = NULL,\ -`channel_digit_percent` = NULL, \ -`channel_digit_reaction` = NULL, \ -`channel_digit_reaction_duration` = NULL, \ -`channel_digit_except` = NULL " - -#define SET_HELP 0x0001 -#define SET_BOOL 0x0002 -#define SET_OPT 0x0004 - -#define SET_SCANOPS 0x0010 -#define SET_SCANVOICE 0x0020 -#define SET_SCANEXCEPT 0x0040 - -#define SET_OPT_MAX 0xff00 -#define SET_OPT_SHIFT 8 - -static const struct { - unsigned int if_flag; - unsigned int indent; - const char *setting; - void *function; - int intparam; - char *charparam; - int flags; -} neonspam_settings[] = { - {0, 0, "Trigger", neonspam_cmd_set_trigger, 0, NULL, SET_HELP}, - - {0, 0, "SpamScan", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_SPAMSCAN, 2, "SpamLimit", neonspam_cmd_set_spamlimit, 0, NULL, SET_HELP}, - {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "SpamReaction", neonspam_cmd_set_reaction, 0, "channel_spam_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, - {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "SpamBanDuration", neonspam_cmd_set_reaction_time, 1, "channel_spam_reaction_duration", 0}, - {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_SPAMEXCINDEX, "channel_spam_except", SET_HELP | SET_SCANEXCEPT}, - - {0, 0, "FloodScan", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_FLOODSCAN, 2, "FloodSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_FLOODSENINDEX, "channel_flood_", SET_HELP}, - {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "FloodReaction", neonspam_cmd_set_reaction, 2, "channel_flood_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, - {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "FloodBanDuration", neonspam_cmd_set_reaction_time, 3, "channel_flood_reaction_duration",0}, - {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_FLOODEXCINDEX, "channel_flood_except", SET_HELP | SET_SCANEXCEPT}, - - {0, 0, "JoinScan", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_JOINSCAN, 2, "JoinSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_JOINSENINDEX, "channel_join_", SET_HELP}, - {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "JoinReaction", neonspam_cmd_set_reaction, 4, "channel_join_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, - {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "JoinBanDuration", neonspam_cmd_set_reaction_time, 5, "channel_join_reaction_duration", 0}, - {SPAMSETTINGS_JOINSCAN, 2, "JoinScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_JOINSCAN, 2, "JoinScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - {SPAMSETTINGS_JOINSCAN, 2, "JoinScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_JOINEXCINDEX, "channel_join_except", SET_HELP | SET_SCANEXCEPT}, - - {0, 0, "BotNetScan", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_BOTNETSCAN, 4, "BotNetBanDuration", neonspam_cmd_set_reaction_time, 6, "channel_botnet_bantime", 0}, - {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - //{SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_BOTNETEXCINDEX, "channel_botnet_except", SET_HELP}, - - {0, 0, "CapsScan", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_CAPSSCAN, 2, "CapsPercent", neonspam_cmd_setpercent, SPAMSETTINGS_CAPSPERCENTINDEX, "channel_caps_percent", SET_HELP}, - {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "CapsReaction", neonspam_cmd_set_reaction, 7, "channel_caps_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, - {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "CapsBanDuration", neonspam_cmd_set_reaction_time, 8, "channel_caps_reaction_duration", 0}, - {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_CAPSEXCINDEX, "channel_caps_except", SET_HELP | SET_SCANEXCEPT}, - - {0, 0, "DigitScan", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN, NULL, SET_BOOL}, - {SPAMSETTINGS_DIGITSCAN, 2, "DigitPercent", neonspam_cmd_setpercent, SPAMSETTINGS_DIGITPERCENTINDEX, "channel_digit_percent", SET_HELP}, - {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "DigitReaction", neonspam_cmd_set_reaction, 9, "channel_digit_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, - {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "DigitBanDuration", neonspam_cmd_set_reaction_time, 10, "channel_digit_reaction_duration", 0}, - {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, - {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, - {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_DIGITEXCINDEX, "channel_digit_except", SET_HELP | SET_SCANEXCEPT}, - - {0, 0, "GlobalScanChanOps", neonspam_cmd_setscanops, 0, NULL, SET_BOOL}, - {0, 0, "GlobalScanVoice", neonspam_cmd_setscanvoice, 0, NULL, SET_BOOL}, - {0, 0, "GlobalScanExcept", neonspam_cmd_setscanexcept, 0, NULL, SET_HELP}, - - {0, 0, NULL, NULL, 0, NULL, 0} -}; - -#define MAX_QUERY_LEN 1024 -CMD_BIND(neonspam_cmd_set) { - int i, j; - loadNeonSpamSettings(chan); - if(argc && !strcmp(argv[0], "defaults")) { - //reset channel settings - int uaccess = getChannelAccess(user, chan); - if(uaccess < 500) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); - return; - } - } - int seed = 0; - char *tmp; - static char defaultskey[16]; - for(tmp = user->auth; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - for(tmp = chan->name; *tmp; tmp++) - seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); - sprintf(defaultskey, "%08x", seed); - if(argc > 1 && !strcmp(argv[1], defaultskey)) { - printf_mysql_query("UPDATE `channels` SET " SPAMSERV_SETTINGS_RESET " WHERE `channel_id` = '%d'", 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); - } - } else if(argc && strcmp(argv[0], "help")) { - //find the correct command - i = 0; - j = 0; - char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL); - neonspam_settings_row = NULL; - neonspam_settings_defaults = NULL; - while(neonspam_settings[i].setting) { - if(!stricmp(neonspam_settings[i].setting, argv[0])) { - //setting found - char valueBuf[MAXLEN], nameBuf[MAXLEN]; - char *value, *optimized_value, *option_help; - neonspam_cmd_set_function *func = neonspam_settings[i].function; - value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, args, valueBuf); - if(value) { - optimized_value = value; - if(neonspam_settings[i].flags & SET_BOOL) { - if(!strcmp(value, "0")) - optimized_value = get_language_string(user, "NS_SET_OFF"); - else if(!strcmp(value, "1")) - optimized_value = get_language_string(user, "NS_SET_ON"); - } - if(neonspam_settings[i].flags & SET_OPT) { - sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value); - option_help = get_language_string(user, nameBuf); - } else - option_help = NULL; - reply(getTextBot(), user, "\002%s\002 %s%s%s", neonspam_settings[i].setting, optimized_value, (option_help ? " - " : ""), (option_help ? option_help : "")); - if(neonspam_settings[i].flags & SET_OPT) { - int maxoption = (neonspam_settings[i].flags & SET_OPT_MAX) >> SET_OPT_SHIFT; - for(j = 0; j < maxoption; j++) { - sprintf(nameBuf, "SS_SET_OPTION_%s_%d", neonspam_settings[i].setting, j); - - reply(getTextBot(), user, " \002%d\002 - %s", j, option_help); - } - } - if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) { - char *tmp; - sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting); - tmp = get_language_string(user, nameBuf); - if(tmp) { - reply(getTextBot(), user, " %s", tmp); - } - } - } - j = 1; - break; - } - i++; - } - if(j == 0) { - //unknown setting - reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]); - } - } else { - char valueBuf[MAXLEN], nameBuf[MAXLEN]; - char *value; - int namePos, boolflag = 0; - MYSQL_RES *res, *defaults_res; - struct Table *table; - char *content[2]; - i = 0; - while(neonspam_settings[i].setting) - i++; - table = table_init(2, i, 0); - table_set_bold(table, 0, 1); - printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_name` = 'defaults'"); - defaults_res = mysql_use(); - neonspam_settings_defaults = mysql_fetch_row(defaults_res); - printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - neonspam_settings_row = mysql_fetch_row(res); - i = -1; - reply(getTextBot(), user, "NS_SET_HEADER", chan->name); - while(neonspam_settings[++i].setting) { - if((chan->spam_settings->flags & (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) != (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) - continue; - if((neonspam_settings[i].if_flag & SPAMSETTINGS_ISTIMEBAN) && !boolflag) - continue; - neonspam_cmd_set_function *func = neonspam_settings[i].function; - value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, NULL, valueBuf); - if(neonspam_settings[i].if_flag & SPAMSETTINGS_SETTIMEBAN) - boolflag = !strcmp(value, "2"); - //TODO: append option or help info - strcpy(valueBuf, value); - if(neonspam_settings[i].flags & SET_BOOL) { - if(!strcmp(value, "0")) - strcpy(valueBuf, get_language_string(user, "NS_SET_OFF")); - else if(!strcmp(value, "1")) - strcpy(valueBuf, get_language_string(user, "NS_SET_ON")); - } - if(neonspam_settings[i].flags & SET_OPT) { - char *tmp; - sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value); - tmp = get_language_string(user, nameBuf); - if(tmp) { - sprintf(valueBuf + strlen(valueBuf), " - %s", tmp); - } - } - if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) { - char *tmp; - sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting); - tmp = get_language_string(user, nameBuf); - if(tmp) { - sprintf(valueBuf + strlen(valueBuf), " - %s", tmp); - } - } - namePos = 0; - for(j = 0; j < neonspam_settings[i].indent; j++) { - nameBuf[namePos++] = ' '; - } - sprintf(nameBuf + namePos, "%s", neonspam_settings[i].setting); - content[0] = nameBuf; - content[1] = valueBuf; - table_add(table, content); - } - char **table_lines = table_end(table); - for(i = 0; i < table->entrys; i++) { - reply(getTextBot(), user, table_lines[i]); - } - table_free(table); - } -} - -static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) { - char *trigger; - //get current trigger - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid); - res = mysql_use(); - row = mysql_fetch_row(res); - trigger = (row[0] ? row[0] : row[1]); - if(argument) { - int uaccess = getChannelAccess(user, chan); - if(uaccess < 500) { - 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); - } - return trigger; -} - -static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { - char *value = ((chan->spam_settings->flags & flag) ? "1" : "0"); - if(argument) { - //binary argument... - if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { - chan->spam_settings->flags &= ~flag; - } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { - chan->spam_settings->flags |= flag; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); - return NULL; - } - char str_flags[50]; - convertNeonSpamSettingsToString(chan->spam_settings->flags, str_flags); - printf_mysql_query("UPDATE `channels` SET `channel_scanner` = '%s' WHERE `channel_id` = '%d' ", str_flags, chan->channel_id); - value = argument; - } - return value; -} - -static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int exceptlvl_index, char *field, char *argument, char *retBuf) { - unsigned int value = chan->spam_settings->exceptlevel[exceptlvl_index]; - if(argument) { - //numeric argument... (access) - int caccess = atoi(argument); - if(caccess < 0 || caccess > 501) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return NULL; - } - int uaccess = getChannelAccess(user, chan); - if(uaccess == 500) uaccess++; - if(value > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_CANNOT_SET"); - return NULL; - } - } - if(caccess > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_BADLEVEL"); - return NULL; - } - } - value = caccess; - chan->spam_settings->exceptlevel[exceptlvl_index] = value; - printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", field, value, chan->channel_id); - } - sprintf(retBuf, "%u", value); - return retBuf; -} - -static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) { - if(argument) { - /* valid options: - * 0/kick - kick - * 1/kickban - kickban - * 2/ban - timed ban - */ - if(!strcmp(argument, "0") || !stricmp(argument, "kick")) { - argument = "0"; - } else if(!strcmp(argument, "1") || !stricmp(argument, "kickban")) { - argument = "1"; - } else if(!strcmp(argument, "2") || !stricmp(argument, "ban")) { - argument = "2"; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_OPTION_STR", argument); - return NULL; - } - printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id); - return argument; - } else { - if(neonspam_settings_row) { - return (neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]); - } else { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - return row[0]; - } - } -} - -static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) { - int duration; - if(argument) { - duration = strToTime(user, argument); - if(duration < 30) { - reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30); - return NULL; - } - printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id); - } else { - if(neonspam_settings_row) { - duration = atoi(neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]); - } else { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - duration = atoi(row[0]); - } - } - timeToStr(user, duration, 3, retBuf); - return retBuf; -} - -static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int percent_index, char *mysqlfield, char *argument, char *retBuf) { - unsigned int value = chan->spam_settings->percent[percent_index]; - if(argument) { - //numeric argument... (access) - value = atoi(argument); - if(value < 0 || value > 100) { - //invalid percent value - reply(getTextBot(), user, "SS_SET_PERCENT", value); - return NULL; - } - chan->spam_settings->percent[percent_index] = value; - printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", mysqlfield, value, chan->channel_id); - } - sprintf(retBuf, "%u", value); - return retBuf; -} - -static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int sensibility_index, char *mysqlfield, char *argument, char *retBuf) { - if(argument) { - //change value - char *delimiter = strstr(argument, ":"); - if(!delimiter) { - //invalid format - reply(getTextBot(), user, "SS_SET_SENSIBILITY", argument); - return NULL; - } - *delimiter = '\0'; - delimiter++; - int amount = atoi(argument); - int timep = atoi(delimiter); - if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) { - //invalid amount - reply(getTextBot(), user, "SS_SET_SENSIBILITY_AMOUNT", amount, MIN_FLOOD_AMOUNT, MAX_FLOOD_AMOUNT); - return NULL; - } - if(timep > MAX_FLOOD_TIME || timep < 0) { - //invalid time period - reply(getTextBot(), user, "SS_SET_SENSIBILITY_TIME", timep, 0, MAX_FLOOD_TIME); - return NULL; - } - char amountfield[50], timefield[50]; - sprintf(amountfield, "%s%s", mysqlfield, "limit"); - sprintf(timefield, "%s%s", mysqlfield, "time"); - printf_mysql_query("UPDATE `channels` SET `%s` = '%d', `%s` = '%d' WHERE `channel_id` = '%d' ", amountfield, amount, timefield, timep, chan->channel_id); - sprintf(retBuf, "%d:%d", amount, timep); - chan->spam_settings->sensibility_amount[sensibility_index] = amount; - chan->spam_settings->sensibility_time[sensibility_index] = timep; - } else { - sprintf(retBuf, "%d:%d", chan->spam_settings->sensibility_amount[sensibility_index], chan->spam_settings->sensibility_time[sensibility_index]); - } - return retBuf; -} - -static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) { - if(argument) { - //change value - int amount = atoi(argument); - if(amount > 10 || amount < 2) { - //invalid amount - reply(getTextBot(), user, "SS_SET_SPAMLIMIT", amount, 2, 10); - return NULL; - } - printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", amount, chan->channel_id); - sprintf(retBuf, "%d", amount); - chan->spam_settings->spam_amount = amount; - } else - sprintf(retBuf, "%d", chan->spam_settings->spam_amount); - return retBuf; -} - -static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { - int i = 0; - int value = -1; - int identical = 1; - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANOPS) { - if(value == -1) - value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0); - else { - if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) { - identical = 0; - break; - } - } - } - i++; - } - if(argument) { - //binary argument... - if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { - value = 0; - } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { - value = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); - return NULL; - } - i = 0; - char valueBuf[MAXLEN]; - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANOPS) { - neonspam_cmd_set_function *func = neonspam_settings[i].function; - func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf); - } - i++; - } - identical = 1; - } - if(identical && value) - return "1"; - if(identical && !value) - return "0"; - return "?"; -} - -static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { - int i = 0; - int value = -1; - int identical = 1; - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANVOICE) { - if(value == -1) - value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0); - else { - if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) { - identical = 0; - break; - } - } - } - i++; - } - if(argument) { - //binary argument... - if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { - value = 0; - } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { - value = 1; - } else { - reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); - return NULL; - } - i = 0; - char valueBuf[MAXLEN]; - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANVOICE) { - neonspam_cmd_set_function *func = neonspam_settings[i].function; - func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf); - } - i++; - } - identical = 1; - } - if(identical && value) - return "1"; - if(identical && !value) - return "0"; - return "?"; -} - -static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { - int i = 0; - int value = -1; - int identical = 1; - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANEXCEPT) { - if(value == -1) - value = chan->spam_settings->exceptlevel[neonspam_settings[i].intparam]; - else { - if(chan->spam_settings->exceptlevel[neonspam_settings[i].intparam] != value) { - identical = 0; - break; - } - } - } - i++; - } - if(argument) { - //numeric argument... (access) - int caccess = atoi(argument); - if(caccess < 0 || caccess > 501) { - reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); - return NULL; - } - int uaccess = getChannelAccess(user, chan); - if(uaccess == 500) uaccess++; - if(identical && value > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_CANNOT_SET"); - return NULL; - } - } - if(caccess > uaccess) { - if(isGodMode(user)) { - event->flags |= CMDFLAG_OPLOG; - } else { - reply(getTextBot(), user, "NS_SET_BADLEVEL"); - return NULL; - } - } - i = 0; - char valueBuf[MAXLEN]; - sprintf(retBuf, "%d", caccess); - while(neonspam_settings[i].setting) { - if(neonspam_settings[i].flags & SET_SCANEXCEPT) { - neonspam_cmd_set_function *func = neonspam_settings[i].function; - func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, retBuf, valueBuf); - } - i++; - } - identical = 1; - value = caccess; - } - if(identical) { - sprintf(retBuf, "%d", value); - return retBuf; - } - return "?"; -} - -#undef MAX_QUERY_LEN diff --git a/src/commands.c b/src/commands.c deleted file mode 100644 index 8705b81..0000000 --- a/src/commands.c +++ /dev/null @@ -1,177 +0,0 @@ -/* commands.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cmd_global.h" -#include "cmd_neonserv.h" -#include "cmd_neonspam.h" -#include "cmd_funcmds.h" -#include "cmd_neonhelp.h" -#include "modcmd.h" -#include "ConfigParser.h" - -void register_commands() { - - //Global Commands - #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(0, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) - // NAME FUNCTION PARAMS PRIVS FLAGS - USER_COMMAND("version", global_cmd_version, 0, NULL, 0); - USER_COMMAND("netinfo", global_cmd_netinfo, 0, NULL, 0); - USER_COMMAND("commands", global_cmd_commands, 0, NULL, 0); - USER_COMMAND("command", global_cmd_command, 1, NULL, CMDFLAG_ESCAPE_ARGS); - USER_COMMAND("staff", global_cmd_staff, 0, NULL, 0); - USER_COMMAND("motd", global_cmd_motd, 0, NULL, 0); - #undef USER_COMMAND - - #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(0, NAME, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS) - // NAME FUNCTION PARAMS ACCS FLAGS - OPER_COMMAND("register", global_cmd_register, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("unregister", global_cmd_unregister,0, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("say", global_cmd_say, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("emote", global_cmd_emote, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("notice", global_cmd_notice, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("raw", global_cmd_raw, 1, 800, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("god", global_cmd_god, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("reloadlang", global_cmd_reloadlang,1, 500, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("bind", global_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); - OPER_COMMAND("unbind", global_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); - OPER_COMMAND("setaccess", global_cmd_setaccess, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("bots", global_cmd_bots, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - OPER_COMMAND("reload", global_cmd_reload, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("restart", global_cmd_restart, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("die", global_cmd_die, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("setbot", global_cmd_setbot, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("addbot", global_cmd_addbot, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("delbot", global_cmd_delbot, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("reconnect", global_cmd_reconnect, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("modcmd", global_cmd_modcmd, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); - OPER_COMMAND("meminfo", global_cmd_meminfo, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - #undef OPER_COMMAND - - //NeonServ Commands - register_command_alias(1, "NeonServ"); - - #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(1, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) - // NAME FUNCTION PARAMS PRIVS FLAGS - USER_COMMAND("adduser", neonserv_cmd_adduser, 2, "#channel_canadd", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("deluser", neonserv_cmd_deluser, 1, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("clvl", neonserv_cmd_clvl, 2, "#channel_canclvl", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("access", neonserv_cmd_access, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG); - USER_COMMAND("users", neonserv_cmd_users, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); - USER_COMMAND("suspend", neonserv_cmd_suspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("unsuspend", neonserv_cmd_unsuspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("delme", neonserv_cmd_delme, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("myaccess", neonserv_cmd_myaccess, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("up", neonserv_cmd_up, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("down", neonserv_cmd_down, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG); - USER_COMMAND("upall", neonserv_cmd_upall, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("downall", neonserv_cmd_downall, 0, NULL, CMDFLAG_LOG); - USER_COMMAND("mdeluser", neonserv_cmd_mdeluser, 2, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("trim", neonserv_cmd_trim, 2, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("giveowner", neonserv_cmd_giveowner, 1, "500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("op", neonserv_cmd_op, 1, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("deop", neonserv_cmd_deop, 1, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("voice", neonserv_cmd_voice, 1, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("devoice", neonserv_cmd_devoice, 1, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("opall", neonserv_cmd_opall, 0, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("deopall", neonserv_cmd_deopall, 0, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("voiceall", neonserv_cmd_voiceall, 0, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("devoiceall", neonserv_cmd_devoiceall,0, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - if(get_int_field("General.have_halfop")) { - USER_COMMAND("halfop", neonserv_cmd_halfop, 1, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("dehalfop", neonserv_cmd_dehalfop, 1, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("halfopall", neonserv_cmd_halfopall, 0, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("dehalfopall", neonserv_cmd_dehalfopall,0,"%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - } - USER_COMMAND("set", neonserv_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("kick", neonserv_cmd_kick, 1, "#channel_cankick", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("kickban", neonserv_cmd_kickban, 1, "#channel_cankick,#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("ban", neonserv_cmd_ban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("wipeinfo", neonserv_cmd_wipeinfo, 1, "#channel_wipeinfo", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("addban", neonserv_cmd_addban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("bans", neonserv_cmd_bans, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("delban", neonserv_cmd_delban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("topic", neonserv_cmd_topic, 0, "#channel_changetopic", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("chanservsync", neonserv_cmd_chanservsync, 0,"500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("resync", neonserv_cmd_resync, 0, "#channel_canresync", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("addtimeban", neonserv_cmd_addtimeban,2, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("mode", neonserv_cmd_mode, 1, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("peek", neonserv_cmd_peek, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); - USER_COMMAND("uset", neonserv_cmd_uset, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_NO_CROSSCHAN); - USER_COMMAND("unban", neonserv_cmd_unban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("unbanall", neonserv_cmd_unbanall, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("unbanme", neonserv_cmd_unbanme, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("invite", neonserv_cmd_invite, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("inviteme", neonserv_cmd_inviteme, 0, "#channel_getinvite", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - USER_COMMAND("help", neonserv_cmd_help, 0, NULL, 0); - USER_COMMAND("events", neonserv_cmd_events, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("info", neonserv_cmd_info, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); - USER_COMMAND("extscript", neonserv_cmd_extscript, 0, NULL, CMDFLAG_EMPTY_ARGS | CMDFLAG_CHAN_PARAM); - USER_COMMAND("nicklist", neonserv_cmd_nicklist, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - #undef USER_COMMAND - - #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(1, NAME, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS) - // NAME FUNCTION PARAMS ACCS FLAGS - OPER_COMMAND("trace", neonserv_cmd_trace, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - OPER_COMMAND("recover", neonserv_cmd_recover, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("csuspend", neonserv_cmd_csuspend, 1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("cunsuspend", neonserv_cmd_cunsuspend,1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("move", neonserv_cmd_move, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - OPER_COMMAND("oplog", neonserv_cmd_oplog, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("search", neonserv_cmd_search, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - OPER_COMMAND("addrank", neonserv_cmd_addrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("delrank", neonserv_cmd_delrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("setrank", neonserv_cmd_setrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("assignrank", neonserv_cmd_assignrank,2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("listrank", neonserv_cmd_listrank, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("rename", neonserv_cmd_rename, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("unvisited", neonserv_cmd_unvisited, 0, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); - OPER_COMMAND("noregister", neonserv_cmd_noregister,0, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); - #undef OPER_COMMAND - - //NeonSpam Commands - register_command_alias(2, "NeonSpam"); - - #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(2, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) - // NAME FUNCTION PARAMS PRIVS FLAGS - USER_COMMAND("set", neonspam_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); - #undef USER_COMMAND - - //Fun Commands - init_funcmds(); - register_command_alias(3, "FunCMD"); - #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,FLAGS) register_command(3, NAME, FUNCTION, PARAMCOUNT, NULL, 0, FLAGS) - // NAME FUNCTION PARAMS FLAGS - USER_COMMAND("extscript", neonserv_cmd_extscript, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_EMPTY_ARGS | CMDFLAG_CHAN_PARAM | CMDFLAG_FUNCMD); - USER_COMMAND("ping", funcmd_ping, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); - USER_COMMAND("pong", funcmd_pong, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); - USER_COMMAND("dice", funcmd_dice, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); - USER_COMMAND("8ball", funcmd_8ball, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); - USER_COMMAND("cookie", funcmd_cookie, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); - #undef USER_COMMAND - - //NeonHelp Commands - register_command_alias(4, "NeonHelp"); - - #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(4, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) - // NAME FUNCTION PARAMS PRIVS FLAGS - USER_COMMAND("next", neonhelp_cmd_next, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("delete", neonhelp_cmd_delete, 1, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("requests", neonhelp_cmd_requests, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - USER_COMMAND("stats", neonhelp_cmd_stats, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); - #undef USER_COMMAND - -} \ No newline at end of file diff --git a/src/commands.h b/src/commands.h deleted file mode 100644 index 1c92d55..0000000 --- a/src/commands.h +++ /dev/null @@ -1,23 +0,0 @@ -/* commands.h - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#ifndef _commands_h -#define _commands_h -#include "main.h" - -void register_commands(); - -#endif \ No newline at end of file diff --git a/src/event_neonserv_ctcp.c b/src/event_neonserv_ctcp.c deleted file mode 100644 index 11d03e2..0000000 --- a/src/event_neonserv_ctcp.c +++ /dev/null @@ -1,112 +0,0 @@ -/* event_neonserv_ctcp.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -struct neonserv_event_ctcp_cache { - struct ClientSocket *client; - struct UserNode *user; - struct ChanNode *chan; - char *command; - char *text; -}; - -static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup); -static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text); - -static void neonserv_event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text) { - if(!stricmp(command, "ACTION")) return; //always allow CTCP ACTION (/me) - struct ClientSocket *client = getBotForChannel(chan); - if(!client) return; //we can't "see" this event - if(isNetworkService(user)) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_event_ctcp_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->user = user; - cache->chan = chan; - cache->command = strdup(command); - cache->text = (text ? strdup(text) : NULL); - get_userauth(user, neonserv_event_ctcp_nick_lookup, cache); - } else - neonserv_event_ctcp_async1(client, user, chan, command, text); -} - -static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup) { - struct neonserv_event_ctcp_cache *cache = data; - if(user) { - neonserv_event_ctcp_async1(cache->client, cache->user, cache->chan, cache->command, cache->text); - } - free(cache->command); - if(cache->text) - free(cache->text); - free(cache); -} - -static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text) { - MYSQL_RES *res; - MYSQL_ROW row, defaultrow = NULL, chanuser; - int uaccess = 0; - printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaultrow = mysql_fetch_row(res); - } - int ctcpaccess = atoi((row[0] ? row[0] : defaultrow[0])); - if((user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - chanuser = mysql_fetch_row(res); - if(chanuser) - uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0])); - } - int duration = 0; - char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; - char *banmask = NULL; - char *reason = "disallowed channel CTCP"; - if(uaccess < ctcpaccess) { - switch(atoi((row[1] ? row[1] : defaultrow[1]))) { - case 2: //TIMEBAN: 3min - duration = 180; - case 3: //TIMEBAN: 1h - if(!duration) - duration = 3600; - banmask = generate_banmask(user, banmaskBuf); - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason)); - int banid = (int) mysql_insert_id(get_mysql_conn()); - char nameBuf[MAXLEN]; - char banidBuf[20]; - sprintf(nameBuf, "ban_%d", banid); - sprintf(banidBuf, "%d", banid); - timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); - case 1: //KICKBAN - if(!banmask) - banmask = generate_banmask(user, banmaskBuf); - putsock(client, "MODE %s +b %s", chan->name, banmask); - case 0: //KICK - putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason); - break; - } - } -} - diff --git a/src/event_neonserv_invite.c b/src/event_neonserv_invite.c deleted file mode 100644 index 2b53429..0000000 --- a/src/event_neonserv_invite.c +++ /dev/null @@ -1,45 +0,0 @@ -/* event_neonserv_invite.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static void neonserv_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) { - reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick); - return; - } - if(!strcmp(row[2], "1")) { - reply(client, user, "MODCMD_CHAN_SUSPENDED"); - return; - } - int botid = atoi(row[0]); - struct ClientSocket *bot; - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->clientid == botid) - break; - } - if(bot) { - struct ChanNode *chan = getChanByName(channel); - if(chan && isUserOnChan(bot->user, chan)) { - reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name); - } else - putsock(bot, "JOIN %s", channel); - } -} - diff --git a/src/event_neonserv_join.c b/src/event_neonserv_join.c deleted file mode 100644 index 77d5de7..0000000 --- a/src/event_neonserv_join.c +++ /dev/null @@ -1,252 +0,0 @@ -/* event_neonserv_join.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -struct neonserv_event_join_cache { - struct ClientSocket *client; - struct ChanUser *chanuser; - int was_registering; -}; - -static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup); -static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser, int was_registering); -static TIMEQ_CALLBACK(neonserv_event_join_dynlimit); - -static void neonserv_event_join(struct ChanUser *chanuser) { - struct UserNode *user = chanuser->user; - struct ClientSocket *client = getBotForChannel(chanuser->chan); - if(!client) return; //we can't "see" this event - if(chanuser->user == client->user) { - requestOp(client->user, chanuser->chan); - return; - } - if(chanuser->user->flags & USERFLAG_ISBOT) return; - loadChannelSettings(chanuser->chan); - if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - char *ban; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); - if((ban = getBanAffectingMask(chanuser->chan, usermask)) != NULL && !(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) { - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `ban_reason`, `user_user` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d' AND `ban_mask` = '%s'", chanuser->chan->channel_id, escape_string(ban)); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) != NULL) { - putsock(client, "MODE %s +b %s", chanuser->chan->name, ban); - putsock(client, "KICK %s %s :(%s) %s", chanuser->chan->name, chanuser->user->nick, (row[1] ? row[1] : client->user->nick), row[0]); - return; - } - } - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_event_join_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->chanuser = chanuser; - cache->was_registering = (user->flags & USERFLAG_WAS_REGISTRING); - get_userauth(user, neonserv_event_join_nick_lookup, cache); - } else - neonserv_event_join_async1(client, chanuser, (user->flags & USERFLAG_WAS_REGISTRING)); -} - -static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup) { - struct neonserv_event_join_cache *cache = data; - if(user) { - neonserv_event_join_async1(cache->client, cache->chanuser, cache->was_registering); - } - free(cache); -} - -static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser, int was_registering) { - struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); - struct ChanNode *chan = chanuser->chan; - struct UserNode *user = chanuser->user; - struct ModeBuffer *modeBuf; - int with_halfops = get_int_field("General.have_halfop"); - MYSQL_RES *res; - MYSQL_ROW row, chanuserrow, defaultrow = NULL; - printf_mysql_query("SELECT `channel_maxusers`, `channel_greeting`, `channel_usergreeting`, `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_dynlimit`, `channel_gethalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(!row[3] || !row[4] || !row[5] || (!row[7] && with_halfops)) { - printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_gethalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaultrow = mysql_fetch_row(res); - } - if(chan->usercount > atoi(row[0])) { - //update maxusers - printf_mysql_query("UPDATE `channels` SET `channel_maxusers` = '%d' WHERE `channel_id` = '%d'", chan->usercount, chan->channel_id); - } - if((user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - chanuserrow = mysql_fetch_row(res); - } else - chanuserrow = NULL; - if(!chanuserrow) - printf_mysql_query("UPDATE `channels` SET `channel_lastvisit` = UNIX_TIMESTAMP() WHERE `channel_id` = '%d'", chan->channel_id); - int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0); - int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0); - //GREETING - char greeting[MAXLEN]; - int greetingPos = 0; - char *a, *b = (chanuserrow && *row[2] ? row[2] : row[1]); - do { - if(!b) break; - a = strstr(b, "$"); - if(a) *a = '\0'; - greetingPos += sprintf(greeting + greetingPos, "%s", b); - if(!a) break; - switch(a[1]) { - case '\0': - a = NULL; - break; - case 'A': - greetingPos += sprintf(greeting + greetingPos, "%d", uaccess); - break; - case 'B': - greetingPos += sprintf(greeting + greetingPos, "%s", client->user->nick); - break; - case 'N': - greetingPos += sprintf(greeting + greetingPos, "%s", user->nick); - break; - case 'H': - greetingPos += sprintf(greeting + greetingPos, "%s@%s", user->ident, user->host); - break; - case 'U': - greetingPos += sprintf(greeting + greetingPos, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*")); - break; - default: - greeting[greetingPos++] = '$'; - greeting[greetingPos++] = a[1]; - break; - } - if(a) - b = a+2; - } while(a); - if(greetingPos && (!was_registering || *row[2])) - reply(textclient, user, "[%s] %s", chan->name, greeting); - //USER RIGHTS - if(!(userflags & DB_CHANUSER_NOAUTOOP)) { - int getop = atoi((row[3] ? row[3] : defaultrow[0])); - int gethalfop = (with_halfops ? atoi((row[7] ? row[7] : defaultrow[3])) : 0); - int getvoice = atoi((row[4] ? row[4] : defaultrow[1])); - modeBuf = initModeBuffer(client, chan); - if(uaccess >= getop && uaccess != 0) { //we disallow auto op for all users - modeBufferOp(modeBuf, user->nick); - } else if(with_halfops && uaccess >= gethalfop) { - modeBufferHalfop(modeBuf, user->nick); - } else if(uaccess >= getvoice) { - modeBufferVoice(modeBuf, user->nick); - } - freeModeBuffer(modeBuf); - } - //INFOLINE - int userinfoaccess = atoi((row[5] ? row[5] : defaultrow[2])); - if(chanuserrow && strcmp(chanuserrow[2], "") && uaccess > userinfoaccess) { - if(!strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30) { - putsock(client, "PRIVMSG %s :[%s] %s", chan->name, user->nick, chanuserrow[2]); - } - } - //SEEN - if(chanuserrow) { - printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[4]); - } - //DYNLIMIT - if(row[6] && strcmp(row[6], "0")) { - char nameBuf[CHANNELLEN + 10]; - sprintf(nameBuf, "dynlimit_%s", chan->name); - if(!timeq_name_exists(nameBuf)) { - //neonserv_event_join_dynlimit - timeq_add_name(nameBuf, 30, neonserv_event_join_dynlimit, strdup(chan->name)); - } - } - //AUTOINVITE - if((user->flags & USERFLAG_ISAUTHED) && (!chanuserrow || !strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30)) { - //check if it's the first channel, the user is seen by the bot (IMPORTANT: ignore other bot's channel!) - char first_chan = 1; - char bot_in_chan; - struct ChanUser *cchanuser, *bchanuser; - struct ClientSocket *bot; - for(cchanuser = getUserChannels(user, NULL); cchanuser; cchanuser = getUserChannels(user, cchanuser)) { - if(chanuser == cchanuser) continue; //ignore this one ;) - //check if this bot is in the specific channel - bot_in_chan = 0; - for(bchanuser = getChannelUsers(cchanuser->chan, NULL); bchanuser; bchanuser = getChannelUsers(cchanuser->chan, bchanuser)) { - if(bchanuser->user->flags & USERFLAG_ISBOT) { - //get the botid - for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { - if(bot->user == bchanuser->user) { - if(bot->botid == client->botid) - bot_in_chan = 1; - break; - } - } - if(bot_in_chan) break; - } - } - if(!bot_in_chan) continue; - first_chan = 0; - break; - } - if(first_chan) { - //autoinvite :) - defaultrow = NULL; - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `channel_name`, `channel_getinvite` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `user_user` = '%s' AND `chanuser_flags` >= '%d'", escape_string(user->auth), DB_CHANUSER_AUTOINVITE); - res = mysql_use(); - int getinvite; - while((chanuserrow = mysql_fetch_row(res)) != NULL) { - userflags = atoi(chanuserrow[1]); - if(!(userflags & DB_CHANUSER_AUTOINVITE)) continue; - if(!(chan = getChanByName(chanuserrow[2]))) continue; //no bot is in the channel - if((bchanuser = getChanUser(client->user, chan)) && (bchanuser->flags & CHANUSERFLAG_OPPED)) - bot = client; - else { - bot = getBotForChannel(chan); - } - if(chanuserrow[3] == NULL && defaultrow == NULL) { - printf_mysql_query("SELECT `channel_getinvite` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaultrow = mysql_fetch_row(res); - } - getinvite = atoi((chanuserrow[3] ? chanuserrow[3] : defaultrow[0])); - if(atoi(chanuserrow[0]) >= getinvite) { - putsock(bot, "INVITE %s %s", user->nick, chan->name); - } - } - } - } -} - -static TIMEQ_CALLBACK(neonserv_event_join_dynlimit) { - char *chanName = data; - struct ChanNode *chan = getChanByName(chanName); - free(chanName); - struct ClientSocket *client = getBotForChannel(chan); - if(!client) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - MYSQL_RES *res; - MYSQL_ROW row; - printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(row[0] && strcmp(row[0], "0")) { - putsock(client, "MODE %s +l %d", chan->name, chan->usercount + atoi(row[0])); - } -} diff --git a/src/event_neonserv_kick.c b/src/event_neonserv_kick.c deleted file mode 100644 index 8e32d02..0000000 --- a/src/event_neonserv_kick.c +++ /dev/null @@ -1,99 +0,0 @@ -/* event_neonserv_kick.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -struct neonserv_event_kick_cache { - struct ClientSocket *client; - struct UserNode *user; - struct UserNode *target; - struct ChanNode *chan; - int userauth_pending; -}; - -static USERAUTH_CALLBACK(neonserv_event_kick_nick_lookup); -static void neonserv_event_kick_async1(struct neonserv_event_kick_cache *cache); -static void neonserv_event_kick_async2(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, struct ChanNode *chan); - -static void neonserv_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { - struct ChanNode *chan = target->chan; - struct ClientSocket *client; - if(isBot(target->user)) { - client = getChannelBot(chan, 0); - struct ClientSocket *bot = client; - for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { - if(client->user == target->user) { - break; - } - } - if(!client) return; - if(bot && bot != client && (isModeSet(chan->modes, 'i') || isModeSet(chan->modes, 'a') || isModeSet(chan->modes, 'l'))) { - struct ChanUser *chanuser = getChanUser(bot->user, chan); - if(chanuser && chanuser->flags & CHANUSERFLAG_OPPED) - putsock(bot, "INVITE %s %s", target->user->nick, chan->name); - } - char *key = ""; - if(isModeSet(chan->modes, 'k')) { - key = getModeValue(chan->modes, 'k'); - } - putsock(client, "JOIN %s %s", chan->name, key); - return; - } - client = getBotForChannel(chan); - if(!client) return; //we can't "see" this event - if(isNetworkService(user)) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - struct neonserv_event_kick_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->user = user; - cache->target = target->user; - cache->chan = target->chan; - cache->userauth_pending = 0; - if(!(user->flags & USERFLAG_ISAUTHED)) { - get_userauth(user, neonserv_event_kick_nick_lookup, cache); - cache->userauth_pending++; - } - if(!(target->user->flags & USERFLAG_ISAUTHED)) { - get_userauth(target->user, neonserv_event_kick_nick_lookup, cache); - cache->userauth_pending++; - } - neonserv_event_kick_async1(cache); -} - -static USERAUTH_CALLBACK(neonserv_event_kick_nick_lookup) { - struct neonserv_event_kick_cache *cache = data; - cache->userauth_pending--; - neonserv_event_kick_async1(cache); -} - -static void neonserv_event_kick_async1(struct neonserv_event_kick_cache *cache) { - if(cache->userauth_pending == 0) { - neonserv_event_kick_async2(cache->client, cache->user, cache->target, cache->chan); - free(cache); - } -} - -static void neonserv_event_kick_async2(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, struct ChanNode *chan) { - if(isUserProtected(chan, target, user)) { - char buf[MAXLEN]; - putsock(client, "KICK %s %s :%s", chan->name, user->nick, build_language_string(user, buf, "NS_USER_PROTECTED", target->nick)); - putsock(client, "INVITE %s %s", target->nick, chan->name); - } -} diff --git a/src/event_neonserv_mode.c b/src/event_neonserv_mode.c deleted file mode 100644 index f0794a9..0000000 --- a/src/event_neonserv_mode.c +++ /dev/null @@ -1,337 +0,0 @@ -/* event_neonserv_mode.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static USERLIST_CALLBACK(neonserv_event_mode_userlist_lookup); -static void neonserv_event_mode_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc); -static int neonserv_cmd_mode_botwar_detect(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int *botwar_detect_executed); - -struct neonserv_event_mode_cache { - struct ClientSocket *client; - struct UserNode *user; - char *modes; - char **argv; - int argc; -}; - -static void neonserv_event_mode(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc) { - struct ClientSocket *client = getBotForChannel(chan); - if(!client) return; //we can't "see" this event - if(isNetworkService(user)) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - struct neonserv_event_mode_cache *cache = malloc(sizeof(*cache)); - char **temp_argv = NULL; - if(argc) - temp_argv = malloc(argc*sizeof(*temp_argv)); - if (!cache || (argc && !temp_argv)) { - perror("malloc() failed"); - return; - } - if(argc) { - int i; - for(i = 0; i < argc; i++) { - temp_argv[i] = strdup(argv[i]); - } - } - cache->client = client; - cache->user = user; - cache->modes = strdup(modes); - cache->argv = temp_argv; - cache->argc = argc; - get_userlist_with_invisible(chan, neonserv_event_mode_userlist_lookup, cache); -} - -static USERLIST_CALLBACK(neonserv_event_mode_userlist_lookup) { - struct neonserv_event_mode_cache *cache = data; - neonserv_event_mode_async1(cache->client, cache->user, chan, cache->modes, cache->argv, cache->argc); - if(cache->argc) { - int i; - for(i = 0; i < cache->argc; i++) { - free(cache->argv[i]); - } - free(cache->argv); - } - free(cache->modes); - free(cache); -} - -static void neonserv_event_mode_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc) { - struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); - int botwar_detect_executed = 0; - MYSQL_ROW row, defaults = NULL; - int i, arg, add = 1, skip = 0; - unsigned int modetype; - int db_canop, db_canhalfop, db_canvoice, db_canban, db_enfmodes, db_getop, db_gethalfop, db_getvoice; - struct ModeNode *modelock = createModeNode(NULL); - struct ModeBuffer *modeBuf; - struct UserNode *cuser; - struct ChanUser *chanuser; - int with_halfops = get_int_field("General.have_halfop"); - modeBuf = initModeBuffer(client, chan); - printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes`, `channel_getop`, `channel_getvoice`, `channel_gethalfop`, `channel_canhalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - row = mysql_fetch_row(mysql_use()); - if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL || row[4] == NULL || row[5] == NULL || row[6] == NULL || (row[7] == NULL && with_halfops) || (row[8] == NULL && with_halfops)) { - printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes`, `channel_getop`, `channel_getvoice`, `channel_gethalfop`, `channel_canhalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); - defaults = mysql_fetch_row(mysql_use()); - } - db_canop = atoi((row[0] ? row[0] : defaults[0])); - db_canvoice = atoi((row[1] ? row[1] : defaults[1])); - db_canban = atoi((row[2] ? row[2] : defaults[2])); - db_enfmodes = atoi((row[3] ? row[3] : defaults[3])); - db_getop = atoi((row[5] ? row[5] : defaults[5])); - db_getvoice = atoi((row[6] ? row[6] : defaults[6])); - db_gethalfop = (with_halfops ? atoi((row[7] ? row[7] : defaults[7])) : 0); - db_canhalfop = (with_halfops ? atoi((row[8] ? row[8] : defaults[8])) : 0); - if(row[4]) - parseModeString(modelock, row[4]); - else if(defaults[4]) - parseModeString(modelock, defaults[4]); - int uaccess = getChannelAccess(user, chan); - int caccess; - char *carg; - int sent_modes_locked = 0; - char deop_user = 0; - char tmp[MAXLEN]; - arg = 0; - for(i = 0; i < strlen(modes); i++) { - switch(modes[i]) { - case '+': - add = 1; - break; - case '-': - add = 0; - break; - case 'o': - case 'h': - case 'v': - if(arg == argc) { - break; - } - carg = argv[arg++]; - cuser = searchUserByNick(carg); - if(!cuser) { - break; //internal Bot error - this should never happen - } - caccess = getChannelAccess(cuser, chan); - if(modes[i] == 'o' && !add && cuser == client->user) { - //someone deopped the bot??? - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - requestOp(client->user, chan); - } - if((modes[i] == 'o' || (modes[i] == 'h' && !with_halfops)) && !(add && isBot(cuser))) { - if(uaccess < db_canop) { - reply(textclient, user, "NS_MODE_ENFOPS", chan->name); - db_canop = -1; - if(uaccess < db_getop) - deop_user = 1; - } - if(db_canop == -1 && caccess < db_getop) { - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - break; - } - } else if(modes[i] == 'h' && with_halfops && !(add && isBot(cuser))) { - if(uaccess < db_canhalfop) { - reply(textclient, user, "NS_MODE_ENFOPS", chan->name); - db_canhalfop = -1; - if(uaccess < db_gethalfop) - deop_user = 1; - } - if(db_canhalfop == -1 && caccess < db_gethalfop) { - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - break; - } - } else if(modes[i] == 'v' && !(add && isBot(cuser))) { - if(uaccess < db_canvoice) { - reply(textclient, user, "NS_MODE_ENFVOICE", chan->name); - db_canvoice = -1; - if(uaccess < db_getop) - deop_user = 1; - } - if(db_canvoice == -1 && caccess < db_getvoice) { - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - break; - } - } - if(!add) { - //check protection - if(isBot(cuser)) { - //don't send this - just try to reop - //reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - break; - } - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - if(uaccess < db_getop) - deop_user = 1; - break; - } - } - break; - case 'b': - if(arg == argc) { - break; - } - carg = argv[arg++]; - if(uaccess < db_canban) { - reply(textclient, user, "NS_MODE_CANBAN", chan->name); - db_canban = -1; - } - if(db_canban == -1) { - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - if(uaccess < db_getop) - deop_user = 1; - break; - } - char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; - char usermask[NICKLEN+USERLEN+HOSTLEN+3]; - int match_count = 0; - carg = make_banmask(carg, hostmask_buffer); - if(add) { - for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { - cuser = chanuser->user; - sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); - if(!match(carg, usermask)) { - if(isUserProtected(chan, cuser, user)) { - reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); - skip = 1; - break; - } - match_count++; - } - } - if(match_count > 4 && (match_count * 3) > chan->usercount) { - reply(textclient, user, "NS_LAME_MASK_WARNING", carg, match_count); - } - } - if(skip) { - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - if(uaccess < db_getop) - deop_user = 1; - } - break; - default: - modetype = getModeType(modelock, modes[i]); - if(modetype == 0) { - break; //unknown mode - } - - if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) { - if(arg == argc) { - break; - } - carg = argv[arg++]; - if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modes[i])) { - char *modelock_val = getModeValue(modelock, modes[i]); - if(stricmp(carg, modelock_val) && uaccess < db_enfmodes && !isGodMode(user)) { - if(!sent_modes_locked) { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - sent_modes_locked = 1; - if(uaccess < db_getop) - deop_user = 1; - } - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, add, modes[i], modelock_val); - break; - } - } - if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modes[i])) { - int *modelock_val = getModeValue(modelock, modes[i]); - if(atoi(carg) != *modelock_val && uaccess < db_enfmodes && !isGodMode(user)) { - if(!sent_modes_locked) { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - sent_modes_locked = 1; - if(uaccess < db_getop) - deop_user = 1; - } - sprintf(tmp, "%d", *modelock_val); - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, add, modes[i], tmp); - break; - } - } - } else if(!add && (modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_B) { - if(arg == argc) { - break; - } - carg = argv[arg++]; - } else - carg = NULL; - if(isModeAffected(modelock, modes[i]) && add == !isModeSet(modelock, modes[i]) && uaccess < db_enfmodes && !isGodMode(user)) { - if(!sent_modes_locked) { - getFullModeString(modelock, tmp); - reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); - sent_modes_locked = 1; - if(uaccess < db_getop) - deop_user = 1; - } - if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) - modeBufferSet(modeBuf, !add, modes[i], carg); - break; - } - break; - } - } - if(deop_user && !neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) { - modeBufferDeop(modeBuf, user->nick); - } - freeModeBuffer(modeBuf); - freeModeNode(modelock); -} - -static int neonserv_cmd_mode_botwar_detect(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int *botwar_detect_executed) { - struct ChanUser *chanuser = getChanUser(user, chan); - if(!chanuser) return 0; //flying super cow? - if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) { - chanuser->changeTime = time(0); - chanuser->chageEvents = 1; - } else { - if(!*botwar_detect_executed) - chanuser->chageEvents++; - *botwar_detect_executed = 1; - if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) { - //BOTWAR! - chanuser->changeTime = time(0); - if(chanuser->chageEvents > 0) { - char *alertchan = get_string_field("General.alertchan"); - putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (alertchan ? get_language_string(user, "NS_BOTWAR_REPORTED") : "")); - if(alertchan) { - struct ChanNode *alertchan_chan = getChanByName(alertchan); - struct ClientSocket *alertclient; - if(alertchan_chan && (alertclient = getBotForChannel(chan)) != NULL) { - char msgBuf[MAXLEN]; - putsock(alertclient, "PRIVMSG %s :%s", alertchan_chan->name, build_language_string(NULL, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick)); - } - } - } - chanuser->chageEvents = -2; - return 1; - } - } - return 0; -} - diff --git a/src/event_neonserv_notice.c b/src/event_neonserv_notice.c deleted file mode 100644 index 84fb51a..0000000 --- a/src/event_neonserv_notice.c +++ /dev/null @@ -1,107 +0,0 @@ -/* event_neonserv_notice.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -struct neonserv_event_notice_cache { - struct ClientSocket *client; - struct UserNode *user; - struct ChanNode *chan; - char *message; -}; - -static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup); -static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message); - -static void neonserv_event_channotice(struct UserNode *user, struct ChanNode *chan, char *message) { - struct ClientSocket *client = getBotForChannel(chan); - if(!client) return; //we can't "see" this event - if(isNetworkService(user)) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_event_notice_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->user = user; - cache->chan = chan; - cache->message = strdup(message); - get_userauth(user, neonserv_event_notice_nick_lookup, cache); - } else - neonserv_event_notice_async1(client, user, chan, message); -} - -static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup) { - struct neonserv_event_notice_cache *cache = data; - if(user) { - neonserv_event_notice_async1(cache->client, cache->user, cache->chan, cache->message); - } - free(cache->message); - free(cache); -} - -static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { - MYSQL_RES *res; - MYSQL_ROW row, defaultrow = NULL, chanuser; - int uaccess = 0; - printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaultrow = mysql_fetch_row(res); - } - int noticeaccess = atoi((row[0] ? row[0] : defaultrow[0])); - if((user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - chanuser = mysql_fetch_row(res); - if(chanuser) - uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0])); - } - int duration = 0; - char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; - char *banmask = NULL; - char *reason = "disallowed channel NOTICE"; - if(uaccess < noticeaccess) { - switch(atoi((row[1] ? row[1] : defaultrow[1]))) { - case 2: //TIMEBAN: 3min - duration = 180; - case 3: //TIMEBAN: 1h - if(!duration) - duration = 3600; - banmask = generate_banmask(user, banmaskBuf); - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason)); - int banid = (int) mysql_insert_id(get_mysql_conn()); - char nameBuf[MAXLEN]; - char banidBuf[20]; - sprintf(nameBuf, "ban_%d", banid); - sprintf(banidBuf, "%d", banid); - timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); - case 1: //KICKBAN - if(!banmask) - banmask = generate_banmask(user, banmaskBuf); - putsock(client, "MODE %s +b %s", chan->name, banmask); - case 0: //KICK - putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason); - break; - } - } -} - diff --git a/src/event_neonserv_part.c b/src/event_neonserv_part.c deleted file mode 100644 index e41436c..0000000 --- a/src/event_neonserv_part.c +++ /dev/null @@ -1,31 +0,0 @@ -/* event_neonserv_part.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static void neonserv_event_part(struct ChanUser *chanuser, char *reason) { - struct ChanNode *chan = chanuser->chan; - struct UserNode *user = chanuser->user; - MYSQL_RES *res; - MYSQL_ROW chanuserrow; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - if((user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - if((chanuserrow = mysql_fetch_row(res)) != NULL) - printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]); - } -} diff --git a/src/event_neonserv_quit.c b/src/event_neonserv_quit.c deleted file mode 100644 index b2f0401..0000000 --- a/src/event_neonserv_quit.c +++ /dev/null @@ -1,30 +0,0 @@ -/* event_neonserv_quit.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static void neonserv_event_quit(struct UserNode *user, char *reason) { - MYSQL_RES *res; - MYSQL_ROW chanuserrow; - struct ChanUser *chanuser; - if((user->flags & USERFLAG_ISAUTHED)) { - for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) { - printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `channel_name` = '%s' AND `user_user` = '%s'", escape_string(chanuser->chan->name), escape_string(user->auth)); - res = mysql_use(); - if((chanuserrow = mysql_fetch_row(res)) != NULL) - printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]); - } - } -} diff --git a/src/event_neonserv_topic.c b/src/event_neonserv_topic.c deleted file mode 100644 index 577e0a3..0000000 --- a/src/event_neonserv_topic.c +++ /dev/null @@ -1,114 +0,0 @@ -/* event_neonserv_topic.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -struct neonserv_event_topic_cache { - struct ClientSocket *client; - struct UserNode *user; - struct ChanNode *chan; - char *new_topic; -}; - -static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup); -static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic); - -static void neonserv_event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic) { - struct ClientSocket *client = getBotForChannel(chan); - if(!client) return; //we can't "see" this event - if(isNetworkService(user)) return; - loadChannelSettings(chan); - if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; - if(!(user->flags & USERFLAG_ISAUTHED)) { - struct neonserv_event_topic_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->user = user; - cache->chan = chan; - cache->new_topic = strdup(new_topic); - get_userauth(user, neonserv_event_topic_nick_lookup, cache); - } else - neonserv_event_topic_async1(client, user, chan, new_topic); -} - -static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup) { - struct neonserv_event_topic_cache *cache = data; - if(user) { - neonserv_event_topic_async1(cache->client, cache->user, cache->chan, cache->new_topic); - } - free(cache->new_topic); - free(cache); -} - -static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic) { - MYSQL_RES *res; - MYSQL_ROW row, defaultrow = NULL, chanuserrow; - int uaccess = 0; - printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); - res = mysql_use(); - if ((row = mysql_fetch_row(res)) == NULL) return; - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaultrow = mysql_fetch_row(res); - } - int changetopic = atoi((row[0] ? row[0] : defaultrow[0])); - int topicsnarf = atoi((row[1] ? row[1] : defaultrow[1])); - if((user->flags & USERFLAG_ISAUTHED)) { - printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); - res = mysql_use(); - chanuserrow = mysql_fetch_row(res); - if(chanuserrow) - uaccess = ((atoi(chanuserrow[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuserrow[0])); - } - if(uaccess < changetopic) { - //undo topic change - struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); - struct ChanUser *chanuser = getChanUser(user, chan); - if(!chanuser) return; //flying super cow? - if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) { - chanuser->changeTime = time(0); - chanuser->chageEvents = 1; - } else { - chanuser->chageEvents++; - if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) { - //BOTWAR! - chanuser->changeTime = time(0); - if(chanuser->chageEvents > 0) { - char *alertchan = get_string_field("General.alertchan"); - putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (alertchan ? get_language_string(user, "NS_BOTWAR_REPORTED") : "")); - if(alertchan) { - struct ChanNode *alertchan_chan = getChanByName(alertchan); - struct ClientSocket *alertclient; - if(alertchan_chan && (alertclient = getBotForChannel(chan)) != NULL) { - char msgBuf[MAXLEN]; - putsock(alertclient, "PRIVMSG %s :%s", alertchan_chan->name, build_language_string(NULL, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick)); - } - } - } - chanuser->chageEvents = -2; - return; - } - } - reply(textclient, user, "NS_TOPIC_ACCESS", chan->name); - putsock(client, "TOPIC %s :%s", chan->name, chan->topic); - } else if(uaccess >= topicsnarf) { - printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(new_topic), chan->channel_id); - } -} - diff --git a/src/event_neonspam_chanmsg.c b/src/event_neonspam_chanmsg.c deleted file mode 100644 index 163315d..0000000 --- a/src/event_neonspam_chanmsg.c +++ /dev/null @@ -1,392 +0,0 @@ -/* event_neonspam_chanmsg.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); -static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser); -static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); -static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); -static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); - -static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup); -static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish); - -struct neonspam_event_chanmsg_cache { - struct ClientSocket *client; - struct ChanUser *chanuser; - struct NeonSpamSettings *settings; - unsigned int warn; - unsigned int punish; -}; - - - -static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { - struct ClientSocket *client = getChannelBot(chan, BOTID); - if(!client || (user->flags & USERFLAG_ISBOT)) return; //we can't "see" this event - loadNeonSpamSettings(chan); - struct NeonSpamSettings *settings = chan->spam_settings; - struct ChanUser *chanuser = getChanUser(user, chan); - if(!settings || !chanuser) return; - #define NEONSPAM_CHANMSG_DO_SCANOPS(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_OPPED)) - #define NEONSPAM_CHANMSG_DO_SCANVOICE(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_VOICED)) - #define NEONSPAM_CHANMSG_DO_EXCEPT(INDEX) (settings->exceptlevel[INDEX] != 0) - #define NEONSPAM_CHANMSG_NEED_WHO(INDEX) (settings->exceptlevel[INDEX] != 501) - //scan the message - int result = 0; - unsigned int warn = 0; - unsigned int punish = 0; - int needwho = 0; - if((settings->flags & SPAMSETTINGS_SPAMSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_SPAMSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_SPAMSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_SPAMEXCINDEX)) { - result = neonspam_spamscan(settings, chanuser, message); - switch(result) { - case SPAMSERV_CHECK_IGNORE: - break; - case SPAMSERV_CHECK_WARN: - warn |= SPAMSETTINGS_SPAMSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX)) - needwho = 1; - break; - case SPAMSERV_CHECK_PUNISH: - punish |= SPAMSETTINGS_SPAMSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX)) - needwho = 1; - break; - } - } - if((settings->flags & SPAMSETTINGS_FLOODSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_FLOODSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_FLOODSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_FLOODEXCINDEX)) { - result = neonspam_floodscan(settings, chanuser); - switch(result) { - case SPAMSERV_CHECK_IGNORE: - break; - case SPAMSERV_CHECK_WARN: - warn |= SPAMSETTINGS_FLOODSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX)) - needwho = 1; - break; - case SPAMSERV_CHECK_PUNISH: - punish |= SPAMSETTINGS_FLOODSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX)) - needwho = 1; - break; - } - } - if((settings->flags & SPAMSETTINGS_BOTNETSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_BOTNETSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_BOTNETSCAN_VOICE)) { - result = neonspam_botnetscan(client, settings, chanuser, message); - switch(result) { - case SPAMSERV_CHECK_DEAD: - return; - case SPAMSERV_CHECK_IGNORE: - break; - } - } - if((settings->flags & SPAMSETTINGS_CAPSSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_CAPSSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_CAPSSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_CAPSEXCINDEX)) { - result = neonspam_capsscan(settings, chanuser, message); - switch(result) { - case SPAMSERV_CHECK_IGNORE: - break; - case SPAMSERV_CHECK_WARN: - warn |= SPAMSETTINGS_CAPSSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX)) - needwho = 1; - break; - case SPAMSERV_CHECK_PUNISH: - punish |= SPAMSETTINGS_CAPSSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX)) - needwho = 1; - break; - } - } - if((settings->flags & SPAMSETTINGS_DIGITSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_DIGITSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_DIGITSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_DIGITEXCINDEX)) { - result = neonspam_digitscan(settings, chanuser, message); - switch(result) { - case SPAMSERV_CHECK_IGNORE: - break; - case SPAMSERV_CHECK_WARN: - warn |= SPAMSETTINGS_DIGITSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX)) - needwho = 1; - break; - case SPAMSERV_CHECK_PUNISH: - punish |= SPAMSETTINGS_DIGITSCAN; - if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX)) - needwho = 1; - break; - } - } - //some other checks? - - if(warn || punish) { - //whois the user to check against exceptlevel - if(!needwho || (user->flags & USERFLAG_ISAUTHED)) { - neonspam_event_chanmsg_punish(client, chanuser, settings, warn, punish); - } else { - struct neonspam_event_chanmsg_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->chanuser = chanuser; - cache->settings = settings; - cache->warn = warn; - cache->punish = punish; - get_userauth(user, neonspam_event_chanmsg_nick_lookup, cache); - } - - } - #undef NEONSPAM_CHANMSG_DO_SCANOPS - #undef NEONSPAM_CHANMSG_DO_SCANVOICE - #undef NEONSPAM_CHANMSG_DO_EXCEPT - #undef NEONSPAM_CHANMSG_NEED_WHO -} - -static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup) { - struct neonspam_event_chanmsg_cache *cache = data; - neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->warn, cache->punish); - free(cache); -} - -static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish) { - MYSQL_RES *res; - MYSQL_ROW row, defaults; - loadChannelSettings(chanuser->chan); - int uaccess = 0; - if(chanuser->user->flags & USERFLAG_ISAUTHED) - uaccess = getChannelAccess(chanuser->user, chanuser->chan); - char reason[MAXLEN]; - reason[0] = '\0'; - int punishment = 0; - int punish_time = 0; - if(!punishment && (punish & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) { - printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM); - punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; - punish_time = atoi((row[1] ? row[1] : defaults[1])); - } - if(!punishment && (punish & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) { - printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD); - punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; - punish_time = atoi((row[1] ? row[1] : defaults[1])); - } - if(!punishment && (punish & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) { - printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS); - punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; - punish_time = atoi((row[1] ? row[1] : defaults[1])); - } - if(!punishment && (punish & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) { - printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1]) { - printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT); - punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; - punish_time = atoi((row[1] ? row[1] : defaults[1])); - } - if(!punishment && (warn & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) { - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM); - } - if(!punishment && (warn & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) { - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD); - } - if(!punishment && (warn & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) { - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS); - } - if(!punishment && (warn & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) { - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT); - } - if(punishment) { - char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; - char *banmask = NULL; - switch (punishment) { - case 3: //TIMEBAN - banmask = generate_banmask(chanuser->user, banmaskBuf); - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (punish_time ? (time(0) + punish_time) : 0), 0, escape_string(reason)); - if(punish_time) { - int banid = (int) mysql_insert_id(get_mysql_conn()); - char nameBuf[MAXLEN]; - char banidBuf[20]; - sprintf(nameBuf, "ban_%d", banid); - sprintf(banidBuf, "%d", banid); - timeq_add_name(nameBuf, punish_time, channel_ban_timeout, strdup(banidBuf)); - } - case 2: //KICKBAN - if(!banmask) - banmask = generate_banmask(chanuser->user, banmaskBuf); - putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); - case 1: //KICK - putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason); - break; - } - } else if(*reason) - reply(client, chanuser->user, "%s", reason); -} - -static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { - //crc32 hash of the message - unsigned long msghash = crc32(message); - if(chanuser->spamnode) { - if(chanuser->spamnode->lastmsg == msghash) { - chanuser->spamnode->spamcount++; - if(chanuser->spamnode->spamcount == settings->spam_amount) - return SPAMSERV_CHECK_WARN; - else if(chanuser->spamnode->spamcount > settings->spam_amount) - return SPAMSERV_CHECK_PUNISH; - else - return SPAMSERV_CHECK_IGNORE; - } - } else - createSpamNode(chanuser); - chanuser->spamnode->lastmsg = msghash; - chanuser->spamnode->spamcount = 1; - return SPAMSERV_CHECK_IGNORE; -} - -static int neonspam_update_penalty(struct NeonSpamSettings *settings, struct ChanUser *chanuser, int addmsg) { - int last_update = time(0) - chanuser->spamnode->last_penalty_update; - if(last_update) { - if(last_update < MAX_FLOOD_TIME && chanuser->spamnode->floodpenalty) { - chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX]); - if(chanuser->spamnode->floodpenalty < 0) - chanuser->spamnode->floodpenalty = 0; - } else - chanuser->spamnode->floodpenalty = 0; - chanuser->spamnode->last_penalty_update = time(0); - } - chanuser->spamnode->floodpenalty += MAX_FLOOD_TIME * addmsg; - return chanuser->spamnode->floodpenalty / MAX_FLOOD_TIME + ((chanuser->spamnode->floodpenalty % MAX_FLOOD_TIME) ? 1 : 0); -} - -static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) { - if(!chanuser->spamnode) - createSpamNode(chanuser); - int messages_pending = neonspam_update_penalty(settings, chanuser, 1); - if(messages_pending == settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX]) - return SPAMSERV_CHECK_WARN; - else if(messages_pending > settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX]) - return SPAMSERV_CHECK_PUNISH; - else - return SPAMSERV_CHECK_IGNORE; -} - -static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { - //crc32 hash of the message - unsigned long msghash = crc32(message); - if((time(0) - settings->lastmsg_time) > BOTNETSCAN_TIME || settings->lastmsg != msghash) { - int i; - for(i = 0; i < BOTNETSCAN_USERS; i++) { - if(settings->botnicks[i]) { - free(settings->botnicks[i]); - settings->botnicks[i] = NULL; - } - } - settings->flags &= ~SPAMSETTINGS_KICKEDBOTQUEUE; - settings->lastmsg = msghash; - } else if(settings->lastmsg == msghash) { - int i; - for(i = 0; i < BOTNETSCAN_USERS; i++) { - if(!settings->botnicks[i]) { - settings->botnicks[i] = strdup(chanuser->user->nick); - break; - } else if(!stricmp(chanuser->user->nick, settings->botnicks[i])) { - return SPAMSERV_CHECK_IGNORE; - } - } - if(i == BOTNETSCAN_USERS) { - //BOTNETSCAN_USERS exceeded - if(!(settings->flags & SPAMSETTINGS_KICKEDBOTQUEUE)) { - for(i = 0; i < BOTNETSCAN_USERS; i++) { - putsock(client, "KICK %s %s :%s", chanuser->chan->name, settings->botnicks[i], SPAMSERV_MSG_BOTNET); - } - settings->flags |= SPAMSETTINGS_KICKEDBOTQUEUE; - } - putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, SPAMSERV_MSG_BOTNET); - return SPAMSERV_CHECK_DEAD; - } - } - settings->lastmsg_time = time(0); - return SPAMSERV_CHECK_IGNORE; -} - -static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { - int caps = 0, msglen = strlen(message); - int i; - if(msglen <= 4) return SPAMSERV_CHECK_IGNORE; - for(i = 0; i < msglen; i++) { - if(isupper(message[i])) caps++; - } - caps = 100*caps/msglen; - if(caps >= settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX]) { - if(!chanuser->spamnode) - createSpamNode(chanuser); - if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_CAPSSCAN_WARNED) - return SPAMSERV_CHECK_PUNISH; - else { - chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_CAPSSCAN_WARNED; - return SPAMSERV_CHECK_WARN; - } - } - return SPAMSERV_CHECK_IGNORE; -} - -static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { - int digit = 0, msglen = strlen(message); - int i; - if(msglen <= 4) return SPAMSERV_CHECK_IGNORE; - for(i = 0; i < msglen; i++) { - if(isdigit(message[i])) digit++; - } - digit = 100*digit/msglen; - if(digit >= settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX]) { - if(!chanuser->spamnode) - createSpamNode(chanuser); - if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_DIGITSCAN_WARNED) - return SPAMSERV_CHECK_PUNISH; - else { - chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_DIGITSCAN_WARNED; - return SPAMSERV_CHECK_WARN; - } - } - return SPAMSERV_CHECK_IGNORE; -} - diff --git a/src/event_neonspam_join.c b/src/event_neonspam_join.c deleted file mode 100644 index 5a169f2..0000000 --- a/src/event_neonspam_join.c +++ /dev/null @@ -1,145 +0,0 @@ -/* event_neonspam_join.c - NeonServ v5.3 - * Copyright (C) 2011-2012 Philipp Kreil (pk910) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup); -static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action); -static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser); - -struct neonspam_event_join_cache { - struct ClientSocket *client; - struct ChanUser *chanuser; - struct NeonSpamSettings *settings; - int action; -}; - -static void neonspam_event_join(struct ChanUser *chanuser) { - if(chanuser->user->flags & USERFLAG_WAS_REGISTRING) return; - struct ClientSocket *client = getChannelBot(chanuser->chan, BOTID); - if(!client) return; //we can't "see" this event - if(chanuser->user == client->user) { - requestOp(client->user, chanuser->chan); - return; - } - if(chanuser->user->flags & USERFLAG_ISBOT) return; - loadNeonSpamSettings(chanuser->chan); - struct NeonSpamSettings *settings = chanuser->chan->spam_settings; - if(!settings || !(settings->flags & SPAMSETTINGS_JOINSCAN)) return; - if(settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 0) return; - int result = neonspam_joinfloodscan(settings, chanuser); - if(result != SPAMSERV_CHECK_IGNORE) { - //whois the user to check against exceptlevel - if((chanuser->user->flags & USERFLAG_ISAUTHED) || settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 501) { - neonspam_event_join_punish(client, chanuser, settings, result); - } else { - struct neonspam_event_join_cache *cache = malloc(sizeof(*cache)); - if (!cache) { - perror("malloc() failed"); - return; - } - cache->client = client; - cache->chanuser = chanuser; - cache->settings = settings; - cache->action = result; - get_userauth(chanuser->user, neonspam_event_join_nick_lookup, cache); - } - } -} - -static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup) { - struct neonspam_event_join_cache *cache = data; - neonspam_event_join_punish(cache->client, cache->chanuser, cache->settings, cache->action); - free(cache); -} - -static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action) { - int uaccess = 0; - if(chanuser->user->flags & USERFLAG_ISAUTHED) - uaccess = getChannelAccess(chanuser->user, chanuser->chan); - if(uaccess >= settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX]) return; - //scanops / scanvoiced - MYSQL_RES *res; - MYSQL_ROW row, defaults = NULL; - loadChannelSettings(chanuser->chan); - printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); - res = mysql_use(); - row = mysql_fetch_row(res); - if(!row[0] || !row[1] || !row[2] || !row[3]) { - printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); - res = mysql_use(); - defaults = mysql_fetch_row(res); - } - if(!(settings->flags & SPAMSETTINGS_JOINSCAN_OPS) && uaccess >= atoi((row[2] ? row[2] : defaults[2]))) return; - if(!(settings->flags & SPAMSETTINGS_JOINSCAN_VOICE) && uaccess >= atoi((row[3] ? row[3] : defaults[3]))) return; - char reason[MAXLEN]; - sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_JOINFLOOD); - if(action == SPAMSERV_CHECK_WARN) { - reply(client, chanuser->user, "%s", reason); - } else if(action == SPAMSERV_CHECK_PUNISH) { - int duration = atoi((row[1] ? row[1] : defaults[1])); - char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; - char *banmask = NULL; - switch (atoi((row[0] ? row[0] : defaults[0]))) { - case 2: //TIMEBAN - banmask = generate_banmask(chanuser->user, banmaskBuf); - printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (duration ? (time(0) + duration) : 0), 0, escape_string(reason)); - if(duration) { - int banid = (int) mysql_insert_id(get_mysql_conn()); - char nameBuf[MAXLEN]; - char banidBuf[20]; - sprintf(nameBuf, "ban_%d", banid); - sprintf(banidBuf, "%d", banid); - timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); - } - case 1: //KICKBAN - if(!banmask) - banmask = generate_banmask(chanuser->user, banmaskBuf); - putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); - case 0: //KICK - putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason); - break; - } - } -} - -static int neonspam_update_join_penalty(struct NeonSpamSettings *settings, struct NeonSpamJoinNode *joinnode, int addjoin) { - int last_update = time(0) - joinnode->last_penalty_update; - if(last_update) { - if(last_update < MAX_JOIN_TIME && joinnode->joinpenalty) { - joinnode->joinpenalty -= last_update * (MAX_JOIN_TIME / settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX]); - if(joinnode->joinpenalty < 0) - joinnode->joinpenalty = 0; - } else - joinnode->joinpenalty = 0; - joinnode->last_penalty_update = time(0); - } - joinnode->joinpenalty += MAX_JOIN_TIME * addjoin; - return joinnode->joinpenalty / MAX_JOIN_TIME + ((joinnode->joinpenalty % MAX_JOIN_TIME) ? 1 : 0); -} - -static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) { - if(!chanuser->spamnode) - createSpamNode(chanuser); - int joins_pending = neonspam_update_join_penalty(settings, getNeonSpamJoinNode(chanuser), 1); - if(joins_pending == settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX]) - return SPAMSERV_CHECK_WARN; - else if(joins_pending > settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX]) - return SPAMSERV_CHECK_PUNISH; - else - return SPAMSERV_CHECK_IGNORE; -} - - diff --git a/src/lang.c b/src/lang.c index 1c0a027..b56322c 100644 --- a/src/lang.c +++ b/src/lang.c @@ -135,13 +135,18 @@ void register_default_language_table(const struct default_language_entry *msgtab void register_language_string(struct language *lang, char *ident, char *text) { int cindex = get_entry_index(ident); - struct language_table *lang_entry = malloc(sizeof(*lang_entry)); - if (!lang_entry) { - perror("malloc() failed"); - return; + struct language_table *lang_entry; + for(lang_entry = lang->entrys[cindex]; lang_entry; lang_entry = lang_entry->next) { + if(!strcmp(lang_entry->ident, ident)) break; + } + if(!lang_entry) { + lang_entry = malloc(sizeof(*lang_entry)); + if (!lang_entry) { + perror("malloc() failed"); + return; + } + lang_entry->ident = strdup(ident); } - - lang_entry->ident = strdup(ident); //replace all: //$b to \002 //$k to \003 diff --git a/src/lang.h b/src/lang.h index 162d6ae..2115050 100644 --- a/src/lang.h +++ b/src/lang.h @@ -39,16 +39,17 @@ struct language { struct language_table **entrys; }; +#ifndef DND_FUNCTIONS void init_lang(); void free_lang(); -struct language* get_language_by_tag(char *tag); -struct language* get_language_by_name(char *name); -struct language* get_default_language(); +/* MODULAR ACCESSIBLE */ struct language* get_language_by_tag(char *tag); +/* MODULAR ACCESSIBLE */ struct language* get_language_by_name(char *name); +/* MODULAR ACCESSIBLE */ struct language* get_default_language(); void load_languages(); -void load_language(char *tag, char *name); +/* MODULAR ACCESSIBLE */ void load_language(char *tag, char *name); void register_language_string(struct language *lang, char *ident, char *text); -void register_default_language_table(const struct default_language_entry *msgtab); -char *get_language_string(struct UserNode *user, const char* msg_ident); -char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...); - -#endif \ No newline at end of file +/* MODULAR ACCESSIBLE */ void register_default_language_table(const struct default_language_entry *msgtab); +/* MODULAR ACCESSIBLE */ char *get_language_string(struct UserNode *user, const char* msg_ident); +/* MODULAR ACCESSIBLE */ char *build_language_string(struct UserNode *user, char *buffer, const char *msg_ident, ...); +#endif +#endif diff --git a/src/main.c b/src/main.c index 79043b1..0ca3d31 100644 --- a/src/main.c +++ b/src/main.c @@ -61,6 +61,7 @@ static pthread_mutex_t log_sync; static void check_firstrun(); void cleanup() { + stop_modules(); free_sockets(); qserver_free(); free_parser(); @@ -69,7 +70,6 @@ void cleanup() { free_bind(); free_modcmd(); free_whoqueue(); - free_bots(); free_mysql(); free_handleinfohandler(); free_lang(); @@ -282,7 +282,7 @@ main: init_modcmd(); init_handleinfohandler(); init_tools(); - register_commands(); + init_bots(); init_DBHelper(); qserver_init(); @@ -290,9 +290,9 @@ main: load_languages(); int update_minutes = get_int_field("statistics.frequency"); if(!update_minutes) update_minutes = 2; - timeq_add(update_minutes * 60 + 10, main_statistics, NULL); + timeq_add(update_minutes * 60 + 10, 0, main_statistics, NULL); - timeq_add(90, main_checkauths, NULL); + timeq_add(90, 0, main_checkauths, NULL); int worker_threads = get_int_field("General.worker_threads"); if(!worker_threads) worker_threads = 1; @@ -307,7 +307,7 @@ main: int usleep_delay = 1000000 / TICKS_PER_SECOND; while(running) { timeq_tick(); - loop_bots(); + loop_modules(); qserver_loop(); queue_loop(); mysql_free(); @@ -329,7 +329,7 @@ main: } } while(time(0) < socket_wait); timeq_tick(); - loop_bots(); + loop_modules(); clearTempUsers(); destroyEvents(); qserver_loop(); @@ -472,13 +472,13 @@ TIMEQ_CALLBACK(main_checkauths) { } } - timeq_add(next_call, main_checkauths, NULL); + timeq_add(next_call, 0, main_checkauths, NULL); } TIMEQ_CALLBACK(main_statistics) { int update_minutes = get_int_field("statistics.frequency"); if(!update_minutes) update_minutes = 2; - timeq_add(update_minutes * 60, main_statistics, NULL); + timeq_add(update_minutes * 60, 0, main_statistics, NULL); if(get_int_field("statistics.enable")) { statistics_enabled = 1; statistics_requested_lusers = 1; @@ -518,6 +518,14 @@ void statistics_update() { } } +time_t getStartTime() { + return start_time; +} + +int getRunningThreads() { + return running_threads; +} + void write_log(int loglevel, const char *line, int len) { SYNCHRONIZE(log_sync); if(!daemonized && (print_loglevel & loglevel)) { diff --git a/src/main.h b/src/main.h index eb39d49..f143031 100644 --- a/src/main.h +++ b/src/main.h @@ -16,139 +16,9 @@ */ #ifndef _main_h #define _main_h -#include "../config.h" - -#define NEONSERV_VERSION "5.3" -#define VERSION_PATCHLEVEL 543 - -#include -#include -#include -#include -#ifdef WIN32 -#include -#include -#include -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#ifdef HAVE_THREADS -#include -#ifdef WIN32 -#define pthread_self_tid() pthread_self().p -#else -#define pthread_self_tid() pthread_self() -#endif -#define THREAD_MUTEX_INIT(var) { \ - pthread_mutexattr_t mutex_attr; \ - pthread_mutexattr_init(&mutex_attr);\ - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);\ - pthread_mutex_init(&var, &mutex_attr); \ -} -#define THREAD_MUTEX_INIT_TYPE(var, type) { \ - pthread_mutexattr_t mutex_attr; \ - pthread_mutexattr_init(&mutex_attr);\ - pthread_mutexattr_settype(&mutex_attr, type);\ - pthread_mutex_init(&var, &mutex_attr); \ -} -#define SYNCHRONIZE(var) pthread_mutex_lock(&var) -#define SET_SYNCHRONIZE(var) pthread_mutex_trylock(&var) -#define DESYNCHRONIZE(var) pthread_mutex_unlock(&var) -#else -#define THREAD_MUTEX_INIT(var) -#define SYNCHRONIZE(var) -#define DESYNCHRONIZE(var) -#endif - -#if __GNUC__ -#define PRINTF_LIKE(M,N) __attribute__((format (printf, M, N))) -#else -#define PRINTF_LIKE(M,N) -#endif - -#if __GNUC__ >= 2 -#define UNUSED_ARG(ARG) ARG __attribute__((unused)) -#elif defined(S_SPLINT_S) -#define UNUSED_ARG(ARG) /*@unused@*/ ARG -#define const /*@observer@*/ /*@temp@*/ -#else -#define UNUSED_ARG(ARG) ARG -#endif - -#define STRINGIFY_(x) #x -#define STRINGIFY(x) STRINGIFY_(x) - -#if defined(__GNUC__) -#if defined(__GNUC_PATCHLEVEL__) -#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__) -#else -#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) -#endif -#elif defined (__IMAGECRAFT__) -#define COMPILER "ICCAVR" -#else -#define COMPILER "Unknown" -#endif - -#ifdef ENABLE_MEMORY_DEBUG -#include "memoryDebug.h" -#endif - -#define PID_FILE "neonserv.pid" -#define CONF_FILE "neonserv.conf" -#define LOG_FILE "neonserv.log" - -#define SOCKET_SELECT_TIME 1 -#define SOCKET_RECONNECT_TIME 20 - -#define NICKLEN 30 -#define USERLEN 10 -#define AUTHLEN 32 -#define HOSTLEN 63 -#define REALLEN 50 -#define TOPICLEN 500 -#define CHANNELLEN 200 -#define MAXLEN 512 -#define MAXLOGLEN 1024 -#define TRIGGERLEN 50 -#define MAXNUMPARAMS 200 /* maximum number of parameters in one line */ -#define MAXLANGUAGES 5 -#define MAXMODES 6 -#define INVITE_TIMEOUT 30 -#define BOTWAR_DETECTION_TIME 7 -#define BOTWAR_DETECTION_EVENTS 6 -#define REWHO_TIMEOUT 10 /* wait 10 seconds before WHO an unauthed user again */ -#define TICKS_PER_SECOND 10 - -//valid nick chars -#define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`" -//the first char is a little bit different -// 0 1 2 3 4 5 6 -// 1234567890123456789012345678901234567890123456789012345678 9012 62 -#define VALID_NICK_CHARS_FIRST "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~[\\]^_`" -#define VALID_NICK_CHARS_FIRST_LEN 62 - -#define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN - -#define LOGLEVEL_INFO 0x01 -#define LOGLEVEL_ERROR 0x02 -#define LOGLEVEL_RAW 0x04 -#define LOGLEVEL_MYSQL 0x08 - -#define timeval_is_bigger(x,y) ((x.tv_sec > y.tv_sec) || (x.tv_sec == y.tv_sec && x.tv_usec > y.tv_usec)) +#include "overall.h" +#ifndef DND_FUNCTIONS extern time_t start_time; extern int statistics_enabled; #ifdef HAVE_THREADS @@ -156,24 +26,25 @@ extern int running_threads; extern pthread_mutex_t cache_sync; extern pthread_mutex_t whohandler_sync, whohandler_mass_sync; -int getCurrentThreadID(); +/* MODULAR ACCESSIBLE */ int getCurrentThreadID(); #endif +/* MODULAR ACCESSIBLE */ time_t getStartTime(); +/* MODULAR ACCESSIBLE */ int getRunningThreads(); + void exit_daemon(); -int stricmp (const char *s1, const char *s2); -int stricmplen (const char *s1, const char *s2, int len); +/* MODULAR ACCESSIBLE */ int stricmp (const char *s1, const char *s2); +/* MODULAR ACCESSIBLE */ int stricmplen (const char *s1, const char *s2, int len); -void restart_process(); -void cleanup(); -void restart_bot(int do_hard_restart); -void stop_bot(); -void reload_config(); +/* MODULAR ACCESSIBLE */ void restart_process(); +/* MODULAR ACCESSIBLE */ void cleanup(); +/* MODULAR ACCESSIBLE */ void restart_bot(int do_hard_restart); +/* MODULAR ACCESSIBLE */ void stop_bot(); +/* MODULAR ACCESSIBLE */ void reload_config(); void statistics_update(); -void putlog(int loglevel, const char *text, ...) PRINTF_LIKE(2, 3); - -#define perror(errmsg) (putlog(LOGLEVEL_ERROR, "ERROR (%s:%d) %s", __FILE__, __LINE__, errmsg)) - +/* MODULAR ACCESSIBLE */ void putlog(int loglevel, const char *text, ...) PRINTF_LIKE(2, 3); +#endif #endif \ No newline at end of file diff --git a/src/memoryDebug.c b/src/memoryDebug.c index e870f4b..b8cb9ce 100644 --- a/src/memoryDebug.c +++ b/src/memoryDebug.c @@ -113,35 +113,6 @@ static void remove_mem_info(void *mem_ref) { DESYNCHRONIZE(synchronized); } -void report_mem_leak() { - SYNCHRONIZE(synchronized); - struct MemoryLeak *leak_info; - FILE *fp_write = fopen(OUTPUT_FILE, "wt"); - char info[1024]; - - if(fp_write != NULL) { - sprintf(info, "%s\n", "Memory Leak Summary"); - fwrite(info, (strlen(info)) , 1, fp_write); - sprintf(info, "%s\n", "-----------------------------------"); - fwrite(info, (strlen(info)) , 1, fp_write); - - for(leak_info = ptr_start; leak_info != NULL; leak_info = leak_info->next) { - sprintf(info, "address : %p\n", leak_info->mem_info.address); - fwrite(info, (strlen(info)) , 1, fp_write); - sprintf(info, "size : %d bytes\n", leak_info->mem_info.size); - fwrite(info, (strlen(info)) , 1, fp_write); - sprintf(info, "file : %s\n", leak_info->mem_info.file_name); - fwrite(info, (strlen(info)) , 1, fp_write); - sprintf(info, "line : %d\n", leak_info->mem_info.line); - fwrite(info, (strlen(info)) , 1, fp_write); - sprintf(info, "%s\n", "-----------------------------------"); - fwrite(info, (strlen(info)) , 1, fp_write); - } - } - fclose(fp_write); - DESYNCHRONIZE(synchronized); -} - void initMemoryDebug() { THREAD_MUTEX_INIT(synchronized); } diff --git a/src/memoryDebug.h b/src/memoryDebug.h index c07d494..9a3adac 100644 --- a/src/memoryDebug.h +++ b/src/memoryDebug.h @@ -22,12 +22,12 @@ #define strdup(data) xstrdup (data, __FILE__, __LINE__) #define free(mem_ref) xfree(mem_ref) -void *xmalloc(unsigned int size, const char *file, unsigned int line); -void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line); -char *xstrdup(const char *data, const char *file, unsigned int line); -void xfree(void *mem_ref); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ void *xmalloc(unsigned int size, const char *file, unsigned int line); +/* MODULAR ACCESSIBLE */ void *xcalloc(unsigned int elements, unsigned int size, const char *file, unsigned int line); +/* MODULAR ACCESSIBLE */ char *xstrdup(const char *data, const char *file, unsigned int line); +/* MODULAR ACCESSIBLE */ void xfree(void *mem_ref); -void report_mem_leak(); void initMemoryDebug(); - +#endif #endif diff --git a/src/memoryInfo.h b/src/memoryInfo.h index f1cca21..f6987bf 100644 --- a/src/memoryInfo.h +++ b/src/memoryInfo.h @@ -24,9 +24,10 @@ struct memoryInfoFiles { struct memoryInfoFiles *next; }; -struct memoryInfoFiles *getMemoryInfoFiles(); -void freeMemoryInfoFiles(struct memoryInfoFiles *files); - +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ struct memoryInfoFiles *getMemoryInfoFiles(); +/* MODULAR ACCESSIBLE */ void freeMemoryInfoFiles(struct memoryInfoFiles *files); +#endif struct memoryInfoLines { unsigned int line; @@ -35,8 +36,9 @@ struct memoryInfoLines { struct memoryInfoLines *next; }; -struct memoryInfoLines *getMemoryInfoLines(const char *filename); -void freeMemoryInfoLines(struct memoryInfoLines *lines); - +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ struct memoryInfoLines *getMemoryInfoLines(const char *filename); +/* MODULAR ACCESSIBLE */ void freeMemoryInfoLines(struct memoryInfoLines *lines); +#endif #endif diff --git a/src/modcmd.c b/src/modcmd.c index 8846d90..7ba0b93 100644 --- a/src/modcmd.c +++ b/src/modcmd.c @@ -30,6 +30,7 @@ struct trigger_callback { int botid; + int module_id; trigger_callback_t *func; struct trigger_callback *next; @@ -596,7 +597,7 @@ static void got_privmsg(struct UserNode *user, struct UserNode *target, char *me } } -int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) { +int register_command(int botid, char *name, int module_id, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags) { struct cmd_function *cmdfunc; for(cmdfunc = cmd_functions; cmdfunc; cmdfunc = cmdfunc->next) { if((cmdfunc->botid == botid || cmdfunc->botid == 0) && strcmp(cmdfunc->name, name) == 0) @@ -609,6 +610,7 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, ch } cmdfunc->botid = botid; cmdfunc->name = strdup(name); + cmdfunc->module_id = module_id; cmdfunc->func = func; cmdfunc->flags = flags; cmdfunc->paramcount = paramcount; @@ -619,7 +621,7 @@ int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, ch return 1; } -int set_trigger_callback(int botid, trigger_callback_t *func) { +int set_trigger_callback(int botid, int module_id, trigger_callback_t *func) { static struct trigger_callback *cb = NULL; for(cb = trigger_callbacks; cb; cb = cb->next) { if(cb->botid == botid) @@ -635,6 +637,7 @@ int set_trigger_callback(int botid, trigger_callback_t *func) { cb->next = trigger_callbacks; trigger_callbacks = cb; } + cb->module_id = module_id; cb->func = func; return 1; } @@ -769,13 +772,13 @@ int unbind_botwise_cmd(int botid, int clientid, char *cmd) { return 0; } -int unbind_botwise_allcmd(int clientid) { +int unbind_botwise_allcmd(int botid, int clientid) { int i; for(i = 0; i < 27; i++) { struct cmd_binding *cbind, *next, *last = NULL; for(cbind = cmd_binds[i]; cbind; cbind = next) { next = cbind->next; - if(clientid == cbind->clientid) { + if((botid == 0 && clientid == cbind->clientid) || (botid && botid == cbind->botid)) { if(last) last->next = cbind->next; else @@ -1011,3 +1014,54 @@ struct cmd_binding *getAllBinds(struct cmd_binding *last) { } while(bind_index < 27); return NULL; } + +void unregister_module_commands(int module_id) { + struct cmd_function *cmdfunct, *nextfunct, *prevfunct = NULL; + int i; + for(cmdfunct = cmd_functions; cmdfunct; cmdfunct = nextfunct) { + nextfunct = cmdfunct->next; + if(cmdfunct->module_id == module_id) { + for(i = 0; i < 27; i++) { + struct cmd_binding *cbind, *next, *last = NULL; + for(cbind = cmd_binds[i]; cbind; cbind = next) { + next = cbind->next; + if(cmdfunct == cbind->func) { + if(last) + last->next = cbind->next; + else + cmd_binds[i] = cbind->next; + free(cbind->cmd); + if(cbind->paramcount) { + int j; + for(j = 0; j < cbind->paramcount; j++) + free(cbind->parameters[j]); + } + if(cbind->channel_access) + free(cbind->channel_access); + free(cbind); + } else + last = cbind; + } + } + if(prevfunct) + prevfunct->next = nextfunct; + else + cmd_functions = nextfunct; + free(cmdfunct->name); + free(cmdfunct); + } else + prevfunct = cmdfunct; + } + static struct trigger_callback *cb, *prevcb = NULL, *nextcb; + for(cb = trigger_callbacks; cb; cb = nextcb) { + nextcb = cb->next; + if(cb->module_id == module_id) { + if(prevcb) + prevcb->next = nextcb; + else + trigger_callbacks = nextcb; + free(cb); + } else + prevcb = cb; + } +} diff --git a/src/modcmd.h b/src/modcmd.h index 7465254..0ccd7f5 100644 --- a/src/modcmd.h +++ b/src/modcmd.h @@ -49,6 +49,7 @@ typedef void trigger_callback_t(int clientid, struct ChanNode *chan, char *trigg struct cmd_function { char *name; int botid; + int module_id; cmd_bind_t *func; unsigned int flags; int paramcount; @@ -83,54 +84,49 @@ struct trigger_cache { struct trigger_cache *next; }; -extern int statistics_commands; - -void init_modcmd(); -void free_modcmd(); - #define get_prefered_bot(BOTID) get_botwise_prefered_bot(BOTID, 0) -struct ClientSocket* get_botwise_prefered_bot(int botid, int clientid); - -int register_command(int botid, char *name, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags); -int set_trigger_callback(int botid, trigger_callback_t *func); - -int flush_trigger_cache(int botid, int clientid); - #define changeChannelTrigger(BOTID,CHAN,NEW) changeBotwiseChannelTrigger(BOTID, 0, CHAN, NEW) -int changeBotwiseChannelTrigger(int botid, int clientid, struct ChanNode *chan, char *new_trigger); - #define bind_cmd_to_function(BOTID,CMD,FUNC) bind_botwise_cmd_to_function(BOTID, 0, CMD, FUNC) -int bind_botwise_cmd_to_function(int botid, int clientid, char *cmd, struct cmd_function *func); - #define bind_cmd_to_command(BOTID,CMD,FUNC) bind_botwise_cmd_to_command(BOTID, 0, CMD, FUNC) -int bind_botwise_cmd_to_command(int botid, int clientid, char *cmd, char *func); - #define unbind_cmd(BOTID,CMD) unbind_botwise_cmd(BOTID, 0, CMD) -int unbind_botwise_cmd(int botid, int clientid, char *cmd); - -int unbind_botwise_allcmd(int clientid); - +#define unbind_allcmd(BOTID) unbind_botwise_allcmd(BOTID, 0) #define bind_set_parameters(BOTID,CMD,PARAMETERS) bind_botwise_set_parameters(BOTID, 0, CMD, PARAMETERS) -void bind_botwise_set_parameters(int botid, int clientid, char *cmd, char *parameters); - #define bind_set_global_access(BOTID,CMD,GACCESS) bind_botwise_set_global_access(BOTID, 0, CMD, GACCESS) -void bind_botwise_set_global_access(int botid, int clientid, char *cmd, int gaccess); - #define bind_set_channel_access(BOTID,CMD,CACCESS) bind_botwise_set_channel_access(BOTID, 0, CMD, CACCESS) -void bind_botwise_set_channel_access(int botid, int clientid, char *cmd, char *chanaccess); - #define bind_set_bind_flags(BOTID,CMD,FLAGS) bind_botwise_set_bind_flags(BOTID, 0, CMD, FLAGS) -void bind_botwise_set_bind_flags(int botid, int clientid, char *cmd, unsigned int flags); - #define find_cmd_binding(BOTID,CMD) find_botwise_cmd_binding(BOTID, 0, CMD) -struct cmd_binding *find_botwise_cmd_binding(int botid, int clientid, char *cmd); - #define bind_unbound_required_functions(BOTID) bind_botwise_unbound_required_functions(BOTID, 0) -void bind_botwise_unbound_required_functions(int botid, int clientid); -struct cmd_function *find_cmd_function(int botid, char *name); -struct ClientSocket *getTextBot(); -void register_command_alias(int botid, char *alias); -struct cmd_binding *getAllBinds(struct cmd_binding *last); -#endif \ No newline at end of file +#ifndef DND_FUNCTIONS +extern int statistics_commands; + +void init_modcmd(); +void free_modcmd(); + +/* MODULAR ACCESSIBLE */ struct ClientSocket* get_botwise_prefered_bot(int botid, int clientid); + +/* MODULAR ACCESSIBLE */ int register_command(int botid, char *name, int module_id, cmd_bind_t *func, int paramcount, char *channel_access, int global_access, unsigned int flags); +/* MODULAR ACCESSIBLE */ int set_trigger_callback(int botid, int module_id, trigger_callback_t *func); + +/* MODULAR ACCESSIBLE */ int flush_trigger_cache(int botid, int clientid); +/* MODULAR ACCESSIBLE */ int changeBotwiseChannelTrigger(int botid, int clientid, struct ChanNode *chan, char *new_trigger); +/* MODULAR ACCESSIBLE */ int bind_botwise_cmd_to_function(int botid, int clientid, char *cmd, struct cmd_function *func); +/* MODULAR ACCESSIBLE */ int bind_botwise_cmd_to_command(int botid, int clientid, char *cmd, char *func); +/* MODULAR ACCESSIBLE */ int unbind_botwise_cmd(int botid, int clientid, char *cmd); +/* MODULAR ACCESSIBLE */ int unbind_botwise_allcmd(int botid, int clientid); +/* MODULAR ACCESSIBLE */ void bind_botwise_set_parameters(int botid, int clientid, char *cmd, char *parameters); +/* MODULAR ACCESSIBLE */ void bind_botwise_set_global_access(int botid, int clientid, char *cmd, int gaccess); +/* MODULAR ACCESSIBLE */ void bind_botwise_set_channel_access(int botid, int clientid, char *cmd, char *chanaccess); +/* MODULAR ACCESSIBLE */ void bind_botwise_set_bind_flags(int botid, int clientid, char *cmd, unsigned int flags); +/* MODULAR ACCESSIBLE */ struct cmd_binding *find_botwise_cmd_binding(int botid, int clientid, char *cmd); +/* MODULAR ACCESSIBLE */ void bind_botwise_unbound_required_functions(int botid, int clientid); +/* MODULAR ACCESSIBLE */ struct cmd_function *find_cmd_function(int botid, char *name); +/* MODULAR ACCESSIBLE */ struct ClientSocket *getTextBot(); +/* MODULAR ACCESSIBLE */ void register_command_alias(int botid, char *alias); +/* MODULAR ACCESSIBLE */ struct cmd_binding *getAllBinds(struct cmd_binding *last); + +void unregister_module_commands(int module_id); + +#endif +#endif diff --git a/src/modules.c b/src/modules.c new file mode 100644 index 0000000..0c2034e --- /dev/null +++ b/src/modules.c @@ -0,0 +1,407 @@ +/* modules.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "modules.h" + +/* 000-011 */ #include "main.h" +/* 012 */ #include "BanNode.h" +/* 013-019 */ #include "bots.h" +/* 020-025 */ #include "ChanNode.h" +/* 026-029 */ #include "ChanUser.h" +/* 030-036 */ #include "ClientSocket.h" +/* 037-038 */ #include "ConfigParser.h" +/* 039-048 */ #include "DBHelper.h" +/* 049 */ #include "EventLogger.h" +/* 050 */ #include "HandleInfoHandler.h" +/* 051-088 */ #include "IRCEvents.h" +/* 089-091 */ #include "IRCParser.h" +/* 092-098 */ #include "lang.h" +#ifdef ENABLE_MEMORY_DEBUG +/* 099-102 */ #include "memoryDebug.h" +#endif +/* 103-106 */ #include "memoryInfo.h" +/* 107-125 */ #include "modcmd.h" +/* 126-136 */ #include "ModeNode.h" +/* 137-142 */ #include "mysqlConn.h" +/* 143-149 */ #include "timeq.h" +/* 150-169 */ #include "tools.h" +/* 170-178 */ #include "UserNode.h" +/* 179 */ #include "version.h" +/* 180-182 */ #include "WHOHandler.h" + +void **global_functions = { +/* 000 */ getStartTime, +/* 001 */ getRunningThreads, +/* 002 */ exit_daemon, +/* 003 */ stricmp, +/* 004 */ stricmplen, +/* 005 */ restart_process, +/* 006 */ cleanup, +/* 007 */ restart_bot, +/* 008 */ stop_bot, +/* 009 */ reload_config, +/* 010 */ putlog, +#ifdef HAVE_THREADS +/* 011 */ getCurrentThreadID, +#else +/* 011 */ NULL, +#endif +/* 012 */ getMatchingChannelBan, +/* 013 */ getChannelBot, +/* 014 */ requestOp, +/* 015 */ channel_ban_timeout, +/* 016 */ general_event_privctcp, +/* 017 */ set_bot_alias, +/* 018 */ resolve_botid, +/* 019 */ resolve_botalias, +/* 020 */ is_valid_chan, +/* 021 */ getAllChans, +/* 022 */ getChanByName, +/* 023 */ getChannelCount, +/* 024 */ getChanUserCount, +/* 025 */ getChanBanCount, +/* 026 */ isUserOnChan, +/* 027 */ getChanUser, +/* 028 */ getChannelUsers, +/* 029 */ getUserChannels, +/* 030 */ create_socket, +/* 031 */ connect_socket, +/* 032 */ close_socket, +/* 033 */ disconnect_socket, +/* 034 */ write_socket, +/* 035 */ putsock, +/* 036 */ getBots, +/* 037 */ get_int_field, +/* 038 */ get_string_field, +/* 039 */ _loadUserSettings, +/* 040 */ isGodMode, +/* 041 */ getChanDefault, +/* 042 */ getChannelAccess, +/* 043 */ checkChannelAccess, +/* 044 */ _loadChannelSettings, +/* 045 */ isUserProtected, +/* 046 */ getBanAffectingMask, +/* 047 */ renameAccount, +/* 048 */ deleteUser, +/* 049 */ logEvent, +/* 050 */ lookup_authname, +/* 051 */ bind_join, +/* 052 */ unbind_join, +/* 053 */ bind_nick, +/* 054 */ unbind_nick, +/* 055 */ bind_part, +/* 056 */ unbind_part, +/* 057 */ bind_quit, +/* 058 */ unbind_quit, +/* 059 */ bind_kick, +/* 060 */ unbind_kick, +/* 061 */ bind_topic, +/* 062 */ unbind_topic, +/* 063 */ bind_mode, +/* 064 */ unbind_mode, +/* 065 */ bind_chanmsg, +/* 066 */ unbind_chanmsg, +/* 067 */ bind_privmsg, +/* 068 */ unbind_privmsg, +/* 069 */ bind_channotice, +/* 070 */ unbind_channotice, +/* 071 */ bind_privnotice, +/* 072 */ unbind_privnotice, +/* 073 */ bind_chanctcp, +/* 074 */ unbind_chanctcp, +/* 075 */ bind_privctcp, +/* 076 */ unbind_privctcp, +/* 077 */ bind_invite, +/* 078 */ unbind_invite, +/* 079 */ bind_raw, +/* 080 */ unbind_raw, +/* 081 */ bind_bot_ready, +/* 082 */ unbind_bot_ready, +/* 083 */ bind_registered, +/* 084 */ unbind_registered, +/* 085 */ bind_freeuser, +/* 086 */ unbind_freeuser, +/* 087 */ bind_freechan, +/* 088 */ unbind_freechan, +/* 089 */ reply, +/* 090 */ merge_argv, +/* 091 */ merge_argv_char, +/* 092 */ get_language_by_tag, +/* 093 */ get_language_by_name, +/* 094 */ get_default_language, +/* 095 */ load_language, +/* 096 */ register_default_language_table, +/* 097 */ get_language_string, +/* 098 */ build_language_string, +#ifdef ENABLE_MEMORY_DEBUG +/* 099 */ xmalloc, +/* 100 */ xcalloc, +/* 101 */ xstrdup, +/* 102 */ xfree, +#else +/* 099 */ NULL, +/* 100 */ NULL, +/* 101 */ NULL, +/* 102 */ NULL, +#endif +/* 103 */ getMemoryInfoFiles, +/* 104 */ freeMemoryInfoFiles, +/* 105 */ getMemoryInfoLines, +/* 106 */ freeMemoryInfoLines, +/* 107 */ get_botwise_prefered_bot, +/* 108 */ register_command, +/* 109 */ set_trigger_callback, +/* 110 */ flush_trigger_cache, +/* 111 */ changeBotwiseChannelTrigger, +/* 112 */ bind_botwise_cmd_to_function, +/* 113 */ bind_botwise_cmd_to_command, +/* 114 */ unbind_botwise_cmd, +/* 115 */ unbind_botwise_allcmd, +/* 116 */ bind_botwise_set_parameters, +/* 117 */ bind_botwise_set_global_access, +/* 118 */ bind_botwise_set_channel_access, +/* 119 */ bind_botwise_set_bind_flags, +/* 120 */ find_botwise_cmd_binding, +/* 121 */ bind_botwise_unbound_required_functions, +/* 122 */ find_cmd_function, +/* 123 */ getTextBot, +/* 124 */ register_command_alias, +/* 125 */ getAllBinds, +/* 126 */ createModeNode, +/* 127 */ freeModeNode, +/* 128 */ isModeSet, +/* 129 */ isModeAffected, +/* 130 */ getModeValue, +/* 131 */ getModeType, +/* 132 */ parseModes, +/* 133 */ parseModeString, +/* 134 */ parseMode, +/* 135 */ getModeString, +/* 136 */ getFullModeString, +/* 137 */ mysql_use, +/* 138 */ mysql_free, +/* 139 */ printf_mysql_query, +/* 140 */ printf_long_mysql_query, +/* 141 */ escape_string, +/* 142 */ get_mysql_conn, +/* 143 */ timeq_add, +/* 144 */ timeq_uadd, +/* 145 */ timeq_add_name, +/* 146 */ timeq_uadd_name, +/* 147 */ timeq_del, +/* 148 */ timeq_del_name, +/* 149 */ timeq_name_exists, +/* 150 */ match, +/* 151 */ table_init, +/* 152 */ table_add, +/* 153 */ table_change, +/* 154 */ table_change_field, +/* 155 */ table_set_bold, +/* 156 */ table_end, +/* 157 */ table_free, +/* 158 */ timeToStr, +/* 159 */ strToTime, +/* 160 */ initModeBuffer, +/* 161 */ modeBufferSet, +/* 162 */ flushModeBuffer, +/* 163 */ freeModeBuffer, +/* 164 */ is_ircmask, +/* 165 */ generate_banmask, +/* 166 */ make_banmask, +/* 167 */ isFakeHost, +/* 168 */ mask_match, +/* 169 */ crc32, +/* 170 */ is_valid_nick, +/* 171 */ getUserByNick, +/* 172 */ getUserByMask, +/* 173 */ countUsersWithHost, +/* 174 */ getAuthFakehost, +/* 175 */ searchUserByNick, +/* 176 */ getAllUsers, +/* 177 */ getUsersWithAuth, +/* 178 */ getUserCount, +/* 179 */ get_userlist, +/* 180 */ _get_userlist_with_invisible, +/* 181 */ get_userauth, +/* 182 */ &compilation, +/* 183 */ &creation, +/* 184 */ &revision, +/* 185 */ &codelines, +/* 186 */ &patchlevel +}; + +#define MODINFO_STATE_STARTED 0x01 + +struct ModuleInfo { + char *name; + int module_id; + #ifndef WIN32 + void *module; + #else + HMODULE module; + #endif + int state; + void *startfunc; + void *loopfunc; + void *stopfunc; + struct ModuleInfo *next; +} + +static int module_id_counter = 1; +static struct ModuleInfo *modules = NULL; + +static void unregister_module_hooks(int module_id); + +int loadModule(char *name) { + char fname[256]; + #ifndef WIN32 + sprintf(fname, "%s.so", name); + void* module = dlopen(fname, RTLD_LAZY); + if(!module) { + putlog(LOGLEVEL_ERROR, "Error loading module '%s': %s not found.", name, fname); + return 0; + } + void* initfunc = dlsym(module, "init_module"); + void* startfunc = dlsym(module, "start_module"); + void* loopfunc = dlsym(module, "loop_module"); + void* stopfunc = dlsym(module, "stop_module"); + void* modversion = dlsym(module, "modversion"); + #else + sprintf(fname, "%s.dll", name); + HMODULE module = LoadLibrary(fname); + if(!module) { + putlog(LOGLEVEL_ERROR, "Error loading module '%s': %s not found.", name, fname); + return 0; + } + FARPROC initfunc = GetProcAddress(module, "init_module"); + FARPROC startfunc = GetProcAddress(module, "start_module"); + FARPROC loopfunc = GetProcAddress(module, "loop_module"); + FARPROC stopfunc = GetProcAddress(module, "stop_module"); + FARPROC modversion = GetProcAddress(module, "modversion"); + #endif + if(!startfunc || !loopfunc || !stopfunc || !modversion) { + putlog(LOGLEVEL_ERROR, "Error loading module '%s': required symbols not found.", name); + return 0; + } + int version = ((int (*)(void)) modversion)(); + if(version != MODULE_VERSION) { + putlog(LOGLEVEL_ERROR, "Error loading module '%s': version mismatch ('%d' main code, '%d' module)", name, MODULE_VERSION, version); + return 0; + } + //start module + int errid; + int module_id = module_id_counter++; + if((errid = ((int (*)(void **, int)) initfunc)(global_functions, module_id))) { + putlog(LOGLEVEL_ERROR, "Error loading module '%s': module reported error (errid: %d)", name, errid); + return 0; + } + struct ModuleInfo *modinfo = malloc(sizeof(*modinfo)); + if(!modinfo) { + unregister_module_hooks(module_id); + return 0; + } + modinfo->name = strdup(name); + modinfo->module_id = module_id; + modinfo->module = module; + modinfo->startfunc = startfunc; + modinfo->loopfunc = loopfunc; + modinfo->stopfunc = stopfunc; + modinfo->next = modules; + modules = modinfo; + return 1; +} + +#ifndef WIN32 +static void closemodule(void *module) { + dlclose(module); +} +#else +static void closemodule(HMODULE module) { + FreeLibrary(module); +} +#endif + +int reload_module(char *name) { + struct ModuleInfo *old_modinfo, *old_prev = NULL; + for(old_modinfo = modules; old_modinfo; old_modinfo = old_modinfo->next) { + if(old_prev) + old_prev->next = old_modinfo->next; + else + modules = old_modinfo->next; + unregister_module_hooks(old_modinfo->module_id); + ((void (*)(void)) old_modinfo->stopfunc)(MODSTATE_RELOAD); + closemodule(old_modinfo->module); + free(old_modinfo->name); + free(old_modinfo); + break; + } else + old_prev = old_modinfo; + if(!loadModule(name)) return 0; + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + if(!(modinfo->state & MODINFO_STATE_STARTED)) { + modinfo->state |= MODINFO_STATE_STARTED; + ((void (*)(void)) modinfo->startfunc)(MODSTATE_STARTSTOP); + } else + ((void (*)(void)) modinfo->startfunc)(MODSTATE_REBIND); + } +} + +void start_modules() { + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + if(!(modinfo->state & MODINFO_STATE_STARTED)) { + modinfo->state |= MODINFO_STATE_STARTED; + ((void (*)(void)) modinfo->startfunc)(MODSTATE_STARTSTOP); + } + } +} + +void loop_modules() { + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + ((void (*)(void)) modinfo->loopfunc)(); + } +} + +void stop_modules() { + struct ModuleInfo *modinfo, *next; + for(modinfo = modules; modinfo; modinfo = next) { + next = modinfo->next; + unregister_module_hooks(modinfo->module_id); + ((void (*)(int)) modinfo->stopfunc)(MODSTATE_STARTSTOP); + closemodule(modinfo->module); + free(modinfo->name); + free(modinfo); + } + modules = NULL; +} + +static void unregister_module_hooks(int module_id) { + unregister_module_commands(module_id); + unregister_module_events(module_id); + unregister_module_timers(module_id); +} + +int module_loaded(int module_id) { + if(!module_id) return 1; + struct ModuleInfo *modinfo; + for(modinfo = modules; modinfo; modinfo = modinfo->next) { + if(modinfo->module_id == module_id) + return 1; + } + return 0; +} diff --git a/src/modules.h b/src/modules.h new file mode 100644 index 0000000..321b5c1 --- /dev/null +++ b/src/modules.h @@ -0,0 +1,26 @@ +/* modules.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _modules_h +#define _modules_h + +void load_module(char *name); +void start_modules(); +void loop_modules(); +void stop_modules(); +int module_loaded(int module_id); + +#endif \ No newline at end of file diff --git a/src/modules/DummyServ.mod/bot_DummyServ.c b/src/modules/DummyServ.mod/bot_DummyServ.c new file mode 100644 index 0000000..9d9d720 --- /dev/null +++ b/src/modules/DummyServ.mod/bot_DummyServ.c @@ -0,0 +1,141 @@ +/* bot_DummyServ.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" + +#include "bot_DummyServ.h" +#include "modcmd.h" +#include "IRCParser.h" +#include "IRCEvents.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "ModeNode.h" +#include "BanNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "version.h" +#include "EventLogger.h" +#include "bots.h" +#include "cmd_neonserv.h" +#include "cmd_neonspam.h" + +#define BOTID 3 +#define BOTALIAS "DummyServ" + +static void dummyserv_bot_ready(struct ClientSocket *client) { + MYSQL_RES *res; + MYSQL_ROW row; + + printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "MODE %s +%s", client->user->nick, row[0]); + } + + printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "JOIN %s %s", row[0], row[1]); + } +} + +static void dummyserv_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { + //this bot doesn't have a trigger + strcpy(trigger, ""); +} + +static void start_bots(int type) { + struct ClientSocket *client; + MYSQL_RES *res, *res2; + MYSQL_ROW row; + + if(type == MODSTATE_STARTSTOP) { + printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); + client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); + client->flags |= SOCKET_FLAG_SILENT; + client->botid = BOTID; + client->clientid = atoi(row[7]); + connect_socket(client); + } + } + + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); + res2 = mysql_use(); + while ((row = mysql_fetch_row(res2)) != NULL) { + if(bind_cmd_to_command(BOTID, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_set_parameters(BOTID, row[0], row[2]); + } + if(row[3]) { + bind_set_global_access(BOTID, row[0], atoi(row[3])); + } + if(row[4]) { + bind_set_channel_access(BOTID, row[0], row[4]); + } + if(strcmp(row[5], "0")) + bind_set_bind_flags(BOTID, row[0], atoi(row[5])); + } + } + bind_unbound_required_functions(BOTID); +} + +void init_DummyServ(int type) { + set_bot_alias(BOTID, BOTALIAS); + start_bots(type); + + if(type == MODSTATE_REBIND) return; + + //register events + bind_bot_ready(dummyserv_bot_ready); + + set_trigger_callback(BOTID, dummyserv_trigger_callback); +} + +void loop_DummyServ() { + +} + +void free_DummyServ(int type) { + unbind_allcmd(BOTID); + if(type == MODSTATE_STARTSTOP) { + //disconnect all our bots + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->botid == BOTID) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } +} + +#undef BOTID +#undef BOTALIAS diff --git a/src/modules/DummyServ.mod/bot_DummyServ.h b/src/modules/DummyServ.mod/bot_DummyServ.h new file mode 100644 index 0000000..7483fec --- /dev/null +++ b/src/modules/DummyServ.mod/bot_DummyServ.h @@ -0,0 +1,26 @@ +/* bot_DummyServ.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _bot_DummyServ_h +#define _bot_DummyServ_h + +#include "main.h" + +void init_DummyServ(int type); +void loop_DummyServ(); +void free_DummyServ(int type); + +#endif \ No newline at end of file diff --git a/src/modules/DummyServ.mod/module.c b/src/modules/DummyServ.mod/module.c new file mode 100644 index 0000000..1213b68 --- /dev/null +++ b/src/modules/DummyServ.mod/module.c @@ -0,0 +1,36 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "bot_DummyServ.h" + +static int module_initialize() { + return 0; +} + +static void module_start(int type) { + init_DummyServ(type); +} + +static void module_loop() { + loop_DummyServ(); +} + +static void module_stop(int type) { + free_DummyServ(type); +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/NeonHelp.mod/bot_NeonHelp.c b/src/modules/NeonHelp.mod/bot_NeonHelp.c new file mode 100644 index 0000000..f3df2fc --- /dev/null +++ b/src/modules/NeonHelp.mod/bot_NeonHelp.c @@ -0,0 +1,552 @@ +/* bot_NeonHelp.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "bot_NeonHelp.h" +#include "modcmd.h" +#include "cmd_neonhelp.h" +#include "lang.h" +#include "mysqlConn.h" +#include "ClientSocket.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "IRCEvents.h" +#include "IRCParser.h" +#include "bots.h" +#include "DBHelper.h" +#include "WHOHandler.h" + +#define BOTID 4 +#define BOTALIAS "NeonHelp" + +static const struct default_language_entry msgtab[] = { + {"NH_NOT_ON_CHAN_1", "You cannot open this request as you are not in %s."}, /* {ARGS: "#test"} */ + {"NH_NOT_ON_CHAN_2", "You cannot open this request as you are not in %s or %s."}, /* {ARGS: "test", "#test-support"} */ + {"NH_REQUEST_RECORDED", "Your message has been recorded and assigned request ID#%d A helper should contact you shortly."}, /* {ARGS: 5} */ + {"NH_REQUEST_OTHERS_0", "There are no other unhandled requests."}, + {"NH_REQUEST_OTHERS_1", "There is 1 other unhandled request."}, + {"NH_REQUEST_OTHERS_2", "There are %d other unhandled requests."}, /* {ARGS: 1337} */ + {"NH_REQUEST_FOOTER_1", "Everything you tell me until you are helped (or you leave %1$s) will be recorded. If you part %1$s, your request will be lost."}, /* {ARGS: "#test"} */ + {"NH_REQUEST_FOOTER_2", "Everything you tell me until you are helped (or you leave %1$s or %2$s) will be recorded. If you part %1$s or %2$s, your request will be lost."}, /* {ARGS: "#test", "#test-support"} */ + {"NH_NEW_REQUEST", "New request #%d by %s: %s"}, /* {ARGS: 5, "pk910", "Help, I've fallen and I can't get up!"} */ + {"NH_NEXT_NONE", "No more requests."}, + {"NH_NEXT_NOT_FOUND", "No request found."}, + {"NH_NEXT_HEADER", "$bNext request: #%d %s$b"}, /* {ARGS: 5, "pk910"} */ + {"NH_NEXT_HELPER", "Your helper for request ID#%d is %s (Current nick: %s)."}, /* {ARGS: 5, "pk910", "Skynet"} */ + {"NH_NEXT_JOIN", "Please /join %s now."}, /* {ARGS: "#test-support"} */ + {"NH_DELETED", "Your request ID#%d has been deleted."}, /* {ARGS: 5} */ + {"NH_DELETED_STAFF", "Request deleted: #%d (%s)"}, /* {ARGS: 5, "pk910"} */ + {"NH_REMIND_OPEN_REQUESTS_1", "There is %d unhandled request!"}, /* {ARGS: 1} */ + {"NH_REMIND_OPEN_REQUESTS_2", "There are %d unhandled requests!"}, /* {ARGS: 4} */ + {"NH_REQUESTS_HEADER_ID", "ID"}, + {"NH_REQUESTS_HEADER_STATUS", "State"}, + {"NH_REQUESTS_HEADER_NICK", "Nick"}, + {"NH_REQUESTS_HEADER_TIME", "Time"}, + {"NH_REQUESTS_HEADER_REQUEST", "Question"}, + {"NH_REQUESTS_STATE_ACTIVE", "active"}, + {"NH_REQUESTS_STATE_PENDING", "pending"}, + {"NH_REQUESTS_STATE_ERROR", "ERROR"}, + {"NH_STATS_HEADER_USER", "User"}, + {"NH_STATS_HEADER_LAST_24H", "last 24h"}, + {"NH_STATS_HEADER_LAST_7DAY", "last 7d"}, + {"NH_STATS_HEADER_LAST_30DAY", "last 30d"}, + {NULL, NULL} +}; + +static void neonhelp_bot_ready(struct ClientSocket *client) { + MYSQL_RES *res; + MYSQL_ROW row; + + printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "MODE %s +%s", client->user->nick, row[0]); + } + + printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "JOIN %s %s", row[0], row[1]); + } +} + +static void neonhelp_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { + MYSQL_RES *res; + MYSQL_ROW row; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + strcpy(trigger, "!"); + return; + } + printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + strcpy(trigger, "!"); + return; + } + if(row[0] && *row[0]) + strcpy(trigger, row[0]); + else + strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "!")); +} + +static void start_bots(int type) { + struct ClientSocket *client; + MYSQL_RES *res, *res2; + MYSQL_ROW row; + + if(type == MODSTATE_STARTSTOP) { + printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); + client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); + client->flags |= SOCKET_FLAG_SILENT; + client->botid = BOTID; + client->clientid = atoi(row[7]); + connect_socket(client); + //close old, still opened requests + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `botid` = '%d'", client->clientid); + } + } + + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); + res2 = mysql_use(); + while ((row = mysql_fetch_row(res2)) != NULL) { + if(bind_cmd_to_command(BOTID, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_set_parameters(BOTID, row[0], row[2]); + } + if(row[3]) { + bind_set_global_access(BOTID, row[0], atoi(row[3])); + } + if(row[4]) { + bind_set_channel_access(BOTID, row[0], row[4]); + } + if(strcmp(row[5], "0")) + bind_set_bind_flags(BOTID, row[0], atoi(row[5])); + } + } + bind_unbound_required_functions(BOTID); +} + +static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message); +static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup); +struct neonhelp_event_privmsg_cache { + struct ClientSocket *client; + struct UserNode *user, *target; + char *message; +}; + +static void neonhelp_event_privmsg(struct UserNode *user, struct UserNode *target, char *message) { + struct ClientSocket *client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->user == target) { + if(client->botid != BOTID) return; + break; + } + } + if(!client) return; //we got the message but we have no client that could receive it??? + if(user->flags & USERFLAG_ISAUTHED) { + neonhelp_event_privmsg_async(client, user, target, message); + } else { + struct neonhelp_event_privmsg_cache *cache = malloc(sizeof(*cache)); + if(!cache) return; + cache->client = client; + cache->user = user; + cache->target = target; + cache->message = strdup(message); + get_userauth(user, neonhelp_event_privmsg_nick_lookup, cache); + } +} + +static USERAUTH_CALLBACK(neonhelp_event_privmsg_nick_lookup) { + struct neonhelp_event_privmsg_cache *cache = data; + neonhelp_event_privmsg_async(cache->client, cache->user, cache->target, cache->message); + free(cache->message); + free(cache); +} + +static TIMEQ_CALLBACK(neonhelp_remind_open_requests); + +static void neonhelp_event_privmsg_async(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, char *message) { + MYSQL_RES *res; + MYSQL_ROW row, row2; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern`, `helpserv_intern_announce` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int caccess = 0; + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + if(caccess) return; //ignore messages from supporters + } + //check if the user is in one of the bot's channels + struct ChanUser *chanuser; + struct ChanNode *chan; + for(chanuser = getUserChannels(target, NULL); chanuser; chanuser = getUserChannels(target, chanuser)) { + chan = chanuser->chan; + if((!stricmp(chan->name, row[0]) || (row[1] && !stricmp(chan->name, row[1]))) && isUserOnChan(user, chan)) + break; + } + if(!chanuser) { + if(row[1]) + reply(client, user, "NH_NOT_ON_CHAN_2", row[0], row[1]); + else + reply(client, user, "NH_NOT_ON_CHAN_1", row[0]); + return; + } + //check if there is already a support request + int others = 0; + if(client->flags & SOCKET_HAVE_HELPNODE) { + struct NeonHelpNode *helpnode; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == user) { + //simply append the message to the database + printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = %d", helpnode->suppid); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + char *old_msg = escape_string(row2[0]); + char *new_msg = escape_string(message); + printf_long_mysql_query(1024 + strlen(old_msg) + strlen(new_msg), "UPDATE `helpserv_requests` SET `text` = '%s\n%s' WHERE `id` = %d", old_msg, new_msg, helpnode->suppid); + } + return; + } + others++; + } + } + //add new request + struct NeonHelpNode *helpnode = malloc(sizeof(*helpnode)); + if(!helpnode) return; + helpnode->user = user; + helpnode->logchan = getChanByName(row[0]); + helpnode->status = 0; + helpnode->announce = (row[2] && strcmp(row[3], "0") ? 1 : 0); + if(helpnode->announce) { + char nameBuf[30]; + sprintf(nameBuf, "neonhelp_%d", client->clientid); + if(!timeq_name_exists(nameBuf)) { + int *cidptr = malloc(sizeof(int)); + *cidptr = client->clientid; + timeq_add_name(nameBuf, 300, neonhelp_remind_open_requests, cidptr); + } + } + printf_mysql_query("INSERT INTO `helpserv_requests` (`botid`, `host`, `hand`, `nick`, `status`, `supporter`, `time`, `text`) VALUES ('%d', '%s@%s', '%s', '%s', '0', '-1', UNIX_TIMESTAMP(), '%s')", client->clientid, escape_string(user->ident), escape_string(user->host), ((user->flags & USERFLAG_ISAUTHED) ? escape_string(user->auth) : "*"), escape_string(user->nick), escape_string(message)); + helpnode->suppid = (int) mysql_insert_id(get_mysql_conn()); + helpnode->log = NULL; + helpnode->next = ((client->flags & SOCKET_HAVE_HELPNODE) ? client->botclass_helpnode : NULL); + client->botclass_helpnode = helpnode; + client->flags |= SOCKET_HAVE_HELPNODE; + //build the user reply... + char user_reply[MAXLEN]; + int user_reply_pos = 0; + char reply_buff[MAXLEN]; + //1st part: NH_REQUEST_RECORDED + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_RECORDED", helpnode->suppid)); + user_reply_pos += strlen(reply_buff); + //2nd part: NH_REQUEST_OTHERS_0 / NH_REQUEST_OTHERS_1 / NH_REQUEST_OTHERS_2 + user_reply[user_reply_pos++] = ' '; + if(others <= 1) + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, (others ? "NH_REQUEST_OTHERS_1" : "NH_REQUEST_OTHERS_0"))); + else + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_OTHERS_2", others)); + user_reply_pos += strlen(reply_buff); + //3th part: NH_REQUEST_FOOTER_1 / NH_REQUEST_FOOTER_2 + user_reply[user_reply_pos++] = ' '; + if(row[1]) + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_2", row[0], row[1])); + else + strcpy(user_reply + user_reply_pos, build_language_string(user, reply_buff, "NH_REQUEST_FOOTER_1", row[0])); + user_reply_pos += strlen(reply_buff); + reply(client, user, "%s", user_reply); + //sent a message to the internal channel / onotice to supp channel + build_language_string(user, reply_buff, "NH_NEW_REQUEST", helpnode->suppid, user->nick, message); + if(row[2]) { + putsock(client, "PRIVMSG %s :%s", row[2], reply_buff); + } else { + putsock(client, "NOTICE @%s :%s", row[0], reply_buff); + } +} + +static TIMEQ_CALLBACK(neonhelp_remind_open_requests) { + int clientid = *((int*)data); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern`, `helpserv_intern_announce` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res)) || !row[2]) { + free(data); + return; + } + struct ClientSocket *client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->clientid == clientid) + break; + } + if(!client) { + free(data); + return; + } + //count open requests + int requests = 0; + struct NeonHelpNode *helpnode; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->status == 0) { + requests++; + } + } + } + if(requests) { + char nameBuf[30]; + sprintf(nameBuf, "neonhelp_%d", client->clientid); + if(!timeq_name_exists(nameBuf)) { + timeq_add_name(nameBuf, 300, neonhelp_remind_open_requests, data); + } + char replybuf[MAXLEN]; + build_language_string(NULL, replybuf, (requests == 1 ? "NH_REMIND_OPEN_REQUESTS_1" : "NH_REMIND_OPEN_REQUESTS_2"), requests); + putsock(client, "PRIVMSG %s :%s", row[2], replybuf); + } else + free(data); +} + +static void neonhelp_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { + char logline[MAXLEN]; + sprintf(logline, "<%s> %s", user->nick, message); + struct ClientSocket *client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID) { + struct NeonHelpNode *helpnode; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->logchan == chan && helpnode->status == 1) { + if(!helpnode->log) { + helpnode->log = calloc(LOGBUFFERLINES, sizeof(char*)); + if(!helpnode->log) return; + } + int i; + for(i = 0; i < LOGBUFFERLINES; i++) { + if(!helpnode->log[i]) { + helpnode->log[i] = strdup(logline); + break; + } + } + if(i == LOGBUFFERLINES) { + //write buffer to database + char logbuff[MAXLEN * LOGBUFFERLINES]; + int len = 0; + for(i = 0; i < LOGBUFFERLINES; i++) { + len += sprintf(logbuff + len, "%s\n", helpnode->log[i]); + free(helpnode->log[i]); + helpnode->log[i] = NULL; + } + printf_long_mysql_query(1024 + len, "UPDATE `helpserv_requests` SET `log` = CONCAT(`log`, '%s') WHERE `id` = %d", escape_string(logbuff), helpnode->suppid); + } + break; + } + } + } + } + } +} + +static void destroy_support_request(struct ClientSocket *client, struct NeonHelpNode *helpnode, int do_reply) { + //write buffer to database + char logbuff[MAXLEN * LOGBUFFERLINES]; + int len = 0; + int i; + if(helpnode->log) { + for(i = 0; i < LOGBUFFERLINES; i++) { + if(!helpnode->log[i]) break; + len += sprintf(logbuff + len, "%s\n", helpnode->log[i]); + free(helpnode->log[i]); + helpnode->log[i] = NULL; + } + free(helpnode->log); + } else + logbuff[0] = '\0'; + printf_long_mysql_query(1024 + len, "UPDATE `helpserv_requests` SET `status`='2', `log` = CONCAT(`log`, '%s') WHERE `id` = %d", escape_string(logbuff), helpnode->suppid); + if(do_reply) { + reply(client, helpnode->user, "NH_DELETED", helpnode->suppid); + } + free(helpnode); +} + +static void neonhelp_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { + struct ClientSocket *client; + MYSQL_RES *res; + MYSQL_ROW row; + struct ChanNode *support, *public; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target->user) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) continue; + support = getChanByName(row[0]); + public = (row[1] ? getChanByName(row[1]) : NULL); + if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 1); + } + } + } +} + +static void neonhelp_event_part(struct ChanUser *target, char *reason) { + struct ClientSocket *client; + MYSQL_RES *res; + MYSQL_ROW row; + struct ChanNode *support, *public; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID && isUserOnChan(client->user, target->chan)) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target->user) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) continue; + support = getChanByName(row[0]); + public = (row[1] ? getChanByName(row[1]) : NULL); + if(target->chan == support || !((support && isUserOnChan(target->user, support)) || (public && isUserOnChan(target->user, public)))) { + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 1); + } + } + } +} + +static void neonhelp_event_quit(struct UserNode *target, char *reason) { + struct ClientSocket *client; + int userHasRequest; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->botid == BOTID) { + userHasRequest = 0; + struct NeonHelpNode *helpnode, *prev_helpnode = NULL; + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->user == target) { + userHasRequest = 1; + break; + } else + prev_helpnode = helpnode; + } + } + if(!userHasRequest) continue; + //free the user's support request + if(prev_helpnode) + prev_helpnode->next = helpnode->next; + else + client->botclass_helpnode = helpnode->next; + destroy_support_request(client, helpnode, 0); + } + } +} + +void init_NeonHelp(int type) { + set_bot_alias(BOTID, BOTALIAS); + start_bots(); + + if(type == MODSTATE_REBIND) return; + + //register events + bind_bot_ready(neonhelp_bot_ready); + bind_privmsg(neonhelp_event_privmsg); + bind_chanmsg(neonhelp_event_chanmsg); + bind_part(neonhelp_event_part); + bind_kick(neonhelp_event_kick); + bind_quit(neonhelp_event_quit); + + set_trigger_callback(BOTID, neonhelp_trigger_callback); + + register_default_language_table(msgtab); +} + +void loop_NeonHelp() { + +} + +void free_NeonHelp(int type) { + unbind_allcmd(BOTID); + if(type == MODSTATE_STARTSTOP) { + //disconnect all our bots + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->botid == BOTID) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } +} + +#undef BOTID +#undef BOTALIAS diff --git a/src/modules/NeonHelp.mod/bot_NeonHelp.h b/src/modules/NeonHelp.mod/bot_NeonHelp.h new file mode 100644 index 0000000..eaf47ff --- /dev/null +++ b/src/modules/NeonHelp.mod/bot_NeonHelp.h @@ -0,0 +1,45 @@ +/* bot_NeonHelp.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _bot_NeonHelp_h +#define _bot_NeonHelp_h + +#include "main.h" + +/* definition for ClientSocket struct */ +#define botclass_helpnode botclassvalue1 +#define SOCKET_HAVE_HELPNODE SOCKET_HAVE_BOTCLASSVALUE1 + +#define LOGBUFFERLINES 20 + +struct UserNode; +struct ChanNode; + +struct NeonHelpNode { + struct UserNode *user; + int suppid; + char status:6; + char announce:2; + struct NeonHelpNode *next; + struct ChanNode *logchan; + char **log; +}; + +void init_NeonHelp(int type); +void loop_NeonHelp(); +void free_NeonHelp(int type); + +#endif \ No newline at end of file diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp.c b/src/modules/NeonHelp.mod/cmd_neonhelp.c new file mode 100644 index 0000000..252d112 --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp.c @@ -0,0 +1,34 @@ +/* cmd_neonhelp.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_neonhelp.h" +#include "modcmd.h" +#include "ConfigParser.h" + +void register_commands() { + //NeonHelp Commands + register_command_alias(4, "NeonHelp"); + + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(4, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) + // NAME FUNCTION PARAMS PRIVS FLAGS + USER_COMMAND("next", neonhelp_cmd_next, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("delete", neonhelp_cmd_delete, 1, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("requests", neonhelp_cmd_requests, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("stats", neonhelp_cmd_stats, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + #undef USER_COMMAND + +} \ No newline at end of file diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp.h b/src/modules/NeonHelp.mod/cmd_neonhelp.h new file mode 100644 index 0000000..9a74fbf --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp.h @@ -0,0 +1,40 @@ +/* cmd_neonhelp.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _cmd_neonhelp_h +#define _cmd_neonhelp_h +#include "../module.h" +#include "main.h" +#include "modcmd.h" +#include "mysqlConn.h" +#include "ClientSocket.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "DBHelper.h" +#include "IRCParser.h" +#include "bot_NeonHelp.h" +#include "lang.h" +#include "tools.h" + +void register_commands(); + +CMD_BIND(neonhelp_cmd_delete); +CMD_BIND(neonhelp_cmd_next); +CMD_BIND(neonhelp_cmd_requests); +CMD_BIND(neonhelp_cmd_stats); + +#endif \ No newline at end of file diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp_delete.c b/src/modules/NeonHelp.mod/cmd_neonhelp_delete.c new file mode 100644 index 0000000..43d5829 --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp_delete.c @@ -0,0 +1,83 @@ +/* cmd_neonhelp_delete.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* argv[0] suppid +*/ + +CMD_BIND(neonhelp_cmd_delete) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { + reply(getTextBot(), user, "NH_NEXT_NONE"); + return; + } + struct NeonHelpNode *helpnode, *next_helpnode = NULL, *prev_helpnode = NULL; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(atoi(argv[0]) == helpnode->suppid) { + next_helpnode = helpnode; + break; + } else + prev_helpnode = helpnode; + } + if(!next_helpnode) { + reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); + return; + } + reply(client, next_helpnode->user, "NH_DELETED", next_helpnode->suppid); + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '2' WHERE `id` = '%d'", next_helpnode->suppid); + if(prev_helpnode) + prev_helpnode->next = next_helpnode->next; + else + client->botclass_helpnode = next_helpnode->next; + reply(getTextBot(), user, "NH_DELETED_STAFF", next_helpnode->suppid, next_helpnode->user->nick); + free(next_helpnode); +} diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp_next.c b/src/modules/NeonHelp.mod/cmd_neonhelp_next.c new file mode 100644 index 0000000..2e2a2d1 --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp_next.c @@ -0,0 +1,108 @@ +/* cmd_neonhelp_next.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* argv[0] (optional) suppid +*/ + +CMD_BIND(neonhelp_cmd_next) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + int userid; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + if(!(client->flags & SOCKET_HAVE_HELPNODE) || client->botclass_helpnode == NULL) { + reply(getTextBot(), user, "NH_NEXT_NONE"); + return; + } + struct NeonHelpNode *helpnode, *next_helpnode = NULL; + int lowest_id = -1; + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->status == 0) { + if(argc) { + if(atoi(argv[0]) == helpnode->suppid) { + next_helpnode = helpnode; + break; + } + } else { + if(helpnode->suppid < lowest_id || lowest_id == -1) { + lowest_id = helpnode->suppid; + next_helpnode = helpnode; + } + } + } + } + if(!next_helpnode) { + reply(getTextBot(), user, "NH_NEXT_NOT_FOUND"); + return; + } + printf_mysql_query("SELECT `text` FROM `helpserv_requests` WHERE `id` = '%d'", next_helpnode->suppid); + res = mysql_use(); + if (!(row2 = mysql_fetch_row(res))) return; + reply(getTextBot(), user, "NH_NEXT_HEADER", next_helpnode->suppid, next_helpnode->user->nick); + char *a, *b = row2[0]; + do { + a = strstr(b, "\n"); + if(a) *a = '\0'; + reply(getTextBot(), user, " %s", b); + if(a) { + *a = '\n'; + b = a+1; + } + } while(a); + if(row[1]) + putsock(client, "INVITE %s %s", next_helpnode->user->nick, row[0]); + else + putsock(client, "MODE %s +v %s", row[0], next_helpnode->user->nick); + char sendbuf1[MAXLEN]; + char sendbuf2[MAXLEN]; + char *join_now = (row[1] ? build_language_string(user, sendbuf2, "NH_NEXT_JOIN", row[0]) : ""); + putsock(client, "PRIVMSG %s :%s %s", next_helpnode->user->nick, build_language_string(user, sendbuf1, "NH_NEXT_HELPER", next_helpnode->suppid, user->auth, user->nick), join_now); + next_helpnode->status = 1; + printf_mysql_query("UPDATE `helpserv_requests` SET `status` = '1', `supporter` = '%d' WHERE `id` = '%d'", userid, next_helpnode->suppid); +} diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp_requests.c b/src/modules/NeonHelp.mod/cmd_neonhelp_requests.c new file mode 100644 index 0000000..b95a4b4 --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp_requests.c @@ -0,0 +1,108 @@ +/* cmd_neonhelp_requests.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* no args +*/ + +CMD_BIND(neonhelp_cmd_requests) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + int userid; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + struct Table *table; + printf_mysql_query("SELECT `id`, `time`, `text` FROM `helpserv_requests` WHERE `botid` = '%d' AND `status` != 2 ORDER BY `time` DESC", client->clientid); + res = mysql_use(); + table = table_init(5, mysql_num_rows(res) + 1, 0); + char *content[5]; + content[0] = get_language_string(user, "NH_REQUESTS_HEADER_ID"); + content[1] = get_language_string(user, "NH_REQUESTS_HEADER_STATUS"); + content[2] = get_language_string(user, "NH_REQUESTS_HEADER_NICK"); + content[3] = get_language_string(user, "NH_REQUESTS_HEADER_TIME"); + content[4] = get_language_string(user, "NH_REQUESTS_HEADER_REQUEST"); + table_add(table, content); + char timestr[MAXLEN]; + struct NeonHelpNode *helpnode; + int suppid; + while ((row = mysql_fetch_row(res)) != NULL) { + content[0] = row[0]; + suppid = atoi(row[0]); + if(client->flags & SOCKET_HAVE_HELPNODE) { + for(helpnode = client->botclass_helpnode; helpnode; helpnode = helpnode->next) { + if(helpnode->suppid == suppid) { + if(helpnode->status) + content[1] = get_language_string(user, "NH_REQUESTS_STATE_ACTIVE"); + else + content[1] = get_language_string(user, "NH_REQUESTS_STATE_PENDING"); + content[2] = helpnode->user->nick; + break; + } + } + } else { + content[1] = get_language_string(user, "NH_REQUESTS_STATE_ERROR"); + content[2] = NULL; + } + timeToStr(user, (time(0) - atoi(row[1])), 2, timestr); + content[3] = timestr; + char *p; + if((p = strstr(row[2], "\n"))) + *p = '\0'; + content[4] = row[2]; + table_add(table, content); + } + //send the table + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + if(table->entrys == 1) + reply(getTextBot(), user, "NS_TABLE_NONE"); + table_free(table); +} diff --git a/src/modules/NeonHelp.mod/cmd_neonhelp_stats.c b/src/modules/NeonHelp.mod/cmd_neonhelp_stats.c new file mode 100644 index 0000000..0d1d9a4 --- /dev/null +++ b/src/modules/NeonHelp.mod/cmd_neonhelp_stats.c @@ -0,0 +1,88 @@ +/* cmd_neonhelp_stats.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonhelp.h" + +/* +* argv[0] user +*/ + +CMD_BIND(neonhelp_cmd_stats) { + //check permissions + MYSQL_RES *res; + MYSQL_ROW row, row2; + int caccess = 0; + printf_mysql_query("SELECT `helpserv_support`, `helpserv_public`, `helpserv_intern` FROM `helpserv_settings` WHERE `helpserv_botid` = '%d'", client->clientid); + res = mysql_use(); + if (!(row = mysql_fetch_row(res))) return; + //check if the user is a supporter (access in the support channel) + if((user->flags & USERFLAG_ISAUTHED)) { + int userid; + if(user->flags & USERFLAG_HAS_USERID) + userid = user->user_id; + else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + userid = atoi(row2[0]); + user->user_id = userid; + user->flags |= USERFLAG_HAS_USERID; + } else + userid = 0; + } + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d' AND `channel_name` = '%s'", userid, escape_string(row[0])); + res = mysql_use(); + if ((row2 = mysql_fetch_row(res)) != NULL) { + int cflags = atoi(row2[1]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) + caccess = atoi(row2[0]); + } + } + if(!caccess) { + reply(getTextBot(), user, "MODCMD_ACCESS_DENIED"); + return; + } + if(argc > 0) { + //following + } else { + struct Table *table; + printf_mysql_query("SELECT DISTINCT a.`supporter`, `user_user`, (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24))), (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24*7))), (SELECT COUNT(*) FROM `helpserv_requests` AS b WHERE b.`supporter` = a.`supporter` AND b.`time` > (UNIX_TIMESTAMP()-(3600*24*7*4))) FROM `helpserv_requests` AS a LEFT JOIN `users` ON a.`supporter` = `user_id` WHERE a.`time` > (UNIX_TIMESTAMP()-(3600*24*7*4)) AND `botid` = '%d' ORDER BY `user_user` ASC", client->clientid); + res = mysql_use(); + table = table_init(4, mysql_num_rows(res) + 1, 0); + char *content[4]; + content[0] = get_language_string(user, "NH_STATS_HEADER_USER"); + content[1] = get_language_string(user, "NH_STATS_HEADER_LAST_24H"); + content[2] = get_language_string(user, "NH_STATS_HEADER_LAST_7DAY"); + content[3] = get_language_string(user, "NH_STATS_HEADER_LAST_30DAY"); + table_add(table, content); + while ((row = mysql_fetch_row(res)) != NULL) { + content[0] = (strcmp(row[0], "-1") ? row[1] : "-"); + content[1] = row[2]; + content[2] = row[3]; + content[3] = row[4]; + table_add(table, content); + } + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + if(table->entrys == 1) + reply(getTextBot(), user, "NS_TABLE_NONE"); + table_free(table); + } +} diff --git a/src/modules/NeonHelp.mod/module.c b/src/modules/NeonHelp.mod/module.c new file mode 100644 index 0000000..16ecc77 --- /dev/null +++ b/src/modules/NeonHelp.mod/module.c @@ -0,0 +1,38 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "bot_NeonHelp.h" +#include "cmd_neonhelp.h" + +static int module_initialize() { + register_commands(); + return 0; +} + +static void module_start(int type) { + init_NeonHelp(type); +} + +static void module_loop() { + loop_NeonHelp(); +} + +static void module_stop(int type) { + free_NeonHelp(type); +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/NeonServ.mod/bot_NeonServ.c b/src/modules/NeonServ.mod/bot_NeonServ.c new file mode 100644 index 0000000..e6ec912 --- /dev/null +++ b/src/modules/NeonServ.mod/bot_NeonServ.c @@ -0,0 +1,537 @@ +/* bot_NeonServ.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" + +#include "bot_NeonServ.h" +#include "modcmd.h" +#include "IRCEvents.h" +#include "IRCParser.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "BanNode.h" +#include "ModeNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "EventLogger.h" +#include "cmd_neonserv.h" +#include "ConfigParser.h" + +#define BOTID 1 +#define BOTALIAS "NeonServ" + +static const struct default_language_entry msgtab[] = { + {"NS_USER_UNKNOWN", "User with nick $b%s$b does not exist."}, /* {ARGS: "TestUser"} */ + {"NS_AUTH_UNKNOWN", "Account $b%s$b has not been registered."}, /* {ARGS: "TestAuth"} */ + {"NS_USER_NEED_AUTH", "%s must first authenticate with $bAuthServ$b."}, /* {ARGS: "TestUser"} */ + {"NS_YOU_NEED_AUTH", "You must first authenticate with $bAuthServ$b."}, + {"NS_INVALID_ACCESS", "$b%d$b is an invalid access level."}, /* {ARGS: 1337} */ + {"NS_ADDUSER_ALREADY_ADDED", "%s is already on the $b%s$b user list (with access %d)."}, /* {ARGS: "TestUser", "#TestChan", 123} */ + {"NS_ADDUSER_DONE", "Added %s to the %s user list with access %d."}, /* {ARGS: "TestUser", "#TestChan", 123} */ + {"NS_NOT_ON_USERLIST", "%s lacks access to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_NOT_ON_USERLIST_YOU", "You lack access to $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_NOT_ON_CHANNEL", "%s isn't currently in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_NOT_ON_CHANNEL_YOU", "You aren't currently in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DELUSER_DONE", "Deleted %s (with access %d) from the %s user list."}, /* {ARGS: "TestUser", 123, "#TestChan"} */ + {"NS_ACCESS_OUTRANKED", "You cannot give users access greater than or equal to your own."}, + {"NS_USER_OUTRANKED", "$b%s$b outranks you (command has no effect)."}, /* {ARGS: "TestUser"} */ + {"NS_ACCESS_DENIED", "Access denied."}, + {"NS_NO_ACCESS", "You lack sufficient access to use this command."}, + {"NS_USER_PROTECTED", "Sorry, $b%s$b is protected."}, /* {ARGS: "TestUser"} */ + {"NS_SERVICE_IMMUNE", "$b%s$b may not be kicked, killed, banned, or deopped."}, /* {ARGS: "TestUser"} */ + {"NS_YOU_PROTECTED", "You may not kick or ban yourself."}, + {"NS_TABLE_NONE", " None"}, + {"NS_TABLE_COUNT", "Found $b%d$b matches."}, /* {ARGS: 5} */ + {"NS_BAN_ALREADY_ADDED", "$b%s$b is already banned in %s."}, /* {ARGS: "*!*@moeeep.*", "#TestChan"} */ + {"NS_INVALID_ACCESS_RANGE", "Invalid access range; minimum (%d) must be lower than maximum (%d)."}, /* {ARGS: 450, 400} */ + {"NS_CLVL_DONE", "%s now has access $b%d$b in %s."}, /* {ARGS: "TestUser", 123, "#TestChan"} */ + {"NS_A_LACKS_ACCESS_BUT_GOD_NICK", "%s lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "#TestChan"} */ + {"NS_A_LACKS_ACCESS_BUT_GOD_AUTH", "%s (%s) lacks access to %s but has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", "#TestChan"} */ + {"NS_A_ACCESS_NICK", "%s has access $b%d$b in %s."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */ + {"NS_A_ACCESS_AUTH", "%s (%s) has access $b%d$b in %s."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */ + {"NS_A_ACCESS_NICK_GOD", "%s has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", 123, "#TestChan"} */ + {"NS_A_ACCESS_AUTH_GOD", "%s (%s) has access $b%d$b in %s and has $bsecurity override$b enabled."}, /* {ARGS: "TestAuth", "TestUser", 123, "#TestChan"} */ + {"NS_A_SUSPENDED", "$b%s$b's access to %s has been suspended."}, /* {ARGS: "TestAuth", "#TestChan"} */ + {"NS_A_IS_IRCOP", "%s is an $bIRC operator$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_USERS_HEADER", "%s users from level %d to %d:"}, /* {ARGS: "#TestChan", 1, 500} */ + {"NS_USERS_HEADER_MATCH", "%s users from level %d to %d matching %s:"}, /* {ARGS: "#TestChan", 1, 500, "Test*"} */ + {"NS_USERS_HEADER_ACCESS", "Access"}, + {"NS_USERS_HEADER_ACCOUNT", "Accout"}, + {"NS_USERS_HEADER_SEEN", "Last Seen"}, + {"NS_USERS_HEADER_STATE", "Status"}, + {"NS_USERS_COUNT", "There are $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_USERS_COUNT_1", "There is $b%d$b user in %s."}, /* {ARGS: 1, "#TestChan"} */ + {"NS_USERS_COUNT_MATCH", "There are $b%d$b users in %s. ($b%d$b matching your request)"}, /* {ARGS: 20, "#TestChan", 5} */ + {"NS_USERS_COUNT_MATCH_1", "There is $b%d$b user in %s. ($b%d$b matching your request)"}, /* {ARGS: 1, "#TestChan", 1} */ + {"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"}, + {"NS_SUSPEND_ALREADY", "$b%s$b is already suspended." }, /* {ARGS: "TestUser"} */ + {"NS_SUSPEND_NOT", "$b%s$b is not suspended." }, /* {ARGS: "TestUser"} */ + {"NS_SUSPEND_DONE", "$b%s$b's access to $b%s$b has been suspended." }, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_SUSPEND_RESTORED", "$b%s$b's access to $b%s$b has been restored." }, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_DELME_OWNER", "You cannot delete your owner access in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DELME_KEY", "To really remove yourself, you must use 'deleteme %s'."}, /* {ARGS: "abc123"} */ + {"NS_DELME_DONE", "Your $b%d$b access has been deleted from $b%s$b."}, /* {ARGS: 123, "#TestChan"} */ + {"NS_MYACCESS_SELF_ONLY", "You may only see the list of infolines for yourself (by using $bmyaccess$b with no arguments)."}, + {"NS_MYACCESS_HEADER", "Showing all channel entries for account $b%s$b:"}, /* {ARGS: "TestAuth"} */ + {"NS_MYACCESS_HEADER_MATCH", "Showing all channel entries for account $b%s$b matching %s:"}, /* {ARGS: "TestAuth", "#Test*"} */ + {"NS_MYACCESS_HEADER_NAME", "Name"}, + {"NS_MYACCESS_HEADER_ACCESS", "Access"}, + {"NS_MYACCESS_HEADER_FLAGS", "Flags"}, + {"NS_MYACCESS_HEADER_INFO", "Info"}, + {"NS_MYACCESS_COUNT", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s)."}, /* {ARGS: "TestUser", 15, 5} */ + {"NS_MYACCESS_COUNT_MATCH", "%s has access in $b%d$b channel(s) and is owner of $b%d$b channel(s) ($b%d$b channels matching your request)."}, /* {ARGS: "TestUser", 15, 5, 7} */ + {"NS_UP_ALREADY_OP", "You are already opped in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_UP_ALREADY_VOICE", "You are already voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DOWN_ALREADY", "You are not opped or voiced in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_MDELUSER_DONE", "Deleted $b%d$b account(s) matching $b%s$b with access from $b%d$b to $b%d$b from the %s user list."}, /* {ARGS: 10, "Test*", 1, 200, "#TestChan"} */ + {"NS_TRIM_DURATION_TOO_SHORT", "You must include a minimum inactivity duration of at least %d seconds to trim."}, + {"NS_TRIM_DONE", "Trimmed $b%d users$b with access from %d to %d from the %s user list who were inactive for at least %s."}, /* {ARGS: 10, 1, 100, "#TestChan", "10 days"} */ + {"NS_TRIM_BAN_DONE", "Trimmed $b%d bans$b from the %s ban list who were banned for at least %s."}, /* {ARGS: 5, "#TestChan", "1 day"} */ + {"NS_GIVEOWNER_SELF", "You cannot give ownership to your own account."}, + {"NS_GIVEOWNER_TIMEOUT", "You must wait %s before you can give ownership of $b%s$b to someone else."}, /* {ARGS: "5 hours", "#TestChan"} */ + {"NS_GIVEOWNER_CONFIRM", "To really give ownership to $b%1$s$b, you must use 'giveownership *%1$s %2$s'."}, /* {ARGS: "TestUser", "abc123"} */ + {"NS_GIVEOWNER_DONE", "Ownership of $b%s$b has been transferred to account $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */ + {"NS_OP_FAIL", "$b%s$b could not op some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_OP_DONE", "Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_HALFOP_FAIL", "$b%s$b could not halfop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_HALFOP_DONE", "Half-Opped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_VOICE_FAIL", "$b%s$b could not voice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_VOICE_DONE", "Voiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DEOP_FAIL", "$b%s$b could not deop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_DEOP_DONE", "Deopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DEHALFOP_FAIL", "$b%s$b could not dehalfop some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_DEHALFOP_DONE", "Dehalfopped users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_DEVOICE_FAIL", "$b%s$b could not devoice some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_DEVOICE_DONE", "Devoiced users in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_OPALL_SECURITY", "$bWARNING$b: Opping all users on a channel is very insecure! If you still want do op all users on %s use: '$bopall FORCE$b [nick mask]'"}, + {"NS_OPALL_DONE", "Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_HALFOPALL_DONE", "Half-Opped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_VOICEALL_DONE", "Voiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_DEOPALL_DONE", "Deopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_DEHALFOPALL_DONE", "Dehalfopped $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_DEVOICEALL_DONE", "Devoiced $b%d$b users in %s."}, /* {ARGS: 20, "#TestChan"} */ + {"NS_KICK_DONE", "Kicked $b%d$b users from %s"}, /* {ARGS: 20, "#TestChan"} */ + {"NS_KICK_FAIL", "$b%s$b could not kick some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_KICKBAN_DONE", "KickBanned $b%d$b users from %s"}, /* {ARGS: 10, "#TestChan"} */ + {"NS_KICKBAN_FAIL", "$b%s$b could not kickban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_BAN_DONE", "$b%d$b masks added to the %s ban list. (matching %d users)"}, /* {ARGS: 5, "#TestChan", 15} */ + {"NS_BAN_FAIL", "$b%s$b could not ban some of the nicks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_LAME_MASK", "$b%s$b is a little too general. Try making it more specific."}, /* {ARGS: "*!*@*"} */ + {"NS_LAME_MASK_WARNING", "$k4WARNING$k: $b%s$b is very general. (matches %d users)"}, + {"NS_SET_HEADER", "Channel Settings for %s:"}, /* {ARGS: "#TestChan"} */ + {"NS_SET_ON", "on"}, + {"NS_SET_OFF", "off"}, + {"NS_SET_UNKNOWN_SETTING", "$b%s$b is an unknown channel setting."}, /* {ARGS: "TestSetting"} */ + {"NS_SET_CANNOT_SET", "That setting is above your current level, so you cannot change it."}, + {"NS_SET_BADLEVEL", "You cannot change any setting to above your level."}, + {"NS_SET_INVALID_OPTION", "$b%d$b is not a valid choice. Choose one:"}, /* {ARGS: 5} */ + {"NS_SET_INVALID_BOOLEAN", "$b%s$b is an invalid binary value."}, /* {ARGS: 2} */ + {"NS_SET_DEFAULTS_OWNER", "You must have access 500 in %s to reset it to the default options."}, /* {ARGS: "#TestChan"} */ + {"NS_SET_DEFAULTS_CODE", "To reset %s's settings to the defaults, you must use 'set defaults %s'."}, /* {ARGS: "#TestChan", "abc123"} */ + {"NS_SET_DEFAULTS_DONE", "All settings for %s have been reset to default values."}, /* {ARGS: "#TestChan"} */ + {"NS_SET_TRIGGER_OWNER", "You must have access 500 in %s to change the channel trigger."}, /* {ARGS: "#TestChan"} */ + {"NS_SET_HELP_USERINFO","(access to set the userinfo)"}, + {"NS_SET_HELP_WIPEINFO","(access to clear the userinfo of other users)"}, + {"NS_SET_HELP_INVITEME","(access to get invited by the bot)"}, + {"NS_SET_HELP_ENFVOICE","(access to give voice to other users)"}, + {"NS_SET_HELP_ENFOPS","(access to give op to their users)"}, + {"NS_SET_HELP_GIVEOPS","(access to get op by the bot)"}, + {"NS_SET_HELP_GIVEVOICE","(access to get voice by the bot)"}, + {"NS_SET_HELP_KICK","(access to kick other users from the channel)"}, + {"NS_SET_HELP_BAN","(access to ban other users from the channel)"}, + {"NS_SET_HELP_STATICBAN","(access to add static bans to the channel banlist e.g. +addban)"}, + {"NS_SET_HELP_PUBCMD","(access to do public commands in the channel e.g. +users)"}, + {"NS_SET_HELP_ENFMODES","(access to override the modelock)"}, + {"NS_SET_HELP_ENFTOPIC","(access to override the topicmask)"}, + {"NS_SET_HELP_TOPICSNARF","(access to set the default topic by changing the topic with /TOPIC)"}, + {"NS_SET_HELP_CHANGETOPIC","(access to change the topic)"}, + {"NS_SET_HELP_SETTERS","(access to change this settings)"}, + {"NS_SET_HELP_ADDUSER","(access to add an user to the userlist)"}, + {"NS_SET_HELP_DELUSER","(access to delete an user from the userlist)"}, + {"NS_SET_HELP_CLVL","(access to change the access of an user in the userlist)"}, + {"NS_SET_HELP_RESYNC","(access to synchronize the channelrights (@,+) with the userlist)"}, + {"NS_SET_HELP_SUSPEND","(access to suspend an user on the userlist)"}, + {"NS_SET_OPTION_CTCPREACTION_0","Kick on disallowed CTCPs"}, + {"NS_SET_OPTION_CTCPREACTION_1","Kickban on disallowed CTCPs"}, + {"NS_SET_OPTION_CTCPREACTION_2","Short timed ban on disallowed CTCPs"}, + {"NS_SET_OPTION_CTCPREACTION_3","Long timed ban on disallowed CTCPs"}, + {"NS_SET_OPTION_NOTICEREACTION_0","Kick on disallowed NOTICEs"}, + {"NS_SET_OPTION_NOTICEREACTION_1","Kickban on disallowed NOTICEs"}, + {"NS_SET_OPTION_NOTICEREACTION_2","Short timed ban on disallowed NOTICEs"}, + {"NS_SET_OPTION_NOTICEREACTION_3","Long timed ban on disallowed NOTICEs"}, + {"NS_SET_OPTION_PROTECT_0","All users will be protected from users with equal or lower access."}, + {"NS_SET_OPTION_PROTECT_1","All users with access will be protected from users with equal or lower access."}, + {"NS_SET_OPTION_PROTECT_2","All users with access will be protected from user with lower access."}, + {"NS_SET_OPTION_PROTECT_3","Nobody will be protected."}, + {"NS_SET_OPTION_TOYS_0","Funcommands can't be used."}, + {"NS_SET_OPTION_TOYS_1","Funcommands are possible but the reply will be sent as a notice."}, + {"NS_SET_OPTION_TOYS_2","Funcommands are possible and the reply will be sent to the channel."}, + {"NS_SET_OPTION_DYNLIMIT_0","off"}, + {"NS_SET_OPTION_NODELETE_0","off (only bot masters)"}, + {"NS_SET_OPTION_NODELETE_1","on (only bot masters)"}, + {"NS_WIPEINFO_DONE", "Removed $b%s$b's infoline in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_TRACE_HEADER", "The following users were found:"}, + {"NS_ADDBAN_DONE", "$b%s$b permantly added to the %s ban list. (matching %d users)"}, /* {ARGS: "*!*@Test.*", "#TestChan", 4} */ + {"NS_BANS_HEADER_MASK", "Mask"}, + {"NS_BANS_HEADER_SETBY", "Set By"}, + {"NS_BANS_HEADER_TRIGGERED", "Triggered"}, + {"NS_BANS_HEADER_EXPIRES", "Expires"}, + {"NS_BANS_HEADER_REASON", "Reason"}, + {"NS_DELBAN_BANNED_BY", "%s is banned by %s."}, /* {ARGS: "*!*@bla*", "*!*@b*"} */ + {"NS_DELBAN_FAIL", "Sorry, no ban found for $b%s$b."}, /* {ARGS: "*!*@bla*"} */ + {"NS_DELBAN_DONE", "Removed $b%s$b from the %s ban list."}, /* {ARGS: "*!*@bla.*", "#TestChan"} */ + {"NS_NETINFO_HEADER", "$bNetwork information$b"}, + {"NS_NETINFO_BOTS", "Bots:"}, + {"NS_NETINFO_UPTIME", "Uptime:"}, + {"NS_NETINFO_TRAFFIC", "Traffic:"}, + {"NS_NETINFO_CACHE", "Cache:"}, + {"NS_NETINFO_DATABASE", "Database:"}, + {"NS_NETINFO_CHANNEL", " Channel:"}, + {"NS_NETINFO_CHANNEL_BAN", " Bans:"}, + {"NS_NETINFO_USER", " User:"}, + {"NS_NETINFO_CHANUSER", " Channel-User:"}, + {"NS_NETINFO_OTHER", " Other:"}, + {"NS_NETINFO_THREADS", "Threads:"}, + {"NS_NETINFO_VERSION", "Version:"}, + {"NS_NETINFO_CODE", "Code:"}, + {"NS_NETINFO_CODE_VALUE", "%s lines c code (view it at http://dev.pk910.de/NeonServ)"}, /* {ARGS: 20} */ + {"NS_NETINFO_COMPILER", "Compiler:"}, + {"NS_NETINFO_COMPILER_VALUE", "%s (%s)"}, /* {ARGS: "GCC 4.4.5", "Sun Sep 18 2011 at 05:21:33 CEST"} */ + {"NS_EXTTOPIC_INVALID_ID", "ADVANCEDTOPIC is enabled and $b%s$b is an invalid TOPIC ID. Valid topic id's are: 1-9"}, /* {ARGS: 10} */ + {"NS_EXTTOPIC_TOPICID", "Topic %d: %s"}, /* {ARGS: 5, "topic"} */ + {"NS_TOPIC_DONE", "Topic is now '%s'."}, /* {ARGS: "i like you :D"} */ + {"NS_CHANSERVSYNC_UNSUPPORTED", "\0034WARNING\003: the user list style of %s is not known. %s can try to synchronize the userlist, but there is no guarantee that it is successful!"}, /* {ARGS: "CowBot"} */ + {"NS_CHANSERVSYNC_KEY", "If you really want to synchronize the %s userlist with %s use: chanservsync %s %s"}, /* {ARGS: "#TestChan", "CowBot", "CowBot", "abc123"} */ + {"NS_CHANSERVSYNC_INUSE", "$bchanservsync$b is already in use by someone else. Please try again in a few seconds..."}, + {"NS_CHANSERVSYNC_SYNCHRONIZING", "Synchronizing userlist in %s with $b%s$b..."}, /* {ARGS: "#TestChan", "CowBot"} */ + {"NS_CHANSERVSYNC_SYNCHRONIZED", "Synchronized user $b%s$b: access $b%d$b"}, /* {ARGS: "TestUser", 123} */ + {"NS_REGISTER_ALREADY", "%s is already registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */ + {"NS_INVALID_CHANNEL_NAME", "%s is not a valid channel name."}, /* {ARGS: "#invalid"} */ + {"NS_REGISTER_FULL", "the bot can not join more channels."}, + {"NS_REGISTER_DISCONNECTED", "%s has been registered with a Bot, that is currently NOT connected. The Bot should join the channel, when it reconnects to the IRC-Network."}, /* {ARGS: "#TestChan"} */ + {"NS_REGISTER_DONE", "$b%s$b is now registered to $b%s$b."}, /* {ARGS: "#TestChan", "TestUser"} */ + {"NS_REGISTER_DONE_NOAUTH", "$b%s$b is now registered."}, /* {ARGS: "#TestChan"} */ + {"NS_UNREGISTER_NOT_REGISTERED", "$b%s$b is not registered with %s."}, /* {ARGS: "#TestChan", "NeonServ"} */ + {"NS_UNREGISTER_DONE", "$b%s$b unregistered."}, /* {ARGS: "#TestChan"} */ + {"NS_RECOVER_DONE", "$b%s$b has been recovered."}, /* {ARGS: "#TestChan"} */ + {"NS_RESYNC_DONE", "Synchronized users in $b%s$b with the userlist."}, /* {ARGS: "#TestChan"} */ + {"NS_TIMEBAN_DURATION_TOO_SHORT", "You must specify a ban duration of at least %d seconds."}, /* {ARGS: 30} */ + {"NS_TIMEBAN_DONE", "Banned $b%s$b from %s for %s. (matching %d users)"}, /* {ARGS: "*!*@bla*", "#TestChan", "2 hours", 5} */ + {"NS_MODE_INVALID", "$b%c$b is an invalid set of channel modes."}, /* {ARGS: "+xyz"} */ + {"NS_MODE_LOCKED", "Modes conflicting with $b%s$b are not allowed in %s."}, /* {ARGS: "+xyz", "#TestChan"} */ + {"NS_MODE_DONE", "Channel modes are now $b%s$b."}, /* {ARGS: "+xyz"} */ + {"NS_MODE_ENFOPS", "You may not op or deop users on $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_MODE_ENFVOICE", "You may not voice or devoice users on $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_MODE_CANBAN", "You may not ban or unban users on $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_GOD_ON", "Security override has been enabled."}, + {"NS_GOD_OFF", "Security override has been disabled."}, + {"NS_PEEK_HEADER", "$b%s$b Status:"}, /* {ARGS: "#TestChan"} */ + {"NS_PEEK_TOPIC", "Topic: %s"}, /* {ARGS: "TOPIC"} */ + {"NS_PEEK_MODES", "Modes: %s"}, /* {ARGS: "+xyz"} */ + {"NS_PEEK_USERS", "Total Users: %d (%d ops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 20, 4, 6, 8, 2} */ + {"NS_PEEK_USERS_HALFOP", "Total Users: %d (%d ops, %d halfops, %d voices, %d regulars, %d invisible)"}, /* {ARGS: 25, 5, 4, 6, 8, 2} */ + {"NS_PEEK_OPS", "Ops:"}, + {"NS_USET_GLOBAL", "$b--- Global ---$b"}, + {"NS_USET_CHANNEL", "$b--- User options (channel) ---$b"}, + {"NS_USET_NO_ACCESS", "no access"}, + {"NS_USET_UNKNOWN_SETTING", "$b%s$b is an unknown uset setting."}, /* {ARGS: "TestSetting"} */ + {"NS_RELOADLANG_UNKNOWN", "$b%s$b is an unknown language tag."}, /* {ARGS: "de"} */ + {"NS_RELOADLANG_DONE", "$b%s$b (%s) reloaded."}, /* {ARGS: "Deutsch", "de"} */ + {"NS_UNBAN_DONE", "$b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ + {"NS_UNBAN_FAIL", "$b%s$b could not unban some of the masks you provided."}, /* {ARGS: "NeonServ"} */ + {"NS_UNBANALL_DONE", "all $b%d$b masks removed from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ + {"NS_UNBANALL_FAIL", "$b%s$b could not find any bans in %s."}, /* {ARGS: "NeonServ", "#TestChan"} */ + {"NS_UNBANME_DONE", "removed $b%d$b masks from the %s ban list."}, /* {ARGS: 5, "#TestChan"} */ + {"NS_UNBANME_FAIL", "$b%s$b could not find any bans matching %s."}, /* {ARGS: "NeonServ", "TestUser!TestIdent@TestUser.user.WebGamesNet"} */ + {"NS_INVITE_RESTRICTION", "%s doesn't want to be invited to %s."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_INVITE_TIMEOUT", "%s has already been invited to $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_INVITE_ON_CHAN", "%s is already in $b%s$b."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_INVITE_DONE_USER", "You have been invited to join $b%s$b by %s. (Do $b/msg %s %1$s uset noinvite 1$b if you don't want to be invited to %1$s anymore.)"}, /* {ARGS: "#TestChan", "TestUser", "NeonServ"} */ + {"NS_INVITE_DONE", "Invited $b%s$b to join %s."}, /* {ARGS: "TestUser", "#TestChan"} */ + {"NS_INVITEME_ON_CHAN", "You are already in $b%s$b."}, /* {ARGS: "#TestChan"} */ + {"NS_INVITEME_DONE", "You have been invited to join %s."}, /* {ARGS: "#TestChan"} */ + {"NS_HELP_TOPIC", "No help on that topic."}, + {"NS_CSUSPEND_ALREADY", "$b%s$b is already suspended."}, /* {ARGS: "#TestChan"} */ + {"NS_CSUSPEND_DONE", "Channel $b%s$b has been temporarily suspended."}, /* {ARGS: "#TestChan"} */ + {"NS_CUNSUSPEND_NOT", "$b%s$b is not suspended."}, /* {ARGS: "#TestChan"} */ + {"NS_CUNSUSPEND_DONE", "Channel $b%s$b has been restored."}, /* {ARGS: "#TestChan"} */ + {"NS_MOVE_SUSPENDED", "Moving cannot be performed if the source channel is suspended."}, + {"NS_MOVE_SELF", "Moving cannot be performed if the source and target channels are the same."}, + {"NS_MOVE_DONE", "Channel $b%s$b has been moved to $b%s$b."}, /* {ARGS: "#TestChan", "#NewTestChan"} */ + {"NS_BIND_ALREADY", "$b%s$b is already bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */ + {"NS_BIND_UNKNOWN", "$b%s$b is an undefined function."}, /* {ARGS: "TestFunction"} */ + {"NS_BIND_DONE", "New command $b%s$b bound to %s."}, /* {ARGS: "TestCommand", "TestFunction"} */ + {"NS_UNBIND_NOT_FOUND", "There is no command called $b%s$b bound."}, /* {ARGS: "TestCommand"} */ + {"NS_UNBIND_DONE", "Unbound command $b%s$b."}, /* {ARGS: "TestCommand"} */ + {"NS_EVENTS_HEADER", "The following channel events were found:"}, + {"NS_OPLOG_HEADER", "The following oper events were found:"}, + {"NS_SEARCH_HEADER", "The following channels were found:"}, + {"NS_COMMAND_BINDING", "$b%s$b is a binding of %s %s"}, /* {ARGS: "TestCommand", "TestFunction", "TestParameters"} */ + {"NS_COMMAND_ACCESS", "You need at least %d channel access and %d oper access to execute this command."}, /* {ARGS: 500, 100} */ + {"NS_TOPIC_ACCESS", "You lack sufficient access in %s to change the topic."}, /* {ARGS: "#TestChan"} */ + {"NS_BOTWAR_DETECTED", "$b$k4BOTWAR DETECTED!$k Please check the channel configuration!$b"}, + {"NS_BOTWAR_REPORTED", "A supporter has been informed to help you preventing botwars in the future."}, + {"NS_BOTWAR_ALERT", "$b$k4BOTWAR ALERT:$k$b Botwar in $b%s$b detected. (opponent: $b%s$b) Please join and help them preventing Botwars."}, /* {ARGS: "#TestChan", "OtherBot"} */ + {"NS_INVITE_FAIL", "$b%s$b is not registered with %s or suspended."}, /* {ARGS: "#TestChan", "NeonServ"} */ + {"NS_SETACCESS_DONE", "$b%s$b has now %d global access."}, /* {ARGS: "TestUser", 1000} */ + {"NS_ADDRANK_EXISTS", "Another support ranking called '$b%s$b' already exists."}, /* {ARGS: "Supporter"} */ + {"NS_ADDRANK_DONE", "Support ranking '$b%s$b' created."}, /* {ARGS: "Supporter"} */ + {"NS_DELRANK_NOT_FOUND", "There is no support ranking called '$b%s$b'."}, /* {ARGS: "Supporter"} */ + {"NS_DELRANK_DELETED", "Support ranking called '$b%s$b' removed."}, /* {ARGS: "Supporter"} */ + {"NS_LISTRANK_ID", "Id"}, + {"NS_LISTRANK_NAME", "Name"}, + {"NS_LISTRANK_ASSIGNED", "Assigned to"}, + {"NS_LISTRANK_UNRANKED", "There are also %d unranked users with global access."}, /* {ARGS: 10} */ + {"NS_SETRANK_NOT_FOUND", "There is no support ranking with ID '$b%s$b'."}, /* {ARGS: 42} */ + {"NS_SETRANK_HEAD", "Support ranking settings for Id %s:"}, /* {ARGS: 42} */ + {"NS_SETRANK_UNKNOWN_SETTING", "$b%s$b is an unknown support rank setting."}, /* {ARGS: "moep"} */ + {"NS_SETRANK_ORDER_INVALID", "%d is an invalid numeric value. (valid: 1-99)"}, /* {ARGS: 100} */ + {"NS_ASSIGNRANK_DONE", "$b%s$b is now ranked as '$b%s$b'."}, /* {ARGS: "TestUser", "Supporter"} */ + {"NS_INFO_HEADER", "$b%s$b Information:"}, /* {ARGS: "#TestChan"} */ + {"NS_INFO_DEFAULTTOPIC", "Default Topic:"}, + {"NS_INFO_MODELOCK", "Mode Lock:"}, + {"NS_INFO_RECORD", "Record Visitors:"}, + {"NS_INFO_OWNER", "Owner:"}, + {"NS_INFO_USERS", "Total User Count:"}, + {"NS_INFO_BANS", "Ban Count:"}, + {"NS_INFO_VISITED", "Visited:"}, + {"NS_INFO_REGISTERED", "Registered:"}, + {"NS_INFO_REGISTRAR", "Registered by:"}, + {"NS_INFO_OWNERLOG", "Ownership transfer history for $b%s$b:"}, /* {ARGS: "#TestChan"} */ + {"NS_INFO_OWNERCHANGE", " from %s to %s on %s"}, + {"NS_RENAME_DONE", "Renamed $b%s$b to $b%s$b."}, /* {ARGS: "TestUser", "TestUser2"} */ + {"NS_RENAME_FAIL", "Failed renaming $b%s$b."}, /* {ARGS: "TestUser"} */ + {"NS_FUN_DISABLED", "Fun commands are disabled in %s."}, /* {ARGS: "#TestChan"} */ + {"NS_UNBIND_REQUIRED", "%1$s is a required function and there is no other command bound to %1$s. Bind another command to %1$s first."}, /* {ARGS: "bind"} */ + {"NS_COMMANDS_NAME", "Name"}, + {"NS_COMMANDS_ACCESS", "Access"}, + {"NS_COMMANDS_GACCESS", "GodAccess"}, + {"NS_COMMANDS_TRIGGERED", "Triggered"}, + {"NS_COMMANDS_FUNCTION", "Function"}, + {"NS_DNR_SET", "$b%s$b is do-not-register (by $b%s$b): %s" }, /* {ARGS: "#TestChan", "TestUser", "because of it is like it is"} */ + {"NS_DNR_SET_EXPIRES", "$b%s$b is do-not-register (by $b%s$b; expires %s): %s" }, /* {ARGS: "#TestChan", "TestUser", "1 day", "because of it is like it is"} */ + {"NS_DNR_SET_ANONYM", "$b%s$b is do-not-register. Please contact the support to get more information."}, /* {ARGS: "TestUser"} */ + {"NS_NOREGISTER_INVALID_DURATION", "$b%s$b is not a valid duration."}, /* {ARGS: "möp"} */ + {"NS_NOREGISTER_REGISTERED", "$b%s$b is currently registered and can't be added to the do-not-register list."}, /* {ARGS: "#TestChan"} */ + {"NS_NOREGISTER_DONE", "added $b%s$b to the do-not-register list."}, /* {ARGS: "#TestChan"} */ + {"NS_NOREGISTER_HEAD", "The following do-not-registers were found:"}, + {"NS_DNR_TARGET", "Target"}, + {"NS_DNR_USER", "Issuer"}, + {"NS_DNR_EXPIRES", "Expires"}, + {"NS_DNR_REASON", "Reason"}, + {"NS_STAFF_LOGGEDIN", "Logged in as"}, + {"NS_BOTS_ID", "Id"}, + {"NS_BOTS_NICK", "Nick"}, + {"NS_BOTS_SERVER", "Server:Port(:Pass)"}, + {"NS_BOTS_CLASS", "Bot Class"}, + {"NS_BOTS_FLAGS", "Flags"}, + {"NS_BOTS_CHANNELS", "Channels"}, + {"NS_BOTS_TRIGGER", "Trigger"}, + {"NS_NICKLIST_NICK", "Nick"}, + {"NS_NICKLIST_STATE", "State"}, + {"NS_NICKLIST_ACCESS", "Access"}, + {"NS_NICKLIST_SYNC", "use `nicklist sync` to fix all red and orange entrys in the list above (add opped users with %d and voiced with %d access)"}, + {"NS_SETBOT_UNKNOWN", "`%d` is an unknown botid."}, /* {ARGS: 50} */ + {"NS_SETBOT_HEADER", "$bSettings for botid `%d`:$b"}, /* {ARGS: 50} */ + {"NS_SETBOT_SETTING", "$b%s$b is an unknown bot setting."}, /* {ARGS: "strangeSetting"} */ + {"NS_SETBOT_NICK_INVALID", "`%s` is an invalid botnick."}, /* {ARGS: "-SuperMagicBananaBotWithManyFunctions"} */ + {"NS_SETBOT_NEED_RESTART", "You need to reconnect the bot to apply this setting."}, + {"NS_SETBOT_PORT_INVALID", "`%s` is an invalid port number."}, /* {ARGS: "-1"} */ + {"NS_SETBOT_INVALID_CLASS", "`%s` is an invalid botclass."}, /* {ARGS: "MistColaLeer"} */ + {"NS_SETBOT_MAXCHAN_INVALID", "`%s` is an invalid maxchan value."}, /* {ARGS: "-1"} */ + {"NS_SETBOT_PRIORITY_INVALID", "`%s` is an invalid priority value."}, /* {ARGS: "-1"} */ + {"NS_SETBOT_TRIGGER_INVALID", "`%s` is an invalid bot trigger."}, /* {ARGS: "tooLongTrigger"} */ + {"NS_SETBOT_TRIGGER_NOTE", "Please note: This Setting will only affect new channels."}, + {"NS_ADDBOT_EXISTING", "A bot with nick %s does already exist."}, /* {ARGS: "NeonServ"} */ + {"NS_ADDBOT_DONE", "Added %s with BotID $b%d$b."}, /* {ARGS: "NeonServ", 2} */ + {"NS_DELBOT_NOT_FOUND", "Bot with BotID / nick $b%s$b not found."}, /* {ARGS: "NeonServ"} */ + {"NS_DELBOT_DONE", "Bot deleted."}, + {"NS_RECONNECT_DONE", "Reconnected bot."}, + {"NS_MODCMD_SETTING", "$b%s$b is an unknown modcmd setting."}, /* {ARGS: "strangeSetting"} */ + {"NS_MODCMD_HEADER", "$bSettings for command %s:$b"}, /* {ARGS: "access"} */ + {"NS_MODCMD_OUTRANKED", "$b%s$b outranks you. (required access: %d)"}, /* {ARGS: "die", 1000} */ + {"NS_MODCMD_STATIC_FLAG", "This Flag is added statically. It can't be modified manually."}, + {"NS_MEMINFO_DISABLED", "Memory Debugger is disabled!"}, + {"NS_MEMINFO_NAME", "Name"}, + {"NS_MEMINFO_COUNT", "Count"}, + {"NS_MEMINFO_SIZE", "Size"}, + {"NS_MEMINFO_LINE", "Line"}, + {"NS_MEMINFO_TOTAL", "Total"}, + {NULL, NULL} +}; + +/* TODO: +cmd_neonserv_open.c +set modelock +cmd_neonserv_modcmd.c +cmd_neonserv_allowregister.c +cmd_neonserv_noregister.c +cmd_neonserv_expire.c +cmd_neonserv_unvisited.c +cmd_neonserv_merge.c +cmd_neonserv_dnrsearch.c +cmd_neonserv_iplocate.c +cmd_neonserv_calc.c +*/ +//EVENTS +#include "event_neonserv_join.c" +#include "event_neonserv_part.c" +#include "event_neonserv_quit.c" +#include "event_neonserv_kick.c" +#include "event_neonserv_mode.c" +#include "event_neonserv_ctcp.c" +#include "event_neonserv_notice.c" +#include "event_neonserv_invite.c" +#include "event_neonserv_topic.c" + + +struct ClientSocket *getBotForChannel(struct ChanNode *chan) { + return getChannelBot(chan, BOTID); +} + +static void neonserv_bot_ready(struct ClientSocket *client) { + MYSQL_RES *res; + MYSQL_ROW row; + + printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "MODE %s +%s", client->user->nick, row[0]); + } + + printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "JOIN %s %s", row[0], row[1]); + } +} + +static void neonserv_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { + MYSQL_RES *res; + MYSQL_ROW row; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + strcpy(trigger, "+"); + return; + } + printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + strcpy(trigger, "+"); + return; + } + if(row[0] && *row[0]) + strcpy(trigger, row[0]); + else + strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "~")); +} + +static void start_bots(int type) { + struct ClientSocket *client; + MYSQL_RES *res, *res2; + MYSQL_ROW row; + + if(type == MODSTATE_STARTSTOP) { + printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); + client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); + client->botid = BOTID; + client->clientid = atoi(row[7]); + connect_socket(client); + } + } + + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); + res2 = mysql_use(); + while ((row = mysql_fetch_row(res2)) != NULL) { + if(bind_cmd_to_command(BOTID, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_set_parameters(BOTID, row[0], row[2]); + } + if(row[3]) { + bind_set_global_access(BOTID, row[0], atoi(row[3])); + } + if(row[4]) { + bind_set_channel_access(BOTID, row[0], row[4]); + } + if(strcmp(row[5], "0")) + bind_set_bind_flags(BOTID, row[0], atoi(row[5])); + } + } + bind_unbound_required_functions(BOTID); +} + +void init_NeonServ(int type) { + set_bot_alias(BOTID, BOTALIAS); + start_bots(type); + + if(type == MODSTATE_REBIND) return; + + //register events + bind_bot_ready(neonserv_bot_ready, module_id); + bind_join(neonserv_event_join, module_id); + bind_part(neonserv_event_part, module_id); + bind_quit(neonserv_event_quit, module_id); + bind_chanctcp(neonserv_event_chanctcp, module_id); + bind_privctcp(general_event_privctcp, module_id); + bind_channotice(neonserv_event_channotice, module_id); + bind_topic(neonserv_event_topic, module_id); + bind_invite(neonserv_event_invite, module_id); + bind_mode(neonserv_event_mode, module_id); + bind_kick(neonserv_event_kick, module_id); + + set_trigger_callback(BOTID, module_id, neonserv_trigger_callback); + + register_default_language_table(msgtab); +} + +void loop_NeonServ() { + +} + +void free_NeonServ(int type) { + unbind_allcmd(BOTID); + if(type == MODSTATE_STARTSTOP) { + //disconnect all our bots + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->botid == BOTID) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } +} + +#undef BOTID +#undef BOTALIAS diff --git a/src/modules/NeonServ.mod/bot_NeonServ.h b/src/modules/NeonServ.mod/bot_NeonServ.h new file mode 100644 index 0000000..883275c --- /dev/null +++ b/src/modules/NeonServ.mod/bot_NeonServ.h @@ -0,0 +1,30 @@ +/* bot_NeonServ.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _bot_NeonServ_h +#define _bot_NeonServ_h + +#include "main.h" + +struct ChanNode; + +void init_NeonServ(int type); +void loop_NeonServ(); +void free_NeonServ(int type); + +struct ClientSocket *getBotForChannel(struct ChanNode *chan); + +#endif \ No newline at end of file diff --git a/src/modules/NeonServ.mod/cmd_neonserv.c b/src/modules/NeonServ.mod/cmd_neonserv.c new file mode 100644 index 0000000..5c24826 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv.c @@ -0,0 +1,103 @@ +/* cmd_neonserv.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_neonserv.h" +#include "modcmd.h" +#include "ConfigParser.h" + +void register_commands() { + //NeonServ Commands + register_command_alias(1, "NeonServ"); + + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(1, NAME, module_id, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) + // NAME FUNCTION PARAMS PRIVS FLAGS + USER_COMMAND("adduser", neonserv_cmd_adduser, 2, "#channel_canadd", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("deluser", neonserv_cmd_deluser, 1, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("clvl", neonserv_cmd_clvl, 2, "#channel_canclvl", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("access", neonserv_cmd_access, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG); + USER_COMMAND("users", neonserv_cmd_users, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); + USER_COMMAND("suspend", neonserv_cmd_suspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("unsuspend", neonserv_cmd_unsuspend, 1, "#channel_cansuspend", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("delme", neonserv_cmd_delme, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("myaccess", neonserv_cmd_myaccess, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("up", neonserv_cmd_up, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("down", neonserv_cmd_down, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_LOG); + USER_COMMAND("upall", neonserv_cmd_upall, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("downall", neonserv_cmd_downall, 0, NULL, CMDFLAG_LOG); + USER_COMMAND("mdeluser", neonserv_cmd_mdeluser, 2, "#channel_candel", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("trim", neonserv_cmd_trim, 2, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("giveowner", neonserv_cmd_giveowner, 1, "500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("op", neonserv_cmd_op, 1, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("deop", neonserv_cmd_deop, 1, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("voice", neonserv_cmd_voice, 1, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("devoice", neonserv_cmd_devoice, 1, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("opall", neonserv_cmd_opall, 0, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("deopall", neonserv_cmd_deopall, 0, "@#channel_getop,#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("voiceall", neonserv_cmd_voiceall, 0, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("devoiceall", neonserv_cmd_devoiceall,0, "+#channel_getvoice,#channel_canvoice", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + if(get_int_field("General.have_halfop")) { + USER_COMMAND("halfop", neonserv_cmd_halfop, 1, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("dehalfop", neonserv_cmd_dehalfop, 1, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("halfopall", neonserv_cmd_halfopall, 0, "%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("dehalfopall", neonserv_cmd_dehalfopall,0,"%#channel_gethalfop,#channel_canhalfop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + } + USER_COMMAND("set", neonserv_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("kick", neonserv_cmd_kick, 1, "#channel_cankick", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("kickban", neonserv_cmd_kickban, 1, "#channel_cankick,#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("ban", neonserv_cmd_ban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("wipeinfo", neonserv_cmd_wipeinfo, 1, "#channel_wipeinfo", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("addban", neonserv_cmd_addban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("bans", neonserv_cmd_bans, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("delban", neonserv_cmd_delban, 1, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("topic", neonserv_cmd_topic, 0, "#channel_changetopic", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("chanservsync", neonserv_cmd_chanservsync, 0,"500", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("resync", neonserv_cmd_resync, 0, "#channel_canresync", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("addtimeban", neonserv_cmd_addtimeban,2, "#channel_staticban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("mode", neonserv_cmd_mode, 1, "#channel_getop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("peek", neonserv_cmd_peek, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); + USER_COMMAND("uset", neonserv_cmd_uset, 0, NULL, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_NO_CROSSCHAN); + USER_COMMAND("unban", neonserv_cmd_unban, 1, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("unbanall", neonserv_cmd_unbanall, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("unbanme", neonserv_cmd_unbanme, 0, "#channel_canban", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("invite", neonserv_cmd_invite, 1, "#channel_canop", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("inviteme", neonserv_cmd_inviteme, 0, "#channel_getinvite", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + USER_COMMAND("help", neonserv_cmd_help, 0, NULL, 0); + USER_COMMAND("events", neonserv_cmd_events, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + USER_COMMAND("info", neonserv_cmd_info, 0, NULL, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_NO_CROSSCHAN); + USER_COMMAND("extscript", neonserv_cmd_extscript, 0, NULL, CMDFLAG_EMPTY_ARGS | CMDFLAG_CHAN_PARAM); + USER_COMMAND("nicklist", neonserv_cmd_nicklist, 0, "1", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + #undef USER_COMMAND + + #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(1, NAME, module_id, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS) + // NAME FUNCTION PARAMS ACCS FLAGS + OPER_COMMAND("trace", neonserv_cmd_trace, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + OPER_COMMAND("recover", neonserv_cmd_recover, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("csuspend", neonserv_cmd_csuspend, 1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("cunsuspend", neonserv_cmd_cunsuspend,1, 100, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("move", neonserv_cmd_move, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("oplog", neonserv_cmd_oplog, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("search", neonserv_cmd_search, 1, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + OPER_COMMAND("addrank", neonserv_cmd_addrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("delrank", neonserv_cmd_delrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("setrank", neonserv_cmd_setrank, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("assignrank", neonserv_cmd_assignrank,2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("listrank", neonserv_cmd_listrank, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("rename", neonserv_cmd_rename, 2, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("unvisited", neonserv_cmd_unvisited, 0, 400, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("noregister", neonserv_cmd_noregister,0, 300, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + #undef OPER_COMMAND +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv.h b/src/modules/NeonServ.mod/cmd_neonserv.h new file mode 100644 index 0000000..9c31b16 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv.h @@ -0,0 +1,114 @@ +/* cmd_neonserv.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _cmd_neonserv_h +#define _cmd_neonserv_h +#include "../module.h" +#include "main.h" +#include "modcmd.h" +#include "IRCParser.h" +#include "IRCEvents.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "ModeNode.h" +#include "BanNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "version.h" +#include "EventLogger.h" +#include "bots.h" +#include "bot_NeonServ.h" +#include "ConfigParser.h" + +void register_commands(); + +CMD_BIND(neonserv_cmd_access); +CMD_BIND(neonserv_cmd_addban); +CMD_BIND(neonserv_cmd_addrank); +CMD_BIND(neonserv_cmd_addtimeban); +CMD_BIND(neonserv_cmd_adduser); +CMD_BIND(neonserv_cmd_assignrank); +CMD_BIND(neonserv_cmd_ban); +CMD_BIND(neonserv_cmd_bans); +CMD_BIND(neonserv_cmd_chanservsync); +CMD_BIND(neonserv_cmd_clvl); +CMD_BIND(neonserv_cmd_csuspend); +CMD_BIND(neonserv_cmd_cunsuspend); +CMD_BIND(neonserv_cmd_dehalfop); +CMD_BIND(neonserv_cmd_dehalfopall); +CMD_BIND(neonserv_cmd_delban); +CMD_BIND(neonserv_cmd_delme); +CMD_BIND(neonserv_cmd_delrank); +CMD_BIND(neonserv_cmd_deluser); +CMD_BIND(neonserv_cmd_deop); +CMD_BIND(neonserv_cmd_deopall); +CMD_BIND(neonserv_cmd_devoice); +CMD_BIND(neonserv_cmd_devoiceall); +CMD_BIND(neonserv_cmd_down); +CMD_BIND(neonserv_cmd_downall); +CMD_BIND(neonserv_cmd_events); +CMD_BIND(neonserv_cmd_extscript); +CMD_BIND(neonserv_cmd_giveowner); +CMD_BIND(neonserv_cmd_halfop); +CMD_BIND(neonserv_cmd_halfopall); +CMD_BIND(neonserv_cmd_help); +CMD_BIND(neonserv_cmd_info); +CMD_BIND(neonserv_cmd_invite); +CMD_BIND(neonserv_cmd_inviteme); +CMD_BIND(neonserv_cmd_kick); +CMD_BIND(neonserv_cmd_kickban); +CMD_BIND(neonserv_cmd_listrank); +CMD_BIND(neonserv_cmd_mdeluser); +CMD_BIND(neonserv_cmd_mode); +CMD_BIND(neonserv_cmd_move); +CMD_BIND(neonserv_cmd_myaccess); +CMD_BIND(neonserv_cmd_nicklist); +CMD_BIND(neonserv_cmd_noregister); +CMD_BIND(neonserv_cmd_op); +CMD_BIND(neonserv_cmd_opall); +CMD_BIND(neonserv_cmd_oplog); +CMD_BIND(neonserv_cmd_peek); +CMD_BIND(neonserv_cmd_recover); +CMD_BIND(neonserv_cmd_rename); +CMD_BIND(neonserv_cmd_resync); +CMD_BIND(neonserv_cmd_search); +CMD_BIND(neonserv_cmd_set); +CMD_BIND(neonserv_cmd_setrank); +CMD_BIND(neonserv_cmd_suspend); +CMD_BIND(neonserv_cmd_topic); +CMD_BIND(neonserv_cmd_trace); +CMD_BIND(neonserv_cmd_trim); +CMD_BIND(neonserv_cmd_unban); +CMD_BIND(neonserv_cmd_unbanall); +CMD_BIND(neonserv_cmd_unbanme); +CMD_BIND(neonserv_cmd_unsuspend); +CMD_BIND(neonserv_cmd_unvisited); +CMD_BIND(neonserv_cmd_up); +CMD_BIND(neonserv_cmd_upall); +CMD_BIND(neonserv_cmd_users); +CMD_BIND(neonserv_cmd_uset); +CMD_BIND(neonserv_cmd_voice); +CMD_BIND(neonserv_cmd_voiceall); +CMD_BIND(neonserv_cmd_wipeinfo); + +#endif \ No newline at end of file diff --git a/src/modules/NeonServ.mod/cmd_neonserv_access.c b/src/modules/NeonServ.mod/cmd_neonserv_access.c new file mode 100644 index 0000000..25b2501 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_access.c @@ -0,0 +1,173 @@ +/* cmd_neonserv_access.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +*/ +static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup); +static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target); +static void neonserv_cmd_access_filter_ranking_info(char *info, char *buffer, char *nick, char *auth, char *rank_name); + +struct neonserv_cmd_access_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + char *nick; +}; + +CMD_BIND(neonserv_cmd_access) { + if(argc == 0) { + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->nick = strdup(user->nick); + get_userauth(user, neonserv_cmd_access_nick_lookup, cache); + } else + neonserv_cmd_access_async1(client, getTextBot(), user, chan, user->nick, user->auth, user); + } + else if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_access_async1(client, getTextBot(), user, chan, NULL, argv[0], NULL); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_access_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, cuser); + } else { + struct neonserv_cmd_access_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->nick = strdup(argv[0]); + get_userauth(cuser, neonserv_cmd_access_nick_lookup, cache); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_access_nick_lookup) { + struct neonserv_cmd_access_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + if(!strcmp(cache->nick, cache->user->nick)) + reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH"); + else + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + neonserv_cmd_access_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, user); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_access_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, struct UserNode *target) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW user_row, chanuser_row; + int userid; + printf_mysql_query("SELECT `user_id`, `user_access`, `user_god`, `user_rank`, `rank_info`, `rank_name` FROM `users` LEFT JOIN `support_ranks` ON `rank_id` = `user_rank` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((user_row = mysql_fetch_row(res)) != NULL) { + userid = atoi(user_row[0]); + //check if the user is already added + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); + res = mysql_use(); + if(strcmp(user_row[3], "0") && strcmp(user_row[4], "")) { + char rank_info[MAXLEN]; + neonserv_cmd_access_filter_ranking_info(user_row[4], rank_info, nick, auth, user_row[5]); + reply(textclient, user, "%s", rank_info); + } + if ((chanuser_row = mysql_fetch_row(res)) != NULL) { + //access output + if(nick) + reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_AUTH" : "NS_A_ACCESS_AUTH_GOD"), nick, auth, atoi(chanuser_row[0]), chan->name); + else + reply(textclient, user, (strcmp(user_row[2], "1") ? "NS_A_ACCESS_NICK" : "NS_A_ACCESS_NICK_GOD"), auth, atoi(chanuser_row[0]), chan->name); + int cflags = atoi(chanuser_row[1]); + if(cflags & DB_CHANUSER_SUSPENDED) + reply(textclient, user, "NS_A_SUSPENDED", (nick ? nick : auth), chan->name); + if(chanuser_row[2] && strcmp(chanuser_row[2], "")) + reply(textclient, user, "[%s] %s", (nick ? nick : auth), chanuser_row[2]); + } else if(!strcmp(user_row[2], "1")) { + if(nick) + reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_AUTH", nick, auth, chan->name); + else + reply(textclient, user, "NS_A_LACKS_ACCESS_BUT_GOD_NICK", auth, chan->name); + } else + reply(textclient, user, "NS_NOT_ON_USERLIST", (nick ? nick : auth), chan->name); + } else + reply(textclient, user, "NS_NOT_ON_USERLIST", (nick ? nick : auth), chan->name); + if(target && (target->flags & USERFLAG_ISIRCOP)) + reply(textclient, user, "NS_A_IS_IRCOP", nick); +} + +static void neonserv_cmd_access_filter_ranking_info(char *info, char *buffer, char *nick, char *auth, char *rank_name) { + int bufferPos = 0; + char *a, *b = info; + do { + if(!b) break; + a = strstr(b, "$"); + if(a) *a = '\0'; + bufferPos += sprintf(buffer + bufferPos, "%s", b); + if(!a) break; + switch(a[1]) { + case '\0': + a = NULL; + break; + case 'U': + bufferPos += sprintf(buffer + bufferPos, "%s", auth); + break; + case 'N': + bufferPos += sprintf(buffer + bufferPos, "%s", (nick ? nick : auth)); + break; + case 'R': + bufferPos += sprintf(buffer + bufferPos, "%s", rank_name); + break; + default: + buffer[bufferPos++] = '$'; + buffer[bufferPos++] = a[1]; + break; + } + if(a) + b = a+2; + } while(a); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_addban.c b/src/modules/NeonServ.mod/cmd_neonserv_addban.c new file mode 100644 index 0000000..fffadf5 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_addban.c @@ -0,0 +1,128 @@ +/* cmd_neonserv_addban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] nick|*auth|*!*@mask +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_addban) { + struct neonserv_cmd_addban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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)); + } else + cache->reason = NULL; + get_userlist(chan, neonserv_cmd_addban_userlist_lookup, cache); +} + +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->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, struct Event *event, char *mask, char *reason) { + int match_count = 0; + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct UserNode *cuser; + struct ChanUser *chanuser; + mask = make_banmask(mask, hostmask_buffer); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + return; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + return; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + return; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + reply(textclient, user, "NS_LAME_MASK", mask); + return; + } + } + } + MYSQL_RES *res; + MYSQL_ROW row; + //check if the provided mask is already banned by another ban + char *ban = getBanAffectingMask(chan, mask); + if(ban != NULL) { + reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name); + return; + } + //check if the provided mask affects any existing bans + printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!match(mask, row[0])) { + //remove the ban + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); + } + } + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + int userid; + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) + userid = atoi(row[0]); + else + return; + //add the ban + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%d', '%s')", chan->channel_id, escape_string(mask), userid, escape_string(reason)); + putsock(client, "MODE %s +b %s", chan->name, mask); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + reply(textclient, user, "NS_ADDBAN_DONE", mask, chan->name, match_count); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_addrank.c b/src/modules/NeonServ.mod/cmd_neonserv_addrank.c new file mode 100644 index 0000000..6ade32d --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_addrank.c @@ -0,0 +1,36 @@ +/* cmd_neonserv_addrank.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] rank name +*/ + +CMD_BIND(neonserv_cmd_addrank) { + char *name = merge_argv(argv, 0, argc); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_ADDRANK_EXISTS", row[0]); + return; + } + printf_mysql_query("INSERT INTO `support_ranks` (`rank_name`) VALUES ('%s')", escape_string(name)); + reply(getTextBot(), user, "NS_ADDRANK_DONE", name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_addtimeban.c b/src/modules/NeonServ.mod/cmd_neonserv_addtimeban.c new file mode 100644 index 0000000..837812e --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_addtimeban.c @@ -0,0 +1,138 @@ +/* cmd_neonserv_addtimeban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] nick|*auth|*!*@mask +* argv[1] time +* argv[2-*] reason +*/ +static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup); +static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason); + +struct neonserv_cmd_addtimeban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *mask; + int duration; + char *reason; +}; + +CMD_BIND(neonserv_cmd_addtimeban) { + int duration = strToTime(user, argv[1]); + if(duration < 5) { + reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 5); + return; + } + struct neonserv_cmd_addtimeban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->mask = strdup(argv[0]); + cache->duration = duration; + if(argc > 2) { + cache->reason = strdup(merge_argv(argv, 2, argc)); + } else + cache->reason = NULL; + get_userlist(chan, neonserv_cmd_addtimeban_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_addtimeban_userlist_lookup) { + struct neonserv_cmd_addtimeban_cache *cache = data; + neonserv_cmd_addtimeban_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mask, cache->duration, (cache->reason ? cache->reason : "Bye.")); + free(cache->mask); + if(cache->reason) + free(cache->reason); + free(cache); +} + +static void neonserv_cmd_addtimeban_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mask, int duration, char *reason) { + int match_count = 0; + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct UserNode *cuser; + struct ChanUser *chanuser; + mask = make_banmask(mask, hostmask_buffer); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + return; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + return; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + reply(textclient, user, "NS_LAME_MASK", mask); + return; + } + } + } + MYSQL_RES *res; + MYSQL_ROW row; + //check if the provided mask is already banned by another ban + char *ban = getBanAffectingMask(chan, mask); + if(ban != NULL) { + reply(textclient, user, "NS_BAN_ALREADY_ADDED", mask, chan->name); + return; + } + //check if the provided mask affects any existing bans + printf_mysql_query("SELECT `ban_mask`, `ban_id` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!match(mask, row[0])) { + //remove the ban + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); + } + } + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + int userid; + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) + userid = atoi(row[0]); + else + return; + //add the ban + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(mask), (unsigned long) (time(0) + duration), userid, escape_string(reason)); + int banid = (int) mysql_insert_id(get_mysql_conn()); + putsock(client, "MODE %s +b %s", chan->name, mask); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); + reply(textclient, user, "NS_TIMEBAN_DONE", mask, chan->name, timeToStr(user, duration, 2, nameBuf), match_count); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_adduser.c b/src/modules/NeonServ.mod/cmd_neonserv_adduser.c new file mode 100644 index 0000000..0e8432b --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_adduser.c @@ -0,0 +1,159 @@ +/* cmd_neonserv_adduser.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +* argv[1] - chan access +*/ +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, 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; +}; + +CMD_BIND(neonserv_cmd_adduser) { + int caccess; + MYSQL_RES *res; + MYSQL_ROW row; + caccess = atoi(argv[1]); + if(caccess <= 0 || caccess > 500) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return; + } + if(caccess >= getChannelAccess(user, chan)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } + } + //check own access + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + 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, 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 + struct neonserv_cmd_adduser_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_adduser_auth_lookup) { + struct neonserv_cmd_adduser_cache *cache = data; + if(!exists) { + //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->event, cache->nick, auth, cache->access); + free(cache->nick); + free(cache); +} + +static USERAUTH_CALLBACK(neonserv_cmd_adduser_nick_lookup) { + struct neonserv_cmd_adduser_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth, int caccess) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + printf_mysql_query("SELECT `chanuser_access` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(textclient, user, "NS_ADDUSER_ALREADY_ADDED", nick, chan->name, atoi(row[0])); + return; + } + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); + userid = (int) mysql_insert_id(get_mysql_conn()); + } + 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/src/modules/NeonServ.mod/cmd_neonserv_assignrank.c b/src/modules/NeonServ.mod/cmd_neonserv_assignrank.c new file mode 100644 index 0000000..4fedaf8 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_assignrank.c @@ -0,0 +1,151 @@ +/* cmd_neonserv_assignrank.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +* argv[1-*] - rank name +*/ +static AUTHLOOKUP_CALLBACK(neonserv_cmd_assignrank_auth_lookup); +static USERAUTH_CALLBACK(neonserv_cmd_assignrank_nick_lookup); +static void neonserv_cmd_assignrank_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int rank_id); + +struct neonserv_cmd_assignrank_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + int rank_id; + char *nick; +}; + +CMD_BIND(neonserv_cmd_assignrank) { + MYSQL_RES *res; + MYSQL_ROW row; + char *name = merge_argv(argv, 1, argc); + int rank_id = 0; + if(stricmp(name, "*") && stricmp(name, "user") && stricmp(name, "none")) { + printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_DELRANK_NOT_FOUND", name); + return; + } + rank_id = atoi(row[0]); + } + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + 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_assignrank_async1(client, getTextBot(), user, event, argv[0], row[0], rank_id); + } else { + //we need to create a new user... + //but first lookup the auth to check if it really exists + struct neonserv_cmd_assignrank_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->rank_id = rank_id; + cache->nick = strdup(argv[0]); + lookup_authname(argv[0], neonserv_cmd_assignrank_auth_lookup, cache); + } + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_assignrank_async1(client, getTextBot(), user, event, argv[0], cuser->auth, rank_id); + } else { + struct neonserv_cmd_assignrank_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->rank_id = rank_id; + cache->nick = strdup(argv[0]); + get_userauth(cuser, neonserv_cmd_assignrank_nick_lookup, cache); + } + } +} + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_assignrank_auth_lookup) { + struct neonserv_cmd_assignrank_cache *cache = data; + if(!exists) { + //AUTH_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); + } else + neonserv_cmd_assignrank_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->rank_id); + free(cache->nick); + free(cache); +} + +static USERAUTH_CALLBACK(neonserv_cmd_assignrank_nick_lookup) { + struct neonserv_cmd_assignrank_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + neonserv_cmd_assignrank_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->rank_id); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_assignrank_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int rank_id) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row, rank = NULL; + int caccess = 0; + if(rank_id) { + printf_mysql_query("SELECT `rank_access`, `rank_name` FROM `support_ranks` WHERE `rank_id` = '%d'", rank_id); + res = mysql_use(); + rank = mysql_fetch_row(res); + caccess = atoi(rank[0]); + } + printf_mysql_query("SELECT `user_id`, `user_rank` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(atoi(row[1]) != rank_id) { + printf_mysql_query("UPDATE `users` SET `user_access` = '%d', `user_rank` = '%d' WHERE `user_id` = '%s'", caccess, rank_id, row[0]); + } + } else if(rank_id) { + printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`, `user_rank`) VALUES ('%s', '%d', '%d')", escape_string(auth), caccess, rank_id); + } + reply(textclient, user, "NS_ASSIGNRANK_DONE", auth, (rank_id ? rank[1] : "*")); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_ban.c b/src/modules/NeonServ.mod/cmd_neonserv_ban.c new file mode 100644 index 0000000..84a497a --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_ban.c @@ -0,0 +1,122 @@ +/* cmd_neonserv_ban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, struct Event *event, char *masks); + +struct neonserv_cmd_ban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *masks; +}; + +CMD_BIND(neonserv_cmd_ban) { + struct neonserv_cmd_ban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->masks = strdup(merge_argv_char(argv, 0, argc, ',')); + 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->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, 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]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + nextmask = masks; + while((mask = nextmask)) { + nextmask = strstr(mask, ","); + if(nextmask) { + *nextmask = '\0'; + nextmask++; + } + provided_masks++; + skip = 0; + match_count = 0; + mask = make_banmask(mask, hostmask_buffer); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(mask, usermask)) { + cuser->flags |= USERFLAG_SCRIPTFLAG1; //we mark the user as 'matching' + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + skip = 1; + break; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + skip = 1; + break; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + skip = 1; + break; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + skip = 1; + reply(textclient, user, "NS_LAME_MASK", mask); + break; + } + } + } + if(!skip) { + done_masks++; + modeBufferBan(modeBuf, mask); + } + } + total_match = 0; // count all users marked as 'matching' + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + if(cuser->flags & USERFLAG_SCRIPTFLAG1) { + cuser->flags &= ~USERFLAG_SCRIPTFLAG1; + total_match++; + } + } + freeModeBuffer(modeBuf); + if(done_masks == provided_masks) + 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/src/modules/NeonServ.mod/cmd_neonserv_bans.c b/src/modules/NeonServ.mod/cmd_neonserv_bans.c new file mode 100644 index 0000000..7ad47e1 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_bans.c @@ -0,0 +1,75 @@ +/* cmd_neonserv_bans.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] (optional) mask +*/ +CMD_BIND(neonserv_cmd_bans) { + MYSQL_RES *res; + MYSQL_ROW row; + //ban list + int i, with_expire = 0, cindex = 0; + char triggered_str[MAXLEN], expires_str[MAXLEN]; + struct Table *table; + printf_mysql_query("SELECT `ban_mask`, `user_user`, `ban_triggered`, `ban_timeout`, `ban_reason` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + table = table_init(5, mysql_num_rows(res) + 1, 0); + char *content[5]; + //add a NULL row (we add values later) + content[0] = NULL; + content[1] = NULL; + content[2] = NULL; + content[3] = NULL; + content[4] = NULL; + table_add(table, content); + while ((row = mysql_fetch_row(res)) != NULL) { + if(argc > 0 && match(argv[0], row[0])) continue; + content[0] = row[0]; + content[1] = row[1]; + content[2] = (strcmp(row[2], "0") ? timeToStr(user, (time(0) - atoi(row[2])), 2, triggered_str) : get_language_string(user, "NS_USERS_SEEN_NEVER")); + if(strcmp(row[3], "0")) { + if(!with_expire) { + //we're using expire times now... + for(i = 0; i < cindex; i++) + table_change_field(table, i+1, 3, get_language_string(user, "NS_USERS_SEEN_NEVER")); + with_expire = 1; + } + content[3] = timeToStr(user, (atoi(row[3]) - time(0)), 2, expires_str); + } else + content[3] = (with_expire ? get_language_string(user, "NS_USERS_SEEN_NEVER") : NULL); + content[4] = row[4]; + cindex++; + table_add(table, content); + } + //now we add the table header + content[0] = get_language_string(user, "NS_BANS_HEADER_MASK"); + content[1] = get_language_string(user, "NS_BANS_HEADER_SETBY"); + content[2] = get_language_string(user, "NS_BANS_HEADER_TRIGGERED"); + content[3] = (with_expire ? get_language_string(user, "NS_BANS_HEADER_EXPIRES") : NULL); + content[4] = get_language_string(user, "NS_BANS_HEADER_REASON"); + table_change(table, 0, content); + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + if(!cindex) + reply(getTextBot(), user, "NS_TABLE_NONE"); + reply(getTextBot(), user, "NS_TABLE_COUNT", cindex); + table_free(table); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_chanservsync.c b/src/modules/NeonServ.mod/cmd_neonserv_chanservsync.c new file mode 100644 index 0000000..8581cb2 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_chanservsync.c @@ -0,0 +1,270 @@ +/* cmd_neonserv_chanservsync.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - botnick +* argv[1] - key +*/ +#define CHANSERVSYNC_END_TIMEOUT 5 + +static void neonserv_cmd_chanservsync_notice_listener(struct UserNode *user, struct UserNode *target, char *message); +static void neonserv_cmd_chanservsync_free_cache(); +static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup); +static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new); + +struct neonserv_cmd_chanservsync_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + char *botnick; + time_t last_response; +}; + +struct neonserv_cmd_chanservsync_auth_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + int caccess; + time_t seen; + int flags; +}; + +struct neonserv_cmd_chanservsync_cache *neonserv_cmd_chanservsync_used = NULL; +const char* neonserv_cmd_chanservsync_supported[] = {"ChanServ", NULL}; + +CMD_BIND(neonserv_cmd_chanservsync) { + if(neonserv_cmd_chanservsync_used && time(0) - neonserv_cmd_chanservsync_used->last_response < CHANSERVSYNC_END_TIMEOUT) { + reply(getTextBot(), user, "NS_CHANSERVSYNC_INUSE"); + return; + } + if(neonserv_cmd_chanservsync_used) { + neonserv_cmd_chanservsync_free_cache(); + } + char *botnick = "ChanServ"; + char *key = ""; + if(argc) { + if(argv[0][0] == '!') { + key = argv[0]; + } else { + botnick = argv[0]; + if(argc > 1) + key = argv[1]; + } + } + int seed = 0; + char *tmp; + char synckey[18]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = botnick; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(synckey, "!%08x!", seed); + if(strcmp(synckey, key)) { + int f = 0; + const char **supp = neonserv_cmd_chanservsync_supported; + while(*supp) { + if(!stricmp(*supp, botnick)) { + f = 1; + break; + } + supp++; + } + if(!f) { + reply(getTextBot(), user, "NS_CHANSERVSYNC_UNSUPPORTED", botnick, client->user->nick); + } + reply(getTextBot(), user, "NS_CHANSERVSYNC_KEY", client->user->nick, botnick, botnick, synckey); + return; + } + struct neonserv_cmd_chanservsync_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->botnick = strdup(botnick); + cache->last_response = time(0); + neonserv_cmd_chanservsync_used = cache; + 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) { + if(neonserv_cmd_chanservsync_used && neonserv_cmd_chanservsync_used->client->user == target && !stricmp(user->nick, neonserv_cmd_chanservsync_used->botnick)) { + //we've got a notice from our bot... + //let's try parsing it.... + char *p = message; + char *tokens[MAXLEN]; + int tokensPos = 0; + while(*p == ' ') //skip leading spaces (airb0t) + p++; + message = p; + char *q = p; + while(*q) { + if(*q < 32) *q = ' '; + q++; + } + while((q = strstr(p, " "))) { + *q = '\0'; + do { + q++; + } while(*q == ' ' || *q == '-'); + if(*p) { + tokens[tokensPos++] = p; + } + p = q; + } + if(*p) { + tokens[tokensPos++] = p; + } + int caccess; + char *username; + if(tokensPos == 1) { + //maybe a chip-like userlist + if(tokens[0][0] == '@') { + caccess = 200; + username = &tokens[0][1]; + } else if(tokens[0][0] == '+') { + caccess = 100; + username = &tokens[0][1]; + } else + return; + } else if(tokensPos >= 2) { + if(atoi(tokens[0]) > 0) { + caccess = atoi(tokens[0]); + username = tokens[1]; + } else { + caccess = atoi(tokens[1]); + username = tokens[0]; + } + } else + return; + if(caccess < 1 || caccess > 500) return; + int flags = 0; + time_t now = time(0); + time_t seen_time = now; //now - now = 0 (never) + neonserv_cmd_chanservsync_used->last_response = now; + if(strlen(username) < 3) return; + //ok we have access and username... maybe there is something else we can parse??? + char *seen = NULL; + char *status = NULL; + if(tokensPos > 2) { + if(!stricmp("normal", tokens[2]) || !stricmp("suspended", tokens[2]) || !stricmp("bot", tokens[2])) { + status = tokens[2]; + if (tokensPos > 3) { + seen = merge_argv(tokens, 3, tokensPos); + } + } else if (tokensPos > 3) { + if(!stricmp("normal", tokens[tokensPos-1]) || !stricmp("suspended", tokens[tokensPos-1]) || !stricmp("bot", tokens[tokensPos-1])) { + status = tokens[tokensPos-1]; + seen = merge_argv(tokens, 2, tokensPos-1); + } else { + seen = merge_argv(tokens, 2, tokensPos); + } + } else { + seen = merge_argv(tokens, 2, tokensPos); + } + } + if(status && !stricmp(status, "suspended")) { + flags |= DB_CHANUSER_SUSPENDED; + } + if(seen) { + if(!stricmp(seen, "here")) + seen_time = 0; + else if(stricmp(seen, "never")) + seen_time = strToTime(user, seen); + } + seen_time = now - seen_time; + //we've collected all information now. synchronize the user (use the higher access if the user is already added) + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(username)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 0); + } else if(!stricmp(user->nick, "chanserv")) { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(username)); + userid = (int) mysql_insert_id(get_mysql_conn()); + neonserv_cmd_chanservsync_synchronize_user(neonserv_cmd_chanservsync_used->client, neonserv_cmd_chanservsync_used->textclient, neonserv_cmd_chanservsync_used->user, neonserv_cmd_chanservsync_used->chan, username, userid, caccess, seen_time, flags, 1); + } else { + //lookup auth + struct neonserv_cmd_chanservsync_auth_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = neonserv_cmd_chanservsync_used->client; + cache->textclient = neonserv_cmd_chanservsync_used->textclient; + cache->user = neonserv_cmd_chanservsync_used->user; + cache->chan = neonserv_cmd_chanservsync_used->chan; + cache->caccess = caccess; + cache->seen = seen_time; + cache->flags = flags; + lookup_authname(username, neonserv_cmd_chanservsync_auth_lookup, cache); + } + } +} + +static void neonserv_cmd_chanservsync_free_cache() { + free(neonserv_cmd_chanservsync_used->botnick); + free(neonserv_cmd_chanservsync_used); + unbind_privnotice(neonserv_cmd_chanservsync_notice_listener); + neonserv_cmd_chanservsync_used = NULL; +} + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_chanservsync_auth_lookup) { + struct neonserv_cmd_chanservsync_auth_cache *cache = data; + if(exists) { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); + int userid = (int) mysql_insert_id(get_mysql_conn()); + neonserv_cmd_chanservsync_synchronize_user(cache->client, cache->textclient, cache->user, cache->chan, auth, userid, cache->caccess, cache->seen, cache->flags, 1); + } + free(cache); +} + +static void neonserv_cmd_chanservsync_synchronize_user(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *username, int userid, int caccess, time_t seen, int flags, int new) { + //just sync the user with the given userid with the providet information + if(caccess == 500) caccess = 499; + if(new) { + //just add + printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags); + } else { + MYSQL_RES *res; + MYSQL_ROW row; + //check if already added + printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + //clvl + if(atoi(row[0]) >= caccess) return; + if(atol(row[2]) > seen) seen = atol(row[2]); + printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d', `chanuser_seen` = '%lu' WHERE `chanuser_id` = '%s'", caccess, (unsigned long) seen, row[1]); + } else + printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`, `chanuser_seen`, `chanuser_flags`) VALUES ('%d', '%d', '%d', '%lu', '%d')", chan->channel_id, userid, caccess, (unsigned long) seen, flags); + } + reply(textclient, user, "NS_CHANSERVSYNC_SYNCHRONIZED", username, caccess); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_clvl.c b/src/modules/NeonServ.mod/cmd_neonserv_clvl.c new file mode 100644 index 0000000..a541c3d --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_clvl.c @@ -0,0 +1,130 @@ +/* cmd_neonserv_clvl.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_clvl) { + int caccess; + caccess = atoi(argv[1]); + if(caccess <= 0 || caccess > 500) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return; + } + if(caccess >= getChannelAccess(user, chan)) { + 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, event, argv[0], argv[0], caccess); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_clvl_nick_lookup) { + struct neonserv_cmd_clvl_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth, int caccess) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + 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) { + //clvl + if(atoi(row[0]) >= getChannelAccess(user, chan)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } + } + 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; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_csuspend.c b/src/modules/NeonServ.mod/cmd_neonserv_csuspend.c new file mode 100644 index 0000000..9ff2fea --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_csuspend.c @@ -0,0 +1,62 @@ +/* cmd_neonserv_csuspend.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - channel +*/ +CMD_BIND(neonserv_cmd_csuspend) { + MYSQL_RES *res; + MYSQL_ROW row; + char *channel = argv[0]; + if(!is_valid_chan(channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + } else { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + if(!strcmp(row[2], "1")) { + reply(getTextBot(), user, "NS_CSUSPEND_ALREADY", channel); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + putsock(bot, "PART %s :Channel suspended.", channel); + } + printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '1' WHERE `id` = '%s'", row[1]); + reply(getTextBot(), user, "NS_CSUSPEND_DONE", channel); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_cunsuspend.c b/src/modules/NeonServ.mod/cmd_neonserv_cunsuspend.c new file mode 100644 index 0000000..53a997d --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_cunsuspend.c @@ -0,0 +1,62 @@ +/* cmd_neonserv_cunsuspend.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - channel +*/ +CMD_BIND(neonserv_cmd_cunsuspend) { + MYSQL_RES *res; + MYSQL_ROW row; + char *channel = argv[0]; + if(!is_valid_chan(channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + } else { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + if(!strcmp(row[2], "0")) { + reply(getTextBot(), user, "NS_CUNSUSPEND_NOT", channel); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + putsock(bot, "JOIN %s", channel); + } + printf_mysql_query("UPDATE `bot_channels` SET `suspended` = '0' WHERE `id` = '%s'", row[1]); + reply(getTextBot(), user, "NS_CUNSUSPEND_DONE", channel); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_dehalfop.c b/src/modules/NeonServ.mod/cmd_neonserv_dehalfop.c new file mode 100644 index 0000000..f995e0f --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_dehalfop.c @@ -0,0 +1,94 @@ +/* cmd_neonserv_dehalfop.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nicks +*/ +static USERLIST_CALLBACK(neonserv_cmd_dehalfop_userlist_lookup); +static void neonserv_cmd_dehalfop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); + +struct neonserv_cmd_dehalfop_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char **argv; + int argc; +}; + +CMD_BIND(neonserv_cmd_dehalfop) { + struct neonserv_cmd_dehalfop_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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++) { + cache->argv[i] = strdup(argv[i]); + } + cache->argc = argc; + get_userlist(chan, neonserv_cmd_dehalfop_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_dehalfop_userlist_lookup) { + struct neonserv_cmd_dehalfop_cache *cache = data; + neonserv_cmd_dehalfop_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]); + } + free(cache->argv); + free(cache); +} + +static void neonserv_cmd_dehalfop_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; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isNetworkService(cuser)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + done_users++; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDehalfop(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + reply(textclient, user, "NS_DEHALFOP_DONE", chan->name); + else + reply(textclient, user, "NS_DEHALFOP_FAIL", client->user->nick); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_dehalfopall.c b/src/modules/NeonServ.mod/cmd_neonserv_dehalfopall.c new file mode 100644 index 0000000..1cb58d0 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_dehalfopall.c @@ -0,0 +1,85 @@ +/* cmd_neonserv_dehalfopall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] (optional) nick mask +*/ +static USERLIST_CALLBACK(neonserv_cmd_dehalfopall_userlist_lookup); +static void neonserv_cmd_dehalfopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); + +struct neonserv_cmd_dehalfopall_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char **argv; + int argc; +}; + +CMD_BIND(neonserv_cmd_dehalfopall) { + struct neonserv_cmd_dehalfopall_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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++) { + cache->argv[i] = strdup(argv[i]); + } + cache->argc = argc; + get_userlist(chan, neonserv_cmd_dehalfopall_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_dehalfopall_userlist_lookup) { + struct neonserv_cmd_dehalfopall_cache *cache = data; + neonserv_cmd_dehalfopall_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]); + } + free(cache->argv); + free(cache); +} + +static void neonserv_cmd_dehalfopall_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(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + issuer_access = getChannelAccess(user, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + victim_access = getChannelAccess(chanuser->user, chan); + if(victim_access >= issuer_access || isNetworkService(chanuser->user)) continue; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDehalfop(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_DEHALFOPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_delban.c b/src/modules/NeonServ.mod/cmd_neonserv_delban.c new file mode 100644 index 0000000..3b4f9d8 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_delban.c @@ -0,0 +1,51 @@ +/* cmd_neonserv_delban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] nick|*auth|*!*@mask +*/ + +CMD_BIND(neonserv_cmd_delban) { + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char *mask = make_banmask(argv[0], hostmask_buffer); + int matching_bans = 0; + MYSQL_RES *res; + MYSQL_ROW row; + //check if the provided mask affects any existing bans + char nameBuf[20]; + printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!match(mask, row[0])) { + //remove the ban + if(strcmp(row[2], "0")) { + sprintf(nameBuf, "ban_%s", row[1]); + timeq_del_name(nameBuf); + } + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); + matching_bans++; + } + } + 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/src/modules/NeonServ.mod/cmd_neonserv_delme.c b/src/modules/NeonServ.mod/cmd_neonserv_delme.c new file mode 100644 index 0000000..256ca69 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_delme.c @@ -0,0 +1,62 @@ +/* cmd_neonserv_delme.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - key +*/ + +CMD_BIND(neonserv_cmd_delme) { + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is added + 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]) == 500) { + reply(getTextBot(), user, "NS_DELME_OWNER", chan->name); + return; + } + //check key + int seed = 0; + char *tmp; + static char unregkey[16]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(unregkey, "%08x", seed); + if(argc < 1 || strcmp(argv[0], unregkey)) { + reply(getTextBot(), user, "NS_DELME_KEY", unregkey); + return; + } else { + //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; + } + } + } + reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_delrank.c b/src/modules/NeonServ.mod/cmd_neonserv_delrank.c new file mode 100644 index 0000000..489b32a --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_delrank.c @@ -0,0 +1,37 @@ +/* cmd_neonserv_delrank.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] rank name +*/ + +CMD_BIND(neonserv_cmd_delrank) { + char *name = merge_argv(argv, 0, argc); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_DELRANK_NOT_FOUND", name); + return; + } + printf_mysql_query("UPDATE `users` SET `user_rank` = '0', `user_access` = '0' WHERE `user_rank` = '%s'", row[0]); + printf_mysql_query("DELETE FROM `support_ranks` WHERE `rank_id` = '%s'", row[0]); + reply(getTextBot(), user, "NS_DELRANK_DELETED", row[1]); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_deluser.c b/src/modules/NeonServ.mod/cmd_neonserv_deluser.c new file mode 100644 index 0000000..5188f01 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_deluser.c @@ -0,0 +1,113 @@ +/* cmd_neonserv_deluser.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_deluser) { + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_deluser_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_deluser_nick_lookup) { + struct neonserv_cmd_deluser_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + 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)) { + 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; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_deop.c b/src/modules/NeonServ.mod/cmd_neonserv_deop.c new file mode 100644 index 0000000..20a4f44 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_deop.c @@ -0,0 +1,94 @@ +/* cmd_neonserv_deop.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_deop) { + struct neonserv_cmd_deop_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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++) { + cache->argv[i] = strdup(argv[i]); + } + cache->argc = argc; + get_userlist(chan, neonserv_cmd_deop_userlist_lookup, cache); +} + +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->event, cache->argv, cache->argc); + int i; + for(i = 0; i < cache->argc; i++) { + free(cache->argv[i]); + } + free(cache->argv); + free(cache); +} + +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; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isNetworkService(cuser)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + done_users++; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDeop(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + 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/src/modules/NeonServ.mod/cmd_neonserv_deopall.c b/src/modules/NeonServ.mod/cmd_neonserv_deopall.c new file mode 100644 index 0000000..7b1cdb2 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_deopall.c @@ -0,0 +1,85 @@ +/* cmd_neonserv_deopall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_deopall) { + struct neonserv_cmd_deopall_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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++) { + cache->argv[i] = strdup(argv[i]); + } + cache->argc = argc; + get_userlist(chan, neonserv_cmd_deopall_userlist_lookup, cache); +} + +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->event, cache->argv, cache->argc); + int i; + for(i = 0; i < cache->argc; i++) { + free(cache->argv[i]); + } + free(cache->argv); + free(cache); +} + +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(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + issuer_access = getChannelAccess(user, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + victim_access = getChannelAccess(chanuser->user, chan); + if(victim_access >= issuer_access || isNetworkService(chanuser->user)) continue; + if(!(chanuser->flags & CHANUSERFLAG_OPPED)) continue; + modeBufferDeop(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_DEOPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_devoice.c b/src/modules/NeonServ.mod/cmd_neonserv_devoice.c new file mode 100644 index 0000000..e7ced34 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_devoice.c @@ -0,0 +1,50 @@ +/* cmd_neonserv_devoice.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nicks +*/ + +CMD_BIND(neonserv_cmd_devoice) { + int i, done_users = 0; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(i = 0; i < argc; i++) { + cuser = searchUserByNick(argv[i]); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isUserProtected(chan, cuser, user)) { + reply(getTextBot(), user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + done_users++; + if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; + modeBufferDevoice(modeBuf, argv[i]); + } + freeModeBuffer(modeBuf); + if(done_users == argc) + 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/src/modules/NeonServ.mod/cmd_neonserv_devoiceall.c b/src/modules/NeonServ.mod/cmd_neonserv_devoiceall.c new file mode 100644 index 0000000..9254e46 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_devoiceall.c @@ -0,0 +1,46 @@ +/* cmd_neonserv_devoiceall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] (optional) nick mask +*/ + +CMD_BIND(neonserv_cmd_devoiceall) { + int issuer_access, victim_access, done_users = 0; + char *nickmask = NULL; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + check_mysql(); + if(argc > 0) + nickmask = argv[0]; + modeBuf = initModeBuffer(client, chan); + issuer_access = getChannelAccess(user, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + victim_access = getChannelAccess(chanuser->user, chan); + if(victim_access >= issuer_access) continue; + if(!(chanuser->flags & CHANUSERFLAG_VOICED)) continue; + modeBufferDevoice(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(getTextBot(), user, "NS_DEVOICEALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_down.c b/src/modules/NeonServ.mod/cmd_neonserv_down.c new file mode 100644 index 0000000..fd29475 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_down.c @@ -0,0 +1,38 @@ +/* cmd_neonserv_down.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +CMD_BIND(neonserv_cmd_down) { + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) { + reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name); + return; + } + 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/src/modules/NeonServ.mod/cmd_neonserv_downall.c b/src/modules/NeonServ.mod/cmd_neonserv_downall.c new file mode 100644 index 0000000..a7add47 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_downall.c @@ -0,0 +1,50 @@ +/* cmd_neonserv_downall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +CMD_BIND(neonserv_cmd_downall) { + struct ChanUser *chanuser; + int botid = client->botid; + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) { + chan = chanuser->chan; + loadChannelSettings(chan); + 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; + int done = 0; + client = getChannelBot(chan, botid); + if(!client) continue; + if((chanuser->flags & CHANUSERFLAG_OPPED)) { + putsock(client, "MODE %s -o %s", chan->name, user->nick); + 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/src/modules/NeonServ.mod/cmd_neonserv_events.c b/src/modules/NeonServ.mod/cmd_neonserv_events.c new file mode 100644 index 0000000..de4fd6c --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_events.c @@ -0,0 +1,57 @@ +/* cmd_neonserv_events.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] time +* argv[1-*] match +*/ + +CMD_BIND(neonserv_cmd_events) { + char *str_match; + int duration = (argc ? strToTime(user, argv[0]) : 0); + if(argc > (duration ? 1 : 0)) + str_match = merge_argv(argv, (duration ? 1 : 0), argc); + else + str_match = ""; + if(!duration) duration = (60*60*24); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `time`, `auth`, `nick`, `command` FROM `events` WHERE `cid` = '%d' AND `time` > '%lu' ORDER BY `time` ASC", chan->channel_id, ((unsigned long) time(0) - duration)); + res = mysql_use(); + int skip = mysql_num_rows(res) - 100; + int count = 0; + char timeBuf[50]; + struct tm *timeinfo; + time_t event_time; + if(skip < 0) skip = 0; + reply(getTextBot(), user, "NS_EVENTS_HEADER"); + while ((row = mysql_fetch_row(res)) != NULL) { + if(skip) { + skip--; + continue; + } + if(*str_match && match(str_match, row[3])) continue; + count++; + event_time = (time_t) atol(row[0]); + timeinfo = localtime(&event_time); + strftime(timeBuf, 80, "%X %x", timeinfo); + reply(getTextBot(), user, "[%s] [%s:%s]: %s", timeBuf, row[2], row[1], row[3]); + } + reply(getTextBot(), user, "NS_TABLE_COUNT", count); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_extscript.c b/src/modules/NeonServ.mod/cmd_neonserv_extscript.c new file mode 100644 index 0000000..e4a4e2e --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_extscript.c @@ -0,0 +1,170 @@ +/* cmd_neonserv_extscript.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" +#include + +/* +* argv[0] 'toys' if it's a toy command (check if toys are enabled) +* argv[0-*] script name & parameter patterns +* argv[argc-1] all arguments passed to the command +*/ + +static TIMEQ_CALLBACK(neonserv_cmd_extscript_callback); + +struct neonserv_cmd_extscript_cache { + struct ClientSocket *client, *textclient; + struct Event *event; + struct UserNode *user; + struct ChanNode *chan; + int answere_channel; + FILE *pipe; +}; + +CMD_BIND(neonserv_cmd_extscript) { + int i, j; + char *args[MAXNUMPARAMS]; + int argpos = 0; + char *next, *curr; + char command[1024]; + int commandpos = 0; + char part[MAXLEN]; + int partpos; + int escape_param; + int answere_channel = 0; + //check first arg + if(argc && !stricmp(argv[0], "toys")) { + if(!chan) return; //toys are not allowed via query + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name)); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row || !strcmp(row[0], "0")) { + //disabled + reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name); + return; + } else if(!strcmp(row[0], "2")) + answere_channel = 1; + argc--; + argv++; + } + //parse arguments + if(argc < 2) return; + curr = argv[argc-1]; + while(curr) { + next = strstr(curr, " "); + args[argpos++] = curr; + if(next) { + *next = '\0'; + curr = next+1; + } else + curr = NULL; + } + //parse command pattern and build command + commandpos = sprintf(command, "%s", argv[0]); + for(i = 1; i < argc-1; i++) { + partpos = 0; + escape_param = 1; + if(argv[i][0] == '$') { + argv[i]++; + if(argv[i][strlen(argv[i])-1] == '-') { + argv[i][strlen(argv[i])-1] = '\0'; + j = atoi(argv[i]); + if(j <= argpos) + partpos = sprintf(part, "%s", merge_argv(args, j-1, argpos)); + } else if((j = atoi(argv[i])) > 0) { + if(j <= argpos) + partpos = sprintf(part, "%s", args[j-1]); + } else if(!strcmp(argv[i], "c")) { + partpos = sprintf(part, "%s", (chan ? chan->name : "")); + } else if(!strcmp(argv[i], "n")) { + partpos = sprintf(part, "%s", user->nick); + } else if(!strcmp(argv[i], "a")) { + partpos = sprintf(part, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "")); + } else if(!strcmp(argv[i], "access")) { + if(chan) + partpos = sprintf(part, "%d", getChannelAccess(user, chan)); + } + } else { + partpos = sprintf(part, "%s", argv[i]); + escape_param = 0; + } + //escape shell argument + command[commandpos++] = ' '; + if(escape_param) { + command[commandpos++] = '\''; + for(j = 0; j < partpos; j++) { + if(part[j] == '\'') { + command[commandpos++] = '\''; + command[commandpos++] = '\\'; + command[commandpos++] = '\''; + command[commandpos++] = '\''; + } else + command[commandpos++] = part[j]; + } + command[commandpos++] = '\''; + } else + commandpos += sprintf(command + commandpos, " %s", part); + } + command[commandpos] = '\0'; + //we should now have a valid command + + struct neonserv_cmd_extscript_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->event = event; + cache->user = user; + cache->chan = chan; + cache->answere_channel = answere_channel; + cache->pipe = popen(command, "r"); + #ifndef WIN32 + fcntl(fileno(cache->pipe), F_SETFL, O_NONBLOCK); + #endif + timeq_uadd(200, neonserv_cmd_extscript_callback, cache); +} + +static TIMEQ_CALLBACK(neonserv_cmd_extscript_callback) { + struct neonserv_cmd_extscript_cache *cache = data; + char command[512]; + char *a; + if(feof(cache->pipe)) { + pclose(cache->pipe); + free(cache); + return; + } + while (fgets(command, 512, cache->pipe) != NULL) { + if((a = strchr(command, '\n'))) + *a = '\0'; + if(!stricmp(command, "/log")) { + logEvent(cache->event); + continue; + } + if(cache->answere_channel) + putsock(cache->client, "PRIVMSG %s :%s", cache->chan->name, command); + else + reply(cache->textclient, cache->user, "%s", command); + } + timeq_uadd(200, neonserv_cmd_extscript_callback, cache); +} + + + diff --git a/src/modules/NeonServ.mod/cmd_neonserv_giveowner.c b/src/modules/NeonServ.mod/cmd_neonserv_giveowner.c new file mode 100644 index 0000000..9cf5ae7 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_giveowner.c @@ -0,0 +1,157 @@ +/* cmd_neonserv_giveowner.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +* argv[1] - key +*/ + +#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, 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; +}; + +CMD_BIND(neonserv_cmd_giveowner) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_lastgiveowner` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(strcmp(row[0], "0") && (atoi(row[0]) + GIVEOWNER_TIMEOUT) > time(0)) { + char timeBuf[MAXLEN]; + reply(getTextBot(), user, "NS_GIVEOWNER_TIMEOUT", timeToStr(user, (GIVEOWNER_TIMEOUT - (time(0) - atoi(row[0]))), 2, timeBuf), chan->name); + return; + } + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + 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) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_giveowner_nick_lookup) { + struct neonserv_cmd_giveowner_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, 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"); + return; + } + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(auth)); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + int expire_time = atoi(row[1]); + if(expire_time) { + if(expire_time - time(0) <= 0) { + printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); + } else { + reply(getTextBot(), user, "NS_DNR_SET_ANONYM", auth); + return; + } + } else { + reply(getTextBot(), user, "NS_DNR_SET_ANONYM", auth); + return; + } + } + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + 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) { + int seed = 0; + char *tmp; + char giveownerkey[16]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(giveownerkey, "%08x", seed); + if(key && !stricmp(giveownerkey, key)) { + //give ownership + printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '500' WHERE `chanuser_id` = '%s'", row[1]); + 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_from_uid`, `owner_history_to_uid`, `owner_history_time`) VALUE ('%d', (SELECT `user_id` FROM `users` WHERE `user_user` = '%s'), '%d', UNIX_TIMESTAMP())", chan->channel_id, escape_string(user->auth), userid); + reply(textclient, user, "NS_GIVEOWNER_DONE", chan->name, auth); + logEvent(event); + } else { + reply(textclient, user, "NS_GIVEOWNER_CONFIRM", auth, giveownerkey); + } + return; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_halfop.c b/src/modules/NeonServ.mod/cmd_neonserv_halfop.c new file mode 100644 index 0000000..ba684cb --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_halfop.c @@ -0,0 +1,93 @@ +/* cmd_neonserv_halfop.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nicks +*/ +static USERLIST_CALLBACK(neonserv_cmd_halfop_userlist_lookup); +static void neonserv_cmd_halfop_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nicks); + +struct neonserv_cmd_halfop_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nicks; +}; + +CMD_BIND(neonserv_cmd_halfop) { + struct neonserv_cmd_halfop_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->nicks = strdup(merge_argv(argv, 0, argc)); + get_userlist_if_invisible(chan, neonserv_cmd_halfop_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_halfop_userlist_lookup) { + struct neonserv_cmd_halfop_cache *cache = data; + neonserv_cmd_halfop_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nicks); + free(cache->nicks); + free(cache); +} + +static void neonserv_cmd_halfop_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; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + char *a, *b = nicks; + do { + a = strstr(b, " "); + if(a) *a = '\0'; + total_users++; + cuser = searchUserByNick(b); + if(!cuser) { + //check for an invisible user + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(!stricmp(chanuser->user->nick, b)) { + cuser = chanuser->user; + break; + } + } + if(!cuser) continue; + } else { + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + } + done_users++; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferHalfop(modeBuf, b); + if(a) { + b = a+1; + } + } while(a); + freeModeBuffer(modeBuf); + if(done_users == total_users) + reply(textclient, user, "NS_HALFOP_DONE", chan->name); + else + reply(textclient, user, "NS_HALFOP_FAIL", client->user->nick); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_halfopall.c b/src/modules/NeonServ.mod/cmd_neonserv_halfopall.c new file mode 100644 index 0000000..a52ad6d --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_halfopall.c @@ -0,0 +1,74 @@ +/* cmd_neonserv_halfopall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] "force" +* argv[1] (optional) nick mask +*/ +static USERLIST_CALLBACK(neonserv_cmd_halfopall_userlist_lookup); +static void neonserv_cmd_halfopall_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask); + +struct neonserv_cmd_halfopall_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nickmask; +}; + +CMD_BIND(neonserv_cmd_halfopall) { + struct neonserv_cmd_halfopall_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + if(argc) { + cache->nickmask = strdup(argv[0]); + } else + cache->nickmask = NULL; + get_userlist_if_invisible(chan, neonserv_cmd_halfopall_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_halfopall_userlist_lookup) { + struct neonserv_cmd_halfopall_cache *cache = data; + neonserv_cmd_halfopall_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask); + if(cache->nickmask) + free(cache->nickmask); + free(cache); +} + +static void neonserv_cmd_halfopall_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; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferHalfop(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(textclient, user, "NS_HALFOPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_help.c b/src/modules/NeonServ.mod/cmd_neonserv_help.c new file mode 100644 index 0000000..20ec2c2 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_help.c @@ -0,0 +1,97 @@ +/* cmd_neonserv_help.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] index +*/ + +CMD_BIND(neonserv_cmd_help) { + char *ident; + if(argc) + ident = merge_argv(argv, 0, argc); + else + ident = "0"; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + char *lang; + if ((row = mysql_fetch_row(res)) != NULL) + lang = row[0]; + else + lang = "en"; + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + if(stricmp(lang, "en")) { + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident)); + res = mysql_use(); + } + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_HELP_TOPIC"); + return; + } + } + char sendBuf[MAXLEN]; + int sendBufPos = 0; + int i; + for(i = 0; i < strlen(row[0]); i++) { + switch(row[0][i]) { + case '\n': + if(sendBufPos) { + sendBuf[sendBufPos] = '\0'; + reply(getTextBot(), user, "%s", sendBuf); + sendBufPos = 0; + } + break; + case '$': + switch(row[0][i+1]) { + case 'b': + sendBuf[sendBufPos++] = 2; + i++; + break; + case 'k': + sendBuf[sendBufPos++] = 3; + i++; + break; + case 'u': + sendBuf[sendBufPos++] = 31; + i++; + break; + case 'C': + case 'S': + sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick); + i++; + break; + default: + sendBuf[sendBufPos++] = '$'; + break; + } + break; + default: + sendBuf[sendBufPos++] = row[0][i]; + break; + } + } + if(sendBufPos) { + sendBuf[sendBufPos] = '\0'; + reply(getTextBot(), user, "%s", sendBuf); + sendBufPos = 0; + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_info.c b/src/modules/NeonServ.mod/cmd_neonserv_info.c new file mode 100644 index 0000000..17a9df6 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_info.c @@ -0,0 +1,105 @@ +/* cmd_neonserv_info.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no parameters +*/ + +CMD_BIND(neonserv_cmd_info) { + MYSQL_RES *res; + MYSQL_ROW row, row2; + struct Table *table; + printf_mysql_query("SELECT `channel_defaulttopic`, `channel_modes`, `channel_maxusers`, `channel_lastvisit`, `channel_registered`, `user_user` FROM `channels` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + table = table_init(2, 9, 0); + table_set_bold(table, 0, 1); + char *content[2]; + reply(getTextBot(), user, "NS_INFO_HEADER", chan->name); + content[0] = get_language_string(user, "NS_INFO_DEFAULTTOPIC"); + content[1] = row[0]; + table_add(table, content); + content[0] = get_language_string(user, "NS_INFO_MODELOCK"); + content[1] = row[1]; + table_add(table, content); + content[0] = get_language_string(user, "NS_INFO_RECORD"); + content[1] = row[2]; + table_add(table, content); + printf_mysql_query("SELECT `user_user`, `chanuser_access` FROM `chanusers` LEFT JOIN `users` ON `user_id` = `chanuser_uid` WHERE `chanuser_cid` = '%d'", chan->channel_id); + res = mysql_use(); + char ownerstr[MAXLEN]; + int ownerpos = 0, usercount = 0; + int userisowner = 0; + while((row2 = mysql_fetch_row(res))) { + if(!strcmp(row2[1], "500")) { + ownerpos += sprintf(ownerstr + ownerpos, (ownerpos ? ", %s" : "%s"), row2[0]); + if((user->flags & USERFLAG_ISAUTHED) && !stricmp(row2[0], user->auth)) + userisowner = 1; + } + usercount++; + } + content[0] = get_language_string(user, "NS_INFO_OWNER"); + content[1] = ownerstr; + table_add(table, content); + sprintf(ownerstr, "%d", usercount); + content[0] = get_language_string(user, "NS_INFO_USERS"); + content[1] = ownerstr; + table_add(table, content); + printf_mysql_query("SELECT COUNT(*) FROM `bans` WHERE `ban_channel` = '%d'", chan->channel_id); + res = mysql_use(); + row2 = mysql_fetch_row(res); + content[0] = get_language_string(user, "NS_INFO_BANS"); + content[1] = row2[0]; + table_add(table, content); + content[0] = get_language_string(user, "NS_INFO_VISITED"); + content[1] = timeToStr(user, time(0) - atoi(row[3]), 2, ownerstr); + table_add(table, content); + if(strcmp(row[4], "0")) { + content[0] = get_language_string(user, "NS_INFO_REGISTERED"); + content[1] = timeToStr(user, time(0) - atoi(row[4]), 2, ownerstr); + table_add(table, content); + } + if(row[5] && isGodMode(user)) { + content[0] = get_language_string(user, "NS_INFO_REGISTRAR"); + content[1] = row[5]; + table_add(table, content); + } + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + if(userisowner || isGodMode(user)) { + printf_mysql_query("SELECT `owner_history_time`, a.`user_user`, b.`user_user` FROM `owner_history` LEFT JOIN `users` a ON `owner_history_from_uid` = a.`user_id` LEFT JOIN `users` b ON `owner_history_to_uid` = b.`user_id` WHERE `owner_history_cid` = '%d'", chan->channel_id); + res = mysql_use(); + if(mysql_num_rows(res)) { + reply(getTextBot(), user, "NS_INFO_OWNERLOG", chan->name); + time_t rawtime; + struct tm *timeinfo; + char timeBuf[80]; + while((row = mysql_fetch_row(res))) { + rawtime = (time_t) atol(row[0]); + timeinfo = localtime(&rawtime); + strftime(timeBuf, 80, "%c", timeinfo); + reply(getTextBot(), user, "NS_INFO_OWNERCHANGE", row[1], row[2], timeBuf); + } + } + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_invite.c b/src/modules/NeonServ.mod/cmd_neonserv_invite.c new file mode 100644 index 0000000..60c00a2 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_invite.c @@ -0,0 +1,180 @@ +/* cmd_neonserv_invite.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +*/ +static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup); +static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth); +static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout); +static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan); +static int neonserv_cmd_invite_is_timeout(char *nick, char *chan); +static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout); + + +struct neonserv_cmd_invite_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + struct Event *event; + char *nick; +}; + +struct neonserv_cmd_invite_timeout { + char *nick; + char *chan; + + struct neonserv_cmd_invite_timeout *next; +}; + +static struct neonserv_cmd_invite_timeout *first_timeout = NULL, *last_timeout = NULL; + +CMD_BIND(neonserv_cmd_invite) { + if(neonserv_cmd_invite_is_timeout(argv[0], chan->name)) { + reply(getTextBot(), user, "NS_INVITE_TIMEOUT", argv[0], chan->name); + return; + } + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } else if(getChanUser(cuser, chan)) { + reply(getTextBot(), user, "NS_INVITE_ON_CHAN", cuser->nick, chan->name); + /* BUG + This check does not work if the user is invisible (CHMODE +D/+d) + to fix this we'd need to request the full userlist... + this is really senseless to invite a simple user so we simply mark this bug as unsolvable. + */ + return; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_invite_async1(client, getTextBot(), user, chan, event, argv[0], cuser->auth); + } else { + struct neonserv_cmd_invite_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(argv[0]); + get_userauth(cuser, neonserv_cmd_invite_nick_lookup, cache); + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_invite_nick_lookup) { + struct neonserv_cmd_invite_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } else + neonserv_cmd_invite_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->nick, ((user->flags & USERFLAG_ISAUTHED) ? user->auth : NULL)); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_invite_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nick, char *auth) { + if(auth) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + //check if the user has set noinvite + printf_mysql_query("SELECT `id` FROM `noinvite` WHERE `uid` = '%s' AND `cid` = '%d'", row[0], chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(textclient, user, "NS_INVITE_RESTRICTION", nick, chan->name); + return; + } + } + } + struct neonserv_cmd_invite_timeout *timeout = neonserv_cmd_invite_add_timeout(nick, chan->name); + timeq_add(INVITE_TIMEOUT, neonserv_cmd_invite_timeout_timeout, timeout); + putsock(client, "INVITE %s %s", nick, chan->name); + struct UserNode *tmpu = getUserByNick(nick); + if(!tmpu) { + tmpu = createTempUser(nick); + tmpu->flags |= USERFLAG_ISTMPUSER | (auth ? USERFLAG_ISAUTHED : 0); + if(auth) + strcpy(tmpu->auth, auth); + } + reply(textclient, tmpu, "NS_INVITE_DONE_USER", chan->name, user->nick, client->user->nick); + reply(textclient, user, "NS_INVITE_DONE", nick, chan->name); +} + +static TIMEQ_CALLBACK(neonserv_cmd_invite_timeout_timeout) { + struct neonserv_cmd_invite_timeout *entry = data; + neonserv_cmd_invite_del_timeout(entry); +} + +static struct neonserv_cmd_invite_timeout* neonserv_cmd_invite_add_timeout(char *nick, char *chan) { + struct neonserv_cmd_invite_timeout *entry = malloc(sizeof(*entry)); + if (!entry) { + perror("malloc() failed"); + return NULL; + } + entry->next = NULL; + entry->nick = strdup(nick); + entry->chan = strdup(chan); + if(last_timeout) { + last_timeout->next = entry; + last_timeout = entry; + } else { + last_timeout = entry; + first_timeout = entry; + } + return entry; +} + +static int neonserv_cmd_invite_is_timeout(char *nick, char *chan) { + if(!first_timeout) return 0; + struct neonserv_cmd_invite_timeout *entry; + for(entry = first_timeout; entry; entry = entry->next) { + if(!stricmp(entry->nick, nick) && !stricmp(entry->chan, chan)) + return 1; + } + return 0; +} + +static void neonserv_cmd_invite_del_timeout(struct neonserv_cmd_invite_timeout *timeout) { + struct neonserv_cmd_invite_timeout *entry, *prev = NULL; + for(entry = first_timeout; entry; entry = entry->next) { + if(entry == timeout) { + if(prev) + prev->next = entry->next; + else + first_timeout = entry->next; + break; + } else + prev = entry; + } + if(last_timeout == timeout) + last_timeout = prev; + free(timeout->nick); + free(timeout->chan); + free(timeout); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_inviteme.c b/src/modules/NeonServ.mod/cmd_neonserv_inviteme.c new file mode 100644 index 0000000..54c2dbf --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_inviteme.c @@ -0,0 +1,36 @@ +/* cmd_neonserv_inviteme.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +CMD_BIND(neonserv_cmd_inviteme) { + if(getChanUser(user, chan)) { + reply(getTextBot(), user, "NS_INVITEME_ON_CHAN", chan->name); + /* BUG + This check does not work if the user is invisible (CHMODE +D/+d) + to fix this we'd need to request the full userlist... + this is really senseless to invite a simple user so we simply mark this bug as unsolvable. + */ + return; + } + putsock(client, "INVITE %s %s", user->nick, chan->name); + reply(getTextBot(), user, "NS_INVITEME_DONE", chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_kick.c b/src/modules/NeonServ.mod/cmd_neonserv_kick.c new file mode 100644 index 0000000..7ffcf65 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_kick.c @@ -0,0 +1,167 @@ +/* cmd_neonserv_kick.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] nick[,*auth[,*!*@mask[...]]] +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_kick) { + struct neonserv_cmd_kick_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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_with_invisible(chan, neonserv_cmd_kick_userlist_lookup, cache); +} + +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->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, struct Event *event, char *nicks, char *reason) { + int i, kicked_users = 0, provided_nicks = 0; + char *nick, *nextnick; + struct UserNode *cuser; + struct ChanUser *chanuser; + nextnick = nicks; + while((nick = nextnick)) { + nextnick = strstr(nick, ","); + if(nextnick) { + *nextnick = '\0'; + nextnick++; + } + if(!*nick) continue; + if(is_ircmask(nick)) { + //KICK HOSTMASK + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct ChanUser *kick_chanuser[chan->usercount]; + int kick_chanuser_pos = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(nick, usermask)) { + provided_nicks++; + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + continue; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + kick_chanuser[kick_chanuser_pos++] = chanuser; + if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) { + kick_chanuser_pos = 0; + reply(textclient, user, "NS_LAME_MASK", nick); + break; + } + } + } + for(i = 0; i < kick_chanuser_pos; i++) { + kicked_users++; + putsock(client, "KICK %s %s :(%s) %s", chan->name, kick_chanuser[i]->user->nick, user->nick, reason); + } + } else if(*nick == '*') { + //KICK AUTH + nick++; + cuser = NULL; + if(!stricmp(user->auth, nick)) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) { + provided_nicks++; + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + continue; + } + if(!cuser) { + //check if the user is protected + if(isUserProtected(chan, chanuser->user, user)) { + reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick); + break; //all other users are also protected... + } + cuser = chanuser->user; + } + kicked_users++; + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + } else { + provided_nicks++; + cuser = NULL; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(!stricmp(chanuser->user->nick, nick)) { + cuser = chanuser->user; + } + } + if(!cuser) continue; + if(isNetworkService(cuser)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + continue; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + kicked_users++; + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + if(kicked_users == provided_nicks) + 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/src/modules/NeonServ.mod/cmd_neonserv_kickban.c b/src/modules/NeonServ.mod/cmd_neonserv_kickban.c new file mode 100644 index 0000000..1123cd7 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_kickban.c @@ -0,0 +1,169 @@ +/* cmd_neonserv_kickban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] nick[,*auth[,*!*@mask[...]]] +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_kickban) { + struct neonserv_cmd_kickban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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_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->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, struct Event *event, char *nicks, char *reason) { + int i, kicked_users = 0, provided_nicks = 0; + char *nick, *nextnick; + struct UserNode *cuser; + struct ChanUser *chanuser; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + nextnick = nicks; + while((nick = nextnick)) { + nextnick = strstr(nick, ","); + if(nextnick) { + *nextnick = '\0'; + nextnick++; + } + if(!*nick) continue; + if(is_ircmask(nick)) { + //KICK HOSTMASK + struct ChanUser *kickban_chanuser[chan->usercount]; + int kick_chanuser_pos = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(nick, usermask)) { + provided_nicks++; + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + continue; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + kickban_chanuser[kick_chanuser_pos++] = chanuser; + if(kick_chanuser_pos > 4 && (kick_chanuser_pos * 3) > chan->usercount && !isGodMode(user)) { + kick_chanuser_pos = 0; + reply(textclient, user, "NS_LAME_MASK", nick); + break; + } + } + } + for(i = 0; i < kick_chanuser_pos; i++) { + if(i == 0) { + putsock(client, "MODE %s +b %s", chan->name, nick); + } + kicked_users++; + putsock(client, "KICK %s %s :(%s) %s", chan->name, kickban_chanuser[i]->user->nick, user->nick, reason); + } + } else if(*nick == '*') { + //KICK AUTH + nick++; + cuser = NULL; + if(!stricmp(user->auth, nick)) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, nick)) { + provided_nicks++; + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + continue; + } + if(!cuser) { + //check if the user is protected + if(isUserProtected(chan, chanuser->user, user)) { + reply(textclient, user, "NS_USER_PROTECTED", chanuser->user->nick); + break; //all other users are also protected... + } + cuser = chanuser->user; + } + kicked_users++; + putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask)); + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + } else { + provided_nicks++; + cuser = searchUserByNick(nick); + if(!cuser) continue; + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + if(isNetworkService(cuser)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + continue; + } + if(cuser == user || ((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth))) { + reply(textclient, user, "NS_YOU_PROTECTED"); + continue; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + continue; + } + kicked_users++; + putsock(client, "MODE %s +b %s", chan->name, generate_banmask(cuser, usermask)); + putsock(client, "KICK %s %s :(%s) %s", chan->name, cuser->nick, user->nick, reason); + } + } + if(kicked_users == provided_nicks) + 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/src/modules/NeonServ.mod/cmd_neonserv_listrank.c b/src/modules/NeonServ.mod/cmd_neonserv_listrank.c new file mode 100644 index 0000000..65d53cf --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_listrank.c @@ -0,0 +1,77 @@ +/* cmd_neonserv_listrank.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +CMD_BIND(neonserv_cmd_listrank) { + MYSQL_RES *res, *res2; + MYSQL_ROW row, row2; + struct Table *table; + int ranks = 0; + printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` ORDER BY `rank_order` ASC"); + res = mysql_use(); + table = table_init(3, mysql_num_rows(res) + 1, 0); + char *content[3]; + content[0] = get_language_string(user, "NS_LISTRANK_ID"); + content[1] = get_language_string(user, "NS_LISTRANK_NAME"); + content[2] = get_language_string(user, "NS_LISTRANK_ASSIGNED"); + table_add(table, content); + char usersBuf[MAXLEN]; + int usersPos, userCount; + char assignedBuf[MAXLEN]; + while ((row = mysql_fetch_row(res)) != NULL) { + ranks++; + content[0] = row[0]; + content[1] = row[1]; + printf_mysql_query("SELECT `user_user`, `user_god` FROM `users` WHERE `user_rank` = '%s'", row[0]); + res2 = mysql_use(); + usersPos = 0; + userCount = 0; + while((row2 = mysql_fetch_row(res2)) != NULL) { + usersPos += sprintf(usersBuf+usersPos, (usersPos ? ", %s%s" : "%s%s"), (strcmp(row2[1], "0") ? "@" : ""), row2[0]); + userCount++; + } + sprintf(assignedBuf, (userCount ? "%d (%s)" : "%d"), userCount, usersBuf); + content[2] = assignedBuf; + table_add(table, content); + } + //send the table + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + if(!ranks) + reply(getTextBot(), user, "NS_TABLE_NONE"); + table_free(table); + printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_rank` = '0' AND `user_access` > 0"); + res2 = mysql_use(); + usersPos = 0; + userCount = 0; + while((row2 = mysql_fetch_row(res2)) != NULL) { + usersPos += sprintf(usersBuf+usersPos, (usersPos ? ", %s%s" : "%s%s"), (strcmp(row2[1], "0") ? "@" : ""), row2[0]); + userCount++; + } + reply(getTextBot(), user, "NS_LISTRANK_UNRANKED", userCount); + if(userCount) { + reply(getTextBot(), user, " %s", usersBuf); + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_mdeluser.c b/src/modules/NeonServ.mod/cmd_neonserv_mdeluser.c new file mode 100644 index 0000000..50090dd --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_mdeluser.c @@ -0,0 +1,64 @@ +/* cmd_neonserv_mdeluser.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] access (format: minaccess-maxaccess) +* argv[1] pattern +*/ + +CMD_BIND(neonserv_cmd_mdeluser) { + int min_access, max_access; + char *seperator = strstr(argv[0], "-"); + if(seperator) { + *seperator = '\0'; + seperator++; + min_access = atoi(argv[0]); + max_access = atoi(seperator); + if(max_access < min_access) { + reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access); + return; + } + } else { + min_access = atoi(argv[0]); + max_access = min_access; + } + if(max_access >= getChannelAccess(user, chan)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_NO_ACCESS"); + return; + } + } + MYSQL_RES *res; + MYSQL_ROW row; + int del_count = 0; + printf_mysql_query("SELECT `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access); + res = mysql_use(); + while((row = mysql_fetch_row(res)) != NULL) { + if(!match(argv[1], row[0])) { + del_count++; + printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[1]); + } + } + reply(getTextBot(), user, "NS_MDELUSER_DONE", del_count, argv[1], min_access, max_access, chan->name); + if(del_count) + logEvent(event); +} + diff --git a/src/modules/NeonServ.mod/cmd_neonserv_mode.c b/src/modules/NeonServ.mod/cmd_neonserv_mode.c new file mode 100644 index 0000000..8a11e36 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_mode.c @@ -0,0 +1,297 @@ +/* cmd_neonserv_mode.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - modes +* argv[1-*] - parameters +*/ +static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup); +static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode); + +struct neonserv_cmd_mode_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *mode; +}; + +CMD_BIND(neonserv_cmd_mode) { + struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->mode = strdup(merge_argv(argv, 0, argc)); + get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup) { + struct neonserv_cmd_mode_cache *cache = data; + neonserv_cmd_mode_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mode); + free(cache->mode); + free(cache); +} + +static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode) { + MYSQL_ROW row, defaults = NULL; + int i, arg, add = 1, skip = 0; + unsigned int modetype; + int db_canop, db_canvoice, db_canban, db_enfmodes; + struct ModeNode *modelock = createModeNode(NULL), *changemodes = createModeNode(NULL); + struct ModeBuffer *modeBuf; + struct UserNode *cuser; + struct ChanUser *chanuser; + modeBuf = initModeBuffer(client, chan); + printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + row = mysql_fetch_row(mysql_use()); + if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) { + printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'"); + defaults = mysql_fetch_row(mysql_use()); + } + db_canop = atoi((row[0] ? row[0] : defaults[0])); + db_canvoice = atoi((row[1] ? row[1] : defaults[1])); + db_canban = atoi((row[2] ? row[2] : defaults[2])); + db_enfmodes = atoi((row[3] ? row[3] : defaults[3])); + if(row[4]) + parseModeString(modelock, row[4]); + else if(defaults[4]) + parseModeString(modelock, defaults[4]); + int uaccess = getChannelAccess(user, chan); + char *a, *b = mode; + char *argv[MAXNUMPARAMS]; + char *carg; + char tmp[MAXLEN]; + int argc = 0; + do { + a = strstr(b, " "); + if(a) *a = '\0'; + argv[argc++] = b; + if(argc == MAXNUMPARAMS) break; + if(a) b = a+1; + } while(a); + arg = 0; + while(arg < argc) { + char *modeStr = argv[arg++]; + for(i = 0; i < strlen(modeStr); i++) { + switch(modeStr[i]) { + case '+': + add = 1; + break; + case '-': + add = 0; + break; + case 'o': + case 'v': + if(arg == argc) { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + carg = argv[arg++]; + if(modeStr[i] == 'o') { + if(uaccess < db_canop) { + reply(textclient, user, "NS_MODE_ENFOPS", chan->name); + db_canop = -1; + break; + } + if(db_canop == -1) break; + } else { + if(uaccess < db_canvoice) { + reply(textclient, user, "NS_MODE_ENFVOICE", chan->name); + db_canvoice = -1; + break; + } + if(db_canvoice == -1) break; + } + cuser = searchUserByNick(carg); + if(!cuser) { + //check for an invisible user + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(!stricmp(chanuser->user->nick, carg)) { + cuser = chanuser->user; + break; + } + } + if(!cuser) break; + } else { + chanuser = getChanUser(cuser, chan); + if(!chanuser) break; + } + if(!(add ^ (chanuser->flags & (modeStr[i] == 'o' ? CHANUSERFLAG_OPPED : CHANUSERFLAG_VOICED)))) break; + if(!add) { + //check protection + if(modeStr[i] == 'o' && isNetworkService(cuser)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + break; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + break; + } + } + modeBufferSet(modeBuf, add, modeStr[i], carg); + break; + case 'b': + if(arg == argc) { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + carg = argv[arg++]; + if(uaccess < db_canban) { + reply(textclient, user, "NS_MODE_CANBAN", chan->name); + db_canban = -1; + break; + } + if(db_canban == -1) break; + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + struct BanNode *ban; + int match_count = 0; + carg = make_banmask(carg, hostmask_buffer); + if(add) { + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(carg, usermask)) { + if(isNetworkService(chanuser->user)) { + reply(textclient, user, "NS_SERVICE_IMMUNE", chanuser->user->nick); + skip = 1; + break; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + skip = 1; + break; + } + match_count++; + if(match_count > 4 && (match_count * 3) > chan->usercount && !isGodMode(user)) { + skip = 1; + reply(textclient, user, "NS_LAME_MASK", carg); + break; + } + } + } + } else { + skip = 1; + for(ban = chan->bans; ban; ban = ban->next) { + if(!match(carg, ban->mask)) { + skip = 0; + break; + } + } + } + if(!skip) { + modeBufferSet(modeBuf, add, 'b', carg); + } + break; + default: + modetype = getModeType(modelock, modeStr[i]); + if(modetype == 0) { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) { + if(isGodMode(user)) + event->flags |= CMDFLAG_OPLOG; + else { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + return; + } + } + if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) { + if(arg == argc) { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + carg = argv[arg++]; + if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) { + char *modelock_val = getModeValue(modelock, modeStr[i]); + if(stricmp(carg, modelock_val)) { + if(isGodMode(user)) + event->flags |= CMDFLAG_OPLOG; + else { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + return; + } + } + } + if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) { + int *modelock_val = getModeValue(modelock, modeStr[i]); + if(atoi(carg) != *modelock_val) { + if(isGodMode(user)) + event->flags |= CMDFLAG_OPLOG; + else { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + return; + } + } + } + } else if(!add && (modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_B) { + if(arg == argc && !(modetype & CHANNEL_MODE_KEY)) { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + carg = (arg == argc ? NULL : argv[arg++]); + } else + carg = NULL; + if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add) + break; + if(!isModeAffected(changemodes, modeStr[i])) { + if(!add && (modetype & CHANNEL_MODE_KEY)) { + if(isModeSet(chan->modes, modeStr[i])) { + char *current_val = getModeValue(chan->modes, modeStr[i]); + carg = current_val; + } + } + if(parseMode(changemodes, add, modeStr[i], carg)) { + if(carg) { + if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) { + char *current_val = getModeValue(chan->modes, modeStr[i]); + modeBufferSet(modeBuf, 0, modeStr[i], current_val); + flushModeBuffer(modeBuf); + } + if(!add && !isModeSet(chan->modes, modeStr[i])) break; + modeBufferSet(modeBuf, add, modeStr[i], carg); + } else { + modeBufferSimpleMode(modeBuf, add, modeStr[i]); + } + } else { + reply(textclient, user, "NS_MODE_INVALID", modeStr[i]); + return; + } + } + break; + } + } + } + getFullModeString(changemodes, tmp); + freeModeBuffer(modeBuf); + if(strcmp(tmp, "+")) + reply(textclient, user, "NS_MODE_DONE", tmp); + + logEvent(event); + freeModeNode(modelock); + freeModeNode(changemodes); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_move.c b/src/modules/NeonServ.mod/cmd_neonserv_move.c new file mode 100644 index 0000000..211247e --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_move.c @@ -0,0 +1,91 @@ +/* cmd_neonserv_move.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - channel +* argv[1] - new channel +*/ +CMD_BIND(neonserv_cmd_move) { + MYSQL_RES *res; + MYSQL_ROW row; + char *channel = argv[0]; + char *new_channel = argv[1]; + if(!is_valid_chan(new_channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", new_channel); + return; + } + if(!stricmp(channel, new_channel)) { + reply(getTextBot(), user, "NS_MOVE_SELF"); + return; + } + printf_mysql_query("SELECT `channel_id` FROM `bot_channels` LEFT JOIN `channels` ON `channel_id` = `chanid` WHERE `channel_name` = '%s'", escape_string(new_channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_REGISTER_ALREADY", new_channel, client->user->nick); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + } else { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + if(!strcmp(row[2], "1")) { + reply(getTextBot(), user, "NS_MOVE_SUSPENDED"); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + putsock(bot, "PART %s :Channel moved to %s.", channel, new_channel); + putsock(bot, "JOIN %s", new_channel); + } + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(new_channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d'", chanid); + printf_mysql_query("DELETE FROM `bans` WHERE `ban_channel` = '%d'", chanid); + printf_mysql_query("DELETE FROM `events` WHERE `cid` = '%d'", chanid); + printf_mysql_query("DELETE FROM `noinvite` WHERE `cid` = '%d'", chanid); + printf_mysql_query("DELETE FROM `owner_history` WHERE `owner_history_cid` = '%d'", chanid); + printf_mysql_query("DELETE FROM `channels` WHERE `channel_id` = '%d'", chanid); + } + printf_mysql_query("UPDATE `channels` SET `channel_name` = '%s' WHERE `channel_name` = '%s'", escape_string(new_channel), escape_string(channel)); + struct ChanNode *channode = getChanByName(channel); + if(channode && channode->flags & CHANFLAG_REQUESTED_CHANINFO) { + channode->flags &= ~CHANFLAG_CHAN_REGISTERED; + channode->channel_id = 0; + } + reply(getTextBot(), user, "NS_MOVE_DONE", channel, new_channel); + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_myaccess.c b/src/modules/NeonServ.mod/cmd_neonserv_myaccess.c new file mode 100644 index 0000000..b9f6581 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_myaccess.c @@ -0,0 +1,190 @@ +/* cmd_neonserv_myaccess.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - nick / *auth +*/ +static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup); +static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch); + +struct neonserv_cmd_myaccess_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + char *nick; + char *chanmatch; +}; + +CMD_BIND(neonserv_cmd_myaccess) { + char *chanmatch = NULL; + if(argc == 0 || argv[0][0] == '#') { + if(argc != 0) { + chanmatch = argv[0]; + } + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->nick = strdup(argv[0]); + cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL); + get_userauth(user, neonserv_cmd_myaccess_nick_lookup, cache); + } else + neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, user->nick, user->auth, chanmatch); + } + else if(argv[0][0] == '*') { + //we've got an auth + if(argc > 1 && argv[1][0] == '#') { + chanmatch = argv[1]; + } + argv[0]++; + neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, NULL, argv[0], chanmatch); + } else { + if(argc > 1 && argv[1][0] == '#') { + chanmatch = argv[1]; + } + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_myaccess_async1(client, getTextBot(), user, chan, argv[0], cuser->auth, chanmatch); + } else { + struct neonserv_cmd_myaccess_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->nick = strdup(argv[0]); + cache->chanmatch = (chanmatch ? strdup(chanmatch) : NULL); + get_userauth(cuser, neonserv_cmd_myaccess_nick_lookup, cache); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_myaccess_nick_lookup) { + struct neonserv_cmd_myaccess_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + if(!strcmp(cache->nick, cache->user->nick)) + reply(cache->textclient, cache->user, "NS_YOU_NEED_AUTH"); + else + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + neonserv_cmd_myaccess_async1(cache->client, cache->textclient, cache->user, cache->chan, user->nick, user->auth, cache->chanmatch); + if(cache->chanmatch) + free(cache->chanmatch); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_myaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *nick, char *auth, char *chanmatch) { + //we've got a valid auth now... + if(stricmp(user->auth, auth) && !isGodMode(user)) { + reply(textclient, user, "NS_MYACCESS_SELF_ONLY"); + return; + } + MYSQL_RES *res, *default_res; + MYSQL_ROW user_row, chanuser_row, default_chan = NULL; + char flagBuf[5]; + int userid, cflags, caccess, flagPos; + int i, total_count = 0, match_count = 0, owner_count = 0; + struct Table *table = NULL; + printf_mysql_query("SELECT `user_id`, `user_access`, `user_god` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + char *content[4]; + content[0] = get_language_string(user, "NS_MYACCESS_HEADER_NAME"); + content[1] = get_language_string(user, "NS_MYACCESS_HEADER_ACCESS"); + content[2] = get_language_string(user, "NS_MYACCESS_HEADER_FLAGS"); + content[3] = get_language_string(user, "NS_MYACCESS_HEADER_INFO"); + if(chanmatch) + reply(textclient, user, "NS_MYACCESS_HEADER_MATCH", auth, chanmatch); + else + reply(textclient, user, "NS_MYACCESS_HEADER", auth); + if ((user_row = mysql_fetch_row(res)) != NULL) { + userid = atoi(user_row[0]); + //check if the user is already added + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `channel_name`, `channel_getop`, `channel_getvoice`, `botid` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` LEFT JOIN `bot_channels` ON `chanuser_cid` = `chanid` LEFT JOIN `bots` ON `bots`.`id` = `botid` WHERE `chanuser_uid` = '%d' AND `botclass` = '%d' AND `active` = '1' ORDER BY `chanuser_access` DESC, `channel_name` ASC", userid, client->botid); + res = mysql_use(); + total_count = mysql_num_rows(res); + table = table_init(4, total_count + 1, 0); + table_add(table, content); + while ((chanuser_row = mysql_fetch_row(res)) != NULL) { + if(!strcmp(chanuser_row[0], "500")) owner_count++; + if(chanmatch && match(chanmatch, chanuser_row[0])) continue; + match_count++; + if((!chanuser_row[4] || !chanuser_row[5]) && !default_chan) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); + default_res = mysql_use(); + default_chan = mysql_fetch_row(default_res); + } + flagPos = 0; + content[0] = chanuser_row[3]; + content[1] = chanuser_row[0]; + cflags = atoi(chanuser_row[1]); + caccess = atoi(chanuser_row[0]); + if((cflags & DB_CHANUSER_SUSPENDED)) + flagPos += sprintf(flagBuf + flagPos, "s"); + if(caccess >= (chanuser_row[4] ? atoi(chanuser_row[4]) : atoi(default_chan[0]))) + flagPos += sprintf(flagBuf + flagPos, "o"); + if(caccess >= (chanuser_row[5] ? atoi(chanuser_row[5]) : atoi(default_chan[1]))) + flagPos += sprintf(flagBuf + flagPos, "v"); + if((cflags & DB_CHANUSER_AUTOINVITE)) + flagPos += sprintf(flagBuf + flagPos, "i"); + content[2] = (flagPos ? flagBuf : ""); + content[3] = chanuser_row[2]; + table_add(table, content); + } + } else { + table = table_init(4, 1, 0); + table_add(table, content); + } + //send the table + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(textclient, user, table_lines[i]); + } + if(!match_count) + reply(textclient, user, "NS_TABLE_NONE"); + if(chanmatch) { + reply(textclient, user, "NS_MYACCESS_COUNT_MATCH", auth, total_count, owner_count, match_count, chanmatch); + } else { + reply(textclient, user, "NS_MYACCESS_COUNT", auth, total_count, owner_count); + } + table_free(table); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c b/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c new file mode 100644 index 0000000..181923c --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_nicklist.c @@ -0,0 +1,249 @@ +/* cmd_neonserv_nicklist.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] "force" +* argv[1] (optional) nick mask +*/ +static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup); +static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers); +static void neonserv_cmd_nicklist_synchronize_user(struct ChanNode *chan, struct UserNode *user, int access); + +struct neonserv_cmd_nicklist_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nickmask; + int syncusers; +}; + +CMD_BIND(neonserv_cmd_nicklist) { + int syncusers = 0; + if(argc && !stricmp(argv[0], "sync")) { + if(!checkChannelAccess(user, chan, "channel_canadd", 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + } + argv++; + argc--; + syncusers = 1; + event->flags |= CMDFLAG_LOG; + } + if(argc && !stricmp(argv[0], "nowho") && isGodMode(user)) { + argv++; + argc--; + neonserv_cmd_nicklist_async1(client, getTextBot(), user, chan, event, (argc ? argv[0] : NULL), syncusers); + return; + } + struct neonserv_cmd_nicklist_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + if(argc) { + cache->nickmask = strdup(argv[0]); + } else + cache->nickmask = NULL; + cache->syncusers = syncusers; + get_userlist_with_invisible(chan, neonserv_cmd_nicklist_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_nicklist_userlist_lookup) { + struct neonserv_cmd_nicklist_cache *cache = data; + neonserv_cmd_nicklist_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->nickmask, cache->syncusers); + if(cache->nickmask) + free(cache->nickmask); + free(cache); +} + +static void neonserv_cmd_nicklist_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *nickmask, int syncusers) { + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + struct Table *table; + table = table_init(3, chan->usercount + 1, 0); + char *content[3]; + content[0] = get_language_string(user, "NS_NICKLIST_NICK"); + content[1] = get_language_string(user, "NS_NICKLIST_STATE"); + content[2] = get_language_string(user, "NS_NICKLIST_ACCESS"); + table_add(table, content); + printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d'", chan->channel_id); + res = mysql_use(); + int userlistlen = mysql_num_rows(res); + int i = 0; + MYSQL_ROW userlist[userlistlen]; + while ((row = mysql_fetch_row(res)) != NULL) { + userlist[i++] = row; + } + int db_enfops, db_enfvoice; + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + row = mysql_fetch_row(mysql_use()); + if(row[0] == NULL || row[1] == NULL) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); + defaults = mysql_fetch_row(mysql_use()); + } + db_enfops = atoi((row[0] ? row[0] : defaults[0])); + db_enfvoice = atoi((row[1] ? row[1] : defaults[1])); + int caccess = getChannelAccess(user, chan); + int synced_user = 0; + struct ChanUser *chanuser; + int sort_nicklist[] = { + CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_OPPED | CHANUSERFLAG_HALFOPPED, + CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_OPPED, + CHANUSERFLAG_HALFOPPED | CHANUSERFLAG_VOICED, + CHANUSERFLAG_HALFOPPED, + CHANUSERFLAG_VOICED, + CHANUSERFLAG_INVISIBLE, + 0 + }; + int *sort_pos = sort_nicklist; + int sort_flags; + do { + sort_flags = *(sort_pos++); + char statebuf[5]; + char accessbuf[9]; + int uaccess; + int stateset = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if((chanuser->flags & (CHANUSERFLAG_OPPED | CHANUSERFLAG_VOICED | CHANUSERFLAG_INVISIBLE)) != sort_flags) continue; + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(!stateset) { + if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) statebuf[stateset++] = '<'; + if((chanuser->flags & CHANUSERFLAG_OPPED)) statebuf[stateset++] = '@'; + if((chanuser->flags & CHANUSERFLAG_HALFOPPED)) statebuf[stateset++] = '%'; + if((chanuser->flags & CHANUSERFLAG_VOICED)) statebuf[stateset++] = '+'; + statebuf[stateset++] = '\0'; + } + content[0] = chanuser->user->nick; + content[1] = statebuf; + uaccess = 0; + if(chanuser->user->flags & USERFLAG_ISAUTHED) { + for(i = 0; i < userlistlen; i++) { + if(!stricmp(chanuser->user->auth, userlist[i][1])) { + uaccess = atoi(userlist[i][0]); + if((((chanuser->flags & CHANUSERFLAG_OPPED) && uaccess < db_enfops) || ((chanuser->flags & CHANUSERFLAG_VOICED) && uaccess < db_enfvoice)) && !isNetworkService(chanuser->user)) { + if(syncusers) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { + if(db_enfops >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfops; + } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (caccess < db_enfvoice || isGodMode(user))) { + if(db_enfvoice >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfvoice; + } else { + //fail... + sprintf(accessbuf, "\00307%d\003", uaccess); + break; + } + neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); + sprintf(accessbuf, "\00309%d\003", uaccess); + synced_user = 1; + } else { + synced_user = 1; + sprintf(accessbuf, "\00307%d\003", uaccess); + } + } else if((uaccess >= db_enfops && !(chanuser->flags & CHANUSERFLAG_OPPED)) || (uaccess >= db_enfvoice && !(chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED))) + sprintf(accessbuf, "\00303%d\003", uaccess); + else + sprintf(accessbuf, "%d", uaccess); + break; + } + } + } + if(!uaccess && (chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && !isNetworkService(chanuser->user)) { + if(syncusers) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && (db_enfops < caccess || isGodMode(user))) { + if(db_enfops >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfops; + } else if((chanuser->flags & CHANUSERFLAG_VOICED) && (db_enfvoice < caccess || isGodMode(user))) { + if(db_enfvoice >= caccess) + event->flags |= CMDFLAG_OPLOG; + uaccess = db_enfvoice; + } else { + uaccess = 0; + sprintf(accessbuf, "\003040\003"); + } + if(uaccess && (chanuser->user->flags & USERFLAG_ISAUTHED)) { + neonserv_cmd_nicklist_synchronize_user(chan, chanuser->user, uaccess); + sprintf(accessbuf, "\00309%d\003", uaccess); + synced_user = 1; + } else if(uaccess) { + sprintf(accessbuf, "\003040\003"); + } + } else { + synced_user = 1; + sprintf(accessbuf, "\003040\003"); + } + } else if(!uaccess) + sprintf(accessbuf, "0"); + content[2] = accessbuf; + table_add(table, content); + } + } while(sort_flags != 0); + //send the table + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(textclient, user, table_lines[i]); + } + if(table->length == 1) + reply(textclient, user, "NS_TABLE_NONE"); + reply(textclient, user, "NS_TABLE_COUNT", table->length - 1); + table_free(table); + if(synced_user) { + if(!syncusers) + reply(textclient, user, "NS_NICKLIST_SYNC", db_enfops, db_enfvoice); + else + logEvent(event); + } +} + +static void neonserv_cmd_nicklist_synchronize_user(struct ChanNode *chan, struct UserNode *user, int caccess) { + if(!(user->flags & USERFLAG_ISAUTHED)) return; + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth)); + userid = (int) mysql_insert_id(get_mysql_conn()); + } + //check if already added + printf_mysql_query("SELECT `chanuser_access`, `chanuser_id`, `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chan->channel_id, userid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + //clvl + if(atoi(row[0]) >= caccess) return; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = '%d' WHERE `chanuser_id` = '%s'", caccess, row[1]); + } else + printf_mysql_query("INSERT INTO `chanusers` (`chanuser_cid`, `chanuser_uid`, `chanuser_access`) VALUES ('%d', '%d', '%d')", chan->channel_id, userid, caccess); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_noregister.c b/src/modules/NeonServ.mod/cmd_neonserv_noregister.c new file mode 100644 index 0000000..f0ba380 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_noregister.c @@ -0,0 +1,199 @@ +/* cmd_neonserv_noregister.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] *auth/#channel +* argv[1] duration +* argv[2-*] reason +*/ + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_noregister_auth_lookup); +static USERAUTH_CALLBACK(neonserv_cmd_noregister_nick_lookup); +static void neonserv_cmd_noregister_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event,char *auth, int duration, char *reason); +static void neonserv_cmd_noregister_list(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc); + +struct neonserv_cmd_noregister_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + struct Event *event; + int duration; + char *reason, *nick; +}; + +CMD_BIND(neonserv_cmd_noregister) { + if(argc < 3) { + neonserv_cmd_noregister_list(client, user, chan, event, argv, argc); + return; + } + int duration = strToTime(user, argv[1]); + if(duration == 0 && strcmp(argv[1], "0")) { + reply(getTextBot(), user, "NS_NOREGISTER_INVALID_DURATION", argv[1]); + return; + } + char *reason = merge_argv(argv, 2, argc); + MYSQL_RES *res; + MYSQL_ROW row; + if(argv[0][0] == '#') { + printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s'", escape_string(argv[0])); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_NOREGISTER_REGISTERED", argv[0]); + return; + } + neonserv_cmd_noregister_async1(client, getTextBot(), user, chan, event, argv[0], duration, reason); + } else if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + 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_noregister_async1(client, getTextBot(), user, chan, event, row[0], duration, reason); + } else { + //we need to create a new user... + //but first lookup the auth to check if it really exists + struct neonserv_cmd_noregister_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(argv[0]); + cache->duration = duration; + cache->reason = strdup(reason); + lookup_authname(argv[0], neonserv_cmd_noregister_auth_lookup, cache); + } + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + neonserv_cmd_noregister_async1(client, getTextBot(), user, chan, event, cuser->auth, duration, reason); + } else { + struct neonserv_cmd_noregister_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(user->nick); + cache->duration = duration; + cache->reason = strdup(reason); + get_userauth(cuser, neonserv_cmd_noregister_nick_lookup, cache); + } + } +} + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_noregister_auth_lookup) { + struct neonserv_cmd_noregister_cache *cache = data; + if(!exists) { + //AUTH_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); + } else + neonserv_cmd_noregister_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, auth, cache->duration, cache->reason); + free(cache->reason); + free(cache->nick); + free(cache); +} + +static USERAUTH_CALLBACK(neonserv_cmd_noregister_nick_lookup) { + struct neonserv_cmd_noregister_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + neonserv_cmd_noregister_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, user->auth, cache->duration, cache->reason); + free(cache->reason); + free(cache->nick); + free(cache); +} + +static void neonserv_cmd_noregister_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event,char *auth, int duration, char *reason) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `dnr_id` FROM `donotregister` WHERE `dnr_target` = '%s'", escape_string(auth)); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[0]); + } + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) + userid = atoi(row[0]); + else + userid = 0; + printf_mysql_query("INSERT INTO `donotregister` (`dnr_target`, `dnr_timeout`, `dnr_user`, `dnr_reason`) VALUES ('%s', '%lu', '%d', '%s')", escape_string(auth), (duration ? (time(0)+duration) : 0), userid, escape_string(reason)); + reply(getTextBot(), user, "NS_NOREGISTER_DONE", auth); +} + +static void neonserv_cmd_noregister_list(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, char **argv, int argc) { + struct Table *table; + int entrys = 0; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `dnr_target`, `dnr_timeout`, `user_user`, `dnr_reason` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` ORDER BY `dnr_target` ASC"); + res = mysql_use(); + table = table_init(4, mysql_num_rows(res) + 1, 0); + char *content[4]; + content[0] = get_language_string(user, "NS_DNR_TARGET"); + content[1] = get_language_string(user, "NS_DNR_USER"); + content[2] = get_language_string(user, "NS_DNR_EXPIRES"); + content[3] = get_language_string(user, "NS_DNR_REASON"); + table_add(table, content); + int duration; + char expires_str[MAXLEN]; + while ((row = mysql_fetch_row(res)) != NULL) { + entrys++; + content[0] = row[0]; + content[1] = row[2]; + duration = atoi(row[1]); + content[2] = (duration ? timeToStr(user, (duration - time(0)), 2, expires_str) : get_language_string(user, "NS_USERS_SEEN_NEVER")); + content[3] = row[3]; + table_add(table, content); + } + //send the table + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + if(!entrys) + reply(getTextBot(), user, "NS_TABLE_NONE"); + table_free(table); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_op.c b/src/modules/NeonServ.mod/cmd_neonserv_op.c new file mode 100644 index 0000000..6bf3b28 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_op.c @@ -0,0 +1,93 @@ +/* cmd_neonserv_op.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, struct Event *event, char *nicks); + +struct neonserv_cmd_op_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nicks; +}; + +CMD_BIND(neonserv_cmd_op) { + struct neonserv_cmd_op_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->nicks = strdup(merge_argv(argv, 0, argc)); + get_userlist_if_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->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, struct Event *event, char *nicks) { + int total_users = 0, done_users = 0; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + char *a, *b = nicks; + do { + a = strstr(b, " "); + if(a) *a = '\0'; + total_users++; + cuser = searchUserByNick(b); + if(!cuser) { + //check for an invisible user + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(!stricmp(chanuser->user->nick, b)) { + cuser = chanuser->user; + break; + } + } + if(!cuser) continue; + } else { + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + } + done_users++; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferOp(modeBuf, b); + if(a) { + b = a+1; + } + } while(a); + freeModeBuffer(modeBuf); + if(done_users == total_users) + 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/src/modules/NeonServ.mod/cmd_neonserv_opall.c b/src/modules/NeonServ.mod/cmd_neonserv_opall.c new file mode 100644 index 0000000..b6bdacc --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_opall.c @@ -0,0 +1,78 @@ +/* cmd_neonserv_opall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] "force" +* 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, struct Event *event, char *nickmask); + +struct neonserv_cmd_opall_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nickmask; +}; + +CMD_BIND(neonserv_cmd_opall) { + if(!argc || strcmp(argv[0], "FORCE")) { + reply(getTextBot(), user, "NS_OPALL_SECURITY", chan->name); + return; + } + struct neonserv_cmd_opall_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + if(argc > 1) { + cache->nickmask = strdup(argv[1]); + } else + cache->nickmask = NULL; + get_userlist_if_invisible(chan, neonserv_cmd_opall_userlist_lookup, cache); +} + +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->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, struct Event *event, char *nickmask) { + int done_users = 0; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(chanuser->flags & CHANUSERFLAG_OPPED) continue; + modeBufferOp(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(textclient, user, "NS_OPALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_oplog.c b/src/modules/NeonServ.mod/cmd_neonserv_oplog.c new file mode 100644 index 0000000..9cf412b --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_oplog.c @@ -0,0 +1,57 @@ +/* cmd_neonserv_oplog.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] time +* argv[1-*] match +*/ + +CMD_BIND(neonserv_cmd_oplog) { + char *str_match; + int duration = (argc ? strToTime(user, argv[0]) : 0); + if(argc > (duration ? 1 : 0)) + str_match = merge_argv(argv, (duration ? 1 : 0), argc); + else + str_match = ""; + if(!duration) duration = (60*60*24); + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `godlog_time`, `user_user`, `channel_name`, `godlog_cmd` FROM `godlog` LEFT JOIN `channels` ON `godlog_cid` = `channel_id` LEFT JOIN `users` ON `godlog_uid` = `user_id` WHERE `godlog_time` > '%lu' ORDER BY `godlog_time` ASC", ((unsigned long) time(0) - duration)); + res = mysql_use(); + int skip = mysql_num_rows(res) - 100; + int count = 0; + char timeBuf[50]; + struct tm *timeinfo; + time_t event_time; + if(skip < 0) skip = 0; + reply(getTextBot(), user, "NS_EVENTS_HEADER"); + while ((row = mysql_fetch_row(res)) != NULL) { + if(skip) { + skip--; + continue; + } + if(*str_match && match(str_match, row[3])) continue; + count++; + event_time = (time_t) atol(row[0]); + timeinfo = localtime(&event_time); + strftime(timeBuf, 80, "%X %x", timeinfo); + reply(getTextBot(), user, "[%s] [%s%s%s]: %s", timeBuf, row[1], (row[2] ? ":" : ""), (row[2] ? row[2] : ""), row[3]); + } + reply(getTextBot(), user, "NS_TABLE_COUNT", count); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_peek.c b/src/modules/NeonServ.mod/cmd_neonserv_peek.c new file mode 100644 index 0000000..51de508 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_peek.c @@ -0,0 +1,89 @@ +/* cmd_neonserv_peek.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no parameters +*/ +static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup); +static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan); + +struct neonserv_cmd_peek_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; +}; + +CMD_BIND(neonserv_cmd_peek) { + struct neonserv_cmd_peek_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + get_userlist_if_invisible(chan, neonserv_cmd_peek_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_peek_userlist_lookup) { + struct neonserv_cmd_peek_cache *cache = data; + neonserv_cmd_peek_async1(cache->client, cache->textclient, cache->user, chan); + free(cache); +} + +static void neonserv_cmd_peek_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan) { + reply(textclient, user, "NS_PEEK_HEADER", chan->name); + reply(textclient, user, "NS_PEEK_TOPIC", chan->topic); + char tmpStr[MAXLEN]; + getModeString(chan->modes, tmpStr); + reply(textclient, user, "NS_PEEK_MODES", tmpStr); + struct ChanUser *chanuser; + int with_halfops = get_int_field("General.have_halfop"); + int op_count = 0, halfop_count = 0, voice_count = 0, normal_count = 0, invi_count = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(chanuser->flags & CHANUSERFLAG_OPPED) + op_count++; + else if(with_halfops && (chanuser->flags & CHANUSERFLAG_HALFOPPED)) + halfop_count++; + else if(chanuser->flags & CHANUSERFLAG_VOICED) + voice_count++; + else if(chanuser->flags & CHANUSERFLAG_INVISIBLE) + invi_count++; + else + normal_count++; + } + if(with_halfops) + reply(textclient, user, "NS_PEEK_USERS_HALFOP", op_count+halfop_count+voice_count+invi_count+normal_count, op_count, halfop_count, voice_count, normal_count, invi_count); + else + reply(textclient, user, "NS_PEEK_USERS", op_count+voice_count+invi_count+normal_count, op_count, voice_count, normal_count, invi_count); + int tmpStrPos = 0; + int headerlen = 10 + strlen(user->nick); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(chanuser->flags & CHANUSERFLAG_OPPED) { + if(tmpStrPos + headerlen + strlen(chanuser->user->nick) + 2 >= 512) { + //clear buffer + reply(textclient, user, "%s", tmpStr); + tmpStrPos = 0; + } + tmpStrPos += sprintf(tmpStr + tmpStrPos, (tmpStrPos ? ", %s" : "%s"), chanuser->user->nick); + } + } + if(tmpStrPos) { + reply(textclient, user, "%s", tmpStr); + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_recover.c b/src/modules/NeonServ.mod/cmd_neonserv_recover.c new file mode 100644 index 0000000..f48a8c5 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_recover.c @@ -0,0 +1,76 @@ +/* cmd_neonserv_recover.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - channel +*/ +CMD_BIND(neonserv_cmd_recover) { + MYSQL_RES *res; + MYSQL_ROW row, row2; + char *channel = argv[0]; + if(!is_valid_chan(channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); + return; + } + printf_mysql_query("SELECT `botid`, `bot_channels`.`id` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + } else { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger` FROM `bots` WHERE `botclass` = '%d' ORDER BY `register_priority` DESC", client->botid); + res = mysql_use(); + int botid = 0; + char *bottrigger; + while ((row = mysql_fetch_row(res)) != NULL) { + //check channel count + printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]); + row2 = mysql_fetch_row(mysql_use()); + if(atoi(row2[0]) < atoi(row[1])) { + botid = atoi(row[0]); + bottrigger = row[2]; + break; + } + } + if(!botid) { + reply(getTextBot(), user, "NS_REGISTER_FULL"); + return; + } + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + putsock(bot, "JOIN %s", channel); + } else + 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/src/modules/NeonServ.mod/cmd_neonserv_rename.c b/src/modules/NeonServ.mod/cmd_neonserv_rename.c new file mode 100644 index 0000000..9b87be4 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_rename.c @@ -0,0 +1,68 @@ +/* cmd_neonserv_rename.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] old auth +* argv[1] new auth +*/ + +struct neonserv_cmd_rename_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *oldauth, *newauth; +}; + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_rename_auth_lookup); +static void neonserv_cmd_rename_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *oldauth, char *newauth); + +CMD_BIND(neonserv_cmd_rename) { + struct neonserv_cmd_rename_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->oldauth = strdup(argv[0]); + cache->newauth = strdup(argv[1]); + lookup_authname(argv[1], neonserv_cmd_rename_auth_lookup, cache); +} + +static AUTHLOOKUP_CALLBACK(neonserv_cmd_rename_auth_lookup) { + struct neonserv_cmd_rename_cache *cache = data; + if(!exists) { + //AUTH_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->newauth); + } else + neonserv_cmd_rename_async1(cache->client, cache->textclient, cache->user, cache->event, cache->oldauth, auth); + free(cache->oldauth); + free(cache->newauth); + free(cache); +} + +static void neonserv_cmd_rename_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *oldauth, char *newauth) { + if(renameAccount(oldauth, newauth)) { + reply(textclient, user, "NS_RENAME_DONE", oldauth, newauth); + } else { + reply(textclient, user, "NS_RENAME_FAIL", oldauth); + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_resync.c b/src/modules/NeonServ.mod/cmd_neonserv_resync.c new file mode 100644 index 0000000..7c60a6e --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_resync.c @@ -0,0 +1,167 @@ +/* cmd_neonserv_resync.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - (optional) usermask +* argv[1] - (optional) min access +* argv[2] - (optional) max access +* argv[1/3] - (optional) FORCE (override NoAutoOp) +*/ +static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup); +static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop); + +struct neonserv_cmd_resync_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + char *usermask; + int min_access; + int max_access; + char override_noautoop; +}; + +CMD_BIND(neonserv_cmd_resync) { + int min_access = 0, max_access = 500; + char *usermask = NULL; + char override_noautoop = 0; + if(argc > 0) { + usermask = argv[0]; + if(argc > 2) { + min_access = atoi(argv[1]); + max_access = atoi(argv[2]); + if(argc > 3) + override_noautoop = (!stricmp(argv[3], "FORCE") ? 1 : 0); + } else if(argc > 1) + override_noautoop = (!stricmp(argv[1], "FORCE") ? 1 : 0); + } + struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->usermask = (usermask ? strdup(usermask) : NULL); + cache->min_access = min_access; + cache->max_access = max_access; + cache->override_noautoop = override_noautoop; + get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) { + struct neonserv_cmd_resync_cache *cache = data; + neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access, cache->override_noautoop); + if(cache->usermask) + free(cache->usermask); + free(cache); +} + +static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop) { + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + int i; + int resync_op = 1; + int with_halfop = get_int_field("General.have_halfop"); + int resync_halfop = with_halfop; + int resync_voice = 1; + if(usermask && usermask[0] == '@') { + resync_voice = 0; + resync_halfop = 0; + usermask++; + if(!*usermask) usermask = NULL; + } else if(usermask && with_halfop && usermask[0] == 'h') { + resync_op = 0; + resync_voice = 0; + usermask++; + if(!*usermask) usermask = NULL; + } else if(usermask && usermask[0] == '+') { + resync_op = 0; + resync_halfop = 0; + usermask++; + if(!*usermask) usermask = NULL; + } + struct ChanUser *chanuser; + int db_enfops, db_enfhalfop, db_enfvoice; + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_gethalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + row = mysql_fetch_row(mysql_use()); + if(row[0] == NULL || row[1] == NULL) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_gethalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); + defaults = mysql_fetch_row(mysql_use()); + } + db_enfops = atoi((row[0] ? row[0] : defaults[0])); + db_enfvoice = atoi((row[1] ? row[1] : defaults[1])); + db_enfhalfop = (with_halfop ? atoi((row[2] ? row[2] : defaults[2])) : 0); + printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id); + res = mysql_use(); + char *db_users[mysql_num_rows(res)]; + int db_access[mysql_num_rows(res)]; + int db_flags[mysql_num_rows(res)]; + int db_count = 0; + while ((row = mysql_fetch_row(res)) != NULL) { + db_users[db_count] = row[1]; + db_access[db_count] = atoi(row[0]); + db_flags[db_count] = atoi(row[2]); + db_count++; + } + int caccess, cflags; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + caccess = 0; + cflags = 0; + if((chanuser->user->flags & USERFLAG_ISAUTHED)) { + for(i = 0; i < db_count; i++) { + if(!stricmp(db_users[i], chanuser->user->auth)) { + caccess = db_access[i]; + cflags = db_flags[i]; + if(cflags & DB_CHANUSER_SUSPENDED) + caccess = 0; + break; + } + } + } + if((usermask && *usermask && match(usermask, chanuser->user->nick)) || caccess < min_access || caccess > max_access) continue; + if(caccess >= db_enfops) { + if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) + modeBufferOp(modeBuf, chanuser->user->nick); + } else if(with_halfop && caccess >= db_enfhalfop) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDeop(modeBuf, chanuser->user->nick); + if(!(chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) + modeBufferHalfop(modeBuf, chanuser->user->nick); + } else if(caccess >= db_enfvoice) { + if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDeop(modeBuf, chanuser->user->nick); + if((chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDehalfop(modeBuf, chanuser->user->nick); + if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP))) + modeBufferVoice(modeBuf, chanuser->user->nick); + } else { + if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDeop(modeBuf, chanuser->user->nick); + if((chanuser->flags & CHANUSERFLAG_HALFOPPED) && resync_halfop && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDehalfop(modeBuf, chanuser->user->nick); + if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) + modeBufferDevoice(modeBuf, chanuser->user->nick); + } + + } + freeModeBuffer(modeBuf); + reply(textclient, user, "NS_RESYNC_DONE", chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_search.c b/src/modules/NeonServ.mod/cmd_neonserv_search.c new file mode 100644 index 0000000..2cefe55 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_search.c @@ -0,0 +1,175 @@ +/* cmd_neonserv_search.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +#define CMD_SEARCH_FLAG_HAS_NODELETE 0x001 +#define CMD_SEARCH_FLAG_NOT_NODELETE 0x002 +#define CMD_SEARCH_FLAG_HAS_SUSPENDED 0x004 +#define CMD_SEARCH_FLAG_NOT_SUSPENDED 0x008 +#define CMD_SEARCH_FLAG_IS_JOINED 0x010 +#define CMD_SEARCH_FLAG_NOT_JOINED 0x020 +#define CMD_SEARCH_FLAG_IS_OPPED 0x040 +#define CMD_SEARCH_FLAG_NOT_OPPED 0x080 +#define CMD_SEARCH_FLAG_IS_VOICED 0x100 +#define CMD_SEARCH_FLAG_NOT_VOICED 0x200 +#define CMD_SEARCH_FLAG_STATES 0x3f0 + +struct neonserv_cmd_search_criteria { + char *name; + char *registrar; + char *onchan; + unsigned int flags : 16; + unsigned int unvisited; + unsigned int registered; + unsigned int limit : 16; +}; + +CMD_BIND(neonserv_cmd_search) { + //ok parse the criterias + struct neonserv_cmd_search_criteria criteria; + memset(&criteria, 0, sizeof(criteria)); + criteria.limit = 50; + int i, show_chans = 0, positive; + if(!stricmp(argv[0], "print")) { + show_chans = 1; + } + for(i = 1; i < argc; i += 2) { + if(argc <= i+1) { + reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT"); + return; + } + if(!stricmp(argv[i], "name")) criteria.name = argv[i+1]; + else if(!stricmp(argv[i], "registrar")) criteria.registrar = argv[i+1]; + else if(!stricmp(argv[i], "onchan")) criteria.onchan = argv[i+1]; + else if(!stricmp(argv[i], "unvisited")) criteria.unvisited = strToTime(user, argv[i+1]); + else if(!stricmp(argv[i], "registered")) criteria.registered = strToTime(user, argv[i+1]); + else if(!stricmp(argv[i], "flags")) { + if(argv[i+1][0] == '+') { + positive = 1; + argv[i+1]++; + } else if(argv[i+1][0] == '-') { + positive = 0; + argv[i+1]++; + } else + positive = 1; + if(!stricmp(argv[i+1], "nodelete")) { + if(positive) + criteria.flags |= CMD_SEARCH_FLAG_HAS_NODELETE; + else + criteria.flags |= CMD_SEARCH_FLAG_NOT_NODELETE; + } else if(!stricmp(argv[i+1], "suspended")) { + if(positive) + criteria.flags |= CMD_SEARCH_FLAG_HAS_SUSPENDED; + else + criteria.flags |= CMD_SEARCH_FLAG_NOT_SUSPENDED; + } + } + else if(!stricmp(argv[i], "state")) { + if(argv[i+1][0] == '+') { + positive = 1; + argv[i+1]++; + } else if(argv[i+1][0] == '-') { + positive = 0; + argv[i+1]++; + } else + positive = 1; + if(!stricmp(argv[i+1], "joined")) { + if(positive) + criteria.flags |= CMD_SEARCH_FLAG_IS_JOINED; + else + criteria.flags |= CMD_SEARCH_FLAG_NOT_JOINED; + } else if(!stricmp(argv[i+1], "opped")) { + if(positive) + criteria.flags |= CMD_SEARCH_FLAG_IS_OPPED; + else + criteria.flags |= CMD_SEARCH_FLAG_NOT_OPPED; + } else if(!stricmp(argv[i+1], "voiced")) { + if(positive) + criteria.flags |= CMD_SEARCH_FLAG_IS_VOICED; + else + criteria.flags |= CMD_SEARCH_FLAG_NOT_VOICED; + } + } + else if(!stricmp(argv[i], "limit")) { + criteria.limit = atoi(argv[i+1]); + } + } + int matches = 0; + reply(getTextBot(), user, "NS_SEARCH_HEADER"); + MYSQL_RES *res, *res2; + MYSQL_ROW row, row2; + printf_mysql_query("SELECT `channel_name`, `user_user`, `channel_registered`, `channel_nodelete`, `suspended`, `channel_id` FROM `bot_channels` LEFT JOIN `bots` ON `bots`.`id` = `botid` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botclass` = '%d' AND `active` = '1'", client->botid); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(show_chans && matches == criteria.limit) { + //too many + break; + } + if(criteria.name && match(criteria.name, row[0])) continue; + if(criteria.registrar && row[1] && match(criteria.registrar, row[1])) continue; + if(criteria.unvisited) { + printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' ORDER BY `chanuser_seen` DESC LIMIT 1", row[5]); + res2 = mysql_use(); + row2 = mysql_fetch_row(res2); + if(!row2) continue; + if((time(0) - atoi(row2[0])) < criteria.unvisited) continue; + } + if(criteria.registered && (time(0) - atoi(row[2])) < criteria.registered) continue; + + if((criteria.flags & CMD_SEARCH_FLAG_HAS_NODELETE) && strcmp(row[3], "1")) continue; + if((criteria.flags & CMD_SEARCH_FLAG_NOT_NODELETE) && strcmp(row[3], "0")) continue; + if((criteria.flags & CMD_SEARCH_FLAG_HAS_SUSPENDED) && strcmp(row[4], "1")) continue; + if((criteria.flags & CMD_SEARCH_FLAG_NOT_SUSPENDED) && strcmp(row[4], "0")) continue; + if((criteria.flags & CMD_SEARCH_FLAG_STATES) || criteria.onchan) { + struct ChanNode *channel = getChanByName(row[0]); + if(criteria.onchan) { + if(!channel) continue; + struct ChanUser *chanuser = NULL; + for(chanuser = getChannelUsers(channel, NULL); chanuser; chanuser = getChannelUsers(channel, chanuser)) { + if(!match(criteria.onchan, chanuser->user->nick)) break; + } + if(!chanuser) continue; + } + if((criteria.flags & CMD_SEARCH_FLAG_IS_JOINED) && !channel) continue; + if((criteria.flags & CMD_SEARCH_FLAG_NOT_JOINED) && channel) continue; + if(channel && (criteria.flags & (CMD_SEARCH_FLAG_IS_OPPED | CMD_SEARCH_FLAG_NOT_OPPED | CMD_SEARCH_FLAG_IS_VOICED | CMD_SEARCH_FLAG_NOT_VOICED))) { + int flags = 0; + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->botid == client->botid) { + struct ChanUser *chanuser = getChanUser(bot->user, channel); + if(chanuser) { + flags = chanuser->flags; + break; + } + } + } + if((criteria.flags & CMD_SEARCH_FLAG_IS_OPPED) && !(flags & CHANUSERFLAG_OPPED)) continue; + if((criteria.flags & CMD_SEARCH_FLAG_NOT_OPPED) && (flags & CHANUSERFLAG_OPPED)) continue; + if((criteria.flags & CMD_SEARCH_FLAG_IS_VOICED) && !(flags & CHANUSERFLAG_VOICED)) continue; + if((criteria.flags & CMD_SEARCH_FLAG_NOT_VOICED) && (flags & CHANUSERFLAG_VOICED)) continue; + } + } + matches++; + //output + if(show_chans) { + reply(getTextBot(), user, "%s", row[0]); + } + } + reply(getTextBot(), user, "NS_TABLE_COUNT", matches); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_set.c b/src/modules/NeonServ.mod/cmd_neonserv_set.c new file mode 100644 index 0000000..ec21e44 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_set.c @@ -0,0 +1,471 @@ +/* cmd_neonserv_set.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +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 +#define NS_VALID_ACCESS 0x04 +#define NS_VALID_NO501 0x08 +#define NS_VALID_OPTIONS 0x10 +#define NS_VALID_NUMERIC 0x20 +#define NS_VALID_BOOLEAN 0x40 +#define NS_VALID_IF_HALFOP 0x80 + +#define NS_HAS_OPT 0x100 /* options (SET_OPTION_{NAME}_{VALUE}) */ +#define NS_HAS_HELP 0x200 /* help (SET_HELP_{NAME}) - only shown if help is requested */ + +static const struct { + const char *setting; + const char *chanfield; + unsigned int valid; + void *parameter; +} channel_settings[] = { + {"TRIGGER", NULL, NS_VALID_FUNCTION, neonserv_cmd_set_trigger}, + {"DEFAULTTOPIC", "channel_defaulttopic", NS_VALID_STRING, NULL}, + {"TOPICMASK", "channel_topicmask", NS_VALID_STRING, NULL}, + {"ADVANCEDTOPIC", "channel_exttopic", NS_VALID_BOOLEAN | NS_HAS_OPT, NULL}, + {"GREETING", "channel_greeting", NS_VALID_STRING, NULL}, + {"USERGREETING", "channel_usergreeting", NS_VALID_STRING, NULL}, + {"USERINFO", "channel_userinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"WIPEINFO", "channel_wipeinfo", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"MODES", "channel_modes", NS_VALID_FUNCTION, neonserv_cmd_set_modes}, + {"INVITEME", "channel_getinvite", NS_VALID_ACCESS, NULL}, + {"GIVEOPS", "channel_getop", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"GIVEHALFOPS", "channel_gethalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL}, + {"GIVEVOICE", "channel_getvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"ENFOPS", "channel_canop", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"ENFHALFOPS", "channel_canhalfop", NS_VALID_ACCESS | NS_HAS_HELP | NS_VALID_IF_HALFOP, NULL}, + {"ENFVOICE", "channel_canvoice", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"KICK", "channel_cankick", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"BAN", "channel_canban", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"STATICBAN", "channel_staticban", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"PUBCMD", "channel_pubcmd", NS_VALID_ACCESS, NULL}, + {"ENFMODES", "channel_enfmodes", NS_VALID_ACCESS, NULL}, + {"ENFTOPIC", "channel_enftopic", NS_VALID_ACCESS, NULL}, + {"TOPICSNARF", "channel_topicsnarf", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"CHANGETOPIC", "channel_changetopic", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"SETTERS", "channel_setters", NS_VALID_ACCESS | NS_VALID_NO501 | NS_HAS_HELP, NULL}, + {"ADDUSER", "channel_canadd", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"DELUSER", "channel_candel", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"CLVL", "channel_canclvl", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"RESYNC", "channel_canresync", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"SUSPEND", "channel_cansuspend", NS_VALID_ACCESS | NS_HAS_HELP, NULL}, + {"NOTICEUSERS", "channel_notice", NS_VALID_ACCESS, NULL}, + {"NOTICEREACTION", "channel_noticereaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, + {"CTCPUSERS", "channel_ctcp", NS_VALID_ACCESS, NULL}, + {"CTCPREACTION", "channel_ctcpreaction", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, + {"PROTECT", "channel_protect", NS_VALID_OPTIONS | NS_HAS_OPT, "4"}, + {"TOYS", "channel_toys", NS_VALID_OPTIONS | NS_HAS_OPT, "3"}, + {"DYNLIMIT", "channel_dynlimit", NS_VALID_NUMERIC | NS_VALID_FUNCTION | NS_HAS_OPT, neonserv_cmd_set_dynlimit}, + {"NODELETE", "channel_nodelete", NS_VALID_BOOLEAN | NS_VALID_FUNCTION, neonserv_cmd_set_nodelete}, + {NULL, NULL, 0, NULL} +}; + +#define MAX_QUERY_LEN 1024 +CMD_BIND(neonserv_cmd_set) { + int i, j; + if(argc && !strcmp(argv[0], "defaults")) { + //reset channel settings + int uaccess = getChannelAccess(user, chan); + if(uaccess < 500) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); + return; + } + } + int seed = 0; + char *tmp; + static char defaultskey[16]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(defaultskey, "%08x", seed); + if(argc > 1 && !strcmp(argv[1], defaultskey)) { + char query[MAX_QUERY_LEN]; + int querypos = 0; + i = 0; + while(channel_settings[i].setting) { + if(channel_settings[i].chanfield) + querypos += sprintf(query + querypos, "`%s` = NULL, ", channel_settings[i].chanfield); + i++; + } + if(querypos) { + query[querypos-2] = '\0'; + } + 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); + } + } else if(argc && strcmp(argv[0], "help")) { + //find the correct command + i = 0; + j = 0; + char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL); + int with_halfops = get_int_field("General.have_halfop"); + while(channel_settings[i].setting) { + if(!stricmp(channel_settings[i].setting, argv[0]) && (!(channel_settings[i].valid & NS_VALID_IF_HALFOP) || with_halfops)) { + //setting found + if(channel_settings[i].valid & NS_VALID_FUNCTION) { + neonserv_cmd_set_function *func = channel_settings[i].parameter; + func(client, user, chan, event, channel_settings[i].setting, args); + } else { + neonserv_cmd_set_setting(client, user, chan, event, i, args); + } + j = 1; + break; + } + i++; + } + if(j == 0) { + //unknown setting + reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]); + } + } else { + char query[MAX_QUERY_LEN], *value, *org_value, *tmp, nameBuf[64]; + int querypos = 0; + MYSQL_RES *res, *defaults_res; + MYSQL_ROW row, defaults; + struct Table *table; + char *content[2]; + int with_halfops = get_int_field("General.have_halfop"); + i = 0; + j = 0; + while(channel_settings[i].setting) { + if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) { + j++; + i++; + continue; + } + if(channel_settings[i].chanfield) + querypos += sprintf(query + querypos, ", `%s`", channel_settings[i].chanfield); + i++; + } + table = table_init(2, i-j, 0); + table_set_bold(table, 0, 1); + printf_mysql_query("SELECT `channel_id` %s FROM `channels` WHERE `channel_name` = 'defaults'", query); + defaults_res = mysql_use(); + defaults = mysql_fetch_row(defaults_res); + printf_mysql_query("SELECT `channel_name` %s FROM `channels` WHERE `channel_id` = '%d'", query, chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + i = 0; + j = 0; + reply(getTextBot(), user, "NS_SET_HEADER", chan->name); + while(channel_settings[i].setting) { + if((channel_settings[i].valid & NS_VALID_IF_HALFOP) && !with_halfops) { + i++; + continue; + } + if(channel_settings[i].chanfield) { + j++; + 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, event, NULL, NULL); + } else + org_value = "0"; + value = org_value; + if(channel_settings[i].valid & NS_VALID_BOOLEAN) { + if(!strcmp(value, "0")) + value = get_language_string(user, "NS_SET_OFF"); + else + value = get_language_string(user, "NS_SET_ON"); + } + strcpy(query, value); + querypos = strlen(query); + if(channel_settings[i].valid & NS_HAS_OPT) { + sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[i].setting, org_value); + tmp = get_language_string(user, nameBuf); + if(tmp) { + querypos += sprintf(query+querypos, " - %s", tmp); + } + } + if(argc && channel_settings[i].valid & NS_HAS_HELP) { + sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[i].setting); + tmp = get_language_string(user, nameBuf); + if(tmp) { + querypos += sprintf(query+querypos, " - %s", tmp); + } + } + content[0] = (char*)channel_settings[i].setting; + content[1] = query; + table_add(table, content); + i++; + } + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + } +} + +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 + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", channel_settings[setting].chanfield, chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row[0] == NULL) { + printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_name` = 'defaults'", channel_settings[setting].chanfield); + res = mysql_use(); + row = mysql_fetch_row(res); + } + value = row[0]; + if(args) { + //change the channel setting + //check the new argument + int valid = channel_settings[setting].valid; + if(valid & NS_VALID_STRING) { + if(!strcmp(args, "*")) { + args = ""; + } + } + if(valid & NS_VALID_ACCESS) { + int caccess = atoi(args); + int max = ((valid & NS_VALID_NO501) ? 500 : 501); + if(caccess < 0 || caccess > max) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return; + } + int uaccess = getChannelAccess(user, chan); + if(uaccess == 500) uaccess++; + if(atoi(value) > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_CANNOT_SET"); + return; + } + } + if(caccess > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_BADLEVEL"); + return; + } + } + sprintf(nameBuf, "%d", caccess); + args = nameBuf; + } + if(valid & NS_VALID_OPTIONS) { + int options = atoi((char *) channel_settings[setting].parameter); + int coption = atoi(args); + if(coption < 0 || coption >= options) { + reply(getTextBot(), user, "NS_SET_INVALID_OPTION", coption); + int i; + int nameBufPos = 0; + if(valid & NS_HAS_OPT) { + for(i = 0; i < options; i++) { + sprintf(nameBuf, "NS_SET_OPTION_%s_%d", channel_settings[setting].setting, i); + reply(getTextBot(), user, "\002%d\002 - %s", i, get_language_string(user, nameBuf)); + } + } else { + for(i = 0; i < options; i++) { + nameBufPos += sprintf(nameBuf + nameBufPos, "\002%d\002, ", i); + } + if(nameBufPos) { + nameBuf[nameBufPos-2] = '\0'; + reply(getTextBot(), user, nameBuf); + } + } + return; + } + } + if(valid & NS_VALID_NUMERIC) { + sprintf(nameBuf, "%d", atoi(args)); + args = nameBuf; + } + if(valid & NS_VALID_BOOLEAN) { + if(!strcmp(args, "0") || !stricmp(args, "off") || !stricmp(args, get_language_string(user, "NS_SET_OFF"))) { + args = "0"; + } else if(!strcmp(args, "1") || !stricmp(args, "on") || !stricmp(args, get_language_string(user, "NS_SET_ON"))) { + args = "1"; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", args); + return; + } + } + //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); + } + if(channel_settings[setting].valid & NS_HAS_OPT) { + sprintf(nameBuf, "NS_SET_OPTION_%s_%s", channel_settings[setting].setting, value); + char *tmp = get_language_string(user, nameBuf); + if(tmp) + reply(getTextBot(), user, "\002%s\002 %s - %s", channel_settings[setting].setting, value, tmp); + else + reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value); + } else + reply(getTextBot(), user, "\002%s\002 %s", channel_settings[setting].setting, value); + if(channel_settings[setting].valid & NS_HAS_HELP) { + sprintf(nameBuf, "NS_SET_HELP_%s", channel_settings[setting].setting); + reply(getTextBot(), user, " %s", get_language_string(user, nameBuf)); + } +} + +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; + MYSQL_ROW row; + printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid); + res = mysql_use(); + row = mysql_fetch_row(res); + trigger = (row[0] ? row[0] : row[1]); + if(argument) { + int uaccess = getChannelAccess(user, chan); + if(uaccess < 500) { + 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); + } + return trigger; +} + +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; + char valueBuf[MAXLEN]; + //get current value + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row[0] == NULL) { + printf_mysql_query("SELECT `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + row = mysql_fetch_row(res); + } + value = row[0]; + if(argument) { + //change the channel setting + struct ModeNode *modenode = createModeNode(NULL); + parseModeString(modenode, argument); + getFullModeString(modenode, valueBuf); + value = valueBuf; + printf_mysql_query("UPDATE `channels` SET `channel_modes` = '%s' WHERE `channel_id` = '%d'", escape_string(value), chan->channel_id); + //TODO: set modelock + freeModeNode(modenode); + } + if(setting) { + reply(getTextBot(), user, "\002%s\002 %s", setting, value); + } + return value; +} + +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 + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row[0] == NULL) { + printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + row = mysql_fetch_row(res); + } + value = row[0]; + if(argument) { + //change the channel setting + sprintf(tmp, "%d", atoi(argument)); + argument = tmp; + printf_mysql_query("UPDATE `channels` SET `channel_dynlimit` = '%s' WHERE `channel_id` = '%d'", escape_string(argument), chan->channel_id); + if(strcmp(argument, "0")) + putsock(client, "MODE %s +l %d", chan->name, (chan->usercount + atoi(argument))); + else if(isModeSet(chan->modes, 'l')) + putsock(client, "MODE %s -l", chan->name); + value = argument; + logEvent(event); + } + if(setting) { + reply(getTextBot(), user, "\002%s\002 %s", setting, value); + } + return value; +} + +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; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row[0] == NULL) { + printf_mysql_query("SELECT `channel_nodelete` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + row = mysql_fetch_row(res); + } + value = row[0]; + if(argument && isGodMode(user)) { + //change the channel setting + if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) { + argument = "0"; + } else if(!strcmp(argument, "0") || !strcmp(argument, "off") || !strcmp(argument, get_language_string(user, "NS_SET_OFF"))) { + argument = "1"; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); + 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; + value = argument; + logEvent(event); + } + if(setting) { + reply(getTextBot(), user, "\002%s\002 %s", setting, value); + } + return value; +} + +#undef MAX_QUERY_LEN diff --git a/src/modules/NeonServ.mod/cmd_neonserv_setrank.c b/src/modules/NeonServ.mod/cmd_neonserv_setrank.c new file mode 100644 index 0000000..f0c20f7 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_setrank.c @@ -0,0 +1,113 @@ +/* cmd_neonserv_setrank.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] rank id +* argv[1] setting +* argv[2-*] value +*/ + +static void neonserv_cmd_setrank_name(struct UserNode *user, int rank_id, char *current, char *value); +static void neonserv_cmd_setrank_info(struct UserNode *user, int rank_id, char *current, char *value); +static void neonserv_cmd_setrank_access(struct UserNode *user, int rank_id, char *current, char *value); +static void neonserv_cmd_setrank_order(struct UserNode *user, int rank_id, char *current, char *value); + +CMD_BIND(neonserv_cmd_setrank) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `rank_id`, `rank_name`, `rank_info`, `rank_access`, `rank_order` FROM `support_ranks` WHERE `rank_id` = '%s'", escape_string(argv[0])); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_SETRANK_NOT_FOUND", argv[0]); + return; + } + if(argc < 2) { + reply(getTextBot(), user, "NS_SETRANK_HEAD", row[0]); + reply(getTextBot(), user, "\002NAME \002 %s", row[1]); + reply(getTextBot(), user, "\002INFO \002 %s", row[2]); + reply(getTextBot(), user, "\002ACCESS \002 %s", row[3]); + reply(getTextBot(), user, "\002ORDER \002 %s", row[4]); + } else { + char *value = NULL; + if(argc > 2) { + value = merge_argv(argv, 2, argc); + } + if(!stricmp(argv[1], "name")) + neonserv_cmd_setrank_name(user, atoi(row[0]), row[1], value); + else if(!stricmp(argv[1], "info")) + neonserv_cmd_setrank_info(user, atoi(row[0]), row[2], value); + else if(!stricmp(argv[1], "access")) + neonserv_cmd_setrank_access(user, atoi(row[0]), row[3], value); + else if(!stricmp(argv[1], "order")) + neonserv_cmd_setrank_order(user, atoi(row[0]), row[4], value); + else + reply(getTextBot(), user, "NS_SETRANK_UNKNOWN_SETTING", row[1]); + } +} + +static void neonserv_cmd_setrank_name(struct UserNode *user, int rank_id, char *current, char *value) { + if(value && stricmp(value, current)) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `rank_id` FROM `support_ranks` WHERE `rank_name` = '%s'", escape_string(value)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_ADDRANK_EXISTS", value); + return; + } + printf_mysql_query("UPDATE `support_ranks` SET `rank_name` = '%s' WHERE `rank_id` = '%d'", escape_string(value), rank_id); + current = value; + } + reply(getTextBot(), user, "\002NAME\002 %s", current); +} + +static void neonserv_cmd_setrank_info(struct UserNode *user, int rank_id, char *current, char *value) { + if(value && stricmp(value, current)) { + printf_mysql_query("UPDATE `support_ranks` SET `rank_info` = '%s' WHERE `rank_id` = '%d'", escape_string(value), rank_id); + current = value; + } + reply(getTextBot(), user, "\002INFO\002 %s", current); +} + +static void neonserv_cmd_setrank_access(struct UserNode *user, int rank_id, char *current, char *value) { + if(value && stricmp(value, current)) { + int new_access = atoi(value); + if(new_access <= 0 || new_access > 1000) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", new_access); + return; + } + printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_rank` = '%d'", new_access, rank_id); + printf_mysql_query("UPDATE `support_ranks` SET `rank_access` = '%d' WHERE `rank_id` = '%d'", new_access, rank_id); + current = value; + } + reply(getTextBot(), user, "\002ACCESS\002 %s", current); +} + +static void neonserv_cmd_setrank_order(struct UserNode *user, int rank_id, char *current, char *value) { + if(value && stricmp(value, current)) { + int new_order = atoi(value); + if(new_order <= 0 || new_order > 99) { + reply(getTextBot(), user, "NS_SETRANK_ORDER_INVALID", new_order); + return; + } + printf_mysql_query("UPDATE `support_ranks` SET `rank_order` = '%d' WHERE `rank_id` = '%d'", new_order, rank_id); + current = value; + } + reply(getTextBot(), user, "\002ORDER\002 %s", current); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_suspend.c b/src/modules/NeonServ.mod/cmd_neonserv_suspend.c new file mode 100644 index 0000000..b6d18b4 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_suspend.c @@ -0,0 +1,119 @@ +/* cmd_neonserv_suspend.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_suspend) { + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_suspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_suspend_nick_lookup) { + struct neonserv_cmd_suspend_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid, cflags; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is added + 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)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } + } + //suspend + cflags = atoi(row[2]); + if(cflags & DB_CHANUSER_SUSPENDED) { + reply(textclient, user, "NS_SUSPEND_ALREADY", nick); + return; + } + 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; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_topic.c b/src/modules/NeonServ.mod/cmd_neonserv_topic.c new file mode 100644 index 0000000..76abea6 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_topic.c @@ -0,0 +1,157 @@ +/* cmd_neonserv_topic.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* ADVANCEDTOPIC enabled +* argv[0] topic id +* argv[1-*] topic +* +* ADVANCEDTOPIC disabled +* argv[0-*] topic +*/ + +#define ADVANCEDTOPIC_MAXID 9 + +CMD_BIND(neonserv_cmd_topic) { + MYSQL_RES *res; + MYSQL_ROW row, default_row = NULL; + int advanced_topic, i; + char *newtopic; + char *a,*b; + + printf_mysql_query("SELECT `channel_exttopic`, `channel_exttopic_topic`, `channel_topicmask`, `channel_enftopic`, `channel_topicsnarf`, `channel_defaulttopic` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[3] || !row[4]) { + printf_mysql_query("SELECT `channel_exttopic`, `channel_enftopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'"); + default_row = mysql_fetch_row(mysql_use()); + } + + if(row[0] == NULL) { + advanced_topic = atoi(default_row[0]); + } else + advanced_topic = atoi(row[0]); + if(argc == 0) { + //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); + if(uaccess >= atoi((row[3] ? row[3] : default_row[1]))) { + //just set the topic + newtopic = merge_argv(argv, 0, argc); + if(uaccess >= atoi((row[4] ? row[4] : default_row[2]))) { + //set the default topic + printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(newtopic), chan->channel_id); + } + putsock(client, "TOPIC %s :%s", chan->name, newtopic); + reply(getTextBot(), user, "NS_TOPIC_DONE", newtopic); + logEvent(event); + return; + } + if(advanced_topic) { + char *advtopics[ADVANCEDTOPIC_MAXID]; + int topic_id = 0; + topic_id = atoi(argv[0]); + if(!topic_id || topic_id > ADVANCEDTOPIC_MAXID) { + reply(getTextBot(), user, "NS_EXTTOPIC_INVALID_ID", argv[0]); + return; + } + //parse topics + i = 0; + b = row[1]; + while((a = strstr(b, "\n")) != NULL) { + *a = '\0'; + if(i == ADVANCEDTOPIC_MAXID-1) break; + advtopics[i++] = b; + b = a+1; + } + advtopics[i++] = b; + for(;i < ADVANCEDTOPIC_MAXID;i++) + advtopics[i] = ""; + if(argc < 2) { + //just show the topic with this id + reply(getTextBot(), user, "NS_EXTTOPIC_TOPICID", topic_id, advtopics[topic_id-1]); + return; + } + newtopic = merge_argv(argv, 1, argc); + if(!strcmp(newtopic, "*")) + newtopic = ""; + advtopics[topic_id-1] = newtopic; + char topiclist[MAXLEN*2]; + topiclist[0] = '\0'; + int topiclistpos = 0; + for(i = 0; i < ADVANCEDTOPIC_MAXID; i++) { + if(topiclistpos + strlen(advtopics[i]) + 2 >= MAXLEN) break; + topiclistpos += sprintf(topiclist+topiclistpos, (i ? "\n%s" : "%s"), advtopics[i]); + } + printf_mysql_query("UPDATE `channels` SET `channel_exttopic_topic` = '%s' WHERE `channel_id` = '%d'", escape_string(topiclist), chan->channel_id); + //now build the new topic and set it... + topiclistpos = 0; + b = row[2]; + char *topicpart, *debugbb; + while((a = strstr(b, "%")) != NULL) { + *a = '\0'; + if(isdigit(a[1]) && a[1] - 48 > 0) { + topicpart = advtopics[a[1] - 49]; + if(isdigit(topicpart[0]) && isdigit(b[strlen(b)-1])) + debugbb = "\002\002"; //double bold to prevent following digits used as color code + else + debugbb = ""; + topiclistpos += sprintf(topiclist + topiclistpos, "%s%s%s", b, debugbb, topicpart); + b = a+2; + } else { + topiclistpos += sprintf(topiclist + topiclistpos, "%s%%", b); + b = a+1; + } + } + topiclistpos += sprintf(topiclist + topiclistpos, "%s", b); + if(topiclistpos > MAXLEN) + 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]; + topiclist[0] = '\0'; + int topiclistpos = 0; + b = row[2]; + char *debugbb; + while((a = strstr(b, "*")) != NULL) { + *a = '\0'; + if(isdigit(newtopic[0]) && isdigit(b[strlen(b)-1])) + debugbb = "\002\002"; //double bold to prevent following digits used as color code + else + debugbb = ""; + topiclistpos += sprintf(topiclist + topiclistpos, "%s%s%s", b, debugbb, newtopic); + b = a+1; + } + topiclistpos += sprintf(topiclist + topiclistpos, "%s", b); + if(topiclistpos > MAXLEN) + topiclist[MAXLEN] = '\0'; + putsock(client, "TOPIC %s :%s", chan->name, topiclist); + reply(getTextBot(), user, "NS_TOPIC_DONE", topiclist); + logEvent(event); + } +} + +#undef ADVANCEDTOPIC_MAXID \ No newline at end of file diff --git a/src/modules/NeonServ.mod/cmd_neonserv_trace.c b/src/modules/NeonServ.mod/cmd_neonserv_trace.c new file mode 100644 index 0000000..eacb67f --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_trace.c @@ -0,0 +1,113 @@ +/* cmd_neonserv_trace.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +#define NS_TRACE_CRITERIA_AUTHED 0x01 +#define NS_TRACE_CRITERIA_NUMCHAN 0x02 + +struct neonserv_cmd_trace_criteria { + char *mask; + char *nick; + char *ident; + char *host; + char *account; + unsigned int flags : 4; + unsigned int authed : 1; + unsigned int used_channel : 5; //32 max + char *channel[10]; + unsigned int numchannels; + unsigned int limit : 16; +}; + +CMD_BIND(neonserv_cmd_trace) { + //ok parse the criterias + struct neonserv_cmd_trace_criteria *criteria = malloc(sizeof(*criteria)); + if (!criteria) { + perror("malloc() failed"); + return; + } + memset(criteria, 0, sizeof(*criteria)); + criteria->limit = 50; + int i, show_user = 0; + if(!stricmp(argv[0], "print")) { + show_user = 1; + } + for(i = 1; i < argc; i += 2) { + if(argc <= i+1) { + reply(getTextBot(), user, "MODCMD_LESS_PARAM_COUNT"); + return; + } + if(!stricmp(argv[i], "mask")) criteria->mask = argv[i+1]; + else if(!stricmp(argv[i], "nick")) criteria->nick = argv[i+1]; + else if(!stricmp(argv[i], "ident")) criteria->ident = argv[i+1]; + else if(!stricmp(argv[i], "host")) criteria->host = argv[i+1]; + else if(!stricmp(argv[i], "account")) criteria->account = argv[i+1]; + else if(!stricmp(argv[i], "authed")) { + if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) { + criteria->authed = 1; + } else if(!strcmp(argv[i+1], "0") || !strcmp(argv[i+1], "off") || !strcmp(argv[i+1], get_language_string(user, "NS_SET_OFF"))) { + criteria->authed = 0; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[i+1]); + return; + } + criteria->flags |= NS_TRACE_CRITERIA_AUTHED; + } + else if(!stricmp(argv[i], "channel")) criteria->channel[criteria->used_channel++] = argv[i+1]; + else if(!stricmp(argv[i], "numchannels")) { + criteria->numchannels = atoi(argv[i+1]); + criteria->flags |= NS_TRACE_CRITERIA_NUMCHAN; + } + else if(!stricmp(argv[i], "limit")) { + criteria->limit = atoi(argv[i+1]); + } + } + char tmp[MAXLEN]; + int matches = 0; + struct UserNode *cuser; + reply(getTextBot(), user, "NS_TRACE_HEADER"); + for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) { + if(show_user && matches == criteria->limit) { + //too many + break; + } + if(criteria->mask) { + sprintf(tmp, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(match(criteria->mask, tmp)) continue; + } + if(criteria->nick && match(criteria->nick, cuser->nick)) continue; + if(criteria->ident && match(criteria->ident, cuser->ident)) continue; + if(criteria->host && match(criteria->host, cuser->host)) continue; + if(criteria->account && (!(cuser->flags & USERFLAG_ISAUTHED) || match(criteria->account, cuser->auth))) continue; + if((criteria->flags & NS_TRACE_CRITERIA_AUTHED) && (criteria->authed ^ (cuser->flags & USERFLAG_ISAUTHED))) continue; + if((criteria->flags & NS_TRACE_CRITERIA_NUMCHAN)) { + int ccount = 0; + struct ChanUser *chanuser; + for(chanuser = getUserChannels(cuser, NULL); chanuser; chanuser = getUserChannels(cuser, chanuser)) + ccount++; + if(ccount < criteria->numchannels) + continue; + } + matches++; + //output + if(show_user) { + reply(getTextBot(), user, "%s!%s@%s %s", cuser->nick, cuser->ident, cuser->host, ((cuser->flags & USERFLAG_ISAUTHED) ? cuser->auth : "*")); + } + } + reply(getTextBot(), user, "NS_TABLE_COUNT", matches); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_trim.c b/src/modules/NeonServ.mod/cmd_neonserv_trim.c new file mode 100644 index 0000000..65a0e73 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_trim.c @@ -0,0 +1,158 @@ +/* cmd_neonserv_trim.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] target (format: minaccess-maxaccess/users/bans) +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_trim) { + if(stricmp(argv[0], "bans") && !checkChannelAccess(user, chan, "channel_candel", 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + } + int min_access, max_access; + int duration = strToTime(user, argv[1]); + if(duration < 30) { + reply(getTextBot(), user, "NS_TRIM_DURATION_TOO_SHORT", 30); + return; + } + if(!stricmp(argv[0], "users")) { + min_access = 1; + max_access = getChannelAccess(user, chan) - 1; + } else if(!stricmp(argv[0], "bans")) { + if(!checkChannelAccess(user, chan, "channel_staticban", 0)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_ACCESS_DENIED"); + return; + } + } + MYSQL_RES *res; + MYSQL_ROW row; + char nameBuf[20]; + printf_mysql_query("SELECT `ban_mask`, `ban_id`, `ban_timeout` FROM `bans` WHERE `ban_channel` = '%d' AND `ban_triggered` < %d", chan->channel_id, (int) (time(0) - duration)); + res = mysql_use(); + int bancount = mysql_num_rows(res); + struct ModeBuffer *modenode = initModeBuffer(client, chan); + while ((row = mysql_fetch_row(res)) != NULL) { + if(strcmp(row[2], "0")) { + sprintf(nameBuf, "ban_%s", row[1]); + timeq_del_name(nameBuf); + } + printf_mysql_query("DELETE FROM `bans` WHERE `ban_id` = '%s'", row[1]); + modeBufferUnban(modenode, row[0]); + } + freeModeBuffer(modenode); + char timeBuf[MAXLEN]; + reply(getTextBot(), user, "NS_TRIM_BAN_DONE", bancount, chan->name, timeToStr(user, duration, 3, timeBuf)); + if(bancount) + logEvent(event); + return; + } else { + char *seperator = strstr(argv[0], "-"); + if(seperator) { + *seperator = '\0'; + seperator++; + min_access = atoi(argv[0]); + max_access = atoi(seperator); + if(max_access < min_access) { + reply(getTextBot(), user, "NS_INVALID_ACCESS_RANGE", min_access, max_access); + return; + } + } else { + min_access = atoi(argv[0]); + max_access = min_access; + } + if(max_access >= getChannelAccess(user, chan)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_NO_ACCESS"); + return; + } + } + } + struct neonserv_cmd_trim_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + 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_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->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, struct Event *event, int min_access, int max_access, int duration) { + MYSQL_RES *res; + MYSQL_ROW row; + int trim_count = 0, is_here; + struct ChanUser *chanuser; + printf_mysql_query("SELECT `chanuser_seen`, `user_user`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `chanuser_access` >= '%d' AND `chanuser_access` <= '%d'", chan->channel_id, min_access, max_access); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!strcmp(row[0], "0") || time(0) - atoi(row[0]) >= duration) { + //check if the user is currently in the channel + 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(!is_here) { + //delete the user + trim_count++; + printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_id` = '%s'", row[2]); + } + } + } + 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/src/modules/NeonServ.mod/cmd_neonserv_unban.c b/src/modules/NeonServ.mod/cmd_neonserv_unban.c new file mode 100644 index 0000000..f88033b --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_unban.c @@ -0,0 +1,145 @@ +/* cmd_neonserv_unban.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nick[,*auth[,*!*@mask[...]]] +*/ +struct neonserv_cmd_unban_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + struct Event *event; + struct ModeBuffer *modeBuf; + int provided_masks, done_masks, pending_whos, unbanned_masks; +}; + +static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup); +static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user); +static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask); +static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache); + +CMD_BIND(neonserv_cmd_unban) { + char *mask, *nextmask; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + nextmask = merge_argv_char(argv, 0, argc, ','); + struct neonserv_cmd_unban_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->modeBuf = modeBuf; + cache->done_masks = 0; + cache->provided_masks = 0; + cache->unbanned_masks = 0; + while((mask = nextmask)) { + nextmask = strstr(mask, ","); + if(nextmask) { + *nextmask = '\0'; + nextmask++; + } + cache->provided_masks++; + if(is_valid_nick(mask)) { + struct UserNode *cuser = getUserByNick(mask); + if(!cuser) { + cuser = createTempUserMask(mask); + if(!cuser) { + break; //internal bot error + } + cuser->flags |= USERFLAG_ISTMPUSER; + get_userauth(cuser, neonserv_cmd_unban_userauth_lookup, cache); + cache->pending_whos++; + } else { + neonserv_cmd_unban_nick(cache, cuser); + } + } else { + neonserv_cmd_unban_mask(cache, mask); + } + } + if(!cache->pending_whos) + neonserv_cmd_unban_finish(cache); +} + +static USERAUTH_CALLBACK(neonserv_cmd_unban_userauth_lookup) { + struct neonserv_cmd_unban_cache *cache = data; + cache->pending_whos--; + if(user) + neonserv_cmd_unban_nick(cache, user); + else + neonserv_cmd_unban_mask(cache, user_nick); + if(!cache->pending_whos) + neonserv_cmd_unban_finish(cache); +} + +static void neonserv_cmd_unban_nick(struct neonserv_cmd_unban_cache *cache, struct UserNode *user) { + int matches = 0; + struct BanNode *ban; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); + for(ban = cache->chan->bans; ban; ban = ban->next) { + if(!match(ban->mask, usermask)) { + modeBufferUnban(cache->modeBuf, ban->mask); + cache->unbanned_masks++; + matches++; + } + } + if(matches) + cache->done_masks++; +} + +static void neonserv_cmd_unban_mask(struct neonserv_cmd_unban_cache *cache, char *mask) { + char banmask[NICKLEN+USERLEN+HOSTLEN+3]; + int matches = 0; + struct BanNode *ban; + mask = make_banmask(mask, banmask); + for(ban = cache->chan->bans; ban; ban = ban->next) { + if(!match(mask, ban->mask)) { + modeBufferUnban(cache->modeBuf, ban->mask); + cache->unbanned_masks++; + matches++; + } + } + if(matches) + cache->done_masks++; + else { + for(ban = cache->chan->bans; ban; ban = ban->next) { + if(!match(ban->mask, mask)) { + reply(cache->textclient, cache->user, "NS_DELBAN_BANNED_BY", mask, ban->mask); + break; + } + } + } +} + +static void neonserv_cmd_unban_finish(struct neonserv_cmd_unban_cache *cache) { + freeModeBuffer(cache->modeBuf); + if(cache->done_masks == cache->provided_masks) + reply(cache->textclient, cache->user, "NS_UNBAN_DONE", cache->unbanned_masks, cache->chan->name); + else + reply(cache->textclient, cache->user, "NS_UNBAN_FAIL", cache->client->user->nick); + if(cache->done_masks) + logEvent(cache->event); + free(cache); +} + diff --git a/src/modules/NeonServ.mod/cmd_neonserv_unbanall.c b/src/modules/NeonServ.mod/cmd_neonserv_unbanall.c new file mode 100644 index 0000000..cff9531 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_unbanall.c @@ -0,0 +1,39 @@ +/* cmd_neonserv_unbanall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nothing +*/ + +CMD_BIND(neonserv_cmd_unbanall) { + struct ModeBuffer *modeBuf; + int bans = 0; + struct BanNode *ban; + modeBuf = initModeBuffer(client, chan); + for(ban = chan->bans; ban; ban = ban->next) { + modeBufferUnban(modeBuf, ban->mask); + bans++; + } + freeModeBuffer(modeBuf); + if(bans) { + reply(getTextBot(), user, "NS_UNBANALL_DONE", bans, chan->name); + logEvent(event); + } else + reply(getTextBot(), user, "NS_UNBANALL_FAIL", client->user->nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_unbanme.c b/src/modules/NeonServ.mod/cmd_neonserv_unbanme.c new file mode 100644 index 0000000..ac1fa6c --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_unbanme.c @@ -0,0 +1,43 @@ +/* cmd_neonserv_unbanme.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0-*] nothing +*/ + +CMD_BIND(neonserv_cmd_unbanme) { + struct ModeBuffer *modeBuf; + int bans = 0; + struct BanNode *ban; + modeBuf = initModeBuffer(client, chan); + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); + for(ban = chan->bans; ban; ban = ban->next) { + if(!match(ban->mask, usermask)) { + modeBufferUnban(modeBuf, ban->mask); + bans++; + } + } + freeModeBuffer(modeBuf); + if(bans) { + reply(getTextBot(), user, "NS_UNBANME_DONE", bans, chan->name); + logEvent(event); + } else + reply(getTextBot(), user, "NS_UNBANME_FAIL", client->user->nick, usermask); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_unsuspend.c b/src/modules/NeonServ.mod/cmd_neonserv_unsuspend.c new file mode 100644 index 0000000..4053950 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_unsuspend.c @@ -0,0 +1,119 @@ +/* cmd_neonserv_unsuspend.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_unsuspend) { + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_unsuspend_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_unsuspend_nick_lookup) { + struct neonserv_cmd_unsuspend_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid, cflags; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is added + 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)) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(textclient, user, "NS_USER_OUTRANKED", nick); + return; + } + } + //unsuspend + cflags = atoi(row[2]); + if(!(cflags & DB_CHANUSER_SUSPENDED)) { + reply(textclient, user, "NS_SUSPEND_NOT", nick); + return; + } + 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; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_unvisited.c b/src/modules/NeonServ.mod/cmd_neonserv_unvisited.c new file mode 100644 index 0000000..9d7cda7 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_unvisited.c @@ -0,0 +1,108 @@ +/* cmd_neonserv_unvisited.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +struct neonserv_cmd_unvisited_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + int duration; + int who_count, matches; +}; + +static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup); +static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration); +static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache); + +CMD_BIND(neonserv_cmd_unvisited) { + int duration = (argc ? strToTime(user, argv[0]) : 60*60*24*7*3); + reply(getTextBot(), user, "NS_SEARCH_HEADER"); + MYSQL_RES *res, *res2; + MYSQL_ROW row, row2; + struct ChanNode *channel; + struct neonserv_cmd_unvisited_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->duration = duration; + cache->who_count = 1; /* small fake to prevent the cache to be freed too early */ + cache->matches = 0; + printf_mysql_query("SELECT `channel_id`, `channel_name`, `channel_nodelete` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` LEFT JOIN `users` ON `channel_registrator` = `user_id` WHERE `botid` = '%d'", client->botid); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(!strcmp(row[2], "1")) continue; + printf_mysql_query("SELECT `chanuser_seen` FROM `chanusers` WHERE `chanuser_cid` = '%s' AND `chanuser_access` >= 300 ORDER BY `chanuser_seen` DESC LIMIT 1", row[0]); + res2 = mysql_use(); + row2 = mysql_fetch_row(res2); + if(row2 && atol(row2[0]) > (time(0) - duration)) continue; + channel = getChanByName(row[1]); + if(channel) { + cache->who_count++; + channel->channel_id = atoi(row[0]); + get_userlist_with_invisible(channel, neonserv_cmd_unvisited_userlist_lookup, cache); + } else { + reply(getTextBot(), user, "%s", row[1]); + cache->matches++; + } + } + cache->who_count--; //see fix on line 46 + if(cache->who_count == 0) { + neonserv_cmd_unvisited_async2(cache); + } +} + +static USERLIST_CALLBACK(neonserv_cmd_unvisited_userlist_lookup) { + struct neonserv_cmd_unvisited_cache *cache = data; + if(neonserv_cmd_unvisited_async1(cache->client, cache->textclient, cache->user, chan, cache->duration)) + cache->matches++; + cache->who_count--; + if(cache->who_count == 0) { + neonserv_cmd_unvisited_async2(cache); + } +} + +static int neonserv_cmd_unvisited_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, int duration) { + struct ChanUser *chanuser; + MYSQL_RES *res2; + MYSQL_ROW row2; + int active = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(isBot(chanuser->user)) continue; + if((chanuser->user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_id`, `chanuser_access` FROM `chanusers` LEFT JOIN `users` ON `user_id` = `chanuser_uid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(chanuser->user->auth)); + res2 = mysql_use(); + row2 = mysql_fetch_row(res2); + if(row2 && atoi(row2[1]) >= 300) { + printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", row2[0]); + active = 1; + } + } + } + if(!active) { + reply(textclient, user, "%s", chan->name); + } + return !active; +} + +static void neonserv_cmd_unvisited_async2(struct neonserv_cmd_unvisited_cache *cache) { + reply(cache->textclient, cache->user, "NS_TABLE_COUNT", cache->matches); + free(cache); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_up.c b/src/modules/NeonServ.mod/cmd_neonserv_up.c new file mode 100644 index 0000000..0085b5f --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_up.c @@ -0,0 +1,95 @@ +/* cmd_neonserv_up.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +struct neonserv_cmd_up_cache { + struct ClientSocket *client; + struct ClientSocket *textclient; + struct UserNode *user; + struct Event *event; +}; + +static void neonserv_cmd_up_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event); +static USERLIST_CALLBACK(neonserv_cmd_up_userlist_lookup); + +CMD_BIND(neonserv_cmd_up) { + if(isModeSet(chan->modes, 'd') || isModeSet(chan->modes, 'D')) { + struct neonserv_cmd_up_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + get_userlist_if_invisible(chan, neonserv_cmd_up_userlist_lookup, cache); + } else { + neonserv_cmd_up_async1(client, getTextBot(), user, chan, event); + } +} + +static USERLIST_CALLBACK(neonserv_cmd_up_userlist_lookup) { + struct neonserv_cmd_up_cache *cache = data; + neonserv_cmd_up_async1(cache->client, cache->textclient, cache->user, chan, cache->event); + free(cache); +} + +static void neonserv_cmd_up_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event) { + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) { + reply(getTextBot(), user, "NS_NOT_ON_CHANNEL_YOU", chan->name); + return; + } + loadChannelSettings(chan); + MYSQL_RES *res, *default_res; + MYSQL_ROW row, default_row; + int chan_getop, chan_getvoice, caccess; + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); + default_res = mysql_use(); + if ((default_row = mysql_fetch_row(default_res)) == NULL) return; + chan_getop = (row[0] ? atoi(row[0]) : atoi(default_row[0])); + chan_getvoice = (row[1] ? atoi(row[1]) : atoi(default_row[1])); + } else { + chan_getop = atoi(row[0]); + chan_getvoice = atoi(row[1]); + } + caccess = getChannelAccess(user, chan); + 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 + reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan->name); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_upall.c b/src/modules/NeonServ.mod/cmd_neonserv_upall.c new file mode 100644 index 0000000..0f12379 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_upall.c @@ -0,0 +1,73 @@ +/* cmd_neonserv_upall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* no arguments +*/ + +CMD_BIND(neonserv_cmd_upall) { + MYSQL_RES *res, *default_res; + MYSQL_ROW row, default_row; + struct ChanUser *chanuser; + int userid, chan_getop, chan_getvoice, caccess; + int botid = client->botid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", user->auth); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) + return; + userid = atoi(row[0]); + printf_mysql_query("SELECT `chanuser_access`, `channel_getop`, `channel_getvoice`, `channel_name`, `channel_id` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `chanuser_uid` = '%d'", userid); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + chan = getChanByName(row[3]); + if(!chan) continue; + printf_mysql_query("SELECT `botid` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%s' AND `botclass` = '%d'", row[4], client->botid); + if (mysql_fetch_row(mysql_use()) == NULL) continue; + if(!(chanuser = getChanUser(user, chan))) continue; + if(!row[1] || !row[2]) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); + default_res = mysql_use(); + if ((default_row = mysql_fetch_row(default_res)) == NULL) return; + chan_getop = (row[1] ? atoi(row[1]) : atoi(default_row[0])); + chan_getvoice = (row[2] ? atoi(row[2]) : atoi(default_row[1])); + } else { + chan_getop = atoi(row[1]); + chan_getvoice = atoi(row[2]); + } + caccess = atoi(row[0]); + int done = 0; + client = getChannelBot(chan, botid); + if(!client) continue; + if(caccess >= chan_getop) { + 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)) { + putsock(client, "MODE %s +v %s", chan->name, user->nick); + done = 1; + } + } + if(done) { + event->chan = chan; + logEvent(event); + } + } +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_users.c b/src/modules/NeonServ.mod/cmd_neonserv_users.c new file mode 100644 index 0000000..cd8d375 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_users.c @@ -0,0 +1,132 @@ +/* cmd_neonserv_users.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* argv[0] - usermask +* argv[1] - min access +* argv[2] - max access +*/ +static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup); +static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access); + +struct neonserv_cmd_users_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + char *usermask; + int min_access; + int max_access; +}; + +CMD_BIND(neonserv_cmd_users) { + int min_access = 1, max_access = 500; + char *usermask = NULL; + if(argc > 0) + usermask = argv[0]; + if(argc > 2) { + min_access = atoi(argv[1]); + max_access = atoi(argv[2]); + } + struct neonserv_cmd_users_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->usermask = (usermask ? strdup(usermask) : NULL); + cache->min_access = min_access; + cache->max_access = max_access; + get_userlist_with_invisible(chan, neonserv_cmd_users_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_cmd_users_userlist_lookup) { + struct neonserv_cmd_users_cache *cache = data; + neonserv_cmd_users_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access); + if(cache->usermask) + free(cache->usermask); + free(cache); +} + +static void neonserv_cmd_users_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access) { + MYSQL_RES *res; + MYSQL_ROW row; + int content_count = 0, cflags, is_here, caccess, i; + char seenstr[MAXLEN]; + struct Table *table; + struct ChanUser *chanuser; + printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_seen`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id); + res = mysql_use(); + table = table_init(4, mysql_num_rows(res) + 1, 0); + if(usermask) + reply(textclient, user, "NS_USERS_HEADER_MATCH", chan->name, min_access, max_access, usermask); + else + reply(textclient, user, "NS_USERS_HEADER", chan->name, min_access, max_access); + char *content[4]; + content[0] = get_language_string(user, "NS_USERS_HEADER_ACCESS"); + content[1] = get_language_string(user, "NS_USERS_HEADER_ACCOUNT"); + content[2] = get_language_string(user, "NS_USERS_HEADER_SEEN"); + content[3] = get_language_string(user, "NS_USERS_HEADER_STATE"); + table_add(table, content); + while ((row = mysql_fetch_row(res)) != NULL) { + caccess = atoi(row[0]); + if((!usermask || !match(usermask, row[1])) && caccess >= min_access && caccess <= max_access) { + content[0] = row[0]; + content[1] = row[1]; + is_here = 0; + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if((chanuser->user->flags & USERFLAG_ISAUTHED) && !stricmp(chanuser->user->auth, row[1])) { + if((chanuser->flags & CHANUSERFLAG_INVISIBLE)) + is_here = 2; + else { + is_here = 1; + break; + } + } + } + if(is_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 { + timeToStr(user, (time(0) - atoi(row[2])), 2, seenstr); + content[2] = seenstr; //generate time + } + cflags = atoi(row[3]); + if(cflags & DB_CHANUSER_SUSPENDED) + content[3] = get_language_string(user, "NS_USERS_STATE_SUSPENDED"); + else + content[3] = get_language_string(user, "NS_USERS_STATE_NORMAL"); + content_count++; + table_add(table, content); + } + } + //send the table + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(textclient, user, table_lines[i]); + } + if(!content_count) + reply(textclient, user, "NS_TABLE_NONE"); + if(usermask || min_access != 1 || max_access != 500) + reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_MATCH_1" : "NS_USERS_COUNT_MATCH"), table->length - 1, chan->name, content_count); + else + reply(textclient, user, (table->length == 2 ? "NS_USERS_COUNT_1" : "NS_USERS_COUNT"), table->length - 1, chan->name); + table_free(table); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_uset.c b/src/modules/NeonServ.mod/cmd_neonserv_uset.c new file mode 100644 index 0000000..25a3118 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_uset.c @@ -0,0 +1,184 @@ +/* cmd_neonserv_uset.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +CMD_BIND(neonserv_cmd_uset) { + MYSQL_RES *res; + MYSQL_ROW row; + loadUserSettings(user); + if(argc > 0) { + if(!stricmp(argv[0], "language")) { + struct language* lang; + if(argc > 1) { + if((lang = get_language_by_tag(argv[1])) == NULL && (lang = get_language_by_name(argv[1])) == NULL) { + lang = user->language; + } else { + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + printf_mysql_query("UPDATE `users` SET `user_lang` = '%s' WHERE `user_id` = '%s'", escape_string(lang->langtag), row[0]); + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`, `user_lang`) VALUES ('%s', '%s')", escape_string(user->auth), escape_string(lang->langtag)); + } + struct UserNode *cuser; + for(cuser = getAllUsers(NULL); cuser; cuser = getAllUsers(cuser)) { + if((cuser->flags & USERFLAG_ISAUTHED) && !stricmp(user->auth, cuser->auth)) + cuser->language = lang; + } + } + } else + lang = user->language; + reply(getTextBot(), user, "\002Language \002%s", lang->langname); + char tmp[MAXLEN]; + int tmppos = 0; + lang = get_default_language(); + tmppos = sprintf(tmp, "%s (%s)", lang->langname, lang->langtag); + printf_mysql_query("SELECT `lang`,`text` FROM `language` WHERE `ident` = 'name'"); + res = mysql_use(); + while((row = mysql_fetch_row(res)) != NULL) { + tmppos += sprintf(tmp + tmppos, ", %s (%s)", row[1], row[0]); + } + reply(getTextBot(), user, " %s", tmp); + } else if(!stricmp(argv[0], "noinvite") && chan) { + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED"); + return; + } + printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + row = mysql_fetch_row(res); + int noinvite = (row ? 1 : 0); + if(argc > 1) { + if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { + if(noinvite) { + printf_mysql_query("DELETE FROM `noinvite` WHERE `id` = '%s'", row[0]); + noinvite = 0; + } + } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { + if(!noinvite) { + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(user->auth)); + userid = (int) mysql_insert_id(get_mysql_conn()); + } + printf_mysql_query("INSERT INTO `noinvite` (`uid`, `cid`) VALUES ('%d', '%d')", userid, chan->channel_id); + noinvite = 1; + } + } + } + reply(getTextBot(), user, "\002NoInvite \002%s", (noinvite ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + } else if((!stricmp(argv[0], "autoinvite") || !stricmp(argv[0], "noautoop") || !stricmp(argv[0], "info")) && chan) { + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + reply(getTextBot(), user, "MODCMD_CHAN_REQUIRED"); + return; + } + printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row) { + int flags = atoi(row[0]); + if(!stricmp(argv[0], "autoinvite")) { + int getInvite = 0; + if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite"))) + getInvite = 1; + else if(row[3] && atoi(row[2]) >= atoi(row[3])) + getInvite = 1; + if(getInvite && argc > 1) { + if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { + if(flags & DB_CHANUSER_AUTOINVITE) { + flags &= ~DB_CHANUSER_AUTOINVITE; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); + } + } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { + if(!(flags & DB_CHANUSER_AUTOINVITE)) { + flags |= DB_CHANUSER_AUTOINVITE; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); + } + } + } + if(getInvite) + reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + else + reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS")); + } else if(!stricmp(argv[0], "noautoop")) { + if(argc > 1) { + if(!strcmp(argv[1], "0") || !stricmp(argv[1], "off") || !stricmp(argv[1], get_language_string(user, "NS_SET_OFF"))) { + if(flags & DB_CHANUSER_NOAUTOOP) { + flags &= ~DB_CHANUSER_NOAUTOOP; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); + } + } else if(!strcmp(argv[1], "1") || !stricmp(argv[1], "on") || !stricmp(argv[1], get_language_string(user, "NS_SET_ON"))) { + if(!(flags & DB_CHANUSER_NOAUTOOP)) { + flags |= DB_CHANUSER_NOAUTOOP; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_flags` = '%d' WHERE `chanuser_id` = '%s'", flags, row[4]); + } + } + } + reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + } else if(!stricmp(argv[0], "info")) { + char *infoline; + if(argc > 1) { + infoline = merge_argv(argv, 1, argc); + if(!strcmp(infoline, "*")) + infoline = ""; + printf_mysql_query("UPDATE `chanusers` SET `chanuser_infoline` = '%s' WHERE `chanuser_id` = '%s'", escape_string(infoline), row[4]); + } else + infoline = row[1]; + reply(getTextBot(), user, "\002Info \002%s", infoline); + } + } else + reply(getTextBot(), user, "NS_NOT_ON_USERLIST_YOU", chan); + } else + reply(getTextBot(), user, "NS_USET_UNKNOWN_SETTING", argv[0]); + } else { + //view all options + reply(getTextBot(), user, "NS_USET_GLOBAL"); + reply(getTextBot(), user, "\002Language \002%s", user->language->langname); + if(!chan) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + reply(getTextBot(), user, "NS_USET_CHANNEL"); + printf_mysql_query("SELECT `id` FROM `noinvite` LEFT JOIN `users` ON `uid` = `user_id` WHERE `cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + row = mysql_fetch_row(res); + reply(getTextBot(), user, "\002NoInvite \002%s", (row ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + printf_mysql_query("SELECT `chanuser_flags`, `chanuser_infoline`, `chanuser_access`, `channel_getinvite` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `channel_id` = `chanuser_cid` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + row = mysql_fetch_row(res); + if(row) { + int flags = atoi(row[0]); + int getInvite = 0; + if(!row[3] && atoi(row[2]) >= atoi(getChanDefault("channel_getinvite"))) + getInvite = 1; + else if(row[3] && atoi(row[2]) >= atoi(row[3])) + getInvite = 1; + if(getInvite) + reply(getTextBot(), user, "\002AutoInvite \002%s", ((flags & DB_CHANUSER_AUTOINVITE) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + else + reply(getTextBot(), user, "\002AutoInvite \002%s", get_language_string(user, "NS_USET_NO_ACCESS")); + reply(getTextBot(), user, "\002NoAutoOp \002%s", ((flags & DB_CHANUSER_NOAUTOOP) ? get_language_string(user, "NS_SET_ON") : get_language_string(user, "NS_SET_OFF"))); + reply(getTextBot(), user, "\002Info \002%s", row[1]); + } + } +} \ No newline at end of file diff --git a/src/modules/NeonServ.mod/cmd_neonserv_voice.c b/src/modules/NeonServ.mod/cmd_neonserv_voice.c new file mode 100644 index 0000000..49dfe6c --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_voice.c @@ -0,0 +1,93 @@ +/* cmd_neonserv_voice.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, struct Event *event, char *nicks); + +struct neonserv_cmd_voice_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nicks; +}; + +CMD_BIND(neonserv_cmd_voice) { + struct neonserv_cmd_voice_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->nicks = strdup(merge_argv(argv, 0, argc)); + get_userlist_if_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->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, struct Event *event, char *nicks) { + int total_users = 0, done_users = 0; + struct UserNode *cuser; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + char *a, *b = nicks; + do { + a = strstr(b, " "); + if(a) *a = '\0'; + total_users++; + cuser = searchUserByNick(b); + if(!cuser) { + //check for an invisible user + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(!stricmp(chanuser->user->nick, b)) { + cuser = chanuser->user; + break; + } + } + if(!cuser) continue; + } else { + chanuser = getChanUser(cuser, chan); + if(!chanuser) continue; + } + done_users++; + if(chanuser->flags & CHANUSERFLAG_VOICED) continue; + modeBufferVoice(modeBuf, b); + if(a) { + b = a+1; + } + } while(a); + freeModeBuffer(modeBuf); + if(done_users == total_users) + 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/src/modules/NeonServ.mod/cmd_neonserv_voiceall.c b/src/modules/NeonServ.mod/cmd_neonserv_voiceall.c new file mode 100644 index 0000000..779110c --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_voiceall.c @@ -0,0 +1,73 @@ +/* cmd_neonserv_voiceall.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, struct Event *event, char *nickmask); + +struct neonserv_cmd_voiceall_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + char *nickmask; +}; + +CMD_BIND(neonserv_cmd_voiceall) { + struct neonserv_cmd_voiceall_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + if(argc > 0) { + cache->nickmask = strdup(argv[0]); + } else + cache->nickmask = NULL; + get_userlist_if_invisible(chan, neonserv_cmd_voiceall_userlist_lookup, cache); +} + +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->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, struct Event *event, char *nickmask) { + int done_users = 0; + struct ChanUser *chanuser; + struct ModeBuffer *modeBuf; + modeBuf = initModeBuffer(client, chan); + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + if(nickmask && match(nickmask, chanuser->user->nick)) continue; + if(chanuser->flags & CHANUSERFLAG_VOICED) continue; + modeBufferVoice(modeBuf, chanuser->user->nick); + done_users++; + } + freeModeBuffer(modeBuf); + reply(textclient, user, "NS_VOICEALL_DONE", done_users, chan->name); + if(done_users) + logEvent(event); +} diff --git a/src/modules/NeonServ.mod/cmd_neonserv_wipeinfo.c b/src/modules/NeonServ.mod/cmd_neonserv_wipeinfo.c new file mode 100644 index 0000000..71a1cc8 --- /dev/null +++ b/src/modules/NeonServ.mod/cmd_neonserv_wipeinfo.c @@ -0,0 +1,113 @@ +/* cmd_neonserv_wipeinfo.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonserv.h" + +/* +* 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, 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; +}; + +CMD_BIND(neonserv_cmd_wipeinfo) { + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + neonserv_cmd_wipeinfo_async1(client, getTextBot(), user, chan, event, argv[0], argv[0]); + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + 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) { + perror("malloc() failed"); + return; + } + cache->client = client; + 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); + } + } +} + +static USERAUTH_CALLBACK(neonserv_cmd_wipeinfo_nick_lookup) { + struct neonserv_cmd_wipeinfo_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + 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, struct Event *event, char *nick, char *auth) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + int userid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + //check if the user is already added + 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)) { + 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; + } + } + reply(textclient, user, "NS_NOT_ON_USERLIST", nick, chan->name); +} diff --git a/src/modules/NeonServ.mod/event_neonserv_ctcp.c b/src/modules/NeonServ.mod/event_neonserv_ctcp.c new file mode 100644 index 0000000..11d03e2 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_ctcp.c @@ -0,0 +1,112 @@ +/* event_neonserv_ctcp.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonserv_event_ctcp_cache { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + char *command; + char *text; +}; + +static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup); +static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text); + +static void neonserv_event_chanctcp(struct UserNode *user, struct ChanNode *chan, char *command, char *text) { + if(!stricmp(command, "ACTION")) return; //always allow CTCP ACTION (/me) + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(isNetworkService(user)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_event_ctcp_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->user = user; + cache->chan = chan; + cache->command = strdup(command); + cache->text = (text ? strdup(text) : NULL); + get_userauth(user, neonserv_event_ctcp_nick_lookup, cache); + } else + neonserv_event_ctcp_async1(client, user, chan, command, text); +} + +static USERAUTH_CALLBACK(neonserv_event_ctcp_nick_lookup) { + struct neonserv_event_ctcp_cache *cache = data; + if(user) { + neonserv_event_ctcp_async1(cache->client, cache->user, cache->chan, cache->command, cache->text); + } + free(cache->command); + if(cache->text) + free(cache->text); + free(cache); +} + +static void neonserv_event_ctcp_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *command, char *text) { + MYSQL_RES *res; + MYSQL_ROW row, defaultrow = NULL, chanuser; + int uaccess = 0; + printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + int ctcpaccess = atoi((row[0] ? row[0] : defaultrow[0])); + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuser = mysql_fetch_row(res); + if(chanuser) + uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0])); + } + int duration = 0; + char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; + char *banmask = NULL; + char *reason = "disallowed channel CTCP"; + if(uaccess < ctcpaccess) { + switch(atoi((row[1] ? row[1] : defaultrow[1]))) { + case 2: //TIMEBAN: 3min + duration = 180; + case 3: //TIMEBAN: 1h + if(!duration) + duration = 3600; + banmask = generate_banmask(user, banmaskBuf); + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason)); + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); + case 1: //KICKBAN + if(!banmask) + banmask = generate_banmask(user, banmaskBuf); + putsock(client, "MODE %s +b %s", chan->name, banmask); + case 0: //KICK + putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason); + break; + } + } +} + diff --git a/src/modules/NeonServ.mod/event_neonserv_invite.c b/src/modules/NeonServ.mod/event_neonserv_invite.c new file mode 100644 index 0000000..2b53429 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_invite.c @@ -0,0 +1,45 @@ +/* event_neonserv_invite.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static void neonserv_event_invite(struct ClientSocket *client, struct UserNode *user, char *channel) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `channel_name` = '%s' AND `botclass` = '%d'", escape_string(channel), client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(client, user, "NS_INVITE_FAIL", channel, client->user->nick); + return; + } + if(!strcmp(row[2], "1")) { + reply(client, user, "MODCMD_CHAN_SUSPENDED"); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + struct ChanNode *chan = getChanByName(channel); + if(chan && isUserOnChan(bot->user, chan)) { + reply(client, user, "NS_INVITE_ON_CHAN", bot->user->nick, chan->name); + } else + putsock(bot, "JOIN %s", channel); + } +} + diff --git a/src/modules/NeonServ.mod/event_neonserv_join.c b/src/modules/NeonServ.mod/event_neonserv_join.c new file mode 100644 index 0000000..77d5de7 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_join.c @@ -0,0 +1,252 @@ +/* event_neonserv_join.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonserv_event_join_cache { + struct ClientSocket *client; + struct ChanUser *chanuser; + int was_registering; +}; + +static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup); +static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser, int was_registering); +static TIMEQ_CALLBACK(neonserv_event_join_dynlimit); + +static void neonserv_event_join(struct ChanUser *chanuser) { + struct UserNode *user = chanuser->user; + struct ClientSocket *client = getBotForChannel(chanuser->chan); + if(!client) return; //we can't "see" this event + if(chanuser->user == client->user) { + requestOp(client->user, chanuser->chan); + return; + } + if(chanuser->user->flags & USERFLAG_ISBOT) return; + loadChannelSettings(chanuser->chan); + if(!(chanuser->chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + char *ban; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + sprintf(usermask, "%s!%s@%s", user->nick, user->ident, user->host); + if((ban = getBanAffectingMask(chanuser->chan, usermask)) != NULL && !(user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP))) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `ban_reason`, `user_user` FROM `bans` LEFT JOIN `users` ON `ban_owner` = `user_id` WHERE `ban_channel` = '%d' AND `ban_mask` = '%s'", chanuser->chan->channel_id, escape_string(ban)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "MODE %s +b %s", chanuser->chan->name, ban); + putsock(client, "KICK %s %s :(%s) %s", chanuser->chan->name, chanuser->user->nick, (row[1] ? row[1] : client->user->nick), row[0]); + return; + } + } + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_event_join_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->chanuser = chanuser; + cache->was_registering = (user->flags & USERFLAG_WAS_REGISTRING); + get_userauth(user, neonserv_event_join_nick_lookup, cache); + } else + neonserv_event_join_async1(client, chanuser, (user->flags & USERFLAG_WAS_REGISTRING)); +} + +static USERAUTH_CALLBACK(neonserv_event_join_nick_lookup) { + struct neonserv_event_join_cache *cache = data; + if(user) { + neonserv_event_join_async1(cache->client, cache->chanuser, cache->was_registering); + } + free(cache); +} + +static void neonserv_event_join_async1(struct ClientSocket *client, struct ChanUser *chanuser, int was_registering) { + struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); + struct ChanNode *chan = chanuser->chan; + struct UserNode *user = chanuser->user; + struct ModeBuffer *modeBuf; + int with_halfops = get_int_field("General.have_halfop"); + MYSQL_RES *res; + MYSQL_ROW row, chanuserrow, defaultrow = NULL; + printf_mysql_query("SELECT `channel_maxusers`, `channel_greeting`, `channel_usergreeting`, `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_dynlimit`, `channel_gethalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[3] || !row[4] || !row[5] || (!row[7] && with_halfops)) { + printf_mysql_query("SELECT `channel_getop`, `channel_getvoice`, `channel_userinfo`, `channel_gethalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + if(chan->usercount > atoi(row[0])) { + //update maxusers + printf_mysql_query("UPDATE `channels` SET `channel_maxusers` = '%d' WHERE `channel_id` = '%d'", chan->usercount, chan->channel_id); + } + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `chanuser_infoline`, `chanuser_seen`, `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuserrow = mysql_fetch_row(res); + } else + chanuserrow = NULL; + if(!chanuserrow) + printf_mysql_query("UPDATE `channels` SET `channel_lastvisit` = UNIX_TIMESTAMP() WHERE `channel_id` = '%d'", chan->channel_id); + int userflags = (chanuserrow ? atoi(chanuserrow[1]) : 0); + int uaccess = ((chanuserrow && !(userflags & DB_CHANUSER_SUSPENDED)) ? atoi(chanuserrow[0]) : 0); + //GREETING + char greeting[MAXLEN]; + int greetingPos = 0; + char *a, *b = (chanuserrow && *row[2] ? row[2] : row[1]); + do { + if(!b) break; + a = strstr(b, "$"); + if(a) *a = '\0'; + greetingPos += sprintf(greeting + greetingPos, "%s", b); + if(!a) break; + switch(a[1]) { + case '\0': + a = NULL; + break; + case 'A': + greetingPos += sprintf(greeting + greetingPos, "%d", uaccess); + break; + case 'B': + greetingPos += sprintf(greeting + greetingPos, "%s", client->user->nick); + break; + case 'N': + greetingPos += sprintf(greeting + greetingPos, "%s", user->nick); + break; + case 'H': + greetingPos += sprintf(greeting + greetingPos, "%s@%s", user->ident, user->host); + break; + case 'U': + greetingPos += sprintf(greeting + greetingPos, "%s", ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*")); + break; + default: + greeting[greetingPos++] = '$'; + greeting[greetingPos++] = a[1]; + break; + } + if(a) + b = a+2; + } while(a); + if(greetingPos && (!was_registering || *row[2])) + reply(textclient, user, "[%s] %s", chan->name, greeting); + //USER RIGHTS + if(!(userflags & DB_CHANUSER_NOAUTOOP)) { + int getop = atoi((row[3] ? row[3] : defaultrow[0])); + int gethalfop = (with_halfops ? atoi((row[7] ? row[7] : defaultrow[3])) : 0); + int getvoice = atoi((row[4] ? row[4] : defaultrow[1])); + modeBuf = initModeBuffer(client, chan); + if(uaccess >= getop && uaccess != 0) { //we disallow auto op for all users + modeBufferOp(modeBuf, user->nick); + } else if(with_halfops && uaccess >= gethalfop) { + modeBufferHalfop(modeBuf, user->nick); + } else if(uaccess >= getvoice) { + modeBufferVoice(modeBuf, user->nick); + } + freeModeBuffer(modeBuf); + } + //INFOLINE + int userinfoaccess = atoi((row[5] ? row[5] : defaultrow[2])); + if(chanuserrow && strcmp(chanuserrow[2], "") && uaccess > userinfoaccess) { + if(!strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30) { + putsock(client, "PRIVMSG %s :[%s] %s", chan->name, user->nick, chanuserrow[2]); + } + } + //SEEN + if(chanuserrow) { + printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[4]); + } + //DYNLIMIT + if(row[6] && strcmp(row[6], "0")) { + char nameBuf[CHANNELLEN + 10]; + sprintf(nameBuf, "dynlimit_%s", chan->name); + if(!timeq_name_exists(nameBuf)) { + //neonserv_event_join_dynlimit + timeq_add_name(nameBuf, 30, neonserv_event_join_dynlimit, strdup(chan->name)); + } + } + //AUTOINVITE + if((user->flags & USERFLAG_ISAUTHED) && (!chanuserrow || !strcmp(chanuserrow[3], "0") || time(0) - atol(chanuserrow[3]) >= 30)) { + //check if it's the first channel, the user is seen by the bot (IMPORTANT: ignore other bot's channel!) + char first_chan = 1; + char bot_in_chan; + struct ChanUser *cchanuser, *bchanuser; + struct ClientSocket *bot; + for(cchanuser = getUserChannels(user, NULL); cchanuser; cchanuser = getUserChannels(user, cchanuser)) { + if(chanuser == cchanuser) continue; //ignore this one ;) + //check if this bot is in the specific channel + bot_in_chan = 0; + for(bchanuser = getChannelUsers(cchanuser->chan, NULL); bchanuser; bchanuser = getChannelUsers(cchanuser->chan, bchanuser)) { + if(bchanuser->user->flags & USERFLAG_ISBOT) { + //get the botid + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->user == bchanuser->user) { + if(bot->botid == client->botid) + bot_in_chan = 1; + break; + } + } + if(bot_in_chan) break; + } + } + if(!bot_in_chan) continue; + first_chan = 0; + break; + } + if(first_chan) { + //autoinvite :) + defaultrow = NULL; + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags`, `channel_name`, `channel_getinvite` FROM `chanusers` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `user_user` = '%s' AND `chanuser_flags` >= '%d'", escape_string(user->auth), DB_CHANUSER_AUTOINVITE); + res = mysql_use(); + int getinvite; + while((chanuserrow = mysql_fetch_row(res)) != NULL) { + userflags = atoi(chanuserrow[1]); + if(!(userflags & DB_CHANUSER_AUTOINVITE)) continue; + if(!(chan = getChanByName(chanuserrow[2]))) continue; //no bot is in the channel + if((bchanuser = getChanUser(client->user, chan)) && (bchanuser->flags & CHANUSERFLAG_OPPED)) + bot = client; + else { + bot = getBotForChannel(chan); + } + if(chanuserrow[3] == NULL && defaultrow == NULL) { + printf_mysql_query("SELECT `channel_getinvite` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + getinvite = atoi((chanuserrow[3] ? chanuserrow[3] : defaultrow[0])); + if(atoi(chanuserrow[0]) >= getinvite) { + putsock(bot, "INVITE %s %s", user->nick, chan->name); + } + } + } + } +} + +static TIMEQ_CALLBACK(neonserv_event_join_dynlimit) { + char *chanName = data; + struct ChanNode *chan = getChanByName(chanName); + free(chanName); + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `channel_dynlimit` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(row[0] && strcmp(row[0], "0")) { + putsock(client, "MODE %s +l %d", chan->name, chan->usercount + atoi(row[0])); + } +} diff --git a/src/modules/NeonServ.mod/event_neonserv_kick.c b/src/modules/NeonServ.mod/event_neonserv_kick.c new file mode 100644 index 0000000..8e32d02 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_kick.c @@ -0,0 +1,99 @@ +/* event_neonserv_kick.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonserv_event_kick_cache { + struct ClientSocket *client; + struct UserNode *user; + struct UserNode *target; + struct ChanNode *chan; + int userauth_pending; +}; + +static USERAUTH_CALLBACK(neonserv_event_kick_nick_lookup); +static void neonserv_event_kick_async1(struct neonserv_event_kick_cache *cache); +static void neonserv_event_kick_async2(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, struct ChanNode *chan); + +static void neonserv_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { + struct ChanNode *chan = target->chan; + struct ClientSocket *client; + if(isBot(target->user)) { + client = getChannelBot(chan, 0); + struct ClientSocket *bot = client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->user == target->user) { + break; + } + } + if(!client) return; + if(bot && bot != client && (isModeSet(chan->modes, 'i') || isModeSet(chan->modes, 'a') || isModeSet(chan->modes, 'l'))) { + struct ChanUser *chanuser = getChanUser(bot->user, chan); + if(chanuser && chanuser->flags & CHANUSERFLAG_OPPED) + putsock(bot, "INVITE %s %s", target->user->nick, chan->name); + } + char *key = ""; + if(isModeSet(chan->modes, 'k')) { + key = getModeValue(chan->modes, 'k'); + } + putsock(client, "JOIN %s %s", chan->name, key); + return; + } + client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(isNetworkService(user)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + struct neonserv_event_kick_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->user = user; + cache->target = target->user; + cache->chan = target->chan; + cache->userauth_pending = 0; + if(!(user->flags & USERFLAG_ISAUTHED)) { + get_userauth(user, neonserv_event_kick_nick_lookup, cache); + cache->userauth_pending++; + } + if(!(target->user->flags & USERFLAG_ISAUTHED)) { + get_userauth(target->user, neonserv_event_kick_nick_lookup, cache); + cache->userauth_pending++; + } + neonserv_event_kick_async1(cache); +} + +static USERAUTH_CALLBACK(neonserv_event_kick_nick_lookup) { + struct neonserv_event_kick_cache *cache = data; + cache->userauth_pending--; + neonserv_event_kick_async1(cache); +} + +static void neonserv_event_kick_async1(struct neonserv_event_kick_cache *cache) { + if(cache->userauth_pending == 0) { + neonserv_event_kick_async2(cache->client, cache->user, cache->target, cache->chan); + free(cache); + } +} + +static void neonserv_event_kick_async2(struct ClientSocket *client, struct UserNode *user, struct UserNode *target, struct ChanNode *chan) { + if(isUserProtected(chan, target, user)) { + char buf[MAXLEN]; + putsock(client, "KICK %s %s :%s", chan->name, user->nick, build_language_string(user, buf, "NS_USER_PROTECTED", target->nick)); + putsock(client, "INVITE %s %s", target->nick, chan->name); + } +} diff --git a/src/modules/NeonServ.mod/event_neonserv_mode.c b/src/modules/NeonServ.mod/event_neonserv_mode.c new file mode 100644 index 0000000..f0794a9 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_mode.c @@ -0,0 +1,337 @@ +/* event_neonserv_mode.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static USERLIST_CALLBACK(neonserv_event_mode_userlist_lookup); +static void neonserv_event_mode_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc); +static int neonserv_cmd_mode_botwar_detect(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int *botwar_detect_executed); + +struct neonserv_event_mode_cache { + struct ClientSocket *client; + struct UserNode *user; + char *modes; + char **argv; + int argc; +}; + +static void neonserv_event_mode(struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc) { + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(isNetworkService(user)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + struct neonserv_event_mode_cache *cache = malloc(sizeof(*cache)); + char **temp_argv = NULL; + if(argc) + temp_argv = malloc(argc*sizeof(*temp_argv)); + if (!cache || (argc && !temp_argv)) { + perror("malloc() failed"); + return; + } + if(argc) { + int i; + for(i = 0; i < argc; i++) { + temp_argv[i] = strdup(argv[i]); + } + } + cache->client = client; + cache->user = user; + cache->modes = strdup(modes); + cache->argv = temp_argv; + cache->argc = argc; + get_userlist_with_invisible(chan, neonserv_event_mode_userlist_lookup, cache); +} + +static USERLIST_CALLBACK(neonserv_event_mode_userlist_lookup) { + struct neonserv_event_mode_cache *cache = data; + neonserv_event_mode_async1(cache->client, cache->user, chan, cache->modes, cache->argv, cache->argc); + if(cache->argc) { + int i; + for(i = 0; i < cache->argc; i++) { + free(cache->argv[i]); + } + free(cache->argv); + } + free(cache->modes); + free(cache); +} + +static void neonserv_event_mode_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *modes, char **argv, int argc) { + struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); + int botwar_detect_executed = 0; + MYSQL_ROW row, defaults = NULL; + int i, arg, add = 1, skip = 0; + unsigned int modetype; + int db_canop, db_canhalfop, db_canvoice, db_canban, db_enfmodes, db_getop, db_gethalfop, db_getvoice; + struct ModeNode *modelock = createModeNode(NULL); + struct ModeBuffer *modeBuf; + struct UserNode *cuser; + struct ChanUser *chanuser; + int with_halfops = get_int_field("General.have_halfop"); + modeBuf = initModeBuffer(client, chan); + printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes`, `channel_getop`, `channel_getvoice`, `channel_gethalfop`, `channel_canhalfop` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + row = mysql_fetch_row(mysql_use()); + if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL || row[4] == NULL || row[5] == NULL || row[6] == NULL || (row[7] == NULL && with_halfops) || (row[8] == NULL && with_halfops)) { + printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes`, `channel_getop`, `channel_getvoice`, `channel_gethalfop`, `channel_canhalfop` FROM `channels` WHERE `channel_name` = 'defaults'"); + defaults = mysql_fetch_row(mysql_use()); + } + db_canop = atoi((row[0] ? row[0] : defaults[0])); + db_canvoice = atoi((row[1] ? row[1] : defaults[1])); + db_canban = atoi((row[2] ? row[2] : defaults[2])); + db_enfmodes = atoi((row[3] ? row[3] : defaults[3])); + db_getop = atoi((row[5] ? row[5] : defaults[5])); + db_getvoice = atoi((row[6] ? row[6] : defaults[6])); + db_gethalfop = (with_halfops ? atoi((row[7] ? row[7] : defaults[7])) : 0); + db_canhalfop = (with_halfops ? atoi((row[8] ? row[8] : defaults[8])) : 0); + if(row[4]) + parseModeString(modelock, row[4]); + else if(defaults[4]) + parseModeString(modelock, defaults[4]); + int uaccess = getChannelAccess(user, chan); + int caccess; + char *carg; + int sent_modes_locked = 0; + char deop_user = 0; + char tmp[MAXLEN]; + arg = 0; + for(i = 0; i < strlen(modes); i++) { + switch(modes[i]) { + case '+': + add = 1; + break; + case '-': + add = 0; + break; + case 'o': + case 'h': + case 'v': + if(arg == argc) { + break; + } + carg = argv[arg++]; + cuser = searchUserByNick(carg); + if(!cuser) { + break; //internal Bot error - this should never happen + } + caccess = getChannelAccess(cuser, chan); + if(modes[i] == 'o' && !add && cuser == client->user) { + //someone deopped the bot??? + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + requestOp(client->user, chan); + } + if((modes[i] == 'o' || (modes[i] == 'h' && !with_halfops)) && !(add && isBot(cuser))) { + if(uaccess < db_canop) { + reply(textclient, user, "NS_MODE_ENFOPS", chan->name); + db_canop = -1; + if(uaccess < db_getop) + deop_user = 1; + } + if(db_canop == -1 && caccess < db_getop) { + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + break; + } + } else if(modes[i] == 'h' && with_halfops && !(add && isBot(cuser))) { + if(uaccess < db_canhalfop) { + reply(textclient, user, "NS_MODE_ENFOPS", chan->name); + db_canhalfop = -1; + if(uaccess < db_gethalfop) + deop_user = 1; + } + if(db_canhalfop == -1 && caccess < db_gethalfop) { + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + break; + } + } else if(modes[i] == 'v' && !(add && isBot(cuser))) { + if(uaccess < db_canvoice) { + reply(textclient, user, "NS_MODE_ENFVOICE", chan->name); + db_canvoice = -1; + if(uaccess < db_getop) + deop_user = 1; + } + if(db_canvoice == -1 && caccess < db_getvoice) { + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + break; + } + } + if(!add) { + //check protection + if(isBot(cuser)) { + //don't send this - just try to reop + //reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick); + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + break; + } + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + if(uaccess < db_getop) + deop_user = 1; + break; + } + } + break; + case 'b': + if(arg == argc) { + break; + } + carg = argv[arg++]; + if(uaccess < db_canban) { + reply(textclient, user, "NS_MODE_CANBAN", chan->name); + db_canban = -1; + } + if(db_canban == -1) { + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + if(uaccess < db_getop) + deop_user = 1; + break; + } + char hostmask_buffer[NICKLEN+USERLEN+HOSTLEN+3]; + char usermask[NICKLEN+USERLEN+HOSTLEN+3]; + int match_count = 0; + carg = make_banmask(carg, hostmask_buffer); + if(add) { + for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) { + cuser = chanuser->user; + sprintf(usermask, "%s!%s@%s", cuser->nick, cuser->ident, cuser->host); + if(!match(carg, usermask)) { + if(isUserProtected(chan, cuser, user)) { + reply(textclient, user, "NS_USER_PROTECTED", cuser->nick); + skip = 1; + break; + } + match_count++; + } + } + if(match_count > 4 && (match_count * 3) > chan->usercount) { + reply(textclient, user, "NS_LAME_MASK_WARNING", carg, match_count); + } + } + if(skip) { + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + if(uaccess < db_getop) + deop_user = 1; + } + break; + default: + modetype = getModeType(modelock, modes[i]); + if(modetype == 0) { + break; //unknown mode + } + + if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) { + if(arg == argc) { + break; + } + carg = argv[arg++]; + if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modes[i])) { + char *modelock_val = getModeValue(modelock, modes[i]); + if(stricmp(carg, modelock_val) && uaccess < db_enfmodes && !isGodMode(user)) { + if(!sent_modes_locked) { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + sent_modes_locked = 1; + if(uaccess < db_getop) + deop_user = 1; + } + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, add, modes[i], modelock_val); + break; + } + } + if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modes[i])) { + int *modelock_val = getModeValue(modelock, modes[i]); + if(atoi(carg) != *modelock_val && uaccess < db_enfmodes && !isGodMode(user)) { + if(!sent_modes_locked) { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + sent_modes_locked = 1; + if(uaccess < db_getop) + deop_user = 1; + } + sprintf(tmp, "%d", *modelock_val); + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, add, modes[i], tmp); + break; + } + } + } else if(!add && (modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_B) { + if(arg == argc) { + break; + } + carg = argv[arg++]; + } else + carg = NULL; + if(isModeAffected(modelock, modes[i]) && add == !isModeSet(modelock, modes[i]) && uaccess < db_enfmodes && !isGodMode(user)) { + if(!sent_modes_locked) { + getFullModeString(modelock, tmp); + reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name); + sent_modes_locked = 1; + if(uaccess < db_getop) + deop_user = 1; + } + if(!neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) + modeBufferSet(modeBuf, !add, modes[i], carg); + break; + } + break; + } + } + if(deop_user && !neonserv_cmd_mode_botwar_detect(client, user, chan, &botwar_detect_executed)) { + modeBufferDeop(modeBuf, user->nick); + } + freeModeBuffer(modeBuf); + freeModeNode(modelock); +} + +static int neonserv_cmd_mode_botwar_detect(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, int *botwar_detect_executed) { + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) return 0; //flying super cow? + if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) { + chanuser->changeTime = time(0); + chanuser->chageEvents = 1; + } else { + if(!*botwar_detect_executed) + chanuser->chageEvents++; + *botwar_detect_executed = 1; + if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) { + //BOTWAR! + chanuser->changeTime = time(0); + if(chanuser->chageEvents > 0) { + char *alertchan = get_string_field("General.alertchan"); + putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (alertchan ? get_language_string(user, "NS_BOTWAR_REPORTED") : "")); + if(alertchan) { + struct ChanNode *alertchan_chan = getChanByName(alertchan); + struct ClientSocket *alertclient; + if(alertchan_chan && (alertclient = getBotForChannel(chan)) != NULL) { + char msgBuf[MAXLEN]; + putsock(alertclient, "PRIVMSG %s :%s", alertchan_chan->name, build_language_string(NULL, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick)); + } + } + } + chanuser->chageEvents = -2; + return 1; + } + } + return 0; +} + diff --git a/src/modules/NeonServ.mod/event_neonserv_notice.c b/src/modules/NeonServ.mod/event_neonserv_notice.c new file mode 100644 index 0000000..84fb51a --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_notice.c @@ -0,0 +1,107 @@ +/* event_neonserv_notice.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonserv_event_notice_cache { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + char *message; +}; + +static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup); +static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message); + +static void neonserv_event_channotice(struct UserNode *user, struct ChanNode *chan, char *message) { + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(isNetworkService(user)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_event_notice_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->user = user; + cache->chan = chan; + cache->message = strdup(message); + get_userauth(user, neonserv_event_notice_nick_lookup, cache); + } else + neonserv_event_notice_async1(client, user, chan, message); +} + +static USERAUTH_CALLBACK(neonserv_event_notice_nick_lookup) { + struct neonserv_event_notice_cache *cache = data; + if(user) { + neonserv_event_notice_async1(cache->client, cache->user, cache->chan, cache->message); + } + free(cache->message); + free(cache); +} + +static void neonserv_event_notice_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, char *message) { + MYSQL_RES *res; + MYSQL_ROW row, defaultrow = NULL, chanuser; + int uaccess = 0; + printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_ctcp`, `channel_ctcpreaction` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + int noticeaccess = atoi((row[0] ? row[0] : defaultrow[0])); + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuser = mysql_fetch_row(res); + if(chanuser) + uaccess = ((atoi(chanuser[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuser[0])); + } + int duration = 0; + char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; + char *banmask = NULL; + char *reason = "disallowed channel NOTICE"; + if(uaccess < noticeaccess) { + switch(atoi((row[1] ? row[1] : defaultrow[1]))) { + case 2: //TIMEBAN: 3min + duration = 180; + case 3: //TIMEBAN: 1h + if(!duration) + duration = 3600; + banmask = generate_banmask(user, banmaskBuf); + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chan->channel_id, escape_string(banmask), (unsigned long) (time(0) + duration), 0, escape_string(reason)); + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); + case 1: //KICKBAN + if(!banmask) + banmask = generate_banmask(user, banmaskBuf); + putsock(client, "MODE %s +b %s", chan->name, banmask); + case 0: //KICK + putsock(client, "KICK %s %s :%s", chan->name, user->nick, reason); + break; + } + } +} + diff --git a/src/modules/NeonServ.mod/event_neonserv_part.c b/src/modules/NeonServ.mod/event_neonserv_part.c new file mode 100644 index 0000000..e41436c --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_part.c @@ -0,0 +1,31 @@ +/* event_neonserv_part.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static void neonserv_event_part(struct ChanUser *chanuser, char *reason) { + struct ChanNode *chan = chanuser->chan; + struct UserNode *user = chanuser->user; + MYSQL_RES *res; + MYSQL_ROW chanuserrow; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + if((chanuserrow = mysql_fetch_row(res)) != NULL) + printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]); + } +} diff --git a/src/modules/NeonServ.mod/event_neonserv_quit.c b/src/modules/NeonServ.mod/event_neonserv_quit.c new file mode 100644 index 0000000..b2f0401 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_quit.c @@ -0,0 +1,30 @@ +/* event_neonserv_quit.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static void neonserv_event_quit(struct UserNode *user, char *reason) { + MYSQL_RES *res; + MYSQL_ROW chanuserrow; + struct ChanUser *chanuser; + if((user->flags & USERFLAG_ISAUTHED)) { + for(chanuser = getUserChannels(user, NULL); chanuser; chanuser = getUserChannels(user, chanuser)) { + printf_mysql_query("SELECT `chanuser_id` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` LEFT JOIN `channels` ON `chanuser_cid` = `channel_id` WHERE `channel_name` = '%s' AND `user_user` = '%s'", escape_string(chanuser->chan->name), escape_string(user->auth)); + res = mysql_use(); + if((chanuserrow = mysql_fetch_row(res)) != NULL) + printf_mysql_query("UPDATE `chanusers` SET `chanuser_seen` = UNIX_TIMESTAMP() WHERE `chanuser_id` = '%s'", chanuserrow[0]); + } + } +} diff --git a/src/modules/NeonServ.mod/event_neonserv_topic.c b/src/modules/NeonServ.mod/event_neonserv_topic.c new file mode 100644 index 0000000..577e0a3 --- /dev/null +++ b/src/modules/NeonServ.mod/event_neonserv_topic.c @@ -0,0 +1,114 @@ +/* event_neonserv_topic.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +struct neonserv_event_topic_cache { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + char *new_topic; +}; + +static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup); +static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic); + +static void neonserv_event_topic(struct UserNode *user, struct ChanNode *chan, const char *new_topic) { + struct ClientSocket *client = getBotForChannel(chan); + if(!client) return; //we can't "see" this event + if(isNetworkService(user)) return; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) return; + if(!(user->flags & USERFLAG_ISAUTHED)) { + struct neonserv_event_topic_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->user = user; + cache->chan = chan; + cache->new_topic = strdup(new_topic); + get_userauth(user, neonserv_event_topic_nick_lookup, cache); + } else + neonserv_event_topic_async1(client, user, chan, new_topic); +} + +static USERAUTH_CALLBACK(neonserv_event_topic_nick_lookup) { + struct neonserv_event_topic_cache *cache = data; + if(user) { + neonserv_event_topic_async1(cache->client, cache->user, cache->chan, cache->new_topic); + } + free(cache->new_topic); + free(cache); +} + +static void neonserv_event_topic_async1(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, const char *new_topic) { + MYSQL_RES *res; + MYSQL_ROW row, defaultrow = NULL, chanuserrow; + int uaccess = 0; + printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) return; + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_changetopic`, `channel_topicsnarf` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaultrow = mysql_fetch_row(res); + } + int changetopic = atoi((row[0] ? row[0] : defaultrow[0])); + int topicsnarf = atoi((row[1] ? row[1] : defaultrow[1])); + if((user->flags & USERFLAG_ISAUTHED)) { + printf_mysql_query("SELECT `chanuser_access`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' AND `user_user` = '%s'", chan->channel_id, escape_string(user->auth)); + res = mysql_use(); + chanuserrow = mysql_fetch_row(res); + if(chanuserrow) + uaccess = ((atoi(chanuserrow[1]) & DB_CHANUSER_SUSPENDED) ? 0 : atoi(chanuserrow[0])); + } + if(uaccess < changetopic) { + //undo topic change + struct ClientSocket *textclient = ((client->flags & SOCKET_FLAG_PREFERRED) ? client : get_prefered_bot(client->botid)); + struct ChanUser *chanuser = getChanUser(user, chan); + if(!chanuser) return; //flying super cow? + if(time(0) - chanuser->changeTime > BOTWAR_DETECTION_TIME) { + chanuser->changeTime = time(0); + chanuser->chageEvents = 1; + } else { + chanuser->chageEvents++; + if(chanuser->chageEvents >= BOTWAR_DETECTION_EVENTS || chanuser->chageEvents < 0) { + //BOTWAR! + chanuser->changeTime = time(0); + if(chanuser->chageEvents > 0) { + char *alertchan = get_string_field("General.alertchan"); + putsock(client, "NOTICE @%s :%s %s", chan->name, get_language_string(user, "NS_BOTWAR_DETECTED"), (alertchan ? get_language_string(user, "NS_BOTWAR_REPORTED") : "")); + if(alertchan) { + struct ChanNode *alertchan_chan = getChanByName(alertchan); + struct ClientSocket *alertclient; + if(alertchan_chan && (alertclient = getBotForChannel(chan)) != NULL) { + char msgBuf[MAXLEN]; + putsock(alertclient, "PRIVMSG %s :%s", alertchan_chan->name, build_language_string(NULL, msgBuf, "NS_BOTWAR_ALERT", chan->name, user->nick)); + } + } + } + chanuser->chageEvents = -2; + return; + } + } + reply(textclient, user, "NS_TOPIC_ACCESS", chan->name); + putsock(client, "TOPIC %s :%s", chan->name, chan->topic); + } else if(uaccess >= topicsnarf) { + printf_mysql_query("UPDATE `channels` SET `channel_defaulttopic` = '%s' WHERE `channel_id` = '%d'", escape_string(new_topic), chan->channel_id); + } +} + diff --git a/src/modules/NeonServ.mod/module.c b/src/modules/NeonServ.mod/module.c new file mode 100644 index 0000000..fff4b4b --- /dev/null +++ b/src/modules/NeonServ.mod/module.c @@ -0,0 +1,38 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "bot_NeonServ.h" +#include "cmd_neonserv.h" + +static int module_initialize() { + register_commands(); + return 0; +} + +static void module_start(int type) { + init_NeonServ(type); +} + +static void module_loop() { + loop_NeonServ(); +} + +static void module_stop(int type) { + free_NeonServ(type); +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/NeonSpam.mod/bot_NeonSpam.c b/src/modules/NeonSpam.mod/bot_NeonSpam.c new file mode 100644 index 0000000..5784f63 --- /dev/null +++ b/src/modules/NeonSpam.mod/bot_NeonSpam.c @@ -0,0 +1,367 @@ +/* bot_NeonSpam.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" + +#include "bot_NeonSpam.h" +#include "modcmd.h" +#include "IRCParser.h" +#include "IRCEvents.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "ModeNode.h" +#include "BanNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "version.h" +#include "EventLogger.h" +#include "bots.h" +#include "cmd_neonserv.h" +#include "cmd_neonspam.h" + +#define BOTID 2 +#define BOTALIAS "NeonSpam" + +static const struct default_language_entry msgtab[] = { + {"SS_SET_PERCENT", "%u is an invalid percent value (valid: 0-100)"}, /* {ARGS: 120} */ + {"SS_SET_SENSIBILITY", "%s is an invalid sensibility format. (valid: amount:time e.g. 5:10)"}, /* {ARGS: "möp"} */ + {"SS_SET_SENSIBILITY_AMOUNT", "%d is an invalid amount value. (valid: %d-%d)"}, /* {ARGS: 120, 1, 5} */ + {"SS_SET_SENSIBILITY_TIME", "%d is an invalid time value. (valid: %d-%d)"}, /* {ARGS: 300, 15, 180} */ + {"SS_SET_SPAMLIMIT", "%d is an invalid spamlimit value. (valid: %d-%d)"}, /* {ARGS: 120, 2, 8} */ + {"SS_SET_OPTION_SpamReaction_0", "Kick"}, + {"SS_SET_OPTION_SpamReaction_1", "KickBan"}, + {"SS_SET_OPTION_SpamReaction_2", "Timed Ban"}, + {"SS_SET_OPTION_FloodReaction_0", "Kick"}, + {"SS_SET_OPTION_FloodReaction_1", "KickBan"}, + {"SS_SET_OPTION_FloodReaction_2", "Timed Ban"}, + {"SS_SET_OPTION_JoinReaction_0", "Kick"}, + {"SS_SET_OPTION_JoinReaction_1", "KickBan"}, + {"SS_SET_OPTION_JoinReaction_2", "Timed Ban"}, + {"SS_SET_OPTION_CapsReaction_0", "Kick"}, + {"SS_SET_OPTION_CapsReaction_1", "KickBan"}, + {"SS_SET_OPTION_CapsReaction_2", "Timed Ban"}, + {"SS_SET_OPTION_DigitReaction_0", "Kick"}, + {"SS_SET_OPTION_DigitReaction_1", "KickBan"}, + {"SS_SET_OPTION_DigitReaction_2", "Timed Ban"}, + {NULL, NULL} +}; + +static unsigned int convertNeonSpamSettingsToFlags(char *str); +static void createSpamNode(struct ChanUser *chanuser); +static void freeJoinNode(struct NeonSpamJoinNode *joinnode); +static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser); + +#define SPAMSERV_CHECK_IGNORE 0 +#define SPAMSERV_CHECK_WARN 1 +#define SPAMSERV_CHECK_PUNISH 2 +#define SPAMSERV_CHECK_DEAD 3 /* scanner has already killed the user */ + +#define SPAMSERV_MSG_SPAM "Spamming" +#define SPAMSERV_MSG_FLOOD "Flooding the channel/network" +#define SPAMSERV_MSG_ADV "Advertising" +#define SPAMSERV_MSG_JOINFLOOD "Join flooding the channel" +#define SPAMSERV_MSG_WARNING "%s is against the channel rules" +#define SPAMSERV_MSG_BOTNET "BotNet detected." +#define SPAMSERV_MSG_CAPS "Using too many chars in UPPER CASE" +#define SPAMSERV_MSG_DIGIT "Using too many numeric chars" + +//EVENTS +#include "event_neonspam_join.c" +#include "event_neonspam_chanmsg.c" + +static void neonspam_event_kick(struct UserNode *user, struct ChanUser *target, char *reason) { + struct ChanNode *chan = target->chan; + if(isBot(target->user)) { + struct ClientSocket *client = getChannelBot(chan, 0); + struct ClientSocket *bot = client; + for(client = getBots(SOCKET_FLAG_READY, NULL); client; client = getBots(SOCKET_FLAG_READY, client)) { + if(client->user == target->user) { + break; + } + } + if(!client) return; + if(bot && bot != client && (isModeSet(chan->modes, 'i') || isModeSet(chan->modes, 'a') || isModeSet(chan->modes, 'l'))) { + struct ChanUser *chanuser = getChanUser(bot->user, chan); + if(chanuser && chanuser->flags & CHANUSERFLAG_OPPED) + putsock(bot, "INVITE %s %s", target->user->nick, chan->name); + } + char *key = ""; + if(isModeSet(chan->modes, 'k')) { + key = getModeValue(chan->modes, 'k'); + } + putsock(client, "JOIN %s %s", chan->name, key); + return; + } +} + +static void neonspam_bot_ready(struct ClientSocket *client) { + MYSQL_RES *res; + MYSQL_ROW row; + + printf_mysql_query("SELECT `automodes` FROM `bots` WHERE `id` = '%d'", client->clientid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "MODE %s +%s", client->user->nick, row[0]); + } + + printf_mysql_query("SELECT `channel_name`, `channel_key` FROM `bot_channels` LEFT JOIN `channels` ON `chanid` = `channel_id` WHERE `botid` = '%d' AND `suspended` = '0'", client->clientid); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + putsock(client, "JOIN %s %s", row[0], row[1]); + } +} + +static void neonspam_trigger_callback(int clientid, struct ChanNode *chan, char *trigger) { + MYSQL_RES *res; + MYSQL_ROW row; + loadChannelSettings(chan); + if(!(chan->flags & CHANFLAG_CHAN_REGISTERED)) { + strcpy(trigger, "~"); + return; + } + printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chan->channel_id, BOTID); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + strcpy(trigger, "~"); + return; + } + if(row[0] && *row[0]) + strcpy(trigger, row[0]); + else + strcpy(trigger, ((row[1] && *row[1]) ? row[1] : "~")); +} + +static void start_bots(int type) { + struct ClientSocket *client; + MYSQL_RES *res, *res2; + MYSQL_ROW row; + + if(type == MODSTATE_STARTSTOP) { + printf_mysql_query("SELECT `nick`, `ident`, `realname`, `server`, `port`, `pass`, `textbot`, `id`, `queue`, `ssl`, `bind` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1'", BOTID); + res = mysql_use(); + + while ((row = mysql_fetch_row(res)) != NULL) { + client = create_socket(row[3], atoi(row[4]), row[10], row[5], row[0], row[1], row[2]); + client->flags |= (strcmp(row[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(row[8], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(row[9], "0") ? SOCKET_FLAG_SSL : 0); + client->botid = BOTID; + client->clientid = atoi(row[7]); + connect_socket(client); + } + } + + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access`, `flags` FROM `bot_binds` WHERE `botclass` = '%d'", BOTID); + res2 = mysql_use(); + while ((row = mysql_fetch_row(res2)) != NULL) { + if(bind_cmd_to_command(BOTID, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_set_parameters(BOTID, row[0], row[2]); + } + if(row[3]) { + bind_set_global_access(BOTID, row[0], atoi(row[3])); + } + if(row[4]) { + bind_set_channel_access(BOTID, row[0], row[4]); + } + if(strcmp(row[5], "0")) + bind_set_bind_flags(BOTID, row[0], atoi(row[5])); + } + } + bind_unbound_required_functions(BOTID); +} + +char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer) { + int pos = 0; + unsigned int i; + int j = 0; + char *chars = SPAMSETTINGS_CHARS; + for(i = 1; i <= SPAMSETTINGS_FLAGS; i = i << 1) { + if(flags & i) + buffer[pos++] = chars[j]; + j++; + } + buffer[pos] = '\0'; + return buffer; +} + +static unsigned int convertNeonSpamSettingsToFlags(char *str) { + unsigned int i = 1, flags = 0; + int j = 0; + char *chars = SPAMSETTINGS_CHARS; + while(*str) { + for(; i <= SPAMSETTINGS_FLAGS; i = i << 1) { + if(*str == chars[j]) { + flags |= i; + j++; + i = i << 1; + break; + } + j++; + } + str++; + } + return flags; +} + +int loadNeonSpamSettings(struct ChanNode *chan) { + if(chan->spam_settings) return 0; + struct NeonSpamSettings *settings = malloc(sizeof(*settings)); + if(!settings) { + perror("malloc() failed"); + return 0; + } + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + loadChannelSettings(chan); + printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1] || !row[2] || !row[3] || !row[4] || !row[5] || !row[6] || !row[7] || !row[8] || !row[9] || !row[10] || !row[11] || !row[12]) { + printf_mysql_query("SELECT `channel_scanner`, `channel_spam_limit`, `channel_spam_except`, `channel_flood_limit`, `channel_flood_time`, `channel_flood_except`, `channel_join_limit`, `channel_join_time`, `channel_join_except`, `channel_caps_percent`, `channel_caps_except`, `channel_digit_percent`, `channel_digit_except` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + settings->flags = convertNeonSpamSettingsToFlags(row[0] ? row[0] : defaults[0]); + settings->spam_amount = atoi(row[1] ? row[1] : defaults[1]); + settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] = atoi(row[2] ? row[2] : defaults[2]); + settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[3] ? row[3] : defaults[3]); + settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX] = atoi(row[4] ? row[4] : defaults[4]); + settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] = atoi(row[5] ? row[5] : defaults[5]); + settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX] = atoi(row[6] ? row[6] : defaults[6]); + settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX] = atoi(row[7] ? row[7] : defaults[7]); + settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] = atoi(row[8] ? row[8] : defaults[8]); + settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX] = atoi(row[9] ? row[9] : defaults[9]); + settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] = atoi(row[10] ? row[10] : defaults[10]); + settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX] = atoi(row[11] ? row[11] : defaults[11]); + settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] = atoi(row[12] ? row[12] : defaults[12]); + settings->join_nodes = NULL; + settings->lastmsg_time = 0; + int i; + for(i = 0; i < BOTNETSCAN_USERS; i++) + settings->botnicks[i] = NULL; + chan->spam_settings = settings; + return 1; +} + +void freeNeonSpamSettings(struct NeonSpamSettings *settings) { + struct NeonSpamJoinNode *joinnode, *nextjoinnode; + for(joinnode = settings->join_nodes; joinnode; joinnode = nextjoinnode) { + nextjoinnode = joinnode->next; + freeJoinNode(joinnode); + } + free(settings); +} + +static void freeJoinNode(struct NeonSpamJoinNode *joinnode) { + free(joinnode->ident); + free(joinnode->host); + free(joinnode); +} + +static struct NeonSpamJoinNode *getNeonSpamJoinNode(struct ChanUser *chanuser) { + struct NeonSpamJoinNode *joinnode, *prevjoinnode = NULL, *nextjoinnode, *result = NULL; + for(joinnode = chanuser->chan->spam_settings->join_nodes; joinnode; joinnode = nextjoinnode) { + nextjoinnode = joinnode->next; + if(!stricmp(joinnode->ident, chanuser->user->ident) && !stricmp(joinnode->host, chanuser->user->host)) { + prevjoinnode = joinnode; + result = joinnode; + } else if(time(0) - joinnode->last_penalty_update > MAX_JOIN_TIME) { + freeJoinNode(joinnode); + if(prevjoinnode) + prevjoinnode->next = nextjoinnode; + else + chanuser->chan->spam_settings->join_nodes = nextjoinnode; + } else + prevjoinnode = joinnode; + } + if(result) + return result; + joinnode = malloc(sizeof(*joinnode)); + if(!joinnode) { + perror("malloc() failed"); + return NULL; + } + joinnode->ident = strdup(chanuser->user->ident); + joinnode->host = strdup(chanuser->user->host); + joinnode->last_penalty_update = time(0); + joinnode->joinpenalty = 0; + joinnode->next = chanuser->chan->spam_settings->join_nodes; + chanuser->chan->spam_settings->join_nodes = joinnode; + return joinnode; +} + +static void createSpamNode(struct ChanUser *chanuser) { + struct NeonSpamNode *spamnode = malloc(sizeof(*spamnode)); + if(!spamnode) { + perror("malloc() failed"); + return; + } + spamnode->lastmsg = 0; + spamnode->spamcount = 0; + spamnode->floodpenalty = 0; + spamnode->last_penalty_update = time(0); + chanuser->spamnode = spamnode; +} + +void init_NeonSpam(int type) { + + set_bot_alias(BOTID, BOTALIAS); + start_bots(type); + + if(type == MODSTATE_REBIND) return; + + //register events + bind_bot_ready(neonspam_bot_ready); + bind_join(neonspam_event_join); + bind_chanmsg(neonspam_event_chanmsg); + bind_privctcp(general_event_privctcp); + bind_kick(neonspam_event_kick); + + set_trigger_callback(BOTID, neonspam_trigger_callback); + + register_default_language_table(msgtab); +} + +void loop_NeonSpam() { + +} + +void free_NeonSpam(int type) { + unbind_allcmd(BOTID); + if(type == MODSTATE_STARTSTOP) { + //disconnect all our bots + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->botid == BOTID) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } +} + +#undef BOTID +#undef BOTALIAS diff --git a/src/modules/NeonSpam.mod/bot_NeonSpam.h b/src/modules/NeonSpam.mod/bot_NeonSpam.h new file mode 100644 index 0000000..34a24b5 --- /dev/null +++ b/src/modules/NeonSpam.mod/bot_NeonSpam.h @@ -0,0 +1,150 @@ +/* bot_NeonSpam.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _bot_NeonSpam_h +#define _bot_NeonSpam_h + +#include "main.h" + +struct ChanNode; + +//SPAMSCAN +#define SPAMSETTINGS_SPAMSCAN 0x000001 +#define SPAMSETTINGS_SPAMSCAN_OPS 0x000002 +#define SPAMSETTINGS_SPAMSCAN_VOICE 0x000004 +#define SPAMSETTINGS_SPAMCHARS "abc" +#define SPAMSETTINGS_SPAMEXCINDEX 0 + +//FLOODSCAN +#define SPAMSETTINGS_FLOODSCAN 0x000008 +#define SPAMSETTINGS_FLOODSCAN_OPS 0x000010 +#define SPAMSETTINGS_FLOODSCAN_VOICE 0x000020 +#define SPAMSETTINGS_FLOODCHARS "def" +#define SPAMSETTINGS_FLOODEXCINDEX 1 +#define SPAMSETTINGS_FLOODSENINDEX 0 + +//JOINSCAN +#define SPAMSETTINGS_JOINSCAN 0x000040 +#define SPAMSETTINGS_JOINSCAN_OPS 0x000080 +#define SPAMSETTINGS_JOINSCAN_VOICE 0x000100 +#define SPAMSETTINGS_JOINCHARS "ghi" +#define SPAMSETTINGS_JOINEXCINDEX 2 +#define SPAMSETTINGS_JOINSENINDEX 1 + +//BOTNET SCAN +#define SPAMSETTINGS_BOTNETSCAN 0x000200 +#define SPAMSETTINGS_BOTNETSCAN_OPS 0x000400 +#define SPAMSETTINGS_BOTNETSCAN_VOICE 0x000800 +#define SPAMSETTINGS_BOTNETSCAN_STRIPCC 0x001000 +#define SPAMSETTINGS_BOTNETCHARS "jklm" +#define SPAMSETTINGS_BOTNETEXCINDEX 3 + +//CAPSSCAN +#define SPAMSETTINGS_CAPSSCAN 0x002000 +#define SPAMSETTINGS_CAPSSCAN_OPS 0x004000 +#define SPAMSETTINGS_CAPSSCAN_VOICE 0x008000 +#define SPAMSETTINGS_CAPSCHARS "nop" +#define SPAMSETTINGS_CAPSEXCINDEX 4 +#define SPAMSETTINGS_CAPSPERCENTINDEX 0 + +//DIGITSCAN +#define SPAMSETTINGS_DIGITSCAN 0x010000 +#define SPAMSETTINGS_DIGITSCAN_OPS 0x020000 +#define SPAMSETTINGS_DIGITSCAN_VOICE 0x040000 +#define SPAMSETTINGS_DIGITCHARS "qrs" +#define SPAMSETTINGS_DIGITEXCINDEX 5 +#define SPAMSETTINGS_DIGITPERCENTINDEX 1 + + +#define SPAMSETTINGS_CHARS SPAMSETTINGS_SPAMCHARS SPAMSETTINGS_FLOODCHARS SPAMSETTINGS_JOINCHARS SPAMSETTINGS_BOTNETCHARS SPAMSETTINGS_CAPSCHARS SPAMSETTINGS_DIGITCHARS +#define SPAMSETTINGS_FLAGS 0x07ffff /* all flags that can be stored in the database */ +#define SPAMSETTINGS_EXCEPTINDEXES 6 +#define SPAMSETTINGS_SENSIBILITYINDEXES 2 +#define SPAMSETTINGS_PERCENTINDEXES 2 + +//SCRIPT FLAGS +#define SPAMSETTINGS_KICKEDBOTQUEUE 0x080000 +#define SPAMSETTINGS_ISTIMEBAN 0x100000 +#define SPAMSETTINGS_SETTIMEBAN 0x200000 + +#define MAX_FLOOD_AMOUNT 300 +#define MIN_FLOOD_AMOUNT 2 +#define MAX_FLOOD_TIME 200 + +#define MAX_JOIN_AMOUNT 300 +#define MIN_JOIN_AMOUNT 2 +#define MAX_JOIN_TIME 200 + +#define BOTNETSCAN_USERS 4 +#define BOTNETSCAN_TIME 2 + +struct NeonSpamSettings { + unsigned int flags; + unsigned char spam_amount; + unsigned char sensibility_amount[SPAMSETTINGS_SENSIBILITYINDEXES]; + unsigned char sensibility_time[SPAMSETTINGS_SENSIBILITYINDEXES]; + unsigned int exceptlevel[SPAMSETTINGS_EXCEPTINDEXES]; + unsigned char percent[SPAMSETTINGS_PERCENTINDEXES]; + + //joinflood + struct NeonSpamJoinNode *join_nodes; + + //botnet + unsigned long lastmsg; //crc32 hash + time_t lastmsg_time; + char *botnicks[BOTNETSCAN_USERS]; + + +}; +/* PENALTY SYSTEM +* user gets MAX_FLOOD_TIME points per message +* points get removed each loop +* pounts to be removed each second: +* MAX_FLOOD_TIME/flood_time +* +* the floodlimit is reached, if the penalty points +* are bigger than MAX_FLOOD_TIME * flood_amount +*/ + +#define NEONSPAMNODE_FLAG_CAPSSCAN_WARNED 0x01 +#define NEONSPAMNODE_FLAG_DIGITSCAN_WARNED 0x02 + +struct NeonSpamNode { + unsigned long lastmsg; //crc32 hash + unsigned char spamcount; + int floodpenalty; + time_t last_penalty_update; + unsigned char flags; +}; + +struct NeonSpamJoinNode { + char *ident; + char *host; + int joinpenalty; + time_t last_penalty_update; + struct NeonSpamJoinNode *next; +}; + +void init_NeonSpam(int type); +void loop_NeonSpam(); +void free_NeonSpam(int type); + +void freeNeonSpamSettings(struct NeonSpamSettings *settings); +char* convertNeonSpamSettingsToString(unsigned int flags, char *buffer); +int loadNeonSpamSettings(struct ChanNode *chan); + +#endif \ No newline at end of file diff --git a/src/modules/NeonSpam.mod/cmd_neonspam.c b/src/modules/NeonSpam.mod/cmd_neonspam.c new file mode 100644 index 0000000..f013299 --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam.c @@ -0,0 +1,32 @@ +/* cmd_neonspam.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" + +#include "cmd_neonspam.h" +#include "modcmd.h" +#include "ConfigParser.h" + +void register_commands() { + //NeonSpam Commands + register_command_alias(2, "NeonSpam"); + + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(2, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) + // NAME FUNCTION PARAMS PRIVS FLAGS + USER_COMMAND("set", neonspam_cmd_set, 0, "#channel_setters", CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_LOG); + #undef USER_COMMAND + +} \ No newline at end of file diff --git a/src/modules/NeonSpam.mod/cmd_neonspam.h b/src/modules/NeonSpam.mod/cmd_neonspam.h new file mode 100644 index 0000000..9989192 --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam.h @@ -0,0 +1,43 @@ +/* cmd_neonspam.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _cmd_neonspam_h +#define _cmd_neonspam_h +#include "main.h" +#include "modcmd.h" +#include "IRCParser.h" +#include "IRCEvents.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "ModeNode.h" +#include "BanNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "version.h" +#include "EventLogger.h" +#include "bots.h" +#include "bot_NeonSpam.h" + +CMD_BIND(neonspam_cmd_set); + +#endif \ No newline at end of file diff --git a/src/modules/NeonSpam.mod/cmd_neonspam_set.c b/src/modules/NeonSpam.mod/cmd_neonspam_set.c new file mode 100644 index 0000000..efaee45 --- /dev/null +++ b/src/modules/NeonSpam.mod/cmd_neonspam_set.c @@ -0,0 +1,655 @@ +/* cmd_neonspam_set.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_neonspam.h" + +typedef char* neonspam_cmd_set_function(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); +static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf); + +static MYSQL_ROW neonspam_settings_row, neonspam_settings_defaults; +#define SPAMSERV_SETTINGS_QUERY "`channel_spam_reaction`, `channel_spam_reaction_duration`, `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_join_reaction`, `channel_join_reaction_duration`, `channel_botnet_bantime`, `channel_caps_reaction`, `channel_caps_reaction_duration`, `channel_digit_reaction`, `channel_digit_reaction_duration`" +#define SPAMSERV_SETTINGS_RESET "\ +`channel_scanner` = NULL, \ +`channel_spam_limit` = NULL, \ +`channel_spam_reaction` = NULL, \ +`channel_spam_reaction_duration` = NULL, \ +`channel_spam_except` = NULL, \ +`channel_flood_limit` = NULL, \ +`channel_flood_time` = NULL, \ +`channel_flood_reaction` = NULL, \ +`channel_flood_reaction_duration` = NULL, \ +`channel_flood_except` = NULL, \ +`channel_join_limit` = NULL, \ +`channel_join_time` = NULL, \ +`channel_join_reaction` = NULL, \ +`channel_join_reaction_duration` = NULL, \ +`channel_join_except` = NULL, \ +`channel_botnet_bantime` = NULL, \ +`channel_botnet_except` = NULL, \ +`channel_caps_percent` = NULL, \ +`channel_caps_reaction` = NULL, \ +`channel_caps_reaction_duration` = NULL, \ +`channel_caps_except` = NULL,\ +`channel_digit_percent` = NULL, \ +`channel_digit_reaction` = NULL, \ +`channel_digit_reaction_duration` = NULL, \ +`channel_digit_except` = NULL " + +#define SET_HELP 0x0001 +#define SET_BOOL 0x0002 +#define SET_OPT 0x0004 + +#define SET_SCANOPS 0x0010 +#define SET_SCANVOICE 0x0020 +#define SET_SCANEXCEPT 0x0040 + +#define SET_OPT_MAX 0xff00 +#define SET_OPT_SHIFT 8 + +static const struct { + unsigned int if_flag; + unsigned int indent; + const char *setting; + void *function; + int intparam; + char *charparam; + int flags; +} neonspam_settings[] = { + {0, 0, "Trigger", neonspam_cmd_set_trigger, 0, NULL, SET_HELP}, + + {0, 0, "SpamScan", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_SPAMSCAN, 2, "SpamLimit", neonspam_cmd_set_spamlimit, 0, NULL, SET_HELP}, + {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "SpamReaction", neonspam_cmd_set_reaction, 0, "channel_spam_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_SPAMSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "SpamBanDuration", neonspam_cmd_set_reaction_time, 1, "channel_spam_reaction_duration", 0}, + {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_SPAMSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_SPAMSCAN, 2, "SpamScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_SPAMEXCINDEX, "channel_spam_except", SET_HELP | SET_SCANEXCEPT}, + + {0, 0, "FloodScan", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_FLOODSCAN, 2, "FloodSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_FLOODSENINDEX, "channel_flood_", SET_HELP}, + {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "FloodReaction", neonspam_cmd_set_reaction, 2, "channel_flood_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_FLOODSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "FloodBanDuration", neonspam_cmd_set_reaction_time, 3, "channel_flood_reaction_duration",0}, + {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_FLOODSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_FLOODSCAN, 2, "FloodScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_FLOODEXCINDEX, "channel_flood_except", SET_HELP | SET_SCANEXCEPT}, + + {0, 0, "JoinScan", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_JOINSCAN, 2, "JoinSensibility", neonspam_cmd_setsensibility, SPAMSETTINGS_JOINSENINDEX, "channel_join_", SET_HELP}, + {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "JoinReaction", neonspam_cmd_set_reaction, 4, "channel_join_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_JOINSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "JoinBanDuration", neonspam_cmd_set_reaction_time, 5, "channel_join_reaction_duration", 0}, + {SPAMSETTINGS_JOINSCAN, 2, "JoinScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_JOINSCAN, 2, "JoinScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_JOINSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_JOINSCAN, 2, "JoinScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_JOINEXCINDEX, "channel_join_except", SET_HELP | SET_SCANEXCEPT}, + + {0, 0, "BotNetScan", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_BOTNETSCAN, 4, "BotNetBanDuration", neonspam_cmd_set_reaction_time, 6, "channel_botnet_bantime", 0}, + {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_BOTNETSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + //{SPAMSETTINGS_BOTNETSCAN, 2, "BotNetScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_BOTNETEXCINDEX, "channel_botnet_except", SET_HELP}, + + {0, 0, "CapsScan", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_CAPSSCAN, 2, "CapsPercent", neonspam_cmd_setpercent, SPAMSETTINGS_CAPSPERCENTINDEX, "channel_caps_percent", SET_HELP}, + {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "CapsReaction", neonspam_cmd_set_reaction, 7, "channel_caps_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_CAPSSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "CapsBanDuration", neonspam_cmd_set_reaction_time, 8, "channel_caps_reaction_duration", 0}, + {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_CAPSSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_CAPSSCAN, 2, "CapsScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_CAPSEXCINDEX, "channel_caps_except", SET_HELP | SET_SCANEXCEPT}, + + {0, 0, "DigitScan", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN, NULL, SET_BOOL}, + {SPAMSETTINGS_DIGITSCAN, 2, "DigitPercent", neonspam_cmd_setpercent, SPAMSETTINGS_DIGITPERCENTINDEX, "channel_digit_percent", SET_HELP}, + {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_SETTIMEBAN, 2, "DigitReaction", neonspam_cmd_set_reaction, 9, "channel_digit_reaction", SET_OPT | (3 << SET_OPT_SHIFT)}, + {SPAMSETTINGS_DIGITSCAN | SPAMSETTINGS_ISTIMEBAN, 4, "DigitBanDuration", neonspam_cmd_set_reaction_time, 10, "channel_digit_reaction_duration", 0}, + {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanChanOps", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_OPS, NULL, SET_BOOL | SET_SCANOPS}, + {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanVoiced", neonspam_cmd_setflags, SPAMSETTINGS_DIGITSCAN_VOICE, NULL, SET_BOOL | SET_SCANVOICE}, + {SPAMSETTINGS_DIGITSCAN, 2, "DigitScanExcept", neonspam_cmd_setexcept, SPAMSETTINGS_DIGITEXCINDEX, "channel_digit_except", SET_HELP | SET_SCANEXCEPT}, + + {0, 0, "GlobalScanChanOps", neonspam_cmd_setscanops, 0, NULL, SET_BOOL}, + {0, 0, "GlobalScanVoice", neonspam_cmd_setscanvoice, 0, NULL, SET_BOOL}, + {0, 0, "GlobalScanExcept", neonspam_cmd_setscanexcept, 0, NULL, SET_HELP}, + + {0, 0, NULL, NULL, 0, NULL, 0} +}; + +#define MAX_QUERY_LEN 1024 +CMD_BIND(neonspam_cmd_set) { + int i, j; + loadNeonSpamSettings(chan); + if(argc && !strcmp(argv[0], "defaults")) { + //reset channel settings + int uaccess = getChannelAccess(user, chan); + if(uaccess < 500) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_DEFAULTS_OWNER", chan->name); + return; + } + } + int seed = 0; + char *tmp; + static char defaultskey[16]; + for(tmp = user->auth; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + for(tmp = chan->name; *tmp; tmp++) + seed = (seed * 0xEECE66DL ^ ((*tmp << 24) | (*tmp << 16) | (*tmp << 8) | *tmp)); + sprintf(defaultskey, "%08x", seed); + if(argc > 1 && !strcmp(argv[1], defaultskey)) { + printf_mysql_query("UPDATE `channels` SET " SPAMSERV_SETTINGS_RESET " WHERE `channel_id` = '%d'", 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); + } + } else if(argc && strcmp(argv[0], "help")) { + //find the correct command + i = 0; + j = 0; + char *args = (argc > 1 ? merge_argv(argv, 1, argc) : NULL); + neonspam_settings_row = NULL; + neonspam_settings_defaults = NULL; + while(neonspam_settings[i].setting) { + if(!stricmp(neonspam_settings[i].setting, argv[0])) { + //setting found + char valueBuf[MAXLEN], nameBuf[MAXLEN]; + char *value, *optimized_value, *option_help; + neonspam_cmd_set_function *func = neonspam_settings[i].function; + value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, args, valueBuf); + if(value) { + optimized_value = value; + if(neonspam_settings[i].flags & SET_BOOL) { + if(!strcmp(value, "0")) + optimized_value = get_language_string(user, "NS_SET_OFF"); + else if(!strcmp(value, "1")) + optimized_value = get_language_string(user, "NS_SET_ON"); + } + if(neonspam_settings[i].flags & SET_OPT) { + sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value); + option_help = get_language_string(user, nameBuf); + } else + option_help = NULL; + reply(getTextBot(), user, "\002%s\002 %s%s%s", neonspam_settings[i].setting, optimized_value, (option_help ? " - " : ""), (option_help ? option_help : "")); + if(neonspam_settings[i].flags & SET_OPT) { + int maxoption = (neonspam_settings[i].flags & SET_OPT_MAX) >> SET_OPT_SHIFT; + for(j = 0; j < maxoption; j++) { + sprintf(nameBuf, "SS_SET_OPTION_%s_%d", neonspam_settings[i].setting, j); + + reply(getTextBot(), user, " \002%d\002 - %s", j, option_help); + } + } + if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) { + char *tmp; + sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting); + tmp = get_language_string(user, nameBuf); + if(tmp) { + reply(getTextBot(), user, " %s", tmp); + } + } + } + j = 1; + break; + } + i++; + } + if(j == 0) { + //unknown setting + reply(getTextBot(), user, "NS_SET_UNKNOWN_SETTING", argv[0]); + } + } else { + char valueBuf[MAXLEN], nameBuf[MAXLEN]; + char *value; + int namePos, boolflag = 0; + MYSQL_RES *res, *defaults_res; + struct Table *table; + char *content[2]; + i = 0; + while(neonspam_settings[i].setting) + i++; + table = table_init(2, i, 0); + table_set_bold(table, 0, 1); + printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_name` = 'defaults'"); + defaults_res = mysql_use(); + neonspam_settings_defaults = mysql_fetch_row(defaults_res); + printf_mysql_query("SELECT " SPAMSERV_SETTINGS_QUERY " FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id); + res = mysql_use(); + neonspam_settings_row = mysql_fetch_row(res); + i = -1; + reply(getTextBot(), user, "NS_SET_HEADER", chan->name); + while(neonspam_settings[++i].setting) { + if((chan->spam_settings->flags & (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) != (neonspam_settings[i].if_flag & SPAMSETTINGS_FLAGS)) + continue; + if((neonspam_settings[i].if_flag & SPAMSETTINGS_ISTIMEBAN) && !boolflag) + continue; + neonspam_cmd_set_function *func = neonspam_settings[i].function; + value = func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, NULL, valueBuf); + if(neonspam_settings[i].if_flag & SPAMSETTINGS_SETTIMEBAN) + boolflag = !strcmp(value, "2"); + //TODO: append option or help info + strcpy(valueBuf, value); + if(neonspam_settings[i].flags & SET_BOOL) { + if(!strcmp(value, "0")) + strcpy(valueBuf, get_language_string(user, "NS_SET_OFF")); + else if(!strcmp(value, "1")) + strcpy(valueBuf, get_language_string(user, "NS_SET_ON")); + } + if(neonspam_settings[i].flags & SET_OPT) { + char *tmp; + sprintf(nameBuf, "SS_SET_OPTION_%s_%s", neonspam_settings[i].setting, value); + tmp = get_language_string(user, nameBuf); + if(tmp) { + sprintf(valueBuf + strlen(valueBuf), " - %s", tmp); + } + } + if((neonspam_settings[i].flags & SET_HELP) && argc && !strcmp(argv[0], "help")) { + char *tmp; + sprintf(nameBuf, "SS_SET_HELP_%s", neonspam_settings[i].setting); + tmp = get_language_string(user, nameBuf); + if(tmp) { + sprintf(valueBuf + strlen(valueBuf), " - %s", tmp); + } + } + namePos = 0; + for(j = 0; j < neonspam_settings[i].indent; j++) { + nameBuf[namePos++] = ' '; + } + sprintf(nameBuf + namePos, "%s", neonspam_settings[i].setting); + content[0] = nameBuf; + content[1] = valueBuf; + table_add(table, content); + } + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + } +} + +static char* neonspam_cmd_set_trigger(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) { + char *trigger; + //get current trigger + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `trigger`, `defaulttrigger` FROM `bot_channels` LEFT JOIN `bots` ON `botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botid` = '%d'", chan->channel_id, client->clientid); + res = mysql_use(); + row = mysql_fetch_row(res); + trigger = (row[0] ? row[0] : row[1]); + if(argument) { + int uaccess = getChannelAccess(user, chan); + if(uaccess < 500) { + 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); + } + return trigger; +} + +static char* neonspam_cmd_setflags(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { + char *value = ((chan->spam_settings->flags & flag) ? "1" : "0"); + if(argument) { + //binary argument... + if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { + chan->spam_settings->flags &= ~flag; + } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { + chan->spam_settings->flags |= flag; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); + return NULL; + } + char str_flags[50]; + convertNeonSpamSettingsToString(chan->spam_settings->flags, str_flags); + printf_mysql_query("UPDATE `channels` SET `channel_scanner` = '%s' WHERE `channel_id` = '%d' ", str_flags, chan->channel_id); + value = argument; + } + return value; +} + +static char* neonspam_cmd_setexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int exceptlvl_index, char *field, char *argument, char *retBuf) { + unsigned int value = chan->spam_settings->exceptlevel[exceptlvl_index]; + if(argument) { + //numeric argument... (access) + int caccess = atoi(argument); + if(caccess < 0 || caccess > 501) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return NULL; + } + int uaccess = getChannelAccess(user, chan); + if(uaccess == 500) uaccess++; + if(value > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_CANNOT_SET"); + return NULL; + } + } + if(caccess > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_BADLEVEL"); + return NULL; + } + } + value = caccess; + chan->spam_settings->exceptlevel[exceptlvl_index] = value; + printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", field, value, chan->channel_id); + } + sprintf(retBuf, "%u", value); + return retBuf; +} + +static char* neonspam_cmd_set_reaction(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) { + if(argument) { + /* valid options: + * 0/kick - kick + * 1/kickban - kickban + * 2/ban - timed ban + */ + if(!strcmp(argument, "0") || !stricmp(argument, "kick")) { + argument = "0"; + } else if(!strcmp(argument, "1") || !stricmp(argument, "kickban")) { + argument = "1"; + } else if(!strcmp(argument, "2") || !stricmp(argument, "ban")) { + argument = "2"; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_OPTION_STR", argument); + return NULL; + } + printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id); + return argument; + } else { + if(neonspam_settings_row) { + return (neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]); + } else { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + return row[0]; + } + } +} + +static char* neonspam_cmd_set_reaction_time(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int mysqlindex, char *mysqlfield, char *argument, char *retBuf) { + int duration; + if(argument) { + duration = strToTime(user, argument); + if(duration < 30) { + reply(getTextBot(), user, "NS_TIMEBAN_DURATION_TOO_SHORT", 30); + return NULL; + } + printf_mysql_query("UPDATE `channels` SET `%s` = '%s' WHERE `channel_id` = '%d' ", mysqlfield, argument, chan->channel_id); + } else { + if(neonspam_settings_row) { + duration = atoi(neonspam_settings_row[mysqlindex] ? neonspam_settings_row[mysqlindex] : neonspam_settings_defaults[mysqlindex]); + } else { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `%s` FROM `channels` WHERE `channel_id` = '%d'", mysqlfield, chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + duration = atoi(row[0]); + } + } + timeToStr(user, duration, 3, retBuf); + return retBuf; +} + +static char* neonspam_cmd_setpercent(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int percent_index, char *mysqlfield, char *argument, char *retBuf) { + unsigned int value = chan->spam_settings->percent[percent_index]; + if(argument) { + //numeric argument... (access) + value = atoi(argument); + if(value < 0 || value > 100) { + //invalid percent value + reply(getTextBot(), user, "SS_SET_PERCENT", value); + return NULL; + } + chan->spam_settings->percent[percent_index] = value; + printf_mysql_query("UPDATE `channels` SET `%s` = '%u' WHERE `channel_id` = '%d' ", mysqlfield, value, chan->channel_id); + } + sprintf(retBuf, "%u", value); + return retBuf; +} + +static char* neonspam_cmd_setsensibility(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int sensibility_index, char *mysqlfield, char *argument, char *retBuf) { + if(argument) { + //change value + char *delimiter = strstr(argument, ":"); + if(!delimiter) { + //invalid format + reply(getTextBot(), user, "SS_SET_SENSIBILITY", argument); + return NULL; + } + *delimiter = '\0'; + delimiter++; + int amount = atoi(argument); + int timep = atoi(delimiter); + if(amount > MAX_FLOOD_AMOUNT || amount < MIN_FLOOD_AMOUNT) { + //invalid amount + reply(getTextBot(), user, "SS_SET_SENSIBILITY_AMOUNT", amount, MIN_FLOOD_AMOUNT, MAX_FLOOD_AMOUNT); + return NULL; + } + if(timep > MAX_FLOOD_TIME || timep < 0) { + //invalid time period + reply(getTextBot(), user, "SS_SET_SENSIBILITY_TIME", timep, 0, MAX_FLOOD_TIME); + return NULL; + } + char amountfield[50], timefield[50]; + sprintf(amountfield, "%s%s", mysqlfield, "limit"); + sprintf(timefield, "%s%s", mysqlfield, "time"); + printf_mysql_query("UPDATE `channels` SET `%s` = '%d', `%s` = '%d' WHERE `channel_id` = '%d' ", amountfield, amount, timefield, timep, chan->channel_id); + sprintf(retBuf, "%d:%d", amount, timep); + chan->spam_settings->sensibility_amount[sensibility_index] = amount; + chan->spam_settings->sensibility_time[sensibility_index] = timep; + } else { + sprintf(retBuf, "%d:%d", chan->spam_settings->sensibility_amount[sensibility_index], chan->spam_settings->sensibility_time[sensibility_index]); + } + return retBuf; +} + +static char* neonspam_cmd_set_spamlimit(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int intparam, char *charparam, char *argument, char *retBuf) { + if(argument) { + //change value + int amount = atoi(argument); + if(amount > 10 || amount < 2) { + //invalid amount + reply(getTextBot(), user, "SS_SET_SPAMLIMIT", amount, 2, 10); + return NULL; + } + printf_mysql_query("UPDATE `channels` SET `channel_maxrepeat` = '%d' WHERE `channel_id` = '%d' ", amount, chan->channel_id); + sprintf(retBuf, "%d", amount); + chan->spam_settings->spam_amount = amount; + } else + sprintf(retBuf, "%d", chan->spam_settings->spam_amount); + return retBuf; +} + +static char* neonspam_cmd_setscanops(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { + int i = 0; + int value = -1; + int identical = 1; + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANOPS) { + if(value == -1) + value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0); + else { + if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) { + identical = 0; + break; + } + } + } + i++; + } + if(argument) { + //binary argument... + if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { + value = 0; + } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { + value = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); + return NULL; + } + i = 0; + char valueBuf[MAXLEN]; + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANOPS) { + neonspam_cmd_set_function *func = neonspam_settings[i].function; + func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf); + } + i++; + } + identical = 1; + } + if(identical && value) + return "1"; + if(identical && !value) + return "0"; + return "?"; +} + +static char* neonspam_cmd_setscanvoice(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { + int i = 0; + int value = -1; + int identical = 1; + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANVOICE) { + if(value == -1) + value = ((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0); + else { + if(((chan->spam_settings->flags & neonspam_settings[i].intparam) ? 1 : 0) != value) { + identical = 0; + break; + } + } + } + i++; + } + if(argument) { + //binary argument... + if(!strcmp(argument, "0") || !stricmp(argument, "off") || !stricmp(argument, get_language_string(user, "NS_SET_OFF"))) { + value = 0; + } else if(!strcmp(argument, "1") || !stricmp(argument, "on") || !stricmp(argument, get_language_string(user, "NS_SET_ON"))) { + value = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argument); + return NULL; + } + i = 0; + char valueBuf[MAXLEN]; + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANVOICE) { + neonspam_cmd_set_function *func = neonspam_settings[i].function; + func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, (value ? "1" : "0"), valueBuf); + } + i++; + } + identical = 1; + } + if(identical && value) + return "1"; + if(identical && !value) + return "0"; + return "?"; +} + +static char* neonspam_cmd_setscanexcept(struct ClientSocket *client, struct UserNode *user, struct ChanNode *chan, struct Event *event, int flag, char *charparam, char *argument, char *retBuf) { + int i = 0; + int value = -1; + int identical = 1; + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANEXCEPT) { + if(value == -1) + value = chan->spam_settings->exceptlevel[neonspam_settings[i].intparam]; + else { + if(chan->spam_settings->exceptlevel[neonspam_settings[i].intparam] != value) { + identical = 0; + break; + } + } + } + i++; + } + if(argument) { + //numeric argument... (access) + int caccess = atoi(argument); + if(caccess < 0 || caccess > 501) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return NULL; + } + int uaccess = getChannelAccess(user, chan); + if(uaccess == 500) uaccess++; + if(identical && value > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_CANNOT_SET"); + return NULL; + } + } + if(caccess > uaccess) { + if(isGodMode(user)) { + event->flags |= CMDFLAG_OPLOG; + } else { + reply(getTextBot(), user, "NS_SET_BADLEVEL"); + return NULL; + } + } + i = 0; + char valueBuf[MAXLEN]; + sprintf(retBuf, "%d", caccess); + while(neonspam_settings[i].setting) { + if(neonspam_settings[i].flags & SET_SCANEXCEPT) { + neonspam_cmd_set_function *func = neonspam_settings[i].function; + func(client, user, chan, event, neonspam_settings[i].intparam, neonspam_settings[i].charparam, retBuf, valueBuf); + } + i++; + } + identical = 1; + value = caccess; + } + if(identical) { + sprintf(retBuf, "%d", value); + return retBuf; + } + return "?"; +} + +#undef MAX_QUERY_LEN diff --git a/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c b/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c new file mode 100644 index 0000000..163315d --- /dev/null +++ b/src/modules/NeonSpam.mod/event_neonspam_chanmsg.c @@ -0,0 +1,392 @@ +/* event_neonspam_chanmsg.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); +static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser); +static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); +static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); +static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message); + +static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup); +static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish); + +struct neonspam_event_chanmsg_cache { + struct ClientSocket *client; + struct ChanUser *chanuser; + struct NeonSpamSettings *settings; + unsigned int warn; + unsigned int punish; +}; + + + +static void neonspam_event_chanmsg(struct UserNode *user, struct ChanNode *chan, char *message) { + struct ClientSocket *client = getChannelBot(chan, BOTID); + if(!client || (user->flags & USERFLAG_ISBOT)) return; //we can't "see" this event + loadNeonSpamSettings(chan); + struct NeonSpamSettings *settings = chan->spam_settings; + struct ChanUser *chanuser = getChanUser(user, chan); + if(!settings || !chanuser) return; + #define NEONSPAM_CHANMSG_DO_SCANOPS(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_OPPED)) + #define NEONSPAM_CHANMSG_DO_SCANVOICE(FLAG) ((settings->flags & FLAG) || !(chanuser->flags & CHANUSERFLAG_VOICED)) + #define NEONSPAM_CHANMSG_DO_EXCEPT(INDEX) (settings->exceptlevel[INDEX] != 0) + #define NEONSPAM_CHANMSG_NEED_WHO(INDEX) (settings->exceptlevel[INDEX] != 501) + //scan the message + int result = 0; + unsigned int warn = 0; + unsigned int punish = 0; + int needwho = 0; + if((settings->flags & SPAMSETTINGS_SPAMSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_SPAMSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_SPAMSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_SPAMEXCINDEX)) { + result = neonspam_spamscan(settings, chanuser, message); + switch(result) { + case SPAMSERV_CHECK_IGNORE: + break; + case SPAMSERV_CHECK_WARN: + warn |= SPAMSETTINGS_SPAMSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX)) + needwho = 1; + break; + case SPAMSERV_CHECK_PUNISH: + punish |= SPAMSETTINGS_SPAMSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_SPAMEXCINDEX)) + needwho = 1; + break; + } + } + if((settings->flags & SPAMSETTINGS_FLOODSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_FLOODSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_FLOODSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_FLOODEXCINDEX)) { + result = neonspam_floodscan(settings, chanuser); + switch(result) { + case SPAMSERV_CHECK_IGNORE: + break; + case SPAMSERV_CHECK_WARN: + warn |= SPAMSETTINGS_FLOODSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX)) + needwho = 1; + break; + case SPAMSERV_CHECK_PUNISH: + punish |= SPAMSETTINGS_FLOODSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_FLOODEXCINDEX)) + needwho = 1; + break; + } + } + if((settings->flags & SPAMSETTINGS_BOTNETSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_BOTNETSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_BOTNETSCAN_VOICE)) { + result = neonspam_botnetscan(client, settings, chanuser, message); + switch(result) { + case SPAMSERV_CHECK_DEAD: + return; + case SPAMSERV_CHECK_IGNORE: + break; + } + } + if((settings->flags & SPAMSETTINGS_CAPSSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_CAPSSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_CAPSSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_CAPSEXCINDEX)) { + result = neonspam_capsscan(settings, chanuser, message); + switch(result) { + case SPAMSERV_CHECK_IGNORE: + break; + case SPAMSERV_CHECK_WARN: + warn |= SPAMSETTINGS_CAPSSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX)) + needwho = 1; + break; + case SPAMSERV_CHECK_PUNISH: + punish |= SPAMSETTINGS_CAPSSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_CAPSEXCINDEX)) + needwho = 1; + break; + } + } + if((settings->flags & SPAMSETTINGS_DIGITSCAN) && NEONSPAM_CHANMSG_DO_SCANOPS(SPAMSETTINGS_DIGITSCAN_OPS) && NEONSPAM_CHANMSG_DO_SCANVOICE(SPAMSETTINGS_DIGITSCAN_VOICE) && NEONSPAM_CHANMSG_DO_EXCEPT(SPAMSETTINGS_DIGITEXCINDEX)) { + result = neonspam_digitscan(settings, chanuser, message); + switch(result) { + case SPAMSERV_CHECK_IGNORE: + break; + case SPAMSERV_CHECK_WARN: + warn |= SPAMSETTINGS_DIGITSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX)) + needwho = 1; + break; + case SPAMSERV_CHECK_PUNISH: + punish |= SPAMSETTINGS_DIGITSCAN; + if(NEONSPAM_CHANMSG_NEED_WHO(SPAMSETTINGS_DIGITEXCINDEX)) + needwho = 1; + break; + } + } + //some other checks? + + if(warn || punish) { + //whois the user to check against exceptlevel + if(!needwho || (user->flags & USERFLAG_ISAUTHED)) { + neonspam_event_chanmsg_punish(client, chanuser, settings, warn, punish); + } else { + struct neonspam_event_chanmsg_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->chanuser = chanuser; + cache->settings = settings; + cache->warn = warn; + cache->punish = punish; + get_userauth(user, neonspam_event_chanmsg_nick_lookup, cache); + } + + } + #undef NEONSPAM_CHANMSG_DO_SCANOPS + #undef NEONSPAM_CHANMSG_DO_SCANVOICE + #undef NEONSPAM_CHANMSG_DO_EXCEPT + #undef NEONSPAM_CHANMSG_NEED_WHO +} + +static USERAUTH_CALLBACK(neonspam_event_chanmsg_nick_lookup) { + struct neonspam_event_chanmsg_cache *cache = data; + neonspam_event_chanmsg_punish(cache->client, cache->chanuser, cache->settings, cache->warn, cache->punish); + free(cache); +} + +static void neonspam_event_chanmsg_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, unsigned int warn, unsigned int punish) { + MYSQL_RES *res; + MYSQL_ROW row, defaults; + loadChannelSettings(chanuser->chan); + int uaccess = 0; + if(chanuser->user->flags & USERFLAG_ISAUTHED) + uaccess = getChannelAccess(chanuser->user, chanuser->chan); + char reason[MAXLEN]; + reason[0] = '\0'; + int punishment = 0; + int punish_time = 0; + if(!punishment && (punish & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) { + printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_spam_reaction`, `channel_spam_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM); + punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; + punish_time = atoi((row[1] ? row[1] : defaults[1])); + } + if(!punishment && (punish & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) { + printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD); + punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; + punish_time = atoi((row[1] ? row[1] : defaults[1])); + } + if(!punishment && (punish & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) { + printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_caps_reaction`, `channel_caps_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS); + punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; + punish_time = atoi((row[1] ? row[1] : defaults[1])); + } + if(!punishment && (punish & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) { + printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1]) { + printf_mysql_query("SELECT `channel_digit_reaction`, `channel_digit_reaction_duration` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT); + punishment = atoi((row[0] ? row[0] : defaults[0])) + 1; + punish_time = atoi((row[1] ? row[1] : defaults[1])); + } + if(!punishment && (warn & SPAMSETTINGS_SPAMSCAN) && settings->exceptlevel[SPAMSETTINGS_SPAMEXCINDEX] > uaccess) { + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_SPAM); + } + if(!punishment && (warn & SPAMSETTINGS_FLOODSCAN) && settings->exceptlevel[SPAMSETTINGS_FLOODEXCINDEX] > uaccess) { + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_FLOOD); + } + if(!punishment && (warn & SPAMSETTINGS_CAPSSCAN) && settings->exceptlevel[SPAMSETTINGS_CAPSEXCINDEX] > uaccess) { + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_CAPS); + } + if(!punishment && (warn & SPAMSETTINGS_DIGITSCAN) && settings->exceptlevel[SPAMSETTINGS_DIGITEXCINDEX] > uaccess) { + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_DIGIT); + } + if(punishment) { + char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; + char *banmask = NULL; + switch (punishment) { + case 3: //TIMEBAN + banmask = generate_banmask(chanuser->user, banmaskBuf); + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (punish_time ? (time(0) + punish_time) : 0), 0, escape_string(reason)); + if(punish_time) { + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, punish_time, channel_ban_timeout, strdup(banidBuf)); + } + case 2: //KICKBAN + if(!banmask) + banmask = generate_banmask(chanuser->user, banmaskBuf); + putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); + case 1: //KICK + putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason); + break; + } + } else if(*reason) + reply(client, chanuser->user, "%s", reason); +} + +static int neonspam_spamscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { + //crc32 hash of the message + unsigned long msghash = crc32(message); + if(chanuser->spamnode) { + if(chanuser->spamnode->lastmsg == msghash) { + chanuser->spamnode->spamcount++; + if(chanuser->spamnode->spamcount == settings->spam_amount) + return SPAMSERV_CHECK_WARN; + else if(chanuser->spamnode->spamcount > settings->spam_amount) + return SPAMSERV_CHECK_PUNISH; + else + return SPAMSERV_CHECK_IGNORE; + } + } else + createSpamNode(chanuser); + chanuser->spamnode->lastmsg = msghash; + chanuser->spamnode->spamcount = 1; + return SPAMSERV_CHECK_IGNORE; +} + +static int neonspam_update_penalty(struct NeonSpamSettings *settings, struct ChanUser *chanuser, int addmsg) { + int last_update = time(0) - chanuser->spamnode->last_penalty_update; + if(last_update) { + if(last_update < MAX_FLOOD_TIME && chanuser->spamnode->floodpenalty) { + chanuser->spamnode->floodpenalty -= last_update * (MAX_FLOOD_TIME / settings->sensibility_time[SPAMSETTINGS_FLOODSENINDEX]); + if(chanuser->spamnode->floodpenalty < 0) + chanuser->spamnode->floodpenalty = 0; + } else + chanuser->spamnode->floodpenalty = 0; + chanuser->spamnode->last_penalty_update = time(0); + } + chanuser->spamnode->floodpenalty += MAX_FLOOD_TIME * addmsg; + return chanuser->spamnode->floodpenalty / MAX_FLOOD_TIME + ((chanuser->spamnode->floodpenalty % MAX_FLOOD_TIME) ? 1 : 0); +} + +static int neonspam_floodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) { + if(!chanuser->spamnode) + createSpamNode(chanuser); + int messages_pending = neonspam_update_penalty(settings, chanuser, 1); + if(messages_pending == settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX]) + return SPAMSERV_CHECK_WARN; + else if(messages_pending > settings->sensibility_amount[SPAMSETTINGS_FLOODSENINDEX]) + return SPAMSERV_CHECK_PUNISH; + else + return SPAMSERV_CHECK_IGNORE; +} + +static int neonspam_botnetscan(struct ClientSocket *client, struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { + //crc32 hash of the message + unsigned long msghash = crc32(message); + if((time(0) - settings->lastmsg_time) > BOTNETSCAN_TIME || settings->lastmsg != msghash) { + int i; + for(i = 0; i < BOTNETSCAN_USERS; i++) { + if(settings->botnicks[i]) { + free(settings->botnicks[i]); + settings->botnicks[i] = NULL; + } + } + settings->flags &= ~SPAMSETTINGS_KICKEDBOTQUEUE; + settings->lastmsg = msghash; + } else if(settings->lastmsg == msghash) { + int i; + for(i = 0; i < BOTNETSCAN_USERS; i++) { + if(!settings->botnicks[i]) { + settings->botnicks[i] = strdup(chanuser->user->nick); + break; + } else if(!stricmp(chanuser->user->nick, settings->botnicks[i])) { + return SPAMSERV_CHECK_IGNORE; + } + } + if(i == BOTNETSCAN_USERS) { + //BOTNETSCAN_USERS exceeded + if(!(settings->flags & SPAMSETTINGS_KICKEDBOTQUEUE)) { + for(i = 0; i < BOTNETSCAN_USERS; i++) { + putsock(client, "KICK %s %s :%s", chanuser->chan->name, settings->botnicks[i], SPAMSERV_MSG_BOTNET); + } + settings->flags |= SPAMSETTINGS_KICKEDBOTQUEUE; + } + putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, SPAMSERV_MSG_BOTNET); + return SPAMSERV_CHECK_DEAD; + } + } + settings->lastmsg_time = time(0); + return SPAMSERV_CHECK_IGNORE; +} + +static int neonspam_capsscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { + int caps = 0, msglen = strlen(message); + int i; + if(msglen <= 4) return SPAMSERV_CHECK_IGNORE; + for(i = 0; i < msglen; i++) { + if(isupper(message[i])) caps++; + } + caps = 100*caps/msglen; + if(caps >= settings->percent[SPAMSETTINGS_CAPSPERCENTINDEX]) { + if(!chanuser->spamnode) + createSpamNode(chanuser); + if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_CAPSSCAN_WARNED) + return SPAMSERV_CHECK_PUNISH; + else { + chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_CAPSSCAN_WARNED; + return SPAMSERV_CHECK_WARN; + } + } + return SPAMSERV_CHECK_IGNORE; +} + +static int neonspam_digitscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser, char *message) { + int digit = 0, msglen = strlen(message); + int i; + if(msglen <= 4) return SPAMSERV_CHECK_IGNORE; + for(i = 0; i < msglen; i++) { + if(isdigit(message[i])) digit++; + } + digit = 100*digit/msglen; + if(digit >= settings->percent[SPAMSETTINGS_DIGITPERCENTINDEX]) { + if(!chanuser->spamnode) + createSpamNode(chanuser); + if(chanuser->spamnode->flags & NEONSPAMNODE_FLAG_DIGITSCAN_WARNED) + return SPAMSERV_CHECK_PUNISH; + else { + chanuser->spamnode->flags |= NEONSPAMNODE_FLAG_DIGITSCAN_WARNED; + return SPAMSERV_CHECK_WARN; + } + } + return SPAMSERV_CHECK_IGNORE; +} + diff --git a/src/modules/NeonSpam.mod/event_neonspam_join.c b/src/modules/NeonSpam.mod/event_neonspam_join.c new file mode 100644 index 0000000..5a169f2 --- /dev/null +++ b/src/modules/NeonSpam.mod/event_neonspam_join.c @@ -0,0 +1,145 @@ +/* event_neonspam_join.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup); +static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action); +static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser); + +struct neonspam_event_join_cache { + struct ClientSocket *client; + struct ChanUser *chanuser; + struct NeonSpamSettings *settings; + int action; +}; + +static void neonspam_event_join(struct ChanUser *chanuser) { + if(chanuser->user->flags & USERFLAG_WAS_REGISTRING) return; + struct ClientSocket *client = getChannelBot(chanuser->chan, BOTID); + if(!client) return; //we can't "see" this event + if(chanuser->user == client->user) { + requestOp(client->user, chanuser->chan); + return; + } + if(chanuser->user->flags & USERFLAG_ISBOT) return; + loadNeonSpamSettings(chanuser->chan); + struct NeonSpamSettings *settings = chanuser->chan->spam_settings; + if(!settings || !(settings->flags & SPAMSETTINGS_JOINSCAN)) return; + if(settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 0) return; + int result = neonspam_joinfloodscan(settings, chanuser); + if(result != SPAMSERV_CHECK_IGNORE) { + //whois the user to check against exceptlevel + if((chanuser->user->flags & USERFLAG_ISAUTHED) || settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX] == 501) { + neonspam_event_join_punish(client, chanuser, settings, result); + } else { + struct neonspam_event_join_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->chanuser = chanuser; + cache->settings = settings; + cache->action = result; + get_userauth(chanuser->user, neonspam_event_join_nick_lookup, cache); + } + } +} + +static USERAUTH_CALLBACK(neonspam_event_join_nick_lookup) { + struct neonspam_event_join_cache *cache = data; + neonspam_event_join_punish(cache->client, cache->chanuser, cache->settings, cache->action); + free(cache); +} + +static void neonspam_event_join_punish(struct ClientSocket *client, struct ChanUser *chanuser, struct NeonSpamSettings *settings, int action) { + int uaccess = 0; + if(chanuser->user->flags & USERFLAG_ISAUTHED) + uaccess = getChannelAccess(chanuser->user, chanuser->chan); + if(uaccess >= settings->exceptlevel[SPAMSETTINGS_JOINEXCINDEX]) return; + //scanops / scanvoiced + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + loadChannelSettings(chanuser->chan); + printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chanuser->chan->channel_id); + res = mysql_use(); + row = mysql_fetch_row(res); + if(!row[0] || !row[1] || !row[2] || !row[3]) { + printf_mysql_query("SELECT `channel_flood_reaction`, `channel_flood_reaction_duration`, `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'"); + res = mysql_use(); + defaults = mysql_fetch_row(res); + } + if(!(settings->flags & SPAMSETTINGS_JOINSCAN_OPS) && uaccess >= atoi((row[2] ? row[2] : defaults[2]))) return; + if(!(settings->flags & SPAMSETTINGS_JOINSCAN_VOICE) && uaccess >= atoi((row[3] ? row[3] : defaults[3]))) return; + char reason[MAXLEN]; + sprintf(reason, SPAMSERV_MSG_WARNING, SPAMSERV_MSG_JOINFLOOD); + if(action == SPAMSERV_CHECK_WARN) { + reply(client, chanuser->user, "%s", reason); + } else if(action == SPAMSERV_CHECK_PUNISH) { + int duration = atoi((row[1] ? row[1] : defaults[1])); + char banmaskBuf[NICKLEN+USERLEN+HOSTLEN+3]; + char *banmask = NULL; + switch (atoi((row[0] ? row[0] : defaults[0]))) { + case 2: //TIMEBAN + banmask = generate_banmask(chanuser->user, banmaskBuf); + printf_mysql_query("INSERT INTO `bans` (`ban_channel`, `ban_mask`, `ban_triggered`, `ban_timeout`, `ban_owner`, `ban_reason`) VALUES ('%d', '%s', UNIX_TIMESTAMP(), '%lu', '%d', '%s')", chanuser->chan->channel_id, escape_string(banmask), (unsigned long) (duration ? (time(0) + duration) : 0), 0, escape_string(reason)); + if(duration) { + int banid = (int) mysql_insert_id(get_mysql_conn()); + char nameBuf[MAXLEN]; + char banidBuf[20]; + sprintf(nameBuf, "ban_%d", banid); + sprintf(banidBuf, "%d", banid); + timeq_add_name(nameBuf, duration, channel_ban_timeout, strdup(banidBuf)); + } + case 1: //KICKBAN + if(!banmask) + banmask = generate_banmask(chanuser->user, banmaskBuf); + putsock(client, "MODE %s +b %s", chanuser->chan->name, banmask); + case 0: //KICK + putsock(client, "KICK %s %s :%s", chanuser->chan->name, chanuser->user->nick, reason); + break; + } + } +} + +static int neonspam_update_join_penalty(struct NeonSpamSettings *settings, struct NeonSpamJoinNode *joinnode, int addjoin) { + int last_update = time(0) - joinnode->last_penalty_update; + if(last_update) { + if(last_update < MAX_JOIN_TIME && joinnode->joinpenalty) { + joinnode->joinpenalty -= last_update * (MAX_JOIN_TIME / settings->sensibility_time[SPAMSETTINGS_JOINSENINDEX]); + if(joinnode->joinpenalty < 0) + joinnode->joinpenalty = 0; + } else + joinnode->joinpenalty = 0; + joinnode->last_penalty_update = time(0); + } + joinnode->joinpenalty += MAX_JOIN_TIME * addjoin; + return joinnode->joinpenalty / MAX_JOIN_TIME + ((joinnode->joinpenalty % MAX_JOIN_TIME) ? 1 : 0); +} + +static int neonspam_joinfloodscan(struct NeonSpamSettings *settings, struct ChanUser *chanuser) { + if(!chanuser->spamnode) + createSpamNode(chanuser); + int joins_pending = neonspam_update_join_penalty(settings, getNeonSpamJoinNode(chanuser), 1); + if(joins_pending == settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX]) + return SPAMSERV_CHECK_WARN; + else if(joins_pending > settings->sensibility_amount[SPAMSETTINGS_JOINSENINDEX]) + return SPAMSERV_CHECK_PUNISH; + else + return SPAMSERV_CHECK_IGNORE; +} + + diff --git a/src/modules/NeonSpam.mod/module.c b/src/modules/NeonSpam.mod/module.c new file mode 100644 index 0000000..64581de --- /dev/null +++ b/src/modules/NeonSpam.mod/module.c @@ -0,0 +1,38 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "bot_NeonSpam.h" +#include "cmd_neonspam.h" + +static int module_initialize() { + register_commands(); + return 0; +} + +static void module_start(int type) { + init_NeonSpam(type); +} + +static void module_loop() { + loop_NeonSpam(); +} + +static void module_stop(int type) { + free_NeonSpam(type); +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/funcmd.mod/cmd_funcmds.c b/src/modules/funcmd.mod/cmd_funcmds.c new file mode 100644 index 0000000..dc3cb8b --- /dev/null +++ b/src/modules/funcmd.mod/cmd_funcmds.c @@ -0,0 +1,232 @@ +/* cmd_funcmds.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_funcmds.h" +#include "modcmd.h" +#include "mysqlConn.h" +#include "IRCParser.h" +#include "ClientSocket.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "lang.h" +#include "tools.h" +#include "DBHelper.h" + +static const struct default_language_entry msgtab[] = { + {"FUN_DICE", "$b%s$b: A $b%d$b shows on the %d-sided die."}, /* {ARGS: "TestUser", 5, 6} */ + {"FUN_DICE_NUM", "I do not understand $b%s$b. Please use a single number above 1."}, /* {ARGS: "bla"} */ + {"FUN_8BALL", "$b%s$b: %s"}, /* {ARGS: "TestUser", "Not a chance."} */ + {"FUN_8BALL_REPLIES", "Not a chance.|In your dreams.|Absolutely!|Could be, could be.|No!"}, + {"FUN_COOKIE", "gives %1$s a very big chocolate cookie. %1$s has got %2$d cookies until now (%3$d in this channel)."}, /* {ARGS: "TestUser", 20, 50} */ + {NULL, NULL} +}; + +void init_funcmds() { + register_default_language_table(msgtab); + srand(time(NULL)); +} + +void register_commands() { + //Fun Commands + register_command_alias(3, "FunCMD"); + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,FLAGS) register_command(3, NAME, FUNCTION, PARAMCOUNT, NULL, 0, FLAGS) + // NAME FUNCTION PARAMS FLAGS + USER_COMMAND("extscript", neonserv_cmd_extscript, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_EMPTY_ARGS | CMDFLAG_CHAN_PARAM | CMDFLAG_FUNCMD); + USER_COMMAND("ping", funcmd_ping, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + USER_COMMAND("pong", funcmd_pong, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + USER_COMMAND("dice", funcmd_dice, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + USER_COMMAND("8ball", funcmd_8ball, 1, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + USER_COMMAND("cookie", funcmd_cookie, 0, CMDFLAG_REQUIRE_CHAN | CMDFLAG_REGISTERED_CHAN | CMDFLAG_FUNCMD); + #undef USER_COMMAND +} + +struct current_funcmd_header { + struct ClientSocket *client; + struct UserNode *user; + struct ChanNode *chan; + char send_notice; +}; + +static struct current_funcmd_header current_funcmd; + +#define FUNCMD_HEADER \ +current_funcmd.client = getTextBot(); \ +current_funcmd.user = user; \ +current_funcmd.chan = chan; \ +{\ + MYSQL_RES *res; \ + MYSQL_ROW row; \ + printf_mysql_query("SELECT `channel_toys` FROM `channels` WHERE `channel_name` = '%s'", escape_string(chan->name)); \ + res = mysql_use(); \ + row = mysql_fetch_row(res); \ + if(!row || !strcmp(row[0], "0")) { \ + reply(getTextBot(), user, "NS_FUN_DISABLED", chan->name); \ + return; \ + } else if(!strcmp(row[0], "1")) \ + current_funcmd.send_notice = 1; \ + else \ + current_funcmd.send_notice = 0; \ +} + +#define REPLYTYPE_NORMAL 0 +#define REPLYTYPE_ACTION 1 +static void funcmd_reply(const char *text, int type, ...) { + if (!(current_funcmd.client->flags & SOCKET_FLAG_CONNECTED)) return; + const char *reply_format = get_language_string(current_funcmd.user, text); + if(reply_format) + text = reply_format; + char formatBuf[MAXLEN]; + if(current_funcmd.send_notice) { + if(type == REPLYTYPE_ACTION) + sprintf(formatBuf, "NOTICE %s :%s %s", current_funcmd.user->nick, current_funcmd.client->user->nick, text); + else + sprintf(formatBuf, "NOTICE %s :%s", current_funcmd.user->nick, text); + } else { + if(type == REPLYTYPE_ACTION) + sprintf(formatBuf, "PRIVMSG %s :\001ACTION %s\001", current_funcmd.chan->name, text); + else + sprintf(formatBuf, "PRIVMSG %s :%s", current_funcmd.chan->name, text); + } + va_list arg_list; + char sendBuf[MAXLEN]; + int pos; + sendBuf[0] = '\0'; + va_start(arg_list, type); + pos = vsnprintf(sendBuf, MAXLEN - 2, formatBuf, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (MAXLEN - 2)) pos = MAXLEN - 2; + sendBuf[pos] = '\n'; + sendBuf[pos+1] = '\0'; + write_socket(current_funcmd.client, sendBuf, pos+1); +} + +static char* getSetting(struct UserNode *user, struct ChanNode *chan, const char *setting) { + char *uname = ""; + int cid = 0; + MYSQL_RES *res; + MYSQL_ROW row; + if(user) { + uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); + } + if(chan) { + loadChannelSettings(chan); + if(chan->flags & CHANFLAG_CHAN_REGISTERED) + cid = chan->channel_id; + } + printf_mysql_query("SELECT `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + return row[0]; + } else + return NULL; +} + +static void setSetting(struct UserNode *user, struct ChanNode *chan, const char *setting, const char *value) { + char *uname = ""; + int cid = 0; + MYSQL_RES *res; + MYSQL_ROW row; + if(user) { + uname = ((user->flags & USERFLAG_ISAUTHED) ? user->auth : "*"); + } + if(chan) { + loadChannelSettings(chan); + if(chan->flags & CHANFLAG_CHAN_REGISTERED) + cid = chan->channel_id; + } + printf_mysql_query("SELECT `id`, `value` FROM `fundata` WHERE `user` = '%s' AND `cid` = '%d' AND `name` = '%s'", escape_string(uname), cid, escape_string(setting)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(strcmp(row[1], value)) + printf_mysql_query("UPDATE `fundata` SET `value` = '%s' WHERE `id` = '%s'", escape_string(value), row[0]); + } else + printf_mysql_query("INSERT INTO `fundata` (`user`, `cid`, `name`, `value`) VALUES ('%s', '%d', '%s', '%s')", escape_string(uname), cid, escape_string(setting), escape_string(value)); +} + +CMD_BIND(funcmd_ping) { + FUNCMD_HEADER; + funcmd_reply("\002%s\002: Pong!", REPLYTYPE_NORMAL, user->nick); +} + +CMD_BIND(funcmd_pong) { + FUNCMD_HEADER; + funcmd_reply("\002%s\002: Ping!", REPLYTYPE_NORMAL, user->nick); +} + +CMD_BIND(funcmd_dice) { + FUNCMD_HEADER; + int max = atoi(argv[0]); + if(max > 1) { + int val = (rand() % max) + 1; + funcmd_reply("FUN_DICE", REPLYTYPE_NORMAL, user->nick, val, max); + } else + funcmd_reply("FUN_DICE_NUM", REPLYTYPE_NORMAL, argv[0]); +} + +CMD_BIND(funcmd_8ball) { + FUNCMD_HEADER; + char *message = merge_argv(argv, 0, argc); + const char *const_replies = get_language_string(current_funcmd.user, "FUN_8BALL_REPLIES"); + char replies[MAXLEN]; + int i, reply_count = 1; + for(i = 0; const_replies[i]; i++) { + if(const_replies[i] == '|') + reply_count++; + replies[i] = const_replies[i]; + } + replies[i] = '\0'; + unsigned int crc32_val = (crc32(message)) % reply_count; + char *creply = (crc32_val == 0 ? replies : NULL); + reply_count = 0; + for(i = 0; replies[i]; i++) { + if(replies[i] == '|') { + if(creply) { + replies[i] = '\0'; + break; + } else { + reply_count++; + if(reply_count == crc32_val) { + creply = &replies[i+1]; + } + } + } + } + if(creply) { + funcmd_reply("FUN_8BALL", REPLYTYPE_NORMAL, user->nick, creply); + } +} + +CMD_BIND(funcmd_cookie) { + FUNCMD_HEADER; + if(argc) { + if(!(user = getUserByNick(argv[0]))) { + reply(current_funcmd.client, current_funcmd.user, "NS_USER_UNKNOWN", argv[0]); + return; + } + } + char *tmp; + int user_count = ((tmp = getSetting(user, chan, "cookies")) ? atoi(tmp) : 0); + int total_count = ((tmp = getSetting(user, NULL, "cookies")) ? atoi(tmp) : 0); + user_count++; + total_count++; + char buf[10]; + sprintf(buf, "%d", user_count); + setSetting(user, chan, "cookies", buf); + sprintf(buf, "%d", total_count); + setSetting(user, NULL, "cookies", buf); + funcmd_reply("FUN_COOKIE", REPLYTYPE_ACTION, user->nick, total_count, user_count); +} diff --git a/src/modules/funcmd.mod/cmd_funcmds.h b/src/modules/funcmd.mod/cmd_funcmds.h new file mode 100644 index 0000000..70125dd --- /dev/null +++ b/src/modules/funcmd.mod/cmd_funcmds.h @@ -0,0 +1,32 @@ +/* cmd_funcmds.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _cmd_funcmds_h +#define _cmd_funcmds_h +#include "../module.h" +#include "main.h" +#include "modcmd.h" + +void init_funcmds(); +void register_commands(); + +CMD_BIND(funcmd_ping); +CMD_BIND(funcmd_pong); +CMD_BIND(funcmd_dice); +CMD_BIND(funcmd_8ball); +CMD_BIND(funcmd_cookie); + +#endif \ No newline at end of file diff --git a/src/modules/funcmd.mod/module.c b/src/modules/funcmd.mod/module.c new file mode 100644 index 0000000..c23dea7 --- /dev/null +++ b/src/modules/funcmd.mod/module.c @@ -0,0 +1,38 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_funcmds.h" + +static int module_initialize() { + init_funcmds(); + register_commands(); + return 0; +} + +static void module_start(int type) { + +} + +static void module_loop() { + +} + +static void module_stop(int type) { + +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/global.mod/cmd_global.c b/src/modules/global.mod/cmd_global.c new file mode 100644 index 0000000..9741e6c --- /dev/null +++ b/src/modules/global.mod/cmd_global.c @@ -0,0 +1,59 @@ +/* cmd_global.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_global.h" +#include "modcmd.h" +#include "ConfigParser.h" + +void register_commands() { + + //Global Commands + #define USER_COMMAND(NAME,FUNCTION,PARAMCOUNT,PRIVS,FLAGS) register_command(0, NAME, FUNCTION, PARAMCOUNT, PRIVS, 0, FLAGS) + // NAME FUNCTION PARAMS PRIVS FLAGS + USER_COMMAND("version", global_cmd_version, 0, NULL, 0); + USER_COMMAND("netinfo", global_cmd_netinfo, 0, NULL, 0); + USER_COMMAND("commands", global_cmd_commands, 0, NULL, 0); + USER_COMMAND("command", global_cmd_command, 1, NULL, CMDFLAG_ESCAPE_ARGS); + USER_COMMAND("staff", global_cmd_staff, 0, NULL, 0); + USER_COMMAND("motd", global_cmd_motd, 0, NULL, 0); + #undef USER_COMMAND + + #define OPER_COMMAND(NAME,FUNCTION,PARAMCOUNT,GACCESS,FLAGS) register_command(0, NAME, FUNCTION, PARAMCOUNT, NULL, GACCESS, FLAGS) + // NAME FUNCTION PARAMS ACCS FLAGS + OPER_COMMAND("register", global_cmd_register, 1, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("unregister", global_cmd_unregister,0, 200, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("say", global_cmd_say, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("emote", global_cmd_emote, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("notice", global_cmd_notice, 2, 600, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_CHAN_PARAM | CMDFLAG_OPLOG); + OPER_COMMAND("raw", global_cmd_raw, 1, 800, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("god", global_cmd_god, 0, 1, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("reloadlang", global_cmd_reloadlang,1, 500, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("bind", global_cmd_bind, 2, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); + OPER_COMMAND("unbind", global_cmd_unbind, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); + OPER_COMMAND("setaccess", global_cmd_setaccess, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("bots", global_cmd_bots, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + OPER_COMMAND("reload", global_cmd_reload, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("restart", global_cmd_restart, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("die", global_cmd_die, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("setbot", global_cmd_setbot, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("addbot", global_cmd_addbot, 2, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("delbot", global_cmd_delbot, 1, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("reconnect", global_cmd_reconnect, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG); + OPER_COMMAND("modcmd", global_cmd_modcmd, 1, 900, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH | CMDFLAG_OPLOG | CMDFLAG_REQUIRED | CMDFLAG_ESCAPE_ARGS); + OPER_COMMAND("meminfo", global_cmd_meminfo, 0, 1000, CMDFLAG_REQUIRE_AUTH | CMDFLAG_CHECK_AUTH); + #undef OPER_COMMAND +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global.h b/src/modules/global.mod/cmd_global.h new file mode 100644 index 0000000..5b3f553 --- /dev/null +++ b/src/modules/global.mod/cmd_global.h @@ -0,0 +1,71 @@ +/* cmd_global.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _cmd_global_h +#define _cmd_global_h +#include "../module.h" +#include "main.h" +#include "modcmd.h" +#include "IRCParser.h" +#include "IRCEvents.h" +#include "UserNode.h" +#include "ChanNode.h" +#include "ChanUser.h" +#include "ModeNode.h" +#include "BanNode.h" +#include "ClientSocket.h" +#include "mysqlConn.h" +#include "lang.h" +#include "HandleInfoHandler.h" +#include "WHOHandler.h" +#include "DBHelper.h" +#include "tools.h" +#include "timeq.h" +#include "version.h" +#include "EventLogger.h" +#include "bots.h" + +void register_commands(); + +CMD_BIND(global_cmd_addbot); +CMD_BIND(global_cmd_bind); +CMD_BIND(global_cmd_bots); +CMD_BIND(global_cmd_command); +CMD_BIND(global_cmd_commands); +CMD_BIND(global_cmd_delbot); +CMD_BIND(global_cmd_die); +CMD_BIND(global_cmd_emote); +CMD_BIND(global_cmd_god); +CMD_BIND(global_cmd_meminfo); +CMD_BIND(global_cmd_modcmd); +CMD_BIND(global_cmd_motd); +CMD_BIND(global_cmd_netinfo); +CMD_BIND(global_cmd_notice); +CMD_BIND(global_cmd_raw); +CMD_BIND(global_cmd_reconnect); +CMD_BIND(global_cmd_register); +CMD_BIND(global_cmd_reload); +CMD_BIND(global_cmd_restart); +CMD_BIND(global_cmd_reloadlang); +CMD_BIND(global_cmd_say); +CMD_BIND(global_cmd_setaccess); +CMD_BIND(global_cmd_setbot); +CMD_BIND(global_cmd_staff); +CMD_BIND(global_cmd_unbind); +CMD_BIND(global_cmd_unregister); +CMD_BIND(global_cmd_version); + +#endif \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_addbot.c b/src/modules/global.mod/cmd_global_addbot.c new file mode 100644 index 0000000..1783834 --- /dev/null +++ b/src/modules/global.mod/cmd_global_addbot.c @@ -0,0 +1,43 @@ +/* cmd_global_addbot.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] nick +* argv[1] class +*/ + +CMD_BIND(global_cmd_addbot) { + MYSQL_RES *res; + int botid; + if((botid = resolve_botalias(argv[1])) == -1) { + reply(getTextBot(), user, "NS_SETBOT_INVALID_CLASS", argv[1]); + return; + } + printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s'", escape_string(argv[0])); + res = mysql_use(); + if(mysql_fetch_row(res)) { + reply(getTextBot(), user, "NS_ADDBOT_EXISTING", argv[0]); + return; + } + printf_mysql_query("INSERT INTO `bots` (`nick`, `botclass`) VALUES ('%s', '%d')", escape_string(argv[0]), botid); + botid = (int) mysql_insert_id(get_mysql_conn()); + reply(getTextBot(), user, "NS_ADDBOT_DONE", argv[0], botid); + logEvent(event); +} + diff --git a/src/modules/global.mod/cmd_global_bind.c b/src/modules/global.mod/cmd_global_bind.c new file mode 100644 index 0000000..2842cf8 --- /dev/null +++ b/src/modules/global.mod/cmd_global_bind.c @@ -0,0 +1,54 @@ +/* cmd_global_bind.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] command name +* argv[1] command function +* argv[2-*] parameters (optional) +*/ + +CMD_BIND(global_cmd_bind) { + MYSQL_RES *res; + MYSQL_ROW row; + if(client->botid == 0) + printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `botid` = '%d' AND `command` = '%s'", client->botid, client->clientid, escape_string(argv[0])); + else + printf_mysql_query("SELECT `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0])); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + reply(getTextBot(), user, "NS_BIND_ALREADY", argv[0], row[0]); + return; + } + char *params; + if(argc > 2) + params = merge_argv(argv, 2, argc); + else + params = ""; + struct cmd_function *function = find_cmd_function(client->botid, argv[1]); + if(!function) { + reply(getTextBot(), user, "NS_BIND_UNKNOWN", argv[1]); + return; + } + bind_botwise_cmd_to_function(client->botid, client->clientid, argv[0], function); + printf_mysql_query("INSERT INTO `bot_binds` (`botclass`, `botid`, `command`, `function`, `parameters`) VALUES ('%d', '%d', '%s', '%s', '%s')", client->botid, (client->botid == 0 ? client->clientid : 0), escape_string(argv[0]), escape_string(argv[1]), params); + if(*params) + bind_botwise_set_parameters(client->botid, client->clientid, argv[0], params); + reply(getTextBot(), user, "NS_BIND_DONE", argv[0], function->name); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_bots.c b/src/modules/global.mod/cmd_global_bots.c new file mode 100644 index 0000000..57ab153 --- /dev/null +++ b/src/modules/global.mod/cmd_global_bots.c @@ -0,0 +1,73 @@ +/* cmd_global_bots.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] (optional) class name +*/ + +CMD_BIND(global_cmd_bots) { + struct Table *table; + MYSQL_RES *res, *res2; + MYSQL_ROW row, row2; + printf_mysql_query("SELECT `active`, `nick`, `server`, `port`, `pass`, `botclass`, `textbot`, `queue`, `defaulttrigger`, `max_channels`, `register_priority`, `id` FROM `bots`"); + res = mysql_use(); + table = table_init(7, mysql_num_rows(res) + 1, 0); + char *content[7]; + content[0] = get_language_string(user, "NS_BOTS_ID"); + content[1] = get_language_string(user, "NS_BOTS_NICK"); + content[2] = get_language_string(user, "NS_BOTS_SERVER"); + content[3] = get_language_string(user, "NS_BOTS_CLASS"); + content[4] = get_language_string(user, "NS_BOTS_FLAGS"); + content[5] = get_language_string(user, "NS_BOTS_CHANNELS"); + content[6] = get_language_string(user, "NS_BOTS_TRIGGER"); + table_add(table, content); + char botnick[NICKLEN + 3]; + char botserver[MAXLEN]; + char botflags[10]; + int flagspos; + char botchans[20]; + while ((row = mysql_fetch_row(res)) != NULL) { + content[0] = row[11]; + sprintf(botnick, (strcmp(row[0], "0") ? "%s" : "!%s"), row[1]); + content[1] = botnick; + sprintf(botserver, (strcmp(row[4], "") ? "%s:%s:*" : "%s:%s"), row[2], row[3]); + content[2] = botserver; + content[3] = (char *) resolve_botid(atoi(row[5])); + flagspos = 0; + if(!strcmp(row[6], "1")) + botflags[flagspos++] = 't'; + if(!strcmp(row[7], "1")) + botflags[flagspos++] = 'q'; + botflags[flagspos] = '\0'; + content[4] = botflags; + printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[11]); + res2 = mysql_use(); + row2 = mysql_fetch_row(res2); + sprintf(botchans, "%s/%s", row2[0], row[9]); + content[5] = botchans; + content[6] = row[8]; + table_add(table, content); + } + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_command.c b/src/modules/global.mod/cmd_global_command.c new file mode 100644 index 0000000..594ea1b --- /dev/null +++ b/src/modules/global.mod/cmd_global_command.c @@ -0,0 +1,179 @@ +/* cmd_global_command.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0-1] command +*/ +static int global_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan); +static int global_cmd_command_operaccess(struct cmd_binding *cbind); + +CMD_BIND(global_cmd_command) { + char *ident; + MYSQL_RES *res; + MYSQL_ROW row; + struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); + if (!cbind) { + reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); + return; + } + ident = argv[0]; + char parameters[MAXLEN]; + if(cbind->paramcount) { + int i, parampos = 0; + for(i = 0; i < cbind->paramcount; i++) { + parampos += sprintf(parameters + parampos, (i ? " %s" : "%s"), cbind->parameters[i]); + } + } else + parameters[0] = '\0'; + reply(getTextBot(), user, "NS_COMMAND_BINDING", cbind->cmd, cbind->func->name, parameters); + if(chan) + reply(getTextBot(), user, "NS_COMMAND_ACCESS", global_cmd_command_chanaccess(cbind, chan), global_cmd_command_operaccess(cbind)); + printf_mysql_query("SELECT `user_lang` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + char *lang; + if ((row = mysql_fetch_row(res)) != NULL) + lang = row[0]; + else + lang = "en"; + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(ident)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + if(stricmp(lang, "en")) { + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(ident)); + res = mysql_use(); + } + if ((row = mysql_fetch_row(res)) == NULL) { + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = '%s' AND `ident` = '%s'", escape_string(lang), escape_string(cbind->func->name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + if(stricmp(lang, "en")) { + printf_mysql_query("SELECT `text` FROM `help` WHERE `lang` = 'en' AND `ident` = '%s'", escape_string(cbind->func->name)); + res = mysql_use(); + } + if ((row = mysql_fetch_row(res)) == NULL) { + return; + } + } + } + } + char sendBuf[MAXLEN]; + int sendBufPos = 0; + int i; + for(i = 0; i < strlen(row[0]); i++) { + switch(row[0][i]) { + case '\n': + if(sendBufPos) { + sendBuf[sendBufPos] = '\0'; + reply(getTextBot(), user, "%s", sendBuf); + sendBufPos = 0; + } + break; + case '$': + switch(row[0][i+1]) { + case 'b': + sendBuf[sendBufPos++] = '\002'; + i++; + break; + case 'k': + sendBuf[sendBufPos++] = '\003'; + i++; + break; + case 'u': + sendBuf[sendBufPos++] = '\031'; + i++; + break; + case 'C': + case 'S': + sendBufPos += sprintf(sendBuf + sendBufPos, "%s", client->user->nick); + i++; + break; + default: + sendBuf[sendBufPos++] = '$'; + break; + } + break; + default: + sendBuf[sendBufPos++] = row[0][i]; + break; + } + } + if(sendBufPos) { + sendBuf[sendBufPos] = '\0'; + reply(getTextBot(), user, "%s", sendBuf); + sendBufPos = 0; + } +} + +static int global_cmd_command_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) { + char access_list[256]; + int access_pos = 0; + int access_count = 0; + int minaccess = 0; + char *str_a, *str_b = cbind->func->channel_access, *str_c; + if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) + str_b = cbind->channel_access; + access_list[0] = '\0'; + if(str_b) { + str_c = strdup(str_b); + str_b = str_c; + while((str_a = str_b)) { + str_b = strstr(str_a, ","); + if(str_b) { + *str_b = '\0'; + str_b++; + } + if(*str_a == '@' || *str_a == '+') { + //privs can override this access requirement + str_a++; + } + if(*str_a == '#') { + str_a++; + access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a); + access_count++; + } else { + if(atoi(str_a) > minaccess) + minaccess = atoi(str_a); + } + } + free(str_c); + } + if(access_count) { + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + int i, caccess; + for(i = 0; i < access_count; i++) { + if(!row[i] && !defaults) { + printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); + defaults = mysql_fetch_row(mysql_use()); + } + caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i])); + if(caccess > minaccess) + minaccess = caccess; + } + } + } + return minaccess; +} + +static int global_cmd_command_operaccess(struct cmd_binding *cbind) { + return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); +} diff --git a/src/modules/global.mod/cmd_global_commands.c b/src/modules/global.mod/cmd_global_commands.c new file mode 100644 index 0000000..caeac97 --- /dev/null +++ b/src/modules/global.mod/cmd_global_commands.c @@ -0,0 +1,153 @@ +/* cmd_global_commands.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] mask +*/ + +static int global_cmd_commands_sort(const void *a, const void *b); +static int global_cmd_commands_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan); +static int global_cmd_commands_operaccess(struct cmd_binding *cbind); + +CMD_BIND(global_cmd_commands) { + struct cmd_binding *cbind; + int bindcount = 0; + for(cbind = getAllBinds(NULL); cbind; cbind = getAllBinds(cbind)) { + if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && !(cbind->func->flags & CMDFLAG_FUNCMD)) + bindcount++; + } + struct cmd_binding *binds[bindcount]; + bindcount = 0; + for(cbind = getAllBinds(NULL); cbind; cbind = getAllBinds(cbind)) { + if(cbind->botid == client->botid && (cbind->botid || cbind->clientid == client->clientid) && !(cbind->func->flags & CMDFLAG_FUNCMD)) + binds[bindcount++] = cbind; + } + qsort(binds, bindcount, sizeof(struct cmd_binding *), global_cmd_commands_sort); + int i; + struct Table *table; + table = table_init(5, bindcount + 1, 0); + char *content[5]; + content[0] = get_language_string(user, "NS_COMMANDS_NAME"); + content[1] = get_language_string(user, "NS_COMMANDS_ACCESS"); + content[2] = get_language_string(user, "NS_COMMANDS_GACCESS"); + content[3] = get_language_string(user, "NS_COMMANDS_TRIGGERED"); + content[4] = get_language_string(user, "NS_COMMANDS_FUNCTION"); + table_add(table, content); + char caccess[5]; + char gaccess[5]; + char triggered[10]; + char funcname[MAXLEN]; + int funcpos; + for(i = 0; i < bindcount; i++) { + cbind = binds[i]; + content[0] = cbind->cmd; + sprintf(caccess, "%d", global_cmd_commands_chanaccess(cbind, chan)); + content[1] = caccess; + sprintf(gaccess, "%d", global_cmd_commands_operaccess(cbind)); + content[2] = gaccess; + sprintf(triggered, "%d", cbind->triggered); + content[3] = triggered; + funcpos = sprintf(funcname, "%s", cbind->func->name); + if(cbind->paramcount) { + int j; + for(j = 0; j < cbind->paramcount; j++) { + funcpos += sprintf(funcname + funcpos, " %s", cbind->parameters[j]); + } + } + content[4] = funcname; + table_add(table, content); + } + //send the table + char **table_lines = table_end(table); + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); +} + +static int global_cmd_commands_sort(const void *a, const void *b) { + const struct cmd_binding *bind_a = *((struct cmd_binding * const *) a); + const struct cmd_binding *bind_b = *((struct cmd_binding * const *) b); + int i = stricmp(bind_a->func->name, bind_b->func->name); + if(i == 0) { + return stricmp(bind_a->cmd, bind_b->cmd); + } else + return i; +} + +static int global_cmd_commands_chanaccess(struct cmd_binding *cbind, struct ChanNode *chan) { + char access_list[256]; + int access_pos = 0; + int access_count = 0; + int minaccess = 0; + char *str_a, *str_b = cbind->func->channel_access, *str_c; + if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) + str_b = cbind->channel_access; + access_list[0] = '\0'; + if(str_b) { + str_c = strdup(str_b); + str_b = str_c; + while((str_a = str_b)) { + str_b = strstr(str_a, ","); + if(str_b) { + *str_b = '\0'; + str_b++; + } + if(*str_a == '@' || *str_a == '+') { + //privs can override this access requirement + str_a++; + } + if(*str_a == '#') { + str_a++; + access_pos += sprintf(access_list+access_pos, (access_pos ? ", `%s`" : "`%s`"), str_a); + access_count++; + } else { + if(atoi(str_a) > minaccess) + minaccess = atoi(str_a); + } + } + free(str_c); + } + if(access_count) { + if(!chan) { + return -1; + } + MYSQL_RES *res; + MYSQL_ROW row, defaults = NULL; + printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = '%s'", access_list, escape_string(chan->name)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + int i, caccess; + for(i = 0; i < access_count; i++) { + if(!row[i] && !defaults) { + printf_mysql_query("SELECT %s FROM `channels` WHERE `channel_name` = 'defaults'", access_list); + defaults = mysql_fetch_row(mysql_use()); + } + caccess = (row[i] ? atoi(row[i]) : atoi(defaults[i])); + if(caccess > minaccess) + minaccess = caccess; + } + } + } + return minaccess; +} + +static int global_cmd_commands_operaccess(struct cmd_binding *cbind) { + return ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); +} diff --git a/src/modules/global.mod/cmd_global_delbot.c b/src/modules/global.mod/cmd_global_delbot.c new file mode 100644 index 0000000..b017f12 --- /dev/null +++ b/src/modules/global.mod/cmd_global_delbot.c @@ -0,0 +1,45 @@ +/* cmd_global_delbot.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] nick/botid +*/ + +CMD_BIND(global_cmd_delbot) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s' OR `id` = '%s'", escape_string(argv[0]), escape_string(argv[0])); + res = mysql_use(); + if((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_DELBOT_NOT_FOUND", argv[0]); + return; + } + int botid = atoi(row[0]); + printf_mysql_query("DELETE FROM `bots` WHERE `id` = '%s'", row[0]); + printf_mysql_query("DELETE FROM `bot_binds` WHERE `botid` = '%s'", row[0]); + printf_mysql_query("DELETE FROM `bot_channels` WHERE `botid` = '%s'", row[0]); + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == botid) { + close_socket(client); + break; + } + } + reply(getTextBot(), user, "NS_DELBOT_DONE"); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_die.c b/src/modules/global.mod/cmd_global_die.c new file mode 100644 index 0000000..c80b0b0 --- /dev/null +++ b/src/modules/global.mod/cmd_global_die.c @@ -0,0 +1,27 @@ +/* cmd_global_die.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* no args +*/ + +CMD_BIND(global_cmd_die) { + //hard work! :D + stop_bot(); +} diff --git a/src/modules/global.mod/cmd_global_emote.c b/src/modules/global.mod/cmd_global_emote.c new file mode 100644 index 0000000..494e5e3 --- /dev/null +++ b/src/modules/global.mod/cmd_global_emote.c @@ -0,0 +1,28 @@ +/* cmd_global_emote.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] target +* argv[1-*] message +*/ + +CMD_BIND(global_cmd_emote) { + char *message = merge_argv(argv, 1, argc); + putsock(client, "PRIVMSG %s :\001ACTION %s\001", argv[0], message); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_god.c b/src/modules/global.mod/cmd_global_god.c new file mode 100644 index 0000000..3e54b7f --- /dev/null +++ b/src/modules/global.mod/cmd_global_god.c @@ -0,0 +1,53 @@ +/* cmd_global_god.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] (optional) on/off +*/ + +CMD_BIND(global_cmd_god) { + if(argc > 0) { + if(!strcmp(argv[0], "0") || !stricmp(argv[0], "off") || !stricmp(argv[0], get_language_string(user, "NS_SET_OFF"))) { + if(isGodMode(user)) { + printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth)); + user->flags &= ~USERFLAG_GOD_MODE; + } + reply(getTextBot(), user, "NS_GOD_OFF"); + } else if(!strcmp(argv[0], "1") || !stricmp(argv[0], "on") || !stricmp(argv[0], get_language_string(user, "NS_SET_ON"))) { + if(!isGodMode(user)) { + printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth)); + user->flags |= USERFLAG_GOD_MODE; + } + reply(getTextBot(), user, "NS_GOD_ON"); + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", argv[0]); + return; + } + } else { + if(isGodMode(user)) { + printf_mysql_query("UPDATE `users` SET `user_god` = '0' WHERE `user_user` = '%s'", escape_string(user->auth)); + user->flags &= ~USERFLAG_GOD_MODE; + reply(getTextBot(), user, "NS_GOD_OFF"); + } else { + printf_mysql_query("UPDATE `users` SET `user_god` = '1' WHERE `user_user` = '%s'", escape_string(user->auth)); + user->flags |= USERFLAG_GOD_MODE; + reply(getTextBot(), user, "NS_GOD_ON"); + } + } +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_meminfo.c b/src/modules/global.mod/cmd_global_meminfo.c new file mode 100644 index 0000000..bdcf45a --- /dev/null +++ b/src/modules/global.mod/cmd_global_meminfo.c @@ -0,0 +1,118 @@ +/* cmd_global_meminfo.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" +#include "memoryInfo.h" + +/* +* no arguments +*/ + +CMD_BIND(global_cmd_meminfo) { + #ifndef ENABLE_MEMORY_DEBUG + reply(getTextBot(), user, "NS_MEMINFO_DISABLED"); + #else + if(argc > 0) { + struct Table *table; + int elementcount = 0; + struct memoryInfoLines *element, *elements; + elements = getMemoryInfoLines(argv[0]); + for(element = elements; element; element = element->next) { + elementcount++; + } + table = table_init(4, elementcount+2, 0); + char *content[4]; + content[0] = get_language_string(user, "NS_MEMINFO_LINE"); + content[1] = get_language_string(user, "NS_MEMINFO_COUNT"); + content[2] = get_language_string(user, "NS_MEMINFO_SIZE"); + content[3] = get_language_string(user, "NS_MEMINFO_TOTAL"); + table_add(table, content); + char lineBuf[20]; + char countBuf[20]; + char sizeBuf[20]; + char totalBuf[50]; + unsigned int total_allocations = 0; + unsigned int total_allocated = 0; + for(element = elements; element; element = element->next) { + sprintf(lineBuf, "%u", element->line); + content[0] = lineBuf; + sprintf(countBuf, "%u", element->allocations); + total_allocations += element->allocations; + content[1] = countBuf; + sprintf(sizeBuf, "%uB", element->allocate); + content[2] = sizeBuf; + sprintf(totalBuf, "%u (%.2f kB)", (element->allocate * element->allocations), ((float)(element->allocate * element->allocations) / 1024)); + total_allocated += (element->allocate * element->allocations); + content[3] = totalBuf; + table_add(table, content); + } + content[0] = "Total"; + sprintf(countBuf, "%u", total_allocations); + content[1] = countBuf; + content[2] = "*"; + sprintf(sizeBuf, "%u (%.2f kB)", total_allocated, ((float)total_allocated / 1024)); + content[3] = sizeBuf; + table_add(table, content); + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + } else { + struct Table *table; + int elementcount = 0; + struct memoryInfoFiles *element, *elements; + elements = getMemoryInfoFiles(); + for(element = elements; element; element = element->next) { + elementcount++; + } + table = table_init(3, elementcount+2, 0); + char *content[3]; + content[0] = get_language_string(user, "NS_MEMINFO_NAME"); + content[1] = get_language_string(user, "NS_MEMINFO_COUNT"); + content[2] = get_language_string(user, "NS_MEMINFO_SIZE"); + table_add(table, content); + char countBuf[20]; + char sizeBuf[50]; + unsigned int total_allocations = 0; + unsigned int total_allocated = 0; + for(element = elements; element; element = element->next) { + content[0] = element->filename; + sprintf(countBuf, "%u", element->allocations); + total_allocations += element->allocations; + content[1] = countBuf; + sprintf(sizeBuf, "%u (%.2f kB)", element->allocated, ((float)element->allocated / 1024)); + total_allocated += element->allocated; + content[2] = sizeBuf; + table_add(table, content); + } + content[0] = "Total"; + sprintf(countBuf, "%u", total_allocations); + content[1] = countBuf; + sprintf(sizeBuf, "%u (%.2f kB)", total_allocated, ((float)total_allocated / 1024)); + content[2] = sizeBuf; + table_add(table, content); + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); + } + #endif +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_modcmd.c b/src/modules/global.mod/cmd_global_modcmd.c new file mode 100644 index 0000000..1506a35 --- /dev/null +++ b/src/modules/global.mod/cmd_global_modcmd.c @@ -0,0 +1,222 @@ +/* cmd_global_modcmd.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] command +* argv[1] setting +* argv[2] value +*/ + +static int global_cmd_modcmd_params(struct UserNode *user, struct cmd_binding *cbind, char *value); +static int global_cmd_modcmd_flags(struct UserNode *user, struct cmd_binding *cbind, char *value); +static int global_cmd_modcmd_caccess(struct UserNode *user, struct cmd_binding *cbind, char *value); +static int global_cmd_modcmd_oaccess(struct UserNode *user, struct cmd_binding *cbind, char *value); + +CMD_BIND(global_cmd_modcmd) { + MYSQL_RES *res; + MYSQL_ROW row; + struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); + if (!cbind) { + reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); + return; + } + int uaccess = 0; + printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + uaccess = atoi(row[0]); + } + int gaccess = ((cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) ? cbind->global_access : cbind->func->global_access); + if(gaccess > uaccess) { + reply(getTextBot(), user, "NS_MODCMD_OUTRANKED", cbind->cmd, gaccess); + return; + } + if(argc > 1) { + char *value; + if(argc > 2) { + value = merge_argv(argv, 2, argc); + } else + value = NULL; + int log_event = 0; + if(!stricmp(argv[1], "caccess")) log_event = global_cmd_modcmd_caccess(user, cbind, value); + else if(!stricmp(argv[1], "oaccess")) log_event = global_cmd_modcmd_oaccess(user, cbind, value); + else if(!stricmp(argv[1], "parameters")) log_event = global_cmd_modcmd_params(user, cbind, value); + else if(!stricmp(argv[1], "flags")) log_event = global_cmd_modcmd_flags(user, cbind, value); + else { + reply(getTextBot(), user, "NS_MODCMD_SETTING", argv[1]); + } + if(log_event) { + logEvent(event); + } + } else { + reply(getTextBot(), user, "NS_MODCMD_HEADER", cbind->cmd); + global_cmd_modcmd_params(user, cbind, NULL); + global_cmd_modcmd_caccess(user, cbind, NULL); + global_cmd_modcmd_oaccess(user, cbind, NULL); + global_cmd_modcmd_flags(user, cbind, NULL); + } +} + +static int global_cmd_modcmd_params(struct UserNode *user, struct cmd_binding *cbind, char *value) { + char parameters[MAXLEN]; + int ret = 0; + if(cbind->paramcount) { + int i, parampos = 0; + for(i = 0; i < cbind->paramcount; i++) { + parampos += sprintf(parameters + parampos, (i ? " %s" : "%s"), cbind->parameters[i]); + } + } else + parameters[0] = '\0'; + if(value) { + if(!strcmp(value, "*")) + value = NULL; + bind_botwise_set_parameters(cbind->botid, cbind->clientid, cbind->cmd, value); + if(cbind->botid == 0) + printf_mysql_query("UPDATE `bot_binds` SET `parameters` = '%s' WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? escape_string(value) : ""), cbind->clientid, escape_string(cbind->cmd)); + else + printf_mysql_query("UPDATE `bot_binds` SET `parameters` = '%s' WHERE `botclass` = '%d' AND `command` = '%s'", (value ? escape_string(value) : ""), cbind->botid, escape_string(cbind->cmd)); + strcpy(parameters, (value ? value : "")); + ret = 1; + } + reply(getTextBot(), user, "\002PARAMETERS \002 %s", parameters); + return ret; +} + +static const struct { + const char *name; + unsigned int flag; +} global_cmd_modcmd_show_flags[] = { + {"REQUIRE_CHAN", CMDFLAG_REQUIRE_CHAN}, //The command requires a valid channel (at least one bot in it) + {"REQUIRE_AUTH", CMDFLAG_REQUIRE_AUTH}, //The command requires the user to be authenticated + {"REQUIRE_GOD", CMDFLAG_REQUIRE_GOD}, //The command requires the user to have security override enabled + {"REQUIRE_REGISTERED", CMDFLAG_REGISTERED_CHAN}, //The command requires the channel to be registered (database entry) + {"CHECK_AUTH", CMDFLAG_CHECK_AUTH}, //WHO the user if no auth is known, yet + {"CHANNEL_ARGS", CMDFLAG_CHAN_PARAM}, //don't interpret channel arguments as channel - just pass them as a string + {"LOG", CMDFLAG_LOG}, + {"OPLOG", CMDFLAG_OPLOG}, + {"FUNCMD", CMDFLAG_FUNCMD}, + {"ESCAPED_ARGS", CMDFLAG_ESCAPE_ARGS}, //allows arguments to be escaped ("a\ b" = "a b" as one argument) + {"NO_CROSSCHAN", CMDFLAG_NO_CROSSCHAN}, + {NULL, 0} +}; + +static int global_cmd_modcmd_flags(struct UserNode *user, struct cmd_binding *cbind, char *value) { + char flags[MAXLEN]; + int flagpos = 0; + int ret = 0; + unsigned int visible_flags = 0; + int i = 0; + while(global_cmd_modcmd_show_flags[i].name) { + if(cbind->func->flags & global_cmd_modcmd_show_flags[i].flag) { + flagpos += sprintf(flags + flagpos, (flagpos ? " %s" : "\00314%s"), global_cmd_modcmd_show_flags[i].name); + } + visible_flags |= global_cmd_modcmd_show_flags[i].flag; + i++; + } + if(flagpos) + flags[flagpos++] = '\003'; + if(value) { + int add = 1; + unsigned int current_flag = 0; + if(value[0] == '+') { + value++; + } else if(value[0] == '-') { + add = 0; + value++; + } + if(*value) { + i = 0; + while(global_cmd_modcmd_show_flags[i].name) { + if(!stricmp(global_cmd_modcmd_show_flags[i].name, value)) { + current_flag = global_cmd_modcmd_show_flags[i].flag; + break; + } + i++; + } + } + if(cbind->func->flags & current_flag) { + reply(getTextBot(), user, "NS_MODCMD_STATIC_FLAG"); + return 0; + } + if(add) + cbind->flags |= current_flag; + else + cbind->flags &= ~current_flag; + if(cbind->botid == 0) + printf_mysql_query("UPDATE `bot_binds` SET `flags` = '%u' WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (cbind->flags & visible_flags), cbind->clientid, escape_string(cbind->cmd)); + else + printf_mysql_query("UPDATE `bot_binds` SET `flags` = '%u' WHERE `botclass` = '%d' AND `command` = '%s'", (cbind->flags & visible_flags), cbind->botid, escape_string(cbind->cmd)); + ret = 1; + } + i = 0; + while(global_cmd_modcmd_show_flags[i].name) { + if(cbind->flags & global_cmd_modcmd_show_flags[i].flag) { + flagpos += sprintf(flags + flagpos, (flagpos ? " %s" : "%s"), global_cmd_modcmd_show_flags[i].name); + } + i++; + } + flags[flagpos] = '\0'; + reply(getTextBot(), user, "\002FLAGS \002 %s", flags); + return ret; +} + +static int global_cmd_modcmd_caccess(struct UserNode *user, struct cmd_binding *cbind, char *value) { + char caccess[MAXLEN]; + int ret = 0; + if(value) { + if(!strcmp(value, "*")) + value = NULL; + bind_botwise_set_channel_access(cbind->botid, cbind->clientid, cbind->cmd, value); + if(cbind->botid == 0) + printf_mysql_query("UPDATE `bot_binds` SET `chan_access` = %s%s%s WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->clientid, escape_string(cbind->cmd)); + else + printf_mysql_query("UPDATE `bot_binds` SET `chan_access` = %s%s%s WHERE `botclass` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->botid, escape_string(cbind->cmd)); + + ret = 1; + } + if(cbind->flags & CMDFLAG_OVERRIDE_CHANNEL_ACCESS) + sprintf(caccess, "%s", cbind->channel_access); + else + sprintf(caccess, "\00314%s\003", (cbind->func->channel_access ? cbind->func->channel_access : "0")); + reply(getTextBot(), user, "\002CACCESS \002 %s", caccess); + return ret; +} + +static int global_cmd_modcmd_oaccess(struct UserNode *user, struct cmd_binding *cbind, char *value) { + char oaccess[MAXLEN]; + int ret = 0; + if(value) { + if(!strcmp(value, "*")) + value = NULL; + bind_botwise_set_global_access(cbind->botid, cbind->clientid, cbind->cmd, atoi(value)); + if(cbind->botid == 0) + printf_mysql_query("UPDATE `bot_binds` SET `global_access` = %s%s%s WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->clientid, escape_string(cbind->cmd)); + else + printf_mysql_query("UPDATE `bot_binds` SET `global_access` = %s%s%s WHERE `botclass` = '%d' AND `command` = '%s'", (value ? "'" : ""), (value ? escape_string(value) : "NULL"), (value ? "'" : ""), cbind->botid, escape_string(cbind->cmd)); + + ret = 1; + } + if(cbind->flags & CMDFLAG_OVERRIDE_GLOBAL_ACCESS) + sprintf(oaccess, "%d", cbind->global_access); + else + sprintf(oaccess, "\00314%d\003", (cbind->func->global_access ? cbind->func->global_access : 0)); + reply(getTextBot(), user, "\002OACCESS \002 %s", oaccess); + return ret; +} + diff --git a/src/modules/global.mod/cmd_global_motd.c b/src/modules/global.mod/cmd_global_motd.c new file mode 100644 index 0000000..0340e47 --- /dev/null +++ b/src/modules/global.mod/cmd_global_motd.c @@ -0,0 +1,36 @@ +/* cmd_global_motd.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* no args +*/ + +CMD_BIND(global_cmd_motd) { + FILE *f; + f = fopen("motd.txt", "rb"); + if(!f) return; + char line[MAXLEN]; + char *a; + while (fgets(line, MAXLEN, f) != NULL) { + if((a = strchr(line, '\n'))) + *a = '\0'; + reply(getTextBot(), user, "%s", line); + } + fclose(f); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_netinfo.c b/src/modules/global.mod/cmd_global_netinfo.c new file mode 100644 index 0000000..3d01c98 --- /dev/null +++ b/src/modules/global.mod/cmd_global_netinfo.c @@ -0,0 +1,177 @@ +/* cmd_global_netinfo.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* no args +*/ + +CMD_BIND(global_cmd_netinfo) { + reply(getTextBot(), user, "NS_NETINFO_HEADER"); + char tmp[MAXLEN]; + struct Table *table; + table = table_init(2, 19, 0); + char *content[2]; + + content[0] = get_language_string(user, "NS_NETINFO_UPTIME"); + content[1] = timeToStr(user, (time(0) - start_time), 3, tmp); + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_BOTS"); + struct ClientSocket *cclient; + int bot_count = 0, connected_bot_count = 0; + float traffic_in = 0, traffic_out = 0; + for(cclient = getBots(0, NULL); cclient; cclient = getBots(0, cclient)) { + bot_count++; + if(cclient->flags & SOCKET_FLAG_READY) + connected_bot_count++; + traffic_in += cclient->traffic_in; + traffic_out += cclient->traffic_out; + } + sprintf(tmp, "%d (%d connected)", bot_count, connected_bot_count); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_TRAFFIC"); + sprintf(tmp, "in: %.2f kb out: %.2f kb", traffic_in / 1024, traffic_out / 1024); + content[1] = tmp; + table_add(table, content); + + int channel_count = getChannelCount(); + float channel_memory = channel_count * sizeof(struct ChanNode); + int channel_ban_count = getChanBanCount(); + float channel_ban_memory = channel_ban_count * sizeof(struct BanNode); + int user_count = getUserCount(); + float user_memory = user_count * sizeof(struct UserNode); + int chanuser_count = getChanUserCount(); + float chanuser_memory = chanuser_count * sizeof(struct ChanUser); + float total_memory = channel_memory + channel_ban_memory + user_memory + chanuser_memory; + content[0] = get_language_string(user, "NS_NETINFO_CACHE"); + sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024); + content[1] = tmp; + table_add(table, content); + content[0] = get_language_string(user, "NS_NETINFO_CHANNEL"); + sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", channel_count, channel_memory / 1024, channel_count, (unsigned int) sizeof(struct ChanNode), channel_memory / 1024); + content[1] = tmp; + table_add(table, content); + content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN"); + sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", channel_ban_count, channel_ban_memory / 1024, channel_ban_count, (unsigned int) sizeof(struct BanNode), channel_ban_memory / 1024); + content[1] = tmp; + table_add(table, content); + content[0] = get_language_string(user, "NS_NETINFO_USER"); + sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", user_count, user_memory / 1024, user_count, (unsigned int) sizeof(struct UserNode), user_memory / 1024); + content[1] = tmp; + table_add(table, content); + content[0] = get_language_string(user, "NS_NETINFO_CHANUSER"); + sprintf(tmp, "%d %.2f kB (%d * %u B = %.2f kB)", chanuser_count, chanuser_memory / 1024, chanuser_count, (unsigned int) sizeof(struct ChanUser), chanuser_memory / 1024); + content[1] = tmp; + table_add(table, content); + + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SHOW TABLE STATUS"); + res = mysql_use(); + int mysql_entrys[4]; + float mysql_length[5]; + total_memory = 0; + mysql_entrys[0] = 0; mysql_entrys[1] = 0; mysql_entrys[2] = 0; mysql_entrys[3] = 0; + mysql_length[0] = 0; mysql_length[1] = 0; mysql_length[2] = 0; mysql_length[3] = 0; mysql_length[4] = 0; + while ((row = mysql_fetch_row(res)) != NULL) { + if(!stricmp(row[0], "channels")) { + mysql_entrys[0] = atoi(row[4]); + mysql_length[0] = atof(row[6]); + total_memory += atof(row[6]); + } else if(!stricmp(row[0], "bans")) { + mysql_entrys[1] = atoi(row[4]); + mysql_length[1] = atof(row[6]); + total_memory += atof(row[6]); + } else if(!stricmp(row[0], "users")) { + mysql_entrys[2] = atoi(row[4]); + mysql_length[2] = atof(row[6]); + total_memory += atof(row[6]); + } else if(!stricmp(row[0], "chanusers")) { + mysql_entrys[3] = atoi(row[4]); + mysql_length[3] = atof(row[6]); + total_memory += atof(row[6]); + } else { + mysql_length[4] += atof(row[6]); + total_memory += atof(row[6]); + } + } + + content[0] = get_language_string(user, "NS_NETINFO_DATABASE"); + sprintf(tmp, "%.2f kB (%.2f MB)", total_memory / 1024, total_memory / 1024 / 1024); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_CHANNEL"); + sprintf(tmp, "%d %.2f kB", mysql_entrys[0], mysql_length[0] / 1024); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_CHANNEL_BAN"); + sprintf(tmp, "%d %.2f kB", mysql_entrys[1], mysql_length[1] / 1024); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_USER"); + sprintf(tmp, "%d %.2f kB", mysql_entrys[2], mysql_length[2] / 1024); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_CHANUSER"); + sprintf(tmp, "%d %.2f kB", mysql_entrys[3], mysql_length[3] / 1024); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_OTHER"); + sprintf(tmp, "* %.2f kB", mysql_length[4] / 1024); + content[1] = tmp; + table_add(table, content); + + #ifdef HAVE_THREADS + content[0] = get_language_string(user, "NS_NETINFO_THREADS"); + sprintf(tmp, "%d (current thread: %i)", running_threads, getCurrentThreadID()); + content[1] = tmp; + table_add(table, content); + #endif + + if(strcmp(revision, "")) + sprintf(tmp, "%s.%d (%s)", NEONSERV_VERSION, patchlevel, revision); + else + sprintf(tmp, "%s.%d", NEONSERV_VERSION, patchlevel); + content[0] = get_language_string(user, "NS_NETINFO_VERSION"); + content[1] = tmp; + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_COMPILER"); + content[1] = build_language_string(user, tmp, "NS_NETINFO_COMPILER_VALUE", COMPILER, creation); + table_add(table, content); + + content[0] = get_language_string(user, "NS_NETINFO_CODE"); + content[1] = build_language_string(user, tmp, "NS_NETINFO_CODE_VALUE", codelines); + table_add(table, content); + + char **table_lines = table_end(table); + int i; + for(i = 0; i < table->entrys; i++) { + reply(getTextBot(), user, table_lines[i]); + } + table_free(table); +} + diff --git a/src/modules/global.mod/cmd_global_notice.c b/src/modules/global.mod/cmd_global_notice.c new file mode 100644 index 0000000..b42b1c3 --- /dev/null +++ b/src/modules/global.mod/cmd_global_notice.c @@ -0,0 +1,28 @@ +/* cmd_global_notice.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] target +* argv[1-*] message +*/ + +CMD_BIND(global_cmd_notice) { + char *message = merge_argv(argv, 1, argc); + putsock(client, "NOTICE %s :%s", argv[0], message); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_raw.c b/src/modules/global.mod/cmd_global_raw.c new file mode 100644 index 0000000..1d8ce55 --- /dev/null +++ b/src/modules/global.mod/cmd_global_raw.c @@ -0,0 +1,27 @@ +/* cmd_global_raw.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0-*] raw +*/ + +CMD_BIND(global_cmd_raw) { + char *raw = merge_argv(argv, 0, argc); + putsock(client, "%s", raw); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_reconnect.c b/src/modules/global.mod/cmd_global_reconnect.c new file mode 100644 index 0000000..acf8c2e --- /dev/null +++ b/src/modules/global.mod/cmd_global_reconnect.c @@ -0,0 +1,49 @@ +/* cmd_global_reconnect.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] nick/botid +*/ + +CMD_BIND(global_cmd_reconnect) { + int botid; + if(argc) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `id` FROM `bots` WHERE `nick` = '%s' OR `id` = '%s'", escape_string(argv[0]), escape_string(argv[0])); + res = mysql_use(); + if((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_DELBOT_NOT_FOUND", argv[0]); + return; + } + botid = atoi(row[0]); + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == botid) { + disconnect_socket(client); + client->flags |= SOCKET_FLAG_FAST_JUMP; + break; + } + } + } else { + disconnect_socket(client); + connect_socket(client); + } + reply(getTextBot(), user, "NS_RECONNECT_DONE"); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_register.c b/src/modules/global.mod/cmd_global_register.c new file mode 100644 index 0000000..548860d --- /dev/null +++ b/src/modules/global.mod/cmd_global_register.c @@ -0,0 +1,266 @@ +/* cmd_global_register.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] - channel +* argv[1] - nick / *auth +* argv[2] - (optional) bot nick +*/ +static AUTHLOOKUP_CALLBACK(global_cmd_register_auth_lookup); +static USERAUTH_CALLBACK(global_cmd_register_nick_lookup); +static void global_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth, int multibot, char *botname); + +struct global_cmd_register_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct ChanNode *chan; + struct Event *event; + char *nick; + char *channel; + char *botname; + int multibot; +}; + +CMD_BIND(global_cmd_register) { + MYSQL_RES *res; + MYSQL_ROW row; + char *channel = argv[0]; + char *botname = (argc > 2 ? argv[2] : NULL); + int multibot = 0; + if(!is_valid_chan(channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); + return; + } + printf_mysql_query("SELECT `botid`, `botclass` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` LEFT JOIN `channels` ON `bot_channels`.`chanid` = `channels`.`channel_id` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(atoi(row[1]) == client->botid && (client->botid || client->clientid == atoi(row[0]))) { + reply(getTextBot(), user, "NS_REGISTER_ALREADY", argv[0], client->user->nick); + return; + } else + multibot = 1; + } + printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(channel)); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + int expire_time = atoi(row[1]); + if(expire_time) { + if(expire_time - time(0) <= 0) { + printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); + } else { + char expireBuf[MAXLEN]; + reply(getTextBot(), user, "NS_DNR_SET_EXPIRES", channel, row[0], timeToStr(user, (expire_time - time(0)), 2, expireBuf), row[2]); + return; + } + } else { + reply(getTextBot(), user, "NS_DNR_SET", channel, row[0], row[2]); + return; + } + } + //if theres already another bot in the channel we don't need a owner parameter... + if(multibot && argc < 2) { + //skip all these owner check lines + multibot = 2; + global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, NULL, multibot, botname); + return; + } else if(argc < 2) { + global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, user->auth, multibot, botname); + return; + } + //check own access + if(argv[1][0] == '*') { + //we've got an auth + argv[1]++; + printf_mysql_query("SELECT `user_user` FROM `users` WHERE `user_user` = '%s'", escape_string(argv[1])); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, row[0], multibot, botname); + } else { + //we need to create a new user... + //but first lookup the auth to check if it really exists + struct global_cmd_register_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(argv[1]); + cache->channel = strdup(channel); + cache->multibot = multibot; + cache->botname = (botname ? strdup(botname) : NULL); + lookup_authname(argv[1], global_cmd_register_auth_lookup, cache); + } + } else { + struct UserNode *cuser = getUserByNick(argv[1]); + if(!cuser) { + cuser = createTempUser(argv[1]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[1]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + global_cmd_register_async1(client, getTextBot(), user, chan, event, channel, cuser->auth, multibot, botname); + } else { + struct global_cmd_register_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->chan = chan; + cache->event = event; + cache->nick = strdup(argv[1]); + cache->channel = strdup(channel); + cache->multibot = multibot; + cache->botname = (botname ? strdup(botname) : NULL); + get_userauth(cuser, global_cmd_register_nick_lookup, cache); + } + } +} + +static AUTHLOOKUP_CALLBACK(global_cmd_register_auth_lookup) { + struct global_cmd_register_cache *cache = data; + if(!exists) { + //AUTH_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); + } else + global_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, auth, cache->multibot, cache->botname); + if(cache->botname) + free(cache->botname); + free(cache->channel); + free(cache->nick); + free(cache); +} + +static USERAUTH_CALLBACK(global_cmd_register_nick_lookup) { + struct global_cmd_register_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + global_cmd_register_async1(cache->client, cache->textclient, cache->user, cache->chan, cache->event, cache->channel, user->auth, cache->multibot, cache->botname); + if(cache->botname) + free(cache->botname); + free(cache->channel); + free(cache->nick); + free(cache); +} + +static void global_cmd_register_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *channel, char *auth, int multibot, char *botname) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row, row2; + int userid = 0, adminid; + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) + adminid = atoi(row[0]); + else + adminid = 0; + if(multibot != 2) { + printf_mysql_query("SELECT `user_user`, `dnr_timeout`, `dnr_reason`, `dnr_id` FROM `donotregister` LEFT JOIN `users` ON `dnr_user` = `user_id` WHERE `dnr_target` = '%s'", escape_string(auth)); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + int expire_time = atoi(row[1]); + if(expire_time) { + if(expire_time - time(0) <= 0) { + printf_mysql_query("DELETE FROM `donotregister` WHERE `dnr_id` = '%s'", row[3]); + } else { + char expireBuf[MAXLEN]; + reply(getTextBot(), user, "NS_DNR_SET_EXPIRES", auth, row[0], timeToStr(user, (expire_time - time(0)), 2, expireBuf), row[2]); + return; + } + } else { + reply(getTextBot(), user, "NS_DNR_SET", auth, row[0], row[2]); + return; + } + } + printf_mysql_query("SELECT `user_id` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + userid = atoi(row[0]); + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`) VALUES ('%s')", escape_string(auth)); + userid = (int) mysql_insert_id(get_mysql_conn()); + } + } + if(client->botid) + printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger`, `nick` FROM `bots` WHERE `botclass` = '%d' AND `active` = '1' ORDER BY `register_priority` DESC", client->botid); + else + printf_mysql_query("SELECT `id`, `max_channels`, `defaulttrigger`, `nick` FROM `bots` WHERE `id` = '%d' AND `active` = '1'", client->clientid); + res = mysql_use(); + int botid = 0; + while ((row = mysql_fetch_row(res)) != NULL) { + //check channel count + printf_mysql_query("SELECT COUNT(*) FROM `bot_channels` WHERE `botid` = '%s'", row[0]); + row2 = mysql_fetch_row(mysql_use()); + if(atoi(row2[0]) < atoi(row[1]) && (!botname || !stricmp(botname, row[3]))) { + botid = atoi(row[0]); + break; + } + } + if(!botid) { + reply(textclient, user, "NS_REGISTER_FULL"); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + printf_mysql_query("UPDATE `channels` SET `channel_registered` = UNIX_TIMESTAMP(), `channel_registrator` = '%d' WHERE `channel_id` = '%d'", adminid, chanid); + } else { + printf_mysql_query("INSERT INTO `channels` (`channel_name`, `channel_registered`, `channel_registrator`) VALUES ('%s', UNIX_TIMESTAMP(), '%d')", escape_string(channel), adminid); + chanid = (int) mysql_insert_id(get_mysql_conn()); + } + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + if(bot) { + putsock(bot, "JOIN %s", channel); + } else + reply(textclient, user, "NS_REGISTER_DISCONNECTED", channel); + printf_mysql_query("INSERT INTO `bot_channels` (`botid`, `chanid`, `trigger`) VALUES ('%d', '%d', NULL)", botid, chanid); + if(multibot != 2) { + if(multibot) { + printf_mysql_query("UPDATE `chanusers` SET `chanuser_access` = 499 WHERE `chanuser_cid` = '%d' AND `chanuser_access` = '500'", chanid); + printf_mysql_query("DELETE FROM `chanusers` WHERE `chanuser_cid` = '%d' AND `chanuser_uid` = '%d'", chanid, userid); + } else + 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); + } else + reply(textclient, user, "NS_REGISTER_DONE_NOAUTH", channel); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_reload.c b/src/modules/global.mod/cmd_global_reload.c new file mode 100644 index 0000000..883b3ed --- /dev/null +++ b/src/modules/global.mod/cmd_global_reload.c @@ -0,0 +1,27 @@ +/* cmd_global_reload.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] soft (optional) +*/ + +CMD_BIND(global_cmd_reload) { + reload_config(); + reply(client, user, "reloaded."); +} diff --git a/src/modules/global.mod/cmd_global_reloadlang.c b/src/modules/global.mod/cmd_global_reloadlang.c new file mode 100644 index 0000000..d99062e --- /dev/null +++ b/src/modules/global.mod/cmd_global_reloadlang.c @@ -0,0 +1,35 @@ +/* cmd_global_reloadlang.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] language tag +*/ + +CMD_BIND(global_cmd_reloadlang) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `text`, `lang` FROM `language` WHERE `ident` = 'name' AND `lang` = '%s'", escape_string(argv[0])); + res = mysql_use(); + if((row = mysql_fetch_row(res)) != NULL) { + load_language(row[1], row[0]); + reply(getTextBot(), user, "NS_RELOADLANG_DONE", row[0], row[1]); + } else { + reply(getTextBot(), user, "NS_RELOADLANG_UNKNOWN", argv[0]); + } +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_restart.c b/src/modules/global.mod/cmd_global_restart.c new file mode 100644 index 0000000..ad580cd --- /dev/null +++ b/src/modules/global.mod/cmd_global_restart.c @@ -0,0 +1,28 @@ +/* cmd_global_restart.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] soft (optional) +*/ + +CMD_BIND(global_cmd_restart) { + int hard_restart = 1; + if(argc > 0 && !stricmp(argv[0], "soft")) hard_restart = 0; + restart_bot(hard_restart); +} diff --git a/src/modules/global.mod/cmd_global_say.c b/src/modules/global.mod/cmd_global_say.c new file mode 100644 index 0000000..e81cfc4 --- /dev/null +++ b/src/modules/global.mod/cmd_global_say.c @@ -0,0 +1,28 @@ +/* cmd_global_say.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] target +* argv[1-*] message +*/ + +CMD_BIND(global_cmd_say) { + char *message = merge_argv(argv, 1, argc); + putsock(client, "PRIVMSG %s :%s", argv[0], message); +} \ No newline at end of file diff --git a/src/modules/global.mod/cmd_global_setaccess.c b/src/modules/global.mod/cmd_global_setaccess.c new file mode 100644 index 0000000..0458bd6 --- /dev/null +++ b/src/modules/global.mod/cmd_global_setaccess.c @@ -0,0 +1,144 @@ +/* cmd_global_setaccess.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] - nick / *auth +* argv[1] - global access +*/ +static AUTHLOOKUP_CALLBACK(global_cmd_setaccess_auth_lookup); +static USERAUTH_CALLBACK(global_cmd_setaccess_nick_lookup); +static void global_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int access); + +struct global_cmd_setaccess_cache { + struct ClientSocket *client, *textclient; + struct UserNode *user; + struct Event *event; + int access; + char *nick; +}; + +CMD_BIND(global_cmd_setaccess) { + int caccess; + MYSQL_RES *res; + MYSQL_ROW row; + caccess = atoi(argv[1]); + if(caccess < 0 || caccess > 1000) { + reply(getTextBot(), user, "NS_INVALID_ACCESS", caccess); + return; + } + printf_mysql_query("SELECT `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(user->auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL || atoi(row[0]) < caccess) { + reply(getTextBot(), user, "NS_ACCESS_OUTRANKED"); + return; + } + if(argv[0][0] == '*') { + //we've got an auth + argv[0]++; + 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) { + global_cmd_setaccess_async1(client, getTextBot(), user, 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 + struct global_cmd_setaccess_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->access = caccess; + cache->nick = strdup(argv[0]); + lookup_authname(argv[0], global_cmd_setaccess_auth_lookup, cache); + } + } else { + struct UserNode *cuser = getUserByNick(argv[0]); + if(!cuser) { + cuser = createTempUser(argv[0]); + if(!cuser) { + reply(getTextBot(), user, "NS_USER_UNKNOWN", argv[0]); + return; + } + cuser->flags |= USERFLAG_ISTMPUSER; + } + if(cuser->flags & USERFLAG_ISAUTHED) { + global_cmd_setaccess_async1(client, getTextBot(), user, event, argv[0], cuser->auth, caccess); + } else { + struct global_cmd_setaccess_cache *cache = malloc(sizeof(*cache)); + if (!cache) { + perror("malloc() failed"); + return; + } + cache->client = client; + cache->textclient = getTextBot(); + cache->user = user; + cache->event = event; + cache->access = caccess; + cache->nick = strdup(argv[0]); + get_userauth(cuser, global_cmd_setaccess_nick_lookup, cache); + } + } +} + +static AUTHLOOKUP_CALLBACK(global_cmd_setaccess_auth_lookup) { + struct global_cmd_setaccess_cache *cache = data; + if(!exists) { + //AUTH_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_AUTH_UNKNOWN", cache->nick); + } else + global_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, cache->nick, auth, cache->access); + free(cache->nick); + free(cache); +} + +static USERAUTH_CALLBACK(global_cmd_setaccess_nick_lookup) { + struct global_cmd_setaccess_cache *cache = data; + if(!user) { + //USER_DOES_NOT_EXIST + reply(cache->textclient, cache->user, "NS_USER_UNKNOWN", cache->nick); + } + else if(!(user->flags & USERFLAG_ISAUTHED)) { + //USER_NOT_AUTHED + reply(cache->textclient, cache->user, "NS_USER_NEED_AUTH", cache->nick); + } + else + global_cmd_setaccess_async1(cache->client, cache->textclient, cache->user, cache->event, user->nick, user->auth, cache->access); + free(cache->nick); + free(cache); +} + +static void global_cmd_setaccess_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct Event *event, char *nick, char *auth, int caccess) { + //we've got a valid auth now... + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `user_id`, `user_access` FROM `users` WHERE `user_user` = '%s'", escape_string(auth)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + if(atoi(row[1]) != caccess) + printf_mysql_query("UPDATE `users` SET `user_access` = '%d' WHERE `user_id` = '%s'", caccess, row[0]); + } else { + printf_mysql_query("INSERT INTO `users` (`user_user`, `user_access`) VALUES ('%s', '%d')", escape_string(auth), caccess); + } + reply(textclient, user, "NS_SETACCESS_DONE", auth, caccess); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_setbot.c b/src/modules/global.mod/cmd_global_setbot.c new file mode 100644 index 0000000..88ffeac --- /dev/null +++ b/src/modules/global.mod/cmd_global_setbot.c @@ -0,0 +1,527 @@ +/* cmd_global_setbot.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] botid +* argv[1] setting +* argv[2] value +*/ + +static int global_cmd_setbot_active(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_nick(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_ident(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_realname(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_server(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_port(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_bind(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_ssl(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_serverpass(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_class(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_queue(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_prefered(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_maxchan(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_priority(struct UserNode *user, MYSQL_ROW bot, char *value); +static int global_cmd_setbot_trigger(struct UserNode *user, MYSQL_ROW bot, char *value); + +CMD_BIND(global_cmd_setbot) { + MYSQL_RES *res; + MYSQL_ROW row; + int botid = atoi(argv[0]); + printf_mysql_query("SELECT `active`, `nick`, `server`, `port`, `pass`, `botclass`, `textbot`, `queue`, `defaulttrigger`, `max_channels`, `register_priority`, `bind`, `ident`, `realname`, `ssl`, `id` FROM `bots` WHERE `id` = '%d'", botid); + res = mysql_use(); + if(!(row = mysql_fetch_row(res))) { + reply(getTextBot(), user, "NS_SETBOT_UNKNOWN", botid); + return; + } + if(argc > 1) { + char *value; + if(argc > 2) { + value = merge_argv(argv, 2, argc); + } else + value = NULL; + int log_event = 0; + if(!stricmp(argv[1], "active")) log_event = global_cmd_setbot_active(user, row, value); + else if(!stricmp(argv[1], "nick")) log_event = global_cmd_setbot_nick(user, row, value); + else if(!stricmp(argv[1], "ident")) log_event = global_cmd_setbot_ident(user, row, value); + else if(!stricmp(argv[1], "realname")) log_event = global_cmd_setbot_realname(user, row, value); + else if(!stricmp(argv[1], "server")) log_event = global_cmd_setbot_server(user, row, value); + else if(!stricmp(argv[1], "port")) log_event = global_cmd_setbot_port(user, row, value); + else if(!stricmp(argv[1], "bind")) log_event = global_cmd_setbot_bind(user, row, value); + else if(!stricmp(argv[1], "ssl")) log_event = global_cmd_setbot_ssl(user, row, value); + else if(!stricmp(argv[1], "serverpass")) log_event = global_cmd_setbot_serverpass(user, row, value); + else if(!stricmp(argv[1], "botclass")) log_event = global_cmd_setbot_class(user, row, value); + else if(!stricmp(argv[1], "queue")) log_event = global_cmd_setbot_queue(user, row, value); + else if(!stricmp(argv[1], "prefered")) log_event = global_cmd_setbot_prefered(user, row, value); + else if(!stricmp(argv[1], "maxchan")) log_event = global_cmd_setbot_maxchan(user, row, value); + else if(!stricmp(argv[1], "priority")) log_event = global_cmd_setbot_priority(user, row, value); + else if(!stricmp(argv[1], "trigger")) log_event = global_cmd_setbot_trigger(user, row, value); + else { + reply(getTextBot(), user, "NS_SETBOT_SETTING", argv[1]); + } + if(log_event) { + if(!stricmp(argv[1], "serverpass") && value) { //censor server password + char cmd_args[MAXLEN]; + sprintf(cmd_args, "%d SERVERPASS ***", botid); + free(event->arguments); + event->arguments = strdup(cmd_args); + } + logEvent(event); + } + } else { + reply(getTextBot(), user, "NS_SETBOT_HEADER", botid); + global_cmd_setbot_active(user, row, NULL); + global_cmd_setbot_nick(user, row, NULL); + global_cmd_setbot_ident(user, row, NULL); + global_cmd_setbot_realname(user, row, NULL); + global_cmd_setbot_server(user, row, NULL); + global_cmd_setbot_port(user, row, NULL); + global_cmd_setbot_bind(user, row, NULL); + global_cmd_setbot_ssl(user, row, NULL); + global_cmd_setbot_serverpass(user, row, NULL); + global_cmd_setbot_class(user, row, NULL); + global_cmd_setbot_queue(user, row, NULL); + global_cmd_setbot_prefered(user, row, NULL); + global_cmd_setbot_maxchan(user, row, NULL); + global_cmd_setbot_priority(user, row, NULL); + global_cmd_setbot_trigger(user, row, NULL); + } +} + +static int global_cmd_setbot_active(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = ((bot[0] && !strcmp(bot[0], "1")) ? 1 : 0); + int ret = 0; + if(value) { + if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { + val = 0; + } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { + val = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); + return 0; + } + if(val != ((bot[0] && !strcmp(bot[0], "1")) ? 1 : 0)) { + if(val) { + //add the bot + struct ClientSocket *client; + client = create_socket(bot[2], atoi(bot[3]), bot[11], bot[4], bot[1], bot[12], bot[13]); + client->flags |= (strcmp(bot[6], "0") ? SOCKET_FLAG_PREFERRED : 0); + client->flags |= (strcmp(bot[7], "0") ? SOCKET_FLAG_USE_QUEUE : 0); + client->flags |= (strcmp(bot[14], "0") ? SOCKET_FLAG_SSL : 0); + client->botid = atoi(bot[5]); + client->clientid = atoi(bot[15]); + connect_socket(client); + if(client->botid == 0) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d'", client->clientid); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(bind_botwise_cmd_to_command(0, client->clientid, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_botwise_set_parameters(0, client->clientid, row[0], row[2]); + } + if(row[3]) { + bind_botwise_set_global_access(0, client->clientid, row[0], atoi(row[3])); + } + if(row[4]) { + bind_botwise_set_channel_access(0, client->clientid, row[0], row[4]); + } + } + } + bind_botwise_unbound_required_functions(0, client->clientid); + } + } else { + //remove the bot + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + unbind_botwise_allcmd(0, client->clientid); + close_socket(client); + break; + } + } + } + printf_mysql_query("UPDATE `bots` SET `active` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + } + reply(getTextBot(), user, "\002ACTIVE \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); + return ret; +} + +static int global_cmd_setbot_nick(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[1]; + int ret = 0; + if(value) { + if(!is_valid_nick(value)) { + reply(getTextBot(), user, "NS_SETBOT_NICK_INVALID", value); + return 0; + } + //rename the bot + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->nick) + free(client->nick); + client->nick = strdup(value); + if(client->flags & SOCKET_FLAG_READY) + putsock(client, "NICK %s", value); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `nick` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002NICK \002 %s", val); + return ret; +} + +static int global_cmd_setbot_ident(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[12]; + int ret = 0; + if(value) { + if(strlen(value) > 12) + value[12] = '\0'; + //rename the bot + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->ident) + free(client->ident); + client->ident = strdup(value); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `ident` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002IDENT \002 %s", val); + return ret; +} + +static int global_cmd_setbot_realname(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[13]; + int ret = 0; + if(value) { + if(strlen(value) > 255) + value[255] = '\0'; + //rename the bot + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->ident) + free(client->ident); + client->ident = strdup(value); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `realname` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002REALNAME \002 %s", val); + return ret; +} + +static int global_cmd_setbot_server(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[2]; + int ret = 0; + if(value) { + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->host) + free(client->host); + client->host = strdup(value); + if(client->flags & SOCKET_FLAG_READY) + reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `server` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002SERVER \002 %s", val); + return ret; +} + +static int global_cmd_setbot_port(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = atoi(bot[3]); + int ret = 0; + if(value) { + val = atoi(value); + if(val <= 0 || val > 65534) { + reply(getTextBot(), user, "NS_SETBOT_PORT_INVALID", value); + return 0; + } + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + client->port = val; + if(client->flags & SOCKET_FLAG_READY) + reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `port` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002PORT \002 %d", val); + return ret; +} + +static int global_cmd_setbot_bind(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[11]; + int ret = 0; + if(value) { + if(!strcmp(value, "*")) + value = NULL; + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->bind) + free(client->bind); + client->bind = (value ? strdup(value) : NULL); + if(client->flags & SOCKET_FLAG_READY) + reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); + break; + } + } + if(value) + printf_mysql_query("UPDATE `bots` SET `bind` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + else + printf_mysql_query("UPDATE `bots` SET `bind` = NULL WHERE `id` = '%s'", bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002BIND \002 %s", val); + return ret; +} + +static int global_cmd_setbot_ssl(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = (strcmp(bot[14], "0") ? 1 : 0); + int ret = 0; + if(value) { + if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { + val = 0; + } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { + val = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); + return 0; + } + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(val) + client->flags |= SOCKET_FLAG_SSL; + else + client->flags &= ~SOCKET_FLAG_SSL; + if(client->flags & SOCKET_FLAG_READY) + reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `ssl` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002SSL \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); + return ret; +} + +static int global_cmd_setbot_serverpass(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[4]; + int ret = 0; + if(value) { + if(!strcmp(value, "*")) + value = ""; + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(client->pass) + free(client->pass); + client->pass = (value ? strdup(value) : NULL); + if(client->flags & SOCKET_FLAG_READY) + reply(getTextBot(), user, "NS_SETBOT_NEED_RESTART"); + break; + } + } + printf_mysql_query("UPDATE `bots` SET `pass` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002SERVERPASS \002 %s", val); + return ret; +} + +static int global_cmd_setbot_class(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = atoi(bot[5]); + int ret = 0; + if(value) { + if((val = resolve_botalias(value)) == -1) { + reply(getTextBot(), user, "NS_SETBOT_INVALID_CLASS", value); + return 0; + } + if(val != atoi(bot[5])) { + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + unbind_botwise_allcmd(client->clientid); + client->botid = val; + if(client->botid == 0) { + MYSQL_RES *res; + MYSQL_ROW row; + printf_mysql_query("SELECT `command`, `function`, `parameters`, `global_access`, `chan_access` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d'", client->clientid); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + if(bind_botwise_cmd_to_command(client->botid, client->clientid, row[0], row[1])) { + if(row[2] && strcmp(row[2], "")) { + bind_botwise_set_parameters(client->botid, client->clientid, row[0], row[2]); + } + if(row[3]) { + bind_botwise_set_global_access(client->botid, client->clientid, row[0], atoi(row[3])); + } + if(row[4]) { + bind_botwise_set_channel_access(client->botid, client->clientid, row[0], row[4]); + } + } + } + bind_botwise_unbound_required_functions(client->botid, client->clientid); + } + break; + } + } + printf_mysql_query("UPDATE `bots` SET `botclass` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + } + reply(getTextBot(), user, "\002BOTCLASS \002 %s", resolve_botid(val)); + return ret; +} + +static int global_cmd_setbot_queue(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = (strcmp(bot[7], "0") ? 1 : 0); + int ret = 0; + if(value) { + if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { + val = 0; + } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { + val = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); + return 0; + } + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(val) + client->flags |= SOCKET_FLAG_USE_QUEUE; + else + client->flags &= ~SOCKET_FLAG_USE_QUEUE; + break; + } + } + printf_mysql_query("UPDATE `bots` SET `queue` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002QUEUE \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); + return ret; +} + +static int global_cmd_setbot_prefered(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = (strcmp(bot[6], "0") ? 1 : 0); + int ret = 0; + if(value) { + if(!strcmp(value, "0") || !stricmp(value, "off") || !stricmp(value, get_language_string(user, "NS_SET_OFF"))) { + val = 0; + } else if(!strcmp(value, "1") || !stricmp(value, "on") || !stricmp(value, get_language_string(user, "NS_SET_ON"))) { + val = 1; + } else { + reply(getTextBot(), user, "NS_SET_INVALID_BOOLEAN", value); + return 0; + } + struct ClientSocket *client; + for(client = getBots(0, NULL); client; client = getBots(0, client)) { + if(client->clientid == atoi(bot[15])) { + if(val) + client->flags |= SOCKET_FLAG_PREFERRED; + else + client->flags &= ~SOCKET_FLAG_PREFERRED; + break; + } + } + printf_mysql_query("UPDATE `bots` SET `prefered` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002PREFERED \002 %s", get_language_string(user, (val ? "NS_SET_ON" : "NS_SET_OFF"))); + return ret; +} + +static int global_cmd_setbot_maxchan(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = atoi(bot[9]); + int ret = 0; + if(value) { + val = atoi(value); + if(val < 0 || val > 99999) { + reply(getTextBot(), user, "NS_SETBOT_MAXCHAN_INVALID", value); + return 0; + } + printf_mysql_query("UPDATE `bots` SET `max_channels` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002MAXCHAN \002 %d", val); + return ret; +} + +static int global_cmd_setbot_priority(struct UserNode *user, MYSQL_ROW bot, char *value) { + int val = atoi(bot[10]); + int ret = 0; + if(value) { + val = atoi(value); + if(val < 0 || val > 99) { + reply(getTextBot(), user, "NS_SETBOT_PRIORITY_INVALID", value); + return 0; + } + printf_mysql_query("UPDATE `bots` SET `register_priority` = '%d' WHERE `id` = '%s'", val, bot[15]); + ret = 1; + } + reply(getTextBot(), user, "\002PRIORITY \002 %d", val); + return ret; +} + +static int global_cmd_setbot_trigger(struct UserNode *user, MYSQL_ROW bot, char *value) { + char *val = bot[8]; + int ret = 0; + if(value) { + if(!*value || strlen(value) > 10) { + reply(getTextBot(), user, "NS_SETBOT_TRIGGER_INVALID", value); + return 0; + } + printf_mysql_query("UPDATE `bots` SET `defaulttrigger` = '%s' WHERE `id` = '%s'", escape_string(value), bot[15]); + flush_trigger_cache(atoi(bot[5]), atoi(bot[15])); + reply(getTextBot(), user, "NS_SETBOT_TRIGGER_NOTE"); + val = value; + ret = 1; + } + reply(getTextBot(), user, "\002TRIGGER \002 %s", val); + return ret; +} diff --git a/src/modules/global.mod/cmd_global_staff.c b/src/modules/global.mod/cmd_global_staff.c new file mode 100644 index 0000000..3f1989e --- /dev/null +++ b/src/modules/global.mod/cmd_global_staff.c @@ -0,0 +1,52 @@ +/* cmd_global_staff.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* no arguments +*/ + +CMD_BIND(global_cmd_staff) { + MYSQL_RES *res, *res2; + MYSQL_ROW row, row2; + printf_mysql_query("SELECT `rank_id`, `rank_name` FROM `support_ranks` ORDER BY `rank_order` ASC"); + res = mysql_use(); + while ((row = mysql_fetch_row(res)) != NULL) { + printf_mysql_query("SELECT `user_user`, `user_god` FROM `users` WHERE `user_rank` = '%s'", row[0]); + res2 = mysql_use(); + if(mysql_num_rows(res2)) { + reply(getTextBot(), user, "\002%s\002", row[1]); + while ((row2 = mysql_fetch_row(res2)) != NULL) { + if(strcmp(row2[1], "0")) { + //god enabled - show nicks + char loggedinBuf[MAXLEN]; + int loggedinPos = 0; + struct UserNode *cuser; + for(cuser = getUsersWithAuth(row2[0], NULL); cuser; cuser = getUsersWithAuth(row2[0], cuser)) { + loggedinPos += sprintf(loggedinBuf+loggedinPos, (loggedinPos ? ", %s" : "%s"), cuser->nick); + } + if(loggedinPos) + reply(getTextBot(), user, " %s (%s: %s)", row2[0], get_language_string(user, "NS_STAFF_LOGGEDIN"), loggedinBuf); + else + reply(getTextBot(), user, " %s", row2[0]); + } else + reply(getTextBot(), user, " %s", row2[0]); + } + } + } +} diff --git a/src/modules/global.mod/cmd_global_unbind.c b/src/modules/global.mod/cmd_global_unbind.c new file mode 100644 index 0000000..8cd8f45 --- /dev/null +++ b/src/modules/global.mod/cmd_global_unbind.c @@ -0,0 +1,54 @@ +/* cmd_global_unbind.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] command name +*/ + +CMD_BIND(global_cmd_unbind) { + MYSQL_RES *res; + MYSQL_ROW row; + struct cmd_binding *cbind = find_botwise_cmd_binding(client->botid, client->clientid, argv[0]); + if(client->botid == 0) + printf_mysql_query("SELECT `id`, `function` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d' AND `command` = '%s'", client->clientid, escape_string(argv[0])); + else + printf_mysql_query("SELECT `id`, `function` FROM `bot_binds` WHERE `botclass` = '%d' AND `command` = '%s'", client->botid, escape_string(argv[0])); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL && (!cbind || !(cbind->flags & CMDFLAG_TEMPONARY_BIND))) { + reply(getTextBot(), user, "NS_UNBIND_NOT_FOUND", argv[0]); + return; + } + struct cmd_function *function = find_cmd_function(client->botid, cbind->func->name); + if(function && (function->flags & CMDFLAG_REQUIRED)) { + if(client->botid == 0) + printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '0' AND `botid` = '%d' AND `function` = '%s'", client->clientid, escape_string(function->name)); + else + printf_mysql_query("SELECT `id` FROM `bot_binds` WHERE `botclass` = '%d' AND `function` = '%s'", client->botid, escape_string(function->name)); + res = mysql_use(); + if (mysql_num_rows(res) <= 1) { + reply(getTextBot(), user, "NS_UNBIND_REQUIRED", function->name); + return; + } + } + unbind_botwise_cmd(client->botid, client->clientid, argv[0]); + if(!cbind || !(cbind->flags & CMDFLAG_TEMPONARY_BIND)) + printf_mysql_query("DELETE FROM `bot_binds` WHERE `id` = '%s'", row[0]); + reply(getTextBot(), user, "NS_UNBIND_DONE", argv[0]); + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_unregister.c b/src/modules/global.mod/cmd_global_unregister.c new file mode 100644 index 0000000..206e763 --- /dev/null +++ b/src/modules/global.mod/cmd_global_unregister.c @@ -0,0 +1,65 @@ +/* cmd_global_unregister.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* argv[0] - channel +*/ +CMD_BIND(global_cmd_unregister) { + MYSQL_RES *res; + MYSQL_ROW row; + char *channel; + if(argc) + channel = argv[0]; + else + channel = (chan ? chan->name : ""); + if(!is_valid_chan(channel)) { + reply(getTextBot(), user, "NS_INVALID_CHANNEL_NAME", argv[0]); + return; + } + int chanid; + printf_mysql_query("SELECT `channel_id` FROM `channels` WHERE `channel_name` = '%s'", escape_string(channel)); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) != NULL) { + chanid = atoi(row[0]); + } else { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + if(client->botid == 0) + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '0' AND `botid` = '%d'", chanid, client->clientid); + else + printf_mysql_query("SELECT `botid`, `bot_channels`.`id`, `suspended` FROM `bot_channels` LEFT JOIN `bots` ON `bot_channels`.`botid` = `bots`.`id` WHERE `chanid` = '%d' AND `botclass` = '%d'", chanid, client->botid); + res = mysql_use(); + if ((row = mysql_fetch_row(res)) == NULL) { + reply(getTextBot(), user, "NS_UNREGISTER_NOT_REGISTERED", argv[0], client->user->nick); + return; + } + int botid = atoi(row[0]); + struct ClientSocket *bot; + for(bot = getBots(SOCKET_FLAG_READY, NULL); bot; bot = getBots(SOCKET_FLAG_READY, bot)) { + if(bot->clientid == botid) + break; + } + printf_mysql_query("DELETE FROM `bot_channels` WHERE `id` = '%s'", row[1]); + reply(getTextBot(), user, "NS_UNREGISTER_DONE", channel); + if(bot && strcmp(row[2], "1")) { + putsock(bot, "PART %s :Channel unregistered.", channel); + } + logEvent(event); +} diff --git a/src/modules/global.mod/cmd_global_version.c b/src/modules/global.mod/cmd_global_version.c new file mode 100644 index 0000000..307e34c --- /dev/null +++ b/src/modules/global.mod/cmd_global_version.c @@ -0,0 +1,37 @@ +/* cmd_global_version.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cmd_global.h" + +/* +* no args +*/ + +CMD_BIND(global_cmd_version) { + reply(getTextBot(), user, "\002NeonServ %s.%d\002 (%s), written by pk910", NEONSERV_VERSION, patchlevel, (strcmp(revision, "") ? revision : "-")); + reply(getTextBot(), user, "Build (#%s) %s (%s lines, " COMPILER ")", compilation, creation, codelines); + reply(getTextBot(), user, "NeonServ can be found on: http://dev.pk910.de/NeonServ"); + //helpers :D + reply(getTextBot(), user, "special thanks to:"); + reply(getTextBot(), user, " Zer0n, TeaTow, Phil (testing and ideas current version)"); + reply(getTextBot(), user, " Buschman, Zer0n, Neon (translating current version)"); + reply(getTextBot(), user, " Patschi95, DerGrinch, Darkfly, Zer0n, Buschman (testing and ideas older versions)"); + reply(getTextBot(), user, " Buschman, Georg, richard (translating older versions)"); + reply(getTextBot(), user, "and all the other users that reported all these nasty bugs :D"); + reply(getTextBot(), user, "\002If you found a bug or if you have a good idea report it on http://dev.pk910.de/BugTrack\002"); + +} \ No newline at end of file diff --git a/src/modules/global.mod/module.c b/src/modules/global.mod/module.c new file mode 100644 index 0000000..3fe2703 --- /dev/null +++ b/src/modules/global.mod/module.c @@ -0,0 +1,37 @@ +/* module.c - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../module.h" +#include "cmd_global.h" + +static int module_initialize() { + register_commands(); + return 0; +} + +static void module_start(int type) { + +} + +static void module_loop() { + +} + +static void module_stop(int type) { + +} + +MODULE_HEADER(module_initialize, module_start, module_loop, module_stop); diff --git a/src/modules/module.h b/src/modules/module.h new file mode 100644 index 0000000..6fc0a8c --- /dev/null +++ b/src/modules/module.h @@ -0,0 +1,241 @@ +/* module.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef _module_h +#define _module_h +#define DND_FUNCTIONS 1 /* DoNotDefine_Functions */ +#include "../overall.h" +#include "../version.h" +#include "../mysqlConn.h" + +extern void **global; +extern int module_id; + +/**** global function list ****/ +/* 000 */ #define getStartTime ((time_t (*)(void))global[0]) +/* 001 */ #define getRunningThreads ((int (*)(void))global[1]) +/* 002 */ #define exit_daemon ((int (*)(void))global[2]) +/* 003 */ #define stricmp ((int (*)(const char *, const char *))global[3]) +/* 004 */ #define stricmplen ((int (*)(const char *, const char *, int))global[4]) +/* 005 */ #define restart_process ((void (*)(void))global[5]) +/* 006 */ #define cleanup ((void (*)(void))global[6]) +/* 007 */ #define restart_bot ((void (*)(int))global[7]) +/* 008 */ #define stop_bot ((void (*)(void))global[8]) +/* 009 */ #define reload_config ((void (*)(void))global[9]) +/* 010 */ #define putlog ((void (*)(int, const char *, ...))global[10]) +#ifdef HAVE_THREADS +/* 011 */ #define getCurrentThreadID ((int (*)(void))global[11]) +#endif +/* 012 */ #define getMatchingChannelBan ((struct BanNode* (*)(struct ChanNode *, char *))global[12]) +/* 013 */ #define getChannelBot ((struct ClientSocket* (*)(struct ChanNode *, int))global[13]) +/* 014 */ #define requestOp ((void (*)(struct UserNode *, struct ChanNode *))global[14]) +/* 015 */ #define channel_ban_timeout ((void (*)(void *))global[15]) +/* 016 */ #define general_event_privctcp ((void (*)(struct UserNode *, struct UserNode *, char *, char *))global[16]) +/* 017 */ #define set_bot_alias ((void (*)(int, char *))global[17]) +/* 018 */ #define resolve_botid ((const char * (*)(int))global[18]) +/* 019 */ #define resolve_botalias ((int (*)(const char *))global[19]) +/* 020 */ #define is_valid_chan ((int (*)(const char *))global[20]) +/* 021 */ #define getAllChans ((struct ChanNode* (*)(struct ChanNode *))global[21]) +/* 022 */ #define getChanByName ((struct ChanNode* (*)(const char *))global[22]) +/* 023 */ #define getChannelCount ((int (*)(void))global[23]) +/* 024 */ #define getChanUserCount ((int (*)(void))global[24]) +/* 025 */ #define getChanBanCount ((int (*)(void))global[25]) +/* 026 */ #define isUserOnChan ((int (*)(struct UserNode *, struct ChanNode *))global[26]) +/* 027 */ #define getChanUser ((struct ChanUser* (*)(struct UserNode *, struct ChanNode *))global[27]) +/* 028 */ #define getChannelUsers ((struct ChanUser* (*)(struct ChanNode *, struct ChanUser *))global[28]) +/* 029 */ #define getUserChannels ((struct ChanUser* (*)(struct UserNode *, struct ChanUser *))global[29]) +/* 030 */ #define create_socket ((struct ClientSocket* (*)(char *, int, char *, char *, char *, char *, char *))global[30]) +/* 031 */ #define connect_socket ((int (*)(struct ClientSocket *))global[31]) +/* 032 */ #define close_socket ((int (*)(struct ClientSocket *))global[32]) +/* 033 */ #define disconnect_socket ((int (*)(struct ClientSocket *))global[33]) +/* 034 */ #define write_socket ((int (*)(struct ClientSocket *, char*, int))global[34]) +/* 035 */ #define putsock ((void (*)(struct ClientSocket *, const char *, ...))global[35]) +/* 036 */ #define getBots ((struct ClientSocket* (*)(int, struct ClientSocket *))global[36]) +/* 037 */ #define get_int_field ((int (*)(char *))global[37]) +/* 038 */ #define get_string_field ((char * (*)(char *))global[38]) +/* 039 */ #define _loadUserSettings ((void (*)(struct UserNode *))global[39]) +/* 040 */ #define isGodMode ((int (*)(struct UserNode *))global[40]) +/* 041 */ #define getChanDefault ((char * (*)(char *))global[41]) +/* 042 */ #define getChannelAccess ((int (*)(struct UserNode *, struct ChanNode *))global[42]) +/* 043 */ #define checkChannelAccess ((int (*)(struct UserNode *, struct ChanNode *, char *, int))global[43]) +/* 044 */ #define _loadChannelSettings ((void (*)(struct ChanNode *))global[44]) +/* 045 */ #define isUserProtected ((int (*)(struct ChanNode *, struct UserNode *, struct UserNode *))global[45]) +/* 046 */ #define getBanAffectingMask ((char * (*)(struct ChanNode *, char *))global[46]) +/* 047 */ #define renameAccount ((int (*)(char *, char *))global[47]) +/* 048 */ #define deleteUser ((void (*)(int))global[48]) +/* 049 */ #define logEvent ((void (*)(struct Event *))global[49]) +/* 050 */ #define lookup_authname ((void (*)(char *, authlookup_callback_t, void *))global[50]) +/* 051 */ #define bind_join ((int (*)(join_func_t *, int))global[51]) +/* 052 */ #define unbind_join ((void (*)(join_func_t *))global[52]) +/* 053 */ #define bind_nick ((int (*)(nick_func_t *, int))global[53]) +/* 054 */ #define unbind_nick ((void (*)(nick_func_t *))global[54]) +/* 055 */ #define bind_part ((int (*)(part_func_t *, int))global[55]) +/* 056 */ #define unbind_part ((void (*)(part_func_t *))global[56]) +/* 057 */ #define bind_quit ((int (*)(quit_func_t *, int))global[57]) +/* 058 */ #define unbind_quit ((void (*)(quit_func_t *))global[58]) +/* 059 */ #define bind_kick ((int (*)(kick_func_t *, int))global[59]) +/* 060 */ #define unbind_kick ((void (*)(kick_func_t *))global[60]) +/* 061 */ #define bind_topic ((int (*)(topic_func_t *, int))global[61]) +/* 062 */ #define unbind_topic ((void (*)(topic_func_t *))global[62]) +/* 063 */ #define bind_mode ((int (*)(mode_func_t *, int))global[63]) +/* 064 */ #define unbind_mode ((void (*)(mode_func_t *))global[64]) +/* 065 */ #define bind_chanmsg ((int (*)(chanmsg_func_t *, int))global[65]) +/* 066 */ #define unbind_chanmsg ((void (*)(chanmsg_func_t *))global[66]) +/* 067 */ #define bind_privmsg ((int (*)(privmsg_func_t *, int))global[67]) +/* 068 */ #define unbind_privmsg ((void (*)(privmsg_func_t *))global[68]) +/* 069 */ #define bind_channotice ((int (*)(channotice_func_t *, int))global[69]) +/* 070 */ #define unbind_channotice ((void (*)(channotice_func_t *))global[70]) +/* 071 */ #define bind_privnotice ((int (*)(privnotice_func_t *, int))global[71]) +/* 072 */ #define unbind_privnotice ((void (*)(privnotice_func_t *))global[72]) +/* 073 */ #define bind_chanctcp ((int (*)(chanctcp_func_t *, int))global[73]) +/* 074 */ #define unbind_chanctcp ((void (*)(chanctcp_func_t *))global[74]) +/* 075 */ #define bind_privctcp ((int (*)(privctcp_func_t *, int))global[75]) +/* 076 */ #define unbind_privctcp ((void (*)(privctcp_func_t *))global[76]) +/* 077 */ #define bind_invite ((int (*)(invite_func_t *, int))global[77]) +/* 078 */ #define unbind_invite ((void (*)(invite_func_t *))global[78]) +/* 079 */ #define bind_raw ((int (*)(raw_func_t *, int))global[79]) +/* 080 */ #define unbind_raw ((void (*)(raw_func_t *))global[80]) +/* 081 */ #define bind_bot_ready ((int (*)(bot_ready_func_t *, int))global[81]) +/* 082 */ #define unbind_bot_ready ((void (*)(bot_ready_func_t *))global[82]) +/* 083 */ #define bind_registered ((int (*)(registered_func_t *, int))global[83]) +/* 084 */ #define unbind_registered ((void (*)(registered_func_t *))global[84]) +/* 085 */ #define bind_freeuser ((int (*)(freeuser_func_t *, int))global[85]) +/* 086 */ #define unbind_freeuser ((void (*)(freeuser_func_t *))global[86]) +/* 087 */ #define bind_freechan ((int (*)(freechan_func_t *, int))global[87]) +/* 088 */ #define unbind_freechan ((void (*)(freechan_func_t *))global[88]) +/* 089 */ #define reply ((void (*)(struct ClientSocket *, struct UserNode *, const char *, ...))global[89]) +/* 090 */ #define merge_argv ((char * (*)(char **, int, int))global[90]) +/* 091 */ #define merge_argv_char ((char * (*)(char **, int, int, char))global[91]) +/* 092 */ #define get_language_by_tag ((struct language * (*)(char *))global[92]) +/* 093 */ #define get_language_by_name ((struct language * (*)(char *))global[93]) +/* 094 */ #define get_default_language ((struct language * (*)(void))global[94]) +/* 095 */ #define load_language ((void (*)(char *, char *))global[95]) +/* 096 */ #define register_default_language_table ((void (*)(const struct default_language_entry *))global[96]) +/* 097 */ #define get_language_string ((char * (*)(struct UserNode *, const char *))global[97]) +/* 098 */ #define build_language_string ((char * (*)(struct UserNode *, char *, const char *, ...))global[98]) +#ifdef ENABLE_MEMORY_DEBUG +/* 099 */ #define xmalloc ((void * (*)(unsigned int, const char *, unsigned int))global[99]) +/* 100 */ #define xcalloc ((void * (*)(unsigned int, unsigned int, const char *, unsigned int))global[100]) +/* 101 */ #define xstrdup ((char * (*)(const char *, const char *, unsigned int))global[101]) +/* 102 */ #define xfree ((void (*)(void *))global[102]) +#endif +/* 103 */ #define getMemoryInfoFiles ((struct memoryInfoFiles * (*)(void))global[103]) +/* 104 */ #define freeMemoryInfoFiles ((void (*)(struct memoryInfoFiles *))global[104]) +/* 105 */ #define getMemoryInfoLines ((struct memoryInfoLines * (*)(const char *))global[105]) +/* 106 */ #define freeMemoryInfoLines ((void (*)(struct memoryInfoLines *))global[106]) +/* 107 */ #define get_botwise_prefered_bot ((struct ClientSocket * (*)(int, int))global[107]) +/* 108 */ #define register_command ((int (*)(int, char *, int, cmd_bind_t *, int, char *, int, unsigned int))global[108]) +/* 109 */ #define set_trigger_callback ((int (*)(int, int, trigger_callback_t *))global[109]) +/* 110 */ #define flush_trigger_cache ((int (*)(int, int))global[110]) +/* 111 */ #define changeBotwiseChannelTrigger ((int (*)(int, int, struct ChanNode *, char *))global[111]) +/* 112 */ #define bind_botwise_cmd_to_function ((int (*)(int, int, char *, struct cmd_function *))global[112]) +/* 113 */ #define bind_botwise_cmd_to_command ((int (*)(int, int, char *, char *))global[113]) +/* 114 */ #define unbind_botwise_cmd ((int (*)(int, int, char *))global[114]) +/* 115 */ #define unbind_botwise_allcmd ((int (*)(int, int))global[115]) +/* 116 */ #define bind_botwise_set_parameters ((void (*)(int, int, char *, char *))global[116]) +/* 117 */ #define bind_botwise_set_global_access ((void (*)(int, int, char *, int))global[117]) +/* 118 */ #define bind_botwise_set_channel_access ((void (*)(int, int, char *, char *))global[118]) +/* 119 */ #define bind_botwise_set_bind_flags ((void (*)(int, int, char *, unsigned int))global[119]) +/* 120 */ #define find_botwise_cmd_binding ((struct cmd_binding * (*)(int, int, char *))global[120]) +/* 121 */ #define bind_botwise_unbound_required_functions ((void (*)(int, int))global[121]) +/* 122 */ #define find_cmd_function ((struct cmd_function * (*)(int , char *))global[122]) +/* 123 */ #define getTextBot ((struct ClientSocket * (*)(void))global[123]) +/* 124 */ #define register_command_alias ((void (*)(int, char *))global[124]) +/* 125 */ #define getAllBinds ((struct cmd_binding * (*)(struct cmd_binding *))global[125]) +/* 126 */ #define createModeNode ((struct ModeNode * (*)(struct ChanNode *))global[126]) +/* 127 */ #define freeModeNode ((void (*)(struct ModeNode *))global[127]) +/* 128 */ #define isModeSet ((int (*)(struct ModeNode *, char))global[128]) +/* 129 */ #define isModeAffected ((int (*)(struct ModeNode *, char))global[129]) +/* 130 */ #define getModeValue ((void * (*)(struct ModeNode *, char))global[130]) +/* 131 */ #define getModeType ((unsigned int (*)(struct ModeNode *, char))global[131]) +/* 132 */ #define parseModes ((void (*)(struct ModeNode *, char *, char **, int))global[132]) +/* 133 */ #define parseModeString ((void (*)(struct ModeNode *, char *))global[133]) +/* 134 */ #define parseMode ((int (*)(struct ModeNode *, int, char, char *))global[134]) +/* 135 */ #define getModeString ((void (*)(struct ModeNode *, char *))global[135]) +/* 136 */ #define getFullModeString ((void (*)(struct ModeNode *, char *))global[136]) +/* 137 */ #define mysql_use ((MYSQL_RES * (*)(void))global[137]) +/* 138 */ #define mysql_free ((void (*)(void))global[138]) +/* 139 */ #define printf_mysql_query ((void (*)(const char *, ...))global[139]) +/* 140 */ #define printf_long_mysql_query ((void (*)(int, const char *, ...))global[140]) +/* 141 */ #define escape_string ((char * (*)(const char *))global[141]) +/* 142 */ #define get_mysql_conn ((MYSQL * (*)(void))global[142]) +/* 143 */ #define timeq_add ((struct timeq_entry * (*)(int, int, timeq_callback_t *, void *))global[143]) +/* 144 */ #define timeq_uadd ((struct timeq_entry * (*)(int, int, timeq_callback_t *, void *))global[144]) +/* 145 */ #define timeq_add_name ((struct timeq_entry * (*)(char *, int, int, timeq_callback_t *, void *))global[145]) +/* 146 */ #define timeq_uadd_name ((struct timeq_entry * (*)(char *, int, int, timeq_callback_t *, void *))global[146]) +/* 147 */ #define timeq_del ((int (*)(struct timeq_entry *))global[147]) +/* 148 */ #define timeq_del_name ((int (*)(char *))global[148]) +/* 149 */ #define timeq_name_exists ((int (*)(char *))global[149]) +/* 150 */ #define match ((int (*)(const char *, const char *))global[150]) +/* 151 */ #define table_init ((struct Table * (*)(int, int, int))global[151]) +/* 152 */ #define table_add ((int (*)(struct Table *, char **))global[152]) +/* 153 */ #define table_change ((int (*)(struct Table *, int, char **))global[153]) +/* 154 */ #define table_change_field ((int (*)(struct Table *, int, int, char *))global[154]) +/* 155 */ #define table_set_bold ((int (*)(struct Table *, int, int))global[155]) +/* 156 */ #define table_end ((char ** (*)(struct Table *))global[156]) +/* 157 */ #define table_free ((void (*)(struct Table *))global[157]) +/* 158 */ #define timeToStr ((char * (*)(struct UserNode *, int, int, char *))global[158]) +/* 159 */ #define strToTime ((int (*)(struct UserNode *, char *))global[159]) +/* 160 */ #define initModeBuffer ((struct ModeBuffer * (*)(struct ClientSocket *, struct ChanNode *))global[160]) +/* 161 */ #define modeBufferSet ((void (*)(struct ModeBuffer *, int, char, char *))global[161]) +/* 162 */ #define flushModeBuffer ((void (*)(struct ModeBuffer *))global[162]) +/* 163 */ #define freeModeBuffer ((void (*)(struct ModeBuffer *))global[163]) +/* 164 */ #define is_ircmask ((int (*)(const char *))global[164]) +/* 165 */ #define generate_banmask ((char * (*)(struct UserNode *, char *))global[165]) +/* 166 */ #define make_banmask ((char * (*)(char *, char *))global[166]) +/* 167 */ #define isFakeHost ((int (*)(char *))global[167]) +/* 168 */ #define mask_match ((int (*)(char *, struct UserNode *))global[168]) +/* 169 */ #define crc32 ((unsigned long (*)(const char *))global[169]) +/* 170 */ #define is_valid_nick ((int (*)(const char *))global[170]) +/* 171 */ #define getUserByNick ((struct UserNode * (*)(const char *))global[171]) +/* 172 */ #define getUserByMask ((struct UserNode * (*)(const char *))global[172]) +/* 173 */ #define countUsersWithHost ((int (*)(char *))global[173]) +/* 174 */ #define getAuthFakehost ((char * (*)(char *))global[174]) +/* 175 */ #define searchUserByNick ((struct UserNode * (*)(const char *))global[175]) +/* 176 */ #define getAllUsers ((struct UserNode * (*)(struct UserNode *))global[176]) +/* 177 */ #define getUsersWithAuth ((struct UserNode * (*)(const char *, struct UserNode *))global[177]) +/* 178 */ #define getUserCount ((int (*)(void))global[178]) +/* 179 */ #define get_userlist ((void (*)(struct ChanNode *, int, userlist_callback_t, void *))global[179]) +/* 180 */ #define _get_userlist_with_invisible ((void (*)(struct ChanNode *, int, userlist_callback_t, void *, int))global[180]) +/* 181 */ #define get_userauth ((void (*)(struct UserNode *, int, userauth_callback_t, void *))global[181]) +/* 182 */ #define compilation ((const char *) *global[182]) +/* 183 */ #define creation ((const char *) *global[183]) +/* 184 */ #define revision ((const char *) *global[184]) +/* 185 */ #define codelines ((const char *) *global[185]) +/* 186 */ #define patchlevel ((const int) *global[186]) + +#define MODULE_HEADER(initfunc,startfunc,loopfunc,stopfunc) \ + void **global = NULL; \ + int module_id = 0; \ + int init_module(void **functions, int modid) { \ + global = functions; \ + module_id = modid; \ + return initfunc(data); \ + } \ + void start_module(int type) { \ + startfunc(type); \ + } \ + void loop_module() { \ + loopfunc(); \ + } \ + void stop_module(int type) { \ + stopfunc(type); \ + } \ + int modversion() { \ + return MODULE_VERSION; \ + } + +#endif \ No newline at end of file diff --git a/src/mysqlConn.c b/src/mysqlConn.c index 3c2bcbe..41f0495 100644 --- a/src/mysqlConn.c +++ b/src/mysqlConn.c @@ -18,6 +18,8 @@ #include "mysqlConn.h" #define DATABASE_VERSION "15" +static void show_mysql_error(); + struct mysql_conn_struct { unsigned int tid; MYSQL *mysql_conn; @@ -46,7 +48,7 @@ static char *mysql_host, *mysql_user, *mysql_pass, *mysql_base; static pthread_mutex_t synchronized; #endif -void check_mysql() { +static void check_mysql() { MYSQL *mysql_conn = get_mysql_conn(); int errid; if((errid = mysql_ping(mysql_conn))) { @@ -200,7 +202,7 @@ void free_mysql() { mysql_conns = NULL; } -void show_mysql_error() { +static void show_mysql_error() { MYSQL *mysql_conn = get_mysql_conn(); //show mysql_error() putlog(LOGLEVEL_ERROR, "MySQL Error: %s\n", mysql_error(mysql_conn)); diff --git a/src/mysqlConn.h b/src/mysqlConn.h index 3af13c2..410f346 100644 --- a/src/mysqlConn.h +++ b/src/mysqlConn.h @@ -23,15 +23,14 @@ #define MYSQLMAXLEN 1024 -void check_mysql(); -MYSQL_RES *mysql_use(); -void mysql_free(); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ MYSQL_RES *mysql_use(); +/* MODULAR ACCESSIBLE */ void mysql_free(); void init_mysql(char *host, int port, char *user, char *pass, char *base); void free_mysql(); -void show_mysql_error(); -void printf_mysql_query(const char *text, ...) PRINTF_LIKE(1, 2); -void printf_long_mysql_query(int len, const char *text, ...) PRINTF_LIKE(2, 3); -char* escape_string(const char *str); -MYSQL *get_mysql_conn(); - -#endif \ No newline at end of file +/* MODULAR ACCESSIBLE */ void printf_mysql_query(const char *text, ...) PRINTF_LIKE(1, 2); +/* MODULAR ACCESSIBLE */ void printf_long_mysql_query(int len, const char *text, ...) PRINTF_LIKE(2, 3); +/* MODULAR ACCESSIBLE */ char* escape_string(const char *str); +/* MODULAR ACCESSIBLE */ MYSQL *get_mysql_conn(); +#endif +#endif diff --git a/src/overall.h b/src/overall.h new file mode 100644 index 0000000..8f167e9 --- /dev/null +++ b/src/overall.h @@ -0,0 +1,159 @@ +/* overall.h - NeonServ v5.3 + * Copyright (C) 2011-2012 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _overall_h +#define _overall_h +#include "../config.h" + +#define NEONSERV_VERSION "5.3" +#define VERSION_PATCHLEVEL 543 + +#include +#include +#include +#include +#ifdef WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#ifdef HAVE_THREADS +#include +#ifdef WIN32 +#define pthread_self_tid() pthread_self().p +#else +#define pthread_self_tid() pthread_self() +#endif +#define THREAD_MUTEX_INIT(var) { \ + pthread_mutexattr_t mutex_attr; \ + pthread_mutexattr_init(&mutex_attr);\ + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP);\ + pthread_mutex_init(&var, &mutex_attr); \ +} +#define THREAD_MUTEX_INIT_TYPE(var, type) { \ + pthread_mutexattr_t mutex_attr; \ + pthread_mutexattr_init(&mutex_attr);\ + pthread_mutexattr_settype(&mutex_attr, type);\ + pthread_mutex_init(&var, &mutex_attr); \ +} +#define SYNCHRONIZE(var) pthread_mutex_lock(&var) +#define SET_SYNCHRONIZE(var) pthread_mutex_trylock(&var) +#define DESYNCHRONIZE(var) pthread_mutex_unlock(&var) +#else +#define THREAD_MUTEX_INIT(var) +#define SYNCHRONIZE(var) +#define DESYNCHRONIZE(var) +#endif + +#if __GNUC__ +#define PRINTF_LIKE(M,N) __attribute__((format (printf, M, N))) +#else +#define PRINTF_LIKE(M,N) +#endif + +#if __GNUC__ >= 2 +#define UNUSED_ARG(ARG) ARG __attribute__((unused)) +#elif defined(S_SPLINT_S) +#define UNUSED_ARG(ARG) /*@unused@*/ ARG +#define const /*@observer@*/ /*@temp@*/ +#else +#define UNUSED_ARG(ARG) ARG +#endif + +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) + +#if defined(__GNUC__) +#if defined(__GNUC_PATCHLEVEL__) +#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__) +#else +#define COMPILER "GCC" " " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) +#endif +#elif defined (__IMAGECRAFT__) +#define COMPILER "ICCAVR" +#else +#define COMPILER "Unknown" +#endif + +#ifdef ENABLE_MEMORY_DEBUG +#include "memoryDebug.h" +#endif + +#define PID_FILE "neonserv.pid" +#define CONF_FILE "neonserv.conf" +#define LOG_FILE "neonserv.log" + +#define SOCKET_SELECT_TIME 1 +#define SOCKET_RECONNECT_TIME 20 + +#define NICKLEN 30 +#define USERLEN 10 +#define AUTHLEN 32 +#define HOSTLEN 63 +#define REALLEN 50 +#define TOPICLEN 500 +#define CHANNELLEN 200 +#define MAXLEN 512 +#define MAXLOGLEN 1024 +#define TRIGGERLEN 50 +#define MAXNUMPARAMS 200 /* maximum number of parameters in one line */ +#define MAXLANGUAGES 5 +#define MAXMODES 6 +#define INVITE_TIMEOUT 30 +#define BOTWAR_DETECTION_TIME 7 +#define BOTWAR_DETECTION_EVENTS 6 +#define REWHO_TIMEOUT 10 /* wait 10 seconds before WHO an unauthed user again */ +#define TICKS_PER_SECOND 10 + +//valid nick chars +#define VALID_NICK_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890{|}~[\\]^-_`" +//the first char is a little bit different +// 0 1 2 3 4 5 6 +// 1234567890123456789012345678901234567890123456789012345678 9012 62 +#define VALID_NICK_CHARS_FIRST "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~[\\]^_`" +#define VALID_NICK_CHARS_FIRST_LEN 62 + +#define TEMPUSER_LIST_INDEX VALID_NICK_CHARS_FIRST_LEN + +#define LOGLEVEL_INFO 0x01 +#define LOGLEVEL_ERROR 0x02 +#define LOGLEVEL_RAW 0x04 +#define LOGLEVEL_MYSQL 0x08 + +#define timeval_is_bigger(x,y) ((x.tv_sec > y.tv_sec) || (x.tv_sec == y.tv_sec && x.tv_usec > y.tv_usec)) + +#define perror(errmsg) (putlog(LOGLEVEL_ERROR, "ERROR (%s:%d) %s", __FILE__, __LINE__, errmsg)) + +#define MODSTATE_RELOAD 0x01 +#define MODSTATE_STARTSTOP 0x02 +#define MODSTATE_REBIND 0x03 + +#endif diff --git a/src/timeq.c b/src/timeq.c index 41e4b1a..4b30285 100644 --- a/src/timeq.c +++ b/src/timeq.c @@ -44,11 +44,11 @@ void timeq_tick() { DESYNCHRONIZE(synchronized); } -struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data) { - return timeq_uadd(seconds * 1000, callback, data); +struct timeq_entry* timeq_add(int seconds, int module_id, timeq_callback_t *callback, void *data) { + return timeq_uadd(seconds * 1000, module_id, callback, data); } -struct timeq_entry* timeq_uadd(int useconds, timeq_callback_t *callback, void *data) { +struct timeq_entry* timeq_uadd(int useconds, int module_id, timeq_callback_t *callback, void *data) { struct timeval now; gettimeofday(&now, NULL); struct timeq_entry *entry = malloc(sizeof(*entry)); @@ -61,6 +61,7 @@ struct timeq_entry* timeq_uadd(int useconds, timeq_callback_t *callback, void *d now.tv_usec += (useconds % 1000); now.tv_sec += (useconds / 1000); entry->execute = now; + entry->module_id = module_id; entry->callback = callback; entry->data = data; entry->name = NULL; @@ -82,13 +83,13 @@ struct timeq_entry* timeq_uadd(int useconds, timeq_callback_t *callback, void *d return entry; } -struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data) { - return timeq_uadd_name(name, seconds * 1000, callback, data); +struct timeq_entry* timeq_add_name(char *name, int seconds, int module_id, timeq_callback_t *callback, void *data) { + return timeq_uadd_name(name, seconds * 1000, module_id, callback, data); } -struct timeq_entry* timeq_uadd_name(char *name, int useconds, timeq_callback_t *callback, void *data) { +struct timeq_entry* timeq_uadd_name(char *name, int useconds, int module_id, timeq_callback_t *callback, void *data) { SYNCHRONIZE(synchronized); - struct timeq_entry *entry = timeq_uadd(useconds, callback, data); + struct timeq_entry *entry = timeq_uadd(useconds, module_id, callback, data); entry->name = strdup(name); DESYNCHRONIZE(synchronized); return entry; @@ -149,3 +150,21 @@ int timeq_name_exists(char *name) { DESYNCHRONIZE(synchronized); return 0; } + +void unregister_module_timers(int module_id) { + SYNCHRONIZE(synchronized); + struct timeq_entry *centry, *next, *last = NULL; + for(centry = timeq_events; centry; centry = next) { + next = centry->next; + if(centry->module_id == module_id) { + if(last) + last->next = centry->next; + else + timeq_events = centry->next; + free(centry->name); + free(centry); + } else + last = centry; + } + DESYNCHRONIZE(synchronized); +} diff --git a/src/timeq.h b/src/timeq.h index 4e943b7..f5a65d4 100644 --- a/src/timeq.h +++ b/src/timeq.h @@ -24,6 +24,7 @@ typedef TIMEQ_CALLBACK(timeq_callback_t); struct timeq_entry { char *name; + int module_id; struct timeval execute; timeq_callback_t *callback; void *data; @@ -31,14 +32,16 @@ struct timeq_entry { struct timeq_entry *next; }; +#ifndef DND_FUNCTIONS void init_timeq(); void timeq_tick(); -struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data); -struct timeq_entry* timeq_uadd(int useconds, timeq_callback_t *callback, void *data); -struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data); -struct timeq_entry* timeq_uadd_name(char *name, int useconds, timeq_callback_t *callback, void *data); -int timeq_del(struct timeq_entry* entry); -int timeq_del_name(char *name); -int timeq_name_exists(char *name); - -#endif \ No newline at end of file +/* MODULAR ACCESSIBLE */ struct timeq_entry* timeq_add(int seconds, int module_id, timeq_callback_t *callback, void *data); +/* MODULAR ACCESSIBLE */ struct timeq_entry* timeq_uadd(int useconds, int module_id, timeq_callback_t *callback, void *data); +/* MODULAR ACCESSIBLE */ struct timeq_entry* timeq_add_name(char *name, int seconds, int module_id, timeq_callback_t *callback, void *data); +/* MODULAR ACCESSIBLE */ struct timeq_entry* timeq_uadd_name(char *name, int useconds, int module_id, timeq_callback_t *callback, void *data); +/* MODULAR ACCESSIBLE */ int timeq_del(struct timeq_entry* entry); +/* MODULAR ACCESSIBLE */ int timeq_del_name(char *name); +/* MODULAR ACCESSIBLE */ int timeq_name_exists(char *name); +void unregister_module_timers(int module_id); +#endif +#endif diff --git a/src/tools.h b/src/tools.h index 7be2e0d..6a37f6b 100644 --- a/src/tools.h +++ b/src/tools.h @@ -51,20 +51,6 @@ struct ModeBuffer { int delCount; }; -int match(const char *mask, const char *name); - -struct Table *table_init(int width, int length, int flags); -int table_add(struct Table *table, char **entry); -int table_change(struct Table *table, int row, char **entry); -int table_change_field(struct Table *table, int row, int col, char *entry); -int table_set_bold(struct Table *table, int collum, int bold); -char **table_end(struct Table *table); -void table_free(struct Table *table); - -char* timeToStr(struct UserNode *user, int seconds, int items, char *buf); -int strToTime(struct UserNode *user, char *str); - -struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan); #define modeBufferSimpleMode(MODEBUF,ADD,MODE) modeBufferSet(MODEBUF, ADD, MODE, NULL) #define modeBufferOp(MODEBUF,USER) modeBufferSet(MODEBUF, 1, 'o', USER) #define modeBufferDeop(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'o', USER) @@ -74,20 +60,37 @@ struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode * #define modeBufferDevoice(MODEBUF,USER) modeBufferSet(MODEBUF, 0, 'v', USER) #define modeBufferBan(MODEBUF,MASK) modeBufferSet(MODEBUF, 1, 'b', MASK) #define modeBufferUnban(MODEBUF,MASK) modeBufferSet(MODEBUF, 0, 'b', MASK) -void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param); -void flushModeBuffer(struct ModeBuffer *modeBuf); -void freeModeBuffer(struct ModeBuffer *modeBuf); -int is_ircmask(const char *text); +#ifndef DND_FUNCTIONS +/* MODULAR ACCESSIBLE */ int match(const char *mask, const char *name); + +/* MODULAR ACCESSIBLE */ struct Table *table_init(int width, int length, int flags); +/* MODULAR ACCESSIBLE */ int table_add(struct Table *table, char **entry); +/* MODULAR ACCESSIBLE */ int table_change(struct Table *table, int row, char **entry); +/* MODULAR ACCESSIBLE */ int table_change_field(struct Table *table, int row, int col, char *entry); +/* MODULAR ACCESSIBLE */ int table_set_bold(struct Table *table, int collum, int bold); +/* MODULAR ACCESSIBLE */ char **table_end(struct Table *table); +/* MODULAR ACCESSIBLE */ void table_free(struct Table *table); + +/* MODULAR ACCESSIBLE */ char* timeToStr(struct UserNode *user, int seconds, int items, char *buf); +/* MODULAR ACCESSIBLE */ int strToTime(struct UserNode *user, char *str); + +/* MODULAR ACCESSIBLE */ struct ModeBuffer* initModeBuffer(struct ClientSocket *client, struct ChanNode *chan); +/* MODULAR ACCESSIBLE */ void modeBufferSet(struct ModeBuffer *modeBuf, int add, char mode, char *param); +/* MODULAR ACCESSIBLE */ void flushModeBuffer(struct ModeBuffer *modeBuf); +/* MODULAR ACCESSIBLE */ void freeModeBuffer(struct ModeBuffer *modeBuf); + +/* MODULAR ACCESSIBLE */ int is_ircmask(const char *text); -char* generate_banmask(struct UserNode *user, char *buffer); -char* make_banmask(char *input, char* buffer); -int isFakeHost(char *host); +/* MODULAR ACCESSIBLE */ char* generate_banmask(struct UserNode *user, char *buffer); +/* MODULAR ACCESSIBLE */ char* make_banmask(char *input, char* buffer); +/* MODULAR ACCESSIBLE */ int isFakeHost(char *host); -int mask_match(char *mask, struct UserNode *user); +/* MODULAR ACCESSIBLE */ int mask_match(char *mask, struct UserNode *user); -unsigned long crc32(const char *text); +/* MODULAR ACCESSIBLE */ unsigned long crc32(const char *text); void init_tools(); -#endif \ No newline at end of file +#endif +#endif diff --git a/src/version.h b/src/version.h index 1248409..8784d08 100644 --- a/src/version.h +++ b/src/version.h @@ -19,10 +19,13 @@ #include "main.h" +#define MODULE_VERSION 1 + +#ifndef DND_FUNCTIONS extern const char *compilation; extern const char *creation; extern const char *revision; extern const char *codelines; extern const int patchlevel; - -#endif \ No newline at end of file +#endif +#endif