rearranged NeonServ code to be modular
authorpk910 <philipp@zoelle1.de>
Sat, 11 Feb 2012 21:21:50 +0000 (22:21 +0100)
committerpk910 <philipp@zoelle1.de>
Sat, 11 Feb 2012 21:24:10 +0000 (22:24 +0100)
298 files changed:
src/BanNode.h
src/ChanNode.h
src/ChanUser.h
src/ClientSocket.h
src/ConfigParser.h
src/DBHelper.h
src/EventLogger.h
src/HandleInfoHandler.h
src/IRCEvents.c
src/IRCEvents.h
src/IRCParser.h
src/ModeNode.h
src/UserNode.h
src/WHOHandler.c
src/WHOHandler.h
src/bot_DummyServ.c [deleted file]
src/bot_DummyServ.h [deleted file]
src/bot_NeonHelp.c [deleted file]
src/bot_NeonHelp.h [deleted file]
src/bot_NeonServ.c [deleted file]
src/bot_NeonServ.h [deleted file]
src/bot_NeonSpam.c [deleted file]
src/bot_NeonSpam.h [deleted file]
src/bots.c
src/bots.h
src/cmd_funcmds.c [deleted file]
src/cmd_funcmds.h [deleted file]
src/cmd_global.h [deleted file]
src/cmd_global_addbot.c [deleted file]
src/cmd_global_bind.c [deleted file]
src/cmd_global_bots.c [deleted file]
src/cmd_global_command.c [deleted file]
src/cmd_global_commands.c [deleted file]
src/cmd_global_delbot.c [deleted file]
src/cmd_global_die.c [deleted file]
src/cmd_global_emote.c [deleted file]
src/cmd_global_god.c [deleted file]
src/cmd_global_meminfo.c [deleted file]
src/cmd_global_modcmd.c [deleted file]
src/cmd_global_motd.c [deleted file]
src/cmd_global_netinfo.c [deleted file]
src/cmd_global_notice.c [deleted file]
src/cmd_global_raw.c [deleted file]
src/cmd_global_reconnect.c [deleted file]
src/cmd_global_register.c [deleted file]
src/cmd_global_reload.c [deleted file]
src/cmd_global_reloadlang.c [deleted file]
src/cmd_global_restart.c [deleted file]
src/cmd_global_say.c [deleted file]
src/cmd_global_setaccess.c [deleted file]
src/cmd_global_setbot.c [deleted file]
src/cmd_global_staff.c [deleted file]
src/cmd_global_unbind.c [deleted file]
src/cmd_global_unregister.c [deleted file]
src/cmd_global_version.c [deleted file]
src/cmd_neonhelp.h [deleted file]
src/cmd_neonhelp_delete.c [deleted file]
src/cmd_neonhelp_next.c [deleted file]
src/cmd_neonhelp_requests.c [deleted file]
src/cmd_neonhelp_stats.c [deleted file]
src/cmd_neonserv.h [deleted file]
src/cmd_neonserv_access.c [deleted file]
src/cmd_neonserv_addban.c [deleted file]
src/cmd_neonserv_addrank.c [deleted file]
src/cmd_neonserv_addtimeban.c [deleted file]
src/cmd_neonserv_adduser.c [deleted file]
src/cmd_neonserv_assignrank.c [deleted file]
src/cmd_neonserv_ban.c [deleted file]
src/cmd_neonserv_bans.c [deleted file]
src/cmd_neonserv_chanservsync.c [deleted file]
src/cmd_neonserv_clvl.c [deleted file]
src/cmd_neonserv_csuspend.c [deleted file]
src/cmd_neonserv_cunsuspend.c [deleted file]
src/cmd_neonserv_dehalfop.c [deleted file]
src/cmd_neonserv_dehalfopall.c [deleted file]
src/cmd_neonserv_delban.c [deleted file]
src/cmd_neonserv_delme.c [deleted file]
src/cmd_neonserv_delrank.c [deleted file]
src/cmd_neonserv_deluser.c [deleted file]
src/cmd_neonserv_deop.c [deleted file]
src/cmd_neonserv_deopall.c [deleted file]
src/cmd_neonserv_devoice.c [deleted file]
src/cmd_neonserv_devoiceall.c [deleted file]
src/cmd_neonserv_down.c [deleted file]
src/cmd_neonserv_downall.c [deleted file]
src/cmd_neonserv_events.c [deleted file]
src/cmd_neonserv_extscript.c [deleted file]
src/cmd_neonserv_giveowner.c [deleted file]
src/cmd_neonserv_halfop.c [deleted file]
src/cmd_neonserv_halfopall.c [deleted file]
src/cmd_neonserv_help.c [deleted file]
src/cmd_neonserv_info.c [deleted file]
src/cmd_neonserv_invite.c [deleted file]
src/cmd_neonserv_inviteme.c [deleted file]
src/cmd_neonserv_kick.c [deleted file]
src/cmd_neonserv_kickban.c [deleted file]
src/cmd_neonserv_listrank.c [deleted file]
src/cmd_neonserv_mdeluser.c [deleted file]
src/cmd_neonserv_mode.c [deleted file]
src/cmd_neonserv_move.c [deleted file]
src/cmd_neonserv_myaccess.c [deleted file]
src/cmd_neonserv_nicklist.c [deleted file]
src/cmd_neonserv_noregister.c [deleted file]
src/cmd_neonserv_op.c [deleted file]
src/cmd_neonserv_opall.c [deleted file]
src/cmd_neonserv_oplog.c [deleted file]
src/cmd_neonserv_peek.c [deleted file]
src/cmd_neonserv_recover.c [deleted file]
src/cmd_neonserv_rename.c [deleted file]
src/cmd_neonserv_resync.c [deleted file]
src/cmd_neonserv_search.c [deleted file]
src/cmd_neonserv_set.c [deleted file]
src/cmd_neonserv_setrank.c [deleted file]
src/cmd_neonserv_suspend.c [deleted file]
src/cmd_neonserv_topic.c [deleted file]
src/cmd_neonserv_trace.c [deleted file]
src/cmd_neonserv_trim.c [deleted file]
src/cmd_neonserv_unban.c [deleted file]
src/cmd_neonserv_unbanall.c [deleted file]
src/cmd_neonserv_unbanme.c [deleted file]
src/cmd_neonserv_unsuspend.c [deleted file]
src/cmd_neonserv_unvisited.c [deleted file]
src/cmd_neonserv_up.c [deleted file]
src/cmd_neonserv_upall.c [deleted file]
src/cmd_neonserv_users.c [deleted file]
src/cmd_neonserv_uset.c [deleted file]
src/cmd_neonserv_voice.c [deleted file]
src/cmd_neonserv_voiceall.c [deleted file]
src/cmd_neonserv_wipeinfo.c [deleted file]
src/cmd_neonspam.h [deleted file]
src/cmd_neonspam_set.c [deleted file]
src/commands.c [deleted file]
src/commands.h [deleted file]
src/event_neonserv_ctcp.c [deleted file]
src/event_neonserv_invite.c [deleted file]
src/event_neonserv_join.c [deleted file]
src/event_neonserv_kick.c [deleted file]
src/event_neonserv_mode.c [deleted file]
src/event_neonserv_notice.c [deleted file]
src/event_neonserv_part.c [deleted file]
src/event_neonserv_quit.c [deleted file]
src/event_neonserv_topic.c [deleted file]
src/event_neonspam_chanmsg.c [deleted file]
src/event_neonspam_join.c [deleted file]
src/lang.c
src/lang.h
src/main.c
src/main.h
src/memoryDebug.c
src/memoryDebug.h
src/memoryInfo.h
src/modcmd.c
src/modcmd.h
src/modules.c [new file with mode: 0644]
src/modules.h [new file with mode: 0644]
src/modules/DummyServ.mod/bot_DummyServ.c [new file with mode: 0644]
src/modules/DummyServ.mod/bot_DummyServ.h [new file with mode: 0644]
src/modules/DummyServ.mod/module.c [new file with mode: 0644]
src/modules/NeonHelp.mod/bot_NeonHelp.c [new file with mode: 0644]
src/modules/NeonHelp.mod/bot_NeonHelp.h [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp.c [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp.h [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp_delete.c [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp_next.c [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp_requests.c [new file with mode: 0644]
src/modules/NeonHelp.mod/cmd_neonhelp_stats.c [new file with mode: 0644]
src/modules/NeonHelp.mod/module.c [new file with mode: 0644]
src/modules/NeonServ.mod/bot_NeonServ.c [new file with mode: 0644]
src/modules/NeonServ.mod/bot_NeonServ.h [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv.h [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_access.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_addban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_addrank.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_addtimeban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_adduser.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_assignrank.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_ban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_bans.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_chanservsync.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_clvl.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_csuspend.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_cunsuspend.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_dehalfop.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_dehalfopall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_delban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_delme.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_delrank.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_deluser.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_deop.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_deopall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_devoice.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_devoiceall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_down.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_downall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_events.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_extscript.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_giveowner.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_halfop.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_halfopall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_help.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_info.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_invite.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_inviteme.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_kick.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_kickban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_listrank.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_mdeluser.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_mode.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_move.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_myaccess.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_nicklist.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_noregister.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_op.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_opall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_oplog.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_peek.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_recover.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_rename.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_resync.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_search.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_set.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_setrank.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_suspend.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_topic.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_trace.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_trim.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_unban.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_unbanall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_unbanme.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_unsuspend.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_unvisited.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_up.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_upall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_users.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_uset.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_voice.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_voiceall.c [new file with mode: 0644]
src/modules/NeonServ.mod/cmd_neonserv_wipeinfo.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_ctcp.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_invite.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_join.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_kick.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_mode.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_notice.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_part.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_quit.c [new file with mode: 0644]
src/modules/NeonServ.mod/event_neonserv_topic.c [new file with mode: 0644]
src/modules/NeonServ.mod/module.c [new file with mode: 0644]
src/modules/NeonSpam.mod/bot_NeonSpam.c [new file with mode: 0644]
src/modules/NeonSpam.mod/bot_NeonSpam.h [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam.c [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam.h [new file with mode: 0644]
src/modules/NeonSpam.mod/cmd_neonspam_set.c [new file with mode: 0644]
src/modules/NeonSpam.mod/event_neonspam_chanmsg.c [new file with mode: 0644]
src/modules/NeonSpam.mod/event_neonspam_join.c [new file with mode: 0644]
src/modules/NeonSpam.mod/module.c [new file with mode: 0644]
src/modules/funcmd.mod/cmd_funcmds.c [new file with mode: 0644]
src/modules/funcmd.mod/cmd_funcmds.h [new file with mode: 0644]
src/modules/funcmd.mod/module.c [new file with mode: 0644]
src/modules/global.mod/cmd_global.c [new file with mode: 0644]
src/modules/global.mod/cmd_global.h [new file with mode: 0644]
src/modules/global.mod/cmd_global_addbot.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_bind.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_bots.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_command.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_commands.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_delbot.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_die.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_emote.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_god.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_meminfo.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_modcmd.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_motd.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_netinfo.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_notice.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_raw.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_reconnect.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_register.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_reload.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_reloadlang.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_restart.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_say.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_setaccess.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_setbot.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_staff.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_unbind.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_unregister.c [new file with mode: 0644]
src/modules/global.mod/cmd_global_version.c [new file with mode: 0644]
src/modules/global.mod/module.c [new file with mode: 0644]
src/modules/module.h [new file with mode: 0644]
src/mysqlConn.c
src/mysqlConn.h
src/overall.h [new file with mode: 0644]
src/timeq.c
src/timeq.h
src/tools.h
src/version.h

index 2367eb83df539a996ff165169f20b36c09ac0fba..028b599346bc4ebe1f0d4764daa85baf25475fbc 100644 (file)
@@ -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
index d0bb4a5f06d24c5b05d38c1be7fd1e511451e535..38a1d892d24f6ab51fdb2f4674aa5ee1aff97cb1 100644 (file)
@@ -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
index 00bfc977b74eb13ffcd059466c2ca23a5749fafb..3e5ca8a702759a9d5bb154bf492b31a5790aeb13 100644 (file)
@@ -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
index 78e207c0144b2372ca0967701d13c01691c87895..34db5d6c6f2b843dd03a4c455db6c6282128741a 100644 (file)
@@ -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
index 231871c2935b6122cef0f9d940240d34fd9d473e..fb529da2eeef41bc2e0a8f0e34fd3e185cc7fbe5 100644 (file)
 #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
index 01658f4cf5f1b70fa9359d598e2478bdf634cf63..55c782c662214f0d93da97227e367d9910a79086 100644 (file)
@@ -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
index 4b8927cd04449fa0ec2fb4653b0c5ef9acc98860..312aa21d406baa91b295cbef47a2334473058e34 100644 (file)
@@ -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
index d5bb9bdf2d806188d134bbfe4913d71583a78a53..c44b9a15e3a766691e9bca65f806c51a4b4b9c17 100644 (file)
@@ -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
index eb29a094ff23f8c3ea238b1c3ea81c488afb1d5f..9e0222bcbb1afaabc915d63045ae40a3d30acd7b 100644 (file)
@@ -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; \
index ceccd642e29b5375010d1f711d7c4e4c988d6544..ff4b972f4fb15474f5593857cdd590b1f2adb5d0 100644 (file)
@@ -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
index 7731cb78aaa004fe298b5a3041deb4098a9146e6..cdf271448ef869e5441b557e0616b301b1c8c4c9 100644 (file)
@@ -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
index 29121c0a3b18a9116aeb9e425229ed846251fb86..07f025710cf0a5b5fa78e753ec11e6c1d3dde8ce 100644 (file)
@@ -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
index bf07e7e133e97701b69e4e7d21e1dea382f3b20e..fb1afc1567c7ce8fd7613de1c6dcdf81fe394c46 100644 (file)
@@ -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
index 28547188eb3f0e0f2e22213a98af3a344ccdf5c5..743896ee39d3572756e66a96f057dea7c6071b4b 100644 (file)
@@ -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;
index 68ad205646b940f0bcc6063c58211129e0c7abc6..76b279b455d51547622d135c7bf1fd685a892c11 100644 (file)
@@ -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 (file)
index afcb637..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 79e6f4b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 1922262..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 2cbf694..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 61d41d6..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 397d34f..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 3c08748..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index a95f3bc..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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
index c9b06164a0caf974d992324dd92fff1e69ff82e5..994dbbac5d0153ac8db931ab105c1b3e00a4248e 100644 (file)
@@ -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;
index 578f509b97e11ae29b6ea94aada6d030387a1237..3344d38753348d5bd515eca9cb2693442e04df67 100644 (file)
@@ -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 (file)
index 3f4095a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 37dc779..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 55bb5a7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 1783834..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 2842cf8..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 57ab153..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 594ea1b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index caeac97..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b017f12..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index c80b0b0..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 494e5e3..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 3e54b7f..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index bdcf45a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 1506a35..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0340e47..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 3d01c98..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b42b1c3..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 1d8ce55..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index acf8c2e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 548860d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 883b3ed..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index d99062e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index ad580cd..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index e81cfc4..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0458bd6..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index e823a9e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 3f1989e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 8cd8f45..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 206e763..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 307e34c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0fce87a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 43d5829..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 2e2a2d1..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b95a4b4..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0d1d9a4..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0df1a7b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 25b2501..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index fffadf5..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 6ade32d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 837812e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0e8432b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 4fedaf8..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 84a497a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 7ad47e1..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 8581cb2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index a541c3d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9ff2fea..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 53a997d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index f995e0f..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 1cb58d0..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 3b4f9d8..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 256ca69..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 489b32a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 5188f01..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 20a4f44..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 7b1cdb2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index e7ced34..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9254e46..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index fd29475..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index a7add47..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index de4fd6c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index e4a4e2e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#include "cmd_neonserv.h"
-#include <fcntl.h>
-
-/*
-* 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 (file)
index 9cf5ae7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index ba684cb..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index a52ad6d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 20ec2c2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 17a9df6..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 60c00a2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 54c2dbf..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 7ffcf65..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 1123cd7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 65d53cf..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 50090dd..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 8a11e36..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 211247e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b9f6581..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 181923c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index f0ba380..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 6bf3b28..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b6bdacc..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9cf412b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 51de508..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index f48a8c5..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9b87be4..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 7c60a6e..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 2cefe55..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index ec21e44..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index f0c20f7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index b6d18b4..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 76abea6..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index eacb67f..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 65a0e73..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index f88033b..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index cff9531..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index ac1fa6c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 4053950..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9d7cda7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 930df02..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 0f12379..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index cd8d375..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 25a3118..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 49dfe6c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 779110c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 71a1cc8..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 9989192..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index efaee45..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 8705b81..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-#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 (file)
index 1c92d55..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-#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 (file)
index 11d03e2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 2b53429..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 77d5de7..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 8e32d02..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index f0794a9..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 84fb51a..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index e41436c..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index b2f0401..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 577e0a3..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 163315d..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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 (file)
index 5a169f2..0000000
+++ /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 <http://www.gnu.org/licenses/>. 
- */
-
-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;
-}
-
-
index 1c0a027cdf1d3a293f6b2d3c10cd96030711aed5..b56322ce2e4421c7201e6d32732ba1a882d831ed 100644 (file)
@@ -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
index 162d6ae79e771481204bb699f6eb54110c257854..2115050d8de2cfdf7a14abb7ae1e2583ddb19a15 100644 (file)
@@ -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
index 79043b19452374fe9648859ccc074ca88e94163a..0ca3d31ea190c1be70efb3f6eded83e96dfa43d9 100644 (file)
@@ -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)) {
index eb39d49b9acf60083c79e77265afb2c2dfede1e5..f1430318a4fadbf3f4ed303e4c4a0a9dcbaad5b1 100644 (file)
  */
 #ifndef _main_h
 #define _main_h
-#include "../config.h"
-
-#define NEONSERV_VERSION "5.3"
-#define VERSION_PATCHLEVEL 543
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifdef WIN32
-#include <windows.h>
-#include <winsock2.h>
-#include <malloc.h>
-#else
-#include <features.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <sys/wait.h>
-#endif
-#include <unistd.h>
-#include <getopt.h>
-#include <stdarg.h>
-#include <sys/time.h>
-#include <time.h>
-#ifdef HAVE_THREADS
-#include <pthread.h>
-#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
index e870f4ba4854f2253a1b424b41c7b71a91dc0f81..b8cb9cec664a61b44f21e774b9c983490ef1c517 100644 (file)
@@ -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);
 }
index c07d494cbf03c9d9e8e1920edcd72f0c379fea2e..9a3adac767e3b589812571bd74157a3bf247367d 100644 (file)
 #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
index f1cca21dc9ab84075dfcfa66f74ef4e35201c99a..f6987bf6f1807edf6f95c9272d8c2971210d91d5 100644 (file)
@@ -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
index 8846d900197bc75b53c1e0181a04b062a093058a..7ba0b939d6cae97eba0645fade114475474accfd 100644 (file)
@@ -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;
+    }
+}
index 7465254d0615cd3dd457ad0579789384c9e72c61..0ccd7f51cc7a6613e3b11556df36e06f082885b0 100644 (file)
@@ -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 (file)
index 0000000..0c2034e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..321b5c1
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..9d9d720
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..7483fec
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..1213b68
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..f3df2fc
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..eaf47ff
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..252d112
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..9a74fbf
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..43d5829
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..2e2a2d1
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b95a4b4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0d1d9a4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..16ecc77
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..e6ec912
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..883275c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..5c24826
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..9c31b16
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..25b2501
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..fffadf5
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..6ade32d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..837812e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0e8432b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..4fedaf8
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..84a497a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..7ad47e1
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..8581cb2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..a541c3d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9ff2fea
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..53a997d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f995e0f
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..1cb58d0
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..3b4f9d8
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..256ca69
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..489b32a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..5188f01
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..20a4f44
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..7b1cdb2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..e7ced34
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9254e46
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..fd29475
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..a7add47
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..de4fd6c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..e4a4e2e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#include "cmd_neonserv.h"
+#include <fcntl.h>
+
+/*
+* 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 (file)
index 0000000..9cf5ae7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..ba684cb
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..a52ad6d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..20ec2c2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..17a9df6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..60c00a2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..54c2dbf
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..7ffcf65
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..1123cd7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..65d53cf
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..50090dd
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..8a11e36
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..211247e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b9f6581
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..181923c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f0ba380
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..6bf3b28
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b6bdacc
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9cf412b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..51de508
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f48a8c5
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9b87be4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..7c60a6e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..2cefe55
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..ec21e44
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f0c20f7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b6d18b4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..76abea6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..eacb67f
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..65a0e73
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f88033b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..cff9531
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..ac1fa6c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..4053950
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..9d7cda7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0085b5f
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0f12379
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..cd8d375
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..25a3118
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..49dfe6c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..779110c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..71a1cc8
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..11d03e2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..2b53429
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..77d5de7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..8e32d02
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..f0794a9
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..84fb51a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..e41436c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..b2f0401
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..577e0a3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..fff4b4b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..5784f63
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..34a24b5
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..f013299
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..9989192
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..efaee45
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..163315d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..5a169f2
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+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 (file)
index 0000000..64581de
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..dc3cb8b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..70125dd
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..c23dea7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..9741e6c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..5b3f553
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..1783834
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..2842cf8
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..57ab153
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..594ea1b
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..caeac97
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b017f12
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..c80b0b0
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..494e5e3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..3e54b7f
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..bdcf45a
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..1506a35
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0340e47
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..3d01c98
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..b42b1c3
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..1d8ce55
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..acf8c2e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..548860d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..883b3ed
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..d99062e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..ad580cd
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..e81cfc4
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..0458bd6
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..88ffeac
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..3f1989e
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..8cd8f45
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..206e763
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..307e34c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#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 (file)
index 0000000..3fe2703
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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 (file)
index 0000000..6fc0a8c
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+#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
index 3c2bcbeb3cb9391d85a54212d2b0e255d0d1f3dc..41f049570938d781ef8ec7fa755aa7d0ddd92ec1 100644 (file)
@@ -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));
index 3af13c26e7032d72c671fb4f3f25ea3487ac9f82..410f346fbf4ee164055c5bc4c53f7eb940e74e35 100644 (file)
 
 #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 (file)
index 0000000..8f167e9
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>. 
+ */
+
+#ifndef _overall_h
+#define _overall_h
+#include "../config.h"
+
+#define NEONSERV_VERSION "5.3"
+#define VERSION_PATCHLEVEL 543
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef WIN32
+#include <windows.h>
+#include <winsock2.h>
+#include <malloc.h>
+#else
+#include <features.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/wait.h>
+#endif
+#include <unistd.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <time.h>
+#ifdef HAVE_THREADS
+#include <pthread.h>
+#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
index 41e4b1a3b1dec349c6547c191e87bd9defac812e..4b30285a543746963472a1ac6ae576d07fc9c250 100644 (file)
@@ -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);
+}
index 4e943b7de8003ae4d38616e6e291cb7a71889ed5..f5a65d4d98ef0ae8164ab3b34c80d87ad933fbd2 100644 (file)
@@ -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
index 7be2e0d233088efb3f5ea0cbcaa7ff0ed73a8788..6a37f6b27deee5e6bc90fee178eaf70e197ef779 100644 (file)
@@ -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
index 1248409047086fdf9de365c9030f7ca149cd4fd1..8784d08e7c61c4cbb940ef77c732cd75adcc00a4 100644 (file)
 
 #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