mirror of
https://github.com/anope/anope.git
synced 2026-06-16 16:54:48 +02:00
Compare commits
111 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 390d0482fc | |||
| 65bb0a374b | |||
| ea4877dc16 | |||
| 4024598bd8 | |||
| a154532e98 | |||
| 665b0fdef8 | |||
| 0802d9d3ff | |||
| 8d3b8c08b3 | |||
| f3e5ccf353 | |||
| b5213d5a81 | |||
| dc09408f1a | |||
| 49d86527ef | |||
| 65183c3c49 | |||
| c60477384c | |||
| 25c3fd51b7 | |||
| a40eaeb2a3 | |||
| e14a650cb9 | |||
| 6401e328bb | |||
| 43dc6f7509 | |||
| 8f0ee6f383 | |||
| 1adbce61cb | |||
| fe60c9a085 | |||
| 39bb5825ad | |||
| 602ff60e21 | |||
| 8d0399e356 | |||
| a4d0213bcb | |||
| ecbf53ba6c | |||
| 6d72fd67d8 | |||
| 0a11bc7693 | |||
| e86fa67e38 | |||
| 1fc2642034 | |||
| 1641f6415a | |||
| bb1f93f150 | |||
| 85fbc500d8 | |||
| 99bcc6d3b7 | |||
| 5fd2145821 | |||
| 4700d48b35 | |||
| 019b2aafef | |||
| 3744649320 | |||
| 30593321f4 | |||
| 3b35199a53 | |||
| 5ac5e1068e | |||
| 0ebc43f0dc | |||
| 5ff86ea2c5 | |||
| 1bdc9c0a64 | |||
| d0d46408bc | |||
| fdc33b0f6d | |||
| 6a43370e13 | |||
| 1fcd045aff | |||
| b4d068b01a | |||
| 23d548336a | |||
| 82371dc279 | |||
| fd6770373f | |||
| 645f969d70 | |||
| 3187233783 | |||
| 8b932dc459 | |||
| a357ba38fb | |||
| 9f8525e3b2 | |||
| ace82596d8 | |||
| 09e10d2a02 | |||
| 9ec3f6abd6 | |||
| e7b18609f6 | |||
| cdcf0e2f9a | |||
| 718f2e922a | |||
| 2b2b6f75a1 | |||
| 883367c1d2 | |||
| 2276c62ff0 | |||
| fb0ee27df0 | |||
| b14befc77c | |||
| 64fd5a862a | |||
| 0ff170c671 | |||
| ea0d5c4d70 | |||
| b96dbfc9ba | |||
| e221c7642a | |||
| b8c28419da | |||
| 1c4f9042e7 | |||
| a3f483ad87 | |||
| 6e90a8ea55 | |||
| 6d7fe69cdf | |||
| 314ef60900 | |||
| 1e8ac58bb4 | |||
| badcf31499 | |||
| c98602bf19 | |||
| 50bec959e5 | |||
| 62bfa33464 | |||
| b4ab7dadb9 | |||
| df0cd3ef3e | |||
| 9e37a643f1 | |||
| b30bfb5d2b | |||
| cccdf0431b | |||
| 0005ebbbc3 | |||
| 161841925d | |||
| e099180d8f | |||
| 2091dc68bc | |||
| 9926ac5a05 | |||
| 14342f6375 | |||
| a0a9d433dc | |||
| c88fac1a20 | |||
| 64d26f7c61 | |||
| 34896cefe9 | |||
| c0c7046a6d | |||
| 937ea7dab4 | |||
| bfd2b0fa8e | |||
| 7f2c281121 | |||
| 224caf32c7 | |||
| 5828cdba45 | |||
| 4526fbed96 | |||
| f9911dde52 | |||
| a5e5eb5eb0 | |||
| 82aecd6c7e | |||
| b448a20f40 |
@@ -12,39 +12,49 @@ Charles Kingsley <chaz@anope.org>
|
||||
Charles Kingsley <chaz@anope.org> <sjaz@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Cronus <cronus@nite-serv.com>
|
||||
Daniel Engel <dane@zero.org> <dane dane@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <robbeh@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <rob rob@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
David Robson <rob@anope.org> <robbeh@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Dennis Friis <peavey@inspircd.org> <peavey peavey@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Dragone2 <dragone2@risposteinformatiche.it> <davide.paolini8@gmail.com>
|
||||
Fabio Scotoni <cculex@gmail.com>
|
||||
Filippo Cortigiani <simos@simosnap.org> <devel@devel.crtnet.it>
|
||||
Filippo Cortigiani <simos@simosnap.org> <simos@H7-25.fritz.box>
|
||||
Florian Schulze <certus@anope.org> <certus certus@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Gabriel Acevedo H. <drstein@anope.org> <drstein drstein@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Harakiri <harakiri@overstack.fr>
|
||||
Hendrik Jäger <gitcommit@henk.geekmail.org> <github@henk.geekmail.org>
|
||||
Jan Milants <viper@anope.org>
|
||||
Jan Milants <viper@anope.org> <jantje_85@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jan Milants <viper@anope.org> <viper viper@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jens Voss <dukepyrolator@anope.org> <anope@s15355730.onlinehome-server.info>
|
||||
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Jens Voss <dukepyrolator@anope.org> <DukePyrolator@anope.org>
|
||||
Jens Voss <dukepyrolator@anope.org> Jens Voß <jens@pyrobook.(none)>
|
||||
Jens Voss <dukepyrolator@anope.org> <jens@pyrobook.(none)>
|
||||
k4be <k4be@pirc.pl> <34816207+k4bek4be@users.noreply.github.com>
|
||||
Lee Holmes <lethality@anope.org>
|
||||
Lee Holmes <lethality@anope.org> <lee@lethality.me.uk>
|
||||
Mark Summers <mark@goopler.net> <mark mark@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Matt Schatz <genius3000@g3k.solutions>
|
||||
Matt Ullman <matt@airraidsirens.com> <blindsight@gamesurge.net>
|
||||
Michael Hazell <michaelhazell@hotmail.com> <Techman-@users.noreply.github.com>
|
||||
Michael Stapelberg <michael@robustirc.net> <stapelberg@users.noreply.github.com>
|
||||
Michael Wobst <wobst.michael@web.de>
|
||||
Michael Wobst <wobst.michael@web.de> <michael@static.163.129.251.148.clients.your-server.de>
|
||||
Michael Wobst <wobst.michael@web.de> <michael@wobst.at>
|
||||
Naram Qashat <cyberbotx@anope.org> <cyberbotx@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Naram Qashat <cyberbotx@anope.org> <cyberbotx@cyberbotx.com>
|
||||
Naram Qashat <cyberbotx@anope.org> <Naram Qashat cyberbotx@cyberbotx.com@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
PeGaSuS <droider.pc@gmail.com>
|
||||
PeGaSuS <droider.pc@gmail.com> <25697531+TehPeGaSuS@users.noreply.github.com>
|
||||
Pieter Bootsma <geniusdex@anope.org> <geniusdex geniusdex@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Robby <robby@chatbelgie.be> <robby@anope.org>
|
||||
Robby <robby@chatbelgie.be> <robby@chat.be>
|
||||
Robert Scheck <robert@fedoraproject.org> <robert-scheck@users.noreply.github.com>
|
||||
Robin Burchell <w00t@inspircd.org> <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Robin Burchell <w00t@inspircd.org> <Robin Burchell w00t@inspircd.org@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Sadie Powell <sadie@witchery.services> Peter Powell <petpow@saberuk.com>
|
||||
Sadie Powell <sadie@witchery.services> <petpow@saberuk.com>
|
||||
Sebastian Barfurth <github@afreshmelon.com>
|
||||
Sebastian V. <hal9000@denorastats.org>
|
||||
Sebastian V. <hal9000@denorastats.org> <pimpmylinux@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Trystan S. Lee <trystan@nomadirc.net> <trystan trystan@31f1291d-b8d6-0310-a050-a5561fc1590b@5417fbe8-f217-4b02-8779-1006273d7864>
|
||||
Val Lorentz <progval+git@progval.net> <progval+git@progval.net>
|
||||
|
||||
@@ -142,11 +142,6 @@ include_directories(
|
||||
${Anope_SOURCE_DIR}/vendor
|
||||
)
|
||||
|
||||
# Pass on REPRODUCIBLE_BUILD
|
||||
if(REPRODUCIBLE_BUILD)
|
||||
add_definitions(-DREPRODUCIBLE_BUILD)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# If using Windows, include the windows specific folder for anope_windows.h
|
||||
include_directories(${Anope_SOURCE_DIR}/src/win32)
|
||||
|
||||
@@ -113,6 +113,7 @@ while [ $# -ge 1 ] ; do
|
||||
exit 0
|
||||
elif [ $1 = "-devel" ] ; then
|
||||
DEBUG="yes"
|
||||
DEVEL="yes"
|
||||
INSTDIR="$SOURCE_DIR/run"
|
||||
elif [ $1 = "-nocache" ] ; then
|
||||
IGNORE_CACHE="1"
|
||||
@@ -171,6 +172,33 @@ export ok INPUT
|
||||
|
||||
####
|
||||
|
||||
TEMP_YN="n"
|
||||
if [ "$DEVEL" = "yes" ] ; then
|
||||
TEMP_YN="y"
|
||||
fi
|
||||
echo "You are building the 2.1 development branch. This branch is not as well tested"
|
||||
echo "as the 2.0 stable branch and may have compatibility breaks without notice. Are"
|
||||
echo "you sure you want to use this version?"
|
||||
echo -n "[$TEMP_YN] "
|
||||
read YN
|
||||
if [ "$YN" ] ; then
|
||||
if [ "$YN" = "y" ] ; then
|
||||
DEVEL="yes"
|
||||
else
|
||||
DEVEL="no"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
if [ "$DEVEL" != "yes" ] ; then
|
||||
echo "If you are building from Git you can run \`git checkout 2.0\` to get the latest"
|
||||
echo "stable code. Otherwise, you can download the latest 2.0 release tarball from"
|
||||
echo "https://github.com/anope/anope/releases/latest"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
ok=0
|
||||
echo "In what directory should Anope be installed?"
|
||||
while [ $ok -eq 0 ] ; do
|
||||
@@ -337,6 +365,7 @@ INSTDIR="$INSTDIR"
|
||||
RUNGROUP="$RUNGROUP"
|
||||
UMASK=$UMASK
|
||||
DEBUG="$DEBUG"
|
||||
DEVEL="$DEVEL"
|
||||
EXTRA_INCLUDE_DIRS="$EXTRA_INCLUDE_DIRS"
|
||||
EXTRA_LIB_DIRS="$EXTRA_LIB_DIRS"
|
||||
EXTRA_CONFIG_ARGS="$EXTRA_CONFIG_ARGS"
|
||||
|
||||
+74
-9
@@ -79,13 +79,16 @@
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can define values to other values, which can be used to easily change
|
||||
* many values in the configuration at once.
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for services clients hostnames.
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
@@ -211,7 +214,7 @@ serverinfo
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "services.example.com"
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
@@ -476,6 +479,18 @@ options
|
||||
*/
|
||||
didyoumeandifference = 4
|
||||
|
||||
/*
|
||||
* If set, the maximum number of bytes after which to wrap services messages. This
|
||||
* can be set a bit higher than the default but should be well under the maximum
|
||||
* message length imposed by your IRC server or messages will end up truncated.
|
||||
*
|
||||
* NOTE: this currently only applies to tables but will be expanded to all messages
|
||||
* in a later release.
|
||||
*
|
||||
* Defaults to 120 if not set.
|
||||
*/
|
||||
linelength = 120
|
||||
|
||||
/* The regex engine to use, as provided by the regex modules.
|
||||
* Leave commented to disable regex matching.
|
||||
*
|
||||
@@ -746,8 +761,8 @@ log
|
||||
* nickserv/getemail nickserv/suspend nickserv/ajoin nickserv/list
|
||||
*
|
||||
* nickserv/saset/autoop nickserv/saset/display nickserv/saset/email nickserv/saset/greet
|
||||
* nickserv/saset/kill nickserv/saset/keepmodes nickserv/saset/language nickserv/saset/message
|
||||
* nickserv/saset/neverop nickserv/saset/noexpire nickserv/saset/password nickserv/saset/private
|
||||
* nickserv/saset/keepmodes nickserv/saset/language nickserv/saset/message nickserv/saset/neverop
|
||||
* nickserv/saset/noexpire nickserv/saset/password nickserv/saset/private nickserv/saset/protect
|
||||
* nickserv/saset/url
|
||||
*
|
||||
* hostserv/set hostserv/del hostserv/list
|
||||
@@ -1087,11 +1102,9 @@ module
|
||||
* Sets the number of days backups of databases are kept. If you don't give it,
|
||||
* or if you set it to 0, Anope won't backup the databases.
|
||||
*
|
||||
* NOTE: Anope must run 24 hours a day for this feature to work.
|
||||
*
|
||||
* This directive is optional, but recommended.
|
||||
*/
|
||||
keepbackups = 3
|
||||
keepbackups = 7
|
||||
|
||||
/*
|
||||
* Allows Anope to continue file write operations (i.e. database saving)
|
||||
@@ -1116,6 +1129,58 @@ module
|
||||
fork = no
|
||||
}
|
||||
|
||||
/*
|
||||
* db_json
|
||||
*
|
||||
* Stores your data in a JSON file. This is currently experimental and has not
|
||||
* been fully tested so make sure you have db_flatfile loaded as a secondary
|
||||
* database module if you use this.
|
||||
*/
|
||||
#module
|
||||
{
|
||||
name = "db_json"
|
||||
|
||||
/*
|
||||
* The file that db_json will write your main database to.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
database = "anope.json"
|
||||
|
||||
/*
|
||||
* The file that db_json will write third-party databases to.
|
||||
*
|
||||
* {name} will be replaced with the name of the module.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
module_database = "{name}.module.json"
|
||||
|
||||
/*
|
||||
* Sets how many days worth of backups should be kept.
|
||||
*
|
||||
* It is recommended that at the very least you keep one backup. Failure to
|
||||
* do so may result in total data loss if you ever run out of disk space or
|
||||
* have a power failure during a database write. However, if you're *REALLY*
|
||||
* sure this won't happen you can disable backups by setting this to 0.
|
||||
*/
|
||||
backups = 14
|
||||
|
||||
/*
|
||||
* The directory in which backups are kept.
|
||||
*
|
||||
* This is relative to your data directory.
|
||||
*/
|
||||
backup_directory = "backups"
|
||||
|
||||
/*
|
||||
* Allows Anope to continue writing the database even if the original can
|
||||
* not be backed up. This is not recommended as it may result in total data
|
||||
* loss during the circumstances described above.
|
||||
*/
|
||||
#ignore_backup_failure = yes
|
||||
}
|
||||
|
||||
/*
|
||||
* db_sql and db_sql_live
|
||||
*
|
||||
|
||||
@@ -31,7 +31,7 @@ service
|
||||
/*
|
||||
* The hostname of the BotServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the BotServ client.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the ChanServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the ChanServ client.
|
||||
@@ -102,10 +102,10 @@ module
|
||||
* to be a registered nick, otherwise the channel will be dropped.
|
||||
* - none: No defaults
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to keeptopic, peace,
|
||||
* securefounder, and signkick. If you really want no defaults, use "none" by itself as the option.
|
||||
* This directive is optional, if left blank, the options will default to cs_keep_modes, keeptopic, peace,
|
||||
* persist, securefounder, and signkick. If you really want no defaults, use "none" by itself as the option.
|
||||
*/
|
||||
defaults = "keeptopic peace securefounder signkick"
|
||||
defaults = "cs_keep_modes keeptopic peace persist securefounder signkick"
|
||||
|
||||
/*
|
||||
* The maximum number of channels which may be registered to a single nickname.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the Global client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the Global client.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the HostServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the HostServ client.
|
||||
|
||||
@@ -18,7 +18,7 @@ service
|
||||
/*
|
||||
* The hostname of the StatServ client.
|
||||
*/
|
||||
host = "stats.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the StatServ client.
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the MemoServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the MemoServ client.
|
||||
|
||||
+28
-10
@@ -558,16 +558,6 @@ module
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sasl
|
||||
*
|
||||
* Some IRCds allow "SASL" authentication to let users identify to services
|
||||
* during the IRCd user registration process. If this module is loaded, Anope will allow
|
||||
* authenticating users through this mechanism. Supported mechanisms are:
|
||||
* PLAIN, EXTERNAL.
|
||||
*/
|
||||
module { name = "sasl" }
|
||||
|
||||
/*
|
||||
* ssl_gnutls [EXTRA]
|
||||
*
|
||||
@@ -815,6 +805,20 @@ module { name = "sasl" }
|
||||
|
||||
/* Web service to use. Requires httpd. */
|
||||
server = "httpd/main"
|
||||
|
||||
/*
|
||||
* Whether to enable the use of XML-RPC extensions.
|
||||
*
|
||||
* By default Anope will use some extended XML-RPC types. If your XML-RPC
|
||||
* client can not handle these you will need to disable them.
|
||||
*
|
||||
* If i8 is disabled a string will be used for values outside of the range
|
||||
* supported by the 32-bit int data type.
|
||||
*
|
||||
* If nil is disabled an empty struct will be used instead.
|
||||
*/
|
||||
#enable_i8 = no
|
||||
#enable_nil = no
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -841,6 +845,20 @@ module { name = "sasl" }
|
||||
*/
|
||||
#module { name = "rpc_main" }
|
||||
|
||||
/*
|
||||
* rpc_message
|
||||
*
|
||||
* Adds support for the following RPC methods:
|
||||
*
|
||||
* anope.messageNetwork anope.messageServer
|
||||
* anope.messageUser
|
||||
*
|
||||
* Requires either the jsonrpc or xmlrpc module.
|
||||
*
|
||||
* See docs/RPC/rpc_message.md for API documentation.
|
||||
*/
|
||||
#module { name = "rpc_message" }
|
||||
|
||||
/*
|
||||
* rpc_system
|
||||
*
|
||||
|
||||
+59
-34
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the NickServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the NickServ client.
|
||||
@@ -105,11 +105,6 @@ module
|
||||
* by spaces.
|
||||
*
|
||||
* The options are:
|
||||
* - killprotect: Kill nick if not identified within 60 seconds
|
||||
* - kill_quick: Kill nick if not identified within 20 seconds, this one overrides the killprotect
|
||||
* option and the killprotect option must be specified with this one
|
||||
* - kill_immed: Kill nick immediately if not identified, this one overrides both the killprotect
|
||||
* and kill_quick options and the killprotect option must be specified with this one
|
||||
* - ns_private: Hide the nick from NickServ's LIST command
|
||||
* - hide_email: Hide the nick's email address from NickServ's INFO command
|
||||
* - hide_mask: Hide the nick's last or current user@host from NickServ's INFO command
|
||||
@@ -122,11 +117,12 @@ module
|
||||
* - neverop: User can not be added to access lists
|
||||
* - msg: Messages will be sent as PRIVMSGs instead of NOTICEs
|
||||
* - ns_keep_modes: Enables keepmodes, which retains user modes across sessions
|
||||
* - protect: Protects the registered nickname from use by unidentified users.
|
||||
*
|
||||
* This directive is optional, if left blank, the options will default to memo_signon, and
|
||||
* memo_receive. If you really want no defaults, use "none" by itself as the option.
|
||||
*/
|
||||
defaults = "killprotect ns_private hide_email hide_mask memo_signon memo_receive autoop"
|
||||
defaults = "autoop hide_email hide_mask memo_receive memo_signon ns_private protect"
|
||||
|
||||
/*
|
||||
* The minimum length of time between consecutive uses of NickServ's REGISTER command. This
|
||||
@@ -171,11 +167,25 @@ module
|
||||
hidenetsplitquit = no
|
||||
|
||||
/*
|
||||
* If set, is the length of time NickServ's killquick and kill options wait before
|
||||
* forcing users off of protected nicknames.
|
||||
* The default period to force users to stop using a protected nickname after.
|
||||
*
|
||||
* Defaults to 1 minute.
|
||||
*/
|
||||
killquick = 20s
|
||||
kill = 60s
|
||||
defaultprotect = 1m
|
||||
|
||||
/*
|
||||
* The minimum period that a user can have a user forced off their protected nickname after.
|
||||
*
|
||||
* Defaults to 10 seconds.
|
||||
*/
|
||||
minprotect = 10s
|
||||
|
||||
/*
|
||||
* The maximum period that a user can have a user forced off their protected nickname after.
|
||||
*
|
||||
* Defaults to 10 minutes.
|
||||
*/
|
||||
maxprotect = 10m
|
||||
|
||||
/*
|
||||
* If set, forbids the registration of nicks that contain an existing
|
||||
@@ -196,7 +206,7 @@ module
|
||||
* hold a nickname.
|
||||
*/
|
||||
enforceruser = "enforcer"
|
||||
enforcerhost = "services.host"
|
||||
enforcerhost = "${services.host}"
|
||||
|
||||
/*
|
||||
* The length of time Anope should hold nicknames for.
|
||||
@@ -519,6 +529,27 @@ command { service = "NickServ"; name = "RESEND"; command = "nickserv/resend"; }
|
||||
module { name = "ns_resetpass" }
|
||||
command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpass"; }
|
||||
|
||||
/*
|
||||
* ns_sasl
|
||||
*
|
||||
* Provides support for authentication to services via IRCv3 SASL. This is a standardised
|
||||
* alternative to ns_identify that is supported by several IRCds.
|
||||
*
|
||||
* You will need to configure your IRCd to use SASL. See the following links for details:
|
||||
*
|
||||
* InspIRCd: https://docs.inspircd.org/4/modules/sasl/
|
||||
* UnrealIRCd: https://www.unrealircd.org/docs/SASL#Enabling_SASL_on_the_server
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "ns_sasl"
|
||||
|
||||
/*
|
||||
* The nick of the client which operates as the SASL agent.
|
||||
*/
|
||||
#agent = "NickServ"
|
||||
}
|
||||
|
||||
/*
|
||||
* ns_set
|
||||
*
|
||||
@@ -575,28 +606,6 @@ module
|
||||
command { service = "NickServ"; name = "SET KEEPMODES"; command = "nickserv/set/keepmodes"; }
|
||||
command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/saset/keepmodes"; permission = "nickserv/saset/keepmodes"; }
|
||||
|
||||
/*
|
||||
* ns_set_kill
|
||||
*
|
||||
* Provides the commands nickserv/set/kill and kickserv/saset/kill.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module
|
||||
{
|
||||
name = "ns_set_kill"
|
||||
|
||||
/*
|
||||
* Allow the use of the IMMED option in the NickServ SET KILL command.
|
||||
*
|
||||
* This directive is optional.
|
||||
*/
|
||||
#allowkillimmed = yes
|
||||
}
|
||||
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
/*
|
||||
* ns_set_language
|
||||
*
|
||||
@@ -641,6 +650,22 @@ command { service = "NickServ"; name = "SASET URL"; command = "nickserv/saset/mi
|
||||
#command { service = "NickServ"; name = "SET TIMEZONE"; command = "nickserv/set/misc"; misc_description = _("Associate a time zone with your account"); }
|
||||
#command { service = "NickServ"; name = "SASET TIMEZONE"; command = "nickserv/saset/misc"; misc_description = _("Associate a time zone with this account"); permission = "nickserv/saset/timezone"; group = "nickserv/admin"; }
|
||||
|
||||
/*
|
||||
* ns_set_protect
|
||||
*
|
||||
* Provides the commands nickserv/set/protect and kickserv/saset/protect.
|
||||
*
|
||||
* Used for configuring nickname protection.
|
||||
*/
|
||||
module { name = "ns_set_protect" }
|
||||
|
||||
command { service = "NickServ"; name = "SET PROTECT"; command = "nickserv/set/protect"; }
|
||||
command { service = "NickServ"; name = "SASET PROTECT"; command = "nickserv/saset/protect"; permission = "nickserv/saset/kill"; }
|
||||
|
||||
# For compatibility with Anope 2.0.
|
||||
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/protect"; hide = true; }
|
||||
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/protect"; permission = "nickserv/saset/protect"; hide = true; }
|
||||
|
||||
/*
|
||||
* ns_suspend
|
||||
*
|
||||
|
||||
@@ -21,7 +21,7 @@ service
|
||||
/*
|
||||
* The hostname of the OperServ client.
|
||||
*/
|
||||
host = "services.host"
|
||||
host = "${services.host}"
|
||||
|
||||
/*
|
||||
* The realname of the OperServ client.
|
||||
|
||||
@@ -79,17 +79,20 @@
|
||||
/*
|
||||
* [OPTIONAL] Defines
|
||||
*
|
||||
* You can define values to other values, which can be used to easily change
|
||||
* many values in the configuration at once.
|
||||
* You can use defines for repeated information, which can be used to easily change many
|
||||
* values in the configuration at once.
|
||||
*
|
||||
* To use a define called foo.bar you use ${foo.bar} in your config file. You can also use
|
||||
* environment variables by prefixing their name with "env." like ${env.USER}.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The stats.host define is used in multiple different locations throughout the
|
||||
* configuration for the stats client hostname.
|
||||
* The services.host define is used in multiple different locations throughout the
|
||||
* configuration for the server name and pseudoclient hostnames.
|
||||
*/
|
||||
define
|
||||
{
|
||||
name = "stats.host"
|
||||
name = "services.host"
|
||||
value = "stats.example.com"
|
||||
}
|
||||
|
||||
@@ -208,7 +211,7 @@ serverinfo
|
||||
* other server names on the rest of your IRC network. Note that it does not have
|
||||
* to be an existing hostname, just one that isn't on your network already.
|
||||
*/
|
||||
name = "stats.example.com"
|
||||
name = "${services.host}"
|
||||
|
||||
/*
|
||||
* The text which should appear as the server's information in /WHOIS and similar
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
Since the first commit in March 2004 88 people have submitted patches, commits,
|
||||
and other useful contributions to Anope. These people, ordered by the number of
|
||||
contributions they have made, are:
|
||||
|
||||
* Adam <adam@anope.org>
|
||||
* Sadie Powell <sadie@witchery.services>
|
||||
* Robin Burchell <w00t@inspircd.org>
|
||||
* Naram Qashat <cyberbotx@anope.org>
|
||||
* Pieter Bootsma <geniusdex@anope.org>
|
||||
* Jens Voss <dukepyrolator@anope.org>
|
||||
* David Robson <rob@anope.org>
|
||||
* Florian Schulze <certus@anope.org>
|
||||
* Daniel Engel <dane@zero.org>
|
||||
* Trystan S. Lee <trystan@nomadirc.net>
|
||||
* Robby <robby@chatbelgie.be>
|
||||
* Charles Kingsley <chaz@anope.org>
|
||||
* Lee Holmes <lethality@anope.org>
|
||||
* Gabriel Acevedo H. <drstein@anope.org>
|
||||
* Jan Milants <viper@anope.org>
|
||||
* Adam Kramer <ribosome@anope.org>
|
||||
* Attila Molnar <attilamolnar@hush.com>
|
||||
* Michael Wobst <wobst.michael@web.de>
|
||||
* Mark Summers <mark@goopler.net>
|
||||
* Matt Schatz <genius3000@g3k.solutions>
|
||||
* Daniel Vassdal <shutter@canternet.org>
|
||||
* MatthewM <mcm@they-got.us>
|
||||
* PeGaSuS <droider.pc@gmail.com>
|
||||
* Sebastian V. <hal9000@denorastats.org>
|
||||
* Alvaro Toledo <atoledo@keldon.org>
|
||||
* Dragone2 <dragone2@risposteinformatiche.it>
|
||||
* Björn Stiddien <keeper@anope.org>
|
||||
* n0kS Phr33d0m <god@politeia.in>
|
||||
* Hendrik Jäger <gitcommit@henk.geekmail.org>
|
||||
* k4be <k4be@pirc.pl>
|
||||
* Thomas Fargeix <t.fargeix@gmail.com>
|
||||
* Bram Matthys <syzop@vulnscan.org>
|
||||
* Federico G. Schwindt <fgsch@lodoss.net>
|
||||
* Val Lorentz <progval+git@progval.net>
|
||||
* Alexander Barton <alex@barton.de>
|
||||
* CaPa CuL <capacul@gmail.com>
|
||||
* Cronus <cronus@nite-serv.com>
|
||||
* H7-25 <simos@simosnap.org>
|
||||
* Jyzee <jyzee.git@gmail.com>
|
||||
* Sebastian Barfurth <github@afreshmelon.com>
|
||||
* Zantox <jyoerger10@msn.com>
|
||||
* Zoddo <zoddo.ino@gmail.com>
|
||||
* Dominic Hargreaves <dom@earth.li>
|
||||
* Michael Hazell <michaelhazell@hotmail.com>
|
||||
* Robert Scheck <robert@fedoraproject.org>
|
||||
* Dennis Friis <peavey@inspircd.org>
|
||||
* Filippo Cortigiani <simos@simosnap.org>
|
||||
* Michał Zegan <webczat_200@poczta.onet.pl>
|
||||
* AlphaTech <alphat3ch@icloud.com>
|
||||
* Austin Ellis <siniStar@IRC4Fun.net>
|
||||
* bonnedav <theD_2011@hotmail.com>
|
||||
* Denis M. (Phr33d0m) <god@politeia.in>
|
||||
* Harakiri <harakiri@overstack.fr>
|
||||
* Marcin Łabanowski <marcin@6irc.net>
|
||||
* Matt Ullman <matt@airraidsirens.com>
|
||||
* Michael Stapelberg <michael@robustirc.net>
|
||||
* Alexander Maassen <outsider@twingoversum.scarynet.org>
|
||||
* artemiiav <artemiiav@gmail.com>
|
||||
* blackbeard420 <blackbeard@blackbeard420.me>
|
||||
* BoGu5 <bogus@onzin.org>
|
||||
* Chris Langsenkamp <chris@langsenkamp.com>
|
||||
* Clem Morton
|
||||
* Daniel Oaks <danneh@danneh.net>
|
||||
* Fabio Scotoni <cculex@gmail.com>
|
||||
* ItsOnlyBinary
|
||||
* Jason Foster <retsofaj@gmail.com>
|
||||
* Jeremy <jeremy@ssnet.ca>
|
||||
* Josh Soref
|
||||
* KindOne <ineedalifetoday@live.com>
|
||||
* linuxdaemon
|
||||
* Mantas Mikulėnas <grawity@gmail.com>
|
||||
* Matthew Beeching <jobe@mdbnet.co.uk>
|
||||
* Michael <michaelhazell@hotmail.com>
|
||||
* Mingjie Shen <shen497@purdue.edu>
|
||||
* nekoswag
|
||||
* Peter Tseng <pht24@cornell.edu>
|
||||
* Romain Rivière <lecoyote@lecoyote.org>
|
||||
* Sam James (sam_c) <sam@cmpct.info>
|
||||
* ShutterQuick <shutter@canternet.org>
|
||||
* Sketch <denverfreeburn@outlook.com>
|
||||
* Tim Gunter <tim@vanillaforums.com>
|
||||
* Toni Kaija <diftraku@gmail.com>
|
||||
* Victor Coss <gtaxl@gtaxl.net>
|
||||
* VisioN <vision@myirc.us>
|
||||
* westor <westor7@gmail.com>
|
||||
* Wilson Birney <wpb@360scada.com>
|
||||
* Yann Sionneau <yann@sionneau.net>
|
||||
* Zach Bloomquist <zrbq@live.com>
|
||||
@@ -1,3 +1,39 @@
|
||||
Anope Version 2.1.13
|
||||
--------------------
|
||||
Added a Config check to ensure users actually want to use the development branch.
|
||||
Added a flag to the version string when Anope is compiled in reproducible mode.
|
||||
Added a warning on rehash when the max password is longer than the maximum bcrypt password length.
|
||||
Added an ALLTIME handler on InspIRCd.
|
||||
Added an opt-out for extended XML-RPC types.
|
||||
Added RPC messages for sending global messages.
|
||||
Added support for importing cs_set_misc and ns_set_misc data from Atheme.
|
||||
Added support for importing news from Atheme.
|
||||
Added support for oper-only quit messages.
|
||||
Added support for the experimental "services cloak" system from the InspIRCd development branch.
|
||||
Added support for using defines from the environment.
|
||||
Added support for using defines within the value of a variable.
|
||||
Blacklisted an old version of an UnrealIRCd module that is known to send malformed S2S messages.
|
||||
Changed RPC events to be registered as core services.
|
||||
Changed the database to refer to accounts by their account identifier instead of their display nick.
|
||||
Changed the syntax of defines from "foo" to "${foo}".
|
||||
Deduplicated JSON generation code in the jsonrpc module.
|
||||
Fixed a warning when importing an Atheme account that uses external authentication.
|
||||
Fixed counting email addresses in ns_maxemail.
|
||||
Fixed db_atheme creating duplicate accounts, bots, and nicks when importing over an existing database.
|
||||
Fixed deleting old database backups after Anope has been restarted.
|
||||
Fixed importing user metadata from Anope 1.8.
|
||||
Fixed including a port in uplink messages when connecting to a UNIX socket endpoint.
|
||||
Fixed memo ignores being erroneously case sensitive.
|
||||
Fixed modules with third-party dependencies writing generic log messages instead of module log messages.
|
||||
Fixed not performing SQL database updates in some rare circumstances.
|
||||
Fixed sending global messages with the default sender.
|
||||
Imported mkauthors from InspIRCd and used it to generate docs/AUTHORS.txt
|
||||
Moved around a bunch of module headers.
|
||||
Moved database serialization from the serializable to the serializable type.
|
||||
Moved the SASL protocol interface to its own service.
|
||||
Refactored handling S2S metadata on InspIRCd.
|
||||
Updated more messages to use gettext plural forms.
|
||||
|
||||
Anope Version 2.1.12
|
||||
--------------------
|
||||
Added an example JavaScript library for accessing the RPC interface.
|
||||
|
||||
+42
-23
@@ -1,3 +1,23 @@
|
||||
Anope Version 2.1.13
|
||||
--------------------
|
||||
Added options:linelength (defaults to 120).
|
||||
Added the db_json module.
|
||||
Added the rpc_message module.
|
||||
Added {nickserv}:defaultprotect (defaults to 1m).
|
||||
Added {nickserv}:maxprotect (defaults to 10m).
|
||||
Added {nickserv}:minprotect (defaults to 10s)
|
||||
Added {xmlrpc}:enable_i8 (defaults to yes).
|
||||
Added {xmlrpc}:enable_nil (defaults to yes).
|
||||
Changed the syntax for using defines (all existing defines will need to be updated).
|
||||
Removed {nickserv}:kill (replaced by custom protection timer durations).
|
||||
Removed {nickserv}:killquick (replaced by custom protection timer durations).
|
||||
Removed {ns_set_kill}:allowkillimmed (replaced by custom protection timer durations).
|
||||
Renamed the nickserv/saset/kill command to nickserv/saset/protect.
|
||||
Renamed the nickserv/saset/kill oper privilege to nickserv/saset/protect.
|
||||
Renamed the nickserv/set/kill command to nickserv/set/protect.
|
||||
Renamed the ns_set_kill module to ns_set_protect.
|
||||
Renamed the sasl module to ns_sasl and moved it to nickserv.example.conf.
|
||||
|
||||
Anope Version 2.1.12
|
||||
--------------------
|
||||
Added the jsonrpc module.
|
||||
@@ -11,16 +31,16 @@ Renamed the xmlrpc_main module to rpc_main.
|
||||
|
||||
Anope Version 2.1.11
|
||||
--------------------
|
||||
Moved {ns_set}:allowkillimmed to {ns_set_kill}:allowkillimmed.
|
||||
Moved nickserv/set/kill and nickserv/saset/kill to the ns_set_kill module.
|
||||
Replaced {nickserv}:guestnickprefix with {nickserv}:guestnick.
|
||||
Moved {ns_set}:allowkillimmed to {ns_set_kill}:allowkillimmed.
|
||||
Replaced {nickserv}:guestnickprefix with {nickserv}:guestnick (defaults to Guest####).
|
||||
|
||||
Anope Version 2.1.10
|
||||
--------------------
|
||||
Added options:servicealias.
|
||||
Added options:servicealias (defaults to no)
|
||||
Moved nickserv/set/message and nickserv/saset/message to the ns_set_message module.
|
||||
Removed options:useprivmsg.
|
||||
Removed options:usestrictprivmsg.
|
||||
Removed options:useprivmsg (replaced by loading the ns_set_message module to enable).
|
||||
Removed options:usestrictprivmsg (feature unusable on modern servers, consider migrating to options:servicealias instead).
|
||||
|
||||
Anope Version 2.1.9
|
||||
-------------------
|
||||
@@ -28,14 +48,14 @@ No significant changes.
|
||||
|
||||
Anope Version 2.1.8
|
||||
-------------------
|
||||
Added {nickserv}:preservedisplay.
|
||||
Added the nickserv/drop/display oper privilege.
|
||||
Added {nickserv}:preservedisplay (defaults to no).
|
||||
|
||||
Anope Version 2.1.7
|
||||
-------------------
|
||||
Moved nickserv/set/language and nickserv/saset/language to the ns_set_language module.
|
||||
Renamed the FANTASIA channel privilege to FANTASY.
|
||||
Renamed {cs_suspend}:expire to {cs_suspend}:suspendexpire.
|
||||
Renamed the FANTASIA privilege to FANTASY.
|
||||
|
||||
Anope Version 2.1.6
|
||||
-------------------
|
||||
@@ -55,8 +75,8 @@ Added the enc_posix module.
|
||||
Added the enc_sha2 module.
|
||||
Added the gl_queue module.
|
||||
Added the gl_server module.
|
||||
Added the global/queue operator privilege.
|
||||
Added the global/server operator privilege.
|
||||
Added the global/queue oper privilege.
|
||||
Added the global/server oper privilege.
|
||||
Changed serverinfo:motd to be relative to the config directory.
|
||||
Changed serverinfo:pid to be relative to the data directory.
|
||||
Changed the default value of mail:sendmailpath to "/usr/sbin/sendmail -it".
|
||||
@@ -64,13 +84,12 @@ Changed the default value of {chanserv}:accessmax to 1000.
|
||||
Changed the default value of {chanserv}:inhabit to 1 minute.
|
||||
Changed the default value of {cs_mode}:max to 50.
|
||||
Changed the default value of {ms_ignore}:max to 50.
|
||||
Removed options:seed.
|
||||
Replaced {webcpanel}:template with {webcpanel}:template_dir.
|
||||
|
||||
Removed options:seed (not needed with modern random number generation).
|
||||
Replaced {webcpanel}:template with {webcpanel}:template_dir (defaults to webcpanel/templates/default).
|
||||
|
||||
Anope Version 2.1.3
|
||||
-------------------
|
||||
Added options:didyoumeandifference.
|
||||
Added options:didyoumeandifference (defaults to 4).
|
||||
Added support for multiple SSL fingerprints in oper:certfp.
|
||||
Added the chanserv/cert oper privilege for modifying other user's certificate lists.
|
||||
Changed networkinfo:chanlen to default to 32 if not set.
|
||||
@@ -80,21 +99,21 @@ Changed networkinfo:nicklen to default to 31 if not set.
|
||||
Changed networkinfo:userlen to default to 10 if not set.
|
||||
Increased the default maximum password length to 50 characters.
|
||||
Increased the default minimum password length to 10 characters.
|
||||
Removed the cs_secure option in {chanserv}:defaults (now always enabled).
|
||||
Removed the nickserv/saset/secure command.
|
||||
Removed the nickserv/saset/secure oper privilege.
|
||||
Removed the nickserv/set/secure command.
|
||||
Removed the nickserv/status command.
|
||||
Removed the ns_access module.
|
||||
Removed the ns_secure option in {nickserv}:defaults (now always enabled).
|
||||
Removed the cs_secure option in {chanserv}:defaults (now always enabled as support for nick access lists has been removed).
|
||||
Removed the nickserv/saset/secure command (support for nick access lists has been removed).
|
||||
Removed the nickserv/saset/secure oper privilege (support for nick access lists has been removed).
|
||||
Removed the nickserv/set/secure command (support for nick access lists has been removed).
|
||||
Removed the nickserv/status command (obsolete with modern IRCv3 extensions and the removal of nick access lists).
|
||||
Removed the ns_access module (support for nick access lists has been removed).
|
||||
Removed the ns_secure option in {nickserv}:defaults (now always enabled as support for nick access lists has been removed).
|
||||
|
||||
Anope Version 2.1.2
|
||||
-------------------
|
||||
Added {ssl_openssl}:tlsv10 for configuring whether TLSv1.0 is usable (defaults to no).
|
||||
Added {ssl_openssl}:tlsv11 for configuring whether TLSv1.1 is usable (defaults to yes).
|
||||
Added {ssl_openssl}:tlsv12 for configuring whether TLSv1.2 is usable (defaults to yes).
|
||||
Removed {ssl_openssl}:sslv3 (now always disabled).
|
||||
Removed the m_ prefix from the names of the chanstats, dns, dnsbl, helpchan, httpd, ldap, ldap_oper, mysql, proxyscan, redis, regex_pcre2, regex_posix, regex_stdlib, regex_tre, rewrite, sasl, sql_log, sql_oper, sqlite, ssl_gnutls, ssl_openssl, xmlrpc, and xmlrpc_main modules.
|
||||
Removed {ssl_openssl}:sslv3 (now always disabled).
|
||||
|
||||
Anope Version 2.1.1
|
||||
-------------------
|
||||
@@ -104,7 +123,7 @@ Removed the m_regex_pcre module (use m_regex_pcre2 instead).
|
||||
Anope Version 2.1.0
|
||||
-------------------
|
||||
Added nickserv:minpasslen for configuring the minimum password length (defaults to 8).
|
||||
Removed nickserv:strictpasswords as it is obsolete now nickserv:minpasslen exists.
|
||||
Removed nickserv:strictpasswords (obsolete now nickserv:minpasslen exists).
|
||||
Removed the inspircd12 and inspircd20 modules (use inspircd instead).
|
||||
Removed the ns_getpass module (no supported encryption modules).
|
||||
Removed the os_oline module (no supported IRCds).
|
||||
@@ -113,4 +132,4 @@ Renamed nickserv:passlen to nickserv:maxpasslen.
|
||||
Renamed the charybdis module to solanum.
|
||||
Renamed the inspircd3 module to inspircd.
|
||||
Renamed the unreal4 module to unrealircd.
|
||||
Replaced uplink:ipv6 with uplink:protocol.
|
||||
Replaced uplink:ipv6 with uplink:protocol (defaults to ipv4).
|
||||
|
||||
@@ -13,8 +13,6 @@ command - Takes three parameters, a service name (BotServ, ChanServ, NickServ),
|
||||
|
||||
stats - Takes no parameters, returns miscellaneous stats that can be found in the /operserv stats command.
|
||||
|
||||
notice - Takes three parameters, source user, target user, and message. Sends a message to the user.
|
||||
|
||||
RPC was designed to be used with db_sql, and will not return any information that can be pulled from the SQL
|
||||
database, such as accounts and registered channel information. It is instead used for pulling realtime data such
|
||||
as users and channels currently online. For examples on how to use these calls in PHP, see xmlrpc.php in docs/RPC.
|
||||
|
||||
@@ -47,6 +47,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of channels.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listChannels() {
|
||||
@@ -56,6 +58,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves information about the specified channel.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the channel.
|
||||
* @returns {object} An object containing information about the channel.
|
||||
*/
|
||||
@@ -66,6 +70,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of services operators.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listOpers() {
|
||||
@@ -75,6 +81,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves information about the specified services operator.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the services operator.
|
||||
* @returns {object} An object containing information about the services operator.
|
||||
*/
|
||||
@@ -85,6 +93,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of servers.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @returns {array} An array of servers names.
|
||||
*/
|
||||
listServers() {
|
||||
@@ -94,6 +104,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves information about the specified server.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the server.
|
||||
* @returns {object} An object containing information about the server.
|
||||
*/
|
||||
@@ -104,6 +116,8 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves a list of users.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @returns {array} An array of channel names.
|
||||
*/
|
||||
listUsers() {
|
||||
@@ -113,12 +127,50 @@ class AnopeRPC {
|
||||
/**
|
||||
* Retrieves information about the specified user.
|
||||
*
|
||||
* Requires the rpc_data module to be loaded.
|
||||
*
|
||||
* @param {string} nick The nick of the user.
|
||||
* @returns {object} An object containing information about the user.
|
||||
*/
|
||||
user(nick) {
|
||||
return this.run("anope.user", nick);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to every user on the network.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageNetwork(...messages) {
|
||||
return this.run("anope.messageNetwork", ...messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to every user on the specified server.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {string} name The name of the server.
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageServer(server, ...messages) {
|
||||
return this.run("anope.messageServer", server, ...messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the specified user.
|
||||
*
|
||||
* Requires the rpc_message module to be loaded.
|
||||
*
|
||||
* @param {string} source The source pseudoclient to send the message from.
|
||||
* @param {string} target The target user to send the message to.
|
||||
* @param {...*} messages One or more messages to send.
|
||||
*/
|
||||
messageUser(source, target, ...messages) {
|
||||
return this.run("anope.messageUser", source, target, ...messages);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -132,7 +132,7 @@ class AnopeRPC
|
||||
*/
|
||||
public function notice($source, $target, $message)
|
||||
{
|
||||
return $this->run("notice", [$source, $target, $message]);
|
||||
return $this->run("anope.messageUser", [$source, $target, $message]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# Anope `rpc_message` RPC interface
|
||||
|
||||
## `anope.messageNetwork`
|
||||
|
||||
Sends a message to all users on the network.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The global service is not available.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
## `anope.messageServer`
|
||||
|
||||
Sends a message to all users on the specified server.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | The name of the server to message users on.
|
||||
1+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The global service is not available.
|
||||
-32098 | The specified server does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
## `anope.messageUser`
|
||||
|
||||
Sends a message to the specified user.
|
||||
|
||||
### Parameters
|
||||
|
||||
Index | Description
|
||||
----- | -----------
|
||||
0 | The source pseudoclient to send the message from.
|
||||
1 | The target user to send the message to.
|
||||
2+ | One or more messages to send.
|
||||
|
||||
### Errors
|
||||
|
||||
Code | Description
|
||||
------ | -----------
|
||||
-32099 | The specified source does not exist.
|
||||
-32098 | The specified target does not exist.
|
||||
|
||||
### Result
|
||||
|
||||
This procedure returns no result.
|
||||
|
||||
+10
-3
@@ -74,6 +74,16 @@ public:
|
||||
class CoreExport ChanAccess
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
Anope::string mask;
|
||||
/* account this access entry is for, if any */
|
||||
Serialize::Reference<NickCore> nc;
|
||||
@@ -97,9 +107,6 @@ public:
|
||||
const Anope::string &Mask() const;
|
||||
NickCore *GetAccount() const;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
static const unsigned int MAX_DEPTH = 4;
|
||||
|
||||
/** Check if this access entry matches the given user or account
|
||||
|
||||
+22
-6
@@ -32,6 +32,16 @@ class CoreExport NickAlias final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
Anope::string vhost_ident, vhost_host, vhost_creator;
|
||||
time_t vhost_created = 0;
|
||||
|
||||
@@ -56,9 +66,6 @@ public:
|
||||
NickAlias(const Anope::string &nickname, NickCore *nickcore);
|
||||
~NickAlias();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Set a vhost for the user
|
||||
* @param ident The ident
|
||||
* @param host The host
|
||||
@@ -106,6 +113,7 @@ public:
|
||||
* @return the nick, if found
|
||||
*/
|
||||
static NickAlias *Find(const Anope::string &nick);
|
||||
static NickAlias *FindId(uint64_t id);
|
||||
};
|
||||
|
||||
/* A registered account. Each account must have a NickAlias with the same nick as the
|
||||
@@ -116,6 +124,16 @@ class CoreExport NickCore final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* Channels which reference this core in some way (this is on their access list, akick list, is founder, successor, etc) */
|
||||
Serialize::Checker<std::map<ChannelInfo *, int> > chanaccess;
|
||||
/* Unique identifier for the account. */
|
||||
@@ -159,9 +177,6 @@ public:
|
||||
NickCore(const Anope::string &nickdisplay, uint64_t nickid = 0);
|
||||
~NickCore();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Changes the display for this account
|
||||
* @param na The new display, must be grouped to this account.
|
||||
*/
|
||||
@@ -180,6 +195,7 @@ public:
|
||||
* @return The account, if it exists
|
||||
*/
|
||||
static NickCore *Find(const Anope::string &nick);
|
||||
static NickCore *FindId(uint64_t id);
|
||||
|
||||
void AddChannelReference(ChannelInfo *ci);
|
||||
void RemoveChannelReference(ChannelInfo *ci);
|
||||
|
||||
+1
-1
@@ -346,7 +346,7 @@ namespace Anope
|
||||
template<typename T>
|
||||
using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
|
||||
|
||||
#ifndef REPRODUCIBLE_BUILD
|
||||
#if !REPRODUCIBLE_BUILD
|
||||
static const char *const compiled = __TIME__ " " __DATE__;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@ class CoreExport BotInfo final
|
||||
: public User
|
||||
, public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* Channels this bot is assigned to */
|
||||
Serialize::Checker<std::set<ChannelInfo *> > channels;
|
||||
public:
|
||||
|
||||
+9
-9
@@ -50,9 +50,9 @@ public:
|
||||
/* When the channel was created */
|
||||
time_t creation_time;
|
||||
/* If the channel has just been created in a netjoin */
|
||||
bool syncing;
|
||||
bool syncing = false;
|
||||
/* Is configured in the conf as a channel bots should be in */
|
||||
bool botchannel;
|
||||
bool botchannel = false;
|
||||
|
||||
/* Users in the channel */
|
||||
typedef std::map<User *, ChanUserContainer *> ChanUserList;
|
||||
@@ -66,15 +66,15 @@ public:
|
||||
* This is the time the topic was *originally set*. When we restore the topic we want to change the TS back
|
||||
* to this, but we can only do this on certain IRCds.
|
||||
*/
|
||||
time_t topic_ts;
|
||||
time_t topic_ts = 0;
|
||||
/* The actual time the topic was set, probably close to Anope::CurTime */
|
||||
time_t topic_time;
|
||||
time_t topic_time = 0;
|
||||
|
||||
time_t server_modetime; /* Time of last server MODE */
|
||||
time_t chanserv_modetime; /* Time of last check_modes() */
|
||||
int16_t server_modecount; /* Number of server MODEs this second */
|
||||
int16_t chanserv_modecount; /* Number of check_mode()'s this sec */
|
||||
int16_t bouncy_modes; /* Did we fail to set modes here? */
|
||||
time_t server_modetime = 0; /* Time of last server MODE */
|
||||
time_t chanserv_modetime = 0; /* Time of last check_modes() */
|
||||
int16_t server_modecount = 0; /* Number of server MODEs this second */
|
||||
int16_t chanserv_modecount = 0; /* Number of check_mode()'s this sec */
|
||||
bool bouncy_modes = false; /* Did we fail to set modes here? */
|
||||
|
||||
private:
|
||||
/** Constructor
|
||||
|
||||
+13
-7
@@ -22,7 +22,7 @@ namespace Configuration
|
||||
{
|
||||
class CoreExport Block
|
||||
{
|
||||
friend struct Configuration::Conf;
|
||||
friend class Configuration::Conf;
|
||||
|
||||
public:
|
||||
typedef Anope::map<Anope::string> item_map;
|
||||
@@ -41,7 +41,7 @@ namespace Configuration
|
||||
Block(const Anope::string &);
|
||||
const Anope::string &GetName() const;
|
||||
int CountBlock(const Anope::string &name) const;
|
||||
const Block *GetBlock(const Anope::string &name, int num = 0) const;
|
||||
const Block &GetBlock(const Anope::string &name, int num = 0) const;
|
||||
Block *GetMutableBlock(const Anope::string &name, int num = 0);
|
||||
|
||||
template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
|
||||
@@ -83,9 +83,14 @@ namespace Configuration
|
||||
|
||||
struct Uplink;
|
||||
|
||||
struct CoreExport Conf final
|
||||
: Block
|
||||
class CoreExport Conf final
|
||||
: public Block
|
||||
{
|
||||
private:
|
||||
/** Replaces defined variables within a string. */
|
||||
Anope::string ReplaceVars(const Anope::string &str, const File &file, int linenumber);
|
||||
|
||||
public:
|
||||
/* options:readtimeout */
|
||||
time_t ReadTimeout;
|
||||
/* If we should default to privmsging clients */
|
||||
@@ -126,12 +131,12 @@ namespace Configuration
|
||||
void LoadConf(File &file);
|
||||
void Post(Conf *old);
|
||||
|
||||
Block *GetModule(const Module *);
|
||||
Block *GetModule(const Anope::string &name);
|
||||
Block &GetModule(const Module *);
|
||||
Block &GetModule(const Anope::string &name);
|
||||
|
||||
BotInfo *GetClient(const Anope::string &name);
|
||||
|
||||
const Block *GetCommand(CommandSource &);
|
||||
const Block &GetCommand(CommandSource &);
|
||||
};
|
||||
|
||||
struct Uplink final
|
||||
@@ -144,6 +149,7 @@ namespace Configuration
|
||||
Uplink(const Anope::string &_host, int _port, const Anope::string &_password, int _protocol) : host(_host), port(_port), password(_password), protocol(_protocol) { }
|
||||
inline bool operator==(const Uplink &other) const { return host == other.host && port == other.port && password == other.password && protocol == other.protocol; }
|
||||
inline bool operator!=(const Uplink &other) const { return !(*this == other); }
|
||||
Anope::string str() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ struct ChanUserContainer;
|
||||
class ClientSocket;
|
||||
class Command;
|
||||
class CommandSource;
|
||||
namespace Configuration { struct Conf; }
|
||||
namespace Configuration { class Conf; }
|
||||
class ConnectionSocket;
|
||||
namespace DNS { struct Query; }
|
||||
class Entry;
|
||||
|
||||
+9
-4
@@ -18,15 +18,20 @@ class CoreExport Memo final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
MemoInfo *mi;
|
||||
bool unread;
|
||||
bool receipt;
|
||||
Memo();
|
||||
~Memo();
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
Anope::string owner;
|
||||
/* When it was sent */
|
||||
time_t time;
|
||||
@@ -41,7 +46,7 @@ struct CoreExport MemoInfo final
|
||||
{
|
||||
int16_t memomax = 0;
|
||||
Serialize::Checker<std::vector<Memo *> > memos;
|
||||
std::vector<Anope::string> ignores;
|
||||
std::set<Anope::string, ci::less> ignores;
|
||||
|
||||
MemoInfo();
|
||||
Memo *GetMemo(unsigned index) const;
|
||||
|
||||
+4
-4
@@ -45,7 +45,7 @@
|
||||
#include "users.h"
|
||||
#include "xline.h"
|
||||
|
||||
#include "modules/pseudoclients/chanserv.h"
|
||||
#include "modules/pseudoclients/global.h"
|
||||
#include "modules/pseudoclients/memoserv.h"
|
||||
#include "modules/pseudoclients/nickserv.h"
|
||||
#include "modules/chanserv/service.h"
|
||||
#include "modules/global/service.h"
|
||||
#include "modules/memoserv/service.h"
|
||||
#include "modules/nickserv/service.h"
|
||||
|
||||
+1
-1
@@ -305,7 +305,7 @@ public:
|
||||
* @param conf The config that is being built now and will replace the global Config object
|
||||
* @throws A ConfigException to abort the config (re)loading process.
|
||||
*/
|
||||
virtual void OnReload(Configuration::Conf *conf) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
|
||||
virtual void OnReload(Configuration::Conf &conf) { throw NotImplementedException(); }
|
||||
|
||||
/** Called before a bot is assigned to a channel.
|
||||
* @param sender The user assigning the bot
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2014-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace SASL
|
||||
{
|
||||
struct Message final
|
||||
{
|
||||
Anope::string source;
|
||||
Anope::string target;
|
||||
Anope::string type;
|
||||
std::vector<Anope::string> data;
|
||||
};
|
||||
|
||||
class Mechanism;
|
||||
struct Session;
|
||||
|
||||
class Service
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { }
|
||||
|
||||
virtual void ProcessMessage(const Message &) = 0;
|
||||
|
||||
virtual Session *GetSession(const Anope::string &uid) = 0;
|
||||
|
||||
virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0;
|
||||
|
||||
virtual void Succeed(Session *, NickCore *) = 0;
|
||||
virtual void Fail(Session *) = 0;
|
||||
virtual void DeleteSessions(Mechanism *, bool = false) = 0;
|
||||
virtual void RemoveSession(Session *) = 0;
|
||||
};
|
||||
|
||||
static ServiceReference<SASL::Service> service("SASL::Service", "sasl");
|
||||
|
||||
struct Session
|
||||
{
|
||||
time_t created;
|
||||
Anope::string uid;
|
||||
Anope::string hostname, ip;
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
|
||||
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
|
||||
virtual ~Session()
|
||||
{
|
||||
if (service)
|
||||
service->RemoveSession(this);
|
||||
}
|
||||
};
|
||||
|
||||
/* PLAIN, EXTERNAL, etc */
|
||||
class Mechanism
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
|
||||
|
||||
virtual Session *CreateSession(const Anope::string &uid) { return new Session(this, uid); }
|
||||
|
||||
virtual bool ProcessMessage(Session *session, const Message &) = 0;
|
||||
|
||||
virtual ~Mechanism()
|
||||
{
|
||||
if (service)
|
||||
service->DeleteSessions(this, true);
|
||||
}
|
||||
};
|
||||
|
||||
/** Sends IRCd messages used by the SASL module. */
|
||||
class ProtocolInterface
|
||||
: public ::Service
|
||||
{
|
||||
protected:
|
||||
ProtocolInterface(Module *o)
|
||||
: ::Service(o, "SASL::ProtocolInterface", "sasl")
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/** Sends the list of SASL mechanisms to the IRCd
|
||||
* @param mechs The list of SASL mechanisms.
|
||||
*/
|
||||
virtual void SendSASLMechanisms(std::vector<Anope::string> &mechs) { };
|
||||
|
||||
/** Sends a SASL message to the IRCd.
|
||||
* @param message The SASL message to send.
|
||||
*/
|
||||
virtual void SendSASLMessage(const SASL::Message &message) = 0;
|
||||
|
||||
/** Sends a login or logout for \p uid to \p na.
|
||||
* @param uid The uid of the user to log in.
|
||||
* @param na The nick alias to log the user in as or logout if nullptr.
|
||||
*/
|
||||
virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) = 0;
|
||||
};
|
||||
|
||||
static ServiceReference<SASL::ProtocolInterface> protocol_interface("SASL::ProtocolInterface", "sasl");
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2011-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct MyOper final
|
||||
: Oper
|
||||
, Serializable
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
|
||||
};
|
||||
@@ -28,8 +28,6 @@ struct Exception final
|
||||
time_t expires; /* Time when it expires. 0 == no expiry */
|
||||
|
||||
Exception() : Serializable("Exception") { }
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
class SessionService
|
||||
@@ -59,35 +57,3 @@ public:
|
||||
};
|
||||
|
||||
static ServiceReference<SessionService> session_service("SessionService", "session");
|
||||
|
||||
void Exception::Serialize(Serialize::Data &data) const
|
||||
{
|
||||
data.Store("mask", this->mask);
|
||||
data.Store("limit", this->limit);
|
||||
data.Store("who", this->who);
|
||||
data.Store("reason", this->reason);
|
||||
data.Store("time", this->time);
|
||||
data.Store("expires", this->expires);
|
||||
}
|
||||
|
||||
Serializable *Exception::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
if (!session_service)
|
||||
return NULL;
|
||||
|
||||
Exception *ex;
|
||||
if (obj)
|
||||
ex = anope_dynamic_static_cast<Exception *>(obj);
|
||||
else
|
||||
ex = new Exception;
|
||||
data["mask"] >> ex->mask;
|
||||
data["limit"] >> ex->limit;
|
||||
data["who"] >> ex->who;
|
||||
data["reason"] >> ex->reason;
|
||||
data["time"] >> ex->time;
|
||||
data["expires"] >> ex->expires;
|
||||
|
||||
if (!obj)
|
||||
session_service->AddException(ex);
|
||||
return ex;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2011-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct MyOper final
|
||||
: Oper
|
||||
, Serializable
|
||||
{
|
||||
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
{
|
||||
data.Store("name", this->name);
|
||||
data.Store("type", this->ot->GetName());
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
{
|
||||
Anope::string stype, sname;
|
||||
|
||||
data["type"] >> stype;
|
||||
data["name"] >> sname;
|
||||
|
||||
OperType *ot = OperType::Find(stype);
|
||||
if (ot == NULL)
|
||||
return NULL;
|
||||
NickCore *nc = NickCore::Find(sname);
|
||||
if (nc == NULL)
|
||||
return NULL;
|
||||
|
||||
MyOper *myo;
|
||||
if (obj)
|
||||
myo = anope_dynamic_static_cast<MyOper *>(obj);
|
||||
else
|
||||
myo = new MyOper(nc->display, ot);
|
||||
nc->o = myo;
|
||||
Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
|
||||
return myo;
|
||||
}
|
||||
};
|
||||
+7
-16
@@ -21,9 +21,6 @@ namespace RPC
|
||||
class ServiceInterface;
|
||||
class Value;
|
||||
|
||||
/** Represents a list of registered events. */
|
||||
using Events = Anope::map<Event *>;
|
||||
|
||||
/** Represents possible types of RPC value. */
|
||||
using ValueUnion = std::variant<Array, Map, Anope::string, std::nullptr_t, bool, double, int64_t, uint64_t>;
|
||||
|
||||
@@ -169,15 +166,17 @@ public:
|
||||
inline const auto &GetRoot() const { return this->root; }
|
||||
};
|
||||
|
||||
#define RPC_EVENT "RPC::Event"
|
||||
|
||||
class RPC::Event
|
||||
: public Service
|
||||
{
|
||||
private:
|
||||
Anope::string event;
|
||||
size_t minparams;
|
||||
|
||||
protected:
|
||||
Event(const Anope::string& e, size_t mp = 0)
|
||||
: event(e)
|
||||
Event(Module *o, const Anope::string& e, size_t mp = 0)
|
||||
: Service(o, RPC_EVENT, e)
|
||||
, minparams(mp)
|
||||
{
|
||||
}
|
||||
@@ -185,8 +184,6 @@ protected:
|
||||
public:
|
||||
virtual ~Event() = default;
|
||||
|
||||
const auto &GetEvent() const { return event; }
|
||||
|
||||
const auto &GetMinParams() const { return minparams; }
|
||||
|
||||
virtual bool Run(ServiceInterface *iface, HTTPClient *client, Request &request) = 0;
|
||||
@@ -196,17 +193,11 @@ class RPC::ServiceInterface
|
||||
: public Service
|
||||
{
|
||||
public:
|
||||
ServiceInterface(Module *creator, const Anope::string &sname)
|
||||
: Service(creator, "RPCServiceInterface", sname)
|
||||
ServiceInterface(Module *creator)
|
||||
: Service(creator, "RPC::ServiceInterface", "rpc")
|
||||
{
|
||||
}
|
||||
|
||||
virtual const Events &GetEvents() = 0;
|
||||
|
||||
virtual bool Register(Event *event) = 0;
|
||||
|
||||
virtual bool Unregister(Event *event) = 0;
|
||||
|
||||
virtual void Reply(Request &request) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2014-2025 Anope Team
|
||||
* Contact us at team@anope.org
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace SASL
|
||||
{
|
||||
struct Message final
|
||||
{
|
||||
Anope::string source;
|
||||
Anope::string target;
|
||||
Anope::string type;
|
||||
std::vector<Anope::string> data;
|
||||
};
|
||||
|
||||
class Mechanism;
|
||||
struct Session;
|
||||
|
||||
class Service
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Service(Module *o) : ::Service(o, "SASL::Service", "sasl") { }
|
||||
|
||||
virtual void ProcessMessage(const Message &) = 0;
|
||||
|
||||
virtual Anope::string GetAgent() = 0;
|
||||
|
||||
virtual Session *GetSession(const Anope::string &uid) = 0;
|
||||
|
||||
virtual void SendMessage(SASL::Session *session, const Anope::string &type, const Anope::string &data) = 0;
|
||||
|
||||
virtual void Succeed(Session *, NickCore *) = 0;
|
||||
virtual void Fail(Session *) = 0;
|
||||
virtual void SendMechs(Session *) = 0;
|
||||
virtual void DeleteSessions(Mechanism *, bool = false) = 0;
|
||||
virtual void RemoveSession(Session *) = 0;
|
||||
};
|
||||
|
||||
static ServiceReference<SASL::Service> sasl("SASL::Service", "sasl");
|
||||
|
||||
struct Session
|
||||
{
|
||||
time_t created;
|
||||
Anope::string uid;
|
||||
Anope::string hostname, ip;
|
||||
Reference<Mechanism> mech;
|
||||
|
||||
Session(Mechanism *m, const Anope::string &u) : created(Anope::CurTime), uid(u), mech(m) { }
|
||||
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !ip.empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), ip.c_str());
|
||||
return "A user";
|
||||
};
|
||||
|
||||
virtual ~Session()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->RemoveSession(this);
|
||||
}
|
||||
};
|
||||
|
||||
/* PLAIN, EXTERNAL, etc */
|
||||
class Mechanism
|
||||
: public ::Service
|
||||
{
|
||||
public:
|
||||
Mechanism(Module *o, const Anope::string &sname) : Service(o, "SASL::Mechanism", sname) { }
|
||||
|
||||
virtual Session *CreateSession(const Anope::string &uid) { return new Session(this, uid); }
|
||||
|
||||
virtual bool ProcessMessage(Session *session, const Message &) = 0;
|
||||
|
||||
virtual ~Mechanism()
|
||||
{
|
||||
if (sasl)
|
||||
sasl->DeleteSessions(this, true);
|
||||
}
|
||||
};
|
||||
|
||||
class IdentifyRequest
|
||||
: public ::IdentifyRequest
|
||||
{
|
||||
Anope::string uid;
|
||||
Anope::string hostname;
|
||||
|
||||
inline Anope::string GetUserInfo()
|
||||
{
|
||||
auto *u = User::Find(uid);
|
||||
if (u)
|
||||
return u->GetMask();
|
||||
if (!hostname.empty() && !GetAddress().empty())
|
||||
return Anope::printf("%s (%s)", hostname.c_str(), GetAddress().c_str());
|
||||
return "A user";
|
||||
};
|
||||
|
||||
public:
|
||||
IdentifyRequest(Module *m, const Anope::string &id, const Anope::string &acc, const Anope::string &pass, const Anope::string &h, const Anope::string &i)
|
||||
: ::IdentifyRequest(m, acc, pass, i)
|
||||
, uid(id)
|
||||
, hostname(h)
|
||||
{
|
||||
}
|
||||
|
||||
void OnSuccess() override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na || na->nc->HasExt("NS_SUSPENDED") || na->nc->HasExt("UNCONFIRMED"))
|
||||
return OnFail();
|
||||
|
||||
unsigned int maxlogins = Config->GetModule("ns_identify")->Get<unsigned int>("maxlogins");
|
||||
if (maxlogins && na->nc->users.size() >= maxlogins)
|
||||
return OnFail();
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << GetUserInfo() << " identified to account " << this->GetAccount() << " using SASL";
|
||||
sasl->Succeed(s, na->nc);
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFail() override
|
||||
{
|
||||
if (!sasl)
|
||||
return;
|
||||
|
||||
Session *s = sasl->GetSession(uid);
|
||||
if (s)
|
||||
{
|
||||
sasl->Fail(s);
|
||||
delete s;
|
||||
}
|
||||
|
||||
Anope::string accountstatus;
|
||||
NickAlias *na = NickAlias::Find(GetAccount());
|
||||
if (!na)
|
||||
accountstatus = "nonexistent ";
|
||||
else if (na->nc->HasExt("NS_SUSPENDED"))
|
||||
accountstatus = "suspended ";
|
||||
else if (na->nc->HasExt("UNCONFIRMED"))
|
||||
accountstatus = "unconfirmed ";
|
||||
|
||||
Log(this->GetOwner(), "sasl", Config->GetClient("NickServ")) << GetUserInfo() << " failed to identify for " << accountstatus << "account " << this->GetAccount() << " using SASL";
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,7 +19,6 @@ namespace SQL
|
||||
public:
|
||||
typedef std::map<Anope::string, std::stringstream *> Map;
|
||||
Map data;
|
||||
std::map<Anope::string, Serialize::DataType> types;
|
||||
|
||||
~Data()
|
||||
{
|
||||
@@ -59,19 +58,6 @@ namespace SQL
|
||||
delete value;
|
||||
this->data.clear();
|
||||
}
|
||||
|
||||
void SetType(const Anope::string &key, Serialize::DataType dt) override
|
||||
{
|
||||
this->types[key] = dt;
|
||||
}
|
||||
|
||||
Serialize::DataType GetType(const Anope::string &key) const override
|
||||
{
|
||||
auto it = this->types.find(key);
|
||||
if (it != this->types.end())
|
||||
return it->second;
|
||||
return Serialize::DataType::TEXT;
|
||||
}
|
||||
};
|
||||
|
||||
/** A SQL exception, can be thrown at various points
|
||||
|
||||
+1
-5
@@ -222,7 +222,7 @@ public:
|
||||
virtual void SendContextNotice(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
virtual void SendContextPrivmsg(BotInfo *bi, User *target, Channel *context, const Anope::string &msg);
|
||||
|
||||
virtual void SendQuit(User *u, const Anope::string &msg);
|
||||
virtual void SendQuit(User *u, const Anope::string &msg = "", const Anope::string &opermsg = "");
|
||||
virtual void SendPing(const Anope::string &servname, const Anope::string &who);
|
||||
virtual void SendPong(const Anope::string &servname, const Anope::string &who);
|
||||
|
||||
@@ -306,10 +306,6 @@ public:
|
||||
|
||||
virtual void SendClearBans(const MessageSource &user, Channel *c, User* u) { }
|
||||
|
||||
virtual void SendSASLMechanisms(std::vector<Anope::string> &) { }
|
||||
virtual void SendSASLMessage(const SASL::Message &) { }
|
||||
virtual void SendSVSLogin(const Anope::string &uid, NickAlias *na) { }
|
||||
|
||||
virtual bool IsNickValid(const Anope::string &);
|
||||
virtual bool IsChannelValid(const Anope::string &);
|
||||
virtual bool IsIdentValid(const Anope::string &);
|
||||
|
||||
+21
-9
@@ -25,6 +25,14 @@ class CoreExport AutoKick final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
/* Channel this autokick is on */
|
||||
Serialize::Reference<ChannelInfo> ci;
|
||||
|
||||
@@ -38,8 +46,6 @@ public:
|
||||
|
||||
AutoKick();
|
||||
~AutoKick();
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
};
|
||||
|
||||
/* It matters that Base is here before Extensible (it is inherited by Serializable)
|
||||
@@ -48,9 +54,18 @@ class CoreExport ChannelInfo final
|
||||
: public Serializable
|
||||
, public Extensible
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
/* channels who reference this one */
|
||||
Anope::map<int> references;
|
||||
private:
|
||||
Serialize::Reference<NickCore> founder; /* Channel founder */
|
||||
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 */
|
||||
@@ -69,11 +84,11 @@ public:
|
||||
|
||||
Anope::string last_topic; /* The last topic that was set on this channel */
|
||||
Anope::string last_topic_setter; /* Setter */
|
||||
time_t last_topic_time; /* Time */
|
||||
time_t last_topic_time = 0; /* Time */
|
||||
|
||||
Channel::ModeList last_modes; /* The last modes set on this channel */
|
||||
|
||||
int16_t bantype;
|
||||
int16_t bantype = 2;
|
||||
|
||||
MemoInfo memos;
|
||||
|
||||
@@ -82,7 +97,7 @@ public:
|
||||
/* For BotServ */
|
||||
Serialize::Reference<BotInfo> bi; /* Bot used on this channel */
|
||||
|
||||
time_t banexpire; /* Time bans expire in */
|
||||
time_t banexpire = 0; /* Time bans expire in */
|
||||
|
||||
/** Constructor
|
||||
* @param chname The channel name
|
||||
@@ -97,9 +112,6 @@ public:
|
||||
~ChannelInfo();
|
||||
ChannelInfo &operator=(const ChannelInfo &) = default;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
|
||||
/** Change the founder of the channel
|
||||
* @params nc The new founder
|
||||
*/
|
||||
|
||||
+93
-57
@@ -16,6 +16,16 @@
|
||||
#include "anope.h"
|
||||
#include "base.h"
|
||||
|
||||
/** Names of serialization types implemented in the core. */
|
||||
#define AUTOKICK_TYPE "AutoKick"
|
||||
#define BOTINFO_TYPE "BotInfo"
|
||||
#define CHANACCESS_TYPE "ChanAccess"
|
||||
#define CHANNELINFO_TYPE "ChannelInfo"
|
||||
#define MEMO_TYPE "Memo"
|
||||
#define NICKALIAS_TYPE "NickAlias"
|
||||
#define NICKCORE_TYPE "NickCore"
|
||||
#define XLINE_TYPE "XLine"
|
||||
|
||||
namespace Serialize
|
||||
{
|
||||
enum class DataType
|
||||
@@ -28,8 +38,11 @@ namespace Serialize
|
||||
UINT,
|
||||
};
|
||||
|
||||
class Data
|
||||
class CoreExport Data
|
||||
{
|
||||
protected:
|
||||
std::map<Anope::string, Serialize::DataType> types;
|
||||
|
||||
public:
|
||||
virtual ~Data() = default;
|
||||
|
||||
@@ -54,8 +67,8 @@ namespace Serialize
|
||||
|
||||
virtual size_t Hash() const { throw CoreException("Not supported"); }
|
||||
|
||||
virtual void SetType(const Anope::string &key, DataType dt) { }
|
||||
virtual DataType GetType(const Anope::string &key) const { return DataType::TEXT; }
|
||||
Serialize::DataType GetType(const Anope::string &key) const;
|
||||
void SetType(const Anope::string &key, Serialize::DataType dt);
|
||||
};
|
||||
|
||||
extern void RegisterTypes();
|
||||
@@ -97,10 +110,11 @@ protected:
|
||||
Serializable &operator=(const Serializable &);
|
||||
|
||||
public:
|
||||
using Id = uint64_t;
|
||||
virtual ~Serializable();
|
||||
|
||||
/* Unique ID (per type, not globally) for this object */
|
||||
uint64_t id = 0;
|
||||
Id id = 0;
|
||||
|
||||
/* Only used by redis, to ignore updates */
|
||||
unsigned short redis_ignore = 0;
|
||||
@@ -120,82 +134,104 @@ public:
|
||||
*/
|
||||
Serialize::Type *GetSerializableType() const { return this->s_type; }
|
||||
|
||||
virtual void Serialize(Serialize::Data &data) const = 0;
|
||||
|
||||
static const std::list<Serializable *> &GetItems();
|
||||
};
|
||||
|
||||
/* A serializable type. There should be one of these classes for each type
|
||||
* of class that inherits from Serializable. Used for unserializing objects
|
||||
* of this type, as it requires a function pointer to a static member function.
|
||||
/* A serializable type. There should be a single instance of a subclass of this
|
||||
* for each subclass of Serializable as this is what is used to serialize and
|
||||
* deserialize data from the database.
|
||||
*/
|
||||
class CoreExport Serialize::Type final
|
||||
class CoreExport Serialize::Type
|
||||
: public Base
|
||||
{
|
||||
typedef Serializable *(*unserialize_func)(Serializable *obj, Serialize::Data &);
|
||||
|
||||
static std::vector<Anope::string> TypeOrder;
|
||||
static std::map<Anope::string, Serialize::Type *> Types;
|
||||
|
||||
/* The name of this type, should be a class name */
|
||||
private:
|
||||
/** The name of this type in the database (e.g. NickAlias). */
|
||||
Anope::string name;
|
||||
unserialize_func unserialize;
|
||||
/* Owner of this type. Used for placing objects of this type in separate databases
|
||||
* based on what module, if any, owns it.
|
||||
|
||||
/** The module which owns this type, or nullptr if it belongs to the core.
|
||||
* Some database backends use this to put third-party module data into their
|
||||
* own database.
|
||||
*/
|
||||
Module *owner;
|
||||
|
||||
/* The timestamp for this type. All objects of this type are as up to date as
|
||||
* this timestamp. if curtime == timestamp then we have the most up to date
|
||||
* version of every object of this type.
|
||||
/** The time at which this type was last synchronised with the database.
|
||||
* Only used by live database backends like db_sql_live.
|
||||
*/
|
||||
time_t timestamp = 0;
|
||||
|
||||
public:
|
||||
/* Map of Serializable::id to Serializable objects */
|
||||
std::map<uint64_t, Serializable *> objects;
|
||||
/* The names of currently registered types in order of registration. */
|
||||
static std::vector<Anope::string> TypeOrder;
|
||||
|
||||
/** Creates a new serializable type
|
||||
* @param n Type name
|
||||
* @param f Func to unserialize objects
|
||||
* @param owner Owner of this type. Leave NULL for the core.
|
||||
/** The currently registered types. */
|
||||
static std::map<Anope::string, Serialize::Type *> Types;
|
||||
|
||||
protected:
|
||||
/** Creates a new serializable type.
|
||||
* @param n The name of the type . This should match the value passed in the
|
||||
* constructor of the equivalent Serializable type.
|
||||
* @param o The module which owns this type, or nullptr if it belongs to the
|
||||
* core.
|
||||
*/
|
||||
Type(const Anope::string &n, unserialize_func f, Module *owner = NULL);
|
||||
Type(const Anope::string &n, Module *o = nullptr);
|
||||
|
||||
public:
|
||||
/* Map of Serializable objects of this type keyed by their object id. */
|
||||
std::map<Serializable::Id, Serializable *> objects;
|
||||
|
||||
/** Destroys a serializable type. */
|
||||
~Type();
|
||||
|
||||
/** Gets the name for this type
|
||||
* @return The name, eg "NickAlias"
|
||||
*/
|
||||
const Anope::string &GetName() { return this->name; }
|
||||
|
||||
/** Unserialized an object.
|
||||
* @param obj NULL if this object doesn't yet exist. If this isn't NULL, instead
|
||||
* update the contents of this object.
|
||||
* @param data The data to unserialize
|
||||
* @return The unserialized object. If obj != NULL this should be obj.
|
||||
*/
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
|
||||
/** Check if this object type has any pending changes and update them.
|
||||
*/
|
||||
/** Checks for and applies any pending object updates for this type. */
|
||||
void Check();
|
||||
|
||||
/** Gets the timestamp for the object type. That is, the time we know
|
||||
* all objects of this type are updated at least to.
|
||||
/** Attempts to find a serializable type with the specified name.
|
||||
* @param n The name of the serializable type to find.
|
||||
*/
|
||||
time_t GetTimestamp() const;
|
||||
static Serialize::Type *Find(const Anope::string &n);
|
||||
|
||||
/** Bumps object type timestamp to current time
|
||||
/** Retrieves the name of this type in the database (e.g. NickAlias). */
|
||||
inline const auto &GetName() const { return this->name; }
|
||||
|
||||
/** Retrieves the module which owns this type, or nullptr if it belongs to
|
||||
* the core. Some database backends use this to put third-party module data
|
||||
* into their own database.
|
||||
*/
|
||||
inline auto *GetOwner() const { return this->owner; }
|
||||
|
||||
/** Retrieves the time at which this type was last synchronised with the
|
||||
* database. Only used by live database backends like db_sql_live.
|
||||
*/
|
||||
inline auto GetTimestamp() const { return this->timestamp; };
|
||||
|
||||
/** Retrieves the names of currently registered types in order of
|
||||
* registration.
|
||||
*/
|
||||
inline static const auto &GetTypeOrder() { return TypeOrder; }
|
||||
|
||||
/** Retrieves the currently registered types. */
|
||||
inline static const auto &GetTypes() { return Types; }
|
||||
|
||||
/** Serializes the specified object to the database.
|
||||
* @param obj The object to serialise. This is guaranteed to be the correct
|
||||
* type so you can cast it without any checks.
|
||||
* @param data The database to serialize to.
|
||||
*/
|
||||
virtual void Serialize(const Serializable *obj, Serialize::Data &data) const = 0;
|
||||
|
||||
/** Unserializes the specified object from the database.
|
||||
* @param obj The object to unserialize into. If the object has not been
|
||||
* unserialized yet this will be nullptr. This is guaranteed to
|
||||
* be the correct type so you can cast it without any checks.
|
||||
* @param data The database to unserialize from.
|
||||
* @return The object specified in obj or a new object it if was nullptr.
|
||||
*/
|
||||
virtual Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const = 0;
|
||||
|
||||
/** Updates the time at which this type was last synchronised with the
|
||||
* database to the current time. Only used by live database backends like
|
||||
* db_sql_live.
|
||||
*/
|
||||
void UpdateTimestamp();
|
||||
|
||||
Module *GetOwner() const { return this->owner; }
|
||||
|
||||
static Serialize::Type *Find(const Anope::string &name);
|
||||
|
||||
static const std::vector<Anope::string> &GetTypeOrder();
|
||||
|
||||
static const std::map<Anope::string, Serialize::Type *>& GetTypes();
|
||||
};
|
||||
|
||||
/** Should be used to hold lists and other objects of a specific type,
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
// Whether the umask() function is available.
|
||||
#cmakedefine01 HAVE_UMASK
|
||||
|
||||
// Whether Anope was built in a reproducible way.
|
||||
#cmakedefine01 REPRODUCIBLE_BUILD
|
||||
|
||||
#ifdef _WIN32
|
||||
# define popen _popen
|
||||
# define pclose _pclose
|
||||
|
||||
+10
-3
@@ -16,6 +16,16 @@
|
||||
class CoreExport XLine final
|
||||
: public Serializable
|
||||
{
|
||||
public:
|
||||
struct Type final
|
||||
: public Serialize::Type
|
||||
{
|
||||
Type();
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
private:
|
||||
void Init();
|
||||
Anope::string nick, user, host, real;
|
||||
public:
|
||||
@@ -43,9 +53,6 @@ public:
|
||||
|
||||
bool HasNickOrReal() const;
|
||||
bool IsRegex() const;
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
};
|
||||
|
||||
/* Managers XLines. There is one XLineManager per type of XLine. */
|
||||
|
||||
+71
-104
@@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Anope\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-14 14:57+0000\n"
|
||||
"PO-Revision-Date: 2024-11-25 01:32+0000\n"
|
||||
"POT-Creation-Date: 2025-03-22 21:04+0000\n"
|
||||
"PO-Revision-Date: 2025-03-08 13:33+0000\n"
|
||||
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en_US\n"
|
||||
@@ -659,10 +659,10 @@ msgstr ""
|
||||
msgid "nickname {EMAIL | STATUS | USERMASK | QUIT} {ON | OFF}"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname {ON | OFF}"
|
||||
msgid "nickname {ON | delay | OFF}"
|
||||
msgstr ""
|
||||
|
||||
msgid "nickname {ON | QUICK | IMMED | OFF}"
|
||||
msgid "nickname {ON | OFF}"
|
||||
msgstr ""
|
||||
|
||||
msgid "option (channel | bot) settings"
|
||||
@@ -2901,70 +2901,57 @@ msgid "Delete the vhost of another user"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from %s %s list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from %s %s list."
|
||||
msgid_plural "Deleted %d entries from %s %s list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from %s access list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from %s access list."
|
||||
msgid_plural "Deleted %d entries from %s access list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from %s autokick list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from %s autokick list."
|
||||
msgid_plural "Deleted %d entries from %s autokick list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from %s bad words list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from %s bad words list."
|
||||
msgid_plural "Deleted %d entries from %s bad words list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from session-limit exception list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from session-limit exception list."
|
||||
msgid_plural "Deleted %d entries from session-limit exception list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from the %s list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from the %s list."
|
||||
msgid_plural "Deleted %d entries from the %s list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %d entries from the AKILL list."
|
||||
msgstr ""
|
||||
msgid "Deleted %d entry from the AKILL list."
|
||||
msgid_plural "Deleted %d entries from the AKILL list."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted %u entries from your message queue."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted 1 entry from %s access list."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted 1 entry from %s autokick list."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted 1 entry from %s bad words list."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deleted 1 entry from session-limit exception list."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted 1 entry from the %s list."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deleted 1 entry from the AKILL list."
|
||||
msgstr ""
|
||||
msgid "Deleted %u entry from your message queue."
|
||||
msgid_plural "Deleted %u entries from your message queue."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted info from %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Deleted one entry from %s %s list."
|
||||
msgstr ""
|
||||
|
||||
msgid "Deleted one entry from your message queue."
|
||||
msgstr ""
|
||||
|
||||
msgid ""
|
||||
"Deletes the specified memo or memos. You can supply\n"
|
||||
"multiple memo numbers or ranges of numbers instead of a\n"
|
||||
@@ -3571,12 +3558,6 @@ msgstr ""
|
||||
msgid "Ignore list is empty."
|
||||
msgstr ""
|
||||
|
||||
msgid "Ignore list:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Immediate protection"
|
||||
msgstr ""
|
||||
|
||||
msgid "Incorrect email address."
|
||||
msgstr ""
|
||||
|
||||
@@ -4145,6 +4126,9 @@ msgstr ""
|
||||
msgid "Memo ignore list is empty."
|
||||
msgstr ""
|
||||
|
||||
msgid "Memo ignore list:"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Memo limit disabled for %s."
|
||||
msgstr ""
|
||||
@@ -4739,16 +4723,16 @@ msgstr ""
|
||||
msgid "Protection"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Protection delay must be between %s and %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Protection is now off for %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Protection is now on for %s, with a reduced delay."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "Protection is now on for %s, with no delay."
|
||||
msgid "Protection is now on after %lu seconds for %s."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
@@ -4761,9 +4745,6 @@ msgid ""
|
||||
"then enforces the AKILL."
|
||||
msgstr ""
|
||||
|
||||
msgid "Quick protection"
|
||||
msgstr ""
|
||||
|
||||
msgid "RANDOMNEWS {ADD|DEL|LIST} [text|num]"
|
||||
msgstr ""
|
||||
|
||||
@@ -5984,9 +5965,6 @@ msgid ""
|
||||
"shown to users when they join the channel."
|
||||
msgstr ""
|
||||
|
||||
msgid "The IMMED option is not available on this network."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"The LEVELS command allows fine control over the meaning of\n"
|
||||
@@ -6083,12 +6061,10 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The email address %s has reached its usage limit of %d users."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The email address %s has reached its usage limit of 1 user."
|
||||
msgstr ""
|
||||
msgid "The email address %s has reached its usage limit of %u user."
|
||||
msgid_plural "The email address %s has reached its usage limit of %u users."
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#, c-format
|
||||
msgid "The email address of %s will now be hidden from %s INFO displays."
|
||||
@@ -6153,6 +6129,10 @@ msgstr ""
|
||||
msgid "The mode lock list of %s is full."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The network name you specified is incorrect. Did you mean to run %s on a different network?"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid "The new display MUST be a nickname of the nickname group %s."
|
||||
msgstr ""
|
||||
@@ -6515,44 +6495,28 @@ msgid ""
|
||||
"information on it using the INFO command.)"
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Turns automatic protection for the nick on or off. With\n"
|
||||
"protection on if a user tries to use a nickname from the\n"
|
||||
"nick's group they will be given some time to change their\n"
|
||||
"nick after which %s will forcibly change their nick."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Turns automatic protection for your account on or off. With\n"
|
||||
"protection on if another user tries to use a nickname from\n"
|
||||
"your group they will be given some time to change their nick\n"
|
||||
"after which %s will forcibly change their nick."
|
||||
msgstr ""
|
||||
|
||||
msgid "Turns chanstats channel statistics ON or OFF for this user."
|
||||
msgstr ""
|
||||
|
||||
msgid "Turns chanstats statistics ON or OFF."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Turns the automatic protection option for the nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take the nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select QUICK, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"IMMED, the user's nick will be changed immediately without being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."
|
||||
msgstr ""
|
||||
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Turns the automatic protection option for your nick\n"
|
||||
"on or off. With protection on, if another user\n"
|
||||
"tries to take your nick, they will be given one minute to\n"
|
||||
"change to another nick, after which %s will forcibly change\n"
|
||||
"their nick.\n"
|
||||
" \n"
|
||||
"If you select QUICK, the user will be given only 20 seconds\n"
|
||||
"to change nicks instead of the usual 60. If you select\n"
|
||||
"IMMED, the user's nick will be changed immediately without being\n"
|
||||
"warned first or given a chance to change their nick; please\n"
|
||||
"do not use this option unless necessary. Also, your\n"
|
||||
"network's administrators may have disabled this option."
|
||||
msgstr ""
|
||||
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
@@ -7419,3 +7383,6 @@ msgstr ""
|
||||
|
||||
msgid "{nick | channel} memo-text"
|
||||
msgstr ""
|
||||
|
||||
msgid "{ON | delay | OFF}"
|
||||
msgstr ""
|
||||
|
||||
+15
-15
@@ -23,9 +23,9 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const Anope::string &bsnick = conf->GetModule(this)->Get<const Anope::string>("client");
|
||||
const Anope::string &bsnick = conf.GetModule(this).Get<const Anope::string>("client");
|
||||
BotServ = BotInfo::Find(bsnick, true);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
/* Do not allow removing bot modes on our service bots */
|
||||
if (chan->ci && chan->ci->bi == user)
|
||||
{
|
||||
const Anope::string &botmodes = Config->GetModule(this)->Get<const Anope::string>("botmodes");
|
||||
const Anope::string &botmodes = Config->GetModule(this).Get<const Anope::string>("botmodes");
|
||||
for (auto botmode : botmodes)
|
||||
chan->SetMode(chan->ci->bi, ModeManager::FindChannelModeByChar(botmode), chan->ci->bi->GetUID());
|
||||
}
|
||||
@@ -42,9 +42,9 @@ public:
|
||||
|
||||
void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) override
|
||||
{
|
||||
if (ci->c && ci->c->users.size() >= Config->GetModule(this)->Get<unsigned>("minusers"))
|
||||
if (ci->c && ci->c->users.size() >= Config->GetModule(this).Get<unsigned>("minusers"))
|
||||
{
|
||||
ChannelStatus status(Config->GetModule(this)->Get<const Anope::string>("botmodes"));
|
||||
ChannelStatus status(Config->GetModule(this).Get<const Anope::string>("botmodes"));
|
||||
bi->Join(ci->c, &status);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
return;
|
||||
|
||||
BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
|
||||
if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
|
||||
if (bi && Config->GetModule(this).Get<bool>("smartjoin"))
|
||||
{
|
||||
if (IRCD->CanClearBans)
|
||||
{
|
||||
@@ -99,9 +99,9 @@ public:
|
||||
* legit users - Rob
|
||||
**/
|
||||
/* This is before the user has joined the channel, so check usercount + 1 */
|
||||
if (c->users.size() + 1 >= Config->GetModule(this)->Get<unsigned>("minusers") && !c->FindUser(c->ci->bi))
|
||||
if (c->users.size() + 1 >= Config->GetModule(this).Get<unsigned>("minusers") && !c->FindUser(c->ci->bi))
|
||||
{
|
||||
ChannelStatus status(Config->GetModule(this)->Get<const Anope::string>("botmodes"));
|
||||
ChannelStatus status(Config->GetModule(this).Get<const Anope::string>("botmodes"));
|
||||
c->ci->bi->Join(c, &status);
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ public:
|
||||
return;
|
||||
|
||||
/* This is called prior to removing the user from the channel, so c->users.size() - 1 should be safe */
|
||||
if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->GetModule(this)->Get<unsigned>("minusers") && c->FindUser(c->ci->bi))
|
||||
if (c->ci && c->ci->bi && u != *c->ci->bi && c->users.size() - 1 <= Config->GetModule(this).Get<unsigned>("minusers") && c->FindUser(c->ci->bi))
|
||||
c->ci->bi->Part(c->ci->c);
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
"channel, and provide a more convenient way to execute commands. Commands that\n"
|
||||
"require a channel as a parameter will automatically have that parameter\n"
|
||||
"given.\n"), source.service->nick.c_str());
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy")->Get<const Anope::string>("fantasycharacter", "!");
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy").Get<const Anope::string>("fantasycharacter", "!");
|
||||
if (!fantasycharacters.empty())
|
||||
source.Reply(_(" \n"
|
||||
"Fantasy commands may be prefixed with one of the following characters: %s\n"), fantasycharacters.c_str());
|
||||
@@ -170,8 +170,8 @@ public:
|
||||
|
||||
source.Reply(_(" \n"
|
||||
"Bot will join a channel whenever there is at least\n"
|
||||
"\002%d\002 user(s) on it."), Config->GetModule(this)->Get<unsigned>("minusers"));
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy")->Get<const Anope::string>("fantasycharacter", "!");
|
||||
"\002%d\002 user(s) on it."), Config->GetModule(this).Get<unsigned>("minusers"));
|
||||
const Anope::string &fantasycharacters = Config->GetModule("fantasy").Get<const Anope::string>("fantasycharacter", "!");
|
||||
if (!fantasycharacters.empty())
|
||||
source.Reply(_("Additionally, if fantasy is enabled fantasy commands\n"
|
||||
"can be executed by prefixing the command name with\n"
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
|
||||
EventReturn OnChannelModeSet(Channel *c, MessageSource &source, ChannelMode *mode, const Anope::string ¶m) override
|
||||
{
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this)->Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
if (source.GetUser() && !source.GetBot() && Config->GetModule(this).Get<bool>("smartjoin") && mode->name == "BAN" && c->ci && c->ci->bi && c->FindUser(c->ci->bi))
|
||||
{
|
||||
BotInfo *bi = c->ci->bi;
|
||||
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
void OnCreateChan(ChannelInfo *ci) override
|
||||
{
|
||||
/* Set default bot flags */
|
||||
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("defaults", "greet fantasy"));
|
||||
spacesepstream sep(Config->GetModule(this).Get<const Anope::string>("defaults", "greet fantasy"));
|
||||
for (Anope::string token; sep.GetToken(token);)
|
||||
ci->Extend<bool>("BS_" + token.upper());
|
||||
}
|
||||
@@ -211,7 +211,7 @@ public:
|
||||
void OnCreateBot(BotInfo *bi) override
|
||||
{
|
||||
if (bi->botmodes.empty())
|
||||
bi->botmodes = Config->GetModule(this)->Get<const Anope::string>("botumodes");
|
||||
bi->botmodes = Config->GetModule(this).Get<const Anope::string>("botumodes");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
|
||||
void OnChanRegistered(ChannelInfo *ci) override
|
||||
{
|
||||
const Anope::string &bot = Config->GetModule(this)->Get<const Anope::string>("bot");
|
||||
const Anope::string &bot = Config->GetModule(this).Get<const Anope::string>("bot");
|
||||
if (bot.empty())
|
||||
return;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
struct BadWordImpl final
|
||||
: BadWord
|
||||
@@ -18,15 +18,25 @@ struct BadWordImpl final
|
||||
{
|
||||
BadWordImpl() : Serializable("BadWord") { }
|
||||
~BadWordImpl() override;
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct BadWordTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
BadWordTypeImpl()
|
||||
: Serialize::Type("BadWord")
|
||||
{
|
||||
data.Store("ci", this->chan);
|
||||
data.Store("word", this->word);
|
||||
data.Store("type", this->type);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *bw = static_cast<const BadWordImpl *>(obj);
|
||||
data.Store("ci", bw->chan);
|
||||
data.Store("word", bw->word);
|
||||
data.Store("type", bw->type);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &) const override;
|
||||
};
|
||||
|
||||
struct BadWordsImpl final
|
||||
@@ -117,7 +127,7 @@ BadWordImpl::~BadWordImpl()
|
||||
}
|
||||
}
|
||||
|
||||
Serializable *BadWordImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *BadWordTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci, sword;
|
||||
|
||||
@@ -166,12 +176,10 @@ public:
|
||||
|
||||
~BadwordsDelCallback() override
|
||||
{
|
||||
if (!deleted)
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
else if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s bad words list."), ci->name.c_str());
|
||||
if (deleted)
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s bad words list.", "Deleted %d entries from %s bad words list."), deleted, ci->name.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s bad words list."), deleted, ci->name.c_str());
|
||||
source.Reply(_("No matching entries on %s bad words list."), ci->name.c_str());
|
||||
}
|
||||
|
||||
void HandleNumber(unsigned Number) override
|
||||
@@ -286,14 +294,14 @@ private:
|
||||
realword = word.substr(0, pos);
|
||||
}
|
||||
|
||||
unsigned badwordsmax = Config->GetModule(this->module)->Get<unsigned>("badwordsmax");
|
||||
unsigned badwordsmax = Config->GetModule(this->module).Get<unsigned>("badwordsmax");
|
||||
if (badwords->GetBadWordCount() >= badwordsmax)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d bad words entries on a channel."), badwordsmax);
|
||||
return;
|
||||
}
|
||||
|
||||
bool casesensitive = Config->GetModule(this->module)->Get<bool>("casesensitive");
|
||||
bool casesensitive = Config->GetModule(this->module).Get<bool>("casesensitive");
|
||||
|
||||
for (unsigned i = 0, end = badwords->GetBadWordCount(); i < end; ++i)
|
||||
{
|
||||
@@ -464,11 +472,13 @@ class BSBadwords final
|
||||
{
|
||||
CommandBSBadwords commandbsbadwords;
|
||||
ExtensibleItem<BadWordsImpl> badwords;
|
||||
Serialize::Type badword_type;
|
||||
BadWordTypeImpl badword_type;
|
||||
|
||||
public:
|
||||
BSBadwords(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandbsbadwords(this), badwords(this, "badwords"), badword_type("BadWord", BadWordImpl::Unserialize)
|
||||
BSBadwords(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandbsbadwords(this)
|
||||
, badwords(this, "badwords")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -142,7 +142,10 @@ private:
|
||||
* And we must finally check that the nick is not already
|
||||
* taken by another bot.
|
||||
*/
|
||||
if (nick.equals_cs(bi->nick) && (!user.empty() ? user.equals_cs(bi->GetIdent()) : 1) && (!host.empty() ? host.equals_cs(bi->host) : 1) && (!real.empty() ? real.equals_cs(bi->realname) : 1))
|
||||
if (nick.equals_cs(bi->nick)
|
||||
&& (user.empty() || user.equals_cs(bi->GetIdent()))
|
||||
&& (host.empty() || host.equals_cs(bi->host))
|
||||
&& (real.empty() || real.equals_cs(bi->realname)))
|
||||
{
|
||||
source.Reply(_("The old information is the same as the new information specified."));
|
||||
return;
|
||||
@@ -179,10 +182,7 @@ private:
|
||||
source.Reply(_("Nick \002%s\002 is currently in use."), nick.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nick.equals_ci(bi->nick))
|
||||
{
|
||||
/* We check whether the nick is registered, and inform the user
|
||||
* if so. You need to drop the nick manually before you can use
|
||||
* it as a bot nick from now on -GD
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_kick.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/kick.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
static Module *me;
|
||||
|
||||
@@ -45,7 +45,7 @@ struct KickerDataImpl final
|
||||
|
||||
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
|
||||
{
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(e);
|
||||
@@ -79,7 +79,7 @@ struct KickerDataImpl final
|
||||
|
||||
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
|
||||
{
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(e);
|
||||
@@ -515,8 +515,8 @@ public:
|
||||
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");
|
||||
if (kd->floodsecs > Config->GetModule(me).Get<time_t>("keepdata"))
|
||||
kd->floodsecs = Config->GetModule(me).Get<time_t>("keepdata");
|
||||
|
||||
kd->flood = true;
|
||||
if (kd->ttb[TTB_FLOOD])
|
||||
@@ -913,7 +913,7 @@ public:
|
||||
|
||||
void purge()
|
||||
{
|
||||
time_t keepdata = Config->GetModule(me)->Get<time_t>("keepdata");
|
||||
time_t keepdata = Config->GetModule(me).Get<time_t>("keepdata");
|
||||
for (data_type::iterator it = data_map.begin(), it_end = data_map.end(); it != it_end;)
|
||||
{
|
||||
const Anope::string &user = it->first;
|
||||
@@ -1299,7 +1299,7 @@ public:
|
||||
|
||||
/* Normalize the buffer */
|
||||
Anope::string nbuf = Anope::NormalizeBuffer(realbuf);
|
||||
bool casesensitive = Config->GetModule("botserv")->Get<bool>("casesensitive");
|
||||
bool casesensitive = Config->GetModule("botserv").Get<bool>("casesensitive");
|
||||
|
||||
/* Normalize can return an empty string if this only contains control codes etc */
|
||||
if (badwords && !nbuf.empty())
|
||||
@@ -1368,7 +1368,7 @@ public:
|
||||
if (mustkick)
|
||||
{
|
||||
check_ban(ci, u, kd, TTB_BADWORDS);
|
||||
if (Config->GetModule(me)->Get<bool>("gentlebadwordreason"))
|
||||
if (Config->GetModule(me).Get<bool>("gentlebadwordreason"))
|
||||
bot_kick(ci, u, _("Watch your language!"));
|
||||
else
|
||||
bot_kick(ci, u, _("Don't use the word \"%s\" on this channel!"), bw->word.c_str());
|
||||
|
||||
@@ -33,8 +33,8 @@ public:
|
||||
source.Reply(_("Configures bot options.\n"
|
||||
" \n"
|
||||
"Available options:"));
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
bool hide_privileged_commands = Config->GetBlock("options").Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options").Get<bool>("hideregisteredcommands");
|
||||
Anope::string this_name = source.command;
|
||||
for (const auto &[c_name, info] : source.service->commands)
|
||||
{
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
inline static Anope::string BotModes()
|
||||
{
|
||||
return Config->GetModule("botserv")->Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv")->Get<Anope::string>("botmodes", "o")
|
||||
return Config->GetModule("botserv").Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv").Get<Anope::string>("botmodes", "o")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
* @param chan The channel
|
||||
*/
|
||||
ChanServTimer(Reference<BotInfo> &cs, ExtensibleItem<bool> &i, Module *m, Channel *chan)
|
||||
: Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "1m"))
|
||||
: Timer(m, Config->GetModule(m).Get<time_t>("inhabit", "1m"))
|
||||
, ChanServ(cs)
|
||||
, inhabit(i)
|
||||
, c(chan)
|
||||
@@ -103,9 +103,9 @@ public:
|
||||
new ChanServTimer(ChanServ, inhabit, this->owner, c);
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const Anope::string &channick = conf->GetModule(this)->Get<const Anope::string>("client");
|
||||
const Anope::string &channick = conf.GetModule(this).Get<const Anope::string>("client");
|
||||
|
||||
if (channick.empty())
|
||||
throw ConfigException(Module::name + ": <client> must be defined");
|
||||
@@ -116,18 +116,21 @@ public:
|
||||
|
||||
ChanServ = bi;
|
||||
|
||||
spacesepstream(conf->GetModule(this)->Get<const Anope::string>("defaults", "keeptopic peace securefounder signkick")).GetTokens(defaults);
|
||||
spacesepstream(conf.GetModule(this).Get<const Anope::string>("defaults")).GetTokens(defaults);
|
||||
if (defaults.empty())
|
||||
{
|
||||
defaults.emplace_back("KEEPTOPIC");
|
||||
defaults.emplace_back("PEACE");
|
||||
defaults.emplace_back("SECUREFOUNDER");
|
||||
defaults.emplace_back("SIGNKICK");
|
||||
defaults = {
|
||||
"CS_KEEP_MODES",
|
||||
"KEEPTOPIC",
|
||||
"PEACE",
|
||||
"SECUREFOUNDER",
|
||||
"SIGNKICK",
|
||||
};
|
||||
}
|
||||
else if (defaults[0].equals_ci("none"))
|
||||
defaults.clear();
|
||||
|
||||
always_lower = conf->GetModule(this)->Get<bool>("always_lower_ts");
|
||||
always_lower = conf.GetModule(this).Get<bool>("always_lower_ts");
|
||||
}
|
||||
|
||||
void OnBotDelete(BotInfo *bi) override
|
||||
@@ -138,7 +141,7 @@ public:
|
||||
|
||||
EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) override
|
||||
{
|
||||
if (bi == ChanServ && Config->GetModule(this)->Get<bool>("opersonly") && !u->HasMode("OPER"))
|
||||
if (bi == ChanServ && Config->GetModule(this).Get<bool>("opersonly") && !u->HasMode("OPER"))
|
||||
{
|
||||
u->SendMessage(bi, ACCESS_DENIED);
|
||||
return EVENT_STOP;
|
||||
@@ -151,7 +154,7 @@ public:
|
||||
{
|
||||
std::deque<ChannelInfo *> chans;
|
||||
nc->GetChannelReferences(chans);
|
||||
int max_reg = Config->GetModule(this)->Get<int>("maxregistered");
|
||||
int max_reg = Config->GetModule(this).Get<int>("maxregistered");
|
||||
|
||||
for (auto *ci : chans)
|
||||
{
|
||||
@@ -247,7 +250,7 @@ public:
|
||||
{
|
||||
ci->c->RemoveMode(ci->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
|
||||
const Anope::string &require = Config->GetModule(this).Get<const Anope::string>("require");
|
||||
if (!require.empty())
|
||||
ci->c->SetModes(ci->WhoSends(), false, "-%s", require.c_str());
|
||||
}
|
||||
@@ -272,7 +275,7 @@ public:
|
||||
{
|
||||
if (!params.empty() || source.c || source.service != *ChanServ)
|
||||
return;
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
if (chanserv_expire >= 86400)
|
||||
source.Reply(_(" \n"
|
||||
"Note that any channel which is not used for %lu days\n"
|
||||
@@ -295,7 +298,7 @@ public:
|
||||
else
|
||||
c->RemoveMode(c->WhoSends(), "REGISTERED", "", false);
|
||||
|
||||
const Anope::string &require = Config->GetModule(this)->Get<const Anope::string>("require");
|
||||
const Anope::string &require = Config->GetModule(this).Get<const Anope::string>("require");
|
||||
if (!require.empty())
|
||||
{
|
||||
if (c->ci)
|
||||
@@ -314,8 +317,8 @@ public:
|
||||
|
||||
EventReturn OnCanSet(User *u, const ChannelMode *cm) override
|
||||
{
|
||||
if (Config->GetModule(this)->Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this)->Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
if (Config->GetModule(this).Get<const Anope::string>("nomlock").find(cm->mchar) != Anope::string::npos
|
||||
|| Config->GetModule(this).Get<const Anope::string>("require").find(cm->mchar) != Anope::string::npos)
|
||||
return EVENT_STOP;
|
||||
return EVENT_CONTINUE;
|
||||
}
|
||||
@@ -337,7 +340,7 @@ public:
|
||||
|
||||
void OnExpireTick() override
|
||||
{
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
|
||||
if (!chanserv_expire || Anope::NoExpire || Anope::ReadOnly)
|
||||
return;
|
||||
@@ -467,7 +470,7 @@ public:
|
||||
if (!show_all)
|
||||
return;
|
||||
|
||||
time_t chanserv_expire = Config->GetModule(this)->Get<time_t>("expire", "30d");
|
||||
time_t chanserv_expire = Config->GetModule(this).Get<time_t>("expire", "30d");
|
||||
if (!ci->HasExt("CS_NO_EXPIRE") && chanserv_expire && !Anope::NoExpire && ci->last_used != Anope::CurTime)
|
||||
info[_("Expires")] = Anope::strftime(ci->last_used + chanserv_expire, source.GetAccount());
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ class CommandCSAccess final
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_("Channels may not be on access lists."));
|
||||
return;
|
||||
@@ -158,7 +158,7 @@ class CommandCSAccess final
|
||||
{
|
||||
na = NickAlias::Find(mask);
|
||||
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
if (!na && Config->GetModule("chanserv").Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
return;
|
||||
@@ -205,7 +205,7 @@ class CommandCSAccess final
|
||||
}
|
||||
}
|
||||
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
if (access_max && ci->GetDeepAccessCount() >= access_max)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
|
||||
@@ -284,11 +284,7 @@ class CommandCSAccess final
|
||||
else
|
||||
{
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << Nicks;
|
||||
|
||||
if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s access list."), ci->name.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s access list."), deleted, ci->name.c_str());
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s access list.", "Deleted %d entries from %s access list."), deleted, ci->name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +597,7 @@ public:
|
||||
"may be a numerical level or the name of a privilege (eg AUTOOP).\n"
|
||||
"When a user joins the channel the access they receive is from the\n"
|
||||
"highest level entry in the access list."));
|
||||
if (!Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (!Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
source.Reply(_("The given mask may also be a channel, which will use the\n"
|
||||
"access list from the other channel up to the given \037level\037."));
|
||||
source.Reply(" ");
|
||||
@@ -878,21 +874,21 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
defaultLevels.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("privilege"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *priv = conf->GetBlock("privilege", i);
|
||||
Configuration::Block &priv = conf.GetBlock("privilege", i);
|
||||
|
||||
const Anope::string &pname = priv->Get<const Anope::string>("name");
|
||||
const Anope::string &pname = priv.Get<const Anope::string>("name");
|
||||
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(pname);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
const Anope::string &value = priv->Get<const Anope::string>("level");
|
||||
const Anope::string &value = priv.Get<const Anope::string>("level");
|
||||
if (value.empty())
|
||||
continue;
|
||||
else if (value.equals_ci("founder"))
|
||||
@@ -900,7 +896,7 @@ public:
|
||||
else if (value.equals_ci("disabled"))
|
||||
defaultLevels[p->name] = ACCESS_INVALID;
|
||||
else
|
||||
defaultLevels[p->name] = priv->Get<int16_t>("level");
|
||||
defaultLevels[p->name] = priv.Get<int16_t>("level");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class CommandCSAKick final
|
||||
const NickAlias *na = NickAlias::Find(mask);
|
||||
NickCore *nc = NULL;
|
||||
const AutoKick *akick;
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
@@ -170,9 +170,9 @@ class CommandCSAKick final
|
||||
}
|
||||
}
|
||||
|
||||
if (ci->GetAkickCount() >= Config->GetModule(this->owner)->Get<unsigned>("autokickmax"))
|
||||
if (ci->GetAkickCount() >= Config->GetModule(this->owner).Get<unsigned>("autokickmax"))
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner)->Get<unsigned>("autokickmax"));
|
||||
source.Reply(_("Sorry, you can only have %d autokick masks on a channel."), Config->GetModule(this->owner).Get<unsigned>("autokickmax"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -219,12 +219,10 @@ class CommandCSAKick final
|
||||
|
||||
~AkickDelCallback() override
|
||||
{
|
||||
if (!deleted)
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
else if (deleted == 1)
|
||||
source.Reply(_("Deleted 1 entry from %s autokick list."), ci->name.c_str());
|
||||
if (deleted)
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s autokick list.", "Deleted %d entries from %s autokick list."), deleted, ci->name.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s autokick list."), deleted, ci->name.c_str());
|
||||
source.Reply(_("No matching entries on %s autokick list."), ci->name.c_str());
|
||||
}
|
||||
|
||||
void HandleNumber(unsigned number) override
|
||||
@@ -568,7 +566,7 @@ public:
|
||||
reason = autokick->reason;
|
||||
if (reason.empty())
|
||||
{
|
||||
reason = Language::Translate(u, Config->GetModule(this)->Get<const Anope::string>("autokickreason").c_str());
|
||||
reason = Language::Translate(u, Config->GetModule(this).Get<const Anope::string>("autokickreason").c_str());
|
||||
reason = reason.replace_all_cs("%n", u->nick)
|
||||
.replace_all_cs("%c", c->name);
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ public:
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) override
|
||||
{
|
||||
Configuration::Block *block = Config->GetCommand(source);
|
||||
const Anope::string &mode = block->Get<Anope::string>("mode", "BAN");
|
||||
Configuration::Block &block = Config->GetCommand(source);
|
||||
const Anope::string &mode = block.Get<Anope::string>("mode", "BAN");
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName(mode);
|
||||
if (cm == NULL)
|
||||
return;
|
||||
@@ -107,11 +107,11 @@ public:
|
||||
reason += " " + params[3];
|
||||
}
|
||||
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
Anope::string signkickformat = Config->GetModule("chanserv").Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
|
||||
User *u = source.GetUser();
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
if (!c->FindUser(u2))
|
||||
return;
|
||||
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
if (block.Get<bool>("kick", "yes"))
|
||||
{
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
|
||||
{
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
else if (uc->user->IsProtected())
|
||||
continue;
|
||||
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
if (block.Get<bool>("kick", "yes"))
|
||||
{
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
|
||||
class CommandCSClone final
|
||||
: public Command
|
||||
@@ -24,7 +24,7 @@ class CommandCSClone final
|
||||
static void CopyAccess(CommandSource &source, ChannelInfo *ci, ChannelInfo *target_ci)
|
||||
{
|
||||
std::set<Anope::string> masks;
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
unsigned count = 0;
|
||||
|
||||
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_entrymsg.h"
|
||||
#include "modules/chanserv/entrymsg.h"
|
||||
|
||||
struct EntryMsgImpl final
|
||||
: EntryMsg
|
||||
@@ -29,16 +29,26 @@ struct EntryMsgImpl final
|
||||
}
|
||||
|
||||
~EntryMsgImpl() override;
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct EntryMsgTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
EntryMsgTypeImpl()
|
||||
: Serialize::Type("EntryMsg")
|
||||
{
|
||||
data.Store("ci", this->chan);
|
||||
data.Store("creator", this->creator);
|
||||
data.Store("message", this->message);
|
||||
data.Store("when", this->when);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *msg = static_cast<const EntryMsgImpl *>(obj);
|
||||
data.Store("ci", msg->chan);
|
||||
data.Store("creator", msg->creator);
|
||||
data.Store("message", msg->message);
|
||||
data.Store("when", msg->when);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
struct EntryMessageListImpl final
|
||||
@@ -68,7 +78,7 @@ EntryMsgImpl::~EntryMsgImpl()
|
||||
}
|
||||
|
||||
|
||||
Serializable *EntryMsgImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *EntryMsgTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci, screator, smessage;
|
||||
time_t swhen;
|
||||
@@ -142,7 +152,7 @@ private:
|
||||
{
|
||||
EntryMessageList *messages = ci->Require<EntryMessageList>("entrymsg");
|
||||
|
||||
if ((*messages)->size() >= Config->GetModule(this->owner)->Get<unsigned>("maxentries"))
|
||||
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());
|
||||
else
|
||||
{
|
||||
@@ -264,12 +274,13 @@ class CSEntryMessage final
|
||||
{
|
||||
CommandEntryMessage commandentrymsg;
|
||||
ExtensibleItem<EntryMessageListImpl> eml;
|
||||
Serialize::Type entrymsg_type;
|
||||
EntryMsgTypeImpl entrymsg_type;
|
||||
|
||||
public:
|
||||
CSEntryMessage(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandentrymsg(this),
|
||||
eml(this, "entrymsg"), entrymsg_type("EntryMsg", EntryMsgImpl::Unserialize)
|
||||
CSEntryMessage(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandentrymsg(this)
|
||||
, eml(this, "entrymsg")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,10 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
|
||||
prefix = conf.GetModule("chanstats").Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf.GetModule("chanstats").Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
|
||||
@@ -104,10 +104,10 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
prefix = conf->GetModule("chanstats")->Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf->GetModule("chanstats")->Get<const Anope::string>("engine"));
|
||||
prefix = conf.GetModule("chanstats").Get<const Anope::string>("prefix", "anope_");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", conf.GetModule("chanstats").Get<const Anope::string>("engine"));
|
||||
}
|
||||
|
||||
SQL::Result RunQuery(const SQL::Query &query)
|
||||
|
||||
@@ -93,7 +93,7 @@ class CommandCSFlags final
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_("Channels may not be on access lists."));
|
||||
return;
|
||||
@@ -116,7 +116,7 @@ class CommandCSFlags final
|
||||
else
|
||||
{
|
||||
na = NickAlias::Find(mask);
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
if (!na && Config->GetModule("chanserv").Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
return;
|
||||
@@ -179,7 +179,7 @@ class CommandCSFlags final
|
||||
}
|
||||
}
|
||||
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
if (access_max && ci->GetDeepAccessCount() >= access_max)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
|
||||
@@ -494,21 +494,21 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
defaultFlags.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("privilege"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *priv = conf->GetBlock("privilege", i);
|
||||
Configuration::Block &priv = conf.GetBlock("privilege", i);
|
||||
|
||||
const Anope::string &pname = priv->Get<const Anope::string>("name");
|
||||
const Anope::string &pname = priv.Get<const Anope::string>("name");
|
||||
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(pname);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
const Anope::string &value = priv->Get<const Anope::string>("flag");
|
||||
const Anope::string &value = priv.Get<const Anope::string>("flag");
|
||||
if (value.empty())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -44,11 +44,11 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned reasonmax = Config->GetModule("chanserv")->Get<unsigned>("reasonmax", "200");
|
||||
unsigned reasonmax = Config->GetModule("chanserv").Get<unsigned>("reasonmax", "200");
|
||||
if (reason.length() > reasonmax)
|
||||
reason = reason.substr(0, reasonmax);
|
||||
|
||||
Anope::string signkickformat = Config->GetModule("chanserv")->Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
Anope::string signkickformat = Config->GetModule("chanserv").Get<Anope::string>("signkickformat", "%m (%n)");
|
||||
signkickformat = signkickformat.replace_all_cs("%n", source.GetNick());
|
||||
|
||||
AccessGroup u_access = source.AccessFor(ci);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
class CommandCSList final
|
||||
: public Command
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
}
|
||||
|
||||
Anope::string spattern = "#" + pattern;
|
||||
unsigned listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50");
|
||||
unsigned listmax = Config->GetModule(this->owner).Get<unsigned>("listmax", "50");
|
||||
|
||||
source.Reply(_("List of entries matching \002%s\002:"), pattern.c_str());
|
||||
|
||||
@@ -160,11 +160,11 @@ public:
|
||||
" \002LIST #51-100\002\n"
|
||||
" Lists all registered channels within the given range (51-100)."));
|
||||
|
||||
if (!Config->GetBlock("options")->Get<const Anope::string>("regexengine").empty())
|
||||
if (!Config->GetBlock("options").Get<const Anope::string>("regexengine").empty())
|
||||
{
|
||||
source.Reply(" ");
|
||||
source.Reply(_("Regex matches are also supported using the %s engine.\n"
|
||||
"Enclose your pattern in // if this is desired."), Config->GetBlock("options")->Get<const Anope::string>("regexengine").c_str());
|
||||
"Enclose your pattern in // if this is desired."), Config->GetBlock("options").Get<const Anope::string>("regexengine").c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+34
-23
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_log.h"
|
||||
#include "modules/chanserv/log.h"
|
||||
|
||||
struct LogSettingImpl final
|
||||
: LogSetting
|
||||
@@ -34,20 +34,30 @@ struct LogSettingImpl final
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct LogSettingTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
LogSettingTypeImpl()
|
||||
: Serialize::Type("LogSetting")
|
||||
{
|
||||
data.Store("ci", chan);
|
||||
data.Store("service_name", service_name);
|
||||
data.Store("command_service", command_service);
|
||||
data.Store("command_name", command_name);
|
||||
data.Store("method", method);
|
||||
data.Store("extra", extra);
|
||||
data.Store("creator", creator);
|
||||
data.Store("created", created);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *ls = static_cast<const LogSettingImpl *>(obj);
|
||||
data.Store("ci", ls->chan);
|
||||
data.Store("service_name", ls->service_name);
|
||||
data.Store("command_service", ls->command_service);
|
||||
data.Store("command_name", ls->command_name);
|
||||
data.Store("method", ls->method);
|
||||
data.Store("extra", ls->extra);
|
||||
data.Store("creator", ls->creator);
|
||||
data.Store("created", ls->created);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
Anope::string sci;
|
||||
data["ci"] >> sci;
|
||||
@@ -291,7 +301,7 @@ class CSLog final
|
||||
ServiceReference<MemoServService> MSService;
|
||||
CommandCSLog commandcslog;
|
||||
ExtensibleItem<LogSettingsImpl> logsettings;
|
||||
Serialize::Type logsetting_type;
|
||||
LogSettingTypeImpl logsetting_type;
|
||||
|
||||
struct LogDefault final
|
||||
{
|
||||
@@ -301,27 +311,28 @@ class CSLog final
|
||||
std::vector<LogDefault> defaults;
|
||||
|
||||
public:
|
||||
CSLog(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
MSService("MemoServService", "MemoServ"), commandcslog(this),
|
||||
logsettings(this, "logsettings"), logsetting_type("LogSetting", LogSettingImpl::Unserialize)
|
||||
CSLog(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, MSService("MemoServService", "MemoServ")
|
||||
, commandcslog(this)
|
||||
, logsettings(this, "logsettings")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
defaults.clear();
|
||||
|
||||
for (int i = 0; i < block->CountBlock("default"); ++i)
|
||||
for (int i = 0; i < block.CountBlock("default"); ++i)
|
||||
{
|
||||
Configuration::Block *def = block->GetBlock("default", i);
|
||||
Configuration::Block &def = block.GetBlock("default", i);
|
||||
|
||||
LogDefault ld;
|
||||
|
||||
ld.service = def->Get<const Anope::string>("service");
|
||||
ld.command = def->Get<const Anope::string>("command");
|
||||
ld.method = def->Get<const Anope::string>("method");
|
||||
ld.service = def.Get<const Anope::string>("service");
|
||||
ld.command = def.Get<const Anope::string>("command");
|
||||
ld.method = def.Get<const Anope::string>("method");
|
||||
|
||||
defaults.push_back(ld);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
struct ModeLockImpl final
|
||||
: ModeLock
|
||||
@@ -30,9 +30,17 @@ struct ModeLockImpl final
|
||||
ml->RemoveMLock(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override;
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
|
||||
struct ModeLockTypeImpl final
|
||||
: Serialize::Type
|
||||
{
|
||||
ModeLockTypeImpl()
|
||||
: Serialize::Type("ModeLock")
|
||||
{
|
||||
}
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override;
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override;
|
||||
};
|
||||
|
||||
struct ModeLocksImpl final
|
||||
@@ -203,17 +211,18 @@ struct ModeLocksImpl final
|
||||
}
|
||||
};
|
||||
|
||||
void ModeLockImpl::Serialize(Serialize::Data &data) const
|
||||
void ModeLockTypeImpl::Serialize(const Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
data.Store("ci", this->ci);
|
||||
data.Store("set", this->set);
|
||||
data.Store("name", this->name);
|
||||
data.Store("param", this->param);
|
||||
data.Store("setter", this->setter);
|
||||
data.Store("created", this->created);
|
||||
const auto *ml = static_cast<const ModeLockImpl *>(obj);
|
||||
data.Store("ci", ml->ci);
|
||||
data.Store("set", ml->set);
|
||||
data.Store("name", ml->name);
|
||||
data.Store("param", ml->param);
|
||||
data.Store("setter", ml->setter);
|
||||
data.Store("created", ml->created);
|
||||
}
|
||||
|
||||
Serializable *ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
Serializable *ModeLockTypeImpl::Unserialize(Serializable *obj, Serialize::Data &data) const
|
||||
{
|
||||
Anope::string sci;
|
||||
|
||||
@@ -336,7 +345,7 @@ class CommandCSMode final
|
||||
continue;
|
||||
}
|
||||
|
||||
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "50"))
|
||||
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner).Get<unsigned>("max", "50"))
|
||||
{
|
||||
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
|
||||
continue;
|
||||
@@ -935,33 +944,33 @@ class CSMode final
|
||||
CommandCSMode commandcsmode;
|
||||
CommandCSModes commandcsmodes;
|
||||
ExtensibleItem<ModeLocksImpl> modelocks;
|
||||
Serialize::Type modelocks_type;
|
||||
ModeLockTypeImpl modelocks_type;
|
||||
|
||||
public:
|
||||
CSMode(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandcsmode(this), commandcsmodes(this),
|
||||
modelocks(this, "modelocks"),
|
||||
modelocks_type("ModeLock", ModeLockImpl::Unserialize)
|
||||
CSMode(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandcsmode(this)
|
||||
, commandcsmodes(this)
|
||||
, modelocks(this, "modelocks")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
modes.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("command"); ++i)
|
||||
{
|
||||
Configuration::Block *block = conf->GetBlock("command", i);
|
||||
Configuration::Block &block = conf.GetBlock("command", i);
|
||||
|
||||
const Anope::string &cname = block->Get<const Anope::string>("name"),
|
||||
&cmd = block->Get<const Anope::string>("command");
|
||||
const Anope::string &cname = block.Get<const Anope::string>("name"),
|
||||
&cmd = block.Get<const Anope::string>("command");
|
||||
|
||||
if (cname.empty() || cmd != "chanserv/modes")
|
||||
continue;
|
||||
|
||||
const Anope::string &set = block->Get<const Anope::string>("set"),
|
||||
&unset = block->Get<const Anope::string>("unset");
|
||||
const Anope::string &set = block.Get<const Anope::string>("set"),
|
||||
&unset = block.Get<const Anope::string>("unset");
|
||||
|
||||
if (set.empty() && unset.empty())
|
||||
continue;
|
||||
@@ -1024,7 +1033,7 @@ public:
|
||||
{
|
||||
ModeLocks *ml = modelocks.Require(ci);
|
||||
Anope::string mlock;
|
||||
spacesepstream sep(Config->GetModule(this)->Get<const Anope::string>("mlock", "+nt"));
|
||||
spacesepstream sep(Config->GetModule(this).Get<const Anope::string>("mlock", "+nt"));
|
||||
if (sep.GetToken(mlock))
|
||||
{
|
||||
bool add = true;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
{
|
||||
const Anope::string &chan = params[0];
|
||||
const Anope::string &chdesc = params.size() > 1 ? params[1] : "";
|
||||
unsigned maxregistered = Config->GetModule("chanserv")->Get<unsigned>("maxregistered");
|
||||
unsigned maxregistered = Config->GetModule("chanserv").Get<unsigned>("maxregistered");
|
||||
|
||||
User *u = source.GetUser();
|
||||
NickCore *nc = source.nc;
|
||||
|
||||
@@ -43,19 +43,29 @@ struct SeenInfo final
|
||||
if (iter != database.end() && iter->second == this)
|
||||
database.erase(iter);
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct SeenInfoType final
|
||||
: Serialize::Type
|
||||
{
|
||||
SeenInfoType()
|
||||
: Serialize::Type("SeenInfo")
|
||||
{
|
||||
data.Store("nick", nick);
|
||||
data.Store("vhost", vhost);
|
||||
data.Store("type", type);
|
||||
data.Store("nick2", nick2);
|
||||
data.Store("channel", channel);
|
||||
data.Store("message", message);
|
||||
data.Store("last", last);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *s = static_cast<const SeenInfo *>(obj);
|
||||
data.Store("nick", s->nick);
|
||||
data.Store("vhost", s->vhost);
|
||||
data.Store("type", s->type);
|
||||
data.Store("nick2", s->nick2);
|
||||
data.Store("channel", s->channel);
|
||||
data.Store("message", s->message);
|
||||
data.Store("last", s->last);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
Anope::string snick;
|
||||
|
||||
@@ -374,23 +384,26 @@ public:
|
||||
class CSSeen final
|
||||
: public Module
|
||||
{
|
||||
Serialize::Type seeninfo_type;
|
||||
SeenInfoType seeninfo_type;
|
||||
CommandSeen commandseen;
|
||||
CommandOSSeen commandosseen;
|
||||
public:
|
||||
CSSeen(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), seeninfo_type("SeenInfo", SeenInfo::Unserialize), commandseen(this), commandosseen(this)
|
||||
CSSeen(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandseen(this)
|
||||
, commandosseen(this)
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
simple = conf->GetModule(this)->Get<bool>("simple");
|
||||
simple = conf.GetModule(this).Get<bool>("simple");
|
||||
}
|
||||
|
||||
void OnExpireTick() override
|
||||
{
|
||||
size_t previous_size = database.size();
|
||||
time_t purgetime = Config->GetModule(this)->Get<time_t>("purgetime");
|
||||
time_t purgetime = Config->GetModule(this).Get<time_t>("purgetime");
|
||||
if (!purgetime)
|
||||
purgetime = Anope::DoTime("30d");
|
||||
for (database_map::iterator it = database.begin(), it_end = database.end(); it != it_end;)
|
||||
|
||||
+12
-12
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
class CommandCSSet final
|
||||
: public Command
|
||||
@@ -36,8 +36,8 @@ public:
|
||||
" \n"
|
||||
"Available options:"));
|
||||
Anope::string this_name = source.command;
|
||||
bool hide_privileged_commands = Config->GetBlock("options")->Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options")->Get<bool>("hideregisteredcommands");
|
||||
bool hide_privileged_commands = Config->GetBlock("options").Get<bool>("hideprivilegedcommands"),
|
||||
hide_registered_commands = Config->GetBlock("options").Get<bool>("hideregisteredcommands");
|
||||
for (const auto &[c_name, info] : source.service->commands)
|
||||
{
|
||||
if (c_name.find_ci(this_name + " ") == 0)
|
||||
@@ -301,7 +301,7 @@ public:
|
||||
}
|
||||
|
||||
NickCore *nc = na->nc;
|
||||
unsigned max_reg = Config->GetModule("chanserv")->Get<unsigned>("maxregistered");
|
||||
unsigned max_reg = Config->GetModule("chanserv").Get<unsigned>("maxregistered");
|
||||
if (max_reg && nc->channelcount >= max_reg && !source.HasPriv("chanserv/no-register-limit"))
|
||||
{
|
||||
source.Reply(_("\002%s\002 has too many channels registered."), na->nick.c_str());
|
||||
@@ -461,8 +461,8 @@ public:
|
||||
|
||||
inline static Anope::string BotModes()
|
||||
{
|
||||
return Config->GetModule("botserv")->Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv")->Get<Anope::string>("botmodes", "o")
|
||||
return Config->GetModule("botserv").Get<Anope::string>("botmodes",
|
||||
Config->GetModule("chanserv").Get<Anope::string>("botmodes", "o")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -969,7 +969,7 @@ public:
|
||||
"access list (with the highest access, if applicable) will\n"
|
||||
"become the new founder, but if the access list is empty, the\n"
|
||||
"channel will be dropped."));
|
||||
unsigned max_reg = Config->GetModule("chanserv")->Get<unsigned>("maxregistered");
|
||||
unsigned max_reg = Config->GetModule("chanserv").Get<unsigned>("maxregistered");
|
||||
if (max_reg)
|
||||
{
|
||||
source.Reply(" ");
|
||||
@@ -1057,7 +1057,7 @@ class CSSet final
|
||||
{
|
||||
SerializableExtensibleItem<bool>::ExtensibleSerialize(e, s, data);
|
||||
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
const ChannelInfo *ci = anope_dynamic_static_cast<const ChannelInfo *>(s);
|
||||
@@ -1077,7 +1077,7 @@ class CSSet final
|
||||
{
|
||||
SerializableExtensibleItem<bool>::ExtensibleUnserialize(e, s, data);
|
||||
|
||||
if (s->GetSerializableType()->GetName() != "ChannelInfo")
|
||||
if (s->GetSerializableType()->GetName() != CHANNELINFO_TYPE)
|
||||
return;
|
||||
|
||||
ChannelInfo *ci = anope_dynamic_static_cast<ChannelInfo *>(s);
|
||||
@@ -1133,14 +1133,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
persist_lower_ts = conf->GetModule(this)->Get<bool>("persist_lower_ts");
|
||||
persist_lower_ts = conf.GetModule(this).Get<bool>("persist_lower_ts");
|
||||
}
|
||||
|
||||
void OnCreateChan(ChannelInfo *ci) override
|
||||
{
|
||||
ci->bantype = Config->GetModule(this)->Get<int>("defbantype", "2");
|
||||
ci->bantype = Config->GetModule(this).Get<int>("defbantype", "2");
|
||||
}
|
||||
|
||||
void OnChannelSync(Channel *c) override
|
||||
|
||||
@@ -44,15 +44,25 @@ struct CSMiscData final
|
||||
name = n;
|
||||
data = d;
|
||||
}
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &sdata) const override
|
||||
struct CSMiscDataType
|
||||
: Serialize::Type
|
||||
{
|
||||
CSMiscDataType()
|
||||
: Serialize::Type("CSMiscData")
|
||||
{
|
||||
sdata.Store("ci", this->object);
|
||||
sdata.Store("name", this->name);
|
||||
sdata.Store("data", this->data);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
void Serialize(const Serializable *obj, Serialize::Data &sdata) const override
|
||||
{
|
||||
const auto *d = static_cast<const CSMiscData *>(obj);
|
||||
sdata.Store("ci", d->object);
|
||||
sdata.Store("name", d->name);
|
||||
sdata.Store("data", d->data);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
Anope::string sci, sname, sdata;
|
||||
|
||||
@@ -172,11 +182,12 @@ class CSSetMisc final
|
||||
: public Module
|
||||
{
|
||||
CommandCSSetMisc commandcssetmisc;
|
||||
Serialize::Type csmiscdata_type;
|
||||
CSMiscDataType csmiscdata_type;
|
||||
|
||||
public:
|
||||
CSSetMisc(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandcssetmisc(this), csmiscdata_type("CSMiscData", CSMiscData::Unserialize)
|
||||
CSSetMisc(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandcssetmisc(this)
|
||||
{
|
||||
me = this;
|
||||
}
|
||||
@@ -187,29 +198,33 @@ public:
|
||||
delete item;
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
descriptions.clear();
|
||||
numerics.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("command"); ++i)
|
||||
{
|
||||
Configuration::Block *block = conf->GetBlock("command", i);
|
||||
Configuration::Block &block = conf.GetBlock("command", i);
|
||||
|
||||
if (block->Get<const Anope::string>("command") != "chanserv/set/misc")
|
||||
if (block.Get<const Anope::string>("command") != "chanserv/set/misc")
|
||||
continue;
|
||||
|
||||
Anope::string cname = block->Get<const Anope::string>("name");
|
||||
Anope::string desc = block->Get<const Anope::string>("misc_description");
|
||||
Anope::string cname = block.Get<const Anope::string>("name");
|
||||
Anope::string desc = block.Get<const Anope::string>("misc_description");
|
||||
|
||||
if (cname.empty() || desc.empty())
|
||||
continue;
|
||||
|
||||
descriptions[cname] = desc;
|
||||
|
||||
auto numeric = block->Get<unsigned>("misc_numeric");
|
||||
// Force creation of the extension item.
|
||||
const auto extname = "cs_set_misc:" + GetAttribute(cname);
|
||||
GetItem(extname);
|
||||
|
||||
auto numeric = block.Get<unsigned>("misc_numeric");
|
||||
if (numeric >= 1 && numeric <= 999)
|
||||
numerics["cs_set_misc:" + GetAttribute(cname)] = numeric;
|
||||
numerics[extname] = numeric;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,17 +17,27 @@ struct CSSuspendInfo final
|
||||
, Serializable
|
||||
{
|
||||
CSSuspendInfo(Extensible *) : Serializable("CSSuspendInfo") { }
|
||||
};
|
||||
|
||||
void Serialize(Serialize::Data &data) const override
|
||||
struct CSSuspendInfoType final
|
||||
: Serialize::Type
|
||||
{
|
||||
CSSuspendInfoType()
|
||||
: Serialize::Type("CSSuspendInfo")
|
||||
{
|
||||
data.Store("chan", what);
|
||||
data.Store("by", by);
|
||||
data.Store("reason", reason);
|
||||
data.Store("time", when);
|
||||
data.Store("expires", expires);
|
||||
}
|
||||
|
||||
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
|
||||
void Serialize(const Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
const auto *si = static_cast<const CSSuspendInfo *>(obj);
|
||||
data.Store("chan", si->what);
|
||||
data.Store("by", si->by);
|
||||
data.Store("reason", si->reason);
|
||||
data.Store("time", si->when);
|
||||
data.Store("expires", si->expires);
|
||||
}
|
||||
|
||||
Serializable *Unserialize(Serializable *obj, Serialize::Data &data) const override
|
||||
{
|
||||
Anope::string schan;
|
||||
data["chan"] >> schan;
|
||||
@@ -67,7 +77,7 @@ public:
|
||||
const Anope::string &chan = params[0];
|
||||
Anope::string expiry = params[1];
|
||||
Anope::string reason = params.size() > 2 ? params[2] : "";
|
||||
time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("suspendexpire");
|
||||
time_t expiry_secs = Config->GetModule(this->owner).Get<time_t>("suspendexpire");
|
||||
|
||||
if (!expiry.empty() && expiry[0] != '+')
|
||||
{
|
||||
@@ -203,7 +213,7 @@ class CSSuspend final
|
||||
CommandCSSuspend commandcssuspend;
|
||||
CommandCSUnSuspend commandcsunsuspend;
|
||||
ExtensibleItem<CSSuspendInfo> suspend;
|
||||
Serialize::Type suspend_type;
|
||||
CSSuspendInfoType suspend_type;
|
||||
std::vector<Anope::string> show;
|
||||
|
||||
struct trim final
|
||||
@@ -227,15 +237,17 @@ class CSSuspend final
|
||||
}
|
||||
|
||||
public:
|
||||
CSSuspend(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
|
||||
commandcssuspend(this), commandcsunsuspend(this), suspend(this, "CS_SUSPENDED"),
|
||||
suspend_type("CSSuspendInfo", CSSuspendInfo::Unserialize)
|
||||
CSSuspend(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, VENDOR)
|
||||
, commandcssuspend(this)
|
||||
, commandcsunsuspend(this)
|
||||
, suspend(this, "CS_SUSPENDED")
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Anope::string s = conf->GetModule(this)->Get<Anope::string>("show");
|
||||
Anope::string s = conf.GetModule(this).Get<Anope::string>("show");
|
||||
commasepstream(s).GetTokens(show);
|
||||
std::transform(show.begin(), show.end(), show.begin(), trim());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
|
||||
class CommandCSSetKeepTopic final
|
||||
: public Command
|
||||
|
||||
+13
-17
@@ -141,7 +141,7 @@ private:
|
||||
|
||||
if (IRCD->IsChannelValid(mask))
|
||||
{
|
||||
if (Config->GetModule("chanserv")->Get<bool>("disallow_channel_access"))
|
||||
if (Config->GetModule("chanserv").Get<bool>("disallow_channel_access"))
|
||||
{
|
||||
source.Reply(_("Channels may not be on access lists."));
|
||||
return;
|
||||
@@ -164,7 +164,7 @@ private:
|
||||
else
|
||||
{
|
||||
na = NickAlias::Find(mask);
|
||||
if (!na && Config->GetModule("chanserv")->Get<bool>("disallow_hostmask_access"))
|
||||
if (!na && Config->GetModule("chanserv").Get<bool>("disallow_hostmask_access"))
|
||||
{
|
||||
source.Reply(_("Masks and unregistered users may not be on access lists."));
|
||||
return;
|
||||
@@ -212,7 +212,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
|
||||
unsigned access_max = Config->GetModule("chanserv").Get<unsigned>("accessmax", "1000");
|
||||
if (access_max && ci->GetDeepAccessCount() >= access_max)
|
||||
{
|
||||
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
|
||||
@@ -319,11 +319,7 @@ private:
|
||||
else
|
||||
{
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, c, ci) << "to delete " << nicks;
|
||||
|
||||
if (deleted == 1)
|
||||
source.Reply(_("Deleted one entry from %s %s list."), ci->name.c_str(), source.command.c_str());
|
||||
else
|
||||
source.Reply(_("Deleted %d entries from %s %s list."), deleted, ci->name.c_str(), source.command.c_str());
|
||||
source.Reply(deleted, N_("Deleted %d entry from %s %s list.", "Deleted %d entries from %s %s list."), deleted, ci->name.c_str(), source.command.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,32 +614,32 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
order.clear();
|
||||
permissions.clear();
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("privilege"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *block = conf->GetBlock("privilege", i);
|
||||
const Anope::string &pname = block->Get<const Anope::string>("name");
|
||||
Configuration::Block &block = conf.GetBlock("privilege", i);
|
||||
const Anope::string &pname = block.Get<const Anope::string>("name");
|
||||
|
||||
Privilege *p = PrivilegeManager::FindPrivilege(pname);
|
||||
if (p == NULL)
|
||||
continue;
|
||||
|
||||
const Anope::string &xop = block->Get<const Anope::string>("xop");
|
||||
const Anope::string &xop = block.Get<const Anope::string>("xop");
|
||||
if (pname.empty() || xop.empty())
|
||||
continue;
|
||||
|
||||
permissions[xop].push_back(pname);
|
||||
}
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("command"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("command"); ++i)
|
||||
{
|
||||
Configuration::Block *block = conf->GetBlock("command", i);
|
||||
const Anope::string &cname = block->Get<const Anope::string>("name"),
|
||||
&cserv = block->Get<const Anope::string>("command");
|
||||
Configuration::Block &block = conf.GetBlock("command", i);
|
||||
const Anope::string &cname = block.Get<const Anope::string>("name"),
|
||||
&cserv = block.Get<const Anope::string>("command");
|
||||
if (cname.empty() || cserv != "chanserv/xop")
|
||||
continue;
|
||||
|
||||
|
||||
@@ -497,16 +497,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
prefix = block->Get<const Anope::string>("prefix", "anope_");
|
||||
SmileysHappy = block->Get<const Anope::string>("SmileysHappy");
|
||||
SmileysSad = block->Get<const Anope::string>("SmileysSad");
|
||||
SmileysOther = block->Get<const Anope::string>("SmileysOther");
|
||||
NSDefChanstats = block->Get<bool>("ns_def_chanstats");
|
||||
CSDefChanstats = block->Get<bool>("cs_def_chanstats");
|
||||
Anope::string engine = block->Get<const Anope::string>("engine");
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
prefix = block.Get<const Anope::string>("prefix", "anope_");
|
||||
SmileysHappy = block.Get<const Anope::string>("SmileysHappy");
|
||||
SmileysSad = block.Get<const Anope::string>("SmileysSad");
|
||||
SmileysOther = block.Get<const Anope::string>("SmileysOther");
|
||||
NSDefChanstats = block.Get<bool>("ns_def_chanstats");
|
||||
CSDefChanstats = block.Get<bool>("cs_def_chanstats");
|
||||
Anope::string engine = block.Get<const Anope::string>("engine");
|
||||
this->sql = ServiceReference<SQL::Provider>("SQL::Provider", engine);
|
||||
if (sql)
|
||||
this->CheckTables();
|
||||
|
||||
+141
-38
@@ -12,16 +12,18 @@
|
||||
#include <functional>
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/bs_kick.h"
|
||||
#include "modules/cs_entrymsg.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/hs_request.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
#include "modules/botserv/kick.h"
|
||||
#include "modules/chanserv/entrymsg.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
#include "modules/hostserv/request.h"
|
||||
#include "modules/info.h"
|
||||
#include "modules/ns_cert.h"
|
||||
#include "modules/os_forbid.h"
|
||||
#include "modules/os_oper.h"
|
||||
#include "modules/os_session.h"
|
||||
#include "modules/nickserv/cert.h"
|
||||
#include "modules/operserv/forbid.h"
|
||||
#include "modules/operserv/news.h"
|
||||
#include "modules/operserv/oper.h"
|
||||
#include "modules/operserv/session.h"
|
||||
#include "modules/set_misc.h"
|
||||
#include "modules/suspend.h"
|
||||
|
||||
// Handles reading from an Atheme database row.
|
||||
@@ -130,7 +132,6 @@ struct ChannelData final
|
||||
|
||||
struct UserData final
|
||||
{
|
||||
bool kill = false;
|
||||
Anope::string info_adder;
|
||||
Anope::string info_message;
|
||||
time_t info_ts = 0;
|
||||
@@ -138,6 +139,8 @@ struct UserData final
|
||||
Anope::string last_quit;
|
||||
Anope::string last_real_mask;
|
||||
bool noexpire = false;
|
||||
bool protect = false;
|
||||
std::optional<time_t> protectafter;
|
||||
Anope::string suspend_by;
|
||||
Anope::string suspend_reason;
|
||||
time_t suspend_ts = 0;
|
||||
@@ -199,6 +202,8 @@ private:
|
||||
{ "JM", &DBAtheme::HandleIgnore },
|
||||
{ "KID", &DBAtheme::HandleIgnore },
|
||||
{ "KL", &DBAtheme::HandleKL },
|
||||
{ "LI", &DBAtheme::HandleLI },
|
||||
{ "LIO", &DBAtheme::HandleLIO },
|
||||
{ "LUID", &DBAtheme::HandleIgnore },
|
||||
{ "MC", &DBAtheme::HandleMC },
|
||||
{ "MCFP", &DBAtheme::HandleMCFP },
|
||||
@@ -500,9 +505,12 @@ private:
|
||||
else
|
||||
{
|
||||
// Generate a new password as we can't use the old one.
|
||||
auto maxpasslen = Config->GetModule("nickserv")->Get<unsigned>("maxpasslen", "50");
|
||||
auto maxpasslen = Config->GetModule("nickserv").Get<unsigned>("maxpasslen", "50");
|
||||
Anope::Encrypt(Anope::Random(maxpasslen), nc->pass);
|
||||
Log(this) << "Unable to convert the password for " << nc->display << " as Anope does not support the format!";
|
||||
|
||||
// If the password is set to * then an external service is being used for authentication.
|
||||
if (pass != "*")
|
||||
Log(this) << "Unable to convert the password for " << nc->display << " as Anope does not support the format!";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -547,7 +555,14 @@ private:
|
||||
if (!row)
|
||||
return row.LogError(this);
|
||||
|
||||
auto *bi = new BotInfo(nick, user, host, real);
|
||||
auto *bi = BotInfo::Find(nick);
|
||||
if (bi)
|
||||
{
|
||||
Log(this) << "Refusing to import duplicate bot: " << nick;
|
||||
return true;
|
||||
}
|
||||
|
||||
bi = new BotInfo(nick, user, host, real);
|
||||
bi->oper_only = operonly;
|
||||
bi->created = created;
|
||||
return true;
|
||||
@@ -787,6 +802,58 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleLI(AthemeRow &row)
|
||||
{
|
||||
// LI <setter> <subject> <ts> <body>
|
||||
auto setter = row.Get();
|
||||
auto subject = row.Get();
|
||||
auto ts = row.GetNum<time_t>();
|
||||
auto body = row.GetRemaining();
|
||||
|
||||
if (!row)
|
||||
return row.LogError(this);
|
||||
|
||||
if (!news_service)
|
||||
{
|
||||
Log(this) << "Unable to convert logon news as os_news is not loaded";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_LOGON;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleLIO(AthemeRow &row)
|
||||
{
|
||||
// LIO <setter> <subject> <ts> <body>
|
||||
auto setter = row.Get();
|
||||
auto subject = row.Get();
|
||||
auto ts = row.GetNum<time_t>();
|
||||
auto body = row.GetRemaining();
|
||||
|
||||
if (!row)
|
||||
return row.LogError(this);
|
||||
|
||||
if (!news_service)
|
||||
{
|
||||
Log(this) << "Unable to convert oper news as os_news is not loaded";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *ni = news_service->CreateNewsItem();
|
||||
ni->type = NEWS_OPER;
|
||||
ni->text = Anope::printf("[%s] %s", subject.c_str(), body.c_str());
|
||||
ni->who = setter;
|
||||
ni->time = ts;
|
||||
news_service->AddNewsItem(ni);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleIgnore(AthemeRow &row)
|
||||
{
|
||||
Log(LOG_DEBUG_3) << "Intentionally ignoring Atheme database row: " << row.GetRow();
|
||||
@@ -1008,6 +1075,20 @@ private:
|
||||
ci->last_topic_time = Anope::Convert<time_t>(value, 0);
|
||||
else if (key.compare(0, 14, "private:stats:", 14) == 0)
|
||||
return HandleIgnoreMetadata(ci->name, key, value);
|
||||
else if (key.find(':') == Anope::string::npos)
|
||||
{
|
||||
ExtensibleRef<MiscData> extref("cs_set_misc:" + key.upper());
|
||||
if (!extref)
|
||||
{
|
||||
Log(this) << "Unknown public channel metadata for " << ci->name << ": " << key << " = " << value;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *data = extref->Set(ci);
|
||||
data->object = ci->name;
|
||||
data->name = key;
|
||||
data->data = value;
|
||||
}
|
||||
else
|
||||
Log(this) << "Unknown channel metadata for " << ci->name << ": " << key << " = " << value;
|
||||
|
||||
@@ -1070,22 +1151,9 @@ private:
|
||||
if (key == "private:autojoin")
|
||||
return true; // TODO
|
||||
else if (key == "private:doenforce")
|
||||
data->kill = true;
|
||||
data->protect = true;
|
||||
else if (key == "private:enforcetime")
|
||||
{
|
||||
if (!data->kill)
|
||||
return true; // Don't apply this.
|
||||
|
||||
auto kill = Config->GetModule("nickserv")->Get<time_t>("kill", "60s");
|
||||
auto killquick = Config->GetModule("nickserv")->Get<time_t>("killquick", "20s");
|
||||
auto secs = Anope::Convert<time_t>(value, kill);
|
||||
if (secs >= kill)
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
else if (secs >= killquick)
|
||||
nc->Shrink<bool>("KILL_QUICK");
|
||||
else
|
||||
nc->Shrink<bool>("KILL_IMMED");
|
||||
}
|
||||
data->protectafter = Anope::TryConvert<time_t>(value);
|
||||
else if (key == "private:freeze:freezer")
|
||||
data->suspend_by = value;
|
||||
else if (key == "private:freeze:reason")
|
||||
@@ -1120,6 +1188,20 @@ private:
|
||||
data->vhost_ts = Anope::Convert<time_t>(value, 0);
|
||||
else if (key.compare(0, 18, "private:usercloak:", 18) == 0)
|
||||
data->vhost_nick[key.substr(18)] = value;
|
||||
else if (key.find(':') == Anope::string::npos)
|
||||
{
|
||||
ExtensibleRef<MiscData> extref("ns_set_misc:" + key.upper());
|
||||
if (!extref)
|
||||
{
|
||||
Log(this) << "Unknown public account metadata for " << nc->display << ": " << key << " = " << value;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto *data = extref->Set(nc);
|
||||
data->object = nc->display;
|
||||
data->name = key;
|
||||
data->data = value;
|
||||
}
|
||||
else
|
||||
Log(this) << "Unknown account metadata for " << nc->display << ": " << key << " = " << value;
|
||||
|
||||
@@ -1172,7 +1254,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
nc->memos.ignores.push_back(ignored);
|
||||
nc->memos.ignores.insert(ignored);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1233,7 +1315,14 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
auto *na = new NickAlias(nick, nc);
|
||||
auto *na = NickAlias::Find(nick);
|
||||
if (na)
|
||||
{
|
||||
Log(this) << "Refusing to import duplicate nick: " << nick;
|
||||
return true;
|
||||
}
|
||||
|
||||
na = new NickAlias(nick, nc);
|
||||
na->time_registered = regtime;
|
||||
na->last_seen = lastseen ? regtime : na->time_registered;
|
||||
|
||||
@@ -1278,13 +1367,20 @@ private:
|
||||
if (!row)
|
||||
return row.LogError(this);
|
||||
|
||||
auto *nc = new NickCore(display);
|
||||
auto *nc = NickCore::Find(display);
|
||||
if (nc)
|
||||
{
|
||||
Log(this) << "Refusing to import duplicate account: " << display;
|
||||
return true;
|
||||
}
|
||||
|
||||
nc = new NickCore(display);
|
||||
nc->email = email;
|
||||
nc->time_registered = regtime;
|
||||
ApplyPassword(nc, flags, pass);
|
||||
|
||||
// No equivalent: bglmNQrS
|
||||
ApplyFlags(nc, flags, 'E', "KILLPROTECT");
|
||||
ApplyFlags(nc, flags, 'E', "PROTECT");
|
||||
ApplyFlags(nc, flags, 'e', "MEMO_MAIL");
|
||||
ApplyFlags(nc, flags, 'n', "NEVEROP");
|
||||
ApplyFlags(nc, flags, 'o', "AUTOOP", false);
|
||||
@@ -1295,7 +1391,7 @@ private:
|
||||
|
||||
// If an Atheme account was awaiting confirmation but Anope is not
|
||||
// configured to use confirmation then autoconfirm it.
|
||||
const auto &nsregister = Config->GetModule("ns_register")->Get<const Anope::string>("registration");
|
||||
const auto &nsregister = Config->GetModule("ns_register").Get<const Anope::string>("registration");
|
||||
if (nsregister.equals_ci("none"))
|
||||
nc->Shrink<bool>("UNCONFIRMED");
|
||||
|
||||
@@ -1453,14 +1549,14 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
flags.clear();
|
||||
for (int i = 0; i < Config->CountBlock("privilege"); ++i)
|
||||
{
|
||||
Configuration::Block *priv = Config->GetBlock("privilege", i);
|
||||
const Anope::string &name = priv->Get<const Anope::string>("name");
|
||||
const Anope::string &value = priv->Get<const Anope::string>("flag");
|
||||
Configuration::Block &priv = Config->GetBlock("privilege", i);
|
||||
const Anope::string &name = priv.Get<const Anope::string>("name");
|
||||
const Anope::string &value = priv.Get<const Anope::string>("flag");
|
||||
if (!name.empty() && !value.empty())
|
||||
flags[name] = value[0];
|
||||
}
|
||||
@@ -1468,7 +1564,7 @@ public:
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
{
|
||||
const auto dbname = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "atheme.db"));
|
||||
const auto dbname = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "atheme.db"));
|
||||
std::ifstream fd(dbname.str());
|
||||
if (!fd.is_open())
|
||||
{
|
||||
@@ -1562,6 +1658,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
if (data->protect)
|
||||
{
|
||||
nc->Extend<bool>("PROTECT");
|
||||
if (data->protectafter)
|
||||
nc->Extend("PROTECT_AFTER", data->protectafter.value());
|
||||
}
|
||||
|
||||
if (!data->suspend_reason.empty())
|
||||
{
|
||||
SuspendInfo si;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
class SaveData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
@@ -38,12 +40,17 @@ class LoadData final
|
||||
: public Serialize::Data
|
||||
{
|
||||
public:
|
||||
std::fstream *fs = nullptr;
|
||||
unsigned int id = 0;
|
||||
std::fstream *fs;
|
||||
Serializable::Id id = 0;
|
||||
std::map<Anope::string, Anope::string> data;
|
||||
std::stringstream ss;
|
||||
bool read = false;
|
||||
|
||||
LoadData(std::fstream &fsref)
|
||||
: fs(&fsref)
|
||||
{
|
||||
}
|
||||
|
||||
std::iostream &operator[](const Anope::string &key) override
|
||||
{
|
||||
if (!read)
|
||||
@@ -52,7 +59,7 @@ public:
|
||||
{
|
||||
if (token.find("ID ") == 0)
|
||||
{
|
||||
this->id = Anope::Convert(token.substr(3), 0);
|
||||
this->id = Anope::Convert<Serializable::Id>(token.substr(3), 0);
|
||||
continue;
|
||||
}
|
||||
else if (token.find("DATA ") != 0)
|
||||
@@ -94,8 +101,6 @@ class DBFlatFile final
|
||||
{
|
||||
/* Day the last backup was on */
|
||||
int last_day = 0;
|
||||
/* Backup file names */
|
||||
std::map<Anope::string, std::list<Anope::string> > backups;
|
||||
bool loaded = false;
|
||||
|
||||
int child_pid = -1;
|
||||
@@ -109,7 +114,7 @@ class DBFlatFile final
|
||||
last_day = tm->tm_mday;
|
||||
|
||||
std::set<Anope::string> dbs;
|
||||
dbs.insert(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
|
||||
dbs.insert(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
@@ -119,11 +124,12 @@ class DBFlatFile final
|
||||
dbs.insert("module_" + stype->GetOwner()->name + ".db");
|
||||
}
|
||||
|
||||
|
||||
const auto backupdir = Anope::ExpandData("backups");
|
||||
for (const auto &db : dbs)
|
||||
{
|
||||
const auto oldname = Anope::ExpandData(db);
|
||||
const auto newname = Anope::ExpandData("backups/" + db + "-" + Anope::ToString(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday));
|
||||
const auto basename = Anope::Expand(backupdir, db + "-");
|
||||
const auto newname = Anope::printf("%s%04i-%02i-%02i", basename.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
|
||||
/* Backup already exists or no database to backup */
|
||||
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
|
||||
@@ -135,7 +141,7 @@ class DBFlatFile final
|
||||
Anope::string err = Anope::LastError();
|
||||
Log(this) << "Unable to back up database " << db << " (" << err << ")!";
|
||||
|
||||
if (!Config->GetModule(this)->Get<bool>("nobackupokay"))
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Unable to back up database " + db + " (" + err + ")";
|
||||
@@ -144,13 +150,29 @@ class DBFlatFile final
|
||||
continue;
|
||||
}
|
||||
|
||||
backups[db].push_back(newname);
|
||||
const auto keepbackups = Config->GetModule(this).Get<unsigned>("keepbackups", "7");
|
||||
if (!keepbackups)
|
||||
continue;
|
||||
|
||||
unsigned keepbackups = Config->GetModule(this)->Get<unsigned>("keepbackups");
|
||||
if (keepbackups > 0 && backups[db].size() > keepbackups)
|
||||
std::error_code ec;
|
||||
std::set<Anope::string> old_backups;
|
||||
for (const auto &entry : std::filesystem::directory_iterator(backupdir.str(), ec))
|
||||
{
|
||||
unlink(backups[db].front().c_str());
|
||||
backups[db].pop_front();
|
||||
Anope::string entryname = entry.path().string();
|
||||
if (entryname.compare(0, basename.length(), basename) != 0)
|
||||
continue;
|
||||
|
||||
old_backups.insert(entryname);
|
||||
if (old_backups.size() <= keepbackups)
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "Deleting expired backup " << *old_backups.begin();
|
||||
if (!std::filesystem::remove(old_backups.begin()->str(), ec))
|
||||
{
|
||||
Log(this) << "Failed to delete expired backup " << *old_backups.begin() << ": " << ec.message();
|
||||
continue;
|
||||
}
|
||||
old_backups.erase(old_backups.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -200,7 +222,7 @@ public:
|
||||
|
||||
Log(this) << "Error saving databases: " << buf;
|
||||
|
||||
if (!Config->GetModule(this)->Get<bool>("nobackupokay"))
|
||||
if (!Config->GetModule(this).Get<bool>("nobackupokay"))
|
||||
Anope::Quitting = true;
|
||||
}
|
||||
|
||||
@@ -208,7 +230,7 @@ public:
|
||||
{
|
||||
std::set<Anope::string> tried_dbs;
|
||||
|
||||
const auto db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
|
||||
const auto db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!fd.is_open())
|
||||
@@ -223,9 +245,7 @@ public:
|
||||
if (buf.find("OBJECT ") == 0)
|
||||
positions[buf.substr(7)].push_back(fd.tellg());
|
||||
|
||||
LoadData ld;
|
||||
ld.fs = &fd;
|
||||
|
||||
LoadData ld(fd);
|
||||
for (const auto &type_order : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
Serialize::Type *stype = Serialize::Type::Find(type_order);
|
||||
@@ -263,7 +283,7 @@ public:
|
||||
|
||||
int i = -1;
|
||||
#ifndef _WIN32
|
||||
if (!Anope::Quitting && Config->GetModule(this)->Get<bool>("fork"))
|
||||
if (!Anope::Quitting && Config->GetModule(this).Get<bool>("fork"))
|
||||
{
|
||||
i = fork();
|
||||
if (i > 0)
|
||||
@@ -290,7 +310,7 @@ public:
|
||||
if (s_type->GetOwner())
|
||||
db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
|
||||
else
|
||||
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
|
||||
db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream((db_name + ".tmp").c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
|
||||
|
||||
@@ -313,13 +333,13 @@ public:
|
||||
*data.fs << "OBJECT " << s_type->GetName();
|
||||
if (base->id)
|
||||
*data.fs << "\nID " << base->id;
|
||||
base->Serialize(data);
|
||||
s_type->Serialize(base, data);
|
||||
*data.fs << "\nEND\n";
|
||||
}
|
||||
|
||||
for (auto &[mod, f] : databases)
|
||||
{
|
||||
const auto db_name = Anope::ExpandData((mod ? (mod->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db")));
|
||||
const auto db_name = Anope::ExpandData((mod ? (mod->name + ".db") : Config->GetModule(this).Get<const Anope::string>("database", "anope.db")));
|
||||
|
||||
if (!f->is_open() || !f->good())
|
||||
{
|
||||
@@ -363,7 +383,7 @@ public:
|
||||
if (stype->GetOwner())
|
||||
db_name = Anope::ExpandData("module_" + stype->GetOwner()->name + ".db");
|
||||
else
|
||||
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
|
||||
db_name = Anope::ExpandData(Config->GetModule(this).Get<const Anope::string>("database", "anope.db"));
|
||||
|
||||
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!fd.is_open())
|
||||
@@ -372,9 +392,7 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
LoadData ld;
|
||||
ld.fs = &fd;
|
||||
|
||||
LoadData ld(fd);
|
||||
for (Anope::string buf; std::getline(fd, buf.str());)
|
||||
{
|
||||
if (buf == "OBJECT " + stype->GetName())
|
||||
|
||||
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
*
|
||||
* (C) 2003-2025 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 <filesystem>
|
||||
|
||||
#include "yyjson/yyjson.c"
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#define ANOPE_DATABASE_VERSION 1
|
||||
|
||||
// TODO:
|
||||
// * forking into background
|
||||
// * stable key order
|
||||
|
||||
inline Anope::string yyjson_mut_get_astr(yyjson_mut_val *val)
|
||||
{
|
||||
const auto *str = yyjson_mut_get_str(val);
|
||||
return str ? str : "";
|
||||
}
|
||||
|
||||
inline void yyjson_mut_obj_upsert(yyjson_mut_doc *doc, yyjson_mut_val *obj, const char *key, yyjson_mut_val *val)
|
||||
{
|
||||
auto *oldval = yyjson_mut_obj_get(obj, key);
|
||||
if (oldval)
|
||||
yyjson_mut_obj_replace(obj, yyjson_mut_str(doc, key), val);
|
||||
else
|
||||
yyjson_mut_obj_add_val(doc, obj, key, val);
|
||||
}
|
||||
|
||||
class Data final
|
||||
: public Serialize::Data
|
||||
{
|
||||
public:
|
||||
// If non-zero then the id of the database entry.
|
||||
Serializable::Id id = 0;
|
||||
|
||||
// Data in this database entry.
|
||||
Anope::map<std::stringstream> data;
|
||||
|
||||
// Used when writing data.
|
||||
Data() = default;
|
||||
|
||||
// Used when reading data.
|
||||
Data(yyjson_mut_val *elem)
|
||||
{
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *key, *value;
|
||||
yyjson_mut_obj_foreach(elem, idx, max, key, value)
|
||||
{
|
||||
if (yyjson_mut_get_type(key) != YYJSON_TYPE_STR)
|
||||
continue;
|
||||
|
||||
Anope::string akey(yyjson_mut_get_str(key));
|
||||
if (akey.equals_ci("id"))
|
||||
{
|
||||
this->id = yyjson_mut_get_uint(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (yyjson_mut_is_bool(value))
|
||||
data[akey] << yyjson_mut_get_bool(value);
|
||||
else if (yyjson_mut_is_int(value))
|
||||
data[akey] << yyjson_mut_get_int(value);
|
||||
else if (yyjson_mut_is_null(value))
|
||||
data[akey];
|
||||
else if (yyjson_mut_is_real(value))
|
||||
data[akey] << yyjson_mut_get_real(value);
|
||||
else if (yyjson_mut_is_str(value))
|
||||
data[akey] << yyjson_mut_get_str(value);
|
||||
else if (yyjson_mut_is_uint(value))
|
||||
data[akey] << yyjson_mut_get_uint(value);
|
||||
}
|
||||
}
|
||||
|
||||
std::iostream &operator[](const Anope::string &key) override
|
||||
{
|
||||
return data[key];
|
||||
}
|
||||
};
|
||||
|
||||
class DBJSON final
|
||||
: public Module
|
||||
{
|
||||
private:
|
||||
using DBPair = std::pair<yyjson_mut_doc *, yyjson_mut_val *>;
|
||||
|
||||
// The databases which have already been loaded from disk.
|
||||
std::unordered_map<Module *, DBPair> databases;
|
||||
|
||||
// Whether OnLoadDatabase has been called yet.
|
||||
bool loaded = false;
|
||||
|
||||
Anope::string GetDatabaseFile(Module *mod)
|
||||
{
|
||||
Anope::string filename;
|
||||
if (mod)
|
||||
{
|
||||
// We are reading the name of a module database.
|
||||
filename = Config->GetModule(this)
|
||||
.Get<Anope::string>("module_database", "{name}.module.json")
|
||||
.replace_all_cs("{name}", mod->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are reading a the name of the core database.
|
||||
filename = Config->GetModule(this)
|
||||
.Get<Anope::string>("database", "anope.json");
|
||||
}
|
||||
|
||||
return Anope::ExpandData(filename);
|
||||
}
|
||||
|
||||
void BackupDatabase(const Anope::string &dbname)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::error_code ec;
|
||||
fs::path dbpath(dbname.str());
|
||||
if (!fs::exists(dbpath, ec) || ec)
|
||||
return; // Nothing to backup.
|
||||
|
||||
auto &modconf = Config->GetModule(this);
|
||||
auto backups = modconf.Get<unsigned>("backups", "14");
|
||||
if (!backups)
|
||||
return; // No backups
|
||||
|
||||
auto ignore_backup_failure = modconf.Get<bool>("ignore_backup_failure");
|
||||
|
||||
auto backupdir = Anope::ExpandData(modconf.Get<Anope::string>("backup_directory", "backups"));
|
||||
if (!fs::is_directory(backupdir.str(), ec) && !ec)
|
||||
{
|
||||
fs::create_directories(backupdir.str(), ec);
|
||||
if (ec)
|
||||
{
|
||||
Log(this) << "Failed to create backup directory: " << ec.message();
|
||||
if (!ignore_backup_failure)
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Failed to create backup directory: " + ec.message();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char timebuf[16];
|
||||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d", localtime(&Anope::CurTime));
|
||||
|
||||
auto backupbase = Anope::Expand(backupdir, dbpath.filename().string()) + ".";
|
||||
auto backupname = backupbase + timebuf;
|
||||
|
||||
Log(LOG_DEBUG) << "Copying " << dbname << " to " << backupname;
|
||||
if (!fs::copy_file(dbname.str(), backupname.str(), fs::copy_options::overwrite_existing, ec))
|
||||
{
|
||||
Log(this) << "Failed to copy " << dbname << " to " << backupname << ": " << ec.message();
|
||||
if (!ignore_backup_failure)
|
||||
{
|
||||
Anope::Quitting = true;
|
||||
Anope::QuitReason = "Failed to copy " + dbname + " to " + backupname + ": " + ec.message();
|
||||
}
|
||||
}
|
||||
|
||||
// Delete older backups.
|
||||
std::set<Anope::string> old_backups;
|
||||
for (const auto &entry : fs::directory_iterator(backupdir.str(), ec))
|
||||
{
|
||||
Anope::string entryname = entry.path().string();
|
||||
if (entryname.compare(0, backupbase.length(), backupbase) != 0)
|
||||
continue; // Not one of our backups.
|
||||
|
||||
old_backups.insert(entryname);
|
||||
if (old_backups.size() <= backups)
|
||||
continue;
|
||||
|
||||
Log(LOG_DEBUG) << "Deleting expired backup " << *old_backups.begin();
|
||||
if (!fs::remove(old_backups.begin()->str(), ec))
|
||||
{
|
||||
Log(this) << "Failed to delete expired backup " << *old_backups.begin() << ": " << ec.message();
|
||||
break;
|
||||
}
|
||||
old_backups.erase(old_backups.begin());
|
||||
}
|
||||
}
|
||||
|
||||
DBPair ReadDatabase(const Anope::string &dbname)
|
||||
{
|
||||
yyjson_read_err errmsg;
|
||||
const auto flags = YYJSON_READ_ALLOW_TRAILING_COMMAS | YYJSON_READ_ALLOW_INVALID_UNICODE;
|
||||
auto *idoc = yyjson_read_file(dbname.c_str(), flags, nullptr, &errmsg);
|
||||
if (!idoc)
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": error #" << errmsg.code << ": " << errmsg.msg;
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
// We operate on a mutable document because we need to write to it later.
|
||||
auto *doc = yyjson_doc_mut_copy(idoc, nullptr);
|
||||
yyjson_doc_free(idoc);
|
||||
|
||||
auto *root = yyjson_mut_doc_get_root(doc);
|
||||
if (!yyjson_mut_is_obj(root))
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": root element is not an object";
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
auto version = yyjson_mut_get_uint(yyjson_mut_obj_get(root, "version"));
|
||||
if (version && version != ANOPE_DATABASE_VERSION)
|
||||
{
|
||||
Log(this) << "Refusing to load an unsupported database version: " << version;
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
auto generator = yyjson_mut_get_astr(yyjson_mut_obj_get(root, "generator"));
|
||||
auto updated = yyjson_mut_get_uint(yyjson_mut_obj_get(root, "updated"));
|
||||
Log(LOG_DEBUG) << "Database " << dbname << " was generated on " << Anope::strftime(updated) << " by " << generator;
|
||||
|
||||
auto *data = yyjson_mut_obj_get(root, "data");
|
||||
if (!data || !yyjson_mut_is_obj(data))
|
||||
{
|
||||
Log(this) << "Unable to read " << dbname << ": data element is missing or not an object";
|
||||
return { nullptr, nullptr };
|
||||
}
|
||||
|
||||
return { doc, data };
|
||||
}
|
||||
|
||||
static void UpdateMetadata(yyjson_mut_doc *doc, yyjson_mut_val *obj)
|
||||
{
|
||||
const auto generator = "Anope " + Anope::Version();
|
||||
yyjson_mut_obj_upsert(doc, obj, "generator", yyjson_mut_strncpy(doc, generator.c_str(), generator.length()));
|
||||
yyjson_mut_obj_upsert(doc, obj, "version", yyjson_mut_uint(doc, ANOPE_DATABASE_VERSION));
|
||||
yyjson_mut_obj_upsert(doc, obj, "updated", yyjson_mut_int(doc, Anope::CurTime));
|
||||
}
|
||||
|
||||
public:
|
||||
DBJSON(const Anope::string &modname, const Anope::string &creator)
|
||||
: Module(modname, creator, DATABASE | VENDOR)
|
||||
{
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
{
|
||||
auto dbname = GetDatabaseFile(nullptr);
|
||||
|
||||
auto [doc, data] = ReadDatabase(dbname);
|
||||
if (!data)
|
||||
return EVENT_STOP;
|
||||
|
||||
for (const auto &type : Serialize::Type::GetTypeOrder())
|
||||
{
|
||||
auto *s_type = Serialize::Type::Find(type);
|
||||
if (!s_type || !s_type->GetOwner())
|
||||
continue;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *elem;
|
||||
yyjson_mut_arr_foreach(data, idx, max, elem)
|
||||
{
|
||||
Data ld(elem);
|
||||
s_type->Unserialize(nullptr, ld);
|
||||
}
|
||||
}
|
||||
|
||||
loaded = false;
|
||||
return EVENT_STOP;
|
||||
}
|
||||
|
||||
void OnSaveDatabase() override
|
||||
{
|
||||
std::set<Module *> updated;
|
||||
for (const auto &[_, s_type] : Serialize::Type::GetTypes())
|
||||
{
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
if (it == databases.end())
|
||||
{
|
||||
auto *doc = yyjson_mut_doc_new(nullptr);
|
||||
|
||||
auto *root = yyjson_mut_obj(doc);
|
||||
yyjson_mut_doc_set_root(doc, root);
|
||||
|
||||
UpdateMetadata(doc, root);
|
||||
|
||||
auto *data = yyjson_mut_obj(doc);
|
||||
yyjson_mut_obj_add_val(doc, root, "data", data);
|
||||
|
||||
databases[s_type->GetOwner()] = { doc, data };
|
||||
}
|
||||
else if (updated.find(s_type->GetOwner()) == updated.end())
|
||||
{
|
||||
auto *doc = it->second.first;
|
||||
auto *root = yyjson_mut_doc_get_root(doc);
|
||||
|
||||
UpdateMetadata(doc, root);
|
||||
updated.insert(s_type->GetOwner());
|
||||
}
|
||||
}
|
||||
|
||||
std::set<Serialize::Type *> seen;
|
||||
for (auto *item : Serializable::GetItems())
|
||||
{
|
||||
auto *s_type = item->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue; // Provider has been unloaded.
|
||||
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
if (it == databases.end())
|
||||
continue; // Type has not been registered?
|
||||
|
||||
auto &[doc, data] = it->second;
|
||||
|
||||
// If the type object doesn't exist then create it. Otherwise, clear.
|
||||
// all of the previous objects stored in it.
|
||||
auto *type = yyjson_mut_obj_getn(data, s_type->GetName().c_str(), s_type->GetName().length());
|
||||
if (!type || yyjson_mut_get_type(type) != YYJSON_TYPE_ARR)
|
||||
{
|
||||
// We haven't seen this element before.
|
||||
type = yyjson_mut_arr(doc);
|
||||
yyjson_mut_obj_add_val(doc, data, s_type->GetName().c_str(), type);
|
||||
}
|
||||
else if (seen.find(s_type) == seen.end())
|
||||
{
|
||||
// We are reusing an existing element, clear it.
|
||||
yyjson_mut_arr_clear(type);
|
||||
seen.insert(s_type);
|
||||
}
|
||||
|
||||
auto *elem = yyjson_mut_arr_add_obj(doc, type);
|
||||
if (item->id)
|
||||
yyjson_mut_obj_add_uint(doc, elem, "id", item->id);
|
||||
|
||||
Data sd;
|
||||
s_type->Serialize(item, sd);
|
||||
for (const auto &[key, value] : sd.data)
|
||||
{
|
||||
yyjson_mut_val *v;
|
||||
switch (sd.GetType(key))
|
||||
{
|
||||
case Serialize::DataType::BOOL:
|
||||
v = yyjson_mut_bool(doc, Anope::Convert<bool>(value.str(), false));
|
||||
break;
|
||||
case Serialize::DataType::FLOAT:
|
||||
v = yyjson_mut_real(doc, Anope::Convert<double>(value.str(), 0.0));
|
||||
break;
|
||||
case Serialize::DataType::INT:
|
||||
v = yyjson_mut_int(doc, Anope::Convert<int64_t>(value.str(), 0));
|
||||
break;
|
||||
case Serialize::DataType::TEXT:
|
||||
{
|
||||
auto str = value.str();
|
||||
v = str.empty() ? yyjson_mut_null(doc) : yyjson_mut_strncpy(doc, str.c_str(), str.length());
|
||||
break;
|
||||
}
|
||||
case Serialize::DataType::UINT:
|
||||
v = yyjson_mut_uint(doc, Anope::Convert<uint64_t>(value.str(), 0));
|
||||
break;
|
||||
}
|
||||
|
||||
auto *k = yyjson_mut_strncpy(doc, key.c_str(), key.length());
|
||||
yyjson_mut_obj_add(elem, k, v);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &[mod, database] : databases)
|
||||
{
|
||||
auto dbname = GetDatabaseFile(mod);
|
||||
BackupDatabase(dbname);
|
||||
|
||||
yyjson_write_err errmsg;
|
||||
const auto flags = YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END | YYJSON_WRITE_PRETTY;
|
||||
if (!yyjson_mut_write_file(dbname.c_str(), database.first, flags, nullptr, &errmsg))
|
||||
{
|
||||
Log(this) << "Unable to write " << dbname << ": error #" << errmsg.code << ": " << errmsg.msg;
|
||||
// TODO: exit??? retry???
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnSerializeTypeCreate(Serialize::Type *s_type) override
|
||||
{
|
||||
if (!loaded)
|
||||
return; // We are creating on boot.
|
||||
|
||||
auto it = databases.find(s_type->GetOwner());
|
||||
if (it == databases.end())
|
||||
{
|
||||
// The database for this type hasn't been loaded yet.
|
||||
const auto dbname = GetDatabaseFile(s_type->GetOwner());
|
||||
|
||||
auto db = ReadDatabase(dbname);
|
||||
if (!db.second)
|
||||
return; // Not much we can do here.
|
||||
|
||||
it = databases.emplace(s_type->GetOwner(), db).first;
|
||||
}
|
||||
|
||||
auto &[doc, data] = it->second;
|
||||
|
||||
size_t idx, max;
|
||||
yyjson_mut_val *elem;
|
||||
yyjson_mut_arr_foreach(data, idx, max, elem)
|
||||
{
|
||||
Data ld(elem);
|
||||
s_type->Unserialize(nullptr, ld);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MODULE_INIT(DBJSON)
|
||||
+37
-13
@@ -10,14 +10,15 @@
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "modules/os_session.h"
|
||||
#include "modules/bs_kick.h"
|
||||
#include "modules/cs_mode.h"
|
||||
#include "modules/bs_badwords.h"
|
||||
#include "modules/os_news.h"
|
||||
#include "modules/botserv/badwords.h"
|
||||
#include "modules/botserv/kick.h"
|
||||
#include "modules/chanserv/entrymsg.h"
|
||||
#include "modules/chanserv/mode.h"
|
||||
#include "modules/operserv/forbid.h"
|
||||
#include "modules/operserv/news.h"
|
||||
#include "modules/operserv/session.h"
|
||||
#include "modules/set_misc.h"
|
||||
#include "modules/suspend.h"
|
||||
#include "modules/os_forbid.h"
|
||||
#include "modules/cs_entrymsg.h"
|
||||
|
||||
#define READ(x) \
|
||||
if (true) \
|
||||
@@ -473,14 +474,31 @@ static void LoadNicks()
|
||||
|
||||
uint32_t u32;
|
||||
READ(read_uint32(&u32, f));
|
||||
//nc->icq = u32;
|
||||
ExtensibleRef<MiscData> icqref("ns_set_misc:ICQ");
|
||||
if (icqref && u32 > 0)
|
||||
{
|
||||
MiscData *data = icqref->Set(nc);
|
||||
data->object = nc->display;
|
||||
data->name = "ns_set_misc:ICQ";
|
||||
data->data = Anope::ToString(u32);
|
||||
}
|
||||
|
||||
READ(read_string(buffer, f));
|
||||
//nc->url = buffer;
|
||||
ExtensibleRef<MiscData> urlref("ns_set_misc:URL");
|
||||
if (urlref && !buffer.empty())
|
||||
{
|
||||
MiscData *data = icqref->Set(nc);
|
||||
data->object = nc->display;
|
||||
data->name = "ns_set_misc:URL";
|
||||
data->data = buffer;
|
||||
}
|
||||
|
||||
READ(read_uint32(&u32, f));
|
||||
if (u32 & OLD_NI_KILLPROTECT)
|
||||
nc->Extend<bool>("KILLPROTECT");
|
||||
{
|
||||
nc->Extend<bool>("PROTECT");
|
||||
nc->Extend("PROTECT_AFTER", 60);
|
||||
}
|
||||
if (u32 & OLD_NI_MSG)
|
||||
nc->Extend<bool>("MSG");
|
||||
if (u32 & OLD_NI_MEMO_HARDMAX)
|
||||
@@ -498,9 +516,15 @@ static void LoadNicks()
|
||||
if (u32 & OLD_NI_HIDE_QUIT)
|
||||
nc->Extend<bool>("HIDE_QUIT");
|
||||
if (u32 & OLD_NI_KILL_QUICK)
|
||||
nc->Extend<bool>("KILL_QUICK");
|
||||
{
|
||||
nc->Extend<bool>("PROTECT");
|
||||
nc->Extend("PROTECT_AFTER", 20);
|
||||
}
|
||||
if (u32 & OLD_NI_KILL_IMMED)
|
||||
nc->Extend<bool>("KILL_IMMED");
|
||||
{
|
||||
nc->Extend<bool>("PROTECT");
|
||||
nc->Extend<time_t>("PROTECT_AFTER", 0);
|
||||
}
|
||||
if (u32 & OLD_NI_MEMO_MAIL)
|
||||
nc->Extend<bool>("MEMO_MAIL");
|
||||
if (u32 & OLD_NI_HIDE_STATUS)
|
||||
@@ -1296,7 +1320,7 @@ public:
|
||||
{
|
||||
|
||||
|
||||
hashm = Config->GetModule(this)->Get<const Anope::string>("hash");
|
||||
hashm = Config->GetModule(this).Get<const Anope::string>("hash");
|
||||
|
||||
if (hashm != "md5" && hashm != "oldmd5" && hashm != "sha1" && hashm != "plain" && hashm != "sha256")
|
||||
throw ModuleException("Invalid hash method");
|
||||
|
||||
@@ -145,7 +145,7 @@ public:
|
||||
else
|
||||
{
|
||||
Data data;
|
||||
obj->Serialize(data);
|
||||
t->Serialize(obj, data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
return;
|
||||
@@ -171,10 +171,10 @@ public:
|
||||
this->updated_items.clear();
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
this->redis = ServiceReference<Provider>("Redis::Provider", block->Get<const Anope::string>("engine", "redis/main"));
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
this->redis = ServiceReference<Provider>("Redis::Provider", block.Get<const Anope::string>("engine", "redis/main"));
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
@@ -402,7 +402,7 @@ void Updater::OnResult(const Reply &r)
|
||||
}
|
||||
|
||||
Data data;
|
||||
obj->Serialize(data);
|
||||
st->Serialize(obj, data);
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
@@ -492,7 +492,7 @@ void SubscriptionListener::OnResult(const Reply &r)
|
||||
if (s_type == NULL)
|
||||
return;
|
||||
|
||||
auto oid = Anope::TryConvert<uint64_t>(id);
|
||||
auto oid = Anope::TryConvert<Serializable::Id>(id);
|
||||
if (!oid.has_value())
|
||||
return;
|
||||
|
||||
@@ -526,8 +526,7 @@ void SubscriptionListener::OnResult(const Reply &r)
|
||||
Log(LOG_DEBUG) << "redis: notify: deleting object id " << obj_id << " of type " << type;
|
||||
|
||||
Data data;
|
||||
|
||||
s->Serialize(data);
|
||||
s_type->Serialize(s, data);
|
||||
|
||||
/* Transaction start */
|
||||
me->redis->StartTransaction();
|
||||
@@ -578,8 +577,7 @@ void ModifiedObject::OnResult(const Reply &r)
|
||||
if (obj)
|
||||
{
|
||||
Data data;
|
||||
|
||||
obj->Serialize(data);
|
||||
st->Serialize(obj, data);
|
||||
|
||||
for (auto &[key, value] : data.data)
|
||||
{
|
||||
|
||||
+16
-14
@@ -109,12 +109,19 @@ public:
|
||||
|
||||
void OnNotify() override
|
||||
{
|
||||
for (auto *obj : this->updated_items)
|
||||
std::set<Serializable *> items;
|
||||
std::swap(this->updated_items, items);
|
||||
|
||||
for (auto *obj : items)
|
||||
{
|
||||
if (this->sql)
|
||||
{
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
Data data;
|
||||
obj->Serialize(data);
|
||||
s_type->Serialize(obj, data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
continue;
|
||||
@@ -125,10 +132,6 @@ public:
|
||||
if (!this->loaded && !this->imported && !this->import)
|
||||
continue;
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
auto create = this->sql->CreateTable(GetTableName(s_type), data);
|
||||
auto insert = this->sql->BuildInsert(GetTableName(s_type), obj->id, data);
|
||||
|
||||
@@ -154,16 +157,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
this->updated_items.clear();
|
||||
this->imported = true;
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
this->sql = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
|
||||
this->prefix = block->Get<const Anope::string>("prefix", "anope_db_");
|
||||
this->import = block->Get<bool>("import");
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
this->sql = ServiceReference<Provider>("SQL::Provider", block.Get<const Anope::string>("engine"));
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope_db_");
|
||||
this->import = block.Get<bool>("import");
|
||||
}
|
||||
|
||||
void OnPostInit() override
|
||||
@@ -255,7 +257,7 @@ public:
|
||||
Serializable *obj = sb->Unserialize(NULL, data);
|
||||
if (obj)
|
||||
{
|
||||
auto oid = Anope::TryConvert<unsigned int>(res.Get(j, "id"));
|
||||
auto oid = Anope::TryConvert<Serializable::Id>(res.Get(j, "id"));
|
||||
if (oid.has_value())
|
||||
obj->id = oid.value();
|
||||
else
|
||||
@@ -267,7 +269,7 @@ public:
|
||||
*/
|
||||
|
||||
Data data2;
|
||||
obj->Serialize(data2);
|
||||
sb->Serialize(obj, data2);
|
||||
obj->UpdateCache(data2); /* We know this is the most up to date copy */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "2m") > lastwarn)
|
||||
if (Anope::CurTime - Config->GetBlock("options").Get<time_t>("updatetimeout", "2m") > lastwarn)
|
||||
{
|
||||
Log() << "Unable to locate SQL reference, going to readonly...";
|
||||
Anope::ReadOnly = this->ro = true;
|
||||
@@ -89,22 +89,25 @@ public:
|
||||
if (!this->CheckInit())
|
||||
return;
|
||||
|
||||
for (auto *obj : this->updated_items)
|
||||
std::set<Serializable *> items;
|
||||
std::swap(this->updated_items, items);
|
||||
|
||||
for (auto *obj : items)
|
||||
{
|
||||
if (obj && this->SQL)
|
||||
{
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
Data data;
|
||||
obj->Serialize(data);
|
||||
s_type->Serialize(obj, data);
|
||||
|
||||
if (obj->IsCached(data))
|
||||
continue;
|
||||
|
||||
obj->UpdateCache(data);
|
||||
|
||||
Serialize::Type *s_type = obj->GetSerializableType();
|
||||
if (!s_type)
|
||||
continue;
|
||||
|
||||
auto create = this->SQL->CreateTable(GetTableName(s_type), data);
|
||||
for (const auto &query : create)
|
||||
this->RunQuery(query);
|
||||
@@ -118,8 +121,6 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->updated_items.clear();
|
||||
}
|
||||
|
||||
EventReturn OnLoadDatabase() override
|
||||
@@ -138,11 +139,11 @@ public:
|
||||
init = false;
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
this->SQL = ServiceReference<Provider>("SQL::Provider", block->Get<const Anope::string>("engine"));
|
||||
this->prefix = block->Get<const Anope::string>("prefix", "anope_db_");
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
this->SQL = ServiceReference<Provider>("SQL::Provider", block.Get<const Anope::string>("engine"));
|
||||
this->prefix = block.Get<const Anope::string>("prefix", "anope_db_");
|
||||
}
|
||||
|
||||
void OnSerializableConstruct(Serializable *obj) override
|
||||
@@ -190,7 +191,7 @@ public:
|
||||
|
||||
|
||||
|
||||
auto oid = Anope::TryConvert<unsigned int>(res.Get(i, "id"));
|
||||
auto oid = Anope::TryConvert<Serializable::Id>(res.Get(i, "id"));
|
||||
if (!oid.has_value())
|
||||
{
|
||||
Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName();
|
||||
@@ -201,7 +202,7 @@ public:
|
||||
if (res.Get(i, "timestamp").empty())
|
||||
{
|
||||
clear_null = true;
|
||||
std::map<uint64_t, Serializable *>::iterator it = obj->objects.find(id);
|
||||
auto it = obj->objects.find(id);
|
||||
if (it != obj->objects.end())
|
||||
delete it->second; // This also removes this object from the map
|
||||
}
|
||||
@@ -213,7 +214,7 @@ public:
|
||||
data[key] << value;
|
||||
|
||||
Serializable *s = NULL;
|
||||
std::map<uint64_t, Serializable *>::iterator it = obj->objects.find(id);
|
||||
auto it = obj->objects.find(id);
|
||||
if (it != obj->objects.end())
|
||||
s = it->second;
|
||||
|
||||
@@ -232,7 +233,7 @@ public:
|
||||
*/
|
||||
|
||||
Data data2;
|
||||
new_s->Serialize(data2);
|
||||
obj->Serialize(new_s, data2);
|
||||
new_s->UpdateCache(data2); /* We know this is the most up to date copy */
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -1045,23 +1045,23 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
|
||||
nameserver = block->Get<const Anope::string>("nameserver", "127.0.0.1");
|
||||
timeout = block->Get<time_t>("timeout", "5");
|
||||
ip = block->Get<const Anope::string>("ip", "0.0.0.0");
|
||||
port = block->Get<int>("port", "53");
|
||||
admin = block->Get<const Anope::string>("admin", "admin@example.com");
|
||||
nameservers = block->Get<const Anope::string>("nameservers", "ns1.example.com");
|
||||
refresh = block->Get<int>("refresh", "3600");
|
||||
nameserver = block.Get<const Anope::string>("nameserver", "127.0.0.1");
|
||||
timeout = block.Get<time_t>("timeout", "5");
|
||||
ip = block.Get<const Anope::string>("ip", "0.0.0.0");
|
||||
port = block.Get<int>("port", "53");
|
||||
admin = block.Get<const Anope::string>("admin", "admin@example.com");
|
||||
nameservers = block.Get<const Anope::string>("nameservers", "ns1.example.com");
|
||||
refresh = block.Get<int>("refresh", "3600");
|
||||
|
||||
for (int i = 0; i < block->CountBlock("notify"); ++i)
|
||||
for (int i = 0; i < block.CountBlock("notify"); ++i)
|
||||
{
|
||||
Configuration::Block *n = block->GetBlock("notify", i);
|
||||
Anope::string nip = n->Get<Anope::string>("ip");
|
||||
short nport = n->Get<short>("port");
|
||||
Configuration::Block &n = block.GetBlock("notify", i);
|
||||
Anope::string nip = n.Get<Anope::string>("ip");
|
||||
short nport = n.Get<short>("port");
|
||||
|
||||
notify.emplace_back(nip, nport);
|
||||
}
|
||||
|
||||
+19
-19
@@ -77,7 +77,7 @@ public:
|
||||
reason = reason.replace_all_cs("%h", user->host);
|
||||
reason = reason.replace_all_cs("%i", addr);
|
||||
reason = reason.replace_all_cs("%r", reply ? reply->reason : "");
|
||||
reason = reason.replace_all_cs("%N", Config->GetBlock("networkinfo")->Get<const Anope::string>("networkname"));
|
||||
reason = reason.replace_all_cs("%N", Config->GetBlock("networkinfo").Get<const Anope::string>("networkname"));
|
||||
|
||||
BotInfo *OperServ = Config->GetClient("OperServ");
|
||||
Log(creator, "dnsbl", OperServ) << user->GetMask() << " (" << addr << ") appears in " << this->blacklist.name;
|
||||
@@ -110,33 +110,33 @@ public:
|
||||
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *block = conf->GetModule(this);
|
||||
this->check_on_connect = block->Get<bool>("check_on_connect");
|
||||
this->check_on_netburst = block->Get<bool>("check_on_netburst");
|
||||
this->add_to_akill = block->Get<bool>("add_to_akill", "yes");
|
||||
Configuration::Block &block = conf.GetModule(this);
|
||||
this->check_on_connect = block.Get<bool>("check_on_connect");
|
||||
this->check_on_netburst = block.Get<bool>("check_on_netburst");
|
||||
this->add_to_akill = block.Get<bool>("add_to_akill", "yes");
|
||||
|
||||
this->blacklists.clear();
|
||||
for (int i = 0; i < block->CountBlock("blacklist"); ++i)
|
||||
for (int i = 0; i < block.CountBlock("blacklist"); ++i)
|
||||
{
|
||||
Configuration::Block *bl = block->GetBlock("blacklist", i);
|
||||
Configuration::Block &bl = block.GetBlock("blacklist", i);
|
||||
Blacklist blacklist;
|
||||
|
||||
blacklist.name = bl->Get<Anope::string>("name");
|
||||
blacklist.name = bl.Get<Anope::string>("name");
|
||||
if (blacklist.name.empty())
|
||||
continue;
|
||||
blacklist.bantime = bl->Get<time_t>("time", "4h");
|
||||
blacklist.reason = bl->Get<Anope::string>("reason");
|
||||
blacklist.bantime = bl.Get<time_t>("time", "4h");
|
||||
blacklist.reason = bl.Get<Anope::string>("reason");
|
||||
|
||||
for (int j = 0; j < bl->CountBlock("reply"); ++j)
|
||||
for (int j = 0; j < bl.CountBlock("reply"); ++j)
|
||||
{
|
||||
Configuration::Block *reply = bl->GetBlock("reply", j);
|
||||
Configuration::Block &reply = bl.GetBlock("reply", j);
|
||||
Blacklist::Reply r;
|
||||
|
||||
r.code = reply->Get<int>("code");
|
||||
r.reason = reply->Get<Anope::string>("reason");
|
||||
r.allow_account = reply->Get<bool>("allow_account");
|
||||
r.code = reply.Get<int>("code");
|
||||
r.reason = reply.Get<Anope::string>("reason");
|
||||
r.allow_account = reply.Get<bool>("allow_account");
|
||||
|
||||
blacklist.replies.push_back(r);
|
||||
}
|
||||
@@ -145,10 +145,10 @@ public:
|
||||
}
|
||||
|
||||
this->exempts.clear();
|
||||
for (int i = 0; i < block->CountBlock("exempt"); ++i)
|
||||
for (int i = 0; i < block.CountBlock("exempt"); ++i)
|
||||
{
|
||||
Configuration::Block *bl = block->GetBlock("exempt", i);
|
||||
this->exempts.insert(bl->Get<Anope::string>("ip"));
|
||||
Configuration::Block &bl = block.GetBlock("exempt", i);
|
||||
this->exempts.insert(bl.Get<Anope::string>("ip"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ class EBCrypt final
|
||||
{
|
||||
private:
|
||||
BCryptProvider bcryptprovider;
|
||||
static const size_t BCRYPT_MAX_LEN = 72;
|
||||
|
||||
public:
|
||||
EBCrypt(const Anope::string &modname, const Anope::string &creator)
|
||||
@@ -118,8 +119,7 @@ public:
|
||||
|
||||
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
|
||||
{
|
||||
// Bcrypt can not generate passwords longer than 71 characters.
|
||||
if (src.length() > 71)
|
||||
if (src.length() > BCRYPT_MAX_LEN)
|
||||
return EVENT_CONTINUE;
|
||||
|
||||
dest = "bcrypt:" + bcryptprovider.Encrypt(src);
|
||||
@@ -165,11 +165,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
auto *block = conf->GetModule(this);
|
||||
const auto maxpasslen = conf.GetModule("nickserv").Get<unsigned>("maxpasslen", "50");
|
||||
if (maxpasslen > BCRYPT_MAX_LEN && ModuleManager::FindFirstOf(ENCRYPTION) == this)
|
||||
Log(this) << "Warning: {nickserv}:maxpasslen is set to " << maxpasslen << " which is longer than the bcrypt maximum length of " << BCRYPT_MAX_LEN;
|
||||
|
||||
auto rounds = block->Get<unsigned long>("rounds", "10");
|
||||
auto &block = conf.GetModule(this);
|
||||
|
||||
auto rounds = block.Get<unsigned long>("rounds", "10");
|
||||
if (rounds < 10 || rounds > 32)
|
||||
{
|
||||
Log(this) << "Bcrypt rounds MUST be between 10 and 32 inclusive; using 10 instead of " << rounds << '.';
|
||||
|
||||
@@ -126,9 +126,9 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
this->defaultprovider = GetAlgorithm(Config->GetModule(this)->Get<const Anope::string>("algorithm", "sha256"));
|
||||
this->defaultprovider = GetAlgorithm(Config->GetModule(this).Get<const Anope::string>("algorithm", "sha256"));
|
||||
}
|
||||
|
||||
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
|
||||
|
||||
@@ -154,15 +154,15 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
const auto *block = Config->GetModule(this);
|
||||
this->defaultprovider = GetAlgorithm(block->Get<const Anope::string>("algorithm", "argon2id"));
|
||||
Argon2Context::memory_cost = block->Get<uint32_t>("memory_cost", "131072");
|
||||
Argon2Context::time_cost = block->Get<uint32_t>("time_cost", "3");
|
||||
Argon2Context::parallelism = block->Get<uint32_t>("parallelism", "1");
|
||||
Argon2Context::hash_length = block->Get<uint32_t>("hash_length", "32");
|
||||
Argon2Context::salt_length = block->Get<uint32_t>("salt_length", "32");
|
||||
const auto &block = Config->GetModule(this);
|
||||
this->defaultprovider = GetAlgorithm(block.Get<const Anope::string>("algorithm", "argon2id"));
|
||||
Argon2Context::memory_cost = block.Get<uint32_t>("memory_cost", "131072");
|
||||
Argon2Context::time_cost = block.Get<uint32_t>("time_cost", "3");
|
||||
Argon2Context::parallelism = block.Get<uint32_t>("parallelism", "1");
|
||||
Argon2Context::hash_length = block.Get<uint32_t>("hash_length", "32");
|
||||
Argon2Context::salt_length = block.Get<uint32_t>("salt_length", "32");
|
||||
}
|
||||
|
||||
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
|
||||
|
||||
+12
-12
@@ -529,7 +529,7 @@ public:
|
||||
{
|
||||
me = this;
|
||||
|
||||
Log() << "Module was compiled against LDAP (" << LDAP_VENDOR_NAME << ") version " << LDAP_VENDOR_VERSION_MAJOR << "." << LDAP_VENDOR_VERSION_MINOR << "." << LDAP_VENDOR_VERSION_PATCH;
|
||||
Log(this) << "Module was compiled against LDAP (" << LDAP_VENDOR_NAME << ") version " << LDAP_VENDOR_VERSION_MAJOR << "." << LDAP_VENDOR_VERSION_MINOR << "." << LDAP_VENDOR_VERSION_PATCH;
|
||||
}
|
||||
|
||||
~ModuleLDAP()
|
||||
@@ -544,9 +544,9 @@ public:
|
||||
LDAPServices.clear();
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *config) override
|
||||
void OnReload(Configuration::Conf &config) override
|
||||
{
|
||||
Configuration::Block *conf = config->GetModule(this);
|
||||
Configuration::Block &conf = config.GetModule(this);
|
||||
|
||||
for (std::map<Anope::string, LDAPService *>::iterator it = this->LDAPServices.begin(); it != this->LDAPServices.end();)
|
||||
{
|
||||
@@ -556,11 +556,11 @@ public:
|
||||
|
||||
++it;
|
||||
|
||||
for (i = 0; i < conf->CountBlock("ldap"); ++i)
|
||||
if (conf->GetBlock("ldap", i)->Get<const Anope::string>("name", "ldap/main") == cname)
|
||||
for (i = 0; i < conf.CountBlock("ldap"); ++i)
|
||||
if (conf.GetBlock("ldap", i).Get<const Anope::string>("name", "ldap/main") == cname)
|
||||
break;
|
||||
|
||||
if (i == conf->CountBlock("ldap"))
|
||||
if (i == conf.CountBlock("ldap"))
|
||||
{
|
||||
Log(LOG_NORMAL, "ldap") << "LDAP: Removing server connection " << cname;
|
||||
|
||||
@@ -572,17 +572,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < conf->CountBlock("ldap"); ++i)
|
||||
for (int i = 0; i < conf.CountBlock("ldap"); ++i)
|
||||
{
|
||||
Configuration::Block *ldap = conf->GetBlock("ldap", i);
|
||||
Configuration::Block &ldap = conf.GetBlock("ldap", i);
|
||||
|
||||
const Anope::string &connname = ldap->Get<const Anope::string>("name", "ldap/main");
|
||||
const Anope::string &connname = ldap.Get<const Anope::string>("name", "ldap/main");
|
||||
|
||||
if (this->LDAPServices.find(connname) == this->LDAPServices.end())
|
||||
{
|
||||
const Anope::string &server = ldap->Get<const Anope::string>("server", "127.0.0.1");
|
||||
const Anope::string &admin_binddn = ldap->Get<const Anope::string>("admin_binddn");
|
||||
const Anope::string &admin_password = ldap->Get<const Anope::string>("admin_password");
|
||||
const Anope::string &server = ldap.Get<const Anope::string>("server", "127.0.0.1");
|
||||
const Anope::string &admin_binddn = ldap.Get<const Anope::string>("admin_binddn");
|
||||
const Anope::string &admin_password = ldap.Get<const Anope::string>("admin_password");
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
+19
-15
@@ -245,7 +245,7 @@ public:
|
||||
DThread = new DispatcherThread();
|
||||
DThread->Start();
|
||||
|
||||
Log() << "Module was compiled against MySQL version " << (MYSQL_VERSION_ID / 10000) << "." << (MYSQL_VERSION_ID / 100 % 100) << "." << (MYSQL_VERSION_ID % 100) << " and is running against version " << mysql_get_client_info();
|
||||
Log(this) << "Module was compiled against MySQL version " << (MYSQL_VERSION_ID / 10000) << "." << (MYSQL_VERSION_ID / 100 % 100) << "." << (MYSQL_VERSION_ID % 100) << " and is running against version " << mysql_get_client_info();
|
||||
}
|
||||
|
||||
~ModuleSQL()
|
||||
@@ -260,9 +260,9 @@ public:
|
||||
delete DThread;
|
||||
}
|
||||
|
||||
void OnReload(Configuration::Conf *conf) override
|
||||
void OnReload(Configuration::Conf &conf) override
|
||||
{
|
||||
Configuration::Block *config = conf->GetModule(this);
|
||||
Configuration::Block &config = conf.GetModule(this);
|
||||
|
||||
for (std::map<Anope::string, MySQLService *>::iterator it = this->MySQLServices.begin(); it != this->MySQLServices.end();)
|
||||
{
|
||||
@@ -272,11 +272,11 @@ public:
|
||||
|
||||
++it;
|
||||
|
||||
for (i = 0; i < config->CountBlock("mysql"); ++i)
|
||||
if (config->GetBlock("mysql", i)->Get<const Anope::string>("name", "mysql/main") == cname)
|
||||
for (i = 0; i < config.CountBlock("mysql"); ++i)
|
||||
if (config.GetBlock("mysql", i).Get<const Anope::string>("name", "mysql/main") == cname)
|
||||
break;
|
||||
|
||||
if (i == config->CountBlock("mysql"))
|
||||
if (i == config.CountBlock("mysql"))
|
||||
{
|
||||
Log(LOG_NORMAL, "mysql") << "MySQL: Removing server connection " << cname;
|
||||
|
||||
@@ -285,19 +285,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < config->CountBlock("mysql"); ++i)
|
||||
for (int i = 0; i < config.CountBlock("mysql"); ++i)
|
||||
{
|
||||
Configuration::Block *block = config->GetBlock("mysql", i);
|
||||
const Anope::string &connname = block->Get<const Anope::string>("name", "mysql/main");
|
||||
Configuration::Block &block = config.GetBlock("mysql", i);
|
||||
const Anope::string &connname = block.Get<const Anope::string>("name", "mysql/main");
|
||||
|
||||
if (this->MySQLServices.find(connname) == this->MySQLServices.end())
|
||||
{
|
||||
const Anope::string &database = block->Get<const Anope::string>("database", "anope");
|
||||
const Anope::string &server = block->Get<const Anope::string>("server", "127.0.0.1");
|
||||
const Anope::string &user = block->Get<const Anope::string>("username", "anope");
|
||||
const Anope::string &password = block->Get<const Anope::string>("password");
|
||||
unsigned int port = block->Get<unsigned int>("port", "3306");
|
||||
const Anope::string &socket = block->Get<const Anope::string>("socket");
|
||||
const Anope::string &database = block.Get<const Anope::string>("database", "anope");
|
||||
const Anope::string &server = block.Get<const Anope::string>("server", "127.0.0.1");
|
||||
const Anope::string &user = block.Get<const Anope::string>("username", "anope");
|
||||
const Anope::string &password = block.Get<const Anope::string>("password");
|
||||
unsigned int port = block.Get<unsigned int>("port", "3306");
|
||||
const Anope::string &socket = block.Get<const Anope::string>("socket");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -631,6 +631,10 @@ void MySQLService::Connect()
|
||||
if (!connect)
|
||||
throw SQL::Exception("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
|
||||
|
||||
// We force UTC so that FromUnixtime works as expected.
|
||||
SQL::Query tzquery("SET time_zone = '+00:00'");
|
||||
RunQuery(tzquery);
|
||||
|
||||
if (this->socket.empty())
|
||||
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
|
||||
else
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
|
||||
std::vector<char> pcre_version(16);
|
||||
if (pcre2_config(PCRE2_CONFIG_VERSION, pcre_version.data()) >= 0)
|
||||
Log() << "Module was compiled against PCRE2 version " << PCRE2_MAJOR << "." << PCRE2_MINOR << " and is running against version " << pcre_version.data();
|
||||
Log(this) << "Module was compiled against PCRE2 version " << PCRE2_MAJOR << "." << PCRE2_MINOR << " and is running against version " << pcre_version.data();
|
||||
}
|
||||
|
||||
~ModuleRegexPCRE()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user