#include "module.h" #define AUTHOR "SGR" #define VERSION "1.19" /* ----------------------------------------------------------- * Name: bs_fantasy * Author: SGR * Date: 14/07/2004 * ----------------------------------------------------------- * Functions: Too bloody many. * Limitations: NONE KNOWN. * Tested: Bahamut-1.8.1+AcidIRC(UVS+HOSTCLOAKING+DYNAMIC_ALIASES) * ----------------------------------------------------------- * This version has been tested on Ultimate2.8.6, viagra * Unreal and Bahamut. All IRCd's should be compatible with * this module. NOTE: this testing was pretty quick and crap. * Indeed, hardly 'testing' at all. * * This module will add the following commands onto the BotServ * FANTASY engine for channels that have it enabled: * * !clear USERS * !clear OPS * !clear VOICES * !clear MODES * !clear BANS * !clear EXCEPTS * !sop ADD [nick] * !sop DEL [nick] * !aop ADD [nick] * !aop DEL [nick] * !hop ADD [nick] * !hop DEL [nick] * !vop ADD [nick] * !vop DEL [nick] * !akick ADD [mask|nick] * !akick STICK [mask] * !akick UNSTICK [mask] * !akick DEL [mask|number|nick] * !akick ENFORCE * !set FOUNDER [nick] * !set SUCCESSOR [nick] * !set EMAIL [address] * !set URL [address] * !set BANTYPE [number] * !set MLOCK [modes] * !set KEEPTOPIC [on|off] * !set TOPICLOCK [on|off] * !set PRIVATE [on|off] * !set SECUREOPS [on|off] * !set SECURE [on|off] * !set SECUREFOUNDER [on|off] * !set RESTRICTED [on|off] * !set SIGNKICK [on|off] * !set OPNOTICE [on|off] * !set XOP [on|off] * !set PEACE [on|off] * !assign [botnick] * !unassign [CONFIRM] * !logout [nick] * !ban [nick] * !mute [nick] * !badwords ADD START [word] * !badwords ADD END [word] * !badwords ADD ANY [word] * !badwords ADD SINGLE [word] * !badwords DEL [word] * !level SET level [number] * !level DIS [level] * !level DISABLE [level] * !levels SET level [number] * !levels DISABLE [level] * !levels DIS [level] * !help * !cmdlist * !kill NICK [reason] * !suspend CHAN [reason] * !forbid CHAN [reason] * !bot ADD [nick|user|host|realname] * !bot DEL [nick] * !bot CHANGE [oldnick|nick|user|host|realname] * * * Please be aware this is an "in development" module that is being * added to and updated. As such this module is BETA, and unsupported. * * This module has no configurable options. * * ----------------------------------------------------------- * Change Log: * * 1: Core * * 2: Fixed spelling issue in successor. * * 2: Completed and tested !badwords and !levels. Added * !set XOP, !suspend, !set noexpire, !forbid and * !access to this 'to do' list. * * 3: finally sorted !set XOP and made !clear for non- * channel staff requrire SuperAdmin not just services * admin. Also coded a !help (!cmdlist) of Fantasy * commands that are suported and added !suspend and * !kill for services admins and opers (in that order). * * 4: Minor typo corrected [botnick used instead of ChanServ * on incorrect syntax message. [Reported by doh] * * 5: Fixed major bug in !mute code [Don't Ask *shudder*]. * * 6: Removed some un-necessary code that might of * caused a memory leak - though I can't see how its * possible - There is still prolly leaks about that I * havent seen - PLEASE REPORT THEM! * Also added !forbid and !bot functionality. * * UPDATE: Thanks to a memory debug report from doh I've * removed a memory leak - that _should_ mean this module * is now entirely leak free. I've done it using a nasty * goto method - but it should work and be efficient. * * 7: Modified code relating to chanmode +e [Excepts] to apply * to bahamut since bahamut now officially supports them. * [Is commented out untill anope updates core] * * 8: Added !akill, !global * * 9: Cleaned up some #ifdefs so module compiles for Unreal * users. * * 10: Added support for anope-1.7.x * * 11: Updated Anope-1.7.x support for revision 364 and * later. Revision 364 or later is now REQUIRED for * for Anope-1.7.x support from this module. * * 12: Fixed Typo. * * 13: Fixed issue with realname for !bot ADD containing the * hostmask for the bot too. [Thanks crazytoon] * * 14: Added some extra (supposedly un-necessary, but * obviously not) sanity checks. Reported by doh. * * ----------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* START OF CONFIGURATION BLOCK - please read the comments :) */ /* ---------------------------------------------------------------------- */ /* If you are using Anope-1.7.x or later, leave this alone. * Otherwise change it to '#undef ANOPE17x' (no quotes). * * THIS IS IMPORTANT * */ #define ANOPE17x /* ---------------------------------------------------------------------- */ /* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING */ /* ---------------------------------------------------------------------- */ #ifndef ANOPE17x #include "../pseudo.h" #define do_cmode(a,b,c,d) chan_set_modes(a,c,d) #define MYGetHost GetHost #define MYNEWNICK(a,b,c,d,e,f) NEWNICK(a,b,c,d,e,f) #else #include "../../include/pseudo.h" #define MYGetHost common_get_vhost #define wallops anope_cmd_global #define MYNEWNICK(a,b,c,d,e,f) anope_cmd_bot_nick(a,b,c,d,ircd->botserv_bot_mode) #define do_cmode(a,b,c,d) chan_set_modes(a,b,c,d,0) #endif int bot_privmsg(char *source, int ac, char **av); void botchanmsg(User *u, ChannelInfo *ci, char *buf); static int do_forbid(User * u, char *chan, char *reason); static int do_clear(User * u, Channel *c, int TYPE); static int xop_del_callback(User * u, int num, va_list args); static int xop_list(User * u, int index, ChannelInfo * ci, int *sent_header, int xlev, int xmsg); static int xop_list_callback(User * u, int num, va_list args); static int akick_del_callback(User * u, int num, va_list args); static int do_suspend(User * u, ChannelInfo *ci, char *reason); static int do_badwords(User * u, ChannelInfo *ci, char *cmd, char *word, char *style); static int do_assign(User * u, char *chan, char *nick); static int do_unassign(User * u, char *chan); static int do_set_xop(User * u, ChannelInfo * ci, char *param); static int do_logout(User * u, char *chan, char *nick); static void unassign(User * u, ChannelInfo * ci); static int is_real_founder(User * user, ChannelInfo * ci); static void make_unidentified(User * u, ChannelInfo * ci); static int do_xop(User * u, char *xname, int xlev, int *xmsgs, char *chan, char *cmd, char *nick); static int xop_del_callback(User * u, int num, va_list args); static int akick_del(User * u, AutoKick * akick); static char *get_mlock_modes(ChannelInfo * ci, int complete); static int do_set_founder(User * u, ChannelInfo * ci, char *param); static int do_set_successor(User * u, ChannelInfo * ci, char *param); static int do_set_email(User * u, ChannelInfo * ci, char *param); static int do_set_url(User * u, ChannelInfo * ci, char *param); static int do_set_bantype(User * u, ChannelInfo * ci, char *param); static int do_set_keeptopic(User * u, ChannelInfo * ci, char *param); static int do_set_topiclock(User * u, ChannelInfo * ci, char *param); static void reset_levelsb(ChannelInfo * ci); static int do_set_private(User * u, ChannelInfo * ci, char *param); static int do_set_secureops(User * u, ChannelInfo * ci, char *param); static int do_set_signkick(User * u, ChannelInfo * ci, char *param); static int do_set_opnotice(User * u, ChannelInfo * ci, char *param); static int do_set_restricted(User * u, ChannelInfo * ci, char *param); static int do_set_securefounder(User * u, ChannelInfo * ci, char *param); static int do_set_peace(User * u, ChannelInfo * ci, char *param); static int do_set_secure(User * u, ChannelInfo * ci, char *param); static int do_set_mlock(User * u, ChannelInfo * ci, char *param); static int do_ban(User * u, char *chan, char *params); static int badwords_del_callback(User * u, int num, va_list args); static int do_levels(User *u, ChannelInfo *ci, char *cmd, char *what, /*char *s,*/ short level); static void insert_bot(BotInfo * bi); static void change_bot_nick(BotInfo * bi, char *newnick); static int delbot(BotInfo * bi); static int do_bot(User * u, int WHAT, char *oldnick, char *nick, char *user, char *host, char *real); static ChannelInfo *makechan(const char *chan); static int do_akick(User * u, char *chan, char *cmd, char *mask, char *reason); static int delchana(ChannelInfo * ci); static BotInfo *makebotA(char *nick); #ifdef HAS_EXCEPT extern int is_excepted(ChannelInfo * ci, User * user); extern int is_excepted_mask(ChannelInfo * ci, char *mask); #endif #ifndef ANOPE17x static void EnforceQlinedNick(char *nick, char *killer); static void alpha_insert_chan(ChannelInfo * ci); #endif #define isvalidnick(c) ( isalnum(c) || ((c) >='\x5B' && (c) <='\x60') || ((c) >='\x7B' && (c) <='\x7D') || (c)=='-' ) #define MyFree(x) if ((x) != NULL) { free(x); } extern int nbots; int xop_msgs[4][14] = { { CHAN_AOP_SYNTAX, CHAN_AOP_DISABLED, CHAN_AOP_NICKS_ONLY, CHAN_AOP_ADDED, CHAN_AOP_MOVED, CHAN_AOP_NO_SUCH_ENTRY, CHAN_AOP_NOT_FOUND, CHAN_AOP_NO_MATCH, CHAN_AOP_DELETED, CHAN_AOP_DELETED_ONE, CHAN_AOP_DELETED_SEVERAL, CHAN_AOP_LIST_EMPTY, CHAN_AOP_LIST_HEADER, CHAN_AOP_CLEAR }, { CHAN_SOP_SYNTAX, CHAN_SOP_DISABLED, CHAN_SOP_NICKS_ONLY, CHAN_SOP_ADDED, CHAN_SOP_MOVED, CHAN_SOP_NO_SUCH_ENTRY, CHAN_SOP_NOT_FOUND, CHAN_SOP_NO_MATCH, CHAN_SOP_DELETED, CHAN_SOP_DELETED_ONE, CHAN_SOP_DELETED_SEVERAL, CHAN_SOP_LIST_EMPTY, CHAN_SOP_LIST_HEADER, CHAN_SOP_CLEAR }, { CHAN_VOP_SYNTAX, CHAN_VOP_DISABLED, CHAN_VOP_NICKS_ONLY, CHAN_VOP_ADDED, CHAN_VOP_MOVED, CHAN_VOP_NO_SUCH_ENTRY, CHAN_VOP_NOT_FOUND, CHAN_VOP_NO_MATCH, CHAN_VOP_DELETED, CHAN_VOP_DELETED_ONE, CHAN_VOP_DELETED_SEVERAL, CHAN_VOP_LIST_EMPTY, CHAN_VOP_LIST_HEADER, CHAN_VOP_CLEAR }, { CHAN_HOP_SYNTAX, CHAN_HOP_DISABLED, CHAN_HOP_NICKS_ONLY, CHAN_HOP_ADDED, CHAN_HOP_MOVED, CHAN_HOP_NO_SUCH_ENTRY, CHAN_HOP_NOT_FOUND, CHAN_HOP_NO_MATCH, CHAN_HOP_DELETED, CHAN_HOP_DELETED_ONE, CHAN_HOP_DELETED_SEVERAL, CHAN_HOP_LIST_EMPTY, CHAN_HOP_LIST_HEADER, CHAN_HOP_CLEAR } }; typedef struct { int what; char *name; int desc; } LevelInfoX; static LevelInfoX levelinfo[] = { { CA_AUTODEOP, "AUTODEOP", CHAN_LEVEL_AUTODEOP }, #ifdef HAS_HALFOP { CA_AUTOHALFOP, "AUTOHALFOP", CHAN_LEVEL_AUTOHALFOP }, #endif { CA_AUTOOP, "AUTOOP", CHAN_LEVEL_AUTOOP }, #if defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_UNREAL32) { CA_AUTOPROTECT, "AUTOPROTECT", CHAN_LEVEL_AUTOPROTECT }, #endif #ifdef IRC_ULTIMATE3 { CA_AUTOPROTECT, "AUTOADMIN", CHAN_LEVEL_AUTOPROTECT }, #endif { CA_AUTOVOICE, "AUTOVOICE", CHAN_LEVEL_AUTOVOICE }, { CA_NOJOIN, "NOJOIN", CHAN_LEVEL_NOJOIN }, { CA_SIGNKICK, "SIGNKICK", CHAN_LEVEL_SIGNKICK }, { CA_ACCESS_LIST, "ACC-LIST", CHAN_LEVEL_ACCESS_LIST }, { CA_ACCESS_CHANGE, "ACC-CHANGE", CHAN_LEVEL_ACCESS_CHANGE }, { CA_AKICK, "AKICK", CHAN_LEVEL_AKICK }, { CA_SET, "SET", CHAN_LEVEL_SET }, { CA_BAN, "BAN", CHAN_LEVEL_BAN }, { CA_BANME, "BANME", CHAN_LEVEL_BANME }, { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR }, { CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY }, #ifdef HAS_HALFOP { CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP }, { CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME }, #endif { CA_INFO, "INFO", CHAN_LEVEL_INFO }, { CA_KICK, "KICK", CHAN_LEVEL_KICK }, { CA_KICKME, "KICKME", CHAN_LEVEL_KICKME }, { CA_INVITE, "INVITE", CHAN_LEVEL_INVITE }, { CA_OPDEOP, "OPDEOP", CHAN_LEVEL_OPDEOP }, { CA_OPDEOPME, "OPDEOPME", CHAN_LEVEL_OPDEOPME }, #if defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_ULTIMATE3) || defined(IRC_UNREAL32) { CA_PROTECT, "PROTECT", CHAN_LEVEL_PROTECT }, { CA_PROTECTME, "PROTECTME", CHAN_LEVEL_PROTECTME }, #endif { CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC }, { CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN }, { CA_VOICE, "VOICE", CHAN_LEVEL_VOICE }, { CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME }, { CA_MEMO, "MEMO", CHAN_LEVEL_MEMO }, { CA_ASSIGN, "ASSIGN", CHAN_LEVEL_ASSIGN }, { CA_BADWORDS, "BADWORDS", CHAN_LEVEL_BADWORDS }, { CA_FANTASIA, "FANTASIA", CHAN_LEVEL_FANTASIA }, { CA_GREET, "GREET", CHAN_LEVEL_GREET }, { CA_NOKICK, "NOKICK", CHAN_LEVEL_NOKICK }, { CA_SAY, "SAY", CHAN_LEVEL_SAY }, { -1 } }; static int def_levels[][2] = { { CA_AUTOOP, 5 }, { CA_AUTOVOICE, 3 }, { CA_AUTODEOP, -1 }, { CA_NOJOIN, -2 }, { CA_INVITE, 5 }, { CA_AKICK, 10 }, { CA_SET, ACCESS_INVALID }, { CA_CLEAR, ACCESS_INVALID }, { CA_UNBAN, 5 }, { CA_OPDEOP, 5 }, { CA_ACCESS_LIST, 1 }, { CA_ACCESS_CHANGE, 10 }, { CA_MEMO, 10 }, { CA_ASSIGN, ACCESS_INVALID }, { CA_BADWORDS, 10 }, { CA_NOKICK, 1 }, { CA_FANTASIA, 3 }, { CA_SAY, 5 }, { CA_GREET, 5 }, { CA_VOICEME, 3 }, { CA_VOICE, 5 }, { CA_GETKEY, 5 }, { CA_AUTOHALFOP, 4 }, { CA_AUTOPROTECT, 10 }, { CA_OPDEOPME, 5 }, { CA_HALFOPME, 4 }, { CA_HALFOP, 5 }, { CA_PROTECTME, 10 }, { CA_PROTECT, ACCESS_INVALID }, { CA_KICKME, 5 }, { CA_KICK, 5 }, { CA_SIGNKICK, ACCESS_INVALID }, { CA_BANME, 5 }, { CA_BAN, 5 }, { CA_TOPIC, ACCESS_INVALID }, { CA_INFO, ACCESS_INVALID }, { -1 } }; char *whosend; int AnopeInit(int argc, char **argv) { int status; Message *msg = NULL; msg = createMessage("PRIVMSG", bot_privmsg); status = moduleAddMessage(msg, MOD_TAIL); moduleAddAuthor(AUTHOR); moduleAddVersion(VERSION); alog("bot_fantasy.so: loaded, message status [%d]", status); return MOD_CONT; } void AnopeFini(void) { alog("Unloading module bot_fantasy.so"); } int bot_privmsg(char *source, int ac, char **av) { User *u; ChannelInfo *ci; if (!source || (ac < 2)) { return MOD_CONT; } u = finduser(source); if (*av[0] == '#') { if (s_BotServ && ((ci = cs_findchan(av[0])))) { if (!(ci->flags & CI_VERBOTEN) && ci->c && ci->bi) { /* Some paranoia checks */ (void) botchanmsg(u, ci, av[1]); } } } return MOD_CONT; } void botchanmsg(User *u, ChannelInfo *ci, char *buf) { int command = 0; char *buffer = moduleGetLastBuffer(); char *cmd = buf; char *arg1 = myStrGetToken(buffer,' ',0); char *arg2 = myStrGetToken(buffer,' ',1); char *arg3 = myStrGetToken(buffer,' ',2); int ISA = 0; int IAO = 0; Channel *c = findchan(ci->name); whosend = whosends(ci); if ((!u) || (!c) || (!cmd)) { goto cleanup_and_exit; } if (!(*cmd == '!')) { goto cleanup_and_exit; } if (!whosend) { whosend = s_ChanServ; } cmd++; if (!(cmd && (ci->botflags & BS_FANTASY) && check_access(u, ci, CA_FANTASIA))) { goto cleanup_and_exit; } if (!stricmp(cmd,"CLEAR")) { command = 1; } // DONE - ALL [users, ops, voices, bans, modes, exempts] else if (!stricmp(cmd,"SOP")) { command = 2; } // DONE - ADD + DEL (clear not included for security reasons) else if (!stricmp(cmd,"AOP")) { command = 3; } // DONE - ADD + DEL (clear not included for security reasons) #ifdef HAS_HALFOP else if (!stricmp(cmd,"HOP")) { command = 4; } // DONE - ADD + DEL (clear not included for security reasons) #endif else if (!stricmp(cmd,"VOP")) { command = 5; } // DONE - ADD + DEL (clear not included for security reasons) else if (!stricmp(cmd,"AKICK")) { command = 6; } // DONE - ADD, DEL, STICK, UNSTICK, ENFORCE (clear/list not inc.) else if (!stricmp(cmd,"ACCESS")) { command = 7; } else if (!stricmp(cmd,"SET")) { command = 8; } // DONE - ALL but XOP. else if (!stricmp(cmd,"ASSIGN")) { command = 9; } // DONE - ALL else if (!stricmp(cmd,"UNASSIGN")) { command = 10; } // DONE - ALL else if (!stricmp(cmd,"BADWORDS")) { command = 11; } // DONE - ADD + DEL (clear/list not inc.) else if (!stricmp(cmd,"LEVELS")) { command = 12; } // DONE - ADD + DEL (reset/list not inc.) else if (!stricmp(cmd,"LEVEL")) { command = 12; } // DONE - ADD + DEL (reset/list not inc.) else if (!stricmp(cmd,"LOGOUT")) { command = 13; } // DONE else if (!stricmp(cmd,"BAN")) { command = 14; } // DONE else if (!stricmp(cmd,"MUTE")) { command = 14; } // DONE else if (!stricmp(cmd,"CMDLIST")) { command = 15; } // DONE else if (!stricmp(cmd,"HELP")) { command = 15; } // DONE else if (!stricmp(cmd,"TTFO")) { command = 16; } // DONE else if (!stricmp(cmd,"KILL")) { command = 17; } // DONE else if (!stricmp(cmd,"SUSPEND")) { command = 18; } // DONE else if (!stricmp(cmd,"FORBID")) { command = 19; } // DONE else if (!stricmp(cmd,"BOT")) { command = 20; } // DONE - ADD + DEL + CHANGE (list not inc.) else if (!stricmp(cmd,"AKILL")) { command = 21; } // DONE - ADD only. [!akill nick reason] else if (!stricmp(cmd,"GLOBAL")) { command = 22; } // DONE else if (!stricmp(cmd,"SKICK")) { command = 23; } // DONE else { goto cleanup_and_exit; } ISA = is_services_admin(u); IAO = is_oper(u); /* if (arg1) { alog("arg1: %s", arg1); } if (arg2) { alog("arg2: %s", arg2); } */ /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !CLEAR /// --------------------------------------------------------------------------------- if (command == 1) { /// !CLEAR ... [Buzzzzz] ... [Beep]..[Beep]..[Beep]..etc.. if ((SuperAdmin ? (!u->isSuperAdmin && !check_access(u, ci, CA_CLEAR)) : ISA)) { goto cleanup_and_exit; } if (!arg1) { notice(whosend, u->nick, "SYNTAX: !clear [modes|users|ops|voices|bans|exempts]"); goto cleanup_and_exit; } if (!stricmp("modes",arg1)) { do_clear(u, c, 1); } else if (!stricmp("bans",arg1)) { do_clear(u, c, 2); } else if (!stricmp("users",arg1)) { do_clear(u, c, 3); } else if (!stricmp("ops",arg1)) { do_clear(u, c, 4); } else if (!stricmp("voices",arg1)) { do_clear(u, c, 5); } else if (!stricmp("exempts",arg1)) { do_clear(u, c, 6); } else { goto cleanup_and_exit; } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !SOP /// --------------------------------------------------------------------------------- if (command == 2) { if (!arg1 || !arg2) { notice(whosend, u->nick, "SYNTAX: !sop [add|del] [nick]"); goto cleanup_and_exit; } if (!stricmp("add",arg1)) { do_xop(u, "SOP", ACCESS_SOP, xop_msgs[1], c->name, arg1, arg2); } if (!stricmp("del",arg1)) { do_xop(u, "SOP", ACCESS_SOP, xop_msgs[1], c->name, arg1, arg2); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !AOP /// --------------------------------------------------------------------------------- if (command == 3) { if (!arg1 || !arg2) { notice(whosend, u->nick, "SYNTAX: !aop [add|del] [nick]"); goto cleanup_and_exit; } if (!stricmp("add",arg1)) { do_xop(u, "AOP", ACCESS_AOP, xop_msgs[0], c->name, arg1, arg2); } if (!stricmp("del",arg1)) { do_xop(u, "AOP", ACCESS_AOP, xop_msgs[0], c->name, arg1, arg2); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !HOP /// --------------------------------------------------------------------------------- if (command == 4) { #ifdef HAS_HALFOP if (!arg1 && !arg2) { notice(whosend, u->nick, "SYNTAX: !hop [add|del] [nick]"); goto cleanup_and_exit; } if (!stricmp("add",arg1)) { do_xop(u, "HOP", ACCESS_HOP, xop_msgs[3], c->name, arg1, arg2); } if (!stricmp("del",arg1)) { do_xop(u, "HOP", ACCESS_HOP, xop_msgs[3], c->name, arg1, arg2); } #endif goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !VOP /// --------------------------------------------------------------------------------- if (command == 5) { if (!arg1 && !arg2) { notice(whosend, u->nick, "SYNTAX: !vop [add|del] [nick]"); goto cleanup_and_exit; } if (!stricmp("add",arg1)) { do_xop(u, "VOP", ACCESS_VOP, xop_msgs[2], c->name, arg1, arg2); } if (!stricmp("del",arg1)) { do_xop(u, "VOP", ACCESS_VOP, xop_msgs[2], c->name, arg1, arg2); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !AKICK /// --------------------------------------------------------------------------------- if (command == 6) { if (!arg1) { notice(whosend, u->nick, "SYNTAX: !akick [ADD|STICK|UNSTICK|DEL|ENFORCE|CLEAR]"); goto cleanup_and_exit; } if (!stricmp(arg1, "ADD")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !akick ADD [mask|nick]"); goto cleanup_and_exit; } do_akick(u, c->name, arg1, arg2, "[Added via !akick]"); goto cleanup_and_exit; } else if (!stricmp(arg1, "STICK")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !akick STICK [mask]"); goto cleanup_and_exit; } do_akick(u, c->name, arg1, arg2, NULL); goto cleanup_and_exit; } else if (!stricmp(arg1, "UNSTICK")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !akick UNSTICK [mask]"); goto cleanup_and_exit; } do_akick(u, c->name, arg1, arg2, NULL); goto cleanup_and_exit; } else if (!stricmp(arg1, "DEL")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !akick DEL [mask]"); goto cleanup_and_exit; } do_akick(u, c->name, arg1, arg2, NULL); goto cleanup_and_exit; } else if (!stricmp(arg1, "ENFORCE")) { do_akick(u, c->name, arg1, NULL, NULL); goto cleanup_and_exit; } else if (!stricmp(arg1, "CLEAR")) { do_akick(u, c->name, arg1, NULL, NULL); goto cleanup_and_exit; } else { notice(whosend, u->nick, "SYNTAX: !akick [ADD|STICK|UNSTICK|DEL|ENFORCE]"); goto cleanup_and_exit; } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !ACCESS /// --------------------------------------------------------------------------------- if (command == 7) { goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !SET /// --------------------------------------------------------------------------------- if (command == 8) { if (readonly) { notice_lang(whosend, u, CHAN_SET_DISABLED); goto cleanup_and_exit; } if (!ISA && !check_access(u, ci, CA_SET)) { notice_lang(whosend, u, ACCESS_DENIED); goto cleanup_and_exit; } if (!arg1) { notice(whosend, u->nick, " SYNTAX: !set [FOUNDER|SUCCESSOR|EMAIL|URL|BANTYPE|MLOCK]"); notice(whosend, u->nick, "SYNTAX cont.: !set [KEEPTOPIC|TOPICLOCK|PRIVATE|SECUREOPS|SECURE]"); notice(whosend, u->nick, "SYNTAX cont.: !set [SECUREFOUNDER|RESTRICTED|SIGNKICK|OPNOTICE]"); notice(whosend, u->nick, "SYNTAX cont.: !set [XOP|PEACE]"); goto cleanup_and_exit; } if (!stricmp(arg1,"FOUNDER")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set FOUNDER [nick]"); goto cleanup_and_exit; } if (!ISA && (ci->flags & CI_SECUREFOUNDER ? !is_real_founder(u,ci) : !is_founder(u, ci))) { notice_lang(whosend, u, ACCESS_DENIED); } else { do_set_founder(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"SUCCESSOR")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set SUCCESSOR [nick]"); goto cleanup_and_exit; } if (!ISA && (ci->flags & CI_SECUREFOUNDER ? !is_real_founder(u,ci) : !is_founder(u, ci))) { notice_lang(whosend, u, ACCESS_DENIED); } else { do_set_successor(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"EMAIL")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set EMAIL [address|UNSET]"); notice(whosend, u->nick, "-- If the text \"UNSET\" is provided for the email address,"); notice(whosend, u->nick, "-- any saved email address for this channel will be deleted."); goto cleanup_and_exit; } if (!stricmp(arg1,"UNSET")) { do_set_email(u, ci, NULL); } else { do_set_email(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"URL")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set URL [address|UNSET]"); notice(whosend, u->nick, "-- If the text \"UNSET\" is provided for the URL, any saved"); notice(whosend, u->nick, "-- link for this channel will be deleted."); goto cleanup_and_exit; } if (!stricmp(arg1,"UNSET")) { do_set_url(u, ci, NULL); } else { do_set_url(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"BANTYPE")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set BANTYPE [number]"); goto cleanup_and_exit; } do_set_bantype(u, ci, arg2); goto cleanup_and_exit; } else if (!stricmp(arg1,"MLOCK")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set MLOCK [modes]"); goto cleanup_and_exit; } do_set_mlock(u, ci, arg2); goto cleanup_and_exit; } else if (!stricmp(arg1,"KEEPTOPIC")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set KEEPTOPIC [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_keeptopic(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_keeptopic(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set KEEPTOPIC [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"TOPICLOCK")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set TOPICLOCK [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_topiclock(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_topiclock(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set TOPICLOCK [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"PRIVATE")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set PRIVATE [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_private(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_private(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set PRIVATE [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"SECURE")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set SECURE [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_secure(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_secure(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set SECURE [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"SECUREOPS")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set SECUREOPS [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_secureops(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_secureops(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set SECUREOPS [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"SECUREFOUNDER")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set SECUREFOUNDER [on|off]"); goto cleanup_and_exit; } if (!ISA && (ci->flags & CI_SECUREFOUNDER ? !is_real_founder(u, ci) : !is_founder(u, ci))) { notice_lang(whosend, u, ACCESS_DENIED); } else { do_set_securefounder(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"RESTRICTED")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set RESTRICTED [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_restricted(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_restricted(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set RESTRICTED [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"SIGNKICK")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set SIGNKICK [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_signkick(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_signkick(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set SIGNKICK [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"OPNOTICE")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set OPNOTICE [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_opnotice(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_opnotice(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set OPNOTICE [on|off]"); } goto cleanup_and_exit; } else if (!stricmp(arg1,"XOP")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set XOP [on|off]"); goto cleanup_and_exit; } if (!u->isSuperAdmin && !is_founder(u, ci)) { notice_lang(whosend, u, ACCESS_DENIED); goto cleanup_and_exit; } else if (!stricmp("ON",arg2)) { do_set_xop(u, ci, arg2); } else if (!stricmp("OFF",arg2)) { do_set_xop(u, ci, arg2); } goto cleanup_and_exit; } else if (!stricmp(arg1,"PEACE")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !set PEACE [on|off]"); goto cleanup_and_exit; } if (!stricmp(arg2,"ON")) { do_set_peace(u, ci, arg2); } else if (!stricmp(arg2,"OFF")) { do_set_peace(u, ci, arg2); } else { notice(whosend, u->nick, "SYNTAX: !set PEACE [on|off]"); } goto cleanup_and_exit; } else { notice(whosend, u->nick, " SYNTAX: !set [FOUNDER|SUCESSOR|EMAIL|URL|BANTYPE|MLOCK]"); notice(whosend, u->nick, "SYNTAX cont.: !set [KEEPTOPIC|TOPICLOCK|PRIVATE|SECUREOPS|SECURE]"); notice(whosend, u->nick, "SYNTAX cont.: !set [SECUREFOUNDER|RESTRICTED|SIGNKICK|OPNOTICE]"); notice(whosend, u->nick, "SYNTAX cont.: !set [XOP|PEACE]"); goto cleanup_and_exit; } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !ASSIGN /// --------------------------------------------------------------------------------- if (command == 9) { if (!arg1) { notice(whosend, u->nick, "SYNTAX: !assign [botnick]"); goto cleanup_and_exit; } do_assign(u, c->name, arg1); goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !UNASSIGN /// --------------------------------------------------------------------------------- if (command == 10) { if (!arg1) { notice(whosend, u->nick, "SYNTAX: !unassign CONFIRM"); notice(whosend, u->nick, "-- The text \"CONFIRM\" is required and must be uppercase."); goto cleanup_and_exit; } if (!(!strcmp(arg1,"CONFIRM"))) { notice(whosend, u->nick, "SYNTAX: !unassign CONFIRM"); notice(whosend, u->nick, "-- The text \"CONFIRM\" is required and must be uppercase."); goto cleanup_and_exit; } do_unassign(u, c->name); goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !BADWORDS /// --------------------------------------------------------------------------------- if (command == 11) { if (!arg1 || !arg2) { notice(whosend, u->nick, "SYNTAX: !badwords ADD [START|SINGLE|END|ANY] [phrase]"); notice(whosend, u->nick, "SYNTAX: !badwords DEL [word|num]"); goto cleanup_and_exit; } if (!stricmp(arg1,"ADD")) { if (!arg3) { notice(whosend, u->nick, "SYNTAX: !badwords ADD [START|SINGLE|END|ANY] [phrase]"); notice(whosend, u->nick, "SYNTAX: !badwords DEL [word|num]"); goto cleanup_and_exit; } if (!stricmp(arg2,"end")) { do_badwords(u, ci, arg1, arg3, arg2); goto cleanup_and_exit; } else if (!stricmp(arg2,"single")) { do_badwords(u, ci, arg1, arg3, arg2); goto cleanup_and_exit; } else if (!stricmp(arg2,"start")) { do_badwords(u, ci, arg1, arg3, arg2); goto cleanup_and_exit; } else if (!stricmp(arg2,"any")) { do_badwords(u, ci, arg1, arg3, arg2); goto cleanup_and_exit; } else { notice(whosend, u->nick, "SYNTAX: !badwords ADD [START|SINGLE|END|ANY] [phrase]"); notice(whosend, u->nick, "SYNTAX: !badwords DEL [word|num]"); notice(whosend, u->nick, "ERROR: Invalid style specified. Please specify START, SINGLE, ANY or END only."); goto cleanup_and_exit; } goto cleanup_and_exit; } if (!stricmp(arg1,"DEL")) { do_badwords(u, ci, arg1, arg2, NULL); goto cleanup_and_exit; } else { notice(whosend, u->nick, "SYNTAX: !badwords ADD [START|SINGLE|END|ANY] [phrase]"); notice(whosend, u->nick, "SYNTAX: !badwords DEL [word|num]"); goto cleanup_and_exit; } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !LEVELS /// --------------------------------------------------------------------------------- // //do_levels(User *u, ChannelInfo *ci, char *cmd, char *what, char *s) if (command == 12) { char *error; short level; if (!arg1 || !arg2) { notice(whosend, u->nick, "SYNTAX: !levels [SET|DISABLE] [level] [value]"); goto cleanup_and_exit; } if (!stricmp(arg1,"SET")) { if (!arg3) { notice(whosend, u->nick, "SYNTAX: !levels [SET|DISABLE] [level] [value]"); notice(whosend, u->nick, "Error: no value provided with SET parameter."); goto cleanup_and_exit; } level = strtol(arg3, &error, 10); if (*error != '\0') { notice(whosend, u->nick, "SYNTAX: !levels [SET|DISABLE] [level] [value]"); notice(whosend, u->nick, "Error: value provided was non-numerical."); goto cleanup_and_exit; } do_levels(u, ci, arg1, arg2, level); goto cleanup_and_exit; } if (!stricmp(arg1,"DIS") || !stricmp(arg1,"DISABLE")) { do_levels(u, ci, arg1, arg2, 0); goto cleanup_and_exit; } else { notice(whosend, u->nick, "SYNTAX: !levels [SET|DISABLE] [level] [value]"); goto cleanup_and_exit; } } // /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !LOGOUT /// --------------------------------------------------------------------------------- if (command == 13) { if (!arg1) { notice(whosend, u->nick, "SYNTAX: !logout [nick]"); goto cleanup_and_exit; } do_logout(u, c->name, arg1); goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !BAN && !MUTE /// --------------------------------------------------------------------------------- if (command == 14) { if (!arg1) { notice(whosend, u->nick, "SYNTAX: !mute [nick]"); goto cleanup_and_exit; } do_ban(u, c->name, arg1); goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !CMDLIST + !HELP /// --------------------------------------------------------------------------------- if (command == 15) { notice(whosend, u->nick, "\002The supported commands are:\002"); notice(whosend, u->nick, "!op, !deop, !kick, !ban, !kb, !voice, !devoice"); notice(whosend, u->nick, "!unban, !seen, !vop, !aop, !sop, !clear, !akick"); notice(whosend, u->nick, "!set, !assign, !unassign, !logout, !levels"); notice(whosend, u->nick, "!badwords, !mute," #ifdef HAS_HALFOP " !hop, !vop" #endif #if defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_UNREAL32) ", !owner, !deowner" #endif ); if (IAO) { notice(whosend, u->nick, " "); notice(whosend, u->nick, "For Opers: !kill, !ttfo, !global, !skick"); if (ISA) { notice(whosend, u->nick, "For Services Admins: !suspend, !forbid, !bot, !akill."); } } notice(whosend, u->nick, " "); notice(whosend, u->nick, "Please note, \002some\002 commands, (e.g. !set) have "); notice(whosend, u->nick, "their own syntax. This will be displayed if"); notice(whosend, u->nick, "you say the command without any parameters."); goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !TTFO (sorta an easter egg :\) /// --------------------------------------------------------------------------------- #define USE_EGG //please leave this :) #ifdef USE_EGG if (command == 16) { if (!arg1) { goto cleanup_and_exit; } if (((((!strcmp("SGR",arg1)) || (!strcmp("SGR|AWAY",arg1))) && strstr(u->host,"broadband.ntl.com"))) || IAO) { privmsg(whosend, ci->name, "%s, someone who matters wants me to tell you this: \002FUCK OFF\002 :)", arg1); } goto cleanup_and_exit; } #endif /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !KILL /// --------------------------------------------------------------------------------- if (command == 17) { User *u2; if (!IAO) { goto cleanup_and_exit; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !kill [nick] [reason]"); } else if ((u2 = finduser(arg1))) { char killreason[600]; if (!arg2) { snprintf(killreason, sizeof(killreason), "Requested by %s (No reason).", u->nick); kill_user(s_OperServ, u2->nick, killreason); } else { char *reason = myStrGetTokenRemainder(buffer,' ',1); snprintf(killreason, sizeof(killreason), "Requested by %s (%s)", u->nick, reason); kill_user(s_OperServ, u2->nick, killreason); MyFree(reason); } } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !SUSPEND /// --------------------------------------------------------------------------------- if (command == 18) { if (!ISA) { goto cleanup_and_exit; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !suspend [#chan] [reason]"); } else if (!arg2) { do_suspend(u, ci, NULL); } else { char *reason = myStrGetTokenRemainder(buffer,' ',1); do_suspend(u, ci, reason); MyFree(reason); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !FORBID /// --------------------------------------------------------------------------------- if (command == 19) { if (!ISA) { goto cleanup_and_exit; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !forbid [#chan] [reason]"); } else if (!arg2) { do_forbid(u, arg1, NULL); } else { char *reason = myStrGetTokenRemainder(buffer,' ',1); do_forbid(u, arg1, reason); MyFree(reason); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !BOT /// --------------------------------------------------------------------------------- if (command == 20) { if (!ISA) { return; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !bot [ADD] [nick] [username] [host] [realname]"); notice(whosend, u->nick, "SYNTAX: !bot [DEL] [nick]"); notice(whosend, u->nick, "SYNTAX: !bot [CHANGE] [nick] [new-nick] [new-username] [new-host] [new-realname]"); goto cleanup_and_exit; } else if (!stricmp(arg1,"ADD")) { char *arg4 = myStrGetToken(buffer,' ',3); char *arg5 = myStrGetTokenRemainder(buffer,' ',4); if (!arg2 || !arg3 || !arg4 || !arg5) { notice(whosend, u->nick, "SYNTAX: !bot [ADD] [nick] [username] [host] [realname]"); MyFree(arg4); MyFree(arg5); goto cleanup_and_exit; } do_bot(u, 2, NULL, arg2, arg3, arg4, arg5); MyFree(arg4); MyFree(arg5); goto cleanup_and_exit; } else if (!stricmp(arg1,"DEL")) { if (!arg2) { notice(whosend, u->nick, "SYNTAX: !bot [DEL] [nick]"); goto cleanup_and_exit; } do_bot(u, 1, NULL, arg2, NULL, NULL, NULL); goto cleanup_and_exit; } else if (!stricmp(arg1,"CHANGE")) { char *arg4 = myStrGetToken(buffer,' ',3); char *arg5 = myStrGetToken(buffer,' ',4); char *arg6 = myStrGetTokenRemainder(buffer,' ',5); if (!arg2 || !arg3 || !arg4 || !arg5 || !arg6) { notice(whosend, u->nick, "SYNTAX: !bot [CHANGE] [nick] [new-nick] [new-username] [new-host] [new-realname]"); MyFree(arg4); MyFree(arg5); MyFree(arg6); goto cleanup_and_exit; } do_bot(u, 3, arg2, arg3, arg4, arg5, arg6); MyFree(arg4); MyFree(arg5); MyFree(arg6); goto cleanup_and_exit; } else { notice(whosend, u->nick, "SYNTAX: !bot [ADD] [nick] [username] [host] [realname]"); notice(whosend, u->nick, "SYNTAX: !bot [DEL] [nick]"); notice(whosend, u->nick, "SYNTAX: !bot [CHANGE] [nick] [new-nick] [new-username] [new-host] [new-realname]"); goto cleanup_and_exit; } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// !AKILL /// --------------------------------------------------------------------------------- if (command == 21) { User *u2; if (!ISA) { goto cleanup_and_exit; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !akill [nick] [reason]"); notice(whosend, u->nick, "The AKILL placed will be on *@ of the nick given and"); notice(whosend, u->nick, "will last for the default AKILL time (%ds).", AutokillExpiry); } else if ((u2 = finduser(arg1))) { char killreason[500]; char mask[USERMAX + HOSTMAX + 2]; sprintf(mask, "*@%s", u2->host); if (((is_oper(u2)) || is_services_oper(u2)) && (!is_services_root(u))) { notice_lang(whosend, u, PERMISSION_DENIED); wallops(s_OperServ, "%s just attempted to AKILL %s", u->nick, u2->nick); goto cleanup_and_exit; } if (!arg2) { snprintf(killreason, sizeof(killreason), "Requested by %s (No reason).", u->nick); add_akill(u, mask, u->nick, time(NULL)+AutokillExpiry, killreason); } else { char *reason = myStrGetTokenRemainder(buffer,' ',1); snprintf(killreason, sizeof(killreason), "Requested by %s (%s)", u->nick, reason); add_akill(u, mask, u->nick, time(NULL)+AutokillExpiry, killreason); MyFree(reason); } if (!AkillOnAdd) { kill_user(s_OperServ, u2->nick, killreason); } } else { notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, arg1); } goto cleanup_and_exit; } if (command == 22) { if (!IAO || !arg1) { goto cleanup_and_exit; } else { char *msg = myStrGetTokenRemainder(buffer,' ',0); if (WallOSGlobal) { wallops(s_OperServ, "\2%s\2 just used GLOBAL command [Via BS_FANTASY - !global].", u->nick); } oper_global(u->nick, "%s", msg); MyFree(msg); } goto cleanup_and_exit; } if (command == 23) { User *u2; if (!IAO) { goto cleanup_and_exit; } else if (!arg1) { notice(whosend, u->nick, "SYNTAX: !skick [nick] [reason]"); notice(whosend, u->nick, "The skick function kicks the given user from all channels."); goto cleanup_and_exit; } else if (!(u2 = finduser(arg1))) { notice_lang(s_OperServ, u, NICK_X_NOT_IN_USE, arg1); } else { struct u_chanlist *uc, *next; ChannelInfo *ci; char *av[3]; char kickreason[500]; if (!arg2) { snprintf(kickreason, sizeof(kickreason), "Requested by %s (No reason).", u->nick); } else { char *reason = myStrGetTokenRemainder(buffer,' ',1); snprintf(kickreason, sizeof(kickreason), "Requested by %s (%s)", u->nick, reason); MyFree(reason); } for (uc = u2->chans; uc; uc = next) { next = uc->next; av[0] = sstrdup(uc->chan->name); av[1] = sstrdup(u2->nick); av[2] = sstrdup(kickreason); if ((ci = uc->chan->ci)) { send_cmd(whosends(ci), "KICK %s %s :%s", av[0], av[1], av[2]); } else { send_cmd(s_BotServ, "KICK %s %s :%s", av[0], av[1], av[2]); } do_kick(s_BotServ, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice(whosend, u->nick, "%s was booted from all channels.", u2->nick); } goto cleanup_and_exit; } /// --------------------------------------------------------------------------------- /// --------------------------------------------------------------------------------- /// [END] /// --------------------------------------------------------------------------------- cleanup_and_exit: MyFree(arg1); MyFree(arg2); MyFree(arg3); return; } static int do_clear(User * u, Channel *c, int TYPE) { // 1= Modes // 2= Bans // 3= Users // 4= Ops // 5= Voices // 6= Excepts char *chan = c->name; if (TYPE == 2) { char *av[3]; int i; /* Save original ban info */ int count = c->bancount; char **bans = scalloc(sizeof(char *) * count, 1); for (i = 0; i < count; i++) { bans[i] = sstrdup(c->bans[i]); } for (i = 0; i < count; i++) { av[0] = sstrdup(chan); av[1] = sstrdup("-b"); av[2] = bans[i]; #ifdef ANOPE17x anope_cmd_mode(whosend, av[0], "%s %s", av[1], av[2]); #else send_cmd(whosend, "MODE %s %s :%s", av[0], av[1], av[2]); #endif do_cmode(whosend, c, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice_lang(whosend, u, CHAN_CLEARED_BANS, chan); free(bans); #ifdef HAS_EXCEPT } else if (TYPE == 6) { char *av[3]; int i; /* Save original except info */ int count = c->exceptcount; char **excepts = scalloc(sizeof(char *) * count, 1); for (i = 0; i < count; i++) { excepts[i] = sstrdup(c->excepts[i]); } for (i = 0; i < count; i++) { av[0] = sstrdup(c->name); av[1] = sstrdup("-e"); av[2] = excepts[i]; #ifdef ANOPE17x anope_cmd_mode(whosend, av[0], "%s %s", av[1], av[2]); #else send_cmd(whosend, "MODE %s %s :%s", av[0], av[1], av[2]); #endif do_cmode(whosend, c, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice_lang(whosend, u, CHAN_CLEARED_EXCEPTS, chan); free(excepts); #endif } else if (TYPE == 1) { char *argv[2]; if (c->mode) { /* Clear modes */ #ifndef ANOPE17x send_cmd(s_ChanServ, "MODE %s %s %s", c->name, MODESTOREMOVE, c->key ? c->key : ""); argv[0] = sstrdup(MODESTOREMOVE); #else send_cmd(s_ChanServ, "MODE %s %s %s", c->name, ircd->modestoremove, c->key ? c->key : ""); argv[0] = sstrdup(ircd->modestoremove); #endif argv[1] = c->key ? c->key : NULL; chan_set_modes(s_OperServ, c, c->key ? 2 : 1, argv, 0); free(argv[0]); check_modes(c); } notice_lang(whosend, u, CHAN_CLEARED_MODES, chan); } else if (TYPE == 4) { char *av[3]; struct c_userlist *cu, *next; for (cu = c->users; cu; cu = next) { next = cu->next; if (!chan_has_user_status(c, cu->user, CUS_OP)) { continue; } av[0] = sstrdup(chan); av[1] = sstrdup("-o"); av[2] = sstrdup(cu->user->nick); #ifdef ANOPE17x anope_cmd_mode(whosend, av[0], "%s %s", av[1], av[2]); #else send_cmd(whosend, "MODE %s %s :%s", av[0], av[1], av[2]); #endif do_cmode(whosend, c, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice_lang(whosend, u, CHAN_CLEARED_OPS, chan); } else if (TYPE == 5) { char *av[3]; struct c_userlist *cu, *next; for (cu = c->users; cu; cu = next) { next = cu->next; if (!chan_has_user_status(c, cu->user, CUS_VOICE)) { continue; } av[0] = sstrdup(chan); av[1] = sstrdup("-v"); av[2] = sstrdup(cu->user->nick); #ifdef ANOPE17x anope_cmd_mode(whosend, av[0], "%s %s", av[1], av[2]); #else send_cmd(whosend, "MODE %s %s :%s", av[0], av[1], av[2]); #endif do_cmode(whosend, c, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice_lang(whosend, u, CHAN_CLEARED_VOICES, chan); } else if (TYPE == 3) { char *av[3]; struct c_userlist *cu, *next; char buf[256]; snprintf(buf, sizeof(buf), "CLEAR USERS command from %s", u->nick); send_cmd(whosend, "MODE %s +b *!*@* %lu", chan, time(NULL)); for (cu = c->users; cu; cu = next) { next = cu->next; av[0] = sstrdup(chan); av[1] = sstrdup(cu->user->nick); av[2] = sstrdup(buf); send_cmd(whosend, "KICK %s %s :%s", av[0], av[1], av[2]); do_kick(s_ChanServ, 3, av); free(av[2]); free(av[1]); free(av[0]); } notice_lang(whosend, u, CHAN_CLEARED_USERS, chan); } return MOD_CONT; } #define CHECKLEV(lev) ((ci->levels[(lev)] != ACCESS_INVALID) && (access->level >= ci->levels[(lev)])) static int do_set_xop(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { if (!(ci->flags & CI_XOP)) { int i; ChanAccess *access; for (access = ci->access, i = 0; i < ci->accesscount; access++, i++) { if (!access->in_use) { continue; } /* This will probably cause wrong levels to be set, but hey, * it's better than losing it altogether. */ if (CHECKLEV(CA_AKICK) || CHECKLEV(CA_SET)) { access->level = ACCESS_SOP; } else if (CHECKLEV(CA_AUTOOP) || CHECKLEV(CA_OPDEOP) || CHECKLEV(CA_OPDEOPME)) { access->level = ACCESS_AOP; } #ifdef HAS_HALFOP else if (CHECKLEV(CA_AUTOHALFOP) || CHECKLEV(CA_HALFOP) || CHECKLEV(CA_HALFOPME)) { access->level = ACCESS_HOP; } #endif else if (CHECKLEV(CA_AUTOVOICE) || CHECKLEV(CA_VOICE) || CHECKLEV(CA_VOICEME)) { access->level = ACCESS_VOP; } else { access->in_use = 0; access->nc = NULL; } } reset_levelsb(ci); ci->flags |= CI_XOP; } alog("%s: %s!%s@%s enabled XOP for %s", whosend, u->nick, u->username, MYGetHost(u), ci->name); notice_lang(whosend, u, CHAN_SET_XOP_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_XOP; alog("%s: %s!%s@%s disabled XOP for %s", whosend, u->nick, u->username, MYGetHost(u), ci->name); notice_lang(whosend, u, CHAN_SET_XOP_OFF); } else { syntax_error(whosend, u, "SET XOP", CHAN_SET_XOP_SYNTAX); } return MOD_CONT; } #undef CHECKLEV static int do_xop(User * u, char *xname, int xlev, int *xmsgs, char *chan, char *cmd, char *nick) { ChannelInfo *ci; NickAlias *na; NickCore *nc; int i; int change = 0; short ulev; int is_list = (cmd && stricmp(cmd, "LIST") == 0); int is_servadmin = is_services_admin(u); ChanAccess *access; /* If CLEAR, we don't need any parameters. * If LIST, we don't *require* any parameters, but we can take any. * If DEL or ADD we require a nick. */ if (!cmd || ((is_list || !stricmp(cmd, "CLEAR")) ? 0 : !nick)) { syntax_error(s_ChanServ, u, xname, xmsgs[0]); } else if (!(ci = cs_findchan(chan))) { notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); } else if (ci->flags & CI_VERBOTEN) { notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); } else if (!(ci->flags & CI_XOP)) { notice_lang(whosend, u, CHAN_XOP_ACCESS, s_ChanServ); } else if (stricmp(cmd, "ADD") == 0) { if (readonly) { notice_lang(whosend, u, xmsgs[1]); return MOD_CONT; } ulev = get_access(u, ci); if (!is_servadmin && (xlev >= ulev || ulev < ACCESS_AOP)) { notice_lang(whosend, u, PERMISSION_DENIED); return MOD_CONT; } na = findnick(nick); if (!na) { notice_lang(whosend, u, xmsgs[2]); return MOD_CONT; } else if (na->status & NS_VERBOTEN) { notice_lang(whosend, u, NICK_X_FORBIDDEN, na->nick); return MOD_CONT; } nc = na->nc; for (access = ci->access, i = 0; i < ci->accesscount; access++, i++) { if (access->nc == nc) { /** * Patch provided by PopCorn to prevert AOP's reducing SOP's levels **/ if ((access->level >= ulev) && (!u->isSuperAdmin)) { notice_lang(whosend, u, PERMISSION_DENIED); return MOD_CONT; } change++; break; } } if (!change) { for (i = 0; i < ci->accesscount; i++) { if (!ci->access[i].in_use) { break; } } if (i == ci->accesscount) { if (i < CSAccessMax) { ci->accesscount++; ci->access = srealloc(ci->access,sizeof(ChanAccess) * ci->accesscount); } else { notice_lang(whosend, u, CHAN_XOP_REACHED_LIMIT, CSAccessMax); return MOD_CONT; } } access = &ci->access[i]; access->nc = nc; } access->in_use = 1; access->level = xlev; access->last_seen = 0; alog("%s: %s!%s@%s (level %d) %s access level %d to %s (group %s) on channel %s", whosend, u->nick, u->username, MYGetHost(u), ulev, change ? "changed" : "set", access->level, na->nick, nc->display, ci->name); if (!change) { notice_lang(whosend, u, xmsgs[3], access->nc->display, ci->name); } else { notice_lang(whosend, u, xmsgs[4], access->nc->display, ci->name); } } else if (stricmp(cmd, "DEL") == 0) { if (readonly) { notice_lang(whosend, u, xmsgs[1]); return MOD_CONT; } if (ci->accesscount == 0) { notice_lang(whosend, u, xmsgs[11], chan); return MOD_CONT; } ulev = get_access(u, ci); /* Special case: is it a number/list? Only do search if it isn't. */ if (isdigit(*nick) && strspn(nick, "1234567890,-") == strlen(nick)) { int count, deleted, last = -1, perm = 0; deleted = process_numlist(nick, &count, xop_del_callback, u, ci, &last, &perm, ulev, xlev); if (!deleted) { if (perm) { notice_lang(whosend, u, PERMISSION_DENIED); } else if (count == 1) { notice_lang(whosend, u, xmsgs[5], last, ci->name); } else { notice_lang(whosend, u, xmsgs[7], ci->name); } } else if (deleted == 1) { notice_lang(whosend, u, xmsgs[9], ci->name); } else { notice_lang(whosend, u, xmsgs[10], deleted, ci->name); } } else { na = findnick(nick); if (!na) { notice_lang(whosend, u, NICK_X_NOT_REGISTERED, nick); return MOD_CONT; } nc = na->nc; for (i = 0; i < ci->accesscount; i++) { if (ci->access[i].nc == nc && ci->access[i].level == xlev) { break; } } if (i == ci->accesscount) { notice_lang(whosend, u, xmsgs[6], nick, chan); return MOD_CONT; } access = &ci->access[i]; if (!is_servadmin && ulev <= access->level) { notice_lang(whosend, u, PERMISSION_DENIED); } else { notice_lang(whosend, u, xmsgs[8], access->nc->display, ci->name); access->nc = NULL; access->in_use = 0; } } } else if (stricmp(cmd, "LIST") == 0) { int sent_header = 0; ulev = get_access(u, ci); if (!is_servadmin && ulev < ACCESS_AOP) { notice_lang(whosend, u, ACCESS_DENIED); return MOD_CONT; } if (ci->accesscount == 0) { notice_lang(whosend, u, xmsgs[11], ci->name); return MOD_CONT; } if (nick && strspn(nick, "1234567890,-") == strlen(nick)) { process_numlist(nick, NULL, xop_list_callback, u, ci, &sent_header, xlev, xmsgs[12]); } else { for (i = 0; i < ci->accesscount; i++) { if (nick && ci->access[i].nc && !match_wild_nocase(nick, ci->access[i].nc->display)) { continue; } xop_list(u, i, ci, &sent_header, xlev, xmsgs[12]); } } if (!sent_header) notice_lang(whosend, u, xmsgs[7], chan); } else if (stricmp(cmd, "CLEAR") == 0) { if (readonly) { notice_lang(whosend, u, CHAN_ACCESS_DISABLED); return MOD_CONT; } if (ci->accesscount == 0) { notice_lang(whosend, u, CHAN_ACCESS_LIST_EMPTY, chan); return MOD_CONT; } if (!is_servadmin && !is_founder(u, ci)) { notice_lang(whosend, u, PERMISSION_DENIED); return MOD_CONT; } for (i = 0; i < ci->accesscount; i++) { if (ci->access[i].in_use && ci->access[i].level == xlev) { ci->access[i].nc = NULL; ci->access[i].in_use = 0; } } notice_lang(whosend, u, xmsgs[13]); } else { syntax_error(whosend, u, xname, xmsgs[0]); } return MOD_CONT; } static int xop_del(User * u, ChanAccess * access, int *perm, int uacc, int xlev) { if (!access->in_use || access->level != xlev) return 0; if (!is_services_admin(u) && uacc <= access->level) { (*perm)++; return 0; } access->nc = NULL; access->in_use = 0; return 1; } static int xop_del_callback(User * u, int num, va_list args) { ChannelInfo *ci = va_arg(args, ChannelInfo *); int *last = va_arg(args, int *); int *perm = va_arg(args, int *); int uacc = va_arg(args, int); int xlev = va_arg(args, int); if (num < 1 || num > ci->accesscount) return 0; *last = num; return xop_del(u, &ci->access[num - 1], perm, uacc, xlev); } static int xop_list(User * u, int index, ChannelInfo * ci, int *sent_header, int xlev, int xmsg) { ChanAccess *access = &ci->access[index]; if (!access->in_use || access->level != xlev) return 0; if (!*sent_header) { notice_lang(whosend, u, xmsg, ci->name); *sent_header = 1; } notice_lang(whosend, u, CHAN_XOP_LIST_FORMAT, index + 1, access->nc->display); return 1; } static int xop_list_callback(User * u, int num, va_list args) { ChannelInfo *ci = va_arg(args, ChannelInfo *); int *sent_header = va_arg(args, int *); int xlev = va_arg(args, int); int xmsg = va_arg(args, int); if (num < 1 || num > ci->accesscount) return 0; return xop_list(u, num - 1, ci, sent_header, xlev, xmsg); } static int do_akick(User * u, char *chan, char *cmd, char *mask, char *reason) { ChannelInfo *ci; AutoKick *akick; int i; if (!cmd || (!mask && (!stricmp(cmd, "ADD") || !stricmp(cmd, "STICK") || !stricmp(cmd, "UNSTICK") || !stricmp(cmd, "DEL")))) { syntax_error(s_ChanServ, u, "AKICK", CHAN_AKICK_SYNTAX); } else if (!(ci = cs_findchan(chan))) { notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); } else if (ci->flags & CI_VERBOTEN) { notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); } else if (!check_access(u, ci, CA_AKICK) && !is_services_admin(u)) { notice_lang(whosend, u, ACCESS_DENIED); } else if (stricmp(cmd, "ADD") == 0) { NickAlias *na = findnick(mask); NickCore *nc = NULL; char *nick, *user, *host; if (readonly) { notice_lang(whosend, u, CHAN_AKICK_DISABLED); return MOD_CONT; } if (!na) { split_usermask(mask, &nick, &user, &host); mask = scalloc(strlen(nick) + strlen(user) + strlen(host) + 3, 1); sprintf(mask, "%s!%s@%s", nick, user, host); free(nick); free(user); free(host); } else { if (na->status & NS_VERBOTEN) { notice_lang(whosend, u, NICK_X_FORBIDDEN, mask); return MOD_CONT; } nc = na->nc; } /* Check excepts BEFORE we get this far */ #ifdef HAS_EXCEPT if (is_excepted_mask(ci, mask) == 1) { notice_lang(whosend, u, CHAN_EXCEPTED, mask, chan); return MOD_CONT; } #endif for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { if (!(akick->flags & AK_USED)) { continue; } if ((akick->flags & AK_ISNICK) ? akick->u.nc == nc : stricmp(akick->u.mask, mask) == 0) { notice_lang(whosend, u, CHAN_AKICK_ALREADY_EXISTS, (akick->flags & AK_ISNICK) ? akick->u.nc-> display : akick->u.mask, chan); return MOD_CONT; } } for (i = 0; i < ci->akickcount; i++) { if (!(ci->akick[i].flags & AK_USED)) { break; } } if (i == ci->akickcount) { if (ci->akickcount >= CSAutokickMax) { notice_lang(whosend, u, CHAN_AKICK_REACHED_LIMIT, CSAutokickMax); return MOD_CONT; } ci->akickcount++; ci->akick = srealloc(ci->akick, sizeof(AutoKick) * ci->akickcount); } akick = &ci->akick[i]; akick->flags = AK_USED; if (nc) { akick->flags |= AK_ISNICK; akick->u.nc = nc; } else { akick->u.mask = mask; } akick->creator = sstrdup(u->nick); akick->addtime = time(NULL); if (reason) { if (strlen(reason) > 200) { reason[200] = '\0'; } akick->reason = sstrdup(reason); } else { akick->reason = NULL; } notice_lang(whosend, u, CHAN_AKICK_ADDED, mask, chan); } else if (stricmp(cmd, "STICK") == 0) { NickAlias *na; NickCore *nc; if (readonly) { notice_lang(whosend, u, CHAN_AKICK_DISABLED); return MOD_CONT; } if (ci->akickcount == 0) { notice_lang(whosend, u, CHAN_AKICK_LIST_EMPTY, ci->name); return MOD_CONT; } na = findnick(mask); nc = (na ? na->nc : NULL); for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) continue; if (!stricmp(akick->u.mask, mask)) break; } if (i == ci->akickcount) { notice_lang(whosend, u, CHAN_AKICK_NOT_FOUND, mask, ci->name); return MOD_CONT; } akick->flags |= AK_STUCK; notice_lang(whosend, u, CHAN_AKICK_STUCK, akick->u.mask, ci->name); if (ci->c) { stick_mask(ci, akick); } } else if (stricmp(cmd, "UNSTICK") == 0) { NickAlias *na; NickCore *nc; if (readonly) { notice_lang(whosend, u, CHAN_AKICK_DISABLED); return MOD_CONT; } if (ci->akickcount == 0) { notice_lang(whosend, u, CHAN_AKICK_LIST_EMPTY, ci->name); return MOD_CONT; } na = findnick(mask); nc = (na ? na->nc : NULL); for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { if (!(akick->flags & AK_USED) || (akick->flags & AK_ISNICK)) { continue; } if (!stricmp(akick->u.mask, mask)) { break; } } if (i == ci->akickcount) { notice_lang(whosend, u, CHAN_AKICK_NOT_FOUND, mask, ci->name); return MOD_CONT; } akick->flags &= ~AK_STUCK; notice_lang(whosend, u, CHAN_AKICK_UNSTUCK, akick->u.mask, ci->name); } else if (stricmp(cmd, "DEL") == 0) { if (readonly) { notice_lang(whosend, u, CHAN_AKICK_DISABLED); return MOD_CONT; } if (ci->akickcount == 0) { notice_lang(whosend, u, CHAN_AKICK_LIST_EMPTY, chan); return MOD_CONT; } /* Special case: is it a number/list? Only do search if it isn't. */ if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) { int count, deleted, last = -1; deleted = process_numlist(mask, &count, akick_del_callback, u, ci, &last); if (!deleted) { if (count == 1) { notice_lang(whosend, u, CHAN_AKICK_NO_SUCH_ENTRY,last, ci->name); } else { notice_lang(whosend, u, CHAN_AKICK_NO_MATCH, ci->name); } } else if (deleted == 1) { notice_lang(whosend, u, CHAN_AKICK_DELETED_ONE, ci->name); } else { notice_lang(whosend, u, CHAN_AKICK_DELETED_SEVERAL, deleted, ci->name); } } else { NickAlias *na = findnick(mask); NickCore *nc = (na ? na->nc : NULL); for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { if (!(akick->flags & AK_USED)) { continue; } if (((akick->flags & AK_ISNICK) && akick->u.nc == nc) || (!(akick->flags & AK_ISNICK) && stricmp(akick->u.mask, mask) == 0)) { break; } } if (i == ci->akickcount) { notice_lang(whosend, u, CHAN_AKICK_NOT_FOUND, mask, chan); return MOD_CONT; } notice_lang(whosend, u, CHAN_AKICK_DELETED, mask, chan); akick_del(u, akick); } } else if (stricmp(cmd, "ENFORCE") == 0) { Channel *c = findchan(ci->name); struct c_userlist *cu = NULL; struct c_userlist *next; char *argv[3]; int count = 0; if (!c) { notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, ci->name); return MOD_CONT; } cu = c->users; while (cu) { next = cu->next; if (check_kick(cu->user, c->name)) { argv[0] = sstrdup(c->name); argv[1] = sstrdup(cu->user->nick); argv[2] = sstrdup(CSAutokickReason); do_kick(s_ChanServ, 3, argv); free(argv[2]); free(argv[1]); free(argv[0]); count++; } cu = next; } notice_lang(whosend, u, CHAN_AKICK_ENFORCE_DONE, chan, count); } else if (stricmp(cmd, "CLEAR") == 0) { if (readonly) { notice_lang(s_ChanServ, u, CHAN_AKICK_DISABLED); return MOD_CONT; } for (akick = ci->akick, i = 0; i < ci->akickcount; akick++, i++) { if (!(akick->flags & AK_USED)) continue; akick_del(u, akick); } free(ci->akick); ci->akick = NULL; ci->akickcount = 0; notice_lang(whosend, u, CHAN_AKICK_CLEAR); } else { syntax_error(whosend, u, "AKICK", CHAN_AKICK_SYNTAX); } return MOD_CONT; } static int akick_del_callback(User * u, int num, va_list args) { ChannelInfo *ci = va_arg(args, ChannelInfo *); int *last = va_arg(args, int *); if (num < 1 || num > ci->akickcount) return 0; *last = num; return akick_del(u, &ci->akick[num - 1]); } static int akick_del(User * u, AutoKick * akick) { if (!(akick->flags & AK_USED)) return 0; if (akick->flags & AK_ISNICK) { akick->u.nc = NULL; } else { free(akick->u.mask); akick->u.mask = NULL; } if (akick->reason) { free(akick->reason); akick->reason = NULL; } if (akick->creator) { free(akick->creator); akick->creator = NULL; } akick->addtime = 0; akick->flags = 0; return 1; } static int do_assign(User * u, char *chan, char *nick) { BotInfo *bi; ChannelInfo *ci; if (!(ci = cs_findchan(chan))) { return MOD_STOP; } if (readonly) { notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); } else if (!(bi = findbot(nick))) { notice_lang(whosend, u, BOT_DOES_NOT_EXIST, nick); } else if (bi->flags & BI_PRIVATE && !is_oper(u)) { notice_lang(whosend, u, PERMISSION_DENIED); } else if (ci->flags & CI_VERBOTEN) { notice_lang(whosend, u, CHAN_X_FORBIDDEN, chan); } else if ((ci->bi) && (stricmp(ci->bi->nick, nick) == 0)) { notice_lang(whosend, u, BOT_ASSIGN_ALREADY, ci->bi->nick, chan); } else if ((ci->botflags & BS_NOBOT) || (!check_access(u, ci, CA_ASSIGN) && !is_services_admin(u))) { notice_lang(whosend, u, PERMISSION_DENIED); } else { if (ci->bi) { unassign(u, ci); } ci->bi = bi; bi->chancount++; if (ci->c && ci->c->usercount >= BSMinUsers) { bot_join(ci); } notice_lang(whosend, u, BOT_ASSIGN_ASSIGNED, bi->nick, ci->name); } return MOD_CONT; } static int do_unassign(User * u, char *chan) { ChannelInfo *ci; if (readonly) { notice_lang(s_BotServ, u, BOT_ASSIGN_READONLY); } else if (!(ci = cs_findchan(chan))) { return MOD_STOP; } else if (ci->flags & CI_VERBOTEN) { notice_lang(whosend, u, CHAN_X_FORBIDDEN, chan); } else if (!is_services_admin(u) && !check_access(u, ci, CA_ASSIGN)) { notice_lang(whosend, u, ACCESS_DENIED); } else { if (ci->bi) { unassign(u, ci); } notice_lang(whosend, u, BOT_UNASSIGN_UNASSIGNED, ci->name); } return MOD_CONT; } static void unassign(User * u, ChannelInfo * ci) { if (ci->c && ci->c->usercount >= BSMinUsers) { send_cmd(ci->bi->nick, "PART %s :UNASSIGN from %s", ci->name, u->nick); } ci->bi->chancount--; ci->bi = NULL; } static int do_logout(User * u, char *chan, char *nick) { ChannelInfo *ci; User *u2 = NULL; int is_servadmin = is_services_admin(u); if (!(ci = cs_findchan(chan))) { return MOD_STOP; } else if (!is_servadmin & (ci->flags & CI_VERBOTEN)) { notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan); } else if (nick && !(u2 = finduser(nick))) { notice_lang(whosend, u, NICK_X_NOT_IN_USE, nick); } else if (!is_servadmin && u2 != u && !is_real_founder(u, ci)) { notice_lang(whosend, u, ACCESS_DENIED); } else { if (u2) { make_unidentified(u2, ci); notice_lang(whosend, u, CHAN_LOGOUT_SUCCEEDED, nick, chan); } else { int i; for (i = 0; i < 1024; i++) { for (u2 = userlist[i]; u2; u2 = u2->next) { make_unidentified(u2, ci); } } notice_lang(whosend, u, CHAN_LOGOUT_ALL_SUCCEEDED, chan); } } return MOD_CONT; } static int is_real_founder(User * user, ChannelInfo * ci) { if (user->isSuperAdmin) { return 1; } if (user->na && user->na->nc == ci->founder) { if ((nick_identified(user) || (nick_recognized(user) && !(ci->flags & CI_SECURE)))) return 1; } return 0; } static void make_unidentified(User * u, ChannelInfo * ci) { struct u_chaninfolist *uci; if (!u || !ci) { return; } for (uci = u->founder_chans; uci; uci = uci->next) { if (uci->chan == ci) { if (uci->next) uci->next->prev = uci->prev; if (uci->prev) uci->prev->next = uci->next; else u->founder_chans = uci->next; free(uci); break; } } } static int do_set_founder(User * u, ChannelInfo * ci, char *param) { NickAlias *na = findnick(param); NickCore *nc, *nc0 = ci->founder; if (!na) { notice_lang(whosend, u, NICK_X_NOT_REGISTERED, param); return MOD_CONT; } else if (na->status & NS_VERBOTEN) { notice_lang(whosend, u, NICK_X_FORBIDDEN, param); return MOD_CONT; } nc = na->nc; if (nc->channelmax > 0 && nc->channelcount >= nc->channelmax && !is_services_admin(u)) { notice_lang(whosend, u, CHAN_SET_FOUNDER_TOO_MANY_CHANS, param); return MOD_CONT; } alog("%s: Changing founder of %s from %s to %s by %s!%s@%s", s_ChanServ, ci->name, ci->founder->display, nc->display, u->nick, u->username, MYGetHost(u)); /* Founder and successor must not be the same group */ if (nc == ci->successor) { ci->successor = NULL; } nc0->channelcount--; ci->founder = nc; nc->channelcount++; notice_lang(whosend, u, CHAN_FOUNDER_CHANGED, ci->name, param); return MOD_CONT; } /*************************************************************************/ static int do_set_successor(User * u, ChannelInfo * ci, char *param) { NickAlias *na; NickCore *nc; if (param) { na = findnick(param); if (!na) { notice_lang(whosend, u, NICK_X_NOT_REGISTERED, param); return MOD_CONT; } if (na->status & NS_VERBOTEN) { notice_lang(whosend, u, NICK_X_FORBIDDEN, param); return MOD_CONT; } if (na->nc == ci->founder) { notice_lang(whosend, u, CHAN_SUCCESSOR_IS_FOUNDER, param, ci->name); return MOD_CONT; } nc = na->nc; } else { nc = NULL; } alog("%s: Changing successor of %s from %s to %s by %s!%s@%s", s_ChanServ, ci->name, (ci->successor ? ci->successor->display : "none"), (nc ? nc->display : "none"), u->nick, u->username, MYGetHost(u)); ci->successor = nc; if (nc) { notice_lang(whosend, u, CHAN_SUCCESSOR_CHANGED, ci->name, param); } else { notice_lang(whosend, u, CHAN_SUCCESSOR_UNSET, ci->name); } return MOD_CONT; } static int do_set_email(User * u, ChannelInfo * ci, char *param) { if (ci->email) { free(ci->email); } if (param) { ci->email = sstrdup(param); notice_lang(whosend, u, CHAN_EMAIL_CHANGED, ci->name, param); } else { ci->email = NULL; notice_lang(whosend, u, CHAN_EMAIL_UNSET, ci->name); } return MOD_CONT; } static int do_set_url(User * u, ChannelInfo * ci, char *param) { if (ci->url) free(ci->url); if (param) { ci->url = sstrdup(param); notice_lang(whosend, u, CHAN_URL_CHANGED, ci->name, param); } else { ci->url = NULL; notice_lang(whosend, u, CHAN_URL_UNSET, ci->name); } return MOD_CONT; } static int do_set_bantype(User * u, ChannelInfo * ci, char *param) { char *endptr; int16 bantype = strtol(param, &endptr, 10); if (*endptr != 0 || bantype < 0 || bantype > 3) { notice_lang(whosend, u, CHAN_SET_BANTYPE_INVALID, param); } else { ci->bantype = bantype; notice_lang(whosend, u, CHAN_SET_BANTYPE_CHANGED, ci->name, ci->bantype); } return MOD_CONT; } static int do_set_keeptopic(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_KEEPTOPIC; notice_lang(whosend, u, CHAN_SET_KEEPTOPIC_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_KEEPTOPIC; notice_lang(whosend, u, CHAN_SET_KEEPTOPIC_OFF); } else { syntax_error(whosend, u, "SET KEEPTOPIC", CHAN_SET_KEEPTOPIC_SYNTAX); } return MOD_CONT; } static int do_set_topiclock(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_TOPICLOCK; notice_lang(whosend, u, CHAN_SET_TOPICLOCK_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_TOPICLOCK; notice_lang(whosend, u, CHAN_SET_TOPICLOCK_OFF); } else { syntax_error(whosend, u, "SET TOPICLOCK", CHAN_SET_TOPICLOCK_SYNTAX); } return MOD_CONT; } static int do_set_private(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_PRIVATE; notice_lang(whosend, u, CHAN_SET_PRIVATE_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_PRIVATE; notice_lang(whosend, u, CHAN_SET_PRIVATE_OFF); } else { syntax_error(whosend, u, "SET PRIVATE", CHAN_SET_PRIVATE_SYNTAX); } return MOD_CONT; } static int do_set_secureops(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_SECUREOPS; notice_lang(whosend, u, CHAN_SET_SECUREOPS_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_SECUREOPS; notice_lang(whosend, u, CHAN_SET_SECUREOPS_OFF); } else { syntax_error(whosend, u, "SET SECUREOPS", CHAN_SET_SECUREOPS_SYNTAX); } return MOD_CONT; } static int do_set_securefounder(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_SECUREFOUNDER; notice_lang(whosend, u, CHAN_SET_SECUREFOUNDER_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_SECUREFOUNDER; notice_lang(whosend, u, CHAN_SET_SECUREFOUNDER_OFF); } else { syntax_error(whosend, u, "SET SECUREFOUNDER", CHAN_SET_SECUREFOUNDER_SYNTAX); } return MOD_CONT; } static int do_set_restricted(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_RESTRICTED; if (ci->levels[CA_NOJOIN] < 0) ci->levels[CA_NOJOIN] = 0; notice_lang(whosend, u, CHAN_SET_RESTRICTED_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_RESTRICTED; if (ci->levels[CA_NOJOIN] >= 0) ci->levels[CA_NOJOIN] = -2; notice_lang(whosend, u, CHAN_SET_RESTRICTED_OFF); } else { syntax_error(whosend, u, "SET RESTRICTED", CHAN_SET_RESTRICTED_SYNTAX); } return MOD_CONT; } static int do_set_secure(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_SECURE; notice_lang(whosend, u, CHAN_SET_SECURE_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_SECURE; notice_lang(whosend, u, CHAN_SET_SECURE_OFF); } else { syntax_error(whosend, u, "SET SECURE", CHAN_SET_SECURE_SYNTAX); } return MOD_CONT; } static int do_set_signkick(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_SIGNKICK; ci->flags &= ~CI_SIGNKICK_LEVEL; notice_lang(whosend, u, CHAN_SET_SIGNKICK_ON); } else if (stricmp(param, "LEVEL") == 0) { ci->flags |= CI_SIGNKICK_LEVEL; ci->flags &= ~CI_SIGNKICK; notice_lang(whosend, u, CHAN_SET_SIGNKICK_LEVEL); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~(CI_SIGNKICK | CI_SIGNKICK_LEVEL); notice_lang(whosend, u, CHAN_SET_SIGNKICK_OFF); } else { syntax_error(whosend, u, "SET SIGNKICK", CHAN_SET_SIGNKICK_SYNTAX); } return MOD_CONT; } static int do_set_opnotice(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_OPNOTICE; notice_lang(whosend, u, CHAN_SET_OPNOTICE_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_OPNOTICE; notice_lang(whosend, u, CHAN_SET_OPNOTICE_OFF); } else { syntax_error(whosend, u, "SET OPNOTICE", CHAN_SET_OPNOTICE_SYNTAX); } return MOD_CONT; } static int do_set_peace(User * u, ChannelInfo * ci, char *param) { if (stricmp(param, "ON") == 0) { ci->flags |= CI_PEACE; notice_lang(whosend, u, CHAN_SET_PEACE_ON); } else if (stricmp(param, "OFF") == 0) { ci->flags &= ~CI_PEACE; notice_lang(whosend, u, CHAN_SET_PEACE_OFF); } else { syntax_error(whosend, u, "SET PEACE", CHAN_SET_PEACE_SYNTAX); } return MOD_CONT; } static int do_set_mlock(User * u, ChannelInfo * ci, char *param) { int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ unsigned char mode; CBMode *cbm; if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) { notice_lang(whosend, u, OPER_DEFCON_DENIED); } /* Reinitialize everything */ #ifdef IRC_HYBRID ci->mlock_on = 0; #else ci->mlock_on = CMODE_r; #endif ci->mlock_off = ci->mlock_limit = 0; ci->mlock_key = NULL; #ifdef HAS_FMODE ci->mlock_flood = NULL; #endif #ifdef HAS_LMODE ci->mlock_redirect = NULL; #endif while ((mode = *param++)) { switch (mode) { case '+': add = 1; continue; case '-': add = 0; continue; default: if (add < 0) continue; } if ((int) mode < 128 && (cbm = &cbmodes[(int) mode])->flag != 0) { if ((cbm->flags & CBM_NO_MLOCK) || ((cbm->flags & CBM_NO_USER_MLOCK) && !is_oper(u))) { notice_lang(whosend, u, CHAN_SET_MLOCK_IMPOSSIBLE_CHAR,mode); } else if (add) { ci->mlock_on |= cbm->flag; ci->mlock_off &= ~cbm->flag; if (cbm->cssetvalue) cbm->cssetvalue(ci, strtok(NULL, " ")); } else { ci->mlock_off |= cbm->flag; if (ci->mlock_on & cbm->flag) { ci->mlock_on &= ~cbm->flag; if (cbm->cssetvalue) { cbm->cssetvalue(ci, NULL); } } } } else { notice_lang(whosend, u, CHAN_SET_MLOCK_UNKNOWN_CHAR, mode); } } /* while (*param) */ #ifdef HAS_LMODE /* We can't mlock +L if +l is not mlocked as well. */ if ((ci->mlock_on & CMODE_L) && !(ci->mlock_on & CMODE_l)) { ci->mlock_on &= ~CMODE_L; free(ci->mlock_redirect); notice_lang(whosend, u, CHAN_SET_MLOCK_L_REQUIRED); } #endif #if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_ULTIMATE3) || defined(IRC_UNREAL32) /* We can't mlock +K if +i is not mlocked as well. */ if ((ci->mlock_on & CMODE_K) && !(ci->mlock_on & CMODE_i)) { ci->mlock_on &= ~CMODE_K; notice_lang(whosend, u, CHAN_SET_MLOCK_K_REQUIRED); } #endif /* Since we always enforce mode r there is no way to have no * mode lock at all. */ #if defined(IRC_HYBRID) /* James: Hybrid doesn't HAVE mode r, so now you have to check :P */ if (get_mlock_modes(ci, 0)) #endif notice_lang(whosend, u, CHAN_MLOCK_CHANGED, ci->name, get_mlock_modes(ci, 0)); /* Implement the new lock. */ if (ci->c) { check_modes(ci->c); } return MOD_CONT; } static char *get_mlock_modes(ChannelInfo * ci, int complete) { static char res[BUFSIZE]; char *end = res; if (ci->mlock_on || ci->mlock_off) { int n = 0; CBModeInfo *cbmi = cbmodeinfos; if (ci->mlock_on) { *end++ = '+'; n++; do { if (ci->mlock_on & cbmi->flag) *end++ = cbmi->mode; } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1); cbmi = cbmodeinfos; } if (ci->mlock_off) { *end++ = '-'; n++; do { if (ci->mlock_off & cbmi->flag) *end++ = cbmi->mode; } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1); cbmi = cbmodeinfos; } if (ci->mlock_on && complete) { do { if (cbmi->csgetvalue && (ci->mlock_on & cbmi->flag)) { char *value = cbmi->csgetvalue(ci); if (value) { *end++ = ' '; while (*value) *end++ = *value++; } } } while ((++cbmi)->flag != 0 && ++n < sizeof(res) - 1); } } *end = 0; return res; } static int do_ban(User * u, char *chan, char *params) { Channel *c; ChannelInfo *ci; User *u2; int is_same; is_same = (params == u->nick) ? 1 : (stricmp(params, u->nick) == 0); if (!(c = findchan(chan))) { notice_lang(s_ChanServ, u, CHAN_X_NOT_IN_USE, chan); } else if (!(ci = c->ci)) { notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan); } else if (ci->flags & CI_VERBOTEN) { notice_lang(whosend, u, CHAN_X_FORBIDDEN, chan); } else if (is_same ? !(u2 = u) : !(u2 = finduser(params))) { notice_lang(whosend, u, NICK_X_NOT_IN_USE, params); } else if (!is_same ? !check_access(u, ci, CA_BAN) : !check_access(u, ci, CA_BANME)) { notice_lang(whosend, u, ACCESS_DENIED); } else if (!is_same && (ci->flags & CI_PEACE) && (get_access(u2, ci) >= get_access(u, ci))) { notice_lang(whosend, u, PERMISSION_DENIED); #ifdef HAS_EXCEPT /* * Dont ban/kick the user on channels where he is excepted * to prevent services <-> server wars. */ } else if (is_excepted(ci, u2)) { notice_lang(whosend, u, CHAN_EXCEPTED, u2->nick, ci->name); #endif } else { char *av[3]; char mask[BUFSIZE]; av[0] = "+b"; get_idealban(ci, u2, mask, sizeof(mask)); av[1] = mask; #if defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_UNREAL32) send_cmd(whosend, "MODE %s -aqohv %s %s %s %s %s", c->name, u2->nick, u2->nick, u2->nick, u2->nick, u2->nick); #elif defined(IRC_ULTIMATE3) send_cmd(whosend, "MODE %s -aohv %s %s %s %s", c->name, u2->nick, u2->nick, u2->nick, u2->nick); #elif defined(IRC_ULTIMATE) send_cmd(whosend, "MODE %s -ohv %s %s %s", c->name, u2->nick, u2->nick, u2->nick); #else send_cmd(whosend, "MODE %s -ov %s %s", c->name, u2->nick, u2->nick); #endif send_cmd(whosend, "MODE %s +b %s", c->name, av[1]); chan_set_modes(s_ChanServ, c, 2, av, 1); return MOD_CONT; } return MOD_CONT; } static int do_badwords(User * u, ChannelInfo *ci, char *cmd, char *word, char *style) { BadWord *bw; int i; if (ci->flags & CI_VERBOTEN) { notice_lang(whosend, u, CHAN_X_FORBIDDEN, ci->name); } else if (!check_access(u, ci, CA_BADWORDS) && !is_services_admin(u)) { notice_lang(whosend, u, ACCESS_DENIED); } else if (stricmp(cmd, "ADD") == 0) { int type = BW_ANY; if (readonly) { notice_lang(whosend, u, BOT_BADWORDS_DISABLED); return MOD_CONT; } if (!stricmp(style, "SINGLE")) { type = BW_SINGLE; } else if (!stricmp(style, "START")) { type = BW_START; } else if (!stricmp(style, "END")) { type = BW_END; } else { type = BW_ANY; } for (bw = ci->badwords, i = 0; i < ci->bwcount; bw++, i++) { if (bw->word && !stricmp(bw->word, word)) { notice_lang(whosend, u, BOT_BADWORDS_ALREADY_EXISTS, bw->word, ci->name); return MOD_CONT; } } for (i = 0; i < ci->bwcount; i++) { if (!ci->badwords[i].in_use) { break; } } if (i == ci->bwcount) { if (i < BSBadWordsMax) { ci->bwcount++; ci->badwords = srealloc(ci->badwords, sizeof(BadWord) * ci->bwcount); } else { notice_lang(whosend, u, BOT_BADWORDS_REACHED_LIMIT, BSBadWordsMax); return MOD_CONT; } } bw = &ci->badwords[i]; bw->in_use = 1; bw->word = sstrdup(word); bw->type = type; notice_lang(whosend, u, BOT_BADWORDS_ADDED, bw->word, ci->name); } else if (stricmp(cmd, "DEL") == 0) { if (readonly) { notice_lang(whosend, u, BOT_BADWORDS_DISABLED); return MOD_CONT; } /* Special case: is it a number/list? Only do search if it isn't. */ if (isdigit(*word) && strspn(word, "1234567890,-") == strlen(word)) { int count, deleted, last = -1; deleted = process_numlist(word, &count, badwords_del_callback, u, ci, &last); if (!deleted) { if (count == 1) { notice_lang(s_BotServ, u, BOT_BADWORDS_NO_SUCH_ENTRY, last, ci->name); } else { notice_lang(s_BotServ, u, BOT_BADWORDS_NO_MATCH, ci->name); } } else if (deleted == 1) { notice_lang(whosend, u, BOT_BADWORDS_DELETED_ONE, ci->name); } else { notice_lang(whosend, u, BOT_BADWORDS_DELETED_SEVERAL, deleted, ci->name); } } else { for (i = 0; i < ci->bwcount; i++) { if (ci->badwords[i].in_use && !stricmp(ci->badwords[i].word, word)) break; } if (i == ci->bwcount) { notice_lang(whosend, u, BOT_BADWORDS_NOT_FOUND, word, ci->name); return MOD_CONT; } bw = &ci->badwords[i]; notice_lang(whosend, u, BOT_BADWORDS_DELETED, bw->word, ci->name); if (bw->word) { free(bw->word); } bw->word = NULL; bw->in_use = 0; } } else { return MOD_CONT; } return MOD_CONT; } static int badwords_del_callback(User * u, int num, va_list args) { BadWord *bw; ChannelInfo *ci = va_arg(args, ChannelInfo *); int *last = va_arg(args, int *); if (num < 1 || num > ci->bwcount) return 0; *last = num; bw = &ci->badwords[num - 1]; if (bw->word) free(bw->word); bw->word = NULL; bw->in_use = 0; return 1; } static int do_levels(User *u, ChannelInfo *ci, char *cmd, char *what, /*char *s,*/ short level) { int i; //LevelInfo *levelinfo; /* If SET, we want two extra parameters; if DIS[ABLE] or FOUNDER, we want only * one; else, we want none. */ if (!cmd || ((stricmp(cmd, "SET") == 0) ? !level : ((strnicmp(cmd, "DIS", 3) == 0)) ? (!what || level) : !!what)) { syntax_error(whosend, u, "LEVELS", CHAN_LEVELS_SYNTAX); } else if (ci->flags & CI_VERBOTEN) { notice_lang(whosend, u, CHAN_X_FORBIDDEN, ci->name); } else if (ci->flags & CI_XOP) { notice_lang(whosend, u, CHAN_LEVELS_XOP); } else if (!is_founder(u, ci) && !is_services_admin(u)) { notice_lang(whosend, u, ACCESS_DENIED); } else if (stricmp(cmd, "SET") == 0) { if (level <= ACCESS_INVALID || level >= ACCESS_FOUNDER) { notice_lang(whosend, u, CHAN_LEVELS_RANGE, ACCESS_INVALID + 1, ACCESS_FOUNDER - 1); return MOD_CONT; } for (i = 0; levelinfo[i].what >= 0; i++) { if (stricmp(levelinfo[i].name, what) == 0) { ci->levels[levelinfo[i].what] = level; alog("%s: %s set level %s on channel %s to %d", whosend, u->nick, levelinfo[i].name, ci->name, level); notice_lang(whosend, u, CHAN_LEVELS_CHANGED, levelinfo[i].name, ci->name, level); return MOD_CONT; } } notice_lang(whosend, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); } else if (stricmp(cmd, "DIS") == 0 || stricmp(cmd, "DISABLE") == 0) { for (i = 0; levelinfo[i].what >= 0; i++) { if (stricmp(levelinfo[i].name, what) == 0) { ci->levels[levelinfo[i].what] = ACCESS_INVALID; alog("%s: %s disabled level %s on channel %s", whosend, u->nick, levelinfo[i].name, ci->name); notice_lang(whosend, u, CHAN_LEVELS_DISABLED, levelinfo[i].name, ci->name); return MOD_CONT; } } notice_lang(whosend, u, CHAN_LEVELS_UNKNOWN, what, s_ChanServ); } else { syntax_error(whosend, u, "LEVELS", CHAN_LEVELS_SYNTAX); } return MOD_CONT; } static void reset_levelsb(ChannelInfo * ci) { int i; if (ci->levels) { free(ci->levels); } ci->levels = scalloc(CA_SIZE * sizeof(*ci->levels), 1); for (i = 0; def_levels[i][0] >= 0; i++) { ci->levels[def_levels[i][0]] = def_levels[i][1]; } return; } /* needs improving */ static int do_suspend(User * u, ChannelInfo *ci, char *reason) { Channel *c; /* Assumes that permission checking has already been done. */ if (!ci || (ForceForbidReason && !reason)) { syntax_error(whosend, u, "SUSPEND", (ForceForbidReason ? CHAN_SUSPEND_SYNTAX_REASON : CHAN_SUSPEND_SYNTAX)); return MOD_CONT; } if (readonly) { notice_lang(whosend, u, READ_ONLY_MODE); return MOD_CONT; } ci->flags |= CI_SUSPENDED; ci->forbidby = sstrdup(u->nick); if (reason) { ci->forbidreason = sstrdup(reason); } if ((c = findchan(ci->name))) { struct c_userlist *cu, *next; char *av[3]; #if defined(IRC_ULTIMATE) || defined(IRC_UNREAL) || defined(IRC_ULTIMATE3) || defined(IRC_HYBRID) || defined(IRC_UNREAL32) // 1st things 1st, remove any exceptions. int i, count = c->exceptcount; char **excepts = scalloc(sizeof(char *) * count, 1); char *an[3]; for (i = 0; i < count; i++) { excepts[i] = sstrdup(c->excepts[i]); } for (i = 0; i < count; i++) { an[0] = sstrdup(ci->name); an[1] = sstrdup("-e"); an[2] = excepts[i]; #ifdef ANOPE17x anope_cmd_mode(s_OperServ, an[0], "%s %s", an[1], an[2]); #else send_cmd(whosend, "MODE %s %s :%s", an[0], an[1], an[2]); #endif do_cmode(whosend, c, 3, an); free(an[2]); free(an[1]); free(an[0]); } free(excepts); #endif // 2nd now do some bannage to prevent rejoiners. send_cmd(whosend, "MODE %s +b *!*@* %lu", ci->name, time(NULL)); for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) { continue; } av[0] = c->name; av[1] = cu->user->nick; av[2] = reason ? reason : "CHAN_SUSPEND_REASON"; send_cmd(whosend, "KICK %s %s :%s", av[0], av[1], av[2]); do_kick(whosend, 3, av); } if (WallForbid) { wallops(s_ChanServ, "\2%s\2 used SUSPEND on channel \2%s\2", u->nick, ci->name); } alog("%s: %s set SUSPEND for channel %s", whosend, u->nick, ci->name); notice_lang(whosend, u, CHAN_SUSPEND_SUCCEEDED, ci->name); } return MOD_CONT; } static int do_forbid(User * u, char *chan, char *reason) { ChannelInfo *ci; Channel *c; /* Assumes that permission checking has already been done. */ if (!chan || (ForceForbidReason && !reason)) { syntax_error(s_ChanServ, u, "FORBID", (ForceForbidReason ? CHAN_FORBID_SYNTAX_REASON : CHAN_FORBID_SYNTAX)); return MOD_CONT; } if (readonly) { notice_lang(s_ChanServ, u, READ_ONLY_MODE); } if ((ci = cs_findchan(chan)) != NULL) { delchana(ci); } ci = makechan(chan); if (ci) { ci->flags |= CI_VERBOTEN; ci->forbidby = sstrdup(u->nick); if (reason) { ci->forbidreason = sstrdup(reason); } if ((c = findchan(ci->name))) { struct c_userlist *cu, *next; char *av[3]; for (cu = c->users; cu; cu = next) { next = cu->next; if (is_oper(cu->user)) { continue; } av[0] = c->name; av[1] = cu->user->nick; av[2] = reason ? reason : "CHAN_FORBID_REASON"; send_cmd(s_ChanServ, "KICK %s %s :%s", av[0], av[1], av[2]); do_kick(s_ChanServ, 3, av); } } if (WallForbid) { wallops(s_ChanServ, "\2%s\2 used FORBID on channel \2%s\2", u->nick, ci->name); } alog("%s: %s set FORBID for channel %s", s_ChanServ, u->nick, ci->name); notice_lang(s_ChanServ, u, CHAN_FORBID_SUCCEEDED, chan); } else { alog("%s: Valid FORBID for %s by %s failed", s_ChanServ, ci->name, u->nick); notice_lang(s_ChanServ, u, CHAN_FORBID_FAILED, chan); } return MOD_CONT; } static int do_bot(User * u, int WHAT, char *oldnick, char *nick, char *user, char *host, char *real) { BotInfo *bi; char *ch = NULL; if (!WHAT) { syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); } else if (WHAT == 2) { if (!nick || !user || !host || !real) { syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); } else if (readonly) { notice_lang(s_BotServ, u, BOT_BOT_READONLY); } else if (findbot(nick)) { notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); } else { NickAlias *na; if (isdigit(nick[0]) || nick[0] == '-') { notice_lang(s_BotServ, u, BOT_BAD_NICK); return MOD_CONT; } for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { if (!isvalidnick(*ch)) { notice_lang(s_BotServ, u, BOT_BAD_NICK); return MOD_CONT; } } if (!isValidHost(host, 3)) { notice_lang(s_BotServ, u, BOT_BAD_HOST); return MOD_CONT; } for (ch = user; *ch && (ch - user) < USERMAX; ch++) { if (!isalnum(*ch)) { notice_lang(s_BotServ, u, BOT_BAD_IDENT); return MOD_CONT; } } if ((s_NickServ && (stricmp(nick, s_NickServ) == 0)) || (s_NickServAlias && !stricmp(nick, s_NickServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_ChanServ && (stricmp(nick, s_ChanServ) == 0)) || (s_ChanServAlias && !stricmp(nick, s_ChanServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_MemoServ && (stricmp(nick, s_MemoServ) == 0))|| (s_MemoServAlias && !stricmp(nick, s_MemoServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_BotServ && (stricmp(nick, s_BotServ) == 0)) || (s_BotServAlias && !stricmp(nick, s_BotServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_HelpServ && (stricmp(nick, s_HelpServ) == 0)) || (s_HelpServAlias && !stricmp(nick, s_HelpServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_OperServ && (stricmp(nick, s_OperServ) == 0)) || (s_OperServAlias && !stricmp(nick, s_OperServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_GlobalNoticer && (stricmp(nick, s_GlobalNoticer) == 0)) || (s_GlobalNoticerAlias && !stricmp(nick, s_GlobalNoticerAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_HostServ && (stricmp(nick, s_HostServ) == 0)) || (s_HostServAlias && !stricmp(nick, s_HostServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } if ((na = findnick(nick))) { notice(s_BotServ, u->nick, "A %s registered nick already has that name, please DROP the nick first", s_NickServ); return MOD_CONT; } bi = makebotA(nick); if (!bi) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } bi->user = sstrdup(user); bi->host = sstrdup(host); bi->real = sstrdup(real); bi->created = time(NULL); bi->chancount = 0; EnforceQlinedNick(nick, s_BotServ); #if defined(BOTSERV_BOTS_MODE) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, BOTSERV_BOTS_MODE, 1); #elif defined(IRC_ULTIMATE) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+oS", 1); #elif defined(IRC_ULTIMATE3) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+opS", 1); #elif defined(IRC_UNREAL) || defined(IRC_VIAGRA) || defined(IRC_UNREAL32) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+oB", 1); #else MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+o", 1); #endif notice_lang(s_BotServ, u, BOT_BOT_ADDED, bi->nick, bi->user, bi->host, bi->real); } } else if (WHAT == 3) { if (!oldnick || !nick) { syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); } else if (readonly) { notice_lang(s_BotServ, u, BOT_BOT_READONLY); } else if (!(bi = findbot(oldnick))) { notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, oldnick); } else { NickAlias *na; if (!strcmp(bi->nick, nick) && ((user) ? !strcmp(bi->user, user) : 1) && ((host) ? !strcmp(bi->host, host) : 1) && ((real) ? !strcmp(bi->real, real) : 1)) { notice_lang(s_BotServ, u, BOT_BOT_ANY_CHANGES); return MOD_CONT; } if ((s_NickServ && (stricmp(nick, s_NickServ) == 0)) || (s_NickServAlias && !stricmp(nick, s_NickServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_ChanServ && (stricmp(nick, s_ChanServ) == 0)) || (s_ChanServAlias && !stricmp(nick, s_ChanServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_MemoServ && (stricmp(nick, s_MemoServ) == 0))|| (s_MemoServAlias && !stricmp(nick, s_MemoServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_BotServ && (stricmp(nick, s_BotServ) == 0)) || (s_BotServAlias && !stricmp(nick, s_BotServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_HelpServ && (stricmp(nick, s_HelpServ) == 0)) || (s_HelpServAlias && !stricmp(nick, s_HelpServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_OperServ && (stricmp(nick, s_OperServ) == 0)) || (s_OperServAlias && !stricmp(nick, s_OperServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_GlobalNoticer && (stricmp(nick, s_GlobalNoticer) == 0)) || (s_GlobalNoticerAlias && !stricmp(nick, s_GlobalNoticerAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } else if ((s_HostServ && (stricmp(nick, s_HostServ) == 0)) || (s_HostServAlias && !stricmp(nick, s_HostServAlias))) { notice_lang(s_BotServ, u, BOT_BOT_CREATION_FAILED); return MOD_CONT; } if (isdigit(nick[0]) || nick[0] == '-') { notice_lang(s_BotServ, u, BOT_BAD_NICK); return MOD_CONT; } for (ch = nick; *ch && (ch - nick) < NICKMAX; ch++) { if (!isvalidnick(*ch)) { notice_lang(s_BotServ, u, BOT_BAD_NICK); return MOD_CONT; } } if (!isValidHost(host, 3)) { notice_lang(s_BotServ, u, BOT_BAD_HOST); return MOD_CONT; } for (ch = user; *ch && (ch - user) < USERMAX; ch++) { if (!isalnum(*ch)) { notice_lang(s_BotServ, u, BOT_BAD_IDENT); return MOD_CONT; } } if (stricmp(bi->nick, nick) && findbot(nick)) { notice_lang(s_BotServ, u, BOT_BOT_ALREADY_EXISTS, nick); return MOD_CONT; } if (stricmp(bi->nick, nick)) { /* The new nick is really different, so we remove the Q line for the old nick. */ #ifndef IRC_HYBRID send_cmd(NULL, "UNSQLINE %s", bi->nick); #endif /* We check whether the nick is registered, and drop it if so */ if ((na = findnick(nick))) { delnick(na); } /* We check whether user with this nick is online, and kill it if so */ EnforceQlinedNick(nick, s_BotServ); } if (strcmp(nick, bi->nick)) change_bot_nick(bi, nick); if (user && strcmp(user, bi->user)) { free(bi->user); bi->user = sstrdup(user); } if (host && strcmp(host, bi->host)) { free(bi->host); bi->host = sstrdup(host); } if (real && strcmp(real, bi->real)) { free(bi->real); bi->real = sstrdup(real); } if (!user) { send_cmd(oldnick, "NICK %s", bi->nick); } else { send_cmd(oldnick, "QUIT :Quit: Be right back"); #if defined(BOTSERV_BOTS_MODE) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, BOTSERV_BOTS_MODE, 1); #elif defined(IRC_ULTIMATE) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+oS", 1); #elif defined(IRC_ULTIMATE3) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+opS", 1); #elif defined(IRC_UNREAL) || defined(IRC_VIAGRA) MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+oB", 1); #else MYNEWNICK(bi->nick, bi->user, bi->host, bi->real, "+o", 1); #endif bot_rejoin_all(bi); } notice_lang(s_BotServ, u, BOT_BOT_CHANGED, oldnick, bi->nick, bi->user, bi->host, bi->real); } } else if (WHAT == 1) { if (!nick) { syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); } else if (readonly) { notice_lang(s_BotServ, u, BOT_BOT_READONLY); } else if (!(bi = findbot(nick))) { notice_lang(s_BotServ, u, BOT_DOES_NOT_EXIST, nick); } else { send_cmd(bi->nick, "QUIT :Quit: Help! I'm being deleted by %s!", u->nick); #ifndef IRC_HYBRID send_cmd(NULL, "UNSQLINE %s", bi->nick); #endif delbot(bi); notice_lang(s_BotServ, u, BOT_BOT_DELETED, nick); } } else { syntax_error(s_BotServ, u, "BOT", BOT_BOT_SYNTAX); } return MOD_CONT; } static void insert_bot(BotInfo * bi) { BotInfo *ptr, *prev; for (prev = NULL, ptr = botlists[tolower(*bi->nick)]; ptr != NULL && stricmp(ptr->nick, bi->nick) < 0; prev = ptr, ptr = ptr->next); bi->prev = prev; bi->next = ptr; if (!prev) botlists[tolower(*bi->nick)] = bi; else prev->next = bi; if (ptr) ptr->prev = bi; } static ChannelInfo *makechan(const char *chan) { int i; ChannelInfo *ci; ci = scalloc(sizeof(ChannelInfo), 1); strscpy(ci->name, chan, CHANMAX); ci->time_registered = time(NULL); reset_levelsb(ci); ci->ttb = scalloc(2 * TTB_SIZE, 1); for (i = 0; i < TTB_SIZE; i++) ci->ttb[i] = 0; alpha_insert_chan(ci); return ci; } static void change_bot_nick(BotInfo * bi, char *newnick) { if (bi->next) bi->next->prev = bi->prev; if (bi->prev) bi->prev->next = bi->next; else botlists[tolower(*bi->nick)] = bi->next; if (bi->nick) free(bi->nick); bi->nick = sstrdup(newnick); insert_bot(bi); } static int delbot(BotInfo * bi) { cs_remove_bot(bi); if (bi->next) bi->next->prev = bi->prev; if (bi->prev) bi->prev->next = bi->next; else botlists[tolower(*bi->nick)] = bi->next; nbots--; free(bi->nick); free(bi->user); free(bi->host); free(bi->real); free(bi); return 1; } static int delchana(ChannelInfo * ci) { int i; NickCore *nc = ci->founder; if (ci->bi) { ci->bi->chancount--; } if (ci->c) { if (ci->bi && ci->c->usercount >= BSMinUsers) { send_cmd(ci->bi->nick, "PART %s", ci->c->name); } ci->c->ci = NULL; } #ifdef USE_RDB if (rdb_open()) { rdb_cs_delchan(ci); rdb_close(); } #endif if (ci->next) ci->next->prev = ci->prev; if (ci->prev) ci->prev->next = ci->next; else chanlists[tolower(ci->name[1])] = ci->next; if (ci->desc) free(ci->desc); if (ci->mlock_key) free(ci->mlock_key); #ifdef HAS_FMODE if (ci->mlock_flood) free(ci->mlock_flood); #endif #ifdef HAS_LMODE if (ci->mlock_redirect) free(ci->mlock_redirect); #endif if (ci->last_topic) free(ci->last_topic); if (ci->forbidby) free(ci->forbidby); if (ci->forbidreason) free(ci->forbidreason); if (ci->access) free(ci->access); for (i = 0; i < ci->akickcount; i++) { if (!(ci->akick[i].flags & AK_ISNICK) && ci->akick[i].u.mask) free(ci->akick[i].u.mask); if (ci->akick[i].reason) free(ci->akick[i].reason); if (ci->akick[i].creator) free(ci->akick[i].creator); } if (ci->akick) free(ci->akick); if (ci->levels) free(ci->levels); if (ci->memos.memos) { for (i = 0; i < ci->memos.memocount; i++) { if (ci->memos.memos[i].text) free(ci->memos.memos[i].text); } free(ci->memos.memos); } if (ci->ttb) free(ci->ttb); for (i = 0; i < ci->bwcount; i++) { if (ci->badwords[i].word) free(ci->badwords[i].word); } if (ci->badwords) free(ci->badwords); free(ci); if (nc) nc->channelcount--; return 1; } static BotInfo *makebotA(char *nick) { BotInfo *bi; bi = scalloc(sizeof(BotInfo), 1); bi->nick = sstrdup(nick); bi->lastmsg = time(NULL); insert_bot(bi); nbots++; return bi; } #ifndef ANOPE17x static void EnforceQlinedNick(char *nick, char *killer) { User *u = finduser(nick); if (u) { kill_user(killer, u->nick, "Enforcing SQ:Lined nickname"); } } static void alpha_insert_chan(ChannelInfo * ci) { ChannelInfo *ptr, *prev; char *chan = ci->name; for (prev = NULL, ptr = chanlists[tolower(chan[1])]; ptr != NULL && stricmp(ptr->name, chan) < 0; prev = ptr, ptr = ptr->next); ci->prev = prev; ci->next = ptr; if (!prev) chanlists[tolower(chan[1])] = ci; else prev->next = ci; if (ptr) ptr->prev = ci; } #endif