summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/botserv.example.conf80
-rw-r--r--data/chanserv.example.conf70
-rw-r--r--data/example.conf1
-rw-r--r--data/nickserv.example.conf54
-rw-r--r--include/account.h73
-rw-r--r--include/channels.h2
-rw-r--r--include/defs.h1
-rw-r--r--include/extensible.h295
-rw-r--r--include/lists.h1
-rw-r--r--include/modules.h23
-rw-r--r--include/modules/bs_badwords.h70
-rw-r--r--include/modules/bs_kick.h45
-rw-r--r--include/modules/cs_log.h41
-rw-r--r--include/modules/cs_mode.h87
-rw-r--r--include/modules/cs_suspend.h19
-rw-r--r--include/modules/ns_cert.h61
-rw-r--r--include/modules/ns_suspend.h19
-rw-r--r--include/regchannel.h206
-rw-r--r--include/service.h2
-rw-r--r--modules/commands/bs_assign.cpp65
-rw-r--r--modules/commands/bs_badwords.cpp187
-rw-r--r--modules/commands/bs_info.cpp127
-rw-r--r--modules/commands/bs_kick.cpp623
-rw-r--r--modules/commands/bs_set.cpp317
-rw-r--r--modules/commands/cs_akick.cpp2
-rw-r--r--modules/commands/cs_clone.cpp19
-rw-r--r--modules/commands/cs_drop.cpp13
-rw-r--r--modules/commands/cs_enforce.cpp4
-rw-r--r--modules/commands/cs_entrymsg.cpp48
-rw-r--r--modules/commands/cs_info.cpp45
-rw-r--r--modules/commands/cs_list.cpp83
-rw-r--r--modules/commands/cs_log.cpp126
-rw-r--r--modules/commands/cs_mode.cpp368
-rw-r--r--modules/commands/cs_seen.cpp2
-rw-r--r--modules/commands/cs_set.cpp263
-rw-r--r--modules/commands/cs_set_misc.cpp57
-rw-r--r--modules/commands/cs_suspend.cpp131
-rw-r--r--modules/commands/cs_topic.cpp129
-rw-r--r--modules/commands/greet.cpp210
-rw-r--r--modules/commands/hs_request.cpp60
-rw-r--r--modules/commands/ms_info.cpp9
-rw-r--r--modules/commands/ms_set.cpp36
-rw-r--r--modules/commands/ns_ajoin.cpp53
-rw-r--r--modules/commands/ns_alist.cpp6
-rw-r--r--modules/commands/ns_cert.cpp224
-rw-r--r--modules/commands/ns_group.cpp10
-rw-r--r--modules/commands/ns_info.cpp170
-rw-r--r--modules/commands/ns_list.cpp112
-rw-r--r--modules/commands/ns_recover.cpp49
-rw-r--r--modules/commands/ns_register.cpp63
-rw-r--r--modules/commands/ns_resetpass.cpp28
-rw-r--r--modules/commands/ns_set.cpp427
-rw-r--r--modules/commands/ns_set_misc.cpp57
-rw-r--r--modules/commands/ns_suspend.cpp125
-rw-r--r--modules/commands/os_defcon.cpp20
-rw-r--r--modules/commands/os_login.cpp21
-rw-r--r--modules/commands/os_noop.cpp20
-rw-r--r--modules/database/db_old.cpp175
-rw-r--r--modules/database/db_plain.cpp339
-rw-r--r--modules/extra/m_chanstats.cpp16
-rw-r--r--modules/extra/m_ldap_authentication.cpp15
-rw-r--r--modules/extra/webcpanel/pages/chanserv/set.cpp40
-rw-r--r--modules/extra/webcpanel/pages/index.cpp4
-rw-r--r--modules/extra/webcpanel/pages/logout.cpp4
-rw-r--r--modules/extra/webcpanel/pages/nickserv/alist.cpp4
-rw-r--r--modules/extra/webcpanel/pages/nickserv/cert.cpp7
-rw-r--r--modules/extra/webcpanel/pages/nickserv/info.cpp54
-rw-r--r--modules/extra/webcpanel/webcpanel.cpp3
-rw-r--r--modules/extra/webcpanel/webcpanel.h2
-rw-r--r--modules/fantasy.cpp200
-rw-r--r--modules/m_dnsbl.cpp4
-rw-r--r--modules/m_helpchan.cpp4
-rw-r--r--modules/protocol/charybdis.cpp19
-rw-r--r--modules/protocol/inspircd12.cpp5
-rw-r--r--modules/protocol/inspircd20.cpp18
-rw-r--r--modules/protocol/unreal.cpp24
-rw-r--r--modules/pseudoclients/botserv.cpp138
-rw-r--r--modules/pseudoclients/chanserv.cpp104
-rw-r--r--modules/pseudoclients/nickserv.cpp126
-rw-r--r--src/bots.cpp4
-rw-r--r--src/channels.cpp72
-rw-r--r--src/config.cpp4
-rw-r--r--src/extensible.cpp101
-rw-r--r--src/misc.cpp21
-rw-r--r--src/nickalias.cpp13
-rw-r--r--src/nickcore.cpp72
-rw-r--r--src/regchannel.cpp498
-rw-r--r--src/serialize.cpp5
-rw-r--r--src/sockets.cpp2
-rw-r--r--src/users.cpp5
90 files changed, 3994 insertions, 3567 deletions
diff --git a/data/botserv.example.conf b/data/botserv.example.conf
index 1bd450123..299289416 100644
--- a/data/botserv.example.conf
+++ b/data/botserv.example.conf
@@ -100,13 +100,6 @@ module
#smartjoin = yes
/*
- * Defines the prefixes for fantasy commands in channels. One of these characters will have to be prepended
- * to all fantasy commands. If you choose "!", for example, fantasy commands will be "!kick",
- * "!op", etc. This directive is optional, if left out, the default fantasy character is "!".
- */
- #fantasycharacter = "!."
-
- /*
* Modes to set on service bots when they join channels, comment this out for no modes
*
* This directive is optional.
@@ -137,13 +130,17 @@ command { service = "BotServ"; name = "HELP"; command = "generic/help"; }
/*
* bs_assign
*
- * Provides the commands botserv/assign and botserv/unassign.
+ * Provides the commands:
+ * botserv/assign - Used to assign BotServ bots to channels
+ * botserv/unassign - Used to unassign BotServ bots
+ * botserv/set/nobot - Used to prohibit channels from being assigned BotServ bots.
*
* Used for assigning and unassigning bots to channels.
*/
module { name = "bs_assign" }
command { service = "BotServ"; name = "ASSIGN"; command = "botserv/assign"; }
command { service = "BotServ"; name = "UNASSIGN"; command = "botserv/unassign"; }
+command { service = "BotServ"; name = "SET NOBOT"; command = "botserv/set/nobot"; permission = "botserv/set/nobot"; }
/*
* bs_autoassign
@@ -240,6 +237,8 @@ command { service = "BotServ"; name = "INFO"; command = "botserv/info"; }
* botserv/kick/repeat - Configures BotServ's repeat kicker.
* botserv/kick/reverses - Configures BotServ's reverse kicker.
* botserv/kick/underlines - Configures BotServ's reverse kicker.
+ * botserv/set/dontkickops - Used for preventing BotServ from kicking channel operators.
+ * botserv/set/dontkickvoices - Used for preventing BotServ from kicking voices.
*
* Used for configuring what bots should kick for.
*/
@@ -275,30 +274,71 @@ command { service = "BotServ"; name = "KICK REPEAT"; command = "botserv/kick/rep
command { service = "BotServ"; name = "KICK REVERSES"; command = "botserv/kick/reverses"; }
command { service = "BotServ"; name = "KICK UNDERLINES"; command = "botserv/kick/underlines"; }
+command { service = "BotServ"; name = "SET DONTKICKOPS"; command = "botserv/set/dontkickops"; }
+command { service = "BotServ"; name = "SET DONTKICKVOICES"; command = "botserv/set/dontkickvoices"; }
+
/*
* bs_set
*
* Provides the commands:
- * botserv/set/dontkickops - Used for preventing BotServ from kicking channel operators.
- * botserv/set/dontkickvoices - Used for preventing BotServ from kicking voices.
- * botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
- * botserv/set/greet - Used for enabling or disabling BotServ's greet messages in a channel.
- * botserv/set/nobot - Used to prohibit specific channels from being assigned BotServ bots.
* botserv/set/private - Used to prohibit specific BotServ bots from being assigned to channels.
- *
- * Used for setting options such as kickers and fantasy replies.
*/
module { name = "bs_set" }
command { service = "BotServ"; name = "SET"; command = "botserv/set"; }
command { service = "BotServ"; name = "SET BANEXPIRE"; command = "botserv/set/banexpire"; }
-command { service = "BotServ"; name = "SET DONTKICKOPS"; command = "botserv/set/dontkickops"; }
-command { service = "BotServ"; name = "SET DONTKICKVOICES"; command = "botserv/set/dontkickvoices"; }
-command { service = "BotServ"; name = "SET FANTASY"; command = "botserv/set/fantasy"; }
-command { service = "BotServ"; name = "SET GREET"; command = "botserv/set/greet"; }
-command { service = "BotServ"; name = "SET NOBOT"; command = "botserv/set/nobot"; permission = "botserv/set/nobot"; }
command { service = "BotServ"; name = "SET PRIVATE"; command = "botserv/set/private"; permission = "botserv/set/private"; }
/*
+ * greet
+ *
+ * Provides the commands:
+ * botserv/set/greet - Used for enabling or disabling BotServ's greet messages in a channel.
+ * nickserv/set/greet, nickserv/saset/greet - Used for changing a users greet message, which is displayed when they enter channels.
+ */
+module { name = "greet" }
+command { service = "BotServ"; name = "SET GREET"; command = "botserv/set/greet"; }
+command { service = "NickServ"; name = "SET GREET"; command = "nickserv/set/greet"; }
+command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/greet"; permission = "nickserv/saset/greet"; }
+
+/*
+ * GREET privilege.
+ *
+ * Used by 'greet'.
+ *
+ * Users with this privilege have their greet shown when they join channels.
+ */
+privilege
+{
+ name = "GREET"
+ rank = 40
+ level = 5
+ flag = "g"
+ xop = "AOP"
+}
+
+
+/*
+ * fantasy
+ *
+ * Allows 'fantaisist' commands to be used in channels.
+ *
+ * Provides the commands:
+ * botserv/set/fantasy - Used for enabling or disabling BotServ's fantasist commands.
+ */
+module
+{
+ name = "fantasy"
+
+ /*
+ * Defines the prefixes for fantasy commands in channels. One of these characters will have to be prepended
+ * to all fantasy commands. If you choose "!", for example, fantasy commands will be "!kick",
+ * "!op", etc. This directive is optional, if left out, the default fantasy character is "!".
+ */
+ #fantasycharacter = "!."
+}
+command { service = "BotServ"; name = "SET FANTASY"; command = "botserv/set/fantasy"; }
+
+/*
* Fantasy commands
*
* Fantasy commands can be executed in channels that have a BotServ bot by prefixing the
diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf
index 6dc40991a..184c170fd 100644
--- a/data/chanserv.example.conf
+++ b/data/chanserv.example.conf
@@ -74,9 +74,9 @@ module
* - keeptopic: Retain topic when the channel is not in use
* - peace: Disallow users from kicking or removing modes from others who are of the same
* access level or superior
- * - private: Hide the channel from ChanServ's LIST command
+ * - cs_private: Hide the channel from ChanServ's LIST command
* - restricted: Kick/ban users who are restricted from the channel
- * - secure: Enable channel security, requiring the user to be identified with NickServ in
+ * - cs_secure: Enable channel security, requiring the user to be identified with NickServ in
* order to be considered for being on the access list of the channel
* - secureops: Only allow operator status to be given if the user is on the access list
* - securefounder: Only allow the real founder of the channel to drop the channel, change it's
@@ -89,10 +89,10 @@ module
* - noautoop: Disables autoop on the channel
* - none: No defaults
*
- * This directive is optional, if left blank, the options will default to keeptopic, secure, securefounder,
+ * This directive is optional, if left blank, the options will default to keeptopic, cs_secure, securefounder,
* and signkick. If you really want no defaults, use "none" by itself as the option.
*/
- defaults = "keeptopic peace secure securefounder signkick"
+ defaults = "keeptopic peace cs_secure securefounder signkick"
/*
* The maximum number of channels which may be registered to a single nickname.
@@ -111,18 +111,6 @@ module
expire = 14d
/*
- * The default ban type for newly registered channels.
- *
- * defbantype can be:
- *
- * 0: ban in the form of *!user@host
- * 1: ban in the form of *!*user@host
- * 2: ban in the form of *!*@host
- * 3: ban in the form of *!*user@*.domain
- */
- defbantype = 2
-
- /*
* The maximum number of entries on a channel's access list.
*/
accessmax = 1024
@@ -424,22 +412,6 @@ privilege
}
/*
- * GREET privilege.
- *
- * Used by botserv/main.
- *
- * Users with this permission get their greet shown on join.
- */
-privilege
-{
- name = "GREET"
- rank = 40
- level = 5
- flag = "g"
- xop = "AOP"
-}
-
-/*
* HALFOP privilege.
*
* Used by chanserv/mode, chanserv/halfop and chanserv/dehalfop.
@@ -983,9 +955,9 @@ command { service = "ChanServ"; name = "KICK"; command = "chanserv/kick"; }
/*
* cs_list
*
- * Provides the command chanserv/list.
- *
- * Used for retrieving and searching the registered channel list.
+ * Provides the commands:
+ * chanserv/list - Used for retrieving and searching the registered channel list.
+ * chanserv/set/private - Used for setting whether channels should show up in chanserv/list.
*/
module
{
@@ -998,6 +970,7 @@ module
}
command { service = "ChanServ"; name = "LIST"; command = "chanserv/list"; permission = "chanserv/list"; group = "chanserv/admin"; }
+command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; }
/*
* cs_log
@@ -1057,10 +1030,8 @@ cs_seen
* chanserv/set/bantype - Used for controlling what format of bans are placed on channels.
* chanserv/set/description - Used for changing channels descriptions.
* chanserv/set/founder - Used for changing a channel's founder.
- * chanserv/set/keeptopic - Used for configuring if ChanServ is to restore the channel topic when a channel is created.
* chanserv/set/peace - Used for configuring if users are able to kick other users with higher access than them.
* chanserv/set/persist - Used for setting whether ChanServ should stay in channels after the last user leaves.
- * chanserv/set/private - Used for setting whether channels should show up in chanserv/list.
* chanserv/set/restricted - Used for setting whether users not on a channel's access list can join.
* chanserv/set/secure - Used for setting whether users who are recognized for accounts should have their access in channels.
* chanserv/set/securefounder - Used for setting whether users with founder level access in channels have true founder or not.
@@ -1071,7 +1042,22 @@ cs_seen
*
* This is a dummy command to provide a help wrapper for the various SET commands.
*/
-module { name = "cs_set" }
+module
+{
+ name = "cs_set"
+
+ /*
+ * The default ban type for newly registered channels.
+ *
+ * defbantype can be:
+ *
+ * 0: ban in the form of *!user@host
+ * 1: ban in the form of *!*user@host
+ * 2: ban in the form of *!*@host
+ * 3: ban in the form of *!*user@*.domain
+ */
+ defbantype = 2
+}
command { service = "ChanServ"; name = "SET"; command = "chanserv/set"; group = "chanserv/management"; }
command { service = "ChanServ"; name = "SET AUTOOP"; command = "chanserv/set/autoop"; }
@@ -1079,10 +1065,8 @@ command { service = "ChanServ"; name = "SET BANTYPE"; command = "chanserv/set/ba
command { service = "ChanServ"; name = "SET DESCRIPTION"; command = "chanserv/set/description"; }
command { service = "ChanServ"; name = "SET DESC"; command = "chanserv/set/description"; }
command { service = "ChanServ"; name = "SET FOUNDER"; command = "chanserv/set/founder"; }
-command { service = "ChanServ"; name = "SET KEEPTOPIC"; command = "chanserv/set/keeptopic"; }
command { service = "ChanServ"; name = "SET PEACE"; command = "chanserv/set/peace"; }
command { service = "ChanServ"; name = "SET PERSIST"; command = "chanserv/set/persist"; }
-command { service = "ChanServ"; name = "SET PRIVATE"; command = "chanserv/set/private"; }
command { service = "ChanServ"; name = "SET RESTRICTED"; command = "chanserv/set/restricted"; }
command { service = "ChanServ"; name = "SET SECURE"; command = "chanserv/set/secure"; }
command { service = "ChanServ"; name = "SET SECUREFOUNDER"; command = "chanserv/set/securefounder"; }
@@ -1149,12 +1133,14 @@ command { service = "ChanServ"; name = "SYNC"; command = "chanserv/sync"; group
/*
* cs_topic
*
- * Provides the command chanserv/topic.
+ * Provides the commands:
+ * chanserv/topic - Used for changing the channel topic. Useful in conjunction with chanserv/set/topiclock.
+ * chanserv/set/keeptopic - Used for configuring if ChanServ is to restore the channel topic when a channel is created.
*
- * Used for changing the channel topic. Useful in conjunction with chanserv/set/topiclock.
*/
module { name = "cs_topic" }
command { service = "ChanServ"; name = "TOPIC"; command = "chanserv/topic"; group = "chanserv/management"; }
+command { service = "ChanServ"; name = "SET KEEPTOPIC"; command = "chanserv/set/keeptopic"; }
/*
* cs_unban
diff --git a/data/example.conf b/data/example.conf
index b8ec96a9c..41a1a0163 100644
--- a/data/example.conf
+++ b/data/example.conf
@@ -1109,6 +1109,7 @@ mail
* [DEPRECATED] db_plain
*
* This is the flatfile database format from Anope-1.9.2 to Anope-1.9.5.
+ * This module only loads this database, and will NOT save it.
* To convert from this format, load both this and db_flatfile. Be sure to name db_flatfile's
* target database to something else. Start Anope then shut down so the new database will be written.
* Then unload this and restart Anope, loading from the new database.
diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf
index 36eec61e1..dab48996a 100644
--- a/data/nickserv.example.conf
+++ b/data/nickserv.example.conf
@@ -94,9 +94,9 @@ module
* - killprotect: Kill nick if not identified within 60 seconds
* - kill_quick: Kill nick if not identified within 20 seconds, this one overrides the above
* option and the above must be specified with this one
- * - secure: Enable nickname security, requiring the nick's password before any operations
+ * - ns_secure: Enable nickname security, requiring the nick's password before any operations
* can be done on it
- * - private: Hide the nick from NickServ's LIST command
+ * - ns_private: Hide the nick from NickServ's LIST command
* - hide_email: Hide's the nick's e-mail address from NickServ's INFO command
* - hide_mask: Hide's the nick's last or current user@host from NickServ's INFO command
* - hide_quit: Hide's the nick's last quit message
@@ -106,10 +106,10 @@ module
* - msg: Services messages will be sent as PRIVMSGs instead of NOTICEs, requires
* options:useprivmsg to be enabled as well
*
- * This directive is optional, if left blank, the options will default to secure, memo_signon, and
+ * This directive is optional, if left blank, the options will default to ns_secure, memo_signon, and
* memo_receive. If you really want no defaults, use "none" by itself as the option.
*/
- defaults = "secure private hide_email hide_mask memo_signon memo_receive autoop"
+ defaults = "ns_secure ns_private hide_email hide_mask memo_signon memo_receive autoop"
/*
* The minimum length of time between consecutive uses of NickServ's REGISTER command. This
@@ -125,14 +125,6 @@ module
expire = 21d
/*
- * The length of time a user using an unconfirmed account has
- * before the account will be released for general use again.
- *
- * This directive is only required if the e-mail registration option is enabled.
- */
- #unconfirmedexpire = 1d
-
- /*
* Prevents the use of the ACCESS (excluding the LIST subcommand), DROP, FORBID, SUSPEND,
* GETPASS and SET PASSWORD commands by services operators on other services operators.
*
@@ -350,19 +342,24 @@ command { service = "NickServ"; name = "IDENTIFY"; command = "nickserv/identify"
/*
* ns_info
*
- * Provides the command nickserv/info.
+ * Provides the commands:
+ * nickserv/info. - Used for gathering information about an account.
+ * nickserv/set/hide, nickserv/saset/hide - Used for configuring which options are publically shown in nickserv/info.
*
- * Used for gathering information about an account.
*/
module { name = "ns_info" }
command { service = "NickServ"; name = "INFO"; command = "nickserv/info"; }
+command { service = "NickServ"; name = "SET HIDE"; command = "nickserv/set/hide"; }
+command { service = "NickServ"; name = "SASET HIDE"; command = "nickserv/saset/hide"; permission = "nickserv/saset/hide"; }
+
/*
* ns_list
*
- * Provides the command nickserv/list.
+ * Provides the commands:
+ * nickserv/list - Used for retrieving and searching the registered account list.
+ * nickserv/set/private, nickserv/saset/private - Used for configuring whether or a users account shows up in nickserv/list.
*
- * Used for retrieving and searching the registered account list.
*/
module
{
@@ -375,6 +372,9 @@ module
}
command { service = "NickServ"; name = "LIST"; command = "nickserv/list"; group = "nickserv/admin"; }
+command { service = "NickServ"; name = "SET PRIVATE"; command = "nickserv/set/private"; }
+command { service = "NickServ"; name = "SASET PRIVATE"; command = "nickserv/saset/private"; permission = "nickserv/saset/private"; }
+
/*
* ns_logout
*
@@ -441,6 +441,12 @@ module
* This directive is optional.
*/
#nickregdelay = 30s
+
+ /*
+ * The length of time a user using an unconfirmed account has
+ * before the account will be released for general use again.
+ */
+ #unconfirmedexpire = 1d
}
command { service = "NickServ"; name = "CONFIRM"; command = "nickserv/confirm"; }
@@ -465,17 +471,12 @@ command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpas
* nickserv/set/autoop, nickserv/saset/autoop - Determines whether or not modes are automatically set users when joining a channel.
* nickserv/set/display, nickserv/saset/display - Used for setting a users display name.
* nickserv/set/email, nickserv/saset/email - Used for setting a users email address.
- * nickserv/set/greet, nickserv/saset/greet - Used for changing a users greet message, which is displayed when they enter channels.
- * nicksrev/set/hide, nickserv/saset/hide - Used for configuring which options are publically shown in nickserv/info for users account.
* nickserv/set/kill, nickserv/saset/kill - Used for configuring nickname protection.
* nickserv/set/language, nickserv/saset/language - Used for configuring what language services use.
* nickserv/set/message, nickserv/saset/message - Used to configure how services send messages to you.
- * nickserv/set/password, nickserv/saset/password - Used for changing a users greet password.
- * nickserv/set/private, nickserv/saset/private - Used for configuring whether or a users account shows up in nickserv/list.
+ * nickserv/set/password, nickserv/saset/password - Used for changing a users password.
* nickserv/set/secure, nickserv/saset/secure - Used for configuring whether a user can identify by simply being recognized by nickserv/access.
* nickserv/saset/noexpire - Used for configuring noexpire, which prevents nicks from expiring.
- *
- * This is a dummy command to provide a help wrapper for the various SET and SASET commands.
*/
module
{
@@ -502,12 +503,6 @@ command { service = "NickServ"; name = "SASET DISPLAY"; command = "nickserv/sase
command { service = "NickServ"; name = "SET EMAIL"; command = "nickserv/set/email"; }
command { service = "NickServ"; name = "SASET EMAIL"; command = "nickserv/saset/email"; permission = "nickserv/saset/email"; }
-command { service = "NickServ"; name = "SET GREET"; command = "nickserv/set/greet"; }
-command { service = "NickServ"; name = "SASET GREET"; command = "nickserv/saset/greet"; permission = "nickserv/saset/greet"; }
-
-command { service = "NickServ"; name = "SET HIDE"; command = "nickserv/set/hide"; }
-command { service = "NickServ"; name = "SASET HIDE"; command = "nickserv/saset/hide"; permission = "nickserv/saset/hide"; }
-
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
@@ -520,9 +515,6 @@ command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/sase
command { service = "NickServ"; name = "SET PASSWORD"; command = "nickserv/set/password"; }
command { service = "NickServ"; name = "SASET PASSWORD"; command = "nickserv/saset/password"; permission = "nickserv/saset/password"; }
-command { service = "NickServ"; name = "SET PRIVATE"; command = "nickserv/set/private"; }
-command { service = "NickServ"; name = "SASET PRIVATE"; command = "nickserv/saset/private"; permission = "nickserv/saset/private"; }
-
command { service = "NickServ"; name = "SET SECURE"; command = "nickserv/set/secure"; }
command { service = "NickServ"; name = "SASET SECURE"; command = "nickserv/saset/secure"; permission = "nickserv/saset/secure"; }
diff --git a/include/account.h b/include/account.h
index 4d6bd714f..15fc0f20f 100644
--- a/include/account.h
+++ b/include/account.h
@@ -27,15 +27,6 @@ extern CoreExport Serialize::Checker<nickcore_map> NickCoreList;
/* A registered nickname.
* It matters that Base is here before Extensible (it is inherited by Serializable)
- *
- * Possible flags:
- * NO_EXPIRE - Nick never expires
- * HELD - This nick is being held after a kill by an enforcer client
- * or is being SVSHeld.
- * COLLIDED - We are taking over this nick, either by SVSNICK or KILL
- * and are waiting for the confirmation of either of these actions to
- * proceed. This is checked in NickAlias::OnCancel
- *
*/
class CoreExport NickAlias : public Serializable, public Extensible
{
@@ -112,26 +103,6 @@ class CoreExport NickAlias : public Serializable, public Extensible
/* A registered account. Each account must have a NickAlias with the same nick as the
* account's display.
* It matters that Base is here before Extensible (it is inherited by Serializable)
- *
- * Possible flags:
- * KILLPROTECT - Kill other users who try to take this nick
- * SECURE - Don't recognize unless identified
- * MSG - Use PRIVMSG instead of notice
- * MEMO_HARDMAX - Don't allow user to change memo limit
- * MEMO_SIGNON - Notify of memos at signon and unaway
- * MEMO_RECEIEVE - Notify of new memos when sent
- * PRIVATE - Don't show in LIST to non-servadmins
- * HIDE_EMAIL - Don't show email in INFO
- * HIDE_MASK - Don't show last seen address in INFO
- * HIDE_QUIT - Don't show last quit message in INFO
- * KILL_QUICK - Kill quicker
- * KILL_IMMED - Kill immediately
- * MEMO_MAIL - User gets email on memo
- * HIDE_STATUS - Don't show services access status
- * SUSPEND - Nickname is suspended
- * AUTOOP - Autoop nickname in channels
- * UNCONFIRMED - Account has not had email address confirmed
- * STATS - ChanStats is enabled for this user
*/
class CoreExport NickCore : public Serializable, public Extensible
{
@@ -143,15 +114,11 @@ class CoreExport NickCore : public Serializable, public Extensible
/* User password in form of hashm:data */
Anope::string pass;
Anope::string email;
- /* Greet associated with the account, sometimes sent when the user joins a channel */
- Anope::string greet;
/* Locale name of the language of the user. Empty means default language */
Anope::string language;
/* Access list, contains user@host masks of users who get certain privileges based
* on if NI_SECURE is set and what (if any) kill protection is enabled. */
std::vector<Anope::string> access;
- /* SSL certificate list. Users who have a matching certificate may be automatically logged in */
- std::vector<Anope::string> cert;
MemoInfo memos;
/* Nicknames registered that are grouped to this account.
@@ -242,46 +209,6 @@ class CoreExport NickCore : public Serializable, public Extensible
*/
bool IsOnAccess(const User *u) const;
- /** Add an entry to the nick's certificate list
- *
- * @param entry The fingerprint to add to the cert list
- *
- * Adds a new entry into the cert list.
- */
- void AddCert(const Anope::string &entry);
-
- /** Get an entry from the nick's cert list by index
- *
- * @param entry Index in the certificaate list vector to retrieve
- * @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
- *
- * Retrieves an entry from the certificate list corresponding to the given index.
- */
- Anope::string GetCert(unsigned entry) const;
-
- /** Find an entry in the nick's cert list
- *
- * @param entry The fingerprint to search for
- * @return True if the fingerprint is found in the cert list, false otherwise
- *
- * Search for an fingerprint within the cert list.
- */
- bool FindCert(const Anope::string &entry) const;
-
- /** Erase a fingerprint from the nick's certificate list
- *
- * @param entry The fingerprint to remove
- *
- * Removes the specified fingerprint from the cert list.
- */
- void EraseCert(const Anope::string &entry);
-
- /** Clears the entire nick's cert list
- *
- * Deletes all the memory allocated in the certificate list vector and then clears the vector.
- */
- void ClearCert();
-
/** Finds an account
* @param nick The account name to find
* @return The account, if it exists
diff --git a/include/channels.h b/include/channels.h
index bdc273415..377b4eebf 100644
--- a/include/channels.h
+++ b/include/channels.h
@@ -48,6 +48,8 @@ class CoreExport Channel : public Base, public Extensible
time_t creation_time;
/* If the channel has just been created in a netjoin */
bool syncing;
+ /* Is configured in the conf as a channel bots should be in */
+ bool botchannel;
/* Users in the channel */
typedef std::map<User *, ChanUserContainer *> ChanUserList;
diff --git a/include/defs.h b/include/defs.h
index e1c7613bc..fc0ad8e6a 100644
--- a/include/defs.h
+++ b/include/defs.h
@@ -32,7 +32,6 @@ class InfoFormatter;
class IRCDProto;
class ListenSocket;
class Log;
-class LogInfo;
class Memo;
class MessageSource;
class Module;
diff --git a/include/extensible.h b/include/extensible.h
index d47690da6..bd92e5635 100644
--- a/include/extensible.h
+++ b/include/extensible.h
@@ -12,109 +12,242 @@
#include "anope.h"
#include "serialize.h"
+#include "service.h"
+#include "logger.h"
-/* All items added to Extensible must inherit from this.
- */
-class CoreExport ExtensibleItem
+class Extensible;
+
+class CoreExport ExtensibleBase : public Service
{
+ protected:
+ std::map<Extensible *, void *> items;
+
+ ExtensibleBase(Module *m, const Anope::string &n);
+ ~ExtensibleBase();
+
public:
- virtual ~ExtensibleItem() { }
+ virtual void Unset(Extensible *obj) = 0;
- virtual const Anope::string *Serialize() { return NULL; }
+ /* called when an object we are keep track of is serializing */
+ virtual void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &) const { }
+ virtual void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &) { }
};
-/** Common class used to Extensible::Extend as it inherits from both ExtensibleItem
- * and whatever basic object you're trying to store.
- * Eg, obj->Extend(key, new ExtensibleItemClass<Anope::string>(value));
- */
-template<typename T> struct CoreExport ExtensibleItemClass : T, ExtensibleItem
+class CoreExport Extensible
{
- ExtensibleItemClass(const T& t) : T(t) { }
-};
+ public:
+ std::set<ExtensibleBase *> extension_items;
-/* Used to attach metadata to this object that is automatically saved
- * when the object is saved (assuming the object's Serialize method
- * correcly calls Extensible::ExtensibleSerialize).
- */
-struct CoreExport ExtensibleMetadata : ExtensibleItemClass<Anope::string>
-{
- ExtensibleMetadata(const Anope::string &t) : ExtensibleItemClass<Anope::string>(t) { }
+ virtual ~Extensible();
- const Anope::string *Serialize() anope_override { return this; }
+ template<typename T> T* GetExt(const Anope::string &name) const;
+ bool HasExt(const Anope::string &name) const;
+
+ template<typename T> T* Extend(const Anope::string &name, const T &what);
+ template<typename T> T* Extend(const Anope::string &name);
+ template<typename T> T* Require(const Anope::string &name);
+ template<typename T> void Shrink(const Anope::string &name);
+
+ static void ExtensibleSerialize(const Extensible *, const Serializable *, Serialize::Data &data);
+ static void ExtensibleUnserialize(Extensible *, Serializable *, Serialize::Data &data);
};
-/* Used to attach arbitrary objects to this object using unique keys */
-class CoreExport Extensible
+template<typename T>
+class BaseExtensibleItem : public ExtensibleBase
{
- private:
- typedef std::map<Anope::string, ExtensibleItem *> extensible_map;
- extensible_map *extension_items;
+ protected:
+ virtual T *Create(Extensible *) = 0;
public:
- /** Default constructor
- */
- Extensible();
+ BaseExtensibleItem(Module *m, const Anope::string &n) : ExtensibleBase(m, n) { }
- /** Destructor, deletes all of the extensible items in this object
- * then clears the map
- */
- virtual ~Extensible();
-
- /** Extend an Extensible class.
- *
- * @param key The key parameter is an arbitary string which identifies the extension data
- * @param p This parameter is a pointer to an ExtensibleItem or ExtensibleItemBase derived class
- *
- * You must provide a key to store the data as via the parameter 'key'.
- * The data will be inserted into the map. If the data already exists, it will be overwritten.
- */
- void Extend(const Anope::string &key, ExtensibleItem *p = NULL);
-
- void ExtendMetadata(const Anope::string &key, const Anope::string &value = "");
-
- /** Shrink an Extensible class.
- *
- * @param key The key parameter is an arbitary string which identifies the extension data
- *
- * You must provide a key name. The given key name will be removed from the classes data. If
- * you provide a nonexistent key (case is important) then the function will return false.
- * @return Returns true on success.
- */
- bool Shrink(const Anope::string &key);
-
- /** Get an extension item.
- *
- * @param key The key parameter is an arbitary string which identifies the extension data
- * @return The item found
- */
- template<typename T> T GetExt(const Anope::string &key) const
+ ~BaseExtensibleItem()
{
- if (this->extension_items)
+ for (std::map<Extensible *, void *>::iterator it = items.begin(); it != items.end(); ++it)
{
- extensible_map::const_iterator it = this->extension_items->find(key);
- if (it != this->extension_items->end())
- return anope_dynamic_static_cast<T>(it->second);
+ T *value = static_cast<T *>(it->second);
+
+ items.erase(it->first);
+ it->first->extension_items.erase(this);
+ delete value;
}
+ }
+
+ T* Set(Extensible *obj, const T &value)
+ {
+ T* t = Set(obj);
+ *t = value;
+ return t;
+ }
+
+ T* Set(Extensible *obj)
+ {
+ T* t = Create(obj);
+ Unset(obj);
+ items[obj] = t;
+ obj->extension_items.insert(this);
+ return t;
+ }
+
+ void Unset(Extensible *obj) anope_override
+ {
+ T *value = Get(obj);
+ items.erase(obj);
+ obj->extension_items.erase(this);
+ delete value;
+ }
+ T* Get(const Extensible *obj) const
+ {
+ std::map<Extensible *, void *>::const_iterator it = items.find(const_cast<Extensible *>(obj));
+ if (it != items.end())
+ return static_cast<T *>(it->second);
return NULL;
}
- /** Check if an extension item exists.
- *
- * @param key The key parameter is an arbitary string which identifies the extension data
- * @return True if the item was found.
- */
- bool HasExt(const Anope::string &key) const;
-
- /** Get a list of all extension items names.
- * @param list A deque of strings to receive the list
- * @return This function writes a list of all extension items stored
- * in this object by name into the given deque and returns void.
- */
- void GetExtList(std::deque<Anope::string> &list) const;
-
- void ExtensibleSerialize(Serialize::Data &data) const;
- void ExtensibleUnserialize(Serialize::Data &data);
+ bool HasExt(const Extensible *obj) const
+ {
+ return items.find(const_cast<Extensible *>(obj)) != items.end();
+ }
+
+ T* Require(Extensible *obj)
+ {
+ T* t = Get(obj);
+ if (t)
+ return t;
+
+ return Set(obj);
+ }
+};
+
+template<typename T>
+class ExtensibleItem : public BaseExtensibleItem<T>
+{
+ protected:
+ T* Create(Extensible *obj) anope_override
+ {
+ return new T(obj);
+ }
+ public:
+ ExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
};
+template<typename T>
+class PrimitiveExtensibleItem : public BaseExtensibleItem<T>
+{
+ protected:
+ T* Create(Extensible *obj) anope_override
+ {
+ return new T();
+ }
+ public:
+ PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<T>(m, n) { }
+};
+
+template<>
+class PrimitiveExtensibleItem<bool> : public BaseExtensibleItem<bool>
+{
+ protected:
+ bool* Create(Extensible *) anope_override
+ {
+ return NULL;
+ }
+ public:
+ PrimitiveExtensibleItem(Module *m, const Anope::string &n) : BaseExtensibleItem<bool>(m, n) { }
+};
+
+template<typename T>
+class SerializableExtensibleItem : public PrimitiveExtensibleItem<T>
+{
+ public:
+ SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<T>(m, n) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ {
+ T* t = this->Get(e);
+ data[this->name] << *t;
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ {
+ T* t = this->Require(e);
+ data[this->name] >> *t;
+ }
+};
+
+template<>
+class SerializableExtensibleItem<bool> : public PrimitiveExtensibleItem<bool>
+{
+ public:
+ SerializableExtensibleItem(Module *m, const Anope::string &n) : PrimitiveExtensibleItem<bool>(m, n) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ {
+ data[this->name] << true;
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ {
+ bool b;
+ data[this->name] >> b;
+ if (b)
+ this->Set(e);
+ }
+};
+
+template<typename T>
+struct ExtensibleRef : ServiceReference<BaseExtensibleItem<T> >
+{
+ ExtensibleRef(const Anope::string &n) : ServiceReference<BaseExtensibleItem<T> >("Extensible", n) { }
+};
+
+template<typename T>
+T* Extensible::GetExt(const Anope::string &name) const
+{
+ ExtensibleRef<T> ref(name);
+ if (ref)
+ return ref->Get(this);
+
+ Log(LOG_DEBUG) << "GetExt for nonexistent type " << name << " on " << static_cast<const void *>(this);
+ return NULL;
+}
+
+template<typename T>
+T* Extensible::Extend(const Anope::string &name, const T &what)
+{
+ T* t = Extend<T>(name);
+ *t = what;
+ return t;
+}
+
+template<typename T>
+T* Extensible::Extend(const Anope::string &name)
+{
+ ExtensibleRef<T> ref(name);
+ if (ref)
+ return ref->Set(this);
+
+ Log(LOG_DEBUG) << "Extend for nonexistent type " << name << " on " << static_cast<void *>(this);
+ return NULL;
+}
+
+template<typename T>
+T* Extensible::Require(const Anope::string &name)
+{
+ if (HasExt(name))
+ return GetExt<T>(name);
+ else
+ return Extend<T>(name);
+}
+
+template<typename T>
+void Extensible::Shrink(const Anope::string &name)
+{
+ ExtensibleRef<T> ref(name);
+ if (ref)
+ ref->Unset(this);
+ else
+ Log(LOG_DEBUG) << "Shrink for nonexistent type " << name << " on " << static_cast<void *>(this);
+}
+
#endif // EXTENSIBLE_H
diff --git a/include/lists.h b/include/lists.h
index 667c643b6..37b3d61a8 100644
--- a/include/lists.h
+++ b/include/lists.h
@@ -87,6 +87,7 @@ class CoreExport InfoFormatter
InfoFormatter(NickCore *nc);
void Process(std::vector<Anope::string> &);
Anope::string &operator[](const Anope::string &key);
+ void AddOption(const Anope::string &opt);
};
#endif // LISTS_H
diff --git a/include/modules.h b/include/modules.h
index c430767db..ffb8bbcc7 100644
--- a/include/modules.h
+++ b/include/modules.h
@@ -626,9 +626,10 @@ class CoreExport Module : public Extensible
virtual void OnLevelChange(CommandSource &source, ChannelInfo *ci, const Anope::string &priv, int16_t what) { throw NotImplementedException(); }
/** Called right before a channel is dropped
+ * @param source The user dropping the channel
* @param ci The channel
*/
- virtual void OnChanDrop(ChannelInfo *ci) { throw NotImplementedException(); }
+ virtual EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) { throw NotImplementedException(); }
/** Called when a channel is registered
* @param ci The channel
@@ -823,6 +824,10 @@ class CoreExport Module : public Extensible
*/
virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) { throw NotImplementedException(); }
+ /** Called when a user uses botserv/info on a bot or channel.
+ */
+ virtual void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) { throw NotImplementedException(); }
+
/** Check whether a username and password is correct
* @param u The user trying to identify, if applicable.
* @param req The login request
@@ -887,20 +892,20 @@ class CoreExport Module : public Extensible
/** Called when a mode is set on a channel
* @param c The channel
* @param setter The user or server that is setting the mode
- * @param mname The mode name
+ * @param mode The mode
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
- virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, const Anope::string &mname, const Anope::string &param) { throw NotImplementedException(); }
+ virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
/** Called when a mode is unset on a channel
* @param c The channel
* @param setter The user or server that is unsetting the mode
- * @param mname The mode name
+ * @param mode The mode
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
- virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, const Anope::string &mname, const Anope::string &param) { throw NotImplementedException(); }
+ virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
/** Called when a mode is set on a user
* @param u The user
@@ -1053,6 +1058,14 @@ class CoreExport Module : public Extensible
* channels, etc.
*/
virtual void OnExpireTick() { throw NotImplementedException(); }
+
+ /** Called when a nick is validated. That is, to determine if a user is permissted
+ * to be on the given nick.
+ * @param u The user
+ * @param na The nick they are on
+ * @return EVENT_STOP to force the user off of the nick
+ */
+ virtual EventReturn OnNickValidate(User *u, NickAlias *na) { throw NotImplementedException(); }
};
/** Used to manage modules.
diff --git a/include/modules/bs_badwords.h b/include/modules/bs_badwords.h
new file mode 100644
index 000000000..4275226cc
--- /dev/null
+++ b/include/modules/bs_badwords.h
@@ -0,0 +1,70 @@
+/* BotServ core functions
+ *
+ * (C) 2003-2013 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.
+ *
+ *
+ */
+
+/** Flags for badwords
+ */
+enum BadWordType
+{
+ /* Always kicks if the word is said */
+ BW_ANY,
+ /* User must way the entire word */
+ BW_SINGLE,
+ /* The word has to start with the badword */
+ BW_START,
+ /* The word has to end with the badword */
+ BW_END
+};
+
+/* Structure used to contain bad words. */
+struct BadWord
+{
+ Anope::string chan;
+ Anope::string word;
+ BadWordType type;
+
+ protected:
+ BadWord() { }
+};
+
+struct BadWords
+{
+ /** Add a badword to the badword list
+ * @param word The badword
+ * @param type The type (SINGLE START END)
+ * @return The badword
+ */
+ virtual BadWord* AddBadWord(const Anope::string &word, BadWordType type) = 0;
+
+ /** Get a badword structure by index
+ * @param index The index
+ * @return The badword
+ */
+ virtual BadWord* GetBadWord(unsigned index) const = 0;
+
+ /** Get how many badwords are on this channel
+ * @return The number of badwords in the vector
+ */
+ virtual unsigned GetBadWordCount() const = 0;
+
+ /** Remove a badword
+ * @param index The index of the badword
+ */
+ virtual void EraseBadWord(unsigned index) = 0;
+
+ /** Clear all badwords from the channel
+ */
+ virtual void ClearBadWords() = 0;
+
+ virtual void Check() = 0;
+};
+
diff --git a/include/modules/bs_kick.h b/include/modules/bs_kick.h
new file mode 100644
index 000000000..e1c43cc8c
--- /dev/null
+++ b/include/modules/bs_kick.h
@@ -0,0 +1,45 @@
+/* BotServ core functions
+ *
+ * (C) 2003-2013 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.
+ *
+ *
+ */
+
+/* Indices for TTB (Times To Ban) */
+enum
+{
+ TTB_BOLDS,
+ TTB_COLORS,
+ TTB_REVERSES,
+ TTB_UNDERLINES,
+ TTB_BADWORDS,
+ TTB_CAPS,
+ TTB_FLOOD,
+ TTB_REPEAT,
+ TTB_ITALICS,
+ TTB_AMSGS,
+ TTB_SIZE
+};
+
+struct KickerData
+{
+ bool amsgs, badwords, bolds, caps, colors, flood, italics, repeat, reverses, underlines;
+ int16_t ttb[TTB_SIZE]; /* Times to ban for each kicker */
+ int16_t capsmin, capspercent; /* For CAPS kicker */
+ int16_t floodlines, floodsecs; /* For FLOOD kicker */
+ int16_t repeattimes; /* For REPEAT kicker */
+
+ bool dontkickops, dontkickvoices;
+
+ protected:
+ KickerData() { }
+
+ public:
+ virtual void Check(ChannelInfo *ci) = 0;
+};
diff --git a/include/modules/cs_log.h b/include/modules/cs_log.h
new file mode 100644
index 000000000..555a44e50
--- /dev/null
+++ b/include/modules/cs_log.h
@@ -0,0 +1,41 @@
+/* ChanServ core functions
+ *
+ * (C) 2003-2013 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.
+ */
+
+struct LogSetting
+{
+ Anope::string chan;
+ /* Our service name of the command */
+ Anope::string service_name;
+ /* The name of the client the command is on */
+ Anope::string command_service;
+ /* Name of the command to the user, can have spaces */
+ Anope::string command_name;
+ Anope::string method, extra;
+ Anope::string creator;
+ time_t created;
+
+ protected:
+ LogSetting() { }
+};
+
+struct LogSettings : Serialize::Checker<std::vector<LogSetting *> >
+{
+ typedef std::vector<LogSetting *>::iterator iterator;
+
+ protected:
+ LogSettings() : Serialize::Checker<std::vector<LogSetting *> >("LogSetting")
+ {
+ }
+
+ public:
+ virtual LogSetting *Create() = 0;
+};
+
diff --git a/include/modules/cs_mode.h b/include/modules/cs_mode.h
new file mode 100644
index 000000000..4d016e672
--- /dev/null
+++ b/include/modules/cs_mode.h
@@ -0,0 +1,87 @@
+/* ChanServ core functions
+ *
+ * (C) 2003-2013 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.
+ */
+
+struct ModeLock
+{
+ Anope::string ci;
+ bool set;
+ Anope::string name;
+ Anope::string param;
+ Anope::string setter;
+ time_t created;
+
+ protected:
+ ModeLock() { }
+};
+
+struct ModeLocks
+{
+ typedef std::vector<ModeLock *> ModeList;
+
+ /** Check if a mode is mlocked
+ * @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
+ */
+ virtual bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const = 0;
+
+ /** Set a mlock
+ * @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)
+ */
+ virtual bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param = "", Anope::string setter = "", time_t created = Anope::CurTime) = 0;
+
+ /** Remove a mlock
+ * @param mode The mode
+ * @param status True for mlock on, false for mlock off
+ * @param param The param of the mode, required if it is a list or status mode
+ * @return true on success, false on failure
+ */
+ virtual bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param = "") = 0;
+
+ virtual void RemoveMLock(ModeLock *mlock) = 0;
+
+ /** Clear all mlocks on the channel
+ */
+ virtual void ClearMLock() = 0;
+
+ /** Get all of the mlocks for this channel
+ * @return The mlocks
+ */
+ virtual const ModeList &GetMLock() const = 0;
+
+ /** Get a list of mode locks on a channel
+ * @param name The mode name to get a list of
+ * @return a list of mlocks for the given mode
+ */
+ virtual std::list<ModeLock *> GetModeLockList(const Anope::string &name) = 0;
+
+ /** Get details for a specific mlock
+ * @param mname The mode name
+ * @param An optional param to match with
+ * @return The MLock, if any
+ */
+ virtual const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "") = 0;
+
+ /** Get the current mode locks as a string
+ * @param complete True to show mlock parameters aswell
+ * @return A string of mode locks, eg: +nrt
+ */
+ virtual Anope::string GetMLockAsString(bool complete) const = 0;
+
+ virtual void Check() = 0;
+};
+
diff --git a/include/modules/cs_suspend.h b/include/modules/cs_suspend.h
new file mode 100644
index 000000000..dbdd3b9e9
--- /dev/null
+++ b/include/modules/cs_suspend.h
@@ -0,0 +1,19 @@
+/* ChanServ core functions
+ *
+ * (C) 2003-2013 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.
+ */
+
+struct CSSuspendInfo
+{
+ Anope::string chan, by, reason;
+ time_t time, expires;
+
+ protected:
+ CSSuspendInfo() { }
+};
diff --git a/include/modules/ns_cert.h b/include/modules/ns_cert.h
new file mode 100644
index 000000000..8587cdfb2
--- /dev/null
+++ b/include/modules/ns_cert.h
@@ -0,0 +1,61 @@
+/* NickServ core functions
+ *
+ * (C) 2003-2013 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.
+ */
+
+struct NSCertList
+{
+ protected:
+ NSCertList() { }
+ public:
+
+ /** Add an entry to the nick's certificate list
+ *
+ * @param entry The fingerprint to add to the cert list
+ *
+ * Adds a new entry into the cert list.
+ */
+ virtual void AddCert(const Anope::string &entry) = 0;
+
+ /** Get an entry from the nick's cert list by index
+ *
+ * @param entry Index in the certificaate list vector to retrieve
+ * @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
+ *
+ * Retrieves an entry from the certificate list corresponding to the given index.
+ */
+ virtual Anope::string GetCert(unsigned entry) const = 0;
+
+ virtual unsigned GetCertCount() const = 0;
+
+ /** Find an entry in the nick's cert list
+ *
+ * @param entry The fingerprint to search for
+ * @return True if the fingerprint is found in the cert list, false otherwise
+ *
+ * Search for an fingerprint within the cert list.
+ */
+ virtual bool FindCert(const Anope::string &entry) const = 0;
+
+ /** Erase a fingerprint from the nick's certificate list
+ *
+ * @param entry The fingerprint to remove
+ *
+ * Removes the specified fingerprint from the cert list.
+ */
+ virtual void EraseCert(const Anope::string &entry) = 0;
+
+ /** Clears the entire nick's cert list
+ *
+ * Deletes all the memory allocated in the certificate list vector and then clears the vector.
+ */
+ virtual void ClearCert() = 0;
+
+ virtual void Check() = 0;
+};
diff --git a/include/modules/ns_suspend.h b/include/modules/ns_suspend.h
new file mode 100644
index 000000000..59f3d5d58
--- /dev/null
+++ b/include/modules/ns_suspend.h
@@ -0,0 +1,19 @@
+/* NickServ core functions
+ *
+ * (C) 2003-2013 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.
+ */
+
+struct NSSuspendInfo
+{
+ Anope::string nick, by, reason;
+ time_t when, expires;
+
+ protected:
+ NSSuspendInfo() { }
+};
diff --git a/include/regchannel.h b/include/regchannel.h
index 65d3236ef..f04156d89 100644
--- a/include/regchannel.h
+++ b/include/regchannel.h
@@ -22,49 +22,6 @@ typedef Anope::hash_map<ChannelInfo *> registered_channel_map;
extern CoreExport Serialize::Checker<registered_channel_map> RegisteredChannelList;
-/* Indices for TTB (Times To Ban) */
-enum
-{
- TTB_BOLDS,
- TTB_COLORS,
- TTB_REVERSES,
- TTB_UNDERLINES,
- TTB_BADWORDS,
- TTB_CAPS,
- TTB_FLOOD,
- TTB_REPEAT,
- TTB_ITALICS,
- TTB_AMSGS,
- TTB_SIZE
-};
-
-/** Flags for badwords
- */
-enum BadWordType
-{
- /* Always kicks if the word is said */
- BW_ANY,
- /* User must way the entire word */
- BW_SINGLE,
- /* The word has to start with the badword */
- BW_START,
- /* The word has to end with the badword */
- BW_END
-};
-
-/* Structure used to contain bad words. */
-struct CoreExport BadWord : Serializable
-{
- Serialize::Reference<ChannelInfo> ci;
- Anope::string word;
- BadWordType type;
-
- BadWord();
- ~BadWord();
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
-};
-
/* AutoKick data. */
class CoreExport AutoKick : public Serializable
{
@@ -86,74 +43,7 @@ class CoreExport AutoKick : public Serializable
static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
};
-struct CoreExport ModeLock : Serializable
-{
- public:
- Serialize::Reference<ChannelInfo> ci;
- bool set;
- Anope::string name;
- Anope::string param;
- Anope::string setter;
- time_t created;
-
- ModeLock(ChannelInfo *ch, bool s, const Anope::string &n, const Anope::string &p, const Anope::string &se = "", time_t c = Anope::CurTime);
- ~ModeLock();
-
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
-};
-
-struct CoreExport LogSetting : Serializable
-{
- Serialize::Reference<ChannelInfo> ci;
- /* Our service name of the command */
- Anope::string service_name;
- /* The name of the client the command is on */
- Anope::string command_service;
- /* Name of the command to the user, can have spaces */
- Anope::string command_name;
- Anope::string method, extra;
- Anope::string creator;
- time_t created;
-
- LogSetting() : Serializable("LogSetting") { }
- void Serialize(Serialize::Data &data) const anope_override;
- static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
-};
-
/* It matters that Base is here before Extensible (it is inherited by Serializable)
- *
- * Possible flags:
- * TOPICLOCK - Topic can only be changed by TOPIC SET
- * RESTRICTED - Only users on the access list may join
- * PEACE - Don't allow ChanServ and BotServ commands to do bad things to users with higher access levels
- * SECURE - Don't allow any privileges
- * NO_EXPIRE - Channel does not expire
- * MEMO_HARDMAX - Channel memo limit may not be changed
- * SECUREFOUNDER - Stricter control of channel founder status
- * SIGNKICK - Sign kicks with the user who did the kick
- * SIGNKICK_LEVEL - Sign kicks if level is < than the one defined by the SIGNKICK level
- * SUSPENDED - Channel is suepended
- * PERSIST - Channel still exists when empited (perm channel mode or leaving a botserv bot).
- * STATS - Chanstats are enabled
- * NOAUTOOP - If set users are not auto given any status on join
- *
- * BotServ flags:
- * BS_DONTKICKOPS - BotServ won't kick ops
- * BS_DONTKICKVOICES - BotServ won't kick voices
- * BS_FANTASY - BotServ bot accepts fantasy commands
- * BS_GREET - BotServ should show greets
- * BS_NOBOT - BotServ bots are not allowed to be in this channel
- * BS_KICK_BOLDS - BotServ kicks for bolds
- * BS_KICK_COLORS - BotServ kicks for colors
- * BS_KICK_REVERSES - BotServ kicks for reverses
- * BS_KICK_UNDERLINES - BotServ kicks for underlines
- * BS_KICK_BADWORD - BotServ kicks for badwords
- * BS_KICK_CAPS - BotServ kicks for caps
- * BS_KICK_FLOOD - BotServ kicks for flood
- * BS_KICK_REPEAT - BotServ kicks for repeating
- * BS_KICK_ITALICS - BotServ kicks for italics
- * BS_KICK_AMSGS - BotServ kicks for amsgs
*/
class CoreExport ChannelInfo : public Serializable, public Extensible
{
@@ -162,17 +52,11 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
Serialize::Reference<NickCore> successor; /* Who gets the channel if the founder nick is dropped or expires */
Serialize::Checker<std::vector<ChanAccess *> > access; /* List of authorized users */
Serialize::Checker<std::vector<AutoKick *> > akick; /* List of users to kickban */
- Serialize::Checker<std::vector<BadWord *> > badwords; /* List of badwords */
Anope::map<int16_t> levels;
public:
friend class ChanAccess;
friend class AutoKick;
- friend struct BadWord;
-
- typedef std::multimap<Anope::string, ModeLock *> ModeList;
- Serialize::Checker<ModeList> mode_locks;
- Serialize::Checker<std::vector<LogSetting *> > log_settings;
Anope::string name; /* Channel name */
Anope::string desc;
@@ -192,11 +76,6 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
/* For BotServ */
Serialize::Reference<BotInfo> bi; /* Bot used on this channel */
- int16_t ttb[TTB_SIZE]; /* Times to ban for each kicker */
-
- int16_t capsmin, capspercent; /* For CAPS kicker */
- int16_t floodlines, floodsecs; /* For FLOOD kicker */
- int16_t repeattimes; /* For REPEAT kicker */
time_t banexpire; /* Time bans expire in */
@@ -206,7 +85,7 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
ChannelInfo(const Anope::string &chname);
/** Copy constructor
- * @param ci The ChannelInfo to copy settings to
+ * @param ci The ChannelInfo to copy settings from
*/
ChannelInfo(const ChannelInfo &ci);
@@ -310,89 +189,6 @@ class CoreExport ChannelInfo : public Serializable, public Extensible
*/
void ClearAkick();
- /** Add a badword to the badword list
- * @param word The badword
- * @param type The type (SINGLE START END)
- * @return The badword
- */
- BadWord* AddBadWord(const Anope::string &word, BadWordType type);
-
- /** Get a badword structure by index
- * @param index The index
- * @return The badword
- */
- BadWord* GetBadWord(unsigned index) const;
-
- /** Get how many badwords are on this channel
- * @return The number of badwords in the vector
- */
- unsigned GetBadWordCount() const;
-
- /** Remove a badword
- * @param index The index of the badword
- */
- void EraseBadWord(unsigned index);
-
- /** Clear all badwords from the channel
- */
- void ClearBadWords();
-
- /** Check if a mode is mlocked
- * @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(ChannelMode *mode, const Anope::string &param, bool status) const;
-
- /** Set a mlock
- * @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(ChannelMode *mode, bool status, const Anope::string &param = "", Anope::string setter = "", time_t created = Anope::CurTime);
-
- /** Remove a mlock
- * @param mode The mode
- * @param status True for mlock on, false for mlock off
- * @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(ChannelMode *mode, bool status, const Anope::string &param = "");
-
- void RemoveMLock(ModeLock *mlock);
-
- /** Clear all mlocks on the channel
- */
- void ClearMLock();
-
- /** Get all of the mlocks for this channel
- * @return The mlocks
- */
- const ModeList &GetMLock() const;
-
- /** 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
- */
- std::pair<ModeList::iterator, ModeList::iterator> GetModeList(const Anope::string &name);
-
- /** Get details for a specific mlock
- * @param mname The mode name
- * @param An optional param to match with
- * @return The MLock, if any
- */
- const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "");
-
- /** Get the current mode locks as a string
- * @param complete True to show mlock parameters aswell
- * @return A string of mode locks, eg: +nrt
- */
- Anope::string GetMLockAsString(bool complete) const;
-
/** Get the level for a privilege
* @param priv The privilege name
* @return the level
diff --git a/include/service.h b/include/service.h
index 545d1b363..b4b9ea9cd 100644
--- a/include/service.h
+++ b/include/service.h
@@ -15,7 +15,7 @@
#include "services.h"
#include "anope.h"
-#include "modules.h"
+#include "base.h"
/** Anything that inherits from this class can be referred to
* using ServiceReference. Any interfaces provided by modules,
diff --git a/modules/commands/bs_assign.cpp b/modules/commands/bs_assign.cpp
index 7b241f09e..ba925ad80 100644
--- a/modules/commands/bs_assign.cpp
+++ b/modules/commands/bs_assign.cpp
@@ -145,14 +145,69 @@ class CommandBSUnassign : public Command
}
};
+class CommandBSSetNoBot : public Command
+{
+ public:
+ CommandBSSetNoBot(Module *creator, const Anope::string &sname = "botserv/set/nobot") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("Prevent a bot from being assigned to a channel"));
+ this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ const Anope::string &value = params[1];
+
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ if (value.equals_ci("ON"))
+ {
+ Log(LOG_ADMIN, source, this, ci) << "to enable nobot";
+
+ ci->Extend<bool>("BS_NOBOT");
+ if (ci->bi)
+ ci->bi->UnAssign(source.GetUser(), ci);
+ source.Reply(_("No-bot mode is now \002on\002 on channel %s."), ci->name.c_str());
+ }
+ else if (value.equals_ci("OFF"))
+ {
+ Log(LOG_ADMIN, source, this, ci) << "to disable nobot";
+
+ ci->Shrink<bool>("BS_NOBOT");
+ source.Reply(_("No-bot mode is now \002off\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "This option makes a channel be unassignable. If a bot\n"
+ "is already assigned to the channel, it is unassigned\n"
+ "automatically when you enable the option."));
+ return true;
+ }
+};
+
class BSAssign : public Module
{
+ ExtensibleItem<bool> nobot;
+
CommandBSAssign commandbsassign;
CommandBSUnassign commandbsunassign;
+ CommandBSSetNoBot commandbssetnobot;
public:
BSAssign(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsassign(this), commandbsunassign(this)
+ nobot(this, "BS_NOBOT"),
+ commandbsassign(this), commandbsunassign(this), commandbssetnobot(this)
{
}
@@ -163,7 +218,7 @@ class BSAssign : public Module
return;
AccessGroup access = c->ci->AccessFor(source);
- if (c->ci->HasExt("BS_NOBOT") || (!access.HasPriv("ASSIGN") && !source->HasPriv("botserv/administration")))
+ if (nobot.HasExt(c->ci) || (!access.HasPriv("ASSIGN") && !source->HasPriv("botserv/administration")))
{
targ->SendMessage(bi, ACCESS_DENIED);
return;
@@ -184,6 +239,12 @@ class BSAssign : public Module
bi->Assign(source, c->ci);
targ->SendMessage(bi, _("Bot \002%s\002 has been assigned to %s."), bi->nick.c_str(), c->name.c_str());
}
+
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ {
+ if (nobot.HasExt(ci))
+ info.AddOption(_("No bot"));
+ }
};
MODULE_INIT(BSAssign)
diff --git a/modules/commands/bs_badwords.cpp b/modules/commands/bs_badwords.cpp
index 22fa74714..ff9707778 100644
--- a/modules/commands/bs_badwords.cpp
+++ b/modules/commands/bs_badwords.cpp
@@ -10,11 +10,132 @@
*/
#include "module.h"
+#include "modules/bs_badwords.h"
+
+struct BadWordImpl : BadWord, Serializable
+{
+ BadWordImpl() : Serializable("BadWord") { }
+ ~BadWordImpl();
+
+ void Serialize(Serialize::Data &data) const anope_override
+ {
+ data["ci"] << this->chan;
+ data["word"] << this->word;
+ data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
+ }
+
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &);
+};
+
+struct BadWordsImpl : BadWords
+{
+ Serialize::Reference<ChannelInfo> ci;
+ typedef std::vector<BadWordImpl *> list;
+ Serialize::Checker<list> badwords;
+
+ BadWordsImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), badwords("BadWord") { }
+
+ BadWord* AddBadWord(const Anope::string &word, BadWordType type) anope_override
+ {
+ BadWordImpl *bw = new BadWordImpl();
+ bw->chan = ci->name;
+ bw->word = word;
+ bw->type = type;
+
+ this->badwords->push_back(bw);
+
+ FOREACH_MOD(OnBadWordAdd, (ci, bw));
+
+ return bw;
+ }
+
+ BadWord* GetBadWord(unsigned index) const anope_override
+ {
+ if (this->badwords->empty() || index >= this->badwords->size())
+ return NULL;
+
+ BadWordImpl *bw = (*this->badwords)[index];
+ bw->QueueUpdate();
+ return bw;
+ }
+
+ unsigned GetBadWordCount() const anope_override
+ {
+ return this->badwords->size();
+ }
+
+ void EraseBadWord(unsigned index) anope_override
+ {
+ if (this->badwords->empty() || index >= this->badwords->size())
+ return;
+
+ FOREACH_MOD(OnBadWordDel, (ci, (*this->badwords)[index]));
+
+ delete this->badwords->at(index);
+ }
+
+ void ClearBadWords() anope_override
+ {
+ while (!this->badwords->empty())
+ delete this->badwords->back();
+ }
+
+ void Check() anope_override
+ {
+ if (this->badwords->empty())
+ ci->Shrink<BadWords>("badwords");
+ }
+};
+
+BadWordImpl::~BadWordImpl()
+{
+ ChannelInfo *ci = ChannelInfo::Find(chan);
+ if (ci)
+ {
+ BadWordsImpl *badwords = ci->GetExt<BadWordsImpl>("badwords");
+ if (badwords)
+ {
+ BadWordsImpl::list::iterator it = std::find(badwords->badwords->begin(), badwords->badwords->end(), this);
+ if (it != badwords->badwords->end())
+ badwords->badwords->erase(it);
+ }
+ }
+}
+
+Serializable* BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+{
+ Anope::string sci, sword;
+
+ data["ci"] >> sci;
+ data["word"] >> sword;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
+ if (!ci)
+ return NULL;
+
+ unsigned int n;
+ data["type"] >> n;
+
+ BadWordImpl *bw;
+ if (obj)
+ bw = anope_dynamic_static_cast<BadWordImpl *>(obj);
+ else
+ bw = new BadWordImpl();
+ bw->chan = sci;
+ bw->word = sword;
+ bw->type = static_cast<BadWordType>(n);
+
+ BadWordsImpl *bws = ci->Require<BadWordsImpl>("badwords");
+ bws->badwords->push_back(bw);
+
+ return bw;
+}
class BadwordsDelCallback : public NumberList
{
CommandSource &source;
ChannelInfo *ci;
+ BadWords *bw;
Command *c;
unsigned deleted;
bool override;
@@ -23,6 +144,7 @@ class BadwordsDelCallback : public NumberList
{
if (!source.AccessFor(ci).HasPriv("BADWORDS") && source.HasPriv("botserv/administration"))
this->override = true;
+ bw = ci->Require<BadWords>("badwords");
}
~BadwordsDelCallback()
@@ -37,12 +159,12 @@ class BadwordsDelCallback : public NumberList
void HandleNumber(unsigned Number) anope_override
{
- if (!Number || Number > ci->GetBadWordCount())
+ if (!bw || !Number || Number > bw->GetBadWordCount())
return;
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << ci->GetBadWord(Number - 1)->word;
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "DEL " << bw->GetBadWord(Number - 1)->word;
++deleted;
- ci->EraseBadWord(Number - 1);
+ bw->EraseBadWord(Number - 1);
}
};
@@ -54,10 +176,11 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "LIST";
ListFormatter list;
+ BadWords *bw = ci->GetExt<BadWords>("badwords");
list.AddColumn("Number").AddColumn("Word").AddColumn("Type");
- if (!ci->GetBadWordCount())
+ if (!bw || !bw->GetBadWordCount())
{
source.Reply(_("%s bad words list is empty."), ci->name.c_str());
return;
@@ -68,40 +191,41 @@ class CommandBSBadwords : public Command
{
ListFormatter &list;
ChannelInfo *ci;
+ BadWords *bw;
public:
- BadwordsListCallback(ListFormatter &_list, ChannelInfo *_ci, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci)
+ BadwordsListCallback(ListFormatter &_list, ChannelInfo *_ci, BadWords *_bw, const Anope::string &numlist) : NumberList(numlist, false), list(_list), ci(_ci), bw(_bw)
{
}
void HandleNumber(unsigned Number) anope_override
{
- if (!Number || Number > ci->GetBadWordCount())
+ if (!Number || Number > bw->GetBadWordCount())
return;
- const BadWord *bw = ci->GetBadWord(Number - 1);
+ const BadWord *b = bw->GetBadWord(Number - 1);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(Number);
- entry["Word"] = bw->word;
- entry["Type"] = bw->type == BW_SINGLE ? "(SINGLE)" : (bw->type == BW_START ? "(START)" : (bw->type == BW_END ? "(END)" : ""));
+ entry["Word"] = b->word;
+ entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
this->list.AddEntry(entry);
}
}
- nl_list(list, ci, word);
+ nl_list(list, ci, bw, word);
nl_list.Process();
}
else
{
- for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (unsigned i = 0, end = bw->GetBadWordCount(); i < end; ++i)
{
- const BadWord *bw = ci->GetBadWord(i);
+ const BadWord *b = bw->GetBadWord(i);
- if (!word.empty() && !Anope::Match(bw->word, word))
+ if (!word.empty() && !Anope::Match(b->word, word))
continue;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
- entry["Word"] = bw->word;
- entry["Type"] = bw->type == BW_SINGLE ? "(SINGLE)" : (bw->type == BW_START ? "(START)" : (bw->type == BW_END ? "(END)" : ""));
+ entry["Word"] = b->word;
+ entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
list.AddEntry(entry);
}
}
@@ -127,6 +251,7 @@ class CommandBSBadwords : public Command
size_t pos = word.rfind(' ');
BadWordType bwtype = BW_ANY;
Anope::string realword = word;
+ BadWords *badwords = ci->Require<BadWords>("badwords");
if (pos != Anope::string::npos)
{
@@ -144,7 +269,7 @@ class CommandBSBadwords : public Command
}
unsigned badwordsmax = Config->GetModule(this->module)->Get<unsigned>("badwordsmax");
- if (ci->GetBadWordCount() >= badwordsmax)
+ if (badwords->GetBadWordCount() >= badwordsmax)
{
source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), badwordsmax);
return;
@@ -152,9 +277,9 @@ class CommandBSBadwords : public Command
bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");
- for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (unsigned i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
{
- const BadWord *bw = ci->GetBadWord(i);
+ const BadWord *bw = badwords->GetBadWord(i);
if ((casesensitive && realword.equals_cs(bw->word)) || (!casesensitive && realword.equals_ci(bw->word)))
{
@@ -165,13 +290,21 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "ADD " << realword;
- ci->AddBadWord(realword, bwtype);
+ badwords->AddBadWord(realword, bwtype);
source.Reply(_("\002%s\002 added to %s bad words list."), realword.c_str(), ci->name.c_str());
}
void DoDelete(CommandSource &source, ChannelInfo *ci, const Anope::string &word)
{
+ BadWords *badwords = ci->GetExt<BadWords>("badwords");
+
+ if (!badwords || !badwords->GetBadWordCount())
+ {
+ source.Reply(_("%s bad words list is empty."), ci->name.c_str());
+ return;
+ }
+
/* Special case: is it a number/list? Only do search if it isn't. */
if (!word.empty() && isdigit(word[0]) && word.find_first_not_of("1234567890,-") == Anope::string::npos)
{
@@ -183,9 +316,9 @@ class CommandBSBadwords : public Command
unsigned i, end;
const BadWord *badword;
- for (i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
{
- badword = ci->GetBadWord(i);
+ badword = badwords->GetBadWord(i);
if (word.equals_ci(badword->word))
break;
@@ -202,10 +335,10 @@ class CommandBSBadwords : public Command
source.Reply(_("\002%s\002 deleted from %s bad words list."), badword->word.c_str(), ci->name.c_str());
- ci->EraseBadWord(i);
+ badwords->EraseBadWord(i);
}
- return;
+ badwords->Check();
}
void DoClear(CommandSource &source, ChannelInfo *ci)
@@ -213,7 +346,9 @@ class CommandBSBadwords : public Command
bool override = !source.AccessFor(ci).HasPriv("BADWORDS");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "CLEAR";
- ci->ClearBadWords();
+ BadWords *badwords = ci->GetExt<BadWords>("badwords");
+ if (badwords)
+ badwords->ClearBadWords();
source.Reply(_("Bad words list is now empty."));
}
@@ -309,10 +444,12 @@ class CommandBSBadwords : public Command
class BSBadwords : public Module
{
CommandBSBadwords commandbsbadwords;
+ ExtensibleItem<BadWordsImpl> badwords;
+ Serialize::Type badword_type;
public:
BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsbadwords(this)
+ commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize)
{
}
};
diff --git a/modules/commands/bs_info.cpp b/modules/commands/bs_info.cpp
index 8bbfd0b18..a3eb9ce2d 100644
--- a/modules/commands/bs_info.cpp
+++ b/modules/commands/bs_info.cpp
@@ -36,16 +36,6 @@ class CommandBSInfo : public Command
buffers.push_back(buf);
}
- void CheckOptStr(Anope::string &buf, const Anope::string &flag, const char *option, Extensible *flags, const NickCore *nc)
- {
- if (flags->HasExt(flag))
- {
- if (!buf.empty())
- buf += ", ";
- buf += Language::Translate(nc, option);
- }
- }
-
public:
CommandBSInfo(Module *creator) : Command(creator, "botserv/info", 1, 1)
{
@@ -57,8 +47,8 @@ class CommandBSInfo : public Command
{
const Anope::string &query = params[0];
- const BotInfo *bi = BotInfo::Find(query, true);
- ChannelInfo *ci;
+ BotInfo *bi = BotInfo::Find(query, true);
+ ChannelInfo *ci = ChannelInfo::Find(query);
InfoFormatter info(source.nc);
if (bi)
@@ -70,6 +60,8 @@ class CommandBSInfo : public Command
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
+ FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
+
std::vector<Anope::string> replies;
info.Process(replies);
@@ -85,7 +77,7 @@ class CommandBSInfo : public Command
}
}
- else if ((ci = ChannelInfo::Find(query)))
+ else if (ci)
{
if (!source.AccessFor(ci).HasPriv("INFO") && !source.HasPriv("botserv/administration"))
{
@@ -99,114 +91,7 @@ class CommandBSInfo : public Command
Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
- if (ci->HasExt("BS_KICK_BADWORDS"))
- {
- if (ci->ttb[TTB_BADWORDS])
- info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), ci->ttb[TTB_BADWORDS]);
- else
- info[_("Bad words kicker")] = enabled;
- }
- else
- info[_("Bad words kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_BOLDS"))
- {
- if (ci->ttb[TTB_BOLDS])
- info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), ci->ttb[TTB_BOLDS]);
- else
- info[_("Bolds kicker")] = enabled;
- }
- else
- info[_("Bolds kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_CAPS"))
- {
- if (ci->ttb[TTB_CAPS])
- info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%"), enabled.c_str(), ci->ttb[TTB_CAPS], ci->capsmin, ci->capspercent);
- else
- info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), ci->capsmin, ci->capspercent);
- }
- else
- info[_("Caps kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_COLORS"))
- {
- if (ci->ttb[TTB_COLORS])
- info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_COLORS]);
- else
- info[_("Colors kicker")] = enabled;
- }
- else
- info[_("Colors kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_FLOOD"))
- {
- if (ci->ttb[TTB_FLOOD])
- info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds"), enabled.c_str(), ci->ttb[TTB_FLOOD], ci->floodlines, ci->floodsecs);
- else
- info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), ci->floodlines, ci->floodsecs);
- }
- else
- info[_("Flood kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_REPEAT"))
- {
- if (ci->ttb[TTB_REPEAT])
- info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), ci->ttb[TTB_REPEAT], ci->repeattimes);
- else
- info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), ci->repeattimes);
- }
- else
- info[_("Repeat kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_REVERSES"))
- {
- if (ci->ttb[TTB_REVERSES])
- info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_REVERSES]);
- else
- info[_("Reverses kicker")] = enabled;
- }
- else
- info[_("Reverses kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_UNDERLINES"))
- {
- if (ci->ttb[TTB_UNDERLINES])
- info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_UNDERLINES]);
- else
- info[_("Underlines kicker")] = enabled;
- }
- else
- info[_("Underlines kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_ITALICS"))
- {
- if (ci->ttb[TTB_ITALICS])
- info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_ITALICS]);
- else
- info[_("Italics kicker")] = enabled;
- }
- else
- info[_("Italics kicker")] = disabled;
-
- if (ci->HasExt("BS_KICK_AMSGS"))
- {
- if (ci->ttb[TTB_AMSGS])
- info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), ci->ttb[TTB_AMSGS]);
- else
- info[_("AMSG kicker")] = enabled;
- }
- else
- info[_("AMSG kicker")] = disabled;
-
- Anope::string flags;
- CheckOptStr(flags, "BS_DONTKICKOPS", _("Ops protection"), ci, source.nc);
- CheckOptStr(flags, "BS_DONTKICKVOICES", _("Voices protection"), ci, source.nc);
- CheckOptStr(flags, "BS_FANTASY", _("Fantasy"), ci, source.nc);
- CheckOptStr(flags, "BS_GREET", _("Greet"), ci, source.nc);
- CheckOptStr(flags, "BS_NOBOT", _("No bot"), ci, source.nc);
-
- info[_("Options")] = flags.empty() ? _("None") : flags;
+ FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
std::vector<Anope::string> replies;
info.Process(replies);
diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp
index 50d4a0e5f..b22dd9ccb 100644
--- a/modules/commands/bs_kick.cpp
+++ b/modules/commands/bs_kick.cpp
@@ -12,9 +12,107 @@
*/
#include "module.h"
+#include "modules/bs_kick.h"
+#include "modules/bs_badwords.h"
static Module *me;
+struct KickerDataImpl : KickerData
+{
+ KickerDataImpl(Extensible *obj)
+ {
+ amsgs = badwords = bolds = caps = colors = flood = italics = repeat = reverses = underlines = false;
+ for (int16_t i = 0; i < TTB_SIZE; ++i)
+ ttb[i] = 0;
+ capsmin = capspercent = 0;
+ floodlines = floodsecs = 0;
+ repeattimes = 0;
+
+ dontkickops = dontkickvoices = false;
+ }
+
+ void Check(ChannelInfo *ci) anope_override
+ {
+ if (amsgs || badwords || bolds || caps || colors || flood || italics || repeat || reverses || underlines)
+ return;
+
+ ci->Shrink<KickerData>("kickerdata");
+ }
+
+ struct ExtensibleItem : ::ExtensibleItem<KickerDataImpl>
+ {
+ ExtensibleItem(Module *m, const Anope::string &name) : ::ExtensibleItem<KickerDataImpl>(m, name) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "ChannelInfo")
+ return;
+
+ const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e);
+ KickerData *kd = this->Get(ci);
+ if (kd == NULL)
+ return;
+
+ data["kickerdata:amsgs"] << kd->amsgs;
+ data["kickerdata:badwords"] << kd->badwords;
+ data["kickerdata:bolds"] << kd->bolds;
+ data["kickerdata:caps"] << kd->caps;
+ data["kickerdata:colors"] << kd->colors;
+ data["kickerdata:flood"] << kd->flood;
+ data["kickerdata:italics"] << kd->italics;
+ data["kickerdata:repeat"] << kd->repeat;
+ data["kickerdata:reverses"] << kd->reverses;
+ data["kickerdata:underlines"] << kd->underlines;
+
+ data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin;
+ data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent;
+ data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines;
+ data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs;
+ data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes;
+ for (int16_t i = 0; i < TTB_SIZE; ++i)
+ data["ttb"] << kd->ttb[i] << " ";
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "ChannelInfo")
+ return;
+
+ ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e);
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+
+ data["kickerdata:amsgs"] >> kd->amsgs;
+ data["kickerdata:badwords"] >> kd->badwords;
+ data["kickerdata:bolds"] >> kd->bolds;
+ data["kickerdata:caps"] >> kd->caps;
+ data["kickerdata:colors"] >> kd->colors;
+ data["kickerdata:flood"] >> kd->flood;
+ data["kickerdata:italics"] >> kd->italics;
+ data["kickerdata:repeat"] >> kd->repeat;
+ data["kickerdata:reverses"] >> kd->reverses;
+ data["kickerdata:underlines"] >> kd->underlines;
+
+ data["capsmin"] >> kd->capsmin;
+ data["capspercent"] >> kd->capspercent;
+ data["floodlines"] >> kd->floodlines;
+ data["floodsecs"] >> kd->floodsecs;
+ data["repeattimes"] >> kd->repeattimes;
+
+ Anope::string ttb, tok;
+ data["ttb"] >> ttb;
+ spacesepstream sep(ttb);
+ for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
+ try
+ {
+ ttb[i] = convertTo<int16_t>(tok);
+ }
+ catch (const ConvertException &) { }
+
+ kd->Check(ci);
+ }
+ };
+};
+
class CommandBSKick : public Command
{
public:
@@ -99,7 +197,7 @@ class CommandBSKickBase : public Command
return false;
}
- void Process(CommandSource &source, ChannelInfo *ci, const Anope::string &param, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, const Anope::string &mdname)
+ void Process(CommandSource &source, ChannelInfo *ci, const Anope::string &param, const Anope::string &ttb, size_t ttb_idx, const Anope::string &optname, KickerData *kd, bool &val)
{
if (param.equals_ci("ON"))
{
@@ -119,15 +217,15 @@ class CommandBSKickBase : public Command
return;
}
- ci->ttb[ttb_idx] = i;
+ kd->ttb[ttb_idx] = i;
}
else
- ci->ttb[ttb_idx] = 0;
+ kd->ttb[ttb_idx] = 0;
- ci->ExtendMetadata(mdname);
- if (ci->ttb[ttb_idx])
+ val = true;
+ if (kd->ttb[ttb_idx])
source.Reply(_("Bot will now kick for \002%s\002, and will place a ban\n"
- "after %d kicks for the same user."), optname.c_str(), ci->ttb[ttb_idx]);
+ "after %d kicks for the same user."), optname.c_str(), kd->ttb[ttb_idx]);
else
source.Reply(_("Bot will now kick for \002%s\002."), optname.c_str());
@@ -139,7 +237,7 @@ class CommandBSKickBase : public Command
bool override = !source.AccessFor(ci).HasPriv("SET");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable the " << optname << "kicker";
- ci->Shrink(mdname);
+ val = false;
source.Reply(_("Bot won't kick for \002%s\002 anymore."), optname.c_str());
}
else
@@ -160,7 +258,11 @@ class CommandBSKickAMSG : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", "BS_KICK_AMSGS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_AMSGS, "AMSG", kd, kd->amsgs);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -188,7 +290,12 @@ class CommandBSKickBadwords : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", "BS_KICK_BADWORDS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BADWORDS, "badwords", kd, kd->badwords);
+ kd->Check(ci);
+ }
+
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -219,7 +326,11 @@ class CommandBSKickBolds : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BOLDS, "bolds", "BS_KICK_BOLDS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_BOLDS, "bolds", kd, kd->bolds);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -248,6 +359,8 @@ class CommandBSKickCaps : public CommandBSKickBase
if (!CheckArguments(source, params, ci))
return;
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+
if (params[1].equals_ci("ON"))
{
const Anope::string &ttb = params.size() > 2 ? params[2] : "",
@@ -258,52 +371,54 @@ class CommandBSKickCaps : public CommandBSKickBase
{
try
{
- ci->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
- if (ci->ttb[TTB_CAPS] < 0)
+ kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
+ if (kd->ttb[TTB_CAPS] < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
- ci->ttb[TTB_CAPS] = 0;
+ kd->ttb[TTB_CAPS] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
}
else
- ci->ttb[TTB_CAPS] = 0;
+ kd->ttb[TTB_CAPS] = 0;
- ci->capsmin = 10;
+ kd->capsmin = 10;
try
{
- ci->capsmin = convertTo<int16_t>(min);
+ kd->capsmin = convertTo<int16_t>(min);
}
catch (const ConvertException &) { }
- if (ci->capsmin < 1)
- ci->capsmin = 10;
+ if (kd->capsmin < 1)
+ kd->capsmin = 10;
- ci->capspercent = 25;
+ kd->capspercent = 25;
try
{
- ci->capspercent = convertTo<int16_t>(percent);
+ kd->capspercent = convertTo<int16_t>(percent);
}
catch (const ConvertException &) { }
- if (ci->capspercent < 1 || ci->capspercent > 100)
- ci->capspercent = 25;
+ if (kd->capspercent < 1 || kd->capspercent > 100)
+ kd->capspercent = 25;
- ci->ExtendMetadata("BS_KICK_CAPS");
- if (ci->ttb[TTB_CAPS])
+ kd->caps = true;
+ if (kd->ttb[TTB_CAPS])
source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
"%d characters and %d%% of the entire message), and will\n"
- "place a ban after %d kicks for the same user."), ci->capsmin, ci->capspercent, ci->ttb[TTB_CAPS]);
+ "place a ban after %d kicks for the same user."), kd->capsmin, kd->capspercent, kd->ttb[TTB_CAPS]);
else
source.Reply(_("Bot will now kick for \002caps\002 (they must constitute at least\n"
- "%d characters and %d%% of the entire message)."), ci->capsmin, ci->capspercent);
+ "%d characters and %d%% of the entire message)."), kd->capsmin, kd->capspercent);
}
else
{
- ci->Shrink("BS_KICK_CAPS");
+ kd->caps = false;
source.Reply(_("Bot won't kick for \002caps\002 anymore."));
}
+
+ kd->Check(ci);
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -335,7 +450,11 @@ class CommandBSKickColors : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_COLORS, "colors", "BS_KICK_COLORS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_COLORS, "colors", kd, kd->colors);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -364,6 +483,8 @@ class CommandBSKickFlood : public CommandBSKickBase
if (!CheckArguments(source, params, ci))
return;
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+
if (params[1].equals_ci("ON"))
{
const Anope::string &ttb = params.size() > 2 ? params[2] : "",
@@ -386,45 +507,47 @@ class CommandBSKickFlood : public CommandBSKickBase
return;
}
- ci->ttb[TTB_FLOOD] = i;
+ kd->ttb[TTB_FLOOD] = i;
}
else
- ci->ttb[TTB_FLOOD] = 0;
+ kd->ttb[TTB_FLOOD] = 0;
- ci->floodlines = 6;
+ kd->floodlines = 6;
try
{
- ci->floodlines = convertTo<int16_t>(lines);
+ kd->floodlines = convertTo<int16_t>(lines);
}
catch (const ConvertException &) { }
- if (ci->floodlines < 2)
- ci->floodlines = 6;
+ if (kd->floodlines < 2)
+ kd->floodlines = 6;
- ci->floodsecs = 10;
+ kd->floodsecs = 10;
try
{
- ci->floodsecs = convertTo<int16_t>(secs);
+ kd->floodsecs = convertTo<int16_t>(secs);
}
catch (const ConvertException &) { }
- if (ci->floodsecs < 1)
- ci->floodsecs = 10;
- if (ci->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata"))
- ci->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata");
+ if (kd->floodsecs < 1)
+ kd->floodsecs = 10;
+ if (kd->floodsecs > Config->GetModule(me)->Get<time_t>("keepdata"))
+ kd->floodsecs = Config->GetModule(me)->Get<time_t>("keepdata");
- ci->ExtendMetadata("BS_KICK_FLOOD");
- if (ci->ttb[TTB_FLOOD])
+ kd->flood = true;
+ if (kd->ttb[TTB_FLOOD])
source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds\n"
- "and will place a ban after %d kicks for the same user."), ci->floodlines, ci->floodsecs, ci->ttb[TTB_FLOOD]);
+ "and will place a ban after %d kicks for the same user."), kd->floodlines, kd->floodsecs, kd->ttb[TTB_FLOOD]);
else
- source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds)."), ci->floodlines, ci->floodsecs);
+ source.Reply(_("Bot will now kick for \002flood\002 (%d lines in %d seconds)."), kd->floodlines, kd->floodsecs);
}
else if (params[1].equals_ci("OFF"))
{
- ci->Shrink("BS_KICK_FLOOD");
+ kd->flood = false;
source.Reply(_("Bot won't kick for \002flood\002 anymore."));
}
else
this->OnSyntaxError(source, params[1]);
+
+ kd->Check(ci);
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -454,7 +577,11 @@ class CommandBSKickItalics : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", "BS_KICK_ITALICS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", kd, kd->italics);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -483,6 +610,8 @@ class CommandBSKickRepeat : public CommandBSKickBase
if (!CheckArguments(source, params, ci))
return;
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+
if (params[1].equals_ci("ON"))
{
const Anope::string &ttb = params[2],
@@ -504,36 +633,38 @@ class CommandBSKickRepeat : public CommandBSKickBase
return;
}
- ci->ttb[TTB_REPEAT] = i;
+ kd->ttb[TTB_REPEAT] = i;
}
else
- ci->ttb[TTB_REPEAT] = 0;
+ kd->ttb[TTB_REPEAT] = 0;
- ci->repeattimes = 3;
+ kd->repeattimes = 3;
try
{
- ci->repeattimes = convertTo<int16_t>(times);
+ kd->repeattimes = convertTo<int16_t>(times);
}
catch (const ConvertException &) { }
- if (ci->repeattimes < 2)
- ci->repeattimes = 3;
+ if (kd->repeattimes < 2)
+ kd->repeattimes = 3;
- ci->ExtendMetadata("BS_KICK_REPEAT");
- if (ci->ttb[TTB_REPEAT])
+ kd->repeat = true;
+ if (kd->ttb[TTB_REPEAT])
source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
"same thing %d times), and will place a ban after %d\n"
- "kicks for the same user."), ci->repeattimes, ci->ttb[TTB_REPEAT]);
+ "kicks for the same user."), kd->repeattimes, kd->ttb[TTB_REPEAT]);
else
source.Reply(_("Bot will now kick for \002repeats\002 (users that say the\n"
- "same thing %d times)."), ci->repeattimes);
+ "same thing %d times)."), kd->repeattimes);
}
else if (params[1].equals_ci("OFF"))
{
- ci->Shrink("BS_KICK_REPEAT");
+ kd->repeat = false;
source.Reply(_("Bot won't kick for \002repeats\002 anymore."));
}
else
this->OnSyntaxError(source, params[1]);
+
+ kd->Check(ci);
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -562,7 +693,11 @@ class CommandBSKickReverses : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", "BS_KICK_ITALICS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_REVERSES, "reverses", kd, kd->reverses);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -589,7 +724,11 @@ class CommandBSKickUnderlines : public CommandBSKickBase
{
ChannelInfo *ci;
if (CheckArguments(source, params, ci))
- Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_ITALICS, "italics", "BS_KICK_ITALICS");
+ {
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ Process(source, ci, params[1], params.size() > 2 ? params[2] : "", TTB_UNDERLINES, "underlines", kd, kd->underlines);
+ kd->Check(ci);
+ }
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -603,7 +742,137 @@ class CommandBSKickUnderlines : public CommandBSKickBase
}
};
-struct BanData : ExtensibleItem
+class CommandBSSetDontKickOps : public Command
+{
+ public:
+ CommandBSSetDontKickOps(Module *creator, const Anope::string &sname = "botserv/set/dontkickops") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("To protect ops against bot kicks"));
+ this->SetSyntax(_("\037channel\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ AccessGroup access = source.AccessFor(ci);
+ if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (Anope::ReadOnly)
+ {
+ source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ return;
+ }
+
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ if (params[1].equals_ci("ON"))
+ {
+ bool override = !access.HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickops";
+
+ kd->dontkickops = true;
+ source.Reply(_("Bot \002won't kick ops\002 on channel %s."), ci->name.c_str());
+ }
+ else if (params[1].equals_ci("OFF"))
+ {
+ bool override = !access.HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickops";
+
+ kd->dontkickops = false;
+ source.Reply(_("Bot \002will kick ops\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+
+ kd->Check(ci);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "Enables or disables \002ops protection\002 mode on a channel.\n"
+ "When it is enabled, ops won't be kicked by the bot\n"
+ "even if they don't match the NOKICK level."));
+ return true;
+ }
+};
+
+class CommandBSSetDontKickVoices : public Command
+{
+ public:
+ CommandBSSetDontKickVoices(Module *creator, const Anope::string &sname = "botserv/set/dontkickvoices") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("To protect voices against bot kicks"));
+ this->SetSyntax(_("\037channel\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ AccessGroup access = source.AccessFor(ci);
+ if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (Anope::ReadOnly)
+ {
+ source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ return;
+ }
+
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ if (params[1].equals_ci("ON"))
+ {
+ bool override = !access.HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickvoices";
+
+ kd->dontkickvoices = true;
+ source.Reply(_("Bot \002won't kick voices\002 on channel %s."), ci->name.c_str());
+ }
+ else if (params[1].equals_ci("OFF"))
+ {
+ bool override = !access.HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickvoices";
+
+ kd->dontkickvoices = false;
+ source.Reply(_("Bot \002will kick voices\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+
+ kd->Check(ci);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "Enables or disables \002voices protection\002 mode on a channel.\n"
+ "When it is enabled, voices won't be kicked by the bot\n"
+ "even if they don't match the NOKICK level."));
+ return true;
+ }
+};
+
+struct BanData
{
struct Data
{
@@ -613,11 +882,6 @@ struct BanData : ExtensibleItem
Data()
{
- this->Clear();
- }
-
- void Clear()
- {
last_use = 0;
for (int i = 0; i < TTB_SIZE; ++i)
this->ttb[i] = 0;
@@ -625,10 +889,12 @@ struct BanData : ExtensibleItem
};
private:
- typedef std::map<Anope::string, Data, ci::less> data_type;
+ typedef Anope::map<Data> data_type;
data_type data_map;
public:
+ BanData(Extensible *) { }
+
Data &get(const Anope::string &key)
{
return this->data_map[key];
@@ -654,14 +920,9 @@ struct BanData : ExtensibleItem
}
};
-struct UserData : ExtensibleItem
+struct UserData
{
- UserData()
- {
- this->Clear();
- }
-
- void Clear()
+ UserData(Extensible *)
{
last_use = last_start = Anope::CurTime;
lines = times = 0;
@@ -682,7 +943,6 @@ struct UserData : ExtensibleItem
Anope::string lastline;
};
-
class BanDataPurger : public Timer
{
public:
@@ -696,12 +956,12 @@ class BanDataPurger : public Timer
{
Channel *c = it->second;
- BanData *bd = c->GetExt<BanData *>("bs_main_bandata");
+ BanData *bd = c->GetExt<BanData>("bandata");
if (bd != NULL)
{
bd->purge();
if (bd->empty())
- c->Shrink("bs_main_bandata");
+ c->Shrink<BanData>("bandata");
}
}
}
@@ -709,6 +969,10 @@ class BanDataPurger : public Timer
class BSKick : public Module
{
+ ExtensibleItem<BanData> bandata;
+ ExtensibleItem<UserData> userdata;
+ KickerDataImpl::ExtensibleItem kickerdata;
+
CommandBSKick commandbskick;
CommandBSKickAMSG commandbskickamsg;
CommandBSKickBadwords commandbskickbadwords;
@@ -721,17 +985,14 @@ class BSKick : public Module
CommandBSKickReverses commandbskickreverse;
CommandBSKickUnderlines commandbskickunderlines;
+ CommandBSSetDontKickOps commandbssetdontkickops;
+ CommandBSSetDontKickVoices commandbssetdontkickvoices;
+
BanDataPurger purger;
BanData::Data &GetBanData(User *u, Channel *c)
{
- BanData *bd = c->GetExt<BanData *>("bs_main_bandata");
- if (bd == NULL)
- {
- bd = new BanData();
- c->Extend("bs_main_bandata", bd);
- }
-
+ BanData *bd = bandata.Require(c);
return bd->get(u->GetMask());
}
@@ -741,17 +1002,11 @@ class BSKick : public Module
if (uc == NULL)
return NULL;
- UserData *ud = uc->GetExt<UserData *>("bs_main_userdata");
- if (ud == NULL)
- {
- ud = new UserData();
- uc->Extend("bs_main_userdata", ud);
- }
-
+ UserData *ud = userdata.Require(uc);
return ud;
}
- void check_ban(ChannelInfo *ci, User *u, int ttbtype)
+ void check_ban(ChannelInfo *ci, User *u, KickerData *kd, int ttbtype)
{
/* Don't ban ulines */
if (u->server->IsULined())
@@ -760,9 +1015,9 @@ class BSKick : public Module
BanData::Data &bd = this->GetBanData(u, ci->c);
++bd.ttb[ttbtype];
- if (ci->ttb[ttbtype] && bd.ttb[ttbtype] >= ci->ttb[ttbtype])
+ if (kd->ttb[ttbtype] && bd.ttb[ttbtype] >= kd->ttb[ttbtype])
{
- /* Should not use == here because bd.ttb[ttbtype] could possibly be > ci->ttb[ttbtype]
+ /* Should not use == here because bd.ttb[ttbtype] could possibly be > kd->ttb[ttbtype]
* if the TTB was changed after it was not set (0) before and the user had already been
* kicked a few times. Bug #1056 - Adam */
@@ -793,26 +1048,136 @@ class BSKick : public Module
public:
BSKick(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ bandata(this, "bandata"),
+ userdata(this, "userdata"),
+ kickerdata(this, "kickerdata"),
+
commandbskick(this),
commandbskickamsg(this), commandbskickbadwords(this), commandbskickbolds(this), commandbskickcaps(this),
commandbskickcolors(this), commandbskickflood(this), commandbskickitalics(this), commandbskickrepeat(this),
commandbskickreverse(this), commandbskickunderlines(this),
+ commandbssetdontkickops(this), commandbssetdontkickvoices(this),
+
purger(this)
{
me = this;
}
- ~BSKick()
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
{
- for (channel_map::const_iterator cit = ChannelList.begin(), cit_end = ChannelList.end(); cit != cit_end; ++cit)
+ if (!ci)
+ return;
+
+ Anope::string enabled = Language::Translate(source.nc, _("Enabled"));
+ Anope::string disabled = Language::Translate(source.nc, _("Disabled"));
+ KickerData *kd = kickerdata.Get(ci);
+
+ if (kd && kd->badwords)
+ {
+ if (kd->ttb[TTB_BADWORDS])
+ info[_("Bad words kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BADWORDS]);
+ else
+ info[_("Bad words kicker")] = enabled;
+ }
+ else
+ info[_("Bad words kicker")] = disabled;
+
+ if (kd && kd->bolds)
+ {
+ if (kd->ttb[TTB_BOLDS])
+ info[_("Bolds kicker")] = Anope::printf("%s (%d kick(s) to ban)", enabled.c_str(), kd->ttb[TTB_BOLDS]);
+ else
+ info[_("Bolds kicker")] = enabled;
+ }
+ else
+ info[_("Bolds kicker")] = disabled;
+
+ if (kd && kd->caps)
+ {
+ if (kd->ttb[TTB_CAPS])
+ info[_("Caps kicker")] = Anope::printf(_("%s (%d kick(s) to ban; minimum %d/%d%%"), enabled.c_str(), kd->ttb[TTB_CAPS], kd->capsmin, kd->capspercent);
+ else
+ info[_("Caps kicker")] = Anope::printf(_("%s (minimum %d/%d%%)"), enabled.c_str(), kd->capsmin, kd->capspercent);
+ }
+ else
+ info[_("Caps kicker")] = disabled;
+
+ if (kd && kd->colors)
+ {
+ if (kd->ttb[TTB_COLORS])
+ info[_("Colors kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_COLORS]);
+ else
+ info[_("Colors kicker")] = enabled;
+ }
+ else
+ info[_("Colors kicker")] = disabled;
+
+ if (kd && kd->flood)
+ {
+ if (kd->ttb[TTB_FLOOD])
+ info[_("Flood kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d lines in %ds"), enabled.c_str(), kd->ttb[TTB_FLOOD], kd->floodlines, kd->floodsecs);
+ else
+ info[_("Flood kicker")] = Anope::printf(_("%s (%d lines in %ds)"), enabled.c_str(), kd->floodlines, kd->floodsecs);
+ }
+ else
+ info[_("Flood kicker")] = disabled;
+
+ if (kd && kd->repeat)
{
- Channel *c = cit->second;
- for (Channel::ChanUserList::iterator it = c->users.begin(), it_end = c->users.end(); it != it_end; ++it)
- it->second->Shrink("bs_main_userdata");
- c->Shrink("bs_main_bandata");
+ if (kd->ttb[TTB_REPEAT])
+ info[_("Repeat kicker")] = Anope::printf(_("%s (%d kick(s) to ban; %d times)"), enabled.c_str(), kd->ttb[TTB_REPEAT], kd->repeattimes);
+ else
+ info[_("Repeat kicker")] = Anope::printf(_("%s (%d times)"), enabled.c_str(), kd->repeattimes);
+ }
+ else
+ info[_("Repeat kicker")] = disabled;
+
+ if (kd && kd->reverses)
+ {
+ if (kd->ttb[TTB_REVERSES])
+ info[_("Reverses kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_REVERSES]);
+ else
+ info[_("Reverses kicker")] = enabled;
}
+ else
+ info[_("Reverses kicker")] = disabled;
+
+ if (kd && kd->underlines)
+ {
+ if (kd->ttb[TTB_UNDERLINES])
+ info[_("Underlines kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_UNDERLINES]);
+ else
+ info[_("Underlines kicker")] = enabled;
+ }
+ else
+ info[_("Underlines kicker")] = disabled;
+
+ if (kd && kd->italics)
+ {
+ if (kd->ttb[TTB_ITALICS])
+ info[_("Italics kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_ITALICS]);
+ else
+ info[_("Italics kicker")] = enabled;
+ }
+ else
+ info[_("Italics kicker")] = disabled;
+
+ if (kd && kd->amsgs)
+ {
+ if (kd->ttb[TTB_AMSGS])
+ info[_("AMSG kicker")] = Anope::printf(_("%s (%d kick(s) to ban)"), enabled.c_str(), kd->ttb[TTB_AMSGS]);
+ else
+ info[_("AMSG kicker")] = enabled;
+ }
+ else
+ info[_("AMSG kicker")] = disabled;
+
+ if (kd && kd->dontkickops)
+ info.AddOption(_("Ops Protection"));
+ if (kd && kd->dontkickvoices)
+ info.AddOption(_("Voices Protection"));
}
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
@@ -828,12 +1193,15 @@ class BSKick : public Module
ChannelInfo *ci = c->ci;
if (ci == NULL)
return;
+ KickerData *kd = kickerdata.Get(ci);
+ if (kd == NULL)
+ return;
if (ci->AccessFor(u).HasPriv("NOKICK"))
return;
- else if (ci->HasExt("BS_DONTKICKOPS") && (c->HasUserStatus(u, "HALFOP") || c->HasUserStatus(u, "OP") || c->HasUserStatus(u, "PROTECT") || c->HasUserStatus(u, "OWNER")))
+ else if (kd->dontkickops && (c->HasUserStatus(u, "HALFOP") || c->HasUserStatus(u, "OP") || c->HasUserStatus(u, "PROTECT") || c->HasUserStatus(u, "OWNER")))
return;
- else if (ci->HasExt("BS_DONTKICKVOICES") && c->HasUserStatus(u, "VOICE"))
+ else if (kd->dontkickvoices && c->HasUserStatus(u, "VOICE"))
return;
Anope::string realbuf = msg;
@@ -851,47 +1219,47 @@ class BSKick : public Module
return;
/* Bolds kicker */
- if (ci->HasExt("BS_KICK_BOLDS") && realbuf.find(2) != Anope::string::npos)
+ if (kd->bolds && realbuf.find(2) != Anope::string::npos)
{
- check_ban(ci, u, TTB_BOLDS);
+ check_ban(ci, u, kd, TTB_BOLDS);
bot_kick(ci, u, _("Don't use bolds on this channel!"));
return;
}
/* Color kicker */
- if (ci->HasExt("BS_KICK_COLORS") && realbuf.find(3) != Anope::string::npos)
+ if (kd->colors && realbuf.find(3) != Anope::string::npos)
{
- check_ban(ci, u, TTB_COLORS);
+ check_ban(ci, u, kd, TTB_COLORS);
bot_kick(ci, u, _("Don't use colors on this channel!"));
return;
}
/* Reverses kicker */
- if (ci->HasExt("BS_KICK_REVERSES") && realbuf.find(22) != Anope::string::npos)
+ if (kd->reverses && realbuf.find(22) != Anope::string::npos)
{
- check_ban(ci, u, TTB_REVERSES);
+ check_ban(ci, u, kd, TTB_REVERSES);
bot_kick(ci, u, _("Don't use reverses on this channel!"));
return;
}
/* Italics kicker */
- if (ci->HasExt("BS_KICK_ITALICS") && realbuf.find(29) != Anope::string::npos)
+ if (kd->italics && realbuf.find(29) != Anope::string::npos)
{
- check_ban(ci, u, TTB_ITALICS);
+ check_ban(ci, u, kd, TTB_ITALICS);
bot_kick(ci, u, _("Don't use italics on this channel!"));
return;
}
/* Underlines kicker */
- if (ci->HasExt("BS_KICK_UNDERLINES") && realbuf.find(31) != Anope::string::npos)
+ if (kd->underlines && realbuf.find(31) != Anope::string::npos)
{
- check_ban(ci, u, TTB_UNDERLINES);
+ check_ban(ci, u, kd, TTB_UNDERLINES);
bot_kick(ci, u, _("Don't use underlines on this channel!"));
return;
}
/* Caps kicker */
- if (ci->HasExt("BS_KICK_CAPS") && realbuf.length() >= static_cast<unsigned>(ci->capsmin))
+ if (kd->caps && realbuf.length() >= static_cast<unsigned>(kd->capsmin))
{
int i = 0, l = 0;
@@ -908,26 +1276,27 @@ class BSKick : public Module
* percentage of caps to kick for; the rest is ignored. -GD
*/
- if ((i || l) && i >= ci->capsmin && i * 100 / (i + l) >= ci->capspercent)
+ if ((i || l) && i >= kd->capsmin && i * 100 / (i + l) >= kd->capspercent)
{
- check_ban(ci, u, TTB_CAPS);
+ check_ban(ci, u, kd, TTB_CAPS);
bot_kick(ci, u, _("Turn caps lock OFF!"));
return;
}
}
/* Bad words kicker */
- if (ci->HasExt("BS_KICK_BADWORDS"))
+ if (kd->badwords)
{
bool mustkick = false;
+ BadWords *badwords = ci->GetExt<BadWords>("badwords");
/* Normalize the buffer */
Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");
- for (unsigned i = 0, end = ci->GetBadWordCount(); i < end; ++i)
+ for (unsigned i = 0; badwords && i < badwords->GetBadWordCount(); ++i)
{
- const BadWord *bw = ci->GetBadWord(i);
+ const BadWord *bw = badwords->GetBadWord(i);
if (bw->type == BW_ANY && ((casesensitive && nbuf.find(bw->word) != Anope::string::npos) || (!casesensitive && nbuf.find_ci(bw->word) != Anope::string::npos)))
mustkick = true;
@@ -983,7 +1352,7 @@ class BSKick : public Module
if (mustkick)
{
- check_ban(ci, u, TTB_BADWORDS);
+ check_ban(ci, u, kd, TTB_BADWORDS);
if (Config->GetModule(me)->Get<bool>("gentlebadwordreason"))
bot_kick(ci, u, _("Watch your language!"));
else
@@ -999,34 +1368,34 @@ class BSKick : public Module
if (ud)
{
/* Flood kicker */
- if (ci->HasExt("BS_KICK_FLOOD"))
+ if (kd->flood)
{
- if (Anope::CurTime - ud->last_start > ci->floodsecs)
+ if (Anope::CurTime - ud->last_start > kd->floodsecs)
{
ud->last_start = Anope::CurTime;
ud->lines = 0;
}
++ud->lines;
- if (ud->lines >= ci->floodlines)
+ if (ud->lines >= kd->floodlines)
{
- check_ban(ci, u, TTB_FLOOD);
+ check_ban(ci, u, kd, TTB_FLOOD);
bot_kick(ci, u, _("Stop flooding!"));
return;
}
}
/* Repeat kicker */
- if (ci->HasExt("BS_KICK_REPEAT"))
+ if (kd->repeat)
{
if (!ud->lastline.equals_ci(realbuf))
ud->times = 0;
else
++ud->times;
- if (ud->times >= ci->repeattimes)
+ if (ud->times >= kd->repeattimes)
{
- check_ban(ci, u, TTB_REPEAT);
+ check_ban(ci, u, kd, TTB_REPEAT);
bot_kick(ci, u, _("Stop repeating yourself!"));
return;
}
@@ -1039,9 +1408,9 @@ class BSKick : public Module
Channel *chan = it->second->chan;
++it;
- if (chan->ci && chan->ci->HasExt("BS_KICK_AMSGS") && !chan->ci->AccessFor(u).HasPriv("NOKICK"))
+ if (chan->ci && kd->amsgs && !chan->ci->AccessFor(u).HasPriv("NOKICK"))
{
- check_ban(chan->ci, u, TTB_AMSGS);
+ check_ban(chan->ci, u, kd, TTB_AMSGS);
bot_kick(chan->ci, u, _("Don't use AMSGs!"));
}
}
diff --git a/modules/commands/bs_set.cpp b/modules/commands/bs_set.cpp
index fa2bd716f..4e1e77ad1 100644
--- a/modules/commands/bs_set.cpp
+++ b/modules/commands/bs_set.cpp
@@ -127,314 +127,6 @@ class CommandBSSetBanExpire : public Command
}
};
-class CommandBSSetDontKickOps : public Command
-{
- public:
- CommandBSSetDontKickOps(Module *creator, const Anope::string &sname = "botserv/set/dontkickops") : Command(creator, sname, 2, 2)
- {
- this->SetDesc(_("To protect ops against bot kicks"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- AccessGroup access = source.AccessFor(ci);
- if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- bool override = !access.HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickops";
-
- ci->ExtendMetadata("BS_DONTKICKOPS");
- source.Reply(_("Bot \002won't kick ops\002 on channel %s."), ci->name.c_str());
- }
- else if (params[1].equals_ci("OFF"))
- {
- bool override = !access.HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickops";
-
- ci->Shrink("BS_DONTKICKOPS");
- source.Reply(_("Bot \002will kick ops\002 on channel %s."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, source.command);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(_(" \n"
- "Enables or disables \002ops protection\002 mode on a channel.\n"
- "When it is enabled, ops won't be kicked by the bot\n"
- "even if they don't match the NOKICK level."));
- return true;
- }
-};
-
-class CommandBSSetDontKickVoices : public Command
-{
- public:
- CommandBSSetDontKickVoices(Module *creator, const Anope::string &sname = "botserv/set/dontkickvoices") : Command(creator, sname, 2, 2)
- {
- this->SetDesc(_("To protect voices against bot kicks"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- AccessGroup access = source.AccessFor(ci);
- if (!source.HasPriv("botserv/administration") && !access.HasPriv("SET"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- bool override = !access.HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable dontkickvoices";
-
- ci->ExtendMetadata("BS_DONTKICKVOICES");
- source.Reply(_("Bot \002won't kick voices\002 on channel %s."), ci->name.c_str());
- }
- else if (params[1].equals_ci("OFF"))
- {
- bool override = !access.HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable dontkickvoices";
-
- ci->Shrink("BS_DONTKICKVOICES");
- source.Reply(_("Bot \002will kick voices\002 on channel %s."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, source.command);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(_(" \n"
- "Enables or disables \002voices protection\002 mode on a channel.\n"
- "When it is enabled, voices won't be kicked by the bot\n"
- "even if they don't match the NOKICK level."));
- return true;
- }
-};
-
-class CommandBSSetFantasy : public Command
-{
- public:
- CommandBSSetFantasy(Module *creator, const Anope::string &sname = "botserv/set/fantasy") : Command(creator, sname, 2, 2)
- {
- this->SetDesc(_("Enable fantaisist commands"));
- this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- const Anope::string &value = params[1];
-
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
- return;
- }
-
- if (value.equals_ci("ON"))
- {
- bool override = !source.AccessFor(ci).HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable fantasy";
-
- ci->ExtendMetadata("BS_FANTASY");
- source.Reply(_("Fantasy mode is now \002on\002 on channel %s."), ci->name.c_str());
- }
- else if (value.equals_ci("OFF"))
- {
- bool override = !source.AccessFor(ci).HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable fantasy";
-
- ci->Shrink("BS_FANTASY");
- source.Reply(_("Fantasy mode is now \002off\002 on channel %s."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, source.command);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(_(" \n"
- "Enables or disables \002fantasy\002 mode on a channel.\n"
- "When it is enabled, users will be able to use\n"
- "fantasy commands on a channel when prefixed\n"
- "with one of the following fantasy characters: \002%s\002\n"
- " \n"
- "Note that users wanting to use fantaisist\n"
- "commands MUST have enough access for both\n"
- "the FANTASIA and the command they are executing."),
- Config->GetModule("botserv")->Get<const Anope::string>("fantasycharacter", "!").c_str());
- return true;
- }
-};
-
-class CommandBSSetGreet : public Command
-{
- public:
- CommandBSSetGreet(Module *creator, const Anope::string &sname = "botserv/set/greet") : Command(creator, sname, 2, 2)
- {
- this->SetDesc(_("Enable greet messages"));
- this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- const Anope::string &value = params[1];
-
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (Anope::ReadOnly)
- {
- source.Reply(_("Sorry, bot option setting is temporarily disabled."));
- return;
- }
-
- if (value.equals_ci("ON"))
- {
- bool override = !source.AccessFor(ci).HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable greets";
-
- ci->ExtendMetadata("BS_GREET");
- source.Reply(_("Greet mode is now \002on\002 on channel %s."), ci->name.c_str());
- }
- else if (value.equals_ci("OFF"))
- {
- bool override = !source.AccessFor(ci).HasPriv("SET");
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable greets";
-
- ci->Shrink("BS_GREET");
- source.Reply(_("Greet mode is now \002off\002 on channel %s."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, source.command);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(_(" \n"
- "Enables or disables \002greet\002 mode on a channel.\n"
- "When it is enabled, the bot will display greet\n"
- "messages of users joining the channel, provided\n"
- "they have enough access to the channel."));
- return true;
- }
-};
-
-class CommandBSSetNoBot : public Command
-{
- public:
- CommandBSSetNoBot(Module *creator, const Anope::string &sname = "botserv/set/nobot") : Command(creator, sname, 2, 2)
- {
- this->SetDesc(_("Prevent a bot from being assigned to a channel"));
- this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- const Anope::string &value = params[1];
-
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- if (value.equals_ci("ON"))
- {
- Log(LOG_ADMIN, source, this, ci) << "to enable nobot";
-
- ci->ExtendMetadata("BS_NOBOT");
- if (ci->bi)
- ci->bi->UnAssign(source.GetUser(), ci);
- source.Reply(_("No-bot mode is now \002on\002 on channel %s."), ci->name.c_str());
- }
- else if (value.equals_ci("OFF"))
- {
- Log(LOG_ADMIN, source, this, ci) << "to disable nobot";
-
- ci->Shrink("BS_NOBOT");
- source.Reply(_("No-bot mode is now \002off\002 on channel %s."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, source.command);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(_(" \n"
- "This option makes a channel be unassignable. If a bot\n"
- "is already assigned to the channel, it is unassigned\n"
- "automatically when you enable the option."));
- return true;
- }
-};
-
class CommandBSSetPrivate : public Command
{
public:
@@ -483,17 +175,12 @@ class BSSet : public Module
{
CommandBSSet commandbsset;
CommandBSSetBanExpire commandbssetbanexpire;
- CommandBSSetDontKickOps commandbssetdontkickops;
- CommandBSSetDontKickVoices commandbssetdontkickvoices;
- CommandBSSetFantasy commandbssetfantasy;
- CommandBSSetGreet commandbssetgreet;
- CommandBSSetNoBot commandbssetnobot;
CommandBSSetPrivate commandbssetprivate;
public:
BSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandbsset(this), commandbssetbanexpire(this), commandbssetdontkickops(this), commandbssetdontkickvoices(this),
- commandbssetfantasy(this), commandbssetgreet(this), commandbssetnobot(this), commandbssetprivate(this)
+ commandbsset(this), commandbssetbanexpire(this),
+ commandbssetprivate(this)
{
}
diff --git a/modules/commands/cs_akick.cpp b/modules/commands/cs_akick.cpp
index 17a20a0dd..3764c54fc 100644
--- a/modules/commands/cs_akick.cpp
+++ b/modules/commands/cs_akick.cpp
@@ -20,8 +20,8 @@ class CommandCSAKick : public Command
const NickAlias *na = NickAlias::Find(mask);
NickCore *nc = NULL;
const AutoKick *akick;
-
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
+
if (reason.length() > reasonmax)
reason = reason.substr(0, reasonmax);
diff --git a/modules/commands/cs_clone.cpp b/modules/commands/cs_clone.cpp
index d9ba97894..a1b04d103 100644
--- a/modules/commands/cs_clone.cpp
+++ b/modules/commands/cs_clone.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/bs_badwords.h"
class CommandCSClone : public Command
{
@@ -125,12 +126,16 @@ public:
}
else if (what.equals_ci("BADWORDS"))
{
- target_ci->ClearBadWords();
- for (unsigned i = 0; i < ci->GetBadWordCount(); ++i)
- {
- const BadWord *bw = ci->GetBadWord(i);
- target_ci->AddBadWord(bw->word, bw->type);
- }
+ BadWords *target_badwords = target_ci->GetExt<BadWords>("badwords"),
+ *badwords = ci->Require<BadWords>("badwords");
+ if (target_badwords)
+ target_badwords->ClearBadWords();
+ if (badwords)
+ for (unsigned i = 0; i < badwords->GetBadWordCount(); ++i)
+ {
+ const BadWord *bw = badwords->GetBadWord(i);
+ target_badwords->AddBadWord(bw->word, bw->type);
+ }
source.Reply(_("All badword entries from \002%s\002 have been cloned to \002%s\002."), channel.c_str(), target.c_str());
}
@@ -141,8 +146,6 @@ public:
}
Log(LOG_COMMAND, source, this, ci) << "to clone " << (what.empty() ? "everything from it" : what) << " to " << target_ci->name;
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
diff --git a/modules/commands/cs_drop.cpp b/modules/commands/cs_drop.cpp
index 3f14aea65..adbe1f2ca 100644
--- a/modules/commands/cs_drop.cpp
+++ b/modules/commands/cs_drop.cpp
@@ -37,23 +37,20 @@ class CommandCSDrop : public Command
return;
}
- if (ci->HasExt("SUSPENDED") && !source.HasCommand("chanserv/drop"))
- {
- source.Reply(CHAN_X_SUSPENDED, chan.c_str());
- return;
- }
-
if ((ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER")) && !source.HasCommand("chanserv/drop"))
{
source.Reply(ACCESS_DENIED);
return;
}
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnChanDrop, MOD_RESULT, (source, ci));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
bool override = (ci->HasExt("SECUREFOUNDER") ? !source.IsFounder(ci) : !source.AccessFor(ci).HasPriv("FOUNDER"));
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "(founder was: " << (ci->GetFounder() ? ci->GetFounder()->display : "none") << ")";
- FOREACH_MOD(OnChanDrop, (ci));
-
Reference<Channel> c = ci->c;
delete ci;
diff --git a/modules/commands/cs_enforce.cpp b/modules/commands/cs_enforce.cpp
index e40676186..b683332f5 100644
--- a/modules/commands/cs_enforce.cpp
+++ b/modules/commands/cs_enforce.cpp
@@ -27,7 +27,7 @@ class CommandCSEnforce : public Command
* if it's off.
*/
bool hadsecureops = ci->HasExt("SECUREOPS");
- ci->ExtendMetadata("SECUREOPS");
+ ci->Extend<bool>("SECUREOPS");
for (Channel::ChanUserList::iterator it = ci->c->users.begin(), it_end = ci->c->users.end(); it != it_end; ++it)
{
@@ -37,7 +37,7 @@ class CommandCSEnforce : public Command
}
if (!hadsecureops)
- ci->Shrink("SECUREOPS");
+ ci->Shrink<bool>("SECUREOPS");
source.Reply(_("Secureops enforced on %s."), ci->name.c_str());
}
diff --git a/modules/commands/cs_entrymsg.cpp b/modules/commands/cs_entrymsg.cpp
index f94aca44c..d3d3bb71b 100644
--- a/modules/commands/cs_entrymsg.cpp
+++ b/modules/commands/cs_entrymsg.cpp
@@ -37,9 +37,9 @@ struct EntryMsg : Serializable
static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
};
-struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >, ExtensibleItem
+struct EntryMessageList : Serialize::Checker<std::vector<EntryMsg *> >
{
- EntryMessageList() : Serialize::Checker<std::vector<EntryMsg *> >("EntryMsg") { }
+ EntryMessageList(Extensible *) : Serialize::Checker<std::vector<EntryMsg *> >("EntryMsg") { }
~EntryMessageList()
{
@@ -71,12 +71,9 @@ Serializable* EntryMsg::Unserialize(Serializable *obj, Serialize::Data &data)
return msg;
}
- EntryMessageList *messages = ci->GetExt<EntryMessageList *>("cs_entrymsg");
+ EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg");
if (messages == NULL)
- {
- messages = new EntryMessageList();
- ci->Extend("cs_entrymsg", messages);
- }
+ messages = ci->Extend<EntryMessageList>("entrymsg");
data["when"] >> swhen;
@@ -90,12 +87,9 @@ class CommandEntryMessage : public Command
private:
void DoList(CommandSource &source, ChannelInfo *ci)
{
- EntryMessageList *messages = ci->GetExt<EntryMessageList *>("cs_entrymsg");
+ EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg");
if (messages == NULL)
- {
- messages = new EntryMessageList();
- ci->Extend("cs_entrymsg", messages);
- }
+ messages = ci->Extend<EntryMessageList>("entrymsg");
if ((*messages)->empty())
{
@@ -129,12 +123,9 @@ class CommandEntryMessage : public Command
void DoAdd(CommandSource &source, ChannelInfo *ci, const Anope::string &message)
{
- EntryMessageList *messages = ci->GetExt<EntryMessageList *>("cs_entrymsg");
+ EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg");
if (messages == NULL)
- {
- messages = new EntryMessageList();
- ci->Extend("cs_entrymsg", messages);
- }
+ messages = ci->Extend<EntryMessageList>("entrymsg");
if ((*messages)->size() >= Config->GetModule(this->owner)->Get<unsigned>("maxentries"))
source.Reply(_("The entry message list for \002%s\002 is full."), ci->name.c_str());
@@ -148,12 +139,9 @@ class CommandEntryMessage : public Command
void DoDel(CommandSource &source, ChannelInfo *ci, const Anope::string &message)
{
- EntryMessageList *messages = ci->GetExt<EntryMessageList *>("cs_entrymsg");
+ EntryMessageList *messages = ci->GetExt<EntryMessageList>("entrymsg");
if (messages == NULL)
- {
- messages = new EntryMessageList();
- ci->Extend("cs_entrymsg", messages);
- }
+ messages = ci->Extend<EntryMessageList>("entrymsg");
if (!message.is_pos_number_only())
source.Reply(("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str());
@@ -169,7 +157,7 @@ class CommandEntryMessage : public Command
delete (*messages)->at(i - 1);
(*messages)->erase((*messages)->begin() + i - 1);
if ((*messages)->empty())
- ci->Shrink("cs_entrymsg");
+ ci->Shrink<EntryMessageList>("entrymsg");
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
}
@@ -185,14 +173,7 @@ class CommandEntryMessage : public Command
void DoClear(CommandSource &source, ChannelInfo *ci)
{
- EntryMessageList *messages = ci->GetExt<EntryMessageList *>("cs_entrymsg");
- if (messages != NULL)
- {
- for (unsigned i = 0; i < (*messages)->size(); ++i)
- delete (*messages)->at(i);
- (*messages)->clear();
- ci->Shrink("cs_entrymsg");
- }
+ ci->Shrink<EntryMessageList>("entrymsg");
Log(source.IsFounder(ci) ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove all messages";
source.Reply(_("Entry messages for \002%s\002 have been cleared."), ci->name.c_str());
@@ -267,9 +248,10 @@ class CSEntryMessage : public Module
{
Serialize::Type entrymsg_type;
CommandEntryMessage commandentrymsg;
+ ExtensibleItem<EntryMessageList> eml;
public:
- CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), entrymsg_type("EntryMsg", EntryMsg::Unserialize), commandentrymsg(this)
+ CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), entrymsg_type("EntryMsg", EntryMsg::Unserialize), commandentrymsg(this), eml(this, "entrymsg")
{
}
@@ -278,7 +260,7 @@ class CSEntryMessage : public Module
{
if (u && c && c->ci && u->server->IsSynced())
{
- EntryMessageList *messages = c->ci->GetExt<EntryMessageList *>("cs_entrymsg");
+ EntryMessageList *messages = c->ci->GetExt<EntryMessageList>("entrymsg");
if (messages != NULL)
for (unsigned i = 0; i < (*messages)->size(); ++i)
diff --git a/modules/commands/cs_info.cpp b/modules/commands/cs_info.cpp
index 0d3623c00..8f910fc83 100644
--- a/modules/commands/cs_info.cpp
+++ b/modules/commands/cs_info.cpp
@@ -13,17 +13,6 @@
class CommandCSInfo : public Command
{
- void CheckOptStr(Anope::string &buf, const Anope::string &opt, const char *str, const ChannelInfo *ci, const NickCore *nc)
- {
- if (ci->HasExt(opt))
- {
- if (!buf.empty())
- buf += ", ";
-
- buf += Language::Translate(nc, str);
- }
- }
-
public:
CommandCSInfo(Module *creator) : Command(creator, "chanserv/info", 1, 2)
{
@@ -66,43 +55,9 @@ class CommandCSInfo : public Command
info["Registered"] = Anope::strftime(ci->time_registered);
info["Last used"] = Anope::strftime(ci->last_used);
- const ModeLock *secret = ci->GetMLock("SECRET");
- if (!ci->last_topic.empty() && (show_all || ((!secret || secret->set == false) && (!ci->c || !ci->c->HasMode("SECRET")))))
- {
- info["Last topic"] = ci->last_topic;
- info["Topic set by"] = ci->last_topic_setter;
- }
-
if (show_all)
{
info["Ban type"] = stringify(ci->bantype);
-
- Anope::string optbuf;
- CheckOptStr(optbuf, "KEEPTOPIC", _("Topic Retention"), ci, nc);
- CheckOptStr(optbuf, "PEACE", _("Peace"), ci, nc);
- CheckOptStr(optbuf, "PRIVATE", _("Private"), ci, nc);
- CheckOptStr(optbuf, "RESTRICTED", _("Restricted Access"), ci, nc);
- CheckOptStr(optbuf, "SECURE", _("Secure"), ci, nc);
- CheckOptStr(optbuf, "SECUREFOUNDER", _("Secure Founder"), ci, nc);
- CheckOptStr(optbuf, "SECUREOPS", _("Secure Ops"), ci, nc);
- if (ci->HasExt("SIGNKICK"))
- CheckOptStr(optbuf, "SIGNKICK", _("Signed kicks"), ci, nc);
- else
- CheckOptStr(optbuf, "SIGNKICK_LEVEL", _("Signed kicks"), ci, nc);
- CheckOptStr(optbuf, "TOPICLOCK", _("Topic Lock"), ci, nc);
- CheckOptStr(optbuf, "PERSIST", _("Persistent"), ci, nc);
- CheckOptStr(optbuf, "NO_EXPIRE", _("No expire"), ci, nc);
- CheckOptStr(optbuf, "STATS", _("Chanstats"), ci, nc);
-
- info["Options"] = optbuf.empty() ? _("None") : optbuf;
-
- const Anope::string &ml = ci->GetMLockAsString(true);
- if (!ml.empty())
- info["Mode lock"] = ml;
-
- time_t chanserv_expire = Config->GetModule("chanserv")->Get<time_t>("expire", "14d");
- if (!ci->HasExt("NO_EXPIRE") && chanserv_expire && !Anope::NoExpire)
- info["Expires on"] = Anope::strftime(ci->last_used + chanserv_expire);
}
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
diff --git a/modules/commands/cs_list.cpp b/modules/commands/cs_list.cpp
index 9e2df0a62..a92729b61 100644
--- a/modules/commands/cs_list.cpp
+++ b/modules/commands/cs_list.cpp
@@ -81,11 +81,11 @@ class CommandCSList : public Command
{
const ChannelInfo *ci = it->second;
- if (!is_servadmin && (ci->HasExt("PRIVATE") || ci->HasExt("SUSPENDED")))
+ if (!is_servadmin && (ci->HasExt("CS_PRIVATE") || ci->HasExt("SUSPENDED")))
continue;
else if (suspended && !ci->HasExt("SUSPENDED"))
continue;
- else if (channoexpire && !ci->HasExt("NO_EXPIRE"))
+ else if (channoexpire && !ci->HasExt("CS_NO_EXPIRE"))
continue;
if (pattern.equals_ci(ci->name) || ci->name.equals_ci(spattern) || Anope::Match(ci->name, pattern, false, true) || Anope::Match(ci->name, spattern, false, true))
@@ -93,7 +93,7 @@ class CommandCSList : public Command
if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nchans <= listmax)
{
bool isnoexpire = false;
- if (is_servadmin && (ci->HasExt("NO_EXPIRE")))
+ if (is_servadmin && (ci->HasExt("CS_NO_EXPIRE")))
isnoexpire = true;
ListFormatter::ListEntry entry;
@@ -159,14 +159,89 @@ class CommandCSList : public Command
}
};
+class CommandCSSetPrivate : public Command
+{
+ public:
+ CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2)
+ {
+ this->SetDesc(_("Hide channel from the LIST command"));
+ this->SetSyntax(_("\037channel\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (params[1].equals_ci("ON"))
+ {
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable private";
+ ci->Extend<bool>("CS_PRIVATE");
+ source.Reply(_("Private option for %s is now \002on\002."), ci->name.c_str());
+ }
+ else if (params[1].equals_ci("OFF"))
+ {
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable private";
+ ci->Shrink<bool>("CS_PRIVATE");
+ source.Reply(_("Private option for %s is now \002off\002."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "PRIVATE");
+
+ return;
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Enables or disables the \002private\002 option for a channel."));
+
+ BotInfo *bi;
+ Anope::string cmd;
+ if (Command::FindCommandFromService("chanserv/list", bi, cmd))
+ source.Reply(_("When \002private\002 is set, the channel will not appear in\n"
+ "%s's %s command."), bi->nick.c_str(), cmd.c_str());
+ return true;
+ }
+};
+
class CSList : public Module
{
CommandCSList commandcslist;
+ CommandCSSetPrivate commandcssetprivate;
+
+ SerializableExtensibleItem<bool> priv;
public:
- CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), commandcslist(this)
+ CSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ commandcslist(this), commandcssetprivate(this), priv(this, "CS_PRIVATE")
{
}
+
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ {
+ if (!show_all)
+ return;
+
+ if (priv.HasExt(ci))
+ info.AddOption(_("Private"));
+ }
};
MODULE_INIT(CSList)
diff --git a/modules/commands/cs_log.cpp b/modules/commands/cs_log.cpp
index 969ebe5ab..bc6ba73c6 100644
--- a/modules/commands/cs_log.cpp
+++ b/modules/commands/cs_log.cpp
@@ -10,6 +10,77 @@
*/
#include "module.h"
+#include "modules/cs_log.h"
+
+struct LogSettingImpl : LogSetting, Serializable
+{
+ LogSettingImpl() : Serializable("LogSetting")
+ {
+ }
+
+ ~LogSettingImpl()
+ {
+ ChannelInfo *ci = ChannelInfo::Find(chan);
+ if (ci)
+ {
+ LogSettings *ls = ci->Require<LogSettings>("logsettings");
+ LogSettings::iterator it = std::find((*ls)->begin(), (*ls)->end(), this);
+ if (it != (*ls)->end())
+ (*ls)->erase(it);
+ }
+ }
+
+ void Serialize(Serialize::Data &data) const anope_override
+ {
+ data["ci"] << chan;
+ data["service_name"] << service_name;
+ data["command_service"] << command_service;
+ data["command_name"] << command_name;
+ data["method"] << method;
+ data["extra"] << extra;
+ data["creator"] << creator;
+ data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
+ }
+
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ {
+ Anope::string sci;
+ data["ci"] >> sci;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
+ if (ci == NULL)
+ return NULL;
+
+ LogSetting *ls;
+ if (obj)
+ ls = anope_dynamic_static_cast<LogSettingImpl *>(obj);
+ else
+ {
+ LogSettings *lsettings = ci->Require<LogSettings>("logsettings");
+ ls = new LogSettingImpl();
+ (*lsettings)->push_back(ls);
+ }
+
+ ls->chan = ci->name;
+ data["service_name"] >> ls->service_name;
+ data["command_service"] >> ls->command_service;
+ data["command_name"] >> ls->command_name;
+ data["method"] >> ls->method;
+ data["extra"] >> ls->extra;
+ data["creator"] >> ls->creator;
+ data["created"] >> ls->created;
+ }
+};
+
+struct LogSettingsImpl : LogSettings
+{
+ LogSettingsImpl(Extensible *) { }
+
+ LogSetting *Create() anope_override
+ {
+ return new LogSettingImpl();
+ }
+};
class CommandCSLog : public Command
{
@@ -32,16 +103,17 @@ public:
source.Reply(ACCESS_DENIED);
else if (params.size() == 1)
{
- if (ci->log_settings->empty())
+ LogSettings *ls = ci->Require<LogSettings>("logsettings");
+ if (!ls || (*ls)->empty())
source.Reply(_("There currently are no logging configurations for %s."), ci->name.c_str());
else
{
ListFormatter list;
list.AddColumn("Number").AddColumn("Service").AddColumn("Command").AddColumn("Method").AddColumn("");
- for (unsigned i = 0; i < ci->log_settings->size(); ++i)
+ for (unsigned i = 0; i < (*ls)->size(); ++i)
{
- const LogSetting *log = ci->log_settings->at(i);
+ const LogSetting *log = (*ls)->at(i);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
@@ -63,6 +135,7 @@ public:
}
else if (params.size() > 2)
{
+ LogSettings *ls = ci->Require<LogSettings>("logsettings");
const Anope::string &command = params[1];
const Anope::string &method = params[2];
const Anope::string &extra = params.size() > 3 ? params[3] : "";
@@ -106,16 +179,15 @@ public:
bool override = !source.AccessFor(ci).HasPriv("SET");
- for (unsigned i = ci->log_settings->size(); i > 0; --i)
+ for (unsigned i = (*ls)->size(); i > 0; --i)
{
- LogSetting *log = ci->log_settings->at(i - 1);
+ LogSetting *log = (*ls)->at(i - 1);
if (log->service_name == bi->commands[command_name].name && log->method.equals_ci(method))
{
if (log->extra == extra)
{
delete log;
- ci->log_settings->erase(ci->log_settings->begin() + i - 1);
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to remove logging for " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
source.Reply(_("Logging for command %s on %s with log method %s%s%s has been removed."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
}
@@ -129,8 +201,8 @@ public:
}
}
- LogSetting *log = new LogSetting();
- log->ci = ci;
+ LogSetting *log = new LogSettingImpl();
+ log->chan = ci->name;
log->service_name = bi->commands[command_name].name;
log->command_service = bi->nick;
log->command_name = command_name;
@@ -139,7 +211,8 @@ public:
log->created = Anope::CurTime;
log->creator = source.GetNick();
- ci->log_settings->push_back(log);
+ (*ls)->push_back(log);
+
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to log " << command << " with method " << method << (extra == "" ? "" : " ") << extra;
source.Reply(_("Logging is now active for command %s on %s, using log method %s%s%s."), command_name.c_str(), bi->nick.c_str(), method.c_str(), extra.empty() ? "" : " ", extra.empty() ? "" : extra.c_str());
@@ -180,10 +253,13 @@ class CSLog : public Module
{
ServiceReference<MemoServService> MSService;
CommandCSLog commandcslog;
+ ExtensibleItem<LogSettingsImpl> logsettings;
+ Serialize::Type logsetting_type;
public:
CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- MSService("MemoServService", "MemoServ"), commandcslog(this)
+ MSService("MemoServService", "MemoServ"), commandcslog(this), logsettings(this, "logsettings"),
+ logsetting_type("LogSetting", LogSettingImpl::Unserialize)
{
}
@@ -193,25 +269,27 @@ class CSLog : public Module
if (l->type != LOG_COMMAND || l->u == NULL || l->c == NULL || l->ci == NULL || !Me || !Me->IsSynced())
return;
- for (unsigned i = l->ci->log_settings->size(); i > 0; --i)
- {
- const LogSetting *log = l->ci->log_settings->at(i - 1);
-
- if (log->service_name == l->c->name)
+ LogSettings *ls = logsettings.Get(l->ci);
+ if (ls)
+ for (unsigned i = 0; i < (*ls)->size(); ++i)
{
- Anope::string buffer = l->u->nick + " used " + log->command_name + " " + l->buf.str();
+ const LogSetting *log = (*ls)->at(i);
- if (log->method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
+ if (log->service_name == l->c->name)
{
- IRCD->SendPrivmsg(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
- l->ci->bi->lastmsg = Anope::CurTime;
+ Anope::string buffer = l->u->nick + " used " + log->command_name + " " + l->buf.str();
+
+ if (log->method.equals_ci("MESSAGE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
+ {
+ IRCD->SendPrivmsg(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
+ l->ci->bi->lastmsg = Anope::CurTime;
+ }
+ else if (log->method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
+ IRCD->SendNotice(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
+ else if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL)
+ MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
}
- else if (log->method.equals_ci("NOTICE") && l->ci->c && l->ci->bi && l->ci->c->FindUser(l->ci->bi) != NULL)
- IRCD->SendNotice(l->ci->bi, log->extra + l->ci->c->name, "%s", buffer.c_str());
- else if (log->method.equals_ci("MEMO") && MSService && l->ci->WhoSends() != NULL)
- MSService->Send(l->ci->WhoSends()->nick, l->ci->name, buffer, true);
}
- }
}
};
diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp
index 895bd3d5b..1299bc543 100644
--- a/modules/commands/cs_mode.cpp
+++ b/modules/commands/cs_mode.cpp
@@ -10,6 +10,234 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
+
+struct ModeLockImpl : ModeLock, Serializable
+{
+ ModeLockImpl() : Serializable("ModeLock")
+ {
+ }
+
+ ~ModeLockImpl()
+ {
+ ChannelInfo *chan = ChannelInfo::Find(ci);
+ if (chan)
+ {
+ ModeLocks *ml = chan->GetExt<ModeLocks>("modelocks");
+ if (ml)
+ ml->RemoveMLock(this);
+ }
+ }
+
+ void Serialize(Serialize::Data &data) const anope_override;
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &data);
+};
+
+struct ModeLocksImpl : ModeLocks
+{
+ Serialize::Reference<ChannelInfo> ci;
+ Serialize::Checker<ModeList> mlocks;
+
+ ModeLocksImpl(Extensible *obj) : ci(anope_dynamic_static_cast<ChannelInfo *>(obj)), mlocks("ModeLock")
+ {
+ }
+
+ bool HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const anope_override
+ {
+ if (!mode)
+ return false;
+
+ for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ {
+ const ModeLock *ml = *it;
+
+ if (ml->name == mode->name && ml->set == status && ml->param == param)
+ return true;
+ }
+
+ return false;
+ }
+
+ bool SetMLock(ChannelMode *mode, bool status, const Anope::string &param, Anope::string setter, time_t created = Anope::CurTime) anope_override
+ {
+ if (!mode)
+ return false;
+
+ RemoveMLock(mode, status, param);
+
+ if (setter.empty())
+ setter = ci->GetFounder() ? ci->GetFounder()->display : "Unknown";
+
+ ModeLock *ml = new ModeLockImpl();
+ ml->ci = ci->name;
+ ml->set = status;
+ ml->name = mode->name;
+ ml->param = param;
+ ml->setter = setter;
+ ml->created = created;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnMLock, MOD_RESULT, (this->ci, ml));
+ if (MOD_RESULT == EVENT_STOP)
+ {
+ delete ml;
+ return false;
+ }
+
+ this->mlocks->push_back(ml);
+ return true;
+ }
+
+ bool RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param = "") anope_override
+ {
+ if (!mode)
+ return false;
+
+ for (ModeList::iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ {
+ ModeLock *m = *it;
+
+ if (m->name == mode->name)
+ {
+ // For list or status modes, we must check the parameter
+ if (mode->type == MODE_LIST || mode->type == MODE_STATUS)
+ if (m->param != param)
+ continue;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnUnMLock, MOD_RESULT, (this->ci, m));
+ if (MOD_RESULT == EVENT_STOP)
+ break;
+
+ delete m;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ void RemoveMLock(ModeLock *mlock) anope_override
+ {
+ ModeList::iterator it = std::find(this->mlocks->begin(), this->mlocks->end(), mlock);
+ if (it != this->mlocks->end())
+ this->mlocks->erase(it);
+ }
+
+ void ClearMLock() anope_override
+ {
+ ModeList ml;
+ this->mlocks->swap(ml);
+ for (unsigned i = 0; i < ml.size(); ++i)
+ delete ml[i];
+ }
+
+ const ModeList &GetMLock() const anope_override
+ {
+ return this->mlocks;
+ }
+
+ std::list<ModeLock *> GetModeLockList(const Anope::string &name) anope_override
+ {
+ std::list<ModeLock *> mlist;
+ for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ {
+ ModeLock *m = *it;
+ if (m->name == name)
+ mlist.push_back(m);
+ }
+ return mlist;
+ }
+
+ const ModeLock *GetMLock(const Anope::string &mname, const Anope::string &param = "") anope_override
+ {
+ for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ {
+ ModeLock *m = *it;
+
+ if (m->name == mname && m->param == param)
+ return m;
+ }
+
+ return NULL;
+ }
+
+ Anope::string GetMLockAsString(bool complete) const anope_override
+ {
+ Anope::string pos = "+", neg = "-", params;
+
+ for (ModeList::const_iterator it = this->mlocks->begin(); it != this->mlocks->end(); ++it)
+ {
+ const ModeLock *ml = *it;
+ ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
+
+ if (!cm || cm->type == MODE_LIST || cm->type == MODE_STATUS)
+ continue;
+
+ if (ml->set)
+ pos += cm->mchar;
+ else
+ neg += cm->mchar;
+
+ if (complete && ml->set && !ml->param.empty() && cm->type == MODE_PARAM)
+ params += " " + ml->param;
+ }
+
+ if (pos.length() == 1)
+ pos.clear();
+ if (neg.length() == 1)
+ neg.clear();
+
+ return pos + neg + params;
+ }
+
+ void Check() anope_override
+ {
+ if (this->mlocks->empty())
+ ci->Shrink<ModeLocks>("modelocks");
+ }
+};
+
+void ModeLockImpl::Serialize(Serialize::Data &data) const
+{
+ data["ci"] << this->ci;
+ data["set"] << this->set;
+ data["name"] << this->name;
+ data["param"] << this->param;
+ data["setter"] << this->setter;
+ data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
+}
+
+Serializable* ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
+{
+ Anope::string sci;
+
+ data["ci"] >> sci;
+
+ ChannelInfo *ci = ChannelInfo::Find(sci);
+ if (!ci)
+ return NULL;
+
+ ModeLockImpl *ml;
+ if (obj)
+ ml = anope_dynamic_static_cast<ModeLockImpl *>(obj);
+ else
+ {
+ ml = new ModeLockImpl();
+ ml->ci = ci->name;
+ }
+
+ data["set"] >> ml->set;
+ data["created"] >> ml->created;
+ data["setter"] >> ml->setter;
+ data["name"] >> ml->name;
+ data["param"] >> ml->param;
+
+ if (!obj)
+ ci->Require<ModeLocksImpl>("modelocks")->mlocks->push_back(ml);
+
+ return ml;
+}
class CommandCSMode : public Command
{
@@ -28,21 +256,20 @@ class CommandCSMode : public Command
const Anope::string &param = params.size() > 3 ? params[3] : "";
bool override = !source.AccessFor(ci).HasPriv("MODE");
+ ModeLocks *modelocks = ci->Require<ModeLocks>("modelocks");
if ((subcommand.equals_ci("ADD") || subcommand.equals_ci("SET")) && !param.empty())
{
/* If setting, remove the existing locks */
if (subcommand.equals_ci("SET"))
{
- const ChannelInfo::ModeList &mlocks = ci->GetMLock();
- for (ChannelInfo::ModeList::const_iterator it = mlocks.begin(), it_next; it != mlocks.end(); it = it_next)
+ const ModeLocks::ModeList mlocks = modelocks->GetMLock();
+ for (ModeLocks::ModeList::const_iterator it = mlocks.begin(); it != mlocks.end(); ++it)
{
- const ModeLock *ml = it->second;
+ const ModeLock *ml = *it;
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
- it_next = it;
- ++it_next;
if (cm && cm->CanSet(source.GetUser()))
- ci->RemoveMLock(cm, ml->set, ml->param);
+ modelocks->RemoveMLock(cm, ml->set, ml->param);
}
}
@@ -86,7 +313,7 @@ class CommandCSMode : public Command
source.Reply(_("List for mode %c is full."), cm->mchar);
else
{
- ci->SetMLock(cm, adding, mode_param, source.GetNick());
+ modelocks->SetMLock(cm, adding, mode_param, source.GetNick());
if (adding)
{
@@ -110,8 +337,8 @@ class CommandCSMode : public Command
neg.clear();
Anope::string reply = pos + neg + pos_params + neg_params;
- source.Reply(_("%s locked on %s."), ci->GetMLockAsString(true).c_str(), ci->name.c_str());
- Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to lock " << ci->GetMLockAsString(true);
+ source.Reply(_("%s locked on %s."), modelocks->GetMLockAsString(true).c_str(), ci->name.c_str());
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to lock " << modelocks->GetMLockAsString(true);
if (ci->c)
ci->c->CheckModes();
@@ -154,7 +381,7 @@ class CommandCSMode : public Command
source.Reply(_("Missing parameter for mode %c."), cm->mchar);
else
{
- if (ci->RemoveMLock(cm, adding, mode_param))
+ if (modelocks->RemoveMLock(cm, adding, mode_param))
{
if (!mode_param.empty())
mode_param = " " + mode_param;
@@ -169,7 +396,7 @@ class CommandCSMode : public Command
}
else if (subcommand.equals_ci("LIST"))
{
- const ChannelInfo::ModeList &mlocks = ci->GetMLock();
+ const ModeLocks::ModeList mlocks = modelocks->GetMLock();
if (mlocks.empty())
{
source.Reply(_("Channel %s has no mode locks."), ci->name.c_str());
@@ -179,9 +406,9 @@ class CommandCSMode : public Command
ListFormatter list;
list.AddColumn("Mode").AddColumn("Param").AddColumn("Creator").AddColumn("Created");
- for (ChannelInfo::ModeList::const_iterator it = mlocks.begin(), it_end = mlocks.end(); it != it_end; ++it)
+ for (ModeLocks::ModeList::const_iterator it = mlocks.begin(), it_end = mlocks.end(); it != it_end; ++it)
{
- const ModeLock *ml = it->second;
+ const ModeLock *ml = *it;
ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
if (!cm)
continue;
@@ -481,12 +708,125 @@ class CommandCSMode : public Command
class CSMode : public Module
{
CommandCSMode commandcsmode;
+ ExtensibleItem<ModeLocksImpl> modelocks;
+ Serialize::Type modelocks_type;
public:
CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcsmode(this)
+ commandcsmode(this), modelocks(this, "modelocks"), modelocks_type("ModeLock", ModeLockImpl::Unserialize)
+ {
+
+ }
+
+ EventReturn OnCheckModes(Channel *c) anope_override
+ {
+ if (!c->ci)
+ return EVENT_CONTINUE;
+
+ ModeLocks *ml = modelocks.Get(c->ci);
+ if (ml)
+ for (ModeLocks::ModeList::const_iterator it = ml->GetMLock().begin(), it_end = ml->GetMLock().end(); it != it_end; ++it)
+ {
+ const ModeLock *ml = *it;
+ ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
+ if (!cm)
+ continue;
+
+ if (cm->type == MODE_REGULAR)
+ {
+ if (!c->HasMode(cm->name) && ml->set)
+ c->SetMode(NULL, cm);
+ else if (c->HasMode(cm->name) && !ml->set)
+ c->RemoveMode(NULL, cm);
+ }
+ else if (cm->type == MODE_PARAM)
+ {
+ /* If the channel doesnt have the mode, or it does and it isn't set correctly */
+ if (ml->set)
+ {
+ Anope::string param;
+ c->GetParam(cm->name, param);
+
+ if (!c->HasMode(cm->name) || (!param.empty() && !ml->param.empty() && !param.equals_cs(ml->param)))
+ c->SetMode(NULL, cm, ml->param);
+ }
+ else
+ {
+ if (c->HasMode(cm->name))
+ c->RemoveMode(NULL, cm);
+ }
+
+ }
+ else if (cm->type == MODE_LIST)
+ {
+ if (ml->set)
+ c->SetMode(NULL, cm, ml->param);
+ else
+ c->RemoveMode(NULL, cm, ml->param);
+ }
+ }
+ }
+
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ {
+ if (!c->ci)
+ return EVENT_CONTINUE;
+
+ ModeLocks *ml = modelocks.Get(c->ci);
+ if (!ml)
+ return EVENT_CONTINUE;
+
+ if (ml->HasMLock(mode, param, false))
+ c->RemoveMode(c->ci->WhoSends(), mode, param);
+ }
+
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
+ {
+ if (!c->ci)
+ return EVENT_CONTINUE;
+
+ ModeLocks *ml = modelocks.Get(c->ci);
+ if (!ml)
+ return EVENT_CONTINUE;
+
+ if (ml->HasMLock(mode, param, true))
+ c->SetMode(c->ci->WhoSends(), mode, param);
+ }
+
+ void OnCreateChan(ChannelInfo *ci) anope_override
+ {
+ ModeLocks *ml = modelocks.Require(ci);
+ Anope::string modes;
+ spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("mlock", "+nrt"));
+ if (sep.GetToken(modes))
+ {
+ bool add = true;
+ for (unsigned i = 0; i < modes.length(); ++i)
+ {
+ if (modes[i] == '+')
+ add = true;
+ else if (modes[i] == '-')
+ add = false;
+ else
+ {
+ ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
+ Anope::string param;
+ if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
+ ml->SetMLock(cm, add, param);
+ }
+ }
+ }
+ ml->Check();
+ }
+
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
{
+ if (!show_hidden)
+ return;
+ ModeLocks *ml = modelocks.Get(ci);
+ if (ml)
+ info[_("Mode lock")] = ml->GetMLockAsString(true);
}
};
diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp
index 877fc31b7..9c0b6abfb 100644
--- a/modules/commands/cs_seen.cpp
+++ b/modules/commands/cs_seen.cpp
@@ -95,7 +95,7 @@ static bool ShouldHide(const Anope::string &channel, User *u)
if (targetchan && targetchan->HasMode("SECRET"))
return true;
- else if (targetchan_ci && targetchan_ci->HasExt("PRIVATE"))
+ else if (targetchan_ci && targetchan_ci->HasExt("CS_PRIVATE"))
return true;
else if (u && u->HasMode("PRIV"))
return true;
diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp
index d07e544cc..d392f6b1d 100644
--- a/modules/commands/cs_set.cpp
+++ b/modules/commands/cs_set.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
class CommandCSSet : public Command
{
@@ -86,13 +87,13 @@ class CommandCSSetAutoOp : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable autoop";
- ci->Shrink("NOAUTOOP");
+ ci->Shrink<bool>("NOAUTOOP");
source.Reply(_("Services will now automatically give modes to users in \002%s\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable autoop";
- ci->ExtendMetadata("NOAUTOOP");
+ ci->Extend<bool>("NOAUTOOP");
source.Reply(_("Services will no longer automatically give modes to users in \002%s\002."), ci->name.c_str());
}
else
@@ -203,14 +204,14 @@ class CommandCSSetChanstats : public Command
if (params[1].equals_ci("ON"))
{
- ci->ExtendMetadata("STATS");
+ ci->Extend<bool>("CS_STATS");
source.Reply(_("Chanstats statistics are now enabled for this channel."));
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable chanstats";
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable chanstats";
- ci->Shrink("STATS");
+ ci->Shrink<bool>("CS_STATS");
source.Reply(_("Chanstats statistics are now disabled for this channel."));
}
else
@@ -344,64 +345,6 @@ class CommandCSSetFounder : public Command
}
};
-class CommandCSSetKeepTopic : public Command
-{
- public:
- CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic") : Command(creator, cname, 2, 2)
- {
- this->SetDesc(_("Retain topic when channel is not in use"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable keeptopic";
- ci->ExtendMetadata("KEEPTOPIC");
- source.Reply(_("Topic retention option for %s is now \002on\002."), ci->name.c_str());
- }
- else if (params[1].equals_ci("OFF"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable keeptopic";
- ci->Shrink("KEEPTOPIC");
- source.Reply(_("Topic retention option for %s is now \002off\002."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, "KEEPTOPIC");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Enables or disables the \002topic retention\002 option for a\n"
- "channel. When \002%s\002 is set, the topic for the\n"
- "channel will be remembered by %s even after the\n"
- "last user leaves the channel, and will be restored the\n"
- "next time the channel is created."), this->name.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
class CommandCSSetPeace : public Command
{
public:
@@ -433,13 +376,13 @@ class CommandCSSetPeace : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable peace";
- ci->ExtendMetadata("PEACE");
+ ci->Extend<bool>("PEACE");
source.Reply(_("Peace option for %s is now \002on\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable peace";
- ci->Shrink("PEACE");
+ ci->Shrink<bool>("PEACE");
source.Reply(_("Peace option for %s is now \002off\002."), ci->name.c_str());
}
else
@@ -495,7 +438,7 @@ class CommandCSSetPersist : public Command
{
if (!ci->HasExt("PERSIST"))
{
- ci->ExtendMetadata("PERSIST");
+ ci->Extend<bool>("PERSIST");
/* Channel doesn't exist, create it */
if (!ci->c)
@@ -535,7 +478,9 @@ class CommandCSSetPersist : public Command
if (ci->c && !ci->c->HasMode("PERM"))
ci->c->SetMode(NULL, cm);
/* Add it to the channels mlock */
- ci->SetMLock(cm, true);
+ ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
+ if (ml)
+ ml->SetMLock(cm, true);
}
}
@@ -546,7 +491,7 @@ class CommandCSSetPersist : public Command
{
if (ci->HasExt("PERSIST"))
{
- ci->Shrink("PERSIST");
+ ci->Shrink<bool>("PERSIST");
/* Unset perm mode */
if (cm)
@@ -554,7 +499,9 @@ class CommandCSSetPersist : public Command
if (ci->c && ci->c->HasMode("PERM"))
ci->c->RemoveMode(NULL, cm);
/* Remove from mlock */
- ci->RemoveMLock(cm, true);
+ ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks");
+ if (ml)
+ ml->RemoveMLock(cm, true);
}
/* No channel mode, no BotServ, but using ChanServ as the botserv bot
@@ -608,68 +555,6 @@ class CommandCSSetPersist : public Command
}
};
-class CommandCSSetPrivate : public Command
-{
- public:
- CommandCSSetPrivate(Module *creator, const Anope::string &cname = "chanserv/set/private") : Command(creator, cname, 2, 2)
- {
- this->SetDesc(_("Hide channel from the LIST command"));
- this->SetSyntax(_("\037channel\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- ChannelInfo *ci = ChannelInfo::Find(params[0]);
- if (ci == NULL)
- {
- source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
- return;
- }
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
- {
- source.Reply(ACCESS_DENIED);
- return;
- }
-
- if (params[1].equals_ci("ON"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable private";
- ci->ExtendMetadata("PRIVATE");
- source.Reply(_("Private option for %s is now \002on\002."), ci->name.c_str());
- }
- else if (params[1].equals_ci("OFF"))
- {
- Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable private";
- ci->Shrink("PRIVATE");
- source.Reply(_("Private option for %s is now \002off\002."), ci->name.c_str());
- }
- else
- this->OnSyntaxError(source, "PRIVATE");
-
- return;
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Enables or disables the \002private\002 option for a channel."));
-
- BotInfo *bi;
- Anope::string cmd;
- if (Command::FindCommandFromService("chanserv/list", bi, cmd))
- source.Reply(_("When \002private\002 is set, the channel will not appear in\n"
- "%s's %s command."), bi->nick.c_str(), cmd.c_str());
- return true;
- }
-};
-
class CommandCSSetRestricted : public Command
{
public:
@@ -702,13 +587,13 @@ class CommandCSSetRestricted : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable restricted";
- ci->ExtendMetadata("RESTRICTED");
+ ci->Extend<bool>("RESTRICTED");
source.Reply(_("Restricted access option for %s is now \002on\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable restricted";
- ci->Shrink("RESTRICTED");
+ ci->Shrink<bool>("RESTRICTED");
source.Reply(_("Restricted access option for %s is now \002off\002."), ci->name.c_str());
}
else
@@ -758,13 +643,13 @@ class CommandCSSetSecure : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure";
- ci->ExtendMetadata("SECURE");
+ ci->Extend<bool>("CS_SECURE");
source.Reply(_("Secure option for %s is now \002on\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure";
- ci->Shrink("SECURE");
+ ci->Shrink<bool>("CS_SECURE");
source.Reply(_("Secure option for %s is now \002off\002."), ci->name.c_str());
}
else
@@ -816,13 +701,13 @@ class CommandCSSetSecureFounder : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure founder";
- ci->ExtendMetadata("SECUREFOUNDER");
+ ci->Extend<bool>("SECUREFOUNDER");
source.Reply(_("Secure founder option for %s is now \002on\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure founder";
- ci->Shrink("SECUREFOUNDER");
+ ci->Shrink<bool>("SECUREFOUNDER");
source.Reply(_("Secure founder option for %s is now \002off\002."), ci->name.c_str());
}
else
@@ -874,13 +759,13 @@ class CommandCSSetSecureOps : public Command
if (params[1].equals_ci("ON"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable secure ops";
- ci->ExtendMetadata("SECUREOPS");
+ ci->Extend<bool>("SECUREOPS");
source.Reply(_("Secure ops option for %s is now \002on\002."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable secure ops";
- ci->Shrink("SECUREOPS");
+ ci->Shrink<bool>("SECUREOPS");
source.Reply(_("Secure ops option for %s is now \002off\002."), ci->name.c_str());
}
else
@@ -904,7 +789,7 @@ class CommandCSSetSignKick : public Command
CommandCSSetSignKick(Module *creator, const Anope::string &cname = "chanserv/set/signkick") : Command(creator, cname, 2, 2)
{
this->SetDesc(_("Sign kicks that are done with the KICK command"));
- this->SetSyntax(_("\037channel\037 SIGNKICK {ON | LEVEL | OFF}"));
+ this->SetSyntax(_("\037channel\037 {ON | LEVEL | OFF}"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
@@ -929,23 +814,23 @@ class CommandCSSetSignKick : public Command
if (params[1].equals_ci("ON"))
{
- ci->ExtendMetadata("SIGNKICK");
- ci->Shrink("SIGNKICK_LEVEL");
+ ci->Extend<bool>("SIGNKICK");
+ ci->Shrink<bool>("SIGNKICK_LEVEL");
source.Reply(_("Signed kick option for %s is now \002on\002."), ci->name.c_str());
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable sign kick";
}
else if (params[1].equals_ci("LEVEL"))
{
- ci->ExtendMetadata("SIGNKICK_LEVEL");
- ci->Shrink("SIGNKICK");
+ ci->Extend<bool>("SIGNKICK_LEVEL");
+ ci->Shrink<bool>("SIGNKICK");
source.Reply(_("Signed kick option for %s is now \002on\002, but depends of the\n"
"level of the user that is using the command."), ci->name.c_str());
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable sign kick level";
}
else if (params[1].equals_ci("OFF"))
{
- ci->Shrink("SIGNKICK");
- ci->Shrink("SIGNKICK_LEVEL");
+ ci->Shrink<bool>("SIGNKICK");
+ ci->Shrink<bool>("SIGNKICK_LEVEL");
source.Reply(_("Signed kick option for %s is now \002off\002."), ci->name.c_str());
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable sign kick";
}
@@ -1075,13 +960,13 @@ class CommandCSSetNoexpire : public Command
if (params[1].equals_ci("ON"))
{
Log(LOG_ADMIN, source, this, ci) << "to enable noexpire";
- ci->ExtendMetadata("NO_EXPIRE");
+ ci->Extend<bool>("CS_NO_EXPIRE");
source.Reply(_("Channel %s \002will not\002 expire."), ci->name.c_str());
}
else if (params[1].equals_ci("OFF"))
{
Log(LOG_ADMIN, source, this, ci) << "to disable noexpire";
- ci->Shrink("NO_EXPIRE");
+ ci->Shrink<bool>("CS_NO_EXPIRE");
source.Reply(_("Channel %s \002will\002 expire."), ci->name.c_str());
}
else
@@ -1102,16 +987,17 @@ class CommandCSSetNoexpire : public Command
class CSSet : public Module
{
+ SerializableExtensibleItem<bool> persist, noautoop, stats, peace, securefounder,
+ restricted, secure, secureops, signkick, signkick_level, noexpire;
+
CommandCSSet commandcsset;
CommandCSSetAutoOp commandcssetautoop;
CommandCSSetBanType commandcssetbantype;
CommandCSSetChanstats commandcssetchanstats;
CommandCSSetDescription commandcssetdescription;
CommandCSSetFounder commandcssetfounder;
- CommandCSSetKeepTopic commandcssetkeeptopic;
CommandCSSetPeace commandcssetpeace;
CommandCSSetPersist commandcssetpersist;
- CommandCSSetPrivate commandcssetprivate;
CommandCSSetRestricted commandcssetrestricted;
CommandCSSetSecure commandcssetsecure;
CommandCSSetSecureFounder commandcssetsecurefounder;
@@ -1122,17 +1008,27 @@ class CSSet : public Module
public:
CSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ persist(this, "PERSIST"), noautoop(this, "NOAUTOOP"), stats(this, "CS_STATS"), peace(this, "PEACE"),
+ securefounder(this, "SECUREFOUNDER"), restricted(this, "RESTRICTED"),
+ secure(this, "CS_SECURE"), secureops(this, "SECUREOPS"), signkick(this, "SIGNKICK"),
+ signkick_level(this, "SIGNKICK_LEVEL"), noexpire(this, "CS_NO_EXPIRE"),
+
commandcsset(this), commandcssetautoop(this), commandcssetbantype(this), commandcssetchanstats(this),
- commandcssetdescription(this), commandcssetfounder(this), commandcssetkeeptopic(this),
- commandcssetpeace(this), commandcssetpersist(this), commandcssetprivate(this), commandcssetrestricted(this),
+ commandcssetdescription(this), commandcssetfounder(this),
+ commandcssetpeace(this), commandcssetpersist(this), commandcssetrestricted(this),
commandcssetsecure(this), commandcssetsecurefounder(this), commandcssetsecureops(this), commandcssetsignkick(this),
commandcssetsuccessor(this), commandcssetnoexpire(this)
{
}
+ void OnCreateChan(ChannelInfo *ci) anope_override
+ {
+ ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
+ }
+
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
{
- if (!c->ci || !c->ci->HasExt("RESTRICTED") || c->MatchesList(u, "EXCEPT"))
+ if (!c->ci || !restricted.HasExt(c->ci) || c->MatchesList(u, "EXCEPT"))
return EVENT_CONTINUE;
if (c->ci->AccessFor(u).empty() && (!c->ci->GetFounder() || u->Account() != c->ci->GetFounder()))
@@ -1143,30 +1039,30 @@ class CSSet : public Module
void OnDelChan(ChannelInfo *ci) anope_override
{
- if (ci->c && ci->HasExt("PERSIST"))
+ if (ci->c && persist.HasExt(ci))
ci->c->RemoveMode(ci->WhoSends(), "PERM", "", false);
- ci->Shrink("PERSIST");
+ persist.Unset(ci);
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, const Anope::string &mname, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
{
/* Channel mode +P or so was set, mark this channel as persistent */
- if (mname == "PERM" && c->ci)
+ if (mode->name == "PERM" && c->ci)
{
- c->ci->ExtendMetadata("PERSIST");
+ persist.Set(c->ci, true);
}
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, const Anope::string &mname, const Anope::string &param) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
{
- if (mname == "PERM")
+ if (mode->name == "PERM")
{
if (c->ci)
- c->ci->Shrink("PERSIST");
+ persist.Unset(c->ci);
- if (c->users.empty() && !c->syncing && c->CheckDelete())
+ if (c->CheckDelete())
{
delete c;
return EVENT_STOP;
@@ -1178,14 +1074,14 @@ class CSSet : public Module
EventReturn OnCheckDelete(Channel *c) anope_override
{
- if (c->ci && c->ci->HasExt("PERSIST"))
+ if (c->ci && persist.HasExt(c->ci))
return EVENT_STOP;
return EVENT_CONTINUE;
}
void OnJoinChannel(User *u, Channel *c) anope_override
{
- if (c->ci && c->ci->HasExt("PERSIST") && c->creation_time > c->ci->time_registered)
+ if (c->ci && persist.HasExt(c->ci) && c->creation_time > c->ci->time_registered)
{
Log(LOG_DEBUG) << "Changing TS of " << c->name << " from " << c->creation_time << " to " << c->ci->time_registered;
c->creation_time = c->ci->time_registered;
@@ -1198,10 +1094,47 @@ class CSSet : public Module
{
if (chan->ci)
{
- give_modes &= !chan->ci->HasExt("NOAUTOOP");
- take_modes |= chan->ci->HasExt("SECUREOPS");
+ if (noautoop.HasExt(chan->ci))
+ give_modes = false;
+ if (secureops.HasExt(chan->ci))
+ take_modes = true;
}
}
+
+ void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
+ {
+ if (noexpire.HasExt(ci))
+ expire = false;
+ }
+
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all) anope_override
+ {
+ if (!show_all)
+ return;
+
+ if (peace.HasExt(ci))
+ info.AddOption(_("Peace"));
+ if (restricted.HasExt(ci))
+ info.AddOption(_("Restricted Access"));
+ if (secure.HasExt(ci))
+ info.AddOption(_("Secure"));
+ if (securefounder.HasExt(ci))
+ info.AddOption(_("Secure Founder"));
+ if (secureops.HasExt(ci))
+ info.AddOption(_("Secure Ops"));
+ if (signkick.HasExt(ci) || signkick_level.HasExt(ci))
+ info.AddOption(_("Signed kicks"));
+ if (persist.HasExt(ci))
+ info.AddOption(_("Persistent"));
+ if (noexpire.HasExt(ci))
+ info.AddOption(_("No expire"));
+ if (stats.HasExt(ci))
+ info.AddOption(_("Chanstats"));
+
+ time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "14d");
+ if (!noexpire.HasExt(ci) && chanserv_expire && !Anope::NoExpire)
+ info["Expires on"] = Anope::strftime(ci->last_used + chanserv_expire);
+ }
};
MODULE_INIT(CSSet)
diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp
index 21ebec815..5467e2b4e 100644
--- a/modules/commands/cs_set_misc.cpp
+++ b/modules/commands/cs_set_misc.cpp
@@ -10,14 +10,24 @@
#include "module.h"
+static Module *me;
+
static std::map<Anope::string, Anope::string> descriptions;
-struct CSMiscData : ExtensibleItem, Serializable
+struct CSMiscData;
+static Anope::map<ExtensibleItem<CSMiscData> *> items;
+static ExtensibleItem<CSMiscData> *GetItem(const Anope::string &name);
+
+struct CSMiscData : Serializable
{
Serialize::Reference<ChannelInfo> ci;
Anope::string name;
Anope::string data;
+ CSMiscData(Extensible *obj) : Serializable("CSMiscData"), ci(anope_dynamic_static_cast<ChannelInfo *>(obj))
+ {
+ }
+
CSMiscData(ChannelInfo *c, const Anope::string &n, const Anope::string &d) : Serializable("CSMiscData"), ci(c), name(n), data(d)
{
}
@@ -41,7 +51,7 @@ struct CSMiscData : ExtensibleItem, Serializable
if (ci == NULL)
return NULL;
- CSMiscData *d;
+ CSMiscData *d = NULL;
if (obj)
{
d = anope_dynamic_static_cast<CSMiscData *>(obj);
@@ -51,14 +61,27 @@ struct CSMiscData : ExtensibleItem, Serializable
}
else
{
- d = new CSMiscData(ci, sname, sdata);
- ci->Extend(sname, d);
+ ExtensibleItem<CSMiscData> *item = GetItem(sname);
+ if (item)
+ d = item->Set(ci, CSMiscData(ci, sname, sdata));
}
return d;
}
};
+static ExtensibleItem<CSMiscData> *GetItem(const Anope::string &name)
+{
+ ExtensibleItem<CSMiscData>* &it = items[name];
+ if (!it)
+ try
+ {
+ it = new ExtensibleItem<CSMiscData>(me, name);
+ }
+ catch (const ModuleException &) { }
+ return it;
+}
+
static Anope::string GetAttribute(const Anope::string &command)
{
size_t sp = command.rfind(' ');
@@ -97,14 +120,20 @@ class CommandCSSetMisc : public Command
Anope::string scommand = GetAttribute(source.command);
Anope::string key = "cs_set_misc:" + scommand;
- ci->Shrink(key);
+ ExtensibleItem<CSMiscData> *item = GetItem(key);
+ if (item == NULL)
+ return;
+
if (params.size() > 1)
{
- ci->Extend(key, new CSMiscData(ci, key, params[1]));
+ item->Set(ci, CSMiscData(ci, key, params[1]));
source.Reply(CHAN_SETTING_CHANGED, scommand.c_str(), ci->name.c_str(), params[1].c_str());
}
else
+ {
+ item->Unset(ci);
source.Reply(CHAN_SETTING_UNSET, scommand.c_str(), ci->name.c_str());
+ }
}
void OnServHelp(CommandSource &source) anope_override
@@ -136,6 +165,7 @@ class CSSetMisc : public Module
CSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
csmiscdata_type("CSMiscData", CSMiscData::Unserialize), commandcssetmisc(this)
{
+ me = this;
}
void OnReload(Configuration::Conf *conf) anope_override
@@ -161,17 +191,14 @@ class CSSetMisc : public Module
void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool ShowHidden) anope_override
{
- std::deque<Anope::string> list;
- ci->GetExtList(list);
-
- for (unsigned i = 0; i < list.size(); ++i)
+ Anope::map<ExtensibleItem<CSMiscData> *> items;
+ for (Anope::map<ExtensibleItem<CSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
{
- if (list[i].find("cs_set_misc:") != 0)
- continue;
-
- CSMiscData *data = ci->GetExt<CSMiscData *>(list[i]);
+ ExtensibleItem<CSMiscData> *e = it->second;
+ CSMiscData *data = e->Get(ci);
+
if (data != NULL)
- info[list[i].substr(12).replace_all_cs("_", " ")] = data->data;
+ info[e->name.substr(12).replace_all_cs("_", " ")] = data->data;
}
}
};
diff --git a/modules/commands/cs_suspend.cpp b/modules/commands/cs_suspend.cpp
index e366e5dc0..b7ffccda6 100644
--- a/modules/commands/cs_suspend.cpp
+++ b/modules/commands/cs_suspend.cpp
@@ -10,6 +10,45 @@
*/
#include "module.h"
+#include "modules/cs_suspend.h"
+
+struct CSSuspendInfoImpl : CSSuspendInfo, Serializable
+{
+ CSSuspendInfoImpl(Extensible *) : Serializable("CSSuspendInfo") { }
+
+ void Serialize(Serialize::Data &data) const anope_override
+ {
+ data["chan"] << chan;
+ data["by"] << by;
+ data["reason"] << reason;
+ data["time"] << time;
+ data["expires"] << expires;
+ }
+
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ {
+ Anope::string schan;
+ data["chan"] >> schan;
+
+ CSSuspendInfoImpl *si;
+ if (obj)
+ si = anope_dynamic_static_cast<CSSuspendInfoImpl *>(obj);
+ else
+ {
+ ChannelInfo *ci = ChannelInfo::Find(schan);
+ if (!ci)
+ return NULL;
+ si = ci->Extend<CSSuspendInfoImpl>("cs_suspend");
+ data["chan"] >> si->chan;
+ }
+
+ data["bi"] >> si->by;
+ data["reason"] >> si->reason;
+ data["time"] >> si->time;
+ data["expires"] >> si->expires;
+ return si;
+ }
+};
class CommandCSSuspend : public Command
{
@@ -46,11 +85,12 @@ class CommandCSSuspend : public Command
return;
}
- ci->ExtendMetadata("SUSPENDED");
- ci->ExtendMetadata("suspend:by", source.GetNick());
- if (!reason.empty())
- ci->ExtendMetadata("suspend:reason", reason);
- ci->ExtendMetadata("suspend:time", stringify(Anope::CurTime));
+ CSSuspendInfo *si = ci->Extend<CSSuspendInfo>("cs_suspend");
+ si->chan = ci->name;
+ si->by = source.GetNick();
+ si->reason = reason;
+ si->time = Anope::CurTime;
+ si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0;
if (ci->c)
{
@@ -68,15 +108,10 @@ class CommandCSSuspend : public Command
ci->c->Kick(NULL, users[i], "%s", !reason.empty() ? reason.c_str() : Language::Translate(users[i], _("This channel has been suspended.")));
}
- if (expiry_secs > 0)
- ci->ExtendMetadata("suspend:expire", stringify(Anope::CurTime + expiry_secs));
-
Log(LOG_ADMIN, source, this, ci) << (!reason.empty() ? reason : "No reason") << ", expires in " << (expiry_secs ? Anope::strftime(Anope::CurTime + expiry_secs) : "never");
source.Reply(_("Channel \002%s\002 is now suspended."), ci->name.c_str());
FOREACH_MOD(OnChanSuspend, (ci));
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -118,21 +153,16 @@ class CommandCSUnSuspend : public Command
}
/* Only UNSUSPEND already suspended channels */
- if (!ci->HasExt("SUSPENDED"))
+ CSSuspendInfo *si = ci->GetExt<CSSuspendInfo>("cs_suspend");
+ if (!si)
{
source.Reply(_("Channel \002%s\002 isn't suspended."), ci->name.c_str());
return;
}
- Anope::string *by = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:by"), *reason = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:reason");
- if (by != NULL)
- Log(LOG_ADMIN, source, this, ci) << " which was suspended by " << *by << " for: " << (reason && !reason->empty() ? *reason : "No reason");
+ Log(LOG_ADMIN, source, this, ci) << " which was suspended by " << si->by << " for: " << (!si->reason.empty() ? si->reason : "No reason");
- ci->Shrink("SUSPENDED");
- ci->Shrink("suspend:by");
- ci->Shrink("suspend:reason");
- ci->Shrink("suspend:expire");
- ci->Shrink("suspend:time");
+ ci->Shrink<CSSuspendInfo>("cs_suspend");
source.Reply(_("Channel \002%s\002 is now released."), ci->name.c_str());
@@ -155,66 +185,73 @@ class CSSuspend : public Module
{
CommandCSSuspend commandcssuspend;
CommandCSUnSuspend commandcsunsuspend;
+ ExtensibleItem<CSSuspendInfoImpl> suspend;
+ Serialize::Type suspend_type;
public:
CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcssuspend(this), commandcsunsuspend(this)
+ commandcssuspend(this), commandcsunsuspend(this), suspend(this, "cs_suspend"),
+ suspend_type("CSSuspendInfo", CSSuspendInfoImpl::Unserialize)
{
-
}
void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) anope_override
{
- if (ci->HasExt("SUSPENDED"))
+ CSSuspendInfo *si = suspend.Get(ci);
+ if (si)
{
- Anope::string *by = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:by"), *reason = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:reason"), *t = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:time");
info["Suspended"] = "This channel is \2suspended\2.";
- if (by)
- info["Suspended by"] = *by;
- if (reason)
- info["Suspend reason"] = *reason;
- if (t)
- info["Suspended on"] = Anope::strftime(convertTo<time_t>(*t), source.GetAccount(), true);
+ if (!si->by.empty())
+ info["Suspended by"] = si->by;
+ if (!si->reason.empty())
+ info["Suspend reason"] = si->reason;
+ if (si->time)
+ info["Suspended on"] = Anope::strftime(si->time, source.GetAccount(), true);
+ if (si->expires)
+ info["Suspended expires"] = Anope::strftime(si->expires, source.GetAccount(), true);
}
}
void OnPreChanExpire(ChannelInfo *ci, bool &expire) anope_override
{
- if (!ci->HasExt("SUSPENDED"))
+ CSSuspendInfo *si = suspend.Get(ci);
+ if (!si)
return;
expire = false;
- Anope::string *str = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:expire");
- if (str == NULL)
+ if (!si->expires)
return;
- try
+ if (si->expires < Anope::CurTime)
{
- time_t when = convertTo<time_t>(*str);
- if (when < Anope::CurTime)
- {
- ci->last_used = Anope::CurTime;
- ci->Shrink("SUSPENDED");
- ci->Shrink("suspend:expire");
- ci->Shrink("suspend:by");
- ci->Shrink("suspend:reason");
- ci->Shrink("suspend:time");
-
- Log(this) << "Expiring suspend for " << ci->name;
- }
+ ci->last_used = Anope::CurTime;
+ suspend.Unset(ci);
+
+ Log(this) << "Expiring suspend for " << ci->name;
}
- catch (const ConvertException &) { }
}
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) anope_override
{
- if (u->HasMode("OPER") || !c->ci || !c->ci->HasExt("SUSPENDED"))
+ if (u->HasMode("OPER") || !c->ci || !suspend.HasExt(c->ci))
return EVENT_CONTINUE;
reason = Language::Translate(u, _("This channel may not be used."));
return EVENT_STOP;
}
+
+ EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) anope_override
+ {
+ CSSuspendInfo *si = suspend.Get(ci);
+ if (si && !source.HasCommand("chanserv/drop"))
+ {
+ source.Reply(CHAN_X_SUSPENDED, ci->name.c_str());
+ return EVENT_STOP;
+ }
+
+ return EVENT_CONTINUE;
+ }
};
MODULE_INIT(CSSuspend)
diff --git a/modules/commands/cs_topic.cpp b/modules/commands/cs_topic.cpp
index 294689864..39ddfe8f9 100644
--- a/modules/commands/cs_topic.cpp
+++ b/modules/commands/cs_topic.cpp
@@ -10,9 +10,70 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
+
+class CommandCSSetKeepTopic : public Command
+{
+ public:
+ CommandCSSetKeepTopic(Module *creator, const Anope::string &cname = "chanserv/set/keeptopic") : Command(creator, cname, 2, 2)
+ {
+ this->SetDesc(_("Retain topic when channel is not in use"));
+ this->SetSyntax(_("\037channel\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetChannelOption, MOD_RESULT, (source, this, ci, params[1]));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (MOD_RESULT != EVENT_ALLOW && !source.AccessFor(ci).HasPriv("SET") && source.permission.empty() && !source.HasPriv("chanserv/administration"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (params[1].equals_ci("ON"))
+ {
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to enable keeptopic";
+ ci->Extend<bool>("KEEPTOPIC");
+ source.Reply(_("Topic retention option for %s is now \002on\002."), ci->name.c_str());
+ }
+ else if (params[1].equals_ci("OFF"))
+ {
+ Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to disable keeptopic";
+ ci->Shrink<bool>("KEEPTOPIC");
+ source.Reply(_("Topic retention option for %s is now \002off\002."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "KEEPTOPIC");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Enables or disables the \002topic retention\002 option for a\n"
+ "channel. When \002%s\002 is set, the topic for the\n"
+ "channel will be remembered by %s even after the\n"
+ "last user leaves the channel, and will be restored the\n"
+ "next time the channel is created."), source.command.c_str(), source.service->nick.c_str());
+ return true;
+ }
+};
class CommandCSTopic : public Command
{
+ ExtensibleRef<bool> topiclock;
+
void Lock(CommandSource &source, ChannelInfo *ci, const std::vector<Anope::string> &params)
{
EventReturn MOD_RESULT;
@@ -20,7 +81,7 @@ class CommandCSTopic : public Command
if (MOD_RESULT == EVENT_STOP)
return;
- ci->ExtendMetadata("TOPICLOCK");
+ topiclock->Set(ci, true);
source.Reply(_("Topic lock option for %s is now \002on\002."), ci->name.c_str());
}
@@ -31,7 +92,7 @@ class CommandCSTopic : public Command
if (MOD_RESULT == EVENT_STOP)
return;
- ci->Shrink("TOPICLOCK");
+ topiclock->Unset(ci);
source.Reply(_("Topic lock option for %s is now \002off\002."), ci->name.c_str());
}
@@ -39,11 +100,11 @@ class CommandCSTopic : public Command
{
const Anope::string &topic = params.size() > 2 ? params[2] : "";
- bool has_topiclock = ci->HasExt("TOPICLOCK");
- ci->Shrink("TOPICLOCK");
+ bool *has_topiclock = topiclock->Get(ci);
+ topiclock->Unset(ci);
ci->c->ChangeTopic(source.GetNick(), topic, Anope::CurTime);
if (has_topiclock)
- ci->ExtendMetadata("TOPICLOCK");
+ topiclock->Set(ci, *has_topiclock);
bool override = !source.AccessFor(ci).HasPriv("TOPIC");
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << (!topic.empty() ? "to change the topic to: " : "to unset the topic") << (!topic.empty() ? topic : "");
@@ -71,7 +132,8 @@ class CommandCSTopic : public Command
}
public:
- CommandCSTopic(Module *creator) : Command(creator, "chanserv/topic", 2, 3)
+ CommandCSTopic(Module *creator) : Command(creator, "chanserv/topic", 2, 3),
+ topiclock("TOPICLOCK")
{
this->SetDesc(_("Manipulate the topic of the specified channel"));
this->SetSyntax(_("\037channel\037 SET [\037topic\037]"));
@@ -120,13 +182,66 @@ class CommandCSTopic : public Command
class CSTopic : public Module
{
CommandCSTopic commandcstopic;
+ CommandCSSetKeepTopic commandcssetkeeptopic;
+
+ SerializableExtensibleItem<bool> topiclock, keeptopic;
public:
CSTopic(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandcstopic(this)
+ commandcstopic(this), commandcssetkeeptopic(this), topiclock(this, "TOPICLOCK"), keeptopic(this, "KEEPTOPIC")
{
}
+
+ void OnChannelSync(Channel *c) anope_override
+ {
+ if (Me && Me->IsSynced() && c->ci)
+ {
+ /* Update channel topic */
+ if ((topiclock.HasExt(c->ci) || keeptopic.HasExt(c->ci)) && c->ci->last_topic != c->topic)
+ {
+ c->ChangeTopic(!c->ci->last_topic_setter.empty() ? c->ci->last_topic_setter : c->ci->WhoSends()->nick, c->ci->last_topic, c->ci->last_topic_time ? c->ci->last_topic_time : Anope::CurTime);
+ }
+ }
+ }
+
+ void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
+ {
+ if (!c->ci)
+ return;
+
+ /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not
+ * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us.
+ * This desyncs what is really set with what we have stored, and we end up resetting the topic often when
+ * it is not required
+ */
+ if (topiclock.HasExt(c->ci) && c->ci->last_topic != c->topic)
+ {
+ c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time);
+ }
+ else
+ {
+ c->ci->last_topic = c->topic;
+ c->ci->last_topic_setter = c->topic_setter;
+ c->ci->last_topic_time = c->topic_ts;
+ }
+ }
+
+ void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_all)
+ {
+ if (keeptopic.HasExt(ci))
+ info.AddOption(_("Topic Retention"));
+ if (topiclock.HasExt(ci))
+ info.AddOption(_("Topic Lock"));
+
+ ModeLocks *ml = ci->GetExt<ModeLocks>("modelocks");
+ const ModeLock *secret = ml ? ml->GetMLock("SECRET") : NULL;
+ if (!ci->last_topic.empty() && (show_all || ((!secret || secret->set == false) && (!ci->c || !ci->c->HasMode("SECRET")))))
+ {
+ info["Last topic"] = ci->last_topic;
+ info["Topic set by"] = ci->last_topic_setter;
+ }
+ }
};
MODULE_INIT(CSTopic)
diff --git a/modules/commands/greet.cpp b/modules/commands/greet.cpp
new file mode 100644
index 000000000..dd3fce66f
--- /dev/null
+++ b/modules/commands/greet.cpp
@@ -0,0 +1,210 @@
+/*
+ *
+ * (C) 2003-2013 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 CommandBSSetGreet : public Command
+{
+ public:
+ CommandBSSetGreet(Module *creator, const Anope::string &sname = "botserv/set/greet") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("Enable greet messages"));
+ this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ const Anope::string &value = params[1];
+
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (Anope::ReadOnly)
+ {
+ source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ return;
+ }
+
+ if (value.equals_ci("ON"))
+ {
+ bool override = !source.AccessFor(ci).HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable greets";
+
+ ci->Extend<bool>("BS_GREET");
+ source.Reply(_("Greet mode is now \002on\002 on channel %s."), ci->name.c_str());
+ }
+ else if (value.equals_ci("OFF"))
+ {
+ bool override = !source.AccessFor(ci).HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable greets";
+
+ ci->Shrink<bool>("BS_GREET");
+ source.Reply(_("Greet mode is now \002off\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "Enables or disables \002greet\002 mode on a channel.\n"
+ "When it is enabled, the bot will display greet\n"
+ "messages of users joining the channel, provided\n"
+ "they have enough access to the channel."));
+ return true;
+ }
+};
+
+class CommandNSSetGreet : public Command
+{
+ public:
+ CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Associate a greet message with your nickname"));
+ this->SetSyntax(_("\037message\037"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (!param.empty())
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the greet of " << nc->display;
+ nc->Extend<Anope::string>("greet", param);
+ source.Reply(_("Greet message for \002%s\002 changed to \002%s\002."), nc->display.c_str(), param.c_str());
+ }
+ else
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the greet of " << nc->display;
+ nc->Shrink<Anope::string>("greet");
+ source.Reply(_("Greet message for \002%s\002 unset."), nc->display.c_str());
+ }
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->Run(source, source.nc->display, params.size() > 0 ? params[0] : "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Makes the given message the greet of your nickname, that\n"
+ "will be displayed when joining a channel that has GREET\n"
+ "option enabled, provided that you have the necessary\n"
+ "access on it."));
+ return true;
+ }
+};
+
+class CommandNSSASetGreet : public CommandNSSetGreet
+{
+ public:
+ CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 \037message\037"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->Run(source, params[0], params.size() > 1 ? params[1] : "");
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Makes the given message the greet of the nickname, that\n"
+ "will be displayed when joining a channel that has GREET\n"
+ "option enabled, provided that the user has the necessary\n"
+ "access on it."));
+ return true;
+ }
+};
+
+class Greet : public Module
+{
+ /* channel setting for whether or not greet should be shown */
+ SerializableExtensibleItem<bool> bs_greet;
+ /* user greets */
+ SerializableExtensibleItem<Anope::string> ns_greet;
+
+ CommandBSSetGreet commandbssetgreet;
+ CommandNSSetGreet commandnssetgreet;
+ CommandNSSASetGreet commandnssasetgreet;
+
+ public:
+ Greet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ bs_greet(this, "BS_GREET"),
+ ns_greet(this, "greet"),
+ commandbssetgreet(this),
+ commandnssetgreet(this), commandnssasetgreet(this)
+ {
+ }
+
+ void OnJoinChannel(User *user, Channel *c) anope_override
+ {
+ /* Only display the greet if the main uplink we're connected
+ * to has synced, or we'll get greet-floods when the net
+ * recovers from a netsplit. -GD
+ */
+ if (!c->ci || !c->ci->bi || !user->server->IsSynced() || !user->Account())
+ return;
+
+ Anope::string *greet = ns_greet.Get(user->Account());
+ if (bs_greet.HasExt(c->ci) && greet != NULL && !greet->empty() && c->FindUser(c->ci->bi) && c->ci->AccessFor(user).HasPriv("GREET"))
+ {
+ IRCD->SendPrivmsg(c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), greet->c_str());
+ c->ci->bi->lastmsg = Anope::CurTime;
+ }
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ {
+ Anope::string *greet = ns_greet.Get(na->nc);
+ if (greet != NULL)
+ info[_("Greet")] = *greet;
+ }
+
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) anope_override
+ {
+ if (bs_greet.HasExt(ci))
+ info.AddOption(_("Greet"));
+ }
+};
+
+MODULE_INIT(Greet)
diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp
index 2b1299f93..5203b086b 100644
--- a/modules/commands/hs_request.cpp
+++ b/modules/commands/hs_request.cpp
@@ -21,14 +21,14 @@ static ServiceReference<MemoServService> memoserv("MemoServService", "MemoServ")
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost);
-struct HostRequest : ExtensibleItem, Serializable
+struct HostRequest : Serializable
{
Anope::string nick;
Anope::string ident;
Anope::string host;
time_t time;
- HostRequest() : Serializable("HostRequest") { }
+ HostRequest(Extensible *) : Serializable("HostRequest") { }
void Serialize(Serialize::Data &data) const anope_override
{
@@ -51,14 +51,15 @@ struct HostRequest : ExtensibleItem, Serializable
if (obj)
req = anope_dynamic_static_cast<HostRequest *>(obj);
else
- req = new HostRequest;
- req->nick = na->nick;
- data["ident"] >> req->ident;
- data["host"] >> req->host;
- data["time"] >> req->time;
-
- if (!obj)
- na->Extend("hs_request", req);
+ req = na->Extend<HostRequest>("hostrequest");
+ if (req)
+ {
+ req->nick = na->nick;
+ data["ident"] >> req->ident;
+ data["host"] >> req->host;
+ data["time"] >> req->time;
+ }
+
return req;
}
};
@@ -148,12 +149,12 @@ class CommandHSRequest : public Command
return;
}
- HostRequest *req = new HostRequest;
- req->nick = source.GetNick();
- req->ident = user;
- req->host = host;
- req->time = Anope::CurTime;
- na->Extend("hs_request", req);
+ HostRequest req(na);
+ req.nick = source.GetNick();
+ req.ident = user;
+ req.host = host;
+ req.time = Anope::CurTime;
+ na->Extend<HostRequest>("hostrequest", req);
source.Reply(_("Your vHost has been requested."));
req_send_memos(owner, source, user, host);
@@ -186,7 +187,7 @@ class CommandHSActivate : public Command
const Anope::string &nick = params[0];
NickAlias *na = NickAlias::Find(nick);
- HostRequest *req = na ? na->GetExt<HostRequest *>("hs_request") : NULL;
+ HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
if (req)
{
na->SetVhost(req->ident, req->host, source.GetNick(), req->time);
@@ -197,7 +198,7 @@ class CommandHSActivate : public Command
source.Reply(_("vHost for %s has been activated."), na->nick.c_str());
Log(LOG_COMMAND, source, this) << "for " << na->nick << " for vhost " << (!req->ident.empty() ? req->ident + "@" : "") << req->host;
- na->Shrink("hs_request");
+ na->Shrink<HostRequest>("hostrequest");
}
else
source.Reply(_("No request for nick %s found."), nick.c_str());
@@ -231,10 +232,10 @@ class CommandHSReject : public Command
const Anope::string &reason = params.size() > 1 ? params[1] : "";
NickAlias *na = NickAlias::Find(nick);
- HostRequest *req = na ? na->GetExt<HostRequest *>("hs_request") : NULL;
+ HostRequest *req = na ? na->GetExt<HostRequest>("hostrequest") : NULL;
if (req)
{
- na->Shrink("hs_request");
+ na->Shrink<HostRequest>("hostrequest");
if (Config->GetModule(this->owner)->Get<bool>("memouser") && memoserv)
{
@@ -244,7 +245,7 @@ class CommandHSReject : public Command
else
message = _("[auto memo] Your requested vHost has been rejected.");
- memoserv->Send(source.service->nick, nick, message, true);
+ memoserv->Send(source.service->nick, nick, Language::Translate(source.GetAccount(), message.c_str()), true);
}
source.Reply(_("vHost for %s has been rejected."), nick.c_str());
@@ -252,8 +253,6 @@ class CommandHSReject : public Command
}
else
source.Reply(_("No request for nick %s found."), nick.c_str());
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -287,7 +286,7 @@ class CommandHSWaiting : public Command
for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
{
const NickAlias *na = it->second;
- HostRequest *hr = na->GetExt<HostRequest *>("hs_request");
+ HostRequest *hr = na->GetExt<HostRequest>("hostrequest");
if (!hr)
continue;
@@ -334,24 +333,17 @@ class HSRequest : public Module
CommandHSActivate commandhsactive;
CommandHSReject commandhsreject;
CommandHSWaiting commandhswaiting;
+ ExtensibleItem<HostRequest> hostrequest;
public:
HSRequest(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- request_type("HostRequest", HostRequest::Unserialize), commandhsrequest(this), commandhsactive(this), commandhsreject(this), commandhswaiting(this)
+ request_type("HostRequest", HostRequest::Unserialize), commandhsrequest(this), commandhsactive(this),
+ commandhsreject(this), commandhswaiting(this), hostrequest(this, "hostrequest")
{
if (!IRCD || !IRCD->CanSetVHost)
throw ModuleException("Your IRCd does not support vhosts");
}
-
- ~HSRequest()
- {
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
- {
- NickAlias *na = it->second;
- na->Shrink("hs_request");
- }
- }
};
static void req_send_memos(Module *me, CommandSource &source, const Anope::string &vIdent, const Anope::string &vHost)
diff --git a/modules/commands/ms_info.cpp b/modules/commands/ms_info.cpp
index 67a504117..909ff4c82 100644
--- a/modules/commands/ms_info.cpp
+++ b/modules/commands/ms_info.cpp
@@ -27,7 +27,7 @@ class CommandMSInfo : public Command
const NickAlias *na = NULL;
ChannelInfo *ci = NULL;
const Anope::string &nname = !params.empty() ? params[0] : "";
- int hardmax = 0;
+ bool hardmax;
if (!nname.empty() && nname[0] != '#' && source.HasPriv("memoserv/info"))
{
@@ -38,7 +38,7 @@ class CommandMSInfo : public Command
return;
}
mi = &na->nc->memos;
- hardmax = na->nc->HasExt("MEMO_HARDMAX") ? 1 : 0;
+ hardmax = na->nc->HasExt("MEMO_HARDMAX");
}
else if (!nname.empty() && nname[0] == '#')
{
@@ -54,7 +54,7 @@ class CommandMSInfo : public Command
return;
}
mi = &ci->memos;
- hardmax = ci->HasExt("MEMO_HARDMAX") ? 1 : 0;
+ hardmax = ci->HasExt("MEMO_HARDMAX");
}
else if (!nname.empty()) /* It's not a chan and we aren't services admin */
{
@@ -64,7 +64,7 @@ class CommandMSInfo : public Command
else
{
mi = &nc->memos;
- hardmax = nc->HasExt("MEMO_HARDMAX") ? 1 : 0;
+ hardmax = nc->HasExt("MEMO_HARDMAX");
}
if (!nname.empty() && (ci || na->nc != nc))
@@ -178,7 +178,6 @@ class CommandMSInfo : public Command
else
source.Reply(_("You will not be notified of new memos."));
}
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
diff --git a/modules/commands/ms_set.cpp b/modules/commands/ms_set.cpp
index 9bf63b15d..e6d48d08a 100644
--- a/modules/commands/ms_set.cpp
+++ b/modules/commands/ms_set.cpp
@@ -25,27 +25,27 @@ class CommandMSSet : public Command
if (param.equals_ci("ON"))
{
- nc->ExtendMetadata("MEMO_SIGNON");
- nc->ExtendMetadata("MEMO_RECEIVE");
+ nc->Extend<bool>("MEMO_SIGNON");
+ nc->Extend<bool>("MEMO_RECEIVE");
source.Reply(_("%s will now notify you of memos when you log on and when they are sent to you."), MemoServ->nick.c_str());
}
else if (param.equals_ci("LOGON"))
{
- nc->ExtendMetadata("MEMO_SIGNON");
- nc->Shrink("MEMO_RECEIVE");
+ nc->Extend<bool>("MEMO_SIGNON");
+ nc->Shrink<bool>("MEMO_RECEIVE");
source.Reply(_("%s will now notify you of memos when you log on or unset /AWAY."), MemoServ->nick.c_str());
}
else if (param.equals_ci("NEW"))
{
- nc->Shrink("MEMO_SIGNON");
- nc->ExtendMetadata("MEMO_RECEIVE");
+ nc->Shrink<bool>("MEMO_SIGNON");
+ nc->Extend<bool>("MEMO_RECEIVE");
source.Reply(_("%s will now notify you of memos when they are sent to you."), MemoServ->nick.c_str());
}
else if (param.equals_ci("MAIL"))
{
if (!nc->email.empty())
{
- nc->ExtendMetadata("MEMO_MAIL");
+ nc->Extend<bool>("MEMO_MAIL");
source.Reply(_("You will now be informed about new memos via email."));
}
else
@@ -53,20 +53,18 @@ class CommandMSSet : public Command
}
else if (param.equals_ci("NOMAIL"))
{
- nc->Shrink("MEMO_MAIL");
+ nc->Shrink<bool>("MEMO_MAIL");
source.Reply(_("You will no longer be informed via email."));
}
else if (param.equals_ci("OFF"))
{
- nc->Shrink("MEMO_SIGNON");
- nc->Shrink("MEMO_RECEIVE");
- nc->Shrink("MEMO_MAIL");
+ nc->Shrink<bool>("MEMO_SIGNON");
+ nc->Shrink<bool>("MEMO_RECEIVE");
+ nc->Shrink<bool>("MEMO_MAIL");
source.Reply(_("%s will not send you any notification of memos."), MemoServ->nick.c_str());
}
else
this->OnSyntaxError(source, "");
-
- return;
}
void DoLimit(CommandSource &source, const std::vector<Anope::string> &params, MemoInfo *mi)
@@ -125,16 +123,16 @@ class CommandMSSet : public Command
if (!chan.empty())
{
if (!p2.empty())
- ci->ExtendMetadata("MEMO_HARDMAX");
+ ci->Extend<bool>("MEMO_HARDMAX");
else
- ci->Shrink("MEMO_HARDMAX");
+ ci->Shrink<bool>("MEMO_HARDMAX");
}
else
{
if (!p2.empty())
- nc->ExtendMetadata("MEMO_HARDMAX");
+ nc->Extend<bool>("MEMO_HARDMAX");
else
- nc->Shrink("MEMO_HARDMAX");
+ nc->Shrink<bool>("MEMO_HARDMAX");
}
limit = -1;
try
@@ -301,10 +299,12 @@ class CommandMSSet : public Command
class MSSet : public Module
{
CommandMSSet commandmsset;
+ PrimitiveExtensibleItem<bool> memo_signon, memo_receive, memo_mail, memo_hardmax;
public:
MSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandmsset(this)
+ commandmsset(this), memo_signon(this, "MEMO_SIGNON"), memo_receive(this, "MEMO_RECEIVE"), memo_mail(this, "MEMO_MAIL"),
+ memo_hardmax(this, "MEMO_HARDMAX")
{
}
diff --git a/modules/commands/ns_ajoin.cpp b/modules/commands/ns_ajoin.cpp
index 0304c7394..79d7fdf4a 100644
--- a/modules/commands/ns_ajoin.cpp
+++ b/modules/commands/ns_ajoin.cpp
@@ -13,9 +13,9 @@
struct AJoinEntry;
-struct AJoinList : Serialize::Checker<std::vector<AJoinEntry *> >, ExtensibleItem
+struct AJoinList : Serialize::Checker<std::vector<AJoinEntry *> >
{
- AJoinList() : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { }
+ AJoinList(Extensible *) : Serialize::Checker<std::vector<AJoinEntry *> >("AJoinEntry") { }
~AJoinList();
};
@@ -25,7 +25,7 @@ struct AJoinEntry : Serializable
Anope::string channel;
Anope::string key;
- AJoinEntry() : Serializable("AJoinEntry") { }
+ AJoinEntry(Extensible *) : Serializable("AJoinEntry") { }
void Serialize(Serialize::Data &sd) const anope_override
{
@@ -52,7 +52,7 @@ struct AJoinEntry : Serializable
aj = anope_dynamic_static_cast<AJoinEntry *>(obj);
else
{
- aj = new AJoinEntry();
+ aj = new AJoinEntry(nc);
aj->owner = nc;
}
@@ -61,12 +61,7 @@ struct AJoinEntry : Serializable
if (!obj)
{
- AJoinList *channels = nc->GetExt<AJoinList *>("ns_ajoin_channels");
- if (channels == NULL)
- {
- channels = new AJoinList();
- nc->Extend("ns_ajoin_channels", channels);
- }
+ AJoinList *channels = nc->Require<AJoinList>("ajoinlist");
(*channels)->push_back(aj);
}
@@ -84,12 +79,7 @@ class CommandNSAJoin : public Command
{
void DoList(CommandSource &source, NickCore *nc)
{
- AJoinList *channels = nc->GetExt<AJoinList *>("ns_ajoin_channels");
- if (channels == NULL)
- {
- channels = new AJoinList();
- nc->Extend("ns_ajoin_channels", channels);
- }
+ AJoinList *channels = nc->Require<AJoinList>("ajoinlist");
if ((*channels)->empty())
source.Reply(_("%s's auto join list is empty."), nc->display.c_str());
@@ -119,12 +109,7 @@ class CommandNSAJoin : public Command
void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &chan, const Anope::string &key)
{
- AJoinList *channels = nc->GetExt<AJoinList *>("ns_ajoin_channels");
- if (channels == NULL)
- {
- channels = new AJoinList();
- nc->Extend("ns_ajoin_channels", channels);
- }
+ AJoinList *channels = nc->Require<AJoinList>("ajoinlist");
unsigned i = 0;
for (; i < (*channels)->size(); ++i)
@@ -139,7 +124,7 @@ class CommandNSAJoin : public Command
source.Reply(CHAN_X_INVALID, chan.c_str());
else
{
- AJoinEntry *entry = new AJoinEntry();
+ AJoinEntry *entry = new AJoinEntry(nc);
entry->owner = nc;
entry->channel = chan;
entry->key = key;
@@ -150,12 +135,7 @@ class CommandNSAJoin : public Command
void DoDel(CommandSource &source, NickCore *nc, const Anope::string &chan)
{
- AJoinList *channels = nc->GetExt<AJoinList *>("ns_ajoin_channels");
- if (channels == NULL)
- {
- channels = new AJoinList();
- nc->Extend("ns_ajoin_channels", channels);
- }
+ AJoinList *channels = nc->Require<AJoinList>("ajoinlist");
unsigned i = 0;
for (; i < (*channels)->size(); ++i)
@@ -170,6 +150,9 @@ class CommandNSAJoin : public Command
(*channels)->erase((*channels)->begin() + i);
source.Reply(_("%s was removed from %s's auto join list."), chan.c_str(), nc->display.c_str());
}
+
+ if ((*channels)->empty())
+ nc->Shrink<AJoinList>("ajoinlist");
}
public:
@@ -233,10 +216,11 @@ class NSAJoin : public Module
{
Serialize::Type ajoinentry_type;
CommandNSAJoin commandnsajoin;
+ ExtensibleItem<AJoinList> ajoinlist;
public:
NSAJoin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- ajoinentry_type("AJoinEntry", AJoinEntry::Unserialize), commandnsajoin(this)
+ ajoinentry_type("AJoinEntry", AJoinEntry::Unserialize), commandnsajoin(this), ajoinlist(this, "ajoinlist")
{
if (!IRCD->CanSVSJoin)
@@ -250,12 +234,9 @@ class NSAJoin : public Module
if (!NickServ)
return;
- AJoinList *channels = u->Account()->GetExt<AJoinList *>("ns_ajoin_channels");
+ AJoinList *channels = u->Account()->GetExt<AJoinList>("ajoinlist");
if (channels == NULL)
- {
- channels = new AJoinList();
- u->Account()->Extend("ns_ajoin_channels", channels);
- }
+ channels = u->Account()->Extend<AJoinList>("ajoinlist");
for (unsigned i = 0; i < (*channels)->size(); ++i)
{
@@ -284,7 +265,7 @@ class NSAJoin : public Module
continue;
else if (c->HasMode("ADMINONLY") && !u->HasMode("ADMIN"))
continue;
- else if (c->HasMode("SSL") && !(u->HasMode("SSL") || u->HasExt("SSL")))
+ else if (c->HasMode("SSL") && !(u->HasMode("SSL") || u->HasExt("ssl")))
continue;
else if (c->MatchesList(u, "BAN") == true && c->MatchesList(u, "EXCEPT") == false)
need_invite = true;
diff --git a/modules/commands/ns_alist.cpp b/modules/commands/ns_alist.cpp
index 591af44c3..2d7b02cfd 100644
--- a/modules/commands/ns_alist.cpp
+++ b/modules/commands/ns_alist.cpp
@@ -62,7 +62,7 @@ class CommandNSAList : public Command
{
++chan_count;
entry["Number"] = stringify(chan_count);
- entry["Channel"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name;
+ entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
entry["Access"] = "Founder";
list.AddEntry(entry);
continue;
@@ -72,7 +72,7 @@ class CommandNSAList : public Command
{
++chan_count;
entry["Number"] = stringify(chan_count);
- entry["Channel"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name;
+ entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
entry["Access"] = "Successor";
list.AddEntry(entry);
continue;
@@ -85,7 +85,7 @@ class CommandNSAList : public Command
++chan_count;
entry["Number"] = stringify(chan_count);
- entry["Channel"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name;
+ entry["Channel"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
for (unsigned j = 0; j < access.size(); ++j)
entry["Access"] = entry["Access"] + ", " + access[j]->AccessSerialize();
entry["Access"] = entry["Access"].substr(2);
diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp
index dc877e467..c87ff7179 100644
--- a/modules/commands/ns_cert.cpp
+++ b/modules/commands/ns_cert.cpp
@@ -10,15 +10,135 @@
*/
#include "module.h"
+#include "modules/ns_cert.h"
-static unsigned accessmax;
+struct NSCertListImpl : NSCertList
+{
+ Serialize::Reference<NickCore> nc;
+ std::vector<Anope::string> certs;
+
+ public:
+ NSCertListImpl(Extensible *obj) : nc(anope_dynamic_static_cast<NickCore *>(obj)) { }
+
+ /** Add an entry to the nick's certificate list
+ *
+ * @param entry The fingerprint to add to the cert list
+ *
+ * Adds a new entry into the cert list.
+ */
+ void AddCert(const Anope::string &entry) anope_override
+ {
+ this->certs.push_back(entry);
+ FOREACH_MOD(OnNickAddCert, (this->nc, entry));
+ }
+
+ /** Get an entry from the nick's cert list by index
+ *
+ * @param entry Index in the certificaate list vector to retrieve
+ * @return The fingerprint entry of the given index if within bounds, an empty string if the vector is empty or the index is out of bounds
+ *
+ * Retrieves an entry from the certificate list corresponding to the given index.
+ */
+ Anope::string GetCert(unsigned entry) const anope_override
+ {
+ if (entry >= this->certs.size())
+ return "";
+ return this->certs[entry];
+ }
+
+ unsigned GetCertCount() const anope_override
+ {
+ return this->certs.size();
+ }
+
+ /** Find an entry in the nick's cert list
+ *
+ * @param entry The fingerprint to search for
+ * @return True if the fingerprint is found in the cert list, false otherwise
+ *
+ * Search for an fingerprint within the cert list.
+ */
+ bool FindCert(const Anope::string &entry) const anope_override
+ {
+ return std::find(this->certs.begin(), this->certs.end(), entry) != this->certs.end();
+ }
+
+ /** Erase a fingerprint from the nick's certificate list
+ *
+ * @param entry The fingerprint to remove
+ *
+ * Removes the specified fingerprint from the cert list.
+ */
+ void EraseCert(const Anope::string &entry) anope_override
+ {
+ std::vector<Anope::string>::iterator it = std::find(this->certs.begin(), this->certs.end(), entry);
+ if (it != this->certs.end())
+ {
+ FOREACH_MOD(OnNickEraseCert, (this->nc, entry));
+ this->certs.erase(it);
+ }
+ }
+
+ /** Clears the entire nick's cert list
+ *
+ * Deletes all the memory allocated in the certificate list vector and then clears the vector.
+ */
+ void ClearCert() anope_override
+ {
+ FOREACH_MOD(OnNickClearCert, (this->nc));
+ this->certs.clear();
+ }
+
+ void Check() anope_override
+ {
+ if (this->certs.empty())
+ nc->Shrink<NSCertList>("certificates");
+ }
+
+ struct ExtensibleItem : ::ExtensibleItem<NSCertListImpl>
+ {
+ ExtensibleItem(Module *m, const Anope::string &name) : ::ExtensibleItem<NSCertListImpl>(m, name) { }
+
+ void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "NickCore")
+ return;
+
+ const NickCore *nc = anope_dynamic_static_cast<const NickCore *>(e);
+ NSCertList *certs = this->Get(nc);
+ if (certs == NULL || !certs->GetCertCount())
+ return;
+
+ for (unsigned i = 0; i < certs->GetCertCount(); ++i)
+ data["cert"] << certs->GetCert(i) << " ";
+ }
+
+ void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) anope_override
+ {
+ if (s->GetSerializableType()->GetName() != "NickCore")
+ return;
+
+ NickCore *nc = anope_dynamic_static_cast<NickCore *>(e);
+ NSCertListImpl *certs = this->Require(nc);
+
+ Anope::string buf;
+ data["cert"] >> buf;
+ spacesepstream sep(buf);
+ certs->certs.clear();
+ while (sep.GetToken(buf))
+ certs->certs.push_back(buf);
+ }
+ };
+};
class CommandNSCert : public Command
{
private:
void DoServAdminList(CommandSource &source, const NickCore *nc)
{
- if (nc->cert.empty())
+ NSCertList *cl = nc->GetExt<NSCertList>("certificates");
+
+ if (!cl || !cl->GetCertCount())
{
source.Reply(_("Certificate list for \002%s\002 is empty."), nc->display.c_str());
return;
@@ -33,9 +153,9 @@ class CommandNSCert : public Command
ListFormatter list;
list.AddColumn("Certificate");
- for (unsigned i = 0, end = nc->cert.size(); i < end; ++i)
+ for (unsigned i = 0; i < cl->GetCertCount(); ++i)
{
- Anope::string fingerprint = nc->GetCert(i);
+ const Anope::string &fingerprint = cl->GetCert(i);
ListFormatter::ListEntry entry;
entry["Certificate"] = fingerprint;
list.AddEntry(entry);
@@ -47,74 +167,74 @@ class CommandNSCert : public Command
list.Process(replies);
for (unsigned i = 0; i < replies.size(); ++i)
source.Reply(replies[i]);
-
- return;
}
void DoAdd(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
+ NSCertList *cl = nc->Require<NSCertList>("certificates");
- if (nc->cert.size() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax"))
+ if (cl->GetCertCount() >= Config->GetModule(this->owner)->Get<unsigned>("accessmax"))
{
source.Reply(_("Sorry, you can only have %d certificate entries for a nickname."), Config->GetModule(this->owner)->Get<unsigned>("accessmax"));
return;
}
- if (source.GetUser() && !source.GetUser()->fingerprint.empty() && !nc->FindCert(source.GetUser()->fingerprint))
- {
- nc->AddCert(source.GetUser()->fingerprint);
- source.Reply(_("\002%s\002 added to your certificate list."), source.GetUser()->fingerprint.c_str());
- return;
- }
-
if (mask.empty())
{
- this->OnSyntaxError(source, "ADD");
+ if (source.GetUser() && !source.GetUser()->fingerprint.empty() && !cl->FindCert(source.GetUser()->fingerprint))
+ {
+ cl->AddCert(source.GetUser()->fingerprint);
+ source.Reply(_("\002%s\002 added to your certificate list."), source.GetUser()->fingerprint.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "ADD");
+
return;
}
- if (nc->FindCert(mask))
+ if (cl->FindCert(mask))
{
source.Reply(_("Fingerprint \002%s\002 already present on your certificate list."), mask.c_str());
return;
}
- nc->AddCert(mask);
+ cl->AddCert(mask);
source.Reply(_("\002%s\002 added to your certificate list."), mask.c_str());
- return;
}
void DoDel(CommandSource &source, NickCore *nc, const Anope::string &mask)
{
- if (source.GetUser() && !source.GetUser()->fingerprint.empty() && nc->FindCert(source.GetUser()->fingerprint))
- {
- nc->EraseCert(source.GetUser()->fingerprint);
- source.Reply(_("\002%s\002 deleted from your certificate list."), source.GetUser()->fingerprint.c_str());
- return;
- }
+ NSCertList *cl = nc->Require<NSCertList>("certificates");
if (mask.empty())
{
- this->OnSyntaxError(source, "DEL");
+ if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl->FindCert(source.GetUser()->fingerprint))
+ {
+ cl->EraseCert(source.GetUser()->fingerprint);
+ source.Reply(_("\002%s\002 deleted from your certificate list."), source.GetUser()->fingerprint.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "DEL");
+
return;
}
- if (!nc->FindCert(mask))
+ if (!cl->FindCert(mask))
{
source.Reply(_("\002%s\002 not found on your certificate list."), mask.c_str());
return;
}
source.Reply(_("\002%s\002 deleted from your certificate list."), mask.c_str());
- nc->EraseCert(mask);
-
- return;
+ cl->EraseCert(mask);
+ cl->Check();
}
void DoList(CommandSource &source, const NickCore *nc)
{
+ NSCertList *cl = nc->GetExt<NSCertList>("certificates");
- if (nc->cert.empty())
+ if (!cl || !cl->GetCertCount())
{
source.Reply(_("Your certificate list is empty."));
return;
@@ -123,10 +243,10 @@ class CommandNSCert : public Command
ListFormatter list;
list.AddColumn("Certificate");
- for (unsigned i = 0, end = nc->cert.size(); i < end; ++i)
+ for (unsigned i = 0; i < cl->GetCertCount(); ++i)
{
ListFormatter::ListEntry entry;
- entry["Certificate"] = nc->GetCert(i);
+ entry["Certificate"] = cl->GetCert(i);
list.AddEntry(entry);
}
@@ -197,8 +317,17 @@ class CommandNSCert : public Command
class NSCert : public Module
{
CommandNSCert commandnscert;
+ NSCertListImpl::ExtensibleItem certs;
+
+ public:
+ NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ commandnscert(this), certs(this, "certificates")
+ {
+ if (!IRCD || !IRCD->CanCertFP)
+ throw ModuleException("Your IRCd does not support ssl client certificates");
+ }
- void DoAutoIdentify(User *u)
+ void OnFingerprint(User *u) anope_override
{
NickAlias *na = NickAlias::Find(u->nick);
BotInfo *NickServ = Config->GetClient("NickServ");
@@ -208,29 +337,28 @@ class NSCert : public Module
return;
if (na->nc->HasExt("SUSPENDED"))
return;
- if (!na->nc->FindCert(u->fingerprint))
+
+ NSCertList *cl = certs.Get(na->nc);
+ if (!cl || !cl->FindCert(u->fingerprint))
return;
u->Identify(na);
u->SendMessage(NickServ, _("SSL Fingerprint accepted. You are now identified."));
- Log(u) << "automatically identified for account " << na->nc->display << " using a valid SSL fingerprint";
- return;
+ Log(u) << "automatically identified for account " << na->nc->display << " via SSL certificate fingerprint";
}
- public:
- NSCert(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnscert(this)
+ EventReturn OnNickValidate(User *u, NickAlias *na) anope_override
{
+ NSCertList *cl = certs.Get(na->nc);
+ if (!u->fingerprint.empty() && cl && cl->FindCert(u->fingerprint))
+ {
+ u->Identify(na);
+ u->SendMessage(Config->GetClient("NickServ"), _("SSL fingerprint accepted, you are now identified."));
+ Log(u) << "automatically identified for account " << na->nc->display << " via SSL fingerprint.";
+ return EVENT_ALLOW;
+ }
- if (!IRCD || !IRCD->CanCertFP)
- throw ModuleException("Your IRCd does not support ssl client certificates");
-
-
- }
-
- void OnFingerprint(User *u) anope_override
- {
- DoAutoIdentify(u);
+ return EVENT_CONTINUE;
}
};
diff --git a/modules/commands/ns_group.cpp b/modules/commands/ns_group.cpp
index 989fc1385..160980bc9 100644
--- a/modules/commands/ns_group.cpp
+++ b/modules/commands/ns_group.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/ns_cert.h"
class NSGroupRequest : public IdentifyRequest
{
@@ -43,7 +44,6 @@ class NSGroupRequest : public IdentifyRequest
na->time_registered = na->last_seen = Anope::CurTime;
u->Login(target->nc);
- IRCD->SendLogin(u);
FOREACH_MOD(OnNickGroup, (u, target));
Log(LOG_COMMAND, source, cmd) << "makes " << nick << " join group of " << target->nick << " (" << target->nc->display << ") (email: " << (!target->nc->email.empty() ? target->nc->email : "none") << ")";
@@ -141,7 +141,9 @@ class CommandNSGroup : public Command
bool ok = false;
if (!na && u->Account())
ok = true;
- else if (!u->fingerprint.empty() && target->nc->FindCert(u->fingerprint))
+
+ NSCertList *cl = target->nc->GetExt<NSCertList>("certificates");
+ if (!u->fingerprint.empty() && cl && cl->FindCert(u->fingerprint))
ok = true;
if (ok == false && !pass.empty())
@@ -236,8 +238,6 @@ class CommandNSUngroup : public Command
nc->pass = oldcore->pass;
if (!oldcore->email.empty())
nc->email = oldcore->email;
- if (!oldcore->greet.empty())
- nc->greet = oldcore->greet;
nc->language = oldcore->language;
source.Reply(_("Nick %s has been ungrouped from %s."), na->nick.c_str(), oldcore->display.c_str());
@@ -303,7 +303,7 @@ class CommandNSGList : public Command
ListFormatter::ListEntry entry;
entry["Nick"] = na2->nick;
- entry["Expires"] = (na2->HasExt("NO_EXPIRE") || !nickserv_expire || Anope::NoExpire) ? "Does not expire" : ("expires in " + Anope::strftime(na2->last_seen + nickserv_expire));
+ entry["Expires"] = (na2->HasExt("NS_NO_EXPIRE") || !nickserv_expire || Anope::NoExpire) ? "Does not expire" : ("expires in " + Anope::strftime(na2->last_seen + nickserv_expire));
list.AddEntry(entry);
}
diff --git a/modules/commands/ns_info.cpp b/modules/commands/ns_info.cpp
index 864136cd8..8fc5aa639 100644
--- a/modules/commands/ns_info.cpp
+++ b/modules/commands/ns_info.cpp
@@ -13,17 +13,6 @@
class CommandNSInfo : public Command
{
- private:
- void CheckOptStr(NickCore *core, Anope::string &buf, const Anope::string &opt, const char *str, const Extensible *e, bool reverse_logic = false)
- {
- if (reverse_logic != e->HasExt(opt))
- {
- if (!buf.empty())
- buf += ", ";
-
- buf += Language::Translate(core, str);
- }
- }
public:
CommandNSInfo(Module *creator) : Command(creator, "nickserv/info", 0, 2)
{
@@ -105,34 +94,6 @@ class CommandNSInfo : public Command
else
info[_("VHost")] = na->GetVhostHost();
}
-
- if (!na->nc->greet.empty())
- info[_("Greet")] = na->nc->greet;
-
- Anope::string optbuf;
-
- CheckOptStr(source.nc, optbuf, "KILLPROTECT", _("Protection"), na->nc);
- CheckOptStr(source.nc, optbuf, "SECURE", _("Security"), na->nc);
- CheckOptStr(source.nc, optbuf, "PRIVATE", _("Private"), na->nc);
- CheckOptStr(source.nc, optbuf, "MSG", _("Message mode"), na->nc);
- CheckOptStr(source.nc, optbuf, "AUTOOP", _("Auto-op"), na->nc);
- CheckOptStr(source.nc, optbuf, "SUSPENDED", _("Suspended"), na->nc);
- CheckOptStr(source.nc, optbuf, "STATS", _("Chanstats"), na->nc);
- CheckOptStr(source.nc, optbuf, "NO_EXPIRE", _("No expire"), na);
-
- info[_("Options")] = optbuf.empty() ? _("None") : optbuf;
-
- if (na->nc->HasExt("UNCONFIRMED") == false)
- {
- time_t nickserv_expire = Config->GetModule("nickserv")->Get<time_t>("expire");
- if (!na->HasExt("NO_EXPIRE") && nickserv_expire && !Anope::NoExpire)
- info[_("Expires")] = Anope::strftime(na->last_seen + nickserv_expire);
- }
- else
- {
- time_t unconfirmed_expire = Config->GetModule("nickserv")->Get<time_t>("unconfirmedexpire", "1d");
- info[_("Expires")] = Anope::strftime(na->time_registered + unconfirmed_expire);
- }
}
FOREACH_MOD(OnNickInfo, (source, na, info, show_hidden));
@@ -159,13 +120,142 @@ class CommandNSInfo : public Command
}
};
+
+class CommandNSSetHide : public Command
+{
+ public:
+ CommandNSSetHide(Module *creator, const Anope::string &sname = "nickserv/set/hide", size_t min = 2) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Hide certain pieces of nickname information"));
+ this->SetSyntax(_("{EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param, const Anope::string &arg)
+ {
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ Anope::string onmsg, offmsg, flag;
+
+ if (param.equals_ci("EMAIL"))
+ {
+ flag = "HIDE_EMAIL";
+ onmsg = _("The E-mail address of \002%s\002 will now be hidden from %s INFO displays.");
+ offmsg = _("The E-mail address of \002%s\002 will now be shown in %s INFO displays.");
+ }
+ else if (param.equals_ci("USERMASK"))
+ {
+ flag = "HIDE_MASK";
+ onmsg = _("The last seen user@host mask of \002%s\002 will now be hidden from %s INFO displays.");
+ offmsg = _("The last seen user@host mask of \002%s\002 will now be shown in %s INFO displays.");
+ }
+ else if (param.equals_ci("STATUS"))
+ {
+ flag = "HIDE_STATUS";
+ onmsg = _("The services access status of \002%s\002 will now be hidden from %s INFO displays.");
+ offmsg = _("The services access status of \002%s\002 will now be shown in %s INFO displays.");
+ }
+ else if (param.equals_ci("QUIT"))
+ {
+ flag = "HIDE_QUIT";
+ onmsg = _("The last quit message of \002%s\002 will now be hidden from %s INFO displays.");
+ offmsg = _("The last quit message of \002%s\002 will now be shown in %s INFO displays.");
+ }
+ else
+ {
+ this->OnSyntaxError(source, "HIDE");
+ return;
+ }
+
+ if (arg.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param << " to " << arg << " for " << nc->display;
+ nc->Extend<bool>(flag);
+ source.Reply(onmsg.c_str(), nc->display.c_str(), source.service->nick.c_str());
+ }
+ else if (arg.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param << " to " << arg << " for " << nc->display;
+ nc->Shrink<bool>(flag);
+ source.Reply(offmsg.c_str(), nc->display.c_str(), source.service->nick.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "HIDE");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->Run(source, source.nc->display, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Allows you to prevent certain pieces of information from\n"
+ "being displayed when someone does a %s \002INFO\002 on your\n"
+ "nick. You can hide your E-mail address (\002EMAIL\002), last seen\n"
+ "user@host mask (\002USERMASK\002), your services access status\n"
+ "(\002STATUS\002) and last quit message (\002QUIT\002).\n"
+ "The second parameter specifies whether the information should\n"
+ "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str());
+ return true;
+ }
+};
+
+class CommandNSSASetHide : public CommandNSSetHide
+{
+ public:
+ CommandNSSASetHide(Module *creator) : CommandNSSetHide(creator, "nickserv/saset/hide", 3)
+ {
+ this->SetSyntax("\037nickname\037 {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->ClearSyntax();
+ this->Run(source, params[0], params[1], params[2]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Allows you to prevent certain pieces of information from\n"
+ "being displayed when someone does a %s \002INFO\002 on the\n"
+ "nick. You can hide the E-mail address (\002EMAIL\002), last seen\n"
+ "user@host mask (\002USERMASK\002), the services access status\n"
+ "(\002STATUS\002) and last quit message (\002QUIT\002).\n"
+ "The second parameter specifies whether the information should\n"
+ "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str());
+ return true;
+ }
+};
+
class NSInfo : public Module
{
CommandNSInfo commandnsinfo;
+ CommandNSSetHide commandnssethide;
+ CommandNSSASetHide commandnssasethide;
+
+ SerializableExtensibleItem<bool> hide_email, hide_usermask, hide_status, hide_quit;
+
public:
NSInfo(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsinfo(this)
+ commandnsinfo(this), commandnssethide(this), commandnssasethide(this),
+ hide_email(this, "HIDE_EMAIL"), hide_usermask(this, "HIDE_MASK"), hide_status(this, "HIDE_STATUS"),
+ hide_quit(this, "HIDE_QUIT")
{
}
diff --git a/modules/commands/ns_list.cpp b/modules/commands/ns_list.cpp
index a4e73e857..b1ab19971 100644
--- a/modules/commands/ns_list.cpp
+++ b/modules/commands/ns_list.cpp
@@ -83,9 +83,9 @@ class CommandNSList : public Command
const NickAlias *na = it->second;
/* Don't show private nicks to non-services admins. */
- if (na->nc->HasExt("PRIVATE") && !is_servadmin && na->nc != mync)
+ if (na->nc->HasExt("NS_PRIVATE") && !is_servadmin && na->nc != mync)
continue;
- else if (nsnoexpire && !na->HasExt("NO_EXPIRE"))
+ else if (nsnoexpire && !na->HasExt("NS_NO_EXPIRE"))
continue;
else if (suspended && !na->nc->HasExt("SUSPENDED"))
continue;
@@ -101,7 +101,7 @@ class CommandNSList : public Command
if (((count + 1 >= from && count + 1 <= to) || (!from && !to)) && ++nnicks <= listmax)
{
bool isnoexpire = false;
- if (is_servadmin && na->HasExt("NO_EXPIRE"))
+ if (is_servadmin && na->HasExt("NS_NO_EXPIRE"))
isnoexpire = true;
ListFormatter::ListEntry entry;
@@ -177,14 +177,118 @@ class CommandNSList : public Command
}
};
+
+class CommandNSSetPrivate : public Command
+{
+ public:
+ CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1) : Command(creator, sname, min, min + 1)
+ {
+ this->SetDesc(_("Prevent the nickname from appearing in the LIST command"));
+ this->SetSyntax(_("{ON | OFF}"));
+ }
+
+ void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
+ {
+ const NickAlias *na = NickAlias::Find(user);
+ if (!na)
+ {
+ source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
+ return;
+ }
+ NickCore *nc = na->nc;
+
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ if (param.equals_ci("ON"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable private for " << nc->display;
+ nc->Extend<bool>("NS_PRIVATE");
+ source.Reply(_("Private option is now \002on\002 for \002%s\002."), nc->display.c_str());
+ }
+ else if (param.equals_ci("OFF"))
+ {
+ Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable private for " << nc->display;
+ nc->Shrink<bool>("NS_PRIVATE");
+ source.Reply(_("Private option is now \002off\002 for \002%s\002."), nc->display.c_str());
+ }
+ else
+ this->OnSyntaxError(source, "PRIVATE");
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->Run(source, source.nc->display, params[0]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Turns %s's privacy option on or off for your nick.\n"
+ "With \002PRIVATE\002 set, your nickname will not appear in\n"
+ "nickname lists generated with %s's \002LIST\002 command.\n"
+ "(However, anyone who knows your nickname can still get\n"
+ "information on it using the \002INFO\002 command.)"),
+ source.service->nick.c_str(), source.service->nick.c_str());
+ return true;
+ }
+};
+
+class CommandNSSASetPrivate : public CommandNSSetPrivate
+{
+ public:
+ CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2)
+ {
+ this->ClearSyntax();
+ this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ this->Run(source, params[0], params[1]);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(" ");
+ source.Reply(_("Turns %s's privacy option on or off for the nick.\n"
+ "With \002PRIVATE\002 set, the nickname will not appear in\n"
+ "nickname lists generated with %s's \002LIST\002 command.\n"
+ "(However, anyone who knows the nickname can still get\n"
+ "information on it using the \002INFO\002 command.)"),
+ source.service->nick.c_str(), source.service->nick.c_str());
+ return true;
+ }
+};
+
+
class NSList : public Module
{
CommandNSList commandnslist;
+ CommandNSSetPrivate commandnssetprivate;
+ CommandNSSASetPrivate commandnssasetprivate;
+
+ SerializableExtensibleItem<bool> priv;
+
public:
NSList(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnslist(this)
+ commandnslist(this), commandnssetprivate(this), commandnssasetprivate(this),
+ priv(this, "NS_PRIVATE")
+ {
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_all) anope_override
{
+ if (!show_all)
+ return;
+
+ if (priv.HasExt(na->nc))
+ info.AddOption(_("Private"));
}
};
diff --git a/modules/commands/ns_recover.cpp b/modules/commands/ns_recover.cpp
index 224b4e2ed..48c625ace 100644
--- a/modules/commands/ns_recover.cpp
+++ b/modules/commands/ns_recover.cpp
@@ -10,10 +10,11 @@
*/
#include "module.h"
+#include "modules/ns_cert.h"
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
-struct NSRecoverExtensibleInfo : ExtensibleItem, std::map<Anope::string, ChannelStatus> { };
+typedef std::map<Anope::string, ChannelStatus> NSRecoverInfo;
class NSRecoverRequest : public IdentifyRequest
{
@@ -50,7 +51,7 @@ class NSRecoverRequest : public IdentifyRequest
// same person that is executing the command, so kill them off (old GHOST command).
else if (u->Account() == na->nc)
{
- if (!source.GetAccount() && na->nc->HasExt("SECURE"))
+ if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
{
source.GetUser()->Login(u->Account());
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << u->Account()->display;
@@ -60,11 +61,9 @@ class NSRecoverRequest : public IdentifyRequest
{
if (!u->chans.empty())
{
- NSRecoverExtensibleInfo *ei = new NSRecoverExtensibleInfo;
+ NSRecoverInfo *ei = source.GetUser()->Extend<NSRecoverInfo>("recover");
for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
(*ei)[it->first->name] = it->second->status;
-
- source.GetUser()->Extend("ns_recover_info", ei);
}
}
@@ -83,7 +82,7 @@ class NSRecoverRequest : public IdentifyRequest
/* User is not identified or not identified to the same account as the person using this command */
else
{
- if (!source.GetAccount() && na->nc->HasExt("SECURE"))
+ if (!source.GetAccount() && na->nc->HasExt("NS_SECURE"))
{
source.GetUser()->Login(na->nc); // Identify the user using the command if they arent identified
Log(LOG_COMMAND, source, cmd) << "and was automatically identified to " << na->nick << " (" << na->nc->display << ")";
@@ -161,9 +160,11 @@ class CommandNSRecover : public Command
bool ok = false;
if (source.GetAccount() == na->nc)
ok = true;
- else if (!na->nc->HasExt("SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser()))
+ else if (!na->nc->HasExt("NS_SECURE") && source.GetUser() && na->nc->IsOnAccess(source.GetUser()))
ok = true;
- else if (source.GetUser() && !source.GetUser()->fingerprint.empty() && na->nc->FindCert(source.GetUser()->fingerprint))
+
+ NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
+ if (source.GetUser() && !source.GetUser()->fingerprint.empty() && cl && cl->FindCert(source.GetUser()->fingerprint))
ok = true;
if (ok == false && !pass.empty())
@@ -200,10 +201,11 @@ class CommandNSRecover : public Command
class NSRecover : public Module
{
CommandNSRecover commandnsrecover;
+ PrimitiveExtensibleItem<NSRecoverInfo> recover;
public:
NSRecover(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsrecover(this)
+ commandnsrecover(this), recover(this, "recover")
{
if (Config->GetBlock("options")->Get<bool>("nonicknameownership"))
@@ -211,34 +213,15 @@ class NSRecover : public Module
}
- ~NSRecover()
- {
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- it->second->Shrink("ns_recover_info");
-
- OnShutdown();
- }
-
- void OnShutdown() anope_override
- {
- /* On shutdown, restart, or mod unload, remove all of our holds for nicks (svshold or qlines)
- * because some IRCds do not allow us to have these automatically expire
- */
- for (nickalias_map::const_iterator it = NickAliasList->begin(); it != NickAliasList->end(); ++it)
- nickserv->Release(it->second);
- }
-
- void OnRestart() anope_override { OnShutdown(); }
-
void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override
{
if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
{
- NSRecoverExtensibleInfo *ei = u->GetExt<NSRecoverExtensibleInfo *>("ns_recover_info");
+ NSRecoverInfo *ei = recover.Get(u);
BotInfo *NickServ = Config->GetClient("NickServ");
if (ei != NULL && NickServ != NULL)
- for (std::map<Anope::string, ChannelStatus>::iterator it = ei->begin(), it_end = ei->end(); it != it_end;)
+ for (NSRecoverInfo::iterator it = ei->begin(), it_end = ei->end(); it != it_end;)
{
Channel *c = Channel::Find(it->first);
const Anope::string &cname = it->first;
@@ -257,11 +240,11 @@ class NSRecover : public Module
{
if (Config->GetModule(this)->Get<bool>("restoreonrecover"))
{
- NSRecoverExtensibleInfo *ei = u->GetExt<NSRecoverExtensibleInfo *>("ns_recover_info");
+ NSRecoverInfo *ei = recover.Get(u);
if (ei != NULL)
{
- std::map<Anope::string, ChannelStatus>::iterator it = ei->find(c->name);
+ NSRecoverInfo::iterator it = ei->find(c->name);
if (it != ei->end())
{
for (size_t i = 0; i < it->second.Modes().length(); ++i)
@@ -269,7 +252,7 @@ class NSRecover : public Module
ei->erase(it);
if (ei->empty())
- u->Shrink("ns_recover_info");
+ recover.Unset(u);
}
}
}
diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp
index 4064ce924..e8adec549 100644
--- a/modules/commands/ns_register.cpp
+++ b/modules/commands/ns_register.cpp
@@ -36,27 +36,27 @@ class CommandNSConfirm : public Command
source.Reply(_("Nick \002%s\002 is already confirmed."), na->nick.c_str());
else
{
- na->nc->Shrink("UNCONFIRMED");
+ na->nc->Shrink<bool>("UNCONFIRMED");
Log(LOG_ADMIN, source, this) << "to confirm nick " << na->nick << " (" << na->nc->display << ")";
source.Reply(_("Nick \002%s\002 has been confirmed."), na->nick.c_str());
}
}
else if (source.nc)
{
- Anope::string *code = source.nc->GetExt<ExtensibleItemClass<Anope::string> *>("ns_register_passcode");
+ Anope::string *code = source.nc->GetExt<Anope::string>("passcode");
if (code != NULL && *code == passcode)
{
NickCore *nc = source.nc;
- nc->Shrink("ns_register_passcode");
+ nc->Shrink<Anope::string>("passcode");
Log(LOG_COMMAND, source, this) << "to confirm their email";
source.Reply(_("Your email address of \002%s\002 has been confirmed."), source.nc->email.c_str());
- nc->Shrink("UNCONFIRMED");
+ nc->Shrink<bool>("UNCONFIRMED");
if (source.GetUser())
{
IRCD->SendLogin(source.GetUser());
const NickAlias *na = NickAlias::Find(source.GetNick());
- if (!Config->GetBlock("options")->Get<bool>("nonicknameownership") && na != NULL && na->nc == source.GetAccount() && na->nc->HasExt("UNCONFIRMED") == false)
+ if (!Config->GetBlock("options")->Get<bool>("nonicknameownership") && na != NULL && na->nc == source.GetAccount() && !na->nc->HasExt("UNCONFIRMED"))
source.GetUser()->SetMode(source.service, "REGISTERED");
}
}
@@ -207,12 +207,12 @@ class CommandNSRegister : public Command
if (nsregister.equals_ci("admin"))
{
- nc->ExtendMetadata("UNCONFIRMED");
+ nc->Extend<bool>("UNCONFIRMED");
source.Reply(_("All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."));
}
else if (nsregister.equals_ci("mail"))
{
- nc->ExtendMetadata("UNCONFIRMED");
+ nc->Extend<bool>("UNCONFIRMED");
if (SendRegmail(u, na, source.service))
{
time_t unconfirmed_expire = Config->GetModule("nickserv")->Get<time_t>("unconfirmedexpire", "1d");
@@ -292,7 +292,7 @@ class CommandNSResend : public Command
if (na == NULL)
source.Reply(NICK_NOT_REGISTERED);
- else if (na->nc != source.GetAccount() || source.nc->HasExt("UNCONFIRMED") == false)
+ else if (na->nc != source.GetAccount() || !source.nc->HasExt("UNCONFIRMED"))
source.Reply(_("Your account is already confirmed."));
else
{
@@ -336,23 +336,55 @@ class NSRegister : public Module
CommandNSConfirm commandnsconfirm;
CommandNSResend commandnsrsend;
+ PrimitiveExtensibleItem<bool> unconfirmed;
+ PrimitiveExtensibleItem<Anope::string> passcode;
+
public:
NSRegister(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsregister(this), commandnsconfirm(this), commandnsrsend(this)
+ commandnsregister(this), commandnsconfirm(this), commandnsrsend(this), unconfirmed(this, "UNCONFIRMED"),
+ passcode(this, "passcode")
{
if (Config->GetModule(this)->Get<const Anope::string>("registration").equals_ci("disable"))
throw ModuleException("Module " + this->name + " will not load with registration disabled.");
}
+
+ void OnNickIdentify(User *u) anope_override
+ {
+ BotInfo *NickServ;
+ if (unconfirmed.HasExt(u->Account()) && (NickServ = Config->GetClient("NickServ")))
+ {
+ const Anope::string &nsregister = Config->GetModule(this)->Get<const Anope::string>("registration");
+ if (nsregister.equals_ci("admin"))
+ u->SendMessage(NickServ, _("All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."));
+ else
+ u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered."));
+ const NickAlias *this_na = NickAlias::Find(u->Account()->display);
+ time_t time_registered = Anope::CurTime - this_na->time_registered;
+ time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
+ if (unconfirmed_expire > time_registered)
+ u->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), Anope::Duration(unconfirmed_expire - time_registered).c_str());
+ }
+ }
+
+ void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ {
+ if (unconfirmed.HasExt(na->nc))
+ {
+ time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
+ if (unconfirmed_expire && Anope::CurTime - na->time_registered >= unconfirmed_expire)
+ expire = true;
+ }
+ }
};
static bool SendRegmail(User *u, const NickAlias *na, const BotInfo *bi)
{
NickCore *nc = na->nc;
- Anope::string *code = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("ns_register_passcode");
- Anope::string codebuf;
+ Anope::string *code = na->nc->GetExt<Anope::string>("passcode");
if (code == NULL)
{
+ code = na->nc->Extend<Anope::string>("passcode");
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
@@ -362,22 +394,19 @@ static bool SendRegmail(User *u, const NickAlias *na, const BotInfo *bi)
};
int idx, min = 1, max = 62;
for (idx = 0; idx < 9; ++idx)
- codebuf += chars[1 + static_cast<int>((static_cast<float>(max - min)) * static_cast<uint16_t>(rand()) / 65536.0) + min];
- nc->Extend("ns_register_passcode", new ExtensibleItemClass<Anope::string>(codebuf));
+ *code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * static_cast<uint16_t>(rand()) / 65536.0) + min];
}
- else
- codebuf = *code;
Anope::string subject = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("registration_subject").c_str()),
message = Language::Translate(na->nc, Config->GetBlock("mail")->Get<const Anope::string>("registration_message").c_str());
subject = subject.replace_all_cs("%n", na->nick);
subject = subject.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
- subject = subject.replace_all_cs("%c", codebuf);
+ subject = subject.replace_all_cs("%c", *code);
message = message.replace_all_cs("%n", na->nick);
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
- message = message.replace_all_cs("%c", codebuf);
+ message = message.replace_all_cs("%c", *code);
return Mail::Send(u, nc, bi, subject, message);
}
diff --git a/modules/commands/ns_resetpass.cpp b/modules/commands/ns_resetpass.cpp
index 9b15e53ac..871864b6d 100644
--- a/modules/commands/ns_resetpass.cpp
+++ b/modules/commands/ns_resetpass.cpp
@@ -53,7 +53,7 @@ class CommandNSResetPass : public Command
}
};
-struct ResetInfo : ExtensibleItem
+struct ResetInfo
{
Anope::string code;
time_t time;
@@ -62,21 +62,14 @@ struct ResetInfo : ExtensibleItem
class NSResetPass : public Module
{
CommandNSResetPass commandnsresetpass;
+ PrimitiveExtensibleItem<ResetInfo> reset;
public:
NSResetPass(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnsresetpass(this)
+ commandnsresetpass(this), reset(this, "reset")
{
if (!Config->GetBlock("mail")->Get<bool>("usemail"))
throw ModuleException("Not using mail.");
-
-
- }
-
- ~NSResetPass()
- {
- for (nickcore_map::const_iterator it = NickCoreList->begin(), it_end = NickCoreList->end(); it != it_end; ++it)
- it->second->Shrink("ns_resetpass");
}
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) anope_override
@@ -85,24 +78,23 @@ class NSResetPass : public Module
{
NickAlias *na = NickAlias::Find(params[0]);
- ResetInfo *ri = na ? na->nc->GetExt<ResetInfo *>("ns_resetpass") : NULL;
+ ResetInfo *ri = na ? reset.Get(na->nc) : NULL;
if (na && ri)
{
NickCore *nc = na->nc;
const Anope::string &passcode = params[1];
if (ri->time < Anope::CurTime - 3600)
{
- nc->Shrink("ns_resetpass");
+ reset.Unset(nc);
source.Reply(_("Your password reset request has expired."));
}
else if (passcode.equals_cs(ri->code))
{
- nc->Shrink("ns_resetpass");
+ reset.Unset(nc);
+ nc->Shrink<bool>("UNCONFIRMED");
Log(LOG_COMMAND, source, &commandnsresetpass) << "confirmed RESETPASS to forcefully identify as " << na->nick;
- nc->Shrink("UNCONFIRMED");
-
if (source.GetUser())
{
source.GetUser()->Identify(na);
@@ -147,13 +139,11 @@ static bool SendResetEmail(User *u, const NickAlias *na, const BotInfo *bi)
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
message = message.replace_all_cs("%c", passcode);
- ResetInfo *ri = new ResetInfo;
+ ResetInfo *ri = na->nc->Extend<ResetInfo>("reset");
ri->code = passcode;
ri->time = Anope::CurTime;
- NickCore *nc = na->nc;
- nc->Extend("ns_resetpass", ri);
- return Mail::Send(u, nc, bi, subject, message);
+ return Mail::Send(u, na->nc, bi, subject, message);
}
MODULE_INIT(NSResetPass)
diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp
index 7b0de5565..08cf3966a 100644
--- a/modules/commands/ns_set.cpp
+++ b/modules/commands/ns_set.cpp
@@ -191,8 +191,6 @@ class CommandNSSASetPassword : public Command
source.Reply(_("Password for \002%s\002 changed to \002%s\002."), nc->display.c_str(), tmp_pass.c_str());
else
source.Reply(_("Password for \002%s\002 changed."), nc->display.c_str());
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &) anope_override
@@ -231,13 +229,13 @@ class CommandNSSetAutoOp : public Command
if (param.equals_ci("ON"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable autoop for " << na->nc->display;
- nc->ExtendMetadata("AUTOOP");
+ nc->Extend<bool>("AUTOOP");
source.Reply(_("Services will from now on set status modes on %s in channels."), nc->display.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable autoop for " << na->nc->display;
- nc->Shrink("AUTOOP");
+ nc->Shrink<bool>("AUTOOP");
source.Reply(_("Services will no longer set status modes on %s in channels."), nc->display.c_str());
}
else
@@ -313,19 +311,17 @@ class CommandNSSetChanstats : public Command
if (param.equals_ci("ON"))
{
Log(na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable chanstats for " << na->nc->display;
- na->nc->ExtendMetadata("STATS");
+ na->nc->Extend<bool>("NS_STATS");
source.Reply(_("Chanstat statistics are now enabled for your nick."));
}
else if (param.equals_ci("OFF"))
{
Log(na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable chanstats for " << na->nc->display;
- na->nc->Shrink("STATS");
+ na->nc->Shrink<bool>("NS_STATS");
source.Reply(_("Chanstat statistics are now disabled for your nick."));
}
else
this->OnSyntaxError(source, "CHANSTATS");
-
- return;
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
@@ -446,7 +442,7 @@ class CommandNSSASetDisplay : public CommandNSSetDisplay
class CommandNSSetEmail : public Command
{
- static bool SendConfirmMail(User *u, const BotInfo *bi)
+ static bool SendConfirmMail(User *u, const BotInfo *bi, const Anope::string &new_email)
{
int chars[] = {
' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
@@ -460,7 +456,9 @@ class CommandNSSetEmail : public Command
for (idx = 0; idx < 9; ++idx)
code += chars[1 + static_cast<int>((static_cast<float>(max - min)) * static_cast<uint16_t>(rand()) / 65536.0) + min];
- u->Account()->Extend("ns_set_email_passcode", new ExtensibleItemClass<Anope::string>(code));
+ std::pair<Anope::string, Anope::string> *n = u->Account()->Extend<std::pair<Anope::string, Anope::string> >("ns_set_email");
+ n->first = new_email;
+ n->second = code;
Anope::string subject = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_subject"),
message = Config->GetBlock("mail")->Get<const Anope::string>("emailchange_message");
@@ -473,7 +471,11 @@ class CommandNSSetEmail : public Command
message = message.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
message = message.replace_all_cs("%c", code);
- return Mail::Send(u, u->Account(), bi, subject, message);
+ Anope::string old = u->Account()->email;
+ u->Account()->email = new_email;
+ bool b = Mail::Send(u, u->Account(), bi, subject, message);
+ u->Account()->email = old;
+ return b;
}
public:
@@ -516,12 +518,8 @@ class CommandNSSetEmail : public Command
if (!param.empty() && Config->GetModule("nickserv")->Get<bool>("forceemail", "yes") && !source.IsServicesOper())
{
- source.nc->Extend("ns_set_email", new ExtensibleItemClass<Anope::string>(param));
- Anope::string old = source.nc->email;
- source.nc->email = param;
- if (SendConfirmMail(source.GetUser(), source.service))
+ if (SendConfirmMail(source.GetUser(), source.service, param))
source.Reply(_("A confirmation e-mail has been sent to \002%s\002. Follow the instructions in it to change your e-mail address."), param.c_str());
- source.nc->email = old;
}
else
{
@@ -579,212 +577,6 @@ class CommandNSSASetEmail : public CommandNSSetEmail
}
};
-class CommandNSSetGreet : public Command
-{
- public:
- CommandNSSetGreet(Module *creator, const Anope::string &sname = "nickserv/set/greet", size_t min = 0) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Associate a greet message with your nickname"));
- this->SetSyntax(_("\037message\037"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (!param.empty())
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the greet of " << nc->display;
- nc->greet = param;
- source.Reply(_("Greet message for \002%s\002 changed to \002%s\002."), nc->display.c_str(), nc->greet.c_str());
- }
- else
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to unset the greet of " << nc->display;
- nc->greet.clear();
- source.Reply(_("Greet message for \002%s\002 unset."), nc->display.c_str());
- }
-
- return;
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params.size() > 0 ? params[0] : "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Makes the given message the greet of your nickname, that\n"
- "will be displayed when joining a channel that has GREET\n"
- "option enabled, provided that you have the necessary\n"
- "access on it."));
- return true;
- }
-};
-
-class CommandNSSASetGreet : public CommandNSSetGreet
-{
- public:
- CommandNSSASetGreet(Module *creator) : CommandNSSetGreet(creator, "nickserv/saset/greet", 1)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 \037message\037"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params.size() > 1 ? params[1] : "");
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Makes the given message the greet of the nickname, that\n"
- "will be displayed when joining a channel that has GREET\n"
- "option enabled, provided that the user has the necessary\n"
- "access on it."));
- return true;
- }
-};
-
-class CommandNSSetHide : public Command
-{
- public:
- CommandNSSetHide(Module *creator, const Anope::string &sname = "nickserv/set/hide", size_t min = 2) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Hide certain pieces of nickname information"));
- this->SetSyntax(_("{EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param, const Anope::string &arg)
- {
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- Anope::string onmsg, offmsg, flag;
-
- if (param.equals_ci("EMAIL"))
- {
- flag = "HIDE_EMAIL";
- onmsg = _("The E-mail address of \002%s\002 will now be hidden from %s INFO displays.");
- offmsg = _("The E-mail address of \002%s\002 will now be shown in %s INFO displays.");
- }
- else if (param.equals_ci("USERMASK"))
- {
- flag = "HIDE_MASK";
- onmsg = _("The last seen user@host mask of \002%s\002 will now be hidden from %s INFO displays.");
- offmsg = _("The last seen user@host mask of \002%s\002 will now be shown in %s INFO displays.");
- }
- else if (param.equals_ci("STATUS"))
- {
- flag = "HIDE_STATUS";
- onmsg = _("The services access status of \002%s\002 will now be hidden from %s INFO displays.");
- offmsg = _("The services access status of \002%s\002 will now be shown in %s INFO displays.");
- }
- else if (param.equals_ci("QUIT"))
- {
- flag = "HIDE_QUIT";
- onmsg = _("The last quit message of \002%s\002 will now be hidden from %s INFO displays.");
- offmsg = _("The last quit message of \002%s\002 will now be shown in %s INFO displays.");
- }
- else
- {
- this->OnSyntaxError(source, "HIDE");
- return;
- }
-
- if (arg.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param << " to " << arg << " for " << nc->display;
- nc->ExtendMetadata(flag);
- source.Reply(onmsg.c_str(), nc->display.c_str(), source.service->nick.c_str());
- }
- else if (arg.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change hide " << param << " to " << arg << " for " << nc->display;
- nc->Shrink(flag);
- source.Reply(offmsg.c_str(), nc->display.c_str(), source.service->nick.c_str());
- }
- else
- this->OnSyntaxError(source, "HIDE");
-
- return;
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows you to prevent certain pieces of information from\n"
- "being displayed when someone does a %s \002INFO\002 on your\n"
- "nick. You can hide your E-mail address (\002EMAIL\002), last seen\n"
- "user@host mask (\002USERMASK\002), your services access status\n"
- "(\002STATUS\002) and last quit message (\002QUIT\002).\n"
- "The second parameter specifies whether the information should\n"
- "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSASetHide : public CommandNSSetHide
-{
- public:
- CommandNSSASetHide(Module *creator) : CommandNSSetHide(creator, "nickserv/saset/hide", 3)
- {
- this->SetSyntax("\037nickname\037 {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}");
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->ClearSyntax();
- this->Run(source, params[0], params[1], params[2]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Allows you to prevent certain pieces of information from\n"
- "being displayed when someone does a %s \002INFO\002 on the\n"
- "nick. You can hide the E-mail address (\002EMAIL\002), last seen\n"
- "user@host mask (\002USERMASK\002), the services access status\n"
- "(\002STATUS\002) and last quit message (\002QUIT\002).\n"
- "The second parameter specifies whether the information should\n"
- "be displayed (\002OFF\002) or hidden (\002ON\002)."), source.service->nick.c_str());
- return true;
- }
-};
-
class CommandNSSetKill : public Command
{
public:
@@ -817,17 +609,17 @@ class CommandNSSetKill : public Command
if (param.equals_ci("ON"))
{
- nc->ExtendMetadata("KILLPROTECT");
- nc->Shrink("KILL_QUICK");
- nc->Shrink("KILL_IMMED");
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill on for " << nc->display;
source.Reply(_("Protection is now \002on\002 for \002%s\002."), nc->display.c_str());
}
else if (param.equals_ci("QUICK"))
{
- nc->ExtendMetadata("KILLPROTECT");
- nc->ExtendMetadata("KILL_QUICK");
- nc->Shrink("KILL_IMMED");
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Extend<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill quick for " << nc->display;
source.Reply(_("Protection is now \002on\002 for \002%s\002, with a reduced delay."), nc->display.c_str());
}
@@ -835,9 +627,9 @@ class CommandNSSetKill : public Command
{
if (Config->GetModule(this->owner)->Get<bool>("allowkillimmed"))
{
- nc->ExtendMetadata("KILLPROTECT");
- nc->ExtendMetadata("KILL_IMMED");
- nc->Shrink("KILL_QUICK");
+ nc->Extend<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Extend<bool>("KILL_IMMED");
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to set kill immed for " << nc->display;
source.Reply(_("Protection is now \002on\002 for \002%s\002, with no delay."), nc->display.c_str());
}
@@ -846,9 +638,9 @@ class CommandNSSetKill : public Command
}
else if (param.equals_ci("OFF"))
{
- nc->Shrink("KILLPROTECT");
- nc->Shrink("KILL_QUICK");
- nc->Shrink("KILL_IMMED");
+ nc->Shrink<bool>("KILLPROTECT");
+ nc->Shrink<bool>("KILL_QUICK");
+ nc->Shrink<bool>("KILL_IMMED");
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable kill for " << nc->display;
source.Reply(_("Protection is now \002off\002 for \002%s\002."), nc->display.c_str());
}
@@ -1053,19 +845,17 @@ class CommandNSSetMessage : public Command
if (param.equals_ci("ON"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable " << source.command << " for " << nc->display;
- nc->ExtendMetadata("MSG");
+ nc->Extend<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002messages\002."), nc->display.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable " << source.command << " for " << nc->display;
- nc->Shrink("MSG");
+ nc->Shrink<bool>("MSG");
source.Reply(_("Services will now reply to \002%s\002 with \002notices\002."), nc->display.c_str());
}
else
this->OnSyntaxError(source, "MSG");
-
- return;
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
@@ -1115,95 +905,6 @@ class CommandNSSASetMessage : public CommandNSSetMessage
}
};
-class CommandNSSetPrivate : public Command
-{
- public:
- CommandNSSetPrivate(Module *creator, const Anope::string &sname = "nickserv/set/private", size_t min = 1) : Command(creator, sname, min, min + 1)
- {
- this->SetDesc(_("Prevent the nickname from appearing in the LIST command"));
- this->SetSyntax(_("{ON | OFF}"));
- }
-
- void Run(CommandSource &source, const Anope::string &user, const Anope::string &param)
- {
- const NickAlias *na = NickAlias::Find(user);
- if (!na)
- {
- source.Reply(NICK_X_NOT_REGISTERED, user.c_str());
- return;
- }
- NickCore *nc = na->nc;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnSetNickOption, MOD_RESULT, (source, this, nc, param));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- if (param.equals_ci("ON"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable private for " << nc->display;
- nc->ExtendMetadata("PRIVATE");
- source.Reply(_("Private option is now \002on\002 for \002%s\002."), nc->display.c_str());
- }
- else if (param.equals_ci("OFF"))
- {
- Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable private for " << nc->display;
- nc->Shrink("PRIVATE");
- source.Reply(_("Private option is now \002off\002 for \002%s\002."), nc->display.c_str());
- }
- else
- this->OnSyntaxError(source, "PRIVATE");
-
- return;
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, source.nc->display, params[0]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns %s's privacy option on or off for your nick.\n"
- "With \002PRIVATE\002 set, your nickname will not appear in\n"
- "nickname lists generated with %s's \002LIST\002 command.\n"
- "(However, anyone who knows your nickname can still get\n"
- "information on it using the \002INFO\002 command.)"),
- source.service->nick.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
-class CommandNSSASetPrivate : public CommandNSSetPrivate
-{
- public:
- CommandNSSASetPrivate(Module *creator) : CommandNSSetPrivate(creator, "nickserv/saset/private", 2)
- {
- this->ClearSyntax();
- this->SetSyntax(_("\037nickname\037 {ON | OFF}"));
- }
-
- void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
- {
- this->Run(source, params[0], params[1]);
- }
-
- bool OnHelp(CommandSource &source, const Anope::string &) anope_override
- {
- this->SendSyntax(source);
- source.Reply(" ");
- source.Reply(_("Turns %s's privacy option on or off for the nick.\n"
- "With \002PRIVATE\002 set, the nickname will not appear in\n"
- "nickname lists generated with %s's \002LIST\002 command.\n"
- "(However, anyone who knows the nickname can still get\n"
- "information on it using the \002INFO\002 command.)"),
- source.service->nick.c_str(), source.service->nick.c_str());
- return true;
- }
-};
-
class CommandNSSetSecure : public Command
{
public:
@@ -1231,13 +932,13 @@ class CommandNSSetSecure : public Command
if (param.equals_ci("ON"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to enable secure for " << nc->display;
- nc->ExtendMetadata("SECURE");
+ nc->Extend<bool>("NS_SECURE");
source.Reply(_("Secure option is now \002on\002 for \002%s\002."), nc->display.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to disable secure for " << nc->display;
- nc->Shrink("SECURE");
+ nc->Shrink<bool>("NS_SECURE");
source.Reply(_("Secure option is now \002off\002 for \002%s\002."), nc->display.c_str());
}
else
@@ -1316,13 +1017,13 @@ class CommandNSSASetNoexpire : public Command
if (param.equals_ci("ON"))
{
Log(LOG_ADMIN, source, this) << "to enable noexpire " << na->nc->display;
- na->ExtendMetadata("NO_EXPIRE");
+ na->Extend<bool>("NS_NO_EXPIRE");
source.Reply(_("Nick %s \002will not\002 expire."), na->nick.c_str());
}
else if (param.equals_ci("OFF"))
{
Log(LOG_ADMIN, source, this) << "to disable noexpire " << na->nc->display;
- na->Shrink("NO_EXPIRE");
+ na->Shrink<bool>("NS_NO_EXPIRE");
source.Reply(_("Nick %s \002will\002 expire."), na->nick.c_str());
}
else
@@ -1355,12 +1056,6 @@ class NSSet : public Module
CommandNSSetEmail commandnssetemail;
CommandNSSASetEmail commandnssasetemail;
-
- CommandNSSetGreet commandnssetgreet;
- CommandNSSASetGreet commandnssasetgreet;
-
- CommandNSSetHide commandnssethide;
- CommandNSSASetHide commandnssasethide;
CommandNSSetKill commandnssetkill;
CommandNSSASetKill commandnssasetkill;
@@ -1374,14 +1069,17 @@ class NSSet : public Module
CommandNSSetPassword commandnssetpassword;
CommandNSSASetPassword commandnssasetpassword;
- CommandNSSetPrivate commandnssetprivate;
- CommandNSSASetPrivate commandnssasetprivate;
-
CommandNSSetSecure commandnssetsecure;
CommandNSSASetSecure commandnssasetsecure;
CommandNSSASetNoexpire commandnssasetnoexpire;
+ SerializableExtensibleItem<bool> autoop, chanstats, killprotect, kill_quick, kill_immed,
+ message, secure, noexpire;
+
+ /* email, passcode */
+ PrimitiveExtensibleItem<std::pair<Anope::string, Anope::string > > ns_set_email;
+
public:
NSSet(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandnsset(this), commandnssaset(this),
@@ -1389,15 +1087,18 @@ class NSSet : public Module
commandnssetchanstats(this), commandnssasetchanstats(this),
commandnssetdisplay(this), commandnssasetdisplay(this),
commandnssetemail(this), commandnssasetemail(this),
- commandnssetgreet(this), commandnssasetgreet(this),
- commandnssethide(this), commandnssasethide(this),
commandnssetkill(this), commandnssasetkill(this),
commandnssetlanguage(this), commandnssasetlanguage(this),
commandnssetmessage(this), commandnssasetmessage(this),
commandnssetpassword(this), commandnssasetpassword(this),
- commandnssetprivate(this), commandnssasetprivate(this),
commandnssetsecure(this), commandnssasetsecure(this),
- commandnssasetnoexpire(this)
+ commandnssasetnoexpire(this),
+
+ autoop(this, "AUTOOP"), chanstats(this, "NS_STATS"), killprotect(this, "KILLPROTECT"),
+ kill_quick(this, "KILL_QUICK"), kill_immed(this, "KILL_IMMED"), message(this, "MSG"),
+ secure(this, "NS_SECURE"), noexpire(this, "NS_NO_EXPIRE"),
+
+ ns_set_email(this, "ns_set_email")
{
}
@@ -1408,16 +1109,15 @@ class NSSet : public Module
if (command->name == "nickserv/confirm" && !params.empty() && uac)
{
- Anope::string *new_email = uac->GetExt<ExtensibleItemClass<Anope::string> *>("ns_set_email"), *passcode = uac->GetExt<ExtensibleItemClass<Anope::string> *>("ns_set_email_passcode");
- if (new_email && passcode)
+ std::pair<Anope::string, Anope::string> *n = ns_set_email.Get(uac);
+ if (n)
{
- if (params[0] == *passcode)
+ if (params[0] == n->second)
{
- uac->email = *new_email;
+ uac->email = n->first;
Log(LOG_COMMAND, source, command) << "to confirm their email address change to " << uac->email;
source.Reply(_("Your email address has been changed to \002%s\002."), uac->email.c_str());
- uac->Shrink("ns_set_email");
- uac->Shrink("ns_set_email_passcode");
+ ns_set_email.Unset(uac);
return EVENT_STOP;
}
}
@@ -1431,9 +1131,34 @@ class NSSet : public Module
if (chan->ci)
{
/* Only give modes if autoop is set */
- give_modes &= !user->Account() || user->Account()->HasExt("AUTOOP");
+ give_modes &= !user->Account() || autoop.HasExt(user->Account());
}
}
+
+ void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
+ {
+ if (noexpire.HasExt(na))
+ expire = false;
+ }
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ {
+ if (!show_hidden)
+ return;
+
+ if (killprotect.HasExt(na->nc))
+ info.AddOption(_("Protection"));
+ if (secure.HasExt(na->nc))
+ info.AddOption(_("Security"));
+ if (message.HasExt(na->nc))
+ info.AddOption(_("Message mode"));
+ if (autoop.HasExt(na->nc))
+ info.AddOption(_("Auto-op"));
+ if (chanstats.HasExt(na->nc))
+ info.AddOption(_("Chanstats"));
+ if (noexpire.HasExt(na->nc))
+ info.AddOption(_("No expire"));
+ }
};
MODULE_INIT(NSSet)
diff --git a/modules/commands/ns_set_misc.cpp b/modules/commands/ns_set_misc.cpp
index 15fb0ed33..5dfba99cb 100644
--- a/modules/commands/ns_set_misc.cpp
+++ b/modules/commands/ns_set_misc.cpp
@@ -11,14 +11,24 @@
#include "module.h"
+static Module *me;
+
static std::map<Anope::string, Anope::string> descriptions;
-struct NSMiscData : ExtensibleItem, Serializable
+struct NSMiscData;
+static Anope::map<ExtensibleItem<NSMiscData> *> items;
+static ExtensibleItem<NSMiscData> *GetItem(const Anope::string &name);
+
+struct NSMiscData : Serializable
{
Serialize::Reference<NickCore> nc;
Anope::string name;
Anope::string data;
+ NSMiscData(Extensible *obj) : Serializable("NSMiscData"), nc(anope_dynamic_static_cast<NickCore *>(obj))
+ {
+ }
+
NSMiscData(NickCore *ncore, const Anope::string &n, const Anope::string &d) : Serializable("NSMiscData"), nc(ncore), name(n), data(d)
{
}
@@ -52,14 +62,27 @@ struct NSMiscData : ExtensibleItem, Serializable
}
else
{
- d = new NSMiscData(nc, sname, sdata);
- nc->Extend(sname, d);
+ ExtensibleItem<NSMiscData> *item = GetItem(sname);
+ if (item)
+ d = item->Set(nc, NSMiscData(nc, sname, sdata));
}
return d;
}
};
+static ExtensibleItem<NSMiscData> *GetItem(const Anope::string &name)
+{
+ ExtensibleItem<NSMiscData>* &it = items[name];
+ if (!it)
+ try
+ {
+ it = new ExtensibleItem<NSMiscData>(me, name);
+ }
+ catch (const ModuleException &) { }
+ return it;
+}
+
static Anope::string GetAttribute(const Anope::string &command)
{
size_t sp = command.rfind(' ');
@@ -93,16 +116,20 @@ class CommandNSSetMisc : public Command
Anope::string scommand = GetAttribute(source.command);
Anope::string key = "ns_set_misc:" + scommand;
- nc->Shrink(key);
+ ExtensibleItem<NSMiscData> *item = GetItem(key);
+ if (item == NULL)
+ return;
+
if (!param.empty())
{
- nc->Extend(key, new NSMiscData(nc, key, param));
+ item->Set(nc, NSMiscData(nc, key, param));
source.Reply(CHAN_SETTING_CHANGED, scommand.c_str(), nc->display.c_str(), param.c_str());
}
else
+ {
+ item->Unset(nc);
source.Reply(CHAN_SETTING_UNSET, scommand.c_str(), nc->display.c_str());
-
- return;
+ }
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
@@ -155,6 +182,7 @@ class NSSetMisc : public Module
NSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
nsmiscdata_type("NSMiscData", NSMiscData::Unserialize), commandnssetmisc(this), commandnssasetmisc(this)
{
+ me = this;
}
void OnReload(Configuration::Conf *conf) anope_override
@@ -182,17 +210,14 @@ class NSSetMisc : public Module
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool ShowHidden) anope_override
{
- std::deque<Anope::string> list;
- na->nc->GetExtList(list);
-
- for (unsigned i = 0; i < list.size(); ++i)
+ Anope::map<ExtensibleItem<NSMiscData> *> items;
+ for (Anope::map<ExtensibleItem<NSMiscData> *>::iterator it = items.begin(); it != items.end(); ++it)
{
- if (list[i].find("ns_set_misc:") != 0)
- continue;
+ ExtensibleItem<NSMiscData> *e = it->second;
+ NSMiscData *data = e->Get(na->nc);
- NSMiscData *data = na->nc->GetExt<NSMiscData *>(list[i]);
- if (data)
- info[list[i].substr(12).replace_all_cs("_", " ")] = data->data;
+ if (data != NULL)
+ info[e->name.substr(12).replace_all_cs("_", " ")] = data->data;
}
}
};
diff --git a/modules/commands/ns_suspend.cpp b/modules/commands/ns_suspend.cpp
index 0db7cd951..76c195a34 100644
--- a/modules/commands/ns_suspend.cpp
+++ b/modules/commands/ns_suspend.cpp
@@ -10,9 +10,48 @@
*/
#include "module.h"
+#include "modules/ns_suspend.h"
static ServiceReference<NickServService> nickserv("NickServService", "NickServ");
+struct NSSuspendInfoImpl : NSSuspendInfo, Serializable
+{
+ NSSuspendInfoImpl(Extensible *) : Serializable("NSSuspendInfo") { }
+
+ void Serialize(Serialize::Data &data) const anope_override
+ {
+ data["nick"] << nick;
+ data["by"] << by;
+ data["reason"] << reason;
+ data["time"] << when;
+ data["expires"] << expires;
+ }
+
+ static Serializable* Unserialize(Serializable *obj, Serialize::Data &data)
+ {
+ Anope::string snick;
+ data["nick"] >> snick;
+
+ NSSuspendInfoImpl *si;
+ if (obj)
+ si = anope_dynamic_static_cast<NSSuspendInfoImpl *>(obj);
+ else
+ {
+ NickAlias *na = NickAlias::Find(snick);
+ if (!na)
+ return NULL;
+ si = na->Extend<NSSuspendInfoImpl>("SUSPENDED");
+ data["nick"] >> si->nick;
+ }
+
+ data["bi"] >> si->by;
+ data["reason"] >> si->reason;
+ data["time"] >> si->when;
+ data["expires"] >> si->expires;
+ return si;
+ }
+};
+
class CommandNSSuspend : public Command
{
public:
@@ -60,18 +99,12 @@ class CommandNSSuspend : public Command
NickCore *nc = na->nc;
- nc->ExtendMetadata("SUSPENDED");
- nc->ExtendMetadata("SECURE");
- nc->Shrink("KILLPROTECT");
- nc->Shrink("KILL_QUICK");
- nc->Shrink("KILL_IMMED");
-
- nc->ExtendMetadata("suspend:by", source.GetNick());
- if (!reason.empty())
- nc->ExtendMetadata("suspend:reason", reason);
- if (expiry_secs > 0)
- nc->ExtendMetadata("suspend:expire", stringify(Anope::CurTime + expiry_secs));
- nc->ExtendMetadata("suspend:time", stringify(Anope::CurTime));
+ NSSuspendInfo *si = nc->Extend<NSSuspendInfo>("SUSPENDED");
+ si->nick = nc->display;
+ si->by = source.GetNick();
+ si->reason = reason;
+ si->when = Anope::CurTime;
+ si->expires = expiry_secs ? expiry_secs + Anope::CurTime : 0;
for (unsigned i = 0; i < nc->aliases->size(); ++i)
{
@@ -81,7 +114,7 @@ class CommandNSSuspend : public Command
{
na2->last_quit = reason;
- User *u2 = User::Find(na2->nick);
+ User *u2 = User::Find(na2->nick, true);
if (u2)
{
u2->Logout();
@@ -141,18 +174,12 @@ class CommandNSUnSuspend : public Command
return;
}
- na->nc->Shrink("SUSPENDED");
- na->nc->Shrink("suspend:expire");
- na->nc->Shrink("suspend:by");
- na->nc->Shrink("suspend:reason");
- na->nc->Shrink("suspend:time");
+ na->nc->Shrink<NSSuspendInfo>("SUSPENDED");
Log(LOG_ADMIN, source, this) << "for " << na->nick;
source.Reply(_("Nick %s is now released."), nick.c_str());
FOREACH_MOD(OnNickUnsuspended, (na));
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -168,55 +195,61 @@ class NSSuspend : public Module
{
CommandNSSuspend commandnssuspend;
CommandNSUnSuspend commandnsunsuspend;
+ ExtensibleItem<NSSuspendInfoImpl> suspend;
+ Serialize::Type suspend_type;
public:
NSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandnssuspend(this), commandnsunsuspend(this)
+ commandnssuspend(this), commandnsunsuspend(this), suspend(this, "SUSPENDED"),
+ suspend_type("NSSuspendInfo", NSSuspendInfoImpl::Unserialize)
{
}
void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
{
- if (na->nc->HasExt("SUSPENDED"))
+ NSSuspendInfo *s = suspend.Get(na->nc);
+ if (s)
{
- Anope::string *by = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:by"), *reason = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:reason"), *t = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:time");
info["Suspended"] = "This nickname is \2suspended\2.";
- if (by)
- info["Suspended by"] = *by;
- if (reason)
- info["Suspend reason"] = *reason;
- if (t)
- info["Suspended on"] = Anope::strftime(convertTo<time_t>(*t), source.GetAccount(), true);
+ if (!s->by.empty())
+ info["Suspended by"] = s->by;
+ if (!s->reason.empty())
+ info["Suspend reason"] = s->reason;
+ if (s->when)
+ info["Suspended on"] = Anope::strftime(s->when, source.GetAccount(), true);
+ if (s->expires)
+ info["Suspended expires"] = Anope::strftime(s->expires, source.GetAccount(), true);
}
}
void OnPreNickExpire(NickAlias *na, bool &expire) anope_override
{
- if (!na->nc->HasExt("SUSPENDED"))
+ NSSuspendInfo *s = suspend.Get(na->nc);
+ if (!s)
return;
expire = false;
- Anope::string *str = na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("suspend:expire");
- if (str == NULL)
+ if (!s->expires)
return;
- try
+ if (s->expires < Anope::CurTime)
{
- time_t when = convertTo<time_t>(*str);
- if (when < Anope::CurTime)
- {
- na->last_seen = Anope::CurTime;
- na->nc->Shrink("SUSPENDED");
- na->nc->Shrink("suspend:expire");
- na->nc->Shrink("suspend:by");
- na->nc->Shrink("suspend:reason");
- na->nc->Shrink("suspend:time");
-
- Log(LOG_NORMAL, "expire", Config->GetClient("NickServ")) << "Expiring suspend for " << na->nick;
- }
+ na->last_seen = Anope::CurTime;
+ suspend.Unset(na->nc);
+
+ Log(LOG_NORMAL, "expire", Config->GetClient("NickServ")) << "Expiring suspend for " << na->nick;
}
- catch (const ConvertException &) { }
+ }
+
+ EventReturn OnNickValidate(User *u, NickAlias *na) anope_override
+ {
+ NSSuspendInfo *s = suspend.Get(na->nc);
+ if (!s)
+ return EVENT_CONTINUE;
+
+ u->SendMessage(Config->GetClient("NickServ"), NICK_X_SUSPENDED, u->nick.c_str());
+ return EVENT_STOP;
}
};
diff --git a/modules/commands/os_defcon.cpp b/modules/commands/os_defcon.cpp
index 8bea10d0f..58d18558b 100644
--- a/modules/commands/os_defcon.cpp
+++ b/modules/commands/os_defcon.cpp
@@ -407,13 +407,11 @@ class OSDefcon : public Module
this->ParseModeString();
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &, const Anope::string &mname, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &param) anope_override
{
- ChannelMode *cm = ModeManager::FindChannelModeByName(mname);
-
- if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOff.count(mname))
+ if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOff.count(mode->name))
{
- c->RemoveMode(Config->GetClient("OperServ"), cm, param);
+ c->RemoveMode(Config->GetClient("OperServ"), mode, param);
return EVENT_STOP;
}
@@ -421,18 +419,16 @@ class OSDefcon : public Module
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &, const Anope::string &mname, const Anope::string &) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &) anope_override
{
- ChannelMode *cm = ModeManager::FindChannelModeByName(mname);
-
- if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && cm && DConfig.DefConModesOn.count(mname))
+ if (DConfig.Check(DEFCON_FORCE_CHAN_MODES) && DConfig.DefConModesOn.count(mode->name))
{
Anope::string param;
- if (DConfig.GetDefConParam(mname, param))
- c->SetMode(Config->GetClient("OperServ"), cm, param);
+ if (DConfig.GetDefConParam(mode->name, param))
+ c->SetMode(Config->GetClient("OperServ"), mode, param);
else
- c->SetMode(Config->GetClient("OperServ"), cm);
+ c->SetMode(Config->GetClient("OperServ"), mode);
return EVENT_STOP;
diff --git a/modules/commands/os_login.cpp b/modules/commands/os_login.cpp
index 9d666188a..6c1edecfb 100644
--- a/modules/commands/os_login.cpp
+++ b/modules/commands/os_login.cpp
@@ -31,7 +31,7 @@ class CommandOSLogin : public Command
source.Reply(_("No oper block for your nick."));
else if (o->password.empty())
source.Reply(_("Your oper block doesn't require logging in."));
- else if (u->HasExt("os_login_password_correct"))
+ else if (u->HasExt("os_login"))
source.Reply(_("You are already identified."));
else if (o->password != password)
{
@@ -41,11 +41,9 @@ class CommandOSLogin : public Command
else
{
Log(LOG_ADMIN, source, this) << "and successfully identified to " << source.service->nick;
- u->Extend("os_login_password_correct");
+ u->Extend<bool>("os_login");
source.Reply(_("Password accepted."));
}
-
- return;
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
@@ -80,12 +78,12 @@ class CommandOSLogout : public Command
source.Reply(_("No oper block for your nick."));
else if (o->password.empty())
source.Reply(_("Your oper block doesn't require logging in."));
- else if (!u->HasExt("os_login_password_correct"))
+ else if (!u->HasExt("os_login"))
source.Reply(_("You are not identified."));
else
{
Log(LOG_ADMIN, source, this);
- u->Shrink("os_login_password_correct");
+ u->Shrink<bool>("os_login");
source.Reply(_("You have been logged out."));
}
}
@@ -110,25 +108,20 @@ class OSLogin : public Module
{
CommandOSLogin commandoslogin;
CommandOSLogout commandoslogout;
+ ExtensibleItem<bool> os_login;
public:
OSLogin(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandoslogin(this), commandoslogout(this)
+ commandoslogin(this), commandoslogout(this), os_login(this, "os_login")
{
}
- ~OSLogin()
- {
- for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
- it->second->Shrink("os_login_password_correct");
- }
-
EventReturn IsServicesOper(User *u) anope_override
{
if (!u->Account()->o->password.empty())
{
- if (u->HasExt("os_login_password_correct"))
+ if (os_login.HasExt(u))
return EVENT_ALLOW;
return EVENT_STOP;
}
diff --git a/modules/commands/os_noop.cpp b/modules/commands/os_noop.cpp
index 171b11c94..0b5dc74d9 100644
--- a/modules/commands/os_noop.cpp
+++ b/modules/commands/os_noop.cpp
@@ -35,7 +35,7 @@ class CommandOSNOOP : public Command
{
/* Remove the O:lines */
IRCD->SendSVSNOOP(s, true);
- s->Extend("noop", new ExtensibleItemClass<Anope::string>(source.GetNick()));
+ s->Extend<Anope::string>("noop", source.GetNick());
Log(LOG_ADMIN, source, this) << "SET on " << s->GetName();
source.Reply(_("All operators from \002%s\002 have been removed."), s->GetName().c_str());
@@ -52,7 +52,7 @@ class CommandOSNOOP : public Command
}
else if (cmd.equals_ci("REVOKE"))
{
- s->Shrink("noop");
+ s->Shrink<Anope::string>("noop");
IRCD->SendSVSNOOP(s, false);
Log(LOG_ADMIN, source, this) << "REVOKE on " << s->GetName();
source.Reply(_("All O:lines of \002%s\002 have been reset."), s->GetName().c_str());
@@ -76,25 +76,23 @@ class CommandOSNOOP : public Command
class OSNOOP : public Module
{
CommandOSNOOP commandosnoop;
+ PrimitiveExtensibleItem<Anope::string> noop;
public:
OSNOOP(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
- commandosnoop(this)
+ commandosnoop(this), noop(this, "noop")
{
}
void OnUserModeSet(User *u, const Anope::string &mname) anope_override
{
- if (mname == "OPER" && u->server->HasExt("noop"))
+ Anope::string *setter;
+ if (mname == "OPER" && (setter = noop.Get(u->server)))
{
- Anope::string *setter = u->server->GetExt<ExtensibleItemClass<Anope::string> *>("noop");
- if (setter)
- {
- Anope::string reason = "NOOP command used by " + *setter;
- BotInfo *OperServ = Config->GetClient("OperServ");
- u->Kill(OperServ ? OperServ->nick : "", reason);
- }
+ Anope::string reason = "NOOP command used by " + *setter;
+ BotInfo *OperServ = Config->GetClient("OperServ");
+ u->Kill(OperServ ? OperServ->nick : "", reason);
}
}
};
diff --git a/modules/database/db_old.cpp b/modules/database/db_old.cpp
index 053a49110..10b2d56e7 100644
--- a/modules/database/db_old.cpp
+++ b/modules/database/db_old.cpp
@@ -10,6 +10,9 @@
#include "module.h"
#include "modules/os_session.h"
+#include "modules/bs_kick.h"
+#include "modules/cs_mode.h"
+#include "modules/bs_badwords.h"
#define READ(x) \
if (true) \
@@ -81,13 +84,6 @@ else \
#define OLD_BS_KICK_FLOOD 0x02000000
#define OLD_BS_KICK_REPEAT 0x01000000
-struct ExtensibleItemUint32 : ExtensibleItem
-{
- uint32_t u;
- ExtensibleItemUint32(uint32_t i) : u(i) { }
-};
-
-
static struct mlock_info
{
char c;
@@ -139,12 +135,13 @@ enum
static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status)
{
+ ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
for (unsigned i = 0; i < (sizeof(mlock_infos) / sizeof(mlock_info)); ++i)
if (lock & mlock_infos[i].m)
{
ChannelMode *cm = ModeManager::FindChannelModeByChar(mlock_infos[i].c);
- if (cm)
- ci->SetMLock(cm, status);
+ if (cm && ml)
+ ml->SetMLock(cm, status);
}
}
@@ -448,7 +445,7 @@ static void LoadNicks()
nc->email = buffer;
READ(read_string(buffer, f));
- nc->greet = buffer;
+ nc->Extend<Anope::string>("greet", buffer);
uint32_t uint;
READ(read_uint32(&uint, f));
@@ -459,37 +456,37 @@ static void LoadNicks()
READ(read_uint32(&uint, f));
if (uint & OLD_NI_KILLPROTECT)
- nc->ExtendMetadata("KILLPROTECT");
+ nc->Extend<bool>("KILLPROTECT");
if (uint & OLD_NI_SECURE)
- nc->ExtendMetadata("SECURE");
+ nc->Extend<bool>("NS_SECURE");
if (uint & OLD_NI_MSG)
- nc->ExtendMetadata("MSG");
+ nc->Extend<bool>("MSG");
if (uint & OLD_NI_MEMO_HARDMAX)
- nc->ExtendMetadata("MEMO_HARDMAX");
+ nc->Extend<bool>("MEMO_HARDMAX");
if (uint & OLD_NI_MEMO_SIGNON)
- nc->ExtendMetadata("MEMO_SIGNON");
+ nc->Extend<bool>("MEMO_SIGNON");
if (uint & OLD_NI_MEMO_RECEIVE)
- nc->ExtendMetadata("MEMO_RECEIVE");
+ nc->Extend<bool>("MEMO_RECEIVE");
if (uint & OLD_NI_PRIVATE)
- nc->ExtendMetadata("PRIVATE");
+ nc->Extend<bool>("NS_PRIVATE");
if (uint & OLD_NI_HIDE_EMAIL)
- nc->ExtendMetadata("HIDE_EMAIL");
+ nc->Extend<bool>("HIDE_EMAIL");
if (uint & OLD_NI_HIDE_MASK)
- nc->ExtendMetadata("HIDE_MASK");
+ nc->Extend<bool>("HIDE_MASK");
if (uint & OLD_NI_HIDE_QUIT)
- nc->ExtendMetadata("HIDE_QUIT");
+ nc->Extend<bool>("HIDE_QUIT");
if (uint & OLD_NI_KILL_QUICK)
- nc->ExtendMetadata("KILL_QUICK");
+ nc->Extend<bool>("KILL_QUICK");
if (uint & OLD_NI_KILL_IMMED)
- nc->ExtendMetadata("KILL_IMMED");
+ nc->Extend<bool>("KILL_IMMED");
if (uint & OLD_NI_MEMO_MAIL)
- nc->ExtendMetadata("MEMO_MAIL");
+ nc->Extend<bool>("MEMO_MAIL");
if (uint & OLD_NI_HIDE_STATUS)
- nc->ExtendMetadata("HIDE_STATUS");
+ nc->Extend<bool>("HIDE_STATUS");
if (uint & OLD_NI_SUSPENDED)
- nc->ExtendMetadata("SUSPENDED");
+ nc->Extend<bool>("SUSPENDED");
if (!(uint & OLD_NI_AUTOOP))
- nc->ExtendMetadata("AUTOOP");
+ nc->Extend<bool>("AUTOOP");
uint16_t u16;
READ(read_uint16(&u16, f));
@@ -607,7 +604,7 @@ static void LoadNicks()
na->last_seen = last_seen;
if (tmpu16 & OLD_NS_NO_EXPIRE)
- na->ExtendMetadata("NO_EXPIRE");
+ na->Extend<bool>("NS_NO_EXPIRE");
Log(LOG_DEBUG) << "Loaded NickAlias " << na->nick;
}
@@ -728,31 +725,31 @@ static void LoadChannels()
// Temporary flags cleanup
tmpu32 &= ~0x80000000;
if (tmpu32 & OLD_CI_KEEPTOPIC)
- ci->ExtendMetadata("KEEPTOPIC");
+ ci->Extend<bool>("KEEPTOPIC");
if (tmpu32 & OLD_CI_SECUREOPS)
- ci->ExtendMetadata("SECUREOPS");
+ ci->Extend<bool>("SECUREOPS");
if (tmpu32 & OLD_CI_PRIVATE)
- ci->ExtendMetadata("PRIVATE");
+ ci->Extend<bool>("CS_PRIVATE");
if (tmpu32 & OLD_CI_TOPICLOCK)
- ci->ExtendMetadata("TOPICLOCK");
+ ci->Extend<bool>("TOPICLOCK");
if (tmpu32 & OLD_CI_RESTRICTED)
- ci->ExtendMetadata("RESTRICTED");
+ ci->Extend<bool>("RESTRICTED");
if (tmpu32 & OLD_CI_PEACE)
- ci->ExtendMetadata("PEACE");
+ ci->Extend<bool>("PEACE");
if (tmpu32 & OLD_CI_SECURE)
- ci->ExtendMetadata("SECURE");
+ ci->Extend<bool>("CS_SECURE");
if (tmpu32 & OLD_CI_NO_EXPIRE)
- ci->ExtendMetadata("NO_EXPIRE");
+ ci->Extend<bool>("CI_NO_EXPIRE");
if (tmpu32 & OLD_CI_MEMO_HARDMAX)
- ci->ExtendMetadata("MEMO_HARDMAX");
+ ci->Extend<bool>("MEMO_HARDMAX");
if (tmpu32 & OLD_CI_SECUREFOUNDER)
- ci->ExtendMetadata("SECUREFOUNDER");
+ ci->Extend<bool>("SECUREFOUNDER");
if (tmpu32 & OLD_CI_SIGNKICK)
- ci->ExtendMetadata("SIGNKICK");
+ ci->Extend<bool>("SIGNKICK");
if (tmpu32 & OLD_CI_SIGNKICK_LEVEL)
- ci->ExtendMetadata("SIGNKICK_LEVEL");
+ ci->Extend<bool>("SIGNKICK_LEVEL");
if (tmpu32 & OLD_CI_SUSPENDED)
- ci->ExtendMetadata("SUSPENDED");
+ ci->Extend<bool>("SUSPENDED");
READ(read_string(buffer, f));
READ(read_string(buffer, f));
@@ -773,7 +770,7 @@ static void LoadChannels()
level = ACCESS_FOUNDER;
if (j == 10 && level < 0) // NOJOIN
- ci->Shrink("RESTRICTED"); // If CSDefRestricted was enabled this can happen
+ ci->Shrink<bool>("RESTRICTED"); // If CSDefRestricted was enabled this can happen
ci->SetLevel(GetLevelName(j), level);
}
@@ -831,9 +828,9 @@ static void LoadChannels()
}
READ(read_uint32(&tmpu32, f)); // mlock on
- ci->Extend("mlock_on", new ExtensibleItemUint32(tmpu32));
+ ci->Extend<uint32_t>("mlock_on", tmpu32);
READ(read_uint32(&tmpu32, f)); // mlock off
- ci->Extend("mlock_off", new ExtensibleItemUint32(tmpu32));
+ ci->Extend<uint32_t>("mlock_off", tmpu32);
READ(read_uint32(&tmpu32, f)); // mlock limit
READ(read_string(buffer, f));
READ(read_string(buffer, f));
@@ -863,52 +860,63 @@ static void LoadChannels()
READ(read_int32(&tmp32, f));
if (tmp32 & OLD_BS_DONTKICKOPS)
- ci->ExtendMetadata("BS_DONTKICKOPS");
+ ci->Extend<bool>("BS_DONTKICKOPS");
if (tmp32 & OLD_BS_DONTKICKVOICES)
- ci->ExtendMetadata("BS_DONTKICKVOICES");
+ ci->Extend<bool>("BS_DONTKICKVOICES");
if (tmp32 & OLD_BS_FANTASY)
- ci->ExtendMetadata("BS_FANTASY");
+ ci->Extend<bool>("BS_FANTASY");
if (tmp32 & OLD_BS_GREET)
- ci->ExtendMetadata("BS_GREET");
+ ci->Extend<bool>("BS_GREET");
if (tmp32 & OLD_BS_NOBOT)
- ci->ExtendMetadata("BS_NOBOT");
- if (tmp32 & OLD_BS_KICK_BOLDS)
- ci->ExtendMetadata("BS_KICK_BOLDS");
- if (tmp32 & OLD_BS_KICK_COLORS)
- ci->ExtendMetadata("BS_KICK_COLORS");
- if (tmp32 & OLD_BS_KICK_REVERSES)
- ci->ExtendMetadata("BS_KICK_REVERSES");
- if (tmp32 & OLD_BS_KICK_UNDERLINES)
- ci->ExtendMetadata("BS_KICK_UNDERLINES");
- if (tmp32 & OLD_BS_KICK_BADWORDS)
- ci->ExtendMetadata("BS_KICK_BADWORDS");
- if (tmp32 & OLD_BS_KICK_CAPS)
- ci->ExtendMetadata("BS_KICK_CAPS");
- if (tmp32 & OLD_BS_KICK_FLOOD)
- ci->ExtendMetadata("BS_KICK_FLOOD");
- if (tmp32 & OLD_BS_KICK_REPEAT)
- ci->ExtendMetadata("BS_KICK_REPEAT");
+ ci->Extend<bool>("BS_NOBOT");
+
+ KickerData *kd = ci->Require<KickerData>("kickerdata");
+ if (kd)
+ {
+ if (tmp32 & OLD_BS_KICK_BOLDS)
+ kd->bolds = true;
+ if (tmp32 & OLD_BS_KICK_COLORS)
+ kd->colors = true;
+ if (tmp32 & OLD_BS_KICK_REVERSES)
+ kd->reverses = true;
+ if (tmp32 & OLD_BS_KICK_UNDERLINES)
+ kd->underlines = true;
+ if (tmp32 & OLD_BS_KICK_BADWORDS)
+ kd->badwords = true;
+ if (tmp32 & OLD_BS_KICK_CAPS)
+ kd->caps = true;
+ if (tmp32 & OLD_BS_KICK_FLOOD)
+ kd->flood = true;
+ if (tmp32 & OLD_BS_KICK_REPEAT)
+ kd->repeat = true;
+ }
READ(read_int16(&tmp16, f));
for (int16_t j = 0; j < tmp16; ++j)
{
int16_t ttb;
READ(read_int16(&ttb, f));
- if (j < TTB_SIZE)
- ci->ttb[j] = ttb;
+ if (j < TTB_SIZE && kd)
+ kd->ttb[j] = ttb;
}
READ(read_int16(&tmp16, f));
- ci->capsmin = tmp16;
+ if (kd)
+ kd->capsmin = tmp16;
READ(read_int16(&tmp16, f));
- ci->capspercent = tmp16;
+ if (kd)
+ kd->capspercent = tmp16;
READ(read_int16(&tmp16, f));
- ci->floodlines = tmp16;
+ if (kd)
+ kd->floodlines = tmp16;
READ(read_int16(&tmp16, f));
- ci->floodsecs = tmp16;
+ if (kd)
+ kd->floodsecs = tmp16;
READ(read_int16(&tmp16, f));
- ci->repeattimes = tmp16;
+ if (kd)
+ kd->repeattimes = tmp16;
+ BadWords *bw = ci->Require<BadWords>("badwords");
READ(read_uint16(&tmpu16, f));
for (uint16_t j = 0; j < tmpu16; ++j)
{
@@ -928,7 +936,8 @@ static void LoadChannels()
else if (type == 3)
bwtype = BW_END;
- ci->AddBadWord(buffer, bwtype);
+ if (bw)
+ bw->AddBadWord(buffer, bwtype);
}
}
@@ -1089,8 +1098,11 @@ static void LoadExceptions()
class DBOld : public Module
{
+ PrimitiveExtensibleItem<uint32_t> mlock_on, mlock_off;
+
public:
- DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR)
+ DBOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, DATABASE | VENDOR),
+ mlock_on(this, "mlock_on"), mlock_off(this, "mlock_off")
{
@@ -1114,22 +1126,21 @@ class DBOld : public Module
void OnUplinkSync(Server *s) anope_override
{
- ExtensibleItemUint32 *mlock;
for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
{
ChannelInfo *ci = it->second;
- if (ci->HasExt("mlock_on"))
+
+ uint32_t *u = mlock_on.Get(ci);
+ if (u)
{
- mlock = ci->GetExt<ExtensibleItemUint32 *>("mlock_on");
- process_mlock(ci, mlock->u, true);
- ci->Shrink("mlock_on");
+ process_mlock(ci, *u, true);
+ mlock_on.Unset(ci);
}
- if (ci->HasExt("mlock_off"))
+ u = mlock_off.Get(ci);
{
- mlock = ci->GetExt<ExtensibleItemUint32 *>("mlock_off");
- process_mlock(ci, mlock->u, false);
- ci->Shrink("mlock_off");
+ process_mlock(ci, *u, false);
+ mlock_off.Unset(ci);
}
}
}
diff --git a/modules/database/db_plain.cpp b/modules/database/db_plain.cpp
index 1e4586a11..62ecaaaa0 100644
--- a/modules/database/db_plain.cpp
+++ b/modules/database/db_plain.cpp
@@ -10,6 +10,11 @@
#include "module.h"
#include "modules/os_session.h"
+#include "modules/cs_suspend.h"
+#include "modules/bs_kick.h"
+#include "modules/cs_log.h"
+#include "modules/cs_mode.h"
+#include "modules/bs_badwords.h"
Anope::string DatabaseFile;
Anope::string BackupFile;
@@ -71,15 +76,13 @@ EventReturn OnDatabaseReadMetadata(NickCore *nc, const Anope::string &key, const
else if (key.equals_ci("EMAIL"))
nc->email = params[0];
else if (key.equals_ci("GREET"))
- nc->greet = params[0];
+ nc->Extend<Anope::string>("greet", params[0]);
else if (key.equals_ci("ACCESS"))
nc->AddAccess(params[0]);
- else if (key.equals_ci("CERT"))
- nc->AddCert(params[0]);
else if (key.equals_ci("FLAGS"))
{
for (unsigned i = 0; i < params.size(); ++i)
- nc->ExtendMetadata(params[i]);
+ nc->Extend<bool>(params[i]);
}
else if (key.equals_ci("MI"))
{
@@ -118,7 +121,7 @@ EventReturn OnDatabaseReadMetadata(NickAlias *na, const Anope::string &key, cons
na->last_quit = params[0];
else if (key.equals_ci("FLAGS"))
for (unsigned i = 0; i < params.size(); ++i)
- na->ExtendMetadata(params[i]);
+ na->Extend<bool>(params[i]);
else if (key.equals_ci("VHOST"))
na->SetVhost(params.size() > 3 ? params[3] : "", params[2], params[0], params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0);
return EVENT_CONTINUE;
@@ -131,6 +134,7 @@ EventReturn OnDatabaseReadMetadata(BotInfo *bi, const Anope::string &key, const
EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, const std::vector<Anope::string> &params)
{
+ KickerData *kd = ci->GetExt<KickerData>("kickerdata");
try
{
if (key.equals_ci("BANTYPE"))
@@ -153,7 +157,7 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
}
else if (key.equals_ci("FLAGS"))
for (unsigned i = 0; i < params.size(); ++i)
- ci->ExtendMetadata(params[i]);
+ ci->Extend<bool>(params[i]);
else if (key.equals_ci("DESC"))
ci->desc = params[0];
else if (key.equals_ci("TOPIC"))
@@ -164,8 +168,9 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
}
else if (key.equals_ci("SUSPEND"))
{
- ci->ExtendMetadata("suspend:by", params[0]);
- ci->ExtendMetadata("suspend:reason", params[1]);
+ CSSuspendInfo *si = ci->Extend<CSSuspendInfo>("suspend");
+ si->by = params[0];
+ si->reason = params[1];
}
else if (key.equals_ci("ACCESS")) // Older access system, from Anope 1.9.4.
{
@@ -220,18 +225,22 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
}
else if (key.equals_ci("LOG"))
{
- LogSetting *l = new LogSetting();
-
- l->ci = ci;
- l->service_name = params[0];
- l->command_service = params[1];
- l->command_name = params[2];
- l->method = params[3];
- l->creator = params[4];
- l->created = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
- l->extra = params.size() > 6 ? params[6] : "";
-
- ci->log_settings->push_back(l);
+ LogSettings *ls = ci->Require<LogSettings>("logsettings");
+ if (ls)
+ {
+ LogSetting *l = ls->Create();
+
+ l->chan = ci->name;
+ l->service_name = params[0];
+ l->command_service = params[1];
+ l->command_name = params[2];
+ l->method = params[3];
+ l->creator = params[4];
+ l->created = params[5].is_pos_number_only() ? convertTo<time_t>(params[5]) : Anope::CurTime;
+ l->extra = params.size() > 6 ? params[6] : "";
+
+ (*ls)->push_back(l);
+ }
}
else if (key.equals_ci("MLOCK"))
{
@@ -240,7 +249,9 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
Anope::string setter = params[2];
time_t mcreated = params[3].is_pos_number_only() ? convertTo<time_t>(params[3]) : Anope::CurTime;
Anope::string param = params.size() > 4 ? params[4] : "";
- ci->mode_locks->insert(std::make_pair(mode_name, new ModeLock(ci, set, mode_name, param, setter, mcreated)));
+ ModeLocks *ml = ci->Require<ModeLocks>("modelocks");
+ if (ml)
+ ml->SetMLock(ModeManager::FindChannelModeByName(mode_name), set, param, setter, mcreated);
}
else if (key.equals_ci("MI"))
{
@@ -265,44 +276,44 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
ci->bi = BotInfo::Find(params[1]);
else if (params[0].equals_ci("FLAGS"))
for (unsigned i = 0; i < params.size(); ++i)
- ci->ExtendMetadata(params[i]);
+ ci->Extend<bool>(params[i]);
else if (params[0].equals_ci("TTB"))
{
- for (unsigned j = 1, end = params.size(); j < end; j += 2)
+ for (unsigned j = 1, end = params.size(); j < end &&& kd; j += 2)
{
if (params[j].equals_ci("BOLDS"))
- ci->ttb[0] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[0] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("COLORS"))
- ci->ttb[1] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[1] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("REVERSES"))
- ci->ttb[2] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[2] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("UNDERLINES"))
- ci->ttb[3] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[3] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("BADWORDS"))
- ci->ttb[4] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[4] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("CAPS"))
- ci->ttb[5] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[5] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("FLOOD"))
- ci->ttb[6] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[6] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("REPEAT"))
- ci->ttb[7] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[7] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("ITALICS"))
- ci->ttb[8] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[8] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
else if (params[j].equals_ci("AMSGS"))
- ci->ttb[9] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
+ kd->ttb[9] = params[j + 1].is_pos_number_only() ? convertTo<int16_t>(params[j + 1]) : 0;
}
}
- else if (params[0].equals_ci("CAPSMIN"))
- ci->capsmin = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
- else if (params[0].equals_ci("CAPSPERCENT"))
- ci->capspercent = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
- else if (params[0].equals_ci("FLOODLINES"))
- ci->floodlines = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
- else if (params[0].equals_ci("FLOODSECS"))
- ci->floodsecs = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
- else if (params[0].equals_ci("REPEATTIMES"))
- ci->repeattimes = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
- else if (params[0].equals_ci("BADWORD"))
+ else if (kd && params[0].equals_ci("CAPSMIN"))
+ kd->capsmin = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
+ else if (kd && params[0].equals_ci("CAPSPERCENT"))
+ kd->capspercent = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
+ else if (kd && params[0].equals_ci("FLOODLINES"))
+ kd->floodlines = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
+ else if (kd && params[0].equals_ci("FLOODSECS"))
+ kd->floodsecs = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
+ else if (kd && params[0].equals_ci("REPEATTIMES"))
+ kd->repeattimes = params[1].is_pos_number_only() ? convertTo<int16_t>(params[1]) : 0;
+ else if (kd && params[0].equals_ci("BADWORD"))
{
BadWordType Type;
if (params[1].equals_ci("SINGLE"))
@@ -313,7 +324,9 @@ EventReturn OnDatabaseReadMetadata(ChannelInfo *ci, const Anope::string &key, co
Type = BW_END;
else
Type = BW_ANY;
- ci->AddBadWord(params[2], Type);
+ BadWords *bw = ci->Require<BadWords>("badwords");
+ if (bw)
+ bw->AddBadWord(params[2], Type);
}
}
}
@@ -467,11 +480,6 @@ static void ReadDatabase(Module *m = NULL)
static void LoadNickCore(const std::vector<Anope::string> &params)
{
NickCore *nc = new NickCore(params[0]);
- /* Clear default flags */
- std::deque<Anope::string> list;
- nc->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- nc->Shrink(list[i]);
nc->pass = params.size() > 1 ? params[1] : "";
@@ -512,13 +520,6 @@ static void LoadBotInfo(const std::vector<Anope::string> &params)
static void LoadChanInfo(const std::vector<Anope::string> &params)
{
ChannelInfo *ci = new ChannelInfo(params[0]);
- /* CLear default mlock */
- ci->ClearMLock();
- /* Remove default channel flags */
- std::deque<Anope::string> list;
- ci->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- ci->Shrink(list[i]);
ci->time_registered = params[1].is_pos_number_only() ? convertTo<time_t>(params[1]) : 0;
@@ -645,230 +646,6 @@ class DBPlain : public Module
return EVENT_STOP;
}
-
-
- void OnSaveDatabase() anope_override
- {
- BackupDatabase();
-
- db_buffer << "VER 2" << endl;
-
- for (nickcore_map::const_iterator nit = NickCoreList->begin(), nit_end = NickCoreList->end(); nit != nit_end; ++nit)
- {
- const NickCore *nc = nit->second;
-
- db_buffer << "NC " << nc->display << " " << nc->pass << endl;
-
- db_buffer << "MD MEMOMAX " << nc->memos.memomax << endl;
-
- if (!nc->language.empty())
- db_buffer << "MD LANGUAGE " << nc->language << endl;
- if (!nc->email.empty())
- db_buffer << "MD EMAIL " << nc->email << endl;
- if (!nc->greet.empty())
- db_buffer << "MD GREET :" << nc->greet << endl;
-
- if (!nc->access.empty())
- {
- for (std::vector<Anope::string>::const_iterator it = nc->access.begin(), it_end = nc->access.end(); it != it_end; ++it)
- db_buffer << "MD ACCESS " << *it << endl;
- }
- if (!nc->cert.empty())
- {
- for (std::vector<Anope::string>::const_iterator it = nc->cert.begin(), it_end = nc->cert.end(); it != it_end; ++it)
- db_buffer << "MD CERT " << *it << endl;
- }
- db_buffer << "MD FLAGS ";
- std::deque<Anope::string> list;
- nc->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- db_buffer << list[i] << " ";
- db_buffer << std::endl;
- const MemoInfo *mi = &nc->memos;
- for (unsigned k = 0, end = mi->memos->size(); k < end; ++k)
- {
- const Memo *m = mi->GetMemo(k);
- db_buffer << "MD MI " << m->time << " " << m->sender;
- if (m->unread)
- db_buffer << " UNREAD";
- if (m->receipt)
- db_buffer << " RECEIPT";
- db_buffer << " :" << m->text << endl;
- }
- for (unsigned k = 0, end = mi->ignores.size(); k < end; ++k)
- db_buffer << "MD MIG " << Anope::string(mi->ignores[k]) << endl;
- //FOREACH_MOD(OnDatabaseWriteMetadata, (WriteMetadata, nc));
- }
-
- for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; ++it)
- {
- const NickAlias *na = it->second;
-
- db_buffer << "NA " << na->nc->display << " " << na->nick << " " << na->time_registered << " " << na->last_seen << endl;
- if (!na->last_usermask.empty())
- db_buffer << "MD LAST_USERMASK " << na->last_usermask << endl;
- if (!na->last_realhost.empty())
- db_buffer << "MD LAST_REALHOST " << na->last_realhost << endl;
- if (!na->last_realname.empty())
- db_buffer << "MD LAST_REALNAME :" << na->last_realname << endl;
- if (!na->last_quit.empty())
- db_buffer << "MD LAST_QUIT :" << na->last_quit << endl;
- db_buffer << "MD FLAGS ";
- std::deque<Anope::string> list;
- na->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- db_buffer << list[i] << " ";
- db_buffer << std::endl;
- if (na->HasVhost())
- db_buffer << "MD VHOST " << na->GetVhostCreator() << " " << na->GetVhostCreated() << " " << na->GetVhostHost() << " :" << na->GetVhostIdent() << endl;
-
- //FOREACH_MOD(OnDatabaseWriteMetadata, (WriteMetadata, na));
- }
-
- for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it)
- {
- BotInfo *bi = it->second;
-
- if (bi->HasExt("CONF"))
- continue;
-
- db_buffer << "BI " << bi->nick << " " << bi->GetIdent() << " " << bi->host << " " << bi->created << " " << bi->GetChannelCount() << " :" << bi->realname << endl;
- db_buffer << "MD FLAGS ";
- std::deque<Anope::string> list;
- bi->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- db_buffer << list[i] << " ";
- db_buffer << std::endl;
- }
-
- for (registered_channel_map::const_iterator cit = RegisteredChannelList->begin(), cit_end = RegisteredChannelList->end(); cit != cit_end; ++cit)
- {
- const ChannelInfo *ci = cit->second;
-
- db_buffer << "CH " << ci->name << " " << ci->time_registered << " " << ci->last_used << endl;
- db_buffer << "MD BANTYPE " << ci->bantype << endl;
- db_buffer << "MD MEMOMAX " << ci->memos.memomax << endl;
- if (ci->GetFounder())
- db_buffer << "MD FOUNDER " << ci->GetFounder()->display << endl;
- if (ci->GetSuccessor())
- db_buffer << "MD SUCCESSOR " << ci->GetSuccessor()->display << endl;
- if (!ci->desc.empty())
- db_buffer << "MD DESC :" << ci->desc << endl;
- if (!ci->last_topic.empty())
- db_buffer << "MD TOPIC " << ci->last_topic_setter << " " << ci->last_topic_time << " :" << ci->last_topic << endl;
- db_buffer << "MD LEVELS";
- const std::vector<Privilege> &privs = PrivilegeManager::GetPrivileges();
- for (unsigned i = 0; i < privs.size(); ++i)
- {
- const Privilege &p = privs[i];
- db_buffer << p.name << " " << ci->GetLevel(p.name);
- }
- db_buffer << endl;
- std::deque<Anope::string> list;
- ci->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
- db_buffer << list[i];
- db_buffer << std::endl;
- if (ci->HasExt("SUSPENDED"))
- {
- Anope::string *by = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend_by"), *reason = ci->GetExt<ExtensibleItemClass<Anope::string> *>("suspend_reason");
- if (by && reason)
- db_buffer << "MD SUSPEND " << *by << " :" << *reason << endl;
- }
- for (unsigned k = 0, end = ci->GetAccessCount(); k < end; ++k)
- {
- const ChanAccess *access = ci->GetAccess(k);
- db_buffer << "MD ACCESS2 " << access->provider->name << " " << access->mask << " " << access->AccessSerialize() << " " << access->last_seen << " " << access->creator << " " << access->created << endl;
- }
- for (unsigned k = 0, end = ci->GetAkickCount(); k < end; ++k)
- {
- db_buffer << "MD AKICK 0 " << (ci->GetAkick(k)->nc ? "NICK " : "MASK ") <<
- (ci->GetAkick(k)->nc ? ci->GetAkick(k)->nc->display : ci->GetAkick(k)->mask) << " " << ci->GetAkick(k)->creator << " " << ci->GetAkick(k)->addtime << " " << ci->last_used << " :";
- if (!ci->GetAkick(k)->reason.empty())
- db_buffer << ci->GetAkick(k)->reason;
- db_buffer << endl;
- }
- for (unsigned k = 0, end = ci->log_settings->size(); k < end; ++k)
- {
- const LogSetting &l = *ci->log_settings->at(k);
-
- db_buffer << "MD LOG " << l.service_name << " " << l.command_service << " " << l.command_name << " " << l.method << " " << l.creator << " " << l.created << " " << l.extra << endl;
- }
- for (ChannelInfo::ModeList::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 != NULL)
- db_buffer << "MD MLOCK " << (ml.set ? 1 : 0) << " " << cm->name << " " << ml.setter << " " << ml.created << " " << ml.param << endl;
- }
- const MemoInfo *memos = &ci->memos;
- for (unsigned k = 0, end = memos->memos->size(); k < end; ++k)
- {
- const Memo *m = memos->GetMemo(k);
- db_buffer << "MD MI " << m->time << " " << m->sender;
- if (m->unread)
- db_buffer << " UNREAD";
- if (m->receipt)
- db_buffer << " RECEIPT";
- db_buffer << " :" << m->text << endl;
- }
- for (unsigned k = 0, end = memos->ignores.size(); k < end; ++k)
- db_buffer << "MD MIG " << Anope::string(memos->ignores[k]) << endl;
- if (ci->bi)
- db_buffer << "MD BI NAME " << ci->bi->nick << endl;
- db_buffer << "MD BI TTB BOLDS " << ci->ttb[0] << " COLORS " << ci->ttb[1] << " REVERSES " << ci->ttb[2] << " UNDERLINES " << ci->ttb[3] << " BADWORDS " << ci->ttb[4] << " CAPS " << ci->ttb[5] << " FLOOD " << ci->ttb[6] << " REPEAT " << ci->ttb[7] << " ITALICS " << ci->ttb[8] << " AMSGS " << ci->ttb[9] << endl;
- if (ci->capsmin)
- db_buffer << "MD BI CAPSMIN " << ci->capsmin << endl;
- if (ci->capspercent)
- db_buffer << "MD BI CAPSPERCENT " << ci->capspercent << endl;
- if (ci->floodlines)
- db_buffer << "MD BI FLOODLINES " << ci->floodlines << endl;
- if (ci->floodsecs)
- db_buffer << "MD BI FLOODSECS " << ci->floodsecs << endl;
- if (ci->repeattimes)
- db_buffer << "MD BI REPEATTIMES " << ci->repeattimes << endl;
- for (unsigned k = 0, end = ci->GetBadWordCount(); k < end; ++k)
- db_buffer << "MD BI BADWORD " << (ci->GetBadWord(k)->type == BW_ANY ? "ANY " : "") << (ci->GetBadWord(k)->type == BW_SINGLE ? "SINGLE " : "") << (ci->GetBadWord(k)->type == BW_START ? "START " : "") <<
- (ci->GetBadWord(k)->type == BW_END ? "END " : "") << ":" << ci->GetBadWord(k)->word << endl;
-
- //FOREACH_MOD(OnDatabaseWriteMetadata, (WriteMetadata, ci));
- }
-
- db_buffer << "OS STATS " << MaxUserCount << " " << MaxUserTime << endl;
-
- for (std::list<XLineManager *>::iterator it = XLineManager::XLineManagers.begin(), it_end = XLineManager::XLineManagers.end(); it != it_end; ++it)
- {
- XLineManager *xl = *it;
- for (unsigned i = 0, end = xl->GetCount(); i < end; ++i)
- {
- const XLine *x = xl->GetEntry(i);
- db_buffer << "OS SXLINE " << xl->Type() << " " << x->GetUser() << " " << x->GetHost() << " " << x->by << " " << x->created << " " << x->expires << " :" << x->reason << endl;
- }
- }
-
- if (session_service)
- for (SessionService::ExceptionVector::iterator it = session_service->GetExceptions().begin(); it != session_service->GetExceptions().end(); ++it)
- {
- Exception *e = *it;
- db_buffer << "OS EXCEPTION " << e->mask << " " << e->limit << " " << e->who << " " << e->time << " " << e->expires << " " << e->reason << endl;
- }
-
- //FOREACH_MOD(OnDatabaseWrite, (Write));
-
- std::fstream db;
- db.open(DatabaseFile.c_str(), std::ios_base::out | std::ios_base::trunc);
-
- if (!db.is_open())
- {
- IRCD->SendGlobops(NULL, "Unable to open %s for writing!", DatabaseFile.c_str());
- return;
- }
-
- db << db_buffer.str();
- db_buffer.str("");
-
- db.close();
- }
};
MODULE_INIT(DBPlain)
diff --git a/modules/extra/m_chanstats.cpp b/modules/extra/m_chanstats.cpp
index 9a3c5dfaf..4ff4d55e3 100644
--- a/modules/extra/m_chanstats.cpp
+++ b/modules/extra/m_chanstats.cpp
@@ -56,7 +56,7 @@ class MChanstats : public Module
const Anope::string GetDisplay(User *u)
{
- if (u && u->Account() && u->Account()->HasExt("STATS"))
+ if (u && u->Account() && u->Account()->HasExt("NS_STATS"))
return u->Account()->display;
else
return "";
@@ -357,7 +357,7 @@ class MChanstats : public Module
void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
{
User *u = User::Find(user);
- if (!u || !u->Account() || !c->ci || !c->ci->HasExt("STATS"))
+ if (!u || !u->Account() || !c->ci || !c->ci->HasExt("CS_STATS"))
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);";
query.SetValue("channel", c->name);
@@ -365,13 +365,13 @@ class MChanstats : public Module
this->RunQuery(query);
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, const Anope::string &, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) anope_override
{
this->OnModeChange(c, setter.GetUser());
return EVENT_CONTINUE;
}
- EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, const Anope::string &, const Anope::string &param) anope_override
+ EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *, const Anope::string &param) anope_override
{
this->OnModeChange(c, setter.GetUser());
return EVENT_CONTINUE;
@@ -380,7 +380,7 @@ class MChanstats : public Module
private:
void OnModeChange(Channel *c, User *u)
{
- if (!u || !u->Account() || !c->ci || !c->ci->HasExt("STATS"))
+ if (!u || !u->Account() || !c->ci || !c->ci->HasExt("CS_STATS"))
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);";
@@ -391,7 +391,7 @@ class MChanstats : public Module
public:
void OnPreUserKicked(MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) anope_override
{
- if (!cu->chan->ci || !cu->chan->ci->HasExt("STATS"))
+ if (!cu->chan->ci || !cu->chan->ci->HasExt("CS_STATS"))
return;
query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);";
@@ -406,7 +406,7 @@ class MChanstats : public Module
}
void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
{
- if (!c->ci || !c->ci->HasExt("STATS"))
+ if (!c->ci || !c->ci->HasExt("CS_STATS"))
return;
size_t letters = msg.length();
@@ -452,7 +452,7 @@ class MChanstats : public Module
query.SetValue("new_display", newdisplay);
this->RunQuery(query);
}
- void OnChanDrop(ChannelInfo *ci) anope_override
+ void OnDelChan(ChannelInfo *ci) anope_override
{
query = "DELETE FROM `" + prefix + "chanstats` WHERE `chan` = @channel@;";
query.SetValue("channel", ci->name);
diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp
index d64987ed6..7fe44b8e0 100644
--- a/modules/extra/m_ldap_authentication.cpp
+++ b/modules/extra/m_ldap_authentication.cpp
@@ -111,7 +111,7 @@ class IdentifyInterface : public LDAPInterface
// encrypt and store the password in the nickcore
Anope::Encrypt(ii->req->GetPassword(), na->nc->pass);
- na->nc->Extend("m_ldap_authentication_dn", new ExtensibleItemClass<Anope::string>(ii->dn));
+ na->nc->Extend<Anope::string>("m_ldap_authentication_dn", ii->dn);
ii->req->Success(me);
}
break;
@@ -207,12 +207,15 @@ class NSIdentifyLDAP : public Module
OnIdentifyInterface oninterface;
OnRegisterInterface orinterface;
+ PrimitiveExtensibleItem<Anope::string> dn;
+
Anope::string password_attribute;
Anope::string disable_register_reason;
Anope::string disable_email_reason;
public:
NSIdentifyLDAP(const Anope::string &modname, const Anope::string &creator) :
- Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this), oninterface(this), orinterface(this)
+ Module(modname, creator, EXTRA | VENDOR), ldap("LDAPProvider", "ldap/main"), iinterface(this), oninterface(this), orinterface(this),
+ dn(this, "m_ldap_authentication_dn")
{
me = this;
@@ -274,16 +277,16 @@ class NSIdentifyLDAP : public Module
void OnNickIdentify(User *u) anope_override
{
- if (email_attribute.empty() || !this->ldap || !u->Account()->HasExt("m_ldap_authentication_dn"))
+ if (email_attribute.empty() || !this->ldap)
return;
- Anope::string *dn = u->Account()->GetExt<ExtensibleItemClass<Anope::string> *>("m_ldap_authentication_dn");
- if (!dn || dn->empty())
+ Anope::string *d = dn.Get(u->Account());
+ if (!d || d->empty())
return;
try
{
- LDAPQuery id = this->ldap->Search(&this->oninterface, *dn, "(" + email_attribute + "=*)");
+ LDAPQuery id = this->ldap->Search(&this->oninterface, *d, "(" + email_attribute + "=*)");
this->oninterface.Add(id, u->nick);
}
catch (const LDAPException &ex)
diff --git a/modules/extra/webcpanel/pages/chanserv/set.cpp b/modules/extra/webcpanel/pages/chanserv/set.cpp
index 20026a08a..cf3784d62 100644
--- a/modules/extra/webcpanel/pages/chanserv/set.cpp
+++ b/modules/extra/webcpanel/pages/chanserv/set.cpp
@@ -32,57 +32,57 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
if (ci->HasExt("KEEPTOPIC") != message.post_data.count("keeptopic"))
{
if (!ci->HasExt("KEEPTOPIC"))
- ci->ExtendMetadata("KEEPTOPIC");
+ ci->Extend<bool>("KEEPTOPIC");
else
- ci->Shrink("KEEPTOPIC");
+ ci->Shrink<bool>("KEEPTOPIC");
replacements["MESSAGES"] = "Secure updated";
}
if (ci->HasExt("PEACE") != message.post_data.count("peace"))
{
if (!ci->HasExt("PEACE"))
- ci->ExtendMetadata("PEACE");
+ ci->Extend<bool>("PEACE");
else
- ci->Shrink("PEACE");
+ ci->Shrink<bool>("PEACE");
replacements["MESSAGES"] = "Peace updated";
}
- if (ci->HasExt("PRIVATE") != message.post_data.count("private"))
+ if (ci->HasExt("CS_PRIVATE") != message.post_data.count("private"))
{
- if (!ci->HasExt("PRIVATE"))
- ci->ExtendMetadata("PRIVATE");
+ if (!ci->HasExt("CS_PRIVATE"))
+ ci->Extend<bool>("CS_PRIVATE");
else
- ci->Shrink("PRIVATE");
+ ci->Shrink<bool>("CS_PRIVATE");
replacements["MESSAGES"] = "Private updated";
}
if (ci->HasExt("RESTRICTED") != message.post_data.count("restricted"))
{
if (!ci->HasExt("RESTRICTED"))
- ci->ExtendMetadata("RESTRICTED");
+ ci->Extend<bool>("RESTRICTED");
else
- ci->Shrink("RESTRICTED");
+ ci->Shrink<bool>("RESTRICTED");
replacements["MESSAGES"] = "Restricted updated";
}
- if (ci->HasExt("SECURE") != message.post_data.count("secure"))
+ if (ci->HasExt("CS_SECURE") != message.post_data.count("secure"))
{
- if (!ci->HasExt("SECURE"))
- ci->ExtendMetadata("SECURE");
+ if (!ci->HasExt("CS_SECURE"))
+ ci->Extend<bool>("CS_SECURE");
else
- ci->Shrink("SECURE");
+ ci->Shrink<bool>("CS_SECURE");
replacements["MESSAGES"] = "Secure updated";
}
if (ci->HasExt("SECUREOPS") != message.post_data.count("secureops"))
{
if (!ci->HasExt("SECUREOPS"))
- ci->ExtendMetadata("SECUREOPS");
+ ci->Extend<bool>("SECUREOPS");
else
- ci->Shrink("SECUREOPS");
+ ci->Shrink<bool>("SECUREOPS");
replacements["MESSAGES"] = "Secureops updated";
}
if (ci->HasExt("TOPICLOCK") != message.post_data.count("topiclock"))
{
if (!ci->HasExt("TOPICLOCK"))
- ci->ExtendMetadata("TOPICLOCK");
+ ci->Extend<bool>("TOPICLOCK");
else
- ci->Shrink("TOPICLOCK");
+ ci->Shrink<bool>("TOPICLOCK");
replacements["MESSAGES"] = "Topiclock updated";
}
}
@@ -108,13 +108,13 @@ bool WebCPanel::ChanServ::Set::OnRequest(HTTPProvider *server, const Anope::stri
if (ci->HasExt("PEACE"))
replacements["PEACE"];
- if (ci->HasExt("PRIVATE"))
+ if (ci->HasExt("CS_PRIVATE"))
replacements["PRIVATE"];
if (ci->HasExt("RESTRICTED"))
replacements["RESTRICTED"];
- if (ci->HasExt("SECURE"))
+ if (ci->HasExt("CS_SECURE"))
replacements["SECURE"];
if (ci->HasExt("SECUREOPS"))
diff --git a/modules/extra/webcpanel/pages/index.cpp b/modules/extra/webcpanel/pages/index.cpp
index 51b908b13..be4bbbc6d 100644
--- a/modules/extra/webcpanel/pages/index.cpp
+++ b/modules/extra/webcpanel/pages/index.cpp
@@ -40,8 +40,8 @@ class WebpanelRequest : public IdentifyRequest
id += c;
}
- na->Extend("webcpanel_id", new ExtensibleItemClass<Anope::string>(id));
- na->Extend("webcpanel_ip", new ExtensibleItemClass<Anope::string>(client->GetIP()));
+ na->Extend<Anope::string>("webcpanel_id", id);
+ na->Extend<Anope::string>("webcpanel_ip", client->GetIP());
{
HTTPReply::cookie c;
diff --git a/modules/extra/webcpanel/pages/logout.cpp b/modules/extra/webcpanel/pages/logout.cpp
index 14e1c24b5..8fafdcd4e 100644
--- a/modules/extra/webcpanel/pages/logout.cpp
+++ b/modules/extra/webcpanel/pages/logout.cpp
@@ -13,8 +13,8 @@ WebCPanel::Logout::Logout(const Anope::string &u) : WebPanelProtectedPage("", u)
bool WebCPanel::Logout::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply, NickAlias *na, TemplateFileServer::Replacements &replacements)
{
- na->Shrink("webcpanel_id");
- na->Shrink("webcpanel_ip");
+ na->Shrink<Anope::string>("webcpanel_id");
+ na->Shrink<Anope::string>("webcpanel_ip");
reply.error = HTTP_FOUND;
reply.headers["Location"] = Anope::string("http") + (use_ssl ? "s" : "") + "://" + message.headers["Host"] + "/";
diff --git a/modules/extra/webcpanel/pages/nickserv/alist.cpp b/modules/extra/webcpanel/pages/nickserv/alist.cpp
index 0afe2a4f3..a0568f5b4 100644
--- a/modules/extra/webcpanel/pages/nickserv/alist.cpp
+++ b/modules/extra/webcpanel/pages/nickserv/alist.cpp
@@ -24,7 +24,7 @@ bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
++chan_count;
replacements["NUMBERS"] = stringify(chan_count);
- replacements["CHANNELS"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name;
+ replacements["CHANNELS"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
replacements["ACCESSES"] = "Founder";
continue;
}
@@ -36,7 +36,7 @@ bool WebCPanel::NickServ::Alist::OnRequest(HTTPProvider *server, const Anope::st
++chan_count;
replacements["NUMBERS"] = stringify(chan_count);
- replacements["CHANNELS"] = (ci->HasExt("NO_EXPIRE") ? "!" : "") + ci->name;
+ replacements["CHANNELS"] = (ci->HasExt("CS_NO_EXPIRE") ? "!" : "") + ci->name;
Anope::string access_str;
for (unsigned i = 0; i < access.size(); ++i)
access_str += ", " + access[i]->AccessSerialize();
diff --git a/modules/extra/webcpanel/pages/nickserv/cert.cpp b/modules/extra/webcpanel/pages/nickserv/cert.cpp
index 9ac95453a..ff9885405 100644
--- a/modules/extra/webcpanel/pages/nickserv/cert.cpp
+++ b/modules/extra/webcpanel/pages/nickserv/cert.cpp
@@ -6,6 +6,7 @@
*/
#include "../../webcpanel.h"
+#include "modules/ns_cert.h"
WebCPanel::NickServ::Cert::Cert(const Anope::string &cat, const Anope::string &u) : WebPanelProtectedPage(cat, u)
{
@@ -30,8 +31,10 @@ bool WebCPanel::NickServ::Cert::OnRequest(HTTPProvider *server, const Anope::str
WebPanel::RunCommand(na->nc->display, na->nc, "NickServ", "nickserv/cert", params, replacements);
}
- for (unsigned i = 0; i < na->nc->cert.size(); ++i)
- replacements["CERTS"] = na->nc->cert[i];
+ NSCertList *cl = na->nc->GetExt<NSCertList>("certificates");
+ if (cl)
+ for (unsigned i = 0; i < cl->GetCertCount(); ++i)
+ replacements["CERTS"] = cl->GetCert(i);
TemplateFileServer page("nickserv/cert.html");
page.Serve(server, page_name, client, message, reply, replacements);
diff --git a/modules/extra/webcpanel/pages/nickserv/info.cpp b/modules/extra/webcpanel/pages/nickserv/info.cpp
index 35a4a8a0a..65f0e4c8a 100644
--- a/modules/extra/webcpanel/pages/nickserv/info.cpp
+++ b/modules/extra/webcpanel/pages/nickserv/info.cpp
@@ -30,52 +30,56 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
}
if (message.post_data.count("greet") > 0)
{
- if (message.post_data["greet"].replace_all_cs("+", " ") != na->nc->greet)
- {
- na->nc->greet = HTTPUtils::URLDecode(message.post_data["greet"]);
- replacements["MESSAGES"] = "Greet updated";
- }
+ Anope::string *greet = na->nc->GetExt<Anope::string>("greet");
+ const Anope::string &post_greet = HTTPUtils::URLDecode(message.post_data["greet"].replace_all_cs("+", " "));
+
+ if (post_greet.empty())
+ na->nc->Shrink<Anope::string>("greet");
+ else if (!greet || post_greet != *greet)
+ na->nc->Extend<Anope::string>("greet", post_greet);
+
+ replacements["MESSAGES"] = "Greet updated";
}
if (na->nc->HasExt("AUTOOP") != message.post_data.count("autoop"))
{
if (!na->nc->HasExt("AUTOOP"))
- na->nc->ExtendMetadata("AUTOOP");
+ na->nc->Extend<bool>("AUTOOP");
else
- na->nc->Shrink("AUTOOP");
+ na->nc->Shrink<bool>("AUTOOP");
replacements["MESSAGES"] = "Autoop updated";
}
- if (na->nc->HasExt("PRIVATE") != message.post_data.count("private"))
+ if (na->nc->HasExt("NS_PRIVATE") != message.post_data.count("private"))
{
- if (!na->nc->HasExt("PRIVATE"))
- na->nc->ExtendMetadata("PRIVATE");
+ if (!na->nc->HasExt("NS_PRIVATE"))
+ na->nc->Extend<bool>("NS_PRIVATE");
else
- na->nc->Shrink("PRIVATE");
+ na->nc->Shrink<bool>("NS_PRIVATE");
replacements["MESSAGES"] = "Private updated";
}
- if (na->nc->HasExt("SECURE") != message.post_data.count("secure"))
+ if (na->nc->HasExt("NS_SECURE") != message.post_data.count("secure"))
{
- if (!na->nc->HasExt("SECURE"))
- na->nc->ExtendMetadata("SECURE");
+ if (!na->nc->HasExt("NS_SECURE"))
+ na->nc->Extend<bool>("NS_SECURE");
else
- na->nc->Shrink("SECURE");
+ na->nc->Shrink<bool>("NS_SECURE");
replacements["MESSAGES"] = "Secure updated";
}
if (message.post_data["kill"] == "on" && !na->nc->HasExt("KILLPROTECT"))
{
- na->nc->ExtendMetadata("KILLPROTECT");
- na->nc->Shrink("KILL_QUICK");
+ na->nc->Extend<bool>("KILLPROTECT");
+ na->nc->Shrink<bool>("KILL_QUICK");
replacements["MESSAGES"] = "Kill updated";
}
else if (message.post_data["kill"] == "quick" && !na->nc->HasExt("KILL_QUICK"))
{
- na->nc->Shrink("KILLPROTECT");
- na->nc->ExtendMetadata("KILL_QUICK");
+ na->nc->Shrink<bool>("KILLPROTECT");
+ na->nc->Extend<bool>("KILL_QUICK");
replacements["MESSAGES"] = "Kill updated";
}
else if (message.post_data["kill"] == "off" && (na->nc->HasExt("KILLPROTECT") || na->nc->HasExt("KILL_QUICK")))
{
- na->nc->Shrink("KILLPROTECT");
- na->nc->Shrink("KILL_QUICK");
+ na->nc->Shrink<bool>("KILLPROTECT");
+ na->nc->Shrink<bool>("KILL_QUICK");
replacements["MESSAGES"] = "Kill updated";
}
}
@@ -91,12 +95,14 @@ bool WebCPanel::NickServ::Info::OnRequest(HTTPProvider *server, const Anope::str
else
replacements["VHOST"] = na->GetVhostHost();
}
- replacements["GREET"] = HTTPUtils::Escape(na->nc->greet);
+ Anope::string *greet = na->nc->GetExt<Anope::string>("greet");
+ if (greet)
+ replacements["GREET"] = HTTPUtils::Escape(*greet);
if (na->nc->HasExt("AUTOOP"))
replacements["AUTOOP"];
- if (na->nc->HasExt("PRIVATE"))
+ if (na->nc->HasExt("NS_PRIVATE"))
replacements["PRIVATE"];
- if (na->nc->HasExt("SECURE"))
+ if (na->nc->HasExt("NS_SECURE"))
replacements["SECURE"];
if (na->nc->HasExt("KILLPROTECT"))
replacements["KILL_ON"];
diff --git a/modules/extra/webcpanel/webcpanel.cpp b/modules/extra/webcpanel/webcpanel.cpp
index 4610c6235..c8926a150 100644
--- a/modules/extra/webcpanel/webcpanel.cpp
+++ b/modules/extra/webcpanel/webcpanel.cpp
@@ -15,6 +15,7 @@ class ModuleWebCPanel : public Module
{
ServiceReference<HTTPProvider> provider;
Panel panel;
+ PrimitiveExtensibleItem<Anope::string> id, ip;
StaticFileServer style_css, logo_png, favicon_ico;
@@ -43,7 +44,7 @@ class ModuleWebCPanel : public Module
public:
ModuleWebCPanel(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, EXTRA | VENDOR),
- panel(this, "webcpanel"),
+ panel(this, "webcpanel"), id(this, "webcpanel_id"), ip(this, "webcpanel_ip"),
style_css("style.css", "/static/style.css", "text/css"), logo_png("logo.png", "/static/logo.png", "image/png"), favicon_ico("favicon.ico", "/favicon.ico", "image/x-icon"),
index("/"), logout("/logout"), _register("/register"), confirm("/confirm"),
nickserv_info("NickServ", "/nickserv/info"), nickserv_cert("NickServ", "/nickserv/cert"), nickserv_access("NickServ", "/nickserv/access"), nickserv_alist("NickServ", "/nickserv/alist"),
diff --git a/modules/extra/webcpanel/webcpanel.h b/modules/extra/webcpanel/webcpanel.h
index 359bde32b..638a7c1c9 100644
--- a/modules/extra/webcpanel/webcpanel.h
+++ b/modules/extra/webcpanel/webcpanel.h
@@ -50,7 +50,7 @@ class Panel : public Section, public Service
if (na == NULL)
return NULL;
- Anope::string *n_id = na->GetExt<ExtensibleItemClass<Anope::string> *>("webcpanel_id"), *n_ip = na->GetExt<ExtensibleItemClass<Anope::string> *>("webcpanel_ip");
+ Anope::string *n_id = na->GetExt<Anope::string>("webcpanel_id"), *n_ip = na->GetExt<Anope::string>("webcpanel_ip");
if (n_id == NULL || n_ip == NULL)
return NULL;
else if (id != *n_id)
diff --git a/modules/fantasy.cpp b/modules/fantasy.cpp
new file mode 100644
index 000000000..01271392b
--- /dev/null
+++ b/modules/fantasy.cpp
@@ -0,0 +1,200 @@
+/* Fantasy functionality
+ *
+ * (C) 2003-2013 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 CommandBSSetFantasy : public Command
+{
+ public:
+ CommandBSSetFantasy(Module *creator, const Anope::string &sname = "botserv/set/fantasy") : Command(creator, sname, 2, 2)
+ {
+ this->SetDesc(_("Enable fantaisist commands"));
+ this->SetSyntax(_("\037channel\037 {\037ON|OFF\037}"));
+ }
+
+ void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
+ {
+ ChannelInfo *ci = ChannelInfo::Find(params[0]);
+ const Anope::string &value = params[1];
+
+ if (ci == NULL)
+ {
+ source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
+ return;
+ }
+
+ if (!source.HasPriv("botserv/administration") && !source.AccessFor(ci).HasPriv("SET"))
+ {
+ source.Reply(ACCESS_DENIED);
+ return;
+ }
+
+ if (Anope::ReadOnly)
+ {
+ source.Reply(_("Sorry, bot option setting is temporarily disabled."));
+ return;
+ }
+
+ if (value.equals_ci("ON"))
+ {
+ bool override = !source.AccessFor(ci).HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to enable fantasy";
+
+ ci->Extend<bool>("BS_FANTASY");
+ source.Reply(_("Fantasy mode is now \002on\002 on channel %s."), ci->name.c_str());
+ }
+ else if (value.equals_ci("OFF"))
+ {
+ bool override = !source.AccessFor(ci).HasPriv("SET");
+ Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to disable fantasy";
+
+ ci->Shrink<bool>("BS_FANTASY");
+ source.Reply(_("Fantasy mode is now \002off\002 on channel %s."), ci->name.c_str());
+ }
+ else
+ this->OnSyntaxError(source, source.command);
+ }
+
+ bool OnHelp(CommandSource &source, const Anope::string &) anope_override
+ {
+ this->SendSyntax(source);
+ source.Reply(_(" \n"
+ "Enables or disables \002fantasy\002 mode on a channel.\n"
+ "When it is enabled, users will be able to use\n"
+ "fantasy commands on a channel when prefixed\n"
+ "with one of the following fantasy characters: \002%s\002\n"
+ " \n"
+ "Note that users wanting to use fantaisist\n"
+ "commands MUST have enough access for both\n"
+ "the FANTASIA and the command they are executing."),
+ Config->GetModule(this->owner)->Get<const Anope::string>("fantasycharacter", "!").c_str());
+ return true;
+ }
+};
+
+class Fantasy : public Module
+{
+ SerializableExtensibleItem<bool> fantasy;
+
+ CommandBSSetFantasy commandbssetfantasy;
+
+ public:
+ Fantasy(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
+ fantasy(this, "BS_FANTASY"), commandbssetfantasy(this)
+ {
+ }
+
+ void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
+ {
+ if (!u || !c || !c->ci || !c->ci->bi || msg.empty() || msg[0] == '\1')
+ return;
+
+ if (!fantasy.HasExt(c->ci))
+ return;
+
+ std::vector<Anope::string> params;
+ spacesepstream(msg).GetTokens(params);
+
+ if (!msg.find(c->ci->bi->nick))
+ params.erase(params.begin());
+ else if (!msg.find_first_of(Config->GetModule(this)->Get<const Anope::string>("fantasycharacter", "!")))
+ params[0].erase(params[0].begin());
+ else
+ return;
+
+ if (params.empty())
+ return;
+
+ CommandInfo::map::const_iterator it = Config->Fantasy.end();
+ unsigned count = 0;
+ for (unsigned max = params.size(); it == Config->Fantasy.end() && max > 0; --max)
+ {
+ Anope::string full_command;
+ for (unsigned i = 0; i < max; ++i)
+ full_command += " " + params[i];
+ full_command.erase(full_command.begin());
+
+ ++count;
+ it = Config->Fantasy.find(full_command);
+ }
+
+ if (it == Config->Fantasy.end())
+ return;
+
+ const CommandInfo &info = it->second;
+ ServiceReference<Command> cmd("Command", info.name);
+ if (!cmd)
+ {
+ Log(LOG_DEBUG) << "Fantasy command " << it->first << " exists for nonexistant service " << info.name << "!";
+ return;
+ }
+
+ for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
+ params.erase(params.begin());
+
+ /* Some commands take the channel as a first parameter */
+ if (info.prepend_channel)
+ params.insert(params.begin(), c->name);
+
+ while (cmd->max_params > 0 && params.size() > cmd->max_params)
+ {
+ params[cmd->max_params - 1] += " " + params[cmd->max_params];
+ params.erase(params.begin() + cmd->max_params);
+ }
+
+ // Command requires registered users only
+ if (!cmd->AllowUnregistered() && !u->Account())
+ return;
+
+ if (params.size() < cmd->min_params)
+ return;
+
+ CommandSource source(u->nick, u, u->Account(), u, c->ci->bi);
+ source.c = c;
+ source.command = it->first;
+ source.permission = info.permission;
+
+ EventReturn MOD_RESULT;
+ if (c->ci->AccessFor(u).HasPriv("FANTASIA"))
+ {
+ FOREACH_RESULT(OnBotFantasy, MOD_RESULT, (source, cmd, c->ci, params));
+ }
+ else
+ {
+ FOREACH_RESULT(OnBotNoFantasyAccess, MOD_RESULT, (source, cmd, c->ci, params));
+ }
+
+ if (MOD_RESULT == EVENT_STOP || !c->ci->AccessFor(u).HasPriv("FANTASIA"))
+ return;
+
+ if (MOD_RESULT != EVENT_ALLOW && !info.permission.empty() && !source.HasCommand(info.permission))
+ return;
+
+ FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, cmd, params));
+ if (MOD_RESULT == EVENT_STOP)
+ return;
+
+ Reference<NickCore> nc_reference(u->Account());
+ cmd->Execute(source, params);
+ if (!nc_reference)
+ source.nc = NULL;
+ FOREACH_MOD(OnPostCommand, (source, cmd, params));
+ }
+
+ void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info)
+ {
+ if (fantasy.HasExt(ci))
+ info.AddOption(_("Fantasy"));
+ }
+};
+
+MODULE_INIT(Fantasy)
+
diff --git a/modules/m_dnsbl.cpp b/modules/m_dnsbl.cpp
index 8a238889f..b12476515 100644
--- a/modules/m_dnsbl.cpp
+++ b/modules/m_dnsbl.cpp
@@ -34,7 +34,7 @@ class DNSBLResolver : public Request
void OnLookupComplete(const Query *record) anope_override
{
- if (!user || user->HasExt("m_dnsbl_akilled"))
+ if (!user || user->Quitting())
return;
const ResourceRecord &ans_record = record->answers[0];
@@ -54,8 +54,6 @@ class DNSBLResolver : public Request
record_reason = this->blacklist.replies[result];
}
- user->Extend("m_dnsbl_akilled");
-
Anope::string reason = this->blacklist.reason;
reason = reason.replace_all_cs("%n", user->nick);
reason = reason.replace_all_cs("%u", user->GetIdent());
diff --git a/modules/m_helpchan.cpp b/modules/m_helpchan.cpp
index 7739fbcd5..0a3d68fae 100644
--- a/modules/m_helpchan.cpp
+++ b/modules/m_helpchan.cpp
@@ -14,9 +14,9 @@ class HelpChannel : public Module
{
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, const Anope::string &mname, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &param) anope_override
{
- if (mname == "OP" && c && c->ci && c->name.equals_ci(Config->GetModule(this)->Get<const Anope::string>("helpchannel")))
+ if (mode->name == "OP" && c && c->ci && c->name.equals_ci(Config->GetModule(this)->Get<const Anope::string>("helpchannel")))
{
User *u = User::Find(param);
diff --git a/modules/protocol/charybdis.cpp b/modules/protocol/charybdis.cpp
index cc9f8a58b..7d34da8d2 100644
--- a/modules/protocol/charybdis.cpp
+++ b/modules/protocol/charybdis.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
static bool sasl = true;
static Anope::string UplinkSID;
@@ -435,19 +436,24 @@ class ProtoCharybdis : public Module
void OnChannelSync(Channel *c) anope_override
{
- if (use_server_side_mlock && c->ci && Servers::Capab.count("MLOCK") > 0)
+ if (!c->ci)
+ return;
+
+ ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
+ if (use_server_side_mlock && modelocks && Servers::Capab.count("MLOCK") > 0)
{
- Anope::string modes = c->ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(c->creation_time) << " " << c->ci->name << " " << modes;
}
}
EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
}
@@ -456,10 +462,11 @@ class ProtoCharybdis : public Module
EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
}
diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp
index 3a2eb2d8a..876d387d1 100644
--- a/modules/protocol/inspircd12.cpp
+++ b/modules/protocol/inspircd12.cpp
@@ -947,7 +947,7 @@ struct IRCDMessageMetadata : IRCDMessage
User *u = User::Find(params[0]);
if (!u)
return;
- u->Extend("SSL");
+ u->Extend<bool>("ssl");
Anope::string data = params[2].c_str();
size_t pos1 = data.find(' ') + 1;
size_t pos2 = data.find(' ', pos1);
@@ -1271,6 +1271,7 @@ struct IRCDMessageEncap : IRCDMessage
class ProtoInspIRCd : public Module
{
InspIRCd12Proto ircd_proto;
+ ExtensibleItem<bool> ssl;
/* Core message handlers */
Message::Away message_away;
@@ -1311,7 +1312,7 @@ class ProtoInspIRCd : public Module
public:
ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL | VENDOR),
- ircd_proto(this),
+ ircd_proto(this), ssl(this, "ssl"),
message_away(this), message_error(this), message_invite(this), message_join(this), message_kick(this), message_kill(this),
message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this), message_squit(this),
message_stats(this), message_topic(this),
diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp
index 73f573e5b..c251b93b8 100644
--- a/modules/protocol/inspircd20.cpp
+++ b/modules/protocol/inspircd20.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
static unsigned int spanningtree_proto_ver = 0;
@@ -137,7 +138,7 @@ class InspIRCdExtBan : public ChannelModeList
{
Anope::string real_mask = mask.substr(2);
- if (Anope::Match(u->fingerprint, real_mask))
+ if (!u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask))
return true;
}
@@ -759,9 +760,10 @@ class ProtoInspIRCd : public Module
void OnChanRegistered(ChannelInfo *ci) anope_override
{
- if (use_server_side_mlock && ci->c && !ci->GetMLockAsString(false).empty())
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
+ if (use_server_side_mlock && ci->c && modelocks && !modelocks->GetMLockAsString(false).empty())
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
SendChannelMetadata(ci->c, "mlock", modes);
}
@@ -783,10 +785,11 @@ class ProtoInspIRCd : public Module
EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
+ if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
SendChannelMetadata(ci->c, "mlock", modes);
}
@@ -795,10 +798,11 @@ class ProtoInspIRCd : public Module
EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
+ if (use_server_side_mlock && cm && ci->c && modelocks && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM))
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
SendChannelMetadata(ci->c, "mlock", modes);
}
diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp
index 5e6534409..856a4aeb4 100644
--- a/modules/protocol/unreal.cpp
+++ b/modules/protocol/unreal.cpp
@@ -10,6 +10,7 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
static bool sasl = true;
@@ -1226,18 +1227,23 @@ class ProtoUnreal : public Module
void OnChannelSync(Channel *c) anope_override
{
- if (use_server_side_mlock && Servers::Capab.count("MLOCK") > 0 && c->ci)
+ if (!c->ci)
+ return;
+
+ ModeLocks *modelocks = c->ci->GetExt<ModeLocks>("modelocks");
+ if (use_server_side_mlock && Servers::Capab.count("MLOCK") > 0 && modelocks)
{
- Anope::string modes = c->ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(c->creation_time) << " " << c->ci->name << " " << modes;
}
}
void OnChanRegistered(ChannelInfo *ci) anope_override
{
- if (!ci->c || !use_server_side_mlock || !Servers::Capab.count("MLOCK"))
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
+ if (!ci->c || !use_server_side_mlock || !modelocks || !Servers::Capab.count("MLOCK"))
return;
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "");
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
}
@@ -1250,10 +1256,11 @@ class ProtoUnreal : public Module
EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "") + cm->mchar;
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
}
@@ -1262,10 +1269,11 @@ class ProtoUnreal : public Module
EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) anope_override
{
+ ModeLocks *modelocks = ci->GetExt<ModeLocks>("modelocks");
ChannelMode *cm = ModeManager::FindChannelModeByName(lock->name);
- if (use_server_side_mlock && cm && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
+ if (use_server_side_mlock && cm && modelocks && ci->c && (cm->type == MODE_REGULAR || cm->type == MODE_PARAM) && Servers::Capab.count("MLOCK") > 0)
{
- Anope::string modes = ci->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
+ Anope::string modes = modelocks->GetMLockAsString(false).replace_all_cs("+", "").replace_all_cs("-", "").replace_all_cs(cm->mchar, "");
UplinkSocket::Message(Me) << "MLOCK " << static_cast<long>(ci->c->creation_time) << " " << ci->name << " " << modes;
}
diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp
index 8322ad3c3..e8452de13 100644
--- a/modules/pseudoclients/botserv.cpp
+++ b/modules/pseudoclients/botserv.cpp
@@ -14,9 +14,11 @@
class BotServCore : public Module
{
Reference<BotInfo> BotServ;
+ ExtensibleRef<bool> persist, inhabit;
public:
- BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR)
+ BotServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
+ persist("persist"), inhabit("inhabit")
{
}
@@ -54,121 +56,6 @@ class BotServCore : public Module
}
}
- void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override
- {
- if (!u || !c || !c->ci || !c->ci->bi || msg.empty())
- return;
-
- /* Answer to ping if needed */
- if (msg.substr(0, 6).equals_ci("\1PING ") && msg[msg.length() - 1] == '\1')
- {
- Anope::string ctcp = msg;
- ctcp.erase(ctcp.begin());
- ctcp.erase(ctcp.length() - 1);
- IRCD->SendCTCP(c->ci->bi, u->nick, "%s", ctcp.c_str());
- }
-
- Anope::string realbuf = msg;
-
- if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1')
- {
- realbuf.erase(0, 8);
- realbuf.erase(realbuf.length() - 1);
- return;
- }
-
- if (realbuf.empty() || !c->ci->HasExt("BS_FANTASY"))
- return;
-
- std::vector<Anope::string> params;
- spacesepstream(realbuf).GetTokens(params);
-
- if (!realbuf.find(c->ci->bi->nick))
- params.erase(params.begin());
- else if (!realbuf.find_first_of(Config->GetModule(this)->Get<const Anope::string>("fantasycharacter", "!")))
- params[0].erase(params[0].begin());
- else
- return;
-
- if (params.empty())
- return;
-
- CommandInfo::map::const_iterator it = Config->Fantasy.end();
- unsigned count = 0;
- for (unsigned max = params.size(); it == Config->Fantasy.end() && max > 0; --max)
- {
- Anope::string full_command;
- for (unsigned i = 0; i < max; ++i)
- full_command += " " + params[i];
- full_command.erase(full_command.begin());
-
- ++count;
- it = Config->Fantasy.find(full_command);
- }
-
- if (it == Config->Fantasy.end())
- return;
-
- const CommandInfo &info = it->second;
- ServiceReference<Command> cmd("Command", info.name);
- if (!cmd)
- {
- Log(LOG_DEBUG) << "Fantasy command " << it->first << " exists for nonexistant service " << info.name << "!";
- return;
- }
-
- for (unsigned i = 0, j = params.size() - (count - 1); i < j; ++i)
- params.erase(params.begin());
-
- /* Some commands take the channel as a first parameter */
- if (info.prepend_channel)
- params.insert(params.begin(), c->name);
-
- while (cmd->max_params > 0 && params.size() > cmd->max_params)
- {
- params[cmd->max_params - 1] += " " + params[cmd->max_params];
- params.erase(params.begin() + cmd->max_params);
- }
-
- // Command requires registered users only
- if (!cmd->AllowUnregistered() && !u->Account())
- return;
-
- if (params.size() < cmd->min_params)
- return;
-
- CommandSource source(u->nick, u, u->Account(), u, c->ci->bi);
- source.c = c;
- source.command = it->first;
- source.permission = info.permission;
-
- EventReturn MOD_RESULT;
- if (c->ci->AccessFor(u).HasPriv("FANTASIA"))
- {
- FOREACH_RESULT(OnBotFantasy, MOD_RESULT, (source, cmd, c->ci, params));
- }
- else
- {
- FOREACH_RESULT(OnBotNoFantasyAccess, MOD_RESULT, (source, cmd, c->ci, params));
- }
-
- if (MOD_RESULT == EVENT_STOP || !c->ci->AccessFor(u).HasPriv("FANTASIA"))
- return;
-
- if (MOD_RESULT != EVENT_ALLOW && !info.permission.empty() && !source.HasCommand(info.permission))
- return;
-
- FOREACH_RESULT(OnPreCommand, MOD_RESULT, (source, cmd, params));
- if (MOD_RESULT == EVENT_STOP)
- return;
-
- Reference<NickCore> nc_reference(u->Account());
- cmd->Execute(source, params);
- if (!nc_reference)
- source.nc = NULL;
- FOREACH_MOD(OnPostCommand, (source, cmd, params));
- }
-
void OnJoinChannel(User *user, Channel *c) anope_override
{
if (!Config || !IRCD)
@@ -221,22 +108,13 @@ class BotServCore : public Module
ChannelStatus status(Config->GetModule(this)->Get<const Anope::string>("botmodes"));
c->ci->bi->Join(c, &status);
}
- /* Only display the greet if the main uplink we're connected
- * to has synced, or we'll get greet-floods when the net
- * recovers from a netsplit. -GD
- */
- if (c->FindUser(c->ci->bi) && c->ci->HasExt("BS_GREET") && user->Account() && !user->Account()->greet.empty() && c->ci->AccessFor(user).HasPriv("GREET") && user->server->IsSynced())
- {
- IRCD->SendPrivmsg(c->ci->bi, c->name, "[%s] %s", user->Account()->display.c_str(), user->Account()->greet.c_str());
- c->ci->bi->lastmsg = Anope::CurTime;
- }
}
}
void OnLeaveChannel(User *u, Channel *c) anope_override
{
/* Channel is persistent, it shouldn't be deleted and the service bot should stay */
- if (c->ci && c->ci->HasExt("PERSIST"))
+ if (c->ci && persist && persist->Get(c->ci))
return;
/* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediatly
@@ -246,7 +124,7 @@ class BotServCore : public Module
return;
/* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
- if (c->HasExt("INHABIT"))
+ if (inhabit && inhabit->Get(c))
return;
/* This is called prior to removing the user from the channnel, so c->users.size() - 1 should be safe */
@@ -304,9 +182,9 @@ class BotServCore : public Module
"one of the following characters: %s"), fantasycharacters.c_str());
}
- EventReturn OnChannelModeSet(Channel *c, MessageSource &, const Anope::string &mname, const Anope::string &param) anope_override
+ EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelMode *mode, const Anope::string &param) anope_override
{
- if (Config->GetModule(this)->Get<bool>("smartjoin") && mname == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
+ if (Config->GetModule(this)->Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
{
BotInfo *bi = c->ci->bi;
@@ -323,7 +201,7 @@ class BotServCore : public Module
/* Set default bot flags */
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
for (Anope::string token; sep.GetToken(token);)
- ci->ExtendMetadata("BS_" + token.upper());
+ ci->Extend<bool>("BS_" + token.upper());
}
void OnUserKicked(MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) anope_override
diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp
index a6871189c..2f7147cc6 100644
--- a/modules/pseudoclients/chanserv.cpp
+++ b/modules/pseudoclients/chanserv.cpp
@@ -10,15 +10,18 @@
*/
#include "module.h"
+#include "modules/cs_mode.h"
class ChanServCore : public Module, public ChanServService
{
Reference<BotInfo> ChanServ;
std::vector<Anope::string> defaults;
+ ExtensibleItem<bool> inhabit;
+ ExtensibleRef<bool> persist;
public:
ChanServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
- ChanServService(this)
+ ChanServService(this), inhabit(this, "inhabit"), persist("PERSIST")
{
}
@@ -30,17 +33,18 @@ class ChanServCore : public Module, public ChanServService
class ChanServTimer : public Timer
{
Reference<BotInfo> &ChanServ;
+ ExtensibleItem<bool> &inhabit;
Reference<Channel> c;
public:
/** Constructor
* @param chan The channel
*/
- ChanServTimer(Reference<BotInfo> &cs, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), c(chan)
+ ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan) : Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "15s")), ChanServ(cs), inhabit(i), c(chan)
{
if (!ChanServ || !c)
return;
- c->Extend("INHABIT");
+ inhabit.Set(c, true);
if (!c->ci || !c->ci->bi)
ChanServ->Join(c);
else if (!c->FindUser(c->ci->bi))
@@ -61,7 +65,7 @@ class ChanServCore : public Module, public ChanServService
if (!c)
return;
- c->Shrink("INHABIT");
+ inhabit.Unset(c);
if (!c->ci || !c->ci->bi)
{
@@ -73,10 +77,10 @@ class ChanServCore : public Module, public ChanServService
}
};
- if (c->HasExt("INHABIT"))
+ if (inhabit.HasExt(c))
return;
- new ChanServTimer(ChanServ, this->owner, c);
+ new ChanServTimer(ChanServ, inhabit, this->owner, c);
}
void OnReload(Configuration::Conf *conf) anope_override
@@ -96,7 +100,7 @@ class ChanServCore : public Module, public ChanServService
if (defaults.empty())
{
defaults.push_back("KEEPTOPIC");
- defaults.push_back("SECURE");
+ defaults.push_back("CS_SECURE");
defaults.push_back("SECUREFOUNDER");
defaults.push_back("SIGNKICK");
}
@@ -243,34 +247,9 @@ class ChanServCore : public Module, public ChanServService
void OnCreateChan(ChannelInfo *ci) anope_override
{
- ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
-
/* Set default chan flags */
for (unsigned i = 0; i < defaults.size(); ++i)
- ci->ExtendMetadata(defaults[i].upper());
-
- {
- Anope::string modes;
- spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("mlock", "+nrt"));
- if (sep.GetToken(modes))
- {
- bool add = true;
- for (unsigned i = 0; i < modes.length(); ++i)
- {
- if (modes[i] == '+')
- add = true;
- else if (modes[i] == '-')
- add = false;
- else
- {
- ChannelMode *cm = ModeManager::FindChannelModeByChar(modes[i]);
- Anope::string param;
- if (cm && (cm->type == MODE_REGULAR || sep.GetToken(param)))
- ci->SetMLock(cm, add, param);
- }
- }
- }
- }
+ ci->Extend<bool>(defaults[i].upper());
}
EventReturn OnCanSet(User *u, const ChannelMode *cm) anope_override
@@ -283,21 +262,13 @@ class ChanServCore : public Module, public ChanServService
void OnChannelSync(Channel *c) anope_override
{
- bool perm = c->HasMode("PERM") || (c->ci && c->ci->HasExt("PERSIST"));
- if (!perm && !c->HasExt("BOTCHANNEL") && (c->users.empty() || (c->users.size() == 1 && c->users.begin()->second->user->server == Me)))
+ bool perm = c->HasMode("PERM") || (c->ci && persist && persist->Get(c->ci));
+ if (!perm && !c->botchannel && (c->users.empty() || (c->users.size() == 1 && c->users.begin()->second->user->server == Me)))
{
this->Hold(c);
}
c->CheckModes();
- if (Me && Me->IsSynced() && c->ci)
- {
- /* Update channel topic */
- if ((c->ci->HasExt("KEEPTOPIC") || c->ci->HasExt("TOPICLOCK")) && c->ci->last_topic != c->topic)
- {
- c->ChangeTopic(!c->ci->last_topic_setter.empty() ? c->ci->last_topic_setter : c->ci->WhoSends()->nick, c->ci->last_topic, c->ci->last_topic_time ? c->ci->last_topic_time : Anope::CurTime);
- }
- }
}
EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason)
@@ -307,7 +278,7 @@ class ChanServCore : public Module, public ChanServService
* ChanServ always enforces channels like this to keep people from deleting bots etc
* that are holding channels.
*/
- if (c->ci && c->users.size() == (c->ci->bi && c->FindUser(c->ci->bi) ? 2 : 1) && !c->HasExt("INHABIT") && !c->syncing)
+ if (c->ci && c->users.size() == (c->ci->bi && c->FindUser(c->ci->bi) ? 2 : 1) && !inhabit.HasExt(c) && !c->syncing)
{
/* Join ChanServ and set a timer for this channel to part ChanServ later */
this->Hold(c);
@@ -349,18 +320,11 @@ class ChanServCore : public Module, public ChanServService
expire = true;
}
- if (ci->HasExt("NO_EXPIRE"))
- expire = false;
-
FOREACH_MOD(OnPreChanExpire, (ci, expire));
if (expire)
{
- Anope::string extra;
- if (ci->HasExt("SUSPENDED"))
- extra = "suspended ";
-
- Log(LOG_NORMAL, "chanserv/expire") << "Expiring " << extra << "channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")";
+ Log(LOG_NORMAL, "chanserv/expire") << "Expiring channel " << ci->name << " (founder: " << (ci->GetFounder() ? ci->GetFounder()->display : "(none)") << ")";
FOREACH_MOD(OnChanExpire, (ci));
delete ci;
}
@@ -370,11 +334,11 @@ class ChanServCore : public Module, public ChanServService
EventReturn OnCheckDelete(Channel *c) anope_override
{
/* Do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
- if (c->HasExt("INHABIT"))
+ if (inhabit.HasExt(c))
return EVENT_STOP;
/* Channel is persistent, it shouldn't be deleted and the service bot should stay */
- if (c->ci && c->ci->HasExt("PERSIST"))
+ if (c->ci && persist && persist->Get(c->ci))
return EVENT_STOP;
return EVENT_CONTINUE;
@@ -382,11 +346,13 @@ class ChanServCore : public Module, public ChanServService
void OnPreUplinkSync(Server *serv) anope_override
{
+ if (!persist)
+ return;
/* Find all persistent channels and create them, as we are about to finish burst to our uplink */
for (registered_channel_map::iterator it = RegisteredChannelList->begin(), it_end = RegisteredChannelList->end(); it != it_end; ++it)
{
ChannelInfo *ci = it->second;
- if (ci->HasExt("PERSIST"))
+ if (persist->Get(ci))
{
bool created;
ci->c = Channel::FindOrCreate(ci->name, created, ci->time_registered);
@@ -414,35 +380,15 @@ class ChanServCore : public Module, public ChanServService
void OnChanRegistered(ChannelInfo *ci) anope_override
{
+ if (!persist)
+ return;
/* Mark the channel as persistent */
if (ci->c->HasMode("PERM"))
- ci->ExtendMetadata("PERSIST");
+ persist->Unset(ci);
/* Persist may be in def cflags, set it here */
- else if (ci->HasExt("PERSIST"))
+ else if (persist->Get(ci))
ci->c->SetMode(NULL, "PERM");
}
-
- void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override
- {
- if (!c->ci)
- return;
-
- /* We only compare the topics here, not the time or setter. This is because some (old) IRCds do not
- * allow us to set the topic as someone else, meaning we have to bump the TS and change the setter to us.
- * This desyncs what is really set with what we have stored, and we end up resetting the topic often when
- * it is not required
- */
- if (c->ci->HasExt("TOPICLOCK") && c->ci->last_topic != c->topic)
- {
- c->ChangeTopic(c->ci->last_topic_setter, c->ci->last_topic, c->ci->last_topic_time);
- }
- else
- {
- c->ci->last_topic = c->topic;
- c->ci->last_topic_setter = c->topic_setter;
- c->ci->last_topic_time = c->topic_ts;
- }
- }
};
MODULE_INIT(ChanServCore)
diff --git a/modules/pseudoclients/nickserv.cpp b/modules/pseudoclients/nickserv.cpp
index f306b1b51..6730e91b9 100644
--- a/modules/pseudoclients/nickserv.cpp
+++ b/modules/pseudoclients/nickserv.cpp
@@ -46,12 +46,13 @@ class NickServHeld : public Timer
public:
NickServHeld(NickAlias *n, long l) : Timer(l), na(n), nick(na->nick)
{
+ n->Extend<bool>("HELD");
}
void Tick(time_t)
{
if (na)
- na->Shrink("HELD");
+ na->Shrink<bool>("HELD");
}
};
@@ -95,13 +96,13 @@ class NickServCore : public Module, public NickServService
{
Reference<BotInfo> NickServ;
std::vector<Anope::string> defaults;
+ ExtensibleItem<bool> held, collided;
void OnCancel(User *u, NickAlias *na)
{
- if (na->HasExt("COLLIDED"))
+ if (collided.HasExt(na))
{
- na->Extend("HELD");
- na->Shrink("COLLIDED");
+ collided.Unset(na);
new NickServHeld(na, Config->GetBlock("options")->Get<time_t>("releasetimeout"));
@@ -113,36 +114,48 @@ class NickServCore : public Module, public NickServService
}
public:
- NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR), NickServService(this)
+ NickServCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
+ NickServService(this), held(this, "HELD"), collided(this, "COLLIDED")
{
}
+ ~NickServCore()
+ {
+ OnShutdown();
+ }
+
+ void OnShutdown() anope_override
+ {
+ /* On shutdown, restart, or mod unload, remove all of our holds for nicks (svshold or qlines)
+ * because some IRCds do not allow us to have these automatically expire
+ */
+ for (nickalias_map::const_iterator it = NickAliasList->begin(); it != NickAliasList->end(); ++it)
+ this->Release(it->second);
+ }
+
+ void OnRestart() anope_override
+ {
+ OnShutdown();
+ }
+
void Validate(User *u) anope_override
{
NickAlias *na = NickAlias::Find(u->nick);
if (!na)
return;
- if (na->nc->HasExt("SUSPENDED"))
+ EventReturn MOD_RESULT;
+ FOREACH_RESULT(OnNickValidate, MOD_RESULT, (u, na));
+ if (MOD_RESULT == EVENT_STOP)
{
- u->SendMessage(NickServ, NICK_X_SUSPENDED, u->nick.c_str());
this->Collide(u, na);
return;
}
- if (!(u->Account() == na->nc) && !u->fingerprint.empty() && na->nc->FindCert(u->fingerprint))
- {
- u->SendMessage(NickServ, _("SSL Fingerprint accepted, you are now identified."));
- Log(u) << "automatically identified for account " << na->nc->display << " using a valid SSL fingerprint.";
- u->Identify(na);
- return;
- }
-
- if (!na->nc->HasExt("SECURE") && u->IsRecognized())
+ if (!na->nc->HasExt("NS_SECURE") && u->IsRecognized())
{
na->last_seen = Anope::CurTime;
- Anope::string last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
- na->last_usermask = last_usermask;
+ na->last_usermask = u->GetIdent() + "@" + u->GetDisplayedHost();
na->last_realname = u->realname;
return;
}
@@ -150,15 +163,16 @@ class NickServCore : public Module, public NickServService
if (Config->GetBlock("options")->Get<bool>("nonicknameownership"))
return;
- if (u->IsRecognized(false) || !na->nc->HasExt("KILL_IMMED"))
+ bool on_access = u->IsRecognized(false);
+
+ if (on_access || !na->nc->HasExt("KILL_IMMED"))
{
- if (na->nc->HasExt("SECURE"))
+ if (na->nc->HasExt("NS_SECURE"))
u->SendMessage(NickServ, NICK_IS_SECURE, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
else
u->SendMessage(NickServ, NICK_IS_REGISTERED, Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
}
-
- if (na->nc->HasExt("KILLPROTECT") && !u->IsRecognized(false))
+ if (na->nc->HasExt("KILLPROTECT") && !on_access)
{
if (na->nc->HasExt("KILL_IMMED"))
{
@@ -184,14 +198,14 @@ class NickServCore : public Module, public NickServService
void OnUserLogin(User *u) anope_override
{
NickAlias *na = NickAlias::Find(u->nick);
- if (na && *na->nc == u->Account() && !Config->GetBlock("options")->Get<bool>("nonicknameownership") && na->nc->HasExt("UNCONFIRMED") == false)
+ if (na && *na->nc == u->Account() && !Config->GetBlock("options")->Get<bool>("nonicknameownership") && !na->nc->HasExt("UNCONFIRMED"))
u->SetMode(NickServ, "REGISTERED");
}
void Collide(User *u, NickAlias *na) anope_override
{
if (na)
- na->Extend("COLLIDED");
+ collided.Set(na);
if (IRCD->CanSVSNick)
{
@@ -221,7 +235,7 @@ class NickServCore : public Module, public NickServService
void Release(NickAlias *na) anope_override
{
- if (na->HasExt("HELD"))
+ if (held.HasExt(na))
{
if (IRCD->CanSVSHold)
IRCD->SendSVSHoldDel(na->nick);
@@ -234,7 +248,7 @@ class NickServCore : public Module, public NickServService
}
}
- na->Shrink("HELD");
+ held.Unset(na);
}
}
@@ -251,10 +265,10 @@ class NickServCore : public Module, public NickServService
NickServ = bi;
- spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "secure memo_signon memo_receive")).GetTokens(defaults);
+ spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "ns_secure memo_signon memo_receive")).GetTokens(defaults);
if (defaults.empty())
{
- defaults.push_back("SECURE");
+ defaults.push_back("NS_SECURE");
defaults.push_back("MEMO_SIGNON");
defaults.push_back("MEMO_RECEIVE");
}
@@ -296,14 +310,8 @@ class NickServCore : public Module, public NickServService
{
Configuration::Block *block = Config->GetModule(this);
- if (!Config->GetBlock("options")->Get<bool>("nonicknameownership"))
- {
- const NickAlias *this_na = NickAlias::Find(u->nick);
- if (this_na && this_na->nc == u->Account() && u->Account()->HasExt("UNCONFIRMED") == false)
- u->SetMode(NickServ, "REGISTERED");
- }
-
if (block->Get<bool>("modeonid", "yes"))
+
for (User::ChanUserList::iterator it = u->chans.begin(), it_end = u->chans.end(); it != it_end; ++it)
{
ChanUserContainer *cc = it->second;
@@ -325,25 +333,11 @@ class NickServCore : public Module, public NickServService
"Your privacy is respected; this e-mail won't be given to\n"
"any third-party person."), Config->StrictPrivmsg.c_str(), NickServ->nick.c_str());
}
-
- if (u->Account()->HasExt("UNCONFIRMED"))
- {
- const Anope::string &nsregister = Config->GetModule("ns_register")->Get<const Anope::string>("registration");
- if (nsregister.equals_ci("admin"))
- u->SendMessage(NickServ, _("All new accounts must be validated by an administrator. Please wait for your registration to be confirmed."));
- else
- u->SendMessage(NickServ, _("Your email address is not confirmed. To confirm it, follow the instructions that were emailed to you when you registered."));
- const NickAlias *this_na = NickAlias::Find(u->Account()->display);
- time_t time_registered = Anope::CurTime - this_na->time_registered;
- time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
- if (unconfirmed_expire > time_registered)
- u->SendMessage(NickServ, _("Your account will expire, if not confirmed, in %s"), Anope::Duration(unconfirmed_expire - time_registered).c_str());
- }
}
void OnNickGroup(User *u, NickAlias *target) anope_override
{
- if (target->nc->HasExt("UNCONFIRMED") == false)
+ if (!target->nc->HasExt("UNCONFIRMED"))
u->SetMode(NickServ, "REGISTERED");
}
@@ -404,7 +398,7 @@ class NickServCore : public Module, public NickServService
{
/* Reset +r and re-send account (even though it really should be set at this point) */
IRCD->SendLogin(u);
- if (!Config->GetBlock("options")->Get<bool>("nonicknameownership") && na->nc == u->Account() && na->nc->HasExt("UNCONFIRMED") == false)
+ if (!Config->GetBlock("options")->Get<bool>("nonicknameownership") && na->nc == u->Account() && !na->nc->HasExt("UNCONFIRMED"))
u->SetMode(NickServ, "REGISTERED");
Log(NickServ) << u->GetMask() << " automatically identified for group " << u->Account()->display;
}
@@ -467,7 +461,7 @@ class NickServCore : public Module, public NickServService
{
/* Set default flags */
for (unsigned i = 0; i < defaults.size(); ++i)
- nc->ExtendMetadata(defaults[i].upper());
+ nc->Extend<bool>(defaults[i].upper());
}
void OnUserQuit(User *u, const Anope::string &msg)
@@ -489,7 +483,6 @@ class NickServCore : public Module, public NickServService
if (Anope::NoExpire || Anope::ReadOnly)
return;
- time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire");
for (nickalias_map::const_iterator it = NickAliasList->begin(), it_end = NickAliasList->end(); it != it_end; )
@@ -498,32 +491,39 @@ class NickServCore : public Module, public NickServService
++it;
User *u = User::Find(na->nick);
- if (u && (na->nc->HasExt("SECURE") ? u->IsIdentified(true) : u->IsRecognized()))
+ if (u && (na->nc->HasExt("NS_SECURE") ? u->IsIdentified(true) : u->IsRecognized()))
na->last_seen = Anope::CurTime;
bool expire = false;
- if (na->nc->HasExt("UNCONFIRMED"))
- if (unconfirmed_expire && Anope::CurTime - na->time_registered >= unconfirmed_expire)
- expire = true;
if (nickserv_expire && Anope::CurTime - na->last_seen >= nickserv_expire)
expire = true;
- if (na->HasExt("NO_EXPIRE"))
- expire = false;
FOREACH_MOD(OnPreNickExpire, (na, expire));
if (expire)
{
- Anope::string extra;
- if (na->nc->HasExt("SUSPENDED"))
- extra = "suspended ";
- Log(LOG_NORMAL, "expire") << "Expiring " << extra << "nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")";
+ Log(LOG_NORMAL, "expire") << "Expiring nickname " << na->nick << " (group: " << na->nc->display << ") (e-mail: " << (na->nc->email.empty() ? "none" : na->nc->email) << ")";
FOREACH_MOD(OnNickExpire, (na));
delete na;
}
}
}
+
+ void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) anope_override
+ {
+ if (!na->nc->HasExt("UNCONFIRMED"))
+ {
+ time_t nickserv_expire = Config->GetModule(this)->Get<time_t>("expire");
+ if (!na->HasExt("NS_NO_EXPIRE") && nickserv_expire && !Anope::NoExpire)
+ info[_("Expires")] = Anope::strftime(na->last_seen + nickserv_expire);
+ }
+ else
+ {
+ time_t unconfirmed_expire = Config->GetModule(this)->Get<time_t>("unconfirmedexpire", "1d");
+ info[_("Expires")] = Anope::strftime(na->time_registered + unconfirmed_expire);
+ }
+ }
};
MODULE_INIT(NickServCore)
diff --git a/src/bots.cpp b/src/bots.cpp
index 2ff4f5340..0a65393bb 100644
--- a/src/bots.cpp
+++ b/src/bots.cpp
@@ -80,7 +80,7 @@ void BotInfo::Serialize(Serialize::Data &data) const
data["created"] << this->created;
data["oper_only"] << this->oper_only;
- this->ExtensibleSerialize(data);
+ Extensible::ExtensibleSerialize(this, this, data);
}
Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
@@ -101,7 +101,7 @@ Serializable* BotInfo::Unserialize(Serializable *obj, Serialize::Data &data)
data["created"] >> bi->created;
data["oper_only"] >> bi->oper_only;
- bi->ExtensibleUnserialize(data);
+ Extensible::ExtensibleUnserialize(bi, bi, data);
return bi;
}
diff --git a/src/channels.cpp b/src/channels.cpp
index 9fdc44a49..0b790e54e 100644
--- a/src/channels.cpp
+++ b/src/channels.cpp
@@ -35,7 +35,7 @@ Channel::Channel(const Anope::string &nname, time_t ts)
this->name = nname;
this->creation_time = ts;
- this->syncing = false;
+ this->syncing = this->botchannel = false;
this->server_modetime = this->chanserv_modetime = 0;
this->server_modecount = this->chanserv_modecount = this->bouncy_modes = this->topic_ts = this->topic_time = 0;
@@ -108,48 +108,6 @@ void Channel::CheckModes()
FOREACH_RESULT(OnCheckModes, MOD_RESULT, (this));
if (MOD_RESULT == EVENT_STOP)
return;
-
- if (this->ci)
- for (ChannelInfo::ModeList::const_iterator it = this->ci->GetMLock().begin(), it_end = this->ci->GetMLock().end(); it != it_end; ++it)
- {
- const ModeLock *ml = it->second;
- ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
- if (!cm)
- continue;
-
- if (cm->type == MODE_REGULAR)
- {
- if (!this->HasMode(cm->name) && ml->set)
- this->SetMode(NULL, cm);
- else if (this->HasMode(cm->name) && !ml->set)
- this->RemoveMode(NULL, cm);
- }
- else if (cm->type == MODE_PARAM)
- {
- /* If the channel doesnt have the mode, or it does and it isn't set correctly */
- if (ml->set)
- {
- Anope::string param;
- this->GetParam(cm->name, param);
-
- if (!this->HasMode(cm->name) || (!param.empty() && !ml->param.empty() && !param.equals_cs(ml->param)))
- this->SetMode(NULL, cm, ml->param);
- }
- else
- {
- if (this->HasMode(cm->name))
- this->RemoveMode(NULL, cm);
- }
-
- }
- else if (cm->type == MODE_LIST)
- {
- if (ml->set)
- this->SetMode(NULL, cm, ml->param);
- else
- this->RemoveMode(NULL, cm, ml->param);
- }
- }
}
bool Channel::CheckDelete()
@@ -312,7 +270,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anop
if (cc)
cc->status.AddMode(cm->mchar);
- FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm->name, param));
+ FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
/* Enforce secureops, etc */
if (enforce_mlock && MOD_RESULT != EVENT_STOP)
@@ -336,7 +294,7 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anop
cml->OnAdd(this, param);
}
- FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm->name, param));
+ FOREACH_RESULT(OnChannelModeSet, MOD_RESULT, (this, setter, cm, param));
/* Check if we should enforce mlock */
if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
@@ -377,7 +335,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const A
if (cc)
cc->status.DelMode(cm->mchar);
- FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm->name, param));
+ FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
if (enforce_mlock && MOD_RESULT != EVENT_STOP)
this->SetCorrectModes(u, false);
@@ -404,7 +362,7 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const A
cml->OnDel(this, param);
}
- FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm->name, param));
+ FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param));
/* Check for mlock */
if (!enforce_mlock || MOD_RESULT == EVENT_STOP)
@@ -865,26 +823,6 @@ void Channel::SetCorrectModes(User *user, bool give_modes)
this->RemoveMode(NULL, cm, user->GetUID());
}
}
-
- // Check mlock
- for (ChannelInfo::ModeList::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 != this->HasUserStatus(user, ml->name))
- {
- if (ml->set)
- this->SetMode(NULL, cm, user->GetUID(), false);
- else if (!ml->set)
- this->RemoveMode(NULL, cm, user->GetUID(), false);
- }
- }
- }
}
bool Channel::Unban(User *u, bool full)
diff --git a/src/config.cpp b/src/config.cpp
index 4b16d8e97..8ba56bda2 100644
--- a/src/config.cpp
+++ b/src/config.cpp
@@ -339,7 +339,7 @@ Conf::Conf() : Block("")
if (!c)
continue; // Can't happen
- c->Extend("BOTCHANNEL");
+ c->botchannel = true;
/* Remove all existing modes */
ChanUserContainer *cu = c->FindUser(bi);
@@ -377,7 +377,7 @@ Conf::Conf() : Block("")
Channel *c = Channel::Find(chname);
if (c)
{
- c->Shrink("BOTCHANNEL");
+ c->botchannel = false;
bi->Part(c);
}
}
diff --git a/src/extensible.cpp b/src/extensible.cpp
index 25fa7938c..9284bdbf2 100644
--- a/src/extensible.cpp
+++ b/src/extensible.cpp
@@ -10,96 +10,63 @@
#include "extensible.h"
-Extensible::Extensible() : extension_items(NULL)
-{
-}
+static std::set<ExtensibleBase *> extensible_items;
-Extensible::~Extensible()
+ExtensibleBase::ExtensibleBase(Module *m, const Anope::string &n) : Service(m, "Extensible", n)
{
- if (extension_items)
- {
- for (extensible_map::iterator it = extension_items->begin(), it_end = extension_items->end(); it != it_end; ++it)
- delete it->second;
- delete extension_items;
- }
+ extensible_items.insert(this);
}
-void Extensible::Extend(const Anope::string &key, ExtensibleItem *p)
+ExtensibleBase::~ExtensibleBase()
{
- this->Shrink(key);
- if (!extension_items)
- extension_items = new extensible_map();
- (*this->extension_items)[key] = p;
+ extensible_items.erase(this);
}
-void Extensible::ExtendMetadata(const Anope::string &key, const Anope::string &value)
+Extensible::~Extensible()
{
- this->Extend(key, new ExtensibleMetadata(!value.empty() ? value : "1"));
+ for (std::set<ExtensibleBase *>::iterator it = extension_items.begin(); it != extension_items.end(); ++it)
+ (*it)->Unset(this);
}
-bool Extensible::Shrink(const Anope::string &key)
+bool Extensible::HasExt(const Anope::string &name) const
{
- if (!extension_items)
- return false;
-
- extensible_map::iterator it = this->extension_items->find(key);
- if (it != this->extension_items->end())
- {
- delete it->second;
- /* map::size_type map::erase( const key_type& key );
- * returns the number of elements removed, std::map
- * is single-associative so this should only be 0 or 1
- */
- return this->extension_items->erase(key) > 0;
- }
+ ExtensibleRef<void *> ref(name);
+ if (ref)
+ return ref->HasExt(this);
+ Log(LOG_DEBUG) << "HasExt for nonexistent type " << name << " on " << static_cast<const void *>(this);
return false;
}
-bool Extensible::HasExt(const Anope::string &key) const
+void Extensible::ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data)
{
- return this->extension_items != NULL && this->extension_items->count(key) > 0;
+ for (std::set<ExtensibleBase *>::iterator it = e->extension_items.begin(); it != e->extension_items.end(); ++it)
+ {
+ ExtensibleBase *eb = *it;
+ eb->ExtensibleSerialize(e, s, data);
+ }
}
-void Extensible::GetExtList(std::deque<Anope::string> &list) const
+void Extensible::ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data)
{
- if (extension_items)
- for (extensible_map::const_iterator it = extension_items->begin(), it_end = extension_items->end(); it != it_end; ++it)
- list.push_back(it->first);
-}
+ while (!e->extension_items.empty())
+ (*e->extension_items.begin())->Unset(e);
-void Extensible::ExtensibleSerialize(Serialize::Data &data) const
-{
- if (extension_items)
- for (extensible_map::const_iterator it = extension_items->begin(), it_end = extension_items->end(); it != it_end; ++it)
- if (it->second && it->second->Serialize())
- data["extensible:" + it->first] << *it->second->Serialize();
-}
-
-void Extensible::ExtensibleUnserialize(Serialize::Data &data)
-{
- /* Shrink existing extensible metadata items */
- std::deque<Anope::string> list;
- this->GetExtList(list);
- for (unsigned i = 0; i < list.size(); ++i)
+ for (std::set<ExtensibleBase *>::iterator it = extensible_items.begin(); it != extensible_items.end(); ++it)
{
- ExtensibleItem *item = extension_items->at(list[i]);
- if (item && item->Serialize())
- this->Shrink(list[i]);
+ ExtensibleBase *eb = *it;
+ eb->ExtensibleUnserialize(e, s, data);
}
-
- std::set<Anope::string> keys = data.KeySet();
- for (std::set<Anope::string>::iterator it = keys.begin(), it_end = keys.end(); it != it_end; ++it)
- if (it->find("extensible:") == 0)
- {
- if (!extension_items)
- extension_items = new extensible_map();
+}
- Anope::string str;
- data[*it] >> str;
+template<>
+bool* Extensible::Extend(const Anope::string &name, const bool &what)
+{
+ ExtensibleRef<bool> ref(name);
+ if (ref)
+ return ref->Set(this);
- if (!str.empty())
- this->ExtendMetadata(it->substr(11), str);
- }
+ Log(LOG_DEBUG) << "Shrink for nonexistant type " << name << " on " << static_cast<void *>(this);
+ return NULL;
}
diff --git a/src/misc.cpp b/src/misc.cpp
index fd08ffb2a..c9e18dc66 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -220,7 +220,7 @@ void InfoFormatter::Process(std::vector<Anope::string> &buffer)
Anope::string s;
for (unsigned i = it->first.length(); i < this->longest; ++i)
s += " ";
- s += Anope::string(Language::Translate(this->nc, it->first.c_str())) + ": " + it->second;
+ s += Anope::string(Language::Translate(this->nc, it->first.c_str())) + ": " + Language::Translate(this->nc, it->second.c_str());
buffer.push_back(s);
}
@@ -234,6 +234,25 @@ Anope::string& InfoFormatter::operator[](const Anope::string &key)
return this->replies.back().second;
}
+void InfoFormatter::AddOption(const Anope::string &opt)
+{
+ Anope::string *optstr = NULL;
+ for (std::vector<std::pair<Anope::string, Anope::string> >::iterator it = this->replies.begin(), it_end = this->replies.end(); it != it_end; ++it)
+ {
+ if (it->first == "Options")
+ {
+ optstr = &it->second;
+ break;
+ }
+ }
+ if (!optstr)
+ optstr = &(*this)["Options"];
+
+ if (!optstr->empty())
+ *optstr += ", ";
+ *optstr += Language::Translate(nc, opt.c_str());
+}
+
bool Anope::IsFile(const Anope::string &filename)
{
struct stat fileinfo;
diff --git a/src/nickalias.cpp b/src/nickalias.cpp
index 1595987e4..a50284cf4 100644
--- a/src/nickalias.cpp
+++ b/src/nickalias.cpp
@@ -140,7 +140,7 @@ void NickAlias::Serialize(Serialize::Data &data) const
data.SetType("time_registered", Serialize::Data::DT_INT); data["time_registered"] << this->time_registered;
data.SetType("time_registered", Serialize::Data::DT_INT); data["last_seen"] << this->last_seen;
data["nc"] << this->nc->display;
- this->ExtensibleSerialize(data);
+ Extensible::ExtensibleSerialize(this, this, data);
if (this->HasVhost())
{
@@ -189,7 +189,7 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
data["last_realhost"] >> na->last_realhost;
data["time_registered"] >> na->time_registered;
data["last_seen"] >> na->last_seen;
- na->ExtensibleUnserialize(data);
+ Extensible::ExtensibleUnserialize(na, na, data);
Anope::string vhost_ident, vhost_host, vhost_creator;
time_t vhost_time;
@@ -201,15 +201,6 @@ Serializable* NickAlias::Unserialize(Serializable *obj, Serialize::Data &data)
na->SetVhost(vhost_ident, vhost_host, vhost_creator, vhost_time);
- /* Compat */
- Anope::string sflags;
- data["flags"] >> sflags;
- spacesepstream sep(sflags);
- Anope::string tok;
- while (sep.GetToken(tok))
- na->ExtendMetadata(tok);
- /* End compat */
-
return na;
}
diff --git a/src/nickcore.cpp b/src/nickcore.cpp
index 5779767dd..9bbaae959 100644
--- a/src/nickcore.cpp
+++ b/src/nickcore.cpp
@@ -67,13 +67,10 @@ void NickCore::Serialize(Serialize::Data &data) const
data["display"] << this->display;
data["pass"] << this->pass;
data["email"] << this->email;
- data["greet"] << this->greet;
data["language"] << this->language;
- this->ExtensibleSerialize(data);
+ Extensible::ExtensibleSerialize(this, this, data);
for (unsigned i = 0; i < this->access.size(); ++i)
data["access"] << this->access[i] << " ";
- for (unsigned i = 0; i < this->cert.size(); ++i)
- data["cert"] << this->cert[i] << " ";
data["memomax"] << this->memos.memomax;
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
data["memoignores"] << this->memos.ignores[i] << " ";
@@ -94,9 +91,8 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
data["pass"] >> nc->pass;
data["email"] >> nc->email;
- data["greet"] >> nc->greet;
data["language"] >> nc->language;
- nc->ExtensibleUnserialize(data);
+ Extensible::ExtensibleUnserialize(nc, nc, data);
{
Anope::string buf;
data["access"] >> buf;
@@ -105,14 +101,6 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
while (sep.GetToken(buf))
nc->access.push_back(buf);
}
- {
- Anope::string buf;
- data["cert"] >> buf;
- spacesepstream sep(buf);
- nc->cert.clear();
- while (sep.GetToken(buf))
- nc->cert.push_back(buf);
- }
data["memomax"] >> nc->memos.memomax;
{
Anope::string buf;
@@ -123,14 +111,15 @@ Serializable* NickCore::Unserialize(Serializable *obj, Serialize::Data &data)
nc->memos.ignores.push_back(buf);
}
- /* Compat */
- Anope::string sflags;
- data["flags"] >> sflags;
- spacesepstream sep(sflags);
- Anope::string tok;
- while (sep.GetToken(tok))
- nc->ExtendMetadata(tok);
- /* End compat */
+ /* compat */
+ bool b;
+ data["extensible:SECURE"] >> b;
+ if (b)
+ nc->Extend<bool>("NS_SECURE");
+ data["extensible:PRIVATE"] >> b;
+ if (b)
+ nc->Extend<bool>("NS_PRIVATE");
+ /* end compat */
return nc;
}
@@ -216,45 +205,6 @@ bool NickCore::IsOnAccess(const User *u) const
return false;
}
-void NickCore::AddCert(const Anope::string &entry)
-{
- this->cert.push_back(entry);
- FOREACH_MOD(OnNickAddCert, (this, entry));
-}
-
-Anope::string NickCore::GetCert(unsigned entry) const
-{
- if (this->cert.empty() || entry >= this->cert.size())
- return "";
- return this->cert[entry];
-}
-
-bool NickCore::FindCert(const Anope::string &entry) const
-{
- for (unsigned i = 0, end = this->cert.size(); i < end; ++i)
- if (this->cert[i] == entry)
- return true;
-
- return false;
-}
-
-void NickCore::EraseCert(const Anope::string &entry)
-{
- for (unsigned i = 0, end = this->cert.size(); i < end; ++i)
- if (this->cert[i] == entry)
- {
- FOREACH_MOD(OnNickEraseCert, (this, entry));
- this->cert.erase(this->cert.begin() + i);
- break;
- }
-}
-
-void NickCore::ClearCert()
-{
- FOREACH_MOD(OnNickClearCert, (this));
- this->cert.clear();
-}
-
void NickCore::AddChannelReference(ChannelInfo *ci)
{
++(*this->chanaccess)[ci];
diff --git a/src/regchannel.cpp b/src/regchannel.cpp
index b1f056b27..e06f53690 100644
--- a/src/regchannel.cpp
+++ b/src/regchannel.cpp
@@ -22,54 +22,6 @@
Serialize::Checker<registered_channel_map> RegisteredChannelList("ChannelInfo");
-BadWord::BadWord() : Serializable("BadWord")
-{
-}
-
-BadWord::~BadWord()
-{
- if (this->ci)
- {
- std::vector<BadWord *>::iterator it = std::find(this->ci->badwords->begin(), this->ci->badwords->end(), this);
- if (it != this->ci->badwords->end())
- this->ci->badwords->erase(it);
- }
-}
-
-void BadWord::Serialize(Serialize::Data &data) const
-{
- data["ci"] << this->ci->name;
- data["word"] << this->word;
- data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
-}
-
-Serializable* BadWord::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string sci, sword;
-
- data["ci"] >> sci;
- data["word"] >> sword;
-
- ChannelInfo *ci = ChannelInfo::Find(sci);
- if (!ci)
- return NULL;
-
- unsigned int n;
- data["type"] >> n;
-
- BadWord *bw;
- if (obj)
- {
- bw = anope_dynamic_static_cast<BadWord *>(obj);
- data["word"] >> bw->word;
- bw->type = static_cast<BadWordType>(n);
- }
- else
- bw = ci->AddBadWord(sword, static_cast<BadWordType>(n));
-
- return bw;
-}
-
AutoKick::AutoKick() : Serializable("AutoKick")
{
}
@@ -145,122 +97,8 @@ Serializable* AutoKick::Unserialize(Serializable *obj, Serialize::Data &data)
return ak;
}
-ModeLock::ModeLock(ChannelInfo *ch, bool s, const Anope::string &n, const Anope::string &p, const Anope::string &se, time_t c) : Serializable("ModeLock"), ci(ch), set(s), name(n), param(p), setter(se), created(c)
-{
-}
-
-ModeLock::~ModeLock()
-{
- if (this->ci)
- this->ci->RemoveMLock(this);
-}
-
-void ModeLock::Serialize(Serialize::Data &data) const
-{
- if (!this->ci)
- return;
-
- data["ci"] << this->ci->name;
- data["set"] << this->set;
- data["name"] << this->name;
- data["param"] << this->param;
- data["setter"] << this->setter;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
-}
-
-Serializable* ModeLock::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string sci;
-
- data["ci"] >> sci;
-
- ChannelInfo *ci = ChannelInfo::Find(sci);
- if (!ci)
- return NULL;
-
- ModeLock *ml;
- if (obj)
- {
- ml = anope_dynamic_static_cast<ModeLock *>(obj);
-
- data["set"] >> ml->set;
- data["name"] >> ml->name;
- data["param"] >> ml->param;
- data["setter"] >> ml->setter;
- data["created"] >> ml->created;
- return ml;
- }
- else
- {
- bool set;
- data["set"] >> set;
-
- time_t created;
- data["created"] >> created;
-
- Anope::string setter;
- data["setter"] >> setter;
-
- Anope::string sname;
- data["name"] >> sname;
-
- ml = new ModeLock(ci, set, sname, "", setter, created);
- data["param"] >> ml->param;
-
- ci->mode_locks->insert(std::make_pair(ml->name, ml));
- return ml;
- }
-}
-
-void LogSetting::Serialize(Serialize::Data &data) const
-{
- if (!ci)
- return;
-
- data["ci"] << ci->name;
- data["service_name"] << service_name;
- data["command_service"] << command_service;
- data["command_name"] << command_name;
- data["method"] << method;
- data["extra"] << extra;
- data["creator"] << creator;
- data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
-}
-
-Serializable* LogSetting::Unserialize(Serializable *obj, Serialize::Data &data)
-{
- Anope::string sci;
-
- data["ci"] >> sci;
-
- ChannelInfo *ci = ChannelInfo::Find(sci);
- if (ci == NULL)
- return NULL;
-
- LogSetting *ls;
- if (obj)
- ls = anope_dynamic_static_cast<LogSetting *>(obj);
- else
- {
- ls = new LogSetting();
- ci->log_settings->push_back(ls);
- }
-
- ls->ci = ci;
- data["service_name"] >> ls->service_name;
- data["command_service"] >> ls->command_service;
- data["command_name"] >> ls->command_name;
- data["method"] >> ls->method;
- data["extra"] >> ls->extra;
- data["creator"] >> ls->creator;
- data["created"] >> ls->created;
-
- return ls;
-}
-
ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInfo"),
- access("ChanAccess"), akick("AutoKick"),
- badwords("BadWord"), mode_locks("ModeLock"), log_settings("LogSetting")
+ access("ChanAccess"), akick("AutoKick")
{
if (chname.empty())
throw CoreException("Empty channel passed to ChannelInfo constructor");
@@ -270,9 +108,6 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInf
this->c = Channel::Find(chname);
if (this->c)
this->c->ci = this;
- this->capsmin = this->capspercent = 0;
- this->floodlines = this->floodsecs = 0;
- this->repeattimes = 0;
this->banexpire = 0;
this->bi = NULL;
this->last_topic_time = 0;
@@ -283,9 +118,6 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInf
this->memos.memomax = 0;
this->last_used = this->time_registered = Anope::CurTime;
- for (int i = 0; i < TTB_SIZE; ++i)
- this->ttb[i] = 0;
-
size_t old = RegisteredChannelList->size();
(*RegisteredChannelList)[this->name] = this;
if (old == RegisteredChannelList->size())
@@ -295,8 +127,7 @@ ChannelInfo::ChannelInfo(const Anope::string &chname) : Serializable("ChannelInf
}
ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
- access("ChanAccess"), akick("AutoKick"),
- badwords("BadWord"), mode_locks("ModeLock"), log_settings("LogSetting")
+ access("ChanAccess"), akick("AutoKick")
{
*this = ci;
@@ -305,10 +136,6 @@ ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
this->access->clear();
this->akick->clear();
- this->badwords->clear();
-
- for (int i = 0; i < TTB_SIZE; ++i)
- this->ttb[i] = ci.ttb[i];
for (unsigned i = 0; i < ci.GetAccessCount(); ++i)
{
@@ -334,18 +161,6 @@ ChannelInfo::ChannelInfo(const ChannelInfo &ci) : Serializable("ChannelInfo"),
else
this->AddAkick(takick->creator, takick->mask, takick->reason, takick->addtime, takick->last_used);
}
- for (unsigned i = 0; i < ci.GetBadWordCount(); ++i)
- {
- const BadWord *bw = ci.GetBadWord(i);
- this->AddBadWord(bw->word, bw->type);
- }
-
- for (unsigned i = 0; i < ci.log_settings->size(); ++i)
- {
- LogSetting *l = new LogSetting(*ci.log_settings->at(i));
- l->ci = this;
- this->log_settings->push_back(l);
- }
FOREACH_MOD(OnCreateChan, (this));
}
@@ -379,14 +194,6 @@ ChannelInfo::~ChannelInfo()
this->ClearAccess();
this->ClearAkick();
- this->ClearBadWords();
-
- for (unsigned i = 0; i < this->log_settings->size(); ++i)
- delete this->log_settings->at(i);
- this->log_settings->clear();
-
- while (!this->mode_locks->empty())
- delete this->mode_locks->begin()->second;
if (!this->memos.memos->empty())
{
@@ -413,7 +220,7 @@ void ChannelInfo::Serialize(Serialize::Data &data) const
data["last_topic_setter"] << this->last_topic_setter;
data.SetType("last_topic_time", Serialize::Data::DT_INT); data["last_topic_time"] << this->last_topic_time;
data.SetType("bantype", Serialize::Data::DT_INT); data["bantype"] << this->bantype;
- this->ExtensibleSerialize(data);
+ Extensible::ExtensibleSerialize(this, this, data);
{
Anope::string levels_buffer;
for (Anope::map<int16_t>::const_iterator it = this->levels.begin(), it_end = this->levels.end(); it != it_end; ++it)
@@ -422,13 +229,6 @@ void ChannelInfo::Serialize(Serialize::Data &data) const
}
if (this->bi)
data["bi"] << this->bi->nick;
- for (int i = 0; i < TTB_SIZE; ++i)
- data["ttb"] << this->ttb[i] << " ";
- data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << this->capsmin;
- data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << this->capspercent;
- data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << this->floodlines;
- data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << this->floodsecs;
- data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << this->repeattimes;
data.SetType("banexpire", Serialize::Data::DT_INT); data["banexpire"] << this->banexpire;
data["memomax"] << this->memos.memomax;
for (unsigned i = 0; i < this->memos.ignores.size(); ++i)
@@ -451,7 +251,7 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
else
ci = new ChannelInfo(sname);
- ci->ExtensibleUnserialize(data);
+ Extensible::ExtensibleUnserialize(ci, ci, data);
ci->SetFounder(NickCore::Find(sfounder));
ci->SetSuccessor(NickCore::Find(ssuccessor));
@@ -477,23 +277,6 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
else if (ci->bi)
ci->bi->UnAssign(NULL, ci);
}
- {
- Anope::string ttb, tok;
- data["ttb"] >> ttb;
- spacesepstream sep(ttb);
- for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
- try
- {
- ci->ttb[i] = convertTo<int16_t>(tok);
- }
- catch (const ConvertException &) { }
-
- }
- data["capsmin"] >> ci->capsmin;
- data["capspercent"] >> ci->capspercent;
- data["floodlines"] >> ci->floodlines;
- data["floodsecs"] >> ci->floodsecs;
- data["repeattimes"] >> ci->repeattimes;
data["banexpire"] >> ci->banexpire;
data["memomax"] >> ci->memos.memomax;
{
@@ -505,18 +288,15 @@ Serializable* ChannelInfo::Unserialize(Serializable *obj, Serialize::Data &data)
ci->memos.ignores.push_back(buf);
}
- /* Compat */
- Anope::string sflags, sbotflags;
- data["flags"] >> sflags;
- data["botflags"] >> sbotflags;
- spacesepstream sep(sflags);
- Anope::string tok;
- while (sep.GetToken(tok))
- ci->ExtendMetadata(tok);
- spacesepstream sep2(sbotflags);
- while (sep2.GetToken(tok))
- ci->ExtendMetadata("BS_" + tok);
- /* End compat */
+ /* compat */
+ bool b;
+ data["extensible:SECURE"] >> b;
+ if (b)
+ ci->Extend<bool>("CS_SECURE");
+ data["extensible:PRIVATE"] >> b;
+ if (b)
+ ci->Extend<bool>("CS_PRIVATE");
+ /* end compat */
return ci;
}
@@ -603,7 +383,7 @@ AccessGroup ChannelInfo::AccessFor(const User *u)
return group;
const NickCore *nc = u->Account();
- if (nc == NULL && !this->HasExt("SECURE") && u->IsRecognized())
+ if (nc == NULL && !this->HasExt("NS_SECURE") && u->IsRecognized())
{
const NickAlias *na = NickAlias::Find(u->nick);
if (na != NULL)
@@ -756,256 +536,6 @@ void ChannelInfo::ClearAkick()
delete this->akick->back();
}
-BadWord* ChannelInfo::AddBadWord(const Anope::string &word, BadWordType type)
-{
- BadWord *bw = new BadWord();
- bw->ci = this;
- bw->word = word;
- bw->type = type;
-
- this->badwords->push_back(bw);
-
- FOREACH_MOD(OnBadWordAdd, (this, bw));
-
- return bw;
-}
-
-BadWord* ChannelInfo::GetBadWord(unsigned index) const
-{
- if (this->badwords->empty() || index >= this->badwords->size())
- return NULL;
-
- BadWord *bw = (*this->badwords)[index];
- bw->QueueUpdate();
- return bw;
-}
-
-unsigned ChannelInfo::GetBadWordCount() const
-{
- return this->badwords->size();
-}
-
-void ChannelInfo::EraseBadWord(unsigned index)
-{
- if (this->badwords->empty() || index >= this->badwords->size())
- return;
-
- FOREACH_MOD(OnBadWordDel, (this, (*this->badwords)[index]));
-
- delete this->badwords->at(index);
-}
-
-void ChannelInfo::ClearBadWords()
-{
- while (!this->badwords->empty())
- delete this->badwords->back();
-}
-
-bool ChannelInfo::HasMLock(ChannelMode *mode, const Anope::string &param, bool status) const
-{
- if (!mode)
- return false;
-
- std::multimap<Anope::string, ModeLock *>::const_iterator it = this->mode_locks->find(mode->name);
-
- if (it != this->mode_locks->end())
- {
- if (mode->type != MODE_REGULAR)
- {
- std::multimap<Anope::string, 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;
-}
-
-bool ChannelInfo::SetMLock(ChannelMode *mode, bool status, const Anope::string &param, Anope::string setter, time_t created)
-{
- if (!mode)
- return false;
-
- if (setter.empty())
- setter = this->founder ? this->founder->display : "Unknown";
- std::pair<Anope::string, ModeLock *> ml = std::make_pair(mode->name, new ModeLock(this, status, mode->name, param, setter, created));
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnMLock, MOD_RESULT, (this, ml.second));
- if (MOD_RESULT == EVENT_STOP)
- return false;
-
- /* First, remove this */
- if (mode->type == MODE_REGULAR || mode->type == MODE_PARAM)
- {
- for (ChannelInfo::ModeList::const_iterator it; (it = this->mode_locks->find(mode->name)) != this->mode_locks->end();)
- delete it->second;
- this->mode_locks->erase(mode->name);
- }
- else
- {
- // For list or status modes, we must check the parameter
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name);
- if (it != this->mode_locks->end())
- {
- ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mode->name);
- for (; it != it_end; ++it)
- {
- const ModeLock *modelock = it->second;
- if (modelock->param == param)
- {
- delete it->second;
- break;
- }
- }
- }
- }
-
- this->mode_locks->insert(ml);
-
- return true;
-}
-
-bool ChannelInfo::RemoveMLock(ChannelMode *mode, bool status, const Anope::string &param)
-{
- if (!mode)
- return false;
-
- if (mode->type == MODE_REGULAR || mode->type == MODE_PARAM)
- {
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name), it_end = this->mode_locks->upper_bound(mode->name), it_next = it;
- if (it != this->mode_locks->end())
- for (; it != it_end; it = it_next)
- {
- const ModeLock *ml = it->second;
- ++it_next;
-
- if (status != ml->set)
- continue;
-
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnUnMLock, MOD_RESULT, (this, it->second));
- if (MOD_RESULT != EVENT_STOP)
- {
- delete it->second;
- return true;
- }
- }
- return false;
- }
- else
- {
- // For list or status modes, we must check the parameter
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mode->name);
- if (it != this->mode_locks->end())
- {
- ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mode->name);
- for (; it != it_end; ++it)
- {
- const ModeLock *ml = it->second;
- if (ml->set == status && ml->param == param)
- {
- EventReturn MOD_RESULT;
- FOREACH_RESULT(OnUnMLock, MOD_RESULT, (this, it->second));
- if (MOD_RESULT == EVENT_STOP)
- return false;
- delete it->second;
- return true;
- }
- }
- }
-
- return false;
- }
-}
-
-void ChannelInfo::RemoveMLock(ModeLock *mlock)
-{
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mlock->name);
- if (it != this->mode_locks->end())
- for (; it != this->mode_locks->upper_bound(mlock->name); ++it)
- if (it->second == mlock)
- {
- this->mode_locks->erase(it);
- break;
- }
-}
-
-void ChannelInfo::ClearMLock()
-{
- while (!this->mode_locks->empty())
- delete this->mode_locks->begin()->second;
- this->mode_locks->clear();
-}
-
-const ChannelInfo::ModeList &ChannelInfo::GetMLock() const
-{
- return this->mode_locks;
-}
-
-std::pair<ChannelInfo::ModeList::iterator, ChannelInfo::ModeList::iterator> ChannelInfo::GetModeList(const Anope::string &mname)
-{
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mname), it_end = it;
- if (it != this->mode_locks->end())
- it_end = this->mode_locks->upper_bound(mname);
- return std::make_pair(it, it_end);
-}
-
-const ModeLock *ChannelInfo::GetMLock(const Anope::string &mname, const Anope::string &param)
-{
- ChannelInfo::ModeList::iterator it = this->mode_locks->find(mname);
- if (it != this->mode_locks->end())
- {
- if (param.empty())
- return it->second;
- else
- {
- ChannelInfo::ModeList::iterator it_end = this->mode_locks->upper_bound(mname);
- for (; it != it_end; ++it)
- {
- if (Anope::Match(param, it->second->param))
- return it->second;
- }
- }
- }
-
- return NULL;
-}
-
-Anope::string ChannelInfo::GetMLockAsString(bool complete) const
-{
- Anope::string pos = "+", neg = "-", params;
-
- for (ChannelInfo::ModeList::const_iterator it = this->GetMLock().begin(), it_end = this->GetMLock().end(); it != it_end; ++it)
- {
- const ModeLock *ml = it->second;
- ChannelMode *cm = ModeManager::FindChannelModeByName(ml->name);
- if (!cm || cm->type == MODE_LIST || cm->type == MODE_STATUS)
- continue;
-
- if (ml->set)
- pos += cm->mchar;
- else
- neg += cm->mchar;
-
- if (complete && !ml->param.empty() && cm->type == MODE_PARAM)
- params += " " + ml->param;
- }
-
- if (pos.length() == 1)
- pos.clear();
- if (neg.length() == 1)
- neg.clear();
-
- return pos + neg + params;
-}
-
int16_t ChannelInfo::GetLevel(const Anope::string &priv) const
{
if (PrivilegeManager::FindPrivilege(priv) == NULL)
diff --git a/src/serialize.cpp b/src/serialize.cpp
index ef79bc396..a957f3046 100644
--- a/src/serialize.cpp
+++ b/src/serialize.cpp
@@ -30,9 +30,8 @@ std::list<Serializable *> *Serializable::SerializableItems;
void Serialize::RegisterTypes()
{
static Type nc("NickCore", NickCore::Unserialize), na("NickAlias", NickAlias::Unserialize), bi("BotInfo", BotInfo::Unserialize),
- ci("ChannelInfo", ChannelInfo::Unserialize), access("ChanAccess", ChanAccess::Unserialize), logsetting("LogSetting", LogSetting::Unserialize),
- modelock("ModeLock", ModeLock::Unserialize), akick("AutoKick", AutoKick::Unserialize), badword("BadWord", BadWord::Unserialize),
- memo("Memo", Memo::Unserialize), xline("XLine", XLine::Unserialize);
+ ci("ChannelInfo", ChannelInfo::Unserialize), access("ChanAccess", ChanAccess::Unserialize),
+ akick("AutoKick", AutoKick::Unserialize), memo("Memo", Memo::Unserialize), xline("XLine", XLine::Unserialize);
}
void Serialize::CheckTypes()
diff --git a/src/sockets.cpp b/src/sockets.cpp
index e136324f9..e3065a1e8 100644
--- a/src/sockets.cpp
+++ b/src/sockets.cpp
@@ -259,7 +259,7 @@ bool cidr::match(const sockaddrs &other)
if (byte)
{
uint8_t m = ~0 << (8 - byte);
- return *ip & m == *their_ip & m;
+ return (*ip & m) == (*their_ip & m);
}
return true;
diff --git a/src/users.cpp b/src/users.cpp
index cd3c6b50f..7f9a49049 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -301,7 +301,6 @@ void User::Identify(NickAlias *na)
}
this->Login(na->nc);
- IRCD->SendLogin(this);
FOREACH_MOD(OnNickIdentify, (this));
@@ -336,6 +335,8 @@ void User::Login(NickCore *core)
this->UpdateHost();
+ IRCD->SendLogin(this);
+
if (this->server->IsSynced())
Log(this, "account") << "is now identified as " << this->nc->display;
@@ -378,7 +379,7 @@ bool User::IsRecognized(bool check_secure) const
{
const NickAlias *na = NickAlias::Find(this->nick);
- if (!na || na->nc->HasExt("SECURE"))
+ if (!na || na->nc->HasExt("NS_SECURE"))
return false;
}