1
0
mirror of https://github.com/anope/anope.git synced 2026-06-16 16:54:48 +02:00

Compare commits

...

111 Commits

Author SHA1 Message Date
Sadie Powell 390d0482fc Release 2.1.13. 2025-04-01 11:04:29 +01:00
Sadie Powell 65bb0a374b Move SASL::IdentifyRequest to ns_sasl.
This is only useful for plain authentication and doesn't need to
be in the header.
2025-03-31 16:58:22 +01:00
Sadie Powell ea4877dc16 Update the changelogs. 2025-03-30 13:06:48 +01:00
Sadie Powell 4024598bd8 Execute SQL updates atomically.
If the Serialize call alters any tables they would have previously
been missed here.
2025-03-30 13:01:13 +01:00
Sadie Powell a154532e98 Use insert_or_assign when creating ChannelInfo instances. 2025-03-30 12:42:18 +01:00
Sadie Powell 665b0fdef8 Refuse to import data that already exists in db_atheme. 2025-03-30 12:17:23 +01:00
Sadie Powell 0802d9d3ff Reference accounts in the database by their id not their nick. 2025-03-30 11:57:47 +01:00
Sadie Powell 8d3b8c08b3 Add NickAlias::FindId. 2025-03-30 11:04:46 +01:00
Sadie Powell f3e5ccf353 Initialize ChannelInfo in the Modern C++ way. 2025-03-26 11:23:05 +00:00
Sadie Powell b5213d5a81 Initialize Channel in the Modern C++ way. 2025-03-26 11:08:02 +00:00
Sadie Powell dc09408f1a Add a typedef for the serializable id. 2025-03-26 10:22:42 +00:00
Sadie Powell 49d86527ef Initialize the db_flatfile LoadData stream reference from the ctor. 2025-03-26 09:32:29 +00:00
Sadie Powell 65183c3c49 Update the change logs. 2025-03-26 09:18:56 +00:00
Sadie Powell c60477384c Add the db_json module. 2025-03-26 09:08:55 +00:00
Sadie Powell 25c3fd51b7 Fix a missing format argument in ns_maxemail. 2025-03-22 21:45:29 +00:00
Sadie Powell a40eaeb2a3 Use a plural form translation for the ns_maxemail error. 2025-03-22 21:04:25 +00:00
Sadie Powell e14a650cb9 Read the ns_maxemail limit as unsigned instead of int. 2025-03-22 21:02:52 +00:00
Sadie Powell 6401e328bb Merge branch '2.0' into 2.1. 2025-03-22 20:52:25 +00:00
Sadie Powell 43dc6f7509 Fix ns_maxemail miscounting email addresses in some cases. 2025-03-22 20:19:50 +00:00
Sadie Powell 8f0ee6f383 Update more messages to use gettext plural forms. 2025-03-22 08:58:24 +00:00
Sadie Powell 1adbce61cb Fix a semicolon that was missing from the previous commit. 2025-03-22 08:43:38 +00:00
Sadie Powell fe60c9a085 Fix an unclear message in gl_queue. 2025-03-22 08:36:57 +00:00
Sadie Powell 39bb5825ad Deduplicate requirename code in os_shutdown. 2025-03-22 08:33:21 +00:00
Sadie Powell 602ff60e21 Document the migration path for removed config options.
Also resort the config changelog so it is listed alphabetically.
2025-03-22 08:17:28 +00:00
Sadie Powell 8d0399e356 Document the default value for new config options in the changelog. 2025-03-22 08:04:55 +00:00
Sadie Powell a4d0213bcb Update the changelogs. 2025-03-22 07:59:54 +00:00
Sadie Powell ecbf53ba6c Allow customising the length at which lines are wrapped after.
Closes #485.
2025-03-22 07:33:02 +00:00
Sadie Powell 6d72fd67d8 Improve logging about the protocol module on startup. 2025-03-19 13:37:11 +00:00
Sadie Powell 0a11bc7693 Merge branch '2.0' into 2.1. 2025-03-19 13:08:14 +00:00
Sadie Powell e86fa67e38 Use a set instead of a vector for storing memo ignores. 2025-03-19 10:12:02 +00:00
Sadie Powell 1fc2642034 Make it clear that an ignore list is for memos in ms_ignore.
Closes #484.
2025-03-19 09:55:32 +00:00
Sadie Powell 1641f6415a RPC::service is not necessary anymore. 2025-03-17 19:06:14 +00:00
Sadie Powell bb1f93f150 Switch RPC event registration to use the service system. 2025-03-17 12:58:22 +00:00
Sadie Powell 85fbc500d8 Simplify the requirename logic. 2025-03-17 11:23:19 +00:00
Sadie Powell 99bcc6d3b7 Improve the error reporting in os_shutdown. 2025-03-16 20:21:34 +00:00
Sadie Powell 5fd2145821 Update author list. 2025-03-16 12:16:02 +00:00
Sadie Powell 4700d48b35 Import a slightly modified version of mkauthors from InspIRCd. 2025-03-16 12:16:02 +00:00
Sadie Powell 019b2aafef Update the mailmap. 2025-03-16 12:16:01 +00:00
Sadie Powell 3744649320 Move the RPC service interface to the RPC header. 2025-03-15 23:49:58 +00:00
Sadie Powell 30593321f4 Fix getting the IP of a user in CommandSource. 2025-03-15 21:08:49 +00:00
Sadie Powell 3b35199a53 Add NickCore::FindId for finding an account by its id. 2025-03-15 21:08:26 +00:00
Sadie Powell 5ac5e1068e Use custom-cloak when setting the SASL hostname too. 2025-03-15 00:17:18 +00:00
Sadie Powell 0ebc43f0dc Refactor the InspIRCd METADATA handler to actually be readable. 2025-03-14 23:21:42 +00:00
Sadie Powell 5ff86ea2c5 Implement support for the new way of setting vhosts on InspIRCd. 2025-03-14 19:45:43 +00:00
Sadie Powell 1bdc9c0a64 Fix {nickserv}:defaults still documenting the old nick protection. 2025-03-14 12:13:13 +00:00
Sadie Powell d0d46408bc Improve JSON-RPC error messages. 2025-03-14 11:49:01 +00:00
Sadie Powell fdc33b0f6d Warn if enc_bcrypt is the first module and maxpasslen is >72. 2025-03-14 11:09:35 +00:00
Sadie Powell 6a43370e13 Deduplicate response building code in the jsonrpc module. 2025-03-13 16:01:16 +00:00
Sadie Powell 1fcd045aff Fix the jsonrpc not having a root element one is not specified. 2025-03-13 15:49:33 +00:00
Sadie Powell b4d068b01a Fix the messageUser function in the JavaScript library. 2025-03-13 15:27:07 +00:00
Sadie Powell 23d548336a Document the required RPC modules in the JavaScript library. 2025-03-13 15:24:48 +00:00
Sadie Powell 82371dc279 Update the changelogs. 2025-03-13 15:17:08 +00:00
Sadie Powell fd6770373f Add the rpc_message module, remove the notice RPC event. 2025-03-13 15:12:47 +00:00
Sadie Powell 645f969d70 Fix sending global messages with the default sender. 2025-03-13 15:12:47 +00:00
Sadie Powell 3187233783 Fix setting keepbackups to 0 in db_flatfile. 2025-03-13 13:37:54 +00:00
Sadie Powell 8b932dc459 Fix a crash in the ns_sasl module.
Closes #481.
2025-03-13 12:52:50 +00:00
Sadie Powell a357ba38fb Fix deleting old db_flatfile database backups. 2025-03-13 12:14:17 +00:00
Sadie Powell 9f8525e3b2 Refactor the TIME handler. 2025-03-13 10:47:18 +00:00
Sadie Powell ace82596d8 Fix a warning on Clang. 2025-03-13 10:43:37 +00:00
Sadie Powell 09e10d2a02 Add an ALLTIME handler on InspIRCd. 2025-03-13 10:39:14 +00:00
Sadie Powell 9ec3f6abd6 Refactor and redocument Serialize::Type. 2025-03-12 16:52:46 +00:00
Sadie Powell e7b18609f6 Add defines for the core serialisation type names. 2025-03-12 15:53:52 +00:00
Sadie Powell cdcf0e2f9a Move serialization from Serializable to a Serialize::Type child. 2025-03-12 15:53:52 +00:00
Sadie Powell 718f2e922a Const correct Serialize::Type::GetName(). 2025-03-12 01:00:02 +00:00
Sadie Powell 2b2b6f75a1 Fix the id data type in db_flatfile. 2025-03-12 00:55:21 +00:00
Sadie Powell 883367c1d2 Fix importing some data from 1.8. 2025-03-12 00:33:41 +00:00
Sadie Powell 2276c62ff0 Move serialization data type logic from sql.h to the core. 2025-03-12 00:16:15 +00:00
Sadie Powell fb0ee27df0 Save the databases on SIGUSR1. 2025-03-12 00:16:15 +00:00
Sadie Powell b14befc77c Fix an outdated comment. 2025-03-10 13:10:13 +00:00
Sadie Powell 64fd5a862a Add an XML-RPC method to rpc_system for debugging RPC responses. 2025-03-10 13:03:29 +00:00
Sadie Powell 0ff170c671 Add a config option for disabling the i8 XML-RPC extension. 2025-03-10 12:48:13 +00:00
Sadie Powell ea0d5c4d70 Add a config option for disabling the nil XML-RPC extension. 2025-03-10 12:48:13 +00:00
Sadie Powell b96dbfc9ba Fix a memory leak in the xmlrpc module. 2025-03-10 11:07:29 +00:00
Sadie Powell e221c7642a Update the changelogs. 2025-03-09 20:14:03 +00:00
Sadie Powell b8c28419da Add a missing override keyword. 2025-03-09 19:49:28 +00:00
Sadie Powell 1c4f9042e7 Simplify some weird logic in bs_bot. 2025-03-09 19:31:58 +00:00
Sadie Powell a3f483ad87 Fix a forward declaration on Clang. 2025-03-09 18:58:49 +00:00
Sadie Powell 6e90a8ea55 Don't tell users that services is shutting down when its restarting. 2025-03-09 18:56:27 +00:00
Sadie Powell 6d7fe69cdf Add support for oper-only quit messages.
This currently only works on InspIRCd but I believe that other
servers also support this.
2025-03-09 18:51:03 +00:00
Sadie Powell 314ef60900 Fix a compiler warning on Clang. 2025-03-09 14:36:57 +00:00
Sadie Powell 1e8ac58bb4 Sync the chanserv defaults between the code and config. 2025-03-09 14:33:29 +00:00
Sadie Powell badcf31499 Make config variables a lot more useful.
- Config variables now no longer conflict with regular values.

