summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/example.conf3
-rw-r--r--data/mysql/tables.sql1
-rw-r--r--docs/Changes.conf2
-rw-r--r--docs/IRCD12
-rw-r--r--include/channels.h56
-rw-r--r--include/extern.h16
-rw-r--r--include/language.h29
-rw-r--r--include/modes.h20
-rw-r--r--include/modules.h14
-rw-r--r--include/regchannel.h63
-rw-r--r--include/services.h35
-rw-r--r--include/sockets.h12
-rw-r--r--include/users.h4
-rw-r--r--modules/core/cs_clearusers.cpp14
-rw-r--r--modules/core/cs_forbid.cpp10
-rw-r--r--modules/core/cs_info.cpp3
-rw-r--r--modules/core/cs_mode.cpp306
-rw-r--r--modules/core/cs_set.cpp2
-rw-r--r--modules/core/cs_set_persist.cpp4
-rw-r--r--modules/core/db_plain.cpp75
-rw-r--r--modules/core/os_defcon.cpp2
-rw-r--r--modules/extra/db_mysql.cpp50
-rw-r--r--modules/extra/m_xmlrpc_main.cpp38
-rw-r--r--modules/protocol/bahamut.cpp1
-rw-r--r--modules/protocol/inspircd11.cpp1
-rw-r--r--modules/protocol/inspircd12.cpp1
-rw-r--r--modules/protocol/inspircd20.cpp1
-rw-r--r--modules/protocol/ratbox.cpp25
-rw-r--r--modules/protocol/unreal32.cpp25
-rw-r--r--src/actions.cpp21
-rw-r--r--src/bots.cpp32
-rw-r--r--src/channels.cpp820
-rw-r--r--src/chanserv.cpp160
-rw-r--r--src/config.cpp2
-rw-r--r--src/language.cpp46
-rw-r--r--src/misc.cpp80
-rw-r--r--src/modes.cpp136
-rw-r--r--src/operserv.cpp13
-rw-r--r--src/regchannel.cpp186
-rw-r--r--src/sockets.cpp74
-rw-r--r--src/users.cpp25
-rw-r--r--src/wildcard.cpp72
42 files changed, 1226 insertions, 1266 deletions
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<ChannelFlags>
{
+ public:
+ typedef std::multimap<ChannelModeName, Anope::string> ModeList;
private:
/** A map of channel modes with their parameters set on this channel
*/
- std::map<ChannelModeName, Anope::string> Params;
-
- /* Modes set on the channel */
- Flags<ChannelModeName, CMODE_END * 2> modes;
+ ModeList modes;
public:
/** Default constructor
@@ -87,10 +86,6 @@ class CoreExport Channel : public Extensible, public Flags<ChannelFlags>
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<ChannelFlags>
*/
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 &param = "");
+
+ /** 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<ModeList::iterator, ModeList::iterator> 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<ChannelFlags>
*/
void RemoveMode(BotInfo *bi, ChannelModeName Name, const Anope::string &param = "", 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<ChannelFlags>
*/
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<ChannelModeName, CMODE_END * 2> DefMLockOn;
-E Flags<ChannelModeName, CMODE_END * 2> DefMLockOff;
-E std::map<ChannelModeName, Anope::string> DefMLockParams;
+E std::multimap<ChannelModeName, ModeLock> 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 &param) { 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 &param) { 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<ChannelInfoFlag, CI_END>
{
private:
- std::map<ChannelModeName, Anope::string> Params; /* Map of parameters by mode name for mlock */
+ typedef std::multimap<ChannelModeName, ModeLock> ModeList;
+ private:
std::vector<ChanAccess *> access; /* List of authorized users */
std::vector<AutoKick *> akick; /* List of users to kickban */
std::vector<BadWord *> badwords; /* List of badwords */
- Flags<ChannelModeName, CMODE_END * 2> mlock_on; /* Modes mlocked on */
- Flags<ChannelModeName, CMODE_END * 2> mlock_off; /* Modes mlocked off */
+ ModeList mode_locks;
public:
/** Default constructor
@@ -241,51 +252,51 @@ class CoreExport ChannelInfo : public Extensible, public Flags<ChannelInfoFlag,
void LoadMLock();
/** Check if a mode is mlocked
- * @param Name The mode
+ * @param mode The mode
+ * @param An optional param
* @param status True to check mlock on, false for mlock off
* @return true on success, false on fail
*/
- bool HasMLock(ChannelModeName Name, bool status) const;
+ bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const;
/** Set a mlock
- * @param Name The mode
+ * @param mode The mode
* @param status True for mlock on, false for mlock off
* @param param An optional param arg for + mlocked modes
+ * @param setter Who is setting the mlock
+ * @param created When the mlock was created
* @return true on success, false on failure (module blocking)
*/
- bool SetMLock(ChannelModeName Name, bool status, const Anope::string &param = "");
+ bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param = "", const Anope::string &setter = "", time_t created = Anope::CurTime);
/** Remove a mlock
- * @param Name The mode
- * @return true on success, false on failure (module blcoking)
+ * @param mode The mode
+ * @param param The param of the mode, required if it is a list or status mode
+ * @return true on success, false on failure
*/
- bool RemoveMLock(ChannelModeName Name);
+ bool RemoveMLock(ChannelMode *mode, const Anope::string &param = "");
/** Clear all mlocks on the channel
*/
void ClearMLock();
- /** Get the number of mlocked modes for this channel
- * @param status true for mlock on, false for mlock off
- * @return The number of mlocked modes
- */
- size_t GetMLockCount(bool status) const;
-
- /** Get a param from the channel
- * @param Name The mode
- * @param Target a string to put the param into
- * @return true on success
+ /** Get all of the mlocks for this channel
+ * @return The mlocks
*/
- bool GetParam(ChannelModeName Name, Anope::string &Target) const;
+ const std::multimap<ChannelModeName, ModeLock> &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<ModeList::iterator, ModeList::iterator> 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 &param = "");
/** 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<EntryType>
{
+ 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<Channel::ModeList::iterator, Channel::ModeList::iterator> 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<Anope::string> &params)
+ {
+ const Anope::string &subcommand = params[2];
+ const Anope::string &param = 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<ChannelModeName, ModeLock> &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<ChannelModeName, ModeLock>::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<Anope::string> &params)
+ {
+ 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<Anope::string, Mode *>::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<ChannelMode *>(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<Channel::ModeList::iterator, Channel::ModeList::iterator> 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<Anope::string> &params)
+ {
+ 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<std::vector<std::pair<Anope::string, Anope::string> > >(mlp));
}
+ else if (key.equals_ci("MLP_OFF"))
+ {
+ std::vector<std::pair<Anope::string, Anope::string> > 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<std::vector<std::pair<Anope::string, Anope::string> > >(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<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ for (std::map<ChannelModeName, ModeLock>::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<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ for (std::map<ChannelModeName, ModeLock>::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<std::pair<Anope::string, Anope::string> > oldparams;;
- if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlp", oldparams))
+ db << endl;
{
- for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = oldparams.begin(), it_end = oldparams.end(); it != it_end; ++it)
+ std::vector<std::pair<Anope::string, Anope::string> > oldparams;;
+ if ((!Me || !Me->IsSynced()) && ci->GetExtRegular("db_mlp", oldparams))
{
- db << "MD MLP " << it->first << " " << it->second << endl;
+ for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = oldparams.begin(), it_end = oldparams.end(); it != it_end; ++it)
+ {
+ db << "MD MLP " << it->first << " " << it->second << endl;
+ }
}
- }
- else
- {
- for (std::map<char, ChannelMode *>::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<ChannelModeName, ModeLock>::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<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ for (std::map<ChannelModeName, ModeLock>::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<std::pair<Anope::string, Anope::string> > 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<std::pair<Anope::string, Anope::string> >::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<char, ChannelMode *>::iterator it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ for (std::map<ChannelModeName, ModeLock>::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<std::vector<std::pair<Anope::string, Anope::string> > >(mlp));
}
+ if (!r.Get(i, "mlock_params_off").empty())
+ {
+ std::vector<std::pair<Anope::string, Anope::string> > 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<std::vector<std::pair<Anope::string, Anope::string> > >(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<Channel::ModeList::iterator, Channel::ModeList::iterator> 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<Anope::string> &
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<ChannelModeList *>(ModeManager::FindChannelModeByChar('b'));
- cml->AddMask(c, b);
- }
- else if (params[2].equals_cs("e"))
- {
- ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByChar('e'));
- cml->AddMask(c, b);
- }
- if (params[2].equals_cs("I"))
- {
- ChannelModeList *cml = debug_cast<ChannelModeList *>(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<Anope::string> &
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<ChannelModeList *>(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<ChannelModeList *>(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<ChannelModeList *>(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<Channel::ModeList::iterator, Channel::ModeList::iterator> 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<Channel::ModeList::iterator, Channel::ModeList::iterator> 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<unsigned>(Limit);
+ Anope::string Limit;
+ unsigned limit = 0;
+ if (c->GetParam(CMODE_LIMIT, Limit) && Limit.is_pos_number_only())
+ limit = convertTo<unsigned>(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 &param)
{
- return modes.HasFlag(Name);
+ if (param.empty())
+ return modes.count(Name);
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> 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::ModeList::iterator, Channel::ModeList::iterator> 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 &param, 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<ChannelModeList *>(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<ChannelModeName, Anope::string>::iterator it = Params.find(cm->Name);
- if (it != Params.end())
- Params.erase(it);
-
- Params.insert(std::make_pair(cm->Name, param));
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(cm);
+ cml->OnAdd(this, param);
}
/* Channel mode +P or so was set, mark this channel as persistant */
@@ -398,33 +383,34 @@ void Channel::SetModeInternal(ChannelMode *cm, const Anope::string &param, bool
if (!ci)
return;
- /* If this channel has this mode locked negative */
- if (ci->HasMLock(cm->Name, false))
+ ModeLock *ml = ci->GetMLock(cm->Name, param);
+ if (ml)
{
- /* Remove the mode */
- if (cm->Type == MODE_PARAM)
+ if (ml->set && cm->Type == MODE_PARAM)
{
Anope::string cparam;
- GetParam(cm->Name, cparam);
- RemoveMode(NULL, cm, cparam);
+ this->GetParam(cm->Name, cparam);
+
+ /* We have the wrong param set */
+ if (cparam.empty() || ml->param.empty() || !cparam.equals_cs(ml->param))
+ /* Reset the mode with the correct param */
+ this->SetMode(NULL, cm, ml->param);
+ }
+ else if (!ml->set)
+ {
+ if (cm->Type == MODE_REGULAR)
+ this->RemoveMode(NULL, cm);
+ else if (cm->Type == MODE_PARAM)
+ {
+ Anope::string cparam;
+ this->GetParam(cm->Name, cparam);
+ this->RemoveMode(NULL, cm, cparam);
+ }
+ else if (cm->Type == MODE_LIST)
+ {
+ this->RemoveMode(NULL, cm, param);
+ }
}
- else if (cm->Type == MODE_REGULAR)
- RemoveMode(NULL, cm);
- }
- /* If this is a param mode and its mlocked +, check to ensure someone didn't reset it with the wrong param */
- else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true))
- {
- ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
- Anope::string cparam, ciparam;
- /* Get the param currently set on this channel */
- GetParam(cmp->Name, cparam);
- /* Get the param set in mlock */
- ci->GetParam(cmp->Name, ciparam);
-
- /* We have the wrong param set */
- if (cparam.empty() || ciparam.empty() || !cparam.equals_cs(ciparam))
- /* Reset the mode with the correct param */
- SetMode(NULL, cm, ciparam);
}
}
@@ -475,29 +461,29 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string &param, bo
this->SetMode(bi, cm, bi->nick);
}
+ /* Enforce secureops, etc */
+ if (EnforceMLock)
+ chan_set_correct_modes(u, this, 1);
return;
}
- /* Setting b/e/I etc */
- else if (cm->Type == MODE_LIST)
- {
- if (param.empty())
- {
- Log() << "Channel::RemoveModeInternal() mode " << cm->ModeChar << " with no parameter for channel " << this->name;
- return;
- }
- ChannelModeList *cml = debug_cast<ChannelModeList *>(cm);
- cml->DelMask(this, param);
- return;
+ if (cm->Type == MODE_LIST && !param.empty())
+ {
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(cm->Name);
+ for (; its.first != its.second; ++its.first)
+ if (Anope::Match(param, its.first->second))
+ {
+ this->modes.erase(its.first);
+ break;
+ }
}
-
- modes.UnsetFlag(cm->Name);
-
- if (cm->Type == MODE_PARAM)
+ else
+ this->modes.erase(cm->Name);
+
+ if (cm->Type == MODE_LIST)
{
- std::map<ChannelModeName, Anope::string>::iterator it = Params.find(cm->Name);
- if (it != Params.end())
- Params.erase(it);
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(cm);
+ cml->OnDel(this, param);
}
if (cm->Name == CMODE_PERM)
@@ -525,22 +511,14 @@ void Channel::RemoveModeInternal(ChannelMode *cm, const Anope::string &param, bo
if (!ci || !EnforceMLock || MOD_RESULT == EVENT_STOP)
return;
+ ModeLock *ml = ci->GetMLock(cm->Name, param);
/* This channel has this the mode locked on */
- if (ci->HasMLock(cm->Name, true))
+ if (ml && ml->set)
{
if (cm->Type == MODE_REGULAR)
- {
- /* Set the mode */
- SetMode(NULL, cm);
- }
- /* This is a param mode */
- else if (cm->Type == MODE_PARAM)
- {
- Anope::string cparam;
- /* Get the param stored in mlock for this mode */
- if (ci->GetParam(cm->Name, cparam))
- SetMode(NULL, cm, cparam);
- }
+ this->SetMode(NULL, cm);
+ else if (cm->Type == MODE_PARAM || cm->Type == MODE_LIST)
+ this->SetMode(NULL, cm, ml->param);
}
}
@@ -557,8 +535,12 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param,
/* Don't set modes already set */
if (cm->Type == MODE_REGULAR && HasMode(cm->Name))
return;
- else if (cm->Type == MODE_PARAM && HasMode(cm->Name))
+ else if (cm->Type == MODE_PARAM)
{
+ ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
+ if (!cmp->IsValid(param))
+ return;
+
Anope::string cparam;
if (GetParam(cm->Name, cparam) && cparam.equals_cs(param))
return;
@@ -571,7 +553,9 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string &param,
}
else if (cm->Type == MODE_LIST)
{
- // XXX this needs rewritten
+ ChannelModeList *cml = debug_cast<ChannelModeList *>(cm);
+ if (this->HasMode(cm->Name, param) || !cml->IsValid(param))
+ return;
}
ModeManager::StackerAdd(bi, this, cm, true, param);
@@ -612,20 +596,22 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string &para
}
else if (cm->Type == MODE_LIST)
{
- // XXX this needs to be rewritten sometime
+ if (!this->HasMode(cm->Name, param))
+ return;
}
- /* If this mode needs no param when being unset, empty the param */
- bool SendParam = true;
+ /* Get the param to send, if we need it */
+ Anope::string realparam = param;
if (cm->Type == MODE_PARAM)
{
+ realparam.clear();
ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
- if (cmp->MinusNoArg)
- SendParam = false;
+ if (!cmp->MinusNoArg)
+ this->GetParam(cmp->Name, realparam);
}
- ModeManager::StackerAdd(bi, this, cm, false, param);
- RemoveModeInternal(cm, SendParam ? param : "", EnforceMLock);
+ ModeManager::StackerAdd(bi, this, cm, false, realparam);
+ RemoveModeInternal(cm, realparam, EnforceMLock);
}
/**
@@ -647,11 +633,11 @@ void Channel::RemoveMode(BotInfo *bi, ChannelModeName Name, const Anope::string
*/
bool Channel::GetParam(ChannelModeName Name, Anope::string &Target) const
{
- std::map<ChannelModeName, Anope::string>::const_iterator it = Params.find(Name);
+ std::multimap<ChannelModeName, Anope::string>::const_iterator it = this->modes.find(Name);
Target.clear();
- if (it != Params.end())
+ if (it != this->modes.end())
{
Target = it->second;
return true;
@@ -660,121 +646,8 @@ bool Channel::GetParam(ChannelModeName Name, Anope::string &Target) const
return false;
}
-/** Check if a mode is set and has a param
- * @param Name The mode
- */
-bool Channel::HasParam(ChannelModeName Name) const
-{
- std::map<ChannelModeName, Anope::string>::const_iterator it = Params.find(Name);
-
- if (it != Params.end())
- return true;
-
- return false;
-}
-
/*************************************************************************/
-/** Clear all the modes from the channel
- * @param bi The client setting the modes
- * @param internal Only remove the modes internally
- */
-void Channel::ClearModes(BotInfo *bi, bool internal)
-{
- for (size_t n = CMODE_BEGIN + 1; n != CMODE_END; ++n)
- {
- ChannelMode *cm = ModeManager::FindChannelModeByName(static_cast<ChannelModeName>(n));
-
- if (cm && this->HasMode(cm->Name))
- {
- if (cm->Type == MODE_REGULAR)
- {
- if (!internal)
- this->RemoveMode(NULL, cm);
- else
- this->RemoveModeInternal(cm);
- }
- else if (cm->Type == MODE_PARAM)
- {
- Anope::string param;
- this->GetParam(cm->Name, param);
- if (!internal)
- this->RemoveMode(NULL, cm, param);
- else
- this->RemoveModeInternal(cm, param);
- }
- }
- }
-
- modes.ClearFlags();
-}
-
-/** Clear all the bans from the channel
- * @param bi The client setting the modes
- * @param internal Only remove the modes internally
- */
-void Channel::ClearBans(BotInfo *bi, bool internal)
-{
- Entry *entry, *nexte;
-
- ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_BAN));
-
- if (cml && this->bans && this->bans->count)
- for (entry = this->bans->entries; entry; entry = nexte)
- {
- nexte = entry->next;
-
- if (!internal)
- this->RemoveMode(bi, cml, entry->mask);
- else
- this->RemoveModeInternal(cml, entry->mask);
- }
-}
-
-/** Clear all the excepts from the channel
- * @param bi The client setting the modes
- * @param internal Only remove the modes internally
- */
-void Channel::ClearExcepts(BotInfo *bi, bool internal)
-{
- Entry *entry, *nexte;
-
- ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_EXCEPT));
-
- if (cml && this->excepts && this->excepts->count)
- for (entry = this->excepts->entries; entry; entry = nexte)
- {
- nexte = entry->next;
-
- if (!internal)
- this->RemoveMode(bi, cml, entry->mask);
- else
- this->RemoveModeInternal(cml, entry->mask);
- }
-}
-
-/** Clear all the invites from the channel
- * @param bi The client setting the modes
- * @param internal Only remove the modes internally
- */
-void Channel::ClearInvites(BotInfo *bi, bool internal)
-{
- Entry *entry, *nexte;
-
- ChannelModeList *cml = debug_cast<ChannelModeList *>(ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE));
-
- if (cml && this->invites && this->invites->count)
- for (entry = this->invites->entries; entry; entry = nexte)
- {
- nexte = entry->next;
-
- if (!internal)
- this->RemoveMode(bi, cml, entry->mask);
- else
- this->RemoveModeInternal(cml, entry->mask);
- }
-}
-
/** 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
@@ -980,45 +853,26 @@ bool Channel::Kick(BotInfo *bi, User *u, const char *reason, ...)
Anope::string Channel::GetModes(bool complete, bool plus)
{
- Anope::string res;
+ Anope::string res, params;
- if (this->HasModes())
+ for (std::multimap<ChannelModeName, Anope::string>::const_iterator it = this->modes.begin(), it_end = this->modes.end(); it != it_end; ++it)
{
- Anope::string params;
- for (std::map<Anope::string, Mode *>::const_iterator it = ModeManager::Modes.begin(), it_end = ModeManager::Modes.end(); it != it_end; ++it)
- {
- if (it->second->Class != MC_CHANNEL)
- continue;
+ ChannelMode *cm = ModeManager::FindChannelModeByName(it->first);
+ if (!cm || cm->Type == MODE_LIST)
+ continue;
- ChannelMode *cm = debug_cast<ChannelMode *>(it->second);
+ res += cm->ModeChar;
- if (this->HasMode(cm->Name))
- {
- res += cm->ModeChar;
+ if (complete && !it->second.empty())
+ {
+ ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
- if (complete)
- {
- if (cm->Type == MODE_PARAM)
- {
- ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
-
- if (plus || !cmp->MinusNoArg)
- {
- Anope::string param;
- this->GetParam(cmp->Name, param);
-
- if (!param.empty())
- params += " " + param;
- }
- }
- }
- }
+ if (plus || !cmp->MinusNoArg)
+ params += " " + it->second;
}
-
- res += params;
}
- return res;
+ return res + params;
}
void Channel::ChangeTopicInternal(const Anope::string &user, const Anope::string &newtopic, time_t ts)
@@ -1083,17 +937,6 @@ void get_channel_stats(long *nrec, long *memuse)
mem += sizeof(*chan);
if (!chan->topic.empty())
mem += chan->topic.length() + 1;
- if (chan->GetParam(CMODE_KEY, buf))
- mem += buf.length() + 1;
- if (chan->GetParam(CMODE_FLOOD, buf))
- mem += buf.length() + 1;
- if (chan->GetParam(CMODE_REDIRECT, buf))
- mem += buf.length() + 1;
- mem += get_memuse(chan->bans);
- if (ModeManager::FindChannelModeByName(CMODE_EXCEPT))
- mem += get_memuse(chan->excepts);
- if (ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE))
- mem += get_memuse(chan->invites);
for (CUserList::iterator it = chan->users.begin(), it_end = chan->users.end(); it != it_end; ++it)
{
mem += sizeof(*it);
@@ -1355,6 +1198,26 @@ void chan_set_correct_modes(User *user, Channel *c, int give_modes)
if (halfop && c->HasUserStatus(user, CMODE_HALFOP) && !check_access(user, ci, CA_AUTOHALFOP) && !check_access(user, ci, CA_HALFOPME))
c->RemoveMode(NULL, CMODE_HALFOP, user->nick);
}
+
+ // Check mlock
+ for (std::multimap<ChannelModeName, ModeLock>::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 || cm->Type != MODE_STATUS)
+ continue;
+
+ if (Anope::Match(user->nick, ml.param) || Anope::Match(user->GetDisplayedMask(), ml.param))
+ {
+ if ((ml.set && !c->HasUserStatus(user, ml.name)) || (!ml.set && c->HasUserStatus(user, ml.name)))
+ {
+ if (ml.set && give_modes)
+ c->SetMode(NULL, cm, user->nick, false);
+ else if (!ml.set && !give_modes)
+ c->RemoveMode(NULL, cm, user->nick, false);
+ }
+ }
+ }
}
/*************************************************************************/
@@ -1376,382 +1239,137 @@ void MassChannelModes(BotInfo *bi, const Anope::string &modes)
}
}
-/*************************************************************************/
-
-/**
- * This handles creating a new Entry.
- * This function destroys and free's the given mask as a side effect.
- * @param mask Host/IP/CIDR mask to convert to an entry
- * @return Entry struct for the given mask, NULL if creation failed
+/** Constructor
+ * @param _host A full nick!ident@host/cidr mask
*/
-Entry *entry_create(const Anope::string &mask)
+Entry::Entry(const Anope::string &_host)
{
- Entry *entry;
- Anope::string cidrhost;
- uint32 ip, cidr;
-
- entry = new Entry;
- entry->SetFlag(ENTRYTYPE_NONE);
- entry->prev = NULL;
- entry->next = NULL;
- entry->mask = mask;
-
- Anope::string newmask = mask, host, nick, user;
+ this->SetFlag(ENTRYTYPE_NONE);
+ this->cidr_len = 0;
+ this->mask = _host;
- size_t at = newmask.find('@');
+ Anope::string _nick, _user, _realhost;
+ size_t at = _host.find('@');
if (at != Anope::string::npos)
{
- host = newmask.substr(at + 1);
- newmask = newmask.substr(0, at);
- /* If the user is purely a wildcard, ignore it */
- if (!str_is_pure_wildcard(newmask))
+ _realhost = _host.substr(at + 1);
+ Anope::string _nickident = _host.substr(0, at);
+
+ size_t ex = _nickident.find('!');
+ if (ex != Anope::string::npos)
{
- /* There might be a nick too */
- //user = strchr(mask, '!');
- size_t ex = newmask.find('!');
- if (ex != Anope::string::npos)
- {
- user = newmask.substr(ex + 1);
- newmask = newmask.substr(0, ex);
- /* If the nick is purely a wildcard, ignore it */
- if (!str_is_pure_wildcard(newmask))
- nick = newmask;
- }
- else
- user = newmask;
+ _user = _nickident.substr(ex + 1);
+ _nick = _nickident.substr(0, ex);
}
+ else
+ _user = _nickident;
}
else
- /* It is possibly an extended ban/invite mask, but we do
- * not support these at this point.. ~ Viper */
- /* If there's no user in the mask, assume a pure wildcard */
- host = newmask;
-
- if (!nick.empty())
+ _realhost = _host;
+
+ if (!_nick.empty() && !str_is_pure_wildcard(_nick))
{
- entry->nick = nick;
- /* Check if we have a wildcard user */
- if (str_is_wildcard(nick))
- entry->SetFlag(ENTRYTYPE_NICK_WILD);
+ this->nick = _nick;
+ if (str_is_wildcard(_nick))
+ this->SetFlag(ENTRYTYPE_NICK_WILD);
else
- entry->SetFlag(ENTRYTYPE_NICK);
+ this->SetFlag(ENTRYTYPE_NICK);
}
- if (!user.empty())
+ if (!_user.empty() && !str_is_pure_wildcard(_user))
{
- entry->user = user;
- /* Check if we have a wildcard user */
- if (str_is_wildcard(user))
- entry->SetFlag(ENTRYTYPE_USER_WILD);
+ this->user = _user;
+ if (str_is_wildcard(_user))
+ this->SetFlag(ENTRYTYPE_USER_WILD);
else
- entry->SetFlag(ENTRYTYPE_USER);
+ this->SetFlag(ENTRYTYPE_USER);
}
- /* Only check the host if it's not a pure wildcard */
- if (!host.empty() && !str_is_pure_wildcard(host))
+ if (!_realhost.empty() && !str_is_pure_wildcard(_realhost))
{
- if (ircd->cidrchanbei && str_is_cidr(host, ip, cidr, cidrhost))
- {
- entry->cidr_ip = ip;
- entry->cidr_mask = cidr;
- entry->SetFlag(ENTRYTYPE_CIDR4);
- host = cidrhost;
- }
- else if (ircd->cidrchanbei && host.find('/') != Anope::string::npos)
+ size_t sl = _realhost.find_last_of('/');
+ if (sl != Anope::string::npos)
{
- /* Most IRCd's don't enforce sane bans therefore it is not
- * so unlikely we will encounter this.
- * Currently we only support strict CIDR without taking into
- * account quirks of every single ircd (nef) that ignore everything
- * after the first /cidr. To add this, sanitaze before sending to
- * str_is_cidr() as this expects a standard cidr.
- * Add it to the internal list (so it is included in for example clear)
- * but do not use if during matching.. ~ Viper */
- entry->ClearFlags();
- entry->SetFlag(ENTRYTYPE_NONE);
- }
- else
- {
- entry->host = host;
- if (str_is_wildcard(host))
- entry->SetFlag(ENTRYTYPE_HOST_WILD);
- else
- entry->SetFlag(ENTRYTYPE_HOST);
- }
- }
-
- return entry;
-}
-
-/**
- * Create an entry and add it at the beginning of given list.
- * @param list The List the mask should be added to
- * @param mask The mask to parse and add to the list
- * @return Pointer to newly added entry. NULL if it fails.
- */
-Entry *entry_add(EList *list, const Anope::string &mask)
-{
- Entry *e;
-
- e = entry_create(mask);
-
- if (!e)
- return NULL;
-
- e->next = list->entries;
- e->prev = NULL;
-
- if (list->entries)
- list->entries->prev = e;
- list->entries = e;
- ++list->count;
-
- return e;
-}
-
-/**
- * Delete the given entry from a given list.
- * @param list Linked list from which entry needs to be removed.
- * @param e The entry to be deleted, must be member of list.
- */
-void entry_delete(EList *list, Entry *e)
-{
- if (!list || !e)
- return;
-
- if (e->next)
- e->next->prev = e->prev;
- if (e->prev)
- e->prev->next = e->next;
-
- if (list->entries == e)
- list->entries = e->next;
-
- delete e;
-
- --list->count;
-}
-
-/**
- * Create and initialize a new entrylist
- * @return Pointer to the created EList object
- **/
-EList *list_create()
-{
- EList *list;
-
- list = new EList;
- list->entries = NULL;
- list->count = 0;
-
- return list;
-}
-
-/**
- * Match the given Entry to the given user/host and optional IP addy
- * @param e Entry struct to match against
- * @param nick Nick to match against
- * @param user User to match against
- * @param host Host to match against
- * @param ip IP to match against, set to 0 to not match this
- * @return 1 for a match, 0 for no match
- */
-int entry_match(Entry *e, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip)
-{
- /* If we don't get an entry, or it s an invalid one, no match ~ Viper */
- if (!e || !e->FlagCount())
- return 0;
-
- if (ircd->cidrchanbei && e->HasFlag(ENTRYTYPE_CIDR4) && (!ip || (ip && (ip & e->cidr_mask) != e->cidr_ip)))
- return 0;
- if (e->HasFlag(ENTRYTYPE_NICK) && (nick.empty() || !e->nick.equals_ci(nick)))
- return 0;
- if (e->HasFlag(ENTRYTYPE_USER) && (user.empty() || !e->user.equals_ci(user)))
- return 0;
- if (e->HasFlag(ENTRYTYPE_HOST) && (host.empty() || !e->host.equals_ci(host)))
- return 0;
- if (e->HasFlag(ENTRYTYPE_NICK_WILD) && !Anope::Match(nick, e->nick))
- return 0;
- if (e->HasFlag(ENTRYTYPE_USER_WILD) && !Anope::Match(user, e->user))
- return 0;
- if (e->HasFlag(ENTRYTYPE_HOST_WILD) && !Anope::Match(host, e->host))
- return 0;
-
- return 1;
-}
-
-/**
- * Match the given Entry to the given hostmask and optional IP addy.
- * @param e Entry struct to match against
- * @param mask Hostmask to match against
- * @param ip IP to match against, set to 0 to not match this
- * @return 1 for a match, 0 for no match
- */
-int entry_match_mask(Entry *e, const Anope::string &mask, uint32 ip)
-{
- int res;
-
- Anope::string hostmask = mask, host, user, nick;
+ try
+ {
+ sockaddrs addr;
+ bool ipv6 = _realhost.substr(0, sl).find(':') != Anope::string::npos;
+ addr.pton(ipv6 ? AF_INET6 : AF_INET, _realhost.substr(0, sl));
+ /* If we got here, _realhost is a valid IP */
- size_t at = hostmask.find('@');
- if (at != Anope::string::npos)
- {
- host = hostmask.substr(at + 1);
- hostmask = hostmask.substr(0, at);
- size_t ex = hostmask.find('!');
- if (ex != Anope::string::npos)
- {
- user = hostmask.substr(ex + 1);
- nick = hostmask.substr(0, ex);
+ Anope::string cidr_range = _realhost.substr(sl + 1);
+ if (cidr_range.is_pos_number_only())
+ {
+ _realhost = _realhost.substr(0, sl);
+ this->cidr_len = convertTo<unsigned int>(cidr_range);
+ this->SetFlag(ENTRYTYPE_CIDR);
+ Log(LOG_DEBUG) << "Ban " << _realhost << " has cidr " << static_cast<unsigned int>(this->cidr_len);
+ }
+ }
+ catch (const SocketException &) { }
}
- else
- user = hostmask;
- }
- else
- host = hostmask;
-
- res = entry_match(e, nick, user, host, ip);
-
- return res;
-}
-
-/**
- * Match a nick, user, host, and ip to a list entry
- * @param e List that should be matched against
- * @param nick The nick to match
- * @param user The user to match
- * @param host The host to match
- * @param ip The ip to match
- * @return Returns the first matching entry, if none, NULL is returned.
- */
-Entry *elist_match(EList *list, const Anope::string &nick, const Anope::string &user, const Anope::string &host, uint32 ip)
-{
- Entry *e;
-
- if (!list || !list->entries)
- return NULL;
-
- for (e = list->entries; e; e = e->next)
- if (entry_match(e, nick, user, host, ip))
- return e;
-
- /* We matched none */
- return NULL;
-}
-/**
- * Match a mask and ip to a list.
- * @param list EntryList that should be matched against
- * @param mask The nick!user@host mask to match
- * @param ip The ip to match
- * @return Returns the first matching entry, if none, NULL is returned.
- */
-Entry *elist_match_mask(EList *list, const Anope::string &mask, uint32 ip)
-{
- Entry *res;
-
- if (!list || !list->entries || mask.empty())
- return NULL;
+ this->host = _realhost;
- Anope::string hostmask = mask, host, user, nick;
-
- size_t at = hostmask.find('@');
- if (at != Anope::string::npos)
- {
- host = hostmask.substr(at + 1);
- hostmask = hostmask.substr(0, at);
- size_t ex = hostmask.find('!');
- if (ex != Anope::string::npos)
+ if (!this->HasFlag(ENTRYTYPE_CIDR))
{
- user = hostmask.substr(ex + 1);
- nick = hostmask.substr(0, ex);
+ if (str_is_wildcard(_realhost))
+ this->SetFlag(ENTRYTYPE_HOST_WILD);
+ else
+ this->SetFlag(ENTRYTYPE_HOST);
}
- else
- user = hostmask;
}
- else
- host = hostmask;
-
- res = elist_match(list, nick, user, host, ip);
-
- return res;
}
-/**
- * Check if a user matches an entry on a list.
- * @param list EntryList that should be matched against
- * @param user The user to match against the entries
- * @return Returns the first matching entry, if none, NULL is returned.
+/** Get the banned mask for this entry
+ * @return The mask
*/
-Entry *elist_match_user(EList *list, User *u)
+const Anope::string Entry::GetMask()
{
- Entry *res;
- //uint32 ip = 0;
-
- if (!list || !list->entries || !u)
- return NULL;
-
- /* Match what we ve got against the lists.. */
- res = elist_match(list, u->nick, u->GetIdent(), u->host, /*ip XXX*/0);
- if (!res)
- res = elist_match(list, u->nick, u->GetIdent(), u->GetDisplayedHost(), /*ip XXX*/0);
- if (!res && !u->GetCloakedHost().empty() && !u->GetCloakedHost().equals_cs(u->GetDisplayedHost()))
- res = elist_match(list, u->nick, u->GetIdent(), u->GetCloakedHost(), /*ip XXX*/ 0);
-
- return res;
+ return this->mask;
}
-/**
- * Find a entry identical to the given mask..
- * @param list EntryList that should be matched against
- * @param mask The *!*@* mask to match
- * @return Returns the first matching entry, if none, NULL is returned.
- */
-Entry *elist_find_mask(EList *list, const Anope::string &mask)
-{
- Entry *e;
-
- if (!list || !list->entries || mask.empty())
- return NULL;
-
- for (e = list->entries; e; e = e->next)
- if (e->mask.equals_ci(mask))
- return e;
-
- return NULL;
-}
-
-/**
- * Gets the total memory use of an entrylit.
- * @param list The list we should estimate the mem use of.
- * @return Returns the memory useage of the given list.
+/** Check if this entry matches a user
+ * @param u The user
+ * @return true on match
*/
-long get_memuse(EList *list)
+bool Entry::Matches(User *u) const
{
- Entry *e;
- long mem = 0;
-
- if (!list)
+ if (!this->FlagCount())
return 0;
+
+ Anope::string _nick = u->nick;
+ Anope::string _user = u->GetVIdent();
+ Anope::string _host = u->GetDisplayedHost();
- mem += sizeof(EList *);
- mem += sizeof(Entry *) * list->count;
- if (list->entries)
+ if (this->HasFlag(ENTRYTYPE_CIDR))
{
- for (e = list->entries; e; e = e->next)
+ try
+ {
+ cidr cidr_mask(this->host, this->cidr_len);
+ if (!u->ip() || !cidr_mask.match(u->ip))
+ {
+ return false;
+ }
+ }
+ catch (const SocketException &)
{
- if (!e->nick.empty())
- mem += e->nick.length() + 1;
- if (!e->user.empty())
- mem += e->user.length() + 1;
- if (!e->host.empty())
- mem += e->host.length() + 1;
- if (!e->mask.empty())
- mem += e->mask.length() + 1;
+ return false;
}
}
+ if (this->HasFlag(ENTRYTYPE_NICK) && (_nick.empty() || !this->nick.equals_ci(_nick)))
+ return false;
+ if (this->HasFlag(ENTRYTYPE_USER) && (_user.empty() || !this->user.equals_ci(_user)))
+ return false;
+ if (this->HasFlag(ENTRYTYPE_HOST) && (_host.empty() || !this->host.equals_ci(_host)))
+ return false;
+ if (this->HasFlag(ENTRYTYPE_NICK_WILD) && !Anope::Match(_nick, this->nick))
+ return false;
+ if (this->HasFlag(ENTRYTYPE_USER_WILD) && !Anope::Match(_user, this->user))
+ return false;
+ if (this->HasFlag(ENTRYTYPE_HOST_WILD) && !Anope::Match(_host, this->host))
+ return false;
- return mem;
+ return true;
}
-/*************************************************************************/
diff --git a/src/chanserv.cpp b/src/chanserv.cpp
index ca37f0cc7..ef3de90cd 100644
--- a/src/chanserv.cpp
+++ b/src/chanserv.cpp
@@ -24,7 +24,6 @@ static int def_levels[][2] = {
{ CA_INVITE, 5 },
{ CA_AKICK, 10 },
{ CA_SET, ACCESS_QOP },
- { CA_CLEAR, ACCESS_FOUNDER },
{ CA_UNBAN, 5 },
{ CA_OPDEOP, 5 },
{ CA_ACCESS_LIST, 1 },
@@ -52,6 +51,7 @@ static int def_levels[][2] = {
{ CA_BANME, 5 },
{ CA_BAN, 5 },
{ CA_TOPIC, ACCESS_FOUNDER },
+ { CA_MODE, ACCESS_FOUNDER },
{ CA_INFO, ACCESS_QOP },
{ CA_AUTOOWNER, ACCESS_QOP },
{ CA_OWNER, ACCESS_FOUNDER },
@@ -74,7 +74,6 @@ LevelInfo levelinfo[] = {
{ CA_SET, "SET", CHAN_LEVEL_SET },
{ CA_BAN, "BAN", CHAN_LEVEL_BAN },
{ CA_BANME, "BANME", CHAN_LEVEL_BANME },
- { CA_CLEAR, "CLEAR", CHAN_LEVEL_CLEAR },
{ CA_GETKEY, "GETKEY", CHAN_LEVEL_GETKEY },
{ CA_HALFOP, "HALFOP", CHAN_LEVEL_HALFOP },
{ CA_HALFOPME, "HALFOPME", CHAN_LEVEL_HALFOPME },
@@ -87,6 +86,7 @@ LevelInfo levelinfo[] = {
{ CA_PROTECT, "PROTECT", CHAN_LEVEL_PROTECT },
{ CA_PROTECTME, "PROTECTME", CHAN_LEVEL_PROTECTME },
{ CA_TOPIC, "TOPIC", CHAN_LEVEL_TOPIC },
+ { CA_MODE, "MODE", CHAN_LEVEL_MODE },
{ CA_UNBAN, "UNBAN", CHAN_LEVEL_UNBAN },
{ CA_VOICE, "VOICE", CHAN_LEVEL_VOICE },
{ CA_VOICEME, "VOICEME", CHAN_LEVEL_VOICEME },
@@ -111,59 +111,30 @@ int levelinfo_maxwidth = 0;
Anope::string get_mlock_modes(ChannelInfo *ci, int complete)
{
- ChannelMode *cm;
- ChannelModeParam *cmp;
- std::map<char, ChannelMode *>::iterator it, it_end;
- Anope::string res, param;
+ Anope::string pos = "+", neg = "-", params;
- if (ci->GetMLockCount(true) || ci->GetMLockCount(false))
+ for (std::map<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it)
{
- if (ci->GetMLockCount(true))
- {
- res += '+';
-
- for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
- {
- cm = it->second;
-
- if (ci->HasMLock(cm->Name, true))
- res += it->first;
- }
- }
-
- if (ci->GetMLockCount(false))
- {
- res += '-';
-
- for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
- {
- cm = it->second;
-
- if (ci->HasMLock(cm->Name, false))
- res += it->first;
- }
- }
-
- if (ci->GetMLockCount(true) && complete)
- {
- for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
- {
- cm = it->second;
-
- if (cm->Type == MODE_PARAM)
- {
- cmp = debug_cast<ChannelModeParam *>(cm);
-
- ci->GetParam(cmp->Name, param);
-
- if (!param.empty())
- res += " " + param;
- }
- }
- }
+ const ModeLock &ml = it->second;
+ ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name);
+ if (!cm)
+ continue;
+
+ if (ml.set)
+ pos += cm->ModeChar;
+ else
+ neg += cm->ModeChar;
+
+ if (complete && !ml.param.empty() && (cm->Type == MODE_PARAM || cm->Type == MODE_LIST))
+ params += " " + ml.param;
}
- return res;
+ if (pos.length() == 1)
+ pos.clear();
+ if (neg.length() == 1)
+ neg.clear();
+
+ return pos + neg + params;
}
/*************************************************************************/
@@ -173,7 +144,7 @@ Anope::string get_mlock_modes(ChannelInfo *ci, int complete)
void get_chanserv_stats(long *nrec, long *memuse)
{
long count = 0, mem = 0;
- Anope::string param;
+ ModeLock *ml;
for (registered_channel_map::const_iterator it = RegisteredChannelList.begin(), it_end = RegisteredChannelList.end(); it != it_end; ++it)
{
@@ -186,14 +157,17 @@ void get_chanserv_stats(long *nrec, long *memuse)
mem += ci->GetAccessCount() * sizeof(ChanAccess);
mem += ci->GetAkickCount() * sizeof(AutoKick);
- if (ci->GetParam(CMODE_KEY, param))
- mem += param.length() + 1;
+ ml = ci->GetMLock(CMODE_KEY);
+ if (ml && !ml->param.empty())
+ mem += ml->param.length() + 1;
- if (ci->GetParam(CMODE_FLOOD, param))
- mem += param.length() + 1;
+ ml = ci->GetMLock(CMODE_FLOOD);
+ if (ml && !ml->param.empty())
+ mem += ml->param.length() + 1;
- if (ci->GetParam(CMODE_REDIRECT, param))
- mem += 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;
@@ -237,11 +211,6 @@ void cs_init()
void check_modes(Channel *c)
{
- ChannelInfo *ci;
- ChannelMode *cm;
- std::map<char, ChannelMode *>::iterator it, it_end;
- Anope::string param, ciparam;
-
if (!c)
{
Log() << "check_modes called with NULL values";
@@ -268,61 +237,52 @@ void check_modes(Channel *c)
c->chanserv_modecount++;
/* Check if the channel is registered; if not remove mode -r */
- if (!(ci = c->ci))
+ ChannelInfo *ci = c->ci;
+ if (!ci)
{
if (c->HasMode(CMODE_REGISTERED))
c->RemoveMode(NULL, CMODE_REGISTERED);
return;
}
- for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
+ for (std::map<ChannelModeName, ModeLock>::const_iterator it = ci->GetMLock().begin(), it_end = ci->GetMLock().end(); it != it_end; ++it)
{
- cm = it->second;
+ const ModeLock &ml = it->second;
+ ChannelMode *cm = ModeManager::FindChannelModeByName(ml.name);
+ if (!cm)
+ continue;
- /* If this channel does not have the mode and the mode is mlocked */
- if (cm->Type == MODE_REGULAR && !c->HasMode(cm->Name) && ci->HasMLock(cm->Name, true))
+ if (cm->Type == MODE_REGULAR)
{
- /* Add the eventual parameter and modify the Channel structure */
- if (cm->Type == MODE_PARAM)
- {
- if (ci->GetParam(cm->Name, ciparam))
- c->SetMode(NULL, cm, ciparam);
- }
- else
+ if (!c->HasMode(cm->Name) && ml.set)
c->SetMode(NULL, cm);
+ else if (c->HasMode(cm->Name) && !ml.set)
+ c->RemoveMode(NULL, cm);
}
- /* If this is a param mode and its mlocked, check to ensure it is set and set to the correct value */
- else if (cm->Type == MODE_PARAM && ci->HasMLock(cm->Name, true))
+ else if (cm->Type == MODE_PARAM)
{
+ Anope::string param;
c->GetParam(cm->Name, param);
- ci->GetParam(cm->Name, ciparam);
/* If the channel doesnt have the mode, or it does and it isn't set correctly */
- if (!c->HasMode(cm->Name) || (!param.empty() && !ciparam.empty() && !param.equals_cs(ciparam)))
- c->SetMode(NULL, cm, ciparam);
- }
- }
-
- for (it = ModeManager::ChannelModesByChar.begin(), it_end = ModeManager::ChannelModesByChar.end(); it != it_end; ++it)
- {
- cm = it->second;
-
- /* If the channel has the mode */
- if (c->HasMode(cm->Name) && ci->HasMLock(cm->Name, false))
- {
- /* Add the eventual parameter */
- if (cm->Type == MODE_PARAM)
+ if (ml.set)
{
- ChannelModeParam *cmp = debug_cast<ChannelModeParam *>(cm);
-
- if (!cmp->MinusNoArg)
- {
- if (c->GetParam(cmp->Name, param))
- c->RemoveMode(NULL, cm, param);
- }
+ if (!c->HasMode(cm->Name) || (!param.empty() && !ml.param.empty() && !param.equals_cs(ml.param)))
+ c->SetMode(NULL, cm, ml.param);
}
else
- c->RemoveMode(NULL, cm);
+ {
+ if (c->HasMode(cm->Name))
+ c->RemoveMode(NULL, cm);
+ }
+
+ }
+ else if (cm->Type == MODE_LIST) // XXX we still need better list code...
+ {
+ if (ml.set)
+ c->SetMode(NULL, cm, ml.param);
+ else
+ c->RemoveMode(NULL, cm, ml.param);
}
}
}
diff --git a/src/config.cpp b/src/config.cpp
index 818021efb..6dddd7691 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -167,7 +167,7 @@ ServerConfig::ServerConfig() : errstr(""), config_data()
}
}
- this->WallOper = this->WallBadOS = this->WallOSGlobal = this->WallOSMode = this->WallOSClearmodes = this->WallOSKick = this->WallOSAkill = this->WallOSSNLine = this->WallOSSQLine =
+ this->WallOper = this->WallBadOS = this->WallOSGlobal = this->WallOSMode = this->WallOSKick = this->WallOSAkill = this->WallOSSNLine = this->WallOSSQLine =
this->WallOSSZLine = this->WallOSNoOp = this->WallOSJupe = this->WallAkillExpire = this->WallSNLineExpire = this->WallSQLineExpire = this->WallSZLineExpire = this->WallExceptionExpire =
this->WallGetpass = this->WallSetpass = this->WallForbid = this->WallDrop = false;
if (!OSNotifications.empty())
diff --git a/src/language.cpp b/src/language.cpp
index 3ef010034..31eb1f1f8 100644
--- a/src/language.cpp
+++ b/src/language.cpp
@@ -769,6 +769,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("Allowed to use BAN command"),
/* CHAN_LEVEL_TOPIC */
_("Allowed to use TOPIC command"),
+ /* CHAN_LEVEL_MODE */
+ _("Allowed to use MODE command"),
/* CHAN_LEVEL_INFO */
_("Allowed to use INFO command with ALL option"),
/* CHAN_LEVEL_AUTOOWNER */
@@ -1294,8 +1296,10 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("%s has been unbanned from %s."),
/* CHAN_TOPIC_SYNTAX */
_("TOPIC channel [topic]"),
- /* CHAN_CLEARUSERS */
+ /* CHAN_CLEARUSERS_SYNTAX */
_("CLEARUSERS \037channel\037"),
+ /* CHAN_CLEARED_USERS */
+ _("All users have been kicked from \2%s\2."),
/* CHAN_CLONED */
_("All settings from \002%s\002 have been transferred to \002%s\002"),
/* CHAN_CLONED_ACCESS */
@@ -1366,6 +1370,24 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_("KICK #channel nick [reason]"),
/* CHAN_BAN_SYNTAX */
_("BAN #channel nick [reason]"),
+ /* CHAN_MODE_SYNTAX */
+ _("MODE \037channel\037 {LOCK|SET} [\037modes\037 | {ADD|DEL|LIST} [\037what\037]]"),
+ /* CHAN_MODE_LOCK_UNKNOWN */
+ _("Unknown mode character %c ignored."),
+ /* CHAN_MODE_LOCK_MISSING_PARAM */
+ _("Missing parameter for mode %c."),
+ /* CHAN_MODE_LOCK_NONE */
+ _("Channel %s has no mode locks."),
+ /* CHAN_MODE_LOCK_HEADER */
+ _("Mode locks for %s:"),
+ /* CHAN_MODE_LOCKED */
+ _("%c%c%s locked on %s"),
+ /* CHAN_MODE_NOT_LOCKED */
+ _("%c is not locked on %s."),
+ /* CHAN_MODE_UNLOCKED */
+ _("%c%c%s has been unlocked from %s."),
+ /* CHAN_MODE_LIST_FMT */
+ _("%c%c%s, by %s on %s"),
/* MEMO_HAVE_NEW_MEMO */
_("You have 1 new memo."),
/* MEMO_HAVE_NEW_MEMOS */
@@ -3338,6 +3360,8 @@ const char *const language_strings[LANG_STRING_COUNT] = {
_(" DEOP Deops a selected nick on a channel"),
/* CHAN_HELP_CMD_CLONE */
_(" CLONE Copy all settings from one channel to another"),
+ /* CHAN_HELP_CMD_MODE */
+ _(" MODE Control modes and mode locks on a channel"),
/* CHAN_HELP */
_("%S allows you to register and control various\n"
"aspects of channels. %S can often prevent\n"
@@ -4062,6 +4086,26 @@ const char *const language_strings[LANG_STRING_COUNT] = {
"target channel. If access, akick, or badwords is specified then only\n"
"the respective settings are transferred. You must have founder level\n"
"access to \037channel\037 and \037target\037."),
+ /* CHAN_HELP_MODE */
+ _("Syntax: \002MODE \037channel\037 LOCK {ADD|DEL|LIST} [\037what\037]\002\n"
+ " \002MODE \037channel\037 SET \037modes\037\002\n"
+ " \n"
+ "Mainly controls mode locks and mode access (which is different from channel access)\n"
+ "on a channel.\n"
+ " \n"
+ "The \002MODE LOCK\002 command allows you to add, delete, and view mode locks on a channel.\n"
+ "If a mode is locked on or off, services will not allow that mode to be changed.\n"
+ "Example:\n"
+ " \002MODE #channel LOCK ADD +bmnt *!*@*aol*\002\n"
+ " \n"
+ "The \002MODE SET\002 command allows you to set modes through services. Wildcards * and ? may\n"
+ "be given as parameters for list and status modes.\n"
+ "Example:\n"
+ " \002MODE #channel SET +v *\002\n"
+ " Sets voice status to all users in the channel.\n"
+ " \n"
+ " \002MODE #channel SET -b ~c:*\n"
+ " Clears all extended bans that start with ~c:"),
/* CHAN_SERVADMIN_HELP */
_(" \n"
"Services Operators can also drop any channel without needing\n"
diff --git a/src/misc.cpp b/src/misc.cpp
index 7e02cc072..c885188f8 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -831,6 +831,74 @@ char *str_signed(unsigned char *str)
return nstr;
}
+bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive)
+{
+ size_t s = 0, m = 0, str_len = str.length(), mask_len = mask.length();
+
+ while (s < str_len && m < mask_len && mask[m] != '*')
+ {
+ char string = str[s], wild = mask[m];
+ if (case_sensitive)
+ {
+ if (wild != string && wild != '?')
+ return false;
+ }
+ else
+ {
+ if (tolower(wild) != tolower(string) && wild != '?')
+ return false;
+ }
+
+ ++m;
+ ++s;
+ }
+
+ size_t sp = Anope::string::npos, mp = Anope::string::npos;
+ while (s < str_len)
+ {
+ char string = str[s], wild = mask[m];
+ if (wild == '*')
+ {
+ if (++m == mask_len)
+ return 1;
+
+ mp = m;
+ sp = s + 1;
+ }
+ else if (case_sensitive)
+ {
+ if (wild == string || wild == '?')
+ {
+ ++m;
+ ++s;
+ }
+ else
+ {
+ m = mp;
+ s = sp++;
+ }
+ }
+ else
+ {
+ if (tolower(wild) == tolower(string) || wild == '?')
+ {
+ ++m;
+ ++s;
+ }
+ else
+ {
+ m = mp;
+ s = sp++;
+ }
+ }
+ }
+
+ if (mask[m] == '*')
+ ++m;
+
+ return m == mask_len;
+}
+
/*
* strlcat and strlcpy were ripped from openssh 2.5.1p2
* They had the following Copyright info:
@@ -1107,11 +1175,7 @@ uint16 netmask_to_cidr(uint32 mask)
*/
bool str_is_wildcard(const Anope::string &str)
{
- for (Anope::string::const_iterator c = str.begin(), c_end = str.end(); c != c_end; ++c)
- if (*c == '*' || *c == '?')
- return true;
-
- return false;
+ return str.find_first_of("*?") != Anope::string::npos;
}
/**
@@ -1121,11 +1185,7 @@ bool str_is_wildcard(const Anope::string &str)
*/
bool str_is_pure_wildcard(const Anope::string &str)
{
- for (Anope::string::const_iterator c = str.begin(), c_end = str.end(); c != c_end; ++c)
- if (*c != '*')
- return false;
-
- return true;
+ return str.find_first_not_of('*') == Anope::string::npos;
}
/*************************************************************************/
diff --git a/src/modes.cpp b/src/modes.cpp
index 6c6d43ad9..4d31f2232 100644
--- a/src/modes.cpp
+++ b/src/modes.cpp
@@ -27,53 +27,42 @@ std::map<ChannelModeName, ChannelMode *> ModeManager::ChannelModesByName;
/* Number of generic modes we support */
unsigned GenericChannelModes = 0, GenericUserModes = 0;
-/* Default mlocked modes on */
-Flags<ChannelModeName, CMODE_END * 2> DefMLockOn;
-/* Default mlocked modes off */
-Flags<ChannelModeName, CMODE_END * 2> DefMLockOff;
-/* Map for default mlocked mode parameters */
-std::map<ChannelModeName, Anope::string> DefMLockParams;
+/* Default mlocked modes */
+std::multimap<ChannelModeName, ModeLock> def_mode_locks;
/** Parse the mode string from the config file and set the default mlocked modes
*/
void SetDefaultMLock(ServerConfig *config)
{
- DefMLockOn.ClearFlags();
- DefMLockOff.ClearFlags();
- DefMLockParams.clear();
- Flags<ChannelModeName, CMODE_END * 2> *ptr = NULL;
+ def_mode_locks.clear();
- Anope::string modes, param;
+ Anope::string modes;
spacesepstream sep(config->MLock);
sep.GetToken(modes);
+ int adding = -1;
for (unsigned i = 0, end_mode = modes.length(); i < end_mode; ++i)
{
if (modes[i] == '+')
- ptr = &DefMLockOn;
+ adding = 1;
else if (modes[i] == '-')
- ptr = &DefMLockOff;
- else
+ adding = 0;
+ else if (adding != -1)
{
- if (!ptr)
- continue;
-
ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
- if (cm && (cm->Type == MODE_REGULAR || cm->Type == MODE_PARAM))
+ if (cm && cm->Type != MODE_STATUS)
{
- ptr->SetFlag(cm->Name);
-
- if (ptr == &DefMLockOn && cm->Type == MODE_PARAM)
+ Anope::string param;
+ if (adding == 1 && cm->Type != MODE_REGULAR && !sep.GetToken(param)) // MODE_LIST OR MODE_PARAM
{
- if (sep.GetToken(param))
- DefMLockParams.insert(std::make_pair(cm->Name, param));
- else
- {
- Log() << "Warning: Got default mlock mode " << cm->ModeChar << " with no param?";
- ptr->UnsetFlag(cm->Name);
- }
+ Log() << "Warning: Got default mlock mode " << cm->ModeChar << " with no param?";
+ continue;
}
+
+ if (cm->Type != MODE_LIST) // Only MODE_LIST can have duplicates
+ def_mode_locks.erase(cm->Name);
+ def_mode_locks.insert(std::make_pair(cm->Name, ModeLock(adding == 1, cm->Name, param)));
}
}
}
@@ -298,36 +287,20 @@ bool ChannelModeRegistered::CanSet(User *u) const
* @param chan The channel
* @param mask The ban
*/
-void ChannelModeBan::AddMask(Channel *chan, const Anope::string &mask)
+void ChannelModeBan::OnAdd(Channel *chan, const Anope::string &mask)
{
/* check for NULL values otherwise we will segfault */
if (!chan || mask.empty())
- {
- Log() << "add_ban called with NULL values";
return;
- }
-
- /* Check if the list already exists, if not create it.
- * Create a new ban and add it to the list.. ~ Viper */
- if (!chan->bans)
- chan->bans = list_create();
- Entry *ban = entry_add(chan->bans, mask);
- if (!ban)
- throw CoreException("Creating new ban entry failed");
-
- /* Check whether it matches a botserv bot after adding internally
- * and parsing it through cidr support. ~ Viper */
+ /* Check whether it matches a botserv bot */
if (!Config->s_BotServ.empty() && Config->BSSmartJoin && chan->ci && chan->ci->bi && chan->FindUser(chan->ci->bi))
{
BotInfo *bi = chan->ci->bi;
- if (entry_match(ban, bi->nick, bi->GetIdent(), bi->host, 0))
- {
- ircdproto->SendMode(bi, chan, "-b %s", mask.c_str());
- entry_delete(chan->bans, ban);
- return;
- }
+ Entry ban(mask);
+ if (ban.Matches(bi))
+ chan->RemoveMode(NULL, CMODE_BAN, mask);
}
Log(LOG_DEBUG) << "Added ban " << mask << " to channel " << chan->name;
@@ -337,41 +310,22 @@ void ChannelModeBan::AddMask(Channel *chan, const Anope::string &mask)
* @param chan The channel
* @param mask The ban
*/
-void ChannelModeBan::DelMask(Channel *chan, const Anope::string &mask)
+void ChannelModeBan::OnDel(Channel *chan, const Anope::string &mask)
{
- /* Sanity check as it seems some IRCD will just send -b without a mask */
- if (mask.empty() || !chan->bans || !chan->bans->count)
+ if (!chan || mask.empty())
return;
- Entry *ban = elist_find_mask(chan->bans, mask);
- if (ban)
- {
- entry_delete(chan->bans, ban);
-
- Log(LOG_DEBUG) << "Deleted ban " << mask << " from channel " << chan->name;
- }
+ Log(LOG_DEBUG) << "Deleted ban " << mask << " from channel " << chan->name;
}
/** Add an except to the channel
* @param chan The channel
* @param mask The except
*/
-void ChannelModeExcept::AddMask(Channel *chan, const Anope::string &mask)
+void ChannelModeExcept::OnAdd(Channel *chan, const Anope::string &mask)
{
if (!chan || mask.empty())
- {
- Log() << "add_exception called with NULL values";
return;
- }
-
- /* Check if the list already exists, if not create it.
- * Create a new exception and add it to the list.. ~ Viper */
- if (!chan->excepts)
- chan->excepts = list_create();
-
- Entry *exception = entry_add(chan->excepts, mask);
- if (!exception)
- throw CoreException("Creating new exception entry failed");
Log(LOG_DEBUG) << "Added except " << mask << " to channel " << chan->name;
}
@@ -380,40 +334,22 @@ void ChannelModeExcept::AddMask(Channel *chan, const Anope::string &mask)
* @param chan The channel
* @param mask The except
*/
-void ChannelModeExcept::DelMask(Channel *chan, const Anope::string &mask)
+void ChannelModeExcept::OnDel(Channel *chan, const Anope::string &mask)
{
- /* Sanity check as it seems some IRCD will just send -e without a mask */
- if (mask.empty() || !chan->excepts || !chan->excepts->count)
+ if (!chan || mask.empty())
return;
- Entry *exception = elist_find_mask(chan->excepts, mask);
- if (exception)
- {
- entry_delete(chan->excepts, exception);
- Log(LOG_DEBUG) << "Deleted except " << mask << " to channel " << chan->name;
- }
+ Log(LOG_DEBUG) << "Deleted except " << mask << " to channel " << chan->name;
}
/** Add an invex to the channel
* @param chan The channel
* @param mask The invex
*/
-void ChannelModeInvex::AddMask(Channel *chan, const Anope::string &mask)
+void ChannelModeInvex::OnAdd(Channel *chan, const Anope::string &mask)
{
if (!chan || mask.empty())
- {
- Log() << "add_invite called with NULL values";
return;
- }
-
- /* Check if the list already exists, if not create it.
- * Create a new invite and add it to the list.. ~ Viper */
- if (!chan->invites)
- chan->invites = list_create();
-
- Entry *invite = entry_add(chan->invites, mask);
- if (!invite)
- throw CoreException("Creating new invex entry failed");
Log(LOG_DEBUG) << "Added invite " << mask << " to channel " << chan->name;
@@ -423,18 +359,12 @@ void ChannelModeInvex::AddMask(Channel *chan, const Anope::string &mask)
* @param chan The channel
* @param mask The index
*/
-void ChannelModeInvex::DelMask(Channel *chan, const Anope::string &mask)
+void ChannelModeInvex::OnDel(Channel *chan, const Anope::string &mask)
{
- /* Sanity check as it seems some IRCD will just send -I without a mask */
- if (mask.empty() || !chan->invites || !chan->invites->count)
+ if (!chan || mask.empty())
return;
- Entry *invite = elist_find_mask(chan->invites, mask);
- if (invite)
- {
- entry_delete(chan->invites, invite);
- Log(LOG_DEBUG) << "Deleted invite " << mask << " to channel " << chan->name;
- }
+ Log(LOG_DEBUG) << "Deleted invite " << mask << " to channel " << chan->name;
}
void StackerInfo::AddMode(Mode *mode, bool Set, const Anope::string &Param)
diff --git a/src/operserv.cpp b/src/operserv.cpp
index 5f6f8c2be..727432585 100644
--- a/src/operserv.cpp
+++ b/src/operserv.cpp
@@ -428,7 +428,18 @@ XLine *XLineManager::Check(User *u)
if (!x->GetUser().empty() && !Anope::Match(u->GetIdent(), x->GetUser()))
continue;
- if (x->GetHost().empty() || (u->ip() && Anope::Match(u->ip.addr(), x->GetHost())) || Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost())))
+ if (u->ip() && !x->GetHost().empty())
+ {
+ try
+ {
+ cidr cidr_ip(x->GetHost());
+ if (cidr_ip.match(u->ip))
+ return x;
+ }
+ catch (const SocketException &) { }
+ }
+
+ if (x->GetHost().empty() || (Anope::Match(u->host, x->GetHost()) || (!u->chost.empty() && Anope::Match(u->chost, x->GetHost())) || (!u->vhost.empty() && Anope::Match(u->vhost, x->GetHost()))))
{
OnMatch(u, x);
return x;
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index b4c42cb82..8228e4ffb 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -33,9 +33,7 @@ ChannelInfo::ChannelInfo(const Anope::string &chname)
this->name = chname;
- this->mlock_on = DefMLockOn;
- this->mlock_off = DefMLockOff;
- this->Params = DefMLockParams;
+ this->mode_locks = def_mode_locks;
size_t t;
/* Set default channel flags */
@@ -392,7 +390,9 @@ void ChannelInfo::LoadMLock()
std::vector<Anope::string> modenames_on, modenames_off;
// Force +r
- this->SetMLock(CMODE_REGISTERED, true);
+ ChannelMode *chm = ModeManager::FindChannelModeByName(CMODE_REGISTERED);
+ if (chm)
+ this->SetMLock(chm, true);
this->GetExtRegular("db_mlock_modes_on", modenames_on);
this->GetExtRegular("db_mlock_modes_off", modenames_off);
@@ -405,7 +405,7 @@ void ChannelInfo::LoadMLock()
if (m && m->NameAsString.equals_cs(*it))
{
ChannelMode *cm = debug_cast<ChannelMode *>(m);
- this->SetMLock(cm->Name, true);
+ this->SetMLock(cm, true);
}
}
for (std::vector<Anope::string>::iterator it = modenames_off.begin(), it_end = modenames_off.end(); it != it_end; ++it)
@@ -415,7 +415,7 @@ void ChannelInfo::LoadMLock()
if (m && m->NameAsString.equals_cs(*it))
{
ChannelMode *cm = debug_cast<ChannelMode *>(m);
- this->SetMLock(cm->Name, false);
+ this->SetMLock(cm, false);
}
}
}
@@ -429,15 +429,28 @@ void ChannelInfo::LoadMLock()
if (m && m->Class == MC_CHANNEL)
{
ChannelMode *cm = debug_cast<ChannelMode *>(m);
- this->SetMLock(cm->Name, true, it->second);
+ this->SetMLock(cm, true, it->second);
}
}
}
+ if (this->GetExtRegular("db_mlp_off", params))
+ {
+ for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = params.begin(), it_end = params.end(); it != it_end; ++it)
+ {
+ Mode *m = ModeManager::FindModeByName(it->first);
+ if (m && m->Class == MC_CHANNEL)
+ {
+ ChannelMode *cm = debug_cast<ChannelMode *>(m);
+ this->SetMLock(cm, false, it->second);
+ }
+ }
+ }
this->Shrink("db_mlock_modes_on");
this->Shrink("db_mlock_modes_off");
this->Shrink("db_mlp");
+ this->Shrink("db_mlp_off");
/* Create perm channel */
if (this->HasFlag(CI_PERSIST) && !this->c)
@@ -453,132 +466,135 @@ void ChannelInfo::LoadMLock()
}
/** Check if a mode is mlocked
- * @param Name The mode
+ * @param mode The mode
* @param status True to check mlock on, false for mlock off
* @return true on success, false on fail
*/
-bool ChannelInfo::HasMLock(ChannelModeName Name, bool status) const
+bool ChannelInfo::HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const
{
- if (status)
- return this->mlock_on.HasFlag(Name);
- else
- return this->mlock_off.HasFlag(Name);
+ std::map<ChannelModeName, ModeLock>::const_iterator it = this->mode_locks.find(mode->Name);
+
+ if (it != this->mode_locks.end())
+ {
+ if (mode->Type != MODE_REGULAR)
+ {
+ std::map<ChannelModeName, ModeLock>::const_iterator it_end = this->mode_locks.upper_bound(mode->Name);
+ for (; it != it_end; ++it)
+ {
+ const ModeLock &ml = it->second;
+ if (ml.param == param)
+ return true;
+ }
+ }
+ else
+ return it->second.set == status;
+ }
+ return false;
}
/** Set a mlock
- * @param Name The mode
+ * @param mode The mode
* @param status True for mlock on, false for mlock off
* @param param The param to use for this mode, if required
* @return true on success, false on failure (module blocking)
*/
-bool ChannelInfo::SetMLock(ChannelModeName Name, bool status, const Anope::string &param)
+bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string &param, const Anope::string &setter, time_t created)
{
- if (!status && !param.empty())
- throw CoreException("Was told to mlock a mode negatively with a param?");
+ std::pair<ChannelModeName, ModeLock> ml = std::make_pair(mode->Name, ModeLock(status, mode->Name, param, setter, created));
EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnMLock, OnMLock(this, Name, status, param));
+ FOREACH_RESULT(I_OnMLock, OnMLock(this, &ml.second));
if (MOD_RESULT == EVENT_STOP)
return false;
- /* First, remove this everywhere */
- this->mlock_on.UnsetFlag(Name);
- this->mlock_off.UnsetFlag(Name);
-
- std::map<ChannelModeName, Anope::string>::iterator it = Params.find(Name);
- if (it != Params.end())
- Params.erase(it);
-
- if (status)
- this->mlock_on.SetFlag(Name);
- else
- this->mlock_off.SetFlag(Name);
-
- if (status && !param.empty())
- this->Params.insert(std::make_pair(Name, param));
+ /* First, remove this */
+ this->RemoveMLock(mode, param);
+
+ this->mode_locks.insert(ml);
return true;
}
/** Remove a mlock
- * @param Name The mode
- * @return true on success, false on failure (module blocking)
+ * @param mode The mode
+ * @param param The param of the mode, required if it is a list or status mode
+ * @return true on success, false on failure
*/
-bool ChannelInfo::RemoveMLock(ChannelModeName Name)
+bool ChannelInfo::RemoveMLock(ChannelMode *mode, const Anope::string &param)
{
EventReturn MOD_RESULT;
- FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, Name));
+ FOREACH_RESULT(I_OnUnMLock, OnUnMLock(this, mode, param));
if (MOD_RESULT == EVENT_STOP)
return false;
- this->mlock_on.UnsetFlag(Name);
- this->mlock_off.UnsetFlag(Name);
-
- std::map<ChannelModeName, Anope::string>::iterator it = Params.find(Name);
- if (it != Params.end())
- this->Params.erase(it);
+ if (mode->Type == MODE_REGULAR || mode->Type == MODE_PARAM)
+ return this->mode_locks.erase(mode->Name) > 0;
+ else
+ {
+ // For list or status modes, we must check the parameter
+ std::multimap<ChannelModeName, ModeLock>::iterator it = this->mode_locks.find(mode->Name), it_end = this->mode_locks.upper_bound(mode->Name);
+ for (; it != it_end; ++it)
+ {
+ const ModeLock &ml = it->second;
+ if (ml.param == param)
+ {
+ this->mode_locks.erase(it);
+ return true;
+ }
+ }
- return true;
+ return false;
+ }
}
/** Clear all mlocks on the channel
*/
void ChannelInfo::ClearMLock()
{
- this->mlock_on.ClearFlags();
- this->mlock_off.ClearFlags();
+ this->mode_locks.clear();
}
-/** Get the number of mlocked modes for this channel
- * @param status true for mlock on, false for mlock off
- * @return The number of mlocked modes
+/** Get all of the mlocks for this channel
+ * @return The mlocks
*/
-size_t ChannelInfo::GetMLockCount(bool status) const
+const std::multimap<ChannelModeName, ModeLock> &ChannelInfo::GetMLock() const
{
- if (status)
- return this->mlock_on.FlagCount();
- else
- return this->mlock_off.FlagCount();
+ return this->mode_locks;
}
-/** Get a param from the channel
- * @param Name The mode
- * @param Target a string to put the param into
- * @return true on success
+/** 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 ChannelInfo::GetParam(ChannelModeName Name, Anope::string &Target) const
+std::pair<ChannelInfo::ModeList::iterator, ChannelInfo::ModeList::iterator> ChannelInfo::GetModeList(ChannelModeName Name)
{
- std::map<ChannelModeName, Anope::string>::const_iterator it = this->Params.find(Name);
-
- Target.clear();
-
- if (it != this->Params.end())
- {
- Target = it->second;
- return true;
- }
-
- return false;
+ return std::make_pair(this->mode_locks.find(Name), this->mode_locks.upper_bound(Name));
}
-/** Check if a mode is set and has a param
- * @param Name The mode
+/** Get details for a specific mlock
+ * @param name The mode name
+ * @param param An optional param to match with
+ * @return The MLock, if any
*/
-bool ChannelInfo::HasParam(ChannelModeName Name) const
+ModeLock *ChannelInfo::GetMLock(ChannelModeName name, const Anope::string &param)
{
- std::map<ChannelModeName, Anope::string>::const_iterator it = this->Params.find(Name);
-
- if (it != this->Params.end())
- return true;
-
- return false;
-}
+ std::multimap<ChannelModeName, ModeLock>::iterator it = this->mode_locks.find(name);
+ if (it != this->mode_locks.end())
+ {
+ if (param.empty())
+ return &it->second;
+ else
+ {
+ std::multimap<ChannelModeName, ModeLock>::iterator it_end = this->mode_locks.upper_bound(name);
+ for (; it != it_end; ++it)
+ {
+ if (Anope::Match(param, it->second.param))
+ return &it->second;
+ }
+ }
+ }
-/** Clear all the params from the channel
- */
-void ChannelInfo::ClearParams()
-{
- Params.clear();
+ return NULL;
}
/** Check whether a user is permitted to be on this channel
diff --git a/src/sockets.cpp b/src/sockets.cpp
index 9e32f85eb..0eb7733cf 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -171,6 +171,80 @@ void sockaddrs::ntop(int type, const void *src)
throw CoreException("Invalid socket type");
}
+cidr::cidr(const Anope::string &ip)
+{
+ if (ip.find_first_not_of("01234567890:./") != Anope::string::npos)
+ throw SocketException("Invalid IP");
+
+ bool ipv6 = ip.find(':') != Anope::string::npos;
+ size_t sl = ip.find_last_of('/');
+ if (sl == Anope::string::npos)
+ {
+ this->cidr_ip = ip;
+ this->cidr_len = ipv6 ? 128 : 32;
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip);
+ }
+ else
+ {
+ Anope::string real_ip = ip.substr(0, sl);
+ Anope::string cidr_range = ip.substr(sl + 1);
+ if (!cidr_range.is_pos_number_only())
+ throw SocketException("Invalid CIDR range");
+
+ this->cidr_ip = real_ip;
+ this->cidr_len = convertTo<unsigned int>(cidr_range);
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, real_ip);
+ }
+}
+
+cidr::cidr(const Anope::string &ip, unsigned char len)
+{
+ bool ipv6 = ip.find(':') != Anope::string::npos;
+ this->addr.pton(ipv6 ? AF_INET6 : AF_INET, ip);
+ this->cidr_ip = ip;
+ this->cidr_len = len;
+}
+
+Anope::string cidr::mask() const
+{
+ return this->cidr_ip + "/" + this->cidr_len;
+}
+
+bool cidr::match(sockaddrs &other)
+{
+ if (this->addr.sa.sa_family != other.sa.sa_family)
+ return false;
+
+ unsigned char *ip, *their_ip, byte;
+
+ switch (this->addr.sa.sa_family)
+ {
+ case AF_INET:
+ ip = reinterpret_cast<unsigned char *>(&this->addr.sa4.sin_addr);
+ byte = this->cidr_len / 8;
+ their_ip = reinterpret_cast<unsigned char *>(&other.sa4.sin_addr);
+ break;
+ case AF_INET6:
+ ip = reinterpret_cast<unsigned char *>(&this->addr.sa6.sin6_addr);
+ byte = this->cidr_len / 8;
+ their_ip = reinterpret_cast<unsigned char *>(&other.sa6.sin6_addr);
+ break;
+ default:
+ throw SocketException("Invalid address type");
+ }
+
+ if (memcmp(ip, their_ip, byte))
+ return false;
+
+ ip += byte;
+ their_ip += byte;
+ byte = this->cidr_len % 8;
+ if ((*ip & byte) != (*their_ip & byte))
+ return false;
+
+ return true;
+}
+
/** Default constructor
*/
SocketEngineBase::SocketEngineBase()
diff --git a/src/users.cpp b/src/users.cpp
index 27426819b..ac16c61ac 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -165,6 +165,11 @@ Anope::string User::GetMask() const
return this->nick + "!" + this->ident + "@" + this->host;
}
+Anope::string User::GetDisplayedMask() const
+{
+ return this->nick + "!" + this->GetVIdent() + "@" + this->GetDisplayedHost();
+}
+
void User::SetRealname(const Anope::string &srealname)
{
if (srealname.empty())
@@ -921,7 +926,16 @@ bool is_excepted(ChannelInfo *ci, User *user)
if (!ci->c || !ModeManager::FindChannelModeByName(CMODE_EXCEPT))
return false;
- return elist_match_user(ci->c->excepts, user);
+
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList(CMODE_EXCEPT);
+ for (; modes.first != modes.second; ++modes.first)
+ {
+ Entry e(modes.first->second);
+ if (e.Matches(user))
+ return true;
+ }
+
+ return false;
}
/*************************************************************************/
@@ -932,7 +946,14 @@ bool is_excepted_mask(ChannelInfo *ci, const Anope::string &mask)
if (!ci->c || !ModeManager::FindChannelModeByName(CMODE_EXCEPT))
return false;
- return elist_match_mask(ci->c->excepts, mask, 0);
+ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = ci->c->GetModeList(CMODE_EXCEPT);
+ for (; modes.first != modes.second; ++modes.first)
+ {
+ if (Anope::Match(modes.first->second, mask))
+ return true;
+ }
+
+ return false;
}
/*************************************************************************/
diff --git a/src/wildcard.cpp b/src/wildcard.cpp
deleted file mode 100644
index c6883a4bc..000000000
--- a/src/wildcard.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "services.h"
-
-bool Anope::Match(const Anope::string &str, const Anope::string &mask, bool case_sensitive)
-{
- size_t s = 0, m = 0, str_len = str.length(), mask_len = mask.length();
-
- while (s < str_len && m < mask_len && mask[m] != '*')
- {
- char string = str[s], wild = mask[m];
- if (case_sensitive)
- {
- if (wild != string && wild != '?')
- return false;
- }
- else
- {
- if (tolower(wild) != tolower(string) && wild != '?')
- return false;
- }
-
- ++m;
- ++s;
- }
-
- size_t sp = 0, mp = 0;
- while (s < str_len)
- {
- char string = str[s], wild = mask[m];
- if (wild == '*')
- {
- if (++m == mask_len)
- return 1;
-
- mp = m;
- sp = s + 1;
- }
- else
- {
- if (case_sensitive)
- {
- if (wild == string || wild == '?')
- {
- ++m;
- ++s;
- }
- else
- {
- m = mp;
- s = sp++;
- }
- }
- else
- {
- if (tolower(wild) == tolower(string) || wild == '?')
- {
- ++m;
- ++s;
- }
- else
- {
- m = mp;
- s = sp++;
- }
- }
- }
- }
-
- if (mask[m] == '*')
- ++m;
-
- return m == mask_len;
-}