diff options
author | Adam <Adam@anope.org> | 2011-04-22 03:16:11 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-05-16 04:06:17 -0400 |
commit | c8c23158a4ff74822d6c7d201dc53d879e3d91e8 (patch) | |
tree | 4bc9ae029691d5e7c03ebc1481683a010b733844 | |
parent | 1782ce260c5bc214ec0b2e39257ab1371b68ae9c (diff) |
Moved the core pseudo clients out into their own modules
226 files changed, 5172 insertions, 4876 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f76306ab..db6bbf837 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,7 +222,7 @@ option(USE_RUN_CC_PL "Use run-cc.pl for building" OFF) # Use the following directories as includes # Note that it is important the binary include directory comes before the # source include directory so the precompiled headers work correctly. -include_directories(${Anope_BINARY_DIR}/include ${Anope_SOURCE_DIR}/include ${Anope_BINARY_DIR}/language) +include_directories(${Anope_BINARY_DIR}/include ${Anope_SOURCE_DIR}/include ${Anope_BINARY_DIR}/language ${Anope_SOURCE_DIR}/modules/core) # If using Windows, always add the _WIN32 define if(WIN32) @@ -337,8 +337,6 @@ check_include_file(sys/eventfd.h HAVE_SYS_EVENTFD_H) check_function_exists(setgrent HAVE_SETGRENT) check_function_exists(strcasecmp HAVE_STRCASECMP) check_function_exists(stricmp HAVE_STRICMP) -check_function_exists(strlcat HAVE_STRLCAT) -check_function_exists(strlcpy HAVE_STRLCPY) check_function_exists(umask HAVE_UMASK) check_function_exists(backtrace HAVE_BACKTRACE) check_function_exists(eventfd HAVE_EVENTFD) diff --git a/data/example.conf b/data/example.conf index 5ad787180..66588cdee 100644 --- a/data/example.conf +++ b/data/example.conf @@ -471,35 +471,6 @@ options #hidestatso = yes /* - * If set, Services will send global messages on starting up and shutting - * down/restarting. - * - * This directive is optional. - */ - #globaloncycle = yes - - /* - * This is the global message that will be sent when Services are being - * shutdown/restarted. This directive is only required if you enable - * globaloncycle above. - */ - globaloncycledown = "Services are restarting, they will be back shortly - please be good while we're gone" - - /* - * This is the global message that will be sent when Services (re)join the - * network. This directive is only required if you enable globaloncycle above. - */ - globaloncycleup = "Services are now back online - have a nice day" - - /* - * If set, Services will hide the IRC operator's nick in a global - * message/notice. - * - * This directive is optional. - */ - #anonymousglobal = yes - - /* * Prevents users from registering their nick if they are not connected * for at least the given number of seconds. * @@ -590,8 +561,8 @@ log /* * Target(s) to log to, which may be one of the following: * - a channel name + * - a filename * - globops - * - filename */ target = "services.log" /* Log to both services.log and the channel #services */ @@ -668,7 +639,7 @@ log log { target = "globops" - admin = "operserv/global operserv/mode operserv/kick opeserv/akill operserv/s*line operserv/noop operserv/jupe */forbid nickserv/getpass */drop" + admin = "global/* operserv/mode operserv/kick opeserv/akill operserv/s*line operserv/noop operserv/jupe */forbid nickserv/getpass */drop" } /* @@ -690,6 +661,7 @@ log * chanserv/set - Can modify the settings of any channel (incl. changing of the owner and password!) * memoserv/info - Can see any information with /memoserv info * memoserv/set-limit - Can set the limit of max stored memos on any user and channel + * memoserv/no-limit - Can send memos through limits and throttles * nickserv/auspex - Can see any information with /nickserv info * nickserv/confirm - Can confirm other users nicknames * nickserv/drop - Can drop other users nicks @@ -703,8 +675,8 @@ log * chanserv/mode * * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/entrymsg - * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/opnotice - * chanserv/saset/peace chanserv/saset/persist chanserv/saset/private chanserv/saset/restricted + * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/opnotice chanserv/saset/restricted + * chanserv/saset/peace chanserv/saset/persist chanserv/saset/private * chanserv/saset/secure chanserv/saset/securefounder chanserv/saset/secureops * chanserv/saset/signkick chanserv/saset/successor chanserv/saset/topiclock * chanserv/saset/url chanserv/saset/xop @@ -720,10 +692,12 @@ log * * hostserv/set hostserv/del * - * operserv/global operserv/news operserv/stats operserv/kick + * global/global + * + * operserv/news operserv/stats operserv/kick * operserv/mode operserv/session operserv/modlist operserv/ignore * operserv/chankill operserv/akill operserv/sqline operserv/snline - * operserv/szline operserv/staff operserv/defcon operserv/config + * operserv/szline operserv/staff operserv/config * operserv/modload operserv/jupe operserv/set operserv/noop * operserv/quit operserv/update operserv/reload operserv/restart * operserv/shutdown operserv/svsnick operserv/oline @@ -767,7 +741,7 @@ opertype inherits = "Services Operator" - commands = "chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey chanserv/set/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/global operserv/news operserv/jupe operserv/svsnick operserv/stats operserv/oline operserv/defcon operserv/noop" + commands = "chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey chanserv/set/noexpire memoserv/sendall nickserv/saset/* nickserv/getemail operserv/news operserv/jupe operserv/svsnick operserv/stats operserv/oline operserv/noop global/*" privs = "*" } @@ -911,6 +885,13 @@ dns } /* + * [RECOMMENDED] NickServ + * + * Comment the following line to disable NickServ. + */ +module { name = "ns_main" } + +/* * [REQUIRED] NickServ Config * * This section is used to set up the Nickname Registration Service pseudo-client. @@ -1134,6 +1115,13 @@ nickserv } /* + * [RECOMMENDED] ChanServ + * + * Comment the following line to disable ChanServ. + */ +module { name = "cs_main" } + +/* * [RECOMMENDED] ChanServ Config * * This section is used to set up the Channel Registration Service pseudo-client. @@ -1158,7 +1146,7 @@ chanserv * * This directive is optional, but highly recommended. */ - modules = "cs_help cs_register cs_set cs_saset cs_saset_noexpire cs_set_bantype cs_set_description cs_set_entrymsg cs_set_founder cs_set_keeptopic cs_set_opnotice cs_set_peace cs_set_persist cs_set_private cs_set_restricted cs_set_secure cs_set_securefounder cs_set_secureops cs_set_signkick cs_set_successor cs_set_topiclock cs_set_xop cs_xop cs_access cs_akick cs_drop cs_ban cs_clearusers cs_modes cs_getkey cs_invite cs_kick cs_list cs_topic cs_info cs_forbid cs_suspend cs_status cs_unban cs_clone cs_mode" + modules = "cs_help cs_register cs_set cs_saset cs_saset_noexpire cs_set_bantype cs_set_description cs_set_founder cs_set_keeptopic cs_set_opnotice cs_set_peace cs_set_persist cs_set_private cs_set_restricted cs_set_secure cs_set_securefounder cs_set_secureops cs_set_signkick cs_set_successor cs_set_topiclock cs_set_xop cs_xop cs_access cs_akick cs_drop cs_ban cs_clearusers cs_modes cs_getkey cs_invite cs_kick cs_list cs_topic cs_info cs_forbid cs_suspend cs_status cs_unban cs_clone cs_mode" /* * The default options for newly registered channels. Note that changing these options @@ -1276,10 +1264,16 @@ chanserv } /* - * [OPTIONAL] MemoServ Config + * [OPTIONAL] MemoServ * - * This section is used to set up the Memo Service pseudo-client. Unless specified otherwise, - * all directives are required if you wish to use MemoServ. + * Comment the following line to disable MemoServ. + */ +module { name = "ms_main" } + +/* [OPTIONAL] MemoServ configuration + * + * This section is used to set up the Memo Service pseudo-client. This is only required if ms_main + * is being loaded. */ memoserv { @@ -1323,15 +1317,6 @@ memoserv senddelay = 3s /* - * Should we notify all appropriate users of a new memo? This applies in cases where a memo is - * sent to a nick which is in the group of another nick. Note that, unlike before, it is currently - * more efficient to enable this. - * - * This directive is optional. - */ - notifyall = yes - - /* * Allow the use of memo receipts for the following groups: * * 1 - Opers Only @@ -1343,11 +1328,16 @@ memoserv } /* - * [OPTIONAL] BotServ Config + * [OPTIONAL] BotServ * - * This section is used to set up the Bot Service pseudo-client. The block is optional and can be - * removed if you do not wish to have BotServ on your network. Unless specified otherwise, - * all directives are required if you do wish to use BotServ. + * Comment the following line to disable BotServ. + */ +module { name = "bs_main" } + +/* [OPTIONAL] BotServ configuration + * + * This section is used to set up the Bot Service pseudo-client. This is only required if ms_main + * is being loaded. */ botserv { @@ -1443,12 +1433,17 @@ botserv } /* + * [OPTIONAL] HostServ + * + * Comment the following line to disable HostServ. + */ +module { name = "hs_main" } + +/* * [OPTIONAL] HostServ Config * * This section is used to set up the vHost Service pseudo-client. * - * The block is optional and can be removed if you do not wish to have HostServ on your network. - * * Unless specified otherwise, all directives are required if you do wish to use HostServ. */ hostserv @@ -1474,6 +1469,13 @@ hostserv } /* + * [RECOMMENDED] OperServ + * + * Comment the following line to disable OperServ. + */ +module { name = "os_main" } + +/* * [RECOMMENDED] OperServ Config * * This section is used to set up the Operator Service pseudo-client. Unless specified otherwise, @@ -1498,7 +1500,7 @@ operserv * * This directive is optional, but highly recommended. */ - modules = "os_help os_global os_stats os_staff os_mode os_kick os_akill os_snline os_sqline os_szline os_chanlist os_userlist os_news os_session os_noop os_jupe os_ignore os_set os_reload os_update os_restart os_quit os_shutdown os_defcon os_chankill os_svsnick os_oline os_modload os_modunload os_modreload os_modlist os_modinfo os_config os_login" + modules = "os_help os_stats os_staff os_mode os_kick os_akill os_snline os_sqline os_szline os_chanlist os_userlist os_news os_session os_noop os_jupe os_ignore os_set os_reload os_update os_restart os_quit os_shutdown os_chankill os_svsnick os_oline os_modload os_modunload os_modreload os_modlist os_modinfo os_config os_login" /* * If set, Services Admins will be able to use SUPERADMIN [ON|OFF] which will temporarily grant @@ -1651,6 +1653,13 @@ operserv } /* + * [RECOMMENDED] Global + * + * Comment the following line to disable Global. + */ +module { name = "gl_main" } + +/* * [RECOMMENDED] Global Config * * This section is used to set up the Global pseudo-client. Unless specified otherwise, @@ -1671,6 +1680,43 @@ global * (real name) of the client. */ description = "Global Noticer" + + /* + * The core modules to load for OperServ. This is a space separated list that corresponds + * to the base names of the modules for OperServ. + * + * This directive is optional, but highly recommended. + */ + modules = "gl_help gl_global" + + /* + * If set, Services will send global messages on starting up and shutting + * down/restarting. + * + * This directive is optional. + */ + #globaloncycle = yes + + /* + * This is the global message that will be sent when Services are being + * shutdown/restarted. This directive is only required if you enable + * globaloncycle above. + */ + globaloncycledown = "Services are restarting, they will be back shortly - please be good while we're gone" + + /* + * This is the global message that will be sent when Services (re)join the + * network. This directive is only required if you enable globaloncycle above. + */ + globaloncycleup = "Services are now back online - have a nice day" + + /* + * If set, Services will hide the IRC operator's nick in a global + * message/notice. + * + * This directive is optional. + */ + #anonymousglobal = yes } /* @@ -1750,18 +1796,10 @@ defcon #globalondefcon = yes /* - * If set, Services will send the global message defined in the message directive on DefCon level - * changes. + * Defines a message that will be sent on DefCon level changes. * * This directive is optional. */ - #globalondefconmore = yes - - /* - * Defines the message that will be sent on DefCon level changes when globalondefconmore is set. - * - * This directive is required only when globalondefconmore is set. - */ #message = "Put your message to send your users here. Dont forget to uncomment globalondefconmore" /* @@ -2208,3 +2246,108 @@ ns_set_misc desc = "Associate an ICQ number with the nick" } + +/* + * os_defcon + * + * Allows you to set services in defcon mode, which can be used to restrict services access + * during bot attacks. + */ +#module { "os_defcon" } +os_defcon +{ + /* + * Default DefCon level (1-5) to use when starting Services up. Level 5 constitutes normal operation + * while level 1 constitutes the most restrictive operation. If this setting is left out or set to + * 0, DefCon will be disabled and the rest of this block will be ignored. + */ + #defaultlevel = 5 + + /* + * The following 4 directives define what operations will take place when DefCon is set to levels + * 1 through 4. Each level is a list that must be separated by spaces. + * + * The following operations can be defined at each level: + * - nonewchannels: Disables registering new channels + * - nonewnicks: Disables registering new nicks + * - nomlockchanges: Disables changing MLOCK on registered channels + * - forcechanmodes: Forces all channels to have the modes given in the later chanmodes directive + * - reducedsessions: Reduces the session limit to the value given in the later sessionlimit directive + * - nonewclients: KILL any new clients trying to connect + * - operonly: Services will ignore all non-IRCops + * - silentoperonly: Services will silently ignore all non-IRCops + * - akillnewclients: AKILL any new clients trying to connect + * - nonewmemos: No new memos will be sent to block MemoServ attacks + */ + level4 = "nonewchannels nonewnicks nomlockchanges reducedsessions" + level3 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions" + level2 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly" + level1 = "nonewchannels nonewnicks nomlockchanges forcechanmodes reducedsessions silentoperonly akillnewclients" + + /* + * New session limit to use when a DefCon level is using "reduced" session limiting. + */ + #sessionlimit = 2 + + /* + * Length of time to add an AKILL for when DefCon is preventing new clients from connecting to the + * network. + */ + #akillexpire = 5m + + /* + * The channel modes to set on all channels when the DefCon channel mode system is in use. + * + * Note 1: Choose these modes carefully, because when DefCon switches to a level which does NOT have + * the mode setting selected, Services will set the reverse on all channels, e.g. if this setting + * is +RN when DefCon is used, all channels will be set to +RN, when DefCon is removed, all + * channels will be set to -RN. You don't want to set this to +k for example, because when DefCon + * is removed all channels with -k. + * + * Note 2: MLOCKed modes will not be lost. + */ + #chanmodes = "+R" + + /* + * This value can be used to automatically return the network to DefCon level 5 after the specified + * time period, just in case any IRC Operator forgets to remove a DefCon setting. + * + * This directive is optional. + */ + #timeout = 15m + + /* + * If set, Services will send a global message on DefCon level changes. + * + * This directive is optional. + */ + #globalondefcon = yes + + /* + * If set, Services will send the global message defined in the message directive on DefCon level + * changes. + * + * This directive is optional. + */ + #globalondefconmore = yes + + /* + * Defines the message that will be sent on DefCon level changes when globalondefconmore is set. + * + * This directive is required only when globalondefconmore is set. + */ + #message = "Put your message to send your users here. Dont forget to uncomment globalondefconmore" + + /* + * Defines the message that will be sent when DefCon is returned to level 5. This directive is optional, + * and will also override globalondefcon and globalondefconmore when set. + */ + #offmessage = "Services are now back to normal, sorry for any inconvenience" + + /* + * Defines the reason to use when clients are KILLed or AKILLed from the network while the proper + * DefCon operation is in effect. + */ + #akillreason = "This network is currently not accepting connections, please try again later" +} + diff --git a/docs/Changes.conf b/docs/Changes.conf index 3690de84a..aae4b6658 100644 --- a/docs/Changes.conf +++ b/docs/Changes.conf @@ -1,5 +1,22 @@ Anope Version 1.9.5 ------------------- +** ADDED CONFIGURATION DIRECTIVES ** +global:modules +global:globaloncycle +global:globaloncycledown +global:globaloncycleup +global:anonymousglobal + +** MODIFIED CONFIGURATION DIRECTIVES ** +opertype:permissions added memoserv/no-limit +operserv:modules removed os_global + +** DELETED CONFIGURATION DIRECTIVES ** +memoserv:notifyall +options:globaloncycle +options:globaloncycledown +options:globaloncycleup +options:anonymousglobal Anope Version 1.9.4 ------------------- diff --git a/docs/README b/docs/README index 34bdaa0be..79a6619c7 100644 --- a/docs/README +++ b/docs/README @@ -116,37 +116,6 @@ Table of Contents * Christopher N. <saka@epiknet.org> (fr.l) * Yusuf Kurekci <ysfm.20@gmail.com> (tr.l) - Anope uses the strlcat() and strlcpy() functions from OpenSSH 2.5.1p2. - These functions are copyrighted by Todd C. Miller: - - Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - - 2) Presentation Anope is a set of Services for IRC networks that allows users to manage diff --git a/include/anope.h b/include/anope.h index 4f116c37e..7aa505661 100644 --- a/include/anope.h +++ b/include/anope.h @@ -468,7 +468,21 @@ class dynamic_reference : public dynamic_reference_base this->invalid = false; this->ref = NULL; } - return this->ref; + return this->ref != NULL; + } + + virtual inline operator T*() + { + if (this->operator bool()) + return this->ref; + return NULL; + } + + virtual inline T *operator->() + { + if (this->operator bool()) + return this->ref; + return NULL; } virtual inline void operator=(T *newref) @@ -484,16 +498,6 @@ class dynamic_reference : public dynamic_reference_base if (this->ref) this->ref->AddReference(this); } - - virtual inline T *operator->() - { - return this->ref; - } - - virtual inline T *operator*() - { - return this->ref; - } }; #endif // ANOPE_H diff --git a/include/bots.h b/include/bots.h index bcbbc83d7..7316f074e 100644 --- a/include/bots.h +++ b/include/bots.h @@ -90,6 +90,12 @@ class CoreExport BotInfo : public User, public Flags<BotFlag, BI_END> * @param reason The reason we're parting */ void Part(Channel *c, const Anope::string &reason = ""); + + /** Called when a user messages this bot + * @param u The user + * @param message The users' message + */ + virtual void OnMessage(User *u, const Anope::string &message); }; #endif // BOTS_H diff --git a/include/channels.h b/include/channels.h index d0f899794..5d18a381f 100644 --- a/include/channels.h +++ b/include/channels.h @@ -12,38 +12,9 @@ typedef Anope::insensitive_map<Channel *> channel_map; extern CoreExport channel_map ChannelList; -struct UserData -{ - UserData() - { - Clear(); - } - - virtual ~UserData() { } - - void Clear() - { - last_use = last_start = Anope::CurTime; - lines = times = 0; - lastline.clear(); - } - - /* Data validity */ - time_t last_use; - - /* for flood kicker */ - int16 lines; - time_t last_start; - - /* for repeat kicker */ - Anope::string lastline; - int16 times; -}; - -struct UserContainer +struct UserContainer : public Extensible { User *user; - UserData ud; ChannelStatus *Status; UserContainer(User *u) : user(u) { } @@ -93,8 +64,6 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlag, 3> Anope::string topic_setter; /* Who set the topic */ time_t topic_time; /* When the topic was set*/ - std::list<BanData *> bd; - time_t server_modetime; /* Time of last server MODE */ time_t chanserv_modetime; /* Time of last check_modes() */ int16 server_modecount; /* Number of server MODEs this second */ diff --git a/include/config.h b/include/config.h index 5cba79587..666649253 100644 --- a/include/config.h +++ b/include/config.h @@ -167,7 +167,7 @@ template<> class ValueContainer<char **> : public ValueContainerBase return; } *val = new char[s]; - strlcpy(*val, newval, s); + memcpy(*val, newval, s); } }; @@ -264,7 +264,6 @@ bool ValidateHostServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateLimitSessions(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); -bool ValidateDefCon(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); bool ValidateNickLen(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data); bool ValidateMail(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); bool ValidateGlobalOnCycle(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data); @@ -435,7 +434,7 @@ class CoreExport ServerConfig /* OperServ name */ Anope::string s_OperServ; /* Global name */ - Anope::string s_GlobalNoticer; + Anope::string s_Global; /* NickServs realname */ Anope::string desc_NickServ; /* ChanServ realname */ @@ -447,18 +446,26 @@ class CoreExport ServerConfig /* OperServ realname */ Anope::string desc_OperServ; /* Global realname */ - Anope::string desc_GlobalNoticer; + Anope::string desc_Global; /* HostServ Name */ Anope::string s_HostServ; /* HostServ realname */ Anope::string desc_HostServ; + /* Core HostServ modules */ + Anope::string HostCoreModules; /* Filename for the PID file */ Anope::string PIDFilename; /* MOTD filename */ Anope::string MOTDFilename; + /* Core MemoServ Modules */ + Anope::string MemoCoreModules; + /* Core OperServ Modules */ + Anope::string OperCoreModules; + /* Core Global Modules */ + Anope::string GlobalCoreModules; /* True if its ok to not be able to save backs */ bool NoBackupOkay; /* Do password checking when new people register */ @@ -578,6 +585,8 @@ class CoreExport ServerConfig bool NSStrictPrivileges; /* Use email to verify new users registering */ bool NSEmailReg; + /* Core NickServ modules */ + Anope::string NickCoreModules; /* Set the proper channel modes on users when they identify */ bool NSModeOnID; /* Add the users hostnask their access list when they register */ @@ -585,6 +594,8 @@ class CoreExport ServerConfig /* Maximum number of channels on AJoin */ unsigned AJoinMax; + /* Core ChanServ modules */ + Anope::string ChanCoreModules; /* Default flags for newly registered channels */ Flags<ChannelInfoFlag, CI_END> CSDefFlags; /* Max number of channels a user can own */ @@ -621,7 +632,9 @@ class CoreExport ServerConfig /* Who can use memos reciepts */ unsigned MSMemoReceipt; - /* Defai;t BotServ flags */ + /* Core BotServ modules */ + Anope::string BotCoreModules; + /* Default BotServ flags */ Flags<BotServFlag> BSDefFlags; /* How long before botserv forgets a user. This is used for flood kickers etc */ time_t BSKeepData; @@ -710,39 +723,6 @@ class CoreExport ServerConfig std::list<Anope::string> EncModuleList; /* Database modules */ std::list<Anope::string> DBModuleList; - /* HostServ Core Modules */ - std::list<Anope::string> HostServCoreModules; - /* MemoServ Core Modules */ - std::list<Anope::string> MemoServCoreModules; - /* BotServ Core Modules */ - std::list<Anope::string> BotServCoreModules; - /* OperServ Core Modules */ - std::list<Anope::string> OperServCoreModules; - /* NickServ Core Modules */ - std::list<Anope::string> NickServCoreModules; - /* ChanServ Core Modules */ - std::list<Anope::string> ChanServCoreModules; - - /* Default defcon level */ - int DefConLevel; - /* Timeout before defcon is reset */ - time_t DefConTimeOut; - /* Session limiit to use when using defcon */ - unsigned DefConSessionLimit; - /* How long to add akills for defcon */ - time_t DefConAKILL; - /* Chan modes for defcon */ - Anope::string DefConChanModes; - /* Should we global on defcon */ - bool GlobalOnDefcon; - /* Should we send DefconMessage aswell? */ - bool GlobalOnDefconMore; - /* Message to send when defcon is off */ - Anope::string DefConOffMessage; - /* Message to send when defcon is on*/ - Anope::string DefconMessage; - /* Reason to akill clients for defcon */ - Anope::string DefConAkillReason; /* The socket engine in use */ Anope::string SocketEngine; diff --git a/include/extern.h b/include/extern.h index 0b29c0d03..6ec3310e9 100644 --- a/include/extern.h +++ b/include/extern.h @@ -31,35 +31,15 @@ E void kill_user(const Anope::string &source, User *user, const Anope::string &r E bool bad_password(User *u); E void common_unban(ChannelInfo *ci, User *u, bool full = false); -E BotInfo *BotServ; -E BotInfo *ChanServ; -E BotInfo *Global; -E BotInfo *HostServ; -E BotInfo *MemoServ; -E BotInfo *NickServ; -E BotInfo *OperServ; - /**** botserv.c ****/ -E void get_botserv_stats(long *nrec, long *memuse); -E void bs_init(); -E void botchanmsgs(User *u, ChannelInfo *ci, const Anope::string &buf); E BotInfo *findbot(const Anope::string &nick); -/** Finds a pseudoclient, given a UID. Useful for TS6 protocol modules. - * @param uid The UID to search for - * @return The pseudoclient structure, or NULL if one could not be found - */ -E Anope::string normalizeBuffer(const Anope::string &); - -E void check_ban(ChannelInfo *ci, User *u, int ttbtype); -E void bot_kick(ChannelInfo *ci, User *u, const char *message, ...); E void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason); E void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason); /**** channels.c ****/ -E void get_channel_stats(long *nrec, long *memuse); E Channel *findchan(const Anope::string &chan); @@ -75,27 +55,14 @@ E void MassChannelModes(BotInfo *bi, const Anope::string &modes); E void chan_set_correct_modes(User *user, Channel *c, int give_modes); -inline BotInfo *whosends(ChannelInfo *ci) -{ - if (!ci || !ci->bi || !ci->c || !ci->botflags.HasFlag(BS_SYMBIOSIS) || !ci->c->FindUser(ci->bi)) - return ChanServ ? ChanServ : NickServ; - return ci->bi; -} - /**** chanserv.c ****/ E LevelInfo levelinfo[]; -E void get_chanserv_stats(long *nrec, long *memuse); E void reset_levels(ChannelInfo *ci); -E void cs_init(); -E void expire_chans(); -E void cs_remove_nick(NickCore *nc); E void check_modes(Channel *c); -E int check_valid_admin(User *user, Channel *chan, int servermode); -E int check_valid_op(User *user, Channel *chan, int servermode); E ChannelInfo *cs_findchan(const Anope::string &chan); E int check_access(User *user, ChannelInfo *ci, int what); @@ -111,17 +78,11 @@ E Anope::string get_mlock_modes(ChannelInfo *ci, int complete); E ConfigurationFile services_conf; E ServerConfig *Config; -/* hostserv.c */ -E void do_on_id(User *u); -E void HostServSyncVhosts(NickAlias *na); - /**** encrypt.c ****/ E int enc_encrypt(const Anope::string &src, Anope::string &dest); E int enc_decrypt(const Anope::string &src, Anope::string &dest); /**** hostserv.c ****/ -E void get_hostserv_stats(long *nrec, long *memuse); -E void hostserv_init(); /**** init.c ****/ @@ -146,9 +107,6 @@ E void PopLanguage(); E const char *anope_gettext(const char *string); E void SyntaxError(CommandSource &source, const Anope::string &command, const Anope::string &message); -/*** logger.cpp ***/ -E void InitLogChannels(ServerConfig *); - /**** main.c ****/ E Anope::string services_dir; @@ -169,7 +127,6 @@ E time_t start_time; E ConnectionSocket *UplinkSock; E void save_databases(); -E void expire_all(); E void sighandler(int signum); E void do_restart_services(); @@ -184,14 +141,6 @@ class CoreExport UplinkSocket : public ConnectionSocket bool Read(const Anope::string &buf); }; -/**** memoserv.c ****/ - -E void ms_init(); -E void rsend_notify(CommandSource &source, Memo *m, const Anope::string &chan); -E void check_memos(User *u); -E MemoInfo *getmemoinfo(const Anope::string &name, bool &ischan, bool &isforbid); -E void memo_send(CommandSource &source, const Anope::string &name, const Anope::string &text, int z); - /**** messages.cpp ****/ E void init_core_messages(); @@ -225,12 +174,6 @@ E bool OnError(const Anope::string &, const std::vector<Anope::string> &); E bool IsFile(const Anope::string &filename); E int toupper(char); E int tolower(char); -#ifndef HAVE_STRLCPY -E size_t strlcpy(char *, const char *, size_t); -#endif -#ifndef HAVE_STRLCAT -E size_t strlcat(char *, const char *, size_t); -#endif E time_t dotime(const Anope::string &s); E Anope::string duration(time_t seconds); @@ -260,6 +203,7 @@ E std::vector<Anope::string> BuildStringVector(const Anope::string &, char = ' ' E bool str_is_wildcard(const Anope::string &str); E bool str_is_pure_wildcard(const Anope::string &str); +E Anope::string normalizeBuffer(const Anope::string &); /**** modes.cpp ****/ /* Number of generic modes we support */ @@ -269,15 +213,9 @@ E void SetDefaultMLock(ServerConfig *config); /**** nickserv.c ****/ -E void get_aliases_stats(long &count, long &mem); -E void get_core_stats(long &count, long &mem); E void change_core_display(NickCore *nc); E void change_core_display(NickCore *nc, const Anope::string &newdisplay); -E int do_setmodes(User *u); -E void ns_init(); -E int validate_user(User *u); -E void expire_nicks(); E NickAlias *findnick(const Anope::string &nick); E NickCore *findcore(const Anope::string &nick); E bool is_on_access(const User *u, const NickCore *nc); @@ -292,24 +230,6 @@ E void send_cmd(const Anope::string &source, const char *fmt, ...) FORMAT(printf E void notice_server(const Anope::string &source, const Server *s, const char *fmt, ...) FORMAT(printf, 3, 4); -/**** sessions.c ****/ - -E std::vector<Exception *> exceptions; - -E void get_session_stats(long &count, long &mem); -E void get_exception_stats(long &count, long &mem); - -E void add_session(User *u); -E void del_session(User *u); - -E void expire_exceptions(); - -E Session *findsession(const Anope::string &host); - -E Exception *find_host_exception(const Anope::string &host); -E Exception *find_hostip_exception(const Anope::string &host, const Anope::string &hostip); -E int exception_add(User *u, const Anope::string &mask, unsigned limit, const Anope::string &reason, const Anope::string &who, time_t expires); - /**** sockets.cpp ****/ E SocketEngineBase *SocketEngine; @@ -323,8 +243,6 @@ E int32 opcnt; E uint32 maxusercnt, usercnt; E time_t maxusertime; -E void get_user_stats(long &count, long &mem); - E User *finduser(const Anope::string &nick); E User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, const Anope::string &ip, const Anope::string &vhost, const Anope::string &uid, const Anope::string &modes); @@ -342,9 +260,4 @@ E Anope::string create_mask(User *u); E void b64_encode(const Anope::string &src, Anope::string &target); E void b64_decode(const Anope::string &src, Anope::string &target); -#ifdef _WIN32 -E Anope::string GetWindowsVersion(); -E bool SupportedWindowsVersion(); -#endif - #endif /* EXTERN_H */ diff --git a/include/logger.h b/include/logger.h index 6d134c227..cb3d00d6a 100644 --- a/include/logger.h +++ b/include/logger.h @@ -39,7 +39,7 @@ class CoreExport Log std::stringstream buf; - Log(LogType type = LOG_NORMAL, const Anope::string &category = "", BotInfo *bi = Global); + Log(LogType type = LOG_NORMAL, const Anope::string &category = "", BotInfo *bi = NULL); /* LOG_COMMAND/OVERRIDE/ADMIN */ Log(LogType type, User *u, Command *c, ChannelInfo *ci = NULL); diff --git a/include/modules.h b/include/modules.h index 51a550316..badb59616 100644 --- a/include/modules.h +++ b/include/modules.h @@ -314,9 +314,8 @@ class CoreExport Module : public Extensible virtual void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) { } /** Called when Services' configuration has been loaded. - * @param startup True if Services is starting for the first time, false otherwise. */ - virtual void OnReload(bool startup) {} + virtual void OnReload() { } /** Called before a bot is assigned to a channel. * @param sender The user assigning the bot @@ -333,20 +332,11 @@ class CoreExport Module : public Extensible */ virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) { return EVENT_CONTINUE; } - /** Called after a user has been introduced, but before any type - * of checking has been done (akills, defcon, s*lines, etc) - * return EVENT_STOP here to allow the user to get by untouched, - * or kill them then return EVENT_STOP to tell Anope the user no - * longer exists - * @param u The user - * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to stop processing - */ - virtual EventReturn OnPreUserConnect(User *u) { return EVENT_CONTINUE; } - /** Called when a new user connects to the network. * @param u The connecting user. + * @param exempt set to true/is true if the user should be excepted from bans etc */ - virtual void OnUserConnect(User *u) { } + virtual void OnUserConnect(dynamic_reference<User> &u, bool &exempt) { } /** Called when a new server connects to the network. * @param s The server that has connected to the network @@ -523,16 +513,6 @@ class CoreExport Module : public Extensible */ virtual void OnServerDisconnect() { } - /** Called before the database expire routines are called - * Note: Code that is in seperate expiry routines should just be done - * when we save the DB, theres no need to have both - */ - virtual void OnPreDatabaseExpire() { } - - /** Called when the database expire routines are called - */ - virtual void OnDatabaseExpire() { } - /** Called when the flatfile dbs are being written * @param Write A callback to the function used to insert a line into the database */ @@ -639,11 +619,10 @@ class CoreExport Module : public Extensible virtual void OnDefconLevel(int level) { } /** Called before an akill is added - * @param u The user adding the akill * @param ak The akill * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnAddAkill(User *u, XLine *ak) { return EVENT_CONTINUE; } + virtual EventReturn OnAddAkill(XLine *ak) { return EVENT_CONTINUE; } /** Called before an akill is deleted * @param u The user removing the akill @@ -652,11 +631,10 @@ class CoreExport Module : public Extensible virtual void OnDelAkill(User *u, XLine *ak) { } /** Called after an exception has been added - * @param u The user who added it * @param ex The exception * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnExceptionAdd(User *u, Exception *ex) { return EVENT_CONTINUE; } + virtual EventReturn OnExceptionAdd(Exception *ex) { return EVENT_CONTINUE; } /** Called before an exception is deleted * @param u The user who is deleting it @@ -665,12 +643,11 @@ class CoreExport Module : public Extensible virtual void OnExceptionDel(User *u, Exception *ex) { } /** Called before a XLine is added - * @param u The user adding the XLine * @param sx The XLine * @param Type The type of XLine this is * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it */ - virtual EventReturn OnAddXLine(User *u, XLine *x, XLineType Type) { return EVENT_CONTINUE; } + virtual EventReturn OnAddXLine(XLine *x, XLineType Type) { return EVENT_CONTINUE; } /** Called before a XLine is deleted * @param u The user deleting the XLine @@ -932,12 +909,22 @@ class CoreExport Module : public Extensible */ virtual EventReturn OnCheckAuthentication(User *u, Command *c, const std::vector<Anope::string> ¶ms, const Anope::string &account, const Anope::string &password) { return EVENT_CONTINUE; } + /** Called when a user does /ns update + * @param u The user + */ + virtual void OnNickUpdate(User *u) { } + /** Called when we get informed about a users SSL fingerprint * when we call this, the fingerprint should already be stored in the user struct * @param u pointer to the user */ virtual void OnFingerprint(User *u) { } + /** Called when a user becomes (un)away + * @param message The message, is .empty() if unaway + */ + virtual void OnUserAway(User *u, const Anope::string &message) { } + /** Called when a vhost is deleted * @param na The nickalias of the vhost */ @@ -949,18 +936,12 @@ class CoreExport Module : public Extensible virtual void OnSetVhost(NickAlias *na) { } /** Called when a memo is sent - * @param u The user sending the memo - * @param nc The nickcore of who the memo was sent to - * @param m The memo - */ - virtual void OnMemoSend(User *u, NickCore *nc, Memo *m) { } - - /** Called when a memo is sent - * @param u The user sending the memo - * @param ci The channel the memo was sent to + * @param source The source of the memo + * @param target The target of the memo + * @param mi Memo info for target * @param m The memo */ - virtual void OnMemoSend(User *u, ChannelInfo *ci, Memo *m) { } + virtual void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) { } /** Called when a memo is deleted * @param nc The nickcore of the memo being deleted @@ -1064,10 +1045,8 @@ class CoreExport Module : public Extensible * @param u The source of the message * @param ci The channel * @param msg The message - * @param Allow set to false to make the flood kickers halt - * @return MOD_STOP to stop processing completely */ - virtual EventReturn OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg, bool &Allow) { return EVENT_CONTINUE; } + virtual void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) { } /** Called when any object is destroyed * @param b The object @@ -1087,6 +1066,7 @@ enum Implementation I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert, I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnFindNick, I_OnFindCore, I_OnCheckAuthentication, + I_OnNickUpdate, /* ChanServ */ I_OnChanForbidden, I_OnChanSuspend, I_OnChanDrop, I_OnPreChanExpire, I_OnChanExpire, I_OnAccessAdd, I_OnAccessChange, @@ -1105,8 +1085,8 @@ enum Implementation I_OnMemoSend, I_OnMemoDel, /* Users */ - I_OnPreUserConnect, I_OnUserConnect, I_OnUserNickChange, I_OnUserQuit, I_OnUserLogoff, I_OnPreJoinChannel, - I_OnJoinChannel, I_OnPrePartChannel, I_OnPartChannel, I_OnFingerprint, + I_OnUserConnect, I_OnUserNickChange, I_OnUserQuit, I_OnUserLogoff, I_OnPreJoinChannel, + I_OnJoinChannel, I_OnPrePartChannel, I_OnPartChannel, I_OnFingerprint, I_OnUserAway, /* OperServ */ I_OnDefconLevel, I_OnAddAkill, I_OnDelAkill, I_OnExceptionAdd, I_OnExceptionDel, @@ -1114,7 +1094,6 @@ enum Implementation /* Database */ I_OnPostLoadDatabases, I_OnSaveDatabase, I_OnLoadDatabase, - I_OnDatabaseExpire, I_OnDatabaseWrite, I_OnDatabaseRead, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata, /* Modules */ @@ -1122,7 +1101,7 @@ enum Implementation /* Other */ I_OnReload, I_OnPreServerConnect, I_OnNewServer, I_OnServerConnect, I_OnPreUplinkSync, I_OnServerDisconnect, I_OnPreCommandRun, - I_OnPreCommand, I_OnPostCommand, I_OnPreDatabaseExpire, I_OnPreRestart, I_OnRestart, I_OnPreShutdown, I_OnShutdown, I_OnSignal, + I_OnPreCommand, I_OnPostCommand, I_OnPreRestart, I_OnRestart, I_OnPreShutdown, I_OnShutdown, I_OnSignal, I_OnServerQuit, I_OnTopicUpdated, I_OnEncrypt, I_OnDecrypt, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd, @@ -1293,10 +1272,6 @@ class service_reference : public dynamic_reference<T> { } - virtual ~service_reference() - { - } - operator bool() { if (this->invalid) diff --git a/include/operserv.h b/include/oper.h index f039b6107..cebd079ca 100644 --- a/include/operserv.h +++ b/include/oper.h @@ -6,15 +6,10 @@ * Please read COPYING and README for further details. */ -#ifndef OPERSERV_H -#define OPERSERV_H +#ifndef OPER_H +#define OPER_H extern CoreExport std::vector<NewsItem *> News; -extern CoreExport std::vector<std::bitset<32> > DefCon; -extern CoreExport bool DefConModesSet; -extern CoreExport Flags<ChannelModeName, CMODE_END * 2> DefConModesOn; -extern CoreExport Flags<ChannelModeName, CMODE_END * 2> DefConModesOff; -extern CoreExport std::map<ChannelModeName, Anope::string> DefConModesOnParams; class XLineManager; extern CoreExport XLineManager *SGLine; @@ -22,19 +17,6 @@ extern CoreExport XLineManager *SZLine; extern CoreExport XLineManager *SQLine; extern CoreExport XLineManager *SNLine; -extern CoreExport bool SetDefConParam(ChannelModeName, const Anope::string &); -extern CoreExport bool GetDefConParam(ChannelModeName, Anope::string &); -extern CoreExport void UnsetDefConParam(ChannelModeName); -extern CoreExport bool CheckDefCon(DefconLevel Level); -extern CoreExport bool CheckDefCon(int level, DefconLevel Level); -extern CoreExport void AddDefCon(int level, DefconLevel Level); -extern CoreExport void DelDefCon(int level, DefconLevel Level); - -extern CoreExport void os_init(); - -extern CoreExport void oper_global(const Anope::string &nick, const char *fmt, ...); -extern CoreExport void server_global(const Server *s, const Anope::string &message); - enum XLineType { X_SNLINE, @@ -129,14 +111,13 @@ class CoreExport XLineManager void Clear(); /** Add an entry to this XLine Manager - * @param bi The bot error replies should be sent from - * @param u The user adding the XLine * @param mask The mask of the XLine + * @param creator The creator of the XLine * @param expires When this should expire * @param reaosn The reason * @return A pointer to the XLine */ - virtual XLine *Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason); + virtual XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); private: /** Delete an XLine, eg, remove it from the IRCd. @@ -190,7 +171,7 @@ class CoreExport XLineManager class SGLineManager : public XLineManager { public: - XLine *Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason); + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); void Del(XLine *x); @@ -204,7 +185,7 @@ class SGLineManager : public XLineManager class SNLineManager : public XLineManager { public: - XLine *Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason); + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); void Del(XLine *x); @@ -220,7 +201,7 @@ class SNLineManager : public XLineManager class SQLineManager : public XLineManager { public: - XLine *Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason); + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); void Del(XLine *x); @@ -236,7 +217,7 @@ class SQLineManager : public XLineManager class SZLineManager : public XLineManager { public: - XLine *Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason); + XLine *Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason); void Del(XLine *x); @@ -247,4 +228,4 @@ class SZLineManager : public XLineManager void Send(User *u, XLine *x); }; -#endif // OPERSERV_H +#endif // OPER_H diff --git a/include/regchannel.h b/include/regchannel.h index 6f9a52fdc..a3112cfbc 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -175,6 +175,11 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag, int16 floodlines, floodsecs; /* For FLOOD kicker */ int16 repeattimes; /* For REPEAT kicker */ + /** Find which bot should send mode/topic/etc changes for this channel + * @return The bot + */ + BotInfo *WhoSends(); + /** Add an entry to the channel access list * * @param mask The mask of the access entry diff --git a/include/services.h b/include/services.h index 6caa06d48..2974465a4 100644 --- a/include/services.h +++ b/include/services.h @@ -272,6 +272,7 @@ template<typename T, size_t Size = 32> class Flags const Anope::string *Flag_Strings; public: + Flags() : Flag_Strings(NULL) { } Flags(const Anope::string *flag_strings) : Flag_Strings(flag_strings) { } /** Add a flag to this item @@ -409,7 +410,6 @@ class ChannelInfo; class Channel; class Server; class Entry; -struct Session; #include "threadengine.h" #include "opertype.h" @@ -454,13 +454,11 @@ enum MemoFlag /* Memo is unread */ MF_UNREAD, /* Sender requests a receipt */ - MF_RECEIPT, - /* Memo is a notification of receipt */ - MF_NOTIFYS + MF_RECEIPT }; const Anope::string MemoFlagStrings[] = { - "MF_UNREAD", "MF_RECEIPT", "MF_NOTIFYS", "" + "MF_UNREAD", "MF_RECEIPT", "" }; /* Memo info structures. Since both nicknames and channels can have memos, @@ -486,6 +484,23 @@ struct CoreExport MemoInfo bool HasIgnore(User *u); }; +struct Session +{ + Anope::string host; /* Host of the session */ + unsigned count; /* Number of clients with this host */ + unsigned hits; /* Number of subsequent kills for a host */ +}; + +struct Exception +{ + Anope::string mask; /* Hosts to which this exception applies */ + unsigned limit; /* Session limit for exception */ + Anope::string who; /* Nick of person who added the exception */ + Anope::string reason; /* Reason for exception's addition */ + time_t time; /* When this exception was added */ + time_t expires; /* Time when it expires. 0 == no expiry */ +}; + /*************************************************************************/ class CoreExport HostInfo @@ -703,13 +718,6 @@ enum #include "account.h" #include "bots.h" -struct BanData -{ - Anope::string mask; /* Since a nick is unsure and a User structure is unsafe */ - time_t last_use; /* Since time is the only way to check whether it's still useful */ - int16 ttb[TTB_SIZE]; -}; - struct LevelInfo { int what; @@ -801,43 +809,7 @@ struct MailInfo /*************************************************************************/ -struct Exception -{ - Anope::string mask; /* Hosts to which this exception applies */ - unsigned limit; /* Session limit for exception */ - Anope::string who; /* Nick of person who added the exception */ - Anope::string reason; /* Reason for exception's addition */ - time_t time; /* When this exception was added */ - time_t expires; /* Time when it expires. 0 == no expiry */ -}; - -/*************************************************************************/ - -extern CoreExport Anope::map<Session *> SessionList; - -struct Session -{ - Anope::string host; - unsigned count; /* Number of clients with this host */ - unsigned hits; /* Number of subsequent kills for a host */ -}; - -/*************************************************************************/ - /* Defcon */ -enum DefconLevel -{ - DEFCON_NO_NEW_CHANNELS, - DEFCON_NO_NEW_NICKS, - DEFCON_NO_MLOCK_CHANGE, - DEFCON_FORCE_CHAN_MODES, - DEFCON_REDUCE_SESSION, - DEFCON_NO_NEW_CLIENTS, - DEFCON_OPER_ONLY, - DEFCON_SILENT_OPER_ONLY, - DEFCON_AKILL_NEW_CLIENTS, - DEFCON_NO_NEW_MEMOS -}; /*************************************************************************/ @@ -863,7 +835,7 @@ class ConfigurationFile; #include "extern.h" #include "language.h" -#include "operserv.h" +#include "oper.h" #include "mail.h" #include "servers.h" #include "logger.h" diff --git a/include/sysconf.h.cmake b/include/sysconf.h.cmake index 78150a82d..68f3f74e6 100644 --- a/include/sysconf.h.cmake +++ b/include/sysconf.h.cmake @@ -12,8 +12,6 @@ #cmakedefine HAVE_STRCASECMP 1 #cmakedefine HAVE_STRICMP 1 #cmakedefine HAVE_STRINGS_H 1 -#cmakedefine HAVE_STRLCAT 1 -#cmakedefine HAVE_STRLCPY 1 #cmakedefine HAVE_UMASK 1 #cmakedefine HAVE_EVENTFD 1 #cmakedefine GETTEXT_FOUND 1 diff --git a/modules/core/botserv.h b/modules/core/botserv.h new file mode 100644 index 000000000..5c707278a --- /dev/null +++ b/modules/core/botserv.h @@ -0,0 +1,65 @@ +#ifndef BOTSERV_H +#define BOTSERV_H + +struct UserData +{ + UserData() + { + this->Clear(); + } + + void Clear() + { + last_use = last_start = Anope::CurTime; + lines = times = 0; + lastline.clear(); + } + + /* Data validity */ + time_t last_use; + + /* for flood kicker */ + int16 lines; + time_t last_start; + + /* for repeat kicker */ + Anope::string lastline; + Anope::string lasttarget; + int16 times; +}; + +struct BanData +{ + Anope::string mask; + time_t last_use; + int16 ttb[TTB_SIZE]; + + BanData() + { + this->Clear(); + } + + void Clear() + { + last_use = 0; + for (int i = 0; i < TTB_SIZE; ++i) + this->ttb[i] = 0; + } +}; + +class BotServService : public Service +{ + public: + BotServService(Module *m) : Service(m, "BotServ") { } + + virtual BotInfo *Bot() = 0; + + virtual UserData *GetUserData(User *u, Channel *c) = 0; + + virtual BanData *GetBanData(User *u, Channel *c) = 0; +}; + +static service_reference<BotServService> botserv("BotServ"); + +#endif // BOTSERV_H + diff --git a/modules/core/bs_act.cpp b/modules/core/bs_act.cpp index 3e868c25a..2547ce3c1 100644 --- a/modules/core/bs_act.cpp +++ b/modules/core/bs_act.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSAct : public Command { @@ -35,7 +36,7 @@ class CommandBSAct : public Command if (!ci->bi) { - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); return MOD_CONT; } @@ -83,7 +84,10 @@ class BSAct : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsact); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsact); } }; diff --git a/modules/core/bs_assign.cpp b/modules/core/bs_assign.cpp index f1000cb11..5be9e6bf3 100644 --- a/modules/core/bs_assign.cpp +++ b/modules/core/bs_assign.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSAssign : public Command { @@ -93,7 +94,10 @@ class BSAssign : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsassign); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsassign); } }; diff --git a/modules/core/bs_badwords.cpp b/modules/core/bs_badwords.cpp index 5acbf913f..1b3b2a884 100644 --- a/modules/core/bs_badwords.cpp +++ b/modules/core/bs_badwords.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class BadwordsListCallback : public NumberList { @@ -291,7 +292,7 @@ class CommandBSBadwords : public Command "will be done if a user says a word that ends with\n" "\037word\037. If you don't specify anything, a kick will\n" "be issued every time \037word\037 is said by a user.\n" - " \n"), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + " \n"), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); source.Reply(_("The \002BADWORDS DEL\002 command removes the given word from the\n" "bad words list. If a list of entry numbers is given, those\n" "entries are deleted. (See the example for LIST below.)\n" @@ -325,7 +326,10 @@ class BSBadwords : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsbadwords); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsbadwords); } }; diff --git a/modules/core/bs_bot.cpp b/modules/core/bs_bot.cpp index d35d90ec1..64413b5f0 100644 --- a/modules/core/bs_bot.cpp +++ b/modules/core/bs_bot.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSBot : public Command { @@ -423,7 +424,10 @@ class BSBot : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsbot); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsbot); } }; diff --git a/modules/core/bs_botlist.cpp b/modules/core/bs_botlist.cpp index 1310a6358..a6a56f088 100644 --- a/modules/core/bs_botlist.cpp +++ b/modules/core/bs_botlist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSBotList : public Command { @@ -83,7 +84,10 @@ class BSBotList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsbotlist); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsbotlist); } }; diff --git a/modules/core/bs_help.cpp b/modules/core/bs_help.cpp index c2632b437..eafa5b44e 100644 --- a/modules/core/bs_help.cpp +++ b/modules/core/bs_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSHelp : public Command { @@ -25,7 +26,7 @@ class CommandBSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(BotServ, source.u, NULL, params[0]); + mod_help_cmd(botserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } @@ -40,9 +41,9 @@ class CommandBSHelp : public Command "below; to use them, type \002%s%s \037command\037\002. For\n" "more information on a specific command, type\n" "\002%s%s HELP \037command\037\002."), - BotServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); - for (CommandMap::const_iterator it = BotServ->Commands.begin(), it_end = BotServ->Commands.end(); it != it_end; ++it) + Config->s_BotServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); + for (CommandMap::const_iterator it = botserv->Bot()->Commands.begin(), it_end = botserv->Bot()->Commands.end(); it != it_end; ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); source.Reply(_("Bot will join a channel whenever there is at least\n" @@ -62,7 +63,10 @@ class BSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbshelp); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbshelp); } }; diff --git a/modules/core/bs_info.cpp b/modules/core/bs_info.cpp index a5853f611..afb13c66d 100644 --- a/modules/core/bs_info.cpp +++ b/modules/core/bs_info.cpp @@ -13,6 +13,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSInfo : public Command { @@ -227,7 +228,7 @@ class CommandBSInfo : public Command "If the parameter is a channel, then you'll get information\n" "such as enabled kickers. If the parameter is a nick,\n" "you'll get information about a bot, such as creation\n" - "time or number of channels it is on."), NickServ->nick.c_str()); + "time or number of channels it is on."), Config->s_NickServ.c_str()); return true; } @@ -247,7 +248,10 @@ class BSInfo : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsinfo); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsinfo); } }; diff --git a/modules/core/bs_kick.cpp b/modules/core/bs_kick.cpp index ff68b7099..9b78d6e7b 100644 --- a/modules/core/bs_kick.cpp +++ b/modules/core/bs_kick.cpp @@ -13,6 +13,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSKick : public Command { @@ -41,7 +42,7 @@ class CommandBSKick : public Command else if (!check_access(u, ci, CA_SET) && !u->HasPriv("botserv/administration")) source.Reply(_(ACCESS_DENIED)); else if (!ci->bi) - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); else { bool override = !check_access(u, ci, CA_SET); @@ -479,7 +480,7 @@ class CommandBSKick : public Command "on a specific option.\n" " \n" "Note: access to this command is controlled by the\n" - "level SET."), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + "level SET."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); else if (subcommand.equals_ci("BADWORDS")) source.Reply(_("Syntax: \002KICK \037#channel\037 BADWORDS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the bad words kicker on or off. When enabled, this\n" @@ -490,7 +491,7 @@ class CommandBSKick : public Command "more information.\n" "ttb is the number of times a user can be kicked\n" "before it get banned. Don't give ttb to disable\n" - "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + "the ban system once activated."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); else if (subcommand.equals_ci("BOLDS")) source.Reply(_("Syntax: \002KICK \037channel\037 BOLDS {\037ON|OFF\037} [\037ttb\037]\002\n" "Sets the bolds kicker on or off. When enabled, this\n" @@ -581,47 +582,301 @@ class BSKick : public Module { CommandBSKick commandbskick; + void check_ban(ChannelInfo *ci, User *u, int ttbtype) + { + /* Don't ban ulines */ + if (u->server->IsULined()) + return; + + BanData *bd = botserv->GetBanData(u, ci->c); + + ++bd->ttb[ttbtype]; + if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) + { + /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype] + * if the TTB was changed after it was not set (0) before and the user had already been + * kicked a few times. Bug #1056 - Adam */ + Anope::string mask; + + bd->ttb[ttbtype] = 0; + + get_idealban(ci, u, mask); + + if (ci->c) + ci->c->SetMode(NULL, CMODE_BAN, mask); + FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask)); + } + } + + void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) + { + va_list args; + char buf[1024]; + + if (!ci || !ci->bi || !ci->c || !u || u->server->IsULined()) + return; + + Anope::string fmt = GetString(u->Account(), message); + va_start(args, message); + if (fmt.empty()) + return; + vsnprintf(buf, sizeof(buf), fmt.c_str(), args); + va_end(args); + + ci->c->Kick(ci->bi, u, "%s", buf); + } + public: BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbskick); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbskick); ModuleManager::Attach(I_OnPrivmsg, this); } - EventReturn OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg, bool &Allow) + void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) { - Anope::string m, ch; - time_t time; - - if (u->GetExtRegular("bs_kick_lastmsg", m) && u->GetExtRegular("bs_kick_lasttime", time) && u->GetExtRegular("bs_kick_lastchan", ch)) + /* Now we can make kicker stuff. We try to order the checks + * from the fastest one to the slowest one, since there's + * no need to process other kickers if a user is kicked before + * the last kicker check. + * + * But FIRST we check whether the user is protected in any + * way. + */ + + bool Allow = true; + if (check_access(u, ci, CA_NOKICK)) + Allow = false; + else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (ci->c->HasUserStatus(u, CMODE_HALFOP) || ci->c->HasUserStatus(u, CMODE_OP) || ci->c->HasUserStatus(u, CMODE_PROTECT) || ci->c->HasUserStatus(u, CMODE_OWNER))) + Allow = false; + else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE)) + Allow = false; + + if (Allow) { - if (time == Anope::CurTime && m == msg && ch != ci->name) + Anope::string realbuf = msg; + + /* Bolds kicker */ + if (ci->botflags.HasFlag(BS_KICK_BOLDS) && realbuf.find(2) != Anope::string::npos) + { + check_ban(ci, u, TTB_BOLDS); + bot_kick(ci, u, _("Don't use bolds on this channel!")); + return; + } + + /* Color kicker */ + if (ci->botflags.HasFlag(BS_KICK_COLORS) && realbuf.find(3) != Anope::string::npos) + { + check_ban(ci, u, TTB_COLORS); + bot_kick(ci, u, _("Don't use colors on this channel!")); + return; + } + + /* Reverses kicker */ + if (ci->botflags.HasFlag(BS_KICK_REVERSES) && realbuf.find(22) != Anope::string::npos) + { + check_ban(ci, u, TTB_REVERSES); + bot_kick(ci, u, _("Don't use reverses on this channel!")); + return; + } + + /* Italics kicker */ + if (ci->botflags.HasFlag(BS_KICK_ITALICS) && realbuf.find(29) != Anope::string::npos) + { + check_ban(ci, u, TTB_ITALICS); + bot_kick(ci, u, _("Don't use italics on this channel!")); + return; + } + + /* Underlines kicker */ + if (ci->botflags.HasFlag(BS_KICK_UNDERLINES) && realbuf.find(31) != Anope::string::npos) + { + check_ban(ci, u, TTB_UNDERLINES); + bot_kick(ci, u, _("Don't use underlines on this channel!")); + return; + } + + /* Caps kicker */ + if (ci->botflags.HasFlag(BS_KICK_CAPS) && realbuf.length() >= ci->capsmin) + { + int i = 0, l = 0; + + for (unsigned j = 0, end = realbuf.length(); j < end; ++j) + { + if (isupper(realbuf[j])) + ++i; + else if (islower(realbuf[j])) + ++l; + } + + /* i counts uppercase chars, l counts lowercase chars. Only + * alphabetic chars (so islower || isupper) qualify for the + * percentage of caps to kick for; the rest is ignored. -GD + */ + + if ((i || l) && i >= ci->capsmin && i * 100 / (i + l) >= ci->capspercent) + { + check_ban(ci, u, TTB_CAPS); + bot_kick(ci, u, _("Turn caps lock OFF!")); + return; + } + } + + /* Bad words kicker */ + if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) { - for (UChannelList::iterator it = u->chans.begin(); it != u->chans.end();) + bool mustkick = false; + + /* Normalize the buffer */ + Anope::string nbuf = normalizeBuffer(realbuf); + + for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i) { - Channel *c = (*it)->chan; - ++it; + BadWord *bw = ci->GetBadWord(i); - if (c->ci != NULL && c->ci->botflags.HasFlag(BS_KICK_AMSGS)) + if (bw->type == BW_ANY && ((Config->BSCaseSensitive && nbuf.find(bw->word) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) != Anope::string::npos))) + mustkick = true; + else if (bw->type == BW_SINGLE) { - check_ban(c->ci, u, TTB_AMSGS); - bot_kick(c->ci, u, _("Don't use AMSGs!")); + size_t len = bw->word.length(); + + if ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf))) + mustkick = true; + else if (nbuf.find(' ') == len && ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf)))) + mustkick = true; + else + { + if (nbuf.rfind(' ') == nbuf.length() - len - 1 && ((Config->BSCaseSensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) == nbuf.length() - len))) + mustkick = true; + else + { + Anope::string wordbuf = " " + bw->word + " "; + + if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) + mustkick = true; + } + } + } + else if (bw->type == BW_START) + { + size_t len = bw->word.length(); + + if ((Config->BSCaseSensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(0, len).equals_ci(bw->word))) + mustkick = true; + else + { + Anope::string wordbuf = " " + bw->word; + + if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) + mustkick = true; + } + } + else if (bw->type == BW_END) + { + size_t len = bw->word.length(); + + if ((Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word))) + mustkick = true; + else + { + Anope::string wordbuf = bw->word + " "; + + if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) + mustkick = true; + } + } + + if (mustkick) + { + check_ban(ci, u, TTB_BADWORDS); + if (Config->BSGentleBWReason) + bot_kick(ci, u, _("Watch your language!")); + else + bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str()); + + return; } } - return EVENT_CONTINUE; + UserData *ud = NULL; + + /* Flood kicker */ + if (ci->botflags.HasFlag(BS_KICK_FLOOD)) + { + ud = botserv->GetUserData(u, ci->c); + if (ud) + { + if (Anope::CurTime - ud->last_start > ci->floodsecs) + { + ud->last_start = Anope::CurTime; + ud->lines = 0; + } + + ++ud->lines; + if (ud->lines >= ci->floodlines) + { + check_ban(ci, u, TTB_FLOOD); + bot_kick(ci, u, _("Stop flooding!")); + return; + } + } + } + + /* Repeat kicker */ + if (ci->botflags.HasFlag(BS_KICK_REPEAT)) + { + if (!ud) + ud = botserv->GetUserData(u, ci->c); + if (ud) + { + + if (!ud->lastline.empty() && !ud->lastline.equals_ci(realbuf)) + { + ud->lastline = realbuf; + ud->times = 0; + } + else + { + if (ud->lastline.empty()) + ud->lastline = realbuf; + ++ud->times; + } + + if (ud->times >= ci->repeattimes) + { + check_ban(ci, u, TTB_REPEAT); + bot_kick(ci, u, _("Stop repeating yourself!")); + return; + } + } + } + + if (ud && ud->lastline.equals_ci(realbuf) && !ud->lasttarget.empty() && !ud->lasttarget.equals_ci(ci->name)) + { + for (UChannelList::iterator it = u->chans.begin(); it != u->chans.end();) + { + Channel *c = (*it)->chan; + ++it; + + if (c->ci != NULL && c->ci->botflags.HasFlag(BS_KICK_AMSGS) && !check_access(u, c->ci, CA_NOKICK)) + { + check_ban(c->ci, u, TTB_AMSGS); + bot_kick(c->ci, u, _("Don't use AMSGs!")); + } + } + } + + if (ud) + ud->lasttarget = ci->name; } } - - u->Extend("bs_kick_lastmsg", new ExtensibleItemRegular<Anope::string>(msg)); - u->Extend("bs_kick_lasttime", new ExtensibleItemRegular<time_t>(Anope::CurTime)); - u->Extend("bs_kick_lastchan", new ExtensibleItemRegular<Anope::string>(ci->name)); - - return EVENT_CONTINUE; } }; diff --git a/modules/core/bs_main.cpp b/modules/core/bs_main.cpp new file mode 100644 index 000000000..5bd7e5ce2 --- /dev/null +++ b/modules/core/bs_main.cpp @@ -0,0 +1,265 @@ +/* BotServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "botserv.h" +#include "chanserv.h" + +static BotInfo *BotServ = NULL; + +class BotServBotInfo : public BotInfo +{ + public: + BotServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } + + void OnMessage(User *u, const Anope::string &message) + { + PushLanguage("anope", u->Account() ? u->Account()->language : ""); + + spacesepstream sep(message); + Anope::string command, param; + if (sep.GetToken(command) && sep.GetToken(param)) + { + Command *c = FindCommand(this, command); + if (c) + { + if (ircdproto->IsChannelValid(param)) + { + ChannelInfo *ci = cs_findchan(param); + if (ci) + { + if (ci->HasFlag(CI_FORBIDDEN) && !c->HasFlag(CFLAG_ALLOW_FORBIDDEN)) + { + u->SendMessage(this, _(_(CHAN_X_FORBIDDEN)), ci->name.c_str()); + Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of FORBIDDEN channel " << ci->name; + PopLanguage(); + return; + } + else if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) + { + u->SendMessage(this, _(_(CHAN_X_FORBIDDEN)), ci->name.c_str()); + Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; + PopLanguage(); + return; + } + } + else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL)) + { + u->SendMessage(this, _(_(CHAN_X_NOT_REGISTERED)), param.c_str()); + PopLanguage(); + return; + } + } + /* A user not giving a channel name for a param that should be a channel */ + else + { + u->SendMessage(this, _(CHAN_X_INVALID), param.c_str()); + PopLanguage(); + return; + } + } + } + + PopLanguage(); + BotInfo::OnMessage(u, message); + } +}; + +class MyBotServService : public BotServService +{ + public: + MyBotServService(Module *m) : BotServService(m) { } + + BotInfo *Bot() + { + return BotServ; + } + + UserData *GetUserData(User *u, Channel *c) + { + UserData *ud = NULL; + UserContainer *uc = c->FindUser(u); + if (uc != NULL) + { + if (!uc->GetExtPointer("bs_main_userdata", ud)) + { + ud = new UserData(); + uc->Extend("bs_main_userdata", new ExtensibleItemPointer<UserData>(ud)); + } + } + return ud; + } + + BanData *GetBanData(User *u, Channel *c) + { + std::map<Anope::string, BanData> bandatamap; + if (!c->GetExtRegular("bs_main_bandata", bandatamap)); + c->Extend("bs_main_bandata", new ExtensibleItemRegular<std::map<Anope::string, BanData> >(bandatamap)); + c->GetExtRegular("bs_main_bandata", bandatamap); + + BanData *bd = &bandatamap[u->GetMask()]; + if (bd->last_use && Anope::CurTime - bd->last_use > Config->BSKeepData) + bd->Clear(); + bd->last_use = Anope::CurTime; + return bd; + } +}; + +class BanDataPurger : public CallBack +{ + public: + BanDataPurger(Module *owner) : CallBack(owner, 300, Anope::CurTime, true) { } + + void Tick(time_t) + { + Log(LOG_DEBUG) << "bs_main: Running bandata purger"; + + for (channel_map::iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it) + { + Channel *c = it->second; + + std::map<Anope::string, BanData> bandata; + if (c->GetExtRegular("bs_main_bandata", bandata)) + { + for (std::map<Anope::string, BanData>::iterator it2 = bandata.begin(), it2_end = bandata.end(); it2 != it2_end; ++it2) + { + BanData *bd = &it2->second; + + if (Anope::CurTime - bd->last_use > Config->BSKeepData) + { + bandata.erase(it2); + continue; + } + } + + if (bandata.empty()) + c->Shrink("bs_main_bandata"); + } + } + } +}; + +class BotServCore : public Module +{ + MyBotServService mybotserv; + BanDataPurger bdpurger; + + public: + BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), mybotserv(this), bdpurger(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + ModuleManager::RegisterService(&this->mybotserv); + + BotServ = new BotServBotInfo(Config->s_BotServ, Config->ServiceUser, Config->ServiceHost, Config->desc_BotServ); + BotServ->SetFlag(BI_CORE); + + Implementation i[] = { I_OnPrivmsg }; + ModuleManager::Attach(i, this, 1); + + spacesepstream coreModules(Config->BotCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~BotServCore() + { + spacesepstream coreModules(Config->BotCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete BotServ; + } + + void OnPrivmsg(User *u, ChannelInfo *ci, Anope::string &msg) + { + if (!u || !ci || !ci->c || !ci->bi || msg.empty()) + return; + + /* Answer to ping if needed */ + if (msg.substr(0, 6).equals_ci("\1PING ") && msg[msg.length() - 1] == '\1') + { + Anope::string ctcp = msg; + ctcp.erase(ctcp.begin()); + ctcp.erase(ctcp.length() - 1); + ircdproto->SendCTCP(ci->bi, u->nick, "%s", ctcp.c_str()); + } + + bool was_action = false; + + Anope::string realbuf = msg; + + /* If it's a /me, cut the CTCP part because the ACTION will cause + * problems with the caps or badwords kicker + */ + if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1') + { + realbuf.erase(0, 8); + realbuf.erase(realbuf.length() - 1); + was_action = true; + } + + if (realbuf.empty()) + return; + + /* Fantaisist commands */ + if (ci->botflags.HasFlag(BS_FANTASY) && realbuf[0] == Config->BSFantasyCharacter[0] && !was_action && chanserv) + { + /* Strip off the fantasy character */ + realbuf.erase(realbuf.begin()); + + size_t space = realbuf.find(' '); + Anope::string command, rest; + if (space == Anope::string::npos) + command = realbuf; + else + { + command = realbuf.substr(0, space); + rest = realbuf.substr(space + 1); + } + + if (check_access(u, ci, CA_FANTASIA)) + { + Command *cmd = FindCommand(chanserv->Bot(), command); + + /* Command exists and can be called by fantasy */ + if (cmd && !cmd->HasFlag(CFLAG_DISABLE_FANTASY)) + { + Anope::string params = rest; + /* Some commands don't need the channel name added.. eg !help */ + if (!cmd->HasFlag(CFLAG_STRIP_CHANNEL)) + params = ci->name + " " + params; + params = command + " " + params; + + mod_run_cmd(chanserv->Bot(), u, ci, params); + } + + FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, ci, rest)); + } + else + { + FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, ci, rest)); + } + } + } +}; + +MODULE_INIT(BotServCore) + diff --git a/modules/core/bs_say.cpp b/modules/core/bs_say.cpp index d64880964..673244a6c 100644 --- a/modules/core/bs_say.cpp +++ b/modules/core/bs_say.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSSay : public Command { @@ -36,7 +37,7 @@ class CommandBSSay : public Command if (!ci->bi) { - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); return MOD_CONT; } @@ -85,7 +86,10 @@ class BSSay : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbssay); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbssay); } }; diff --git a/modules/core/bs_set.cpp b/modules/core/bs_set.cpp index 24843fff7..daf37c199 100644 --- a/modules/core/bs_set.cpp +++ b/modules/core/bs_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSSet : public Command { @@ -216,7 +217,7 @@ class CommandBSSet : public Command "Type \002%s%s HELP SET \037option\037\002 for more information\n" "on a specific option.\n" "Note: access to this command is controlled by the\n" - "level SET."), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + "level SET."), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); User *u = source.u; if (u->IsServicesOper()) source.Reply(_("These options are reserved to Services Operators:\n" @@ -308,7 +309,10 @@ class BSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsset); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsset); } }; diff --git a/modules/core/bs_unassign.cpp b/modules/core/bs_unassign.cpp index 8e28508ab..104eded56 100644 --- a/modules/core/bs_unassign.cpp +++ b/modules/core/bs_unassign.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "botserv.h" class CommandBSUnassign : public Command { @@ -33,7 +34,7 @@ class CommandBSUnassign : public Command else if (!u->HasPriv("botserv/administration") && !check_access(u, ci, CA_ASSIGN)) source.Reply(_(ACCESS_DENIED)); else if (!ci->bi) - source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), BotServ->nick.c_str()); + source.Reply(_(BOT_NOT_ASSIGNED), Config->UseStrictPrivMsgString.c_str(), Config->s_BotServ.c_str()); else if (ci->HasFlag(CI_PERSIST) && !cm) source.Reply(_("You can not unassign bots while persist is set on the channel.")); else @@ -75,7 +76,10 @@ class BSUnassign : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(BotServ, &commandbsunassign); + if (!botserv) + throw ModuleException("BotServ is not loaded!"); + + this->AddCommand(botserv->Bot(), &commandbsunassign); } }; diff --git a/modules/core/chanserv.h b/modules/core/chanserv.h new file mode 100644 index 000000000..2017aa156 --- /dev/null +++ b/modules/core/chanserv.h @@ -0,0 +1,15 @@ +#ifndef CHANSERV_H +#define CHANSERV_H + +class ChanServService : public Service +{ + public: + ChanServService(Module *m) : Service(m, "ChanServ") { } + + virtual BotInfo *Bot() = 0; +}; + +static service_reference<ChanServService> chanserv("ChanServ"); + +#endif // CHANSERV_H + diff --git a/modules/core/cs_access.cpp b/modules/core/cs_access.cpp index 0cf8263ac..5fc4e7290 100644 --- a/modules/core/cs_access.cpp +++ b/modules/core/cs_access.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class AccessListCallback : public NumberList { @@ -504,7 +505,7 @@ class CommandCSAccess : public Command " \n" "The \002ACCESS CLEAR\002 command clears all entries of the\n" "access list."), - ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); source.Reply(_("\002User access levels\002\n" " \n" "By default, the following access levels are defined:\n" @@ -523,7 +524,7 @@ class CommandCSAccess : public Command " \n" "These levels may be changed, or new ones added, using the\n" "\002LEVELS\002 command; type \002%s%s HELP LEVELS\002 for\n" - "information."), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + "information."), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -746,7 +747,7 @@ class CommandCSLevels : public Command "\002HELP ACCESS LEVELS\002).\n" " \n" "For a list of the features and functions whose levels can be\n" - "set, see \002HELP LEVELS DESC\002."), ChanServ->nick.c_str()); + "set, see \002HELP LEVELS DESC\002."), Config->s_ChanServ.c_str()); return true; } @@ -767,8 +768,11 @@ class CSAccess : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsaccess); - this->AddCommand(ChanServ, &commandcslevels); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsaccess); + this->AddCommand(chanserv->Bot(), &commandcslevels); } }; diff --git a/modules/core/cs_akick.cpp b/modules/core/cs_akick.cpp index 4584ac6b5..e168bdb67 100644 --- a/modules/core/cs_akick.cpp +++ b/modules/core/cs_akick.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" /* Split a usermask up into its constitutent parts. Returned strings are * malloc()'d, and should be free()'d when done with. Returns "*" for @@ -532,7 +533,7 @@ class CommandCSAKick : public Command "When akicking a \037registered nick\037 the nickserv account\n" "will be added to the akick list instead of the mask.\n" "All users within that nickgroup will then be akicked.\n"), - ChanServ->nick.c_str()); + Config->s_ChanServ.c_str()); source.Reply(_( " \n" "The \002AKICK DEL\002 command removes the given nick or mask\n" @@ -552,7 +553,7 @@ class CommandCSAKick : public Command "AKICK mask.\n" " \n" "The \002AKICK CLEAR\002 command clears all entries of the\n" - "akick list."), ChanServ->nick.c_str()); + "akick list."), Config->s_ChanServ.c_str()); return true; } @@ -572,7 +573,10 @@ class CSAKick : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsakick); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsakick); } }; diff --git a/modules/core/cs_ban.cpp b/modules/core/cs_ban.cpp index 97d205156..3bccd9897 100644 --- a/modules/core/cs_ban.cpp +++ b/modules/core/cs_ban.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSBan : public Command { @@ -67,9 +68,9 @@ class CommandCSBan : public Command return MOD_CONT; if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(u, ci, CA_SIGNKICK))) - c->Kick(whosends(ci), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); + c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); else - c->Kick(whosends(ci), u2, "%s", reason.c_str()); + c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); } return MOD_CONT; @@ -102,7 +103,10 @@ class CSBan : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsban); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsban); } }; diff --git a/modules/core/cs_clearusers.cpp b/modules/core/cs_clearusers.cpp index 572c396af..7cf5055b7 100644 --- a/modules/core/cs_clearusers.cpp +++ b/modules/core/cs_clearusers.cpp @@ -12,13 +12,14 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSClearUsers : public Command { public: CommandCSClearUsers() : Command("CLEARUSERS", 1, 1) { - this->SetDesc(_("Tells ChanServ to clear (kick) all users on a channel")); + this->SetDesc(Anope::printf(_("Tells %s to kick all users on a channel"), Config->s_ChanServ.c_str())); } CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -57,7 +58,7 @@ class CommandCSClearUsers : public Command "Tells %s to clear (kick) all users certain settings on a channel." " \n" "By default, limited to those with founder access on the\n" - "channel."), ChanServ->nick.c_str()); + "channel."), Config->s_ChanServ.c_str()); return true; } @@ -77,7 +78,10 @@ class CSClearUsers : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsclearusers); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsclearusers); } }; diff --git a/modules/core/cs_clone.cpp b/modules/core/cs_clone.cpp index bbdae4c5f..52161abf1 100644 --- a/modules/core/cs_clone.cpp +++ b/modules/core/cs_clone.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSClone : public Command { @@ -177,7 +178,10 @@ class CSClone : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsclone); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsclone); } }; diff --git a/modules/core/cs_drop.cpp b/modules/core/cs_drop.cpp index 248cfa37e..66f1b31f6 100644 --- a/modules/core/cs_drop.cpp +++ b/modules/core/cs_drop.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSDrop : public Command { @@ -67,8 +68,6 @@ class CommandCSDrop : public Command bool override = (ci->HasFlag(CI_SECUREFOUNDER) ? !IsFounder(u, ci) : !check_access(u, ci, CA_FOUNDER)); Log(override ? LOG_OVERRIDE : LOG_COMMAND, u, this, ci) << "founder: " << (ci->founder ? ci->founder->display : "none"); - if (override) - ircdproto->SendGlobops(ChanServ, "\2%s\2 used DROP on channel \2%s\2", u->nick.c_str(), ci->name.c_str()); delete ci; @@ -112,7 +111,10 @@ class CSDrop : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsdrop); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsdrop); } }; diff --git a/modules/core/cs_forbid.cpp b/modules/core/cs_forbid.cpp index e17a1777c..9c0573971 100644 --- a/modules/core/cs_forbid.cpp +++ b/modules/core/cs_forbid.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSForbid : public Command { @@ -75,7 +76,7 @@ class CommandCSForbid : public Command if (uc->user->HasMode(UMODE_OPER)) continue; - c->Kick(ChanServ, uc->user, "%s", !reason.empty() ? reason.c_str() : GetString(uc->user->Account(), "This channel has been forbidden.").c_str()); + c->Kick(chanserv->Bot(), uc->user, "%s", !reason.empty() ? reason.c_str() : GetString(uc->user->Account(), "This channel has been forbidden.").c_str()); } } @@ -121,7 +122,10 @@ class CSForbid : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsforbid); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsforbid); } }; diff --git a/modules/core/cs_getkey.cpp b/modules/core/cs_getkey.cpp index da71e690e..b46a7df53 100644 --- a/modules/core/cs_getkey.cpp +++ b/modules/core/cs_getkey.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSGetKey : public Command { @@ -72,7 +73,10 @@ class CSGetKey : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsgetkey); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsgetkey); } }; diff --git a/modules/core/cs_help.cpp b/modules/core/cs_help.cpp index be2436d29..aff4c5165 100644 --- a/modules/core/cs_help.cpp +++ b/modules/core/cs_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSHelp : public Command { @@ -25,7 +26,7 @@ class CommandCSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(ChanServ, source.u, NULL, params[0]); + mod_help_cmd(chanserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } @@ -40,9 +41,8 @@ class CommandCSHelp : public Command "commands are listed below; to use them, type\n" "\002%s%s \037command\037\002. For more information on a\n" "specific command, type \002%s%s HELP \037command\037\002."), - ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - ChanServ->nick.c_str()); - for (CommandMap::const_iterator it = ChanServ->Commands.begin(); it != ChanServ->Commands.end(); ++it) + Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str()); + for (CommandMap::const_iterator it = chanserv->Bot()->Commands.begin(); it != chanserv->Bot()->Commands.end(); ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); if (Config->CSExpire >= 86400) @@ -67,7 +67,10 @@ class CSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcshelp); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcshelp); } }; diff --git a/modules/core/cs_info.cpp b/modules/core/cs_info.cpp index c9c8b674c..19823004d 100644 --- a/modules/core/cs_info.cpp +++ b/modules/core/cs_info.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSInfo : public Command { @@ -140,7 +141,10 @@ class CSInfo : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsinfo); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsinfo); } }; diff --git a/modules/core/cs_invite.cpp b/modules/core/cs_invite.cpp index efafdeedd..e7bcbbdab 100644 --- a/modules/core/cs_invite.cpp +++ b/modules/core/cs_invite.cpp @@ -12,13 +12,14 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSInvite : public Command { public: CommandCSInvite() : Command("INVITE", 1, 3) { - this->SetDesc(_("Tells ChanServ to invite you into a channel")); + this->SetDesc(Anope::printf(_("Tells %s to invite you into a channel"), Config->s_ChanServ.c_str())); } CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -62,9 +63,9 @@ class CommandCSInvite : public Command source.Reply(_("You are already in \002%s\002! "), c->name.c_str()); else { - ircdproto->SendInvite(whosends(ci), chan, u2->nick); + ircdproto->SendInvite(ci->WhoSends(), chan, u2->nick); source.Reply(_("\002%s\002 has been invited to \002%s\002."), u2->nick.c_str(), c->name.c_str()); - u2->SendMessage(whosends(ci), _("You have been invited to \002%s\002."), c->name.c_str()); + u2->SendMessage(ci->WhoSends(), _("You have been invited to \002%s\002."), c->name.c_str()); } return MOD_CONT; } @@ -76,7 +77,7 @@ class CommandCSInvite : public Command "Tells %s to invite you into the given channel.\n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), ChanServ->nick.c_str()); + "on the channel."), Config->s_ChanServ.c_str()); return true; } @@ -96,7 +97,10 @@ class CSInvite : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsinvite); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsinvite); } }; diff --git a/modules/core/cs_kick.cpp b/modules/core/cs_kick.cpp index 2f165fb72..2cf06e1e4 100644 --- a/modules/core/cs_kick.cpp +++ b/modules/core/cs_kick.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSKick : public Command { @@ -54,9 +55,9 @@ class CommandCSKick : public Command Log(LOG_COMMAND, u, this, ci) << "for " << u2->nick; if (ci->HasFlag(CI_SIGNKICK) || (ci->HasFlag(CI_SIGNKICK_LEVEL) && !check_access(u, ci, CA_SIGNKICK))) - ci->c->Kick(whosends(ci), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); + ci->c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), u->nick.c_str()); else - ci->c->Kick(whosends(ci), u2, "%s", reason.c_str()); + ci->c->Kick(ci->WhoSends(), u2, "%s", reason.c_str()); } return MOD_CONT; } @@ -88,7 +89,10 @@ class CSKick : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcskick); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcskick); } }; diff --git a/modules/core/cs_list.cpp b/modules/core/cs_list.cpp index 8e3d75e5f..318eea59f 100644 --- a/modules/core/cs_list.cpp +++ b/modules/core/cs_list.cpp @@ -12,7 +12,7 @@ /*************************************************************************/ #include "module.h" -#include "hashcomp.h" +#include "chanserv.h" class CommandCSList : public Command { @@ -147,7 +147,10 @@ class CSList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcslist); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcslist); } }; diff --git a/modules/core/cs_main.cpp b/modules/core/cs_main.cpp new file mode 100644 index 000000000..04258b646 --- /dev/null +++ b/modules/core/cs_main.cpp @@ -0,0 +1,256 @@ +/* ChanServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "chanserv.h" + +static BotInfo *ChanServ = NULL; + +class ChanServBotInfo : public BotInfo +{ + public: + ChanServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } + + void OnMessage(User *u, const Anope::string &message) + { + PushLanguage("anope", u->Account() ? u->Account()->language : ""); + + if (!u->HasMode(UMODE_OPER) && Config->CSOpersOnly) + { + u->SendMessage(ChanServ, _(ACCESS_DENIED)); + PopLanguage(); + return; + } + + spacesepstream sep(message); + Anope::string command, param; + if (sep.GetToken(command) && sep.GetToken(param)) + { + Command *c = FindCommand(this, command); + if (c) + { + if (ircdproto->IsChannelValid(param)) + { + ChannelInfo *ci = cs_findchan(param); + if (ci) + { + if (ci->HasFlag(CI_FORBIDDEN) && !c->HasFlag(CFLAG_ALLOW_FORBIDDEN)) + { + u->SendMessage(this, _(_(CHAN_X_FORBIDDEN)), ci->name.c_str()); + Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of FORBIDDEN channel " << ci->name; + PopLanguage(); + return; + } + else if (ci->HasFlag(CI_SUSPENDED) && !c->HasFlag(CFLAG_ALLOW_SUSPENDED)) + { + u->SendMessage(this, _(_(CHAN_X_FORBIDDEN)), ci->name.c_str()); + Log(LOG_COMMAND, "denied", this) << "Access denied for user " << u->GetMask() << " with command " << command << " because of SUSPENDED channel " << ci->name; + PopLanguage(); + return; + } + } + else if (!c->HasFlag(CFLAG_ALLOW_UNREGISTEREDCHANNEL)) + { + u->SendMessage(this, _(_(CHAN_X_NOT_REGISTERED)), param.c_str()); + PopLanguage(); + return; + } + } + /* A user not giving a channel name for a param that should be a channel */ + else + { + u->SendMessage(this, _(CHAN_X_INVALID), param.c_str()); + PopLanguage(); + return; + } + } + } + + PopLanguage(); + BotInfo::OnMessage(u, message); + } +}; + +class MyChanServService : public ChanServService +{ + public: + MyChanServService(Module *m) : ChanServService(m) { } + + BotInfo *Bot() + { + return ChanServ; + } +}; + +class ExpireCallback : public CallBack +{ + public: + ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { } + + void Tick(time_t) + { + if (!Config->CSExpire || noexpire || readonly) + return; + + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) + { + ChannelInfo *ci = it->second; + ++it; + + bool expire = false; + if (ci->HasFlag(CI_SUSPENDED)) + { + if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) + expire = true; + } + else if (ci->HasFlag(CI_FORBIDDEN)) + { + if (Config->CSForbidExpire && Anope::CurTime - ci->last_used >= Config->CSForbidExpire) + expire = true; + } + else if (!ci->c && Anope::CurTime - ci->last_used >= Config->CSExpire) + expire = true; + + if (ci->HasFlag(CI_NO_EXPIRE)) + expire = false; + + if (expire) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); + if (MOD_RESULT == EVENT_STOP) + continue; + + Anope::string extra; + if (ci->HasFlag(CI_FORBIDDEN)) + extra = "forbidden "; + else if (ci->HasFlag(CI_SUSPENDED)) + extra = "suspended "; + + Log(LOG_NORMAL, "chanserv/expire", ChanServ) << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << ")"; + FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); + delete ci; + } + } + } +}; + +class ChanServCore : public Module +{ + MyChanServService mychanserv; + ExpireCallback expires; + + public: + ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), mychanserv(this), expires(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + ModuleManager::RegisterService(&this->mychanserv); + + ChanServ = new ChanServBotInfo(Config->s_ChanServ, Config->ServiceUser, Config->ServiceHost, Config->desc_ChanServ); + ChanServ->SetFlag(BI_CORE); + + Implementation i[] = { I_OnDelCore, I_OnDelChan }; + ModuleManager::Attach(i, this, 2); + + spacesepstream coreModules(Config->ChanCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~ChanServCore() + { + spacesepstream coreModules(Config->ChanCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete ChanServ; + } + + void OnDelCore(NickCore *nc) + { + // XXX this is slightly inefficient + for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end;) + { + ChannelInfo *ci = it->second; + ++it; + + if (ci->founder == nc) + { + NickCore *newowner = NULL; + if (ci->successor && (ci->successor->IsServicesOper() || !Config->CSMaxReg || ci->successor->channelcount < Config->CSMaxReg)) + newowner = ci->successor; + else + { + ChanAccess *highest = NULL; + for (unsigned j = 0; j < ci->GetAccessCount(); ++j) + { + ChanAccess *ca = ci->GetAccess(j); + + if (!ca->nc || (!ca->nc->IsServicesOper() && Config->CSMaxReg && ca->nc->channelcount >= Config->CSMaxReg) || (ca->nc == nc)) + continue; + if (!highest || ca->level > highest->level) + highest = ca; + } + if (highest) + newowner = highest->nc; + } + + if (newowner) + { + Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display; + ci->founder = newowner; + ci->successor = NULL; + ++newowner->channelcount; + } + else + { + Log(LOG_NORMAL, "chanserv/expire") << "Deleting channel " << ci->name << " owned by deleted nick " << nc->display; + + delete ci; + continue; + } + } + + if (ci->successor == nc) + ci->successor = NULL; + + ChanAccess *access = ci->GetAccess(nc); + if (access) + ci->EraseAccess(access); + + for (unsigned j = ci->GetAkickCount(); j > 0; --j) + { + AutoKick *akick = ci->GetAkick(j - 1); + if (akick->HasFlag(AK_ISNICK) && akick->nc == nc) + ci->EraseAkick(j - 1); + } + } + } + + void OnDelChan(ChannelInfo *ci) + { + if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) + ci->c->RemoveMode(NULL, CMODE_REGISTERED, "", false); + } +}; + +MODULE_INIT(ChanServCore) + diff --git a/modules/core/cs_mode.cpp b/modules/core/cs_mode.cpp index 55da9762c..fc4538033 100644 --- a/modules/core/cs_mode.cpp +++ b/modules/core/cs_mode.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSMode : public Command { @@ -366,7 +367,10 @@ class CSMode : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsmode); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsmode); } }; diff --git a/modules/core/cs_modes.cpp b/modules/core/cs_modes.cpp index 96520b215..eeaf9f733 100644 --- a/modules/core/cs_modes.cpp +++ b/modules/core/cs_modes.cpp @@ -12,7 +12,7 @@ /*************************************************************************/ #include "module.h" - +#include "chanserv.h" class CommandModeBase : public Command { @@ -76,7 +76,7 @@ class CommandModeBase : public Command Log(LOG_COMMAND, u, com, ci) << "for " << u2->nick; if (notice && ci->HasFlag(notice)) - ircdproto->SendMessage(whosends(ci), c->name, "%s command used for %s by %s", com->name.c_str(), u2->nick.c_str(), u->nick.c_str()); + ircdproto->SendMessage(ci->WhoSends(), c->name, "%s command used for %s by %s", com->name.c_str(), u2->nick.c_str(), u->nick.c_str()); } } @@ -462,10 +462,13 @@ class CSModes : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsop); - this->AddCommand(ChanServ, &commandcsdeop); - this->AddCommand(ChanServ, &commandcsvoice); - this->AddCommand(ChanServ, &commandcsdevoice); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsop); + this->AddCommand(chanserv->Bot(), &commandcsdeop); + this->AddCommand(chanserv->Bot(), &commandcsvoice); + this->AddCommand(chanserv->Bot(), &commandcsdevoice); if (Me && Me->IsSynced()) OnUplinkSync(NULL); @@ -478,31 +481,31 @@ class CSModes : public Module { if (ModeManager::FindChannelModeByName(CMODE_OWNER)) { - this->AddCommand(ChanServ, &commandcsowner); - this->AddCommand(ChanServ, &commandcsdeowner); + this->AddCommand(chanserv->Bot(), &commandcsowner); + this->AddCommand(chanserv->Bot(), &commandcsdeowner); } if (ModeManager::FindChannelModeByName(CMODE_PROTECT)) { - this->AddCommand(ChanServ, &commandcsprotect); - this->AddCommand(ChanServ, &commandcsdeprotect); + this->AddCommand(chanserv->Bot(), &commandcsprotect); + this->AddCommand(chanserv->Bot(), &commandcsdeprotect); } if (ModeManager::FindChannelModeByName(CMODE_HALFOP)) { - this->AddCommand(ChanServ, &commandcshalfop); - this->AddCommand(ChanServ, &commandcsdehalfop); + this->AddCommand(chanserv->Bot(), &commandcshalfop); + this->AddCommand(chanserv->Bot(), &commandcsdehalfop); } } void OnServerDisconnect() { - this->DelCommand(ChanServ, &commandcsowner); - this->DelCommand(ChanServ, &commandcsdeowner); - this->DelCommand(ChanServ, &commandcsprotect); - this->DelCommand(ChanServ, &commandcsdeprotect); - this->DelCommand(ChanServ, &commandcshalfop); - this->DelCommand(ChanServ, &commandcsdehalfop); + this->DelCommand(chanserv->Bot(), &commandcsowner); + this->DelCommand(chanserv->Bot(), &commandcsdeowner); + this->DelCommand(chanserv->Bot(), &commandcsprotect); + this->DelCommand(chanserv->Bot(), &commandcsdeprotect); + this->DelCommand(chanserv->Bot(), &commandcshalfop); + this->DelCommand(chanserv->Bot(), &commandcsdehalfop); } }; diff --git a/modules/core/cs_register.cpp b/modules/core/cs_register.cpp index 09bcd812f..0682f045a 100644 --- a/modules/core/cs_register.cpp +++ b/modules/core/cs_register.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSRegister : public Command { @@ -117,7 +118,7 @@ class CommandCSRegister : public Command "NOTICE: In order to register a channel, you must have\n" "first registered your nickname. If you haven't,\n" "\002%s%s HELP\002 for information on how to do so."), - ChanServ->nick.c_str(), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->s_ChanServ.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -137,7 +138,10 @@ class CSRegister : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsregister); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsregister); } }; diff --git a/modules/core/cs_saset.cpp b/modules/core/cs_saset.cpp index 4a512c26d..b262ce14a 100644 --- a/modules/core/cs_saset.cpp +++ b/modules/core/cs_saset.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSASet : public Command { @@ -55,7 +56,7 @@ class CommandCSSASet : public Command for (std::vector<Anope::string>::const_iterator it = params.begin() + 2, it_end = params.end(); it != it_end; ++it) cmdparams += " " + *it; Log(LOG_ADMIN, u, this, ci) << params[1] << " " << cmdparams; - mod_run_cmd(ChanServ, u, NULL, c, params[1], cmdparams); + mod_run_cmd(chanserv->Bot(), u, NULL, c, params[1], cmdparams); } else { @@ -79,7 +80,7 @@ class CommandCSSASet : public Command for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) it->second->OnServHelp(source); source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + "particular option."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } else @@ -131,7 +132,10 @@ class CSSASet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcssaset); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcssaset); } }; diff --git a/modules/core/cs_saset_noexpire.cpp b/modules/core/cs_saset_noexpire.cpp index 8ff884d92..1026d8976 100644 --- a/modules/core/cs_saset_noexpire.cpp +++ b/modules/core/cs_saset_noexpire.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSASetNoexpire : public Command { @@ -68,14 +69,17 @@ class CSSetNoexpire : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SASET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetnoexpire); } ~CSSetNoexpire() { - Command *c = FindCommand(ChanServ, "SASET"); + Command *c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetnoexpire); } diff --git a/modules/core/cs_set.cpp b/modules/core/cs_set.cpp index 92ae43cfe..d395fad32 100644 --- a/modules/core/cs_set.cpp +++ b/modules/core/cs_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSet : public Command { @@ -59,7 +60,7 @@ class CommandCSSet : public Command Anope::string cmdparams = ci->name; for (std::vector<Anope::string>::const_iterator it = params.begin() + 2, it_end = params.end(); it != it_end; ++it) cmdparams += " " + *it; - mod_run_cmd(ChanServ, u, NULL, c, params[1], cmdparams); + mod_run_cmd(chanserv->Bot(), u, NULL, c, params[1], cmdparams); } else { @@ -83,7 +84,7 @@ class CommandCSSet : public Command for (subcommand_map::iterator it = this->subcommands.begin(), it_end = this->subcommands.end(); it != it_end; ++it) it->second->OnServHelp(source); source.Reply(_("Type \002%s%s HELP SET \037option\037\002 for more information on a\n" - "particular option."), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + "particular option."), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } else @@ -135,7 +136,10 @@ class CSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsset); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + this->AddCommand(chanserv->Bot(), &commandcsset); } }; diff --git a/modules/core/cs_set_bantype.cpp b/modules/core/cs_set_bantype.cpp index 1b0c2eb7d..35b8c6c14 100644 --- a/modules/core/cs_set_bantype.cpp +++ b/modules/core/cs_set_bantype.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetBanType : public Command { @@ -88,22 +89,25 @@ class CSSetBanType : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetbantype); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetbantype); } ~CSSetBanType() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetbantype); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetbantype); } diff --git a/modules/core/cs_set_description.cpp b/modules/core/cs_set_description.cpp index dcd7eb24b..a65f4511b 100644 --- a/modules/core/cs_set_description.cpp +++ b/modules/core/cs_set_description.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetDescription : public Command { @@ -75,22 +76,25 @@ class CSSetDescription : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetdescription); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetdescription); } ~CSSetDescription() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetdescription); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetdescription); } diff --git a/modules/core/cs_set_founder.cpp b/modules/core/cs_set_founder.cpp index 200d32e95..27d6f86fc 100644 --- a/modules/core/cs_set_founder.cpp +++ b/modules/core/cs_set_founder.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetFounder : public Command { @@ -111,22 +112,25 @@ class CSSetFounder : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetfounder); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetfounder); } ~CSSetFounder() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetfounder); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetfounder); } diff --git a/modules/core/cs_set_keeptopic.cpp b/modules/core/cs_set_keeptopic.cpp index 049ff1b5f..89491d418 100644 --- a/modules/core/cs_set_keeptopic.cpp +++ b/modules/core/cs_set_keeptopic.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetKeepTopic : public Command { @@ -51,7 +52,7 @@ class CommandCSSetKeepTopic : public Command "channel. When \002topic retention\002 is set, the topic for the\n" "channel will be remembered by %s even after the\n" "last user leaves the channel, and will be restored the\n" - "next time the channel is created."), this->name.c_str(), ChanServ->nick.c_str()); + "next time the channel is created."), this->name.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -85,22 +86,25 @@ class CSSetKeepTopic : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetkeeptopic); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetkeeptopic); } ~CSSetKeepTopic() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetkeeptopic); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetkeeptopic); } diff --git a/modules/core/cs_set_opnotice.cpp b/modules/core/cs_set_opnotice.cpp index 6e0a5d49b..0d71b42c4 100644 --- a/modules/core/cs_set_opnotice.cpp +++ b/modules/core/cs_set_opnotice.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetOpNotice : public Command { @@ -50,7 +51,7 @@ class CommandCSSetOpNotice : public Command "Enables or disables the \002op-notice\002 option for a channel.\n" "When \002op-notice\002 is set, %s will send a notice to the\n" "channel whenever the \002OP\002 or \002DEOP\002 commands are used for a user\n" - "in the channel."), this->name.c_str(), ChanServ->nick.c_str()); + "in the channel."), this->name.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -84,22 +85,25 @@ class CSSetOpNotice : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetopnotice); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetopnotice); } ~CSSetOpNotice() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetopnotice); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetopnotice); } diff --git a/modules/core/cs_set_peace.cpp b/modules/core/cs_set_peace.cpp index 4b89338ee..51c7bc827 100644 --- a/modules/core/cs_set_peace.cpp +++ b/modules/core/cs_set_peace.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetPeace : public Command { @@ -50,7 +51,7 @@ class CommandCSSetPeace : public Command "Enables or disables the \002peace\002 option for a channel.\n" "When \002peace\002 is set, a user won't be able to kick,\n" "ban or remove a channel status of a user that has\n" - "a level superior or equal to his via %s commands."), this->name.c_str(), ChanServ->nick.c_str()); + "a level superior or equal to his via %s commands."), this->name.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -84,22 +85,25 @@ class CSSetPeace : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetpeace); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetpeace); } ~CSSetPeace() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetpeace); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetpeace); } diff --git a/modules/core/cs_set_persist.cpp b/modules/core/cs_set_persist.cpp index 291203ea2..683bd4481 100644 --- a/modules/core/cs_set_persist.cpp +++ b/modules/core/cs_set_persist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetPersist : public Command { @@ -51,9 +52,9 @@ class CommandCSSetPersist : public Command */ if (!ci->bi && !cm) { - ChanServ->Assign(NULL, ci); - if (!ci->c->FindUser(ChanServ)) - ChanServ->Join(ci->c); + chanserv->Bot()->Assign(NULL, ci); + if (!ci->c->FindUser(chanserv->Bot())) + chanserv->Bot()->Join(ci->c); } /* Set the perm mode */ @@ -90,7 +91,7 @@ class CommandCSSetPersist : public Command */ if (!cm && Config->s_BotServ.empty() && ci->bi) /* Unassign bot */ - ChanServ->UnAssign(NULL, ci); + chanserv->Bot()->UnAssign(NULL, ci); } source.Reply(_("Channel \002%s\002 is no longer persistant."), ci->name.c_str()); @@ -156,22 +157,25 @@ class CSSetPersist : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetpeace); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetpeace); } ~CSSetPersist() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetpeace); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetpeace); } diff --git a/modules/core/cs_set_private.cpp b/modules/core/cs_set_private.cpp index 90618bfac..42f7a2261 100644 --- a/modules/core/cs_set_private.cpp +++ b/modules/core/cs_set_private.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetPrivate : public Command { @@ -49,7 +50,7 @@ class CommandCSSetPrivate : public Command " \n" "Enables or disables the \002private\002 option for a channel.\n" "When \002private\002 is set, a \002%s%s LIST\002 will not\n" - "include the channel in any lists."), this->name.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + "include the channel in any lists."), this->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -83,22 +84,25 @@ class CSSetPrivate : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetprivate); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetprivate); } ~CSSetPrivate() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetprivate); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetprivate); } diff --git a/modules/core/cs_set_restricted.cpp b/modules/core/cs_set_restricted.cpp index cc149449c..93fe0d023 100644 --- a/modules/core/cs_set_restricted.cpp +++ b/modules/core/cs_set_restricted.cpp @@ -11,6 +11,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetRestricted : public Command { @@ -86,22 +87,25 @@ class CSSetRestricted : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetrestricted); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetrestricted); } ~CSSetRestricted() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetrestricted); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetrestricted); } diff --git a/modules/core/cs_set_secure.cpp b/modules/core/cs_set_secure.cpp index 25977285c..5fb8d9a7c 100644 --- a/modules/core/cs_set_secure.cpp +++ b/modules/core/cs_set_secure.cpp @@ -12,13 +12,14 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetSecure : public Command { public: CommandCSSetSecure(const Anope::string &cpermission = "") : Command("SECURE", 2, 2, cpermission) { - this->SetDesc(Anope::printf(_("Activate %s's security features"), ChanServ->nick.c_str())); + this->SetDesc(Anope::printf(_("Activate %s's security features"), Config->s_ChanServ.c_str())); } CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -51,7 +52,7 @@ class CommandCSSetSecure : public Command "channel. When \002SECURE\002 is set, only users who have\n" "registered their nicknames with %s and IDENTIFY'd\n" "with their password will be given access to the channel\n" - "as controlled by the access list."), this->name.c_str(), NickServ->nick.c_str(), NickServ->nick.c_str()); + "as controlled by the access list."), this->name.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -85,22 +86,25 @@ class CSSetSecure : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetsecure); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetsecure); } ~CSSetSecure() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetsecure); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetsecure); } diff --git a/modules/core/cs_set_securefounder.cpp b/modules/core/cs_set_securefounder.cpp index 44ac0528d..3daa67924 100644 --- a/modules/core/cs_set_securefounder.cpp +++ b/modules/core/cs_set_securefounder.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetSecureFounder : public Command { @@ -92,22 +93,25 @@ class CSSetSecureFounder : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetsecurefounder); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetsecurefounder); } ~CSSetSecureFounder() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetsecurefounder); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetsecurefounder); } diff --git a/modules/core/cs_set_secureops.cpp b/modules/core/cs_set_secureops.cpp index 21fefdb61..773ae8ffd 100644 --- a/modules/core/cs_set_secureops.cpp +++ b/modules/core/cs_set_secureops.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetSecureOps : public Command { @@ -83,22 +84,25 @@ class CSSetSecureOps : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetsecureops); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetsecureops); } ~CSSetSecureOps() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetsecureops); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetsecureops); } diff --git a/modules/core/cs_set_signkick.cpp b/modules/core/cs_set_signkick.cpp index 3ca967af9..50c0d74f9 100644 --- a/modules/core/cs_set_signkick.cpp +++ b/modules/core/cs_set_signkick.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetSignKick : public Command { @@ -64,7 +65,7 @@ class CommandCSSetSignKick : public Command "If you use \002LEVEL\002, those who have a level that is superior \n" "or equal to the SIGNKICK level on the channel won't have their \n" "kicks signed. See \002%s%s HELP LEVELS\002 for more information."), this->name.c_str(), - ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -98,22 +99,25 @@ class CSSetSignKick : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetsignkick); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetsignkick); } ~CSSetSignKick() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetsignkick); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetsignkick); } diff --git a/modules/core/cs_set_successor.cpp b/modules/core/cs_set_successor.cpp index b80493432..7c3b156e3 100644 --- a/modules/core/cs_set_successor.cpp +++ b/modules/core/cs_set_successor.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetSuccessor : public Command { @@ -118,22 +119,25 @@ class CSSetSuccessor : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetsuccessor); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetsuccessor); } ~CSSetSuccessor() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetsuccessor); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetsuccessor); } diff --git a/modules/core/cs_set_topiclock.cpp b/modules/core/cs_set_topiclock.cpp index 434d9961d..add079c52 100644 --- a/modules/core/cs_set_topiclock.cpp +++ b/modules/core/cs_set_topiclock.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetTopicLock : public Command { @@ -50,7 +51,7 @@ class CommandCSSetTopicLock : public Command "Enables or disables the \002topic lock\002 option for a channel.\n" "When \002topic lock\002 is set, %s will not allow the\n" "channel topic to be changed except via the \002TOPIC\002\n" - "command."), this->name.c_str(), ChanServ->nick.c_str()); + "command."), this->name.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -84,22 +85,25 @@ class CSSetTopicLock : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssettopiclock); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasettopiclock); } ~CSSetTopicLock() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssettopiclock); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasettopiclock); } diff --git a/modules/core/cs_set_xop.cpp b/modules/core/cs_set_xop.cpp index b4c2657d6..2f423e098 100644 --- a/modules/core/cs_set_xop.cpp +++ b/modules/core/cs_set_xop.cpp @@ -11,6 +11,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" #define CHECKLEV(lev) (ci->levels[(lev)] != ACCESS_INVALID && access->level >= ci->levels[(lev)]) @@ -138,22 +139,25 @@ class CSSetXOP : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(ChanServ, "SET"); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandcssetxop); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandcssasetxop); } ~CSSetXOP() { - Command *c = FindCommand(ChanServ, "SET"); + Command *c = FindCommand(chanserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandcssetxop); - c = FindCommand(ChanServ, "SASET"); + c = FindCommand(chanserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandcssasetxop); } diff --git a/modules/core/cs_status.cpp b/modules/core/cs_status.cpp index d45c09ab8..0ff2db90a 100644 --- a/modules/core/cs_status.cpp +++ b/modules/core/cs_status.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSStatus : public Command { @@ -66,7 +67,7 @@ class CSStatus : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsstatus); + this->AddCommand(chanserv->Bot(), &commandcsstatus); } }; diff --git a/modules/core/cs_suspend.cpp b/modules/core/cs_suspend.cpp index 7475f2e3a..37fae7723 100644 --- a/modules/core/cs_suspend.cpp +++ b/modules/core/cs_suspend.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSuspend : public Command { @@ -153,8 +154,8 @@ class CSSuspend : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcssuspend); - this->AddCommand(ChanServ, &commandcsunsuspend); + this->AddCommand(chanserv->Bot(), &commandcssuspend); + this->AddCommand(chanserv->Bot(), &commandcsunsuspend); } }; diff --git a/modules/core/cs_topic.cpp b/modules/core/cs_topic.cpp index c832d0ca4..52fecd7a4 100644 --- a/modules/core/cs_topic.cpp +++ b/modules/core/cs_topic.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSTopic : public Command { @@ -58,7 +59,7 @@ class CommandCSTopic : public Command "for more information.\n" " \n" "By default, limited to those with founder access on the\n" - "channel."), ChanServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + "channel."), Config->s_ChanServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -78,7 +79,7 @@ class CSTopic : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcstopic); + this->AddCommand(chanserv->Bot(), &commandcstopic); } }; diff --git a/modules/core/cs_unban.cpp b/modules/core/cs_unban.cpp index 35b1244e4..be567db9a 100644 --- a/modules/core/cs_unban.cpp +++ b/modules/core/cs_unban.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSUnban : public Command { @@ -66,7 +67,7 @@ class CommandCSUnban : public Command "user from entering the given channel. \n" " \n" "By default, limited to AOPs or those with level 5 and above\n" - "on the channel."), ChanServ->nick.c_str()); + "on the channel."), Config->s_ChanServ.c_str()); return true; } @@ -86,7 +87,7 @@ class CSUnban : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcsunban); + this->AddCommand(chanserv->Bot(), &commandcsunban); } }; diff --git a/modules/core/cs_xop.cpp b/modules/core/cs_xop.cpp index 22ffb4f68..3b65e035f 100644 --- a/modules/core/cs_xop.cpp +++ b/modules/core/cs_xop.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" enum { @@ -449,8 +450,8 @@ class CommandCSQOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -513,8 +514,8 @@ class CommandCSAOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -575,8 +576,8 @@ class CommandCSHOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -639,8 +640,8 @@ class CommandCSSOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -702,8 +703,8 @@ class CommandCSVOP : public XOPBase "\002%s%s HELP ACCESS\002 for information about the access list,\n" "and \002%s%s HELP SET XOP\002 to know how to toggle between \n" "the access list and xOP list systems."), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str(), - Config->UseStrictPrivMsgString.c_str(), ChanServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str(), + Config->UseStrictPrivMsgString.c_str(), Config->s_ChanServ.c_str()); return true; } @@ -727,9 +728,9 @@ class CSXOP : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(ChanServ, &commandcssop); - this->AddCommand(ChanServ, &commandcsaop); - this->AddCommand(ChanServ, &commandcsvop); + this->AddCommand(chanserv->Bot(), &commandcssop); + this->AddCommand(chanserv->Bot(), &commandcsaop); + this->AddCommand(chanserv->Bot(), &commandcsvop); if (Me && Me->IsSynced()) OnUplinkSync(NULL); @@ -741,15 +742,15 @@ class CSXOP : public Module void OnUplinkSync(Server *) { if (ModeManager::FindChannelModeByName(CMODE_OWNER)) - this->AddCommand(ChanServ, &commandcsqop); + this->AddCommand(chanserv->Bot(), &commandcsqop); if (ModeManager::FindChannelModeByName(CMODE_HALFOP)) - this->AddCommand(ChanServ, &commandcshop); + this->AddCommand(chanserv->Bot(), &commandcshop); } void OnServerDisconnect() { - this->DelCommand(ChanServ, &commandcsqop); - this->DelCommand(ChanServ, &commandcshop); + this->DelCommand(chanserv->Bot(), &commandcsqop); + this->DelCommand(chanserv->Bot(), &commandcshop); } }; diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp index e4678a8d9..4ab248f76 100644 --- a/modules/core/db_plain.cpp +++ b/modules/core/db_plain.cpp @@ -11,9 +11,12 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" +#include "os_session.h" Anope::string DatabaseFile; std::stringstream db_buffer; +service_reference<SessionService> SessionInterface("session"); /** Enum used for what METADATA type we are reading */ @@ -317,16 +320,13 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms) XLine *x = NULL; if (params[0].equals_ci("SNLINE") && SNLine) - x = SNLine->Add(NULL, NULL, mask, expires, reason); + x = SNLine->Add(mask, by, expires, reason); else if (params[0].equals_ci("SQLINE") && SQLine) - x = SQLine->Add(NULL, NULL, mask, expires, reason); + x = SQLine->Add(mask, by, expires, reason); else if (params[0].equals_ci("SZLINE") && SZLine) - x = SZLine->Add(NULL, NULL, mask, expires, reason); + x = SZLine->Add(mask, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } else if (params[0].equals_ci("AKILL") && SGLine) { @@ -337,12 +337,9 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms) time_t expires = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0; Anope::string reason = params[6]; - XLine *x = SGLine->Add(NULL, NULL, user + "@" + host, expires, reason); + XLine *x = SGLine->Add(user + "@" + host, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } else if (params[0].equals_ci("EXCEPTION")) { @@ -353,7 +350,7 @@ static void LoadOperInfo(const std::vector<Anope::string> ¶ms) exception->time = params[4].is_pos_number_only() ? convertTo<time_t>(params[4]) : 0; exception->expires = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : 0; exception->reason = params[6]; - exceptions.push_back(exception); + SessionInterface->AddException(exception); } } @@ -382,7 +379,7 @@ class DBPlain : public Module Implementation i[] = { I_OnReload, I_OnDatabaseRead, I_OnLoadDatabase, I_OnDatabaseReadMetadata, I_OnSaveDatabase, I_OnModuleLoad }; ModuleManager::Attach(i, this, 6); - OnReload(true); + OnReload(); LastDay = 0; } @@ -412,7 +409,8 @@ class DBPlain : public Module Log(LOG_DEBUG) << "db_plain: Attemping to rename " << DatabaseFile << " to " << newname; if (rename(DatabaseFile.c_str(), newname.c_str())) { - ircdproto->SendGlobops(OperServ, "Unable to backup database!"); + if (operserv) + ircdproto->SendGlobops(operserv->Bot(), "Unable to backup database!"); Log() << "Unable to back up database!"; if (!Config->NoBackupOkay) @@ -432,7 +430,7 @@ class DBPlain : public Module } } - void OnReload(bool) + void OnReload() { ConfigReader config; DatabaseFile = config.ReadValue("db_plain", "database", "anope.db", 0); @@ -494,14 +492,12 @@ class DBPlain : public Module Memo *m = new Memo; m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; m->sender = params[1]; - for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT") || params[j].equals_ci("NOTIFYS"); ++j) + for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j) { if (params[j].equals_ci("UNREAD")) m->SetFlag(MF_UNREAD); else if (params[j].equals_ci("RECEIPT")) m->SetFlag(MF_RECEIPT); - else if (params[j].equals_ci("NOTIFYS")) - m->SetFlag(MF_NOTIFYS); } m->text = params[params.size() - 1]; nc->memos.memos.push_back(m); @@ -633,14 +629,12 @@ class DBPlain : public Module Memo *m = new Memo; m->time = params[0].is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; m->sender = params[1]; - for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT") || params[j].equals_ci("NOTIFYS"); ++j) + for (unsigned j = 2; params[j].equals_ci("UNREAD") || params[j].equals_ci("RECEIPT"); ++j) { if (params[j].equals_ci("UNREAD")) m->SetFlag(MF_UNREAD); else if (params[j].equals_ci("RECEIPT")) m->SetFlag(MF_RECEIPT); - else if (params[j].equals_ci("NOTIFYS")) - m->SetFlag(MF_NOTIFYS); } m->text = params[params.size() - 1]; ci->memos.memos.push_back(m); @@ -754,8 +748,6 @@ class DBPlain : public Module db_buffer << " UNREAD"; if (mi->memos[k]->HasFlag(MF_RECEIPT)) db_buffer << " RECEIPT"; - if (mi->memos[k]->HasFlag(MF_NOTIFYS)) - db_buffer << " NOTIFYS"; db_buffer << " :" << mi->memos[k]->text << endl; } for (unsigned k = 0, end = mi->ignores.size(); k < end; ++k) @@ -848,8 +840,6 @@ class DBPlain : public Module db_buffer << " UNREAD"; if (memos->memos[k]->HasFlag(MF_RECEIPT)) db_buffer << " RECEIPT"; - if (memos->memos[k]->HasFlag(MF_NOTIFYS)) - db_buffer << " NOTIFYS"; db_buffer << " :" << memos->memos[k]->text << endl; } for (unsigned k = 0, end = memos->ignores.size(); k < end; ++k) @@ -906,7 +896,7 @@ class DBPlain : public Module db_buffer << "OS SZLINE " << x->Mask << " " << x->By << " " << x->Created << " " << x->Expires << " :" << x->Reason << endl; } - for (std::vector<Exception *>::iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) + for (SessionService::ExceptionVector::iterator it = SessionInterface->GetExceptions().begin(); it != SessionInterface->GetExceptions().end(); ++it) { Exception *e = *it; db_buffer << "OS EXCEPTION " << e->mask << " " << e->limit << " " << e->who << " " << e->time << " " << e->expires << " " << e->reason << endl; diff --git a/modules/core/os_global.cpp b/modules/core/gl_global.cpp index 08fda8fc7..e03c3f788 100644 --- a/modules/core/os_global.cpp +++ b/modules/core/gl_global.cpp @@ -1,4 +1,4 @@ -/* OperServ core functions +/* Global core functions * * (C) 2003-2011 Anope Team * Contact us at team@anope.org @@ -12,11 +12,12 @@ /*************************************************************************/ #include "module.h" +#include "global.h" -class CommandOSGlobal : public Command +class CommandGLGlobal : public Command { public: - CommandOSGlobal() : Command("GLOBAL", 1, 1, "operserv/global") + CommandGLGlobal() : Command("GLOBAL", 1, 1, "global/global") { this->SetDesc(_("Send a message to all users")); } @@ -27,7 +28,7 @@ class CommandOSGlobal : public Command const Anope::string &msg = params[0]; Log(LOG_ADMIN, u, this); - oper_global(u->nick, "%s", msg.c_str()); + global->SendGlobal(global->Bot(), u->nick, msg); return MOD_CONT; } @@ -36,7 +37,7 @@ class CommandOSGlobal : public Command source.Reply(_("Syntax: \002GLOBAL \037message\037\002\n" " \n" "Allows Administrators to send messages to all users on the \n" - "network. The message will be sent from the nick \002%s\002."), Config->s_GlobalNoticer.c_str()); + "network. The message will be sent from the nick \002%s\002."), Config->s_Global.c_str()); return true; } @@ -46,22 +47,21 @@ class CommandOSGlobal : public Command } }; -class OSGlobal : public Module +class GLGlobal : public Module { - CommandOSGlobal commandosglobal; + CommandGLGlobal commandglglobal; public: - OSGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { this->SetAuthor("Anope"); this->SetType(CORE); - if (Config->s_GlobalNoticer.empty()) + if (Config->s_Global.empty()) throw ModuleException("Global is disabled"); - // Maybe we should put this ON Global? - this->AddCommand(OperServ, &commandosglobal); + this->AddCommand(global->Bot(), &commandglglobal); } }; -MODULE_INIT(OSGlobal) +MODULE_INIT(GLGlobal) diff --git a/modules/core/gl_help.cpp b/modules/core/gl_help.cpp new file mode 100644 index 000000000..ea67a8efc --- /dev/null +++ b/modules/core/gl_help.cpp @@ -0,0 +1,58 @@ +/* Global core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "global.h" + +class CommandGLHelp : public Command +{ + public: + CommandGLHelp() : Command("HELP", 1, 1) + { + this->SetDesc(_("Displays this list and give information about commands")); + } + + CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + mod_help_cmd(global->Bot(), source.u, NULL, params[0]); + return MOD_CONT; + } + + void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + { + User *u = source.u; + source.Reply(_("%s commands:"), Config->s_Global.c_str()); + for (CommandMap::const_iterator it = global->Bot()->Commands.begin(), it_end = global->Bot()->Commands.end(); it != it_end; ++it) + if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) + it->second->OnServHelp(source); + } +}; + +class GLHelp : public Module +{ + CommandGLHelp commandoshelp; + + public: + GLHelp(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + if (!global) + throw ModuleException("Global is not loaded!"); + + this->AddCommand(global->Bot(), &commandoshelp); + } +}; + +MODULE_INIT(GLHelp) diff --git a/modules/core/gl_main.cpp b/modules/core/gl_main.cpp new file mode 100644 index 000000000..84eea0e20 --- /dev/null +++ b/modules/core/gl_main.cpp @@ -0,0 +1,111 @@ +/* Global core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "global.h" + +static BotInfo *Global = NULL; + +class MyGlobalService : public GlobalService +{ + void ServerGlobal(Server *s, const Anope::string &message) + { + if (s != Me && !s->HasFlag(SERVER_JUPED)) + notice_server(Config->s_Global, s, "%s", message.c_str()); + for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) + this->ServerGlobal(s->GetLinks()[i], message); + } + + public: + MyGlobalService(Module *m) : GlobalService(m) { } + + BotInfo *Bot() + { + return Global; + } + + void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) + { + if (Me->GetLinks().empty()) + return; + + Anope::string rmessage; + + if (!source.empty() && !Config->AnonymousGlobal) + rmessage = "[" + source + "] " + message; + else + rmessage = message; + + this->ServerGlobal(Me->GetLinks().front(), rmessage); + } +}; + +class GlobalCore : public Module +{ + MyGlobalService myglobal; + + public: + GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), myglobal(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + Implementation i[] = { I_OnPreRestart, I_OnPreShutdown, I_OnNewServer }; + ModuleManager::Attach(i, this, 3); + + ModuleManager::RegisterService(&this->myglobal); + + Global = new BotInfo(Config->s_Global, Config->ServiceUser, Config->ServiceHost, Config->desc_Global); + Global->SetFlag(BI_CORE); + + spacesepstream coreModules(Config->GlobalCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~GlobalCore() + { + spacesepstream coreModules(Config->GlobalCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete Global; + } + + void OnPreRestart() + { + if (Config->GlobalOnCycle) + global->SendGlobal(global->Bot(), "", Config->GlobalOnCycleMessage); + } + + void OnPreShutdown() + { + if (Config->GlobalOnCycle) + global->SendGlobal(global->Bot(), "", Config->GlobalOnCycleMessage); + } + + void OnNewServer(Server *s) + { + if (Config->GlobalOnCycle && !Config->GlobalOnCycleUP.empty()) + notice_server(Config->s_Global, s, "%s", Config->GlobalOnCycleUP.c_str()); + } +}; + +MODULE_INIT(GlobalCore) + diff --git a/modules/core/global.h b/modules/core/global.h new file mode 100644 index 000000000..977a327e4 --- /dev/null +++ b/modules/core/global.h @@ -0,0 +1,22 @@ +#ifndef GLOBAL_H +#define GLOBAL_H + +class GlobalService : public Service +{ + public: + GlobalService(Module *m) : Service(m, "Global") { } + + virtual BotInfo *Bot() = 0; + + /** Send out a global message to all users + * @param sender Our client which should send the global + * @param source The sender of the global + * @param message The message + */ + virtual void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) = 0; +}; + +static service_reference<GlobalService> global("Global"); + +#endif // GLOBAL_H + diff --git a/modules/core/hostserv.h b/modules/core/hostserv.h new file mode 100644 index 000000000..6f491a30e --- /dev/null +++ b/modules/core/hostserv.h @@ -0,0 +1,17 @@ +#ifndef HOSTSERV_H +#define HOSTSERV_H + +class HostServService : public Service +{ + public: + HostServService(Module *m) : Service(m, "HostServ") { } + + virtual BotInfo *Bot() = 0; + + virtual void Sync(NickAlias *na) = 0; +}; + +static service_reference<HostServService> hostserv("HostServ"); + +#endif // HOSTSERV_H + diff --git a/modules/core/hs_del.cpp b/modules/core/hs_del.cpp index 6e5458538..bdd1bc525 100644 --- a/modules/core/hs_del.cpp +++ b/modules/core/hs_del.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSDel : public Command { @@ -68,7 +69,10 @@ class HSDel : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhsdel); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsdel); } }; diff --git a/modules/core/hs_delall.cpp b/modules/core/hs_delall.cpp index 5b32ea191..905fe4ec3 100644 --- a/modules/core/hs_delall.cpp +++ b/modules/core/hs_delall.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSDelAll : public Command { @@ -73,7 +74,10 @@ class HSDelAll : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhsdelall); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsdelall); } }; diff --git a/modules/core/hs_group.cpp b/modules/core/hs_group.cpp index 3bb42ee94..9525b4646 100644 --- a/modules/core/hs_group.cpp +++ b/modules/core/hs_group.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSGroup : public Command { @@ -27,7 +28,7 @@ class CommandHSGroup : public Command NickAlias *na = findnick(u->nick); if (na && u->Account() == na->nc && na->hostinfo.HasVhost()) { - HostServSyncVhosts(na); + hostserv->Sync(na); if (!na->hostinfo.GetIdent().empty()) source.Reply(_("All vhost's in the group \002%s\002 have been set to \002%s\002@\002%s\002"), u->Account()->display.c_str(), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); else @@ -60,7 +61,10 @@ class HSGroup : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhsgroup); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsgroup); } }; diff --git a/modules/core/hs_help.cpp b/modules/core/hs_help.cpp index bcf8fd28d..53b40ef89 100644 --- a/modules/core/hs_help.cpp +++ b/modules/core/hs_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSHelp : public Command { @@ -24,7 +25,7 @@ class CommandHSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(HostServ, source.u, NULL, params[0]); + mod_help_cmd(hostserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } @@ -32,7 +33,7 @@ class CommandHSHelp : public Command { User *u = source.u; source.Reply(_("%s commands:"), Config->s_HostServ.c_str()); - for (CommandMap::const_iterator it = HostServ->Commands.begin(), it_end = HostServ->Commands.end(); it != it_end; ++it) + for (CommandMap::const_iterator it = hostserv->Bot()->Commands.begin(), it_end = hostserv->Bot()->Commands.end(); it != it_end; ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); } @@ -48,7 +49,10 @@ class HSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhshelp); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhshelp); } }; diff --git a/modules/core/hs_list.cpp b/modules/core/hs_list.cpp index 61fee9fcc..a85c2e8b2 100644 --- a/modules/core/hs_list.cpp +++ b/modules/core/hs_list.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSList : public Command { @@ -128,7 +129,10 @@ class HSList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhslist); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhslist); } }; diff --git a/modules/core/hs_main.cpp b/modules/core/hs_main.cpp new file mode 100644 index 000000000..c4b1433c8 --- /dev/null +++ b/modules/core/hs_main.cpp @@ -0,0 +1,123 @@ +/* HostServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "hostserv.h" + +static BotInfo *HostServ = NULL; + +class MyHostServService : public HostServService +{ + public: + MyHostServService(Module *m) : HostServService(m) { } + + BotInfo *Bot() + { + return HostServ; + } + + void Sync(NickAlias *na) + { + if (!na || !na->hostinfo.HasVhost()) + return; + + for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) + { + NickAlias *nick = *it; + nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); + } + } +}; + +class HostServCore : public Module +{ + MyHostServService myhostserv; + + public: + HostServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), myhostserv(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + if (!ircd->vhost) + throw ModuleException("Your IRCd does not suppor vhosts"); + + ModuleManager::RegisterService(&this->myhostserv); + + HostServ = new BotInfo(Config->s_HostServ, Config->ServiceUser, Config->ServiceHost, Config->desc_HostServ); + HostServ->SetFlag(BI_CORE); + + Implementation i[] = { I_OnNickIdentify, I_OnNickUpdate }; + ModuleManager::Attach(i, this, 2); + + spacesepstream coreModules(Config->HostCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~HostServCore() + { + spacesepstream coreModules(Config->HostCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete HostServ; + } + + void OnNickIdentify(User *u) + { + HostInfo *ho = NULL; + NickAlias *na = findnick(u->nick); + if (na && na->hostinfo.HasVhost()) + ho = &na->hostinfo; + else + { + na = findnick(u->Account()->display); + if (na && na->hostinfo.HasVhost()) + ho = &na->hostinfo; + } + if (ho == NULL) + return; + + if (u->vhost.empty() || !u->vhost.equals_cs(na->hostinfo.GetHost()) || (!na->hostinfo.GetIdent().empty() && !u->GetVIdent().equals_cs(na->hostinfo.GetIdent()))) + { + ircdproto->SendVhost(u, na->hostinfo.GetIdent(), na->hostinfo.GetHost()); + if (ircd->vhost) + { + u->vhost = na->hostinfo.GetHost(); + u->UpdateHost(); + } + if (ircd->vident && !na->hostinfo.GetIdent().empty()) + u->SetVIdent(na->hostinfo.GetIdent()); + + if (!na->hostinfo.GetIdent().empty()) + u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); + else + u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->hostinfo.GetHost().c_str()); + } + } + + void OnNickUpdate(User *u) + { + this->OnNickIdentify(u); + } +}; + +MODULE_INIT(HostServCore) + diff --git a/modules/core/hs_off.cpp b/modules/core/hs_off.cpp index dfbeaa2f8..d06d125fa 100644 --- a/modules/core/hs_off.cpp +++ b/modules/core/hs_off.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSOff : public Command { @@ -58,7 +59,10 @@ class HSOff : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhsoff); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsoff); } }; diff --git a/modules/core/hs_on.cpp b/modules/core/hs_on.cpp index 8838d6b62..43fd06b04 100644 --- a/modules/core/hs_on.cpp +++ b/modules/core/hs_on.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSOn : public Command { @@ -68,7 +69,10 @@ class HSOn : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhson); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhson); } }; diff --git a/modules/core/hs_set.cpp b/modules/core/hs_set.cpp index 9f79fedd7..9521bc57e 100644 --- a/modules/core/hs_set.cpp +++ b/modules/core/hs_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSSet : public Command { @@ -122,7 +123,10 @@ class HSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhsset); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsset); } }; diff --git a/modules/core/hs_setall.cpp b/modules/core/hs_setall.cpp index 18f24d359..52061203f 100644 --- a/modules/core/hs_setall.cpp +++ b/modules/core/hs_setall.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "hostserv.h" class CommandHSSetAll : public Command { @@ -92,7 +93,7 @@ class CommandHSSetAll : public Command Log(LOG_ADMIN, u, this) << "to set the vhost for all nicks in group " << na->nc->display << " to " << (!vIdent.empty() ? vIdent + "@" : "") << hostmask; na->hostinfo.SetVhost(vIdent, hostmask, u->nick); - HostServSyncVhosts(na); + hostserv->Sync(na); FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); if (!vIdent.empty()) source.Reply(_("vhost for group \002%s\002 set to \002%s\002@\002%s\002."), nick.c_str(), vIdent.c_str(), hostmask.c_str()); @@ -129,7 +130,10 @@ class HSSetAll : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(HostServ, &commandhssetall); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhssetall); } }; diff --git a/modules/core/memoserv.h b/modules/core/memoserv.h new file mode 100644 index 000000000..3252a2a2b --- /dev/null +++ b/modules/core/memoserv.h @@ -0,0 +1,44 @@ +#ifndef MEMOSERV_H +#define MEMOSERV_H + +class MemoServService : public Service +{ + public: + enum MemoResult + { + MEMO_SUCCESS, + MEMO_INVALID_TARGET, + MEMO_TOO_FAST, + MEMO_TARGET_FULL + }; + + MemoServService(Module *m) : Service(m, "MemoServ") { } + + virtual BotInfo *Bot() = 0; + + /** Retrieve the memo info for a nick or channel + * @param target Target + * @param ischan Set to true if target is a channel + * @param isforbid Set to true if the target is forbidden + * @return A memoinfo structure or NULL + */ + virtual MemoInfo *GetMemoInfo(const Anope::string &target, bool &ischan, bool &isforbid) = 0; + + /** Sends a memo. + * @param source The source of the memo, can be anythin. + * @param target The target of the memo, nick or channel. + * @param message Memo text + * @param force true to force the memo, restrictions/delays etc are not checked + */ + virtual MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force = false) = 0; + + /** Check for new memos and notify the user if there are any + * @param u The user + */ + virtual void Check(User *u) = 0; +}; + +static service_reference<MemoServService> memoserv("MemoServ"); + +#endif // MEMOSERV_H + diff --git a/modules/core/ms_cancel.cpp b/modules/core/ms_cancel.cpp index d5bedc8fb..1cfd20767 100644 --- a/modules/core/ms_cancel.cpp +++ b/modules/core/ms_cancel.cpp @@ -12,8 +12,7 @@ /*************************************************************************/ #include "module.h" - -void myMemoServHelp(User *u); +#include "memoserv.h" class CommandMSCancel : public Command { @@ -30,9 +29,9 @@ class CommandMSCancel : public Command const Anope::string &nname = params[0]; bool ischan, isforbid; - MemoInfo *mi; + MemoInfo *mi = memoserv->GetMemoInfo(nname, ischan, isforbid); - if (!(mi = getmemoinfo(nname, ischan, isforbid))) + if (mi == NULL) { if (isforbid) source.Reply(ischan ? _(CHAN_X_FORBIDDEN) : _(NICK_X_FORBIDDEN), nname.c_str()); @@ -42,7 +41,7 @@ class CommandMSCancel : public Command else { for (int i = mi->memos.size() - 1; i >= 0; --i) - if (mi->memos[i]->HasFlag(MF_UNREAD) && u->Account()->display.equals_ci(mi->memos[i]->sender) && !mi->memos[i]->HasFlag(MF_NOTIFYS)) + if (mi->memos[i]->HasFlag(MF_UNREAD) && u->Account()->display.equals_ci(mi->memos[i]->sender)) { FOREACH_MOD(I_OnMemoDel, OnMemoDel(findnick(nname)->nc, mi, mi->memos[i])); mi->Del(mi->memos[i]); @@ -80,7 +79,10 @@ class MSCancel : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmscancel); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmscancel); } }; diff --git a/modules/core/ms_check.cpp b/modules/core/ms_check.cpp index 8134b98a7..34adcf2c4 100644 --- a/modules/core/ms_check.cpp +++ b/modules/core/ms_check.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSCheck : public Command { @@ -92,7 +93,10 @@ class MSCheck : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmscheck); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmscheck); } }; diff --git a/modules/core/ms_del.cpp b/modules/core/ms_del.cpp index 1f0a038ee..077b5bdba 100644 --- a/modules/core/ms_del.cpp +++ b/modules/core/ms_del.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class MemoDelCallback : public NumberList { @@ -160,7 +161,10 @@ class MSDel : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsdel); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsdel); } }; diff --git a/modules/core/ms_help.cpp b/modules/core/ms_help.cpp index b672e06bf..dcd5f4e03 100644 --- a/modules/core/ms_help.cpp +++ b/modules/core/ms_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSHelp : public Command { @@ -24,7 +25,7 @@ class CommandMSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(MemoServ, source.u, NULL, params[0]); + mod_help_cmd(memoserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } @@ -36,15 +37,15 @@ class CommandMSHelp : public Command "the time or not, or to channels(*). Both the sender's\n" "nickname and the target nickname or channel must be\n" "registered in order to send a memo.\n" - "%s's commands include:"), MemoServ->nick.c_str(), MemoServ->nick.c_str()); - for (CommandMap::const_iterator it = MemoServ->Commands.begin(), it_end = MemoServ->Commands.end(); it != it_end; ++it) + "%s's commands include:"), Config->s_MemoServ.c_str(), Config->s_MemoServ.c_str()); + for (CommandMap::const_iterator it = memoserv->Bot()->Commands.begin(), it_end = memoserv->Bot()->Commands.end(); it != it_end; ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); source.Reply(_("Type \002%s%s HELP \037command\037\002 for help on any of the\n" "above commands.\n" "(*) By default, any user with at least level 10 access on a\n" " channel can read that channel's memos. This can be\n" - " changed with the %s \002LEVELS\002 command."), Config->UseStrictPrivMsgString.c_str(), MemoServ->nick.c_str(), Config->s_ChanServ.c_str()); + " changed with the %s \002LEVELS\002 command."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), Config->s_ChanServ.c_str()); } }; @@ -58,7 +59,10 @@ class MSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmshelp); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmshelp); } }; diff --git a/modules/core/ms_ignore.cpp b/modules/core/ms_ignore.cpp index fd1d09ebf..6747798d2 100644 --- a/modules/core/ms_ignore.cpp +++ b/modules/core/ms_ignore.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSIgnore : public Command { @@ -37,7 +38,7 @@ class CommandMSIgnore : public Command } bool ischan, isforbid; - MemoInfo *mi = getmemoinfo(channel, ischan, isforbid); + MemoInfo *mi = memoserv->GetMemoInfo(channel, ischan, isforbid); if (!mi) { if (isforbid) @@ -111,7 +112,10 @@ class MSIgnore : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsignore); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsignore); } }; diff --git a/modules/core/ms_info.cpp b/modules/core/ms_info.cpp index f87b8af60..1e12f97e9 100644 --- a/modules/core/ms_info.cpp +++ b/modules/core/ms_info.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSInfo : public Command { @@ -224,7 +225,10 @@ class MSInfo : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsinfo); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsinfo); } }; diff --git a/modules/core/ms_list.cpp b/modules/core/ms_list.cpp index 1b393688b..e09fcecc2 100644 --- a/modules/core/ms_list.cpp +++ b/modules/core/ms_list.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class MemoListCallback : public NumberList { @@ -172,7 +173,10 @@ class MSList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmslist); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmslist); } }; diff --git a/modules/core/ms_main.cpp b/modules/core/ms_main.cpp new file mode 100644 index 000000000..40cc6d6d5 --- /dev/null +++ b/modules/core/ms_main.cpp @@ -0,0 +1,250 @@ +/* MemoServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "memoserv.h" + +static BotInfo *MemoServ = NULL; +static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) +{ + Anope::string message = Anope::printf(GetString(nc, + "Hi %s\n" + " \n" + "You've just received a new memo from %s. This is memo number %d.\n" + " \n" + "Memo text:\n" + " \n" + "%s").c_str(), nc->display.c_str(), m->sender.c_str(), mi->GetIndex(m), m->text.c_str()); + + return Mail(nc, GetString(nc, _("New memo")), message); +} + +class MyMemoServService : public MemoServService +{ + public: + MyMemoServService(Module *m) : MemoServService(m) { } + + BotInfo *Bot() + { + return MemoServ; + } + + MemoInfo *GetMemoInfo(const Anope::string &target, bool &ischan, bool &isforbid) + { + isforbid = false; + + if (!target.empty() && target[0] == '#') + { + ischan = true; + ChannelInfo *ci = cs_findchan(target); + if (ci != NULL) + { + isforbid = ci->HasFlag(CI_FORBIDDEN); + return &ci->memos; + } + } + else + { + ischan = false; + NickAlias *na = findnick(target); + if (na != NULL) + { + isforbid = na->HasFlag(NS_FORBIDDEN); + return &na->nc->memos; + } + } + + return NULL; + } + + MemoResult Send(const Anope::string &source, const Anope::string &target, const Anope::string &message, bool force) + { + bool ischan, isforbid; + MemoInfo *mi = this->GetMemoInfo(target, ischan, isforbid); + + if (mi == NULL || isforbid == true) + return MEMO_INVALID_TARGET; + + User *sender = finduser(source); + if (sender != NULL && !sender->HasPriv("memoserv/no-limit") && !force) + { + if (Config->MSSendDelay > 0 && sender->lastmemosend + Config->MSSendDelay > Anope::CurTime) + return MEMO_TOO_FAST; + else if (!mi->memomax) + return MEMO_TARGET_FULL; + else if (mi->memomax > 0 && mi->memos.size() >= mi->memomax) + return MEMO_TARGET_FULL; + else if (mi->HasIgnore(sender)) + return MEMO_SUCCESS; + } + + if (sender != NULL) + sender->lastmemosend = Anope::CurTime; + + Memo *m = new Memo(); + mi->memos.push_back(m); + m->sender = source; + m->time = Anope::CurTime; + m->text = message; + m->SetFlag(MF_UNREAD); + + FOREACH_MOD(I_OnMemoSend, OnMemoSend(source, target, mi, m)); + + if (ischan) + { + ChannelInfo *ci = cs_findchan(target); + + if (ci->c) + { + for (CUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) + { + UserContainer *cu = *it; + + if (check_access(cu->user, ci, CA_MEMO)) + { + if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE)) + cu->user->SendMessage(MemoServ, _(MEMO_NEW_X_MEMO_ARRIVED), ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), ci->name.c_str(), mi->memos.size()); + } + } + } + } + else + { + NickCore *nc = findnick(target)->nc; + + if (nc->HasFlag(NI_MEMO_RECEIVE)) + { + for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it) + { + NickAlias *na = *it; + User *user = finduser(na->nick); + if (user && user->IsIdentified()) + user->SendMessage(MemoServ, _(MEMO_NEW_MEMO_ARRIVED), source.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); + } + } + + /* let's get out the mail if set in the nickcore - certus */ + if (nc->HasFlag(NI_MEMO_MAIL)) + SendMemoMail(nc, mi, m); + } + + return MEMO_SUCCESS; + } + + void Check(User *u) + { + NickCore *nc = u->Account(); + if (!nc) + return; + + unsigned i = 0, end = nc->memos.memos.size(), newcnt = 0; + for (; i < end; ++i) + { + if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) + ++newcnt; + } + if (newcnt > 0) + { + u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); + if (newcnt == 1 && (nc->memos.memos[i - 1]->HasFlag(MF_UNREAD))) + u->SendMessage(MemoServ, _("Type \002%s%s READ LAST\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); + else if (newcnt == 1) + { + for (i = 0; i < end; ++i) + { + if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) + break; + } + u->SendMessage(MemoServ, _("Type \002%s%s READ %d\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), i); + } + else + u->SendMessage(MemoServ, _("Type \002%s%s LIST NEW\002 to list them."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); + } + if (nc->memos.memomax > 0 && nc->memos.memos.size() >= nc->memos.memomax) + { + if (nc->memos.memos.size() > nc->memos.memomax) + u->SendMessage(MemoServ, _("You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); + else + u->SendMessage(MemoServ, _("You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); + } + } +}; + +class MemoServCore : public Module +{ + MyMemoServService mymemoserv; + + public: + MemoServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), mymemoserv(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + Implementation i[] = { I_OnNickIdentify, I_OnJoinChannel, I_OnUserAway, I_OnNickUpdate }; + ModuleManager::Attach(i, this, 4); + + ModuleManager::RegisterService(&this->mymemoserv); + + MemoServ = new BotInfo(Config->s_MemoServ, Config->ServiceUser, Config->ServiceHost, Config->desc_MemoServ); + MemoServ->SetFlag(BI_CORE); + + spacesepstream coreModules(Config->MemoCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~MemoServCore() + { + spacesepstream coreModules(Config->MemoCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete MemoServ; + } + + void OnNickIdentify(User *u) + { + this->mymemoserv.Check(u); + } + + void OnJoinChannel(User *u, Channel *c) + { + if (c->ci && check_access(u, c->ci, CA_MEMO) && c->ci->memos.memos.size() > 0) + { + if (c->ci->memos.memos.size() == 1) + u->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), c->ci->memos.memos.size(), c->ci->name.c_str()); + else + u->SendMessage(MemoServ, _("There are \002%d\002 memos on channel %s."), c->ci->memos.memos.size(), c->ci->name.c_str()); + } + } + + void OnUserAway(User *u, const Anope::string &message) + { + if (message.empty()) + this->mymemoserv.Check(u); + } + + void OnNickUpdate(User *u) + { + this->mymemoserv.Check(u); + } +}; + +MODULE_INIT(MemoServCore) + diff --git a/modules/core/ms_read.cpp b/modules/core/ms_read.cpp index 632bfd056..4b6e03aed 100644 --- a/modules/core/ms_read.cpp +++ b/modules/core/ms_read.cpp @@ -12,6 +12,41 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" + +void rsend_notify(CommandSource &source, MemoInfo *mi, Memo *m, const Anope::string &targ) +{ + /* Only send receipt if memos are allowed */ + if (memoserv && !readonly) + { + /* Get nick alias for sender */ + NickAlias *na = findnick(m->sender); + + if (!na) + return; + + /* Get nick core for sender */ + NickCore *nc = na->nc; + + if (!nc) + return; + + /* Text of the memo varies if the recepient was a + nick or channel */ + Anope::string text = Anope::printf(GetString(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")).c_str(), targ.c_str()); + + /* Send notification */ + memoserv->Send(source.u->nick, m->sender, text, true); + + /* Notify recepient of the memo that a notification has + been sent to the sender */ + source.Reply(_("A notification memo has been sent to %s informing him/her you have\n" + "read his/her memo."), nc->display.c_str()); + } + + /* Remove receipt flag from the original memo */ + m->UnsetFlag(MF_RECEIPT); +} class MemoListCallback : public NumberList { @@ -42,7 +77,7 @@ class MemoListCallback : public NumberList /* Check if a receipt notification was requested */ if (m->HasFlag(MF_RECEIPT)) - rsend_notify(source, m, ci ? ci->name : ""); + rsend_notify(source, mi, m, ci ? ci->name : source.u->nick); } }; @@ -157,7 +192,10 @@ class MSRead : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsread); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsread); } }; diff --git a/modules/core/ms_rsend.cpp b/modules/core/ms_rsend.cpp index 7e6af4950..46183ec77 100644 --- a/modules/core/ms_rsend.cpp +++ b/modules/core/ms_rsend.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSRSend : public Command { @@ -36,22 +37,34 @@ class CommandMSRSend : public Command return MOD_CONT; } - if (Config->MSMemoReceipt == 1) + if (Config->MSMemoReceipt == 1 && !u->IsServicesOper()) + source.Reply(_(ACCESS_DENIED)); + else if (Config->MSMemoReceipt > 2 || Config->MSMemoReceipt == 0) { - /* Services opers and above can use rsend */ - if (u->IsServicesOper()) - memo_send(source, nick, text, 3); - else - source.Reply(_(ACCESS_DENIED)); + Log() << "MSMemoReceipt is set misconfigured to " << Config->MSMemoReceipt; + source.Reply(_("Sorry, RSEND has been disabled on this network.")); } - else if (Config->MSMemoReceipt == 2) - /* Everybody can use rsend */ - memo_send(source, nick, text, 3); else { - /* rsend has been disabled */ - Log() << "MSMemoReceipt is set misconfigured to " << Config->MSMemoReceipt; - source.Reply(_("Sorry, RSEND has been disabled on this network.")); + MemoServService::MemoResult result = memoserv->Send(u->nick, nick, text); + if (result == MemoServService::MEMO_INVALID_TARGET) + source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str()); + else if (result == MemoServService::MEMO_TOO_FAST) + source.Reply(_("Please wait %d seconds before using the SEND command again."), Config->MSSendDelay); + else if (result == MemoServService::MEMO_TARGET_FULL) + source.Reply(_("%s currently has too many memos and cannot receive more."), nick.c_str()); + else + { + source.Reply(_("Memo sent to \002%s\002."), name.c_str()); + + bool ischan, isforbid; + MemoInfo *mi = memoserv->GetMemoInfo(nick, ischan, isforbid); + if (mi == NULL) + throw CoreException("NULL mi in ms_rsend"); + Memo *m = (mi->memos.size() ? mi->memos[mi->memos.size() - 1] : NULL); + if (m != NULL) + m->SetFlag(MF_RECEIPT); + } } return MOD_CONT; @@ -85,12 +98,15 @@ class MSRSend : public Module MSRSend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { if (!Config->MSMemoReceipt) - throw ModuleException("Don't like memo reciepts, or something."); + throw ModuleException("Invalid value for memoreceipt"); this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsrsend); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsrsend); } }; diff --git a/modules/core/ms_send.cpp b/modules/core/ms_send.cpp index babeb291c..c7bc0bb4c 100644 --- a/modules/core/ms_send.cpp +++ b/modules/core/ms_send.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSSend : public Command { @@ -25,7 +26,17 @@ class CommandMSSend : public Command { const Anope::string &nick = params[0]; const Anope::string &text = params[1]; - memo_send(source, nick, text, 0); + + MemoServService::MemoResult result = memoserv->Send(source.u->nick, nick, text); + if (result == MemoServService::MEMO_SUCCESS) + source.Reply(_("Memo sent to \002%s\002."), nick.c_str()); + else if (result == MemoServService::MEMO_INVALID_TARGET) + source.Reply(_("\002%s\002 is not a registered unforbidden nick or channel."), nick.c_str()); + else if (result == MemoServService::MEMO_TOO_FAST) + source.Reply(_("Please wait %d seconds before using the SEND command again."), Config->MSSendDelay); + else if (result == MemoServService::MEMO_TARGET_FULL) + source.Reply(_("%s currently has too many memos and cannot receive more."), nick.c_str()); + return MOD_CONT; } @@ -56,7 +67,10 @@ class MSSend : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmssend); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmssend); } }; diff --git a/modules/core/ms_sendall.cpp b/modules/core/ms_sendall.cpp index df084a85d..6fea77ae1 100644 --- a/modules/core/ms_sendall.cpp +++ b/modules/core/ms_sendall.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSSendAll : public Command { @@ -39,7 +40,7 @@ class CommandMSSendAll : public Command NickCore *nc = it->second; if ((na && na->nc == nc) || !nc->display.equals_ci(u->nick)) - memo_send(source, nc->display, text, 1); + memoserv->Send(u->nick, nc->display, text); } source.Reply(_("A massmemo has been sent to all registered users.")); @@ -69,7 +70,10 @@ class MSSendAll : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmssendall); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmssendall); } }; diff --git a/modules/core/ms_set.cpp b/modules/core/ms_set.cpp index 35e5c6db5..0b5dd3831 100644 --- a/modules/core/ms_set.cpp +++ b/modules/core/ms_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSSet : public Command { @@ -237,7 +238,7 @@ class CommandMSSet : public Command " receive\n" " \n" "Type \002%s%s HELP SET \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), MemoServ->nick.c_str()); + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); else if (subcommand.equals_ci("NOTIFY")) source.Reply(_("Syntax: \002SET NOTIFY {ON | LOGON | NEW | MAIL | NOMAIL | OFF}\002\n" "Changes when you will be notified about new memos:\n" @@ -307,7 +308,10 @@ class MSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsset); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsset); } }; diff --git a/modules/core/ms_staff.cpp b/modules/core/ms_staff.cpp index 1de1b11bf..1d7fbc288 100644 --- a/modules/core/ms_staff.cpp +++ b/modules/core/ms_staff.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "memoserv.h" class CommandMSStaff : public Command { @@ -36,7 +37,7 @@ class CommandMSStaff : public Command NickCore *nc = it->second; if (nc->IsServicesOper()) - memo_send(source, nc->display, text, 0); + memoserv->Send(source.u->nick, nc->display, text, true); } return MOD_CONT; @@ -67,7 +68,10 @@ class MSStaff : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(MemoServ, &commandmsstaff); + if (!memoserv) + throw ModuleException("MemoServ is not loaded!"); + + this->AddCommand(memoserv->Bot(), &commandmsstaff); } }; diff --git a/modules/core/nickserv.h b/modules/core/nickserv.h new file mode 100644 index 000000000..71039c7ba --- /dev/null +++ b/modules/core/nickserv.h @@ -0,0 +1,17 @@ +#ifndef NICKSERV_H +#define NICKSERV_H + +class NickServService : public Service +{ + public: + NickServService(Module *m) : Service(m, "NickServ") { } + + virtual BotInfo *Bot() = 0; + + virtual void Validate(User *u) = 0; +}; + +static service_reference<NickServService> nickserv("NickServ"); + +#endif // NICKSERV_H + diff --git a/modules/core/ns_access.cpp b/modules/core/ns_access.cpp index 96aa0e137..7e69dbf4e 100644 --- a/modules/core/ns_access.cpp +++ b/modules/core/ns_access.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSAccess : public Command { @@ -172,7 +173,7 @@ class CommandNSAccess : public Command " Reverses the previous command.\n" " \n" " \002ACCESS LIST\002\n" - " Displays the current access list."), NickServ->nick.c_str(), NickServ->nick.c_str()); + " Displays the current access list."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -192,7 +193,10 @@ class NSAccess : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsaccess); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsaccess); } }; diff --git a/modules/core/ns_ajoin.cpp b/modules/core/ns_ajoin.cpp index 2f5c4e753..2d5ac146e 100644 --- a/modules/core/ns_ajoin.cpp +++ b/modules/core/ns_ajoin.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSAJoin : public Command { @@ -117,7 +118,10 @@ class NSAJoin : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsajoin); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsajoin); Implementation i[] = { I_OnNickIdentify, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 3); @@ -189,10 +193,10 @@ class NSAJoin : public Module { if (!check_access(u, ci, CA_INVITE)) continue; - ircdproto->SendInvite(NickServ, channels[i].first, u->nick); + ircdproto->SendInvite(nickserv->Bot(), channels[i].first, u->nick); } - ircdproto->SendSVSJoin(NickServ->nick, u->nick, channels[i].first, key); + ircdproto->SendSVSJoin(Config->s_NickServ, u->nick, channels[i].first, key); } } diff --git a/modules/core/ns_alist.cpp b/modules/core/ns_alist.cpp index f0fd3f7aa..78b4cf096 100644 --- a/modules/core/ns_alist.cpp +++ b/modules/core/ns_alist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSAList : public Command { @@ -175,7 +176,7 @@ class NSAList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsalist); + this->AddCommand(nickserv->Bot(), &commandnsalist); } }; diff --git a/modules/core/ns_cert.cpp b/modules/core/ns_cert.cpp index 583502ba9..87acf7ac2 100644 --- a/modules/core/ns_cert.cpp +++ b/modules/core/ns_cert.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSCert : public Command { @@ -161,7 +162,7 @@ class CommandNSCert : public Command "If you connect to IRC and provide a client certificate with a\n" "matching fingerprint in the cert list, your nick will be\n" "automatically identified to %s.\n" - " \n"), NickServ->nick.c_str(), NickServ->nick.c_str()); + " \n"), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); source.Reply(_("Examples:\n" " \n" " \002CERT ADD <fingerprint>\002\n" @@ -173,7 +174,7 @@ class CommandNSCert : public Command " Reverses the previous command.\n" " \n" " \002CERT LIST\002\n" - " Displays the current certificate list."), NickServ->nick.c_str()); + " Displays the current certificate list."), Config->s_NickServ.c_str()); return true; } @@ -200,7 +201,7 @@ class NSCert : public Module return; u->Identify(na); - u->SendMessage(NickServ, _("SSL Fingerprint accepted. You are now identified.")); + u->SendMessage(nickserv->Bot(), _("SSL Fingerprint accepted. You are now identified.")); return; } @@ -213,10 +214,13 @@ class NSCert : public Module if (!ircd->certfp) throw ModuleException("Your IRCd does not support ssl client certificates"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + Implementation i[] = { I_OnUserNickChange, I_OnFingerprint }; ModuleManager::Attach(i, this, 2); - this->AddCommand(NickServ, &commandnscert); + this->AddCommand(nickserv->Bot(), &commandnscert); } void OnFingerprint(User *u) diff --git a/modules/core/ns_drop.cpp b/modules/core/ns_drop.cpp index 75a0b7899..475359002 100644 --- a/modules/core/ns_drop.cpp +++ b/modules/core/ns_drop.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSDrop : public Command { @@ -99,7 +100,7 @@ class CommandNSDrop : public Command "With a parameter, drops the named nick from the database.\n" "You may drop any nick within your group without any \n" "special privileges. Dropping any nick is limited to \n" - "\002Services Operators\002."), NickServ->nick.c_str()); + "\002Services Operators\002."), Config->s_NickServ.c_str()); else source.Reply(_("Syntax: \002DROP [\037nickname\037 | \037password\037]\002\n" " \n" @@ -115,7 +116,7 @@ class CommandNSDrop : public Command " \n" "In order to use this command, you must first identify\n" "with your password (\002%s%s HELP IDENTIFY\002 for more\n" - "information)."), NickServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + "information)."), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); return true; } @@ -131,7 +132,10 @@ class NSDrop : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsdrop); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsdrop); } }; diff --git a/modules/core/ns_forbid.cpp b/modules/core/ns_forbid.cpp index a5f4324a3..d9c13ca67 100644 --- a/modules/core/ns_forbid.cpp +++ b/modules/core/ns_forbid.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSForbid : public Command { @@ -64,7 +65,7 @@ class CommandNSForbid : public Command if (curr) { - curr->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); + curr->SendMessage(nickserv->Bot(), _(FORCENICKCHANGE_NOW)); curr->Collide(na); } @@ -109,7 +110,10 @@ class NSForbid : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsforbid); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsforbid); } }; diff --git a/modules/core/ns_getemail.cpp b/modules/core/ns_getemail.cpp index e31bfb0f5..8f80a5cdf 100644 --- a/modules/core/ns_getemail.cpp +++ b/modules/core/ns_getemail.cpp @@ -16,6 +16,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSGetEMail : public Command { @@ -78,7 +79,10 @@ class NSGetEMail : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsgetemail); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsgetemail); } }; diff --git a/modules/core/ns_getpass.cpp b/modules/core/ns_getpass.cpp index e106b7a8b..eba380dfb 100644 --- a/modules/core/ns_getpass.cpp +++ b/modules/core/ns_getpass.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSGetPass : public Command { @@ -71,14 +72,17 @@ class NSGetPass : public Module public: NSGetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { + this->SetAuthor("Anope"); + this->SetType(CORE); + + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + Anope::string tmp_pass = "plain:tmp"; if (enc_decrypt(tmp_pass, tmp_pass) == -1) throw ModuleException("Incompatible with the encryption module being used"); - this->SetAuthor("Anope"); - this->SetType(CORE); - - this->AddCommand(NickServ, &commandnsgetpass); + this->AddCommand(nickserv->Bot(), &commandnsgetpass); } }; diff --git a/modules/core/ns_ghost.cpp b/modules/core/ns_ghost.cpp index 60bd9aea2..d22b82472 100644 --- a/modules/core/ns_ghost.cpp +++ b/modules/core/ns_ghost.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSGhost : public Command { @@ -62,7 +63,7 @@ class CommandNSGhost : public Command if (ok) { - if (!user->IsIdentified() && FindCommand(NickServ, "RECOVER")) + if (!user->IsIdentified() && FindCommand(nickserv->Bot(), "RECOVER")) source.Reply(_("You may not ghost an unidentified user, use RECOVER instead.")); else { @@ -121,7 +122,10 @@ class NSGhost : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsghost); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsghost); } }; diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp index c7a56cb8f..cd3b4946d 100644 --- a/modules/core/ns_group.cpp +++ b/modules/core/ns_group.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSGroup : public Command { @@ -60,7 +61,7 @@ class CommandNSGroup : public Command source.Reply(_("Please wait %d seconds before using the GROUP command again."), (Config->NSRegDelay + u->lastnickreg) - Anope::CurTime); else if (u->Account() && u->Account()->HasFlag(NI_SUSPENDED)) { - Log(NickServ) << NickServ << u->GetMask() << " tried to use GROUP from SUSPENDED nick " << target->nick; + Log(nickserv->Bot()) << u->GetMask() << " tried to use GROUP from SUSPENDED nick " << target->nick; source.Reply(_(NICK_X_SUSPENDED), u->nick.c_str()); } else if (target && target->nc->HasFlag(NI_SUSPENDED)) @@ -124,16 +125,13 @@ class CommandNSGroup : public Command u->Login(na->nc); FOREACH_MOD(I_OnNickGroup, OnNickGroup(u, target)); + ircdproto->SendAccountLogin(u, u->Account()); ircdproto->SetAutoIdentificationToken(u); - if (target->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); Log(LOG_COMMAND, u, this) << "makes " << u->nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")"; source.Reply(_("You are now in the group of \002%s\002."), target->nick.c_str()); u->lastnickreg = Anope::CurTime; - - check_memos(u); } else { @@ -177,7 +175,7 @@ class CommandNSGroup : public Command "not possible.\n" " \n" "\037Note\037: all the nicknames of a group have the same password."), - Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); return true; } @@ -233,7 +231,7 @@ class CommandNSUngroup : public Command User *user = finduser(na->nick); if (user) /* The user on the nick who was ungrouped may be identified to the old group, set -r */ - user->RemoveMode(NickServ, UMODE_REGISTERED); + user->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); } return MOD_CONT; @@ -318,9 +316,9 @@ class NSGroup : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsgroup); - this->AddCommand(NickServ, &commandnsungroup); - this->AddCommand(NickServ, &commandnsglist); + this->AddCommand(nickserv->Bot(), &commandnsgroup); + this->AddCommand(nickserv->Bot(), &commandnsungroup); + this->AddCommand(nickserv->Bot(), &commandnsglist); } }; diff --git a/modules/core/ns_help.cpp b/modules/core/ns_help.cpp index d586901f8..61088d979 100644 --- a/modules/core/ns_help.cpp +++ b/modules/core/ns_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSHelp : public Command { @@ -24,7 +25,7 @@ class CommandNSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(NickServ, source.u, NULL, params[0]); + mod_help_cmd(nickserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } @@ -36,9 +37,8 @@ class CommandNSHelp : public Command "commands allow for registration and maintenance of\n" "nicknames; to use them, type \002%s%s \037command\037\002.\n" "For more information on a specific command, type\n" - "\002%s%s HELP \037command\037\002."), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str(), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str(), - NickServ->nick.c_str()); - for (CommandMap::const_iterator it = NickServ->Commands.begin(), it_end = NickServ->Commands.end(); it != it_end; ++it) + "\002%s%s HELP \037command\037\002."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); + for (CommandMap::const_iterator it = nickserv->Bot()->Commands.begin(), it_end = nickserv->Bot()->Commands.end(); it != it_end; ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); if (u->IsServicesOper()) @@ -46,7 +46,7 @@ class CommandNSHelp : public Command "Services Operators can also drop any nickname without needing\n" "to identify for the nick, and may view the access list for\n" "any nickname (\002%s%s ACCESS LIST \037nick\037\002)."), - Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); if (Config->NSExpire >= 86400) source.Reply(_("Nicknames that are not used anymore are subject to \n" "the automatic expiration, i.e. they will be deleted\n" @@ -57,7 +57,7 @@ class CommandNSHelp : public Command "It is \002NOT\002 intended to facilitate \"stealing\" of\n" "nicknames or other malicious actions. Abuse of %s\n" "will result in, at minimum, loss of the abused\n" - "nickname(s)."), NickServ->nick.c_str()); + "nickname(s)."), Config->s_NickServ.c_str()); } }; @@ -71,7 +71,10 @@ class NSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnshelp); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnshelp); } }; diff --git a/modules/core/ns_identify.cpp b/modules/core/ns_identify.cpp index f5f196f62..3ef47b7d7 100644 --- a/modules/core/ns_identify.cpp +++ b/modules/core/ns_identify.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSIdentify : public Command { @@ -72,7 +73,7 @@ class CommandNSIdentify : public Command "nick. Many commands require you to authenticate yourself\n" "with this command before you use them. The password\n" "should be the same one you sent with the \002REGISTER\002\n" - "command."), NickServ->nick.c_str()); + "command."), Config->s_NickServ.c_str()); return true; } @@ -92,7 +93,10 @@ class NSIdentify : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsidentify); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsidentify); } }; diff --git a/modules/core/ns_info.cpp b/modules/core/ns_info.cpp index 6328341cb..59cd60e6d 100644 --- a/modules/core/ns_info.cpp +++ b/modules/core/ns_info.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSInfo : public Command { @@ -175,7 +176,10 @@ class NSInfo : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsinfo); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsinfo); } }; diff --git a/modules/core/ns_list.cpp b/modules/core/ns_list.cpp index b032543de..60dfa9732 100644 --- a/modules/core/ns_list.cpp +++ b/modules/core/ns_list.cpp @@ -12,7 +12,7 @@ /*************************************************************************/ #include "module.h" -#include "hashcomp.h" +#include "nickserv.h" class CommandNSList : public Command { @@ -219,7 +219,10 @@ class NSList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnslist); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnslist); } }; diff --git a/modules/core/ns_logout.cpp b/modules/core/ns_logout.cpp index c074fecf8..6675e85b4 100644 --- a/modules/core/ns_logout.cpp +++ b/modules/core/ns_logout.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSLogout : public Command { @@ -38,7 +39,7 @@ class CommandNSLogout : public Command else { if (!nick.empty() && !param.empty() && param.equals_ci("REVALIDATE")) - validate_user(u2); + nickserv->Validate(u2); u2->isSuperAdmin = 0; /* Dont let people logout and remain a SuperAdmin */ Log(LOG_COMMAND, u, this) << "to logout " << u2->nick; @@ -50,7 +51,7 @@ class CommandNSLogout : public Command source.Reply(_("Your nick has been logged out.")); ircdproto->SendAccountLogout(u2, u2->Account()); - u2->RemoveMode(NickServ, UMODE_REGISTERED); + u2->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); ircdproto->SendUnregisteredNick(u2); u2->Logout(); @@ -102,7 +103,10 @@ class NSLogout : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnslogout); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnslogout); } }; diff --git a/modules/core/ns_main.cpp b/modules/core/ns_main.cpp new file mode 100644 index 000000000..dbf72ca09 --- /dev/null +++ b/modules/core/ns_main.cpp @@ -0,0 +1,282 @@ +/* NickServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "nickserv.h" + +static BotInfo *NickServ = NULL; + +class MyNickServService : public NickServService +{ + public: + MyNickServService(Module *m) : NickServService(m) { } + + BotInfo *Bot() + { + return NickServ; + } + + void Validate(User *u) + { + NickAlias *na = findnick(u->nick); + if (!na) + return; + + if (na->HasFlag(NS_FORBIDDEN)) + { + u->SendMessage(NickServ, _("This nickname may not be used. Please choose another one.")); + u->Collide(na); + return; + } + + if (na->nc->HasFlag(NI_SUSPENDED)) + { + u->SendMessage(NickServ, _(NICK_X_SUSPENDED), u->nick.c_str()); + u->Collide(na); + return; + } + + if (!u->IsIdentified() && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint)) + { + u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified")); + u->Identify(na); + return; + } + + if (!na->nc->HasFlag(NI_SECURE) && u->IsRecognized()) + { + na->last_seen = Anope::CurTime; + Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); + na->last_usermask = last_usermask; + na->last_realname = u->realname; + return; + } + + if (u->IsRecognized() || !na->nc->HasFlag(NI_KILL_IMMED)) + { + if (na->nc->HasFlag(NI_SECURE)) + u->SendMessage(NickServ, _(NICK_IS_SECURE), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + else + u->SendMessage(NickServ, _(NICK_IS_REGISTERED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + } + + if (na->nc->HasFlag(NI_KILLPROTECT) && !u->IsRecognized()) + { + if (na->nc->HasFlag(NI_KILL_IMMED)) + { + u->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); + u->Collide(na); + } + else if (na->nc->HasFlag(NI_KILL_QUICK)) + { + u->SendMessage(NickServ, _("If you do not change within 20 seconds, I will change your nick.")); + new NickServCollide(u, 20); + } + else + { + u->SendMessage(NickServ, _("If you do not change within one minute, I will change your nick.")); + new NickServCollide(u, 60); + } + } + + } +}; + +class ExpireCallback : public CallBack +{ + public: + ExpireCallback(Module *owner) : CallBack(owner, Config->ExpireTimeout, Anope::CurTime, true) { } + + void Tick(time_t) + { + if (noexpire || readonly) + return; + + for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ) + { + NickAlias *na = it->second; + ++it; + + User *u = finduser(na->nick); + if (u && (na->nc->HasFlag(NI_SECURE) ? u->IsIdentified(true) : u->IsRecognized(true))) + na->last_seen = Anope::CurTime; + + bool expire = false; + + if (na->nc->HasFlag(NI_UNCONFIRMED)) + if (Config->NSUnconfirmedExpire && Anope::CurTime - na->time_registered >= Config->NSUnconfirmedExpire) + expire = true; + if (na->nc->HasFlag(NI_SUSPENDED)) + { + if (Config->NSSuspendExpire && Anope::CurTime - na->last_seen >= Config->NSSuspendExpire) + expire = true; + } + else if (na->HasFlag(NS_FORBIDDEN)) + { + if (Config->NSForbidExpire && Anope::CurTime - na->last_seen >= Config->NSForbidExpire) + expire = true; + } + else if (Config->NSExpire && Anope::CurTime - na->last_seen >= Config->NSExpire) + expire = true; + if (na->HasFlag(NS_NO_EXPIRE)) + expire = false; + + if (expire) + { + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreNickExpire, OnPreNickExpire(na)); + if (MOD_RESULT == EVENT_STOP) + continue; + Anope::string extra; + if (na->HasFlag(NS_FORBIDDEN)) + extra = "forbidden "; + else if (na->nc->HasFlag(NI_SUSPENDED)) + extra = "suspended "; + Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")"; + FOREACH_MOD(I_OnNickExpire, OnNickExpire(na)); + delete na; + } + } + } +}; + +class NickServCore : public Module +{ + MyNickServService mynickserv; + ExpireCallback expires; + + public: + NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), mynickserv(this), expires(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + Implementation i[] = { I_OnDelNick, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickIdentify, I_OnNickGroup, I_OnNickUpdate }; + ModuleManager::Attach(i, this, 5); + + ModuleManager::RegisterService(&this->mynickserv); + + NickServ = new BotInfo(Config->s_NickServ, Config->ServiceUser, Config->ServiceHost, Config->desc_NickServ); + NickServ->SetFlag(BI_CORE); + + spacesepstream coreModules(Config->NickCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~NickServCore() + { + spacesepstream coreModules(Config->NickCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete NickServ; + } + + void OnDelNick(NickAlias *na) + { + User *u = finduser(na->nick); + if (u && u->Account() == na->nc) + { + u->RemoveMode(NickServ, UMODE_REGISTERED); + ircdproto->SendAccountLogout(u, u->Account()); + ircdproto->SendUnregisteredNick(u); + u->Logout(); + } + } + + void OnDelCore(NickCore *nc) + { + Log(NickServ, "nick") << "deleting nickname group " << nc->display; + + /* Clean up this nick core from any users online using it + * (ones that /nick but remain unidentified) + */ + for (std::list<User *>::iterator it = nc->Users.begin(); it != nc->Users.end();) + { + User *user = *it++; + ircdproto->SendAccountLogout(user, user->Account()); + user->RemoveMode(NickServ, UMODE_REGISTERED); + ircdproto->SendUnregisteredNick(user); + user->Logout(); + FOREACH_MOD(I_OnNickLogout, OnNickLogout(user)); + } + nc->Users.clear(); + } + + void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) + { + Log(LOG_NORMAL, "nick", NickServ) << "Changing " << nc->display << " nickname group display to " << newdisplay; + } + + void OnNickIdentify(User *u) + { + NickAlias *this_na = findnick(u->nick); + if (this_na && this_na->nc == u->Account() && u->Account()->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(NickServ, UMODE_REGISTERED); + + if (Config->NSModeOnID) + for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) + { + ChannelContainer *cc = *it; + Channel *c = cc->chan; + if (c) + chan_set_correct_modes(u, c, 1); + } + + if (Config->NSForceEmail && u->Account()->email.empty()) + { + u->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n" + "This e-mail will allow you to retrieve your password in\n" + "case you forget it.")); + u->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" + "Your privacy is respected; this e-mail won't be given to\n" + "any third-party person."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); + } + + if (u->Account()->HasFlag(NI_UNCONFIRMED)) + { + u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered.")); + this_na = findnick(u->Account()->display); + time_t time_registered = Anope::CurTime - this_na->time_registered; + if (Config->NSUnconfirmedExpire > time_registered) + u->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str()); + } + } + + void OnNickGroup(User *u, NickAlias *target) + { + if (target->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(NickServ, UMODE_REGISTERED); + } + + void OnNickUpdate(User *u) + { + for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) + { + ChannelContainer *cc = *it; + Channel *c = cc->chan; + if (c) + chan_set_correct_modes(u, c, 1); + } + } +}; + +MODULE_INIT(NickServCore) + diff --git a/modules/core/ns_recover.cpp b/modules/core/ns_recover.cpp index f9e088586..30e1476c3 100644 --- a/modules/core/ns_recover.cpp +++ b/modules/core/ns_recover.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSRecover : public Command { @@ -50,7 +51,7 @@ class CommandNSRecover : public Command if (MOD_RESULT == EVENT_ALLOW) { - u2->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); + u2->SendMessage(nickserv->Bot(), _(FORCENICKCHANGE_NOW)); u2->Collide(na); /* Convert Config->NSReleaseTimeout seconds to string format */ @@ -70,7 +71,7 @@ class CommandNSRecover : public Command if (u->Account() == na->nc || (!na->nc->HasFlag(NI_SECURE) && is_on_access(u, na->nc)) || (!u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))) { - u2->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); + u2->SendMessage(nickserv->Bot(), _(FORCENICKCHANGE_NOW)); u2->Collide(na); /* Convert Config->NSReleaseTimeout seconds to string format */ @@ -110,7 +111,7 @@ class CommandNSRecover : public Command "current address as shown in /WHOIS must be on that nick's\n" "access list, you must be identified and in the group of\n" "that nick, or you must supply the correct password for\n" - "the nickname."), NickServ->nick.c_str(), NickServ->nick.c_str(), relstr.c_str(), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + "the nickname."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str(), relstr.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); return true; } @@ -131,7 +132,10 @@ class NSRecover : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsrecover); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsrecover); } }; diff --git a/modules/core/ns_register.cpp b/modules/core/ns_register.cpp index b1d70c9a5..56c8072ca 100644 --- a/modules/core/ns_register.cpp +++ b/modules/core/ns_register.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" static bool SendRegmail(User *u, NickAlias *na); @@ -155,7 +156,7 @@ class CommandNSRegister : public Command /* i.e. there's already such a nick regged */ if (na->HasFlag(NS_FORBIDDEN)) { - Log(NickServ) << u->GetMask() << " tried to register FORBIDden nick " << u->nick; + Log(nickserv->Bot()) << u->GetMask() << " tried to register FORBIDden nick " << u->nick; source.Reply(_(NICK_CANNOT_BE_REGISTERED), u->nick.c_str()); } else @@ -200,7 +201,7 @@ class CommandNSRegister : public Command na->nc->SetFlag(NI_UNCONFIRMED); if (SendRegmail(u, na)) { - source.Reply(_("A passcode has been sent to %s, please type %s%s confirm <passcode> to confirm your email address."), email.c_str(), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + source.Reply(_("A passcode has been sent to %s, please type %s%s confirm <passcode> to confirm your email address."), email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); source.Reply(_("If you do not confirm your email address within %s your account will expire."), duration(Config->NSUnconfirmedExpire).c_str()); } } @@ -235,10 +236,9 @@ class CommandNSRegister : public Command "passwords are vulnerable to trial-and-error searches, so\n" "you should choose a password at least 5 characters long.\n" "Finally, the space character cannot be used in passwords.\n"), - NickServ->nick.c_str(), NickServ->nick.c_str()); + Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); - source.Reply(_( - " \n" + source.Reply(_(" \n" "The parameter \037email\037 is optional and will set the email\n" "for your nick immediately. However, it may be required\n" "on certain networks.\n" @@ -250,7 +250,7 @@ class CommandNSRegister : public Command "the same configuration, the same set of memos and the\n" "same channel privileges. For more information on this\n" "feature, type \002%s%s HELP GROUP\002."), - Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); return true; } @@ -330,9 +330,12 @@ class NSRegister : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsregister); - this->AddCommand(NickServ, &commandnsconfirm); - this->AddCommand(NickServ, &commandnsrsend); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsregister); + this->AddCommand(nickserv->Bot(), &commandnsconfirm); + this->AddCommand(nickserv->Bot(), &commandnsrsend); } }; @@ -364,7 +367,7 @@ static bool SendRegmail(User *u, NickAlias *na) " \n" "%s administrators."), na->nick.c_str(), Config->NetworkName.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); - return Mail(u, na->nc, NickServ, subject, message); + return Mail(u, na->nc, nickserv->Bot(), subject, message); } MODULE_INIT(NSRegister) diff --git a/modules/core/ns_release.cpp b/modules/core/ns_release.cpp index a6f5f862f..251355b0d 100644 --- a/modules/core/ns_release.cpp +++ b/modules/core/ns_release.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSRelease : public Command { @@ -87,7 +88,7 @@ class CommandNSRelease : public Command "current address as shown in /WHOIS must be on that nick's\n" "access list, you must be identified and in the group of\n" "that nick, or you must supply the correct password for\n" - "the nickname."), NickServ->nick.c_str(), relstr.c_str()); + "the nickname."), Config->s_NickServ.c_str(), relstr.c_str()); return true; @@ -109,7 +110,10 @@ class NSRelease : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsrelease); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsrelease); } }; diff --git a/modules/core/ns_resetpass.cpp b/modules/core/ns_resetpass.cpp index 626af80c8..3cbbe5903 100644 --- a/modules/core/ns_resetpass.cpp +++ b/modules/core/ns_resetpass.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" static bool SendResetEmail(User *u, NickAlias *na); @@ -68,13 +69,16 @@ class NSResetPass : public Module public: NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - if (!Config->UseMail) - throw ModuleException("Not using mail."); - this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsresetpass); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + if (!Config->UseMail) + throw ModuleException("Not using mail."); + + this->AddCommand(nickserv->Bot(), &commandnsresetpass); ModuleManager::Attach(I_OnPreCommand, this); } @@ -82,7 +86,7 @@ class NSResetPass : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { User *u = source.u; - if (command->service == NickServ && command->name.equals_ci("CONFIRM") && params.size() > 1) + if (command->service->nick == Config->s_NickServ && command->name.equals_ci("CONFIRM") && params.size() > 1) { NickAlias *na = findnick(params[0]); @@ -151,7 +155,7 @@ static bool SendResetEmail(User *u, NickAlias *na) na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<Anope::string>(passcode)); na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(Anope::CurTime)); - return Mail(u, na->nc, NickServ, subject, message); + return Mail(u, na->nc, nickserv->Bot(), subject, message); } MODULE_INIT(NSResetPass) diff --git a/modules/core/ns_saset.cpp b/modules/core/ns_saset.cpp index 94da56ec6..69fb747d6 100644 --- a/modules/core/ns_saset.cpp +++ b/modules/core/ns_saset.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSASet : public Command { @@ -62,7 +63,7 @@ class CommandNSSASet : public Command Log(LOG_ADMIN, u, this) << params[1] << " " << cmdparams; else Log(LOG_ADMIN, u, this) << params[1] << " for " << params[0]; - mod_run_cmd(NickServ, u, NULL, c, params[1], cmdparams); + mod_run_cmd(nickserv->Bot(), u, NULL, c, params[1], cmdparams); } else source.Reply(_("Unknown SASET option \002%s\002."), cmd.c_str()); @@ -82,7 +83,7 @@ class CommandNSSASet : public Command it->second->OnServHelp(source); source.Reply(_("Type \002%s%s HELP SASET \037option\037\002 for more information\n" "on a specific option. The options will be set on the given\n" - "\037nickname\037."), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); + "\037nickname\037."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); return true; } else @@ -203,7 +204,7 @@ class CommandNSSASetPassword : public Command if (enc_encrypt(params[1], nc->pass)) { - Log(NickServ) << "Failed to encrypt password for " << nc->display << " (saset)"; + Log() << "Failed to encrypt password for " << nc->display << " (saset)"; source.Reply(_(NICK_SASET_PASSWORD_FAILED), nc->display.c_str()); return MOD_CONT; } @@ -243,7 +244,10 @@ class NSSASet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnssaset); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnssaset); commandnssaset.AddSubcommand(this, &commandnssasetdisplay); commandnssaset.AddSubcommand(this, &commandnssasetpassword); diff --git a/modules/core/ns_saset_noexpire.cpp b/modules/core/ns_saset_noexpire.cpp index 532d6c8fe..e1bbaf87f 100644 --- a/modules/core/ns_saset_noexpire.cpp +++ b/modules/core/ns_saset_noexpire.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSASetNoexpire : public Command { @@ -70,14 +71,17 @@ class NSSASetNoexpire : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SASET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetnoexpire); } ~NSSASetNoexpire() { - Command *c = FindCommand(NickServ, "SASET"); + Command *c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetnoexpire); } diff --git a/modules/core/ns_sendpass.cpp b/modules/core/ns_sendpass.cpp index 9614211c1..98530c236 100644 --- a/modules/core/ns_sendpass.cpp +++ b/modules/core/ns_sendpass.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" static bool SendPassMail(User *u, NickAlias *na, const Anope::string &pass); @@ -79,6 +80,12 @@ class NSSendPass : public Module public: NSSendPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { + this->SetAuthor("Anope"); + this->SetType(CORE); + + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + if (!Config->UseMail) throw ModuleException("Not using mail, whut."); @@ -86,10 +93,7 @@ class NSSendPass : public Module if (enc_decrypt(tmp_pass, tmp_pass) == -1) throw ModuleException("Incompatible with the encryption module being used"); - this->SetAuthor("Anope"); - this->SetType(CORE); - - this->AddCommand(NickServ, &commandnssendpass); + this->AddCommand(nickserv->Bot(), &commandnssendpass); } }; @@ -108,7 +112,7 @@ static bool SendPassMail(User *u, NickAlias *na, const Anope::string &pass) " \n" "%s administrators.").c_str(), na->nick.c_str(), pass.c_str(), Config->NetworkName.c_str()); - return Mail(u, na->nc, NickServ, subject, message); + return Mail(u, na->nc, nickserv->Bot(), subject, message); } MODULE_INIT(NSSendPass) diff --git a/modules/core/ns_set.cpp b/modules/core/ns_set.cpp index bfae7f508..895542cc7 100644 --- a/modules/core/ns_set.cpp +++ b/modules/core/ns_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSet : public Command { @@ -57,7 +58,7 @@ class CommandNSSet : public Command Log(LOG_COMMAND, u, this) << params[0] << " " << cmdparams; else Log(LOG_COMMAND, u, this) << params[0]; - mod_run_cmd(NickServ, u, NULL, c, params[0], cmdparams); + mod_run_cmd(nickserv->Bot(), u, NULL, c, params[0], cmdparams); } else source.Reply(_(NICK_SET_UNKNOWN_OPTION), Config->UseStrictPrivMsgString.c_str(), params[0].c_str()); @@ -79,7 +80,7 @@ class CommandNSSet : public Command "information).\n" " \n" "Type \002%s%s HELP SET \037option\037\002 for more information\n" - "on a specific option."), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str(), (Config->UseStrictPrivMsg ? "/msg " : "/"), NickServ->nick.c_str()); + "on a specific option."), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), (Config->UseStrictPrivMsg ? "/msg " : "/"), Config->s_NickServ.c_str()); return true; } else @@ -189,7 +190,7 @@ class CommandNSSetPassword : public Command if (enc_encrypt(param, u->Account()->pass) < 0) { - Log(NickServ) << "Failed to encrypt password for " << u->Account()->display << " (set)"; + Log() << "Failed to encrypt password for " << u->Account()->display << " (set)"; source.Reply(_(NICK_SASET_PASSWORD_FAILED)); return MOD_CONT; } @@ -231,7 +232,10 @@ class NSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsset); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsset); commandnsset.AddSubcommand(this, &commandnssetdisplay); commandnsset.AddSubcommand(this, &commandnssetpassword); diff --git a/modules/core/ns_set_autoop.cpp b/modules/core/ns_set_autoop.cpp index f25e3a749..051ce22e6 100644 --- a/modules/core/ns_set_autoop.cpp +++ b/modules/core/ns_set_autoop.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetAutoOp : public Command { @@ -95,22 +96,25 @@ class NSSetAutoOp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetautoop); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetautoop); } ~NSSetAutoOp() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetautoop); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetautoop); } diff --git a/modules/core/ns_set_email.cpp b/modules/core/ns_set_email.cpp index d63329f50..ed49cfd89 100644 --- a/modules/core/ns_set_email.cpp +++ b/modules/core/ns_set_email.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" static bool SendConfirmMail(User *u) { @@ -38,7 +39,7 @@ static bool SendConfirmMail(User *u) " \n" "%s administrators."), u->Account()->email.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str(), code.c_str(), Config->NetworkName.c_str()); - return Mail(u, u->Account(), NickServ, subject, message); + return Mail(u, u->Account(), nickserv->Bot(), subject, message); } class CommandNSSetEmail : public Command @@ -139,24 +140,27 @@ class NSSetEmail : public Module this->SetAuthor("Anope"); this->SetType(CORE); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + ModuleManager::Attach(I_OnPreCommand, this); - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetemail); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetemail); } ~NSSetEmail() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetemail); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetemail); } @@ -164,7 +168,7 @@ class NSSetEmail : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { User *u = source.u; - if (command->service == NickServ && command->name.equals_ci("CONFIRM") && !params.empty() && u->IsIdentified()) + if (command->service->nick == Config->s_NickServ && command->name.equals_ci("CONFIRM") && !params.empty() && u->IsIdentified()) { Anope::string new_email, passcode; if (u->Account()->GetExtRegular("ns_set_email", new_email) && u->Account()->GetExtRegular("ns_set_email_passcode", passcode)) diff --git a/modules/core/ns_set_greet.cpp b/modules/core/ns_set_greet.cpp index f5c2a26ab..d36694791 100644 --- a/modules/core/ns_set_greet.cpp +++ b/modules/core/ns_set_greet.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetGreet : public Command { @@ -86,22 +87,25 @@ class NSSetGreet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetgreet); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetgreet); } ~NSSetGreet() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetgreet); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetgreet); } diff --git a/modules/core/ns_set_hide.cpp b/modules/core/ns_set_hide.cpp index b827b67fe..5d315d6fa 100644 --- a/modules/core/ns_set_hide.cpp +++ b/modules/core/ns_set_hide.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetHide : public Command { @@ -90,7 +91,7 @@ class CommandNSSetHide : public Command "user@host mask (\002USERMASK\002), your services access status\n" "(\002STATUS\002) and last quit message (\002QUIT\002).\n" "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), NickServ->nick.c_str()); + "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->s_NickServ.c_str()); return true; } @@ -117,7 +118,7 @@ class CommandNSSASetHide : public CommandNSSetHide "user@host mask (\002USERMASK\002), the services access status\n" "(\002STATUS\002) and last quit message (\002QUIT\002).\n" "The second parameter specifies whether the information should\n" - "be displayed (\002OFF\002) or hidden (\002ON\002)."), NickServ->nick.c_str()); + "be displayed (\002OFF\002) or hidden (\002ON\002)."), Config->s_NickServ.c_str()); return true; } @@ -138,22 +139,25 @@ class NSSetHide : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssethide); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasethide); } ~NSSetHide() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssethide); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasethide); } diff --git a/modules/core/ns_set_kill.cpp b/modules/core/ns_set_kill.cpp index c09228992..6b3952f37 100644 --- a/modules/core/ns_set_kill.cpp +++ b/modules/core/ns_set_kill.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetKill : public Command { @@ -85,7 +86,7 @@ class CommandNSSetKill : public Command "\002IMMED\002, user's nick will be changed immediately \037without\037 being\n" "warned first or given a chance to change their nick; please\n" "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), NickServ->nick.c_str()); + "network's administrators may have disabled this option."), Config->s_NickServ.c_str()); return true; } @@ -117,7 +118,7 @@ class CommandNSSASetKill : public CommandNSSetKill "\002IMMED\002, the user's nick will be changed immediately \037without\037 being\n" "warned first or given a chance to change their nick; please\n" "do not use this option unless necessary. Also, your\n" - "network's administrators may have disabled this option."), NickServ->nick.c_str()); + "network's administrators may have disabled this option."), Config->s_NickServ.c_str()); return true; } @@ -138,22 +139,25 @@ class NSSetKill : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetkill); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetkill); } ~NSSetKill() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetkill); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetkill); } diff --git a/modules/core/ns_set_language.cpp b/modules/core/ns_set_language.cpp index 1497ad498..e73bc6f97 100644 --- a/modules/core/ns_set_language.cpp +++ b/modules/core/ns_set_language.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetLanguage : public Command { @@ -113,22 +114,25 @@ class NSSetLanguage : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetlanguage); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetlanguage); } ~NSSetLanguage() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetlanguage); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetlanguage); } diff --git a/modules/core/ns_set_message.cpp b/modules/core/ns_set_message.cpp index 671398b11..e842e49bd 100644 --- a/modules/core/ns_set_message.cpp +++ b/modules/core/ns_set_message.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetMessage : public Command { @@ -102,22 +103,25 @@ class NSSetMessage : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetmessage); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetmessage); } ~NSSetMessage() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetmessage); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetmessage); } diff --git a/modules/core/ns_set_private.cpp b/modules/core/ns_set_private.cpp index efcd4da09..40fe2e7c0 100644 --- a/modules/core/ns_set_private.cpp +++ b/modules/core/ns_set_private.cpp @@ -12,13 +12,14 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetPrivate : public Command { public: CommandNSSetPrivate(const Anope::string &spermission = "") : Command("PRIVATE", 2, 2, spermission) { - this->SetDesc(Anope::printf(_("Prevent the nickname from appearing in a \002%s%s LIST\002"), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str())); + this->SetDesc(Anope::printf(_("Prevent the nickname from appearing in a \002%s%s LIST\002"), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str())); } CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -55,7 +56,7 @@ class CommandNSSetPrivate : public Command "nickname lists generated with %s's \002LIST\002 command.\n" "(However, anyone who knows your nickname can still get\n" "information on it using the \002INFO\002 command.)"), - NickServ->nick.c_str(), NickServ->nick.c_str()); + Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -81,7 +82,7 @@ class CommandNSSASetPrivate : public CommandNSSetPrivate "nickname lists generated with %s's \002LIST\002 command.\n" "(However, anyone who knows the nickname can still get\n" "information on it using the \002INFO\002 command.)"), - NickServ->nick.c_str(), NickServ->nick.c_str()); + Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -102,22 +103,25 @@ class NSSetPrivate : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetprivate); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetprivate); } ~NSSetPrivate() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetprivate); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetprivate); } diff --git a/modules/core/ns_set_secure.cpp b/modules/core/ns_set_secure.cpp index 62e7f88a9..f3e3128ac 100644 --- a/modules/core/ns_set_secure.cpp +++ b/modules/core/ns_set_secure.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetSecure : public Command { @@ -56,7 +57,7 @@ class CommandNSSetSecure : public Command "regardless of whether your address is on the access\n" "list. However, if you are on the access list, %s\n" "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), NickServ->nick.c_str(), NickServ->nick.c_str()); + "\002KILL\002 option."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -83,7 +84,7 @@ class CommandNSSASetSecure : public CommandNSSetSecure "regardless of whether your address is on the access\n" "list. However, if you are on the access list, %s\n" "will not auto-kill you regardless of the setting of the\n" - "\002KILL\002 option."), NickServ->nick.c_str(), NickServ->nick.c_str()); + "\002KILL\002 option."), Config->s_NickServ.c_str(), Config->s_NickServ.c_str()); return true; } @@ -104,22 +105,25 @@ class NSSetSecure : public Module this->SetAuthor("Anope"); this->SetType(CORE); - Command *c = FindCommand(NickServ, "SET"); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->AddSubcommand(this, &commandnssetsecure); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->AddSubcommand(this, &commandnssasetsecure); } ~NSSetSecure() { - Command *c = FindCommand(NickServ, "SET"); + Command *c = FindCommand(nickserv->Bot(), "SET"); if (c) c->DelSubcommand(&commandnssetsecure); - c = FindCommand(NickServ, "SASET"); + c = FindCommand(nickserv->Bot(), "SASET"); if (c) c->DelSubcommand(&commandnssasetsecure); } diff --git a/modules/core/ns_status.cpp b/modules/core/ns_status.cpp index fa04d92e2..a7710d326 100644 --- a/modules/core/ns_status.cpp +++ b/modules/core/ns_status.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSStatus : public Command { @@ -86,7 +87,10 @@ class NSStatus : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsstatus); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsstatus); } }; diff --git a/modules/core/ns_suspend.cpp b/modules/core/ns_suspend.cpp index 41eddb6f4..1692e88fc 100644 --- a/modules/core/ns_suspend.cpp +++ b/modules/core/ns_suspend.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSuspend : public Command { @@ -169,8 +170,11 @@ class NSSuspend : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnssuspend); - this->AddCommand(NickServ, &commandnsunsuspend); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnssuspend); + this->AddCommand(nickserv->Bot(), &commandnsunsuspend); } }; diff --git a/modules/core/ns_update.cpp b/modules/core/ns_update.cpp index ac7ba9a09..0146ec954 100644 --- a/modules/core/ns_update.cpp +++ b/modules/core/ns_update.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSUpdate : public Command { @@ -26,16 +27,11 @@ class CommandNSUpdate : public Command User *u = source.u; NickAlias *na = findnick(u->nick); - if (!na) - return MOD_CONT; - - do_setmodes(u); - check_memos(u); - na->last_realname = u->realname; na->last_seen = Anope::CurTime; - if (ircd->vhost) - do_on_id(u); + + FOREACH_MOD(I_OnNickUpdate, OnNickUpdate(u)); + source.Reply(_("Status updated (memos, vhost, chmodes, flags)."), Config->s_NickServ.c_str()); return MOD_CONT; } @@ -60,7 +56,10 @@ class NSUpdate : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(NickServ, &commandnsupdate); + if (!nickserv) + throw ModuleException("NickServ is not loaded!"); + + this->AddCommand(nickserv->Bot(), &commandnsupdate); } }; diff --git a/modules/core/operserv.h b/modules/core/operserv.h new file mode 100644 index 000000000..97436b789 --- /dev/null +++ b/modules/core/operserv.h @@ -0,0 +1,15 @@ +#ifndef OPERSERV_H +#define OPERSERV_H + +class OperServService : public Service +{ + public: + OperServService(Module *m) : Service(m, "OperServ") { } + + virtual BotInfo *Bot() = 0; +}; + +static service_reference<OperServService> operserv("OperServ"); + +#endif // OPERSERV_H + diff --git a/modules/core/os_akill.cpp b/modules/core/os_akill.cpp index a616695ce..076335840 100644 --- a/modules/core/os_akill.cpp +++ b/modules/core/os_akill.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class AkillDelCallback : public NumberList { @@ -172,33 +173,49 @@ class CommandOSAKill : public Command reason += " " + params[3]; if (!mask.empty() && !reason.empty()) { - User *user = finduser(mask); - if (user) - mask = "*@" + user->host; - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (Anope::Match(it->second->GetIdent() + "@" + it->second->host, mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { + std::pair<int, XLine *> canAdd = SGLine->CanAdd(mask, expires); + if (mask.find('!') != Anope::string::npos) + source.Reply(_("\002Reminder\002: AKILL masks cannot contain nicknames; make sure you have \002not\002 included a nick portion in your mask.")); + else if (mask.find('@') == Anope::string::npos) + source.Reply(_(BAD_USERHOST_MASK)); + else if (mask.find_first_not_of("~@.*?") == Anope::string::npos) source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to akill " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the AKILL list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + User *user = finduser(mask); + if (user) + mask = "*@" + user->host; + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (Anope::Match(it->second->GetIdent() + "@" + it->second->host, mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to akill " << percent << "% of the network (" << affected << " users)"; + return MOD_CONT; + } - XLine *x = SGLine->Add(OperServ, u, mask, expires, reason); + XLine *x = SGLine->Add(mask, u->nick, expires, reason); - if (!x) - return MOD_CONT; + if (!x) + return MOD_CONT; - source.Reply(_("\002%s\002 added to the AKILL list."), mask.c_str()); + source.Reply(_("\002%s\002 added to the AKILL list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (readonly) - source.Reply(_(READ_ONLY_MODE)); + if (readonly) + source.Reply(_(READ_ONLY_MODE)); + } } else this->OnSyntaxError(source, "ADD"); @@ -435,7 +452,10 @@ class OSAKill : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosakill); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosakill); } }; diff --git a/modules/core/os_chankill.cpp b/modules/core/os_chankill.cpp index 9c69973a4..5e3fab915 100644 --- a/modules/core/os_chankill.cpp +++ b/modules/core/os_chankill.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSChanKill : public Command { @@ -74,7 +75,7 @@ class CommandOSChanKill : public Command if (uc->user->HasMode(UMODE_OPER)) continue; - SGLine->Add(OperServ, u, "*@" + uc->user->host, expires, realreason); + SGLine->Add("*@" + uc->user->host, u->nick, expires, realreason); SGLine->Check(uc->user); } @@ -111,7 +112,10 @@ class OSChanKill : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandoschankill); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoschankill); } }; diff --git a/modules/core/os_chanlist.cpp b/modules/core/os_chanlist.cpp index 8ab6d509a..b70edf35a 100644 --- a/modules/core/os_chanlist.cpp +++ b/modules/core/os_chanlist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSChanList : public Command { @@ -97,9 +98,12 @@ class OSChanList : public Module OSChanList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { this->SetAuthor("Anope"); - this->SetType(CORE); + this->SetType(CORE); - this->AddCommand(OperServ, &commandoschanlist); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoschanlist); } }; diff --git a/modules/core/os_config.cpp b/modules/core/os_config.cpp index f0bfb69bd..a4e129ed5 100644 --- a/modules/core/os_config.cpp +++ b/modules/core/os_config.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSConfig : public Command { @@ -224,7 +225,10 @@ class OSConfig : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosconfig); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosconfig); } }; diff --git a/modules/core/os_defcon.cpp b/modules/core/os_defcon.cpp deleted file mode 100644 index 03a8f0de4..000000000 --- a/modules/core/os_defcon.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* OperServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -/*************************************************************************/ - -#include "module.h" - -void defcon_sendlvls(CommandSource &source); -void runDefCon(); -void defconParseModeString(const Anope::string &str); -void resetDefCon(int level); -static Anope::string defconReverseModes(const Anope::string &modes); - -class DefConTimeout : public Timer -{ - int level; - - public: - DefConTimeout(int newlevel) : Timer(Config->DefConTimeOut), level(newlevel) { } - - void Tick(time_t) - { - if (Config->DefConLevel != level) - { - Config->DefConLevel = level; - FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(level)); - Log(OperServ, "operserv/defcon") << "Defcon level timeout, returning to level " << level; - ircdproto->SendGlobops(OperServ, GetString(NULL, _("\002%s\002 Changed the DEFCON level to \002%d\002")).c_str(), Config->s_OperServ.c_str(), level); - - if (Config->GlobalOnDefcon) - { - if (!Config->DefConOffMessage.empty()) - oper_global("", "%s", Config->DefConOffMessage.c_str()); - else - oper_global("", GetString(NULL, _("The Defcon Level is now at Level: \002%d\002")).c_str(), Config->DefConLevel); - - if (Config->GlobalOnDefconMore && Config->DefConOffMessage.empty()) - oper_global("", "%s", Config->DefconMessage.c_str()); - } - - runDefCon(); - } - } -}; -static DefConTimeout *timeout; - -class CommandOSDefcon : public Command -{ - public: - CommandOSDefcon() : Command("DEFCON", 1, 1, "operserv/defcon") - { - this->SetDesc(_("Manipulate the DefCon system")); - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - const Anope::string &lvl = params[0]; - - if (lvl.empty()) - { - source.Reply(_("Services are now at DEFCON \002%d\002"), Config->DefConLevel); - defcon_sendlvls(source); - return MOD_CONT; - } - - int newLevel = 0; - try - { - newLevel = convertTo<int>(lvl); - } - catch (const ConvertException &) { } - - if (newLevel < 1 || newLevel > 5) - { - this->OnSyntaxError(source, ""); - return MOD_CONT; - } - - Config->DefConLevel = newLevel; - - FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(newLevel)); - - if (timeout) - { - delete timeout; - timeout = NULL; - } - - if (Config->DefConTimeOut) - timeout = new DefConTimeout(5); - - source.Reply(_("Services are now at DEFCON \002%d\002"), Config->DefConLevel); - defcon_sendlvls(source); - Log(LOG_ADMIN, u, this) << "to change defcon level to " << newLevel; - ircdproto->SendGlobops(OperServ, GetString(NULL, _("\002%s\002 Changed the DEFCON level to \002%d\002")).c_str(), u->nick.c_str(), newLevel); - /* Global notice the user what is happening. Also any Message that - the Admin would like to add. Set in config file. */ - if (Config->GlobalOnDefcon) - { - if (Config->DefConLevel == 5 && !Config->DefConOffMessage.empty()) - oper_global("", "%s", Config->DefConOffMessage.c_str()); - else - oper_global("", GetString(NULL, _("The Defcon Level is now at Level: \002%d\002")).c_str(), Config->DefConLevel); - } - if (Config->GlobalOnDefconMore) - { - if (Config->DefConOffMessage.empty() || Config->DefConLevel != 5) - oper_global("", "%s", Config->DefconMessage.c_str()); - } - /* Run any defcon functions, e.g. FORCE CHAN MODE */ - runDefCon(); - return MOD_CONT; - } - - bool OnHelp(CommandSource &source, const Anope::string &subcommand) - { - source.Reply(_("Syntax: \002DEFCON\002 [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]\n" - "The defcon system can be used to implement a pre-defined\n" - "set of restrictions to services useful during an attempted\n" - "attack on the network.")); - return true; - } - - void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) - { - SyntaxError(source, "DEFCON", _("DEFCON [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); - } -}; - -class OSDefcon : public Module -{ - CommandOSDefcon commandosdefcon; - - public: - OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) - { - if (!Config->DefConLevel) - throw ModuleException("Invalid configuration settings"); - - this->SetAuthor("Anope"); - this->SetType(CORE); - - Implementation i[] = { I_OnPreUserConnect, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommandRun, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate }; - ModuleManager::Attach(i, this, 8); - - this->AddCommand(OperServ, &commandosdefcon); - - defconParseModeString(Config->DefConChanModes); - } - - EventReturn OnPreUserConnect(User *u) - { - if (u->server->IsSynced() && CheckDefCon(DEFCON_AKILL_NEW_CLIENTS) && !u->server->IsULined()) - { - if (CheckDefCon(DEFCON_AKILL_NEW_CLIENTS)) - { - Log(OperServ, "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; - XLine *x = SGLine->Add(NULL, NULL, "*@" + u->host, Anope::CurTime + Config->DefConAKILL, !Config->DefConAkillReason.empty() ? Config->DefConAkillReason : "DEFCON AKILL"); - if (x) - x->By = Config->s_OperServ; - } - - if (CheckDefCon(DEFCON_NO_NEW_CLIENTS) || CheckDefCon(DEFCON_AKILL_NEW_CLIENTS)) - kill_user(Config->s_OperServ, u, Config->DefConAkillReason); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) - { - ChannelMode *cm = ModeManager::FindChannelModeByName(Name); - - if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesOff.HasFlag(Name)) - { - c->RemoveMode(OperServ, Name, param); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnChannelModeUnset(Channel *c, ChannelModeName Name, const Anope::string &) - { - ChannelMode *cm = ModeManager::FindChannelModeByName(Name); - - if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && cm && DefConModesOn.HasFlag(Name)) - { - Anope::string param; - - if (GetDefConParam(Name, param)) - c->SetMode(OperServ, Name, param); - else - c->SetMode(OperServ, Name); - - return EVENT_STOP; - - } - - return EVENT_CONTINUE; - } - - EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) - { - if (!u->HasMode(UMODE_OPER) && (CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY))) - { - if (!CheckDefCon(DEFCON_SILENT_OPER_ONLY)) - u->SendMessage(bi, _("Services are in Defcon mode, Please try again later.")); - - return EVENT_STOP; - } - - return EVENT_CONTINUE; - } - - EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) - { - BotInfo *service = source.owner; - if (service == NickServ) - { - if (command->name.equals_ci("REGISTER") || command->name.equals_ci("GROUP")) - { - if (CheckDefCon(DEFCON_NO_NEW_NICKS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } - } - } - else if (ChanServ && service == ChanServ) - { - if (command->name.equals_ci("SET")) - { - if (!params.empty() && params[0].equals_ci("MLOCK") && CheckDefCon(DEFCON_NO_MLOCK_CHANGE)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } - } - else if (command->name.equals_ci("REGISTER")) - { - if (CheckDefCon(DEFCON_NO_NEW_CHANNELS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } - } - } - else if (MemoServ && service == MemoServ) - { - if (command->name.equals_ci("SEND") || command->name.equals_ci("SENDALL")) - { - if (CheckDefCon(DEFCON_NO_NEW_MEMOS)) - { - source.Reply(_("Services are in Defcon mode, Please try again later.")); - return EVENT_STOP; - } - } - } - - return EVENT_CONTINUE; - } - - void OnUserConnect(User *u) - { - Session *session = findsession(u->host); - Exception *exception = find_hostip_exception(u->host, u->ip.addr()); - - if (CheckDefCon(DEFCON_REDUCE_SESSION) && !exception) - { - if (session && session->count > Config->DefConSessionLimit) - { - if (!Config->SessionLimitExceeded.empty()) - ircdproto->SendMessage(OperServ, u->nick, Config->SessionLimitExceeded.c_str(), u->host.c_str()); - if (!Config->SessionLimitDetailsLoc.empty()) - ircdproto->SendMessage(OperServ, u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); - - kill_user(Config->s_OperServ, u, "Session limit exceeded"); - ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) - { - SGLine->Add(NULL, NULL, "*@" + u->host, Anope::CurTime + Config->SessionAutoKillExpiry, "Session limit exceeded"); - ircdproto->SendGlobops(OperServ, "Added a temporary AKILL for \2*@%s\2 due to excessive connections", u->host.c_str()); - } - } - } - } - - void OnChannelModeAdd(ChannelMode *cm) - { - if (!Config->DefConChanModes.empty()) - { - Anope::string modes = Config->DefConChanModes; - - if (modes.find(cm->ModeChar) != Anope::string::npos) - /* New mode has been added to Anope, check to see if defcon - * requires it - */ - defconParseModeString(Config->DefConChanModes); - } - } - - void OnChannelCreate(Channel *c) - { - if (CheckDefCon(DEFCON_FORCE_CHAN_MODES)) - c->SetModes(OperServ, false, "%s", Config->DefConChanModes.c_str()); - } -}; - -/** - * Send a message to the oper about which precautions are "active" for this level - **/ -void defcon_sendlvls(CommandSource &source) -{ - if (CheckDefCon(DEFCON_NO_NEW_CHANNELS)) - source.Reply(_("* No new channel registrations")); - if (CheckDefCon(DEFCON_NO_NEW_NICKS)) - source.Reply(_("* No new nick registrations")); - if (CheckDefCon(DEFCON_NO_MLOCK_CHANGE)) - source.Reply(_("* No MLOCK changes")); - if (CheckDefCon(DEFCON_FORCE_CHAN_MODES) && !Config->DefConChanModes.empty()) - source.Reply(_("* Force Chan Modes (%s) to be set on all channels"), Config->DefConChanModes.c_str()); - if (CheckDefCon(DEFCON_REDUCE_SESSION)) - source.Reply(_("* Use the reduced session limit of %d"), Config->DefConSessionLimit); - if (CheckDefCon(DEFCON_NO_NEW_CLIENTS)) - source.Reply(_("* Kill any NEW clients connecting")); - if (CheckDefCon(DEFCON_OPER_ONLY)) - source.Reply(_("* Ignore any non-opers with message")); - if (CheckDefCon(DEFCON_SILENT_OPER_ONLY)) - source.Reply(_("* Silently ignore non-opers")); - if (CheckDefCon(DEFCON_AKILL_NEW_CLIENTS)) - source.Reply(_("* AKILL any new clients connecting")); - if (CheckDefCon(DEFCON_NO_NEW_MEMOS)) - source.Reply(_("* No new memos sent")); -} - -void runDefCon() -{ - if (CheckDefCon(DEFCON_FORCE_CHAN_MODES)) - { - if (!Config->DefConChanModes.empty() && !DefConModesSet) - { - if (Config->DefConChanModes[0] == '+' || Config->DefConChanModes[0] == '-') - { - Log(OperServ, "operserv/defcon") << "DEFCON: setting " << Config->DefConChanModes << " on all channels"; - DefConModesSet = true; - MassChannelModes(OperServ, Config->DefConChanModes); - } - } - } - else - { - if (!Config->DefConChanModes.empty() && DefConModesSet) - { - if (Config->DefConChanModes[0] == '+' || Config->DefConChanModes[0] == '-') - { - DefConModesSet = false; - Anope::string newmodes = defconReverseModes(Config->DefConChanModes); - if (!newmodes.empty()) - { - Log(OperServ, "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; - MassChannelModes(OperServ, newmodes); - } - } - } - } -} - -/* Parse the defcon mlock mode string and set the correct global vars. - * - * @param str mode string to parse - * @return 1 if accepted, 0 if failed - */ -void defconParseModeString(const Anope::string &str) -{ - int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ - unsigned char mode; - ChannelMode *cm; - ChannelModeParam *cmp; - Anope::string modes, param; - - if (str.empty()) - return; - - spacesepstream ss(str); - - DefConModesOn.ClearFlags(); - DefConModesOff.ClearFlags(); - ss.GetToken(modes); - - /* Loop while there are modes to set */ - for (unsigned i = 0, end = modes.length(); i < end; ++i) - { - mode = modes[i]; - - switch (mode) - { - case '+': - add = 1; - continue; - case '-': - add = 0; - continue; - default: - if (add < 0) - continue; - } - - if ((cm = ModeManager::FindChannelModeByChar(mode))) - { - if (cm->Type == MODE_STATUS || cm->Type == MODE_LIST || !cm->CanSet(NULL)) - { - Log() << "DefConChanModes mode character '" << mode << "' cannot be locked"; - continue; - } - else if (add) - { - DefConModesOn.SetFlag(cm->Name); - DefConModesOff.UnsetFlag(cm->Name); - - if (cm->Type == MODE_PARAM) - { - cmp = debug_cast<ChannelModeParam *>(cm); - - if (!ss.GetToken(param)) - { - Log() << "DefConChanModes mode character '" << mode << "' has no parameter while one is expected"; - continue; - } - - if (!cmp->IsValid(param)) - continue; - - SetDefConParam(cmp->Name, param); - } - } - else - { - if (DefConModesOn.HasFlag(cm->Name)) - { - DefConModesOn.UnsetFlag(cm->Name); - - if (cm->Type == MODE_PARAM) - UnsetDefConParam(cm->Name); - } - } - } - } - - /* We can't mlock +L if +l is not mlocked as well. */ - if ((cm = ModeManager::FindChannelModeByName(CMODE_REDIRECT)) && DefConModesOn.HasFlag(cm->Name) && !DefConModesOn.HasFlag(CMODE_LIMIT)) - { - DefConModesOn.UnsetFlag(CMODE_REDIRECT); - - Log() << "DefConChanModes must lock mode +l as well to lock mode +L"; - } - - /* Some ircd we can't set NOKNOCK without INVITE */ - /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */ - if (ircd->knock_needs_i && (cm = ModeManager::FindChannelModeByName(CMODE_NOKNOCK)) && DefConModesOn.HasFlag(cm->Name) && !DefConModesOn.HasFlag(CMODE_INVITE)) - { - DefConModesOn.UnsetFlag(CMODE_NOKNOCK); - Log() << "DefConChanModes must lock mode +i as well to lock mode +K"; - } -} - -static Anope::string defconReverseModes(const Anope::string &modes) -{ - if (modes.empty()) - return ""; - Anope::string newmodes; - for (unsigned i = 0, end = modes.length(); i < end; ++i) - { - if (modes[i] == '+') - newmodes += '-'; - else if (modes[i] == '-') - newmodes += '+'; - else - newmodes += modes[i]; - } - return newmodes; -} - -MODULE_INIT(OSDefcon) diff --git a/modules/core/os_help.cpp b/modules/core/os_help.cpp index b64a614b9..3694ad3ff 100644 --- a/modules/core/os_help.cpp +++ b/modules/core/os_help.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSHelp : public Command { @@ -23,18 +24,18 @@ class CommandOSHelp : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - mod_help_cmd(OperServ, source.u, NULL, params[0]); + mod_help_cmd(operserv->Bot(), source.u, NULL, params[0]); return MOD_CONT; } void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) { User *u = source.u; - source.Reply(_("%s commands:"), OperServ->nick.c_str()); - for (CommandMap::const_iterator it = OperServ->Commands.begin(), it_end = OperServ->Commands.end(); it != it_end; ++it) + source.Reply(_("%s commands:"), Config->s_OperServ.c_str()); + for (CommandMap::const_iterator it = operserv->Bot()->Commands.begin(), it_end = operserv->Bot()->Commands.end(); it != it_end; ++it) if (!Config->HidePrivilegedCommands || it->second->permission.empty() || u->HasCommand(it->second->permission)) it->second->OnServHelp(source); - source.Reply(_("\002Notice:\002 All commands sent to %s are logged!"), OperServ->nick.c_str()); + source.Reply(_("\002Notice:\002 All commands sent to %s are logged!"), Config->s_OperServ.c_str()); } }; @@ -48,7 +49,10 @@ class OSHelp : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandoshelp); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoshelp); } }; diff --git a/modules/core/os_ignore.cpp b/modules/core/os_ignore.cpp index ae5ea008a..cd55677cc 100644 --- a/modules/core/os_ignore.cpp +++ b/modules/core/os_ignore.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" #include "os_ignore.h" class OSIgnoreService : public IgnoreService @@ -292,7 +293,10 @@ class OSIgnore : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosignore); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosignore); Implementation i[] = { I_OnDatabaseRead, I_OnDatabaseWrite, I_OnPreCommandRun, I_OnBotPrivmsg }; ModuleManager::Attach(i, this, 4); diff --git a/modules/core/os_jupe.cpp b/modules/core/os_jupe.cpp index 31e301ee0..7eab7d009 100644 --- a/modules/core/os_jupe.cpp +++ b/modules/core/os_jupe.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSJupe : public Command { @@ -76,7 +77,10 @@ class OSJupe : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosjupe); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosjupe); } }; diff --git a/modules/core/os_kick.cpp b/modules/core/os_kick.cpp index d29573285..38eda21b8 100644 --- a/modules/core/os_kick.cpp +++ b/modules/core/os_kick.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSKick : public Command { @@ -46,7 +47,7 @@ class CommandOSKick : public Command return MOD_CONT; } - c->Kick(OperServ, u2, "%s (%s)", u->nick.c_str(), s.c_str()); + c->Kick(operserv->Bot(), u2, "%s (%s)", u->nick.c_str(), s.c_str()); Log(LOG_ADMIN, u, this) << "on " << u2->nick << " in " << c->name; return MOD_CONT; } @@ -60,7 +61,7 @@ class CommandOSKick : public Command "command. The kick message will have the nickname of the\n" "IRCop sending the KICK command prepended; for example:\n" " \n" - "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), OperServ->nick.c_str()); + "*** SpamMan has been kicked off channel #my_channel by %s (Alcan (Flood))"), Config->s_OperServ.c_str()); return true; } @@ -80,7 +81,10 @@ class OSKick : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandoskick); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoskick); } }; diff --git a/modules/core/os_login.cpp b/modules/core/os_login.cpp index fcbae9cfe..fd96165c2 100644 --- a/modules/core/os_login.cpp +++ b/modules/core/os_login.cpp @@ -13,13 +13,14 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSLogin : public Command { public: CommandOSLogin() : Command("LOGIN", 1, 1) { - this->SetDesc(Anope::printf(_("Login to %s"), OperServ->nick.c_str())); + this->SetDesc(Anope::printf(_("Login to %s"), Config->s_OperServ.c_str())); } CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) @@ -40,7 +41,7 @@ class CommandOSLogin : public Command } else { - Log(LOG_ADMIN, source.u, this) << "and succesfully identified to " << OperServ->nick; + Log(LOG_ADMIN, source.u, this) << "and succesfully identified to " << Config->s_OperServ; source.u->Extend("os_login_password_correct"); source.Reply(_("Password accepted.")); } @@ -54,7 +55,7 @@ class CommandOSLogin : public Command " \n" "Logs you in to %s so you gain Services Operator privileges.\n" "This command may be unnecessary if your oper block is\n" - "configured without a password."), OperServ->nick.c_str()); + "configured without a password."), Config->s_OperServ.c_str()); return true; } @@ -74,7 +75,10 @@ class OSLogin : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandoslogin); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoslogin); } }; diff --git a/modules/core/os_main.cpp b/modules/core/os_main.cpp new file mode 100644 index 000000000..4659fdf57 --- /dev/null +++ b/modules/core/os_main.cpp @@ -0,0 +1,137 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "operserv.h" + +static BotInfo *OperServ = NULL; + +class OperServBotInfo : public BotInfo +{ + public: + OperServBotInfo(const Anope::string &bnick, const Anope::string &user = "", const Anope::string &bhost = "", const Anope::string &real = "") : BotInfo(bnick, user, bhost, real) { } + + void OnMessage(User *u, const Anope::string &message) + { + if (!u->HasMode(UMODE_OPER) && Config->OSOpersOnly) + { + PushLanguage("anope", u->Account() ? u->Account()->language : ""); + u->SendMessage(OperServ, _(ACCESS_DENIED)); + PopLanguage(); + if (Config->WallBadOS) + ircdproto->SendGlobops(this, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); + } + else + { + Log(OperServ) << u->nick << ": " << message; + BotInfo::OnMessage(u, message); + } + } +}; + +class MyOperServService : public OperServService +{ + public: + MyOperServService(Module *m) : OperServService(m) { } + + BotInfo *Bot() + { + return OperServ; + } +}; + +class OperServCore : public Module +{ + MyOperServService myoperserv; + + public: + OperServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), myoperserv(this) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + this->SetPermanent(true); // Currently, /os modunload os_main explodes for obvious reasons + + Implementation i[] = { I_OnServerQuit, I_OnUserModeSet, I_OnUserModeUnset, I_OnUserConnect }; + ModuleManager::Attach(i, this, 4); + + ModuleManager::RegisterService(&this->myoperserv); + + OperServ = new OperServBotInfo(Config->s_OperServ, Config->ServiceUser, Config->ServiceHost, Config->desc_OperServ); + OperServ->SetFlag(BI_CORE); + + /* Yes, these are in this order for a reason. Most violent->least violent. */ + XLineManager::RegisterXLineManager(SGLine = new SGLineManager()); + XLineManager::RegisterXLineManager(SZLine = new SZLineManager()); + XLineManager::RegisterXLineManager(SQLine = new SQLineManager()); + XLineManager::RegisterXLineManager(SNLine = new SNLineManager()); + + spacesepstream coreModules(Config->OperCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + ModuleManager::LoadModule(module, NULL); + } + + ~OperServCore() + { + spacesepstream coreModules(Config->OperCoreModules); + Anope::string module; + while (coreModules.GetToken(module)) + { + Module *m = FindModule(module); + if (m != NULL) + ModuleManager::UnloadModule(m, NULL); + } + + delete SGLine; + SGLine = NULL; + delete SZLine; + SZLine = NULL; + delete SQLine; + SQLine = NULL; + delete SNLine; + SNLine = NULL; + + delete OperServ; + } + + void OnServerQuit(Server *server) + { + if (server->HasFlag(SERVER_JUPED)) + ircdproto->SendGlobops(operserv->Bot(), "Received SQUIT for juped server %s", server->GetName().c_str()); + } + + void OnUserModeSet(User *u, UserModeName Name) + { + if (Name == UMODE_OPER) + { + if (Config->WallOper) + ircdproto->SendGlobops(OperServ, "\2%s\2 is now an IRC operator.", u->nick.c_str()); + Log(OperServ) << u->nick << " is now an IRC operator"; + } + } + + void OnUserModeUnset(User *u, UserModeName Name) + { + if (Name == UMODE_OPER) + Log(OperServ) << u->nick << " is no longer an IRC operator"; + } + + void OnUserConnect(dynamic_reference<User> &u, bool &exempt) + { + if (u && !exempt) + XLineManager::CheckAll(u); + } +}; + +MODULE_INIT(OperServCore) + diff --git a/modules/core/os_mode.cpp b/modules/core/os_mode.cpp index 476eef032..5efed5383 100644 --- a/modules/core/os_mode.cpp +++ b/modules/core/os_mode.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSMode : public Command { @@ -36,7 +37,7 @@ class CommandOSMode : public Command source.Reply(_("Services is unable to change modes. Are your servers' U:lines configured correctly?")); else { - c->SetModes(OperServ, false, modes.c_str()); + c->SetModes(operserv->Bot(), false, modes.c_str()); Log(LOG_ADMIN, u, this) << modes << " on " << target; } @@ -48,10 +49,10 @@ class CommandOSMode : public Command source.Reply(_(NICK_X_NOT_IN_USE), target.c_str()); else { - u2->SetModes(OperServ, "%s", modes.c_str()); + u2->SetModes(operserv->Bot(), "%s", modes.c_str()); source.Reply(_("Changed usermodes of \002%s\002 to %s."), u2->nick.c_str(), modes.c_str()); - u2->SendMessage(OperServ, _("\002%s\002 changed your usermodes to %s."), u->nick.c_str(), modes.c_str()); + u2->SendMessage(operserv->Bot(), _("\002%s\002 changed your usermodes to %s."), u->nick.c_str(), modes.c_str()); Log(LOG_ADMIN, u, this) << modes << " on " << target; } @@ -86,7 +87,10 @@ class OSMode : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosmode); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmode); } }; diff --git a/modules/core/os_modinfo.cpp b/modules/core/os_modinfo.cpp index 2817b8f72..6634d2939 100644 --- a/modules/core/os_modinfo.cpp +++ b/modules/core/os_modinfo.cpp @@ -12,16 +12,14 @@ /*************************************************************************/ #include "module.h" - +#include "operserv.h" class CommandOSModInfo : public Command { - int showModuleCmdLoaded(BotInfo *bi, const Anope::string &mod_name, CommandSource &source) + void showModuleCmdLoaded(BotInfo *bi, const Anope::string &mod_name, CommandSource &source) { if (!bi) - return 0; - - int display = 0; + return; for (CommandMap::iterator it = bi->Commands.begin(), it_end = bi->Commands.end(); it != it_end; ++it) { @@ -30,11 +28,8 @@ class CommandOSModInfo : public Command if (c->module && c->module->name.equals_ci(mod_name) && c->service) { source.Reply(_("Providing command: %\002%s %s\002"), c->service->nick.c_str(), c->name.c_str()); - ++display; } } - - return display; } public: @@ -52,12 +47,8 @@ class CommandOSModInfo : public Command { source.Reply(_("Module: \002%s\002 Version: \002%s\002 Author: \002%s\002 loaded: \002%s\002"), m->name.c_str(), !m->version.empty() ? m->version.c_str() : "?", !m->author.empty() ? m->author.c_str() : "?", do_strftime(m->created).c_str()); - showModuleCmdLoaded(HostServ, m->name, source); - showModuleCmdLoaded(OperServ, m->name, source); - showModuleCmdLoaded(NickServ, m->name, source); - showModuleCmdLoaded(ChanServ, m->name, source); - showModuleCmdLoaded(BotServ, m->name, source); - showModuleCmdLoaded(MemoServ, m->name, source); + for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + this->showModuleCmdLoaded(it->second, m->name, source); } else source.Reply(_("No information about module \002%s\002 is available"), file.c_str()); @@ -89,7 +80,10 @@ class OSModInfo : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosmodinfo); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmodinfo); } }; diff --git a/modules/core/os_modlist.cpp b/modules/core/os_modlist.cpp index 5d8ab6450..cb3afbd65 100644 --- a/modules/core/os_modlist.cpp +++ b/modules/core/os_modlist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSModList : public Command { @@ -225,7 +226,10 @@ class OSModList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosmodlist); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmodlist); } }; diff --git a/modules/core/os_modload.cpp b/modules/core/os_modload.cpp index ed1041564..ff41b5235 100644 --- a/modules/core/os_modload.cpp +++ b/modules/core/os_modload.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSModLoad : public Command { @@ -36,7 +37,7 @@ class CommandOSModLoad : public Command ModuleReturn status = ModuleManager::LoadModule(mname, u); if (status == MOD_ERR_OK) { - ircdproto->SendGlobops(OperServ, "%s loaded module %s", u->nick.c_str(), mname.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "%s loaded module %s", u->nick.c_str(), mname.c_str()); source.Reply(_("Module \002%s\002 loaded"), mname.c_str()); /* If a user is loading this module, then the core databases have already been loaded @@ -78,7 +79,10 @@ class OSModLoad : public Module this->SetType(CORE); this->SetPermanent(true); - this->AddCommand(OperServ, &commandosmodload); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmodload); } }; diff --git a/modules/core/os_modreload.cpp b/modules/core/os_modreload.cpp index 43625d980..e721f76a9 100644 --- a/modules/core/os_modreload.cpp +++ b/modules/core/os_modreload.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSModReLoad : public Command { @@ -58,7 +59,7 @@ class CommandOSModReLoad : public Command status = ModuleManager::LoadModule(mname, u); if (status == MOD_ERR_OK) { - ircdproto->SendGlobops(OperServ, "%s reloaded module %s", u->nick.c_str(), mname.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "%s reloaded module %s", u->nick.c_str(), mname.c_str()); source.Reply(_("Module \002%s\002 reloaded"), mname.c_str()); /* If a user is loading this module, then the core databases have already been loaded @@ -104,7 +105,10 @@ class OSModReLoad : public Module this->SetType(CORE); this->SetPermanent(true); - this->AddCommand(OperServ, &commandosmodreload); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmodreload); } }; diff --git a/modules/core/os_modunload.cpp b/modules/core/os_modunload.cpp index 6a9bc9cb9..a2045c555 100644 --- a/modules/core/os_modunload.cpp +++ b/modules/core/os_modunload.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSModUnLoad : public Command { @@ -52,7 +53,7 @@ class CommandOSModUnLoad : public Command if (status == MOD_ERR_OK) { source.Reply(_("Module \002%s\002 unloaded"), mname.c_str()); - ircdproto->SendGlobops(OperServ, "%s unloaded module %s", u->nick.c_str(), mname.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "%s unloaded module %s", u->nick.c_str(), mname.c_str()); } else source.Reply(_("Unable to remove module \002%s\002"), mname.c_str()); @@ -86,7 +87,10 @@ class OSModUnLoad : public Module this->SetType(CORE); this->SetPermanent(true); - this->AddCommand(OperServ, &commandosmodunload); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosmodunload); } }; diff --git a/modules/core/os_news.cpp b/modules/core/os_news.cpp index f67a2a9ca..1cf3e0edf 100644 --- a/modules/core/os_news.cpp +++ b/modules/core/os_news.cpp @@ -12,6 +12,8 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" +#include "global.h" #define lenof(a) (sizeof(a) / sizeof(*(a))) @@ -95,7 +97,7 @@ static void DisplayNews(User *u, NewsType Type) if (Type == NEWS_RANDOM && i == current_news) continue; - u->SendMessage(Type != NEWS_OPER && Global ? Global : OperServ, msg.c_str(), do_strftime(News[i]->time).c_str(), News[i]->Text.c_str()); + u->SendMessage(Type != NEWS_OPER && global ? global->Bot() : operserv->Bot(), msg.c_str(), do_strftime(News[i]->time).c_str(), News[i]->Text.c_str()); ++displayed; @@ -406,9 +408,12 @@ class OSNews : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandoslogonnews); - this->AddCommand(OperServ, &commandosopernews); - this->AddCommand(OperServ, &commandosrandomnews); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandoslogonnews); + this->AddCommand(operserv->Bot(), &commandosopernews); + this->AddCommand(operserv->Bot(), &commandosrandomnews); Implementation i[] = { I_OnUserModeSet, I_OnUserConnect, I_OnDatabaseRead, I_OnDatabaseWrite }; ModuleManager::Attach(i, this, 4); @@ -427,10 +432,13 @@ class OSNews : public Module DisplayNews(u, NEWS_OPER); } - void OnUserConnect(User *u) + void OnUserConnect(dynamic_reference<User> &user, bool &) { - DisplayNews(u, NEWS_LOGON); - DisplayNews(u, NEWS_RANDOM); + if (!user) + return; + + DisplayNews(user, NEWS_LOGON); + DisplayNews(user, NEWS_RANDOM); } EventReturn OnDatabaseRead(const std::vector<Anope::string> ¶ms) diff --git a/modules/core/os_noop.cpp b/modules/core/os_noop.cpp index a3269d121..e86508d49 100644 --- a/modules/core/os_noop.cpp +++ b/modules/core/os_noop.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSNOOP : public Command { @@ -90,7 +91,10 @@ class OSNOOP : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosnoop); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosnoop); } }; diff --git a/modules/core/os_oline.cpp b/modules/core/os_oline.cpp index 8ed74ffb3..0e4835cff 100644 --- a/modules/core/os_oline.cpp +++ b/modules/core/os_oline.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSOLine : public Command { @@ -34,16 +35,16 @@ class CommandOSOLine : public Command else if (u2 && flag[0] == '+') { ircdproto->SendSVSO(Config->s_OperServ, nick, flag); - u2->SetMode(OperServ, UMODE_OPER); - u2->SendMessage(OperServ, _("You are now an IRC Operator.")); + u2->SetMode(operserv->Bot(), UMODE_OPER); + u2->SendMessage(operserv->Bot(), _("You are now an IRC Operator.")); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); - ircdproto->SendGlobops(OperServ, "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); } else if (u2 && flag[0] == '-') { ircdproto->SendSVSO(Config->s_OperServ, nick, flag); source.Reply(_("Operflags \002%s\002 have been added for \002%s\002."), flag.c_str(), nick.c_str()); - ircdproto->SendGlobops(OperServ, "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "\2%s\2 used OLINE for %s", u->nick.c_str(), nick.c_str()); } else this->OnSyntaxError(source, ""); @@ -77,10 +78,13 @@ class OSOLine : public Module if (!ircd->omode) throw ModuleException("Your IRCd does not support OMODE."); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosoline); + this->AddCommand(operserv->Bot(), &commandosoline); } }; diff --git a/modules/core/os_quit.cpp b/modules/core/os_quit.cpp index ed85467c4..d21ac78be 100644 --- a/modules/core/os_quit.cpp +++ b/modules/core/os_quit.cpp @@ -13,6 +13,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSQuit : public Command { @@ -26,9 +27,6 @@ class CommandOSQuit : public Command { User *u = source.u; quitmsg = "QUIT command received from " + u->nick; - - if (Config->GlobalOnCycle) - oper_global("", "%s", Config->GlobalOnCycleMessage.c_str()); quitting = true; return MOD_CONT; } @@ -56,7 +54,10 @@ class OSQuit : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosquit); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosquit); } }; diff --git a/modules/core/os_reload.cpp b/modules/core/os_reload.cpp index 9b00ea8d8..08bb78444 100644 --- a/modules/core/os_reload.cpp +++ b/modules/core/os_reload.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSReload : public Command { @@ -23,16 +24,18 @@ class CommandOSReload : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { + ServerConfig *old_config = Config; + try { - ServerConfig *newconfig = new ServerConfig(); - delete Config; - Config = newconfig; - FOREACH_MOD(I_OnReload, OnReload(false)); + Config = new ServerConfig(); + FOREACH_MOD(I_OnReload, OnReload()); + delete old_config; source.Reply(_("Services' configuration file has been reloaded.")); } catch (const ConfigException &ex) { + Config = old_config; Log() << "Error reloading configuration file: " << ex.GetReason(); source.Reply(_("Error reloading confguration file: ") + ex.GetReason()); } @@ -61,7 +64,10 @@ class OSReload : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosreload); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosreload); } }; diff --git a/modules/core/os_restart.cpp b/modules/core/os_restart.cpp index 02663e862..73c36d21e 100644 --- a/modules/core/os_restart.cpp +++ b/modules/core/os_restart.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSRestart : public Command { @@ -25,9 +26,6 @@ class CommandOSRestart : public Command { User *u = source.u; quitmsg = "RESTART command received from " + u->nick; - - if (Config->GlobalOnCycle) - oper_global("", "%s", Config->GlobalOnCycleMessage.c_str()); do_restart_services(); return MOD_CONT; } @@ -52,7 +50,10 @@ class OSRestart : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosrestart); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosrestart); } }; diff --git a/modules/core/os_session.cpp b/modules/core/os_session.cpp index 8090efe10..4a3695796 100644 --- a/modules/core/os_session.cpp +++ b/modules/core/os_session.cpp @@ -12,6 +12,33 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" +#include "os_session.h" + +static service_reference<SessionService> sessionservice("session"); + +class ExpireTimer : public Timer +{ + public: + ExpireTimer() : Timer(Config->ExpireTimeout, Anope::CurTime, true) { } + + void Tick(time_t) + { + if (!sessionservice) + return; + for (unsigned i = sessionservice->GetExceptions().size(); i > 0; --i) + { + Exception *e = sessionservice->GetExceptions()[i - 1]; + + if (!e->expires || e->expires > Anope::CurTime) + continue; + if (Config->WallExceptionExpire) + ircdproto->SendGlobops(operserv->Bot(), "Session exception for %s has expired.", e->mask.c_str()); + sessionservice->DelException(e); + delete e; + } + } +}; class ExceptionDelCallback : public NumberList { @@ -35,7 +62,7 @@ class ExceptionDelCallback : public NumberList virtual void HandleNumber(unsigned Number) { - if (!Number || Number > exceptions.size()) + if (!Number || Number > sessionservice->GetExceptions().size()) return; ++Deleted; @@ -45,10 +72,10 @@ class ExceptionDelCallback : public NumberList static void DoDel(CommandSource &source, unsigned index) { - FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(source.u, exceptions[index])); + FOREACH_MOD(I_OnExceptionDel, OnExceptionDel(source.u, sessionservice->GetExceptions()[index])); - delete exceptions[index]; - exceptions.erase(exceptions.begin() + index); + sessionservice->DelException(sessionservice->GetExceptions()[index]); + delete sessionservice->GetExceptions()[index]; } }; @@ -64,7 +91,7 @@ class ExceptionListCallback : public NumberList virtual void HandleNumber(unsigned Number) { - if (!Number || Number > exceptions.size()) + if (!Number || Number > sessionservice->GetExceptions().size()) return; if (!SentHeader) @@ -79,10 +106,10 @@ class ExceptionListCallback : public NumberList static void DoList(CommandSource &source, unsigned index) { - if (index >= exceptions.size()) + if (index >= sessionservice->GetExceptions().size()) return; - source.Reply(_("%3d %4d %s"), index + 1, exceptions[index]->limit, exceptions[index]->mask.c_str()); + source.Reply(_("%3d %4d %s"), index + 1, sessionservice->GetExceptions()[index]->limit, sessionservice->GetExceptions()[index]->mask.c_str()); } }; @@ -95,7 +122,7 @@ class ExceptionViewCallback : public ExceptionListCallback void HandleNumber(unsigned Number) { - if (!Number || Number > exceptions.size()) + if (!Number || Number > sessionservice->GetExceptions().size()) return; if (!SentHeader) @@ -109,12 +136,12 @@ class ExceptionViewCallback : public ExceptionListCallback static void DoList(CommandSource &source, unsigned index) { - if (index >= exceptions.size()) + if (index >= sessionservice->GetExceptions().size()) return; - Anope::string expirebuf = expire_left(source.u->Account(), exceptions[index]->expires); + Anope::string expirebuf = expire_left(source.u->Account(), sessionservice->GetExceptions()[index]->expires); - source.Reply(_("%3d. %s (by %s on %s; %s)\n " " Limit: %-4d - %s"), index + 1, exceptions[index]->mask.c_str(), !exceptions[index]->who.empty() ? exceptions[index]->who.c_str() : "<unknown>", do_strftime((exceptions[index]->time ? exceptions[index]->time : Anope::CurTime)).c_str(), expirebuf.c_str(), exceptions[index]->limit, exceptions[index]->reason.c_str()); + source.Reply(_("%3d. %s (by %s on %s; %s)\n " " Limit: %-4d - %s"), index + 1, sessionservice->GetExceptions()[index]->mask.c_str(), !sessionservice->GetExceptions()[index]->who.empty() ? sessionservice->GetExceptions()[index]->who.c_str() : "<unknown>", do_strftime((sessionservice->GetExceptions()[index]->time ? sessionservice->GetExceptions()[index]->time : Anope::CurTime)).c_str(), expirebuf.c_str(), sessionservice->GetExceptions()[index]->limit, sessionservice->GetExceptions()[index]->reason.c_str()); } }; @@ -139,7 +166,7 @@ class CommandOSSession : public Command source.Reply(_("Hosts with at least \002%d\002 sessions:"), mincount); source.Reply(_("Sessions Host")); - for (Anope::map<Session *>::iterator it = SessionList.begin(), it_end = SessionList.end(); it != it_end; ++it) + for (SessionService::SessionMap::iterator it = sessionservice->GetSessions().begin(), it_end = sessionservice->GetSessions().end(); it != it_end; ++it) { Session *session = it->second; @@ -154,13 +181,13 @@ class CommandOSSession : public Command CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) { Anope::string param = params[1]; - Session *session = findsession(param); + Session *session = sessionservice->FindSession(param); if (!session) source.Reply(_("\002%s\002 not found on session list."), param.c_str()); else { - Exception *exception = find_host_exception(param); + Exception *exception = sessionservice->FindException(param); source.Reply(_("The host \002%s\002 currently has \002%d\002 sessions with a limit of \002%d\002."), param.c_str(), session->count, exception ? exception-> limit : Config->DefSessionLimit); } @@ -225,7 +252,6 @@ class CommandOSException : public Command User *u = source.u; Anope::string mask, expiry, limitstr; unsigned last_param = 3; - int x; mask = params.size() > 1 ? params[1] : ""; if (!mask.empty() && mask[0] == '+') @@ -277,17 +303,44 @@ class CommandOSException : public Command { if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) { - source.Reply(_("Invalid hostmask. Only real hostmasks are valid as exceptions are not matched against nicks or usernames.")); + source.Reply(_("Invalid hostmask. Only real hostmasks are valid as sessionservice->GetExceptions() are not matched against nicks or usernames.")); return MOD_CONT; } - x = exception_add(u, mask, limit, reason, u->nick, expires); + for (std::vector<Exception *>::iterator it = sessionservice->GetExceptions().begin(), it_end = sessionservice->GetExceptions().end(); it != it_end; ++it) + { + Exception *e = *it; + if (e->mask.equals_ci(mask)) + { + if (e->limit != limit) + { + e->limit = limit; + source.Reply(_("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); + } + else + source.Reply(_("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); + } + } - if (x == 1) + Exception *exception = new Exception(); + exception->mask = mask; + exception->limit = limit; + exception->reason = reason; + exception->time = Anope::CurTime; + exception->who = u->nick; + exception->expires = expires; + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(exception)); + if (MOD_RESULT == EVENT_STOP) + delete exception; + else + { + sessionservice->AddException(exception); source.Reply(_("Session limit for \002%s\002 set to \002%d\002."), mask.c_str(), limit); - - if (readonly) - source.Reply(_(READ_ONLY_MODE)); + if (readonly) + source.Reply(_(READ_ONLY_MODE)); + } } return MOD_CONT; @@ -310,9 +363,9 @@ class CommandOSException : public Command } else { - unsigned i = 0, end = exceptions.size(); + unsigned i = 0, end = sessionservice->GetExceptions().size(); for (; i < end; ++i) - if (mask.equals_ci(exceptions[i]->mask)) + if (mask.equals_ci(sessionservice->GetExceptions()[i]->mask)) { ExceptionDelCallback::DoDel(source, i); source.Reply(_("\002%s\002 deleted from session-limit exception list."), mask.c_str()); @@ -348,13 +401,13 @@ class CommandOSException : public Command } catch (const ConvertException &) { } - if (n1 >= 0 && n1 < exceptions.size() && n2 >= 0 && n2 < exceptions.size() && n1 != n2) + if (n1 >= 0 && n1 < sessionservice->GetExceptions().size() && n2 >= 0 && n2 < sessionservice->GetExceptions().size() && n1 != n2) { - Exception *temp = exceptions[n1]; - exceptions[n1] = exceptions[n2]; - exceptions[n2] = temp; + Exception *temp = sessionservice->GetExceptions()[n1]; + sessionservice->GetExceptions()[n1] = sessionservice->GetExceptions()[n2]; + sessionservice->GetExceptions()[n2] = temp; - source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), exceptions[n1]->mask.c_str(), n1 + 1, n2 + 1); + source.Reply(_("Exception for \002%s\002 (#%d) moved to position \002%d\002."), sessionservice->GetExceptions()[n1]->mask.c_str(), n1 + 1, n2 + 1); if (readonly) source.Reply(_(READ_ONLY_MODE)); @@ -367,7 +420,6 @@ class CommandOSException : public Command CommandReturn DoList(CommandSource &source, const std::vector<Anope::string> ¶ms) { - expire_exceptions(); Anope::string mask = params.size() > 1 ? params[1] : ""; if (!mask.empty() && mask.find_first_not_of("1234567890,-") == Anope::string::npos) @@ -379,8 +431,8 @@ class CommandOSException : public Command { bool SentHeader = false; - for (unsigned i = 0, end = exceptions.size(); i < end; ++i) - if (mask.empty() || Anope::Match(exceptions[i]->mask, mask)) + for (unsigned i = 0, end = sessionservice->GetExceptions().size(); i < end; ++i) + if (mask.empty() || Anope::Match(sessionservice->GetExceptions()[i]->mask, mask)) { if (!SentHeader) { @@ -401,7 +453,6 @@ class CommandOSException : public Command CommandReturn DoView(CommandSource &source, const std::vector<Anope::string> ¶ms) { - expire_exceptions(); Anope::string mask = params.size() > 1 ? params[1] : ""; if (!mask.empty() && mask.find_first_not_of("1234567890,-") == Anope::string::npos) @@ -413,8 +464,8 @@ class CommandOSException : public Command { bool SentHeader = false; - for (unsigned i = 0, end = exceptions.size(); i < end; ++i) - if (mask.empty() || Anope::Match(exceptions[i]->mask, mask)) + for (unsigned i = 0, end = sessionservice->GetExceptions().size(); i < end; ++i) + if (mask.empty() || Anope::Match(sessionservice->GetExceptions()[i]->mask, mask)) { if (!SentHeader) { @@ -431,6 +482,7 @@ class CommandOSException : public Command return MOD_CONT; } + public: CommandOSException() : Command("EXCEPTION", 1, 5) { @@ -491,10 +543,10 @@ class CommandOSException : public Command "the format of the optional \037expiry\037 parameter.\n" "\002EXCEPTION DEL\002 removes the given mask from the exception list.\n" "\002EXCEPTION MOVE\002 moves exception \037num\037 to \037position\037. The\n" - "exceptions inbetween will be shifted up or down to fill the gap.\n" + "sessionservice->GetExceptions() inbetween will be shifted up or down to fill the gap.\n" "\002EXCEPTION LIST\002 and \002EXCEPTION VIEW\002 show all current\n" - "exceptions; if the optional mask is given, the list is limited\n" - "to those exceptions matching the mask. The difference is that\n" + "sessionservice->GetExceptions(); if the optional mask is given, the list is limited\n" + "to those sessionservice->GetExceptions() matching the mask. The difference is that\n" "\002EXCEPTION VIEW\002 is more verbose, displaying the name of the\n" "person who added the exception, its session limit, reason, \n" "host mask and the expiry date and time.\n" @@ -502,7 +554,7 @@ class CommandOSException : public Command "Note that a connecting client will \"use\" the first exception\n" "their host matches. Large exception lists and widely matching\n" "exception masks are likely to degrade services' performance."), - OperServ->nick.c_str()); + Config->s_OperServ.c_str()); return true; } @@ -514,17 +566,117 @@ class CommandOSException : public Command class OSSession : public Module { + SessionService ss; + ExpireTimer expiretimer; CommandOSSession commandossession; CommandOSException commandosexception; + void AddSession(User *u, bool exempt) + { + Session *session = sessionservice->FindSession(u->host); + + if (session) + { + bool kill = false; + if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) + { + kill = true; + Exception *exception = sessionservice->FindException(u); + if (exception) + { + kill = false; + if (exception->limit && session->count >= exception->limit) + kill = true; + } + } + + /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was + * decremented in do_quit, which caused problems and fixed here + * + * Now, we create the user struture before calling this to fix some user tracking issues, + * so we must increment this here no matter what because it will either be + * decremented in do_kill or in do_quit - Adam + */ + ++session->count; + + if (kill && !exempt) + { + if (!Config->SessionLimitExceeded.empty()) + u->SendMessage(operserv->Bot(), Config->SessionLimitExceeded.c_str(), u->host.c_str()); + if (!Config->SessionLimitDetailsLoc.empty()) + u->SendMessage(operserv->Bot(), "%s", Config->SessionLimitDetailsLoc.c_str()); + + kill_user(Config->s_OperServ, u, "Session limit exceeded"); + + ++session->hits; + if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && SGLine) + { + const Anope::string &akillmask = "*@" + u->host; + const Anope::string &akillreason = "Session limit exceeded for " + u->host; + SGLine->Add(akillmask, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, akillreason); + ircdproto->SendGlobops(operserv->Bot(), "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); + } + } + } + else + { + session = new Session(); + session->host = u->host; + session->count = 1; + session->hits = 0; + + sessionservice->AddSession(session); + } + } + + void DelSession(User *u) + { + Session *session = sessionservice->FindSession(u->host); + if (!session) + { + if (debug) + Log() << "session: Tried to delete non-existant session: " << u->host; + return; + } + + if (session->count > 1) + { + --session->count; + return; + } + + sessionservice->DelSession(session); + delete session; + } + public: - OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + OSSession(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), ss(this) { this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandossession); - this->AddCommand(OperServ, &commandosexception); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + Implementation i[] = { I_OnUserConnect, I_OnUserLogoff }; + ModuleManager::Attach(i, this, 2); + + this->AddCommand(operserv->Bot(), &commandossession); + this->AddCommand(operserv->Bot(), &commandosexception); + + ModuleManager::RegisterService(&this->ss); + } + + void OnUserConnect(dynamic_reference<User> &user, bool &exempt) + { + if (user && Config->LimitSessions) + this->AddSession(user, exempt); + } + + void OnUserLogoff(User *u) + { + if (Config->LimitSessions && (!u->server || !u->server->IsULined())) + this->DelSession(u); } }; diff --git a/modules/core/os_session.h b/modules/core/os_session.h new file mode 100644 index 000000000..e08ed70fa --- /dev/null +++ b/modules/core/os_session.h @@ -0,0 +1,80 @@ +#ifndef OS_SESSION_H +#define OS_SESSION_H + +class SessionService : public Service +{ + public: + typedef Anope::map<Session *> SessionMap; + typedef std::vector<Exception *> ExceptionVector; + private: + SessionMap Sessions; + ExceptionVector Exceptions; + public: + SessionService(Module *m) : Service(m, "session") { } + + void AddException(Exception *e) + { + this->Exceptions.push_back(e); + } + + void DelException(Exception *e) + { + ExceptionVector::iterator it = std::find(this->Exceptions.begin(), this->Exceptions.end(), e); + if (it != this->Exceptions.end()) + this->Exceptions.erase(it); + } + + Exception *FindException(User *u) + { + for (std::vector<Exception *>::const_iterator it = this->Exceptions.begin(), it_end = this->Exceptions.end(); it != it_end; ++it) + { + Exception *e = *it; + if (Anope::Match(u->host, e->mask) || (u->ip() && Anope::Match(u->ip.addr(), e->mask))) + return e; + } + return NULL; + } + + Exception *FindException(const Anope::string &host) + { + for (std::vector<Exception *>::const_iterator it = this->Exceptions.begin(), it_end = this->Exceptions.end(); it != it_end; ++it) + { + Exception *e = *it; + if (Anope::Match(host, e->mask)) + return e; + } + + return NULL; + } + + ExceptionVector &GetExceptions() + { + return this->Exceptions; + } + + void AddSession(Session *s) + { + this->Sessions[s->host] = s; + } + + void DelSession(Session *s) + { + this->Sessions.erase(s->host); + } + + Session *FindSession(const Anope::string &mask) + { + SessionMap::iterator it = this->Sessions.find(mask); + if (it != this->Sessions.end()) + return it->second; + return NULL; + } + + SessionMap &GetSessions() + { + return this->Sessions; + } +}; + +#endif + diff --git a/modules/core/os_set.cpp b/modules/core/os_set.cpp index cb50aa8fe..de622537d 100644 --- a/modules/core/os_set.cpp +++ b/modules/core/os_set.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSSet : public Command { @@ -84,14 +85,14 @@ class CommandOSSet : public Command u->isSuperAdmin = 1; source.Reply(_("You are now a SuperAdmin")); Log(LOG_ADMIN, u, this) << "SUPERADMIN ON"; - ircdproto->SendGlobops(OperServ, GetString(NULL, _("%s is now a Super-Admin")).c_str(), u->nick.c_str()); + ircdproto->SendGlobops(operserv->Bot(), _("%s is now a Super-Admin"), u->nick.c_str()); } else if (setting.equals_ci("OFF")) { u->isSuperAdmin = 0; source.Reply(_("You are no longer a SuperAdmin")); Log(LOG_ADMIN, u, this) << "SUPERADMIN OFF"; - ircdproto->SendGlobops(OperServ, GetString(NULL, _("%s is no longer a Super-Admin")).c_str(), u->nick.c_str()); + ircdproto->SendGlobops(operserv->Bot(), _("%s is no longer a Super-Admin"), u->nick.c_str()); } else source.Reply(_("Setting for SuperAdmin must be \002on\002 or \002off\002 (must be enabled in services.conf)")); @@ -206,7 +207,7 @@ class CommandOSSet : public Command " LIST List the options")); else if (subcommand.equals_ci("LIST")) source.Reply(_("Syntax: \002SET LIST\n" - "Display the various %s settings"), OperServ->nick.c_str()); + "Display the various %s settings"), Config->s_OperServ.c_str()); else if (subcommand.equals_ci("READONLY")) source.Reply(_("Syntax: \002SET READONLY {ON | OFF}\002\n" " \n" @@ -255,7 +256,10 @@ class OSSet : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosset); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosset); } }; diff --git a/modules/core/os_shutdown.cpp b/modules/core/os_shutdown.cpp index c714623af..24642f244 100644 --- a/modules/core/os_shutdown.cpp +++ b/modules/core/os_shutdown.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSShutdown : public Command { @@ -25,9 +26,6 @@ class CommandOSShutdown : public Command { User *u = source.u; quitmsg = "SHUTDOWN command received from " + u->nick; - - if (Config->GlobalOnCycle) - oper_global("", "%s", Config->GlobalOnCycleMessage.c_str()); shutting_down = true; return MOD_CONT; } @@ -51,7 +49,10 @@ class OSShutdown : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosshutdown); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosshutdown); } }; diff --git a/modules/core/os_snline.cpp b/modules/core/os_snline.cpp index 03ec40658..8eea0dfb1 100644 --- a/modules/core/os_snline.cpp +++ b/modules/core/os_snline.cpp @@ -12,7 +12,7 @@ /*************************************************************************/ #include "module.h" -#include "hashcomp.h" +#include "operserv.h" class SNLineDelCallback : public NumberList { @@ -183,35 +183,47 @@ class CommandOSSNLine : public Command if (!mask.empty() && !reason.empty()) { - /* Clean up the last character of the mask if it is a space - * See bug #761 - */ - unsigned masklen = mask.length(); - if (mask[masklen - 1] == ' ') - mask.erase(masklen - 1); - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (Anope::Match(it->second->realname, mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { + std::pair<int, XLine *> canAdd = SNLine->CanAdd(mask, expires); + if (mask.find_first_not_of("*?") == Anope::string::npos) source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SNLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the SNLINE list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + /* Clean up the last character of the mask if it is a space + * See bug #761 + */ + unsigned masklen = mask.length(); + if (mask[masklen - 1] == ' ') + mask.erase(masklen - 1); + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (Anope::Match(it->second->realname, mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to SNLine " << percent << "% of the network (" << affected << " users)"; + return MOD_CONT; + } - XLine *x = SNLine->Add(OperServ, u, mask, expires, reason); + XLine *x = SNLine->Add(mask, u->nick, expires, reason); - if (!x) - return MOD_CONT; + if (!x) + return MOD_CONT; - source.Reply(_("\002%s\002 added to the SNLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + source.Reply(_("\002%s\002 added to the SNLINE list."), mask.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (readonly) - source.Reply(_(READ_ONLY_MODE)); + if (readonly) + source.Reply(_(READ_ONLY_MODE)); + } } else @@ -450,10 +462,13 @@ class OSSNLine : public Module if (!ircd->snline) throw ModuleException("Your IRCd does not support SNLine"); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandossnline); + this->AddCommand(operserv->Bot(), &commandossnline); } }; diff --git a/modules/core/os_sqline.cpp b/modules/core/os_sqline.cpp index 85c42ec4c..d582945fe 100644 --- a/modules/core/os_sqline.cpp +++ b/modules/core/os_sqline.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class SQLineDelCallback : public NumberList { @@ -170,28 +171,40 @@ class CommandOSSQLine : public Command reason += " " + params[3]; if (!mask.empty() && !reason.empty()) { - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (Anope::Match(it->second->nick, mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { + std::pair<int, XLine *> canAdd = SQLine->CanAdd(mask, expires); + if (mask.find_first_not_of("*") == Anope::string::npos) source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } - XLine *x = SQLine->Add(OperServ, u, mask, expires, reason); + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the SQLINE list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (Anope::Match(it->second->nick, mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - if (!x) - return MOD_CONT; + if (percent > 95) + { + source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to SQLine " << percent << "% of the network (" << affected << " users)"; + return MOD_CONT; + } + XLine *x = SQLine->Add(mask, u->nick, expires, reason); - source.Reply(_("\002%s\002 added to the SQLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + if (!x) + return MOD_CONT; - if (readonly) - source.Reply(_(READ_ONLY_MODE)); + source.Reply(_("\002%s\002 added to the SQLINE list."), mask.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + + if (readonly) + source.Reply(_(READ_ONLY_MODE)); + } } else @@ -430,10 +443,13 @@ class OSSQLine : public Module if (!ircd->sqline) throw ModuleException("Your IRCd does not support QLines."); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandossqline); + this->AddCommand(operserv->Bot(), &commandossqline); } }; diff --git a/modules/core/os_staff.cpp b/modules/core/os_staff.cpp index f2dbc7613..2e9dce04b 100644 --- a/modules/core/os_staff.cpp +++ b/modules/core/os_staff.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSStaff : public Command { @@ -70,7 +71,10 @@ class OSStaff : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosstaff); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosstaff); } }; diff --git a/modules/core/os_stats.cpp b/modules/core/os_stats.cpp index d7680018b..acaf2e72e 100644 --- a/modules/core/os_stats.cpp +++ b/modules/core/os_stats.cpp @@ -12,8 +12,7 @@ /*************************************************************************/ #include "module.h" - -void get_operserv_stats(long *nrec, long *memuse); +#include "operserv.h" /** * Count servers connected to server s @@ -154,40 +153,6 @@ class CommandOSStats : public Command return MOD_CONT; } - CommandReturn DoStatsMemory(CommandSource &source) - { - long count, mem; - - source.Reply(_("Bytes read : %5d kB"), TotalRead / 1024); - source.Reply(_("Bytes written : %5d kB"), TotalWritten / 1024); - - get_user_stats(count, mem); - source.Reply(_("User : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - get_channel_stats(&count, &mem); - source.Reply(_("Channel : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - get_core_stats(count, mem); - source.Reply(_("NS Groups : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - get_aliases_stats(count, mem); - source.Reply(_("NS Aliases : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - get_chanserv_stats(&count, &mem); - source.Reply(_("ChanServ : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - if (!Config->s_BotServ.empty()) - { - get_botserv_stats(&count, &mem); - source.Reply(_("BotServ : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - } - if (!Config->s_HostServ.empty()) - { - get_hostserv_stats(&count, &mem); - source.Reply(_("HostServ : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - } - get_operserv_stats(&count, &mem); - source.Reply(_("OperServ : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - get_session_stats(count, mem); - source.Reply(_("Sessions : \002%6d\002 records, \002%5d\002 kB"), count, (mem + 512) / 1024); - - return MOD_CONT; - } public: CommandOSStats() : Command("STATS", 0, 1, "operserv/stats") { @@ -196,33 +161,28 @@ class CommandOSStats : public Command CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - const Anope::string &extra = !params.empty() ? params[0] : ""; + Anope::string extra = !params.empty() ? params[0] : ""; - if (!extra.empty() && !extra.equals_ci("ALL")) - { - if (extra.equals_ci("AKILL")) - return this->DoStatsAkill(source); - else if (extra.equals_ci("RESET")) - return this->DoStatsReset(source); - else if (!extra.equals_ci("MEMORY") && !extra.equals_ci("UPLINK")) - source.Reply(_("Unknown STATS option \002%s\002."), extra.c_str()); - } + if (extra.equals_ci("ALL")) + extra.clear(); - if (extra.empty() || (!extra.equals_ci("MEMORY") && !extra.equals_ci("UPLINK"))) + if (extra.empty() || extra.equals_ci("AKILL")) + return this->DoStatsAkill(source); + else if (extra.equals_ci("RESET")) + return this->DoStatsReset(source); + else if (extra.empty() || extra.equals_ci("UPTIME")) this->DoStatsUptime(source); - - if (!extra.empty() && (extra.equals_ci("ALL") || extra.equals_ci("UPLINK"))) + else if (extra.empty() || extra.equals_ci("UPLINK")) this->DoStatsUplink(source); - - if (!extra.empty() && (extra.equals_ci("ALL") || extra.equals_ci("MEMORY"))) - this->DoStatsMemory(source); + else if (!extra.equals_ci("UPLINK")) + source.Reply(_("Unknown STATS option \002%s\002."), extra.c_str()); return MOD_CONT; } bool OnHelp(CommandSource &source, const Anope::string &subcommand) { - source.Reply(_("Syntax: \002STATS [AKILL | ALL | RESET | MEMORY | UPLINK]\002\n" + source.Reply(_("Syntax: \002STATS [AKILL | ALL | RESET | UPLINK]\002\n" " \n" "Without any option, shows the current number of users and\n" "IRCops online (excluding Services), the highest number of\n" @@ -235,10 +195,6 @@ class CommandOSStats : public Command "The \002RESET\002 option currently resets the maximum user count\n" "to the number of users currently present on the network.\n" " \n" - "The \002MEMORY\002 option displays information on the memory\n" - "usage of Services. Using this option can freeze Services for\n" - "a short period of time on large networks; don't overuse it!\n" - " \n" "The \002UPLINK\002 option displays information about the current\n" "server Anope uses as an uplink to the network.\n" " \n" @@ -258,93 +214,11 @@ class OSStats : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosstats); - } -}; - -void get_operserv_stats(long *nrec, long *memuse) -{ - unsigned i, end; - long mem = 0, count = 0, mem2 = 0, count2 = 0; - XLine *x; - - end = SGLine->GetCount(); - count += end; - mem += end * sizeof(XLine); - - for (i = 0; i < end; ++i) - { - x = SGLine->GetEntry(i); - - mem += x->GetNick().length() + 1; - mem += x->GetUser().length() + 1; - mem += x->GetHost().length() + 1; - mem += x->Mask.length() + 1; - mem += x->By.length() + 1; - mem += x->Reason.length() + 1; - } - - if (ircd->snline) - { - end = SNLine->GetCount(); - count += end; - mem += end * sizeof(XLine); - - for (i = 0; i < end; ++i) - { - x = SNLine->GetEntry(i); - - mem += x->GetNick().length() + 1; - mem += x->GetUser().length() + 1; - mem += x->GetHost().length() + 1; - mem += x->Mask.length() + 1; - mem += x->By.length() + 1; - mem += x->Reason.length() + 1; - } - } - if (ircd->sqline) - { - end = SQLine->GetCount(); - count += end; - mem += end * sizeof(XLine); - - for (i = 0; i < end; ++i) - { - x = SQLine->GetEntry(i); - - mem += x->GetNick().length() + 1; - mem += x->GetUser().length() + 1; - mem += x->GetHost().length() + 1; - mem += x->Mask.length() + 1; - mem += x->By.length() + 1; - mem += x->Reason.length() + 1; - } - } - if (ircd->szline) - { - end = SZLine->GetCount(); - count += end; - mem += end * sizeof(XLine); - - for (i = 0; i < end; ++i) - { - x = SZLine->GetEntry(i); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); - mem += x->GetNick().length() + 1; - mem += x->GetUser().length() + 1; - mem += x->GetHost().length() + 1; - mem += x->Mask.length() + 1; - mem += x->By.length() + 1; - mem += x->Reason.length() + 1; - } + this->AddCommand(operserv->Bot(), &commandosstats); } - - get_exception_stats(count2, mem2); - count += count2; - mem += mem2; - - *nrec = count; - *memuse = mem; -} +}; MODULE_INIT(OSStats) diff --git a/modules/core/os_svsnick.cpp b/modules/core/os_svsnick.cpp index 9465f84d2..be8a21729 100644 --- a/modules/core/os_svsnick.cpp +++ b/modules/core/os_svsnick.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSSVSNick : public Command { @@ -30,7 +31,7 @@ class CommandOSSVSNick : public Command NickAlias *na; - /* Truncate long nicknames to NICKMAX-2 characters */ + /* Truncate long nicknames to Config->NickLen characters */ if (newnick.length() > Config->NickLen) { source.Reply(_("Nick \002%s\002 was truncated to %d characters."), newnick.c_str(), Config->NickLen, newnick.c_str()); @@ -60,7 +61,7 @@ class CommandOSSVSNick : public Command else { source.Reply(_("The nick \002%s\002 is now being changed to \002%s\002."), nick.c_str(), newnick.c_str()); - ircdproto->SendGlobops(OperServ, "%s used SVSNICK to change %s to %s", u->nick.c_str(), nick.c_str(), newnick.c_str()); + ircdproto->SendGlobops(operserv->Bot(), "%s used SVSNICK to change %s to %s", u->nick.c_str(), nick.c_str(), newnick.c_str()); ircdproto->SendForceNickChange(u2, newnick, Anope::CurTime); } return MOD_CONT; @@ -90,10 +91,13 @@ class OSSVSNick : public Module if (!ircd->svsnick) throw ModuleException("Your IRCd does not support SVSNICK"); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandossvsnick); + this->AddCommand(operserv->Bot(), &commandossvsnick); } }; diff --git a/modules/core/os_szline.cpp b/modules/core/os_szline.cpp index 4274e94f9..d8a4f6283 100644 --- a/modules/core/os_szline.cpp +++ b/modules/core/os_szline.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class SZLineDelCallback : public NumberList { @@ -170,32 +171,46 @@ class CommandOSSZLine : public Command reason += " " + params[3]; if (!mask.empty() && !reason.empty()) { - User *user = finduser(mask); - if (user && user->ip()) - mask = user->ip.addr(); - unsigned int affected = 0; - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - if (it->second->ip() && Anope::Match(it->second->ip.addr(), mask)) - ++affected; - float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; - - if (percent > 95) - { + std::pair<int, XLine *> canAdd = SZLine->CanAdd(mask, expires); + if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) + source.Reply(_("You can only add IP masks to the SZLINE list.")); + else if (mask.find_first_not_of("*?") == Anope::string::npos) source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); - Log(LOG_ADMIN, u, this) << "tried to SZLine " << percent << "% of the network (" << affected << " users)"; - return MOD_CONT; - } + else if (canAdd.first == 1) + source.Reply(_("\002%s\002 already exists on the SZLINE list."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 2) + source.Reply(_("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); + else if (canAdd.first == 3) + source.Reply(_("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); + else + { + User *user = finduser(mask); + if (user && user->ip()) + mask = user->ip.addr(); + unsigned int affected = 0; + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + if (it->second->ip() && Anope::Match(it->second->ip.addr(), mask)) + ++affected; + float percent = static_cast<float>(affected) / static_cast<float>(UserListByNick.size()) * 100.0; + + if (percent > 95) + { + source.Reply(_(USERHOST_MASK_TOO_WIDE), mask.c_str()); + Log(LOG_ADMIN, u, this) << "tried to SZLine " << percent << "% of the network (" << affected << " users)"; + return MOD_CONT; + } - XLine *x = SZLine->Add(OperServ, u, mask, expires, reason); + XLine *x = SZLine->Add(mask, u->nick, expires, reason); - if (!x) - return MOD_CONT; + if (!x) + return MOD_CONT; - source.Reply(_("\002%s\002 added to the SZLINE list."), mask.c_str()); - Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; + source.Reply(_("\002%s\002 added to the SZLINE list."), mask.c_str()); + Log(LOG_ADMIN, u, this) << "on " << mask << " (" << reason << ") expires in " << (expires ? duration(expires - Anope::CurTime) : "never") << " [affects " << affected << " user(s) (" << percent << "%)]"; - if (readonly) - source.Reply(_(READ_ONLY_MODE)); + if (readonly) + source.Reply(_(READ_ONLY_MODE)); + } } else @@ -430,10 +445,13 @@ class OSSZLine : public Module if (!ircd->szline) throw ModuleException("Your IRCd does not support ZLINEs"); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosszline); + this->AddCommand(operserv->Bot(), &commandosszline); } }; diff --git a/modules/core/os_update.cpp b/modules/core/os_update.cpp index 094f3570d..8a1e10c68 100644 --- a/modules/core/os_update.cpp +++ b/modules/core/os_update.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSUpdate : public Command { @@ -48,7 +49,10 @@ class OSUpdate : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosupdate); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosupdate); } }; diff --git a/modules/core/os_userlist.cpp b/modules/core/os_userlist.cpp index a511fbf25..1b219214d 100644 --- a/modules/core/os_userlist.cpp +++ b/modules/core/os_userlist.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "operserv.h" class CommandOSUserList : public Command { @@ -100,7 +101,10 @@ class OSUserList : public Module this->SetAuthor("Anope"); this->SetType(CORE); - this->AddCommand(OperServ, &commandosuserlist); + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosuserlist); } }; diff --git a/modules/core/ss_main.cpp b/modules/core/ss_main.cpp deleted file mode 100644 index e452f53c1..000000000 --- a/modules/core/ss_main.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* StatServ core functions - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "module.h" - -BotInfo *statserv = NULL; - -class CommandSSHelp : public Command -{ - public: - CommandSSHelp() : Command("HELP", 0, 0) - { - } - - CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) - { - User *u = source.u; - ircdproto->SendMessage(statserv, u->nick, "This is a test of the emergency StatServ system."); - return MOD_CONT; - } -}; - -class SSMain : public Module -{ - CommandSSHelp commandsshelp; - - public: - SSMain(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) - { - this->SetAuthor("Anope"); - this->SetType(CORE); - this->SetPermanent(true); - - statserv = findbot("StatServ"); - if (!statserv) - { - Log() << "Creating SS"; - statserv = new BotInfo("StatServ", Config->ServiceUser, Config->ServiceHost, "Stats Service"); - } - Log() << "Done creating SS"; - - this->AddCommand(statserv, &commandsshelp); - } - - ~SSMain() - { - if (statserv) - { - for (CommandMap::iterator it = statserv->Commands.begin(), it_end = statserv->Commands.end(); it != it_end; ++it) - this->DelCommand(statserv, it->second); - - delete statserv; - } - } -}; - -MODULE_INIT(SSMain) diff --git a/modules/extra/cs_appendtopic.cpp b/modules/extra/cs_appendtopic.cpp index b02717d92..dc3b40288 100644 --- a/modules/extra/cs_appendtopic.cpp +++ b/modules/extra/cs_appendtopic.cpp @@ -17,8 +17,7 @@ /*************************************************************************/ #include "module.h" - -#define AUTHOR "SGR" +#include "chanserv.h" /* ------------------------------------------------------------ * Name: cs_appendtopic @@ -110,12 +109,15 @@ class CSAppendTopic : public Module public: CSAppendTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - - this->SetAuthor(AUTHOR); + this->SetAuthor("SGR"); this->SetType(SUPPORTED); - this->AddCommand(ChanServ, &commandcsappendtopic); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcsappendtopic); } }; diff --git a/modules/extra/cs_enforce.cpp b/modules/extra/cs_enforce.cpp index 3a8e11735..6e39f33f3 100644 --- a/modules/extra/cs_enforce.cpp +++ b/modules/extra/cs_enforce.cpp @@ -14,6 +14,7 @@ */ #include "module.h" +#include "chanserv.h" static Module *me; @@ -217,12 +218,15 @@ class CSEnforce : public Module public: CSEnforce(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - this->SetAuthor("Anope"); this->SetType(SUPPORTED); - this->AddCommand(ChanServ, &commandcsenforce); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcsenforce); } }; diff --git a/modules/extra/cs_entrymsg.cpp b/modules/extra/cs_entrymsg.cpp index 649fd69f8..f424baede 100644 --- a/modules/extra/cs_entrymsg.cpp +++ b/modules/extra/cs_entrymsg.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" struct EntryMsg { @@ -162,13 +163,16 @@ class CSEntryMessage : public Module { this->SetAuthor("Anope"); this->SetType(CORE); + + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); Implementation i[] = { I_OnJoinChannel, I_OnReload, I_OnDatabaseReadMetadata, I_OnDatabaseWriteMetadata }; ModuleManager::Attach(i, this, 4); - this->AddCommand(ChanServ, &commandentrymsg); + this->AddCommand(chanserv->Bot(), &commandentrymsg); - this->OnReload(false); + this->OnReload(); } void OnJoinChannel(User *u, Channel *c) @@ -179,11 +183,11 @@ class CSEntryMessage : public Module if (c->ci->GetExtRegular("cs_entrymsg", messages)) for (unsigned i = 0; i < messages.size(); ++i) - u->SendMessage(whosends(c->ci), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); + u->SendMessage(c->ci->WhoSends(), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); } } - void OnReload(bool) + void OnReload() { ConfigReader config; EntryMsg::MaxEntries = config.ReadInteger("cs_entrymsg", "maxentries", "5", 0, true); diff --git a/modules/extra/cs_set_misc.cpp b/modules/extra/cs_set_misc.cpp index cb654a9a1..4bd7a772a 100644 --- a/modules/extra/cs_set_misc.cpp +++ b/modules/extra/cs_set_misc.cpp @@ -11,6 +11,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" class CommandCSSetMisc : public Command { @@ -77,8 +78,8 @@ class CSSetMisc : public Module if (Commands.empty()) return; - Command *set = FindCommand(ChanServ, "SET"); - Command *saset = FindCommand(ChanServ, "SASET"); + Command *set = FindCommand(chanserv->Bot(), "SET"); + Command *saset = FindCommand(chanserv->Bot(), "SASET"); if (!set && !saset) return; @@ -114,10 +115,13 @@ class CSSetMisc : public Module this->SetAuthor("Anope"); this->SetType(CORE); + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + Implementation i[] = { I_OnReload, I_OnChanInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); - OnReload(true); + OnReload(); } ~CSSetMisc() @@ -125,12 +129,12 @@ class CSSetMisc : public Module RemoveAll(); } - void OnReload(bool) + void OnReload() { RemoveAll(); - Command *set = FindCommand(ChanServ, "SET"); - Command *saset = FindCommand(ChanServ, "SASET"); + Command *set = FindCommand(chanserv->Bot(), "SET"); + Command *saset = FindCommand(chanserv->Bot(), "SASET"); if (!set && !saset) return; diff --git a/modules/extra/cs_tban.cpp b/modules/extra/cs_tban.cpp index e3470504d..04d608246 100644 --- a/modules/extra/cs_tban.cpp +++ b/modules/extra/cs_tban.cpp @@ -16,6 +16,7 @@ /*************************************************************************/ #include "module.h" +#include "chanserv.h" static Module *me; @@ -110,12 +111,15 @@ class CSTBan : public Module public: CSTBan(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) { - me = this; - - this->AddCommand(ChanServ, &commandcstban); - this->SetAuthor("Anope"); this->SetType(SUPPORTED); + + if (!chanserv) + throw ModuleException("ChanServ is not loaded!"); + + me = this; + + this->AddCommand(chanserv->Bot(), &commandcstban); } }; diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp index 9a2c44d47..30a71c809 100644 --- a/modules/extra/db_mysql.cpp +++ b/modules/extra/db_mysql.cpp @@ -1,5 +1,7 @@ #include "module.h" +#include "operserv.h" #include "sql.h" +#include "os_session.h" static Anope::string ToString(const std::vector<Anope::string> &strings) { @@ -89,6 +91,7 @@ class DBMySQL : public Module service_reference<SQLProvider> SQL; public: + service_reference<SessionService> SessionInterface; time_t lastwarn; bool ro; @@ -99,7 +102,8 @@ class DBMySQL : public Module if (readonly && this->ro) { readonly = this->ro = false; - ircdproto->SendGlobops(OperServ, "Found SQL again, going out of readonly mode..."); + if (operserv) + ircdproto->SendGlobops(operserv->Bot(), "Found SQL again, going out of readonly mode..."); } SQL->Run(&sqlinterface, query); @@ -108,7 +112,8 @@ class DBMySQL : public Module { if (Anope::CurTime - Config->UpdateTimeout > lastwarn) { - ircdproto->SendGlobops(OperServ, "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); + if (operserv) + ircdproto->SendGlobops(operserv->Bot(), "Unable to locate SQL reference, is m_mysql loaded? Going to readonly..."); readonly = this->ro = true; this->lastwarn = Anope::CurTime; } @@ -120,7 +125,7 @@ class DBMySQL : public Module return SQL ? SQL->Escape(query) : query; } - DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), sqlinterface(this), SQL("mysql/main") + DBMySQL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), sqlinterface(this), SQL("mysql/main"), SessionInterface("session") { me = this; @@ -134,7 +139,8 @@ class DBMySQL : public Module }; ModuleManager::Attach(i, this, 2); - this->AddCommand(OperServ, &commandsqlsync); + if (operserv) + this->AddCommand(operserv->Bot(), &commandsqlsync); if (uplink_server) OnServerConnect(); @@ -542,12 +548,9 @@ class DBMySQL : public Module time_t seton = r.Get(i, "seton").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "seton")) : Anope::CurTime; time_t expires = r.Get(i, "expires").is_pos_number_only() ? convertTo<time_t>(r.Get(i, "expires")) : Anope::CurTime; - XLine *x = SGLine->Add(NULL, NULL, user + "@" + host, expires, reason); + XLine *x = SGLine->Add(user + "@" + host, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } } @@ -562,16 +565,13 @@ class DBMySQL : public Module XLine *x = NULL; if (SNLine && r.Get(i, "type").equals_cs("SNLINE")) - x = SNLine->Add(NULL, NULL, mask, expires, reason); + x = SNLine->Add(mask, by, expires, reason); else if (SQLine && r.Get(i, "type").equals_cs("SQLINE")) - x = SQLine->Add(NULL, NULL, mask, expires, reason); + x = SQLine->Add(mask, by, expires, reason); else if (SZLine && r.Get(i, "type").equals_cs("SZLINE")) - x = SZLine->Add(NULL, NULL, mask, expires, reason); + x = SZLine->Add(mask, by, expires, reason); if (x) - { - x->By = by; x->Created = seton; - } } r = SQL->RunQuery("SELECT * FROM `anope_os_exceptions`"); @@ -583,7 +583,16 @@ class DBMySQL : public Module Anope::string reason = r.Get(i, "reason"); time_t expires = convertTo<time_t>(r.Get(i, "expires")); - exception_add(NULL, mask, limit, reason, creator, expires); + if (SessionInterface) + { + Exception *e = new Exception(); + e->mask = mask; + e->limit = limit; + e->who = creator; + e->reason = reason; + e->time = expires; + SessionInterface->AddException(e); + } } r = SQL->RunQuery("SELECT * FROM `anope_extra`"); @@ -661,7 +670,7 @@ class DBMySQL : public Module BotInfo *service = command->service; ChannelInfo *ci = source.ci; - if (service == NickServ) + if (service->nick == Config->s_NickServ) { if (u->Account() && ((command->name.equals_ci("SET") && !params.empty()) || (command->name.equals_ci("SASET") && u->HasCommand("nickserv/saset") && params.size() > 1))) { @@ -691,7 +700,7 @@ class DBMySQL : public Module } } } - else if (service == ChanServ) + else if (service->nick == Config->s_ChanServ) { if (command->name.equals_ci("SET") && u->Account() && params.size() > 1) { @@ -721,7 +730,7 @@ class DBMySQL : public Module } } } - else if (service == BotServ) + else if (service->nick == Config->s_BotServ) { if (command->name.equals_ci("KICK") && params.size() > 2) { @@ -773,7 +782,7 @@ class DBMySQL : public Module } } } - else if (service == MemoServ) + else if (service->nick == Config->s_MemoServ) { if (command->name.equals_ci("IGNORE") && params.size() > 0) { @@ -1049,18 +1058,12 @@ class DBMySQL : public Module this->RunQuery(query); } - void OnMemoSend(User *, NickCore *nc, Memo *m) - { - this->RunQuery("INSERT INTO `anope_ms_info` (receiver, flags, time, sender, text, serv) VALUES('" + - this->Escape(nc->display) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + - this->Escape(m->sender) + "', '" + this->Escape(m->text) + "', 'NICK')"); - } - - void OnMemoSend(User *, ChannelInfo *ci, Memo *m) + void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) { + const Anope::string &mtype = (!target.empty() && target[0] == '#' ? "CHAN" : "NICK"); this->RunQuery("INSERT INTO `anope_ms_info` (receiver, flags, time, sender, text, serv) VALUES('" + - this->Escape(ci->name) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + - this->Escape(m->sender) + "', '" + this->Escape(m->text) + "', 'CHAN')"); + this->Escape(target) + "', '" + ToString(m->ToString()) + "', " + stringify(m->time) + ", '" + + this->Escape(source) + "', '" + this->Escape(m->text) + "', '" + mtype + "')"); } void OnMemoDel(const NickCore *nc, MemoInfo *mi, Memo *m) @@ -1079,7 +1082,7 @@ class DBMySQL : public Module this->RunQuery("DELETE FROM `anope_ms_info` WHERE `receiver` = '" + this->Escape(ci->name) + "'"); } - EventReturn OnAddAkill(User *, XLine *ak) + EventReturn OnAddAkill(XLine *ak) { this->RunQuery("INSERT INTO `anope_os_akills` (user, host, xby, reason, seton, expire) VALUES('" + this->Escape(ak->GetUser()) + "', '" + this->Escape(ak->GetHost()) + "', '" + this->Escape(ak->By) + "', '" + @@ -1095,7 +1098,7 @@ class DBMySQL : public Module this->RunQuery("TRUNCATE TABLE `anope_os_akills`"); } - EventReturn OnExceptionAdd(User *, Exception *ex) + EventReturn OnExceptionAdd(Exception *ex) { this->RunQuery("INSERT INTO `anope_os_exceptions` (mask, slimit, who, reason, time, expires) VALUES('" + this->Escape(ex->mask) + "', " + stringify(ex->limit) + ", '" + this->Escape(ex->who) + "', '" + this->Escape(ex->reason) + "', " + @@ -1108,7 +1111,7 @@ class DBMySQL : public Module this->RunQuery("DELETE FROM `anope_os_exceptions` WHERE `mask` = '" + this->Escape(ex->mask) + "'"); } - EventReturn OnAddXLine(User *, XLine *x, XLineType Type) + EventReturn OnAddXLine(XLine *x, XLineType Type) { this->RunQuery(Anope::string("INSERT INTO `anope_os_xlines` (type, mask, xby, reason, seton, expire) VALUES('") + (Type == X_SNLINE ? "SNLINE" : (Type == X_SQLINE ? "SQLINE" : "SZLINE")) + "', '" + @@ -1216,7 +1219,7 @@ static void SaveDatabases() { Memo *m = nc->memos.memos[j]; - me->OnMemoSend(NULL, nc, m); + me->OnMemoSend(m->sender, nc->display, &nc->memos, m); } } @@ -1267,35 +1270,35 @@ static void SaveDatabases() { Memo *m = ci->memos.memos[j]; - me->OnMemoSend(NULL, ci, m); + me->OnMemoSend(m->sender, ci->name, &ci->memos, m); } } if (SGLine) for (unsigned i = 0, end = SGLine->GetCount(); i < end; ++i) - me->OnAddAkill(NULL, SGLine->GetEntry(i)); + me->OnAddAkill(SGLine->GetEntry(i)); if (SZLine) for (unsigned i = 0, end = SZLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SZLine->GetEntry(i), X_SZLINE); + me->OnAddXLine(SZLine->GetEntry(i), X_SZLINE); if (SQLine) for (unsigned i = 0, end = SQLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SQLine->GetEntry(i), X_SQLINE); + me->OnAddXLine(SQLine->GetEntry(i), X_SQLINE); if (SNLine) for (unsigned i = 0, end = SNLine->GetCount(); i < end; ++i) - me->OnAddXLine(NULL, SNLine->GetEntry(i), X_SNLINE); + me->OnAddXLine(SNLine->GetEntry(i), X_SNLINE); - for (unsigned i = 0, end = exceptions.size(); i < end; ++i) - me->OnExceptionAdd(NULL, exceptions[i]); + if (me->SessionInterface) + for (SessionService::ExceptionVector::iterator it = me->SessionInterface->GetExceptions().begin(); it != me->SessionInterface->GetExceptions().end(); ++it) + me->OnExceptionAdd(*it); } CommandReturn CommandSQLSync::Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) { - User *u = source.u; SaveDatabases(); - u->SendMessage(OperServ, _("Updating MySQL.")); + source.Reply(_("Updating MySQL.")); return MOD_CONT; } diff --git a/modules/extra/hs_request.cpp b/modules/extra/hs_request.cpp index 4978035d3..f208d72b3 100644 --- a/modules/extra/hs_request.cpp +++ b/modules/extra/hs_request.cpp @@ -16,6 +16,8 @@ */ #include "module.h" +#include "hostserv.h" +#include "memoserv.h" static bool HSRequestMemoUser = false; static bool HSRequestMemoOper = false; @@ -152,8 +154,8 @@ class CommandHSActivate : public Command na->hostinfo.SetVhost(it->second->ident, it->second->host, u->nick, it->second->time); FOREACH_MOD(I_OnSetVhost, OnSetVhost(na)); - if (HSRequestMemoUser) - memo_send(source, na->nick, _("[auto memo] Your requested vHost has been approved."), 2); + if (HSRequestMemoUser && memoserv) + memoserv->Send(Config->s_HostServ, na->nick, _("[auto memo] Your requested vHost has been approved."), true); me->SendMessage(source, _("vHost for %s has been activated"), na->nick.c_str()); Log(LOG_COMMAND, u, this, NULL) << "for " << na->nick << " for vhost " << (!it->second->ident.empty() ? it->second->ident + "@" : "") << it->second->host; @@ -207,15 +209,15 @@ class CommandHSReject : public Command delete it->second; Requests.erase(it); - if (HSRequestMemoUser) + if (HSRequestMemoUser && memoserv) { - char message[BUFSIZE]; + Anope::string message; if (!reason.empty()) - snprintf(message, sizeof(message), _("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); + message = Anope::printf(_("[auto memo] Your requested vHost has been rejected. Reason: %s"), reason.c_str()); else - snprintf(message, sizeof(message), "%s", _("[auto memo] Your requested vHost has been rejected.")); + message = _("[auto memo] Your requested vHost has been rejected."); - memo_send(source, nick, message, 2); + memoserv->Send(Config->s_HostServ, nick, message, true); } me->SendMessage(source, _("vHost for %s has been rejected"), nick.c_str()); @@ -312,18 +314,21 @@ class HSRequest : public Module { me = this; - this->AddCommand(HostServ, &commandhsrequest); - this->AddCommand(HostServ, &commandhsactive); - this->AddCommand(HostServ, &commandhsreject); - this->AddCommand(HostServ, &commandhswaiting); + if (!hostserv) + throw ModuleException("HostServ is not loaded!"); + + this->AddCommand(hostserv->Bot(), &commandhsrequest); + this->AddCommand(hostserv->Bot(), &commandhsactive); + this->AddCommand(hostserv->Bot(), &commandhsreject); + this->AddCommand(hostserv->Bot(), &commandhswaiting); this->SetAuthor("Anope"); this->SetType(SUPPORTED); - this->OnReload(false); - Implementation i[] = { I_OnPreCommand, I_OnDatabaseRead, I_OnDatabaseWrite, I_OnReload }; ModuleManager::Attach(i, this, 4); + + this->OnReload(); } ~HSRequest() @@ -339,7 +344,7 @@ class HSRequest : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { BotInfo *service = source.owner; - if (service == HostServ) + if (service->nick == Config->s_HostServ) { if (command->name.equals_ci("LIST")) { @@ -348,7 +353,7 @@ class HSRequest : public Module if (!key.empty() && key.equals_ci("+req")) { std::vector<Anope::string> emptyParams; - Command *c = FindCommand(HostServ, "WAITING"); + Command *c = FindCommand(hostserv->Bot(), "WAITING"); if (!c) throw CoreException("No waiting command?"); c->Execute(source, emptyParams); @@ -356,7 +361,7 @@ class HSRequest : public Module } } } - else if (service == NickServ) + else if (service->nick == Config->s_NickServ) { if (command->name.equals_ci("DROP")) { @@ -402,7 +407,7 @@ class HSRequest : public Module } } - void OnReload(bool) + void OnReload() { ConfigReader config; HSRequestMemoUser = config.ReadFlag("hs_request", "memouser", "no", 0); @@ -422,7 +427,7 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An else host = vHost; - if (HSRequestMemoOper == 1) + if (HSRequestMemoOper == 1 && memoserv) for (unsigned i = 0; i < Config->Opers.size(); ++i) { Oper *o = Config->Opers[i]; @@ -431,9 +436,9 @@ void req_send_memos(CommandSource &source, const Anope::string &vIdent, const An if (!na) continue; - char message[BUFSIZE]; - snprintf(message, sizeof(message), _("[auto memo] vHost \002%s\002 has been requested."), host.c_str()); - memo_send(source, na->nick, message, 2); + Anope::string message = Anope::printf(_("[auto memo] vHost \002%s\002 has been requested by %s."), host.c_str(), source.u->GetMask().c_str()); + + memoserv->Send(Config->s_HostServ, na->nick, message, true); } } diff --git a/modules/extra/m_alias.cpp b/modules/extra/m_alias.cpp index c5f52bef2..025a53df0 100644 --- a/modules/extra/m_alias.cpp +++ b/modules/extra/m_alias.cpp @@ -6,6 +6,7 @@ */ #include "module.h" +#include "chanserv.h" struct CommandAlias { @@ -26,10 +27,10 @@ class ModuleAlias : public Module Implementation i[] = { I_OnReload, I_OnPreCommandRun, I_OnBotFantasy }; ModuleManager::Attach(i, this, 3); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -102,10 +103,10 @@ class ModuleAlias : public Module BotInfo *target = findbot(alias.target_client); if (!target) - target = ChanServ; + target = chanserv->Bot(); Anope::string full_message = alias.target_command; - if (target == ChanServ || target == BotServ) + if (target == chanserv->Bot() || target->nick == Config->s_BotServ) { Command *target_c = FindCommand(target, alias.target_command); if (target_c && !target_c->HasFlag(CFLAG_STRIP_CHANNEL)) diff --git a/modules/extra/m_dnsbl.cpp b/modules/extra/m_dnsbl.cpp index 5c88e75b5..f2572e694 100644 --- a/modules/extra/m_dnsbl.cpp +++ b/modules/extra/m_dnsbl.cpp @@ -6,10 +6,11 @@ */ #include "module.h" +#include "operserv.h" struct FakeAkill : public Command { - FakeAkill() : Command("AKILL", 0, 0) { this->service = OperServ; } + FakeAkill() : Command("AKILL", 0, 0) { this->service = findbot(Config->s_OperServ); } CommandReturn Execute(CommandSource &, const std::vector<Anope::string> &) { return MOD_CONT; } } fake_akill; @@ -61,18 +62,18 @@ class DNSBLResolver : public DNSRequest reason = reason.replace_all_cs("%N", Config->NetworkName); XLine *x = NULL; - if (this->add_to_akill && SGLine && (x = SGLine->Add(NULL, NULL, Anope::string("*@") + user->host, Anope::CurTime + this->blacklist.bantime, reason))) + if (this->add_to_akill && SGLine && (x = SGLine->Add(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason))) { - Log(LOG_COMMAND, OperServ, &fake_akill) << "for " << user->GetMask() << " (Listed in " << this->blacklist.name << ")"; + Log(LOG_COMMAND, operserv->Bot(), &fake_akill) << "for " << user->GetMask() << " (Listed in " << this->blacklist.name << ")"; /* If AkillOnAdd is disabled send it anyway, noone wants bots around... */ if (!Config->AkillOnAdd) - ircdproto->SendAkill(*user, x); + ircdproto->SendAkill(user, x); } else { - Log(OperServ) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; - XLine xline(Anope::string("*@") + user->host, OperServ ? OperServ->nick : "OperServ", Anope::CurTime + this->blacklist.bantime, reason); - ircdproto->SendAkill(*user, &xline); + Log(operserv->Bot()) << "DNSBL: " << user->GetMask() << " appears in " << this->blacklist.name; + XLine xline(Anope::string("*@") + user->host, Config->s_OperServ, Anope::CurTime + this->blacklist.bantime, reason); + ircdproto->SendAkill(user, &xline); } } }; @@ -90,13 +91,13 @@ class ModuleDNSBL : public Module this->SetAuthor("Anope"); this->SetType(SUPPORTED); - OnReload(false); - - Implementation i[] = { I_OnReload, I_OnPreUserConnect }; + Implementation i[] = { I_OnReload, I_OnUserConnect }; ModuleManager::Attach(i, this, 2); + + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -127,17 +128,18 @@ class ModuleDNSBL : public Module } } - EventReturn OnPreUserConnect(User *u) + void OnUserConnect(dynamic_reference<User> &user, bool &exempt) { - if (!this->check_on_connect && !Me->IsSynced()) - return EVENT_CONTINUE; - if (!this->check_on_netburst && !u->server->IsSynced()) - return EVENT_CONTINUE; + if (exempt || !user || (!this->check_on_connect && !Me->IsSynced())) + return; + + if (!this->check_on_netburst && !user->server->IsSynced()) + return; /* At this time we only support IPv4 */ - if (u->ip.sa.sa_family != AF_INET) - return EVENT_CONTINUE; + if (user->ip.sa.sa_family != AF_INET) + return; - unsigned long ip = u->ip.sa4.sin_addr.s_addr; + unsigned long ip = user->ip.sa4.sin_addr.s_addr; unsigned long reverse_ip = ((ip & 0xFF) << 24) | ((ip & 0xFF00) << 8) | ((ip & 0xFF0000) >> 8) | ((ip & 0xFF000000) >> 24); sockaddrs user_ip; @@ -151,7 +153,7 @@ class ModuleDNSBL : public Module try { Anope::string dnsbl_host = user_ip.addr() + "." + b.name; - DNSBLResolver *res = new DNSBLResolver(this, u, b, dnsbl_host, this->add_to_akill); + DNSBLResolver *res = new DNSBLResolver(this, user, b, dnsbl_host, this->add_to_akill); res->Process(); } catch (const SocketException &ex) @@ -160,7 +162,7 @@ class ModuleDNSBL : public Module } } - return EVENT_CONTINUE; + return; } }; diff --git a/modules/extra/m_helpchan.cpp b/modules/extra/m_helpchan.cpp index 028e5e332..90a33ca79 100644 --- a/modules/extra/m_helpchan.cpp +++ b/modules/extra/m_helpchan.cpp @@ -6,6 +6,7 @@ */ #include "module.h" +#include "operserv.h" class HelpChannel : public Module { @@ -20,23 +21,23 @@ class HelpChannel : public Module Implementation i[] = { I_OnChannelModeSet, I_OnReload }; ModuleManager::Attach(i, this, 2); - OnReload(true); + OnReload(); } EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) { - if (Name == CMODE_OP && c && c->ci && c->name.equals_ci(this->HelpChan)) + if (Name == CMODE_OP && operserv && c && c->ci && c->name.equals_ci(this->HelpChan)) { User *u = finduser(param); if (u && check_access(u, c->ci, CA_OPDEOPME)) - u->SetMode(OperServ, UMODE_HELPOP); + u->SetMode(operserv->Bot(), UMODE_HELPOP); } return EVENT_CONTINUE; } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_ldap.cpp b/modules/extra/m_ldap.cpp index c7f0914a0..157bc70ac 100644 --- a/modules/extra/m_ldap.cpp +++ b/modules/extra/m_ldap.cpp @@ -210,7 +210,7 @@ class ModuleLDAP : public Module, public Pipe Implementation i[] = { I_OnReload, I_OnModuleUnload }; ModuleManager::Attach(i, this, 2); - OnReload(true); + OnReload(); } ~ModuleLDAP() @@ -225,7 +225,7 @@ class ModuleLDAP : public Module, public Pipe LDAPServices.clear(); } - void OnReload(bool startup) + void OnReload() { ConfigReader config; int i, num; diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index fa60247e5..f2caac63d 100644 --- a/modules/extra/m_ldap_authentication.cpp +++ b/modules/extra/m_ldap_authentication.cpp @@ -1,4 +1,5 @@ #include "module.h" +#include "nickserv.h" #include "ldap.h" static Anope::string email_attribute; @@ -44,8 +45,8 @@ class IdentifyInterface : public LDAPInterface return; } - User *u = *ii->user; - Command *c = *ii->command; + User *u = ii->user; + Command *c = ii->command; u->Extend("m_ldap_authentication_authenticated"); @@ -56,7 +57,7 @@ class IdentifyInterface : public LDAPInterface if (Config->NSAddAccessOnReg) na->nc->AddAccess(create_mask(u)); - u->SendMessage(NickServ, _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); + u->SendMessage(nickserv->Bot(), _("Your account \002%s\002 has been successfully created."), na->nick.c_str()); } enc_encrypt(ii->pass, na->nc->pass); @@ -83,8 +84,8 @@ class IdentifyInterface : public LDAPInterface return; } - User *u = *ii->user; - Command *c = *ii->command; + User *u = ii->user; + Command *c = ii->command; u->Extend("m_ldap_authentication_error"); @@ -128,7 +129,7 @@ class OnIdentifyInterface : public LDAPInterface if (!email.equals_ci(u->Account()->email)) { u->Account()->email = email; - u->SendMessage(NickServ, _("Your email has been updated to \002%s\002"), email.c_str()); + u->SendMessage(nickserv->Bot(), _("Your email has been updated to \002%s\002"), email.c_str()); Log() << "m_ldap_authentication: Updated email address for " << u->nick << " (" << u->Account()->display << ") to " << email; } } @@ -166,10 +167,10 @@ class NSIdentifyLDAP : public Module ModuleManager::Attach(i, this, 4); ModuleManager::SetPriority(this, PRIORITY_FIRST); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; @@ -182,7 +183,7 @@ class NSIdentifyLDAP : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { - if (this->disable_register && command->service == NickServ && command->name == "REGISTER") + if (this->disable_register && nickserv && command->service == nickserv->Bot() && command->name == "REGISTER") { source.Reply(_(this->disable_reason.c_str())); return EVENT_STOP; diff --git a/modules/extra/m_ldap_oper.cpp b/modules/extra/m_ldap_oper.cpp index b8a1d5f51..8010031cb 100644 --- a/modules/extra/m_ldap_oper.cpp +++ b/modules/extra/m_ldap_oper.cpp @@ -93,10 +93,10 @@ class LDAPOper : public Module Implementation i[] = { I_OnReload, I_OnNickIdentify, I_OnDelCore }; ModuleManager::Attach(i, this, 3); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_mysql.cpp b/modules/extra/m_mysql.cpp index 9895d025d..a54426b37 100644 --- a/modules/extra/m_mysql.cpp +++ b/modules/extra/m_mysql.cpp @@ -158,7 +158,7 @@ class ModuleSQL : public Module, public Pipe DThread = new DispatcherThread(); threadEngine.Start(DThread); - OnReload(true); + OnReload(); } ~ModuleSQL() @@ -173,7 +173,7 @@ class ModuleSQL : public Module, public Pipe delete DThread; } - void OnReload(bool startup) + void OnReload() { ConfigReader config; int i, num; diff --git a/modules/extra/m_xmlrpc.cpp b/modules/extra/m_xmlrpc.cpp index db1242970..34288195a 100644 --- a/modules/extra/m_xmlrpc.cpp +++ b/modules/extra/m_xmlrpc.cpp @@ -218,12 +218,12 @@ class ModuleXMLRPC : public Module { me = this; - OnReload(false); - ModuleManager::RegisterService(&this->xmlrpcinterface); Implementation i[] = { I_OnReload }; ModuleManager::Attach(i, this, 1); + + OnReload(); } ~ModuleXMLRPC() @@ -250,7 +250,7 @@ class ModuleXMLRPC : public Module this->listen_sockets.clear(); } - void OnReload(bool) + void OnReload() { ConfigReader config; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 593aba6ef..6f4b4b05c 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -87,14 +87,15 @@ class MyXMLRPCEvent : public XMLRPCEvent else request->reply("online", "yes"); - mod_run_cmd(bi, *u, NULL, command); + mod_run_cmd(bi, u, NULL, command); if (created && u) { - XMLRPCUser *myu = debug_cast<XMLRPCUser *>(*u); + User *useru = u; + XMLRPCUser *myu = debug_cast<XMLRPCUser *>(useru); if (!myu->GetOut().empty()) request->reply("return", iface->Sanitize(myu->GetOut())); - delete *u; + delete u; } } } diff --git a/modules/extra/ns_maxemail.cpp b/modules/extra/ns_maxemail.cpp index 94b4ef12c..2a0141508 100644 --- a/modules/extra/ns_maxemail.cpp +++ b/modules/extra/ns_maxemail.cpp @@ -59,13 +59,13 @@ class NSMaxEmail : public Module this->SetAuthor("Anope"); this->SetType(SUPPORTED); - ModuleManager::Attach(I_OnReload, this); - ModuleManager::Attach(I_OnPreCommand, this); + Implementation i[] = { I_OnReload, I_OnPreCommand }; + ModuleManager::Attach(i, this, 2); - OnReload(false); + OnReload(); } - void OnReload(bool) + void OnReload() { ConfigReader config; this->NSEmailMax = config.ReadInteger("ns_maxemail", "maxemails", "0", 0, false); @@ -75,7 +75,7 @@ class NSMaxEmail : public Module EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) { BotInfo *service = source.owner; - if (service == NickServ) + if (service->nick == Config->s_NickServ) { if (command->name.equals_ci("REGISTER")) { diff --git a/modules/extra/ns_set_misc.cpp b/modules/extra/ns_set_misc.cpp index a1bf091c5..385fb9648 100644 --- a/modules/extra/ns_set_misc.cpp +++ b/modules/extra/ns_set_misc.cpp @@ -12,6 +12,7 @@ /*************************************************************************/ #include "module.h" +#include "nickserv.h" class CommandNSSetMisc : public Command { @@ -80,8 +81,8 @@ class NSSetMisc : public Module if (Commands.empty()) return; - Command *set = FindCommand(NickServ, "SET"); - Command *saset = FindCommand(NickServ, "SASET"); + Command *set = FindCommand(nickserv->Bot(), "SET"); + Command *saset = FindCommand(nickserv->Bot(), "SASET"); if (!set && !saset) return; @@ -120,7 +121,7 @@ class NSSetMisc : public Module Implementation i[] = { I_OnReload, I_OnNickInfo, I_OnDatabaseWriteMetadata, I_OnDatabaseReadMetadata }; ModuleManager::Attach(i, this, 4); - OnReload(true); + OnReload(); } ~NSSetMisc() @@ -128,12 +129,12 @@ class NSSetMisc : public Module RemoveAll(); } - void OnReload(bool) + void OnReload() { RemoveAll(); - Command *set = FindCommand(NickServ, "SET"); - Command *saset = FindCommand(NickServ, "SASET"); + Command *set = FindCommand(nickserv->Bot(), "SET"); + Command *saset = FindCommand(nickserv->Bot(), "SASET"); if (!set && !saset) return; diff --git a/modules/extra/os_defcon.cpp b/modules/extra/os_defcon.cpp new file mode 100644 index 000000000..a2a536adf --- /dev/null +++ b/modules/extra/os_defcon.cpp @@ -0,0 +1,693 @@ +/* OperServ core functions + * + * (C) 2003-2011 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +/*************************************************************************/ + +#include "module.h" +#include "operserv.h" +#include "global.h" +#include "os_session.h" + +enum DefconLevel +{ + DEFCON_NO_NEW_CHANNELS, + DEFCON_NO_NEW_NICKS, + DEFCON_NO_MLOCK_CHANGE, + DEFCON_FORCE_CHAN_MODES, + DEFCON_REDUCE_SESSION, + DEFCON_NO_NEW_CLIENTS, + DEFCON_OPER_ONLY, + DEFCON_SILENT_OPER_ONLY, + DEFCON_AKILL_NEW_CLIENTS, + DEFCON_NO_NEW_MEMOS +}; + +static Module *me = NULL; +bool DefConModesSet = false; + +struct DefconConfig +{ + std::vector<std::bitset<32> > DefCon; + Flags<ChannelModeName, CMODE_END * 2> DefConModesOn; + Flags<ChannelModeName, CMODE_END * 2> DefConModesOff; + std::map<ChannelModeName, Anope::string> DefConModesOnParams; + + int defaultlevel, sessionlimit; + Anope::string chanmodes, message, offmessage, akillreason; + std::vector<Anope::string> defcons; + time_t akillexpire, timeout; + bool globalondefcon; + + DefconConfig() + { + this->DefCon.resize(5); + } + + bool Check(DefconLevel level) + { + return this->Check(this->defaultlevel, level); + } + + bool Check(int dlevel, DefconLevel level) + { + return this->DefCon[dlevel].test(level); + } + + void Add(int dlevel, DefconLevel level) + { + this->DefCon[dlevel][level] = true; + } + + void Del(int dlevel, DefconLevel level) + { + this->DefCon[dlevel][level] = false; + } + + bool SetDefConParam(ChannelModeName Name, const Anope::string &buf) + { + return DefConModesOnParams.insert(std::make_pair(Name, buf)).second; + } + + void UnsetDefConParam(ChannelModeName Name) + { + DefConModesOnParams.erase(Name); + } + + bool GetDefConParam(ChannelModeName Name, Anope::string &buf) + { + std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); + + buf.clear(); + + if (it != DefConModesOnParams.end()) + { + buf = it->second; + return true; + } + + return false; + } +}; + +static DefconConfig DConfig; + +/**************************************************************************/ + +void defcon_sendlvls(CommandSource &source); +void runDefCon(); +static Anope::string defconReverseModes(const Anope::string &modes); + +class DefConTimeout : public CallBack +{ + int level; + + public: + DefConTimeout(Module *mod, int newlevel) : CallBack(mod, DConfig.timeout), level(newlevel) { } + + void Tick(time_t) + { + if (DConfig.defaultlevel != level) + { + DConfig.defaultlevel = level; + FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(level)); + Log(operserv->Bot(), "operserv/defcon") << "Defcon level timeout, returning to level " << level; + ircdproto->SendGlobops(operserv->Bot(), GetString(NULL, _("\002%s\002 Changed the DEFCON level to \002%d\002")).c_str(), Config->s_OperServ.c_str(), level); + + if (DConfig.globalondefcon) + { + if (!DConfig.offmessage.empty()) + global->SendGlobal(global->Bot(), "", DConfig.offmessage); + else + global->SendGlobal(global->Bot(), "", Anope::printf(GetString(NULL, _("The Defcon Level is now at Level: \002%d\002")).c_str(), DConfig.defaultlevel)); + + if (!DConfig.message.empty()) + global->SendGlobal(global->Bot(), "", DConfig.message); + } + + runDefCon(); + } + } +}; +static DefConTimeout *timeout; + +class CommandOSDefcon : public Command +{ + void SendLevels(CommandSource &source) + { + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + source.Reply(_("* No new channel registrations")); + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + source.Reply(_("* No new nick registrations")); + if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + source.Reply(_("* No MLOCK changes")); + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && !DConfig.chanmodes.empty()) + source.Reply(_("* Force Chan Modes (%s) to be set on all channels"), DConfig.chanmodes.c_str()); + if (DConfig.Check(DEFCON_REDUCE_SESSION)) + source.Reply(_("* Use the reduced session limit of %d"), DConfig.sessionlimit); + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS)) + source.Reply(_("* Kill any NEW clients connecting")); + if (DConfig.Check(DEFCON_OPER_ONLY)) + source.Reply(_("* Ignore any non-opers with message")); + if (DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + source.Reply(_("* Silently ignore non-opers")); + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + source.Reply(_("* AKILL any new clients connecting")); + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + source.Reply(_("* No new memos sent")); + } + + public: + CommandOSDefcon() : Command("DEFCON", 1, 1, "operserv/defcon") + { + this->SetDesc(_("Manipulate the DefCon system")); + } + + CommandReturn Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) + { + User *u = source.u; + const Anope::string &lvl = params[0]; + + if (lvl.empty()) + { + source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); + this->SendLevels(source); + return MOD_CONT; + } + + int newLevel = 0; + try + { + newLevel = convertTo<int>(lvl); + } + catch (const ConvertException &) { } + + if (newLevel < 1 || newLevel > 5) + { + this->OnSyntaxError(source, ""); + return MOD_CONT; + } + + DConfig.defaultlevel = newLevel; + + FOREACH_MOD(I_OnDefconLevel, OnDefconLevel(newLevel)); + + if (timeout) + { + delete timeout; + timeout = NULL; + } + + if (DConfig.timeout) + timeout = new DefConTimeout(me, 5); + + source.Reply(_("Services are now at DEFCON \002%d\002"), DConfig.defaultlevel); + this->SendLevels(source); + Log(LOG_ADMIN, u, this) << "to change defcon level to " << newLevel; + ircdproto->SendGlobops(operserv->Bot(), _("\002%s\002 Changed the DEFCON level to \002%d\002"), u->nick.c_str(), newLevel); + /* Global notice the user what is happening. Also any Message that + the Admin would like to add. Set in config file. */ + if (DConfig.globalondefcon) + { + if (DConfig.defaultlevel == 5 && !DConfig.offmessage.empty()) + global->SendGlobal(global->Bot(), "", DConfig.offmessage); + else if (DConfig.defaultlevel != 5) + { + global->SendGlobal(global->Bot(), "", Anope::printf(_("The Defcon level is now at: \002%d\002"), DConfig.defaultlevel)); + if (!DConfig.message.empty()) + global->SendGlobal(global->Bot(), "", DConfig.message); + } + } + + /* Run any defcon functions, e.g. FORCE CHAN MODE */ + runDefCon(); + return MOD_CONT; + } + + bool OnHelp(CommandSource &source, const Anope::string &subcommand) + { + source.Reply(_("Syntax: \002DEFCON\002 [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]\n" + "The defcon system can be used to implement a pre-defined\n" + "set of restrictions to services useful during an attempted\n" + "attack on the network.")); + return true; + } + + void OnSyntaxError(CommandSource &source, const Anope::string &subcommand) + { + SyntaxError(source, "DEFCON", _("DEFCON [\0021\002|\0022\002|\0023\002|\0024\002|\0025\002]")); + } +}; + +class OSDefcon : public Module +{ + service_reference<SessionService> session_service; + CommandOSDefcon commandosdefcon; + + void ParseModeString() + { + int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */ + unsigned char mode; + ChannelMode *cm; + ChannelModeParam *cmp; + Anope::string modes, param; + + spacesepstream ss(DConfig.chanmodes); + + DConfig.DefConModesOn.ClearFlags(); + DConfig.DefConModesOff.ClearFlags(); + ss.GetToken(modes); + + /* Loop while there are modes to set */ + for (unsigned i = 0, end = modes.length(); i < end; ++i) + { + mode = modes[i]; + + switch (mode) + { + case '+': + add = 1; + continue; + case '-': + add = 0; + continue; + default: + if (add < 0) + continue; + } + + if ((cm = ModeManager::FindChannelModeByChar(mode))) + { + if (cm->Type == MODE_STATUS || cm->Type == MODE_LIST || !cm->CanSet(NULL)) + { + Log() << "DefConChanModes mode character '" << mode << "' cannot be locked"; + continue; + } + else if (add) + { + DConfig.DefConModesOn.SetFlag(cm->Name); + DConfig.DefConModesOff.UnsetFlag(cm->Name); + + if (cm->Type == MODE_PARAM) + { + cmp = debug_cast<ChannelModeParam *>(cm); + + if (!ss.GetToken(param)) + { + Log() << "DefConChanModes mode character '" << mode << "' has no parameter while one is expected"; + continue; + } + + if (!cmp->IsValid(param)) + continue; + + DConfig.SetDefConParam(cmp->Name, param); + } + } + else if (DConfig.DefConModesOn.HasFlag(cm->Name)) + { + DConfig.DefConModesOn.UnsetFlag(cm->Name); + + if (cm->Type == MODE_PARAM) + DConfig.UnsetDefConParam(cm->Name); + } + } + } + + /* We can't mlock +L if +l is not mlocked as well. */ + if ((cm = ModeManager::FindChannelModeByName(CMODE_REDIRECT)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_LIMIT)) + { + DConfig.DefConModesOn.UnsetFlag(CMODE_REDIRECT); + + Log() << "DefConChanModes must lock mode +l as well to lock mode +L"; + } + + /* Some ircd we can't set NOKNOCK without INVITE */ + /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */ + if (ircd->knock_needs_i && (cm = ModeManager::FindChannelModeByName(CMODE_NOKNOCK)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_INVITE)) + { + DConfig.DefConModesOn.UnsetFlag(CMODE_NOKNOCK); + Log() << "DefConChanModes must lock mode +i as well to lock mode +K"; + } + } + + public: + OSDefcon(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), session_service("session") + { + if (!DConfig.defaultlevel) + throw ModuleException("Invalid configuration settings"); + + me = this; + + this->SetAuthor("Anope"); + this->SetType(CORE); + + Implementation i[] = { I_OnReload, I_OnChannelModeSet, I_OnChannelModeUnset, I_OnPreCommandRun, I_OnPreCommand, I_OnUserConnect, I_OnChannelModeAdd, I_OnChannelCreate }; + ModuleManager::Attach(i, this, 9); + + if (!operserv) + throw ModuleException("OperServ is not loaded!"); + + this->AddCommand(operserv->Bot(), &commandosdefcon); + + this->OnReload(); + } + + void OnReload() + { + ConfigReader config; + DefconConfig dconfig; + + dconfig.defaultlevel = config.ReadInteger("defcon", "defaultlevel", 0, 0); + dconfig.defcons[4] = config.ReadValue("defcon", "level4", 0); + dconfig.defcons[3] = config.ReadValue("defcon", "level3", 0); + dconfig.defcons[2] = config.ReadValue("defcon", "level2", 0); + dconfig.defcons[1] = config.ReadValue("defcon", "level1", 0); + dconfig.sessionlimit = config.ReadInteger("defcon", "sessionlimit", 0, 0); + dconfig.akillexpire = dotime(config.ReadValue("defcon", "akillexpire", 0)); + dconfig.chanmodes = config.ReadValue("defcon", "chanmodes", 0); + dconfig.timeout = dotime(config.ReadValue("defcon", "timeout", 0)); + dconfig.globalondefcon = config.ReadFlag("defcon", "globalondefcon", 0); + dconfig.message = config.ReadValue("defcon", "message", 0); + dconfig.offmessage = config.ReadValue("defcon", "offmessage", 0); + + if (dconfig.defaultlevel < 1 || dconfig.defaultlevel > 5) + throw ConfigException("The value for <os_defcon:defaultlevel> must be between 1 and 5"); + else if (dconfig.akillexpire <= 0) + throw ConfigException("The value for <os_defcon:akillexpire> must be greater than zero!"); + + for (unsigned level = 1; level < 5; ++level) + { + spacesepstream operations(dconfig.defcons[level]); + Anope::string operation; + while (operations.GetToken(operation)) + { + if (operation.equals_ci("nonewchannels")) + dconfig.Add(level, DEFCON_NO_NEW_CHANNELS); + else if (operation.equals_ci("nonewnicks")) + dconfig.Add(level, DEFCON_NO_NEW_NICKS); + else if (operation.equals_ci("nomlockchanges")) + dconfig.Add(level, DEFCON_NO_MLOCK_CHANGE); + else if (operation.equals_ci("forcechanmodes")) + dconfig.Add(level, DEFCON_FORCE_CHAN_MODES); + else if (operation.equals_ci("reducedsessions")) + dconfig.Add(level, DEFCON_REDUCE_SESSION); + else if (operation.equals_ci("nonewclients")) + dconfig.Add(level, DEFCON_NO_NEW_CLIENTS); + else if (operation.equals_ci("operonly")) + dconfig.Add(level, DEFCON_OPER_ONLY); + else if (operation.equals_ci("silentoperonly")) + dconfig.Add(level, DEFCON_SILENT_OPER_ONLY); + else if (operation.equals_ci("akillnewclients")) + dconfig.Add(level, DEFCON_AKILL_NEW_CLIENTS); + else if (operation.equals_ci("nonewmemos")) + dconfig.Add(level, DEFCON_NO_NEW_MEMOS); + } + + if (dconfig.Check(level, DEFCON_REDUCE_SESSION) && dconfig.sessionlimit <= 0) + throw ConfigException("The value for <os_defcon:sessionlimit> must be greater than zero!"); + else if (dconfig.Check(level, DEFCON_AKILL_NEW_CLIENTS) && dconfig.akillreason.empty()) + throw ConfigException("The value for <os_defcon:akillreason> must not be empty!"); + else if (dconfig.Check(level, DEFCON_FORCE_CHAN_MODES) && dconfig.chanmodes.empty()) + throw ConfigException("The value for <os_defcon:chanmodes> must not be empty!"); + } + + DConfig = dconfig; + this->ParseModeString(); + } + + EventReturn OnUserConnect(User *u, bool &exempt) + { + if (!exempt && u->server->IsSynced() && DConfig.Check(DEFCON_AKILL_NEW_CLIENTS) && !u->server->IsULined()) + { + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + kill_user(Config->s_OperServ, u, DConfig.akillreason); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnChannelModeSet(Channel *c, ChannelModeName Name, const Anope::string ¶m) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(Name); + + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOff.HasFlag(Name)) + { + c->RemoveMode(operserv->Bot(), Name, param); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnChannelModeUnset(Channel *c, ChannelModeName Name, const Anope::string &) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(Name); + + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOn.HasFlag(Name)) + { + Anope::string param; + + if (DConfig.GetDefConParam(Name, param)) + c->SetMode(operserv->Bot(), Name, param); + else + c->SetMode(operserv->Bot(), Name); + + return EVENT_STOP; + + } + + return EVENT_CONTINUE; + } + + EventReturn OnPreCommandRun(User *&u, BotInfo *&bi, Anope::string &command, Anope::string &message, ChannelInfo *&ci) + { + if (!u->HasMode(UMODE_OPER) && (DConfig.Check(DEFCON_OPER_ONLY) || DConfig.Check(DEFCON_SILENT_OPER_ONLY))) + { + if (!DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + u->SendMessage(bi, _("Services are in Defcon mode, Please try again later.")); + + return EVENT_STOP; + } + + return EVENT_CONTINUE; + } + + EventReturn OnPreCommand(CommandSource &source, Command *command, const std::vector<Anope::string> ¶ms) + { + BotInfo *service = command->service; + if (service->nick == Config->s_NickServ) + { + if (command->name.equals_ci("REGISTER") || command->name.equals_ci("GROUP")) + { + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + else if (service->nick == Config->s_ChanServ) + { + if (command->name.equals_ci("SET")) + { + if (!params.empty() && params[0].equals_ci("MLOCK") && DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + else if (command->name.equals_ci("REGISTER")) + { + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + else if (service->nick == Config->s_MemoServ) + { + if (command->name.equals_ci("SEND") || command->name.equals_ci("SENDALL")) + { + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + { + source.Reply(_("Services are in Defcon mode, Please try again later.")); + return EVENT_STOP; + } + } + } + + return EVENT_CONTINUE; + } + + void OnUserConnect(dynamic_reference<User> &u, bool &exempt) + { + if (exempt || !u || !u->server->IsSynced() || u->server->IsULined()) + return; + + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, DConfig.akillreason); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + kill_user(Config->s_OperServ, u, DConfig.akillreason); + return; + } + } + + if (!DConfig.sessionlimit) + return; + + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: adding akill for *@" << u->host; + XLine *x = SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + DConfig.akillexpire, !DConfig.akillreason.empty() ? DConfig.akillreason : "DEFCON AKILL"); + if (x) + x->By = Config->s_OperServ; + } + + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS) || DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + { + kill_user(Config->s_OperServ, u, DConfig.akillreason); + return; + } + + Session *session = session_service->FindSession(u->host); + Exception *exception = session_service->FindException(u); + + if (DConfig.Check(DEFCON_REDUCE_SESSION) && !exception) + { + if (session && session->count > DConfig.sessionlimit) + { + if (!Config->SessionLimitExceeded.empty()) + ircdproto->SendMessage(operserv->Bot(), u->nick, Config->SessionLimitExceeded.c_str(), u->host.c_str()); + if (!Config->SessionLimitDetailsLoc.empty()) + ircdproto->SendMessage(operserv->Bot(), u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); + + kill_user(Config->s_OperServ, u, "Defcon session limit exceeded"); + ++session->hits; + if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) + { + SGLine->Add("*@" + u->host, Config->s_OperServ, Anope::CurTime + Config->SessionAutoKillExpiry, "Defcon session limit exceeded"); + ircdproto->SendGlobops(operserv->Bot(), "[DEFCON] Added a temporary AKILL for \2*@%s\2 due to excessive connections", u->host.c_str()); + } + } + } + } + + void OnChannelModeAdd(ChannelMode *cm) + { + if (DConfig.chanmodes.find(cm->ModeChar) != Anope::string::npos) + this->ParseModeString(); + } + + void OnChannelCreate(Channel *c) + { + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) + c->SetModes(operserv->Bot(), false, "%s", DConfig.chanmodes.c_str()); + } +}; + +/** + * Send a message to the oper about which precautions are "active" for this level + **/ +void defcon_sendlvls(CommandSource &source) +{ + if (DConfig.Check(DEFCON_NO_NEW_CHANNELS)) + source.Reply(_("* No new channel registrations")); + if (DConfig.Check(DEFCON_NO_NEW_NICKS)) + source.Reply(_("* No new nick registrations")); + if (DConfig.Check(DEFCON_NO_MLOCK_CHANGE)) + source.Reply(_("* No MLOCK changes")); + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && !DConfig.chanmodes.empty()) + source.Reply(_("* Force Chan Modes (%s) to be set on all channels"), DConfig.chanmodes.c_str()); + if (DConfig.Check(DEFCON_REDUCE_SESSION)) + source.Reply(_("* Use the reduced session limit of %d"), DConfig.sessionlimit); + if (DConfig.Check(DEFCON_NO_NEW_CLIENTS)) + source.Reply(_("* Kill any NEW clients connecting")); + if (DConfig.Check(DEFCON_OPER_ONLY)) + source.Reply(_("* Ignore any non-opers with message")); + if (DConfig.Check(DEFCON_SILENT_OPER_ONLY)) + source.Reply(_("* Silently ignore non-opers")); + if (DConfig.Check(DEFCON_AKILL_NEW_CLIENTS)) + source.Reply(_("* AKILL any new clients connecting")); + if (DConfig.Check(DEFCON_NO_NEW_MEMOS)) + source.Reply(_("* No new memos sent")); +} + +void runDefCon() +{ + if (DConfig.Check(DEFCON_FORCE_CHAN_MODES)) + { + if (!DConfig.chanmodes.empty() && !DefConModesSet) + { + if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << DConfig.chanmodes << " on all channels"; + DefConModesSet = true; + MassChannelModes(operserv->Bot(), DConfig.chanmodes); + } + } + } + else + { + if (!DConfig.chanmodes.empty() && DefConModesSet) + { + if (DConfig.chanmodes[0] == '+' || DConfig.chanmodes[0] == '-') + { + DefConModesSet = false; + Anope::string newmodes = defconReverseModes(DConfig.chanmodes); + if (!newmodes.empty()) + { + Log(operserv->Bot(), "operserv/defcon") << "DEFCON: setting " << newmodes << " on all channels"; + MassChannelModes(operserv->Bot(), newmodes); + } + } + } + } +} + +static Anope::string defconReverseModes(const Anope::string &modes) +{ + if (modes.empty()) + return ""; + Anope::string newmodes; + for (unsigned i = 0, end = modes.length(); i < end; ++i) + { + if (modes[i] == '+') + newmodes += '-'; + else if (modes[i] == '-') + newmodes += '+'; + else + newmodes += modes[i]; + } + return newmodes; +} + +MODULE_INIT(OSDefcon) diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 68ff578ea..f4735132e 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" IRCDVar myIrcd[] = { {"Bahamut 1.8.x", /* ircd name */ @@ -219,7 +220,7 @@ class BahamutIRCdProto : public IRCDProto /* nc_change was = 1, and there is no na->status */ void SendUnregisteredNick(const User *u) { - ircdproto->SendMode(NickServ, u, "+d 1"); + ircdproto->SendMode(nickserv->Bot(), u, "+d 1"); } /* SERVER */ @@ -242,7 +243,7 @@ class BahamutIRCdProto : public IRCDProto if (!u->Account()) return; - ircdproto->SendMode(NickServ, u, "+d %d", u->timestamp); + ircdproto->SendMode(nickserv->Bot(), u, "+d %d", u->timestamp); } void SendChannel(Channel *c) @@ -291,17 +292,17 @@ class BahamutIRCdMessage : public IRCdMessage ip.ntop(AF_INET, params[8].c_str()); User *user = do_nick(source, params[0], params[4], params[5], params[6], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), "", "", params[3]); - if (user) + if (user && nickserv) { NickAlias *na; if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick))) { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(NickServ, UMODE_REGISTERED); + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); } else - validate_user(user); + nickserv->Validate(user); } } else @@ -464,12 +465,12 @@ class BahamutIRCdMessage : public IRCdMessage } }; -static bool event_xs(BotInfo *bi, const Anope::string &source, const std::vector<Anope::string> ¶ms) +static bool event_xs(const Anope::string &bot, const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty() && bi) + if (!params.empty() && !bot.empty()) { std::vector<Anope::string> p; - p.push_back(bi->nick); + p.push_back(bot); p.push_back(params[0]); return ircdmessage->OnPrivmsg(source, p); } @@ -480,31 +481,31 @@ static bool event_xs(BotInfo *bi, const Anope::string &source, const std::vector /* EVENT : OS */ bool event_os(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - return event_xs(OperServ, source, params); + return event_xs(Config->s_OperServ, source, params); } /* EVENT : NS */ bool event_ns(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - return event_xs(NickServ, source, params); + return event_xs(Config->s_NickServ, source, params); } /* EVENT : MS */ bool event_ms(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - return event_xs(MemoServ, source, params); + return event_xs(Config->s_MemoServ, source, params); } /* EVENT : HS */ bool event_hs(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - return event_xs(HostServ, source, params); + return event_xs(Config->s_HostServ, source, params); } /* EVENT : CS */ bool event_cs(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - return event_xs(ChanServ, source, params); + return event_xs(Config->s_ChanServ, source, params); } bool event_burst(const Anope::string &source, const std::vector<Anope::string> ¶ms) diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index ce226407c..eaa02467b 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -33,25 +33,28 @@ class InspIRCdTS6Proto : public IRCDProto private: void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent) { + User *u = finduser(Config->s_HostServ); if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT not loaded!"); + Log() << "CHGIDENT not loaded!"; else - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); + send_cmd(u ? u->GetUID() : Config->Numeric, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); } void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost) { + User *u = finduser(Config->s_HostServ); if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST not loaded!"); + Log() << "CHGHOST not loaded!"; else - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); + send_cmd(u ? u->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); } public: void SendAkillDel(const XLine *x) { - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); + User *u = finduser(Config->s_OperServ); + send_cmd(u ? u->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); } void SendTopic(BotInfo *whosets, Channel *c) @@ -76,7 +79,8 @@ class InspIRCdTS6Proto : public IRCDProto time_t timeleft = x->Expires - Anope::CurTime; if (timeleft > 172800 || !x->Expires) timeleft = 172800; - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); + User *u = finduser(Config->s_OperServ); + send_cmd(u ? u->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); } void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) @@ -175,13 +179,13 @@ class InspIRCdTS6Proto : public IRCDProto /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) { - send_cmd(NickServ->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); + send_cmd(nickserv->Bot()->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); } /* SVSHOLD - release */ void SendSVSHoldDel(const Anope::string &nick) { - send_cmd(NickServ->GetUID(), "SVSHOLD %s", nick.c_str()); + send_cmd(nickserv->Bot()->GetUID(), "SVSHOLD %s", nick.c_str()); } /* UNSZLINE */ diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index ce0611916..0e787b0fe 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" IRCDVar myIrcd[] = { {"InspIRCd 1.1", /* ircd name */ @@ -59,7 +60,11 @@ void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) send_cmd(Config->s_OperServ, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); } else - ircdproto->SendGlobops(OperServ, "CHGHOST not loaded!"); + { + BotInfo *bi = findbot(Config->s_OperServ); + if (bi) + ircdproto->SendGlobops(bi, "CHGHOST not loaded!"); + } } bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -210,7 +215,7 @@ class InspIRCdProto : public IRCDProto send_cmd(Config->s_OperServ, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); } else - ircdproto->SendGlobops(OperServ, "CHGIDENT not loaded!"); + Log() << "CHGIDENT not loaded!"; } /* SVSHOLD - set */ @@ -307,7 +312,7 @@ class InspircdIRCdMessage : public IRCdMessage time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; User *user = do_nick("", params[1], params[4], params[2], source, params[7], ts, params[6], params[3], "", params[5]); - if (user) + if (user && nickserv) { user->SetCloakedHost(params[3]); @@ -317,10 +322,10 @@ class InspircdIRCdMessage : public IRCdMessage { user->Login(na->nc); if (na->nc->HasFlag(NI_UNCONFIRMED)) - user->SetMode(NickServ, UMODE_REGISTERED); + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); } else - validate_user(user); + nickserv->Validate(user); } } else if (params.size() == 1) @@ -567,11 +572,11 @@ class InspircdIRCdMessage : public IRCdMessage return false; } if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + Log() << "SVSHOLD missing, Usage disabled until module is loaded."; if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + Log() << "CHGIDENT missing, Usage disabled until module is loaded."; ircd->svshold = has_svsholdmod; } diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index 82d43434c..4723a21af 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" /* inspircd-ts6.h uses these */ static bool has_globopsmod = false; @@ -57,11 +58,12 @@ void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) { if (!has_chghostmod) { - ircdproto->SendGlobops(OperServ, "CHGHOST not loaded!"); + Log() << "CHGHOST not loaded!"; return; } - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); + User *u = finduser(nick); + send_cmd(u ? u->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); } bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -260,13 +262,14 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string else if (params[1].equals_cs("accountname")) { User *u = finduser(params[0]); - NickAlias *user_na = u ? findnick(u->nick) : NULL; NickCore *nc = findcore(params[2]); if (u && nc) { u->Login(nc); - if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); + + NickAlias *user_na = findnick(u->nick); + if (nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(nickserv->Bot(), UMODE_REGISTERED); } } @@ -383,8 +386,8 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage for (unsigned i = 9; i < params.size() - 1; ++i) modes += " " + params[i]; User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced()) - validate_user(user); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); return true; } @@ -709,11 +712,11 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage return false; } if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + Log() << "SVSHOLD missing, Usage disabled until module is loaded."; if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + Log() << "CHGIDENT missing, Usage disabled until module is loaded."; ircd->svshold = has_svsholdmod; } @@ -763,17 +766,18 @@ class ProtoInspIRCd : public Module /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later * this will cancel out this -r, resulting in no mode changes. */ - u->RemoveMode(NickServ, UMODE_REGISTERED); + u->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); } void OnServerSync(Server *s) { - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u = it->second; - if (u->server == s && !u->IsIdentified()) - validate_user(u); - } + if (nickserv) + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u = it->second; + if (u->server == s && !u->IsIdentified()) + nickserv->Validate(u); + } } }; diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 575958bd8..3cb4979a9 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" /* inspircd-ts6.h uses these */ static bool has_chghostmod = false; @@ -56,11 +57,12 @@ void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) { if (!has_chghostmod) { - ircdproto->SendGlobops(OperServ, "CHGHOST not loaded!"); + Log() << "CHGHOST not loaded!"; return; } - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); + User *u = finduser(nick); + send_cmd(u ? u->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); } bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -270,13 +272,14 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string else if (params[1].equals_cs("accountname")) { User *u = finduser(params[0]); - NickAlias *user_na = u ? findnick(u->nick) : NULL; NickCore *nc = findcore(params[2]); if (u && nc) { u->Login(nc); - if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); + + NickAlias *user_na = findnick(u->nick); + if (nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(nickserv->Bot(), UMODE_REGISTERED); } } @@ -414,8 +417,8 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage for (unsigned i = 9; i < params.size() - 1; ++i) modes += Anope::string(" ") + params[i]; User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced()) - validate_user(user); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); return true; } @@ -704,11 +707,11 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage return false; } if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + Log() << "SVSHOLD missing, Usage disabled until module is loaded."; if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + Log() << "CHGIDENT missing, Usage disabled until module is loaded."; ircd->svshold = has_svsholdmod; } @@ -759,12 +762,13 @@ class ProtoInspIRCd : public Module void OnServerSync(Server *s) { - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u = it->second; - if (u->server == s && !u->IsIdentified()) - validate_user(u); - } + if (nickserv) + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u = it->second; + if (u->server == s && !u->IsIdentified()) + nickserv->Validate(u); + } } }; diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 3b299e962..a078e6b77 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" static Anope::string TS6UPLINK; @@ -100,19 +101,19 @@ class PlexusProto : public IRCDProto void SendSGLineDel(const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNXLINE * %s", x->Mask.c_str()); } void SendSGLine(User *, const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); } void SendAkillDel(const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); } @@ -132,7 +133,7 @@ class PlexusProto : public IRCDProto void SendAkill(User *, const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); } @@ -269,7 +270,7 @@ class PlexusIRCdMessage : public IRCdMessage ip.clear(); User *user = do_nick("", params[0], params[4], params[9], source, params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip, params[5], params[7], params[3]); if (user && user->server->IsSynced()) - validate_user(user); + nickserv->Validate(user); return true; } @@ -528,7 +529,7 @@ bool event_encap(const Anope::string &source, const std::vector<Anope::string> & { u->Login(nc); if (user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(NickServ, UMODE_REGISTERED); + u->SetMode(nickserv->Bot(), UMODE_REGISTERED); } } @@ -648,7 +649,7 @@ class ProtoPlexus : public Module { User *u = it->second; if (u->server == s && !u->IsIdentified()) - validate_user(u); + nickserv->Validate(u); } } }; diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 62a8d5a72..11d4ccfe6 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" static Anope::string TS6UPLINK; @@ -103,19 +104,19 @@ class RatboxProto : public IRCDProto void SendSGLineDel(const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNXLINE * %s", x->Mask.c_str()); } void SendSGLine(User *, const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "XLINE * %s 0 :%s", x->Mask.c_str(), x->Reason.c_str()); } void SendAkillDel(const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "UNKLINE * %s %s", x->GetUser().c_str(), x->GetHost().c_str()); } @@ -142,7 +143,7 @@ class RatboxProto : public IRCDProto void SendAkill(User *, const XLine *x) { - BotInfo *bi = OperServ; + BotInfo *bi = findbot(Config->s_OperServ); send_cmd(bi ? bi->GetUID() : Config->s_OperServ, "KLINE * %ld %s %s :%s", static_cast<long>(x->Expires - Anope::CurTime), x->GetUser().c_str(), x->GetHost().c_str(), x->Reason.c_str()); } @@ -269,8 +270,8 @@ class RatboxIRCdMessage : public IRCdMessage { /* Source is always the server */ User *user = do_nick("", params[0], params[4], params[5], source, params[8], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[6], "*", params[7], params[3]); - if (user && user->server->IsSynced()) - validate_user(user); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); return true; } @@ -579,12 +580,13 @@ class ProtoRatbox : public Module void OnServerSync(Server *s) { - for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *u = it->second; - if (u->server == s && !u->IsIdentified()) - validate_user(u); - } + if (nickserv) + for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) + { + User *u = it->second; + if (u->server == s && !u->IsIdentified()) + nickserv->Validate(u); + } } }; diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp index b6e438461..7e874838d 100644 --- a/modules/protocol/unreal32.cpp +++ b/modules/protocol/unreal32.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" IRCDVar myIrcd[] = { {"UnrealIRCd 3.2.x", /* ircd name */ @@ -107,11 +108,11 @@ class UnrealIRCdProto : public IRCDProto void SendVhostDel(User *u) { - u->RemoveMode(HostServ, UMODE_CLOAK); - u->RemoveMode(HostServ, UMODE_VHOST); - ModeManager::ProcessModes(); - u->SetMode(HostServ, UMODE_CLOAK); + BotInfo *bi = findbot(Config->s_HostServ); + u->RemoveMode(bi, UMODE_CLOAK); + u->RemoveMode(bi, UMODE_VHOST); ModeManager::ProcessModes(); + u->SetMode(bi, UMODE_CLOAK); } void SendAkill(User *, const XLine *x) @@ -322,12 +323,12 @@ class UnrealIRCdProto : public IRCDProto if (!u->Account()) return; - ircdproto->SendMode(NickServ, u, "+d %d", u->timestamp); + ircdproto->SendMode(nickserv->Bot(), u, "+d %d", u->timestamp); } void SendUnregisteredNick(const User *u) { - ircdproto->SendMode(NickServ, u, "+d 1"); + ircdproto->SendMode(nickserv->Bot(), u, "+d 1"); } void SendChannel(Channel *c) @@ -335,7 +336,7 @@ class UnrealIRCdProto : public IRCDProto /* Unreal does not support updating a channels TS without actually joining a user, * so we will join and part us now */ - BotInfo *bi = whosends(c->ci); + BotInfo *bi = c->ci->WhoSends(); if (c->FindUser(bi) == NULL) { bi->Join(c); @@ -529,11 +530,11 @@ class Unreal32IRCdMessage : public IRCdMessage if (na && user->timestamp == convertTo<time_t>(params[6])) { user->Login(na->nc); - if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(NickServ, UMODE_REGISTERED); + if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); } - else - validate_user(user); + else if (nickserv) + nickserv->Validate(user); } } else if (params.size() != 2) @@ -551,11 +552,11 @@ class Unreal32IRCdMessage : public IRCdMessage if (na && user->timestamp == convertTo<time_t>(params[6])) { user->Login(na->nc); - if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(NickServ, UMODE_REGISTERED); + if (na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); } - else - validate_user(user); + else if (nickserv) + nickserv->Validate(user); } } else diff --git a/src/bots.cpp b/src/bots.cpp index 95a5c2aa5..c67456ba4 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -12,14 +12,6 @@ Anope::insensitive_map<BotInfo *> BotListByNick; Anope::map<BotInfo *> BotListByUID; -BotInfo *BotServ = NULL; -BotInfo *ChanServ = NULL; -BotInfo *Global = NULL; -BotInfo *HostServ = NULL; -BotInfo *MemoServ = NULL; -BotInfo *NickServ = NULL; -BotInfo *OperServ = NULL; - BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const Anope::string &nhost, const Anope::string &nreal) : User(nnick, nuser, nhost, ts6_uid_retrieve()), Flags<BotFlag, BI_END>(BotFlagString) { this->realname = nreal; @@ -28,24 +20,6 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A this->chancount = 0; this->lastmsg = this->created = Anope::CurTime; - this->SetFlag(BI_CORE); - if (!Config->s_ChanServ.empty() && nnick.equals_ci(Config->s_ChanServ)) - ChanServ = this; - else if (!Config->s_BotServ.empty() && nnick.equals_ci(Config->s_BotServ)) - BotServ = this; - else if (!Config->s_HostServ.empty() && nnick.equals_ci(Config->s_HostServ)) - HostServ = this; - else if (!Config->s_OperServ.empty() && nnick.equals_ci(Config->s_OperServ)) - OperServ = this; - else if (!Config->s_MemoServ.empty() && nnick.equals_ci(Config->s_MemoServ)) - MemoServ = this; - else if (!Config->s_NickServ.empty() && nnick.equals_ci(Config->s_NickServ)) - NickServ = this; - else if (!Config->s_GlobalNoticer.empty() && nnick.equals_ci(Config->s_GlobalNoticer)) - Global = this; - else - this->UnsetFlag(BI_CORE); - BotListByNick[this->nick] = this; if (!this->uid.empty()) BotListByUID[this->uid] = this; @@ -60,6 +34,31 @@ BotInfo::BotInfo(const Anope::string &nnick, const Anope::string &nuser, const A this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_PROTECTED)); this->SetModeInternal(ModeManager::FindUserModeByName(UMODE_GOD)); + + for (unsigned i = 0; i < Config->LogInfos.size(); ++i) + { + LogInfo *l = Config->LogInfos[i]; + + if (!ircd->join2msg && !l->Inhabit) + continue; + + for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + if (!c->FindUser(this)) + this->Join(c, &Config->BotModeList); + } + } + } } BotInfo::~BotInfo() @@ -91,24 +90,6 @@ BotInfo::~BotInfo() BotListByNick.erase(this->nick); if (!this->uid.empty()) BotListByUID.erase(this->uid); - - if (this->HasFlag(BI_CORE)) - { - if (this == ChanServ) - ChanServ = NULL; - else if (this == BotServ) - BotServ = NULL; - else if (this == HostServ) - HostServ = NULL; - else if (this == OperServ) - OperServ = NULL; - else if (this == MemoServ) - MemoServ = NULL; - else if (this == NickServ) - NickServ = NULL; - else if (this == Global) - Global = NULL; - } } void BotInfo::SetNewNick(const Anope::string &newnick) @@ -213,3 +194,9 @@ void BotInfo::Part(Channel *c, const Anope::string &reason) ircdproto->SendPart(this, c, "%s", !reason.empty() ? reason.c_str() : ""); c->DeleteUser(this); } + +void BotInfo::OnMessage(User *u, const Anope::string &message) +{ + mod_run_cmd(this, u, NULL, message); +} + diff --git a/src/botserv.cpp b/src/botserv.cpp index 119264c1d..45d30b395 100644 --- a/src/botserv.cpp +++ b/src/botserv.cpp @@ -14,351 +14,6 @@ #include "services.h" #include "modules.h" -static UserData *get_user_data(Channel *c, User *u); - -E void moduleAddBotServCmds(); - -/*************************************************************************/ - -void moduleAddBotServCmds() -{ - ModuleManager::LoadModuleList(Config->BotServCoreModules); -} - -/*************************************************************************/ -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_botserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - - for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - ++count; - mem += sizeof(*bi); - mem += bi->nick.length() + 1; - mem += bi->GetIdent().length() + 1; - mem += bi->host.length() + 1; - mem += bi->realname.length() + 1; - } - - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* BotServ initialization. */ - -void bs_init() -{ - if (!Config->s_BotServ.empty()) - moduleAddBotServCmds(); -} - -/*************************************************************************/ - -/* Handles all messages that are sent to registered channels where a - * bot is on. - */ - -void botchanmsgs(User *u, ChannelInfo *ci, const Anope::string &buf) -{ - if (!u || !ci || !ci->c || buf.empty()) - return; - - /* Answer to ping if needed */ - if (buf.substr(0, 6).equals_ci("\1PING ") && buf[buf.length() - 1] == '\1') - { - Anope::string ctcp = buf; - ctcp.erase(ctcp.begin()); - ctcp.erase(ctcp.length() - 1); - ircdproto->SendCTCP(ci->bi, u->nick, "%s", ctcp.c_str()); - } - - bool was_action = false; - Anope::string realbuf = buf; - - /* If it's a /me, cut the CTCP part because the ACTION will cause - * problems with the caps or badwords kicker - */ - if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1') - { - realbuf.erase(0, 8); - realbuf.erase(realbuf.length() - 1); - was_action = true; - } - - if (realbuf.empty()) - return; - - /* Now we can make kicker stuff. We try to order the checks - * from the fastest one to the slowest one, since there's - * no need to process other kickers if a user is kicked before - * the last kicker check. - * - * But FIRST we check whether the user is protected in any - * way. - */ - - bool Allow = true; - if (check_access(u, ci, CA_NOKICK)) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKOPS) && (ci->c->HasUserStatus(u, CMODE_HALFOP) || ci->c->HasUserStatus(u, CMODE_OP) || ci->c->HasUserStatus(u, CMODE_PROTECT) || ci->c->HasUserStatus(u, CMODE_OWNER))) - Allow = false; - else if (ci->botflags.HasFlag(BS_DONTKICKVOICES) && ci->c->HasUserStatus(u, CMODE_VOICE)) - Allow = false; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPrivmsg, OnPrivmsg(u, ci, realbuf, Allow)); - if (MOD_RESULT == EVENT_STOP) - return; - - if (Allow) - { - /* Bolds kicker */ - if (ci->botflags.HasFlag(BS_KICK_BOLDS) && realbuf.find(2) != Anope::string::npos) - { - check_ban(ci, u, TTB_BOLDS); - bot_kick(ci, u, _("Don't use bolds on this channel!")); - return; - } - - /* Color kicker */ - if (ci->botflags.HasFlag(BS_KICK_COLORS) && realbuf.find(3) != Anope::string::npos) - { - check_ban(ci, u, TTB_COLORS); - bot_kick(ci, u, _("Don't use colors on this channel!")); - return; - } - - /* Reverses kicker */ - if (ci->botflags.HasFlag(BS_KICK_REVERSES) && realbuf.find(22) != Anope::string::npos) - { - check_ban(ci, u, TTB_REVERSES); - bot_kick(ci, u, _("Don't use reverses on this channel!")); - return; - } - - /* Italics kicker */ - if (ci->botflags.HasFlag(BS_KICK_ITALICS) && realbuf.find(29) != Anope::string::npos) - { - check_ban(ci, u, TTB_ITALICS); - bot_kick(ci, u, _("Don't use italics on this channel!")); - return; - } - - /* Underlines kicker */ - if (ci->botflags.HasFlag(BS_KICK_UNDERLINES) && realbuf.find(31) != Anope::string::npos) - { - check_ban(ci, u, TTB_UNDERLINES); - bot_kick(ci, u, _("Don't use underlines on this channel!")); - return; - } - - /* Caps kicker */ - if (ci->botflags.HasFlag(BS_KICK_CAPS) && realbuf.length() >= ci->capsmin) - { - int i = 0, l = 0; - - for (unsigned j = 0, end = realbuf.length(); j < end; ++j) - { - if (isupper(realbuf[j])) - ++i; - else if (islower(realbuf[j])) - ++l; - } - - /* i counts uppercase chars, l counts lowercase chars. Only - * alphabetic chars (so islower || isupper) qualify for the - * percentage of caps to kick for; the rest is ignored. -GD - */ - - if ((i || l) && i >= ci->capsmin && i * 100 / (i + l) >= ci->capspercent) - { - check_ban(ci, u, TTB_CAPS); - bot_kick(ci, u, _("Turn caps lock OFF!")); - return; - } - } - - /* Bad words kicker */ - if (ci->botflags.HasFlag(BS_KICK_BADWORDS)) - { - bool mustkick = false; - - /* Normalize the buffer */ - Anope::string nbuf = normalizeBuffer(realbuf); - - for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i) - { - BadWord *bw = ci->GetBadWord(i); - - if (bw->type == BW_ANY && ((Config->BSCaseSensitive && nbuf.find(bw->word) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) != Anope::string::npos))) - mustkick = true; - else if (bw->type == BW_SINGLE) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf))) - mustkick = true; - else if (nbuf.find(' ') == len && ((Config->BSCaseSensitive && bw->word.equals_cs(nbuf)) || (!Config->BSCaseSensitive && bw->word.equals_ci(nbuf)))) - mustkick = true; - else - { - if (nbuf.rfind(' ') == nbuf.length() - len - 1 && ((Config->BSCaseSensitive && nbuf.find(bw->word) == nbuf.length() - len) || (!Config->BSCaseSensitive && nbuf.find_ci(bw->word) == nbuf.length() - len))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - } - else if (bw->type == BW_START) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(0, len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(0, len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = " " + bw->word; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - else if (bw->type == BW_END) - { - size_t len = bw->word.length(); - - if ((Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_cs(bw->word)) || (!Config->BSCaseSensitive && nbuf.substr(nbuf.length() - len).equals_ci(bw->word))) - mustkick = true; - else - { - Anope::string wordbuf = bw->word + " "; - - if ((Config->BSCaseSensitive && nbuf.find(wordbuf) != Anope::string::npos) || (!Config->BSCaseSensitive && nbuf.find_ci(wordbuf) != Anope::string::npos)) - mustkick = true; - } - } - - if (mustkick) - { - check_ban(ci, u, TTB_BADWORDS); - if (Config->BSGentleBWReason) - bot_kick(ci, u, _("Watch your language!")); - else - bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str()); - - return; - } - } - } - - /* Flood kicker */ - if (ci->botflags.HasFlag(BS_KICK_FLOOD)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (Anope::CurTime - ud->last_start > ci->floodsecs) - { - ud->last_start = Anope::CurTime; - ud->lines = 0; - } - - ++ud->lines; - if (ud->lines >= ci->floodlines) - { - check_ban(ci, u, TTB_FLOOD); - bot_kick(ci, u, _("Stop flooding!")); - return; - } - } - - /* Repeat kicker */ - if (ci->botflags.HasFlag(BS_KICK_REPEAT)) - { - UserData *ud = get_user_data(ci->c, u); - if (!ud) - return; - - if (!ud->lastline.empty() && !ud->lastline.equals_ci(buf)) - { - ud->lastline = buf; - ud->times = 0; - } - else - { - if (ud->lastline.empty()) - ud->lastline = buf; - ++ud->times; - } - - if (ud->times >= ci->repeattimes) - { - check_ban(ci, u, TTB_REPEAT); - bot_kick(ci, u, _("Stop repeating yourself!")); - return; - } - } - } - - /* Fantaisist commands */ - if (ci->botflags.HasFlag(BS_FANTASY) && buf[0] == Config->BSFantasyCharacter[0] && !was_action) - { - Anope::string message = buf; - /* Strip off the fantasy character */ - message.erase(message.begin()); - - size_t space = message.find(' '); - Anope::string command, rest; - if (space == Anope::string::npos) - command = message; - else - { - command = message.substr(0, space); - rest = message.substr(space + 1); - } - - if (check_access(u, ci, CA_FANTASIA)) - { - - Command *cmd = FindCommand(ChanServ, command); - - /* Command exists and can be called by fantasy */ - if (cmd && !cmd->HasFlag(CFLAG_DISABLE_FANTASY)) - { - Anope::string params = rest; - /* Some commands don't need the channel name added.. eg !help */ - if (!cmd->HasFlag(CFLAG_STRIP_CHANNEL)) - params = ci->name + " " + params; - params = command + " " + params; - - mod_run_cmd(ChanServ, u, ci, params); - } - - FOREACH_MOD(I_OnBotFantasy, OnBotFantasy(command, u, ci, rest)); - } - else - { - FOREACH_MOD(I_OnBotNoFantasyAccess, OnBotNoFantasyAccess(command, u, ci, rest)); - } - } -} - -/*************************************************************************/ - BotInfo *findbot(const Anope::string &nick) { BotInfo *bi = NULL; @@ -380,138 +35,6 @@ BotInfo *findbot(const Anope::string &nick) return bi; } -/*************************************************************************/ - -/* Returns ban data associated with a user if it exists, allocates it - otherwise. */ - -static BanData *get_ban_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - Anope::string mask = u->GetIdent() + "@" + u->GetDisplayedHost(); - /* XXX This should really be on some sort of timer/garbage collector, and use std::map */ - for (std::list<BanData *>::iterator it = c->bd.begin(), it_end = c->bd.end(), it_next; it != it_end; it = it_next) - { - it_next = it; - ++it_next; - - if (Anope::CurTime - (*it)->last_use > Config->BSKeepData) - { - delete *it; - c->bd.erase(it); - continue; - } - if ((*it)->mask.equals_ci(mask)) - { - (*it)->last_use = Anope::CurTime; - return *it; - } - } - - /* If we fall here it is that we haven't found the record */ - BanData *bd = new BanData(); - bd->mask = mask; - bd->last_use = Anope::CurTime; - for (int x = 0; x < TTB_SIZE; ++x) - bd->ttb[x] = 0; - - c->bd.push_front(bd); - - return bd; -} - -/*************************************************************************/ - -/* Returns BotServ data associated with a user on a given channel. - * Allocates it if necessary. - */ - -static UserData *get_user_data(Channel *c, User *u) -{ - if (!c || !u) - return NULL; - - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - UserContainer *uc = *it; - - if (uc->user == u) - { - /* Checks whether data is obsolete */ - if (Anope::CurTime - uc->ud.last_use > Config->BSKeepData) - { - /* We should not free and realloc, but reset to 0 - instead. */ - uc->ud.Clear(); - uc->ud.last_use = Anope::CurTime; - } - - return &uc->ud; - } - } - - return NULL; -} - -/*************************************************************************/ - -/** Check if a user should be banned by botserv - * @param ci The channel the user is on - * @param u The user - * @param ttbtype The type of bot kicker the user should be checked against - */ -void check_ban(ChannelInfo *ci, User *u, int ttbtype) -{ - BanData *bd = get_ban_data(ci->c, u); - - if (!bd) - return; - - /* Don't ban ulines */ - if (u->server->IsULined()) - return; - - ++bd->ttb[ttbtype]; - if (ci->ttb[ttbtype] && bd->ttb[ttbtype] >= ci->ttb[ttbtype]) - { - /* Should not use == here because bd->ttb[ttbtype] could possibly be > ci->ttb[ttbtype] - * if the TTB was changed after it was not set (0) before and the user had already been - * kicked a few times. Bug #1056 - Adam */ - Anope::string mask; - - bd->ttb[ttbtype] = 0; - - get_idealban(ci, u, mask); - - if (ci->c) - ci->c->SetMode(NULL, CMODE_BAN, mask); - FOREACH_MOD(I_OnBotBan, OnBotBan(u, ci, mask)); - } -} - -/*************************************************************************/ - -/* This makes a bot kick a user. Works somewhat like notice_lang in fact ;) */ - -void bot_kick(ChannelInfo *ci, User *u, const char *message, ...) -{ - va_list args; - char buf[1024]; - - if (!ci || !ci->bi || !ci->c || !u) - return; - - Anope::string fmt = GetString(u->Account(), message); - va_start(args, message); - if (fmt.empty()) - return; - vsnprintf(buf, sizeof(buf), fmt.c_str(), args); - va_end(args); - - ci->c->Kick(ci->bi, u, "%s", buf); -} /*************************************************************************/ @@ -585,80 +108,3 @@ void bot_raw_kick(User *requester, ChannelInfo *ci, User *u, const Anope::string ci->c->Kick(ci->bi, u, "%s", !reason.empty() ? reason.c_str() : ci->bi->nick.c_str()); } -/*************************************************************************/ - -/** - * Normalize buffer stripping control characters and colors - * @param A string to be parsed for control and color codes - * @return A string stripped of control and color codes - */ -Anope::string normalizeBuffer(const Anope::string &buf) -{ - Anope::string newbuf; - - for (unsigned i = 0, end = buf.length(); i < end; ++i) - { - switch (buf[i]) - { - /* ctrl char */ - case 1: - break; - /* Bold ctrl char */ - case 2: - break; - /* Color ctrl char */ - case 3: - /* If the next character is a digit, its also removed */ - if (isdigit(buf[i + 1])) - { - ++i; - - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - - /* Check for background color code - * and remove it as well - */ - if (buf[i + 1] == ',') - { - ++i; - - if (isdigit(buf[i + 1])) - ++i; - /* not the best way to remove colors - * which are two digit but no worse then - * how the Unreal does with +S - TSL - */ - if (isdigit(buf[i + 1])) - ++i; - } - } - - break; - /* line feed char */ - case 10: - break; - /* carriage returns char */ - case 13: - break; - /* Reverse ctrl char */ - case 22: - break; - /* Underline ctrl char */ - case 31: - break; - /* Italic ctrl char */ - case 29: - break; - /* A valid char gets copied into the new buffer */ - default: - newbuf += buf[i]; - } - } - - return newbuf; -} diff --git a/src/channels.cpp b/src/channels.cpp index 2fe4e037d..29e34cfaf 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -52,9 +52,6 @@ Channel::~Channel() Log(NULL, this, "destroy"); - for (std::list<BanData *>::iterator it = this->bd.begin(), it_end = this->bd.end(); it != it_end; ++it) - delete *it; - if (this->ci) this->ci->c = NULL; @@ -128,14 +125,6 @@ void Channel::JoinUser(User *user) this->Reset(); } - if (this->ci && check_access(user, this->ci, CA_MEMO) && this->ci->memos.memos.size() > 0) - { - if (this->ci->memos.memos.size() == 1) - user->SendMessage(MemoServ, _("There is \002%d\002 memo on channel %s."), this->ci->memos.memos.size(), this->ci->name.c_str()); - else - user->SendMessage(MemoServ, _("There are \002%d\002 memos on channel %s."), this->ci->memos.memos.size(), this->ci->name.c_str()); - } - if (!Config->s_BotServ.empty() && this->ci && this->ci->bi) { /** @@ -838,8 +827,8 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...) FOREACH_RESULT(I_OnBotKick, OnBotKick(bi, this, u, buf)); if (MOD_RESULT == EVENT_STOP) return false; - ircdproto->SendKick(bi ? bi : whosends(this->ci), this, u, "%s", buf); - this->KickInternal(bi ? bi->nick : whosends(this->ci)->nick, u->nick, buf); + ircdproto->SendKick(bi ? bi : this->ci->WhoSends(), this, u, "%s", buf); + this->KickInternal(bi ? bi->nick : this->ci->WhoSends()->nick, u->nick, buf); return true; } @@ -891,7 +880,7 @@ void Channel::ChangeTopic(const Anope::string &user, const Anope::string &newtop this->topic_setter = u ? u->nick : user; this->topic_time = ts; - ircdproto->SendTopic(whosends(this->ci), this); + ircdproto->SendTopic(this->ci->WhoSends(), this); FOREACH_MOD(I_OnTopicUpdated, OnTopicUpdated(this, this->topic)); @@ -914,41 +903,6 @@ Channel *findchan(const Anope::string &chan) /*************************************************************************/ -/* Return statistics. Pointers are assumed to be valid. */ - -void get_channel_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - Anope::string buf; - - for (channel_map::const_iterator cit = ChannelList.begin(); cit != ChannelList.end(); ++cit) - { - Channel *chan = cit->second; - - ++count; - mem += sizeof(*chan); - if (!chan->topic.empty()) - mem += chan->topic.length() + 1; - for (CUserList::iterator it = chan->users.begin(), it_end = chan->users.end(); it != it_end; ++it) - { - mem += sizeof(*it); - mem += sizeof((*it)->ud); - if (!(*it)->ud.lastline.empty()) - mem += (*it)->ud.lastline.length() + 1; - } - for (std::list<BanData *>::iterator it = chan->bd.begin(), it_end = chan->bd.end(); it != it_end; ++it) - { - if (!(*it)->mask.empty()) - mem += (*it)->mask.length() + 1; - mem += sizeof(*it); - } - } - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ - /* Is the given nick on the given channel? This function supports links. */ diff --git a/src/chanserv.cpp b/src/chanserv.cpp index ef7005667..fe86cdae3 100644 --- a/src/chanserv.cpp +++ b/src/chanserv.cpp @@ -13,6 +13,7 @@ #include "services.h" #include "modules.h" +#include "chanserv.h" registered_channel_map RegisteredChannelList; @@ -140,70 +141,6 @@ Anope::string get_mlock_modes(ChannelInfo *ci, int complete) /*************************************************************************/ -/* Return information on memory use. Assumes pointers are valid. */ - -void get_chanserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - ModeLock *ml; - - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it) - { - ChannelInfo *ci = it->second; - - ++count; - mem += sizeof(*ci); - if (!ci->desc.empty()) - mem += ci->desc.length() + 1; - mem += ci->GetAccessCount() * sizeof(ChanAccess); - mem += ci->GetAkickCount() * sizeof(AutoKick); - - ml = ci->GetMLock(CMODE_KEY); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - ml = ci->GetMLock(CMODE_FLOOD); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - ml = ci->GetMLock(CMODE_REDIRECT); - if (ml && !ml->param.empty()) - mem += ml->param.length() + 1; - - if (!ci->last_topic.empty()) - mem += ci->last_topic.length() + 1; - if (!ci->forbidby.empty()) - mem += ci->forbidby.length() + 1; - if (!ci->forbidreason.empty()) - mem += ci->forbidreason.length() + 1; - if (ci->levels) - mem += sizeof(*ci->levels) * CA_SIZE; - unsigned memos = ci->memos.memos.size(); - mem += memos * sizeof(Memo); - for (unsigned j = 0; j < memos; ++j) - if (!ci->memos.memos[j]->text.empty()) - mem += ci->memos.memos[j]->text.length() + 1; - if (ci->ttb) - mem += sizeof(*ci->ttb) * TTB_SIZE; - mem += ci->GetBadWordCount() * sizeof(BadWord); - } - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ -/*************************************************************************/ - -/* ChanServ initialization. */ - -void cs_init() -{ - if (!Config->s_ChanServ.empty()) - ModuleManager::LoadModuleList(Config->ChanServCoreModules); -} - -/*************************************************************************/ - /* Check the current modes on a channel; if they conflict with a mode lock, * fix them. */ @@ -288,194 +225,6 @@ void check_modes(Channel *c) /*************************************************************************/ -int check_valid_admin(User *user, Channel *chan, int servermode) -{ - ChannelMode *cm; - - if (!chan || !chan->ci) - return 1; - - if (!(cm = ModeManager::FindChannelModeByName(CMODE_PROTECT))) - return 0; - - /* They will be kicked; no need to deop, no need to update our internal struct too */ - if (chan->ci->HasFlag(CI_FORBIDDEN)) - return 0; - - if (servermode && !check_access(user, chan->ci, CA_AUTOPROTECT)) - { - user->SendMessage(ChanServ, _("This channel has been registered with %s."), Config->s_ChanServ.c_str()); - chan->RemoveMode(NULL, CMODE_PROTECT, user->nick); - return 0; - } - - return 1; -} - -/*************************************************************************/ - -/* Check whether a user is allowed to be opped on a channel; if they - * aren't, deop them. If serverop is 1, the +o was done by a server. - * Return 1 if the user is allowed to be opped, 0 otherwise. */ - -int check_valid_op(User *user, Channel *chan, int servermode) -{ - ChannelMode *owner, *protect, *halfop; - if (!chan || !chan->ci) - return 1; - - /* They will be kicked; no need to deop, no need to update our internal struct too */ - if (chan->ci->HasFlag(CI_FORBIDDEN)) - return 0; - - owner = ModeManager::FindChannelModeByName(CMODE_OWNER); - protect = ModeManager::FindChannelModeByName(CMODE_PROTECT); - halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); - - if (servermode && !check_access(user, chan->ci, CA_AUTOOP)) - { - user->SendMessage(ChanServ, _("This channel has been registered with %s."), Config->s_ChanServ.c_str()); - - if (owner) - chan->RemoveMode(NULL, CMODE_OWNER, user->nick); - if (protect) - chan->RemoveMode(NULL, CMODE_PROTECT, user->nick); - chan->RemoveMode(NULL, CMODE_OP, user->nick); - if (halfop && !check_access(user, chan->ci, CA_AUTOHALFOP)) - chan->RemoveMode(NULL, CMODE_HALFOP, user->nick); - - return 0; - } - - return 1; -} - -/*************************************************************************/ - -/* Remove all channels which have expired. */ - -void expire_chans() -{ - if (!Config->CSExpire) - return; - - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ) - { - ChannelInfo *ci = it->second; - ++it; - - bool expire = false; - if (ci->HasFlag(CI_SUSPENDED)) - { - if (Config->CSSuspendExpire && Anope::CurTime - ci->last_used >= Config->CSSuspendExpire) - expire = true; - } - else if (ci->HasFlag(CI_FORBIDDEN)) - { - if (Config->CSForbidExpire && Anope::CurTime - ci->last_used >= Config->CSForbidExpire) - expire = true; - } - else if (!ci->c && Anope::CurTime - ci->last_used >= Config->CSExpire) - expire = true; - - if (ci->HasFlag(CI_NO_EXPIRE)) - expire = false; - - if (expire) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreChanExpire, OnPreChanExpire(ci)); - if (MOD_RESULT == EVENT_STOP) - continue; - - Anope::string extra; - if (ci->HasFlag(CI_FORBIDDEN)) - extra = "forbidden "; - else if (ci->HasFlag(CI_SUSPENDED)) - extra = "suspended "; - - Log(LOG_NORMAL, "chanserv/expire") << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->founder ? ci->founder->display : "(none)") << ")"; - FOREACH_MOD(I_OnChanExpire, OnChanExpire(ci)); - delete ci; - } - } -} - -/*************************************************************************/ - -// XXX this is slightly inefficient -void cs_remove_nick(NickCore *nc) -{ - for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end;) - { - ChannelInfo *ci = it->second; - ++it; - - for (unsigned j = ci->GetAkickCount(); j > 0; --j) - { - AutoKick *akick = ci->GetAkick(j - 1); - if (akick->HasFlag(AK_ISNICK) && akick->nc == nc) - ci->EraseAkick(j - 1); - } - - if (ci->founder == nc) - { - NickCore *newowner = NULL; - if (ci->successor && (ci->successor->IsServicesOper() || !Config->CSMaxReg || ci->successor->channelcount < Config->CSMaxReg)) - newowner = ci->successor; - else - { - ChanAccess *highest = NULL; - for (unsigned j = 0; j < ci->GetAccessCount(); ++j) - { - ChanAccess *ca = ci->GetAccess(j); - - if (!ca->nc || (!ca->nc->IsServicesOper() && Config->CSMaxReg && ca->nc->channelcount >= Config->CSMaxReg) || (ca->nc == nc)) - continue; - if (!highest || ca->level > highest->level) - highest = ca; - } - if (highest) - newowner = highest->nc; - } - - if (newowner) - { - Log(LOG_NORMAL, "chanserv/expire") << "Transferring foundership of " << ci->name << " from deleted nick " << nc->display << " to " << newowner->display; - ci->founder = newowner; - ci->successor = NULL; - ++newowner->channelcount; - } - else - { - Log(LOG_NORMAL, "chanserv/expire") << "Deleting channel " << ci->name << " owned by deleted nick " << nc->display; - - if (ModeManager::FindChannelModeByName(CMODE_REGISTERED)) - { - /* Maybe move this to delchan() ? */ - if (ci->c && ci->c->HasMode(CMODE_REGISTERED)) - ci->c->RemoveMode(NULL, CMODE_REGISTERED, true); - } - - delete ci; - continue; - } - } - - if (ci->successor == nc) - ci->successor = NULL; - - /* Note that it is important we lookup the access for the channel after the new founder - * has been determined incase this user was the founder and also was on the access list! - */ - ChanAccess *access = ci->GetAccess(nc); - if (access) - ci->EraseAccess(access); - } -} - -/*************************************************************************/ - ChannelInfo *cs_findchan(const Anope::string &chan) { FOREACH_MOD(I_OnFindChan, OnFindChan(chan)); @@ -534,10 +283,6 @@ int check_access(User *user, ChannelInfo *ci, int what) return level >= ci->levels[what]; } -/*************************************************************************/ -/*********************** ChanServ private routines ***********************/ -/*************************************************************************/ - /* Reset channel access level values to their default state. */ void reset_levels(ChannelInfo *ci) @@ -657,26 +402,29 @@ Anope::string get_xop_level(int level) ChanServTimer::ChanServTimer(Channel *chan) : Timer(Config->CSInhabit), c(chan) { - if (!ChanServ) + if (!chanserv) return; if (c->ci) c->ci->SetFlag(CI_INHABIT); if (!c->ci || !c->ci->bi) - ChanServ->Join(*c); + chanserv->Bot()->Join(c); else if (!c->FindUser(c->ci->bi)) - c->ci->bi->Join(*c); + c->ci->bi->Join(c); } void ChanServTimer::Tick(time_t) { - if (!c || !c->ci || !ChanServ) + if (!c || !c->ci) return; c->ci->UnsetFlag(CI_INHABIT); - if (!c->ci->bi && ChanServ) - ChanServ->Part(*c); + if (!c->ci->bi) + { + if (chanserv) + chanserv->Bot()->Part(c); + } else if (c->users.size() == 1 || c->users.size() < Config->BSMinUsers) - c->ci->bi->Part(*c); + c->ci->bi->Part(c); } diff --git a/src/commands.cpp b/src/commands.cpp index cfff8c764..03bc368cd 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -93,7 +93,7 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope: } bool fantasy = ci != NULL; - if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && (bi == ChanServ || bi == BotServ)) +/* if (params.size() > 0 && !c->HasFlag(CFLAG_STRIP_CHANNEL) && (bi == ChanServ || bi == BotServ)) { if (ircdproto->IsChannelValid(params[0])) { @@ -121,15 +121,15 @@ void mod_run_cmd(BotInfo *bi, User *u, ChannelInfo *ci, Command *c, const Anope: PopLanguage(); return; } - } + }*/ /* A user not giving a channel name for a param that should be a channel */ - else +/* else { u->SendMessage(bi, _(CHAN_X_INVALID), params[0].c_str()); PopLanguage(); return; } - } + }*/ CommandSource source; source.u = u; diff --git a/src/config.cpp b/src/config.cpp index f75913fc9..293f3947f 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -20,16 +20,6 @@ ServerConfig *Config = NULL; static Anope::string Modules; static Anope::string EncModules; static Anope::string DBModules; -static Anope::string HostCoreModules; -static Anope::string MemoCoreModules; -static Anope::string BotCoreModules; -static Anope::string OperCoreModules; -static Anope::string NickCoreModules; -static Anope::string ChanCoreModules; -static Anope::string DefCon1; -static Anope::string DefCon2; -static Anope::string DefCon3; -static Anope::string DefCon4; static Anope::string UlineServers; static Anope::string OSNotifications; static Anope::string BSDefaults; @@ -212,12 +202,6 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->ModulesAutoLoad = BuildStringList(Modules); this->EncModuleList = BuildStringList(EncModules); this->DBModuleList = BuildStringList(DBModules); - this->HostServCoreModules = BuildStringList(HostCoreModules); - this->MemoServCoreModules = BuildStringList(MemoCoreModules); - this->BotServCoreModules = BuildStringList(BotCoreModules); - this->OperServCoreModules = BuildStringList(OperCoreModules); - this->ChanServCoreModules = BuildStringList(ChanCoreModules); - this->NickServCoreModules = BuildStringList(NickCoreModules); if (this->LimitSessions) { @@ -237,93 +221,7 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C if (this->UserKey1 == this->UserKey2 || this->UserKey1 == this->UserKey3 || this->UserKey3 == this->UserKey2) Log() << "Every UserKey must be different. It's for YOUR safety! Remember that!"; - /** - * Check all DEFCON dependiencies... - **/ - if (this->DefConLevel) - { - /* Build DefCon's */ - DefCon.resize(6); - DefCon[5].reset(); - for (unsigned int level = 1; level < 5; ++level) - { - DefCon[level] = 0; - Anope::string *levelDefinition = NULL; - switch (level) - { - case 1: - levelDefinition = &DefCon1; - break; - case 2: - levelDefinition = &DefCon2; - break; - case 3: - levelDefinition = &DefCon3; - break; - case 4: - levelDefinition = &DefCon4; - } - spacesepstream operations(*levelDefinition); - Anope::string operation; - while (operations.GetToken(operation)) - { - if (operation.equals_ci("nonewchannels")) - AddDefCon(level, DEFCON_NO_NEW_CHANNELS); - else if (operation.equals_ci("nonewnicks")) - AddDefCon(level, DEFCON_NO_NEW_NICKS); - else if (operation.equals_ci("nomlockchanges")) - AddDefCon(level, DEFCON_NO_MLOCK_CHANGE); - else if (operation.equals_ci("forcechanmodes")) - AddDefCon(level, DEFCON_FORCE_CHAN_MODES); - else if (operation.equals_ci("reducedsessions")) - AddDefCon(level, DEFCON_REDUCE_SESSION); - else if (operation.equals_ci("nonewclients")) - AddDefCon(level, DEFCON_NO_NEW_CLIENTS); - else if (operation.equals_ci("operonly")) - AddDefCon(level, DEFCON_OPER_ONLY); - else if (operation.equals_ci("silentoperonly")) - AddDefCon(level, DEFCON_SILENT_OPER_ONLY); - else if (operation.equals_ci("akillnewclients")) - AddDefCon(level, DEFCON_AKILL_NEW_CLIENTS); - else if (operation.equals_ci("nonewmemos")) - AddDefCon(level, DEFCON_NO_NEW_MEMOS); - } - } - - /* Check any defcon needed settings */ - for (int defconCount = 1; defconCount <= 5; ++defconCount) - { - if (CheckDefCon(defconCount, DEFCON_REDUCE_SESSION)) - { - if (!this->DefConSessionLimit) - { - throw ConfigException("this->DefConSessionLimit missing"); - } - } - if (CheckDefCon(defconCount, DEFCON_AKILL_NEW_CLIENTS)) - { - if (!this->DefConAKILL) - { - throw ConfigException("this->DefConAKILL missing"); - } - if (this->DefConAkillReason.empty()) - { - throw ConfigException("this->DefConAkillReason missing"); - } - } - if (CheckDefCon(defconCount, DEFCON_FORCE_CHAN_MODES)) - { - if (this->DefConChanModes.empty()) - { - throw ConfigException("this->DefConChanModes missing"); - } - } - } - } - SetDefaultMLock(this); - if (ircd) - InitLogChannels(this); if (IsFile(this->NameServer)) { @@ -614,7 +512,7 @@ bool ValidateOperServ(ServerConfig *config, const Anope::string &tag, const Anop bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) { - if (!config->s_GlobalNoticer.empty()) + if (!config->s_Global.empty()) { if (value.equals_ci("description") && data.GetValue().empty()) throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when Global is enabled!"); @@ -622,37 +520,6 @@ bool ValidateGlobal(ServerConfig *config, const Anope::string &tag, const Anope: return true; } -bool ValidateDefCon(ServerConfig *config, const Anope::string &tag, const Anope::string &value, ValueItem &data) -{ - if (value.equals_ci("defaultlevel")) - { - int level = data.GetInteger(); - if (!level) - return true; - if (level > 5) - throw ConfigException("The value for <defcon:defaultlevel> must be between 1 through 5 if you wish to use DefCon or 0 if you wish to disable it!"); - } - else if (config->DefConLevel) - { - if ((value.substr(0, 5).equals_ci("level") && isdigit(value[5])) || value.equals_ci("chanmodes") || value.equals_ci("akillreason")) - { - if (data.GetValue().empty()) - throw ConfigException("The value for <" + tag + ":" + value + "> cannot be empty when DefCon is enabled!"); - } - else if (value.equals_ci("message") && config->GlobalOnDefconMore) - { - if (data.GetValue().empty()) - throw ConfigException("The value for <defcon:message> cannot be empty when globalondefconmore is enabled!"); - } - else if (value.equals_ci("sessionlimit") || value.equals_ci("akillexpire")) - { - if (!data.GetInteger() && dotime(data.GetValue()) <= 0) - throw ConfigException("The value for <" + tag + ":" + value + "> must be non-zero when DefCon is enabled!"); - } - } - return true; -} - bool ValidateNickLen(ServerConfig *, const Anope::string &, const Anope::string &, ValueItem &data) { int nicklen = data.GetInteger(); @@ -927,10 +794,8 @@ bool InitLogs(ServerConfig *config, const Anope::string &) UserContainer *uc = *cit; BotInfo *bi = findbot(uc->user->nick); - if (bi && bi->HasFlag(BI_CORE)) - { + if (bi) bi->Part(c, "Reloading configuration"); - } } c->UnsetFlag(CH_PERSIST); @@ -989,6 +854,35 @@ bool DoneLogs(ServerConfig *config, const Anope::string &) { Log() << "Loaded " << config->LogInfos.size() << " log blocks"; + for (unsigned i = 0; i < config->LogInfos.size(); ++i) + { + LogInfo *l = config->LogInfos[i]; + + if ((!ircd || !ircd->join2msg) && !l->Inhabit) + continue; + + for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) + { + const Anope::string &target = *sit; + + if (target[0] == '#') + { + Channel *c = findchan(target); + if (!c) + c = new Channel(target); + c->SetFlag(CH_LOGCHAN); + c->SetFlag(CH_PERSIST); + + for (Anope::insensitive_map<BotInfo *>::const_iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) + { + BotInfo *bi = it->second; + if (!c->FindUser(bi)) + bi->Join(c, &config->BotModeList); + } + } + } + } + return true; } @@ -1144,10 +1038,6 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"options", "useprivmsg", "no", new ValueContainerBool(&conf->UsePrivmsg), DT_BOOLEAN, NoValidation}, {"options", "usestrictprivmsg", "no", new ValueContainerBool(&conf->UseStrictPrivMsg), DT_BOOLEAN, NoValidation}, {"options", "hidestatso", "no", new ValueContainerBool(&conf->HideStatsO), DT_BOOLEAN, NoValidation}, - {"options", "globaloncycle", "no", new ValueContainerBool(&conf->GlobalOnCycle), DT_BOOLEAN, NoValidation}, - {"options", "globaloncycledown", "", new ValueContainerString(&conf->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, - {"options", "globaloncycleup", "", new ValueContainerString(&conf->GlobalOnCycleUP), DT_STRING, ValidateGlobalOnCycle}, - {"options", "anonymousglobal", "no", new ValueContainerBool(&conf->AnonymousGlobal), DT_BOOLEAN, NoValidation}, {"options", "nickregdelay", "0", new ValueContainerUInt(&conf->NickRegDelay), DT_UINTEGER, NoValidation}, {"options", "restrictopernicks", "no", new ValueContainerBool(&conf->RestrictOperNicks), DT_BOOLEAN, NoValidation}, {"options", "newscount", "3", new ValueContainerUInt(&conf->NewsCount), DT_UINTEGER, NoValidation}, @@ -1161,7 +1051,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"nickserv", "nick", "NickServ", new ValueContainerString(&conf->s_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"nickserv", "description", "Nickname Registration Service", new ValueContainerString(&conf->desc_NickServ), DT_STRING | DT_NORELOAD, ValidateNotEmpty}, {"nickserv", "emailregistration", "no", new ValueContainerBool(&conf->NSEmailReg), DT_BOOLEAN, NoValidation}, - {"nickserv", "modules", "", new ValueContainerString(&NickCoreModules), DT_STRING, NoValidation}, + {"nickserv", "modules", "", new ValueContainerString(&conf->NickCoreModules), DT_STRING, NoValidation}, {"nickserv", "forceemail", "no", new ValueContainerBool(&conf->NSForceEmail), DT_BOOLEAN, ValidateEmailReg}, {"nickserv", "confirmemailchanges", "no", new ValueContainerBool(&conf->NSConfirmEmailChanges), DT_BOOLEAN, NoValidation}, {"nickserv", "defaults", "secure memosignon memoreceive", new ValueContainerString(&NSDefaults), DT_STRING, NoValidation}, @@ -1197,7 +1087,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"dns", "timeout", "5", new ValueContainerTime(&conf->DNSTimeout), DT_TIME, NoValidation}, {"chanserv", "nick", "", new ValueContainerString(&conf->s_ChanServ), DT_STRING | DT_NORELOAD, NoValidation}, {"chanserv", "description", "Channel Registration Service", new ValueContainerString(&conf->desc_ChanServ), DT_STRING | DT_NORELOAD, ValidateChanServ}, - {"chanserv", "modules", "", new ValueContainerString(&ChanCoreModules), DT_STRING, ValidateChanServ}, + {"chanserv", "modules", "", new ValueContainerString(&conf->ChanCoreModules), DT_STRING, ValidateChanServ}, {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, ValidateChanServ}, {"chanserv", "maxregistered", "0", new ValueContainerUInt(&conf->CSMaxReg), DT_UINTEGER, ValidateChanServ}, {"chanserv", "expire", "14d", new ValueContainerTime(&conf->CSExpire), DT_TIME, ValidateChanServ}, @@ -1213,14 +1103,14 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"chanserv", "opersonly", "no", new ValueContainerBool(&conf->CSOpersOnly), DT_BOOLEAN, ValidateChanServ}, {"memoserv", "nick", "", new ValueContainerString(&conf->s_MemoServ), DT_STRING | DT_NORELOAD, NoValidation}, {"memoserv", "description", "Memo Service", new ValueContainerString(&conf->desc_MemoServ), DT_STRING | DT_NORELOAD, ValidateMemoServ}, - {"memoserv", "modules", "", new ValueContainerString(&MemoCoreModules), DT_STRING, NoValidation}, + {"memoserv", "modules", "", new ValueContainerString(&Config->MemoCoreModules), DT_STRING, NoValidation}, {"memoserv", "maxmemos", "0", new ValueContainerUInt(&conf->MSMaxMemos), DT_UINTEGER, NoValidation}, {"memoserv", "senddelay", "0", new ValueContainerTime(&conf->MSSendDelay), DT_TIME, NoValidation}, {"memoserv", "notifyall", "no", new ValueContainerBool(&conf->MSNotifyAll), DT_BOOLEAN, NoValidation}, {"memoserv", "memoreceipt", "0", new ValueContainerUInt(&conf->MSMemoReceipt), DT_UINTEGER, NoValidation}, {"botserv", "nick", "", new ValueContainerString(&conf->s_BotServ), DT_STRING | DT_NORELOAD, NoValidation}, {"botserv", "description", "Bot Service", new ValueContainerString(&conf->desc_BotServ), DT_STRING | DT_NORELOAD, ValidateBotServ}, - {"botserv", "modules", "", new ValueContainerString(&BotCoreModules), DT_STRING, NoValidation}, + {"botserv", "modules", "", new ValueContainerString(&conf->BotCoreModules), DT_STRING, NoValidation}, {"botserv", "defaults", "", new ValueContainerString(&BSDefaults), DT_STRING, NoValidation}, {"botserv", "minusers", "0", new ValueContainerUInt(&conf->BSMinUsers), DT_UINTEGER, ValidateBotServ}, {"botserv", "badwordsmax", "0", new ValueContainerUInt(&conf->BSBadWordsMax), DT_UINTEGER, ValidateBotServ}, @@ -1231,10 +1121,10 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"botserv", "fantasycharacter", "!", new ValueContainerString(&conf->BSFantasyCharacter), DT_STRING, NoValidation}, {"hostserv", "nick", "", new ValueContainerString(&conf->s_HostServ), DT_STRING | DT_NORELOAD, NoValidation}, {"hostserv", "description", "vHost Service", new ValueContainerString(&conf->desc_HostServ), DT_STRING | DT_NORELOAD, ValidateHostServ}, - {"hostserv", "modules", "", new ValueContainerString(&HostCoreModules), DT_STRING, NoValidation}, + {"hostserv", "modules", "", new ValueContainerString(&conf->HostCoreModules), DT_STRING, NoValidation}, {"operserv", "nick", "", new ValueContainerString(&conf->s_OperServ), DT_STRING | DT_NORELOAD, NoValidation}, {"operserv", "description", "Operator Service", new ValueContainerString(&conf->desc_OperServ), DT_STRING | DT_NORELOAD, ValidateOperServ}, - {"operserv", "modules", "", new ValueContainerString(&OperCoreModules), DT_STRING, NoValidation}, + {"operserv", "modules", "", new ValueContainerString(&conf->OperCoreModules), DT_STRING, NoValidation}, {"operserv", "superadmin", "no", new ValueContainerBool(&conf->SuperAdmin), DT_BOOLEAN, NoValidation}, {"operserv", "autokillexpiry", "0", new ValueContainerTime(&conf->AutokillExpiry), DT_TIME, ValidateOperServ}, {"operserv", "chankillexpiry", "0", new ValueContainerTime(&conf->ChankillExpiry), DT_TIME, ValidateOperServ}, @@ -1255,22 +1145,13 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"operserv", "sessionautokillexpiry", "0", new ValueContainerTime(&conf->SessionAutoKillExpiry), DT_TIME, NoValidation}, {"operserv", "addakiller", "no", new ValueContainerBool(&conf->AddAkiller), DT_BOOLEAN, NoValidation}, {"operserv", "opersonly", "no", new ValueContainerBool(&conf->OSOpersOnly), DT_BOOLEAN, NoValidation}, - {"global", "nick", "", new ValueContainerString(&conf->s_GlobalNoticer), DT_STRING | DT_NORELOAD, NoValidation}, - {"global", "description", "Global Noticer", new ValueContainerString(&conf->desc_GlobalNoticer), DT_STRING | DT_NORELOAD, ValidateGlobal}, - {"defcon", "defaultlevel", "0", new ValueContainerInt(&conf->DefConLevel), DT_INTEGER, ValidateDefCon}, - {"defcon", "level4", "", new ValueContainerString(&DefCon4), DT_STRING, ValidateDefCon}, - {"defcon", "level3", "", new ValueContainerString(&DefCon3), DT_STRING, ValidateDefCon}, - {"defcon", "level2", "", new ValueContainerString(&DefCon2), DT_STRING, ValidateDefCon}, - {"defcon", "level1", "", new ValueContainerString(&DefCon1), DT_STRING, ValidateDefCon}, - {"defcon", "sessionlimit", "0", new ValueContainerUInt(&conf->DefConSessionLimit), DT_UINTEGER, ValidateDefCon}, - {"defcon", "akillexpire", "0", new ValueContainerTime(&conf->DefConAKILL), DT_TIME, ValidateDefCon}, - {"defcon", "chanmodes", "", new ValueContainerString(&conf->DefConChanModes), DT_STRING, ValidateDefCon}, - {"defcon", "timeout", "0", new ValueContainerTime(&conf->DefConTimeOut), DT_TIME, NoValidation}, - {"defcon", "globalondefcon", "no", new ValueContainerBool(&conf->GlobalOnDefcon), DT_BOOLEAN, NoValidation}, - {"defcon", "globalondefconmore", "no", new ValueContainerBool(&conf->GlobalOnDefconMore), DT_BOOLEAN, NoValidation}, - {"defcon", "message", "", new ValueContainerString(&conf->DefconMessage), DT_STRING, ValidateDefCon}, - {"defcon", "offmessage", "", new ValueContainerString(&conf->DefConOffMessage), DT_STRING, NoValidation}, - {"defcon", "akillreason", "", new ValueContainerString(&conf->DefConAkillReason), DT_STRING, ValidateDefCon}, + {"global", "nick", "", new ValueContainerString(&conf->s_Global), DT_STRING | DT_NORELOAD, NoValidation}, + {"global", "description", "Global Noticer", new ValueContainerString(&conf->desc_Global), DT_STRING | DT_NORELOAD, ValidateGlobal}, + {"global", "modules", "", new ValueContainerString(&conf->GlobalCoreModules), DT_STRING, NoValidation}, + {"global", "globaloncycle", "no", new ValueContainerBool(&conf->GlobalOnCycle), DT_BOOLEAN, NoValidation}, + {"global", "globaloncycledown", "", new ValueContainerString(&conf->GlobalOnCycleMessage), DT_STRING, ValidateGlobalOnCycle}, + {"global", "globaloncycleup", "", new ValueContainerString(&conf->GlobalOnCycleUP), DT_STRING, ValidateGlobalOnCycle}, + {"global", "anonymousglobal", "no", new ValueContainerBool(&conf->AnonymousGlobal), DT_BOOLEAN, NoValidation}, {"", "", "", NULL, DT_NOTHING, NoValidation} }; diff --git a/src/hostserv.cpp b/src/hostserv.cpp index bfd68f17f..d3000d552 100644 --- a/src/hostserv.cpp +++ b/src/hostserv.cpp @@ -12,59 +12,6 @@ #include "services.h" #include "modules.h" -E void moduleAddHostServCmds(); - -/*************************************************************************/ - -void moduleAddHostServCmds() -{ - ModuleManager::LoadModuleList(Config->HostServCoreModules); -} - -/*************************************************************************/ - -/** - * Return information on memory use. - * Assumes pointers are valid. - **/ - -void get_hostserv_stats(long *nrec, long *memuse) -{ - long count = 0, mem = 0; - - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) - { - NickAlias *na = it->second; - - if (!na->hostinfo.HasVhost()) - continue; - - if (!na->hostinfo.GetIdent().empty()) - mem += na->hostinfo.GetIdent().length(); - if (!na->hostinfo.GetHost().empty()) - mem += na->hostinfo.GetHost().length(); - if (!na->hostinfo.GetCreator().empty()) - mem += na->hostinfo.GetCreator().length(); - ++count; - } - - *nrec = count; - *memuse = mem; -} - -/*************************************************************************/ - -/** - * HostServ initialization. - * @return void - */ -void hostserv_init() -{ - if (!Config->s_HostServ.empty()) - moduleAddHostServCmds(); -} - -/*************************************************************************/ /** Set a vhost for the user * @param ident The ident @@ -130,47 +77,3 @@ const time_t HostInfo::GetTime() const return Time; } -/*************************************************************************/ -/* Start of Generic Functions */ -/*************************************************************************/ - -/** Sync all vhosts in a group to the same thing - * @param na The nick with the vhost wanting to by synced - */ -void HostServSyncVhosts(NickAlias *na) -{ - if (!na || !na->hostinfo.HasVhost()) - return; - - for (std::list<NickAlias *>::iterator it = na->nc->aliases.begin(), it_end = na->nc->aliases.end(); it != it_end; ++it) - { - NickAlias *nick = *it; - nick->hostinfo.SetVhost(na->hostinfo.GetIdent(), na->hostinfo.GetHost(), na->hostinfo.GetCreator()); - } -} - -/*************************************************************************/ - -void do_on_id(User *u) -{ - if (!u) - return; - NickAlias *na = findnick(u->nick); - if (!na || !na->hostinfo.HasVhost()) - return; - - if (u->vhost.empty() || !u->vhost.equals_cs(na->hostinfo.GetHost()) || (!na->hostinfo.GetIdent().empty() && !u->GetVIdent().equals_cs(na->hostinfo.GetIdent()))) - { - ircdproto->SendVhost(u, na->hostinfo.GetIdent(), na->hostinfo.GetHost()); - if (ircd->vhost) - u->vhost = na->hostinfo.GetHost(); - if (ircd->vident && !na->hostinfo.GetIdent().empty()) - u->SetVIdent(na->hostinfo.GetIdent()); - u->UpdateHost(); - - if (!na->hostinfo.GetIdent().empty()) - u->SendMessage(HostServ, _("Your vhost of \002%s\002@\002%s\002 is now activated."), na->hostinfo.GetIdent().c_str(), na->hostinfo.GetHost().c_str()); - else - u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."), na->hostinfo.GetHost().c_str()); - } -} diff --git a/src/init.cpp b/src/init.cpp index 31d525c7b..f79de5a34 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -342,33 +342,6 @@ void Init(int ac, char **av) /* Create me */ Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric); - /* First thing, add our core bots internally. Before modules are loaded and before the database is read - * This is used for modules adding commands and for the BotInfo* poiners in the command classes. - * When these bots are loaded from the databases the proper user/host/rname are added. - * - * If a user renames a bot in the configuration file, the new bot gets created here, and the old bot - * that is in the database gets created aswell, on its old nick. The old nick remains in all the channels - * etc and the new bot becomes the new client to accept commands. The user can use /bs bot del later - * if they want the old bot deleted. - * - * Note that it is important this is after loading the protocol module. The ircd struct must exist for - * the ts6_ functions - */ - if (!Config->s_OperServ.empty()) - new BotInfo(Config->s_OperServ, Config->ServiceUser, Config->ServiceHost, Config->desc_OperServ); - if (!Config->s_NickServ.empty()) - new BotInfo(Config->s_NickServ, Config->ServiceUser, Config->ServiceHost, Config->desc_NickServ); - if (!Config->s_ChanServ.empty()) - new BotInfo(Config->s_ChanServ, Config->ServiceUser, Config->ServiceHost, Config->desc_ChanServ); - if (!Config->s_HostServ.empty()) - new BotInfo(Config->s_HostServ, Config->ServiceUser, Config->ServiceHost, Config->desc_HostServ); - if (!Config->s_MemoServ.empty()) - new BotInfo(Config->s_MemoServ, Config->ServiceUser, Config->ServiceHost, Config->desc_MemoServ); - if (!Config->s_BotServ.empty()) - new BotInfo(Config->s_BotServ, Config->ServiceUser, Config->ServiceHost, Config->desc_BotServ); - if (!Config->s_GlobalNoticer.empty()) - new BotInfo(Config->s_GlobalNoticer, Config->ServiceUser, Config->ServiceHost, Config->desc_GlobalNoticer); - /* Add Encryption Modules */ ModuleManager::LoadModuleList(Config->EncModuleList); @@ -379,14 +352,7 @@ void Init(int ac, char **av) /* Add Database Modules */ ModuleManager::LoadModuleList(Config->DBModuleList); - try - { - DNSEngine = new DNSManager(); - } - catch (const SocketException &ex) - { - throw FatalException(ex.GetReason()); - } + DNSEngine = new DNSManager(); #ifndef _WIN32 if (!nofork) @@ -440,14 +406,6 @@ void Init(int ac, char **av) Log(LOG_DEBUG) << "Loading Languages..."; InitLanguages(); - /* Initialize subservices */ - ns_init(); - cs_init(); - ms_init(); - bs_init(); - os_init(); - hostserv_init(); - /* load any custom modules */ if (!nothird) ModuleManager::LoadModuleList(Config->ModulesAutoLoad); @@ -456,9 +414,6 @@ void Init(int ac, char **av) rand_init(); add_entropy_userkeys(); - /* Init log channels */ - InitLogChannels(Config); - /* Load up databases */ Log() << "Loading databases..."; EventReturn MOD_RESULT; diff --git a/src/logger.cpp b/src/logger.cpp index 51a8ce69c..4ccfa813f 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -10,39 +10,10 @@ */ #include "services.h" - -void InitLogChannels(ServerConfig *config) -{ - for (unsigned i = 0; i < config->LogInfos.size(); ++i) - { - LogInfo *l = config->LogInfos[i]; - - if (!ircd->join2msg && !l->Inhabit) - continue; - - for (std::list<Anope::string>::const_iterator sit = l->Targets.begin(), sit_end = l->Targets.end(); sit != sit_end; ++sit) - { - const Anope::string &target = *sit; - - if (target[0] == '#') - { - Channel *c = findchan(target); - if (!c) - c = new Channel(target); - c->SetFlag(CH_LOGCHAN); - c->SetFlag(CH_PERSIST); - - for (Anope::insensitive_map<BotInfo *>::iterator it = BotListByNick.begin(), it_end = BotListByNick.end(); it != it_end; ++it) - { - BotInfo *bi = it->second; - - if (bi->HasFlag(BI_CORE) && !c->FindUser(bi)) - bi->Join(c, &config->BotModeList); - } - } - } - } -} +#include "modules.h" +#include "chanserv.h" +#include "operserv.h" +#include "global.h" static Anope::string GetTimeStamp() { @@ -96,10 +67,10 @@ Anope::string LogFile::GetName() const Log::Log(LogType type, const Anope::string &category, BotInfo *b) : bi(b), Type(type), Category(category) { - if (!b) - b = Global; - if (b) - this->Sources.push_back(b->nick); + if (!bi && global) + bi = global->Bot(); + if (bi) + this->Sources.push_back(bi->nick); } Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) @@ -110,7 +81,7 @@ Log::Log(LogType type, User *u, Command *c, ChannelInfo *ci) : Type(type) if (type != LOG_COMMAND && type != LOG_OVERRIDE && type != LOG_ADMIN) throw CoreException("This constructor does not support this log type"); - this->bi = c->service ? c->service : Global; + this->bi = c->service ? c->service : (global ? global->Bot() : NULL); this->Category = (c->service ? c->service->nick + "/" : "") + c->name; if (this->bi) this->Sources.push_back(this->bi->nick); @@ -135,7 +106,7 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) if (!c) throw CoreException("Invalid pointers passed to Log::Log"); - this->bi = ChanServ; + this->bi = chanserv ? chanserv->Bot() : NULL; this->Category = category; if (this->bi) this->Sources.push_back(this->bi->nick); @@ -150,11 +121,13 @@ Log::Log(User *u, Channel *c, const Anope::string &category) : Type(LOG_CHANNEL) buf << this->Category << " " << c->name << " "; } -Log::Log(User *u, const Anope::string &category) : bi(Global), Type(LOG_USER), Category(category) +Log::Log(User *u, const Anope::string &category) : bi(NULL), Type(LOG_USER), Category(category) { if (!u) throw CoreException("Invalid pointers passed to Log::Log"); + if (!this->bi && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(u->nick); @@ -162,13 +135,15 @@ Log::Log(User *u, const Anope::string &category) : bi(Global), Type(LOG_USER), C buf << "USERS: " << u->GetMask() << " "; } -Log::Log(Server *s, const Anope::string &category) : bi(OperServ), Type(LOG_SERVER), Category(category) +Log::Log(Server *s, const Anope::string &category) : bi(NULL), Type(LOG_SERVER), Category(category) { if (!s) throw CoreException("Invalid pointer passed to Log::Log"); - if (!this->bi) - this->bi = Global; + if (operserv) + this->bi = operserv->Bot(); + if (!this->bi && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(this->bi->nick); this->Sources.push_back(s->GetName()); @@ -178,8 +153,8 @@ Log::Log(Server *s, const Anope::string &category) : bi(OperServ), Type(LOG_SERV Log::Log(BotInfo *b, const Anope::string &category) : bi(b), Type(LOG_NORMAL), Category(category) { - if (!b) - this->bi = Global; + if (!b && global) + this->bi = global->Bot(); if (this->bi) this->Sources.push_back(bi->nick); } diff --git a/src/main.cpp b/src/main.cpp index b71a7754a..fd3ab52d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -79,22 +79,10 @@ static bool started = false; /*************************************************************************/ -class ExpireTimer : public Timer -{ - public: - ExpireTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } - - void Tick(time_t) - { - if (!readonly && !noexpire) - expire_all(); - } -}; - class UpdateTimer : public Timer { public: - UpdateTimer(time_t timeout, time_t now) : Timer(timeout, now, true) { } + UpdateTimer(time_t timeout) : Timer(timeout, Anope::CurTime, true) { } void Tick(time_t) { @@ -123,26 +111,6 @@ bool UplinkSocket::Read(const Anope::string &buf) /*************************************************************************/ -/* Run expiration routines */ - -extern void expire_all() -{ - if (noexpire || readonly) - // Definitely *do not* want. - return; - - FOREACH_MOD(I_OnPreDatabaseExpire, OnPreDatabaseExpire()); - - Log(LOG_DEBUG) << "Running expire routines"; - expire_nicks(); - expire_chans(); - expire_exceptions(); - - FOREACH_MOD(I_OnDatabaseExpire, OnDatabaseExpire()); -} - -/*************************************************************************/ - void save_databases() { if (readonly) @@ -160,7 +128,6 @@ void do_restart_services() { if (!readonly) { - expire_all(); save_databases(); } Log() << "Restarting"; @@ -261,23 +228,25 @@ void sighandler(int signum) { #ifndef _WIN32 case SIGHUP: + { Log() << "Received SIGHUP: Saving databases & rehashing configuration"; - expire_all(); save_databases(); + ServerConfig *old_config = Config; try { - ServerConfig *newconfig = new ServerConfig(); - delete Config; - Config = newconfig; - FOREACH_MOD(I_OnReload, OnReload(true)); + Config = new ServerConfig(); + FOREACH_MOD(I_OnReload, OnReload()); + delete old_config; } catch (const ConfigException &ex) { + Config = old_config; Log() << "Error reloading configuration file: " << ex.GetReason(); } break; + } #endif case SIGINT: case SIGTERM: @@ -292,11 +261,8 @@ void sighandler(int signum) Log() << "Received signal " << signum << ", exiting."; #endif - if (Config->GlobalOnCycle) - oper_global("", "%s", Config->GlobalOnCycleMessage.c_str()); - - expire_all(); save_databases(); + services_shutdown(); default: fatal = true; break; @@ -455,8 +421,7 @@ int main(int ac, char **av, char **envp) /* Set up timers */ time_t last_check = Anope::CurTime; - ExpireTimer expireTimer(Config->ExpireTimeout, Anope::CurTime); - UpdateTimer updateTimer(Config->UpdateTimeout, Anope::CurTime); + UpdateTimer updateTimer(Config->UpdateTimeout); /*** Main loop. ***/ while (!quitting) @@ -467,8 +432,6 @@ int main(int ac, char **av, char **envp) if (!readonly && (save_data || shutting_down)) { - if (!noexpire) - expire_all(); if (shutting_down) ircdproto->SendGlobops(NULL, "Updating databases on shutdown, please wait."); save_databases(); diff --git a/src/memoserv.cpp b/src/memoserv.cpp index f10a11d5f..21940aca1 100644 --- a/src/memoserv.cpp +++ b/src/memoserv.cpp @@ -12,281 +12,8 @@ #include "services.h" #include "modules.h" -static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m); - Memo::Memo() : Flags<MemoFlag>(MemoFlagStrings) { } -/** - * MemoServ initialization. - * @return void - */ -void ms_init() -{ - if (!Config->s_MemoServ.empty()) - ModuleManager::LoadModuleList(Config->MemoServCoreModules); -} - -/*************************************************************************/ -/** - * check_memos: See if the given user has any unread memos, and send a - * NOTICE to that user if so (and if the appropriate flag is - * set). - * @param u User Struct - * @return void - */ -void check_memos(User *u) -{ - if (Config->s_MemoServ.empty()) - return; - - if (!u) - { - Log() << "check_memos called with NULL values"; - return; - } - - const NickCore *nc = u->Account(); - if (!nc || !u->IsRecognized() || !nc->HasFlag(NI_MEMO_SIGNON)) - return; - - unsigned i = 0, end = nc->memos.memos.size(), newcnt = 0; - for (; i < end; ++i) - { - if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) - ++newcnt; - } - if (newcnt > 0) - { - u->SendMessage(MemoServ, newcnt == 1 ? _("You have 1 new memo.") : _("You have %d new memos."), newcnt); - if (newcnt == 1 && (nc->memos.memos[i - 1]->HasFlag(MF_UNREAD))) - u->SendMessage(MemoServ, _("Type \002%s%s READ LAST\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - else if (newcnt == 1) - { - for (i = 0; i < end; ++i) - { - if (nc->memos.memos[i]->HasFlag(MF_UNREAD)) - break; - } - u->SendMessage(MemoServ, _("Type \002%s%s READ %d\002 to read it."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), i); - } - else - u->SendMessage(MemoServ, _("Type \002%s%s LIST NEW\002 to list them."), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str()); - } - if (nc->memos.memomax > 0 && nc->memos.memos.size() >= nc->memos.memomax) - { - if (nc->memos.memos.size() > nc->memos.memomax) - u->SendMessage(MemoServ, _("Warning: You are over your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); - else - u->SendMessage(MemoServ, _("Warning: You have reached your maximum number of memos (%d). You will be unable to receive any new memos until you delete some of your current ones."), nc->memos.memomax); - } -} - -/*************************************************************************/ -/*********************** MemoServ private routines ***********************/ -/*************************************************************************/ - -/** - * Return the MemoInfo corresponding to the given nick or channel name. - * @param name Name to check - * @param ischan - the result its a channel will be stored in here - * @param isforbid - the result if its forbidden will be stored in here - * @return `ischan' 1 if the name was a channel name, else 0. - * @return `isforbid' 1 if the name is forbidden, else 0. - */ -MemoInfo *getmemoinfo(const Anope::string &name, bool &ischan, bool &isforbid) -{ - if (name[0] == '#') - { - ischan = true; - ChannelInfo *ci = cs_findchan(name); - if (ci) - { - if (!ci->HasFlag(CI_FORBIDDEN)) - { - isforbid = false; - return &ci->memos; - } - else - { - isforbid = true; - return NULL; - } - } - else - { - isforbid = false; - return NULL; - } - } - else - { - ischan = false; - NickAlias *na = findnick(name); - if (na) - { - if (!na->HasFlag(NS_FORBIDDEN)) - { - isforbid = false; - return &na->nc->memos; - } - else - { - isforbid = true; - return NULL; - } - } - else - { - isforbid = false; - return NULL; - } - } -} - -/*************************************************************************/ - -/** - * Split from do_send, this way we can easily send a memo from any point - * @param source Where replies should go - * @param name Target of the memo - * @param text Memo Text - * @param z type see info - * 0 - reply to user - * 1 - silent - * 2 - silent with no delay timer - * 3 - reply to user and request read receipt - * @return void - */ -void memo_send(CommandSource &source, const Anope::string &name, const Anope::string &text, int z) -{ - if (Config->s_MemoServ.empty()) - return; - - User *u = source.u; - - bool ischan, isforbid; - MemoInfo *mi; - Anope::string sender = u && u->Account() ? u->Account()->display : ""; - bool is_servoper = u != NULL && u->IsServicesOper(); - - if (readonly) - u->SendMessage(MemoServ, _(MEMO_SEND_DISABLED)); - else if (text.empty()) - { - if (!z) - SyntaxError(source, "SEND", _(MEMO_SEND_SYNTAX)); - - if (z == 3) - SyntaxError(source, "RSEND", _("{\037nick\037 | \037channel\037} \037memo-text\037")); // XXX? - } - else if (!u->IsIdentified() && !u->IsRecognized()) - { - if (!z || z == 3) - source.Reply(_(NICK_IDENTIFY_REQUIRED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - } - else if (!(mi = getmemoinfo(name, ischan, isforbid))) - { - if (!z || z == 3) - { - if (isforbid) - source.Reply(ischan ? _(CHAN_X_FORBIDDEN) : _(NICK_X_FORBIDDEN), name.c_str()); - else - source.Reply(ischan ? _(CHAN_X_NOT_REGISTERED) : _(NICK_X_NOT_REGISTERED), name.c_str()); - } - } - else if (z != 2 && Config->MSSendDelay > 0 && u && u->lastmemosend + Config->MSSendDelay > Anope::CurTime) - { - u->lastmemosend = Anope::CurTime; - if (!z) - source.Reply(_("Please wait %d seconds before using the SEND command again."), Config->MSSendDelay); - - if (z == 3) - source.Reply(_("Please wait %d seconds before using the RSEND command again."), Config->MSSendDelay); - } - else if (!mi->memomax && !is_servoper) - { - if (!z || z == 3) - source.Reply(_("%s cannot receive memos."), name.c_str()); - } - else if (mi->memomax > 0 && mi->memos.size() >= mi->memomax && !is_servoper) - { - if (!z || z == 3) - source.Reply(_("%s currently has too many memos and cannot receive more."), name.c_str()); - } - else - { - if (!z || z == 3) - source.Reply(_("Memo sent to \002%s\002."), name.c_str()); - if (!u->IsServicesOper() && mi->HasIgnore(u)) - return; - - u->lastmemosend = Anope::CurTime; - Memo *m = new Memo(); - mi->memos.push_back(m); - m->sender = sender; - m->time = Anope::CurTime; - m->text = text; - m->SetFlag(MF_UNREAD); - /* Set notify sent flag - DrStein */ - if (z == 2) - m->SetFlag(MF_NOTIFYS); - /* Set receipt request flag */ - if (z == 3) - m->SetFlag(MF_RECEIPT); - if (!ischan) - { - NickCore *nc = findnick(name)->nc; - - FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, nc, m)); - - if (Config->MSNotifyAll) - { - if (nc->HasFlag(NI_MEMO_RECEIVE)) - { - for (std::list<NickAlias *>::iterator it = nc->aliases.begin(), it_end = nc->aliases.end(); it != it_end; ++it) - { - NickAlias *na = *it; - User *user = finduser(na->nick); - if (user && user->IsIdentified()) - user->SendMessage(MemoServ, _(MEMO_NEW_MEMO_ARRIVED), sender.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); - } - } - else - { - if ((u = finduser(name)) && u->IsIdentified() && nc->HasFlag(NI_MEMO_RECEIVE)) - u->SendMessage(MemoServ, _(MEMO_NEW_MEMO_ARRIVED), sender.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), mi->memos.size()); - } /* if (flags & MEMO_RECEIVE) */ - } - /* if (MSNotifyAll) */ - /* let's get out the mail if set in the nickcore - certus */ - if (nc->HasFlag(NI_MEMO_MAIL)) - SendMemoMail(nc, mi, m); - } - else - { - Channel *c; - - FOREACH_MOD(I_OnMemoSend, OnMemoSend(u, cs_findchan(name), m)); - - if (Config->MSNotifyAll && (c = findchan(name))) - { - for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it) - { - UserContainer *cu = *it; - - if (check_access(cu->user, c->ci, CA_MEMO)) - { - if (cu->user->Account() && cu->user->Account()->HasFlag(NI_MEMO_RECEIVE)) - cu->user->SendMessage(MemoServ, _(MEMO_NEW_X_MEMO_ARRIVED), c->ci->name.c_str(), Config->UseStrictPrivMsgString.c_str(), Config->s_MemoServ.c_str(), c->ci->name.c_str(), mi->memos.size()); - } - } - } /* MSNotifyAll */ - } /* if (!ischan) */ - } /* if command is valid */ -} - -/*************************************************************************/ - unsigned MemoInfo::GetIndex(Memo *m) const { for (unsigned i = 0; i < this->memos.size(); ++i) @@ -322,64 +49,3 @@ bool MemoInfo::HasIgnore(User *u) return false; } -/*************************************************************************/ - -static bool SendMemoMail(NickCore *nc, MemoInfo *mi, Memo *m) -{ - char message[BUFSIZE]; - - snprintf(message, sizeof(message), GetString(nc, - "Hi %s\n" - " \n" - "You've just received a new memo from %s. This is memo number %d.\n" - " \n" - "Memo text:\n" - " \n" - "%s").c_str(), nc->display.c_str(), m->sender.c_str(), mi->GetIndex(m), m->text.c_str()); - - return Mail(nc, GetString(nc, _("New memo")), message); -} - -/*************************************************************************/ - -/* Send receipt notification to sender. */ - -void rsend_notify(CommandSource &source, Memo *m, const Anope::string &chan) -{ - /* Only send receipt if memos are allowed */ - if (!readonly) - { - /* Get nick alias for sender */ - NickAlias *na = findnick(m->sender); - - if (!na) - return; - - /* Get nick core for sender */ - NickCore *nc = na->nc; - - if (!nc) - return; - - /* Text of the memo varies if the recepient was a - nick or channel */ - char text[256]; - if (!chan.empty()) - snprintf(text, sizeof(text), GetString(na->nc, _("\002[auto-memo]\002 The memo you sent to %s has been viewed.")).c_str(), chan.c_str()); - else - snprintf(text, sizeof(text), "%s", GetString(na->nc, _("\002[auto-memo]\002 The memo you sent has been viewed.")).c_str()); - - /* Send notification */ - memo_send(source, m->sender, text, 2); - - /* Notify recepient of the memo that a notification has - been sent to the sender */ - source.Reply(_("A notification memo has been sent to %s informing him/her you have\n" - "read his/her memo."), nc->display.c_str()); - } - - /* Remove receipt flag from the original memo */ - m->UnsetFlag(MF_RECEIPT); - - return; -} diff --git a/src/misc.cpp b/src/misc.cpp index 113dc059c..90239a886 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -14,9 +14,6 @@ #include "version.h" #include "modules.h" -/* Cheaper than isspace() or isblank() */ -#define issp(c) ((c) == 32) - struct arc4_stream { uint8 i; @@ -800,242 +797,6 @@ Anope::string Anope::printf(const char *fmt, ...) } -/* -* strlcat and strlcpy were ripped from openssh 2.5.1p2 -* They had the following Copyright info: -* -* -* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. The name of the author may not be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef HAVE_STRLCAT -size_t strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz, dlen; - - while (n-- && *d) - ++d; - - dlen = d - dst; - n = siz - dlen; - - if (!n) - return dlen + strlen(s); - - while (*s) - { - if (n != 1) - { - *d++ = *s; - --n; - } - - ++s; - } - - *d = '\0'; - return dlen + (s - src); /* count does not include NUL */ -} -#endif - -#ifndef HAVE_STRLCPY -size_t strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n && --n) - { - do - { - if (!(*d++ = *s++)) - break; - } - while (--n); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (!n) - { - if (siz) - *d = '\0'; /* NUL-terminate dst */ - while (*s++); - } - - return s - src - 1; /* count does not include NUL */ -} -#endif - -#ifdef _WIN32 -Anope::string GetWindowsVersion() -{ - OSVERSIONINFOEX osvi; - SYSTEM_INFO si; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - ZeroMemory(&si, sizeof(SYSTEM_INFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) - return ""; - } - GetSystemInfo(&si); - - Anope::string buf, extra, cputype; - /* Determine CPU type 32 or 64 */ - if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - cputype = " 64-bit"; - else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) - cputype = " 32-bit"; - else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) - cputype = " Itanium 64-bit"; - - switch (osvi.dwPlatformId) - { - /* test for the Windows NT product family. */ - case VER_PLATFORM_WIN32_NT: - /* Windows Vista or Windows Server 2008 */ - if (osvi.dwMajorVersion == 6 && !osvi.dwMinorVersion) - { - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; - else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Edition"; - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - extra = " Home Premium/Basic"; - if (osvi.wProductType & VER_NT_WORKSTATION) - buf = "Microsoft Windows Vista" + cputype + extra; - else - buf = "Microsoft Windows Server 2008" + cputype + extra; - } - /* Windows 2003 or Windows XP Pro 64 */ - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Edition"; - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; -#ifdef VER_SUITE_COMPUTE_SERVER - else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) - extra = " Compute Cluster Edition"; -#endif - else if (osvi.wSuiteMask == VER_SUITE_BLADE) - extra = " Web Edition"; - else - extra = " Standard Edition"; - if (osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) - buf = "Microsoft Windows XP Professional x64 Edition" + extra; - else - buf = "Microsoft Windows Server 2003 Family" + cputype + extra; - } - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - { - if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) - extra = " Embedded"; - else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) - extra = " Home Edition"; - buf = "Microsoft Windows XP" + extra; - } - if (osvi.dwMajorVersion == 5 && !osvi.dwMinorVersion) - { - if (osvi.wSuiteMask & VER_SUITE_DATACENTER) - extra = " Datacenter Server"; - else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Advanced Server"; - else - extra = " Server"; - buf = "Microsoft Windows 2000" + extra; - } - if (osvi.dwMajorVersion <= 4) - { - if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) - extra = " Enterprise Edition"; - buf = "Microsoft Windows NT Server 4.0" + extra; - } - break; - case VER_PLATFORM_WIN32_WINDOWS: - if (osvi.dwMajorVersion == 4 && !osvi.dwMinorVersion) - { - if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') - extra = " OSR2"; - buf = "Microsoft Windows 95" + extra; - } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) - { - if (osvi.szCSDVersion[1] == 'A') - extra = "SE"; - buf = "Microsoft Windows 98" + extra; - } - if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) - buf = "Microsoft Windows Millenium Edition"; - } - return buf; -} - -bool SupportedWindowsVersion() -{ - OSVERSIONINFOEX osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) - return false; - } - - switch (osvi.dwPlatformId) - { - /* test for the Windows NT product family. */ - case VER_PLATFORM_WIN32_NT: - /* win nt4 */ - if (osvi.dwMajorVersion <= 4) - return false; - /* the rest */ - return true; - /* win95 win98 winME */ - case VER_PLATFORM_WIN32_WINDOWS: - return false; - } - return false; -} - -#endif - /*************************************************************************/ /** @@ -1163,3 +924,74 @@ int Anope::VersionMinor() { return VERSION_MINOR; } int Anope::VersionPatch() { return VERSION_PATCH; } int Anope::VersionBuild() { return VERSION_BUILD; } +/** + * Normalize buffer stripping control characters and colors + * @param A string to be parsed for control and color codes + * @return A string stripped of control and color codes + */ +Anope::string normalizeBuffer(const Anope::string &buf) +{ + Anope::string newbuf; + + for (unsigned i = 0, end = buf.length(); i < end; ++i) + { + switch (buf[i]) + { + /* ctrl char */ + case 1: + /* Bold ctrl char */ + case 2: + break; + /* Color ctrl char */ + case 3: + /* If the next character is a digit, its also removed */ + if (isdigit(buf[i + 1])) + { + ++i; + + /* not the best way to remove colors + * which are two digit but no worse then + * how the Unreal does with +S - TSL + */ + if (isdigit(buf[i + 1])) + ++i; + + /* Check for background color code + * and remove it as well + */ + if (buf[i + 1] == ',') + { + ++i; + + if (isdigit(buf[i + 1])) + ++i; + /* not the best way to remove colors + * which are two digit but no worse then + * how the Unreal does with +S - TSL + */ + if (isdigit(buf[i + 1])) + ++i; + } + } + + break; + /* line feed char */ + case 10: + /* carriage returns char */ + case 13: + /* Reverse ctrl char */ + case 22: + /* Italic ctrl char */ + case 29: + /* Underline ctrl char */ + case 31: + break; + /* A valid char gets copied into the new buffer */ + default: + newbuf += buf[i]; + } + } + + return newbuf; +} + diff --git a/src/modes.cpp b/src/modes.cpp index dd147118c..b91cc9b85 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -477,7 +477,7 @@ void ModeManager::StackerAddInternal(BotInfo *bi, Base *Object, Mode *mode, bool if (bi) s->bi = bi; else if (Type == ST_CHANNEL) - s->bi = whosends(debug_cast<Channel *>(Object)->ci); + s->bi = debug_cast<Channel *>(Object)->ci->WhoSends(); else if (Type == ST_USER) s->bi = NULL; } diff --git a/src/nickalias.cpp b/src/nickalias.cpp index 06e5f60dd..019c54615 100644 --- a/src/nickalias.cpp +++ b/src/nickalias.cpp @@ -34,17 +34,6 @@ NickAlias::~NickAlias() { FOREACH_MOD(I_OnDelNick, OnDelNick(this)); - /* Second thing to do: look for a user using the alias - * being deleted, and make appropriate changes */ - User *u = finduser(this->nick); - if (u && u->Account() == this->nc) - { - ircdproto->SendAccountLogout(u, u->Account()); - u->RemoveMode(NickServ, UMODE_REGISTERED); - ircdproto->SendUnregisteredNick(u); - u->Logout(); - } - /* Accept nicks that have no core, because of database load functions */ if (this->nc) { diff --git a/src/nickcore.cpp b/src/nickcore.cpp index 5fdf9c2dd..a33382f06 100644 --- a/src/nickcore.cpp +++ b/src/nickcore.cpp @@ -31,29 +31,9 @@ NickCore::~NickCore() { FOREACH_MOD(I_OnDelCore, OnDelCore(this)); - /* Clean up this nick core from any users online using it - * (ones that /nick but remain unidentified) - */ - for (std::list<User *>::iterator it = this->Users.begin(); it != this->Users.end();) - { - User *user = *it++; - ircdproto->SendAccountLogout(user, user->Account()); - user->RemoveMode(NickServ, UMODE_REGISTERED); - ircdproto->SendUnregisteredNick(user); - user->Logout(); - FOREACH_MOD(I_OnNickLogout, OnNickLogout(user)); - } - this->Users.clear(); - - /* (Hopefully complete) cleanup */ - cs_remove_nick(this); - /* Remove the core from the list */ NickCoreList.erase(this->display); - /* Log .. */ - Log(NickServ, "nick") << "deleting nickname group " << this->display; - /* Clear access before deleting display name, we want to be able to use the display name in the clear access event */ this->ClearAccess(); diff --git a/src/nickserv.cpp b/src/nickserv.cpp index 396c55c53..943b0715b 100644 --- a/src/nickserv.cpp +++ b/src/nickserv.cpp @@ -77,225 +77,6 @@ void NickServRelease::Tick(time_t) */ } -/*************************************************************************/ -/* *INDENT-OFF* */ -void moduleAddNickServCmds() -{ - ModuleManager::LoadModuleList(Config->NickServCoreModules); -} -/* *INDENT-ON* */ -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_aliases_stats(long &count, long &mem) -{ - count = mem = 0; - - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end; ++it) - { - NickAlias *na = it->second; - - ++count; - mem += sizeof(*na); - if (!na->nick.empty()) - mem += na->nick.length() + 1; - if (!na->last_usermask.empty()) - mem += na->last_usermask.length() + 1; - if (!na->last_realname.empty()) - mem += na->last_realname.length() + 1; - if (!na->last_quit.empty()) - mem += na->last_quit.length() + 1; - } -} - -/*************************************************************************/ - -/* Return information on memory use. Assumes pointers are valid. */ - -void get_core_stats(long &count, long &mem) -{ - count = mem = 0; - unsigned j, end; - - for (nickcore_map::const_iterator it = NickCoreList.begin(), it_end = NickCoreList.end(); it != it_end; ++it) - { - NickCore *nc = it->second; - - ++count; - mem += sizeof(*nc); - - if (!nc->display.empty()) - mem += nc->display.length() + 1; - if (!nc->pass.empty()) - mem += nc->pass.length() + 1; - if (!nc->greet.empty()) - mem += nc->greet.length() + 1; - - mem += sizeof(Anope::string) * nc->access.size(); - - for (j = 0, end = nc->access.size(); j < end; ++j) - mem += nc->GetAccess(j).length() + 1; - - mem += nc->memos.memos.size() * sizeof(Memo); - for (j = 0, end = nc->memos.memos.size(); j < end; ++j) - if (!nc->memos.memos[j]->text.empty()) - mem += nc->memos.memos[j]->text.length() + 1; - - mem += sizeof(NickAlias *) * nc->aliases.size(); - } -} - -/*************************************************************************/ -/*************************************************************************/ - -/* NickServ initialization. */ - -void ns_init() -{ - moduleAddNickServCmds(); -} - -/*************************************************************************/ - -/* Check whether a user is on the access list of the nick they're using If - * not, send warnings as appropriate. If so (and not NI_SECURE), update - * last seen info. - * Return 1 if the user is valid and recognized, 0 otherwise (note - * that this means an NI_SECURE nick will return 0 from here). - * If the user's nick is not registered, 0 is returned. - */ - -int validate_user(User *u) -{ - NickAlias *na = findnick(u->nick); - if (!na) - return 0; - - if (na->HasFlag(NS_FORBIDDEN)) - { - u->SendMessage(NickServ, _("This nickname may not be used. Please choose another one.")); - u->Collide(na); - return 0; - } - - if (na->nc->HasFlag(NI_SUSPENDED)) - { - u->SendMessage(NickServ, _(NICK_X_SUSPENDED), u->nick.c_str()); - u->Collide(na); - return 0; - } - - if (!u->IsIdentified() && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint)) - { - u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified")); - u->Identify(na); - return 1; - } - - if (!na->nc->HasFlag(NI_SECURE) && u->IsRecognized()) - { - na->last_seen = Anope::CurTime; - Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost(); - na->last_usermask = last_usermask; - na->last_realname = u->realname; - - check_memos(u); - - return 1; - } - - if (u->IsRecognized() || !na->nc->HasFlag(NI_KILL_IMMED)) - { - if (na->nc->HasFlag(NI_SECURE)) - u->SendMessage(NickServ, _(NICK_IS_SECURE), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - else - u->SendMessage(NickServ, _(NICK_IS_REGISTERED), Config->UseStrictPrivMsgString.c_str(), Config->s_NickServ.c_str()); - } - - if (na->nc->HasFlag(NI_KILLPROTECT) && !u->IsRecognized()) - { - if (na->nc->HasFlag(NI_KILL_IMMED)) - { - u->SendMessage(NickServ, _(FORCENICKCHANGE_NOW)); - u->Collide(na); - } - else if (na->nc->HasFlag(NI_KILL_QUICK)) - { - u->SendMessage(NickServ, _("If you do not change within 20 seconds, I will change your nick.")); - new NickServCollide(u, 20); - } - else - { - u->SendMessage(NickServ, _("If you do not change within one minute, I will change your nick.")); - new NickServCollide(u, 60); - } - } - - return 0; -} - -/*************************************************************************/ - -/* Remove all nicks which have expired. Also update last-seen time for all - * nicks. - */ - -void expire_nicks() -{ - for (nickalias_map::const_iterator it = NickAliasList.begin(), it_end = NickAliasList.end(); it != it_end;) - { - NickAlias *na = it->second; - ++it; - - User *u = finduser(na->nick); - if (u && (na->nc->HasFlag(NI_SECURE) ? u->IsIdentified(true) : u->IsRecognized(true))) - { - Log(LOG_DEBUG_2) << "NickServ: updating last seen time for " << na->nick; - na->last_seen = Anope::CurTime; - } - - bool expire = false; - - if (na->nc->HasFlag(NI_UNCONFIRMED)) - if (Config->NSUnconfirmedExpire && Anope::CurTime - na->time_registered >= Config->NSUnconfirmedExpire) - expire = true; - - if (na->nc->HasFlag(NI_SUSPENDED)) - { - if (Config->NSSuspendExpire && Anope::CurTime - na->last_seen >= Config->NSSuspendExpire) - expire = true; - } - else if (na->HasFlag(NS_FORBIDDEN)) - { - if (Config->NSForbidExpire && Anope::CurTime - na->last_seen >= Config->NSForbidExpire) - expire = true; - } - else if (Config->NSExpire && Anope::CurTime - na->last_seen >= Config->NSExpire) - expire = true; - if (na->HasFlag(NS_NO_EXPIRE)) - expire = false; - - if (expire) - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreNickExpire, OnPreNickExpire(na)); - if (MOD_RESULT == EVENT_STOP) - continue; - Anope::string extra; - if (na->HasFlag(NS_FORBIDDEN)) - extra = "forbidden "; - else if (na->nc->HasFlag(NI_SUSPENDED)) - extra = "suspended "; - Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")"; - FOREACH_MOD(I_OnNickExpire, OnNickExpire(na)); - delete na; - } - } -} - -/*************************************************************************/ - NickAlias *findnick(const Anope::string &nick) { FOREACH_MOD(I_OnFindNick, OnFindNick(nick)); @@ -320,10 +101,6 @@ NickCore *findcore(const Anope::string &nick) return NULL; } -/*************************************************************************/ -/*********************** NickServ private routines ***********************/ -/*************************************************************************/ - /** Is the user's address on the nickcores access list? * @param u The user * @param nc The nickcore @@ -360,9 +137,7 @@ bool is_on_access(const User *u, const NickCore *nc) void change_core_display(NickCore *nc, const Anope::string &newdisplay) { - /* Log ... */ FOREACH_MOD(I_OnChangeCoreDisplay, OnChangeCoreDisplay(nc, newdisplay)); - Log(LOG_NORMAL, "nick") << Config->s_NickServ << ": changing " << nc->display << " nickname group display to " << newdisplay; /* Remove the core from the list */ NickCoreList.erase(nc->display); @@ -381,20 +156,3 @@ void change_core_display(NickCore *nc) change_core_display(nc, na->nick); } -/*************************************************************************/ -/*********************** NickServ command routines ***********************/ -/*************************************************************************/ - -int do_setmodes(User *u) -{ - /* Walk users current channels */ - for (UChannelList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it) - { - ChannelContainer *cc = *it; - - Channel *c = cc->chan; - if (c) - chan_set_correct_modes(u, c, 1); - } - return MOD_CONT; -} diff --git a/src/operserv.cpp b/src/operserv.cpp index 86afda8bc..44f62e48c 100644 --- a/src/operserv.cpp +++ b/src/operserv.cpp @@ -11,137 +11,12 @@ #include "services.h" #include "modules.h" +#include "operserv.h" std::vector<NewsItem *> News; -std::vector<std::bitset<32> > DefCon; -bool DefConModesSet = false; -/* Defcon modes mlocked on */ -Flags<ChannelModeName, CMODE_END * 2> DefConModesOn(ChannelModeNameStrings); -/* Defcon modes mlocked off */ -Flags<ChannelModeName, CMODE_END * 2> DefConModesOff(ChannelModeNameStrings); -/* Map of Modesa and Params for DefCon */ -std::map<ChannelModeName, Anope::string> DefConModesOnParams; - XLineManager *SGLine = NULL, *SZLine = NULL, *SQLine = NULL, *SNLine = NULL; -void os_init() -{ - if (!Config->s_OperServ.empty()) - { - ModuleManager::LoadModuleList(Config->OperServCoreModules); - - /* Yes, these are in this order for a reason. Most violent->least violent. */ - XLineManager::RegisterXLineManager(SGLine = new SGLineManager()); - XLineManager::RegisterXLineManager(SZLine = new SZLineManager()); - XLineManager::RegisterXLineManager(SQLine = new SQLineManager()); - XLineManager::RegisterXLineManager(SNLine = new SNLineManager()); - } -} - -bool SetDefConParam(ChannelModeName Name, const Anope::string &buf) -{ - return DefConModesOnParams.insert(std::make_pair(Name, buf)).second; -} - -bool GetDefConParam(ChannelModeName Name, Anope::string &buf) -{ - std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); - - buf.clear(); - - if (it != DefConModesOnParams.end()) - { - buf = it->second; - return true; - } - - return false; -} - -void UnsetDefConParam(ChannelModeName Name) -{ - std::map<ChannelModeName, Anope::string>::iterator it = DefConModesOnParams.find(Name); - - if (it != DefConModesOnParams.end()) - DefConModesOnParams.erase(it); -} - -/** Check if a certain defcon option is currently in affect - * @param Level The level - * @return true and false - */ -bool CheckDefCon(DefconLevel Level) -{ - if (Config->DefConLevel) - return DefCon[Config->DefConLevel][Level]; - return false; -} - -/** Check if a certain defcon option is in a certain defcon level - * @param level The defcon level - * @param Level The defcon level name - * @return true or false - */ -bool CheckDefCon(int level, DefconLevel Level) -{ - return DefCon[level][Level]; -} - -/** Add a defcon level option to a defcon level - * @param level The defcon level - * @param Level The defcon level option - */ -void AddDefCon(int level, DefconLevel Level) -{ - DefCon[level][Level] = true; -} - -/** Remove a defcon level option from a defcon level - * @param level The defcon level - * @param Level The defcon level option - */ -void DelDefCon(int level, DefconLevel Level) -{ - DefCon[level][Level] = false; -} - -void server_global(const Server *s, const Anope::string &message) -{ - if (Config->s_GlobalNoticer.empty()) - return; - - /* Do not send the notice to ourselves our juped servers */ - if (s != Me && !s->HasFlag(SERVER_JUPED)) - notice_server(Config->s_GlobalNoticer, s, "%s", message.c_str()); - - if (!s->GetLinks().empty()) - { - for (unsigned i = 0, j = s->GetLinks().size(); i < j; ++i) - server_global(s->GetLinks()[i], message); - } -} - -void oper_global(const Anope::string &nick, const char *fmt, ...) -{ - va_list args; - char msg[2048]; /* largest valid message is 512, this should cover any global */ - - va_start(args, fmt); - vsnprintf(msg, sizeof(msg), fmt, args); - va_end(args); - - if (!nick.empty() && !Config->AnonymousGlobal) - { - Anope::string rmsg = "[" + nick + "] " + msg; - server_global(Me->GetLinks().front(), rmsg); - } - else - server_global(Me->GetLinks().front(), msg); -} - -/**************************************************************************/ - /* List of XLine managers we check users against in XLineManager::CheckAll */ std::list<XLineManager *> XLineManager::XLineManagers; @@ -318,14 +193,13 @@ void XLineManager::Clear() } /** Add an entry to this XLine Manager - * @param bi The bot error replies should be sent from - * @param u The user adding the XLine * @param mask The mask of the XLine + * @param creator The creator of the XLine * @param expires When this should expire * @param reaosn The reason * @return A pointer to the XLine */ -XLine *XLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *XLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { return NULL; } @@ -468,53 +342,16 @@ void XLineManager::OnExpire(XLine *x) { } -XLine *SGLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SGLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find('!') != Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _("\002Reminder\002: AKILL masks cannot contain nicknames; make sure you have \002not\002 included a nick portion in your mask.")); - return NULL; - } - - if (mask.find('@') == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(BAD_USERHOST_MASK)); - return NULL; - } - - if (mask.find_first_not_of("~@.*?") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the AKILL list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - Anope::string realreason = reason; - if (u && Config->AddAkiller) - realreason = "[" + u->nick + "] " + reason; + if (!creator.empty() && Config->AddAkiller) + realreason = "[" + creator + "] " + reason; - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, realreason); + XLine *x = new XLine(mask, creator, expires, realreason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddAkill, OnAddAkill(u, x)); + FOREACH_RESULT(I_OnAddAkill, OnAddAkill(x)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -543,8 +380,8 @@ void SGLineManager::OnMatch(User *u, XLine *x) void SGLineManager::OnExpire(XLine *x) { - if (Config->WallAkillExpire) - ircdproto->SendGlobops(OperServ, "AKILL on %s has expired", x->Mask.c_str()); + if (Config->WallAkillExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "AKILL on %s has expired", x->Mask.c_str()); } void SGLineManager::Send(User *u, XLine *x) @@ -552,35 +389,12 @@ void SGLineManager::Send(User *u, XLine *x) ircdproto->SendAkill(u, x); } -XLine *SNLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SNLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (!mask.empty() && mask.find_first_not_of("*?") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(bi, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SNLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SNLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SNLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -623,8 +437,8 @@ void SNLineManager::OnMatch(User *u, XLine *x) void SNLineManager::OnExpire(XLine *x) { - if (Config->WallSNLineExpire) - ircdproto->SendGlobops(OperServ, "SNLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSNLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SNLINE on \2%s\2 has expired", x->Mask.c_str()); } void SNLineManager::Send(User *u, XLine *x) @@ -657,42 +471,12 @@ XLine *SNLineManager::Check(User *u) return NULL; } -XLine *SQLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SQLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find_first_not_of("*") == Anope::string::npos) - { - if (bi && u) - u->SendMessage(OperServ, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - if (mask[0] == '#' && !ircd->chansqline) - { - if (bi && u) - u->SendMessage(OperServ, _("Channel SQLINEs are not supported by your IRCd, so you can't use them.")); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SQLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SQLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SQLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -761,8 +545,8 @@ void SQLineManager::OnMatch(User *u, XLine *x) void SQLineManager::OnExpire(XLine *x) { - if (Config->WallSQLineExpire) - ircdproto->SendGlobops(OperServ, "SQLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSQLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SQLINE on \2%s\2 has expired", x->Mask.c_str()); } void SQLineManager::Send(User *u, XLine *x) @@ -786,40 +570,12 @@ bool SQLineManager::Check(Channel *c) return false; } -XLine *SZLineManager::Add(BotInfo *bi, User *u, const Anope::string &mask, time_t expires, const Anope::string &reason) +XLine *SZLineManager::Add(const Anope::string &mask, const Anope::string &creator, time_t expires, const Anope::string &reason) { - if (mask.find('!') != Anope::string::npos || mask.find('@') != Anope::string::npos) - { - u->SendMessage(OperServ, _("\002Reminder:\002 you can only add IP masks to the SZLINE list.")); - return NULL; - } - - if (mask.find_first_not_of("*?") == Anope::string::npos) - { - u->SendMessage(OperServ, _(USERHOST_MASK_TOO_WIDE), mask.c_str()); - return NULL; - } - - std::pair<int, XLine *> canAdd = this->CanAdd(mask, expires); - if (canAdd.first) - { - if (bi && u) - { - if (canAdd.first == 1) - u->SendMessage(bi, _("\002%s\002 already exists on the SZLINE list."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 2) - u->SendMessage(bi, _("Expiry time of \002%s\002 changed."), canAdd.second->Mask.c_str()); - else if (canAdd.first == 3) - u->SendMessage(bi, _("\002%s\002 is already covered by %s."), mask.c_str(), canAdd.second->Mask.c_str()); - } - - return NULL; - } - - XLine *x = new XLine(mask, u ? u->nick : (OperServ ? OperServ->nick : "OperServ"), expires, reason); + XLine *x = new XLine(mask, creator, expires, reason); EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnAddXLine, OnAddXLine(u, x, X_SZLINE)); + FOREACH_RESULT(I_OnAddXLine, OnAddXLine(x, X_SZLINE)); if (MOD_RESULT == EVENT_STOP) { delete x; @@ -852,8 +608,8 @@ void SZLineManager::OnMatch(User *u, XLine *x) void SZLineManager::OnExpire(XLine *x) { - if (Config->WallSZLineExpire) - ircdproto->SendGlobops(OperServ, "SZLINE on \2%s\2 has expired", x->Mask.c_str()); + if (Config->WallSZLineExpire && operserv) + ircdproto->SendGlobops(operserv->Bot(), "SZLINE on \2%s\2 has expired", x->Mask.c_str()); } void SZLineManager::Send(User *u, XLine *x) diff --git a/src/protocol.cpp b/src/protocol.cpp index ddf1557bd..d923f914e 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -295,8 +295,10 @@ bool IRCdMessage::On436(const Anope::string &, const std::vector<Anope::string> bool IRCdMessage::OnAway(const Anope::string &source, const std::vector<Anope::string> ¶ms) { User *u = finduser(source); - if (u && params.empty()) /* un-away */ - check_memos(u); + if (u) + { + FOREACH_MOD(I_OnUserAway, OnUserAway(u, params.empty() ? "" : params[0])); + } return true; } @@ -361,7 +363,7 @@ bool IRCdMessage::OnPing(const Anope::string &, const std::vector<Anope::string> bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) { const Anope::string &receiver = params.size() > 0 ? params[0] : ""; - const Anope::string &message = params.size() > 1 ? params[1] : ""; + Anope::string message = params.size() > 1 ? params[1] : ""; /* Messages from servers can happen on some IRCds, check for . */ if (source.empty() || receiver.empty() || message.empty() || source.find('.') != Anope::string::npos) @@ -380,12 +382,14 @@ bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope return true; } - if (receiver[0] == '#' && !Config->s_BotServ.empty()) + if (receiver[0] == '#') { ChannelInfo *ci = cs_findchan(receiver); /* Some paranoia checks */ - if (ci && !ci->HasFlag(CI_FORBIDDEN) && ci->c && ci->bi) - botchanmsgs(u, ci, message); + if (ci && !ci->HasFlag(CI_FORBIDDEN) && ci->c) + { + FOREACH_MOD(I_OnPrivmsg, OnPrivmsg(u, ci, message)); + } } else { @@ -433,36 +437,8 @@ bool IRCdMessage::OnPrivmsg(const Anope::string &source, const std::vector<Anope ircdproto->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, Config->EncModuleList.begin()->c_str(), Anope::VersionBuildString().c_str()); } } - else if (bi == ChanServ) - { - if (!u->HasMode(UMODE_OPER) && Config->CSOpersOnly) - u->SendMessage(ChanServ, _(ACCESS_DENIED)); - else - mod_run_cmd(bi, u, NULL, message); - } - else if (bi == HostServ) - { - if (!ircd->vhost) - u->SendMessage(HostServ, _("%s is currently offline."), Config->s_HostServ.c_str()); - else - mod_run_cmd(bi, u, NULL, message); - } - else if (bi == OperServ) - { - if (!u->HasMode(UMODE_OPER) && Config->OSOpersOnly) - { - u->SendMessage(OperServ, _(ACCESS_DENIED)); - if (Config->WallBadOS) - ircdproto->SendGlobops(OperServ, "Denied access to %s from %s!%s@%s (non-oper)", Config->s_OperServ.c_str(), u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str()); - } - else - { - Log(OperServ) << u->nick << ": " << message; - mod_run_cmd(bi, u, NULL, message); - } - } - else - mod_run_cmd(bi, u, NULL, message); + + bi->OnMessage(u, message); } } @@ -507,17 +483,7 @@ bool IRCdMessage::OnSQuit(const Anope::string &source, const std::vector<Anope:: FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); - Anope::string buf; - /* If this is a juped server, send a nice global to inform the online - * opers that we received it. - */ - if (s->HasFlag(SERVER_JUPED)) - { - buf = "Received SQUIT for juped server " + s->GetName(); - ircdproto->SendGlobops(OperServ, "%s", buf.c_str()); - } - - buf = s->GetName() + " " + s->GetUplink()->GetName(); + Anope::string buf = s->GetName() + " " + s->GetUplink()->GetName(); if (s->GetUplink() == Me && Capab.HasFlag(CAPAB_UNCONNECT)) { @@ -547,14 +513,14 @@ bool IRCdMessage::OnWhois(const Anope::string &source, const std::vector<Anope:: ircdproto->SendNumeric(Config->ServerName, 317, source, "%s %ld %ld :seconds idle, signon time", bi->nick.c_str(), static_cast<long>(Anope::CurTime - bi->lastmsg), static_cast<long>(start_time)); ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", who.c_str()); } - else if (!ircd->svshold && (u = finduser(who)) && u->server == Me) + else if ((u = finduser(who)) && u->server == Me) { ircdproto->SendNumeric(Config->ServerName, 311, source, "%s %s %s * :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), u->realname.c_str()); ircdproto->SendNumeric(Config->ServerName, 312, source, "%s %s :%s", u->nick.c_str(), Config->ServerName.c_str(), Config->ServerDesc.c_str()); ircdproto->SendNumeric(Config->ServerName, 318, source, "%s :End of /WHOIS list.", u->nick.c_str()); } else - ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such service.", who.c_str()); + ircdproto->SendNumeric(Config->ServerName, 401, source, "%s :No such user.", who.c_str()); } return true; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 9d0a95059..8bc369511 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -11,6 +11,8 @@ #include "services.h" #include "modules.h" +#include "chanserv.h" +#include "nickserv.h" ChanAccess::ChanAccess(const Anope::string &umask) { @@ -164,6 +166,16 @@ ChannelInfo::~ChannelInfo() --this->founder->channelcount; } +/** Find which bot should send mode/topic/etc changes for this channel + * @return The bot + */ +BotInfo *ChannelInfo::WhoSends() +{ + if (!this || !this->bi || !this->c || !this->botflags.HasFlag(BS_SYMBIOSIS) || !this->c->FindUser(this->bi)) + return chanserv ? chanserv->Bot() : (nickserv ? nickserv->Bot() : NULL); + return this->bi; +} + /** Add an entry to the channel access list * * @param mask The mask of the access entry @@ -553,7 +565,7 @@ void ChannelInfo::LoadMLock() else { if (!this->bi) - whosends(this)->Assign(NULL, this); + this->WhoSends()->Assign(NULL, this); if (this->c->FindUser(this->bi) == NULL) this->bi->Join(this->c); @@ -860,7 +872,7 @@ void ChannelInfo::RestoreTopic() if ((this->HasFlag(CI_KEEPTOPIC) || this->HasFlag(CI_TOPICLOCK)) && this->last_topic != this->c->topic) { - this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : whosends(this)->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime); + this->c->ChangeTopic(!this->last_topic_setter.empty() ? this->last_topic_setter : this->WhoSends()->nick, this->last_topic, this->last_topic_time ? this->last_topic_time : Anope::CurTime); } } diff --git a/src/servers.cpp b/src/servers.cpp index 7bde57a35..096be0c9c 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -309,10 +309,6 @@ void do_server(const Anope::string &source, const Anope::string &servername, uns /* Create a server structure. */ Server *newserver = new Server(s, servername, hops, descript, numeric); - /* Announce services being online. */ - if (Config->GlobalOnCycle && !Config->GlobalOnCycleUP.empty() && !Config->s_GlobalNoticer.empty()) - notice_server(Config->s_GlobalNoticer, newserver, "%s", Config->GlobalOnCycleUP.c_str()); - /* Let modules know about the connection */ FOREACH_MOD(I_OnNewServer, OnNewServer(newserver)); } diff --git a/src/sessions.cpp b/src/sessions.cpp deleted file mode 100644 index 358527ea0..000000000 --- a/src/sessions.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* Session Limiting functions. - * - * (C) 2003-2011 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - */ - -#include "services.h" -#include "modules.h" - -/*************************************************************************/ - -/* SESSION LIMITING - * - * The basic idea of session limiting is to prevent one host from having more - * than a specified number of sessions (client connections/clones) on the - * network at any one time. To do this we have a list of sessions and - * exceptions. Each session structure records information about a single host, - * including how many clients (sessions) that host has on the network. When a - * host reaches it's session limit, no more clients from that host will be - * allowed to connect. - * - * When a client connects to the network, we check to see if their host has - * reached the default session limit per host, and thus whether it is allowed - * any more. If it has reached the limit, we kill the connecting client; all - * the other clients are left alone. Otherwise we simply increment the counter - * within the session structure. When a client disconnects, we decrement the - * counter. When the counter reaches 0, we free the session. - * - * Exceptions allow one to specify custom session limits for a specific host - * or a range thereof. The first exception that the host matches is the one - * used. - * - * -TheShadow (02 April 1999) - */ - -/*************************************************************************/ - -Anope::map<Session *> SessionList; - -std::vector<Exception *> exceptions; - -/*************************************************************************/ -/****************************** Statistics *******************************/ -/*************************************************************************/ - -void get_session_stats(long &count, long &mem) -{ - count = SessionList.size(); - mem = sizeof(Session) * SessionList.size(); - - for (Anope::map<Session *>::iterator it = SessionList.begin(), it_end = SessionList.end(); it != it_end; ++it) - { - Session *session = it->second; - mem += session->host.length() + 1; - } -} - -void get_exception_stats(long &count, long &mem) -{ - count = exceptions.size(); - mem = sizeof(Exception) * exceptions.size(); - - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (!e->mask.empty()) - mem += e->mask.length() + 1; - if (!e->reason.empty()) - mem += e->reason.length() + 1; - if (!e->who.empty()) - mem += e->who.length() + 1; - } -} - -/*************************************************************************/ -/********************* Internal Session Functions ************************/ -/*************************************************************************/ - -Session *findsession(const Anope::string &host) -{ - Anope::map<Session *>::iterator it = SessionList.find(host); - if (it != SessionList.end()) - return it->second; - return NULL; -} - -/* Attempt to add a host to the session list. If the addition of the new host - * causes the the session limit to be exceeded, kill the connecting user. - */ - -void add_session(User *u) -{ - const Anope::string &hostip = u->ip() ? u->ip.addr() : ""; - Session *session = findsession(u->host); - - if (session) - { - bool kill = false; - if (Config->DefSessionLimit && session->count >= Config->DefSessionLimit) - { - kill = true; - Exception *exception = find_hostip_exception(u->host, hostip); - if (exception) - { - kill = false; - if (exception->limit && session->count >= exception->limit) - kill = true; - } - } - - if (kill) - { - if (!Config->SessionLimitExceeded.empty()) - u->SendMessage(OperServ, Config->SessionLimitExceeded.c_str(), u->host.c_str()); - if (!Config->SessionLimitDetailsLoc.empty()) - u->SendMessage(OperServ, "%s", Config->SessionLimitDetailsLoc.c_str()); - - /* Previously on IRCds that send a QUIT (InspIRCD) when a user is killed, the session for a host was - * decremented in do_quit, which caused problems and fixed here - * - * Now, we create the user struture before calling this to fix some user tracking issues, - * so we must increment this here no matter what because it will either be - * decremented in do_kill or in do_quit - Adam - */ - ++session->count; - kill_user(Config->s_OperServ, u, "Session limit exceeded"); - - ++session->hits; - if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill && SGLine) - { - const Anope::string &akillmask = "*@" + u->host; - const Anope::string &akillreason = "Session limit exceeded for " + u->host; - SGLine->Add(NULL, NULL, akillmask, Anope::CurTime + Config->SessionAutoKillExpiry, akillreason); - ircdproto->SendGlobops(OperServ, "Added a temporary AKILL for \2%s\2 due to excessive connections", akillmask.c_str()); - } - } - else - { - ++session->count; - } - } - else - { - session = new Session(); - session->host = u->host; - session->count = 1; - session->hits = 0; - - SessionList[session->host] = session; - } -} - -void del_session(User *u) -{ - if (!Config->LimitSessions) - { - Log(LOG_DEBUG) << "del_session called when LimitSessions is disabled"; - return; - } - - if (!u) - { - Log(LOG_DEBUG) << "del_session called with NULL values"; - return; - } - - Log(LOG_DEBUG_2) << "del_session() called"; - - Session *session = findsession(u->host); - - if (!session) - { - if (debug) - { - ircdproto->SendGlobops(OperServ, "WARNING: Tried to delete non-existant session: \2%s", u->host.c_str()); - Log() << "session: Tried to delete non-existant session: " << u->host; - } - return; - } - - if (session->count > 1) - { - --session->count; - return; - } - - SessionList.erase(session->host); - - delete session; - - Log(LOG_DEBUG_2) << "del_session() done"; -} - -/*************************************************************************/ -/********************** Internal Exception Functions *********************/ -/*************************************************************************/ - -void expire_exceptions() -{ - for (unsigned i = exceptions.size(); i > 0; --i) - { - Exception *e = exceptions[i - 1]; - - if (!e->expires || e->expires > Anope::CurTime) - continue; - if (Config->WallExceptionExpire) - ircdproto->SendGlobops(OperServ, "Session limit exception for %s has expired.", e->mask.c_str()); - delete e; - exceptions.erase(exceptions.begin() + i - 1); - } -} - -/* Find the first exception this host matches and return it. */ -Exception *find_host_exception(const Anope::string &host) -{ - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(host, e->mask)) - return e; - } - - return NULL; -} - -/* Same as find_host_exception() except - * this tries to find the exception by IP also. */ -Exception *find_hostip_exception(const Anope::string &host, const Anope::string &hostip) -{ - for (std::vector<Exception *>::const_iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (Anope::Match(host, e->mask) || (!hostip.empty() && Anope::Match(hostip, e->mask))) - return e; - } - - return NULL; -} - -/*************************************************************************/ -/************************ Exception Manipulation *************************/ -/*************************************************************************/ - -int exception_add(User *u, const Anope::string &mask, unsigned limit, const Anope::string &reason, const Anope::string &who, time_t expires) -{ - /* Check if an exception already exists for this mask */ - for (std::vector<Exception *>::iterator it = exceptions.begin(), it_end = exceptions.end(); it != it_end; ++it) - { - Exception *e = *it; - if (e->mask.equals_ci(mask)) - { - if (e->limit != limit) - { - e->limit = limit; - if (u) - u->SendMessage(OperServ, _("Exception for \002%s\002 has been updated to %d."), mask.c_str(), e->limit); - return -2; - } - else - { - if (u) - u->SendMessage(OperServ, _("\002%s\002 already exists on the EXCEPTION list."), mask.c_str()); - return -1; - } - } - } - - Exception *exception = new Exception(); - exception->mask = mask; - exception->limit = limit; - exception->reason = reason; - exception->time = Anope::CurTime; - exception->who = who; - exception->expires = expires; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnExceptionAdd, OnExceptionAdd(u, exception)); - if (MOD_RESULT == EVENT_STOP) - { - delete exception; - return -3; - } - - exceptions.push_back(exception); - - return 1; -} diff --git a/src/users.cpp b/src/users.cpp index f2206be7f..88ab225b6 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -11,6 +11,7 @@ #include "services.h" #include "modules.h" +#include "nickserv.h" Anope::insensitive_map<User *> UserListByNick; Anope::map<User *> UserListByUID; @@ -204,9 +205,6 @@ User::~User() while (!this->chans.empty()) this->chans.front()->chan->DeleteUser(this); - if (Config->LimitSessions && !this->server->IsULined()) - del_session(this); - UserListByNick.erase(this->nick); if (!this->uid.empty()) UserListByUID.erase(this->uid); @@ -322,7 +320,7 @@ void User::Collide(NickAlias *na) guestnick = Config->NSGuestNickPrefix + stringify(getrandom16()); } while (finduser(guestnick)); - this->SendMessage(NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); + this->SendMessage(nickserv->Bot(), _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); ircdproto->SendForceNickChange(this, guestnick, Anope::CurTime); } else @@ -354,36 +352,7 @@ void User::Identify(NickAlias *na) ircdproto->SendAccountLogin(this, this->Account()); ircdproto->SetAutoIdentificationToken(this); - NickAlias *this_na = findnick(this->nick); - if (this_na && this_na->nc == na->nc && this_na->nc->HasFlag(NI_UNCONFIRMED) == false) - this->SetMode(NickServ, UMODE_REGISTERED); - if (ircd->vhost) - do_on_id(this); - if (Config->NSModeOnID) - do_setmodes(this); - FOREACH_MOD(I_OnNickIdentify, OnNickIdentify(this)); - - if (Config->NSForceEmail && na->nc->email.empty()) - { - this->SendMessage(NickServ, _("You must now supply an e-mail for your nick.\n" - "This e-mail will allow you to retrieve your password in\n" - "case you forget it.")); - this->SendMessage(NickServ, _("Type \002%s%s SET EMAIL \037e-mail\037\002 in order to set your e-mail.\n" - "Your privacy is respected; this e-mail won't be given to\n" - "any third-party person."), Config->UseStrictPrivMsgString.c_str(), NickServ->nick.c_str()); - } - - if (na->nc->HasFlag(NI_UNCONFIRMED)) - { - this->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered.")); - time_t time_registered = Anope::CurTime - na->time_registered; - if (Config->NSUnconfirmedExpire > time_registered) - this->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), duration(Config->NSUnconfirmedExpire - time_registered).c_str()); - } - - check_memos(this); - } @@ -397,7 +366,6 @@ void User::Login(NickCore *core) core->Users.push_back(this); this->UpdateHost(); - check_memos(this); } /** Logout the user @@ -698,22 +666,14 @@ void User::SetModesInternal(const char *umodes, ...) { case UMODE_OPER: if (add) - { ++opcnt; - if (Config->WallOper) - ircdproto->SendGlobops(OperServ, "\2%s\2 is now an IRC operator.", this->nick.c_str()); - Log(OperServ) << this->nick << " is now an IRC operator"; - } else - { --opcnt; - Log(OperServ) << this->nick << " is no longer an IRC operator"; - } break; case UMODE_REGISTERED: - if (add && !this->IsIdentified()) - this->RemoveMode(NickServ, UMODE_REGISTERED); + if (add && !this->IsIdentified() && nickserv) + this->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); break; case UMODE_CLOAK: case UMODE_VHOST: @@ -751,32 +711,6 @@ bool User::IsProtected() const return false; } -/*************************************************************************/ - -void get_user_stats(long &count, long &mem) -{ - count = mem = 0; - - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it) - { - User *user = it->second; - - ++count; - mem += sizeof(*user); - if (!user->host.empty()) - mem += user->host.length() + 1; - if (ircd->vhost) - { - if (!user->vhost.empty()) - mem += user->vhost.length() + 1; - } - if (!user->realname.empty()) - mem += user->realname.length() + 1; - mem += user->server->GetName().length() + 1; - mem += (sizeof(ChannelContainer) * user->chans.size()); - } -} - User *finduser(const Anope::string &nick) { if (isdigit(nick[0]) && ircd->ts6) @@ -836,28 +770,14 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop } } - Log(*user, "connect") << (!vhost.empty() ? Anope::string("(") + vhost + ")" : "") << " (" << user->realname << ") " << (user->ip() ? Anope::string("[") + user->ip.addr() + "] " : "") << "connected to the network (" << serv->GetName() << ")"; - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreUserConnect, OnPreUserConnect(*user)); - - if (user && MOD_RESULT != EVENT_STOP) - { - if (Config->LimitSessions && !serv->IsULined()) - add_session(*user); + Log(user, "connect") << (!vhost.empty() ? Anope::string("(") + vhost + ")" : "") << " (" << user->realname << ") " << (user->ip() ? Anope::string("[") + user->ip.addr() + "] " : "") << "connected to the network (" << serv->GetName() << ")"; - if (!user) - return NULL; - - XLineManager::CheckAll(*user); - } - - if (!user) - return NULL; - - FOREACH_MOD(I_OnUserConnect, OnUserConnect(*user)); + bool exempt = false; + if (user->server && user->server->IsULined()) + exempt = true; + FOREACH_MOD(I_OnUserConnect, OnUserConnect(user, exempt)); - return user ? *user : NULL; + return user; } else { @@ -898,20 +818,19 @@ User *do_nick(const Anope::string &source, const Anope::string &nick, const Anop /* If the new nick isnt registerd or its registerd and not yours */ if (!na || na->nc != user->Account()) { - user->RemoveMode(NickServ, UMODE_REGISTERED); + user->RemoveMode(nickserv->Bot(), UMODE_REGISTERED); ircdproto->SendUnregisteredNick(user); - validate_user(user); + nickserv->Validate(user); } else { na->last_seen = Anope::CurTime; user->UpdateHost(); - do_on_id(user); ircdproto->SetAutoIdentificationToken(user); if (na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(NickServ, UMODE_REGISTERED); - Log(NickServ) << user->GetMask() << " automatically identified for group " << user->Account()->display; + user->SetMode(nickserv->Bot(), UMODE_REGISTERED); + Log(nickserv->Bot()) << user->GetMask() << " automatically identified for group " << user->Account()->display; } if (ircd->sqline) diff --git a/src/win32/anope_windows.h b/src/win32/anope_windows.h index 3abe8bd13..97ad76080 100644 --- a/src/win32/anope_windows.h +++ b/src/win32/anope_windows.h @@ -45,7 +45,9 @@ extern CoreExport USHORT WindowsGetLanguage(const char *lang);
extern CoreExport int inet_pton(int af, const char *src, void *dst);
extern CoreExport const char *inet_ntop(int af, const void *src, char *dst, size_t size);
-extern CoreExport int gettimeofday(timeval *tv, char *);
+extern CoreExport int gettimeofday(timeval *tv, void *);
+extern CoreExport Anope::string GetWindowsVersion();
+extern CoreExport bool SupportedWindowsVersion();
#endif // _WIN32
- #endif // WINDOWS_H
\ No newline at end of file + #endif // WINDOWS_H
diff --git a/src/win32/windows.cpp b/src/win32/windows.cpp index b57171dec..3876c62bf 100644 --- a/src/win32/windows.cpp +++ b/src/win32/windows.cpp @@ -128,7 +128,7 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size) * @param tz Should be NULL, it is not used * @return 0 on success */ -int gettimeofday(timeval *tv, char *) +int gettimeofday(timeval *tv, void *) { SYSTEMTIME st; GetSystemTime(&st); @@ -139,4 +139,154 @@ int gettimeofday(timeval *tv, char *) return 0; } +Anope::string GetWindowsVersion() +{ + OSVERSIONINFOEX osvi; + SYSTEM_INFO si; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) + return ""; + } + GetSystemInfo(&si); + + Anope::string buf, extra, cputype; + /* Determine CPU type 32 or 64 */ + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + cputype = " 64-bit"; + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) + cputype = " 32-bit"; + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) + cputype = " Itanium 64-bit"; + + switch (osvi.dwPlatformId) + { + /* test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + /* Windows Vista or Windows Server 2008 */ + if (osvi.dwMajorVersion == 6 && !osvi.dwMinorVersion) + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; + else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Edition"; + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + extra = " Home Premium/Basic"; + if (osvi.dwMinorVersion == 0) + { + if (osvi.wProductType & VER_NT_WORKSTATION) + buf = "Microsoft Windows Vista" + cputype + extra; + else + buf = "Microsoft Windows Server 2008" + cputype + extra; + } + else if (osvi.dwMinorVersion == 1) + { + if (osvi.wProductType & VER_NT_WORKSTATION) + buf = "Microsoft Windows 7" + cputype + extra; + else + buf = "Microsoft Windows Server 2008 R2" + cputype + extra; + } + } + /* Windows 2003 or Windows XP Pro 64 */ + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Edition"; + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; +#ifdef VER_SUITE_COMPUTE_SERVER + else if (osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER) + extra = " Compute Cluster Edition"; +#endif + else if (osvi.wSuiteMask == VER_SUITE_BLADE) + extra = " Web Edition"; + else + extra = " Standard Edition"; + if (osvi.wProductType & VER_NT_WORKSTATION && si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) + buf = "Microsoft Windows XP Professional x64 Edition" + extra; + else + buf = "Microsoft Windows Server 2003 Family" + cputype + extra; + } + if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) + { + if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) + extra = " Embedded"; + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + extra = " Home Edition"; + buf = "Microsoft Windows XP" + extra; + } + if (osvi.dwMajorVersion == 5 && !osvi.dwMinorVersion) + { + if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + extra = " Datacenter Server"; + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Advanced Server"; + else + extra = " Server"; + buf = "Microsoft Windows 2000" + extra; + } + if (osvi.dwMajorVersion <= 4) + { + if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + extra = " Enterprise Edition"; + buf = "Microsoft Windows NT Server 4.0" + extra; + } + break; + case VER_PLATFORM_WIN32_WINDOWS: + if (osvi.dwMajorVersion == 4 && !osvi.dwMinorVersion) + { + if (osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B') + extra = " OSR2"; + buf = "Microsoft Windows 95" + extra; + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) + { + if (osvi.szCSDVersion[1] == 'A') + extra = "SE"; + buf = "Microsoft Windows 98" + extra; + } + if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + buf = "Microsoft Windows Millenium Edition"; + } + return buf; +} + +bool SupportedWindowsVersion() +{ + OSVERSIONINFOEX osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + BOOL bOsVersionInfoEx = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi)); + if (!bOsVersionInfoEx) + { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (!GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&osvi))) + return false; + } + + switch (osvi.dwPlatformId) + { + /* test for the Windows NT product family. */ + case VER_PLATFORM_WIN32_NT: + /* win nt4 */ + if (osvi.dwMajorVersion <= 4) + return false; + /* the rest */ + return true; + /* win95 win98 winME */ + case VER_PLATFORM_WIN32_WINDOWS: + return false; + } + return false; +} + #endif |