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

Compare commits

..

3 Commits

Author SHA1 Message Date
Sadie Powell 258daf6c26 Release 2.1.3. 2024-03-04 10:42:12 +00:00
Sadie Powell 57e8b4305e Update the changelogs. 2024-03-04 10:41:31 +00:00
Sadie Powell db4f845fe7 Add NickAlias::GetVhostMask for getting the vident@vhost. 2024-03-04 10:36:10 +00:00
223 changed files with 3070 additions and 7171 deletions
-1
View File
@@ -4,4 +4,3 @@ updates:
directory: /
schedule:
interval: monthly
target-branch: "2.1"
+1 -2
View File
@@ -20,7 +20,6 @@ jobs:
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
apk update
apk add \
argon2-dev \
clang \
cmake \
g++ \
@@ -37,7 +36,7 @@ jobs:
- name: Enable extras
run: |
for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
for MODULE in ldap ldap_authentication ldap_oper mysql regex_pcre2 regex_posix regex_tre sql_authentication sql_log sql_oper sqlite ssl_gnutls ssl_openssl
do
ln -s $PWD/modules/extra/$MODULE.cpp $PWD/modules
done
+1 -2
View File
@@ -20,7 +20,6 @@ jobs:
g++ \
gettext \
git \
libargon2-dev \
libgnutls28-dev \
libldap2-dev \
libmysqlclient-dev \
@@ -32,7 +31,7 @@ jobs:
- name: Enable extras
run: |
for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
for MODULE in ldap ldap_authentication ldap_oper mysql regex_pcre2 regex_posix regex_tre sql_authentication sql_log sql_oper sqlite ssl_gnutls ssl_openssl
do
ln -s ${{ github.workspace }}/modules/extra/$MODULE.cpp ${{ github.workspace }}/modules
done
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
runs-on: windows-2019
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.3
+5 -2
View File
@@ -1,13 +1,16 @@
build/
config.cache
include/sysconf.h
modules/enc_argon2.cpp
modules/enc_posix.cpp
modules/ldap.cpp
modules/ldap_authentication.cpp
modules/ldap_oper.cpp
modules/mysql.cpp
modules/regex_pcre2.cpp
modules/regex_posix.cpp
modules/regex_tre.cpp
modules/sql_authentication.cpp
modules/sql_log.cpp
modules/sql_oper.cpp
modules/sqlite.cpp
modules/ssl_gnutls.cpp
modules/ssl_openssl.cpp
-1
View File
@@ -224,7 +224,6 @@ if(CMAKE_BUILD_TYPE STREQUAL "DEBUG" OR CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINF
endif()
# Check for the existence of the following functions
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
check_function_exists(umask HAVE_UMASK)
check_function_exists(epoll_wait HAVE_EPOLL)
check_function_exists(poll HAVE_POLL)
+62 -137
View File
@@ -238,15 +238,15 @@ serverinfo
/*
* The filename containing the Anope process ID. The path is relative to the
* data directory.
* services root directory.
*/
pid = "anope.pid"
pid = "data/anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
* config directory.
* services root directory.
*/
motd = "motd.txt"
motd = "conf/motd.txt"
}
/*
@@ -395,6 +395,19 @@ options
*/
casemap = "ascii"
/*
* This key is used to initiate the random number generator. This number
* MUST be random as you want your passcodes to be random. Don't give this
* key to anyone! Keep it private!
*
* NOTE: If you don't uncomment this or keep the default values, any talented
* programmer would be able to easily "guess" random strings used to mask
* information. Be safe, and come up with a 7-digit number.
*
* This directive is optional, but highly recommended.
*/
#seed = 9866235
/*
* Sets the number of invalid password tries before services removes a user
* from the network. If a user enters a number of invalid passwords equal to
@@ -789,7 +802,7 @@ log
*
* hostserv/set hostserv/del hostserv/list
*
* global/global global/queue global/server
* global/global
*
* operserv/news operserv/stats operserv/kick operserv/exception operserv/seen
* operserv/mode operserv/session operserv/modinfo operserv/ignore operserv/chanlist
@@ -918,7 +931,7 @@ opertype
/*
* [OPTIONAL] Mail Config
*
* This section contains settings related to the use of email from services.
* This section contains settings related to the use of e-mail from services.
* If the usemail directive is set to yes, unless specified otherwise, all other
* directives are required.
*
@@ -938,7 +951,7 @@ mail
/*
* This is the command-line that will be used to call the mailer to send an
* email. It must be called with all the parameters needed to make it
* e-mail. It must be called with all the parameters needed to make it
* scan the mail input to find the mail recipient; consult your mailer
* documentation.
*
@@ -950,18 +963,18 @@ mail
* If you are running on Windows you should use a Windows sendmail port
* like https://www.glob.com.au/sendmail/ for sending emails.
*/
#sendmailpath = "/usr/sbin/sendmail -it"
sendmailpath = "/usr/sbin/sendmail -t"
/*
* This is the email address from which all the emails are to be sent from.
* This is the e-mail address from which all the e-mails are to be sent from.
* It should really exist.
*/
sendfrom = "services@example.com"
/*
* This controls the minimum amount of time a user must wait before sending
* another email after they have sent one. It also controls the minimum time
* a user must wait before they can receive another email.
* another e-mail after they have sent one. It also controls the minimum time
* a user must wait before they can receive another e-mail.
*
* This feature prevents users from being mail bombed using services and
* it is highly recommended that it be used.
@@ -972,10 +985,10 @@ mail
/*
* If set, Anope will not put quotes around the TO: fields
* in emails.
* in e-mails.
*
* This directive is optional, and as far as we know, it's only needed
* if you are using ESMTP or QMail to send out emails.
* if you are using ESMTP or QMail to send out e-mails.
*/
#dontquoteaddresses = yes
@@ -1092,22 +1105,6 @@ mail
#hash = "md5"
}
/*
* db_atheme
*
* This allows importing databases from Atheme. You should load another database module as
* well as this as it can only read Atheme databases not write them.
*/
#module
{
name = "db_atheme"
/*
* The database name db_atheme should use.
*/
database = "atheme.db"
}
/*
* [RECOMMENDED] db_flatfile
*
@@ -1228,121 +1225,49 @@ module
/*
* [RECOMMENDED] Encryption modules.
*
* The encryption modules are used when dealing with passwords. This determines
* how the passwords are stored in the databases.
* The encryption modules are used when dealing with passwords. This determines how
* the passwords are stored in the databases, and does not add any security as
* far as transmitting passwords over the network goes.
*
* Without any encryption modules loaded users will not be able to authenticate unless
* there is another module loaded that provides authentication checking, such as
* ldap_authentication or sql_authentication.
*
* With enc_none, passwords will be stored in plain text, allowing for passwords
* to be recovered later but it isn't secure and therefore is not recommended.
*
* The other encryption modules use one-way encryption, so the passwords can not
* be recovered later if those are used.
*
* The first encryption module loaded is the primary encryption module. All new passwords are
* encrypted by this module. Old passwords stored in another encryption method are
* automatically re-encrypted by the primary encryption module on next identify.
*
* enc_md5, enc_sha1, and enc_old are deprecated, and are provided for users
* to upgrade to a newer encryption module. Do not use them as the primary
* encryption module. They will be removed in a future release.
*
* The first encryption module loaded is the primary encryption module. All new
* passwords are encrypted by this module. Old passwords encrypted with another
* encryption method are automatically re-encrypted with the primary encryption
* module the next time the user identifies.
*/
/*
* enc_sha2
*
* Provides support for encrypting passwords using the HMAC-SHA-2 algorithm. See
* https://en.wikipedia.org/wiki/SHA-2 and https://en.wikipedia.org/wiki/HMAC
* for more information.
*/
module
{
name = "enc_sha2"
#module { name = "enc_bcrypt" }
module { name = "enc_sha256" }
/** The sub-algorithm to use. Can be set to sha224 for SHA-224, sha256 for
* SHA-256, sha284 for SHA-384 or sha512 to SHA-512. Defaults to sha256.
*/
#algorithm = "sha256"
}
/*
* [EXTRA] enc_argon2
*
* Provides support for encrypting passwords using the Argon2 algorithm. See
* https://en.wikipedia.org/wiki/Argon2 for more information.
*/
#module
{
name = "enc_argon2"
/** The sub-algorithm to use. Can be set to argon2d for Argon2d, argon2i for
* Argon2i, or argon2id for Argon2id. Defaults to argon2id.
*/
#algorithm = "argon2id"
/** The memory hardness in kibibytes of the Argon2 algorithm. Defaults to
* 128 mebibytes.
*/
#memory_cost = 121072
/** The time hardness (iterations) of the Argon2 algorithm. Defaults to 3.
*/
#time_cost = 3
/** The amount of parallel threads to use when encrypting passwords.
* Defaults to 1.
*/
#parallelism = 1
/** The length in bytes of an Argon2 hash. Defaults to 32. */
#hash_length = 32
/** The length in bytes of an Argon2 salt. Defaults to 32. */
#salt_length = 32
}
/*
* enc_bcrypt
*
* Provides support for encrypting passwords using the Bcrypt algorithm. See
* https://en.wikipedia.org/wiki/Bcrypt for more information.
*/
#module
{
name = "enc_bcrypt"
/** The number of Bcrypt rounds to perform on passwords. Can be set to any
* number between 10 and 32 but higher numbers are more CPU intensive and
* may impact performance.
*/
#rounds = 10
}
/*
* [EXTRA] enc_posix
*
* Provides verify-only support for passwords encrypted using the POSIX crypt()
* function. Load this if you are migratign from another services packages such
* as Atheme. See https://en.wikipedia.org/wiki/Crypt_(C) for more information.
*
* You must load another encryption method before this to re-encrypt passwords
* with when a user logs in.
*/
#module { name = "enc_posix" }
/*
* [DEPRECATED] enc_md5, enc_none, enc_old, enc_sha1, enc_sha256
*
* Provides verify-only support for passwords encrypted using encryption methods
* from older versions of Anope. These methods are no longer considered secure
* and will be removed in a future version of Anope. Only load them if you are
* upgrading from a previous version of Anope that used them.
*
* enc_md5: Verifies passwords encrypted with the MD5 algorithm
* enc_none: Verifies passwords that are not encrypted
* enc_sha1: Verifies passwords encrypted with the SHA1 algorithm
* enc_old: Verifies passwords encrypted with the broken MD5 algorithm used
* before 1.7.17.
* enc_sha256: Verifies passwords encrypted with the SHA256 algorithm using a
* custom initialisation vector as a salt.
*
* You must load another encryption method before this to re-encrypt passwords
* with when a user logs in.
*/
/*
* [DEPRECATED] Deprecated encryption modules. You can only use these for compatibility with
* old databases and will need to load one of the above modules as your primary encryption
* module.
*/
#module { name = "enc_md5" }
#module { name = "enc_none" }
#module { name = "enc_old" }
#module { name = "enc_sha1" }
#module { name = "enc_sha256" }
/*
* enc_old is Anope's previous (broken) MD5 implementation used from 1.4.x to 1.7.16.
* If your databases were made using that module, load it here to allow conversion to the primary
* encryption method.
*/
#module { name = "enc_old" }
/* Extra (optional) modules. */
include
+1 -1
View File
@@ -183,7 +183,7 @@ module
/*
* The maximum number of entries a single bad words list can have.
*/
badwordsmax = 50
badwordsmax = 32
/*
* If set, BotServ will use case sensitive checking for badwords.
+6 -6
View File
@@ -114,15 +114,15 @@ module
/*
* The maximum number of entries on a channel's access list.
* If not set, the default is 1000. This can be set to 0 for unlimited.
* If not set, the default is 1024. This can be set to 0 for unlimited.
*/
accessmax = 1000
accessmax = 1024
/*
* The length of time ChanServ stays in a channel after kicking a user from a channel they are not
* permitted to be in. This only occurs when the user is the only one in the channel.
*/
inhabit = 1m
inhabit = 15s
/*
* Allow only IRC Operators to use ChanServ.
@@ -913,7 +913,7 @@ module
/*
* The maximum number of entries on a channel's autokick list.
*/
autokickmax = 50
autokickmax = 32
/*
* The default reason for an autokick if none is given.
@@ -1126,7 +1126,7 @@ module
*
* This directive is optional.
*/
max = 50
max = 32
}
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
@@ -1247,7 +1247,7 @@ command { service = "ChanServ"; name = "SET NOEXPIRE"; command = "chanserv/saset
*/
module { name = "cs_set_misc" }
command { service = "ChanServ"; name = "SET URL"; command = "chanserv/set/misc"; misc_description = _("Associate a URL with the channel"); }
command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an email address with the channel"); }
command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an E-mail address with the channel"); }
/*
* cs_status
-26
View File
@@ -113,29 +113,3 @@ command { service = "Global"; name = "HELP"; command = "generic/help"; }
*/
module { name = "gl_global" }
command { service = "Global"; name = "GLOBAL"; command = "global/global"; permission = "global/global"; }
/*
* gl_queue
*
* Provides the command global/queue.
*
* Used for queuing messages to send to every online user.
*/
module
{
name = "gl_queue"
/* The maximum number of messages in a message queue. Defaults to 10. */
maxqueue = 10
}
command { service = "Global"; name = "QUEUE"; command = "global/queue"; permission = "global/queue"; }
/*
* gl_server
*
* Provides the command global/server.
*
* Used for sending a message to every online user on a server.
*/
module { name = "gl_server" }
command { service = "Global"; name = "SERVER"; command = "global/server"; permission = "global/server"; }
+2 -2
View File
@@ -83,7 +83,7 @@ module
*
* This directive is optional, but recommended.
*/
senddelay = 30s
senddelay = 3s
}
/*
@@ -146,7 +146,7 @@ module
*
* This directive is optional.
*/
max = 50
max = 32
}
command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; }
+14 -19
View File
@@ -59,7 +59,7 @@ module { name = "help" }
* SOA record information.
*/
/* Email address of the DNS administrator. */
/* E-mail address of the DNS administrator. */
admin = "admin@example.com"
/* This should be the names of the public facing nameservers serving the records. */
@@ -254,7 +254,7 @@ module { name = "help" }
}
/*
* ldap_authentication
* ldap_authentication [EXTRA]
*
* This module allows many commands such as IDENTIFY, RELEASE, RECOVER, GHOST, etc. use
* LDAP to authenticate users. Requires ldap.
@@ -314,7 +314,7 @@ module { name = "help" }
}
/*
* ldap_oper
* ldap_oper [EXTRA]
*
* This module dynamically ties users to Anope opertypes when they identify
* via LDAP group membership. Requires ldap.
@@ -580,8 +580,7 @@ module { name = "sasl" }
name = "ssl_gnutls"
/*
* An optional certificate and key for ssl_gnutls to give to the uplink. All
* paths are relative to the config directory.
* An optional certificate and key for ssl_gnutls to give to the uplink.
*
* You can generate your own certificate and key pair by using:
*
@@ -589,8 +588,8 @@ module { name = "sasl" }
* certtool --generate-self-signed --load-privkey privkey.pem --outfile fullchain.pem
*
*/
cert = "fullchain.pem"
key = "privkey.pem"
cert = "data/fullchain.pem"
key = "data/privkey.pem"
/*
* Diffie-Hellman parameters to use when acting as a server. This is only
@@ -603,7 +602,7 @@ module { name = "sasl" }
* certtool --generate-dh-params --bits 2048 --outfile dhparams.pem
*
*/
#dhparams = "dhparams.pem"
# dhparams = "data/dhparams.pem"
}
/*
@@ -621,15 +620,14 @@ module { name = "sasl" }
/*
* An optional certificate and key for ssl_openssl to give to the uplink.
* All paths are relative to the config directory.
*
* You can generate your own certificate and key pair by using:
*
* openssl genrsa -out privkey.pem 2048
* openssl req -new -x509 -key privkey.pem -out fullchain.pem -days 1095
*/
cert = "fullchain.pem"
key = "privkey.pem"
cert = "data/fullchain.pem"
key = "data/privkey.pem"
/*
* If you wish to increase security you can disable support for older
@@ -642,7 +640,7 @@ module { name = "sasl" }
}
/*
* sql_authentication
* sql_authentication [EXTRA]
*
* This module allows authenticating users against an external SQL database using a custom
* query.
@@ -693,7 +691,7 @@ module { name = "sasl" }
}
/*
* sql_log
* sql_log [EXTRA]
*
* This module adds an additional target option to log{} blocks
* that allows logging Service's logs to SQL. To log to SQL, add
@@ -713,7 +711,7 @@ module { name = "sasl" }
#module { name = "sql_log" }
/*
* sql_oper
* sql_oper [EXTRA]
*
* This module allows granting users services operator privileges and possibly IRC Operator
* privileges based on an external SQL database using a custom query.
@@ -774,11 +772,8 @@ module { name = "sasl" }
/* Web server to use. */
server = "httpd/main";
/*
* The directory containing the webcpanel templates. This is relative to the
* data directory.
*/
template_dir = "webcpanel/templates/default";
/* Template to use. */
template = "default";
/* Page title. */
title = "Anope IRC Services";
+7 -8
View File
@@ -66,9 +66,9 @@ module
client = "NickServ"
/*
* Requires users to give an email address when they register a nick.
* Force users to give an e-mail address when they register a nick.
*
* This directive defaults to "yes" and is recommended to be enabled.
* This directive defaults to "yes" and is recommended to be enabled. This is required if e-mail registration is enabled.
*/
forceemail = yes
@@ -97,7 +97,7 @@ module
* - 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_email: Hide the nick's e-mail address from NickServ's INFO command
* - hide_mask: Hide the nick's last or current user@host from NickServ's INFO command
* - hide_status: Hide the nick's services operator access status from NickServ's INFO command
* - hide_quit: Hide the nick's last quit message from NickServ's INFO command
@@ -119,7 +119,7 @@ module
* The minimum length of time between consecutive uses of NickServ's REGISTER command. This
* directive is optional, but recommended. If not set, this restriction will be disabled.
*/
regdelay = 5m
regdelay = 30s
/*
* The length of time before a nick's registration expires.
@@ -273,7 +273,6 @@ command { service = "NickServ"; name = "AJOIN"; command = "nickserv/ajoin"; }
*/
module { name = "ns_alist" }
command { service = "NickServ"; name = "ALIST"; command = "nickserv/alist"; }
command { service = "NickServ"; name = "ACCESS"; command = "nickserv/alist"; hide = true; }
/*
* ns_cert
@@ -330,7 +329,7 @@ module
*
* This directive is optional, but recommended. If not set or set to 0, no limits will be applied.
*/
maxaliases = 10
maxaliases = 16
/*
* If set, the NickServ GROUP command won't allow any group changes. This is recommended to
@@ -468,7 +467,7 @@ module
*
* This directive is optional.
*/
nickregdelay = 15s
#nickregdelay = 30s
/*
* The length of time a user using an unconfirmed account has
@@ -623,7 +622,7 @@ command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; }
name = "ns_maxemail"
/*
* The limit to how many registered nicks can use the same email address. If set to 0 or left
* The limit to how many registered nicks can use the same e-mail address. If set to 0 or left
* commented, there will be no limit enforced when registering new accounts or using
* /msg NickServ SET EMAIL.
*/
+4 -4
View File
@@ -235,15 +235,15 @@ serverinfo
/*
* The filename containing the Anope process ID. The path is relative to the
* data directory.
* services root directory.
*/
pid = "anope.pid"
pid = "data/anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
* config directory.
* services root directory.
*/
motd = "motd.txt"
motd = "conf/motd.txt"
}
/*
+1 -36
View File
@@ -1,38 +1,3 @@
Anope Version 2.1.4
-------------------
Added a check for a non-deprecated encryption module on start.
Added a way for protocol modules to report an error to the uplink.
Added more account settings to the webcpanel.
Added self-test functionality for all encryption modules.
Added support for challenge authentication on InspIRCd.
Added support for importing databases from Atheme.
Added support for sending client tags on UnrealIRCd.
Added support for the InspIRCd 1206 (v4) protocol.
Added the --nopid option to disable writing a pid file.
Added the enc_argon2 module to encrypt passwords with Argon2.
Added the enc_sha2 module to encrypt passwords with HMAC-SHA-2.
Added the global/queue command for queueing multi-line messages.
Added the global/server command for sending messages to an individual server.
Added the PASSWORD category to operserv/stats to view password encryption methods.
Added the verify-only enc_posix module to validate passwords from Atheme that were encrypted with Argon2.
Changed nickserv/drop to use confirmation codes to confirm a nickname drop.
Changed various paths to be relative to the data and config directories.
Converted some IRCDProto member functions to variables.
Converted the enc_md5, enc_none, enc_old, enc_sha1, and enc_sha256 modules to be verify-only.
Deduplicated page headers and footers in the webcpanel templates.
Deprecated the enc_sha256 module.
Fixed inconsistent spelling/casing of email, vhost, and vident.
Fixed various bugs in the inspircd module.
Improved portability of email sending.
Improved protocol debug messages.
Improved the performance and reliability of internal conversion logic.
Improved the randomness of randomly generated numbers.
Refactored the enc_bcrypt module and exposed it as an encryption context.
Removed several duplicate translation strings.
Replaced the custom MD5 implementation in enc_md5 with a vendored one.
Replaced the custom SHA256 implementation in enc_sha256 with a vendored one.
The ldap_authentication, ldap_oper, sql_authentication, sql_log, and sql_oper modules are now always enabled.
Anope Version 2.1.3
-------------------
Added alternate command suggestions when a user runs an invalid command.
@@ -53,7 +18,7 @@ Reworked how messages are sent in protocol modules to allow sending message tags
Anope Version 2.1.2
-------------------
Bumped the minimum OpenSSL version to 1.1.0.
Bumped the minimum GnuTLS version to 3.0.0.
Bumped the minumum GnuTLS version to 3.0.0.
Disabled SSLv3 support in the m_ssl_openssl module.
Modernized mutex and thread code to use Modern C++.
Normalised the program exit codes.
-21
View File
@@ -1,24 +1,3 @@
Anope Version 2.1.4
-------------------
Added the db_atheme module.
Added the enc_argon2 module.
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.
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".
Changed the default value of module:accessmax for the chanserv module to 1000.
Changed the default value of module:inhabit for the chanserv module to 1 minute.
Changed the default value of module:max for the cs_mode module to 50.
Changed the default value of module:max for the ms_ignore module to 50.
Removed options:seed.
Replaced module:template for the webcpanel module with module:template_dir.
Anope Version 2.1.3
-------------------
Added options:didyoumeandifference.
+1 -1
View File
@@ -33,7 +33,7 @@ Anope Multi Language Support
po files (especially on Windows).
If you have finished a language file translation and you want others to use it, please send it to team@anope.org
(don't forget to mention clearly your (nick)name, your email and the language name). You'll of course get full credit for it.
(don't forget to mention clearly your (nick)name, your e-mail and the language name). You'll of course get full credit for it.
NOTE: There is no guarantee we will use your work so please do not be offended if we say no thanks.
+17 -18
View File
@@ -17,8 +17,8 @@
#include "memo.h"
#include "base.h"
typedef Anope::unordered_map<NickAlias *> nickalias_map;
typedef Anope::unordered_map<NickCore *> nickcore_map;
typedef Anope::hash_map<NickAlias *> nickalias_map;
typedef Anope::hash_map<NickCore *> nickcore_map;
typedef std::unordered_map<uint64_t, NickCore *> nickcoreid_map;
extern CoreExport Serialize::Checker<nickalias_map> NickAliasList;
@@ -33,7 +33,7 @@ class CoreExport NickAlias final
, public Extensible
{
Anope::string vhost_ident, vhost_host, vhost_creator;
time_t vhost_created = 0;
time_t vhost_created;
public:
Anope::string nick;
@@ -43,9 +43,8 @@ public:
Anope::string last_usermask;
/* Last uncloaked usermask, requires nickserv/auspex to see */
Anope::string last_realhost;
time_t time_registered = Anope::CurTime;
time_t last_seen = Anope::CurTime;
time_t time_registered;
time_t last_seen;
/* Account this nick is tied to. Multiple nicks can be tied to a single account. */
Serialize::Reference<NickCore> nc;
@@ -65,41 +64,41 @@ public:
* @param creator Who created the vhost
* @param time When the vhost was created
*/
void SetVHost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime);
void SetVhost(const Anope::string &ident, const Anope::string &host, const Anope::string &creator, time_t created = Anope::CurTime);
/** Remove a users vhost
**/
void RemoveVHost();
void RemoveVhost();
/** Check if the user has a vhost
* @return true or false
*/
bool HasVHost() const;
bool HasVhost() const;
/** Retrieve the vhost ident
* @return the ident
*/
const Anope::string &GetVHostIdent() const;
const Anope::string &GetVhostIdent() const;
/** Retrieve the vhost host
* @return the host
*/
const Anope::string &GetVHostHost() const;
const Anope::string &GetVhostHost() const;
/** Retrieve the vhost mask
* @param the mask
*/
Anope::string GetVHostMask() const;
Anope::string GetVhostMask() const;
/** Retrieve the vhost creator
* @return the creator
*/
const Anope::string &GetVHostCreator() const;
const Anope::string &GetVhostCreator() const;
/** Retrieve when the vhost was created
* @return the time it was created
*/
time_t GetVHostCreated() const;
time_t GetVhostCreated() const;
/** Finds a registered nick
* @param nick The nick to lookup
@@ -128,8 +127,6 @@ public:
Anope::string email;
/* Locale name of the language of the user. Empty means default language */
Anope::string language;
/* Last time an email was sent to this user */
time_t lastmail = 0;
MemoInfo memos;
std::map<Anope::string, Anope::string> last_modes;
@@ -139,12 +136,14 @@ public:
Serialize::Checker<std::vector<NickAlias *> > aliases;
/* Set if this user is a services operator. o->ot must exist. */
Oper *o = nullptr;
Oper *o;
/* Unsaved data */
/* Number of channels registered by this account */
uint16_t channelcount = 0;
uint16_t channelcount;
/* Last time an email was sent to this user */
time_t lastmail;
/* Users online now logged into this account */
std::list<User *> users;
+72 -49
View File
@@ -39,7 +39,6 @@ namespace Anope
typedef std::string::reverse_iterator reverse_iterator;
typedef std::string::const_reverse_iterator const_reverse_iterator;
typedef std::string::size_type size_type;
typedef std::string::value_type value_type;
static const size_type npos = static_cast<size_type>(-1);
/**
@@ -344,7 +343,7 @@ namespace Anope
using multimap = std::multimap<string, T, ci::less>;
template<typename T>
using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
using hash_map = std::unordered_map<string, T, hash_ci, compare>;
#ifndef REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
@@ -367,7 +366,6 @@ namespace Anope
* Use this unless you need very specific time checks
*/
extern CoreExport time_t CurTime;
extern CoreExport long long CurTimeNs;
/** The debug level we are running at.
*/
@@ -375,7 +373,7 @@ namespace Anope
/** Other command line options.
*/
extern CoreExport bool ReadOnly, NoFork, NoThird, NoPID, NoExpire, ProtocolDebug;
extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
/** The root of the Anope installation. Usually ~/anope
*/
@@ -471,7 +469,7 @@ namespace Anope
* @param src The source string to encrypt
* @param dest The destination where the encrypted string is placed
*/
extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest);
extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest);
/** Hashes a buffer with SipHash-2-4
* @param src The start of the buffer to hash
@@ -536,18 +534,10 @@ namespace Anope
*/
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
/** Parses a raw message from the uplink and calls its command handler.
* @param message Raw message from the uplink
/** Main processing routine. Parses the message and takes the appropriate action.
* @param Raw message from the uplink
*/
extern void Process(const Anope::string &message);
/** Calls the command handler for an already parsed message.
* @param source Source of the message.
* @param command Command name.
* @param params Any extra parameters.
* @param tags IRCv3 message tags.
*/
extern CoreExport void ProcessInternal(MessageSource &src, const Anope::string &command, const std::vector<Anope::string> &params, const Anope::map<Anope::string> & tags);
extern void Process(const Anope::string &);
/** Does a blocking dns query and returns the first IP.
* @param host host to look up
@@ -568,39 +558,11 @@ namespace Anope
*/
extern CoreExport Anope::string Random(size_t len);
/** Generate a random number. */
extern CoreExport int RandomNumber();
/** Calculates the levenshtein distance between two strings.
* @param s1 The first string.
* @param s2 The second string.
*/
extern CoreExport size_t Distance(const Anope::string &s1, const Anope::string &s2);
/** Update the current time. */
extern CoreExport void UpdateTime();
/** Expands a path fragment that is relative to the base directory.
* @param base The base directory that it is relative to.
* @param fragment The fragment to expand.
*/
extern CoreExport Anope::string Expand(const Anope::string &base, const Anope::string &fragment);
/** Expands a config path. */
inline auto ExpandConfig(const Anope::string &path) { return Expand(ConfigDir, path); }
/** Expands a data path. */
inline auto ExpandData(const Anope::string &path) { return Expand(DataDir, path); }
/** Expands a locale path. */
inline auto ExpandLocale(const Anope::string &path) { return Expand(LocaleDir, path); }
/** Expands a log path. */
inline auto ExpandLog(const Anope::string &path) { return Expand(LogDir, path); }
/** Expands a module path. */
inline auto ExpandModule(const Anope::string &path) { return Expand(ModuleDir, path); }
}
/** sepstream allows for splitting token separated lists.
@@ -628,9 +590,6 @@ public:
*/
sepstream(const Anope::string &source, char separator, bool allowempty = false);
/** Retrieves the underlying string. */
const auto &GetString() const { return tokens; }
/** Fetch the next token from the stream
* @param token The next token from the stream is placed here
* @return True if tokens still remain, false if there are none left
@@ -764,6 +723,72 @@ public:
virtual ~ModuleException() noexcept = default;
};
class CoreExport ConvertException final
: public CoreException
{
public:
ConvertException(const Anope::string &reason = "") : CoreException(reason) { }
virtual ~ConvertException() noexcept = default;
};
/** Convert something to a string
*/
inline Anope::string stringify(const Anope::string &x)
{
return x;
}
template<typename T> inline Anope::string stringify(const T &x)
{
std::ostringstream stream;
if (!(stream << x))
throw ConvertException("Stringify fail");
return stream.str();
}
template<typename T> inline void convert(const Anope::string &s, T &x, Anope::string &leftover, bool failIfLeftoverChars = true)
{
leftover.clear();
std::istringstream i(s.str());
char c;
if (!(i >> x))
throw ConvertException("Convert fail");
if (failIfLeftoverChars)
{
if (i.get(c))
throw ConvertException("Convert fail");
}
else
{
std::string left;
getline(i, left);
leftover = left;
}
}
template<typename T> inline void convert(const Anope::string &s, T &x, bool failIfLeftoverChars = true)
{
Anope::string Unused;
convert(s, x, Unused, failIfLeftoverChars);
}
template<typename T> inline T convertTo(const Anope::string &s, Anope::string &leftover, bool failIfLeftoverChars = true)
{
T x;
convert(s, x, leftover, failIfLeftoverChars);
return x;
}
template<typename T> inline T convertTo(const Anope::string &s, bool failIfLeftoverChars = true)
{
T x;
convert(s, x, failIfLeftoverChars);
return x;
}
/** Casts to be used instead of dynamic_cast, this uses dynamic_cast
* for debug builds and static_cast on release builds
* to speed up the program because dynamic_cast relies on RTTI.
@@ -783,5 +808,3 @@ template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
return static_cast<T>(ptr);
}
#endif
#include "convert.h"
+1 -1
View File
@@ -13,7 +13,7 @@
#include "modes.h"
#include "serialize.h"
typedef Anope::unordered_map<Channel *> channel_map;
typedef Anope::hash_map<Channel *> channel_map;
extern CoreExport channel_map ChannelList;
+9 -1
View File
@@ -15,6 +15,7 @@
#include "regchannel.h"
#include "users.h"
#include "opertype.h"
#include <stack>
namespace Configuration
{
@@ -46,7 +47,14 @@ namespace Configuration
template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
{
return Anope::TryConvert<T>(this->Get<const Anope::string>(tag, def)).value_or(T());
const Anope::string &value = this->Get<const Anope::string>(tag, def);
if (!value.empty())
try
{
return convertTo<T>(value);
}
catch (const ConvertException &) { }
return T();
}
bool Set(const Anope::string &tag, const Anope::string &value);
-132
View File
@@ -1,132 +0,0 @@
/*
*
* (C) 2003-2024 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.
*/
#pragma once
#include <optional>
namespace Anope
{
/** Attempts to convert a string to any type.
* @param in The value to convert.
* @param leftover If non-nullptr then the location to store leftover data.
*/
template<typename T>
inline std::optional<T> TryConvert(const Anope::string &in, Anope::string *leftover = nullptr)
{
std::istringstream tmp(in.str());
T out;
if (!(tmp >> out))
return std::nullopt;
if (leftover)
{
leftover->clear();
std::getline(tmp, leftover->str());
}
else
{
char extra;
if (tmp >> extra)
return std::nullopt;
}
return out;
}
/** Converts a string to any type.
* @param in The value to convert.
* @param def The default to use if the conversion failed.
* @param leftover If non-nullptr then the location to store leftover data.
*/
template<typename T>
inline T Convert(const Anope::string &in, T def, Anope::string *leftover = nullptr)
{
return TryConvert<T>(in, leftover).value_or(def);
}
/** Attempts to convert any type to a string.
* @param in The value to convert.
*/
template <class T>
inline std::optional<Anope::string> TryString(const T &in)
{
std::ostringstream tmp;
if (!(tmp << in))
return std::nullopt;
return tmp.str();
}
/** No-op function that returns the string that was passed to it.
* @param in The string to return.
*/
inline const string &ToString(const string &in)
{
return in;
}
/** Converts a std::string to a string.
* @param in The value to convert.
*/
inline string ToString(const std::string &in)
{
return in;
}
/** Converts a char array to a string.
* @param in The value to convert.
*/
inline string ToString(const char *in)
{
return string(in);
}
/** Converts a char to a string.
* @param in The value to convert.
*/
inline string ToString(char in)
{
return string(1, static_cast<string::value_type>(in));
}
/** Converts an unsigned char to a string.
* @param in The value to convert.
*/
inline string ToString(unsigned char in)
{
return string(1, static_cast<string::value_type>(in));
}
/** Converts a bool to a string.
* @param in The value to convert.
*/
inline string ToString(bool in)
{
return (in ? "1" : "0");
}
/** Converts a type that std::to_string is implemented for to a string.
* @param in The value to convert.
*/
template<typename Stringable>
inline std::enable_if_t<std::is_arithmetic_v<Stringable>, string> ToString(const Stringable &in)
{
return std::to_string(in);
}
/** Converts any type to a string.
* @param in The value to convert.
*/
template <class T>
inline std::enable_if_t<!std::is_arithmetic_v<T>, string> ToString(const T &in)
{
return TryString(in).value_or(Anope::string());
}
}
+10 -11
View File
@@ -65,13 +65,11 @@ namespace Language
} // namespace Language
/* Commonly used language strings */
#define CONFIRM_DROP _("Please confirm that you want to drop \002%s\002 with \002%s%s DROP %s %s\002")
#define SERVICE_UNAVAILABLE _("Sorry, %s is temporarily unavailable.")
#define MORE_INFO _("\002%s%s HELP %s\002 for more information.")
#define BAD_USERHOST_MASK _("Mask must be in the form \037user\037@\037host\037.")
#define BAD_EXPIRY_TIME _("Invalid expiry time.")
#define USERHOST_MASK_TOO_WIDE _("%s coverage is too wide; Please use a more specific mask.")
#define READ_ONLY_MODE _("Services are temporarily in read-only mode.")
#define READ_ONLY_MODE _("Services are in read-only mode!")
#define PASSWORD_INCORRECT _("Password incorrect.")
#define ACCESS_DENIED _("Access denied.")
#define MORE_OBSCURE_PASSWORD _("Please try again with a more obscure password. Passwords should not be\n" \
@@ -88,7 +86,7 @@ namespace Language
#define CHAN_X_NOT_REGISTERED _("Channel \002%s\002 isn't registered.")
#define CHAN_X_NOT_IN_USE _("Channel \002%s\002 doesn't exist.")
#define NICK_IDENTIFY_REQUIRED _("You must be logged into an account to use that command.")
#define MAIL_X_INVALID _("\002%s\002 is not a valid email address.")
#define MAIL_X_INVALID _("\002%s\002 is not a valid e-mail address.")
#define UNKNOWN _("<unknown>")
#define NO_EXPIRE _("does not expire")
#define LIST_INCORRECT_RANGE _("Incorrect range specified. The correct syntax is \002#\037from\037-\037to\037\002.")
@@ -99,7 +97,7 @@ namespace Language
#define NICK_CANNOT_BE_REGISTERED _("Nickname \002%s\002 may not be registered.")
#define NICK_ALREADY_REGISTERED _("Nickname \002%s\002 is already registered!")
#define NICK_SET_DISPLAY_CHANGED _("The new display is now \002%s\002.")
#define NICK_CONFIRM_INVALID _("Invalid passcode has been entered, please check the email again, and retry.")
#define NICK_CONFIRM_INVALID _("Invalid passcode has been entered, please check the e-mail again, and retry.")
#define CHAN_NOT_ALLOWED_TO_JOIN _("You are not permitted to be on this channel.")
#define CHAN_X_INVALID _("Channel %s is not a valid channel.")
#define CHAN_REACHED_CHANNEL_LIMIT _("Sorry, you have already reached your limit of \002%d\002 channels.")
@@ -116,14 +114,15 @@ namespace Language
"Type \002%s%s READ %zu\002 to read it.")
#define MEMO_HAVE_NO_MEMOS _("You have no memos.")
#define MEMO_X_HAS_NO_MEMOS _("%s has no memos.")
#define MEMO_SEND_DISABLED _("Sorry, memo sending is temporarily disabled.")
#define MEMO_HAVE_NO_NEW_MEMOS _("You have no new memos.")
#define MEMO_X_HAS_NO_NEW_MEMOS _("%s has no new memos.")
#define BOT_DOES_NOT_EXIST _("Bot \002%s\002 does not exist.")
#define BOT_NOT_ASSIGNED _("You must assign a bot to the channel before using this command.")
#define BOT_NOT_ON_CHANNEL _("Bot is not on channel \002%s\002.")
#define HOST_SET_ERROR _("A vhost must be in the format of a valid hostname.")
#define HOST_SET_IDENT_ERROR _("A vident must be in the format of a valid ident.")
#define HOST_SET_TOOLONG _("Error! The vhost is too long, please use a hostname shorter than %zu characters.")
#define HOST_SET_IDENTTOOLONG _("Error! The vident is too long, please use an ident shorter than %zu characters.")
#define HOST_NOT_ASSIGNED _("Please contact an Operator to get a vhost assigned to this nick.")
#define HOST_NO_VIDENT _("Your IRCd does not support vidents. If this is incorrect please report this as a possible bug.")
#define HOST_SET_ERROR _("A vHost must be in the format of a valid hostname.")
#define HOST_SET_IDENT_ERROR _("A vHost ident must be in the format of a valid ident.")
#define HOST_SET_TOOLONG _("Error! The vHost is too long, please use a hostname shorter than %zu characters.")
#define HOST_SET_IDENTTOOLONG _("Error! The vHost ident is too long, please use an ident shorter than %zu characters.")
#define HOST_NOT_ASSIGNED _("Please contact an Operator to get a vHost assigned to this nick.")
#define HOST_NO_VIDENT _("Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug")
+1 -1
View File
@@ -26,7 +26,6 @@ namespace Mail
: public Thread
{
private:
Anope::string error;
Anope::string sendmail_path;
Anope::string send_from;
Anope::string mail_to;
@@ -36,6 +35,7 @@ namespace Mail
Anope::string content_type;
bool dont_quote_addresses;
bool success = false;
public:
/** Construct this message. Once constructed call Thread::Start to launch the mail sending.
* @param sf Config->SendFrom
+3 -3
View File
@@ -838,12 +838,12 @@ public:
/** Called when a vhost is deleted
* @param na The nickalias of the vhost
*/
virtual void OnDeleteVHost(NickAlias *na) { throw NotImplementedException(); }
virtual void OnDeleteVhost(NickAlias *na) { throw NotImplementedException(); }
/** Called when a vhost is set
* @param na The nickalias of the vhost
*/
virtual void OnSetVHost(NickAlias *na) { throw NotImplementedException(); }
virtual void OnSetVhost(NickAlias *na) { throw NotImplementedException(); }
/** Called when a users host changes
* @param u The user
@@ -1081,7 +1081,7 @@ enum Implementation
I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickConfirm, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate,
I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearCert,
I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate,
I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVHost, I_OnSetVHost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
I_OnFingerprint, I_OnUserAway, I_OnInvite, I_OnDeleteVhost, I_OnSetVhost, I_OnSetDisplayedHost, I_OnMemoSend, I_OnMemoDel,
I_OnChannelModeSet, I_OnChannelModeUnset, I_OnUserModeSet, I_OnUserModeUnset, I_OnChannelModeAdd, I_OnUserModeAdd,
I_OnMLock, I_OnUnMLock, I_OnModuleLoad, I_OnModuleUnload, I_OnServerSync, I_OnUplinkSync, I_OnBotPrivmsg, I_OnBotNotice,
I_OnPrivmsg, I_OnLog, I_OnLogMessage, I_OnDnsRequest, I_OnCheckModes, I_OnChannelSync, I_OnSetCorrectModes,
+8 -117
View File
@@ -13,135 +13,26 @@
namespace Encryption
{
/** Base class for encryption contexts. */
typedef std::pair<const unsigned char *, size_t> Hash;
typedef std::pair<const uint32_t *, size_t> IV;
class Context
{
public:
virtual ~Context() = default;
/** Updates the encryption context with the specified data.
* @param str The data to update the context with.
*/
inline void Update(const Anope::string &str)
{
Update(reinterpret_cast<const unsigned char *>(str.c_str()), str.length());
}
/** Updates the encryption context with the specified data.
* @param data The data to update the context with.
* @param len The length of the data.
*/
virtual void Update(const unsigned char *data, size_t len) = 0;
/** Finalises the encryption context and returns the digest. */
virtual Anope::string Finalize() = 0;
virtual void Finalize() = 0;
virtual Hash GetFinalizedHash() = 0;
};
/** Provider of encryption contexts. */
class Provider
: public Service
{
public:
/** The byte size of the block cipher. */
const size_t block_size;
/** The byte size of the resulting digest. */
const size_t digest_size;
/** Creates a provider of encryption contexts.
* @param creator The module that created this provider.
* @param algorithm The name of the encryption algorithm.
* @param bs The byte size of the block cipher.
* @param ds The byte size of the resulting digest.
*/
Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
: Service(creator, "Encryption::Provider", algorithm)
, block_size(bs)
, digest_size(ds)
{
}
Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { }
virtual ~Provider() = default;
/** Checks whether a plain text value matches a hash created by this provider. */
virtual bool Compare(const Anope::string &hash, const Anope::string &plain)
{
return !hash.empty() && hash.equals_cs(ToPrintable(Encrypt(plain)));
}
/** Called on initialising a encryption provider to check it works properly. */
void Check(const Anope::map<Anope::string> &checks)
{
for (const auto &[hash, plain] : checks)
{
if (!Compare(hash, plain))
throw ModuleException("BUG: unable to generate " + this->name + " hashes safely! Please report this!");
}
Log(LOG_DEBUG) << "The " << this->name << " encryption provider appears to be working correctly.";
}
/** Creates a new encryption context. */
virtual std::unique_ptr<Context> CreateContext() = 0;
/** Quickly encrypts the specified values and returns the digest. */
template<typename... Args>
Anope::string Encrypt(Args &&...args)
{
auto context = CreateContext();
context->Update(std::forward<Args>(args)...);
return context->Finalize();
}
/** Calculates the RFC 2104 hash-based message authentication code for the specified data. */
inline Anope::string HMAC(const Anope::string &key, const Anope::string &data)
{
if (!block_size)
return {};
auto keybuf = key.length() > block_size ? Encrypt(key) : key;
keybuf.resize(block_size);
Anope::string hmac1;
Anope::string hmac2;
for (size_t i = 0; i < block_size; ++i)
{
hmac1.push_back(static_cast<char>(keybuf[i] ^ 0x5C));
hmac2.push_back(static_cast<char>(keybuf[i] ^ 0x36));
}
hmac2.append(data);
hmac1.append(Encrypt(hmac2));
return Encrypt(hmac1);
}
/** Converts a hash to its printable form. */
virtual Anope::string ToPrintable(const Anope::string &hash)
{
return Anope::Hex(hash);
}
};
/** Helper template for creating simple providers of encryption contexts. */
template <typename T>
class SimpleProvider final
: public Provider
{
public:
/** Creates a simple provider of encryption contexts.
* @param creator The module that created this provider.
* @param algorithm The name of the encryption algorithm.
* @param bs The byte size of the block cipher.
* @param ds The byte size of the resulting digest.
*/
SimpleProvider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
: Provider(creator, algorithm, bs, ds)
{
}
/** @copydoc Encryption::Provider::CreateContext. */
std::unique_ptr<Context> CreateContext() override
{
return std::make_unique<T>();
}
virtual Context *CreateContext(IV * = NULL) = 0;
virtual IV GetDefaultIV() = 0;
};
}
-23
View File
@@ -1,23 +0,0 @@
/*
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#pragma once
class HostRequest
{
protected:
HostRequest() = default;
public:
Anope::string nick;
Anope::string ident;
Anope::string host;
time_t time = 0;
virtual ~HostRequest() = default;
};
-49
View File
@@ -1,49 +0,0 @@
/*
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#pragma once
class OperInfo
{
protected:
OperInfo() = default;
OperInfo(const Anope::string &t, const Anope::string &i, const Anope::string &a, time_t c)
: target(t)
, info(i)
, adder(a)
, created(c)
{
}
public:
Anope::string target;
Anope::string info;
Anope::string adder;
time_t created = 0;
virtual ~OperInfo() = default;
};
class OperInfoList
: public Serialize::Checker<std::vector<OperInfo *>>
{
public:
OperInfoList()
: Serialize::Checker<std::vector<OperInfo *>>("OperInfo")
{
}
virtual ~OperInfoList()
{
for (auto *info : *(*this))
delete info;
}
virtual OperInfo *Create() = 0;
};
+7 -54
View File
@@ -8,68 +8,21 @@
#pragma once
#define GLOBAL_NO_MESSAGE _("You do not have any messages queued and did not specify a message to send.")
#define GLOBAL_QUEUE_CONFLICT _("You can not send a single message while you have messages queued.")
class GlobalService
: public Service
{
public:
GlobalService(Module *m)
: Service(m, "GlobalService", "Global")
GlobalService(Module *m) : Service(m, "GlobalService", "Global")
{
}
/** Retrieves the bot which sends global messages unless otherwise specified. */
virtual Reference<BotInfo> GetDefaultSender() const = 0;
virtual Reference<BotInfo> GetDefaultSender() = 0;
/** Clears any queued messages for the specified account.
* @param nc The account to clear queued messages for.
/** Send out a global message to all users
* @param sender Our client which should send the global
* @param source The sender of the global
* @param message The message
*/
virtual void ClearQueue(NickCore *nc) = 0;
/** Retrieves the size of the messages queue for the specified user.
* @param nc The account to count queued messages for.
*/
inline size_t CountQueue(NickCore* nc) const
{
auto *q = GetQueue(nc);
return q ? q->size() : 0;
}
/** Retrieves the messages queue for the specified user.
* @param nc The account to retrieve queued messages for.
*/
virtual const std::vector<Anope::string> *GetQueue(NickCore* nc) const = 0;
/** Queues a message to be sent later.
* @param nc The account to queue the message for.
* @param message The message to queue.
* @return The new number of messages in the queue.
*/
virtual size_t Queue(NickCore *nc, const Anope::string &message) = 0;
/** Sends a single message to all users on the network.
* @param message The message to send.
* @param source If non-nullptr then the source of the message.
* @param sender If non-nullptr then the bot to send the message from.
* @param server If non-nullptr then the server to send messages to.
* @return If the message was sent then true; otherwise, false.
*/
virtual bool SendSingle(const Anope::string &message, CommandSource *source = nullptr, BotInfo *sender = nullptr, Server *server = nullptr) = 0;
/** Sends a message queue to all users on the network.
* @param source The source of the message.
* @param sender If non-nullptr then the bot to send the message from.
* @param server If non-nullptr then the server to send messages to.
* @return If the message queue was sent then true; otherwise, false.
*/
virtual bool SendQueue(CommandSource &source, BotInfo *sender = nullptr, Server *server = nullptr) = 0;
/** Unqueues a message from the message queue.
* @param nc The account to unqueue the message from.
* @param idx The index of the item to remove.
* @return Whether the message was removed from the queue.
*/
virtual bool Unqueue(NickCore *nc, size_t idx) = 0;
virtual void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) = 0;
};
+7 -8
View File
@@ -8,8 +8,6 @@
#pragma once
#include <stdexcept>
namespace SQL
{
@@ -128,12 +126,13 @@ namespace SQL
template<typename T> void SetValue(const Anope::string &key, const T &value, bool escape = true)
{
auto str = Anope::TryString(value);
if (!str.has_value())
return;
this->parameters[key].data = str.value();
this->parameters[key].escape = escape;
try
{
Anope::string string_value = stringify(value);
this->parameters[key].data = string_value;
this->parameters[key].escape = escape;
}
catch (const ConvertException &ex) { }
}
};
+19 -40
View File
@@ -16,17 +16,6 @@
#include "service.h"
#include "modes.h"
/** Thrown when a protocol error happens. */
class CoreExport ProtocolException final
: public ModuleException
{
public:
ProtocolException(const Anope::string &message)
: ModuleException(message)
{
}
};
/* Encapsulates the IRCd protocol we are speaking. */
class CoreExport IRCDProto
: public Service
@@ -110,37 +99,16 @@ public:
/** Can we ask the server to unban a user? */
bool CanClearBans = false;
/* The maximum length of a channel name. */
size_t MaxChannel = 0;
/* The maximum length of a hostname. */
size_t MaxHost = 0;
/* The maximum number of modes we are allowed to set with one MODE command */
unsigned MaxModes = 3;
/* The maximum number of bytes a line may have */
size_t MaxLine = 512;
/* The maximum number of modes we are allowed to set with one MODE command */
size_t MaxModes = 3;
/* The maximum length of a nickname. */
size_t MaxNick = 0;
/* The maximum length of a username. */
size_t MaxUser = 0;
unsigned MaxLine = 512;
/* Retrieves the next free UID or SID */
virtual Anope::string UID_Retrieve();
virtual Anope::string SID_Retrieve();
/** Extracts a timestamp from a string. */
virtual time_t ExtractTimestamp(const Anope::string &str);
/** Sends an error to the uplink before disconnecting.
* @param reason The error message.
*/
virtual void SendError(const Anope::string &reason);
/** Sets the server in NOOP mode. If NOOP mode is enabled, no users
* will be able to oper on the server.
* @param s The server
@@ -159,8 +127,8 @@ public:
* @param vident The ident to set
* @param vhost The vhost to set
*/
virtual void SendVHost(User *u, const Anope::string &vident, const Anope::string &vhost) { }
virtual void SendVHostDel(User *) { }
virtual void SendVhost(User *u, const Anope::string &vident, const Anope::string &vhost) { }
virtual void SendVhostDel(User *) { }
/** Sets an akill. This is a recursive function that can be called multiple times
* for the same xline, but for different users, if the xline is not one that can be
@@ -196,14 +164,14 @@ public:
template <typename... Args>
void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args &&...args)
{
SendModeInternal(source, chan, modes, { Anope::ToString(args)... });
SendModeInternal(source, chan, modes, { stringify(args)... });
}
virtual void SendModeInternal(const MessageSource &source, User *u, const Anope::string &modes, const std::vector<Anope::string> &values);
template <typename... Args>
void SendMode(const MessageSource &source, User *u, const Anope::string &modes, Args &&...args)
{
SendModeInternal(source, u, modes, { Anope::ToString(args)... });
SendModeInternal(source, u, modes, { stringify(args)... });
}
/** Introduces a client to the rest of the network
@@ -290,7 +258,7 @@ public:
template <typename... Args>
void SendNumeric(int numeric, const Anope::string &dest, Args &&...args)
{
SendNumericInternal(numeric, dest, { Anope::ToString(args)... });
SendNumericInternal(numeric, dest, { stringify(args)... });
}
virtual void SendLogin(User *u, NickAlias *na) = 0;
@@ -326,6 +294,17 @@ public:
virtual Anope::string NormalizeMask(const Anope::string &mask);
/** Retrieves the maximum length of a channel name. */
virtual size_t GetMaxChannel();
/** Retrieves the maximum length of a hostname. */
virtual size_t GetMaxHost();
/** Retrieves the maximum length of a nickname. */
virtual size_t GetMaxNick();
/** Retrieves the maximum length of a username. */
virtual size_t GetMaxUser();
};
class CoreExport MessageSource final
+1 -1
View File
@@ -16,7 +16,7 @@
#include "serialize.h"
#include "bots.h"
typedef Anope::unordered_map<ChannelInfo *> registered_channel_map;
typedef Anope::hash_map<ChannelInfo *> registered_channel_map;
extern CoreExport Serialize::Checker<registered_channel_map> RegisteredChannelList;
+29 -23
View File
@@ -11,33 +11,39 @@
#pragma once
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <bitset>
#include <deque>
#include <exception>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <vector>
#ifndef _WIN32
# include <unistd.h>
#endif
#include "defs.h"
#include "sysconf.h"
#define BUFSIZE 1024
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <stdexcept>
#include <cstring>
#ifndef _WIN32
#include <unistd.h>
#endif
/* Pull in the various bits of STL */
#include <cstdint>
#include <cstddef>
#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <exception>
#include <list>
#include <vector>
#include <deque>
#include <bitset>
#include <set>
#include <algorithm>
#include <iterator>
#include "defs.h"
#define _(x) x
#ifndef _WIN32
-3
View File
@@ -20,9 +20,6 @@
// Whether Anope was built in debug mode.
#cmakedefine01 DEBUG_BUILD
// Whether the clock_gettime() function is available.
#cmakedefine01 HAVE_CLOCK_GETTIME
// Whether Anope was built with localization support.
#cmakedefine01 HAVE_LOCALIZATION
+1 -1
View File
@@ -18,7 +18,7 @@ class CoreExport Timer
private:
/** The owner of the timer, if any
*/
Module *owner = nullptr;
Module *owner;
/** The triggering time
*/
+4 -4
View File
@@ -23,25 +23,25 @@ namespace Uplink
template<typename... Args>
void Send(const Anope::map<Anope::string> &tags, const MessageSource &source, const Anope::string &command, Args &&...args)
{
SendInternal(tags, source, command, { Anope::ToString(args)... });
SendInternal(tags, source, command, { stringify(args)... });
}
template<typename... Args>
void Send(const Anope::map<Anope::string> &tags, const Anope::string &command, Args &&...args)
{
SendInternal(tags, Me, command, { Anope::ToString(args)... });
SendInternal(tags, Me, command, { stringify(args)... });
}
template<typename... Args>
void Send(const MessageSource &source, const Anope::string &command, Args &&...args)
{
SendInternal({}, source, command, { Anope::ToString(args)... });
SendInternal({}, source, command, { stringify(args)... });
}
template<typename... Args>
void Send(const Anope::string &command, Args &&...args)
{
SendInternal({}, Me, command, { Anope::ToString(args)... });
SendInternal({}, Me, command, { stringify(args)... });
}
}
+1 -1
View File
@@ -19,7 +19,7 @@
#include "account.h"
#include "sockets.h"
typedef Anope::unordered_map<User *> user_map;
typedef Anope::hash_map<User *> user_map;
extern CoreExport user_map UserListByNick, UserListByUID;
+186 -245
View File
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Anope\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-15 12:41+0000\n"
"PO-Revision-Date: 2024-03-15 12:41+0000\n"
"POT-Creation-Date: 2024-03-04 10:34+0000\n"
"PO-Revision-Date: 2024-03-04 10:34+0000\n"
"Last-Translator: Sadie Powell <sadie@witchery.services>\n"
"Language-Team: English\n"
"Language: en_US\n"
@@ -283,8 +283,8 @@ msgid "%s is not a valid bot or registered channel."
msgstr "%s is not a valid bot or registered channel."
#, c-format
msgid "%s is not a valid email address."
msgstr "%s is not a valid email address."
msgid "%s is not a valid e-mail address."
msgstr "%s is not a valid e-mail address."
#, c-format
msgid "%s is not currently on channel %s."
@@ -700,9 +700,6 @@ msgstr "nickname new-display"
msgid "nickname new-password"
msgstr "nickname new-password"
msgid "nickname [code]"
msgstr "nickname [code]"
msgid "nickname [parameter]"
msgstr "nickname [parameter]"
@@ -757,9 +754,6 @@ msgstr "pattern [SUSPENDED] [NOEXPIRE]"
msgid "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
msgstr "pattern [SUSPENDED] [NOEXPIRE] [UNCONFIRMED]"
msgid "server [message]"
msgstr "server [message]"
msgid "server [reason]"
msgstr "server [reason]"
@@ -1691,8 +1685,8 @@ msgid "<unknown>"
msgstr "<unknown>"
#, c-format
msgid "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
msgstr "A confirmation email has been sent to %s. Follow the instructions in it to change your email address."
msgid "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
msgstr "A confirmation e-mail has been sent to %s. Follow the instructions in it to change your e-mail address."
msgid "A massmemo has been sent to all registered users."
msgstr "A massmemo has been sent to all registered users."
@@ -1711,18 +1705,15 @@ msgstr ""
"A notification memo has been sent to %s informing them you have\n"
"read their memo."
msgid "A vhost must be in the format of a valid hostname."
msgstr "A vhost must be in the format of a valid hostname."
msgid "A vHost ident must be in the format of a valid ident."
msgstr "A vHost ident must be in the format of a valid ident."
msgid "A vident must be in the format of a valid ident."
msgstr "A vident must be in the format of a valid ident."
msgid "A vHost must be in the format of a valid hostname."
msgstr "A vHost must be in the format of a valid hostname."
msgid "ADD expiry {nick|mask} [reason]"
msgstr "ADD expiry {nick|mask} [reason]"
msgid "ADD message"
msgstr "ADD message"
msgid "ADD oper type"
msgstr "ADD oper type"
@@ -1812,11 +1803,8 @@ msgstr "Account"
msgid "Account %s has already reached the maximum number of simultaneous logins (%u)."
msgstr "Account %s has already reached the maximum number of simultaneous logins (%u)."
msgid "Accounts can not be registered right now. Please try again later."
msgstr "Accounts can not be registered right now. Please try again later."
msgid "Activate the requested vhost for the given nick."
msgstr "Activate the requested vhost for the given nick."
msgid "Activate the requested vHost for the given nick."
msgstr "Activate the requested vHost for the given nick."
msgid ""
"Activates the vhost currently assigned to the nick in use.\n"
@@ -2038,6 +2026,14 @@ msgstr "Allowed to use the MODE command"
msgid "Allowed to view the access list"
msgstr "Allowed to view the access list"
#, c-format
msgid ""
"Allows Administrators to send messages to all users on the\n"
"network. The message will be sent from the nick %s."
msgstr ""
"Allows Administrators to send messages to all users on the\n"
"network. The message will be sent from the nick %s."
msgid ""
"Allows Services Operators to change modes for any channel.\n"
"Parameters are the same as for the standard /MODE command.\n"
@@ -2260,51 +2256,6 @@ msgstr ""
"topic lock is set, the channel topic will be unchangeable by users who do not have\n"
"the TOPIC privilege."
msgid ""
"Allows queueing messages to send to users on the network.\n"
"\n"
"The QUEUE ADD command adds the given message to the message queue.\n"
"The QUEUE CLEAR command clears the message queue.\n"
"The QUEUE DEL command removes the specified message from the message queue. The\n"
"message number can be obtained from the output of the QUEUE LIST command.\n"
"The QUEUE LIST command lists all messages that are currently in the message queue."
msgstr ""
"Allows queueing messages to send to users on the network.\n"
"\n"
"The QUEUE ADD command adds the given message to the message queue.\n"
"The QUEUE CLEAR command clears the message queue.\n"
"The QUEUE DEL command removes the specified message from the message queue. The\n"
"message number can be obtained from the output of the QUEUE LIST command.\n"
"The QUEUE LIST command lists all messages that are currently in the message queue."
#, c-format
msgid ""
"Allows sending messages to all users on a server. The message will be sent\n"
"from %s.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
msgstr ""
"Allows sending messages to all users on a server. The message will be sent\n"
"from %s.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
#, c-format
msgid ""
"Allows sending messages to all users on the network. The message will be sent\n"
"from %s.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
msgstr ""
"Allows sending messages to all users on the network. The message will be sent\n"
"from %s.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
#, c-format
msgid ""
"Allows staff to kick a user from any channel.\n"
@@ -2401,7 +2352,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
"nick. You can hide the email address (EMAIL), last seen\n"
"nick. You can hide the E-mail address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2409,7 +2360,7 @@ msgid ""
msgstr ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on the\n"
"nick. You can hide the email address (EMAIL), last seen\n"
"nick. You can hide the E-mail address (EMAIL), last seen\n"
"user@host mask (USERMASK), the services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2419,7 +2370,7 @@ msgstr ""
msgid ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
"nick. You can hide your email address (EMAIL), last seen\n"
"nick. You can hide your E-mail address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2427,7 +2378,7 @@ msgid ""
msgstr ""
"Allows you to prevent certain pieces of information from\n"
"being displayed when someone does a %s INFO on your\n"
"nick. You can hide your email address (EMAIL), last seen\n"
"nick. You can hide your E-mail address (EMAIL), last seen\n"
"user@host mask (USERMASK), your services access status\n"
"(STATUS) and last quit message (QUIT).\n"
"The second parameter specifies whether the information should\n"
@@ -2458,8 +2409,8 @@ msgstr ""
"Alternative methods of modifying channel access lists are\n"
"available."
msgid "Approve the requested vhost of a user"
msgstr "Approve the requested vhost of a user"
msgid "Approve the requested vHost of a user"
msgstr "Approve the requested vHost of a user"
msgid "As a Services Operator, you may drop any nick."
msgstr "As a Services Operator, you may drop any nick."
@@ -2488,24 +2439,24 @@ msgstr "Associate a URL with your account"
msgid "Associate a greet message with your nickname"
msgstr "Associate a greet message with your nickname"
msgid "Associate an email address with the channel"
msgstr "Associate an email address with the channel"
msgid "Associate an E-mail address with the channel"
msgstr "Associate an E-mail address with the channel"
msgid "Associate an email address with your nickname"
msgstr "Associate an email address with your nickname"
msgid "Associate an E-mail address with your nickname"
msgstr "Associate an E-mail address with your nickname"
msgid "Associate oper info with a nick or channel"
msgstr "Associate oper info with a nick or channel"
msgid "Associates the given email address with the nickname."
msgstr "Associates the given email address with the nickname."
msgid "Associates the given E-mail address with the nickname."
msgstr "Associates the given E-mail address with the nickname."
msgid ""
"Associates the given email address with your nickname.\n"
"Associates the given E-mail address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
msgstr ""
"Associates the given email address with your nickname.\n"
"Associates the given E-mail address with your nickname.\n"
"This address will be displayed whenever someone requests\n"
"information on the nickname with the INFO command."
@@ -3206,9 +3157,6 @@ msgstr "Current number of SQLINEs: %zu"
msgid "Current users: %zu (%d ops)"
msgstr "Current users: %zu (%d ops)"
msgid "DEL entry-num"
msgstr "DEL entry-num"
msgid "DEL oper"
msgstr "DEL oper"
@@ -3382,10 +3330,6 @@ msgstr "Deleted %d entries from the %s list."
msgid "Deleted %d entries from the AKILL list."
msgstr "Deleted %d entries from the AKILL list."
#, c-format
msgid "Deleted %u entries from your message queue."
msgstr "Deleted %u entries from your message queue."
#, c-format
msgid "Deleted 1 entry from %s access list."
msgstr "Deleted 1 entry from %s access list."
@@ -3416,9 +3360,6 @@ msgstr "Deleted info from %s."
msgid "Deleted one entry from %s %s list."
msgstr "Deleted one entry from %s %s list."
msgid "Deleted one entry from your message queue."
msgstr "Deleted one entry from your message queue."
msgid ""
"Deletes the specified memo or memos. You can supply\n"
"multiple memo numbers or ranges of numbers instead of a\n"
@@ -3596,6 +3537,18 @@ msgstr ""
"you may own. Any other user will be able to gain control of\n"
"this nick."
#, c-format
msgid "E-mail address for %s changed to %s."
msgstr "E-mail address for %s changed to %s."
#, c-format
msgid "E-mail address for %s unset."
msgstr "E-mail address for %s unset."
#, c-format
msgid "E-mail for %s is invalid."
msgstr "E-mail for %s is invalid."
#, c-format
msgid ""
"Edits or displays the list of logon news messages. When a\n"
@@ -3636,18 +3589,6 @@ msgstr ""
msgid "Email address"
msgstr "Email address"
#, c-format
msgid "Email address for %s changed to %s."
msgstr "Email address for %s changed to %s."
#, c-format
msgid "Email address for %s unset."
msgstr "Email address for %s unset."
#, c-format
msgid "Email for %s is invalid."
msgstr "Email for %s is invalid."
#, c-format
msgid "Email matched: %s (%s) to %s."
msgstr "Email matched: %s (%s) to %s."
@@ -3937,12 +3878,12 @@ msgid "Error reloading configuration file: %s"
msgstr "Error reloading configuration file: %s"
#, c-format
msgid "Error! The vhost is too long, please use a hostname shorter than %zu characters."
msgstr "Error! The vhost is too long, please use a hostname shorter than %zu characters."
msgid "Error! The vHost ident is too long, please use an ident shorter than %zu characters."
msgstr "Error! The vHost ident is too long, please use an ident shorter than %zu characters."
#, c-format
msgid "Error! The vident is too long, please use an ident shorter than %zu characters."
msgstr "Error! The vident is too long, please use an ident shorter than %zu characters."
msgid "Error! The vHost is too long, please use a hostname shorter than %zu characters."
msgstr "Error! The vHost is too long, please use a hostname shorter than %zu characters."
msgid ""
"Examples:\n"
@@ -4198,8 +4139,8 @@ msgstr "Invalid hostmask. Only real hostmasks are valid, as exceptions are not m
msgid "Invalid limit %s, using %d."
msgstr "Invalid limit %s, using %d."
msgid "Invalid passcode has been entered, please check the email again, and retry."
msgstr "Invalid passcode has been entered, please check the email again, and retry."
msgid "Invalid passcode has been entered, please check the e-mail again, and retry."
msgstr "Invalid passcode has been entered, please check the e-mail again, and retry."
msgid "Invalid passcode."
msgstr "Invalid passcode."
@@ -4842,9 +4783,6 @@ msgstr "Manage the memo ignore list"
msgid "Manage your auto join list"
msgstr "Manage your auto join list"
msgid "Manages your pending message queue."
msgstr "Manages your pending message queue."
#, c-format
msgid "Manipulate the %s list"
msgstr "Manipulate the %s list"
@@ -4926,10 +4864,6 @@ msgstr "Method"
msgid "Missing parameter for mode %c."
msgstr "Missing parameter for mode %c."
#, c-format
msgid "Missing passwords: %zu"
msgstr "Missing passwords: %zu"
msgid "Mode"
msgstr "Mode"
@@ -5175,9 +5109,6 @@ msgstr "No logon news items to delete!"
msgid "No matches for %s found."
msgstr "No matches for %s found."
msgid "No matching entries in your message queue."
msgstr "No matching entries in your message queue."
#, c-format
msgid "No matching entries on %s %s list."
msgstr "No matching entries on %s %s list."
@@ -5361,13 +5292,6 @@ msgstr "Password incorrect."
msgid "Password reset email for %s has been sent."
msgstr "Password reset email for %s has been sent."
msgid "Passwords can not be changed right now. Please try again later."
msgstr "Passwords can not be changed right now. Please try again later."
#, c-format
msgid "Passwords encrypted with %s: %zu"
msgstr "Passwords encrypted with %s: %zu"
msgid "Peace"
msgstr "Peace"
@@ -5383,11 +5307,11 @@ msgid "Persistent"
msgstr "Persistent"
#, c-format
msgid "Please confirm that you want to drop %s with %s%s DROP %s %s"
msgstr "Please confirm that you want to drop %s with %s%s DROP %s %s"
msgid "Please confirm that you want to drop %s with DROP %s %s"
msgstr "Please confirm that you want to drop %s with DROP %s %s"
msgid "Please contact an Operator to get a vhost assigned to this nick."
msgstr "Please contact an Operator to get a vhost assigned to this nick."
msgid "Please contact an Operator to get a vHost assigned to this nick."
msgstr "Please contact an Operator to get a vHost assigned to this nick."
msgid ""
"Please try again with a more obscure password. Passwords should not be\n"
@@ -5409,8 +5333,8 @@ msgid "Please wait %lu seconds and retry."
msgstr "Please wait %lu seconds and retry."
#, c-format
msgid "Please wait %lu seconds before requesting a new vhost."
msgstr "Please wait %lu seconds before requesting a new vhost."
msgid "Please wait %lu seconds before requesting a new vHost."
msgstr "Please wait %lu seconds before requesting a new vHost."
#, c-format
msgid "Please wait %lu seconds before using the %s command again."
@@ -5695,11 +5619,11 @@ msgstr "Registration is currently disabled."
msgid "Regulate the use of critical commands"
msgstr "Regulate the use of critical commands"
msgid "Reject the requested vhost for the given nick."
msgstr "Reject the requested vhost for the given nick."
msgid "Reject the requested vHost for the given nick."
msgstr "Reject the requested vHost for the given nick."
msgid "Reject the requested vhost of a user"
msgstr "Reject the requested vhost of a user"
msgid "Reject the requested vHost of a user"
msgstr "Reject the requested vHost of a user"
msgid "Releases a suspended channel"
msgstr "Releases a suspended channel"
@@ -5769,15 +5693,15 @@ msgstr "Removing %s because %s covers it."
msgid "Repeat kicker"
msgstr "Repeat kicker"
msgid "Request a vhost for your nick"
msgstr "Request a vhost for your nick"
msgid "Request a vHost for your nick"
msgstr "Request a vHost for your nick"
msgid ""
"Request the given vhost to be activated for your nick by the\n"
"Request the given vHost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
msgstr ""
"Request the given vhost to be activated for your nick by the\n"
"Request the given vHost to be activated for your nick by the\n"
"network administrators. Please be patient while your request\n"
"is being considered."
@@ -5906,9 +5830,6 @@ msgstr "Send a memo to all registered users"
msgid "Send a message to all users"
msgstr "Send a message to all users"
msgid "Send a message to all users on a server"
msgstr "Send a message to all users on a server"
msgid "Sender"
msgstr "Sender"
@@ -5982,10 +5903,6 @@ msgstr ""
msgid "Server"
msgstr "Server"
#, c-format
msgid "Server %s is not linked to the network."
msgstr "Server %s is not linked to the network."
#, c-format
msgid "Server %s added to zone %s."
msgstr "Server %s added to zone %s."
@@ -6050,6 +5967,9 @@ msgstr "Services Operator commands"
msgid "Services are in DefCon mode, please try again later."
msgstr "Services are in DefCon mode, please try again later."
msgid "Services are in read-only mode!"
msgstr "Services are in read-only mode!"
#, c-format
msgid "Services are now at DEFCON %d."
msgstr "Services are now at DEFCON %d."
@@ -6076,9 +5996,6 @@ msgstr "Services are now in read-only mode."
msgid "Services are now in read-write mode."
msgstr "Services are now in read-write mode."
msgid "Services are temporarily in read-only mode."
msgstr "Services are temporarily in read-only mode."
msgid "Services have been configured to not send mail."
msgstr "Services have been configured to not send mail."
@@ -6392,14 +6309,14 @@ msgstr ""
msgid ""
"Sets the vhost for all nicks in the same group as that\n"
"of the given nick. If your IRCD supports vidents, then\n"
"of the given nick. If your IRCD supports vIdents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
"added to the group after this command was used."
msgstr ""
"Sets the vhost for all nicks in the same group as that\n"
"of the given nick. If your IRCD supports vidents, then\n"
"of the given nick. If your IRCD supports vIdents, then\n"
"using SETALL <nick> <ident>@<hostmask> will set idents\n"
"for users as well as vhosts.\n"
"* NOTE, this will not update the vhost for any nicks\n"
@@ -6407,12 +6324,12 @@ msgstr ""
msgid ""
"Sets the vhost for the given nick to that of the given\n"
"hostmask. If your IRCD supports vidents, then using\n"
"hostmask. If your IRCD supports vIdents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
msgstr ""
"Sets the vhost for the given nick to that of the given\n"
"hostmask. If your IRCD supports vidents, then using\n"
"hostmask. If your IRCD supports vIdents, then using\n"
"SET <nick> <ident>@<hostmask> set idents for users as\n"
"well as vhosts."
@@ -6559,14 +6476,59 @@ msgstr "Signed kicks"
msgid "Sorry, %s currently has too many memos and cannot receive more."
msgstr "Sorry, %s currently has too many memos and cannot receive more."
#, c-format
msgid "Sorry, %s is temporarily unavailable."
msgstr "Sorry, %s is temporarily unavailable."
#, c-format
msgid "Sorry, I have not seen %s."
msgstr "Sorry, I have not seen %s."
msgid "Sorry, bad words list modification is temporarily disabled."
msgstr "Sorry, bad words list modification is temporarily disabled."
msgid "Sorry, bot assignment is temporarily disabled."
msgstr "Sorry, bot assignment is temporarily disabled."
msgid "Sorry, bot modification is temporarily disabled."
msgstr "Sorry, bot modification is temporarily disabled."
msgid "Sorry, bot option setting is temporarily disabled."
msgstr "Sorry, bot option setting is temporarily disabled."
msgid "Sorry, changing bot options is temporarily disabled."
msgstr "Sorry, changing bot options is temporarily disabled."
#, c-format
msgid "Sorry, channel %s list modification is temporarily disabled."
msgstr "Sorry, channel %s list modification is temporarily disabled."
msgid "Sorry, channel access list modification is temporarily disabled."
msgstr "Sorry, channel access list modification is temporarily disabled."
msgid "Sorry, channel autokick list modification is temporarily disabled."
msgstr "Sorry, channel autokick list modification is temporarily disabled."
msgid "Sorry, channel de-registration is temporarily disabled."
msgstr "Sorry, channel de-registration is temporarily disabled."
msgid "Sorry, channel registration is temporarily disabled."
msgstr "Sorry, channel registration is temporarily disabled."
msgid "Sorry, kicker configuration is temporarily disabled."
msgstr "Sorry, kicker configuration is temporarily disabled."
msgid "Sorry, memo option setting is temporarily disabled."
msgstr "Sorry, memo option setting is temporarily disabled."
msgid "Sorry, memo sending is temporarily disabled."
msgstr "Sorry, memo sending is temporarily disabled."
msgid "Sorry, nickname de-registration is temporarily disabled."
msgstr "Sorry, nickname de-registration is temporarily disabled."
msgid "Sorry, nickname grouping is temporarily disabled."
msgstr "Sorry, nickname grouping is temporarily disabled."
msgid "Sorry, nickname registration is temporarily disabled."
msgstr "Sorry, nickname registration is temporarily disabled."
#, c-format
msgid "Sorry, the maximum of %d auto join entries has been reached."
msgstr "Sorry, the maximum of %d auto join entries has been reached."
@@ -7197,11 +7159,15 @@ msgstr "The STATS command prints out statistics about stored nicks and memory
msgid ""
"The email parameter is optional and will set the email\n"
"for your nick immediately. You may also wish to SET HIDE it\n"
"for your nick immediately.\n"
"Your privacy is respected; this e-mail won't be given to\n"
"any third-party person. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
msgstr ""
"The email parameter is optional and will set the email\n"
"for your nick immediately. You may also wish to SET HIDE it\n"
"for your nick immediately.\n"
"Your privacy is respected; this e-mail won't be given to\n"
"any third-party person. You may also wish to SET HIDE it\n"
"after registering if it isn't the default setting already."
#, c-format
@@ -7261,6 +7227,14 @@ msgstr "The AKILL list has been cleared."
msgid "The Defcon level is now at: %d"
msgstr "The Defcon level is now at: %d"
#, c-format
msgid "The E-mail address of %s will now be hidden from %s INFO displays."
msgstr "The E-mail address of %s will now be hidden from %s INFO displays."
#, c-format
msgid "The E-mail address of %s will now be shown in %s INFO displays."
msgstr "The E-mail address of %s will now be shown in %s INFO displays."
msgid "The available flags are:"
msgstr "The available flags are:"
@@ -7281,14 +7255,6 @@ msgstr "The email address %s has reached its usage limit of %d users."
msgid "The email address %s has reached its usage limit of 1 user."
msgstr "The email address %s has reached its usage limit of 1 user."
#, c-format
msgid "The email address of %s will now be hidden from %s INFO displays."
msgstr "The email address of %s will now be hidden from %s INFO displays."
#, c-format
msgid "The email address of %s will now be shown in %s INFO displays."
msgstr "The email address of %s will now be shown in %s INFO displays."
#, c-format
msgid "The entry message list for %s is full."
msgstr "The entry message list for %s is full."
@@ -7926,8 +7892,14 @@ msgstr ""
"particular option."
#, c-format
msgid "Type %s%s SET EMAIL email in order to set your email."
msgstr "Type %s%s SET EMAIL email in order to set your email."
msgid ""
"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
"Your privacy is respected; this e-mail won't be given to\n"
"any third-party person."
msgstr ""
"Type %s%s SET EMAIL e-mail in order to set your e-mail.\n"
"Your privacy is respected; this e-mail won't be given to\n"
"any third-party person."
msgid "Un-Load a module"
msgstr "Un-Load a module"
@@ -7994,10 +7966,6 @@ msgstr "Unknown mode character %c ignored."
msgid "Unknown parameter: %s"
msgstr "Unknown parameter: %s"
#, c-format
msgid "Unknown passwords: %zu"
msgstr "Unknown passwords: %zu"
msgid "Unpooled"
msgstr "Unpooled"
@@ -8100,30 +8068,14 @@ msgstr "Users list:"
msgid "VHost"
msgstr "VHost"
#, c-format
msgid "VHost for %s removed."
msgstr "VHost for %s removed."
#, c-format
msgid "VHost for %s set to %s."
msgstr "VHost for %s set to %s."
#, c-format
msgid "VHost for %s has been activated."
msgstr "VHost for %s has been activated."
#, c-format
msgid "VHost for %s has been rejected."
msgstr "VHost for %s has been rejected."
#, c-format
msgid "VHost for group %s set to %s."
msgstr "VHost for group %s set to %s."
#, c-format
msgid "VHosts for group %s have been removed."
msgstr "VHosts for group %s have been removed."
msgid "VIEW host"
msgstr "VIEW host"
@@ -8140,6 +8092,13 @@ msgstr "Value"
msgid "Value of %s:%s changed to %s"
msgstr "Value of %s:%s changed to %s"
msgid "Vhost"
msgstr "Vhost"
#, c-format
msgid "Vhost for %s removed."
msgstr "Vhost for %s removed."
msgid "View and change Services Operators"
msgstr "View and change Services Operators"
@@ -8216,9 +8175,6 @@ msgid ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
"The PASSWORD option displays the encryption algorithms used\n"
"for user passwords.\n"
" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -8236,9 +8192,6 @@ msgstr ""
"The RESET option currently resets the maximum user count\n"
"to the number of users currently present on the network.\n"
" \n"
"The PASSWORD option displays the encryption algorithms used\n"
"for user passwords.\n"
" \n"
"The UPLINK option displays information about the current\n"
"server Anope uses as an uplink to the network.\n"
" \n"
@@ -8301,9 +8254,6 @@ msgstr "You can not jupe an already juped server."
msgid "You can not jupe your services' pseudoserver or your uplink server."
msgstr "You can not jupe your services' pseudoserver or your uplink server."
msgid "You can not queue any more messages."
msgstr "You can not queue any more messages."
#, c-format
msgid "You can not reload this module directly, instead reload %s."
msgstr "You can not reload this module directly, instead reload %s."
@@ -8311,9 +8261,6 @@ msgstr "You can not reload this module directly, instead reload %s."
msgid "You can not request a receipt when sending a memo to yourself."
msgstr "You can not request a receipt when sending a memo to yourself."
msgid "You can not send a single message while you have messages queued."
msgstr "You can not send a single message while you have messages queued."
#, c-format
msgid "You can't %s yourself!"
msgstr "You can't %s yourself!"
@@ -8344,8 +8291,8 @@ msgstr "You cannot set your memo limit higher than %d."
msgid "You cannot unassign bots while persist is set on the channel."
msgstr "You cannot unassign bots while persist is set on the channel."
msgid "You cannot unset the email on this network."
msgstr "You cannot unset the email on this network."
msgid "You cannot unset the e-mail on this network."
msgstr "You cannot unset the e-mail on this network."
msgid "You cannot use this command."
msgstr "You cannot use this command."
@@ -8379,12 +8326,6 @@ msgstr "You currently have no memos."
msgid "You do not have access to set mode %c."
msgstr "You do not have access to set mode %c."
msgid "You do not have any messages queued and did not specify a message to send."
msgstr "You do not have any messages queued and did not specify a message to send."
msgid "You do not have any queued messages."
msgstr "You do not have any queued messages."
#, c-format
msgid "You do not have the access to change %s's modes."
msgstr "You do not have the access to change %s's modes."
@@ -8437,9 +8378,6 @@ msgstr "You have no limit on the number of memos you may keep."
msgid "You have no memos."
msgstr "You have no memos."
msgid "You have no messages queued."
msgstr "You have no messages queued."
msgid "You have no new memos."
msgstr "You have no new memos."
@@ -8458,12 +8396,12 @@ msgstr "You may drop any nick within your group."
msgid "You may not (un)lock mode %c."
msgstr "You may not (un)lock mode %c."
msgid "You may not change the e-mail of other Services Operators."
msgstr "You may not change the e-mail of other Services Operators."
msgid "You may not change the email of an unconfirmed account."
msgstr "You may not change the email of an unconfirmed account."
msgid "You may not change the email of other Services Operators."
msgstr "You may not change the email of other Services Operators."
msgid "You may not change the password of other Services Operators."
msgstr "You may not change the password of other Services Operators."
@@ -8511,12 +8449,12 @@ msgid "You must have the %s(ME) privilege on the channel to use this command."
msgstr "You must have the %s(ME) privilege on the channel to use this command."
msgid ""
"You must now supply an email for your nick.\n"
"This email will allow you to retrieve your password in\n"
"You must now supply an e-mail for your nick.\n"
"This e-mail will allow you to retrieve your password in\n"
"case you forget it."
msgstr ""
"You must now supply an email for your nick.\n"
"This email will allow you to retrieve your password in\n"
"You must now supply an e-mail for your nick.\n"
"This e-mail will allow you to retrieve your password in\n"
"case you forget it."
msgid "You need to be identified to use this command."
@@ -8561,8 +8499,8 @@ msgstr "Your IRCd does not support SVSNICK."
msgid "Your IRCd does not support SVSPART."
msgstr "Your IRCd does not support SVSPART."
msgid "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
msgstr "Your IRCd does not support vidents. If this is incorrect please report this as a possible bug."
msgid "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
msgstr "Your IRCd does not support vIdent's, if this is incorrect, please report this as a possible bug"
#, c-format
msgid "Your account %s has been successfully created."
@@ -8618,12 +8556,6 @@ msgstr "Your memo limit is 0; you will not receive any new memos."
msgid "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
msgstr "Your memo limit is 0; you will not receive any new memos. You cannot change this limit."
msgid "Your message has been queued."
msgstr "Your message has been queued."
msgid "Your message queue has been cleared."
msgstr "Your message queue has been cleared."
msgid "Your nick has been logged out."
msgstr "Your nick has been logged out."
@@ -8658,8 +8590,8 @@ msgstr "Your password is too short. It must be longer than %u characters."
msgid "Your password reset request has expired."
msgstr "Your password reset request has expired."
msgid "Your vhost has been requested."
msgstr "Your vhost has been requested."
msgid "Your vHost has been requested."
msgstr "Your vHost has been requested."
#, c-format
msgid "Your vhost of %s is now activated."
@@ -8728,9 +8660,6 @@ msgstr "[channel] {num | list | LAST | NEW | ALL}"
msgid "[key|#X-Y]"
msgstr "[key|#X-Y]"
msgid "[message]"
msgstr "[message]"
msgid "[nick | channel]"
msgstr "[nick | channel]"
@@ -8761,19 +8690,19 @@ msgstr "[Suspended]"
msgid "[Unconfirmed]"
msgstr "[Unconfirmed]"
#, c-format
msgid "[auto memo] VHost %s has been requested by %s."
msgstr "[auto memo] VHost %s has been requested by %s."
msgid "[auto memo] Your requested vHost has been approved."
msgstr "[auto memo] Your requested vHost has been approved."
msgid "[auto memo] Your requested vhost has been approved."
msgstr "[auto memo] Your requested vhost has been approved."
msgid "[auto memo] Your requested vhost has been rejected."
msgstr "[auto memo] Your requested vhost has been rejected."
msgid "[auto memo] Your requested vHost has been rejected."
msgstr "[auto memo] Your requested vHost has been rejected."
#, c-format
msgid "[auto memo] Your requested vhost has been rejected. Reason: %s"
msgstr "[auto memo] Your requested vhost has been rejected. Reason: %s"
msgid "[auto memo] Your requested vHost has been rejected. Reason: %s"
msgstr "[auto memo] Your requested vHost has been rejected. Reason: %s"
#, c-format
msgid "[auto memo] vHost %s has been requested by %s."
msgstr "[auto memo] vHost %s has been requested by %s."
msgid "[{pattern | channel} [INVISIBLE]]"
msgstr "[{pattern | channel} [INVISIBLE]]"
@@ -8850,9 +8779,21 @@ msgstr "second"
msgid "seconds"
msgstr "seconds"
#, c-format
msgid "vHost for %s has been activated."
msgstr "vHost for %s has been activated."
#, c-format
msgid "vHost for %s has been rejected."
msgstr "vHost for %s has been rejected."
msgid "vhost"
msgstr "vhost"
#, c-format
msgid "vhosts for group %s have been removed."
msgstr "vhosts for group %s have been removed."
msgid "year"
msgstr "year"
+6 -1
View File
@@ -19,13 +19,18 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../conanbuildinfo.cmake")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/extra/${NAME}.cpp" DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}")
endfunction()
enable_extra("enc_argon2" "ARGON2")
enable_extra("mysql" "LIBMYSQLCLIENT")
enable_extra("regex_pcre2" "PCRE2")
enable_extra("sqlite" "SQLITE3")
enable_extra("ssl_openssl" "OPENSSL")
# this uses Wldap so should always be available
copy_extra("ldap")
# these don't actually have extra dependencies, but require a module which does
copy_extra("sql_authentication")
copy_extra("sql_log")
copy_extra("sql_oper")
copy_extra("ldap_authentication")
copy_extra("ldap_oper")
# Package extra dlls
file(GLOB EXTRA_DLLS "${Anope_SOURCE_DIR}/extradll/bin/*.dll" "${Anope_SOURCE_DIR}/extradll/lib/*.dll")
+6 -2
View File
@@ -67,8 +67,12 @@ public:
Anope::string Limit;
unsigned limit = 0;
if (c->GetParam("LIMIT", Limit))
limit = Anope::Convert<unsigned>(Limit, limit);
try
{
if (c->GetParam("LIMIT", Limit))
limit = convertTo<unsigned>(Limit);
}
catch (const ConvertException &) { }
/* Should we be invited? */
if (c->HasMode("INVITE") || (limit && c->users.size() >= limit))
+3 -3
View File
@@ -28,7 +28,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot assignment is temporarily disabled."));
return;
}
@@ -97,7 +97,7 @@ public:
{
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot assignment is temporarily disabled."));
return;
}
@@ -164,7 +164,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot modification is temporarily disabled."));
return;
}
+3 -3
View File
@@ -222,7 +222,7 @@ private:
const BadWord *b = bw->GetBadWord(Number - 1);
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(Number);
entry["Number"] = stringify(Number);
entry["Word"] = b->word;
entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
this->list.AddEntry(entry);
@@ -241,7 +241,7 @@ private:
continue;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Word"] = b->word;
entry["Type"] = b->type == BW_SINGLE ? "(SINGLE)" : (b->type == BW_START ? "(START)" : (b->type == BW_END ? "(END)" : ""));
list.AddEntry(entry);
@@ -407,7 +407,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bad words list modification is temporarily disabled."));
return;
}
+13 -13
View File
@@ -28,21 +28,21 @@ private:
return;
}
if (nick.length() > IRCD->MaxNick)
if (nick.length() > IRCD->GetMaxNick())
{
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->GetMaxNick());
return;
}
if (user.length() > IRCD->MaxUser)
if (user.length() > IRCD->GetMaxUser())
{
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->GetMaxUser());
return;
}
if (host.length() > IRCD->MaxHost)
if (host.length() > IRCD->GetMaxHost())
{
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost);
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->GetMaxHost());
return;
}
@@ -118,21 +118,21 @@ private:
return;
}
if (nick.length() > IRCD->MaxNick)
if (nick.length() > IRCD->GetMaxNick())
{
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->GetMaxNick());
return;
}
if (user.length() > IRCD->MaxUser)
if (user.length() > IRCD->GetMaxUser())
{
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->GetMaxUser());
return;
}
if (host.length() > IRCD->MaxHost)
if (host.length() > IRCD->GetMaxHost())
{
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->GetMaxHost()
);
return;
}
@@ -276,7 +276,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot modification is temporarily disabled."));
return;
}
+1 -1
View File
@@ -55,7 +55,7 @@ public:
info[_("Real name")] = bi->realname;
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
info[_("Used on")] = Anope::ToString(bi->GetChannelCount()) + " channel(s)";
info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
+78 -24
View File
@@ -106,10 +106,11 @@ struct KickerDataImpl final
data["ttb"] >> ttb;
spacesepstream sep(ttb);
for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
{
if (auto n = Anope::TryConvert<int16_t>(tok))
kd->ttb[i] = n.value();
}
try
{
kd->ttb[i] = convertTo<int16_t>(tok);
}
catch (const ConvertException &) { }
kd->Check(ci);
}
@@ -182,7 +183,7 @@ protected:
ci = ChannelInfo::Find(chan);
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, kicker configuration is temporarily disabled."));
else if (ci == NULL)
source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
else if (option.empty())
@@ -205,13 +206,21 @@ protected:
{
if (!ttb.empty())
{
kd->ttb[ttb_idx] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[ttb_idx] < 0)
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
kd->ttb[ttb_idx] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
kd->ttb[ttb_idx] = i;
}
else
kd->ttb[ttb_idx] = 0;
@@ -377,8 +386,13 @@ public:
if (!ttb.empty())
{
kd->ttb[TTB_CAPS] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[TTB_CAPS] < 0)
try
{
kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
if (kd->ttb[TTB_CAPS] < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
kd->ttb[TTB_CAPS] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
@@ -388,11 +402,21 @@ public:
else
kd->ttb[TTB_CAPS] = 0;
kd->capsmin = Anope::Convert(min, 0);
kd->capsmin = 10;
try
{
kd->capsmin = convertTo<int16_t>(min);
}
catch (const ConvertException &) { }
if (kd->capsmin < 1)
kd->capsmin = 10;
kd->capspercent = Anope::Convert(percent, 0);
kd->capspercent = 25;
try
{
kd->capspercent = convertTo<int16_t>(percent);
}
catch (const ConvertException &) { }
if (kd->capspercent < 1 || kd->capspercent > 100)
kd->capspercent = 25;
@@ -494,25 +518,42 @@ public:
if (!ttb.empty())
{
kd->ttb[TTB_FLOOD] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[TTB_FLOOD] < 0)
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
kd->ttb[TTB_FLOOD] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
kd->ttb[TTB_FLOOD] = i;
}
else
kd->ttb[TTB_FLOOD] = 0;
kd->floodlines = Anope::Convert(lines, -1);
kd->floodlines = 6;
try
{
kd->floodlines = convertTo<int16_t>(lines);
}
catch (const ConvertException &) { }
if (kd->floodlines < 2)
kd->floodlines = 6;
kd->floodsecs = Anope::Convert(secs, -1);
kd->floodsecs = 10;
try
{
kd->floodsecs = convertTo<int16_t>(secs);
}
catch (const ConvertException &) { }
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");
@@ -610,18 +651,31 @@ public:
if (!ttb.empty())
{
kd->ttb[TTB_REPEAT] = Anope::Convert(ttb, -1);
if (kd->ttb[TTB_REPEAT] < 0)
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
kd->ttb[TTB_REPEAT] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
return;
}
kd->ttb[TTB_REPEAT] = i;
}
else
kd->ttb[TTB_REPEAT] = 0;
kd->repeattimes = Anope::Convert<int16_t>(times, -1);
kd->repeattimes = 3;
try
{
kd->repeattimes = convertTo<int16_t>(times);
}
catch (const ConvertException &) { }
if (kd->repeattimes < 1)
kd->repeattimes = 3;
@@ -772,7 +826,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
return;
}
@@ -838,7 +892,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
return;
}
+1 -1
View File
@@ -118,7 +118,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, changing bot options is temporarily disabled."));
return;
}
+1 -1
View File
@@ -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", "15s"))
, ChanServ(cs)
, inhabit(i)
, c(chan)
+23 -14
View File
@@ -37,13 +37,18 @@ public:
Anope::string AccessSerialize() const override
{
return Anope::ToString(this->level);
return stringify(this->level);
}
void AccessUnserialize(const Anope::string &data) override
{
if (auto l = Anope::TryConvert<int>(data))
this->level = l.value();
try
{
this->level = convertTo<int>(data);
}
catch (const ConvertException &)
{
}
}
bool operator>(const ChanAccess &other) const override
@@ -90,9 +95,11 @@ class CommandCSAccess final
Privilege *p = NULL;
int level = ACCESS_INVALID;
if (auto lvl = Anope::TryConvert<int>(params[3]))
level = lvl.value();
else
try
{
level = convertTo<int>(params[3]);
}
catch (const ConvertException &)
{
p = PrivilegeManager::FindPrivilege(params[3]);
if (p != NULL && defaultLevels[p->name])
@@ -200,7 +207,7 @@ class CommandCSAccess final
}
}
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
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);
@@ -395,7 +402,7 @@ class CommandCSAccess final
}
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(number);
entry["Number"] = stringify(number);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
@@ -435,7 +442,7 @@ class CommandCSAccess final
}
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
@@ -560,7 +567,7 @@ public:
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
else if (cmd.equals_ci("ADD"))
this->DoAdd(source, ci, params);
else if (cmd.equals_ci("DEL"))
@@ -645,9 +652,11 @@ class CommandCSLevels final
level = ACCESS_FOUNDER;
else
{
if (auto lvl = Anope::TryConvert<int>(lev))
level = lvl.value();
else
try
{
level = convertTo<int>(lev);
}
catch (const ConvertException &)
{
this->OnSyntaxError(source, "SET");
return;
@@ -725,7 +734,7 @@ class CommandCSLevels final
else if (j == ACCESS_FOUNDER)
entry["Level"] = Language::Translate(source.GetAccount(), _("(founder only)"));
else
entry["Level"] = Anope::ToString(j);
entry["Level"] = stringify(j);
list.AddEntry(entry);
}
+3 -3
View File
@@ -311,7 +311,7 @@ class CommandCSAKick final
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(number);
entry["Number"] = stringify(number);
if (akick->nc)
entry["Mask"] = akick->nc->display;
else
@@ -351,7 +351,7 @@ class CommandCSAKick final
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
if (akick->nc)
entry["Mask"] = akick->nc->display;
else
@@ -466,7 +466,7 @@ public:
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (!cmd.equals_ci("LIST") && !cmd.equals_ci("VIEW") && !cmd.equals_ci("ENFORCE") && Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel autokick list modification is temporarily disabled."));
else if (cmd.equals_ci("ADD"))
this->DoAdd(source, ci, params);
else if (cmd.equals_ci("DEL"))
+1 -1
View File
@@ -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", "1024");
unsigned count = 0;
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
+5 -5
View File
@@ -20,7 +20,7 @@ private:
public:
CommandCSDrop(Module *creator)
: Command(creator, "chanserv/drop", 1, 2)
, dropcode(creator, "channel-dropcode")
, dropcode(creator, "dropcode")
{
this->SetDesc(_("Cancel the registration of a channel"));
this->SetSyntax(_("\037channel\037 [\037code\037]"));
@@ -32,7 +32,7 @@ public:
if (Anope::ReadOnly && !source.HasPriv("chanserv/administration"))
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel de-registration is temporarily disabled.")); // XXX: READ_ONLY_MODE?
return;
}
@@ -54,12 +54,12 @@ public:
{
if (!code)
{
code = ci->Extend<Anope::string>("channel-dropcode");
code = ci->Extend<Anope::string>("dropcode");
*code = Anope::Random(15);
}
source.Reply(CONFIRM_DROP, ci->name.c_str(), Config->StrictPrivmsg.c_str(),
source.service->nick.c_str(), ci->name.c_str(), code->c_str());
source.Reply(_("Please confirm that you want to drop \002%s\002 with \002DROP %s %s\002"),
chan.c_str(), chan.c_str(), code->c_str());
return;
}
+8 -2
View File
@@ -166,8 +166,14 @@ private:
return;
}
auto l = Anope::Convert<int>(l_str, -1);
if (l < 0)
int l;
try
{
l = convertTo<int>(l_str);
if (l < 0)
throw ConvertException();
}
catch (const ConvertException &)
{
source.Reply(_("The limit on %s is not valid."), ci->name.c_str());
return;
+14 -9
View File
@@ -123,7 +123,7 @@ private:
EntryMsg *msg = (*messages)->at(i);
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Creator"] = msg->creator;
entry["Created"] = Anope::strftime(msg->when, NULL, true);
entry["Message"] = msg->message;
@@ -162,16 +162,21 @@ private:
source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str());
else
{
auto i = Anope::Convert<unsigned>(message, 0);
if (i > 0 && i <= (*messages)->size())
try
{
delete (*messages)->at(i - 1);
if ((*messages)->empty())
ci->Shrink<EntryMessageList>("entrymsg");
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
unsigned i = convertTo<unsigned>(message);
if (i > 0 && i <= (*messages)->size())
{
delete (*messages)->at(i - 1);
if ((*messages)->empty())
ci->Shrink<EntryMessageList>("entrymsg");
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to remove a message";
source.Reply(_("Entry message \002%i\002 for \002%s\002 deleted."), i, ci->name.c_str());
}
else
throw ConvertException();
}
else
catch (const ConvertException &)
{
source.Reply(_("Entry message \002%s\002 not found on channel \002%s\002."), message.c_str(), ci->name.c_str());
}
+3 -3
View File
@@ -175,7 +175,7 @@ class CommandCSFlags final
}
}
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
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);
@@ -331,7 +331,7 @@ class CommandCSFlags final
ListFormatter::ListEntry entry;
++count;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Mask"] = access->Mask();
entry["Flags"] = flags;
entry["Creator"] = access->creator;
@@ -411,7 +411,7 @@ public:
if (!has_access)
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
else if (is_list)
this->DoList(source, ci, params);
else if (cmd.equals_ci("CLEAR"))
+1 -1
View File
@@ -58,7 +58,7 @@ public:
if (show_all)
{
info[_("Ban type")] = Anope::ToString(ci->bantype);
info[_("Ban type")] = stringify(ci->bantype);
}
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
+6 -6
View File
@@ -36,10 +36,12 @@ public:
sepstream(pattern.substr(1), '-').GetToken(n1, 0);
sepstream(pattern, '-').GetToken(n2, 1);
auto num1 = Anope::TryConvert<int>(n1);
auto num2 = Anope::TryConvert<int>(n2);
if (!num1.has_value() || !num2.has_value())
try
{
from = convertTo<int>(n1);
to = convertTo<int>(n2);
}
catch (const ConvertException &)
{
source.Reply(LIST_INCORRECT_RANGE);
source.Reply(_("To search for channels starting with #, search for the channel\n"
@@ -47,8 +49,6 @@ public:
return;
}
from = num1.value();
to = num2.value();
pattern = "*";
}
+1 -1
View File
@@ -135,7 +135,7 @@ public:
const LogSetting *log = (*ls)->at(i);
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Service"] = log->command_service;
entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name;
entry["Method"] = log->method;
+2 -2
View File
@@ -336,7 +336,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", "32"))
{
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
continue;
@@ -716,7 +716,7 @@ class CommandCSMode final
std::vector<Anope::string> new_params;
new_params.push_back(params[0]);
new_params.emplace_back("SET");
new_params.push_back("-" + Anope::ToString(cm->mchar));
new_params.push_back("-" + stringify(cm->mchar));
new_params.emplace_back("*");
this->DoSet(source, ci, new_params);
}
+1 -1
View File
@@ -33,7 +33,7 @@ public:
ChannelInfo *ci = ChannelInfo::Find(params[0]);
if (Anope::ReadOnly)
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel registration is temporarily disabled."));
else if (nc->HasExt("UNCONFIRMED"))
source.Reply(_("You must confirm your account before you can register a channel."));
else if (chan[0] == '&')
+3 -3
View File
@@ -19,7 +19,7 @@ enum TypeInfo
static bool simple;
struct SeenInfo;
static SeenInfo *FindInfo(const Anope::string &nick);
typedef Anope::unordered_map<SeenInfo *> database_map;
typedef Anope::hash_map<SeenInfo *> database_map;
database_map database;
struct SeenInfo final
@@ -270,9 +270,9 @@ public:
if (simple)
return this->SimpleSeen(source, params);
if (target.length() > IRCD->MaxNick)
if (target.length() > IRCD->GetMaxNick())
{
source.Reply(_("Nick too long, max length is %zu characters."), IRCD->MaxNick);
source.Reply(_("Nick too long, max length is %zu characters."), IRCD->GetMaxNick());
return;
}
+10 -7
View File
@@ -165,16 +165,19 @@ public:
return;
}
auto new_type = Anope::Convert<int16_t>(params[1], -1);
if (new_type < 0 || new_type > 3)
try
{
int16_t new_type = convertTo<int16_t>(params[1]);
if (new_type < 0 || new_type > 3)
throw ConvertException("Invalid range");
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type;
ci->bantype = new_type;
source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype);
}
catch (const ConvertException &)
{
source.Reply(_("\002%s\002 is not a valid ban type."), params[1].c_str());
return;
}
Log(source.AccessFor(ci).HasPriv("SET") ? LOG_COMMAND : LOG_OVERRIDE, source, this, ci) << "to change the ban type to " << new_type;
ci->bantype = new_type;
source.Reply(_("Ban type for channel %s is now #%d."), ci->name.c_str(), ci->bantype);
}
bool OnHelp(CommandSource &source, const Anope::string &) override
+8 -20
View File
@@ -214,13 +214,6 @@ class CSSuspend final
}
};
void Expire(ChannelInfo *ci)
{
suspend.Unset(ci);
Log(this) << "Expiring suspend for " << ci->name;
}
bool Show(CommandSource &source, const Anope::string &what) const
{
return source.IsOper() || std::find(show.begin(), show.end(), what) != show.end();
@@ -266,28 +259,23 @@ public:
expire = false;
if (!Anope::NoExpire && si->expires && si->expires < Anope::CurTime)
if (!si->expires)
return;
if (si->expires < Anope::CurTime)
{
ci->last_used = Anope::CurTime;
Expire(ci);
suspend.Unset(ci);
Log(this) << "Expiring suspend for " << ci->name;
}
}
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (u->HasMode("OPER") || !c->ci)
if (u->HasMode("OPER") || !c->ci || !suspend.HasExt(c->ci))
return EVENT_CONTINUE;
CSSuspendInfo *si = suspend.Get(c->ci);
if (!si)
return EVENT_CONTINUE;
if (!Anope::NoExpire && si->expires && si->expires < Anope::CurTime)
{
Expire(c->ci);
return EVENT_CONTINUE;
}
reason = Language::Translate(u, _("This channel may not be used."));
return EVENT_STOP;
}
+6 -6
View File
@@ -116,7 +116,7 @@ private:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
return;
}
@@ -208,7 +208,7 @@ private:
}
}
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
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);
@@ -246,7 +246,7 @@ private:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
return;
}
@@ -420,7 +420,7 @@ private:
return;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(Number);
entry["Number"] = stringify(Number);
entry["Mask"] = a->Mask();
entry["Description"] = a->description;
this->list.AddEntry(entry);
@@ -440,7 +440,7 @@ private:
continue;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Number"] = stringify(i + 1);
entry["Mask"] = a->Mask();
entry["Description"] = a->description;
list.AddEntry(entry);
@@ -464,7 +464,7 @@ private:
{
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
return;
}
File diff suppressed because it is too large Load Diff
+14 -9
View File
@@ -52,7 +52,12 @@ public:
{
if (token.find("ID ") == 0)
{
this->id = Anope::Convert(token.substr(3), 0);
try
{
this->id = convertTo<unsigned int>(token.substr(3));
}
catch (const ConvertException &) { }
continue;
}
else if (token.find("DATA ") != 0)
@@ -130,8 +135,8 @@ class DBFlatFile final
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 Anope::string &oldname = Anope::DataDir + "/" + db;
Anope::string newname = Anope::DataDir + "/backups/" + db + "-" + stringify(tm->tm_year + 1900) + Anope::printf("-%02i-", tm->tm_mon + 1) + Anope::printf("%02i", tm->tm_mday);
/* Backup already exists or no database to backup */
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
@@ -216,7 +221,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 Anope::string &db_name = Anope::DataDir + "/" + 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())
@@ -296,9 +301,9 @@ public:
Anope::string db_name;
if (s_type->GetOwner())
db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
else
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
db_name = Anope::DataDir + "/" + 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);
@@ -325,7 +330,7 @@ public:
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 Anope::string &db_name = Anope::DataDir + "/" + (mod ? (mod->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
if (!f->is_open() || !f->good())
{
@@ -367,9 +372,9 @@ public:
Anope::string db_name;
if (stype->GetOwner())
db_name = Anope::ExpandData("module_" + stype->GetOwner()->name + ".db");
db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
else
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
db_name = Anope::DataDir + "/" + 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())
+6 -6
View File
@@ -40,7 +40,7 @@ else \
#define OLD_NI_MEMO_SIGNON 0x00000010 /* Notify of memos at signon and un-away */
#define OLD_NI_MEMO_RECEIVE 0x00000020 /* Notify of new memos when sent */
#define OLD_NI_PRIVATE 0x00000040 /* Don't show in LIST to non-servadmins */
#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show email in INFO */
#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show E-mail in INFO */
#define OLD_NI_HIDE_MASK 0x00000100 /* Don't show last seen address in INFO */
#define OLD_NI_HIDE_QUIT 0x00000200 /* Don't show last quit message in INFO */
#define OLD_NI_KILL_QUICK 0x00000400 /* Kill in 20 seconds instead of 60 */
@@ -152,7 +152,7 @@ static void process_mlock(ChannelInfo *ci, uint32_t lock, bool status, uint32_t
if (cm && ml)
{
if (limit && mlock_info.c == 'l')
ml->SetMLock(cm, status, Anope::ToString(*limit));
ml->SetMLock(cm, status, stringify(*limit));
else if (key && mlock_info.c == 'k')
ml->SetMLock(cm, status, *key);
else
@@ -205,7 +205,7 @@ static Anope::string Hex(const char *data, size_t l)
{
const char hextable[] = "0123456789abcdef";
Anope::string rv;
std::string rv;
for (size_t i = 0; i < l; ++i)
{
unsigned char c = data[i];
@@ -321,7 +321,7 @@ static dbFILE *open_db_read(const char *service, const char *filename, int versi
int myversion;
f = new dbFILE;
strscpy(f->filename, Anope::ExpandData(filename).c_str(), sizeof(f->filename));
strscpy(f->filename, (Anope::DataDir + "/" + filename).c_str(), sizeof(f->filename));
f->mode = 'r';
fp = fopen(f->filename, "rb");
if (!fp)
@@ -690,7 +690,7 @@ static void LoadVHosts()
continue;
}
na->SetVHost(ident, host, creator, vtime);
na->SetVhost(ident, host, creator, vtime);
Log() << "Loaded vhost for " << na->nick;
}
@@ -889,7 +889,7 @@ static void LoadChannels()
}
}
else
access->AccessUnserialize(Anope::ToString(level));
access->AccessUnserialize(stringify(level));
}
Anope::string mask;
+30 -20
View File
@@ -162,7 +162,7 @@ public:
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
/* Get object attrs to clear before updating */
redis->SendCommand(new Updater(this, t->GetName(), obj->id), args);
@@ -248,7 +248,7 @@ public:
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
/* Get all of the attributes for this object */
redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args);
@@ -278,14 +278,19 @@ void TypeLoader::OnResult(const Reply &r)
if (reply->type != Reply::BULK)
continue;
auto i = Anope::TryConvert<int64_t>(reply->bulk);
if (!i)
int64_t id;
try
{
id = convertTo<int64_t>(reply->bulk);
}
catch (const ConvertException &)
{
continue;
}
auto id = i.value();
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + this->type + ":" + Anope::ToString(id));
args.push_back("hash:" + this->type + ":" + stringify(id));
me->redis->SendCommand(new ObjectLoader(me, this->type, id), args);
}
@@ -359,7 +364,7 @@ void Deleter::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("DEL");
args.push_back("hash:" + this->type + ":" + Anope::ToString(this->id));
args.push_back("hash:" + this->type + ":" + stringify(this->id));
/* Delete hash object */
me->redis->SendCommand(NULL, args);
@@ -367,7 +372,7 @@ void Deleter::OnResult(const Reply &r)
args.clear();
args.emplace_back("SREM");
args.push_back("ids:" + this->type);
args.push_back(Anope::ToString(this->id));
args.push_back(stringify(this->id));
/* Delete id from ids set */
me->redis->SendCommand(NULL, args);
@@ -380,7 +385,7 @@ void Deleter::OnResult(const Reply &r)
args.clear();
args.emplace_back("SREM");
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
args.push_back(Anope::ToString(this->id));
args.push_back(stringify(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -423,7 +428,7 @@ void Updater::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SREM");
args.push_back("value:" + this->type + ":" + key->bulk + ":" + value->bulk);
args.push_back(Anope::ToString(this->id));
args.push_back(stringify(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -433,12 +438,12 @@ void Updater::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SADD");
args.push_back("ids:" + this->type);
args.push_back(Anope::ToString(obj->id));
args.push_back(stringify(obj->id));
me->redis->SendCommand(NULL, args);
args.clear();
args.emplace_back("HMSET");
args.push_back("hash:" + this->type + ":" + Anope::ToString(obj->id));
args.push_back("hash:" + this->type + ":" + stringify(obj->id));
for (const auto &[key, value] : data.data)
{
@@ -449,7 +454,7 @@ void Updater::OnResult(const Reply &r)
args2.emplace_back("SADD");
args2.push_back("value:" + this->type + ":" + key + ":" + value->str());
args2.push_back(Anope::ToString(obj->id));
args2.push_back(stringify(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args2);
@@ -500,11 +505,16 @@ void SubscriptionListener::OnResult(const Reply &r)
if (s_type == NULL)
return;
auto oid = Anope::TryConvert<uint64_t>(id);
if (!oid.has_value())
uint64_t obj_id;
try
{
obj_id = convertTo<uint64_t>(id);
}
catch (const ConvertException &)
{
return;
}
auto obj_id = oid.value();
if (op == "hset" || op == "hdel")
{
Serializable *s = s_type->objects[obj_id];
@@ -554,7 +564,7 @@ void SubscriptionListener::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SREM");
args.push_back("ids:" + type);
args.push_back(Anope::ToString(s->id));
args.push_back(stringify(s->id));
/* Delete object from id set */
me->redis->SendCommand(NULL, args);
@@ -594,7 +604,7 @@ void ModifiedObject::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SREM");
args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
args.push_back(Anope::ToString(this->id));
args.push_back(stringify(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -623,7 +633,7 @@ void ModifiedObject::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SADD");
args.push_back("value:" + st->GetName() + ":" + key + ":" + value->str());
args.push_back(Anope::ToString(obj->id));
args.push_back(stringify(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args);
@@ -632,7 +642,7 @@ void ModifiedObject::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SADD");
args.push_back("ids:" + st->GetName());
args.push_back(Anope::ToString(obj->id));
args.push_back(stringify(obj->id));
/* Add to type -> id set */
me->redis->SendCommand(NULL, args);
+11 -7
View File
@@ -209,7 +209,7 @@ public:
return;
Serialize::Type *s_type = obj->GetSerializableType();
if (s_type && obj->id > 0)
this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
this->updated_items.erase(obj);
}
@@ -240,14 +240,18 @@ public:
data[key] << value;
Serializable *obj = sb->Unserialize(NULL, data);
try
{
if (obj)
obj->id = convertTo<unsigned int>(res.Get(j, "id"));
}
catch (const ConvertException &)
{
Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
}
if (obj)
{
auto oid = Anope::TryConvert<unsigned int>(res.Get(j, "id"));
if (oid.has_value())
obj->id = oid.value();
else
Log(this) << "Unable to convert id for object #" << j << " of type " << sb->GetName();
/* The Unserialize operation is destructive so rebuild the data for UpdateCache.
* Also the old data may contain columns that we don't use, so we reserialize the
* object to know for sure our cache is consistent
+8 -7
View File
@@ -163,7 +163,7 @@ public:
if (s_type)
{
if (obj->id > 0)
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
s_type->objects.erase(obj->id);
}
this->updated_items.erase(obj);
@@ -185,16 +185,17 @@ public:
{
const std::map<Anope::string, Anope::string> &row = res.Row(i);
auto oid = Anope::TryConvert<unsigned int>(res.Get(i, "id"));
if (!oid.has_value())
unsigned int id;
try
{
id = convertTo<unsigned int>(res.Get(i, "id"));
}
catch (const ConvertException &)
{
Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName();
continue;
}
auto id = oid.value();
if (res.Get(i, "timestamp").empty())
{
clear_null = true;
@@ -236,7 +237,7 @@ public:
else
{
if (!s)
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
else
delete s;
}
+1 -1
View File
@@ -679,7 +679,7 @@ public:
: Manager(creator)
, Timer(300, true)
, serial(Anope::CurTime)
, cur_id(Anope::RandomNumber())
, cur_id(rand())
{
}
+70 -116
View File
@@ -8,154 +8,100 @@
*
*/
#include <climits>
#include <random>
#include "bcrypt/crypt_blowfish.c"
#include "module.h"
#include "modules/encryption.h"
class BCryptContext final
: public Encryption::Context
{
private:
Anope::string buffer;
#include "bcrypt/crypt_blowfish.c"
Anope::string GenerateSalt()
class EBCRYPT final
: public Module
{
unsigned int rounds;
Anope::string Salt()
{
static std::random_device device;
static std::mt19937 engine(device());
static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
char entropy[16];
for (size_t i = 0; i < sizeof(entropy); ++i)
entropy[i] = static_cast<char>(dist(engine));
for (auto &chr : entropy)
chr = static_cast<char>(rand() % 0xFF);
char salt[32];
if (!_crypt_gensalt_blowfish_rn("$2a$", rounds, entropy, sizeof(entropy), salt, sizeof(salt)))
{
Log(LOG_DEBUG) << "Unable to generate a salt for Bcrypt: " << strerror(errno);
return {};
}
return "";
return salt;
}
public:
static unsigned long rounds;
static Anope::string Hash(const Anope::string &data, const Anope::string &salt)
static Anope::string Generate(const Anope::string &data, const Anope::string &salt)
{
char hash[64];
if (!_crypt_blowfish_rn(data.c_str(), salt.c_str(), hash, sizeof(hash)))
{
Log(LOG_DEBUG) << "Unable to generate a hash for Bcrypt: " << strerror(errno);
return {};
}
_crypt_blowfish_rn(data.c_str(), salt.c_str(), hash, sizeof(hash));
return hash;
}
void Update(const unsigned char *data, size_t len) override
bool Compare(const Anope::string &string, const Anope::string &hash)
{
buffer.append(reinterpret_cast<const char *>(data), len);
Anope::string ret = Generate(string, hash);
if (ret.empty())
return false;
return (ret == hash);
}
Anope::string Finalize() override
{
auto salt = GenerateSalt();
if (salt.empty())
return {};
return Hash(this->buffer, salt);
}
};
unsigned long BCryptContext::rounds = 10;
class BCryptProvider final
: public Encryption::Provider
{
public:
BCryptProvider(Module *creator)
: Encryption::Provider(creator, "bcrypt", 0, 0)
{
}
bool Compare(const Anope::string &hash, const Anope::string &plain) override
{
auto newhash = BCryptContext::Hash(plain, hash);
return !newhash.empty() && hash.equals_cs(newhash);
}
std::unique_ptr<Encryption::Context> CreateContext() override
{
return std::make_unique<BCryptContext>();
}
Anope::string ToPrintable(const Anope::string &hash) override
{
// The crypt_blowfish library does not expose a raw form.
return hash;
}
};
class EBCrypt final
: public Module
{
private:
BCryptProvider bcryptprovider;
public:
EBCrypt(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, bcryptprovider(this)
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
rounds(10)
{
bcryptprovider.Check({
{ "$2a$10$c9lUAuJmTYXEfNuLOiyIp.lZTMM.Rw5qsSAyZhvGT9EC3JevkUuOu", "" },
{ "$2a$10$YV4jDSGs0ZtQbpL6IHtNO.lt5Q.uzghIohCcnERQVBGyw7QJMfyhe", "The quick brown fox jumps over the lazy dog" },
});
// Test a pre-calculated hash
bool test = Compare("Test!", "$2a$10$x9AQFAQScY0v9KF2suqkEOepsHFrG.CXHbIXI.1F28SfSUb56A/7K");
Anope::string salt;
Anope::string hash;
// Make sure it's working
if (!test || (salt = Salt()).empty() || (hash = Generate("Test!", salt)).empty() || !Compare("Test!", hash))
throw ModuleException("BCrypt could not load!");
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
dest = "bcrypt:" + bcryptprovider.Encrypt(src);
dest = "bcrypt:" + Generate(src, Salt());
Log(LOG_DEBUG_2) << "(enc_bcrypt) hashed password from [" << src << "] to [" << dest << "]";
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("bcrypt"))
if (hash_method != "bcrypt")
return;
Anope::string hash_value(nc->pass.begin() + pos + 1, nc->pass.end());
if (bcryptprovider.Compare(hash_value, req->GetPassword()))
if (Compare(req->GetPassword(), nc->pass.substr(7)))
{
unsigned long rounds = 0;
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
// Try to extract the rounds count to check if we need to
// re-encrypt the password.
pos = hash_value.find('$', 4);
if (pos != Anope::string::npos)
rounds = Anope::Convert<unsigned long>(hash_value.substr(4, pos - 4), 0);
unsigned int hashrounds = 0;
try
{
size_t roundspos = nc->pass.find('$', 11);
if (roundspos == Anope::string::npos)
throw ConvertException("Could not find hashrounds");
if (!rounds)
Log(LOG_DEBUG) << "Unable to determine the rounds of a bcrypt hash: " << hash_value;
hashrounds = convertTo<unsigned int>(nc->pass.substr(11, roundspos - 11));
}
catch (const ConvertException &)
{
Log(this) << "Could not get the round size of a hash. This is probably a bug. Hash: " << nc->pass;
}
// If we are NOT the first encryption module or the Bcrypt rounds
// are different we want to re-encrypt the password with the primary
// encryption method.
if (ModuleManager::FindFirstOf(ENCRYPTION) != this || (rounds && rounds != BCryptContext::rounds))
if (ModuleManager::FindFirstOf(ENCRYPTION) != this || (hashrounds && hashrounds != rounds))
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
@@ -163,20 +109,28 @@ public:
void OnReload(Configuration::Conf *conf) override
{
auto *block = conf->GetModule(this);
Configuration::Block *block = conf->GetModule(this);
rounds = block->Get<unsigned int>("rounds", "10");
auto rounds = block->Get<unsigned long>("rounds", "10");
if (rounds < 10 || rounds > 32)
if (rounds == 0)
{
Log(this) << "Bcrypt rounds MUST be between 10 and 32 inclusive; using 10 instead of " << rounds << '.';
BCryptContext::rounds = 10;
return;
rounds = 10;
Log(this) << "Rounds can't be 0! Setting ignored.";
}
else if (rounds < 10)
{
Log(this) << "10 to 12 rounds is recommended.";
}
else if (rounds >= 32)
{
rounds = 10;
Log(this) << "The maximum number of rounds supported is 31. Ignoring setting and using 10.";
}
else if (rounds >= 14)
{
Log(this) << "Are you sure you want to use " << stringify(rounds) << " in your bcrypt settings? This is very CPU intensive! Recommended rounds is 10-12.";
}
if (rounds > 14)
Log(this) << "Bcrypt rounds higher than 14 are very CPU intensive; are you sure you want to use " << rounds << '?';
BCryptContext::rounds = rounds;
}
};
MODULE_INIT(EBCrypt)
MODULE_INIT(EBCRYPT)
+337 -29
View File
@@ -5,7 +5,7 @@
* Contact us at team@anope.org
*
* Taken from IRC Services and is copyright (c) 1996-2002 Andrew Church.
* Email: <achurch@achurch.org>
* E-mail: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
@@ -14,73 +14,381 @@
#include "module.h"
#include "modules/encryption.h"
#include "md5/md5.c"
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
inline static unsigned F(unsigned x, unsigned y, unsigned z) { return (x & y) | (~x & z); }
inline static unsigned G(unsigned x, unsigned y, unsigned z) { return (x & z) | (y & ~z); }
inline static unsigned H(unsigned x, unsigned y, unsigned z) { return x ^ y ^ z; }
inline static unsigned I(unsigned x, unsigned y, unsigned z) { return y ^ (x | ~z); }
/* ROTATE_LEFT rotates x left n bits.
*/
inline static unsigned ROTATE_LEFT(unsigned x, unsigned n) { return (x << n) | (x >> (32 - n)); }
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
* Rotation is separate from addition to prevent recomputation.
*/
inline static void FF(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
{
a += F(b, c, d) + x + ac;
a = ROTATE_LEFT(a, s);
a += b;
}
inline static void GG(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
{
a += G(b, c, d) + x + ac;
a = ROTATE_LEFT(a, s);
a += b;
}
inline static void HH(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
{
a += H(b, c, d) + x + ac;
a = ROTATE_LEFT(a, s);
a += b;
}
inline static void II(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac)
{
a += I(b, c, d) + x + ac;
a = ROTATE_LEFT(a, s);
a += b;
}
static const uint32_t md5_iv[4] =
{
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
};
class MD5Context final
: public Encryption::Context
{
private:
MD5_CTX context;
unsigned state[4]; /* state (ABCD) */
unsigned count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
unsigned char digest[16]; /* final digest */
/* Constants for MD5Transform routine.
*/
enum
{
S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22,
S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20,
S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23,
S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21
};
/* MD5 basic transformation. Transforms state based on block.
*/
void Transform(const unsigned char block[64])
{
unsigned a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode(x, block, 64);
/* Round 1 */
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof(x));
}
/* Encodes input (unsigned) into output (unsigned char). Assumes len is
* a multiple of 4.
*/
static void Encode(unsigned char *output, unsigned *input, unsigned len)
{
for (unsigned i = 0, j = 0; j < len; ++i, j += 4)
{
output[j] = static_cast<unsigned char>(input[i] & 0xff);
output[j + 1] = static_cast<unsigned char>((input[i] >> 8) & 0xff);
output[j + 2] = static_cast<unsigned char>((input[i] >> 16) & 0xff);
output[j + 3] = static_cast<unsigned char>((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (unsigned). Assumes len is
* a multiple of 4.
*/
static void Decode(unsigned *output, const unsigned char *input, unsigned len)
{
for (unsigned i = 0, j = 0; j < len; ++i, j += 4)
output[i] = static_cast<unsigned>(input[j]) | (static_cast<unsigned>(input[j + 1]) << 8) | (static_cast<unsigned>(input[j + 2]) << 16) | (static_cast<unsigned>(input[j + 3]) << 24);
}
public:
MD5Context()
MD5Context(Encryption::IV *iv = NULL)
{
MD5_Init(&context);
if (iv != NULL)
{
if (iv->second != 4)
throw CoreException("Invalid IV size");
/* Load magic initialization constants. */
for (int i = 0; i < 4; ++i)
this->state[i] = iv->first[i];
}
else
for (int i = 0; i < 4; ++i)
this->state[i] = md5_iv[i];
this->count[0] = this->count[1] = 0;
memset(this->buffer, 0, sizeof(this->buffer));
}
/* MD5 block update operation. Continues an MD5 message-digest
* operation, processing another message block, and updating the
* context.
*/
void Update(const unsigned char *input, size_t len) override
{
MD5_Update(&context, input, len);
unsigned i, index, partLen;
/* Compute number of bytes mod 64 */
index = (this->count[0] >> 3) & 0x3F;
/* Update number of bits */
if ((this->count[0] += len << 3) < (len << 3))
++this->count[1];
this->count[1] += len >> 29;
partLen = 64 - index;
/* Transform as many times as possible. */
if (len >= partLen)
{
memcpy(&this->buffer[index], input, partLen);
this->Transform(this->buffer);
for (i = partLen; i + 63 < len; i += 64)
this->Transform(&input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy(&this->buffer[index], &input[i], len - i);
}
Anope::string Finalize() override
/* MD5 finalization. Ends an MD5 message-digest opera
* the message digest and zeroizing the context.
*/
void Finalize() override
{
unsigned char digest[16];
MD5_Final(digest, &context);
return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
unsigned char bits[8];
unsigned index, padLen;
/* Save number of bits */
this->Encode(bits, this->count, 8);
/* Pad out to 56 mod 64. */
index = (this->count[0] >> 3) & 0x3f;
padLen = index < 56 ? 56 - index : 120 - index;
this->Update(PADDING, padLen);
/* Append length (before padding) */
this->Update(bits, 8);
/* Store state in digest */
this->Encode(digest, this->state, 16);
/* Zeroize sensitive information. */
memset(this->state, 0, sizeof(this->state));
memset(this->count, 0, sizeof(this->count));
memset(this->buffer, 0, sizeof(this->buffer));
}
Encryption::Hash GetFinalizedHash() override
{
Encryption::Hash hash;
hash.first = this->digest;
hash.second = sizeof(this->digest);
return hash;
}
};
class MD5Provider final
: public Encryption::Provider
{
public:
MD5Provider(Module *creator) : Encryption::Provider(creator, "md5") { }
Encryption::Context *CreateContext(Encryption::IV *iv) override
{
return new MD5Context(iv);
}
Encryption::IV GetDefaultIV() override
{
Encryption::IV iv;
iv.first = md5_iv;
iv.second = sizeof(md5_iv) / sizeof(uint32_t);
return iv;
}
};
class EMD5 final
: public Module
{
private:
Encryption::SimpleProvider<MD5Context> md5provider;
MD5Provider md5provider;
public:
EMD5(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, md5provider(this, "md5", 16, 64)
EMD5(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
md5provider(this)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_md5 is deprecated and can not be used as a primary encryption method");
}
md5provider.Check({
{ "d41d8cd98f00b204e9800998ecf8427e", "" },
{ "9e107d9d372bb6826bd81d3542a419d6", "The quick brown fox jumps over the lazy dog" },
});
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
MD5Context context;
context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
context.Finalize();
Encryption::Hash hash = context.GetFinalizedHash();
Anope::string buf = "md5:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second);
Log(LOG_DEBUG_2) << "(enc_md5) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("md5"))
return;
auto enc = "md5:" + Anope::Hex(md5provider.Encrypt(req->GetPassword()));
if (nc->pass.equals_cs(enc))
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
+22 -13
View File
@@ -13,35 +13,44 @@ class ENone final
: public Module
{
public:
ENone(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
ENone(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_none is deprecated and can not be used as a primary encryption method");
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
Anope::string buf = "plain:";
Anope::string cpass;
Anope::B64Encode(src, cpass);
buf += cpass;
Log(LOG_DEBUG_2) << "(enc_none) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("plain"))
return;
Anope::string b64pass;
Anope::B64Encode(req->GetPassword(), b64pass);
auto enc = "plain:" + b64pass;
if (nc->pass.equals_cs(enc))
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
+65 -37
View File
@@ -12,41 +12,39 @@
#include "module.h"
#include "modules/encryption.h"
static ServiceReference<Encryption::Provider> md5("Encryption::Provider", "md5");
class OldMD5Provider final
: public Encryption::Provider
{
public:
OldMD5Provider(Module *creator) : Encryption::Provider(creator, "oldmd5") { }
Encryption::Context *CreateContext(Encryption::IV *iv) override
{
if (md5)
return md5->CreateContext(iv);
return NULL;
}
Encryption::IV GetDefaultIV() override
{
if (md5)
return md5->GetDefaultIV();
return Encryption::IV(static_cast<const uint32_t *>(NULL), 0);
}
};
class EOld final
: public Module
{
private:
ServiceReference<Encryption::Provider> md5;
OldMD5Provider oldmd5provider;
Anope::string EncryptInternal(const Anope::string &src)
{
if (!md5)
return {};
char digest[32];
memset(digest, 0, sizeof(digest));
auto hash = md5->Encrypt(src);
if (hash.length() != sizeof(digest))
return {}; // Probably a bug?
memcpy(digest, hash.data(), hash.length());
char digest2[16];
for (size_t i = 0; i < sizeof(digest); i += 2)
digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
return Anope::Hex(digest2, sizeof(digest2));
}
inline static char XTOI(char c)
{
return c > 9 ? c - 'A' + 10 : c - '0';
}
inline static char XTOI(char c) { return c > 9 ? c - 'A' + 10 : c - '0'; }
public:
EOld(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, md5("Encryption::Provider", "md5")
EOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
oldmd5provider(this)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_old is deprecated and can not be used as a primary encryption method");
@@ -54,28 +52,58 @@ public:
ModuleManager::LoadModule("enc_md5", User::Find(creator, true));
if (!md5)
throw ModuleException("Unable to find md5 reference");
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
if (!md5)
return EVENT_CONTINUE;
Encryption::Context *context = md5->CreateContext();
context->Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
context->Finalize();
Encryption::Hash hash = context->GetFinalizedHash();
char digest[32], digest2[16];
memset(digest, 0, sizeof(digest));
if (hash.second > sizeof(digest))
throw CoreException("Hash too large");
memcpy(digest, hash.first, hash.second);
for (int i = 0; i < 32; i += 2)
digest2[i / 2] = XTOI(digest[i]) << 4 | XTOI(digest[i + 1]);
Anope::string buf = "oldmd5:" + Anope::Hex(digest2, sizeof(digest2));
Log(LOG_DEBUG_2) << "(enc_old) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
delete context;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("oldmd5"))
return;
auto enc = EncryptInternal(req->GetPassword());
if (!enc.empty() && nc->pass.equals_cs(enc))
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
+67 -26
View File
@@ -60,6 +60,7 @@ class SHA1Context final
uint32_t state[5];
uint32_t count[2];
unsigned char buffer[64];
unsigned char digest[20];
void Transform(const unsigned char buf[64])
{
@@ -107,13 +108,22 @@ class SHA1Context final
}
public:
SHA1Context()
SHA1Context(Encryption::IV *iv = NULL)
{
for (int i = 0; i < 5; ++i)
this->state[i] = sha1_iv[i];
if (iv != NULL)
{
if (iv->second != 5)
throw CoreException("Invalid IV size");
for (int i = 0; i < 5; ++i)
this->state[i] = iv->first[i];
}
else
for (int i = 0; i < 5; ++i)
this->state[i] = sha1_iv[i];
this->count[0] = this->count[1] = 0;
memset(this->buffer, 0, sizeof(this->buffer));
memset(this->digest, 0, sizeof(this->digest));
}
void Update(const unsigned char *data, size_t len) override
@@ -137,7 +147,7 @@ public:
memcpy(&this->buffer[j], &data[i], len - i);
}
Anope::string Finalize() override
void Finalize() override
{
uint32_t i;
unsigned char finalcount[8];
@@ -148,10 +158,8 @@ public:
while ((this->count[0] & 504) != 448)
this->Update(reinterpret_cast<const unsigned char *>("\0"), 1);
this->Update(finalcount, 8); /* Should cause a SHA1Transform() */
unsigned char digest[20];
memset(digest, 0, sizeof(digest));
for (i = 0; i < 20; ++i)
digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
this->digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
/* Wipe variables */
memset(this->buffer, 0, sizeof(this->buffer));
@@ -160,51 +168,84 @@ public:
memset(&finalcount, 0, sizeof(finalcount));
this->Transform(this->buffer);
}
return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
Encryption::Hash GetFinalizedHash() override
{
Encryption::Hash hash;
hash.first = this->digest;
hash.second = sizeof(this->digest);
return hash;
}
};
class SHA1Provider final
: public Encryption::Provider
{
public:
SHA1Provider(Module *creator) : Encryption::Provider(creator, "sha1") { }
Encryption::Context *CreateContext(Encryption::IV *iv) override
{
return new SHA1Context(iv);
}
Encryption::IV GetDefaultIV() override
{
Encryption::IV iv;
iv.first = sha1_iv;
iv.second = sizeof(sha1_iv) / sizeof(uint32_t);
return iv;
}
};
class ESHA1 final
: public Module
{
private:
Encryption::SimpleProvider<SHA1Context> sha1provider;
SHA1Provider sha1provider;
public:
ESHA1(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, sha1provider(this, "sha1", 20, 64)
ESHA1(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
sha1provider(this)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_sha1 is deprecated and can not be used as a primary encryption method");
}
sha1provider.Check({
{ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "" },
{ "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", "The quick brown fox jumps over the lazy dog" },
});
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
SHA1Context context;
context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
context.Finalize();
Encryption::Hash hash = context.GetFinalizedHash();
Anope::string buf = "sha1:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second);
Log(LOG_DEBUG_2) << "(enc_sha1) hashed password from [" << src << "] to [" << buf << "]";
dest = buf;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("sha1"))
return;
auto enc = "sha1:" + Anope::Hex(sha1provider.Encrypt(req->GetPassword()));
if (nc->pass.equals_cs(enc))
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
-200
View File
@@ -1,200 +0,0 @@
/* Module for providing SHA-2 hashing
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* This program is free but copyrighted software; see the file COPYING for
* details.
*
*/
#include <climits>
#include <random>
#include "sha2/sha2.c"
#include "module.h"
#include "modules/encryption.h"
template <typename SHAContext,
void (* SHAInit)(SHAContext *),
void (* SHAUpdate)(SHAContext *, const unsigned char *, unsigned int),
void (* SHAFinal)(SHAContext *, unsigned char *)>
class SHA2Context final
: public Encryption::Context
{
private:
SHAContext context;
const size_t digest_size;
public:
SHA2Context(size_t ds)
: digest_size(ds)
{
SHAInit(&context);
}
void Update(const unsigned char *data, size_t len) override
{
SHAUpdate(&context, data, len);
}
Anope::string Finalize() override
{
std::vector<unsigned char> digest(digest_size);
SHAFinal(&context, digest.data());
return Anope::string(reinterpret_cast<const char *>(digest.data()), digest.size());
}
};
template <typename SHAContext,
void (* SHAInit)(SHAContext *),
void (* SHAUpdate)(SHAContext *, const unsigned char *, unsigned int),
void (* SHAFinal)(SHAContext *, unsigned char *)>
class SHA2Provider final
: public Encryption::Provider
{
public:
SHA2Provider(Module *creator, const Anope::string &algorithm, size_t bs, size_t ds)
: Encryption::Provider(creator, algorithm, bs, ds)
{
}
std::unique_ptr<Encryption::Context> CreateContext() override
{
return std::make_unique<SHA2Context<SHAContext, SHAInit, SHAUpdate, SHAFinal>>(this->digest_size);
}
};
class ESHA2 final
: public Module
{
private:
Encryption::Provider *defaultprovider = nullptr;
SHA2Provider<sha224_ctx, sha224_init, sha224_update, sha224_final> sha224provider;
SHA2Provider<sha256_ctx, sha256_init, sha256_update, sha256_final> sha256provider;
SHA2Provider<sha384_ctx, sha384_init, sha384_update, sha384_final> sha384provider;
SHA2Provider<sha512_ctx, sha512_init, sha512_update, sha512_final> sha512provider;
Anope::string GenerateKey(size_t keylen)
{
static std::random_device device;
static std::mt19937 engine(device());
static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
Anope::string keybuf(keylen, ' ');
for (size_t i = 0; i < keylen; ++i)
keybuf[i] = static_cast<char>(dist(engine));
return keybuf;
}
Encryption::Provider *GetAlgorithm(const Anope::string &algorithm)
{
if (algorithm == "sha224")
return &sha224provider;
if (algorithm == "sha256")
return &sha256provider;
if (algorithm == "sha384")
return &sha384provider;
if (algorithm == "sha512")
return &sha512provider;
return nullptr;
}
public:
ESHA2(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, sha224provider(this, "sha224", SHA224_BLOCK_SIZE, SHA224_DIGEST_SIZE)
, sha256provider(this, "sha256", SHA256_BLOCK_SIZE, SHA256_DIGEST_SIZE)
, sha384provider(this, "sha384", SHA384_BLOCK_SIZE, SHA384_DIGEST_SIZE)
, sha512provider(this, "sha512", SHA512_BLOCK_SIZE, SHA512_DIGEST_SIZE)
{
sha224provider.Check({
{ "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "" },
{ "730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525", "The quick brown fox jumps over the lazy dog" },
});
sha256provider.Check({
{ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "" },
{ "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592", "The quick brown fox jumps over the lazy dog" },
});
sha384provider.Check({
{ "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b", "" },
{ "ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1", "The quick brown fox jumps over the lazy dog" },
});
sha512provider.Check({
{ "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e", "" },
{ "07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6", "The quick brown fox jumps over the lazy dog" },
});
}
void OnReload(Configuration::Conf *conf) override
{
this->defaultprovider = GetAlgorithm(Config->GetModule(this)->Get<const Anope::string>("algorithm", "sha256"));
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
if (!defaultprovider)
return EVENT_CONTINUE;
auto key = GenerateKey(defaultprovider->digest_size);
auto hmac = defaultprovider->HMAC(key, src);
auto enc = "hmac-" + defaultprovider->name + ":" + Anope::Hex(hmac) + ":" + Anope::Hex(key);
Log(LOG_DEBUG_2) << "(enc_sha2) hashed password from [" << src << "] to [" << enc << "]";
dest = enc;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
auto apos = nc->pass.find(':');
if (apos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + apos);
bool is_hmac = !hash_method.compare(0, 5, "hmac-", 5);
if (!is_hmac && hash_method.compare(0, 4, "raw-", 4))
return; // Not a SHA-2 password.
auto provider = GetAlgorithm(hash_method.substr(is_hmac ? 5 : 4));
if (!provider)
return; // Not a hash for this module.
auto valid = false;
if (is_hmac)
{
auto bpos = nc->pass.find(':', apos + 1);
if (bpos == Anope::string::npos)
return; // No HMAC key.
Anope::string pass_hex(nc->pass.begin() + apos + 1, nc->pass.begin() + bpos);
Anope::string key_hex(nc->pass.begin() + bpos + 1, nc->pass.end());
Anope::string key;
Anope::Unhex(key_hex, key);
auto enc = Anope::Hex(provider->HMAC(key, req->GetPassword()));
valid = pass_hex.equals_cs(enc);
}
else
{
Anope::string pass_hex(nc->pass.begin() + apos + 1, nc->pass.end());
valid = provider->Compare(pass_hex, req->GetPassword());
}
if (valid)
{
// If we are NOT the first encryption module, the password is a raw
// hash, or the algorithm is different we want to re-encrypt the
// password with the primary encryption method.
if (ModuleManager::FindFirstOf(ENCRYPTION) != this || !is_hmac || provider != defaultprovider)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
}
};
MODULE_INIT(ESHA2)
+262 -33
View File
@@ -1,21 +1,247 @@
/* This module generates and compares password hashes using SHA256 algorithms.
*
* If an intruder gets access to your system or uses a brute force attack,
* salt will not provide much value.
* IMPORTANT: DATA HASHES CANNOT BE "DECRYPTED" BACK TO PLAIN TEXT.
*
* Modified for Anope.
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* This program is free but copyrighted software; see the file COPYING for
* details.
* Taken from InspIRCd (https://www.inspircd.org/),
* see https://wiki.inspircd.org/Credits
*
* This program is free but copyrighted software; see
* the file COPYING for details.
*/
#include "sha2/sha2.c"
/* FIPS 180-2 SHA-224/256/384/512 implementation
* Last update: 05/23/2005
* Issue date: 04/30/2005
*
* Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "module.h"
#include "modules/encryption.h"
static const unsigned SHA256_DIGEST_SIZE = 256 / 8;
static const unsigned SHA256_BLOCK_SIZE = 512 / 8;
inline static uint32_t SHFR(uint32_t x, uint32_t n) { return x >> n; }
inline static uint32_t ROTR(uint32_t x, uint32_t n) { return (x >> n) | (x << ((sizeof(x) << 3) - n)); }
inline static uint32_t CH(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (~x & z); }
inline static uint32_t MAJ(uint32_t x, uint32_t y, uint32_t z) { return (x & y) ^ (x & z) ^ (y & z); }
inline static uint32_t SHA256_F1(uint32_t x) { return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22); }
inline static uint32_t SHA256_F2(uint32_t x) { return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25); }
inline static uint32_t SHA256_F3(uint32_t x) { return ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3); }
inline static uint32_t SHA256_F4(uint32_t x) { return ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10); }
inline static void UNPACK32(unsigned x, unsigned char *str)
{
str[3] = static_cast<uint8_t>(x);
str[2] = static_cast<uint8_t>(x >> 8);
str[1] = static_cast<uint8_t>(x >> 16);
str[0] = static_cast<uint8_t>(x >> 24);
}
inline static void PACK32(unsigned char *str, uint32_t &x)
{
x = static_cast<uint32_t>(str[3]) | static_cast<uint32_t>(str[2]) << 8 | static_cast<uint32_t>(str[1]) << 16 | static_cast<uint32_t>(str[0]) << 24;
}
/* Macros used for loops unrolling */
inline static void SHA256_SCR(uint32_t w[64], int i)
{
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] + SHA256_F3(w[i - 15]) + w[i - 16];
}
static const uint32_t sha256_h0[8] =
{
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
static const uint32_t sha256_k[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
/** An sha256 context
*/
class SHA256Context final
: public Encryption::Context
{
void Transform(unsigned char *message, unsigned block_nb)
{
uint32_t w[64], wv[8];
unsigned char *sub_block;
for (unsigned i = 1; i <= block_nb; ++i)
{
int j;
sub_block = message + ((i - 1) << 6);
for (j = 0; j < 16; ++j)
PACK32(&sub_block[j << 2], w[j]);
for (j = 16; j < 64; ++j)
SHA256_SCR(w, j);
for (j = 0; j < 8; ++j)
wv[j] = this->h[j];
for (j = 0; j < 64; ++j)
{
uint32_t t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + sha256_k[j] + w[j];
uint32_t t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
wv[7] = wv[6];
wv[6] = wv[5];
wv[5] = wv[4];
wv[4] = wv[3] + t1;
wv[3] = wv[2];
wv[2] = wv[1];
wv[1] = wv[0];
wv[0] = t1 + t2;
}
for (j = 0; j < 8; ++j)
this->h[j] += wv[j];
}
}
unsigned tot_len;
unsigned len;
unsigned char block[2 * SHA256_BLOCK_SIZE];
uint32_t h[8];
unsigned char digest[SHA256_DIGEST_SIZE];
public:
SHA256Context(Encryption::IV *iv)
{
if (iv != NULL)
{
if (iv->second != 8)
throw CoreException("Invalid IV size");
for (int i = 0; i < 8; ++i)
this->h[i] = iv->first[i];
}
else
for (int i = 0; i < 8; ++i)
this->h[i] = sha256_h0[i];
this->tot_len = 0;
this->len = 0;
memset(this->block, 0, sizeof(this->block));
memset(this->digest, 0, sizeof(this->digest));
}
void Update(const unsigned char *message, size_t mlen) override
{
unsigned tmp_len = SHA256_BLOCK_SIZE - this->len, rem_len = mlen < tmp_len ? mlen : tmp_len;
memcpy(&this->block[this->len], message, rem_len);
if (this->len + mlen < SHA256_BLOCK_SIZE)
{
this->len += mlen;
return;
}
unsigned new_len = mlen - rem_len, block_nb = new_len / SHA256_BLOCK_SIZE;
unsigned char *shifted_message = new unsigned char[mlen - rem_len];
memcpy(shifted_message, message + rem_len, mlen - rem_len);
this->Transform(this->block, 1);
this->Transform(shifted_message, block_nb);
rem_len = new_len % SHA256_BLOCK_SIZE;
memcpy(this->block, &shifted_message[block_nb << 6], rem_len);
delete [] shifted_message;
this->len = rem_len;
this->tot_len += (block_nb + 1) << 6;
}
void Finalize() override
{
unsigned block_nb = 1 + ((SHA256_BLOCK_SIZE - 9) < (this->len % SHA256_BLOCK_SIZE));
unsigned len_b = (this->tot_len + this->len) << 3;
unsigned pm_len = block_nb << 6;
memset(this->block + this->len, 0, pm_len - this->len);
this->block[this->len] = 0x80;
UNPACK32(len_b, this->block + pm_len - 4);
this->Transform(this->block, block_nb);
for (int i = 0 ; i < 8; ++i)
UNPACK32(this->h[i], &this->digest[i << 2]);
}
Encryption::Hash GetFinalizedHash() override
{
Encryption::Hash hash;
hash.first = this->digest;
hash.second = SHA256_DIGEST_SIZE;
return hash;
}
};
class SHA256Provider final
: public Encryption::Provider
{
public:
SHA256Provider(Module *creator) : Encryption::Provider(creator, "sha256") { }
Encryption::Context *CreateContext(Encryption::IV *iv) override
{
return new SHA256Context(iv);
}
Encryption::IV GetDefaultIV() override
{
Encryption::IV iv;
iv.first = sha256_h0;
iv.second = sizeof(sha256_h0) / sizeof(uint32_t);
return iv;
}
};
class ESHA256 final
: public Module
{
private:
SHA256Provider sha256provider;
unsigned iv[8];
bool use_iv;
@@ -23,7 +249,7 @@ private:
void NewRandomIV()
{
for (auto &ivsegment : iv)
ivsegment = static_cast<uint32_t>(Anope::RandomNumber());
ivsegment = static_cast<uint32_t>(rand());
}
/* returns the IV as base64-encrypted string */
@@ -45,59 +271,62 @@ private:
char buf2[33];
Anope::Unhex(buf, buf2, sizeof(buf2));
for (int i = 0 ; i < 8; ++i)
PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), &iv[i]);
PACK32(reinterpret_cast<unsigned char *>(&buf2[i << 2]), iv[i]);
}
Anope::string EncryptInternal(const Anope::string &src)
public:
ESHA256(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
sha256provider(this)
{
use_iv = false;
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
if (!use_iv)
NewRandomIV();
else
use_iv = false;
sha256_ctx ctx;
sha256_init(&ctx);
for (size_t i = 0; i < 8; ++i)
ctx.h[i] = iv[i];
sha256_update(&ctx, reinterpret_cast<const unsigned char *>(src.data()), src.length());
unsigned char digest[SHA256_DIGEST_SIZE];
sha256_final(&ctx, digest);
Anope::string hash(reinterpret_cast<const char *>(&digest), sizeof(digest));
Encryption::IV initialization(this->iv, 8);
SHA256Context ctx(&initialization);
ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
ctx.Finalize();
return "sha256:" + Anope::Hex(hash) + ":" + GetIVString();
}
Encryption::Hash hash = ctx.GetFinalizedHash();
public:
ESHA256(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
{
use_iv = false;
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_sha256 is deprecated and can not be used as a primary encryption method");
std::stringstream buf;
buf << "sha256:" << Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second) << ":" << GetIVString();
Log(LOG_DEBUG_2) << "(enc_sha256) hashed password from [" << src << "] to [" << buf.str() << " ]";
dest = buf.str();
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
size_t pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("sha256"))
return;
GetIVFromPass(nc->pass);
use_iv = true;
auto enc = EncryptInternal(req->GetPassword());
if (nc->pass.equals_cs(enc))
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
-199
View File
@@ -1,199 +0,0 @@
/* Module for providing Argon2 hashing
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* This program is free but copyrighted software; see the file COPYING for
* details.
*
*/
/* RequiredLibraries: argon2 */
/* RequiredWindowsLibraries: argon2 */
#include <climits>
#include <random>
#include <argon2.h>
#include "module.h"
#include "modules/encryption.h"
class Argon2Context final
: public Encryption::Context
{
private:
Anope::string buffer;
argon2_type type;
Anope::string GenerateSalt()
{
static std::random_device device;
static std::mt19937 engine(device());
static std::uniform_int_distribution<int> dist(CHAR_MIN, CHAR_MAX);
Anope::string saltbuf(this->salt_length, ' ');
for (size_t i = 0; i < this->salt_length; ++i)
saltbuf[i] = static_cast<char>(dist(engine));
return saltbuf;
}
public:
static uint32_t memory_cost;
static uint32_t time_cost;
static uint32_t parallelism;
static uint32_t hash_length;
static uint32_t salt_length;
Argon2Context(argon2_type at)
: type(at)
{
}
void Update(const unsigned char *data, size_t len) override
{
buffer.append(reinterpret_cast<const char *>(data), len);
}
Anope::string Finalize() override
{
auto salt = GenerateSalt();
// Calculate the size of and allocate the output buffer.
auto length = argon2_encodedlen(this->time_cost, this->memory_cost, this->parallelism,
this->salt_length, this->hash_length, this->type);
std::vector<char> digest(length);
auto result = argon2_hash(this->time_cost, this->memory_cost, this->parallelism,
buffer.c_str(), buffer.length(), salt.c_str(), salt.length(), nullptr,
this->hash_length, digest.data(), digest.size(), this->type,
ARGON2_VERSION_NUMBER);
if (result == ARGON2_OK)
return Anope::string(digest.data(), digest.size());
Log(LOG_DEBUG_2) << "Argon2 error: " << argon2_error_message(result);
return {};
}
};
uint32_t Argon2Context::memory_cost;
uint32_t Argon2Context::time_cost;
uint32_t Argon2Context::parallelism;
uint32_t Argon2Context::hash_length;
uint32_t Argon2Context::salt_length;
class Argon2Provider final
: public Encryption::Provider
{
private:
argon2_type type;
public:
Argon2Provider(Module *creator, argon2_type at)
: Encryption::Provider(creator, argon2_type2string(at, 0), 0, 0)
, type(at)
{
}
bool Compare(const Anope::string &hash, const Anope::string &plain) override
{
return argon2_verify(hash.c_str(), plain.c_str(), plain.length(), this->type) == ARGON2_OK;
}
std::unique_ptr<Encryption::Context> CreateContext() override
{
return std::make_unique<Argon2Context>(this->type);
}
Anope::string ToPrintable(const Anope::string &hash) override
{
// We have no way to make this printable without the creating context
// so we always return the printed form.
return hash;
}
};
class EArgon2 final
: public Module
{
private:
Encryption::Provider *defaultprovider = nullptr;
Argon2Provider argon2dprovider;
Argon2Provider argon2iprovider;
Argon2Provider argon2idprovider;
Encryption::Provider *GetAlgorithm(const Anope::string &algorithm)
{
if (algorithm == "argon2d")
return &argon2dprovider;
if (algorithm == "argon2i")
return &argon2iprovider;
if (algorithm == "argon2id")
return &argon2idprovider;
return nullptr;
}
public:
EArgon2(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, argon2dprovider(this, Argon2_d)
, argon2iprovider(this, Argon2_i)
, argon2idprovider(this, Argon2_id)
{
}
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");
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
if (!defaultprovider)
return EVENT_CONTINUE;
auto hash = defaultprovider->Encrypt(src);
auto enc = defaultprovider->name + ":" + hash;
Log(LOG_DEBUG_2) << "(enc_argon2) hashed password from [" << src << "] to [" << enc << "]";
dest = enc;
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
auto provider = GetAlgorithm(hash_method);
if (!provider)
return; // Not a hash for this module.
Anope::string hash_value(nc->pass.begin() + pos + 1, nc->pass.end());
if (provider->Compare(hash_value, req->GetPassword()))
{
// If we are NOT the first encryption module or the algorithm is
// different we want to re-encrypt the password with the primary
// encryption method.
if (ModuleManager::FindFirstOf(ENCRYPTION) != this || provider != defaultprovider)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
}
};
MODULE_INIT(EArgon2)
-53
View File
@@ -1,53 +0,0 @@
/* Module for providing POSIX crypt() hashing
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* This program is free but copyrighted software; see the file COPYING for
* details.
*
*/
/* RequiredLibraries: crypt */
#include "module.h"
class EPOSIX final
: public Module
{
public:
EPOSIX(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_posix can not be used as a primary encryption method");
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
auto pos = nc->pass.find(':');
if (pos == Anope::string::npos)
return;
Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos);
if (!hash_method.equals_cs("posix"))
return;
Anope::string pass_hash(nc->pass.begin() + pos + 1, nc->pass.end());
if (pass_hash.equals_cs(crypt(req->GetPassword().c_str(), pass_hash.c_str())))
{
// If we are NOT the first encryption module we want to re-encrypt
// the password with the primary encryption method.
if (ModuleManager::FindFirstOf(ENCRYPTION) != this)
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
}
};
MODULE_INIT(EPOSIX)
@@ -229,10 +229,8 @@ public:
this->disable_email_reason = conf->Get<const Anope::string>("disable_email_reason");
if (!email_attribute.empty())
{
/* Don't complain to users about how they need to update their email, we will do it for them */
config->GetModule("nickserv")->Set("forceemail", "no");
}
config->GetModule("nickserv")->Set("forceemail", "false");
}
EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) override
@@ -305,15 +303,6 @@ public:
Anope::string new_dn = username_attribute + "=" + na->nick + "," + basedn;
this->ldap->Add(&this->orinterface, new_dn, attributes);
}
void OnPreNickExpire(NickAlias *na, bool &expire) override
{
// We can't let nicks expire if they still have a group or
// there will be a zombie account left over that can't be
// authenticated to.
if (na->nick == na->nc->display && na->nc->aliases->size() > 1)
expire = false;
}
};
MODULE_INIT(ModuleLDAPAuthentication)
+2 -2
View File
@@ -452,7 +452,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
for (const auto &[field, _] : data.data)
query_text += ",`" + field + "`";
query_text += ") VALUES (" + Anope::ToString(id);
query_text += ") VALUES (" + stringify(id);
for (const auto &[field, _] : data.data)
query_text += ",@" + field + "@";
query_text += ") ON DUPLICATE KEY UPDATE ";
@@ -536,7 +536,7 @@ Anope::string MySQLService::BuildQuery(const Query &q)
Anope::string MySQLService::FromUnixtime(time_t t)
{
return "FROM_UNIXTIME(" + Anope::ToString(t) + ")";
return "FROM_UNIXTIME(" + stringify(t) + ")";
}
void DispatcherThread::Run()
+1 -1
View File
@@ -30,7 +30,7 @@ public:
{
PCRE2_UCHAR error[128];
pcre2_get_error_message(errcode, error, sizeof error);
throw RegexException("Error in regex " + expr + " at offset " + Anope::ToString(erroffset) + ": " + reinterpret_cast<const char*>(error));
throw RegexException("Error in regex " + expr + " at offset " + stringify(erroffset) + ": " + reinterpret_cast<const char*>(error));
}
}
@@ -145,15 +145,6 @@ public:
Log(LOG_DEBUG) << "sql_authentication: Checking authentication for " << req->GetAccount();
}
void OnPreNickExpire(NickAlias *na, bool &expire) override
{
// We can't let nicks expire if they still have a group or
// there will be a zombie account left over that can't be
// authenticated to.
if (na->nick == na->nc->display && na->nc->aliases->size() > 1)
expire = false;
}
};
MODULE_INIT(ModuleSQLAuthentication)
+4 -3
View File
@@ -118,7 +118,8 @@ public:
if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
{
auto database = Anope::ExpandData(block->Get<const Anope::string>("database", "anope"));
Anope::string database = Anope::DataDir + "/" + block->Get<const Anope::string>("database", "anope");
try
{
auto *ss = new SQLiteService(this, connname, database);
@@ -296,7 +297,7 @@ Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Da
query_text.erase(query_text.length() - 1);
query_text += ") VALUES (";
if (id > 0)
query_text += Anope::ToString(id) + ",";
query_text += stringify(id) + ",";
for (const auto &[field, _] : data.data)
query_text += "@" + field + "@,";
query_text.erase(query_text.length() - 1);
@@ -338,7 +339,7 @@ Anope::string SQLiteService::BuildQuery(const Query &q)
Anope::string SQLiteService::FromUnixtime(time_t t)
{
return "datetime('" + Anope::ToString(t) + "', 'unixepoch')";
return "datetime('" + stringify(t) + "', 'unixepoch')";
}
MODULE_INIT(ModuleSQLite)
+3 -3
View File
@@ -329,9 +329,9 @@ public:
{
Configuration::Block *config = conf->GetModule(this);
const Anope::string certfile = Anope::ExpandConfig(config->Get<const Anope::string>("cert", "fullchain.pem"));
const Anope::string keyfile = Anope::ExpandConfig(config->Get<const Anope::string>("key", "privkey.pem"));
const Anope::string dhfile = Anope::ExpandConfig(config->Get<const Anope::string>("dh", "dhparams.pem"));
const Anope::string certfile = config->Get<const Anope::string>("cert", "data/fullchain.pem");
const Anope::string keyfile = config->Get<const Anope::string>("key", "data/privkey.pem");
const Anope::string dhfile = config->Get<const Anope::string>("dh", "data/dhparams.pem");
CheckFile(certfile);
CheckFile(keyfile);
+2 -2
View File
@@ -146,8 +146,8 @@ public:
{
Configuration::Block *config = conf->GetModule(this);
this->certfile = Anope::ExpandConfig(config->Get<const Anope::string>("cert", "fullchain.pem"));
this->keyfile = Anope::ExpandConfig(config->Get<const Anope::string>("key", "privkey.pem"));
this->certfile = config->Get<const Anope::string>("cert", "data/fullchain.pem");
this->keyfile = config->Get<const Anope::string>("key", "data/privkey.pem");
if (Anope::IsFile(this->certfile.c_str()))
{
+1 -1
View File
@@ -40,7 +40,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(READ_ONLY_MODE);
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
return;
}
+18 -55
View File
@@ -14,75 +14,40 @@
class CommandGLGlobal final
: public Command
{
private:
ServiceReference<GlobalService> global;
BotInfo *GetSender(CommandSource &source)
{
Reference<BotInfo> sender;
if (global)
sender = global->GetDefaultSender();
if (!sender)
sender = source.service;
return sender;
}
ServiceReference<GlobalService> GService;
public:
CommandGLGlobal(Module *creator)
: Command(creator, "global/global", 0)
, global("GlobalService", "Global")
CommandGLGlobal(Module *creator) : Command(creator, "global/global", 1, 1), GService("GlobalService", "Global")
{
this->SetDesc(_("Send a message to all users"));
this->SetSyntax(_("[\037message\037]"));
this->SetSyntax(_("\037message\037"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!global)
{
source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
return;
}
const Anope::string &msg = params[0];
auto queuesize = global->CountQueue(source.nc);
if (!queuesize && params.empty())
{
source.Reply(GLOBAL_NO_MESSAGE);
return;
}
if (queuesize && !params.empty())
{
source.Reply(GLOBAL_QUEUE_CONFLICT);
return;
}
if (params.empty())
{
// We are sending the message queue.
global->SendQueue(source, GetSender(source));
}
if (!GService)
source.Reply("No global reference, is global loaded?");
else
{
// We are sending a single message.
global->SendSingle(params[0], &source, GetSender(source));
queuesize = 1;
Log(LOG_ADMIN, source, this);
GService->SendGlobal(NULL, source.GetNick(), msg);
}
Log(LOG_ADMIN, source, this) << "to send " << queuesize << " messages to all users";
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
Reference<BotInfo> sender;
if (GService)
sender = GService->GetDefaultSender();
if (!sender)
sender = source.service;
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_(
"Allows sending messages to all users on the network. The message will be sent\n"
"from \002%s\002.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
), GetSender(source)->nick.c_str());
source.Reply(_("Allows Administrators to send messages to all users on the\n"
"network. The message will be sent from the nick \002%s\002."), sender->nick.c_str());
return true;
}
};
@@ -90,13 +55,11 @@ public:
class GLGlobal final
: public Module
{
private:
CommandGLGlobal commandglglobal;
public:
GLGlobal(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
, commandglglobal(this)
GLGlobal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
commandglglobal(this)
{
}
-208
View File
@@ -1,208 +0,0 @@
/* Global core functions
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
#include "module.h"
#define QUEUE_EMPTY _("You have no messages queued.")
class QueueDelCallback final
: public NumberList
{
private:
unsigned deleted = 0;
ServiceReference<GlobalService> &global;
CommandSource &source;
public:
QueueDelCallback(CommandSource &src, ServiceReference<GlobalService>& gl, const Anope::string &list)
: NumberList(list, true)
, global(gl)
, source(src)
{
}
~QueueDelCallback() override
{
switch (deleted)
{
case 0:
source.Reply(_("No matching entries in your message queue."));
break;
case 1:
source.Reply(_("Deleted one entry from your message queue."));
break;
default:
source.Reply(_("Deleted %u entries from your message queue."), deleted);
break;
}
}
void HandleNumber(unsigned number) override
{
if (!number || number > global->CountQueue(source.nc))
return;
if (global->Unqueue(source.nc, number - 1))
deleted++;
}
};
class CommandGLQueue final
: public Command
{
private:
ServiceReference<GlobalService> global;
void DoAdd(CommandSource &source, const Anope::string &message)
{
if (message.empty())
{
this->OnSyntaxError(source, "ADD");
return;
}
auto maxqueue = Config->GetModule(this->module)->Get<size_t>("maxqueue", "10");
if (global->CountQueue(source.nc) >= maxqueue)
{
source.Reply(_("You can not queue any more messages."));
return;
}
global->Queue(source.nc, message);
source.Reply(_("Your message has been queued."));
Log(LOG_ADMIN, source, this) << "to queue: " << message;
}
void DoClear(CommandSource &source)
{
if (!global->CountQueue(source.nc))
{
source.Reply(_("You do not have any queued messages."));
return;
}
global->ClearQueue(source.nc);
source.Reply(_("Your message queue has been cleared."));
Log(LOG_ADMIN, source, this);
}
void DoDel(CommandSource &source, const Anope::string &what)
{
if (what.empty())
{
this->OnSyntaxError(source, "DEL");
return;
}
if (!global->CountQueue(source.nc))
{
source.Reply(QUEUE_EMPTY);
return;
}
QueueDelCallback(source, global, what).Process();
}
void DoList(CommandSource &source)
{
const auto *q = global->GetQueue(source.nc);
if (!q || q->empty())
{
source.Reply(QUEUE_EMPTY);
return;
}
ListFormatter list(source.nc);
list.AddColumn(_("Number")).AddColumn(_("Message"));
for (size_t i = 0; i < q->size(); ++i)
{
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(i + 1);
entry["Message"] = (*q)[i];
list.AddEntry(entry);
}
std::vector<Anope::string> replies;
list.Process(replies);
for (const auto &reply : replies)
source.Reply(reply);
}
public:
CommandGLQueue(Module *creator)
: Command(creator, "global/queue", 1, 2)
, global("GlobalService", "Global")
{
this->SetDesc(_("Manages your pending message queue."));
this->SetSyntax(_("ADD \037message\037"));
this->SetSyntax(_("DEL \037entry-num\037"));
this->SetSyntax("LIST");
this->SetSyntax("CLEAR");
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!global)
{
source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
return;
}
const auto &cmd = params[0];
const auto &what = params.size() > 1 ? params[1] : "";
if (cmd.equals_ci("ADD"))
this->DoAdd(source, what);
else if (cmd.equals_ci("CLEAR"))
this->DoClear(source);
else if (cmd.equals_ci("DEL"))
this->DoDel(source, what);
else if (cmd.equals_ci("LIST"))
this->DoList(source);
else
this->OnSyntaxError(source, "");
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply("");
source.Reply(_(
"Allows queueing messages to send to users on the network.\n"
"\n"
"The \002QUEUE ADD\002 command adds the given message to the message queue."
"\n"
"The \002QUEUE CLEAR\002 command clears the message queue."
"\n"
"The \002QUEUE DEL\002 command removes the specified message from the message queue. The\n"
"message number can be obtained from the output of the \002QUEUE LIST\002 command."
"\n"
"The \002QUEUE LIST\002 command lists all messages that are currently in the message queue."
));
return true;
}
};
class GLQueue final
: public Module
{
private:
CommandGLQueue commandglqueue;
public:
GLQueue(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
, commandglqueue(this)
{
}
};
MODULE_INIT(GLQueue)
-112
View File
@@ -1,112 +0,0 @@
/* Global core functions
*
* (C) 2003-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*
* Based on the original code of Epona by Lara.
* Based on the original code of Services by Andy Church.
*/
#include "module.h"
class CommandGLServer final
: public Command
{
private:
ServiceReference<GlobalService> global;
BotInfo *GetSender(CommandSource &source)
{
Reference<BotInfo> sender;
if (global)
sender = global->GetDefaultSender();
if (!sender)
sender = source.service;
return sender;
}
public:
CommandGLServer(Module *creator)
: Command(creator, "global/server", 1)
, global("GlobalService", "Global")
{
this->SetDesc(_("Send a message to all users on a server"));
this->SetSyntax(_("\037server\037 [\037message\037]"));
}
void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!global)
{
source.Reply(SERVICE_UNAVAILABLE, source.service->nick.c_str());
return;
}
auto *server = Server::Find(params[0]);
if (!server || server == Me || server->IsJuped())
{
source.Reply(_("Server \002%s\002 is not linked to the network."), params[0].c_str());
return;
}
auto queuesize = global->CountQueue(source.nc);
if (!queuesize && params.size() < 2)
{
source.Reply(GLOBAL_NO_MESSAGE);
return;
}
if (queuesize && params.size() > 1)
{
source.Reply(GLOBAL_QUEUE_CONFLICT);
return;
}
if (params.empty())
{
// We are sending the message queue.
global->SendQueue(source, GetSender(source), server);
}
else
{
// We are sending a single message.
global->SendSingle(params[1], &source, GetSender(source), server);
queuesize = 1;
}
Log(LOG_ADMIN, source, this) << "to send " << queuesize << " messages to users on " << server->GetName();
}
bool OnHelp(CommandSource &source, const Anope::string &subcommand) override
{
this->SendSyntax(source);
source.Reply(" ");
source.Reply(_(
"Allows sending messages to all users on a server. The message will be sent\n"
"from \002%s\002.\n"
"\n"
"You can either send a message by specifying it as a parameter or provide no\n"
"parameters to send a previously queued message.\n"
), GetSender(source)->nick.c_str());
return true;
}
};
class GLServer final
: public Module
{
private:
CommandGLServer commandglserver;
public:
GLServer(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, VENDOR)
, commandglserver(this)
{
}
};
MODULE_INIT(GLServer)
+39 -113
View File
@@ -15,162 +15,88 @@ class GlobalCore final
: public Module
, public GlobalService
{
private:
Reference<BotInfo> global;
PrimitiveExtensibleItem<std::vector<Anope::string>> queue;
Reference<BotInfo> Global;
void ServerGlobal(BotInfo *sender, Server *server, bool children, const Anope::string &message)
void ServerGlobal(BotInfo *sender, Server *s, const Anope::string &message)
{
if (server != Me && !server->IsJuped())
server->Notice(sender, message);
if (children)
{
for (auto *link : server->GetLinks())
this->ServerGlobal(sender, link, true, message);
}
if (s != Me && !s->IsJuped())
s->Notice(sender, message);
for (auto *link : s->GetLinks())
this->ServerGlobal(sender, link, message);
}
public:
GlobalCore(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, PSEUDOCLIENT | VENDOR)
, GlobalService(this)
, queue(this, "global-queue")
GlobalCore(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PSEUDOCLIENT | VENDOR),
GlobalService(this)
{
}
void ClearQueue(NickCore *nc) override
Reference<BotInfo> GetDefaultSender() override
{
queue.Unset(nc);
return Global;
}
Reference<BotInfo> GetDefaultSender() const override
void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) override
{
return global;
}
if (Me->GetLinks().empty())
return;
if (!sender)
sender = Global;
if (!sender)
return;
const std::vector<Anope::string> *GetQueue(NickCore* nc) const override
{
return queue.Get(nc);
}
Anope::string rmessage;
size_t Queue(NickCore *nc, const Anope::string &message) override
{
auto *q = queue.Require(nc);
q->push_back(message);
return q->size();
if (!source.empty() && !Config->GetModule("global")->Get<bool>("anonymousglobal"))
rmessage = "[" + source + "] " + message;
else
rmessage = message;
this->ServerGlobal(sender, Servers::GetUplink(), rmessage);
}
void OnReload(Configuration::Conf *conf) override
{
const auto glnick = conf->GetModule(this)->Get<const Anope::string>("client");
const Anope::string &glnick = conf->GetModule(this)->Get<const Anope::string>("client");
if (glnick.empty())
throw ConfigException(Module::name + ": <client> must be defined");
auto *bi = BotInfo::Find(glnick, true);
BotInfo *bi = BotInfo::Find(glnick, true);
if (!bi)
throw ConfigException(Module::name + ": no bot named " + glnick);
global = bi;
Global = bi;
}
void OnRestart() override
{
const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
if (!msg.empty())
this->SendSingle(msg, nullptr, nullptr, nullptr);
const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
if (!gl.empty())
this->SendGlobal(Global, "", gl);
}
void OnShutdown() override
{
const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
if (!msg.empty())
this->SendSingle(msg, nullptr, nullptr, nullptr);
const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycledown");
if (!gl.empty())
this->SendGlobal(Global, "", gl);
}
void OnNewServer(Server *s) override
{
const auto msg = Config->GetModule(this)->Get<const Anope::string>("globaloncycleup");
if (!msg.empty() && !Me->IsSynced())
s->Notice(global, msg);
const Anope::string &gl = Config->GetModule(this)->Get<const Anope::string>("globaloncycleup");
if (!gl.empty() && !Me->IsSynced())
s->Notice(Global, gl);
}
EventReturn OnPreHelp(CommandSource &source, const std::vector<Anope::string> &params) override
{
if (!params.empty() || source.c || source.service != *global)
if (!params.empty() || source.c || source.service != *Global)
return EVENT_CONTINUE;
source.Reply(_("%s commands:"), global->nick.c_str());
source.Reply(_("%s commands:"), Global->nick.c_str());
return EVENT_CONTINUE;
}
bool SendQueue(CommandSource &source, BotInfo *sender, Server *server) override
{
// We MUST have an account.
if (!source.nc)
return false;
// We MUST have a message queue.
auto *q = queue.Get(source.nc);
if (!q || q->empty())
return false;
auto success = true;
for (const auto &message : *q)
{
if (!SendSingle(message, &source, sender, server))
{
success = false;
break;
}
}
queue.Unset(source.nc);
return success;
}
bool SendSingle(const Anope::string &message, CommandSource *source, BotInfo* sender, Server* server) override
{
// We MUST have a sender.
if (sender)
sender = global;
if (!sender)
return false;
if (!server)
server = Servers::GetUplink();
Anope::string line;
if (source && !Config->GetModule(this)->Get<bool>("anonymousglobal"))
{
// A source is available and they're not anonymous.
line = Anope::printf("[%s] %s", source->GetNick().c_str(), message.c_str());
}
else
{
// A source isn't available or they're anonymous.
line = message.empty() ? " " : message;
}
if (server)
this->ServerGlobal(sender, Servers::GetUplink(), true, line);
else
this->ServerGlobal(sender, server, false, line);
return true;
}
bool Unqueue(NickCore *nc, size_t idx) override
{
auto *q = queue.Get(nc);
if (!q || idx > q->size())
return false;
q->erase(q->begin() + idx);
if (q->empty())
queue.Unset(nc);
return true;
}
};
MODULE_INIT(GlobalCore)
+19 -19
View File
@@ -42,35 +42,35 @@ public:
return;
const NickAlias *na = NickAlias::Find(u->nick);
if (!na || na->nc != u->Account() || !na->HasVHost())
if (!na || na->nc != u->Account() || !na->HasVhost())
na = NickAlias::Find(u->Account()->display);
if (!na || !na->HasVHost())
if (!na || !na->HasVhost())
return;
if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVHostHost()) || (!na->GetVHostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVHostIdent())))
if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVhostHost()) || (!na->GetVhostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVhostIdent())))
{
IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
u->vhost = na->GetVHostHost();
u->vhost = na->GetVhostHost();
u->UpdateHost();
if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
u->SetVIdent(na->GetVHostIdent());
if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
u->SetVIdent(na->GetVhostIdent());
if (HostServ)
{
u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."),
na->GetVHostMask().c_str());
na->GetVhostMask().c_str());
}
}
}
void OnNickDrop(CommandSource &source, NickAlias *na) override
{
if (na->HasVHost())
if (na->HasVhost())
{
FOREACH_MOD(OnDeleteVHost, (na));
na->RemoveVHost();
FOREACH_MOD(OnDeleteVhost, (na));
na->RemoveVhost();
}
}
@@ -87,7 +87,7 @@ public:
return EVENT_CONTINUE;
}
void OnSetVHost(NickAlias *na) override
void OnSetVhost(NickAlias *na) override
{
if (Config->GetModule(this)->Get<bool>("activate_on_set"))
{
@@ -95,31 +95,31 @@ public:
if (u && u->Account() == na->nc)
{
IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
u->vhost = na->GetVHostHost();
u->vhost = na->GetVhostHost();
u->UpdateHost();
if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
u->SetVIdent(na->GetVHostIdent());
if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
u->SetVIdent(na->GetVhostIdent());
if (HostServ)
{
u->SendMessage(HostServ, _("Your vhost of \002%s\002 is now activated."),
na->GetVHostMask().c_str());
na->GetVhostMask().c_str());
}
}
}
}
void OnDeleteVHost(NickAlias *na) override
void OnDeleteVhost(NickAlias *na) override
{
if (Config->GetModule(this)->Get<bool>("activate_on_set"))
{
User *u = User::Find(na->nick);
if (u && u->Account() == na->nc)
IRCD->SendVHostDel(u);
IRCD->SendVhostDel(u);
}
}
};
+6 -6
View File
@@ -34,9 +34,9 @@ public:
if (na)
{
Log(LOG_ADMIN, source, this) << "for user " << na->nick;
FOREACH_MOD(OnDeleteVHost, (na));
na->RemoveVHost();
source.Reply(_("VHost for \002%s\002 removed."), nick.c_str());
FOREACH_MOD(OnDeleteVhost, (na));
na->RemoveVhost();
source.Reply(_("Vhost for \002%s\002 removed."), nick.c_str());
}
else
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
@@ -74,15 +74,15 @@ public:
NickAlias *na = NickAlias::Find(nick);
if (na)
{
FOREACH_MOD(OnDeleteVHost, (na));
FOREACH_MOD(OnDeleteVhost, (na));
const NickCore *nc = na->nc;
for (auto *alias : *nc->aliases)
{
na = alias;
na->RemoveVHost();
na->RemoveVhost();
}
Log(LOG_ADMIN, source, this) << "for all nicks in group " << nc->display;
source.Reply(_("VHosts for group \002%s\002 have been removed."), nc->display.c_str());
source.Reply(_("vhosts for group \002%s\002 have been removed."), nc->display.c_str());
}
else
source.Reply(NICK_X_NOT_REGISTERED, nick.c_str());
+7 -7
View File
@@ -22,16 +22,16 @@ public:
if (setting)
return;
if (!na || !na->HasVHost())
if (!na || !na->HasVhost())
return;
setting = true;
for (auto *nick : *na->nc->aliases)
{
if (nick && nick != na)
if (nick)
{
nick->SetVHost(na->GetVHostIdent(), na->GetVHostHost(), na->GetVHostCreator());
FOREACH_MOD(OnSetVHost, (nick));
nick->SetVhost(na->GetVhostIdent(), na->GetVhostHost(), na->GetVhostCreator());
FOREACH_MOD(OnSetVhost, (nick));
}
}
setting = false;
@@ -51,11 +51,11 @@ public:
}
NickAlias *na = NickAlias::Find(source.GetNick());
if (na && source.GetAccount() == na->nc && na->HasVHost())
if (na && source.GetAccount() == na->nc && na->HasVhost())
{
this->Sync(na);
source.Reply(_("All vhosts in the group \002%s\002 have been set to \002%s\002."),
source.nc->display.c_str(), na->GetVHostMask().c_str());
source.nc->display.c_str(), na->GetVhostMask().c_str());
}
else
source.Reply(HOST_NOT_ASSIGNED);
@@ -89,7 +89,7 @@ public:
throw ModuleException("Your IRCd does not support vhosts");
}
void OnSetVHost(NickAlias *na) override
void OnSetVhost(NickAlias *na) override
{
if (!synconset)
return;
+17 -14
View File
@@ -45,33 +45,36 @@ public:
source.Reply(LIST_INCORRECT_RANGE);
return;
}
from = Anope::Convert<int>(key.substr(1, tmp - 1), 0);
to = Anope::Convert<int>(key.substr(tmp + 1), 0);
try
{
from = convertTo<int>(key.substr(1, tmp - 1));
to = convertTo<int>(key.substr(tmp + 1));
}
catch (const ConvertException &) { }
}
}
unsigned display_counter = 0, listmax = Config->GetModule(this->owner)->Get<unsigned>("listmax", "50");
ListFormatter list(source.GetAccount());
list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("VHost")).AddColumn(_("Creator")).AddColumn(_("Created"));
list.AddColumn(_("Number")).AddColumn(_("Nick")).AddColumn(_("Vhost")).AddColumn(_("Creator")).AddColumn(_("Created"));
for (const auto &[_, na] : *NickAliasList)
{
if (!na->HasVHost())
if (!na->HasVhost())
continue;
if (!key.empty() && key[0] != '#')
{
if ((Anope::Match(na->nick, key) || Anope::Match(na->GetVHostHost(), key)) && display_counter < listmax)
if ((Anope::Match(na->nick, key) || Anope::Match(na->GetVhostHost(), key)) && display_counter < listmax)
{
++display_counter;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(display_counter);
entry["Number"] = stringify(display_counter);
entry["Nick"] = na->nick;
entry["VHost"] = na->GetVHostMask();
entry["Creator"] = na->GetVHostCreator();
entry["Created"] = Anope::strftime(na->GetVHostCreated(), NULL, true);
entry["Vhost"] = na->GetVhostMask();
entry["Creator"] = na->GetVhostCreator();
entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true);
list.AddEntry(entry);
}
}
@@ -85,11 +88,11 @@ public:
{
++display_counter;
ListFormatter::ListEntry entry;
entry["Number"] = Anope::ToString(display_counter);
entry["Number"] = stringify(display_counter);
entry["Nick"] = na->nick;
entry["VHost"] = na->GetVHostMask();
entry["Creator"] = na->GetVHostCreator();
entry["Created"] = Anope::strftime(na->GetVHostCreated(), NULL, true);
entry["Vhost"] = na->GetVhostMask();
entry["Creator"] = na->GetVhostCreator();
entry["Created"] = Anope::strftime(na->GetVhostCreated(), NULL, true);
list.AddEntry(entry);
}
}
+3 -3
View File
@@ -26,15 +26,15 @@ public:
User *u = source.GetUser();
const NickAlias *na = NickAlias::Find(u->nick);
if (!na || na->nc != u->Account() || !na->HasVHost())
if (!na || na->nc != u->Account() || !na->HasVhost())
na = NickAlias::Find(u->Account()->display);
if (!na || !na->HasVHost())
if (!na || !na->HasVhost())
source.Reply(HOST_NOT_ASSIGNED);
else
{
u->vhost.clear();
IRCD->SendVHostDel(u);
IRCD->SendVhostDel(u);
u->UpdateHost();
Log(LOG_COMMAND, source, this) << "to disable their vhost";
source.Reply(_("Your vhost was removed and the normal cloaking restored."));
+8 -8
View File
@@ -28,16 +28,16 @@ public:
User *u = source.GetUser();
const NickAlias *na = NickAlias::Find(u->nick);
if (!na || na->nc != u->Account() || !na->HasVHost())
if (!na || na->nc != u->Account() || !na->HasVhost())
na = NickAlias::Find(u->Account()->display);
if (na && u->Account() == na->nc && na->HasVHost())
if (na && u->Account() == na->nc && na->HasVhost())
{
source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVHostMask().c_str());
Log(LOG_COMMAND, source, this) << "to enable their vhost of " << na->GetVHostMask();
IRCD->SendVHost(u, na->GetVHostIdent(), na->GetVHostHost());
u->vhost = na->GetVHostHost();
if (IRCD->CanSetVIdent && !na->GetVHostIdent().empty())
u->SetVIdent(na->GetVHostIdent());
source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVhostMask().c_str());
Log(LOG_COMMAND, source, this) << "to enable their vhost of " << na->GetVhostMask();
IRCD->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost());
u->vhost = na->GetVhostHost();
if (IRCD->CanSetVIdent && !na->GetVhostIdent().empty())
u->SetVIdent(na->GetVhostIdent());
u->UpdateHost();
}
else

Some files were not shown because too many files have changed in this diff Show More