From 246f44b9888161aecefc81f0ff17ddd893287e3c Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 20 Nov 2010 21:45:30 -0500 Subject: Added cs_mode, rewrote the old list mode code, and added CIDR support --- data/example.conf | 3 +- data/mysql/tables.sql | 1 + docs/Changes.conf | 2 +- docs/IRCD | 12 +- include/channels.h | 56 +-- include/extern.h | 16 +- include/language.h | 29 +- include/modes.h | 20 +- include/modules.h | 14 +- include/regchannel.h | 63 +-- include/services.h | 35 +- include/sockets.h | 12 + include/users.h | 4 + modules/core/cs_clearusers.cpp | 14 +- modules/core/cs_forbid.cpp | 10 +- modules/core/cs_info.cpp | 3 +- modules/core/cs_mode.cpp | 306 +++++++++++++++ modules/core/cs_set.cpp | 2 +- modules/core/cs_set_persist.cpp | 4 +- modules/core/db_plain.cpp | 75 ++-- modules/core/os_defcon.cpp | 2 +- modules/extra/db_mysql.cpp | 50 ++- modules/extra/m_xmlrpc_main.cpp | 38 +- modules/protocol/bahamut.cpp | 1 - modules/protocol/inspircd11.cpp | 1 - modules/protocol/inspircd12.cpp | 1 - modules/protocol/inspircd20.cpp | 1 - modules/protocol/ratbox.cpp | 25 +- modules/protocol/unreal32.cpp | 25 +- src/actions.cpp | 21 +- src/bots.cpp | 32 +- src/channels.cpp | 820 +++++++++++----------------------------- src/chanserv.cpp | 160 +++----- src/config.cpp | 2 +- src/language.cpp | 46 ++- src/misc.cpp | 80 +++- src/modes.cpp | 136 ++----- src/operserv.cpp | 13 +- src/regchannel.cpp | 186 ++++----- src/sockets.cpp | 74 ++++ src/users.cpp | 25 +- src/wildcard.cpp | 72 ---- 42 files changed, 1226 insertions(+), 1266 deletions(-) create mode 100644 modules/core/cs_mode.cpp delete mode 100644 src/wildcard.cpp diff --git a/data/example.conf b/data/example.conf index 1216e163b..777e28748 100644 --- a/data/example.conf +++ b/data/example.conf @@ -639,6 +639,7 @@ log * * chanserv/access/list chanserv/drop chanserv/forbid chanserv/getkey * chanserv/list chanserv/suspend chanserv/topic chanserv/status + * chanserv/mode * * chanserv/saset/bantype chanserv/saset/description chanserv/saset/email chanserv/saset/entrymsg * chanserv/saset/founder chanserv/saset/keeptopic chanserv/saset/opnotice @@ -1044,7 +1045,7 @@ chanserv * The core modules to load for ChanServ. This is a space separated list that corresponds * to the base names of the modules for 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" + 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" /* * The default options for newly registered channels. Note that changing these options diff --git a/data/mysql/tables.sql b/data/mysql/tables.sql index fb9b7335a..e165e94ad 100644 --- a/data/mysql/tables.sql +++ b/data/mysql/tables.sql @@ -111,6 +111,7 @@ CREATE TABLE IF NOT EXISTS `anope_cs_info` ( `mlock_on` text NOT NULL, `mlock_off` text NOT NULL, `mlock_params` text NOT NULL, + `mlock_params_off` text NOT NULL, `entry_message` text NOT NULL, `memomax` smallint(5) unsigned NOT NULL DEFAULT '0', `botnick` varchar(255) NOT NULL DEFAULT '', diff --git a/docs/Changes.conf b/docs/Changes.conf index 792477f12..def316054 100644 --- a/docs/Changes.conf +++ b/docs/Changes.conf @@ -1,7 +1,7 @@ Anope Version 1.9.4 ------------------- memoserv:modules added ms_ignore -chanserv:modules added cs_clone +chanserv:modules added cs_clone and cs_mode Anope Version 1.9.3 ------------------ diff --git a/docs/IRCD b/docs/IRCD index 7e7c4e163..ce44d893f 100644 --- a/docs/IRCD +++ b/docs/IRCD @@ -106,18 +106,10 @@ How To Add IRCd Support 23) TS6: Does the IRCd support TS6? Use 1 for yes, 0 for no. - 24) Channel CIDR: Set to 1 if channel bans, excepts and invites - support CIDR masks. Expected syntax: *!*@ip/mask. - When set to 1, anope will only parse strict CIDR masks. - IRCd's that try to correct invalid CIDR's (like nefarious) - will need a custom implementation in the core. - Contact the anope Dev Team if this is the case. - Set to 0 if CIDR's are not supported by your IRCd. - - 25) Global TLD Prefix: Prefix used to send global messages, should probably + 24) Global TLD Prefix: Prefix used to send global messages, should probably be "$" - 26) Max Modes: The max number of mode changes we can send in one line + 25) Max Modes: The max number of mode changes we can send in one line 3) Modes diff --git a/include/channels.h b/include/channels.h index 54a85426b..cf4d97df3 100644 --- a/include/channels.h +++ b/include/channels.h @@ -64,13 +64,12 @@ enum ChannelFlags class CoreExport Channel : public Extensible, public Flags { + public: + typedef std::multimap ModeList; private: /** A map of channel modes with their parameters set on this channel */ - std::map Params; - - /* Modes set on the channel */ - Flags modes; + ModeList modes; public: /** Default constructor @@ -87,10 +86,6 @@ class CoreExport Channel : public Extensible, public Flags ChannelInfo *ci; /* Corresponding ChannelInfo */ time_t creation_time; /* When channel was created */ - EList *bans; - EList *excepts; - EList *invites; - /* List of users in the channel */ CUserList users; @@ -146,16 +141,18 @@ class CoreExport Channel : public Extensible, public Flags */ bool HasUserStatus(User *u, ChannelModeName Name) const; - /** See if the channel has any modes at all - * @return true or false - */ - inline bool HasModes() const { return modes.FlagCount(); } - /** See if a channel has a mode * @param Name The mode name - * @return true or false + * @return The number of modes set + * @param param The optional mode param */ - bool HasMode(ChannelModeName Name) const; + size_t HasMode(ChannelModeName Name, const Anope::string ¶m = ""); + + /** Get a list of modes on a channel + * @param Name A mode name to get the list of + * @return a pair of iterators for the beginning and end of the list + */ + std::pair GetModeList(ChannelModeName Name); /** Set a mode internally on a channel, this is not sent out to the IRCd * @param cm The mode @@ -205,30 +202,6 @@ class CoreExport Channel : public Extensible, public Flags */ void RemoveMode(BotInfo *bi, ChannelModeName Name, const Anope::string ¶m = "", bool EnforceMLock = true); - /** Clear all the modes from the channel - * @param bi The client unsetting the modes - * @param internal Only remove the modes internally - */ - void ClearModes(BotInfo *bi = NULL, bool internal = false); - - /** Clear all the bans from the channel - * @param bi The client unsetting the modes - * @param internal Only remove the modes internally - */ - void ClearBans(BotInfo *bi = NULL, bool internal = false); - - /** Clear all the excepts from the channel - * @param bi The client unsetting the modes - * @param internal Only remove the modes internally - */ - void ClearExcepts(BotInfo *bi = NULL, bool internal = false); - - /** Clear all the invites from the channel - * @param bi The client unsetting the modes - * @param internal Only remove the modes internally - */ - void ClearInvites(BotInfo *bi = NULL, bool internal = false); - /** Get a param from the channel * @param Name The mode * @param Target a string to put the param into @@ -236,11 +209,6 @@ class CoreExport Channel : public Extensible, public Flags */ bool GetParam(ChannelModeName Name, Anope::string &Target) const; - /** Check if a mode is set and has a param - * @param Name The mode - */ - bool HasParam(ChannelModeName Name) const; - /** Set a string of modes on the channel * @param bi The client setting the modes * @param EnforceMLock Should mlock be enforced on this mode change diff --git a/include/extern.h b/include/extern.h index b8bcb5be3..bd951ee5e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -75,18 +75,6 @@ E void MassChannelModes(BotInfo *bi, const Anope::string &modes); E void chan_set_correct_modes(User *user, Channel *c, int give_modes); -E Entry *entry_create(const Anope::string &mask); -E Entry *entry_add(EList *list, const Anope::string &mask); -E void entry_delete(EList *list, Entry *e); -E EList *list_create(); -E int entry_match(Entry *e, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip); -E int entry_match_mask(Entry *e, const Anope::string &mask, uint32 ip); -E Entry *elist_match(EList *list, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip); -E Entry *elist_match_mask(EList *list, const Anope::string &mask, uint32 ip); -E Entry *elist_match_user(EList *list, User *u); -E Entry *elist_find_mask(EList *list, const Anope::string &mask); -E long get_memuse(EList *list); - inline BotInfo *whosends(ChannelInfo *ci) { if (!ci || !ci->bi || !ci->c || !ci->botflags.HasFlag(BS_SYMBIOSIS) || !ci->c->FindUser(ci->bi)) @@ -272,9 +260,7 @@ E bool str_is_cidr(const Anope::string &str, uint32 &ip, uint32 &mask, Anope::st /**** modes.cpp ****/ /* Number of generic modes we support */ E unsigned GenericChannelModes, GenericUserModes; -E Flags DefMLockOn; -E Flags DefMLockOff; -E std::map DefMLockParams; +E std::multimap def_mode_locks; E void SetDefaultMLock(ServerConfig *config); /**** nickserv.c ****/ diff --git a/include/language.h b/include/language.h index 0b1c60f2c..634b840dd 100644 --- a/include/language.h +++ b/include/language.h @@ -274,7 +274,6 @@ enum LanguageString CHAN_LEVEL_INVITE, CHAN_LEVEL_AKICK, CHAN_LEVEL_SET, - CHAN_LEVEL_CLEAR, CHAN_LEVEL_UNBAN, CHAN_LEVEL_OPDEOP, CHAN_LEVEL_ACCESS_LIST, @@ -300,6 +299,7 @@ enum LanguageString CHAN_LEVEL_BANME, CHAN_LEVEL_BAN, CHAN_LEVEL_TOPIC, + CHAN_LEVEL_MODE, CHAN_LEVEL_INFO, CHAN_LEVEL_AUTOOWNER, CHAN_LEVEL_OWNER, @@ -555,13 +555,8 @@ enum LanguageString CHAN_UNBANNED, CHAN_UNBANNED_OTHER, CHAN_TOPIC_SYNTAX, - CHAN_CLEAR_SYNTAX, - CHAN_CLEARED_BANS, - CHAN_CLEARED_EXCEPTS, - CHAN_CLEARED_MODES, - CHAN_CLEARED_OPS, + CHAN_CLEARUSERS_SYNTAX, CHAN_CLEARED_USERS, - CHAN_CLEARED_INVITES, CHAN_CLONED, CHAN_CLONED_ACCESS, CHAN_CLONED_AKICK, @@ -597,6 +592,15 @@ enum LanguageString CHAN_DEOWNER_SYNTAX, CHAN_KICK_SYNTAX, CHAN_BAN_SYNTAX, + CHAN_MODE_SYNTAX, + CHAN_MODE_LOCK_UNKNOWN, + CHAN_MODE_LOCK_MISSING_PARAM, + CHAN_MODE_LOCK_NONE, + CHAN_MODE_LOCK_HEADER, + CHAN_MODE_LOCKED, + CHAN_MODE_NOT_LOCKED, + CHAN_MODE_UNLOCKED, + CHAN_MODE_LIST_FMT, MEMO_HAVE_NEW_MEMO, MEMO_HAVE_NEW_MEMOS, MEMO_TYPE_READ_LAST, @@ -931,9 +935,6 @@ enum LanguageString OPER_OLINE_SYNTAX, OPER_OLINE_SUCCESS, OPER_OLINE_IRCOP, - OPER_CLEARMODES_SYNTAX, - OPER_CLEARMODES_DONE, - OPER_CLEARMODES_ALL_DONE, OPER_KICK_SYNTAX, OPER_SVSNICK_SYNTAX, OPER_SVSNICK_NEWNICK, @@ -1266,7 +1267,7 @@ enum LanguageString CHAN_HELP_CMD_AKICK, CHAN_HELP_CMD_DROP, CHAN_HELP_CMD_BAN, - CHAN_HELP_CMD_CLEAR, + CHAN_HELP_CMD_CLEARUSERS, CHAN_HELP_CMD_DEVOICE, CHAN_HELP_CMD_GETKEY, CHAN_HELP_CMD_INFO, @@ -1287,6 +1288,7 @@ enum LanguageString CHAN_HELP_CMD_PROTECT, CHAN_HELP_CMD_DEOP, CHAN_HELP_CMD_CLONE, + CHAN_HELP_CMD_MODE, CHAN_HELP, CHAN_HELP_EXPIRES, CHAN_HELP_REGISTER, @@ -1358,9 +1360,10 @@ enum LanguageString CHAN_HELP_KICK, CHAN_HELP_BAN, CHAN_HELP_TOPIC, - CHAN_HELP_CLEAR, + CHAN_HELP_CLEARUSERS, CHAN_HELP_GETKEY, CHAN_HELP_CLONE, + CHAN_HELP_MODE, CHAN_SERVADMIN_HELP, CHAN_SERVADMIN_HELP_DROP, CHAN_SERVADMIN_HELP_SET_NOEXPIRE, @@ -1403,7 +1406,6 @@ enum LanguageString OPER_HELP_CMD_STAFF, OPER_HELP_CMD_MODE, OPER_HELP_CMD_KICK, - OPER_HELP_CMD_CLEARMODES, OPER_HELP_CMD_AKILL, OPER_HELP_CMD_SNLINE, OPER_HELP_CMD_SQLINE, @@ -1442,7 +1444,6 @@ enum LanguageString OPER_HELP_MODE, OPER_HELP_UMODE, OPER_HELP_OLINE, - OPER_HELP_CLEARMODES, OPER_HELP_KICK, OPER_HELP_SVSNICK, OPER_HELP_AKILL, diff --git a/include/modes.h b/include/modes.h index 299d1a2db..ce0281cd0 100644 --- a/include/modes.h +++ b/include/modes.h @@ -185,17 +185,17 @@ class CoreExport ChannelModeList : public ChannelMode */ virtual bool IsValid(const Anope::string &mask) const { return true; } - /** Add the mask to the channel, this should be overridden + /** Called when a mask is added to a channel * @param chan The channel * @param mask The mask */ - virtual void AddMask(Channel *chan, const Anope::string &mask) { } + virtual void OnAdd(Channel *chan, const Anope::string &mask) { } - /** Delete the mask from the channel, this should be overridden + /** Called when a mask is removed from a channel * @param chan The channel * @param mask The mask */ - virtual void DelMask(Channel *chan, const Anope::string &mask) { } + virtual void OnDel(Channel *chan, const Anope::string &mask) { } }; @@ -254,9 +254,9 @@ class CoreExport ChannelModeBan : public ChannelModeList public: ChannelModeBan(char modeChar) : ChannelModeList(CMODE_BAN, "CMODE_BAN", modeChar) { } - void AddMask(Channel *chan, const Anope::string &mask); + void OnAdd(Channel *chan, const Anope::string &mask); - void DelMask(Channel *chan, const Anope::string &mask); + void OnDel(Channel *chan, const Anope::string &mask); }; /** Channel mode +e @@ -266,9 +266,9 @@ class CoreExport ChannelModeExcept : public ChannelModeList public: ChannelModeExcept(char modeChar) : ChannelModeList(CMODE_EXCEPT, "CMODE_EXCEPT", modeChar) { } - void AddMask(Channel *chan, const Anope::string &mask); + void OnAdd(Channel *chan, const Anope::string &mask); - void DelMask(Channel *chan, const Anope::string &mask); + void OnDel(Channel *chan, const Anope::string &mask); }; /** Channel mode +I @@ -278,9 +278,9 @@ class CoreExport ChannelModeInvex : public ChannelModeList public: ChannelModeInvex(char modeChar) : ChannelModeList(CMODE_INVITEOVERRIDE, "CMODE_INVITEOVERRIDE", modeChar) { } - void AddMask(Channel *chan, const Anope::string &mask); + void OnAdd(Channel *chan, const Anope::string &mask); - void DelMask(Channel *chan, const Anope::string &mask); + void OnDel(Channel *chan, const Anope::string &mask); }; diff --git a/include/modules.h b/include/modules.h index 481b5180b..be5c14447 100644 --- a/include/modules.h +++ b/include/modules.h @@ -991,20 +991,18 @@ class CoreExport Module : public Extensible virtual void OnUserModeAdd(UserMode *um) { } /** Called when a mode is about to be mlocked - * @param ci The channel - * @param Name The mode being mlocked - * @param status true if its being mlocked +, false for - - * @param param The param, if there is one and if status is true + * @param ci The channel the mode is being locked on + * @param lock The mode lock * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock. */ - virtual EventReturn OnMLock(ChannelInfo *ci, ChannelModeName Name, bool status, const Anope::string ¶m) { return EVENT_CONTINUE; } + virtual EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) { return EVENT_CONTINUE; } /** Called when a mode is about to be unlocked - * @param ci The channel - * @param Name The mode being mlocked + * @param ci The channel the mode is being unlocked from + * @param mode The mode being unlocked * @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock. */ - virtual EventReturn OnUnMLock(ChannelInfo *ci, ChannelModeName Name) { return EVENT_CONTINUE; } + virtual EventReturn OnUnMLock(ChannelInfo *ci, ChannelMode *mode, const Anope::string ¶m) { return EVENT_CONTINUE; } /** Called after a module is loaded * @param u The user loading the module, can be NULL diff --git a/include/regchannel.h b/include/regchannel.h index 1300b9cf4..dd47a88fc 100644 --- a/include/regchannel.h +++ b/include/regchannel.h @@ -62,15 +62,26 @@ enum ChannelInfoFlag CI_END }; +struct ModeLock +{ + bool set; + ChannelModeName name; + Anope::string param; + Anope::string setter; + time_t created; + + ModeLock(bool s, ChannelModeName n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime) : set(s), name(n), param(p), setter(se), created(c) { } +}; + class CoreExport ChannelInfo : public Extensible, public Flags { private: - std::map Params; /* Map of parameters by mode name for mlock */ + typedef std::multimap ModeList; + private: std::vector access; /* List of authorized users */ std::vector akick; /* List of users to kickban */ std::vector badwords; /* List of badwords */ - Flags mlock_on; /* Modes mlocked on */ - Flags mlock_off; /* Modes mlocked off */ + ModeList mode_locks; public: /** Default constructor @@ -241,51 +252,51 @@ class CoreExport ChannelInfo : public Extensible, public Flags &GetMLock() const; - /** Check if a mode is set and has a param - * @param Name The mode + /** Get a list of modes on a channel + * @param Name The mode name to get a list of + * @return a pair of iterators for the beginning and end of the list */ - bool HasParam(ChannelModeName Name) const; + std::pair GetModeList(ChannelModeName Name); - /** Clear all the params from the channel + /** Get details for a specific mlock + * @param name The mode name + * @param An optional param to match with + * @return The MLock, if any */ - void ClearParams(); + ModeLock *GetMLock(ChannelModeName name, const Anope::string ¶m = ""); /** Check whether a user is permitted to be on this channel * @param u The user diff --git a/include/services.h b/include/services.h index 38abf931f..4d2401883 100644 --- a/include/services.h +++ b/include/services.h @@ -453,9 +453,6 @@ struct IRCDVar int svsmode_ucmode; /* Can remove User Channel Modes with SVSMODE */ int sglineenforce; int ts6; /* ircd is TS6 */ - int cidrchanbei; /* channel bans/excepts/invites support CIDR (syntax: +b *!*@192.168.0.0/15) - * 0 for no support, 1 for strict cidr support, anything else - * for ircd specific support (nefarious only cares about first /mask) */ const char *globaltldprefix; /* TLD prefix used for Global */ unsigned maxmodes; /* Max modes to send per line */ }; @@ -636,7 +633,6 @@ enum ChannelAccess CA_AUTOVOICE, CA_OPDEOP, /* ChanServ commands OP and DEOP */ CA_ACCESS_LIST, - CA_CLEAR, CA_NOJOIN, /* Maximum */ CA_ACCESS_CHANGE, CA_MEMO, @@ -662,6 +658,7 @@ enum ChannelAccess CA_BANME, CA_BAN, CA_TOPIC, + CA_MODE, CA_INFO, CA_AUTOOWNER, CA_OWNER, @@ -756,7 +753,7 @@ struct LevelInfo enum EntryType { ENTRYTYPE_NONE, - ENTRYTYPE_CIDR4, + ENTRYTYPE_CIDR, ENTRYTYPE_NICK_WILD, ENTRYTYPE_NICK, ENTRYTYPE_USER_WILD, @@ -767,17 +764,27 @@ enum EntryType class Entry : public Flags { + Anope::string mask; + public: - Entry *next, *prev; - uint32 cidr_ip; /* IP mask for CIDR matching */ - uint32 cidr_mask; /* Netmask for CIDR matching */ - Anope::string nick, user, host, mask; -}; + unsigned char cidr_len; + Anope::string nick, user, host; -struct EList -{ - Entry *entries; - int32 count; + /** Constructor + * @param _host A full nick!ident@host/cidr mask + */ + Entry(const Anope::string &_host); + + /** Get the banned mask for this entry + * @return The mask + */ + const Anope::string GetMask(); + + /** Check if this entry matches a user + * @param u The user + * @return true on match + */ + bool Matches(User *u) const; }; /*************************************************************************/ diff --git a/include/sockets.h b/include/sockets.h index a24e346d7..c9e5bfed0 100644 --- a/include/sockets.h +++ b/include/sockets.h @@ -80,6 +80,18 @@ union CoreExport sockaddrs void ntop(int type, const void *src); }; +class CoreExport cidr +{ + sockaddrs addr; + Anope::string cidr_ip; + unsigned char cidr_len; + public: + cidr(const Anope::string &ip); + cidr(const Anope::string &ip, unsigned char len); + Anope::string mask() const; + bool match(sockaddrs &other); +}; + class SocketException : public CoreException { public: diff --git a/include/users.h b/include/users.h index 6aed13548..d9f47792f 100644 --- a/include/users.h +++ b/include/users.h @@ -139,6 +139,10 @@ class CoreExport User : public Extensible */ Anope::string GetMask() const; + /** Get the full display mask (nick!vident@vhost/chost) + */ + Anope::string GetDisplayedMask() const; + /** Updates the realname of the user record. */ void SetRealname(const Anope::string &realname); diff --git a/modules/core/cs_clearusers.cpp b/modules/core/cs_clearusers.cpp index 55c6f684e..028c7e5d6 100644 --- a/modules/core/cs_clearusers.cpp +++ b/modules/core/cs_clearusers.cpp @@ -28,15 +28,9 @@ class CommandCSClearUsers : public Command ChannelInfo *ci = c ? c->ci : NULL; Anope::string modebuf; - ChannelMode *owner = ModeManager::FindChannelModeByName(CMODE_OWNER); - ChannelMode *admin = ModeManager::FindChannelModeByName(CMODE_PROTECT); - ChannelMode *op = ModeManager::FindChannelModeByName(CMODE_OP); - ChannelMode *halfop = ModeManager::FindChannelModeByName(CMODE_HALFOP); - ChannelMode *voice = ModeManager::FindChannelModeByName(CMODE_VOICE); - if (!c) u->SendMessage(ChanServ, CHAN_X_NOT_IN_USE, chan.c_str()); - else if (!check_access(u, ci, CA_CLEAR)) + else if (!check_access(u, ci, CA_FOUNDER)) u->SendMessage(ChanServ, ACCESS_DENIED); Anope::string buf = "CLEAR USERS command from " + u->nick + " (" + u->Account()->display + ")"; @@ -55,18 +49,18 @@ class CommandCSClearUsers : public Command bool OnHelp(User *u, const Anope::string &subcommand) { - u->SendMessage(ChanServ, CHAN_HELP_CLEAR); + u->SendMessage(ChanServ, CHAN_HELP_CLEARUSERS); return true; } void OnSyntaxError(User *u, const Anope::string &subcommand) { - SyntaxError(ChanServ, u, "CLEAR", CHAN_CLEAR_SYNTAX); + SyntaxError(ChanServ, u, "CLEAR", CHAN_CLEARUSERS_SYNTAX); } void OnServHelp(User *u) { - u->SendMessage(ChanServ, CHAN_HELP_CMD_CLEAR); + u->SendMessage(ChanServ, CHAN_HELP_CMD_CLEARUSERS); } }; diff --git a/modules/core/cs_forbid.cpp b/modules/core/cs_forbid.cpp index ef55439b2..25fd90868 100644 --- a/modules/core/cs_forbid.cpp +++ b/modules/core/cs_forbid.cpp @@ -63,12 +63,16 @@ class CommandCSForbid : public Command ci->forbidby = u->nick; ci->forbidreason = reason; - if ((c = findchan(ci->name))) + if ((c = ci->c)) { /* Before banning everyone, it might be prudent to clear +e and +I lists.. * to prevent ppl from rejoining.. ~ Viper */ - c->ClearExcepts(); - c->ClearInvites(); + std::pair modes = c->GetModeList(CMODE_EXCEPT); + for (; modes.first != modes.second; ++modes.first) + c->RemoveMode(NULL, CMODE_EXCEPT, modes.first->second); + modes = c->GetModeList(CMODE_INVITEOVERRIDE); + for (; modes.first != modes.second; ++modes.first) + c->RemoveMode(NULL, CMODE_INVITEOVERRIDE, modes.first->second); for (CUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ) { diff --git a/modules/core/cs_info.cpp b/modules/core/cs_info.cpp index d9c507505..0df02ff43 100644 --- a/modules/core/cs_info.cpp +++ b/modules/core/cs_info.cpp @@ -66,7 +66,8 @@ class CommandCSInfo : public Command u->SendMessage(ChanServ, CHAN_INFO_TIME_REGGED, do_strftime(ci->time_registered).c_str()); u->SendMessage(ChanServ, CHAN_INFO_LAST_USED, do_strftime(ci->last_used).c_str()); - if (!ci->last_topic.empty() && (show_all || (!ci->HasMLock(CMODE_SECRET, true) && (!ci->c || !ci->c->HasMode(CMODE_SECRET))))) + ModeLock *secret = ci->GetMLock(CMODE_SECRET); + if (!ci->last_topic.empty() && (show_all || ((!secret || secret->set == false) && (!ci->c || !ci->c->HasMode(CMODE_SECRET))))) { u->SendMessage(ChanServ, CHAN_INFO_LAST_TOPIC, ci->last_topic.c_str()); u->SendMessage(ChanServ, CHAN_INFO_TOPIC_SET_BY, ci->last_topic_setter.c_str()); diff --git a/modules/core/cs_mode.cpp b/modules/core/cs_mode.cpp new file mode 100644 index 000000000..e92a76988 --- /dev/null +++ b/modules/core/cs_mode.cpp @@ -0,0 +1,306 @@ +/* ChanServ core functions + * + * (C) 2003-2010 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" + +class CommandCSMode : public Command +{ + void DoLock(User *u, ChannelInfo *ci, const std::vector ¶ms) + { + const Anope::string &subcommand = params[2]; + const Anope::string ¶m = params.size() > 3 ? params[3] : ""; + + if (subcommand.equals_ci("ADD") && !param.empty()) + { + spacesepstream sep(param); + Anope::string modes; + + sep.GetToken(modes); + + int adding = -1; + for (size_t i = 0; i < modes.length(); ++i) + { + switch (modes[i]) + { + case '+': + adding = 1; + break; + case '-': + adding = 0; + break; + default: + if (adding == -1) + break; + ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); + if (!cm || !cm->CanSet(u)) + { + u->SendMessage(ChanServ, CHAN_MODE_LOCK_UNKNOWN, modes[i]); + break; + } + Anope::string mode_param; + if (((cm->Type == MODE_STATUS || cm->Type == MODE_LIST) && !sep.GetToken(mode_param)) || (cm->Type == MODE_PARAM && adding && !sep.GetToken(mode_param))) + u->SendMessage(ChanServ, CHAN_MODE_LOCK_MISSING_PARAM, cm->ModeChar); + else + { + ci->SetMLock(cm, adding, mode_param, u->nick); + if (!mode_param.empty()) + mode_param = " " + mode_param; + u->SendMessage(ChanServ, CHAN_MODE_LOCKED, adding ? '+' : '-', cm->ModeChar, mode_param.c_str(), ci->name.c_str()); + } + } + } + + if (ci->c) + check_modes(ci->c); + } + else if (subcommand.equals_ci("DEL") && !param.empty()) + { + spacesepstream sep(param); + Anope::string modes; + + sep.GetToken(modes); + + int adding = -1; + for (size_t i = 0; i < modes.length(); ++i) + { + switch (modes[i]) + { + case '+': + adding = 1; + break; + case '-': + adding = 0; + break; + default: + if (adding == -1) + break; + ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); + if (!cm || !cm->CanSet(u)) + { + u->SendMessage(ChanServ, CHAN_MODE_LOCK_UNKNOWN, modes[i]); + break; + } + Anope::string mode_param; + if (!cm->Type == MODE_REGULAR && !sep.GetToken(mode_param)) + u->SendMessage(ChanServ, CHAN_MODE_LOCK_MISSING_PARAM, cm->ModeChar); + else + { + if (ci->RemoveMLock(cm, mode_param)) + { + if (!mode_param.empty()) + mode_param = " " + mode_param; + u->SendMessage(ChanServ, CHAN_MODE_UNLOCKED, adding == 1 ? '+' : '-', cm->ModeChar, mode_param.c_str(), ci->name.c_str()); + } + else + u->SendMessage(ChanServ, CHAN_MODE_NOT_LOCKED, cm->ModeChar, ci->name.c_str()); + } + } + } + } + else if (subcommand.equals_ci("LIST")) + { + const std::multimap &mlocks = ci->GetMLock(); + if (mlocks.empty()) + { + u->SendMessage(ChanServ, CHAN_MODE_LOCK_NONE, ci->name.c_str()); + } + else + { + u->SendMessage(ChanServ, CHAN_MODE_LOCK_HEADER, ci->name.c_str()); + for (std::multimap::const_iterator it = mlocks.begin(), it_end = mlocks.end(); it != it_end; ++it) + { + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm) + continue; + + Anope::string modeparam = ml.param; + if (!modeparam.empty()) + modeparam = " " + modeparam; + Anope::string setter = ml.setter; + if (setter.empty()) + setter = ci->founder ? ci->founder->display : "Unknown"; + u->SendMessage(ChanServ, CHAN_MODE_LIST_FMT, ml.set ? '+' : '-', cm->ModeChar, modeparam.c_str(), setter.c_str(), do_strftime(ml.created).c_str()); + } + } + } + else + this->OnSyntaxError(u, subcommand); + } + + void DoSet(User *u, ChannelInfo *ci, const std::vector ¶ms) + { + spacesepstream sep(params.size() > 3 ? params[3] : ""); + Anope::string modes = params[2], param; + + Log(LOG_COMMAND, u, this, ci) << "to set " << params[2]; + + int adding = -1; + for (size_t i = 0; i < modes.length(); ++i) + { + switch (modes[i]) + { + case '+': + adding = 1; + break; + case '-': + adding = 0; + break; + case '*': + if (adding == -1) + break; + for (std::map::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it) + { + Mode *m = it->second; + if (m->Class == MC_CHANNEL) + { + ChannelMode *cm = debug_cast(m); + if (cm->Type == MODE_REGULAR || (!adding && cm->Type == MODE_PARAM)) + { + if (!cm->CanSet(u)) + continue; + if (adding) + ci->c->SetMode(NULL, cm); + else + ci->c->RemoveMode(NULL, cm); + } + } + } + break; + default: + if (adding == -1) + break; + ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]); + if (!cm || !cm->CanSet(u)) + continue; + switch (cm->Type) + { + case MODE_REGULAR: + if (adding) + ci->c->SetMode(NULL, cm); + else + ci->c->RemoveMode(NULL, cm); + break; + case MODE_PARAM: + if (adding && !sep.GetToken(param)) + break; + if (adding) + ci->c->SetMode(NULL, cm, param); + else + ci->c->RemoveMode(NULL, cm); + break; + case MODE_STATUS: + if (!sep.GetToken(param)) + break; + if (str_is_wildcard(param)) + { + for (CUserList::const_iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it) + { + UserContainer *uc = *it; + + if (Anope::Match(u->GetMask(), param)) + { + if (adding) + ci->c->SetMode(NULL, cm, uc->user->nick); + else + ci->c->RemoveMode(NULL, cm, uc->user->nick); + } + } + } + else + { + if (adding) + ci->c->SetMode(NULL, cm, param); + else + ci->c->RemoveMode(NULL, cm, param); + } + break; + case MODE_LIST: + if (!sep.GetToken(param)) + break; + if (adding) + ci->c->SetMode(NULL, cm, param); + else + { + std::pair its = ci->c->GetModeList(cm->Name); + for (; its.first != its.second;) + { + const Anope::string &mask = its.first->second; + ++its.first; + + if (Anope::Match(mask, param)) + ci->c->RemoveMode(NULL, cm, mask); + } + } + } + } + } + } + + public: + CommandCSMode() : Command("MODE", 3, 4) + { + } + + CommandReturn Execute(User *u, const std::vector ¶ms) + { + const Anope::string &subcommand = params[1]; + + ChannelInfo *ci = cs_findchan(params[0]); + + if (!ci || !ci->c) + u->SendMessage(ChanServ, CHAN_X_NOT_IN_USE, ci->name.c_str()); + else if (!check_access(u, ci, CA_MODE) && !u->Account()->HasCommand("chanserv/mode")) + u->SendMessage(ChanServ, ACCESS_DENIED); + else if (subcommand.equals_ci("LOCK")) + this->DoLock(u, ci, params); + else if (subcommand.equals_ci("SET")) + this->DoSet(u, ci, params); + else + this->OnSyntaxError(u, ""); + + return MOD_CONT; + } + + bool OnHelp(User *u, const Anope::string &subcommand) + { + u->SendMessage(ChanServ, CHAN_HELP_MODE); + return true; + } + + void OnSyntaxError(User *u, const Anope::string &subcommand) + { + SyntaxError(ChanServ, u, "MODE", CHAN_MODE_SYNTAX); + } + + void OnServHelp(User *u) + { + u->SendMessage(ChanServ, CHAN_HELP_CMD_MODE); + } +}; + +class CSMode : public Module +{ + CommandCSMode commandcsmode; + + public: + CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator) + { + this->SetAuthor("Anope"); + this->SetType(CORE); + + this->AddCommand(ChanServ, &commandcsmode); + } +}; + +MODULE_INIT(CSMode) diff --git a/modules/core/cs_set.cpp b/modules/core/cs_set.cpp index 04721cab8..e9774ba42 100644 --- a/modules/core/cs_set.cpp +++ b/modules/core/cs_set.cpp @@ -44,7 +44,7 @@ class CommandCSSet : public Command // XXX Remove after 1.9.4 release if (params[1].equals_ci("MLOCK")) { - u->SendMessage(ChanServ, CHAN_SET_MLOCK_DEPRECATED); + u->SendMessage(ChanServ, CHAN_SET_MLOCK_DEPRECATED, Config->s_ChanServ.c_str()); return MOD_CONT; } diff --git a/modules/core/cs_set_persist.cpp b/modules/core/cs_set_persist.cpp index bee71f95e..1a567ef83 100644 --- a/modules/core/cs_set_persist.cpp +++ b/modules/core/cs_set_persist.cpp @@ -61,7 +61,7 @@ class CommandCSSetPersist : public Command if (ci->c && !ci->c->HasMode(CMODE_PERM)) ci->c->SetMode(NULL, cm); /* Add it to the channels mlock */ - ci->SetMLock(CMODE_PERM, true); + ci->SetMLock(cm, true); } } @@ -81,7 +81,7 @@ class CommandCSSetPersist : public Command if (ci->c && ci->c->HasMode(CMODE_PERM)) ci->c->RemoveMode(NULL, cm); /* Remove from mlock */ - ci->RemoveMLock(CMODE_PERM); + ci->RemoveMLock(cm); } /* No channel mode, no BotServ, but using ChanServ as the botserv bot diff --git a/modules/core/db_plain.cpp b/modules/core/db_plain.cpp index d6f7963d5..5db485fc8 100644 --- a/modules/core/db_plain.cpp +++ b/modules/core/db_plain.cpp @@ -258,7 +258,6 @@ ChannelLevel ChannelLevels[] = { {"AUTOVOICE", CA_AUTOVOICE}, {"OPDEOP", CA_OPDEOP}, {"ACCESS_LIST", CA_ACCESS_LIST}, - {"CLEAR", CA_CLEAR}, {"NOJOIN", CA_NOJOIN}, {"ACCESS_CHANGE", CA_ACCESS_CHANGE}, {"MEMO", CA_MEMO}, @@ -749,6 +748,16 @@ class DBPlain : public Module /* For now store mlocked modes in extensible, Anope hasn't yet connected to the IRCd and doesn't know what modes exist */ ci->Extend("db_mlp", new ExtensibleItemRegular > >(mlp)); } + else if (key.equals_ci("MLP_OFF")) + { + std::vector > mlp; + ci->GetExtRegular("db_mlp_off", mlp); + + mlp.push_back(std::make_pair(params[0], params[1])); + + /* For now store mlocked modes in extensible, Anope hasn't yet connected to the IRCd and doesn't know what modes exist */ + ci->Extend("db_mlp_off", new ExtensibleItemRegular > >(mlp)); + } else if (key.equals_ci("MI")) { Memo *m = new Memo; @@ -972,30 +981,29 @@ class DBPlain : public Module db << ci->GetAkick(k)->reason; db << endl; } - if (ci->GetMLockCount(true)) + db << "MD MLOCK_ON"; { - db << "MD MLOCK_ON"; - Anope::string oldmodes; if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlock_modes_on", oldmodes)) - { db << " " << oldmodes; - } else { - for (std::map::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + for (std::map::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - ChannelMode *cm = it->second; - if (ci->HasMLock(cm->Name, true)) + const ModeLock &ml = it->second; + if (ml.set) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm || cm->Type != MODE_REGULAR) + continue; db << " " << cm->NameAsString; + } } } - db << endl; } - if (ci->GetMLockCount(false)) + db << endl; + db << "MD MLOCK_OFF"; { - db << "MD MLOCK_OFF"; - Anope::string oldmodes; if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlock_modes_off", oldmodes)) { @@ -1003,32 +1011,41 @@ class DBPlain : public Module } else { - for (std::map::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + for (std::map::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - ChannelMode *cm = it->second; - if (ci->HasMLock(cm->Name, false)) + const ModeLock &ml = it->second; + if (!ml.set) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm || cm->Type != MODE_REGULAR) + continue; db << " " << cm->NameAsString; + } } } - db << endl; } - std::vector > oldparams;; - if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlp", oldparams)) + db << endl; { - for (std::vector >::iterator it = oldparams.begin(), it_end = oldparams.end(); it != it_end; ++it) + std::vector > oldparams;; + if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlp", oldparams)) { - db << "MD MLP " << it->first << " " << it->second << endl; + for (std::vector >::iterator it = oldparams.begin(), it_end = oldparams.end(); it != it_end; ++it) + { + db << "MD MLP " << it->first << " " << it->second << endl; + } } - } - else - { - for (std::map::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + else { - ChannelMode *cm = it->second; - Anope::string Param; + for (std::map::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) + { + const ModeLock &ml = it->second; + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm) + continue; - if (ci->GetParam(cm->Name, Param)) - db << "MD MLP " << cm->NameAsString << " " << Param << endl; + if (!ml.param.empty()) + db << "MD MLP" << (ml.set ? " " : "_OFF ") << cm->NameAsString << " " << ml.param << endl; + } } } MemoInfo *memos = &ci->memos; diff --git a/modules/core/os_defcon.cpp b/modules/core/os_defcon.cpp index e17a6d33a..cfc8ebe62 100644 --- a/modules/core/os_defcon.cpp +++ b/modules/core/os_defcon.cpp @@ -207,7 +207,7 @@ class OSDefcon : public Module EventReturn OnPreCommandRun(User *u, BotInfo *bi, Anope::string &command, Anope::string &message, bool fantasy) { - if (!is_oper(u) && CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY)) + if (!is_oper(u) && (CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY))) { if (!CheckDefCon(DEFCON_SILENT_OPER_ONLY)) u->SendMessage(bi, OPER_DEFCON_DENIED); diff --git a/modules/extra/db_mysql.cpp b/modules/extra/db_mysql.cpp index 147a35229..e49676658 100644 --- a/modules/extra/db_mysql.cpp +++ b/modules/extra/db_mysql.cpp @@ -203,11 +203,16 @@ static Anope::string MakeMLock(ChannelInfo *ci, bool status) ; else { - for (std::map::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + for (std::map::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - ChannelMode *cm = it->second; - if (ci->HasMLock(cm->Name, status)) + const ModeLock &ml = it->second; + if (ml.set == status) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (!cm || cm->Type != MODE_REGULAR) + continue; ret += " " + cm->NameAsString; + } } if (!ret.empty()) @@ -227,12 +232,12 @@ static inline Anope::string GetMLockOff(ChannelInfo *ci) return MakeMLock(ci, false); } -static Anope::string GetMLockParams(ChannelInfo *ci) +static Anope::string GetMLockParams(ChannelInfo *ci, bool onoff) { Anope::string ret; std::vector > oldparams;; - if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlp", oldparams)) + if ((!Me || !Me->IsSynced()) && ci->GetExtRegular(onoff ? "db_mlp" : "db_mlp_off", oldparams)) { for (std::vector >::iterator it = oldparams.begin(), it_end = oldparams.end(); it != it_end; ++it) { @@ -241,13 +246,16 @@ static Anope::string GetMLockParams(ChannelInfo *ci) } else { - for (std::map::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it) + for (std::map::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it) { - ChannelMode *cm = it->second; + const ModeLock &ml = it->second; - Anope::string param; - if (ci->GetParam(cm->Name, param)) - ret += " " + cm->NameAsString + " " + param; + if (!ml.param.empty() && ml.set == onoff) + { + ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name); + if (cm) + ret += " " + cm->NameAsString + " " + ml.param; + } } } @@ -661,10 +669,21 @@ class DBMySQL : public Module spacesepstream sep(r.Get(i, "mlock_params")); Anope::string buf, buf2; while (sep.GetToken(buf) && sep.GetToken(buf2)) - mlp.push_back(std::make_pair(Anope::string(buf), Anope::string(buf2))); + mlp.push_back(std::make_pair(buf, buf2)); ci->Extend("db_mlp", new ExtensibleItemRegular > >(mlp)); } + if (!r.Get(i, "mlock_params_off").empty()) + { + std::vector > mlp; + + spacesepstream sep(r.Get(i, "mlock_params_off")); + Anope::string buf, buf2; + while (sep.GetToken(buf) && sep.GetToken(buf2)) + mlp.push_back(std::make_pair(buf, buf2)); + + ci->Extend("db_mlp_off", new ExtensibleItemRegular > >(mlp)); + } if (!r.Get(i, "flags").empty()) { @@ -1022,7 +1041,8 @@ class DBMySQL : public Module { this->RunQuery("UPDATE `anope_cs_info` SET `mlock_on` = '" + GetMLockOn(ci) + "' WHERE `name` = '" + this->Escape(ci->name) + "'"); this->RunQuery("UPDATE `anope_cs_info` SET `mlock_off` = '" + GetMLockOff(ci) + "' WHERE `name` = '" + this->Escape(ci->name) + "'"); - this->RunQuery("UPDATE `anope_cs_info` SET `mlock_params` = '" + GetMLockParams(ci) + "' WHERE `name` = '" + this->Escape(ci->name) + "'"); + this->RunQuery("UPDATE `anope_cs_info` SET `mlock_params` = '" + GetMLockParams(ci, true) + "' WHERE `name` = '" + this->Escape(ci->name) + "'"); + this->RunQuery("UPDATE `anope_cs_info` SET `mlock_params_off` = '" + GetMLockParams(ci, false) + "' WHERE `name` = '" + this->Escape(ci->name) + "'"); } else if (params[1].equals_ci("BANTYPE")) { @@ -1240,14 +1260,14 @@ class DBMySQL : public Module void OnChanRegistered(ChannelInfo *ci) { - Anope::string flags = BuildFlagsList(ci), mlockon = GetMLockOn(ci), mlockoff = GetMLockOff(ci), mlockparams = GetMLockParams(ci); - this->RunQuery("INSERT INTO `anope_cs_info` (name, founder, successor, descr, time_registered, last_used, last_topic, last_topic_setter, last_topic_time, flags, forbidby, forbidreason, bantype, mlock_on, mlock_off, mlock_params, entry_message, memomax, botnick, botflags, capsmin, capspercent, floodlines, floodsecs, repeattimes) VALUES('" + + Anope::string flags = BuildFlagsList(ci), mlockon = GetMLockOn(ci), mlockoff = GetMLockOff(ci), mlockparams = GetMLockParams(ci, true), mlockparams_off = GetMLockParams(ci, false); + this->RunQuery("INSERT INTO `anope_cs_info` (name, founder, successor, descr, time_registered, last_used, last_topic, last_topic_setter, last_topic_time, flags, forbidby, forbidreason, bantype, mlock_on, mlock_off, mlock_params, mlock_params_off, entry_message, memomax, botnick, botflags, capsmin, capspercent, floodlines, floodsecs, repeattimes) VALUES('" + this->Escape(ci->name) + "', '" + this->Escape(ci->founder ? ci->founder->display : "") + "', '" + this->Escape(ci->successor ? ci->successor->display : "") + "', '" + this->Escape(ci->desc) + "', " + stringify(ci->time_registered) + ", " + stringify(ci->last_used) + ", '" + this->Escape(ci->last_topic) + "', '" + this->Escape(ci->last_topic_setter) + "', " + stringify(ci->last_topic_time) + ", '" + flags + "', '" + this->Escape(ci->forbidby) + "', '" + this->Escape(ci->forbidreason) + "', " + stringify(ci->bantype) + ", '" + - mlockon + "', '" + mlockoff + "', '" + mlockparams + "', '" + this->Escape(ci->entry_message) + "', " + + mlockon + "', '" + mlockoff + "', '" + mlockparams + "', '" + mlockparams_off + "', '" + this->Escape(ci->entry_message) + "', " + stringify(ci->memos.memomax) + ", '" + this->Escape(ci->bi ? ci->bi->nick : "") + "', '" + GetBotFlags(ci->botflags) + "', " + stringify(ci->capsmin) + ", " + stringify(ci->capspercent) + ", " + stringify(ci->floodlines) + ", " + stringify(ci->floodsecs) + ", " + stringify(ci->repeattimes) + ") " + "ON DUPLICATE KEY UPDATE founder=VALUES(founder), successor=VALUES(successor), descr=VALUES(descr), time_registered=VALUES(time_registered), last_used=VALUES(last_used), last_topic=VALUES(last_topic), last_topic_setter=VALUES(last_topic_setter), last_topic_time=VALUES(last_topic_time), flags=VALUES(flags), forbidby=VALUES(forbidby), forbidreason=VALUES(forbidreason), bantype=VALUES(bantype), mlock_on=VALUES(mlock_on), mlock_off=VALUES(mlock_off), mlock_params=VALUES(mlock_params), entry_message=VALUES(entry_message), memomax=VALUES(memomax), botnick=VALUES(botnick), botflags=VALUES(botflags), capsmin=VALUES(capsmin), capspercent=VALUES(capspercent), floodlines=VALUES(floodlines), floodsecs=VALUES(floodsecs), repeattimes=VALUES(repeattimes)"); diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 1053523b8..74b570ee2 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -174,27 +174,23 @@ class MyXMLRPCEvent : public XMLRPCEvent if (c) { - request->reply("bancount", stringify((c && c->bans ? c->bans->count : 0))); - if (c->bans && c->bans->count) - { - int i = 0; - for (Entry *entry = c->bans->entries; entry; entry = entry->next, ++i) - request->reply("ban" + stringify(i), iface->Sanitize(entry->mask)); - } - request->reply("exceptcount", stringify((c && c->excepts ? c->excepts->count : 0))); - if (c->excepts && c->excepts->count) - { - int i = 0; - for (Entry *entry = c->excepts->entries; entry; entry = entry->next, ++i) - request->reply("except" + stringify(i), iface->Sanitize(entry->mask)); - } - request->reply("invitecount", stringify((c && c->invites ? c->invites->count : 0))); - if (c->invites && c->invites->count) - { - int i = 0; - for (Entry *entry = c->invites->entries; entry; entry = entry->next, ++i) - request->reply("invite" + stringify(i), iface->Sanitize(entry->mask)); - } + request->reply("bancount", stringify(c->HasMode(CMODE_BAN))); + int count = 0; + std::pair its = c->GetModeList(CMODE_BAN); + for (; its.first != its.second; ++its.first) + request->reply("ban" + stringify(++count), iface->Sanitize(its.first->second)); + + request->reply("exceptcount", stringify(c->HasMode(CMODE_EXCEPT))); + count = 0; + its = c->GetModeList(CMODE_EXCEPT); + for (; its.first != its.second; ++its.first) + request->reply("except" + stringify(++count), iface->Sanitize(its.first->second)); + + request->reply("invitecount", stringify(c->HasMode(CMODE_INVITEOVERRIDE))); + count = 0; + its = c->GetModeList(CMODE_INVITEOVERRIDE); + for (; its.first != its.second; ++its.first) + request->reply("invite" + stringify(++count), iface->Sanitize(its.first->second)); Anope::string users; for (CUserList::const_iterator it = c->users.begin(); it != c->users.end(); ++it) diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 70dffb8ce..e2a5b2af7 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -37,7 +37,6 @@ IRCDVar myIrcd[] = { 0, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 0, /* ts6 */ - 0, /* CIDR channelbans */ "$", /* TLD Prefix for Global */ 6, /* Max number of modes we can send per line */ } diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 7d1d456ac..f7a13ad7a 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -38,7 +38,6 @@ IRCDVar myIrcd[] = { 0, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 0, /* ts6 */ - 1, /* CIDR channelbans */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ } diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index c4c5fa558..196c748cf 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -38,7 +38,6 @@ IRCDVar myIrcd[] = { 0, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 1, /* ts6 */ - 1, /* CIDR channelbans */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ } diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index ea696c15a..848590b2d 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -38,7 +38,6 @@ IRCDVar myIrcd[] = { 0, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 1, /* ts6 */ - 1, /* CIDR channelbans */ "$", /* TLD Prefix for Global */ 20, /* Max number of modes we can send per line */ } diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 9b5f02e46..0e034aa00 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -37,7 +37,6 @@ IRCDVar myIrcd[] = { 0, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 1, /* ts6 */ - 0, /* CIDR channelbans */ "$$", /* TLD Prefix for Global */ 4, /* Max number of modes we can send per line */ } @@ -626,26 +625,20 @@ bool event_bmask(const Anope::string &source, const std::vector & if (c) { + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); Anope::string bans = params[3]; int count = myNumToken(bans, ' '), i; for (i = 0; i <= count - 1; ++i) { Anope::string b = myStrGetToken(bans, ' ', i); - if (params[2].equals_cs("b")) - { - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByChar('b')); - cml->AddMask(c, b); - } - else if (params[2].equals_cs("e")) - { - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByChar('e')); - cml->AddMask(c, b); - } - if (params[2].equals_cs("I")) - { - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByChar('I')); - cml->AddMask(c, b); - } + if (ban && params[2].equals_cs("b")) + c->SetModeInternal(ban, b); + else if (except && params[2].equals_cs("e")) + c->SetModeInternal(except, b); + if (invex && params[2].equals_cs("I")) + c->SetModeInternal(invex, b); } } return true; diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp index 074bd5f62..70e03cf55 100644 --- a/modules/protocol/unreal32.cpp +++ b/modules/protocol/unreal32.cpp @@ -37,7 +37,6 @@ IRCDVar myIrcd[] = { 1, /* Can remove User Channel Modes with SVSMODE */ 0, /* Sglines are not enforced until user reconnects */ 0, /* ts6 */ - 0, /* CIDR channelbans */ "$", /* TLD Prefix for Global */ 12, /* Max number of modes we can send per line */ } @@ -986,36 +985,30 @@ bool event_sjoin(const Anope::string &source, const std::vector & c->SetModesInternal(NULL, modes); } + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); spacesepstream sep(params[params.size() - 1]); Anope::string buf; while (sep.GetToken(buf)) { /* Ban */ - if (keep_their_modes && buf[0] == '&') + if (keep_their_modes && ban && buf[0] == '&') { buf.erase(buf.begin()); - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByName(CMODE_BAN)); - - if (cml->IsValid(buf)) - cml->AddMask(c, buf); + c->SetModeInternal(ban, buf); } /* Except */ - else if (keep_their_modes && buf[0] == '"') + else if (keep_their_modes && except && buf[0] == '"') { buf.erase(buf.begin()); - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByName(CMODE_EXCEPT)); - - if (cml->IsValid(buf)) - cml->AddMask(c, buf); + c->SetModeInternal(except, buf); } /* Invex */ - else if (keep_their_modes && buf[0] == '\'') + else if (keep_their_modes && invex && buf[0] == '\'') { buf.erase(buf.begin()); - ChannelModeList *cml = debug_cast(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE)); - - if (cml->IsValid(buf)) - cml->AddMask(c, buf); + c->SetModeInternal(invex, buf); } else { diff --git a/src/actions.cpp b/src/actions.cpp index 4bb3563e5..6b3a96a24 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -71,28 +71,29 @@ void kill_user(const Anope::string &source, const Anope::string &user, const Ano */ void common_unban(ChannelInfo *ci, const Anope::string &nick) { - //uint32 ip = 0; - User *u; - Entry *ban, *next; - if (!ci || !ci->c || nick.empty()) return; - if (!(u = finduser(nick))) + User *u = finduser(nick); + if (!u) return; - if (!ci->c->bans || !ci->c->bans->count) + if (!ci->c->HasMode(CMODE_BAN)) return; if (ircd->svsmode_unban) ircdproto->SendBanDel(ci->c, nick); else - for (ban = ci->c->bans->entries; ban; ban = next) + { + std::pair bans = ci->c->GetModeList(CMODE_BAN); + for (; bans.first != bans.second;) { - next = ban->next; - if (entry_match(ban, u->nick, u->GetIdent(), u->host, /*ip XXX */ 0) || entry_match(ban, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX */0)) - ci->c->RemoveMode(NULL, CMODE_BAN, ban->mask); + Entry ban(bans.first->second); + ++bans.first; + if (ban.Matches(u)) + ci->c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); } + } } /*************************************************************************/ diff --git a/src/bots.cpp b/src/bots.cpp index 9b2cfddb6..3d57afe6e 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -141,28 +141,24 @@ void BotInfo::Join(Channel *c, bool update_ts) { if (Config->BSSmartJoin) { + std::pair bans = c->GetModeList(CMODE_BAN); + /* We check for bans */ - if (c->bans && c->bans->count) + for (; bans.first != bans.second; ++bans.first) { - Entry *ban, *next; - - for (ban = c->bans->entries; ban; ban = next) - { - next = ban->next; - - if (entry_match(ban, this->nick, this->GetIdent(), this->host, 0)) - c->RemoveMode(NULL, CMODE_BAN, ban->mask); - } + Entry ban(bans.first->second); + if (ban.Matches(this)) + c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); + } - Anope::string Limit; - unsigned limit = 0; - if (c->GetParam(CMODE_LIMIT, Limit) && Limit.is_pos_number_only()) - limit = convertTo(Limit); + Anope::string Limit; + unsigned limit = 0; + if (c->GetParam(CMODE_LIMIT, Limit) && Limit.is_pos_number_only()) + limit = convertTo(Limit); - /* Should we be invited? */ - if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit)) - ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); - } + /* Should we be invited? */ + if (c->HasMode(CMODE_INVITE) || (limit && c->users.size() >= limit)) + ircdproto->SendNoticeChanops(this, c, "%s invited %s into the channel.", this->nick.c_str(), this->nick.c_str()); ModeManager::ProcessModes(); } diff --git a/src/channels.cpp b/src/channels.cpp index 72e573029..27d804c18 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -28,7 +28,6 @@ Channel::Channel(const Anope::string &nname, time_t ts) ChannelList[this->name] = this; this->creation_time = ts; - this->bans = this->excepts = this->invites = NULL; this->server_modetime = this->chanserv_modetime = 0; this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_time = 0; @@ -57,27 +56,12 @@ Channel::~Channel() if (this->ci) this->ci->c = NULL; - if (this->bans && this->bans->count) - while (this->bans->entries) - entry_delete(this->bans, this->bans->entries); - - if (ModeManager::FindChannelModeByName(CMODE_EXCEPT) && this->excepts && this->excepts->count) - while (this->excepts->entries) - entry_delete(this->excepts, this->excepts->entries); - - if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE) && this->invites && this->invites->count) - while (this->invites->entries) - entry_delete(this->invites, this->invites->entries); - ChannelList.erase(this->name); } void Channel::Reset() { - this->ClearModes(NULL, false); - this->ClearBans(NULL, false); - this->ClearExcepts(NULL, false); - this->ClearInvites(NULL, false); + this->modes.clear(); for (CUserList::const_iterator it = this->users.begin(), it_end = this->users.end(); it != it_end; ++it) { @@ -294,11 +278,27 @@ bool Channel::HasUserStatus(User *u, ChannelModeName Name) const /** * See if a channel has a mode * @param Name The mode name - * @return true or false + * @param param The optional mode param + * @return The number of modes set */ -bool Channel::HasMode(ChannelModeName Name) const +size_t Channel::HasMode(ChannelModeName Name, const Anope::string ¶m) { - return modes.HasFlag(Name); + if (param.empty()) + return modes.count(Name); + std::pair its = this->GetModeList(Name); + for (; its.first != its.second; ++its.first) + if (its.first->second == param) + return 1; + return 0; +} + +/** Get a list of modes on a channel + * @param Name A mode name to get the list of + * @return a pair of iterators for the beginning and end of the list + */ +std::pair Channel::GetModeList(ChannelModeName Name) +{ + return std::make_pair(this->modes.find(Name), this->modes.upper_bound(Name)); } /** Set a mode internally on a channel, this is not sent out to the IRCd @@ -346,36 +346,21 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string ¶m, bool chan_set_correct_modes(u, this, 0); return; } - /* Setting b/e/I etc */ - else if (cm->Type == MODE_LIST) - { - if (param.empty()) - { - Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name; - return; - } - ChannelModeList *cml = debug_cast(cm); - cml->AddMask(this, param); + if (cm->Type != MODE_LIST) + this->modes.erase(cm->Name); + this->modes.insert(std::make_pair(cm->Name, param)); + + if (param.empty() && cm->Type != MODE_REGULAR) + { + Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; return; } - modes.SetFlag(cm->Name); - - if (!param.empty()) + if (cm->Type == MODE_LIST) { - if (cm->Type != MODE_PARAM) - { - Log() << "Channel::SetModeInternal() mode " << cm->ModeChar << " for " << this->name << " with a paramater, but its not a param mode"; - return; - } - - /* They could be resetting the mode to change its params */ - std::map::iterator it = Params.find(cm->Name); - if (it != Params.end()) - Params.erase(it); - - Params.insert(std::make_pair(cm->Name, param)); + ChannelModeList *cml = d