- Config variables can now be read from the environment.
  (e.g. ${env.USER}).

- Config variables can now be used as partial values
  (e.g. support@${network.domain})
2025-03-09 14:20:34 +00:00
Sadie Powell c98602bf19 Fix various webcpanel bugs relating to nickname protection. 2025-03-08 14:45:26 +00:00
Sadie Powell 50bec959e5 Turn on channel persistence by default. 2025-03-08 14:25:08 +00:00
Sadie Powell 62bfa33464 Rework how nickname protection works.
- Rename the command and module from kill to protect (this command
  hasn't actually killed users in a long time).
- Replace QUICK/IMMED with a duration option.
2025-03-08 14:07:15 +00:00
Sadie Powell b4ab7dadb9 Use a C++11 lambda instead of a channel sorting method. 2025-03-08 12:41:22 +00:00
Sadie Powell df0cd3ef3e Move some headers around. 2025-03-08 12:22:07 +00:00
Sadie Powell 9e37a643f1 Fix some minor issues with db_atheme error messages. 2025-03-07 12:34:19 +00:00
Sadie Powell b30bfb5d2b Import misc channel and user metadata in db_atheme. 2025-03-07 12:31:42 +00:00
Sadie Powell cccdf0431b Don't warn when importing an external auth account from Atheme.
This happens when Atheme was using LDAP to authenticate users. We
will replace the temporary password at a later date if Anope is set
up to use LDAP too.
2025-03-06 23:31:56 +00:00
Sadie Powell 0005ebbbc3 Import logon and oper news from Atheme. 2025-03-06 23:05:38 +00:00
Sadie Powell 161841925d Force the MySQL module to use UTC for connections.
This prevents conversion issues when the MySQL server is in a
different timezone to the services server.
2025-03-06 20:51:13 +00:00
Sadie Powell e099180d8f Fix a REPRODUCIBLE_BUILD check after the previous commit. 2025-03-06 11:29:47 +00:00
Sadie Powell 2091dc68bc Move REPRODUCIBLE_BUILD to sysconf. 2025-03-06 01:24:39 +00:00
Sadie Powell 9926ac5a05 Fix reading the config of some modules. 2025-03-05 16:25:17 +00:00
Sadie Powell 14342f6375 Fix the on start library version logging to include the module. 2025-03-05 16:03:23 +00:00
Sadie Powell a0a9d433dc Blacklist an old UnrealIRCd contrib module that breaks Anope. 2025-03-04 17:15:07 +00:00
Sadie Powell c88fac1a20 Document {ns_sasl}:agent. 2025-03-04 00:50:20 +00:00
Sadie Powell 64d26f7c61 Remove GetAgent and SendMechs from the SASL interface.
These are only used by ns_sasl.
2025-03-04 00:43:06 +00:00
Sadie Powell 34896cefe9 Misc cleanup of ns_sasl and sasl.h. 2025-03-03 23:57:12 +00:00
Sadie Powell c0c7046a6d Check if users really want to use 2.1 in Config. 2025-03-03 23:29:53 +00:00
Sadie Powell 937ea7dab4 SASL::ProtocolInterface should not be exported. 2025-03-03 22:53:16 +00:00
Sadie Powell bfd2b0fa8e Merge branch '2.0' into 2.1. 2025-03-03 22:48:23 +00:00
Sadie Powell 7f2c281121 Fix a compiler warning on newer versions of MSVC. 2025-03-03 22:46:12 +00:00
Sadie Powell 224caf32c7 Rename sasl to ns_sasl, move to nickserv.example.conf. 2025-03-03 22:02:48 +00:00
Sadie Powell 5828cdba45 Move SASL protocol messages to the SASL header. 2025-03-03 21:45:59 +00:00
Sadie Powell 4526fbed96 Add a helper method for getting a description of an uplink. 2025-03-02 15:42:25 +00:00
Sadie Powell f9911dde52 Return references instead of pointers from the config system.
We used to return NULL from these methods but now we return an empty
block so this can never actually be null now.
2025-03-02 15:27:47 +00:00
Sadie Powell a5e5eb5eb0 Return EmptyBlock instead of NULL from GetModule. 2025-03-02 14:43:57 +00:00
Sadie Powell 82aecd6c7e Bump for 2.1.13-git. 2025-02-28 16:11:40 +00:00
Robby b448a20f40 Update the dutch language file. 2025-02-23 04:22:33 +01:00
210 changed files with 4516 additions and 2773 deletions
+13 -3
View File
@@ -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>
-5
View File
@@ -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)
+29
View File
@@ -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
View File
@@ -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
*
+1 -1
View File
@@ -31,7 +31,7 @@ service
/*
* The hostname of the BotServ client.
*/
host = "services.host"
host = "${services.host}"
/*
* The realname of the BotServ client.
+4 -4
View File
@@ -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.
+1 -1
View File
@@ -21,7 +21,7 @@ service
/*
* The hostname of the Global client.
*/
host = "services.host"
host = "${services.host}"
/*
* The realname of the Global client.
+1 -1
View File
@@ -21,7 +21,7 @@ service
/*
* The hostname of the HostServ client.
*/
host = "services.host"
host = "${services.host}"
/*
* The realname of the HostServ client.
+1 -1
View File
@@ -18,7 +18,7 @@ service
/*
* The hostname of the StatServ client.
*/
host = "stats.host"
host = "${services.host}"
/*
* The realname of the StatServ client.
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
*
+1 -1
View File
@@ -21,7 +21,7 @@ service
/*
* The hostname of the OperServ client.
*/
host = "services.host"
host = "${services.host}"
/*
* The realname of the OperServ client.
+9 -6
View File
@@ -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
+92
View File
@@ -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>
+36
View File
@@ -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
View File
@@ -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).
-2
View File
@@ -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.
+52
View File
@@ -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);
}
}
/*
+1 -1
View File
@@ -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]);
}
/**
+67
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+10
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+117
View File
@@ -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");
}
+16
View File
@@ -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;
}
-46
View File
@@ -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
View File
@@ -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;
};
-161
View File
@@ -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";
}
};
}
-14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 &param) 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");
}
};
+1 -1
View File
@@ -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;
+27 -17
View File
@@ -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")
{
}
};
+4 -4
View File
@@ -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
+9 -9
View File
@@ -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());
+2 -2
View File
@@ -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)
{
+24 -21
View File
@@ -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());
}
+11 -15
View File
@@ -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");
}
}
+7 -9
View File
@@ -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);
}
+6 -6
View File
@@ -50,8 +50,8 @@ public:
void Execute(CommandSource &source, const std::vector<Anope::string> &params) 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")))
+2 -2
View File
@@ -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)
+24 -13
View File
@@ -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")
{
}
+3 -3
View File
@@ -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)
+3 -3
View File
@@ -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)
+8 -8
View File
@@ -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;
+2 -2
View File
@@ -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);
+4 -4
View File
@@ -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
View File
@@ -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);
}
+35 -26
View File
@@ -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;
+1 -1
View File
@@ -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;
+27 -14
View File
@@ -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
View File
@@ -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
+31 -16
View File
@@ -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;
}
}
+26 -14
View File
@@ -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());
}
+1 -1
View File
@@ -10,7 +10,7 @@
*/
#include "module.h"
#include "modules/cs_mode.h"
#include "modules/chanserv/mode.h"
class CommandCSSetKeepTopic final
: public Command
+13 -17
View File
@@ -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;
+9 -9
View File
@@ -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
View File
@@ -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;
+45 -27
View File
@@ -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())
+417
View File
@@ -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
View File
@@ -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");
+8 -10
View File
@@ -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
View File
@@ -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 */
}
}
+18 -17
View File
@@ -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
View File
@@ -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
View File
@@ -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"));
}
}
+9 -5
View File
@@ -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 << '.';
+2 -2
View File
@@ -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
+8 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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