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

Compare commits

..

247 Commits

Author SHA1 Message Date
Sadie Powell ab0b851d28 Release 2.1.8. 2024-09-01 09:46:17 +01:00
Sadie Powell 4e3720b810 Merge branch '2.0' into 2.1. 2024-09-01 09:43:38 +01:00
TehPeGaSuS 4b48fc98d3 Fix the documentation of mail:usemail.
`nickserv:registration` only has as options: none, admin, mail.

I assume that `mail` is the word that should replace `yes`
2024-09-01 09:41:32 +01:00
Sadie Powell 82993c8d1e Update the changelogs. 2024-08-30 14:49:43 +01:00
Sadie Powell d352718a39 Fix parsing named extbans on InspIRCd. 2024-08-30 14:49:39 +01:00
Sadie Powell d44632e57d Use CMake's -B option instead of cding to the build directory. 2024-08-30 14:48:31 +01:00
Sadie Powell 80451011dd Remove pointless semicolons in the config for the webcpanel module. 2024-08-29 13:40:39 +01:00
Sadie Powell b4e673b2f4 Refactor ns_getemail slightly. 2024-08-29 13:21:18 +01:00
Sadie Powell 58a78e9aa5 Allow server admins to require that a display nick drops last.
Closes #348.
2024-08-29 13:14:39 +01:00
Sadie Powell 6da4a148fa Fix translating mail:memo_message. 2024-08-24 12:27:05 +01:00
Sadie Powell a3edb09eda Use CanClearBans/SendClearBans when enforcing smartjoin. 2024-08-22 00:29:30 +01:00
Sadie Powell 27beb8f877 Improve the CTCP version output. 2024-08-21 15:38:35 +01:00
Sadie Powell 136680f917 Fix the grammar of some info messages. 2024-08-18 03:17:33 +01:00
Sadie Powell 378ae21ac7 Add account identifier to nickserv/info output. 2024-08-18 01:19:39 +01:00
Sadie Powell e35a86661d Remove support for MinGW.
All of our builds are fully native on Windows so there's no need
for this anymore.
2024-08-15 12:14:06 +01:00
Sadie Powell 528b5938ec Automatically determine SQL column type from the field.
Also add more column types to ensure we are storing data in the
best format in the database.
2024-08-14 05:47:55 +01:00
Sadie Powell 03bee17063 Remove the unused KeySet method in Serialize::Data. 2024-08-14 00:10:12 +01:00
Sadie Powell fe18050c49 Fix parsing SVSMODE and SVS2MODE messages on UnrealIRCd.
At some point UnrealIRCd made an undocumented change to the protocol
where the last parameter on a server-source message would not be a
timestamp. This behaviour is preserved for MODE.
2024-08-09 20:39:46 +01:00
Wilson Birney aa0496f69b Add <cstring> include to services.h to fix build on some musl systems.
Co-authored-by: blackbeard420 <blackbeard@blackbeard420.me>
2024-08-06 11:00:47 +01:00
Sadie Powell 4ee22ab05e Merge branch '2.0' into 2.1. 2024-07-28 22:50:30 +01:00
Sadie Powell 63ad540e55 Add a note to LANGUAGE about rebuilding from scratch. 2024-07-20 19:25:58 +01:00
Sadie Powell a1165eea94 Fix the type of the InspIRCd IJOIN chants when converting. 2024-07-20 19:25:58 +01:00
Sadie Powell bfca74f6b3 Bump for 2.0.17-git. 2024-07-19 13:24:41 +01:00
Sadie Powell 3acf74483c Release 2.0.16. 2024-07-19 12:49:56 +01:00
Sadie Powell a3ec8329f4 Document the previous commit. 2024-07-19 12:48:44 +01:00
Sadie Powell 7d0184ca34 Merge branch '2.0' into 2.1. 2024-07-19 01:43:41 +01:00
Sadie Powell 31bc597c81 Send the vhost/vident before the account name on InspIRCd.
This fixes IRCd-side account cloaks causing CHGHOST spam.
2024-07-19 01:11:32 +01:00
Sadie Powell e0b687f289 Merge branch '2.0' into 2.1. 2024-07-14 16:42:26 +01:00
Sadie Powell 2de0dddb1c Fix joining channels with keys on InspIRCd v3. 2024-07-14 16:39:37 +01:00
Sadie Powell ff65b68dfa Fix the name of the key parameter in SendSVSJoin. 2024-07-14 15:21:00 +01:00
Sadie Powell 94456a6063 Fix sending global messages to remotely linked servers. 2024-07-14 11:44:22 +01:00
Sadie Powell 41ea346551 Update the change log. 2024-07-11 01:13:59 +01:00
Sadie Powell 439ad3e736 Make it clear that inspircd3 also works with InspIRCd 4. 2024-07-11 01:13:59 +01:00
Sadie Powell 347d82f59b Qualify a use of auto in db_atheme. 2024-07-08 00:53:47 +01:00
Sadie Powell fe68f40634 Remove some obsolete echo compatibility wrappers. 2024-07-08 00:53:47 +01:00
ItsOnlyBinary 08b1344056 Add UNIX socket support to mysql module.
Ref: #419
2024-07-04 13:13:56 +01:00
Sadie Powell ff67a80a71 Bump for 2.1.8-git. 2024-07-01 10:08:16 +01:00
Sadie Powell 230e85798d Release 2.1.7. 2024-07-01 10:06:17 +01:00
Sadie Powell 9604690e9d Update the change logs. 2024-06-29 16:25:17 +01:00
Sadie Powell 01e0cf4868 Add support for sending tag messages. 2024-06-24 14:46:41 +01:00
Sadie Powell 693eeed762 Rework how CTCP messages are sent and received. 2024-06-24 14:29:55 +01:00
Sadie Powell 6e5713d64a Remove the formatting overloads of SendNotice/SendPrivmsg. 2024-06-24 13:30:17 +01:00
Sadie Powell 249ad3dfea Update the Turkish translation.
Co-authored-by: CaPa CuL <capacul@gmail.com>
2024-06-23 18:36:00 +01:00
Sadie Powell b94c3740b9 Make the language around fantasy commands less weird. 2024-06-23 14:36:03 +01:00
Sadie Powell 59ec42f0e6 Rename suspend in cs_expire to suspendexpire to match ns_expire. 2024-06-23 13:55:25 +01:00
Sadie Powell 8a65f116b6 Merge branch '2.0' into 2.1. 2024-06-23 13:52:46 +01:00
Sadie Powell 8105607257 Fix the default config for channel suspensions. 2024-06-23 13:51:53 +01:00
Sadie Powell 601da1141e Fix the default config for channel suspensions. 2024-06-23 13:50:50 +01:00
Sadie Powell 8c0edef714 Split nickserv/{sa,}set/language out to its own module. 2024-06-22 17:46:42 +01:00
Sadie Powell c3efd9426d Update the change log. 2024-06-20 17:16:16 +01:00
Sadie Powell a386439f86 Misc improvements to db_atheme. 2024-06-20 17:16:16 +01:00
Sadie Powell 016a5b3903 Fix importing Atheme mode locks. 2024-06-20 17:16:16 +01:00
Sadie Powell 60aeb2a71a Silently ignore some Atheme metadata that we know we can't import. 2024-06-19 22:45:43 +01:00
Sadie Powell 54ea63df66 Avoid creating extra service references in db_atheme. 2024-06-19 22:44:31 +01:00
Sadie Powell 01fc3ea22e Fix importing Atheme opers. 2024-06-19 22:44:31 +01:00
Sadie Powell 3388736fab Use auto in more places in db_atheme. 2024-06-19 22:44:31 +01:00
Sadie Powell 0065a0f405 Only import clones from Atheme if we recognise the database version. 2024-06-19 22:44:16 +01:00
Sadie Powell 490f832dc0 Fix importing Atheme session limits. 2024-06-19 21:12:28 +01:00
Sadie Powell a44acb6de5 Fix importing Atheme forbid reasons. 2024-06-19 20:31:55 +01:00
Sadie Powell 13e5ddf807 Fix importing Atheme akick reasons. 2024-06-19 20:22:57 +01:00
Sadie Powell e42c728ab8 Log the channel that a mode lock was unable to be imported for. 2024-06-19 19:41:16 +01:00
Sadie Powell 4eec5c5435 Save the databases directly after importing. 2024-06-19 19:30:24 +01:00
Sadie Powell 2667d9e90c Update the databases more regularly. 2024-06-19 11:28:21 +01:00
Sadie Powell f2b66278aa Fix a string that should be marked as translatable in ns_info. 2024-06-12 17:53:15 +01:00
Sadie Powell 5b7d952626 Remove the broken Catalan, Hungarian, and Russian translations. 2024-06-12 17:50:00 +01:00
Sadie Powell 24375d53e6 Add support for looking up account information from a nick.
Closes #407.
2024-06-12 17:46:07 +01:00
Sadie Powell 88ac47e217 The sender can be null in OnBotUnAssign. 2024-06-10 12:51:56 +01:00
Sadie Powell 8a1bffba9b Fix a crash in ns_cert. 2024-06-10 11:16:05 +01:00
TehPeGaSuS 01eef7a392 Rename example.chk to cron.example.sh. 2024-06-07 23:23:44 +01:00
Sadie Powell 67b76fadca Fix a memory leak in os_akill and os_sxline. 2024-06-07 22:39:08 +01:00
Sadie Powell 7861712437 Add nullability attributes to the module events. 2024-06-07 22:15:58 +01:00
Sadie Powell ccc088d946 Log a user out fully when their nick gets suspended.
Closes #409.
2024-06-04 22:41:32 +01:00
Sadie Powell 4468fe77fa Fix an inverted if in the global odule. 2024-06-03 20:02:03 +01:00
Sadie Powell e71a9e2894 Avoid NickAlias lookups by storing a pointer in the NickCore. 2024-06-03 16:04:53 +01:00
Sadie Powell f80bdf06ba Fix a null pointer dereference in the sasl module. 2024-06-03 14:39:08 +01:00
Sadie Powell 2d6033c73f Bump for 2.1.7-git. 2024-06-01 09:44:43 +01:00
Sadie Powell 756dc49813 Release 2.1.6. 2024-06-01 09:43:36 +01:00
Sadie Powell aa92559aa0 Document the previous commit. 2024-06-01 09:43:20 +01:00
Sadie Powell eb12a89b8e Fix creating the runtime directory on Windows. 2024-05-28 01:07:27 +01:00
Sadie Powell d4a34308e5 Update the change logs. 2024-05-23 16:02:54 +01:00
Sadie Powell aab3a8e5b6 Clarify that one non-deprecated protocol module must be loaded. 2024-05-23 15:40:56 +01:00
Sadie Powell c72e12d0a6 Fix setting the history mode on UnrealIRCd.
Closes #406.
2024-05-22 15:08:13 +01:00
Sadie Powell bce0d629fd Fix another iterator invalidation issue. 2024-05-22 14:30:18 +01:00
Sadie Powell 7d0dacc86c Change --modulesdir to be singular like the other config options. 2024-05-22 10:30:03 +01:00
Sadie Powell 729aa4ab4a Fix parsing the flood mode on UnrealIRCd. 2024-05-18 18:36:17 +01:00
Sadie Powell 18e9e12261 Fix an iterator invalidation issue in cs_set and ns_set. 2024-05-18 16:35:35 +01:00
TehPeGaSuS 9d68b29c9e Initial Portuguese retranslation. 2024-05-17 17:24:24 +01:00
Sadie Powell a4792412ba Merge branch '2.0' into 2.1. 2024-05-16 18:00:13 +01:00
Sadie Powell 8bb83f6b1a Explicitly specify ROW_FORMAT=DYNAMIC when creating tables.
Resolves the issues some people were having with extremely wide rows.
2024-05-16 17:29:25 +01:00
Sadie Powell da99a53dfa Don't specify a width for DT_INT columns.
This isn't actually used by MySQL for the column width.
2024-05-16 17:28:15 +01:00
Sadie Powell a9e9ac32a0 Store boolean extension items as DT_INT. 2024-05-16 17:28:15 +01:00
Sadie Powell 05e6df23a2 Mark boolean columns as DT_INT in bs_kick. 2024-05-16 16:50:41 +01:00
Sadie Powell 3f9fc23270 Remove some unnecessary advice. 2024-05-16 16:44:38 +01:00
Sadie Powell cb21c7c1fa Fix some untranslated strings in the Turkish translation. 2024-05-11 18:35:17 +01:00
Sadie Powell 4008e64f26 Store when the account name was registered in the NickCore. 2024-05-11 17:40:38 +01:00
Sadie Powell 1cf5918574 Merge branch '2.0' into 2.1. 2024-05-11 14:24:37 +01:00
Sadie Powell afe87bf693 Ensure we are connected to MySQL before trying to escape data. 2024-05-11 11:36:29 +01:00
Sadie Powell ff1c5adb8b Always use server-side topic and mode locks where available. 2024-05-10 19:03:50 +01:00
Sadie Powell c36030c826 Remove CanSVSLogout and implement logout support on Plexus. 2024-05-09 18:54:40 +01:00
Sadie Powell 33a02b1223 Require a reason when throwing an exception. 2024-05-09 18:37:16 +01:00
Sadie Powell 68f4556609 Store an IP in CommandSource for IRC messages too. 2024-05-06 17:08:37 +01:00
Sadie Powell 23db58a303 Change badpasslimit from int to unsigned int. 2024-05-06 16:42:13 +01:00
Sadie Powell ee69dc3105 Fix parsing backup client certificate fingerprints on InspIRCd. 2024-05-01 21:21:19 +01:00
Sadie Powell e9243c3fde Add the ReplaceCert method to CertService. 2024-05-01 21:20:31 +01:00
Sadie Powell 4cfee23303 Simplify InspIRCd user metadata handler slightly. 2024-05-01 20:20:47 +01:00
Sadie Powell be3822523b Automatically add client certificates to the cert list on register. 2024-05-01 17:23:10 +01:00
dependabot[bot] 111f81aa95 Bump microsoft/setup-msbuild from 1.3 to 2
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.3 to 2.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.3...v2)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 17:20:06 +01:00
Sadie Powell f12e1ad222 Bump for 2.1.6-git. 2024-05-01 14:37:06 +01:00
Sadie Powell 72318a6bf0 Release 2.1.5. 2024-05-01 14:16:09 +01:00
Sadie Powell 2f77cb38e2 Update the changelogs. 2024-05-01 14:15:17 +01:00
Sadie Powell 84ca4c0d27 Update the inspircd module for recent 1206 protocol changes. 2024-05-01 14:03:11 +01:00
Sadie Powell 1f9a197b18 Merge branch '2.0' into 2.1. 2024-04-29 08:36:23 +01:00
Sadie Powell 0c5bf51378 Skip serializing data without a type in db_flatfile. 2024-04-29 08:16:45 +01:00
Sadie Powell 1647968c50 Fix message truncation in global/global and global/server. 2024-04-28 08:52:16 +01:00
Sadie Powell 5473311bd7 Only enable os_noop on IRCDs that actually have a SendSVSNOOP impl. 2024-04-15 21:08:40 +01:00
Sadie Powell f3ebb67469 Make SendChannel abstract. 2024-04-15 21:00:10 +01:00
Sadie Powell 0d149ce195 Install a systemd service file on Linux. 2024-04-15 20:29:57 +01:00
Sadie Powell d68ba1b570 Implement support for BIGLINES on UnrealIRCd. 2024-04-15 20:05:43 +01:00
Sadie Powell 1877833e73 Bump Bahamut support to require 2.0 or newer. 2024-04-15 18:29:36 +01:00
Sadie Powell 63c3710785 Fix some missing translations in the tr_TR translation. 2024-04-15 15:32:19 +01:00
Sadie Powell 0043d137e5 Update the Turkish translation for the changes in 2.1.4.
Co-authored-by: CaPa CuL <capacul@gmail.com>
2024-04-15 15:26:55 +01:00
Sadie Powell 3e5d3c5bdc Avoid packaging unnecessary .lib files on Windows.
[skip alpine ci]
[skip ubuntu ci]
2024-04-15 12:41:56 +01:00
Sadie Powell 62deedfa75 Automatically upload the Windows package on release.
[skip alpine ci]
[skip ubuntu ci]
2024-04-15 11:57:40 +01:00
Sadie Powell 44af4eac6b Update the Windows CI to the latest Conan. 2024-04-15 11:11:40 +01:00
Sadie Powell 5fdc637327 Expand relative paths when installing. 2024-04-14 12:23:19 +01:00
Sadie Powell 7c93007aa6 Avoid duplicate entries in ReplaceCert. 2024-04-14 12:23:19 +01:00
Robert Scheck e8fee93a7e Fix a typo in the example configs. 2024-04-14 09:21:50 +01:00
Sadie Powell 260539e987 Add more documentation for overriding confirmation codes. 2024-04-07 15:52:24 +01:00
Sadie Powell 4603cd467b Add an operator privilege to allow overriding drop codes.
Closes #392
2024-04-05 14:14:10 +01:00
Sadie Powell 00549bc9b2 Merge branch '2.0' into 2.1. 2024-04-04 19:59:19 +01:00
Sadie Powell e0a6f7456b Fix extracting timestamps from UnrealIRCd MODE messages.
Oversight from commit 04e1a4f5c8.
2024-04-04 19:48:34 +01:00
Sadie Powell 5a54b37aeb Remove the g prefix from git hashes. 2024-04-04 14:16:21 +01:00
Sadie Powell 2e43665266 Log the services directory when chdiring to it. 2024-04-04 14:02:57 +01:00
Sadie Powell 8b4cd65e2a Fix erroring out when sendmailpath is empty.
This has a default now.
2024-04-02 16:52:41 +01:00
Sadie Powell c08aaa86d1 Sync the build system directory names with the core. 2024-04-02 16:52:41 +01:00
Sadie Powell 87a8af0ad7 Use the paths from the build system instead of hardcoding them. 2024-04-02 16:45:49 +01:00
Sadie Powell 4691dfa3f0 Bump for 2.1.5-git. 2024-04-01 11:26:07 +01:00
Sadie Powell 507eefc820 Release 2.1.4. 2024-04-01 11:24:48 +01:00
Sadie Powell 72af764861 Fix some typos in the changelog. 2024-03-31 15:21:18 +01:00
Sadie Powell 1b631e96bd Add a default value for sendmailpath. 2024-03-31 15:17:03 +01:00
Sadie Powell 3b4a4da52d Update the changelogs. 2024-03-29 14:24:17 +00:00
Sadie Powell 2e59aac025 Fix the default value of accessmax in cs_access. 2024-03-29 14:21:51 +00:00
Sadie Powell 3de6da80c6 Alias ACCESS to ALIST now the former is unused. 2024-03-27 23:32:16 +00:00
Sadie Powell 2829c83118 Add more nick options to webcpanel's nickserv/info page. 2024-03-26 14:27:52 +00:00
Sadie Powell f58012ea0e Remove some leftover references to nickserv/access. 2024-03-26 13:40:53 +00:00
Sadie Powell f8605ec188 Allow specifying the webcpanel template directory directly.
There's no need to hardcode a base path here.
2024-03-26 12:59:03 +00:00
Sadie Powell 5a12beff15 Fix some spelling issues in the webcpanel that were missed earlier. 2024-03-26 12:33:59 +00:00
Sadie Powell 6b1f8de885 Use consistent headers and footers on all webcpanel templates. 2024-03-26 11:52:04 +00:00
Sadie Powell 33be5de66e Flatten the webcpanel hierarchy slightly. 2024-03-26 11:22:43 +00:00
Sadie Powell 4399eeaa58 Add the --nopid option to disable writing a pidfile.
This is useful for init scripts that don't fork.
2024-03-20 21:34:28 +00:00
Sadie Powell 38cfb0603a Fix deleting pidfiles. 2024-03-20 21:34:18 +00:00
Sadie Powell 1a3844e74e Fix the Windows build. 2024-03-19 15:58:41 +00:00
Sadie Powell bfed2e1bf5 Use paths relative to data/conf in the config file.
This was done in some places already but not consistently.

Closes #349.
2024-03-19 15:51:55 +00:00
Sadie Powell e488f294a1 Put the webcpanel directory in the data directory not a subdir. 2024-03-19 15:19:15 +00:00
Sadie Powell fde3438ef2 Allow using absolute paths in more places. 2024-03-19 15:11:40 +00:00
Sadie Powell 1575dea5b9 Redocument deprecated encryption modules. 2024-03-19 12:40:01 +00:00
Sadie Powell a1972ba9b6 Prevent using enc_posix as a primary encryption module. 2024-03-19 11:54:39 +00:00
Sadie Powell 5a72d8783e Add verify-only support for POSIX crypt() hashes from Atheme. 2024-03-18 22:17:14 +00:00
Sadie Powell e6770bc2fd Fix an off by one error in enc_sha2. 2024-03-18 22:04:57 +00:00
Sadie Powell 413fed474e Fix unnecessary uses of std::string. 2024-03-18 12:47:43 +00:00
Sadie Powell 60083834f8 Improve sending email.
- Use consistent line endings as expected by the email spec.
- Don't require admins to escape . at the start of lines.
- Log the reason why sending email fails.
2024-03-18 12:34:34 +00:00
Sadie Powell 9ac4da0489 Fix not storing the start time after calling UpdateTime. 2024-03-18 11:45:33 +00:00
Sadie Powell cb3848b7db Use clock_gettime if it is available. 2024-03-18 11:27:10 +00:00
Sadie Powell d41764bfd6 Fix sending emails to nicks ending with a backslash. 2024-03-15 18:52:12 +00:00
Sadie Powell 753119c4a1 Use consistent casing when referring to vhosts and vidents. 2024-03-15 12:42:13 +00:00
Sadie Powell d996c3aa8f Fix a format-extra-args warning on some versions on GCC. 2024-03-15 12:22:22 +00:00
dependabot[bot] ac6e8c617d Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-15 12:19:07 +00:00
Sadie Powell 3b09f4aa54 Merge branch '2.0' into 2.1. 2024-03-15 12:17:49 +00:00
Sadie Powell 10f4724b6b Dependabot requires that the target-branch is a string. 2024-03-15 12:17:15 +00:00
Sadie Powell ad86535024 Consistently use READ_ONLY_MODE everywhere. 2024-03-15 12:09:58 +00:00
Sadie Powell 628f4d2a7e Merge branch '2.0' into 2.1. 2024-03-15 11:58:09 +00:00
Sadie Powell 8d5be77c93 Send dependabot pull requests to the 2.1 branch. 2024-03-15 11:56:56 +00:00
Sadie Powell 13a556df89 Initialize timer members with constructor initialization. 2024-03-14 23:19:32 +00:00
Sadie Powell 4e9d183523 Restore some functionality that was removed in an earlier commit. 2024-03-14 23:10:53 +00:00
Sadie Powell 074dfb63a7 Fix a warning when building with Clang. 2024-03-14 21:37:18 +00:00
Sadie Powell beaf09de7b Rework sending global notices.
Admins can now queue multiple messages and send them when they are
ready. This is fully compatible with the previous global behaviour.

Admins can now also send messages to individual servers. This is
useful for informing users of maintenance due to downtime.
2024-03-14 21:35:17 +00:00
Sadie Powell c8d8978cd0 Require that at least one encryption module is loaded. 2024-03-12 21:57:38 +00:00
Sadie Powell 11edba04fe Add command handlers for encap commands on InspIRCd. 2024-03-12 21:57:06 +00:00
Sadie Powell 22ba54b00d Show the full command in CONFIRM_DROP. 2024-03-12 19:24:31 +00:00
Sadie Powell 6fd7ca39e2 Fix the reason when kicking users from suspended channels.
Closes #372.
2024-03-12 17:00:42 +00:00
Sadie Powell b8cd00b412 Merge branch '2.0' into 2.1. 2024-03-12 16:50:30 +00:00
Sadie Powell f4bd43e898 Add a workaround for users matching expired sqlines.
I'll fix this properly in 2.1 because I don't want to make big
changes to 2.0.

Closes #384.
2024-03-12 16:47:57 +00:00
Sadie Powell 7d7664444a Fix expiring forbids. 2024-03-12 16:26:33 +00:00
Sadie Powell 1a8bbd6004 Respect --noexpire in cs_suspend and ns_suspend. 2024-03-12 14:43:12 +00:00
Sadie Powell e725c880a9 Fix expiring channel suspensions.
Closes #386.
2024-03-12 14:12:37 +00:00
Sadie Powell f5abcd1c4c Fix expiring nick suspensions.
Closes #376.
2024-03-12 14:02:16 +00:00
Sadie Powell 1986aa6581 Fix duplicate messages when synconset/syncongroup is set.
Closes #366.
2024-03-12 13:26:25 +00:00
Sadie Powell b52e1b2b02 Implement support for challenge authentication on InspIRCd. 2024-03-12 13:19:20 +00:00
Sadie Powell 54719fbfc6 Allow protocol modules to declare that they have no line/mode limit.
InspIRCd allows us to send infinite length lines and mode changes
and will restack before sending to users.
2024-03-12 12:39:33 +00:00
Sadie Powell 06add0e5fc Simplify limit extraction code. 2024-03-12 12:24:02 +00:00
Sadie Powell 63d682314b Merge branch '2.0' into 2.1. 2024-03-12 11:53:14 +00:00
Sadie Powell 1a6060ac5b Fix sending SVSTOPIC when topiclock is loaded on InspIRCd. 2024-03-12 11:46:41 +00:00
Sadie Powell a302f8f1be Refactor sending vhosts in the InspIRCd protocol module. 2024-03-12 11:43:21 +00:00
Sadie Powell 04e1a4f5c8 Add a protocol module function for extracting timestamps. 2024-03-12 11:02:08 +00:00
Sadie Powell 1538909ac0 Add ProtocolException and use it to send fatal errors. 2024-03-12 00:17:49 +00:00
Sadie Powell a15f165a1d Fix an inverted condition in enc_bcrypt. 2024-03-12 00:17:49 +00:00
Sadie Powell 77435dd0d9 Merge branch '2.0' into 2.1. 2024-03-11 22:43:29 +00:00
Sadie Powell 6f57907416 Fix the TIME message on InspIRCd. 2024-03-11 22:38:15 +00:00
Sadie Powell 7c1cfd2849 Fix comparing passwords in enc_sha256. 2024-03-11 21:07:39 +00:00
Sadie Powell 259b10b83a Fix some InspIRCd 1206 protocol compatibility issues. 2024-03-11 20:27:30 +00:00
Sadie Powell 02355546ff Reject registrations and password changes if password encryption fails. 2024-03-11 19:39:47 +00:00
Sadie Powell 6ad3430ac4 Clean up some dead code in ns_register. 2024-03-11 19:30:57 +00:00
Sadie Powell 29e7674e56 Replace convertTo/stringify with non-throwing alternatives.
Having these throw is terrible for ergonomics and there are loads
of places where the exception was either silently ignored or not
handled at all. Having a function which returns an optional and
another that returns a default works a lot better imo.
2024-03-11 19:17:29 +00:00
Bram Matthys b09632d1c3 Fix OS SQLINE expiry with UnrealIRCd 2024-03-11 18:30:55 +00:00
Sadie Powell e2df7d4d01 Ensure that verify-only encryption modules can never encrypt passwords.
If another module was loaded first and then later unloaded it was
possible for a deprecated module to encrypt passwords.
2024-03-10 20:46:03 +00:00
Sadie Powell 9a984a8148 Implement verify-only support for raw SHA-2 passwords. 2024-03-10 20:46:03 +00:00
Sadie Powell fb9c8950ed Refactor the enc_bcrypt module and expose an encryption provider. 2024-03-10 20:46:03 +00:00
Sadie Powell a849a81ac3 Refactor the enc_old module. 2024-03-10 20:28:00 +00:00
Sadie Powell f919bb0748 Add self-tests to the encryption providers. 2024-03-10 20:20:24 +00:00
Sadie Powell 3b85a8071f Add some missing documentation comments. 2024-03-10 15:58:58 +00:00
Sadie Powell 9a8cac060d Add support for encrypting passwords with the Argon2 algorithm.
Closes #369.
2024-03-10 15:09:38 +00:00
Sadie Powell 0353338436 Replace the custom SHA-2 implementation in enc_sha256. 2024-03-10 12:27:49 +00:00
Sadie Powell defb8348a7 Move the HMAC function to the encryption header.
This will be useful for doing challenge authentication on InspIRCd.
2024-03-09 22:51:23 +00:00
Sadie Powell 1b86665d81 Add a stats category for password encryption algorithms. 2024-03-09 22:22:56 +00:00
Sadie Powell 2f52fa723c Redocument the encryption module config. 2024-03-09 22:22:56 +00:00
Sadie Powell 6e0f0b8896 Add the enc_sha2 module which hashes passwords with HMAC-SHA-2.
Using HMAC instead of changing the IV is a lot safer.
2024-03-09 22:22:56 +00:00
Sadie Powell 2c5b2c649e Convert enc_md5 to use a vendored MD5 library. 2024-03-09 22:22:56 +00:00
Sadie Powell a6bc4cab9d Misc improvements to the encryption API. 2024-03-09 22:22:56 +00:00
Sadie Powell ef37daf44a Clean up the services.h includes. 2024-03-09 22:22:56 +00:00
Sadie Powell 39d288f99f Rename hash_map to unordered_map to match the underlying container. 2024-03-09 22:22:56 +00:00
Sadie Powell 9ead3f15c3 Save the last email time for accounts. 2024-03-09 22:22:55 +00:00
Sadie Powell 272104af95 Modernize the initialisation of NickAlias and NickCore. 2024-03-09 22:22:55 +00:00
Bram Matthys 51e95d72e3 Enable message-tags support for UnrealIRCd 2024-03-09 14:53:38 +00:00
Sadie Powell 12486f6cee Tweak the config default limits slightly. 2024-03-09 11:43:38 +00:00
Sadie Powell 891375baca Use a separate CAPAB handler on InspIRCd to avoid pollution. 2024-03-08 19:05:12 +00:00
Sadie Powell 41a295202e Only enable InspIRCd parser logging when using --protocoldebug. 2024-03-08 18:17:17 +00:00
Sadie Powell 722c5b7d61 Implement support for the InspIRCd 1206 protocol. 2024-03-08 17:12:44 +00:00
Sadie Powell 52216b56a1 Merge branch '2.0' into 2.1. 2024-03-08 17:05:49 +00:00
Sadie Powell cd614831de Fix feature detection on InspIRCd. 2024-03-08 16:49:55 +00:00
Sadie Powell 1d0a836a2e Improve protocol debug messages. 2024-03-08 12:24:44 +00:00
Sadie Powell 46b7064834 Keep the InspIRCd protocol version around for later use. 2024-03-08 11:07:30 +00:00
Sadie Powell bb8df01e25 Move some modules which can be built by default out of extra. 2024-03-07 23:18:08 +00:00
Sadie Powell 16700b0e30 Remove a guarantee that may not necessarily be correct. 2024-03-07 23:09:25 +00:00
Sadie Powell 4e04a11995 Consistently use email instead of e-mail. 2024-03-07 22:52:41 +00:00
Sadie Powell 76e5480be9 Update the changelogs. 2024-03-07 22:52:41 +00:00
Sadie Powell 464e6b8010 Use the C++11 random number generator instead of rand().
This is safer, faster, and doesn't require seeding.
2024-03-07 22:52:41 +00:00
Sadie Powell 3272c1bbc6 Require new accounts to have email addresses. 2024-03-07 22:25:32 +00:00
Sadie Powell 307ffea951 Update the English translation for the previous commit.
y
2024-03-07 21:19:47 +00:00
Sadie Powell bb94f286f5 Also use drop confirmation codes for nicknames. 2024-03-07 21:18:06 +00:00
Sadie Powell 86e3556438 Fix some misc bugs in the InspIRCd protocol module.
Closes #373.
2024-03-07 20:55:22 +00:00
Sadie Powell 12214bee72 Add the initial version of the Atheme database importer. 2024-03-07 18:50:36 +00:00
Sadie Powell 08a35231ef Merge branch '2.0' into 2.1. 2024-03-04 12:10:22 +00:00
Sadie Powell 9649dc78a1 When using ldap/sql auth prevent displays expiring before their group.
This prevents zombie accounts from being left around that can't be
authenticated to.

Closes #355.
2024-03-04 12:08:28 +00:00
Sadie Powell 9970b4e37b Bump for 2.1.4-git. 2024-03-04 11:09:51 +00:00
Sadie Powell a5a615d5c7 Release 2.1.3. 2024-03-04 11:09:51 +00:00
Sadie Powell ce97fdd1c6 Update the changelogs. 2024-03-04 11:09:51 +00:00
Sadie Powell 1a8ae513b4 Add NickAlias::GetVhostMask for getting the vident@vhost. 2024-03-04 11:09:50 +00:00
258 changed files with 11577 additions and 39494 deletions
+1
View File
@@ -4,3 +4,4 @@ updates:
directory: /
schedule:
interval: monthly
target-branch: "2.1"
+2 -1
View File
@@ -20,6 +20,7 @@ jobs:
echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
apk update
apk add \
argon2-dev \
clang \
cmake \
g++ \
@@ -36,7 +37,7 @@ jobs:
- name: Enable extras
run: |
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
for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
do
ln -s $PWD/modules/extra/$MODULE.cpp $PWD/modules
done
+2 -1
View File
@@ -20,6 +20,7 @@ jobs:
g++ \
gettext \
git \
libargon2-dev \
libgnutls28-dev \
libldap2-dev \
libmysqlclient-dev \
@@ -31,7 +32,7 @@ jobs:
- name: Enable extras
run: |
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
for MODULE in enc_argon2 enc_posix ldap mysql regex_pcre2 regex_posix regex_tre sqlite ssl_gnutls ssl_openssl
do
ln -s ${{ github.workspace }}/modules/extra/$MODULE.cpp ${{ github.workspace }}/modules
done
+16 -5
View File
@@ -2,6 +2,9 @@ name: Windows CI
on:
pull_request:
push:
release:
types:
- published
schedule:
- cron: '0 0 * * 0'
jobs:
@@ -9,15 +12,15 @@ jobs:
if: "!contains(github.event.head_commit.message, '[skip windows ci]')"
runs-on: windows-2019
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.3
uses: microsoft/setup-msbuild@v2
- name: Setup Conan
uses: turtlebrowser/get-conan@v1.2
with:
version: 1.59.0
version: 1.64.0
- name: Install libraries
run: |
@@ -27,9 +30,17 @@ jobs:
run: |
mkdir ${{ github.workspace }}\build
cd ${{ github.workspace }}\build
cmake -A "x64" -G "Visual Studio 16 2019" ..
cmake -A "x64" -D "CMAKE_BUILD_TYPE=${{ github.event_name == 'release' && 'Release' || 'Debug' }}" -G "Visual Studio 16 2019" ..
- name: Build Anope
working-directory: ${{ github.workspace }}\build
run: |
msbuild PACKAGE.vcxproj /M:3 /P:Configuration=Release /P:Platform=x64 /VERBOSITY:MINIMAL
msbuild PACKAGE.vcxproj /M:3 /P:Configuration=${{ github.event_name == 'release' && 'Release' || 'Debug' }} /P:Platform=x64 /VERBOSITY:MINIMAL
- name: Upload installer
if: "${{ github.event_name == 'release' }}"
working-directory: ${{ github.workspace }}\build
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ github.event.release.tag_name }} $(Get-ChildItem anope-*.exe)
+2 -5
View File
@@ -1,16 +1,13 @@
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
+18 -30
View File
@@ -31,12 +31,8 @@ if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang$")
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-search-dirs OUTPUT_VARIABLE LINES OUTPUT_STRIP_TRAILING_WHITESPACE)
# Find only the part after "libraries: "
string(REGEX REPLACE ".*\nlibraries: (.*)$" "\\1" LINE "${LINES}")
# Replace the colons in the list with semicolons (only when not on MinGW, which uses semicolons already), and if on MinGW, just copy the line
if(NOT MINGW)
string(REGEX REPLACE ":" ";" LIBRARIES ${LINE})
else()
set(LIBRARIES "${LINE}")
endif()
# Replace the colons in the list with semicolons
string(REGEX REPLACE ":" ";" LIBRARIES ${LINE})
# Iterate through the libraries
foreach(LIBRARY ${LIBRARIES})
# Check if the first character is an equal sign, and skip that library directory as it is (I believe) the primary default and shows up later in the list anyways
@@ -106,13 +102,6 @@ if(NOT MSVC)
endif()
endif()
# If running under MinGW, we have to force the resource compiler settings (hopefully this will be fixed in a later version of CMake)
if(MINGW)
set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC)
set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> <FLAGS> <DEFINES> -o <OBJECT> <SOURCE>")
endif()
# Include the checking functions used later in this CMakeLists.txt
include(CheckFunctionExists)
include(CheckTypeSize)
@@ -189,11 +178,6 @@ if(CMAKE_THREAD_LIBS_INIT)
list(APPEND LINK_LIBS ${CMAKE_THREAD_LIBS_INIT})
endif()
# Under MinGW, the -shared flag isn't properly set in the module-specific linker flags, add it from the C flags for shared libraries
if(MINGW)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS}")
endif()
if(NOT PROGRAM_NAME)
set(PROGRAM_NAME anope)
endif()
@@ -224,6 +208,7 @@ 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)
@@ -255,8 +240,8 @@ endif()
if(NOT BIN_DIR)
set(BIN_DIR "bin")
endif()
if(NOT DB_DIR)
set(DB_DIR "data")
if(NOT DATA_DIR)
set(DATA_DIR "data")
endif()
if(NOT DOC_DIR)
set(DOC_DIR "doc")
@@ -264,14 +249,14 @@ endif()
if(NOT CONF_DIR)
set(CONF_DIR "conf")
endif()
if(NOT LIB_DIR)
set(LIB_DIR "lib")
if(NOT MODULE_DIR)
set(MODULE_DIR "modules")
endif()
if(NOT LOCALE_DIR)
set(LOCALE_DIR "locale")
endif()
if(NOT LOGS_DIR)
set(LOGS_DIR "logs")
if(NOT LOG_DIR)
set(LOG_DIR "logs")
endif()
# Version number processing
@@ -349,15 +334,17 @@ set(SERVICES_BINARY "$<TARGET_FILE:${PROGRAM_NAME}>")
get_filename_component(SERVICES_BINARY ${SERVICES_BINARY} NAME)
# At install time, create the following additional directories
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${LOGS_DIR}\")")
get_filename_component(ABSOLUTE_DATA_DIR ${DATA_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
get_filename_component(ABSOLUTE_LOG_DIR ${LOG_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/backups\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_LOG_DIR}\")")
if(WIN32)
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${DB_DIR}/runtime\")")
install(CODE "file(MAKE_DIRECTORY \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/runtime\")")
endif()
# On non-Windows platforms, if RUNGROUP is set, change the permissions of the below directories, as well as the group of the data directory
if(NOT WIN32 AND RUNGROUP)
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${DB_DIR}/backups\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/\${LOGS_DIR}\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${ABSOLUTE_DATA_DIR}/backups\")")
install(CODE "execute_process(COMMAND ${CHMOD} 2775 \"\$ENV{DESTDIR}${ABSOLUTE_LOG_DIR}\")")
install(CODE "execute_process(COMMAND ${CHGRP} -R ${RUNGROUP} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}\")")
endif()
# On Windows platforms, install extra files
@@ -367,7 +354,8 @@ if(WIN32)
)
endif()
install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIB_DIR}/modules\")")
get_filename_component(ABSOLUTE_MODULE_DIR ${MODULE_DIR} REALPATH BASE_DIR ${CMAKE_INSTALL_PREFIX})
install(CODE "file(REMOVE_RECURSE \"$ENV{DESTDIR}${ABSOLUTE_MODULE_DIR}\")")
# Only process the CPack section if we have CPack
if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
+18 -43
View File
@@ -13,10 +13,6 @@
#
###########################################################################
echo2 () {
$ECHO2 "$*$ECHO2SUF" # these are defined later
}
exists () { # because some shells don't have test -e
if [ -f $1 -o -d $1 -o -p $1 -o -c $1 -o -b $1 ] ; then
return 0
@@ -42,7 +38,6 @@ Run_Build_System () {
WITH_PERM=""
EXTRA_INCLUDE=""
EXTRA_LIBS=""
GEN_TYPE=""
if [ "$INSTDIR" != "" ] ; then
WITH_INST="-DINSTDIR:STRING=$INSTDIR"
@@ -70,45 +65,25 @@ Run_Build_System () {
EXTRA_LIBS="-DEXTRA_LIBS:STRING=$EXTRA_LIB_DIRS"
fi
if [ "$SOURCE_DIR" = "." ] ; then
pwdsave=`pwd`
test -d build || mkdir build
cd "build"
REAL_SOURCE_DIR=".."
else
REAL_SOURCE_DIR="$SOURCE_DIR"
fi
BUILD_PATHS="-B ${SOURCE_DIR}/build ${SOURCE_DIR}"
echo "cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR"
CMAKE="cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $BUILD_PATHS"
echo $CMAKE
$CMAKE
cmake $GEN_TYPE $WITH_INST $WITH_RUN $WITH_PERM $BUILD_TYPE $EXTRA_INCLUDE $EXTRA_LIBS $EXTRA_CONFIG_ARGS $REAL_SOURCE_DIR
if [ $? -ne 0 ]; then
echo "You should fix these issues and then run ./Config -quick to rerun CMake."
exit 1
fi
echo ""
if [ "$SOURCE_DIR" = "." ] ; then
echo "Now cd build, then run make to build Anope."
cd "$pwdsave"
else
if [ "$PWD" = "${SOURCE_DIR}/build" ]; then
echo "Now run make to build Anope."
else
echo "Now cd build, then run make to build Anope."
fi
}
ECHO2SUF=''
if [ "`echo -n a ; echo -n b`" = "ab" ] ; then
ECHO2='echo -n'
elif [ "`echo 'a\c' ; echo 'b\c'`" = "ab" ] ; then
ECHO2='echo' ; ECHO2SUF='\c'
elif [ "`printf 'a' 2>&1 ; printf 'b' 2>&1`" = "ab" ] ; then
ECHO2='printf "%s"'
else
# oh well...
ECHO2='echo'
fi
export ECHO2 ECHO2SUF
###########################################################################
# Init values
###########################################################################
@@ -121,7 +96,7 @@ EXTRA_INCLUDE_DIRS=
EXTRA_LIB_DIRS=
EXTRA_CONFIG_ARGS=
CAN_QUICK="no"
SOURCE_DIR=`dirname $0`
SOURCE_DIR="$(cd "$(dirname "$0")" && pwd)"
###########################################################################
# Check out the options
@@ -138,7 +113,7 @@ while [ $# -ge 1 ] ; do
exit 0
elif [ $1 = "-devel" ] ; then
DEBUG="yes"
INSTDIR="$PWD/run"
INSTDIR="$SOURCE_DIR/run"
elif [ $1 = "-nocache" ] ; then
IGNORE_CACHE="1"
elif [ $1 = "-nointro" ] ; then
@@ -199,7 +174,7 @@ export ok INPUT
ok=0
echo "In what directory should Anope be installed?"
while [ $ok -eq 0 ] ; do
echo2 "[$INSTDIR] "
echo -n "[$INSTDIR] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$INSTDIR
@@ -209,7 +184,7 @@ while [ $ok -eq 0 ] ; do
echo "$INPUT exists, but is not a directory!"
else
echo "$INPUT does not exist. Create it?"
echo2 "[y] "
echo -n "[y] "
read YN
if [ "$YN" != "n" ] ; then
if mkdir -p $INPUT ; then
@@ -238,7 +213,7 @@ else
echo "should not force files to be owned by a particular group, just press"
echo "Return.)"
fi
echo2 "[$RUNGROUP] "
echo -n "[$RUNGROUP] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "none" ] ; then
@@ -263,7 +238,7 @@ ok=0
echo "What should the default umask for data files be (in octal)?"
echo "(077 = only accessible by owner; 007 = accessible by owner and group)"
while [ $ok -eq 0 ] ; do
echo2 "[$UMASK] "
echo -n "[$UMASK] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ ! "$INPUT" ] ; then
INPUT=$UMASK
@@ -287,7 +262,7 @@ if [ "$DEBUG" = "yes" ] ; then
TEMP_YN="y"
fi
echo "Would you like to build a debug version of Anope?"
echo2 "[$TEMP_YN] "
echo -n "[$TEMP_YN] "
read YN
if [ "$YN" ] ; then
if [ "$YN" = "y" ] ; then
@@ -305,7 +280,7 @@ echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra include directories, enter NONE in all caps."
echo2 "[$EXTRA_INCLUDE_DIRS] "
echo -n "[$EXTRA_INCLUDE_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -323,7 +298,7 @@ echo "You may only need to do this if CMake is unable to locate"
echo "missing dependencies without hints."
echo "Separate directories with semicolons."
echo "If you need no extra library directories, enter NONE in all caps."
echo2 "[$EXTRA_LIB_DIRS] "
echo -n "[$EXTRA_LIB_DIRS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -338,7 +313,7 @@ echo ""
echo "Are there any extra arguments you wish to pass to CMake?"
echo "If you need no extra arguments to CMake, enter NONE in all caps."
echo2 "[$EXTRA_CONFIG_ARGS] "
echo -n "[$EXTRA_CONFIG_ARGS] "
if read INPUT ; then : ; else echo "" ; exit 1 ; fi
if [ "$INPUT" ] ; then
if [ "$INPUT" = "NONE" ] ; then
@@ -355,7 +330,7 @@ echo ""
# Store values
################################################################################
echo2 "Saving configuration results in config.cache... "
echo -n "Saving configuration results in config.cache... "
cat <<EOT >$SOURCE_DIR/config.cache
INSTDIR="$INSTDIR"
+1 -1
View File
@@ -1,6 +1,6 @@
# Only install example.chk and anope.example.conf from this directory
# NOTE: I would've had this just find all files in the directory, but that would include files not needed (like this file)
set(DATA example.chk anope.example.conf botserv.example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf irc2sql.example.conf stats.standalone.example.conf)
set(DATA cron.example.sh anope.example.conf botserv.example.conf hostserv.example.conf modules.example.conf operserv.example.conf chanserv.example.conf global.example.conf memoserv.example.conf nickserv.example.conf chanstats.example.conf irc2sql.example.conf stats.standalone.example.conf)
install(FILES ${DATA}
DESTINATION ${CONF_DIR}
)
+146 -92
View File
@@ -238,15 +238,15 @@ serverinfo
/*
* The filename containing the Anope process ID. The path is relative to the
* services root directory.
* data directory.
*/
pid = "data/anope.pid"
pid = "anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
* services root directory.
* config directory.
*/
motd = "conf/motd.txt"
motd = "motd.txt"
}
/*
@@ -265,26 +265,7 @@ serverinfo
* - solanum
* - unrealircd
*/
module
{
name = "inspircd"
/*
* Some protocol modules can enforce mode locks server-side. This reduces the spam caused by
* services immediately reversing mode changes for locked modes.
*
* If the protocol module you have loaded does not support this, this setting will have no effect.
*/
use_server_side_mlock = yes
/*
* Some protocol modules can enforce topic locks server-side. This reduces the spam caused by
* services immediately reversing topic changes.
*
* If the protocol module you have loaded does not support this, this setting will have no effect.
*/
use_server_side_topiclock = yes
}
module { name = "inspircd" }
/*
* [REQUIRED] Network Information
@@ -395,19 +376,6 @@ 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
@@ -434,7 +402,7 @@ options
/*
* Sets the delay between automatic database updates.
*/
updatetimeout = 5m
updatetimeout = 2m
/*
* Sets the delay between checks for expired nicknames and channels.
@@ -543,7 +511,7 @@ options
*
* Removing .UTF-8 will instead use the default encoding for the language, e.g. iso-8859-1 for western European languages.
*/
languages = "ca_ES.UTF-8 de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 hu_HU.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 ru_RU.UTF-8 tr_TR.UTF-8"
languages = "de_DE.UTF-8 el_GR.UTF-8 es_ES.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 nl_NL.UTF-8 pl_PL.UTF-8 pt_PT.UTF-8 tr_TR.UTF-8"
/*
* Default language that non- and newly-registered nicks will receive messages in.
@@ -762,13 +730,14 @@ log
*
* Available privileges:
* botserv/administration - Can view and assign private BotServ bots
* botserv/fantasy - Can use fantasy commands without the FANTASIA privilege
* botserv/fantasy - Can use fantasy commands without the FANTASY privilege
* chanserv/administration - Can modify the settings of any channel (including changing of the owner!)
* chanserv/access/list - Can view channel access and akick lists, but not modify them
* chanserv/access/modify - Can modify channel access and akick lists, and use /chanserv enforce
* chanserv/auspex - Can see any information with /CHANSERV INFO
* chanserv/no-register-limit - May register an unlimited number of channels and nicknames
* chanserv/kick - Can kick and ban users from channels through ChanServ
* chanserv/drop/override - Allows dropping channels without using a confirmation code
* memoserv/info - Can see any information with /MEMOSERV INFO
* memoserv/set-limit - Can set the limit of max stored memos on any user and channel
* memoserv/no-limit - Can send memos through limits and throttles
@@ -777,6 +746,8 @@ log
* nickserv/cert - Can modify other users certificate lists
* nickserv/confirm - Can confirm other users nicknames
* nickserv/drop - Can drop other users nicks
* nickserv/drop/display - Allows dropping display nicks when preservedisplay is enabled
* nickserv/drop/override - Allows dropping nicks without using a confirmation code
* nickserv/recover - Can recover other users nicks
* operserv/config - Can modify services's configuration
* operserv/oper/modify - Can add and remove operators with at most the same privileges
@@ -802,7 +773,7 @@ log
*
* hostserv/set hostserv/del hostserv/list
*
* global/global
* global/global global/queue global/server
*
* operserv/news operserv/stats operserv/kick operserv/exception operserv/seen
* operserv/mode operserv/session operserv/modinfo operserv/ignore operserv/chanlist
@@ -931,7 +902,7 @@ opertype
/*
* [OPTIONAL] Mail Config
*
* This section contains settings related to the use of e-mail from services.
* This section contains settings related to the use of email from services.
* If the usemail directive is set to yes, unless specified otherwise, all other
* directives are required.
*
@@ -945,13 +916,13 @@ mail
* If set, this option enables the mail commands in Anope. You may choose
* to disable it if you have no Sendmail-compatible mailer installed. Whilst
* this directive (and entire block) is optional, it is required if
* nickserv:registration is set to yes.
* nickserv:registration is set to mail.
*/
usemail = yes
/*
* This is the command-line that will be used to call the mailer to send an
* e-mail. It must be called with all the parameters needed to make it
* email. 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.
*
@@ -963,18 +934,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 -t"
#sendmailpath = "/usr/sbin/sendmail -it"
/*
* This is the e-mail address from which all the e-mails are to be sent from.
* This is the email address from which all the emails 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 e-mail after they have sent one. It also controls the minimum time
* a user must wait before they can receive another e-mail.
* another email after they have sent one. It also controls the minimum time
* a user must wait before they can receive another email.
*
* This feature prevents users from being mail bombed using services and
* it is highly recommended that it be used.
@@ -985,10 +956,10 @@ mail
/*
* If set, Anope will not put quotes around the TO: fields
* in e-mails.
* in emails.
*
* This directive is optional, and as far as we know, it's only needed
* if you are using ESMTP or QMail to send out e-mails.
* if you are using ESMTP or QMail to send out emails.
*/
#dontquoteaddresses = yes
@@ -1105,6 +1076,22 @@ 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
*
@@ -1148,11 +1135,6 @@ module
* This is only useful with very large databases, with hundreds
* of thousands of objects, that have a noticeable delay from
* writing databases.
*
* If your database is large enough cause a noticeable delay when
* saving you should consider a more powerful alternative such
* as db_sql or db_redis, which incrementally update their
* databases asynchronously in real time.
*/
fork = no
}
@@ -1225,49 +1207,121 @@ module
/*
* [RECOMMENDED] Encryption modules.
*
* 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 encryption modules are used when dealing with passwords. This determines
* how the passwords are stored in the databases.
*
* 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.
*/
#module { name = "enc_bcrypt" }
module { name = "enc_sha256" }
/*
* [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_sha1" }
/*
* 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.
* 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_old" }
module
{
name = "enc_sha2"
/** 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 migrating 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.
*/
#module { name = "enc_md5" }
#module { name = "enc_none" }
#module { name = "enc_old" }
#module { name = "enc_sha1" }
#module { name = "enc_sha256" }
/* 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 = 32
badwordsmax = 50
/*
* If set, BotServ will use case sensitive checking for badwords.
+11 -12
View File
@@ -107,22 +107,21 @@ module
/*
* The length of time before a channel registration expires.
*
* This directive is optional, but recommended.
* If not set, the default is 30 days.
* This directive is optional. If not set, the default is never.
*/
expire = 30d
#expire = 90d
/*
* The maximum number of entries on a channel's access list.
* If not set, the default is 1024. This can be set to 0 for unlimited.
* If not set, the default is 1000. This can be set to 0 for unlimited.
*/
accessmax = 1024
accessmax = 1000
/*
* 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 = 15s
inhabit = 1m
/*
* Allow only IRC Operators to use ChanServ.
@@ -392,7 +391,7 @@ privilege
}
/*
* FANTASIA privilege.
* FANTASY privilege.
*
* Used by botserv/main and chanserv/xop.
*
@@ -400,7 +399,7 @@ privilege
*/
privilege
{
name = "FANTASIA"
name = "FANTASY"
desc = _("Allowed to use fantasy commands")
rank = 30
level = 3
@@ -913,7 +912,7 @@ module
/*
* The maximum number of entries on a channel's autokick list.
*/
autokickmax = 32
autokickmax = 50
/*
* The default reason for an autokick if none is given.
@@ -1126,7 +1125,7 @@ module
*
* This directive is optional.
*/
max = 32
max = 50
}
command { service = "ChanServ"; name = "MODE"; command = "chanserv/mode"; group = "chanserv/management"; }
@@ -1247,7 +1246,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 E-mail address with the channel"); }
command { service = "ChanServ"; name = "SET EMAIL"; command = "chanserv/set/misc"; misc_description = _("Associate an email address with the channel"); }
/*
* cs_status
@@ -1278,7 +1277,7 @@ module
* This directive is optional.
* If not set, the default is never.
*/
expire = 90d
suspendexpire = 90d
/*
* Settings to show to non-opers in ChanServ's INFO output.
+26
View File
@@ -113,3 +113,29 @@ 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 = 3s
senddelay = 30s
}
/*
@@ -146,7 +146,7 @@ module
*
* This directive is optional.
*/
max = 32
max = 50
}
command { service = "MemoServ"; name = "IGNORE"; command = "memoserv/ignore"; }
+23 -17
View File
@@ -59,7 +59,7 @@ module { name = "help" }
* SOA record information.
*/
/* E-mail address of the DNS administrator. */
/* Email 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 [EXTRA]
* ldap_authentication
*
* 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 [EXTRA]
* ldap_oper
*
* This module dynamically ties users to Anope opertypes when they identify
* via LDAP group membership. Requires ldap.
@@ -372,6 +372,7 @@ module { name = "help" }
username = "anope"
password = "mypassword"
port = 3306
socket = ""
}
}
@@ -580,7 +581,8 @@ module { name = "sasl" }
name = "ssl_gnutls"
/*
* An optional certificate and key for ssl_gnutls to give to the uplink.
* An optional certificate and key for ssl_gnutls to give to the uplink. All
* paths are relative to the config directory.
*
* You can generate your own certificate and key pair by using:
*
@@ -588,8 +590,8 @@ module { name = "sasl" }
* certtool --generate-self-signed --load-privkey privkey.pem --outfile fullchain.pem
*
*/
cert = "data/fullchain.pem"
key = "data/privkey.pem"
cert = "fullchain.pem"
key = "privkey.pem"
/*
* Diffie-Hellman parameters to use when acting as a server. This is only
@@ -602,7 +604,7 @@ module { name = "sasl" }
* certtool --generate-dh-params --bits 2048 --outfile dhparams.pem
*
*/
# dhparams = "data/dhparams.pem"
#dhparams = "dhparams.pem"
}
/*
@@ -620,14 +622,15 @@ 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 = "data/fullchain.pem"
key = "data/privkey.pem"
cert = "fullchain.pem"
key = "privkey.pem"
/*
* If you wish to increase security you can disable support for older
@@ -640,7 +643,7 @@ module { name = "sasl" }
}
/*
* sql_authentication [EXTRA]
* sql_authentication
*
* This module allows authenticating users against an external SQL database using a custom
* query.
@@ -691,7 +694,7 @@ module { name = "sasl" }
}
/*
* sql_log [EXTRA]
* sql_log
*
* This module adds an additional target option to log{} blocks
* that allows logging Service's logs to SQL. To log to SQL, add
@@ -711,7 +714,7 @@ module { name = "sasl" }
#module { name = "sql_log" }
/*
* sql_oper [EXTRA]
* sql_oper
*
* This module allows granting users services operator privileges and possibly IRC Operator
* privileges based on an external SQL database using a custom query.
@@ -752,7 +755,7 @@ module { name = "sasl" }
name = "sqlite/main"
/* The database name, it will be created if it does not exist. */
database = "anope.db"
database = "anope.sqlite"
}
}
@@ -770,13 +773,16 @@ module { name = "sasl" }
name = "webcpanel"
/* Web server to use. */
server = "httpd/main";
server = "httpd/main"
/* Template to use. */
template = "default";
/*
* The directory containing the webcpanel templates. This is relative to the
* data directory.
*/
template_dir = "webcpanel/templates/default"
/* Page title. */
title = "Anope IRC Services";
title = "Anope IRC Services"
}
/*
+30 -11
View File
@@ -66,9 +66,9 @@ module
client = "NickServ"
/*
* Force users to give an e-mail address when they register a nick.
* Requires users to give an email address when they register a nick.
*
* This directive defaults to "yes" and is recommended to be enabled. This is required if e-mail registration is enabled.
* This directive defaults to "yes" and is recommended to be 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 e-mail address from NickServ's INFO command
* - hide_email: Hide the nick's email address from NickServ's INFO command
* - hide_mask: Hide the nick's last or current user@host from NickServ's INFO command
* - 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 = 30s
regdelay = 5m
/*
* The length of time before a nick's registration expires.
@@ -219,6 +219,12 @@ module
* This directive is optional. If not set it defaults to 50.
*/
maxpasslen = 50
/*
* Whether all of the secondary nicks of a nick group have to expire or be
dropped before the display nick can expire or be dropped.
*/
preservedisplay = no
}
/*
@@ -273,6 +279,7 @@ 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
@@ -285,6 +292,12 @@ module
{
name = "ns_cert"
/*
* Should users who are connected with a SSL client certificate have its fingerprint be added to
* their account when they register. Defaults to yes.
*/
automatic = yes
/*
* The maximum number of entries allowed on a nickname's certificate fingerprint list.
* The default is 5. This number cannot be set to 0.
@@ -329,7 +342,7 @@ module
*
* This directive is optional, but recommended. If not set or set to 0, no limits will be applied.
*/
maxaliases = 16
maxaliases = 10
/*
* If set, the NickServ GROUP command won't allow any group changes. This is recommended to
@@ -467,7 +480,7 @@ module
*
* This directive is optional.
*/
#nickregdelay = 30s
nickregdelay = 15s
/*
* The length of time a user using an unconfirmed account has
@@ -499,7 +512,6 @@ command { service = "NickServ"; name = "RESETPASS"; command = "nickserv/resetpas
* nickserv/set/email, nickserv/saset/email - Used for setting a users email address.
* nickserv/set/keepmodes, nickserv/saset/keepmodes - Configure whether or not services should retain a user's modes across sessions.
* nickserv/set/kill, nickserv/saset/kill - Used for configuring nickname protection.
* nickserv/set/language, nickserv/saset/language - Used for configuring what language services use.
* nickserv/set/message, nickserv/saset/message - Used to configure how services send messages to you.
* nickserv/set/neverop, nickserv/saset/neverop - Used to configure whether a user can be added to access lists
* nickserv/saset/noexpire - Used for configuring noexpire, which prevents nicks from expiring.
@@ -535,9 +547,6 @@ command { service = "NickServ"; name = "SASET KEEPMODES"; command = "nickserv/sa
command { service = "NickServ"; name = "SET KILL"; command = "nickserv/set/kill"; }
command { service = "NickServ"; name = "SASET KILL"; command = "nickserv/saset/kill"; permission = "nickserv/saset/kill"; }
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
command { service = "NickServ"; name = "SET MESSAGE"; command = "nickserv/set/message"; }
command { service = "NickServ"; name = "SASET MESSAGE"; command = "nickserv/saset/message"; permission = "nickserv/saset/message"; }
@@ -549,6 +558,16 @@ command { service = "NickServ"; name = "SASET NEVEROP"; command = "nickserv/sase
command { service = "NickServ"; name = "SASET NOEXPIRE"; command = "nickserv/saset/noexpire"; permission = "nickserv/saset/noexpire"; }
/*
* ns_set_language
*
* Provides the command nickserv/set/language and nickserv/saset/language.
*
* Allows configuring the language that services uses.
*/
module { name = "ns_set_language" }
command { service = "NickServ"; name = "SET LANGUAGE"; command = "nickserv/set/language"; }
command { service = "NickServ"; name = "SASET LANGUAGE"; command = "nickserv/saset/language"; permission = "nickserv/saset/language"; }
/*
* ns_set_misc
@@ -622,7 +641,7 @@ command { service = "NickServ"; name = "UPDATE"; command = "nickserv/update"; }
name = "ns_maxemail"
/*
* The limit to how many registered nicks can use the same e-mail address. If set to 0 or left
* The limit to how many registered nicks can use the same email address. If set to 0 or left
* commented, there will be no limit enforced when registering new accounts or using
* /msg NickServ SET EMAIL.
*/
+1 -1
View File
@@ -503,7 +503,7 @@ command { service = "OperServ"; name = "RANDOMNEWS"; command = "operserv/randomn
*
* Used to NOOP a server, which prevents users from opering on that server.
*/
module { name = "os_noop" }
#module { name = "os_noop" }
command { service = "OperServ"; name = "NOOP"; command = "operserv/noop"; permission = "operserv/noop"; }
/*
+4 -4
View File
@@ -235,15 +235,15 @@ serverinfo
/*
* The filename containing the Anope process ID. The path is relative to the
* services root directory.
* data directory.
*/
pid = "data/anope.pid"
pid = "anope.pid"
/*
* The filename containing the Message of the Day. The path is relative to the
* services root directory.
* config directory.
*/
motd = "conf/motd.txt"
motd = "motd.txt"
}
/*
+88 -1
View File
@@ -1,3 +1,90 @@
Anope Version 2.1.8
-------------------
Added account identifiers to the nickserv/info output.
Added support for bool, float, and uint SQL columns.
Added the ability to automatically determine SQL column types based on the native type.
Added UNIX socket support to mysql module.
Changed smartjoin to use SendClearBans where available.
Dropped support for MinGW in favour of native builds.
Fixed parsing named extbans on InspIRCd.
Fixed parsing SVSMODE and SVS2MODE from UnrealIRCd.
Fixed sending global messages to remotely linked servers.
Removed the services server name from the CTCP version response.
Anope Version 2.1.7
-------------------
Added importing of akick reasons, forbid reasons, opers and session exceptions to db_atheme.
Added support for sending tag messages.
Added the ability to look up account information of an authenticated user.
Fixed a crash in ns_cert when an IRC user is not present during a nick registration.
Fixed a null pointer dereference in the global module.
Fixed a rare memory leak in os_akill and os_sxline.
Improved the performance of some code that looks up the primary nick from an account.
Removed the broken Catalan, Hungarian, and Russian translations.
Reworked the protocol interface for sending messages.
Updated the Turkish translation.
Anope Version 2.1.6
-------------------
Added opportunistic upgrading of TLS fingerprints to more secure algorithms on InspIRCd.
Added support for logging out partially connected users on Plexus.
Added the account registration time to nickserv/info.
Changed ns_cert to automatically add a TLS fingerprint to new accounts if available.
Clarified that a non-deprecated encryption module must be loaded.
Fixed creating the runtime directory on Windows.
Fixed mistakenly allowing badpasslimit to be set to a negative value.
Fixed parsing backup TLS fingerprints on InspIRCd.
Fixed parsing the flood mode on UnrealIRCd.
Fixed parsing the history mode on UnrealIRCd.
Fixed various iterator invalidation issues.
Partially rewrote the Portuguese translation.
Removed some incorrect strings from the Turkish translation.
Renamed the --modulesdir option to --moduledir to match the name of other path options.
Anope Version 2.1.5
-------------------
Added an example systemd unit file.
Added support for BIGLINES on UnrealIRCd.
Bumped the minimum supported version of Bahamut to 2.0.
Fixed truncating messages in global/global and global/server.
Improved building Anope for use as a system package.
Updated the Turkish translation.
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.
@@ -18,7 +105,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 minumum GnuTLS version to 3.0.0.
Bumped the minimum 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.
+42
View File
@@ -1,3 +1,45 @@
Anope Version 2.1.8
-------------------
Added module:preservedisplay to the nickserv module.
Added the nickserv/drop/display oper privilege.
Anope Version 2.1.7
-------------------
Moved nickserv/set/language and nickserv/saset/language to the ns_set_language module.
Renamed module:expire for the cs_suspend module to suspendexpire.
Renamed the FANTASIA privilege to FANTASY.
Anope Version 2.1.6
-------------------
Added module:automatic to the ns_cert module (defaults to yes).
Removed module:use_server_side_mlock for the protocol modules (now always enabled).
Removed module:use_server_side_topiclock for the protocol modules (now always enabled).
Anope Version 2.1.5
-------------------
Added the nickserv/drop/override and chanserv/drop/override oper privileges.
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.
+3 -1
View File
@@ -19,6 +19,8 @@ Anope Multi Language Support
Then execute:
dpkg-reconfigure locales
If you have already built Anope you will need to delete the build directory and rebuild from scratch.
Building Anope on Windows with gettext support is explained in docs/WIN32.txt
2) Adding a new language
@@ -33,7 +35,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 e-mail and the language name). You'll of course get full credit for it.
(don't forget to mention clearly your (nick)name, your email 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.
+1 -1
View File
@@ -166,7 +166,7 @@ Table of Contents
Anope currently works with:
* Bahamut 1.4.27 or later (including 1.8)
* Bahamut 2.0 or later
* ircd-hybrid 8.2.23 or later
* InspIRCd 3 or later
* ngIRCd 19.2 or later
+23 -18
View File
@@ -17,8 +17,8 @@
#include "memo.h"
#include "base.h"
typedef Anope::hash_map<NickAlias *> nickalias_map;
typedef Anope::hash_map<NickCore *> nickcore_map;
typedef Anope::unordered_map<NickAlias *> nickalias_map;
typedef Anope::unordered_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;
time_t vhost_created = 0;
public:
Anope::string nick;
@@ -43,8 +43,9 @@ public:
Anope::string last_usermask;
/* Last uncloaked usermask, requires nickserv/auspex to see */
Anope::string last_realhost;
time_t time_registered;
time_t last_seen;
time_t time_registered = Anope::CurTime;
time_t last_seen = Anope::CurTime;
/* Account this nick is tied to. Multiple nicks can be tied to a single account. */
Serialize::Reference<NickCore> nc;
@@ -64,41 +65,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
@@ -127,6 +128,10 @@ 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;
/* The time this account was registered */
time_t time_registered = Anope::CurTime;
MemoInfo memos;
std::map<Anope::string, Anope::string> last_modes;
@@ -136,14 +141,14 @@ public:
Serialize::Checker<std::vector<NickAlias *> > aliases;
/* Set if this user is a services operator. o->ot must exist. */
Oper *o;
Oper *o = nullptr;
/* Unsaved data */
/** The display nick for this account. */
NickAlias *na = nullptr;
/* Number of channels registered by this account */
uint16_t channelcount;
/* Last time an email was sent to this user */
time_t lastmail;
uint16_t channelcount = 0;
/* Users online now logged into this account */
std::list<User *> users;
@@ -160,7 +165,7 @@ public:
/** Changes the display for this account
* @param na The new display, must be grouped to this account.
*/
void SetDisplay(const NickAlias *na);
void SetDisplay(NickAlias *na);
/** Checks whether this account is a services oper or not.
* @return True if this account is a services oper, false otherwise.
+63 -79
View File
@@ -39,6 +39,7 @@ 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);
/**
@@ -343,7 +344,7 @@ namespace Anope
using multimap = std::multimap<string, T, ci::less>;
template<typename T>
using hash_map = std::unordered_map<string, T, hash_ci, compare>;
using unordered_map = std::unordered_map<string, T, hash_ci, compare>;
#ifndef REPRODUCIBLE_BUILD
static const char *const compiled = __TIME__ " " __DATE__;
@@ -366,6 +367,7 @@ 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.
*/
@@ -373,7 +375,7 @@ namespace Anope
/** Other command line options.
*/
extern CoreExport bool ReadOnly, NoFork, NoThird, NoExpire, ProtocolDebug;
extern CoreExport bool ReadOnly, NoFork, NoThird, NoPID, NoExpire, ProtocolDebug;
/** The root of the Anope installation. Usually ~/anope
*/
@@ -469,7 +471,7 @@ namespace Anope
* @param src The source string to encrypt
* @param dest The destination where the encrypted string is placed
*/
extern CoreExport void Encrypt(const Anope::string &src, Anope::string &dest);
extern CoreExport bool Encrypt(const Anope::string &src, Anope::string &dest);
/** Hashes a buffer with SipHash-2-4
* @param src The start of the buffer to hash
@@ -534,10 +536,18 @@ namespace Anope
*/
extern CoreExport Anope::string NormalizeBuffer(const Anope::string &);
/** Main processing routine. Parses the message and takes the appropriate action.
* @param Raw message from the uplink
/** Parses a raw message from the uplink and calls its command handler.
* @param message Raw message from the uplink
*/
extern void Process(const Anope::string &);
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);
/** Does a blocking dns query and returns the first IP.
* @param host host to look up
@@ -558,11 +568,53 @@ 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); }
/** Formats a CTCP message for sending to a client.
* @param name The name of the CTCP.
* @param body If present then the body of the CTCP.
* @return A formatted CTCP ready to send to a client.
*/
extern CoreExport Anope::string FormatCTCP(const Anope::string &name, const Anope::string &body = "");
/** Parses a CTCP message received from a client.
* @param text The raw message to parse.
* @param name The location to store the name of the CTCP.
* @param body The location to store body of the CTCP if one is present.
* @return True if the message was a well formed CTCP; otherwise, false.
*/
extern CoreExport bool ParseCTCP(const Anope::string &text, Anope::string &name, Anope::string &body);
}
/** sepstream allows for splitting token separated lists.
@@ -590,6 +642,9 @@ 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
@@ -676,9 +731,6 @@ protected:
*/
Anope::string source;
public:
/** Default constructor, just uses the error message 'Core threw an exception'.
*/
CoreException() : err("Core threw an exception"), source("The core") { }
/** This constructor can be used to specify an error message before throwing.
*/
CoreException(const Anope::string &message) : err(message), source("The core") { }
@@ -709,10 +761,6 @@ class CoreExport ModuleException
: public CoreException
{
public:
/** Default constructor, just uses the error message 'Module threw an exception'.
*/
ModuleException() : CoreException("Module threw an exception", "A Module") { }
/** This constructor can be used to specify an error message before throwing.
*/
ModuleException(const Anope::string &message) : CoreException(message, "A Module") { }
@@ -723,72 +771,6 @@ 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.
@@ -808,3 +790,5 @@ 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::hash_map<Channel *> channel_map;
typedef Anope::unordered_map<Channel *> channel_map;
extern CoreExport channel_map ChannelList;
+1 -9
View File
@@ -15,7 +15,6 @@
#include "regchannel.h"
#include "users.h"
#include "opertype.h"
#include <stack>
namespace Configuration
{
@@ -47,14 +46,7 @@ namespace Configuration
template<typename T> T Get(const Anope::string &tag, const Anope::string &def = "") const
{
const Anope::string &value = this->Get<const Anope::string>(tag, def);
if (!value.empty())
try
{
return convertTo<T>(value);
}
catch (const ConvertException &) { }
return T();
return Anope::TryConvert<T>(this->Get<const Anope::string>(tag, def)).value_or(T());
}
bool Set(const Anope::string &tag, const Anope::string &value);
+132
View File
@@ -0,0 +1,132 @@
/*
*
* (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());
}
}
+2 -2
View File
@@ -173,7 +173,7 @@ public:
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
T *t = this->Get(e);
data[this->name] << *t;
data.Store(this->name, *t);
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
@@ -194,7 +194,7 @@ public:
void ExtensibleSerialize(const Extensible *e, const Serializable *s, Serialize::Data &data) const override
{
data[this->name] << true;
data.Store(this->name, true);
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
+12 -11
View File
@@ -65,11 +65,13 @@ 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 in read-only mode!")
#define READ_ONLY_MODE _("Services are temporarily 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" \
@@ -86,7 +88,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 e-mail address.")
#define MAIL_X_INVALID _("\002%s\002 is not a valid email 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.")
@@ -97,7 +99,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 e-mail again, and retry.")
#define NICK_CONFIRM_INVALID _("Invalid passcode has been entered, please check the email 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.")
@@ -106,7 +108,7 @@ namespace Language
#define CHAN_SETTING_CHANGED _("%s for %s set to %s.")
#define CHAN_SETTING_UNSET _("%s for %s unset.")
#define CHAN_ACCESS_LEVEL_RANGE _("Access level must be between %d and %d inclusive.")
#define CHAN_INFO_HEADER _("Information for channel \002%s\002:")
#define CHAN_INFO_HEADER _("Information about channel \002%s\002:")
#define CHAN_EXCEPTED _("\002%s\002 matches an except on %s and cannot be banned until the except has been removed.")
#define MEMO_NEW_X_MEMO_ARRIVED _("There is a new memo on channel %s.\n" \
"Type \002%s%s READ %s %zu\002 to read it.")
@@ -114,15 +116,14 @@ 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 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")
#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.")
+1 -1
View File
@@ -26,6 +26,7 @@ namespace Mail
: public Thread
{
private:
Anope::string error;
Anope::string sendmail_path;
Anope::string send_from;
Anope::string mail_to;
@@ -35,7 +36,6 @@ 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
+121 -119
View File
@@ -199,6 +199,8 @@ public:
class CoreExport NotImplementedException final
: public CoreException
{
public:
NotImplementedException() : CoreException("") { }
};
/** Every module in Anope is actually a class.
@@ -288,7 +290,7 @@ public:
* @param cu The user, channel, and status of the user being kicked
* @param kickmsg The reason for the kick.
*/
virtual void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) { throw NotImplementedException(); }
virtual void OnPreUserKicked(const MessageSource &source, ChanUserContainer *cu, const Anope::string &kickmsg) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user has been kicked from a channel.
* @param source The kicker
@@ -297,13 +299,13 @@ public:
* @param status The status the kicked user had on the channel before they were kicked
* @param kickmsg The reason for the kick.
*/
virtual void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) { throw NotImplementedException(); }
virtual void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when the configuration is being (re)loaded.
* @param conf The config that is being built now and will replace the global Config object
* @throws A ConfigException to abort the config (re)loading process.
*/
virtual void OnReload(Configuration::Conf *conf) { throw NotImplementedException(); }
virtual void OnReload(Configuration::Conf *conf) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a bot is assigned to a channel.
* @param sender The user assigning the bot
@@ -311,35 +313,35 @@ public:
* @param bi The bot being assigned.
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the assign.
*/
virtual EventReturn OnPreBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) { throw NotImplementedException(); }
virtual EventReturn OnPreBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called when a bot is assigned ot a channel
*/
virtual void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) { throw NotImplementedException(); }
virtual void OnBotAssign(User *sender, ChannelInfo *ci, BotInfo *bi) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called before a bot is unassigned from a channel.
* @param sender The user unassigning the bot
* @param ci The channel the bot is being removed from
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the unassign.
*/
virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) { throw NotImplementedException(); }
virtual EventReturn OnBotUnAssign(User *sender, ChannelInfo *ci) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a new user connects to the network.
* @param u The connecting user.
* @param exempt set to true/is true if the user should be excepted from bans etc
*/
virtual void OnUserConnect(User *u, bool &exempt) { throw NotImplementedException(); }
virtual void OnUserConnect(User *u, bool &exempt) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new server connects to the network.
* @param s The server that has connected to the network
*/
virtual void OnNewServer(Server *s) { throw NotImplementedException(); }
virtual void OnNewServer(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after a user changed the nick
* @param u The user.
* @param oldnick The old nick of the user
*/
virtual void OnUserNickChange(User *u, const Anope::string &oldnick) { throw NotImplementedException(); }
virtual void OnUserNickChange(User *u, const Anope::string &oldnick) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when someone uses the generic/help command
* @param source Command source
@@ -360,14 +362,14 @@ public:
* @param params The parameters the user is sending
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) { throw NotImplementedException(); }
virtual EventReturn OnPreCommand(CommandSource &source, Command *command, std::vector<Anope::string> &params) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called after a command has been executed.
* @param source The source of the command
* @param command The command the user executed
* @param params The parameters the user sent
*/
virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
virtual void OnPostCommand(CommandSource &source, Command *command, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when the databases are saved
*/
@@ -389,7 +391,7 @@ public:
* @param params The params
* @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed
*/
virtual EventReturn OnBotFantasy(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
virtual EventReturn OnBotFantasy(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called on fantasy command without access
* @param source The source of the command
@@ -398,31 +400,31 @@ public:
* @param params The params
* @return EVENT_STOP to halt processing and not run the command, EVENT_ALLOW to allow the command to be executed
*/
virtual EventReturn OnBotNoFantasyAccess(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) { throw NotImplementedException(); }
virtual EventReturn OnBotNoFantasyAccess(CommandSource &source, Command *c, ChannelInfo *ci, const std::vector<Anope::string> &params) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a bot places a ban
* @param u User being banned
* @param ci Channel the ban is placed on
* @param mask The mask being banned
*/
virtual void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) { throw NotImplementedException(); }
virtual void OnBotBan(User *u, ChannelInfo *ci, const Anope::string &mask) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called before a badword is added to the badword list
* @param ci The channel
* @param bw The badword
*/
virtual void OnBadWordAdd(ChannelInfo *ci, const BadWord *bw) { throw NotImplementedException(); }
virtual void OnBadWordAdd(ChannelInfo *ci, const BadWord *bw) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called before a badword is deleted from a channel
* @param ci The channel
* @param bw The badword
*/
virtual void OnBadWordDel(ChannelInfo *ci, const BadWord *bw) { throw NotImplementedException(); }
virtual void OnBadWordDel(ChannelInfo *ci, const BadWord *bw) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a bot is created or destroyed
*/
virtual void OnCreateBot(BotInfo *bi) { throw NotImplementedException(); }
virtual void OnDelBot(BotInfo *bi) { throw NotImplementedException(); }
virtual void OnCreateBot(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnDelBot(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a bot kicks a user
* @param bi The bot sending the kick
@@ -431,13 +433,13 @@ public:
* @param reason The reason
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
virtual EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason) { throw NotImplementedException(); }
virtual EventReturn OnBotKick(BotInfo *bi, Channel *c, User *u, const Anope::string &reason) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** Called before a user parts a channel
* @param u The user
* @param c The channel
*/
virtual void OnPrePartChannel(User *u, Channel *c) {}
virtual void OnPrePartChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user parts a channel
* @param u The user
@@ -445,14 +447,14 @@ public:
* @param channel The channel name
* @param msg The part reason
*/
virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) { throw NotImplementedException(); }
virtual void OnPartChannel(User *u, Channel *c, const Anope::string &channel, const Anope::string &msg) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user leaves a channel.
* From either parting, being kicked, or quitting/killed!
* @param u The user
* @param c The channel
*/
virtual void OnLeaveChannel(User *u, Channel *c) { throw NotImplementedException(); }
virtual void OnLeaveChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called after a user joins a channel
* If this event triggers the user is allowed to be in the channel, and will
@@ -461,7 +463,7 @@ public:
* @param u The user
* @param channel The channel
*/
virtual void OnJoinChannel(User *u, Channel *c) { throw NotImplementedException(); }
virtual void OnJoinChannel(User *u, Channel *c) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a new topic is set
* @param source The user changing the topic, if any
@@ -469,18 +471,18 @@ public:
* @param setter The user who set the new topic, if there is no source
* @param topic The new topic
*/
virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) { throw NotImplementedException(); }
virtual void OnTopicUpdated(User *source, Channel *c, const Anope::string &user, const Anope::string &topic) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a channel expires
* @param ci The channel
* @param expire Set to true to allow the chan to expire
*/
virtual void OnPreChanExpire(ChannelInfo *ci, bool &expire) { throw NotImplementedException(); }
virtual void OnPreChanExpire(ChannelInfo *ci, bool &expire) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before a channel expires
* @param ci The channel
*/
virtual void OnChanExpire(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnChanExpire(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before Anope connects to its uplink
*/
@@ -492,7 +494,7 @@ public:
/** Called when we are almost done synching with the uplink, just before we send the EOB
*/
virtual void OnPreUplinkSync(Server *serv) { throw NotImplementedException(); }
virtual void OnPreUplinkSync(Server *serv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when Anope disconnects from its uplink, before it tries to reconnect
*/
@@ -510,12 +512,12 @@ public:
* @param na The nick
* @param expire Set to true to allow the nick to expire
*/
virtual void OnPreNickExpire(NickAlias *na, bool &expire) { throw NotImplementedException(); }
virtual void OnPreNickExpire(NickAlias *na, bool &expire) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick drops
* @param na The nick
*/
virtual void OnNickExpire(NickAlias *na) { throw NotImplementedException(); }
virtual void OnNickExpire(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when defcon level changes
* @param level The level
@@ -526,13 +528,13 @@ public:
* @param ex The exception
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
virtual EventReturn OnExceptionAdd(Exception *ex) { throw NotImplementedException(); }
virtual EventReturn OnExceptionAdd(Exception *ex) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called before an exception is deleted
* @param source The source deleting it
* @param ex The exception
*/
virtual void OnExceptionDel(CommandSource &source, Exception *ex) { throw NotImplementedException(); }
virtual void OnExceptionDel(CommandSource &source, Exception *ex) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a XLine is added
* @param source The source of the XLine
@@ -540,31 +542,31 @@ public:
* @param xlm The xline manager it was added to
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to halt the command and not process it
*/
virtual EventReturn OnAddXLine(CommandSource &source, const XLine *x, XLineManager *xlm) { throw NotImplementedException(); }
virtual EventReturn OnAddXLine(CommandSource &source, const XLine *x, XLineManager *xlm) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called before a XLine is deleted
* @param source The source of the XLine
* @param x The XLine
* @param xlm The xline manager it was deleted from
*/
virtual void OnDelXLine(CommandSource &source, const XLine *x, XLineManager *xlm) { throw NotImplementedException(); }
virtual void OnDelXLine(CommandSource &source, const XLine *x, XLineManager *xlm) ATTR_NOT_NULL(4) { throw NotImplementedException(); }
/** Called when a user is checked for whether they are a services oper
* @param u The user
* @return EVENT_ALLOW to allow, anything else to deny
*/
virtual EventReturn IsServicesOper(User *u) { throw NotImplementedException(); }
virtual EventReturn IsServicesOper(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a server quits
* @param server The server
*/
virtual void OnServerQuit(Server *server) { throw NotImplementedException(); }
virtual void OnServerQuit(Server *server) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user quits, or is killed
* @param u The user
* @param msg The quit message
*/
virtual void OnUserQuit(User *u, const Anope::string &msg) { throw NotImplementedException(); }
virtual void OnUserQuit(User *u, const Anope::string &msg) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user is quit, before and after being internally removed from
* This is different from OnUserQuit, which takes place at the time of the quit.
@@ -572,43 +574,43 @@ public:
* all lists (channels, user list, etc)
* @param u The user
*/
virtual void OnPreUserLogoff(User *u) { throw NotImplementedException(); }
virtual void OnPostUserLogoff(User *u) { throw NotImplementedException(); }
virtual void OnPreUserLogoff(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnPostUserLogoff(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new bot is made
* @param bi The bot
*/
virtual void OnBotCreate(BotInfo *bi) { throw NotImplementedException(); }
virtual void OnBotCreate(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a bot is changed
* @param bi The bot
*/
virtual void OnBotChange(BotInfo *bi) { throw NotImplementedException(); }
virtual void OnBotChange(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a bot is deleted
* @param bi The bot
*/
virtual void OnBotDelete(BotInfo *bi) { throw NotImplementedException(); }
virtual void OnBotDelete(BotInfo *bi) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after an access entry is deleted from a channel
* @param ci The channel
* @param source The source of the command
* @param access The access entry that was removed
*/
virtual void OnAccessDel(ChannelInfo *ci, CommandSource &source, ChanAccess *access) { throw NotImplementedException(); }
virtual void OnAccessDel(ChannelInfo *ci, CommandSource &source, ChanAccess *access) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when access is added
* @param ci The channel
* @param source The source of the command
* @param access The access changed
*/
virtual void OnAccessAdd(ChannelInfo *ci, CommandSource &source, ChanAccess *access) { throw NotImplementedException(); }
virtual void OnAccessAdd(ChannelInfo *ci, CommandSource &source, ChanAccess *access) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when the access list is cleared
* @param ci The channel
* @param u The user who cleared the access
*/
virtual void OnAccessClear(ChannelInfo *ci, CommandSource &source) { throw NotImplementedException(); }
virtual void OnAccessClear(ChannelInfo *ci, CommandSource &source) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a level for a channel is changed
* @param source The source of the command
@@ -616,63 +618,63 @@ public:
* @param priv The privilege changed
* @param what The new level
*/
virtual void OnLevelChange(CommandSource &source, ChannelInfo *ci, const Anope::string &priv, int16_t what) { throw NotImplementedException(); }
virtual void OnLevelChange(CommandSource &source, ChannelInfo *ci, const Anope::string &priv, int16_t what) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called right before a channel is dropped
* @param source The user dropping the channel
* @param ci The channel
*/
virtual EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) { throw NotImplementedException(); }
virtual EventReturn OnChanDrop(CommandSource &source, ChannelInfo *ci) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channel is registered
* @param ci The channel
*/
virtual void OnChanRegistered(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnChanRegistered(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is suspended
* @param ci The channel
*/
virtual void OnChanSuspend(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnChanSuspend(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is unsuspended
* @param ci The channel
*/
virtual void OnChanUnsuspend(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnChanUnsuspend(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is being created, for any reason
* @param ci The channel
*/
virtual void OnCreateChan(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnCreateChan(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is being deleted, for any reason
* @param ci The channel
*/
virtual void OnDelChan(ChannelInfo *ci) { throw NotImplementedException(); }
virtual void OnDelChan(ChannelInfo *ci) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a new channel is created
* Note that this channel may not be introduced to the uplink at this point.
* @param c The channel
*/
virtual void OnChannelCreate(Channel *c) { throw NotImplementedException(); }
virtual void OnChannelCreate(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a channel is deleted
* @param c The channel
*/
virtual void OnChannelDelete(Channel *c) { throw NotImplementedException(); }
virtual void OnChannelDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called after adding an akick to a channel
* @param source The source of the command
* @param ci The channel
* @param ak The akick
*/
virtual void OnAkickAdd(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) { throw NotImplementedException(); }
virtual void OnAkickAdd(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called before removing an akick from a channel
* @param source The source of the command
* @param ci The channel
* @param ak The akick
*/
virtual void OnAkickDel(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) { throw NotImplementedException(); }
virtual void OnAkickDel(CommandSource &source, ChannelInfo *ci, const AutoKick *ak) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called after a user join a channel when we decide whether to kick them or not
* @param u The user
@@ -682,7 +684,7 @@ public:
* @param reason The reason for the kick
* @return EVENT_STOP to prevent the user from joining by kicking/banning the user
*/
virtual EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) { throw NotImplementedException(); }
virtual EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user requests info for a channel
* @param source The user requesting info
@@ -690,109 +692,109 @@ public:
* @param info Data to show the user requesting information
* @param show_hidden true if we should show the user everything
*/
virtual void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) { throw NotImplementedException(); }
virtual void OnChanInfo(CommandSource &source, ChannelInfo *ci, InfoFormatter &info, bool show_hidden) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Checks if access has the channel privilege 'priv'.
* @param access THe access struct
* @param priv The privilege being checked for
* @return EVENT_ALLOW for yes, EVENT_STOP to stop all processing
*/
virtual EventReturn OnCheckPriv(const ChanAccess *access, const Anope::string &priv) { throw NotImplementedException(); }
virtual EventReturn OnCheckPriv(const ChanAccess *access, const Anope::string &priv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Check whether an access group has a privilege
* @param group The group
* @param priv The privilege
* @return MOD_ALLOW to allow, MOD_STOP to stop
*/
virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) { throw NotImplementedException(); }
virtual EventReturn OnGroupCheckPriv(const AccessGroup *group, const Anope::string &priv) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is dropped
* @param source The source of the command
* @param na The nick
*/
virtual void OnNickDrop(CommandSource &source, NickAlias *na) { throw NotImplementedException(); }
virtual void OnNickDrop(CommandSource &source, NickAlias *na) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user groups their nick
* @param u The user grouping
* @param target The target they're grouping to
*/
virtual void OnNickGroup(User *u, NickAlias *target) { throw NotImplementedException(); }
virtual void OnNickGroup(User *u, NickAlias *target) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a user identifies to a nick
* @param u The user
*/
virtual void OnNickIdentify(User *u) { throw NotImplementedException(); }
virtual void OnNickIdentify(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user is logged into an account
* @param u The user
*/
virtual void OnUserLogin(User *u) { throw NotImplementedException(); }
virtual void OnUserLogin(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick logs out
* @param u The nick
*/
virtual void OnNickLogout(User *u) { throw NotImplementedException(); }
virtual void OnNickLogout(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is registered
* @param user The user registering the nick, of any
* @param The nick
* @param pass The password of the newly registered nick
*/
virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) { throw NotImplementedException(); }
virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a nick is confirmed. This will never be called if registration confirmation is not enabled.
* @param user The user confirming the nick
* @param The account being confirmed
* @param nc The account being confirmed
*/
virtual void OnNickConfirm(User *user, NickCore *) { throw NotImplementedException(); }
virtual void OnNickConfirm(User *user, NickCore *nc) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a nick is suspended
* @param na The nick alias
*/
virtual void OnNickSuspend(NickAlias *na) { throw NotImplementedException(); }
virtual void OnNickSuspend(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nick is unsuspended
* @param na The nick alias
*/
virtual void OnNickUnsuspended(NickAlias *na) { throw NotImplementedException(); }
virtual void OnNickUnsuspended(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on delnick()
* @ param na pointer to the nickalias
*/
virtual void OnDelNick(NickAlias *na) { throw NotImplementedException(); }
virtual void OnDelNick(NickAlias *na) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a nickcore is created
* @param nc The nickcore
*/
virtual void OnNickCoreCreate(NickCore *nc) { throw NotImplementedException(); }
virtual void OnNickCoreCreate(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on delcore()
* @param nc pointer to the NickCore
*/
virtual void OnDelCore(NickCore *nc) { throw NotImplementedException(); }
virtual void OnDelCore(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called on change_core_display()
* @param nc pointer to the NickCore
* @param newdisplay the new display
*/
virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) { throw NotImplementedException(); }
virtual void OnChangeCoreDisplay(NickCore *nc, const Anope::string &newdisplay) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** called from NickCore::ClearCert()
* @param nc pointer to the NickCore
*/
virtual void OnNickClearCert(NickCore *nc) { throw NotImplementedException(); }
virtual void OnNickClearCert(NickCore *nc) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user adds an entry to their cert list
* @param nc The nick
* @param entry The entry
*/
virtual void OnNickAddCert(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
virtual void OnNickAddCert(NickCore *nc, const Anope::string &entry) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called from NickCore::EraseCert()
* @param nc pointer to the NickCore
* @param entry The fingerprint
*/
virtual void OnNickEraseCert(NickCore *nc, const Anope::string &entry) { throw NotImplementedException(); }
virtual void OnNickEraseCert(NickCore *nc, const Anope::string &entry) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user requests info for a nick
* @param source The user requesting info
@@ -800,55 +802,55 @@ public:
* @param info Data to show the user requesting information
* @param show_hidden true if we should show the user everything
*/
virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) { throw NotImplementedException(); }
virtual void OnNickInfo(CommandSource &source, NickAlias *na, InfoFormatter &info, bool show_hidden) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user uses botserv/info on a bot or channel.
*/
virtual void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) { throw NotImplementedException(); }
virtual void OnBotInfo(CommandSource &source, BotInfo *bi, ChannelInfo *ci, InfoFormatter &info) ATTR_NOT_NULL(4) { throw NotImplementedException(); }
/** Check whether a username and password is correct
* @param u The user trying to identify, if applicable.
* @param req The login request
*/
virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) { throw NotImplementedException(); }
virtual void OnCheckAuthentication(User *u, IdentifyRequest *req) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a user does /ns update
* @param u The user
*/
virtual void OnNickUpdate(User *u) { throw NotImplementedException(); }
virtual void OnNickUpdate(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we get informed about a users SSL fingerprint
* when we call this, the fingerprint should already be stored in the user struct
* @param u pointer to the user
*/
virtual void OnFingerprint(User *u) { throw NotImplementedException(); }
virtual void OnFingerprint(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user becomes (un)away
* @param message The message, is .empty() if unaway
*/
virtual void OnUserAway(User *u, const Anope::string &message) { throw NotImplementedException(); }
virtual void OnUserAway(User *u, const Anope::string &message) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user invites one of our users to a channel
* @param source The user doing the inviting
* @param c The channel the user is inviting to
* @param targ The user being invited
*/
virtual void OnInvite(User *source, Channel *c, User *targ) { throw NotImplementedException(); }
virtual void OnInvite(User *source, Channel *c, User *targ) ATTR_NOT_NULL(2, 3, 4) { throw NotImplementedException(); }
/** 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) ATTR_NOT_NULL(2) { 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) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a users host changes
* @param u The user
*/
virtual void OnSetDisplayedHost(User *) { throw NotImplementedException(); }
virtual void OnSetDisplayedHost(User *u) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a memo is sent
* @param source The source of the memo
@@ -856,14 +858,14 @@ public:
* @param mi Memo info for target
* @param m The memo
*/
virtual void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) { throw NotImplementedException(); }
virtual void OnMemoSend(const Anope::string &source, const Anope::string &target, MemoInfo *mi, Memo *m) ATTR_NOT_NULL(4, 5) { throw NotImplementedException(); }
/** Called when a memo is deleted
* @param target The target the memo is being deleted from (nick or channel)
* @param mi The memo info
* @param m The memo
*/
virtual void OnMemoDel(const Anope::string &target, MemoInfo *mi, const Memo *m) { throw NotImplementedException(); }
virtual void OnMemoDel(const Anope::string &target, MemoInfo *mi, const Memo *m) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a mode is set on a channel
* @param c The channel
@@ -872,7 +874,7 @@ public:
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
virtual EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when a mode is unset on a channel
* @param c The channel
@@ -881,67 +883,67 @@ public:
* @param param The mode param, if there is one
* @return EVENT_STOP to make mlock/secureops etc checks not happen
*/
virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) { throw NotImplementedException(); }
virtual EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelMode *mode, const Anope::string &param) ATTR_NOT_NULL(2, 4) { throw NotImplementedException(); }
/** Called when a mode is set on a user
* @param setter who/what is setting the mode
* @param u The user
* @param mname The mode name
*/
virtual void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) { throw NotImplementedException(); }
virtual void OnUserModeSet(const MessageSource &setter, User *u, const Anope::string &mname) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a mode is unset from a user
* @param setter who/what is setting the mode
* @param u The user
* @param mname The mode name
*/
virtual void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) { throw NotImplementedException(); }
virtual void OnUserModeUnset(const MessageSource &setter, User *u, const Anope::string &mname) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channel mode is introduced into Anope
* @param cm The mode
*/
virtual void OnChannelModeAdd(ChannelMode *cm) { throw NotImplementedException(); }
virtual void OnChannelModeAdd(ChannelMode *cm) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a user mode is introduced into Anope
* @param um The mode
*/
virtual void OnUserModeAdd(UserMode *um) { throw NotImplementedException(); }
virtual void OnUserModeAdd(UserMode *um) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a mode is about to be mlocked
* @param ci The channel the mode is being locked on
* @param lock The mode lock
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock.
*/
virtual EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) { throw NotImplementedException(); }
virtual EventReturn OnMLock(ChannelInfo *ci, ModeLock *lock) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a mode is about to be unlocked
* @param ci The channel the mode is being unlocked from
* @param lock The mode lock
* @return EVENT_CONTINUE to let other modules decide, EVENT_STOP to deny the mlock.
*/
virtual EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) { throw NotImplementedException(); }
virtual EventReturn OnUnMLock(ChannelInfo *ci, ModeLock *lock) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called after a module is loaded
* @param u The user loading the module, can be NULL
* @param m The module
*/
virtual void OnModuleLoad(User *u, Module *m) { throw NotImplementedException(); }
virtual void OnModuleLoad(User *u, Module *m) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called before a module is unloaded
* @param u The user, can be NULL
* @param m The module
*/
virtual void OnModuleUnload(User *u, Module *m) { throw NotImplementedException(); }
virtual void OnModuleUnload(User *u, Module *m) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a server is synced
* @param s The server, can be our uplink server
*/
virtual void OnServerSync(Server *s) { throw NotImplementedException(); }
virtual void OnServerSync(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we sync with our uplink
* @param s Our uplink
*/
virtual void OnUplinkSync(Server *s) { throw NotImplementedException(); }
virtual void OnUplinkSync(Server *s) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when we receive a PRIVMSG for one of our clients
* @param u The user sending the PRIVMSG
@@ -950,7 +952,7 @@ public:
* @param tags Message tags
* @return EVENT_STOP to halt processing
*/
virtual EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) { throw NotImplementedException(); }
virtual EventReturn OnBotPrivmsg(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when we receive a NOTICE for one of our clients
* @param u The user sending the NOTICE
@@ -958,7 +960,7 @@ public:
* @param tags Message tags
* @param message The message
*/
virtual void OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) { throw NotImplementedException(); }
virtual void OnBotNotice(User *u, BotInfo *bi, Anope::string &message, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when we receive a PRIVMSG for a registered channel we are in
* @param u The source of the message
@@ -966,12 +968,12 @@ public:
* @param msg The message
* @param tags Message tags
*/
virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) { throw NotImplementedException(); }
virtual void OnPrivmsg(User *u, Channel *c, Anope::string &msg, const Anope::map<Anope::string> &tags) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a message is logged
* @param l The log message
*/
virtual void OnLog(Log *l) { throw NotImplementedException(); }
virtual void OnLog(Log *l) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a log message is actually logged to a given log info
* The message has already passed validation checks by the LogInfo
@@ -979,13 +981,13 @@ public:
* @param l The log message
* @param msg The final formatted message, derived from 'l'
*/
virtual void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) { throw NotImplementedException(); }
virtual void OnLogMessage(LogInfo *li, const Log *l, const Anope::string &msg) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
/** Called when a DNS request (question) is received.
* @param req The dns request
* @param reply The reply that will be sent
*/
virtual void OnDnsRequest(DNS::Query &req, DNS::Query *reply) { throw NotImplementedException(); }
virtual void OnDnsRequest(DNS::Query &req, DNS::Query *reply) ATTR_NOT_NULL(3) { throw NotImplementedException(); }
/** Called when a channels modes are being checked to see if they are allowed,
* mostly to ensure mlock/+r are set.
@@ -998,7 +1000,7 @@ public:
* for a newly created channel to set the correct modes, topic,
* set.
*/
virtual void OnChannelSync(Channel *c) { throw NotImplementedException(); }
virtual void OnChannelSync(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called to set the correct modes on the user on the given channel
* @param user The user
@@ -1007,13 +1009,13 @@ public:
* @param give_modes If giving modes is desired
* @param take_modes If taking modes is desired
*/
virtual void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) { throw NotImplementedException(); }
virtual void OnSetCorrectModes(User *user, Channel *chan, AccessGroup &access, bool &give_modes, bool &take_modes) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
virtual void OnSerializeCheck(Serialize::Type *) { throw NotImplementedException(); }
virtual void OnSerializableConstruct(Serializable *) { throw NotImplementedException(); }
virtual void OnSerializableDestruct(Serializable *) { throw NotImplementedException(); }
virtual void OnSerializableUpdate(Serializable *) { throw NotImplementedException(); }
virtual void OnSerializeTypeCreate(Serialize::Type *) { throw NotImplementedException(); }
virtual void OnSerializeCheck(Serialize::Type *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnSerializableConstruct(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnSerializableDestruct(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnSerializableUpdate(Serializable *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
virtual void OnSerializeTypeCreate(Serialize::Type *st) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called when a chanserv/set command is used
* @param source The source of the command
@@ -1022,7 +1024,7 @@ public:
* @param setting The setting passed to the command. Probably ON/OFF.
* @return EVENT_ALLOW to bypass access checks, EVENT_STOP to halt immediately.
*/
virtual EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) { throw NotImplementedException(); }
virtual EventReturn OnSetChannelOption(CommandSource &source, Command *cmd, ChannelInfo *ci, const Anope::string &setting) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called when a nickserv/set command is used.
* @param source The source of the command
@@ -1031,7 +1033,7 @@ public:
* @param setting The setting passed to the command. Probably ON/OFF.
* @return EVENT_STOP to halt immediately
*/
virtual EventReturn OnSetNickOption(CommandSource &source, Command *cmd, NickCore *nc, const Anope::string &setting) { throw NotImplementedException(); }
virtual EventReturn OnSetNickOption(CommandSource &source, Command *cmd, NickCore *nc, const Anope::string &setting) ATTR_NOT_NULL(3, 4) { throw NotImplementedException(); }
/** Called whenever a message is received from the uplink
* @param source The source of the message
@@ -1046,9 +1048,9 @@ public:
* @param u The user
* @param cm The mode
*/
virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) { throw NotImplementedException(); }
virtual EventReturn OnCanSet(User *u, const ChannelMode *cm) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
virtual EventReturn OnCheckDelete(Channel *) { throw NotImplementedException(); }
virtual EventReturn OnCheckDelete(Channel *c) ATTR_NOT_NULL(2) { throw NotImplementedException(); }
/** Called every options:expiretimeout seconds. Should be used to expire nicks,
* channels, etc.
@@ -1061,7 +1063,7 @@ public:
* @param na The nick they are on
* @return EVENT_STOP to force the user off of the nick
*/
virtual EventReturn OnNickValidate(User *u, NickAlias *na) { throw NotImplementedException(); }
virtual EventReturn OnNickValidate(User *u, NickAlias *na) ATTR_NOT_NULL(2, 3) { throw NotImplementedException(); }
};
enum Implementation
@@ -1081,7 +1083,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,
+117 -8
View File
@@ -13,26 +13,135 @@
namespace Encryption
{
typedef std::pair<const unsigned char *, size_t> Hash;
typedef std::pair<const uint32_t *, size_t> IV;
/** Base class for encryption contexts. */
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;
virtual void Finalize() = 0;
virtual Hash GetFinalizedHash() = 0;
/** Finalises the encryption context and returns the digest. */
virtual Anope::string Finalize() = 0;
};
/** Provider of encryption contexts. */
class Provider
: public Service
{
public:
Provider(Module *creator, const Anope::string &sname) : Service(creator, "Encryption::Provider", sname) { }
/** 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)
{
}
virtual ~Provider() = default;
virtual Context *CreateContext(IV * = NULL) = 0;
virtual IV GetDefaultIV() = 0;
/** 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>();
}
};
}
+23
View File
@@ -0,0 +1,23 @@
/*
*
* (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
@@ -0,0 +1,49 @@
/*
*
* (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;
};
+1
View File
@@ -79,4 +79,5 @@ public:
CertService(Module *c) : Service(c, "CertService", "certs") { }
virtual NickCore *FindAccountFromCert(const Anope::string &cert) = 0;
virtual void ReplaceCert(const Anope::string &oldcert, const Anope::string &newcert) = 0;
};
+46
View File
@@ -0,0 +1,46 @@
/*
*
* (C) 2011-2024 Anope Team
* Contact us at team@anope.org
*
* Please read COPYING and README for further details.
*/
#pragma once
struct MyOper final
: Oper
, Serializable
{
MyOper(const Anope::string &n, OperType *o) : Oper(n, o), Serializable("Oper") { }
void Serialize(Serialize::Data &data) const override
{
data.Store("name", this->name);
data.Store("type", this->ot->GetName());
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
{
Anope::string stype, sname;
data["type"] >> stype;
data["name"] >> sname;
OperType *ot = OperType::Find(stype);
if (ot == NULL)
return NULL;
NickCore *nc = NickCore::Find(sname);
if (nc == NULL)
return NULL;
MyOper *myo;
if (obj)
myo = anope_dynamic_static_cast<MyOper *>(obj);
else
myo = new MyOper(nc->display, ot);
nc->o = myo;
Log(LOG_NORMAL, "operserv/oper") << "Tied oper " << nc->display << " to type " << ot->GetName();
return myo;
}
};
+6 -6
View File
@@ -62,12 +62,12 @@ static ServiceReference<SessionService> session_service("SessionService", "sessi
void Exception::Serialize(Serialize::Data &data) const
{
data["mask"] << this->mask;
data["limit"] << this->limit;
data["who"] << this->who;
data["reason"] << this->reason;
data["time"] << this->time;
data["expires"] << this->expires;
data.Store("mask", this->mask);
data.Store("limit", this->limit);
data.Store("who", this->who);
data.Store("reason", this->reason);
data.Store("time", this->time);
data.Store("expires", this->expires);
}
Serializable *Exception::Unserialize(Serializable *obj, Serialize::Data &data)
+54 -7
View File
@@ -8,21 +8,68 @@
#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() = 0;
virtual Reference<BotInfo> GetDefaultSender() const = 0;
/** 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
/** Clears any queued messages for the specified account.
* @param nc The account to clear queued messages for.
*/
virtual void SendGlobal(BotInfo *sender, const Anope::string &source, const Anope::string &message) = 0;
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;
};
+14 -21
View File
@@ -8,6 +8,8 @@
#pragma once
#include <stdexcept>
namespace SQL
{
@@ -17,7 +19,7 @@ namespace SQL
public:
typedef std::map<Anope::string, std::stringstream *> Map;
Map data;
std::map<Anope::string, Type> types;
std::map<Anope::string, Serialize::DataType> types;
~Data()
{
@@ -32,14 +34,6 @@ namespace SQL
return *ss;
}
std::set<Anope::string> KeySet() const override
{
std::set<Anope::string> keys;
for (const auto &[key, _] : this->data)
keys.insert(key);
return keys;
}
size_t Hash() const override
{
size_t hash = 0;
@@ -66,17 +60,17 @@ namespace SQL
this->data.clear();
}
void SetType(const Anope::string &key, Type t) override
void SetType(const Anope::string &key, Serialize::DataType dt) override
{
this->types[key] = t;
this->types[key] = dt;
}
Type GetType(const Anope::string &key) const override
Serialize::DataType GetType(const Anope::string &key) const override
{
std::map<Anope::string, Type>::const_iterator it = this->types.find(key);
auto it = this->types.find(key);
if (it != this->types.end())
return it->second;
return DT_TEXT;
return Serialize::DataType::TEXT;
}
};
@@ -126,13 +120,12 @@ namespace SQL
template<typename T> void SetValue(const Anope::string &key, const T &value, bool escape = true)
{
try
{
Anope::string string_value = stringify(value);
this->parameters[key].data = string_value;
this->parameters[key].escape = escape;
}
catch (const ConvertException &ex) { }
auto str = Anope::TryString(value);
if (!str.has_value())
return;
this->parameters[key].data = str.value();
this->parameters[key].escape = escape;
}
};
+52 -33
View File
@@ -16,6 +16,17 @@
#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
@@ -30,9 +41,9 @@ public:
virtual ~IRCDProto();
virtual void SendNoticeInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
virtual void SendPrivmsgInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
virtual void SendCTCPInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &msg, const Anope::map<Anope::string> &tags = {});
virtual void SendTagmsg(const MessageSource &source, const Anope::string &dest, const Anope::map<Anope::string> &tags);
/** Parses an incoming message from the IRC server.
* @param message The message to parse.
@@ -63,6 +74,9 @@ public:
/* Can we force join or part users? */
bool CanSVSJoin = false;
/** Can we force servers to remove opers? */
bool CanSVSNOOP = false;
/* Can we set vhosts on users? */
bool CanSetVHost = false;
@@ -87,9 +101,6 @@ public:
/* See ns_cert */
bool CanCertFP = false;
/* Can users log out before being fully connected? */
bool CanSVSLogout = false;
/* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */
bool RequiresID = false;
@@ -99,16 +110,40 @@ public:
/** Can we ask the server to unban a user? */
bool CanClearBans = false;
/* The maximum number of modes we are allowed to set with one MODE command */
unsigned MaxModes = 3;
/** Can we send tag messages? */
bool CanTagMessage = 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 bytes a line may have */
unsigned MaxLine = 512;
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;
/* 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
@@ -127,8 +162,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
@@ -164,14 +199,14 @@ public:
template <typename... Args>
void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args &&...args)
{
SendModeInternal(source, chan, modes, { stringify(args)... });
SendModeInternal(source, chan, modes, { Anope::ToString(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, { stringify(args)... });
SendModeInternal(source, u, modes, { Anope::ToString(args)... });
}
/** Introduces a client to the rest of the network
@@ -181,11 +216,6 @@ public:
virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const Anope::string &msg);
virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) ATTR_FORMAT(4, 5);
virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) ATTR_FORMAT(4, 5);
virtual void SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) ATTR_FORMAT(4, 5);
virtual void SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) ATTR_FORMAT(4, 5);
virtual void SendGlobalNotice(BotInfo *bi, const Server *dest, const Anope::string &msg) = 0;
virtual void SendGlobalPrivmsg(BotInfo *bi, const Server *desc, const Anope::string &msg) = 0;
@@ -210,9 +240,9 @@ public:
* @param bi The source of the message
* @param u The user to join
* @param chan The channel to join the user to
* @param param Channel key?
* @param key Channel key
*/
virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &param) { }
virtual void SendSVSJoin(const MessageSource &source, User *u, const Anope::string &chan, const Anope::string &key) { }
/** Force parts a user that isn't ours from a channel.
* @param source The source of the message
@@ -258,7 +288,7 @@ public:
template <typename... Args>
void SendNumeric(int numeric, const Anope::string &dest, Args &&...args)
{
SendNumericInternal(numeric, dest, { stringify(args)... });
SendNumericInternal(numeric, dest, { Anope::ToString(args)... });
}
virtual void SendLogin(User *u, NickAlias *na) = 0;
@@ -267,7 +297,7 @@ public:
/** Send a channel creation message to the uplink.
* On most TS6 IRCds this is a SJOIN with no nick
*/
virtual void SendChannel(Channel *c) { }
virtual void SendChannel(Channel *c) = 0;
/** Make the user an IRC operator
* Normally this is a simple +o, though some IRCds require us to send the oper type
@@ -294,17 +324,6 @@ 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::hash_map<ChannelInfo *> registered_channel_map;
typedef Anope::unordered_map<ChannelInfo *> registered_channel_map;
extern CoreExport Serialize::Checker<registered_channel_map> RegisteredChannelList;
+30 -9
View File
@@ -18,23 +18,44 @@
namespace Serialize
{
enum class DataType
: uint8_t
{
BOOL,
FLOAT,
INT,
TEXT,
UINT,
};
class Data
{
public:
enum Type
{
DT_TEXT,
DT_INT
};
virtual ~Data() = default;
virtual std::iostream &operator[](const Anope::string &key) = 0;
virtual std::set<Anope::string> KeySet() const { throw CoreException("Not supported"); }
template <typename T>
void Store(const Anope::string &key, const T &value)
{
using Type = std::remove_cv_t<std::remove_reference_t<T>>;
if constexpr (std::is_same_v<Type, bool>)
SetType(key, DataType::BOOL);
else if constexpr (std::is_floating_point_v<Type>)
SetType(key, DataType::FLOAT);
else if constexpr (std::is_integral_v<Type> && std::is_signed_v<Type>)
SetType(key, DataType::INT);
else if constexpr (std::is_integral_v<Type> && std::is_unsigned_v<Type>)
SetType(key, DataType::UINT);
this->operator[](key) << value;
}
virtual size_t Hash() const { throw CoreException("Not supported"); }
virtual void SetType(const Anope::string &key, Type t) { }
virtual Type GetType(const Anope::string &key) const { return DT_TEXT; }
virtual void SetType(const Anope::string &key, DataType dt) { }
virtual DataType GetType(const Anope::string &key) const { return DataType::TEXT; }
};
extern void RegisterTypes();
+24 -29
View File
@@ -11,39 +11,34 @@
#pragma once
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#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
+20
View File
@@ -20,6 +20,24 @@
// Whether Anope was built in debug mode.
#cmakedefine01 DEBUG_BUILD
// The default config directory.
#define DEFAULT_CONF_DIR "@CONF_DIR@"
// The default data directory.
#define DEFAULT_DATA_DIR "@DATA_DIR@"
// The default locale directory.
#define DEFAULT_LOCALE_DIR "@LOCALE_DIR@"
// The default log directory.
#define DEFAULT_LOG_DIR "@LOG_DIR@"
// The default module directory.
#define DEFAULT_MODULE_DIR "@MODULE_DIR@"
// Whether the clock_gettime() function is available.
#cmakedefine01 HAVE_CLOCK_GETTIME
// Whether Anope was built with localization support.
#cmakedefine01 HAVE_LOCALIZATION
@@ -33,6 +51,8 @@
#if defined __GNUC__
# define ATTR_FORMAT(STRINGPOS, FIRSTPOS) __attribute__((format(printf, STRINGPOS, FIRSTPOS)))
# define ATTR_NOT_NULL(...) __attribute__((nonnull(__VA_ARGS__)))
#else
# define ATTR_FORMAT(STRINGPOS, FIRSTPOS)
# define ATTR_NOT_NULL(...)
#endif
+1 -1
View File
@@ -18,7 +18,7 @@ class CoreExport Timer
private:
/** The owner of the timer, if any
*/
Module *owner;
Module *owner = nullptr;
/** 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, { stringify(args)... });
SendInternal(tags, source, command, { Anope::ToString(args)... });
}
template<typename... Args>
void Send(const Anope::map<Anope::string> &tags, const Anope::string &command, Args &&...args)
{
SendInternal(tags, Me, command, { stringify(args)... });
SendInternal(tags, Me, command, { Anope::ToString(args)... });
}
template<typename... Args>
void Send(const MessageSource &source, const Anope::string &command, Args &&...args)
{
SendInternal({}, source, command, { stringify(args)... });
SendInternal({}, source, command, { Anope::ToString(args)... });
}
template<typename... Args>
void Send(const Anope::string &command, Args &&...args)
{
SendInternal({}, Me, command, { stringify(args)... });
SendInternal({}, Me, command, { Anope::ToString(args)... });
}
}
+6 -1
View File
@@ -19,7 +19,7 @@
#include "account.h"
#include "sockets.h"
typedef Anope::hash_map<User *> user_map;
typedef Anope::unordered_map<User *> user_map;
extern CoreExport user_map UserListByNick, UserListByUID;
@@ -215,6 +215,11 @@ public:
*/
NickCore *Account() const;
/** Get the account nick the user is logged in using
* @return The account nick or NULL
*/
NickAlias *AccountNick() const;
/** Check if the user is identified for their nick
* @param check_nick True to check if the user is identified to the nickname they are on too
* @return true or false
+1 -1
View File
@@ -42,7 +42,7 @@ static std::string get_git_hash(const std::string &git_dir)
}
fd.close();
return "g" + filebuf.substr(0, 7);
return filebuf.substr(0, 7);
}
static bool read_version_sh(const std::string &version_sh, std::map<std::string, std::string> &versions)
File diff suppressed because it is too large Load Diff
+500 -414
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2350 -4599
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+260 -367
View File
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -19,18 +19,13 @@ 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")
@@ -99,7 +94,9 @@ macro(build_modules SRC)
target_link_libraries(${SO} ${PROGRAM_NAME})
endif()
# Set the module to be installed to the module directory under the data directory
install(TARGETS ${SO} DESTINATION ${LIB_DIR}/modules)
install(TARGETS ${SO}
DESTINATION ${MODULE_DIR}
LIBRARY)
endif()
endif()
endforeach()
@@ -173,7 +170,9 @@ macro(build_subdir)
endif()
# Set the module to be installed to the module directory under the data directory
install(TARGETS ${SO} DESTINATION ${LIB_DIR}/modules)
install(TARGETS ${SO}
DESTINATION ${MODULE_DIR}
LIBRARY)
endmacro()
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+17 -12
View File
@@ -57,29 +57,34 @@ public:
BotInfo *bi = user->server == Me ? dynamic_cast<BotInfo *>(user) : NULL;
if (bi && Config->GetModule(this)->Get<bool>("smartjoin"))
{
/* We check for bans */
for (const auto &entry : c->GetModeList("BAN"))
if (IRCD->CanClearBans)
{
Entry ban("BAN", entry);
if (ban.Matches(user))
c->RemoveMode(NULL, "BAN", ban.GetMask());
// We can ask the IRCd to clear bans.
IRCD->SendClearBans(bi, c, bi);
}
else
{
// We have to check for bans.
for (const auto &entry : c->GetModeList("BAN"))
{
Entry ban("BAN", entry);
if (ban.Matches(user))
c->RemoveMode(NULL, "BAN", ban.GetMask());
}
}
Anope::string Limit;
unsigned limit = 0;
try
{
if (c->GetParam("LIMIT", Limit))
limit = convertTo<unsigned>(Limit);
}
catch (const ConvertException &) { }
if (c->GetParam("LIMIT", Limit))
limit = Anope::Convert<unsigned>(Limit, limit);
/* Should we be invited? */
if (c->HasMode("INVITE") || (limit && c->users.size() >= limit))
{
ChannelMode *cm = ModeManager::FindChannelModeByName("OP");
char symbol = cm ? anope_dynamic_static_cast<ChannelModeStatus *>(cm)->symbol : 0;
IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, "%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
const auto message = Anope::printf("%s invited %s into the channel.", user->nick.c_str(), user->nick.c_str());
IRCD->SendNotice(bi, (symbol ? Anope::string(symbol) : "") + c->name, message);
}
ModeManager::ProcessModes();
+3 -3
View File
@@ -28,7 +28,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot assignment is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
@@ -97,7 +97,7 @@ public:
{
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot assignment is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
@@ -164,7 +164,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
+6 -6
View File
@@ -21,9 +21,9 @@ struct BadWordImpl final
void Serialize(Serialize::Data &data) const override
{
data["ci"] << this->chan;
data["word"] << this->word;
data.SetType("type", Serialize::Data::DT_INT); data["type"] << this->type;
data.Store("ci", this->chan);
data.Store("word", this->word);
data.Store("type", this->type);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &);
@@ -222,7 +222,7 @@ private:
const BadWord *b = bw->GetBadWord(Number - 1);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(Number);
entry["Number"] = Anope::ToString(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"] = stringify(i + 1);
entry["Number"] = Anope::ToString(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(_("Sorry, bad words list modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
+13 -13
View File
@@ -28,21 +28,21 @@ private:
return;
}
if (nick.length() > IRCD->GetMaxNick())
if (nick.length() > IRCD->MaxNick)
{
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->GetMaxNick());
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
return;
}
if (user.length() > IRCD->GetMaxUser())
if (user.length() > IRCD->MaxUser)
{
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->GetMaxUser());
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
return;
}
if (host.length() > IRCD->GetMaxHost())
if (host.length() > IRCD->MaxHost)
{
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->GetMaxHost());
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost);
return;
}
@@ -118,21 +118,21 @@ private:
return;
}
if (nick.length() > IRCD->GetMaxNick())
if (nick.length() > IRCD->MaxNick)
{
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->GetMaxNick());
source.Reply(_("Bot nicks may only be %zu characters long."), IRCD->MaxNick);
return;
}
if (user.length() > IRCD->GetMaxUser())
if (user.length() > IRCD->MaxUser)
{
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->GetMaxUser());
source.Reply(_("Bot idents may only be %zu characters long."), IRCD->MaxUser);
return;
}
if (host.length() > IRCD->GetMaxHost())
if (host.length() > IRCD->MaxHost)
{
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->GetMaxHost()
source.Reply(_("Bot hosts may only be %zu characters long."), IRCD->MaxHost
);
return;
}
@@ -276,7 +276,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
+2 -6
View File
@@ -56,7 +56,7 @@ public:
return;
}
IRCD->SendPrivmsg(*ci->bi, ci->name, "%s", text.c_str());
IRCD->SendPrivmsg(*ci->bi, ci->name, text);
ci->bi->lastmsg = Anope::CurTime;
bool override = !source.AccessFor(ci).HasPriv("SAY");
@@ -111,11 +111,7 @@ public:
return;
}
message = message.replace_all_cs("\1", "");
if (message.empty())
return;
IRCD->SendAction(*ci->bi, ci->name, "%s", message.c_str());
IRCD->SendPrivmsg(*ci->bi, ci->name, Anope::FormatCTCP("ACTION", message));
ci->bi->lastmsg = Anope::CurTime;
bool override = !source.AccessFor(ci).HasPriv("SAY");
+2 -2
View File
@@ -50,12 +50,12 @@ public:
if (bi)
{
source.Reply(_("Information for bot \002%s\002:"), bi->nick.c_str());
source.Reply(_("Information about bot \002%s\002:"), bi->nick.c_str());
info[_("Mask")] = bi->GetIdent() + "@" + bi->host;
info[_("Real name")] = bi->realname;
info[_("Created")] = Anope::strftime(bi->created, source.GetAccount());
info[_("Options")] = bi->oper_only ? _("Private") : _("None");
info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";
info[_("Used on")] = Anope::ToString(bi->GetChannelCount()) + " channel(s)";
FOREACH_MOD(OnBotInfo, (source, bi, ci, info));
+47 -101
View File
@@ -53,26 +53,28 @@ struct KickerDataImpl final
if (kd == NULL)
return;
data["kickerdata:amsgs"] << kd->amsgs;
data["kickerdata:badwords"] << kd->badwords;
data["kickerdata:bolds"] << kd->bolds;
data["kickerdata:caps"] << kd->caps;
data["kickerdata:colors"] << kd->colors;
data["kickerdata:flood"] << kd->flood;
data["kickerdata:italics"] << kd->italics;
data["kickerdata:repeat"] << kd->repeat;
data["kickerdata:reverses"] << kd->reverses;
data["kickerdata:underlines"] << kd->underlines;
data.Store("kickerdata:amsgs", kd->amsgs);
data.Store("kickerdata:badwords", kd->badwords);
data.Store("kickerdata:bolds", kd->bolds);
data.Store("kickerdata:caps", kd->caps);
data.Store("kickerdata:colors", kd->colors);
data.Store("kickerdata:flood", kd->flood);
data.Store("kickerdata:italics", kd->italics);
data.Store("kickerdata:repeat", kd->repeat);
data.Store("kickerdata:reverses", kd->reverses);
data.Store("kickerdata:underlines", kd->underlines);
data.Store("capsmin", kd->capsmin);
data.Store("capspercent", kd->capspercent);
data.Store("floodlines", kd->floodlines);
data.Store("floodsecs", kd->floodsecs);
data.Store("repeattimes", kd->repeattimes);
data.Store("dontkickops", kd->dontkickops);
data.Store("dontkickvoices", kd->dontkickvoices);
data.SetType("capsmin", Serialize::Data::DT_INT); data["capsmin"] << kd->capsmin;
data.SetType("capspercent", Serialize::Data::DT_INT); data["capspercent"] << kd->capspercent;
data.SetType("floodlines", Serialize::Data::DT_INT); data["floodlines"] << kd->floodlines;
data.SetType("floodsecs", Serialize::Data::DT_INT); data["floodsecs"] << kd->floodsecs;
data.SetType("repeattimes", Serialize::Data::DT_INT); data["repeattimes"] << kd->repeattimes;
data.SetType("dontkickops", Serialize::Data::DT_INT); data["dontkickops"] << kd->dontkickops;
data.SetType("dontkickvoices", Serialize::Data::DT_INT); data["dontkickvoices"] << kd->dontkickvoices;
std::ostringstream oss;
for (auto ttbtype : kd->ttb)
data["ttb"] << ttbtype << " ";
oss << ttbtype << " ";
data.Store("ttb", oss.str());
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
@@ -106,11 +108,10 @@ struct KickerDataImpl final
data["ttb"] >> ttb;
spacesepstream sep(ttb);
for (int i = 0; sep.GetToken(tok) && i < TTB_SIZE; ++i)
try
{
kd->ttb[i] = convertTo<int16_t>(tok);
}
catch (const ConvertException &) { }
{
if (auto n = Anope::TryConvert<int16_t>(tok))
kd->ttb[i] = n.value();
}
kd->Check(ci);
}
@@ -183,7 +184,7 @@ protected:
ci = ChannelInfo::Find(chan);
if (Anope::ReadOnly)
source.Reply(_("Sorry, kicker configuration is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
else if (ci == NULL)
source.Reply(CHAN_X_NOT_REGISTERED, params[0].c_str());
else if (option.empty())
@@ -206,21 +207,13 @@ protected:
{
if (!ttb.empty())
{
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
kd->ttb[ttb_idx] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[ttb_idx] < 0)
{
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;
@@ -386,13 +379,8 @@ public:
if (!ttb.empty())
{
try
{
kd->ttb[TTB_CAPS] = convertTo<int16_t>(ttb);
if (kd->ttb[TTB_CAPS] < 0)
throw ConvertException();
}
catch (const ConvertException &)
kd->ttb[TTB_CAPS] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[TTB_CAPS] < 0)
{
kd->ttb[TTB_CAPS] = 0;
source.Reply(_("\002%s\002 cannot be taken as times to ban."), ttb.c_str());
@@ -402,21 +390,11 @@ public:
else
kd->ttb[TTB_CAPS] = 0;
kd->capsmin = 10;
try
{
kd->capsmin = convertTo<int16_t>(min);
}
catch (const ConvertException &) { }
kd->capsmin = Anope::Convert(min, 0);
if (kd->capsmin < 1)
kd->capsmin = 10;
kd->capspercent = 25;
try
{
kd->capspercent = convertTo<int16_t>(percent);
}
catch (const ConvertException &) { }
kd->capspercent = Anope::Convert(percent, 0);
if (kd->capspercent < 1 || kd->capspercent > 100)
kd->capspercent = 25;
@@ -518,42 +496,25 @@ public:
if (!ttb.empty())
{
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
kd->ttb[TTB_FLOOD] = Anope::Convert<int16_t>(ttb, -1);
if (kd->ttb[TTB_FLOOD] < 0)
{
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 = 6;
try
{
kd->floodlines = convertTo<int16_t>(lines);
}
catch (const ConvertException &) { }
kd->floodlines = Anope::Convert(lines, -1);
if (kd->floodlines < 2)
kd->floodlines = 6;
kd->floodsecs = 10;
try
{
kd->floodsecs = convertTo<int16_t>(secs);
}
catch (const ConvertException &) { }
kd->floodsecs = Anope::Convert(secs, -1);
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");
@@ -651,31 +612,18 @@ public:
if (!ttb.empty())
{
int16_t i;
try
{
i = convertTo<int16_t>(ttb);
if (i < 0)
throw ConvertException();
}
catch (const ConvertException &)
kd->ttb[TTB_REPEAT] = Anope::Convert(ttb, -1);
if (kd->ttb[TTB_REPEAT] < 0)
{
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 = 3;
try
{
kd->repeattimes = convertTo<int16_t>(times);
}
catch (const ConvertException &) { }
kd->repeattimes = Anope::Convert<int16_t>(times, -1);
if (kd->repeattimes < 1)
kd->repeattimes = 3;
@@ -826,7 +774,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
@@ -892,7 +840,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, bot option setting is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
return;
}
@@ -1270,11 +1218,9 @@ public:
/* If it's a /me, cut the CTCP part because the ACTION will cause
* problems with the caps or badwords kicker
*/
if (realbuf.substr(0, 8).equals_ci("\1ACTION ") && realbuf[realbuf.length() - 1] == '\1')
{
realbuf.erase(0, 8);
realbuf.erase(realbuf.length() - 1);
}
Anope::string ctcpname, ctcpbody;
if (Anope::ParseCTCP(msg, ctcpname, ctcpbody) && ctcpname.equals_ci("ACTION"))
realbuf = ctcpbody;
if (realbuf.empty())
return;
+1 -1
View File
@@ -118,7 +118,7 @@ public:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, changing bot options is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
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", "15s"))
: Timer(m, Config->GetModule(m)->Get<time_t>("inhabit", "1m"))
, ChanServ(cs)
, inhabit(i)
, c(chan)
+14 -23
View File
@@ -37,18 +37,13 @@ public:
Anope::string AccessSerialize() const override
{
return stringify(this->level);
return Anope::ToString(this->level);
}
void AccessUnserialize(const Anope::string &data) override
{
try
{
this->level = convertTo<int>(data);
}
catch (const ConvertException &)
{
}
if (auto l = Anope::TryConvert<int>(data))
this->level = l.value();
}
bool operator>(const ChanAccess &other) const override
@@ -95,11 +90,9 @@ class CommandCSAccess final
Privilege *p = NULL;
int level = ACCESS_INVALID;
try
{
level = convertTo<int>(params[3]);
}
catch (const ConvertException &)
if (auto lvl = Anope::TryConvert<int>(params[3]))
level = lvl.value();
else
{
p = PrivilegeManager::FindPrivilege(params[3]);
if (p != NULL && defaultLevels[p->name])
@@ -207,7 +200,7 @@ class CommandCSAccess final
}
}
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -402,7 +395,7 @@ class CommandCSAccess final
}
ListFormatter::ListEntry entry;
entry["Number"] = stringify(number);
entry["Number"] = Anope::ToString(number);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
@@ -442,7 +435,7 @@ class CommandCSAccess final
}
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(i + 1);
entry["Level"] = access->AccessSerialize();
entry["Mask"] = access->Mask();
entry["By"] = access->creator;
@@ -567,7 +560,7 @@ public:
else if (!has_access)
source.Reply(ACCESS_DENIED);
else if (Anope::ReadOnly && !is_list)
source.Reply(_("Sorry, channel access list modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
else if (cmd.equals_ci("ADD"))
this->DoAdd(source, ci, params);
else if (cmd.equals_ci("DEL"))
@@ -652,11 +645,9 @@ class CommandCSLevels final
level = ACCESS_FOUNDER;
else
{
try
{
level = convertTo<int>(lev);
}
catch (const ConvertException &)
if (auto lvl = Anope::TryConvert<int>(lev))
level = lvl.value();
else
{
this->OnSyntaxError(source, "SET");
return;
@@ -734,7 +725,7 @@ class CommandCSLevels final
else if (j == ACCESS_FOUNDER)
entry["Level"] = Language::Translate(source.GetAccount(), _("(founder only)"));
else
entry["Level"] = stringify(j);
entry["Level"] = Anope::ToString(j);
list.AddEntry(entry);
}
+3 -3
View File
@@ -311,7 +311,7 @@ class CommandCSAKick final
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(number);
entry["Number"] = Anope::ToString(number);
if (akick->nc)
entry["Mask"] = akick->nc->display;
else
@@ -351,7 +351,7 @@ class CommandCSAKick final
lastused = UNKNOWN;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(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(_("Sorry, channel autokick list modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
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", "1024");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
unsigned count = 0;
for (unsigned i = 0; i < target_ci->GetAccessCount(); ++i)
+10 -6
View File
@@ -20,7 +20,7 @@ private:
public:
CommandCSDrop(Module *creator)
: Command(creator, "chanserv/drop", 1, 2)
, dropcode(creator, "dropcode")
, dropcode(creator, "channel-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(_("Sorry, channel de-registration is temporarily disabled.")); // XXX: READ_ONLY_MODE?
source.Reply(READ_ONLY_MODE);
return;
}
@@ -50,16 +50,16 @@ public:
}
auto *code = dropcode.Get(ci);
if (params.size() < 2 || !code || !code->equals_ci(params[1]))
if (params.size() < 2 || ((!code || !code->equals_ci(params[1])) && (!source.HasPriv("chanserv/drop/override") || params[1] != "OVERRIDE")))
{
if (!code)
{
code = ci->Extend<Anope::string>("dropcode");
code = ci->Extend<Anope::string>("channel-dropcode");
*code = Anope::Random(15);
}
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());
source.Reply(CONFIRM_DROP, ci->name.c_str(), Config->StrictPrivmsg.c_str(),
source.service->nick.c_str(), ci->name.c_str(), code->c_str());
return;
}
@@ -94,6 +94,10 @@ public:
source.Reply(_("Unregisters the named channel. Can only be used by\n"
"the \002channel founder\002."));
source.Reply(" ");
if (source.HasPriv("chanserv/drop/override"))
source.Reply(_("Additionally, Services Operators with the \037chanserv/drop/override\037 permission can\n"
"replace \037code\037 with \002OVERRIDE\002 to drop without a confirmation code."));
return true;
}
};
+2 -8
View File
@@ -166,14 +166,8 @@ private:
return;
}
int l;
try
{
l = convertTo<int>(l_str);
if (l < 0)
throw ConvertException();
}
catch (const ConvertException &)
auto l = Anope::Convert<int>(l_str, -1);
if (l < 0)
{
source.Reply(_("The limit on %s is not valid."), ci->name.c_str());
return;
+13 -18
View File
@@ -32,10 +32,10 @@ struct EntryMsgImpl final
void Serialize(Serialize::Data &data) const override
{
data["ci"] << this->chan;
data["creator"] << this->creator;
data["message"] << this->message;
data.SetType("when", Serialize::Data::DT_INT); data["when"] << this->when;
data.Store("ci", this->chan);
data.Store("creator", this->creator);
data.Store("message", this->message);
data.Store("when", this->when);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data);
@@ -123,7 +123,7 @@ private:
EntryMsg *msg = (*messages)->at(i);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(i + 1);
entry["Creator"] = msg->creator;
entry["Created"] = Anope::strftime(msg->when, NULL, true);
entry["Message"] = msg->message;
@@ -162,21 +162,16 @@ private:
source.Reply(_("Entry message list for \002%s\002 is empty."), ci->name.c_str());
else
{
try
auto i = Anope::Convert<unsigned>(message, 0);
if (i > 0 && i <= (*messages)->size())
{
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();
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());
}
catch (const ConvertException &)
else
{
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", "1024");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -331,7 +331,7 @@ class CommandCSFlags final
ListFormatter::ListEntry entry;
++count;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(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(_("Sorry, channel access list modification is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
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")] = stringify(ci->bantype);
info[_("Ban type")] = Anope::ToString(ci->bantype);
}
FOREACH_MOD(OnChanInfo, (source, ci, info, show_all));
+6 -6
View File
@@ -36,12 +36,10 @@ public:
sepstream(pattern.substr(1), '-').GetToken(n1, 0);
sepstream(pattern, '-').GetToken(n2, 1);
try
{
from = convertTo<int>(n1);
to = convertTo<int>(n2);
}
catch (const ConvertException &)
auto num1 = Anope::TryConvert<int>(n1);
auto num2 = Anope::TryConvert<int>(n2);
if (!num1.has_value() || !num2.has_value())
{
source.Reply(LIST_INCORRECT_RANGE);
source.Reply(_("To search for channels starting with #, search for the channel\n"
@@ -49,6 +47,8 @@ public:
return;
}
from = num1.value();
to = num2.value();
pattern = "*";
}
+11 -11
View File
@@ -37,14 +37,14 @@ struct LogSettingImpl final
void Serialize(Serialize::Data &data) const override
{
data["ci"] << chan;
data["service_name"] << service_name;
data["command_service"] << command_service;
data["command_name"] << command_name;
data["method"] << method;
data["extra"] << extra;
data["creator"] << creator;
data.SetType("created", Serialize::Data::DT_INT); data["created"] << created;
data.Store("ci", chan);
data.Store("service_name", service_name);
data.Store("command_service", command_service);
data.Store("command_name", command_name);
data.Store("method", method);
data.Store("extra", extra);
data.Store("creator", creator);
data.Store("created", created);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
@@ -135,7 +135,7 @@ public:
const LogSetting *log = (*ls)->at(i);
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(i + 1);
entry["Service"] = log->command_service;
entry["Command"] = !log->command_name.empty() ? log->command_name : log->service_name;
entry["Method"] = log->method;
@@ -391,11 +391,11 @@ public:
/* Sending a channel message or notice in response to a fantasy command */;
else if (log->method.equals_ci("MESSAGE") && l->ci->c)
{
IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
IRCD->SendPrivmsg(l->ci->WhoSends(), log->extra + l->ci->c->name, buffer);
l->ci->WhoSends()->lastmsg = Anope::CurTime;
}
else if (log->method.equals_ci("NOTICE") && l->ci->c)
IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, "%s", buffer.c_str());
IRCD->SendNotice(l->ci->WhoSends(), log->extra + l->ci->c->name, buffer);
}
}
}
+10 -9
View File
@@ -205,12 +205,12 @@ struct ModeLocksImpl final
void ModeLockImpl::Serialize(Serialize::Data &data) const
{
data["ci"] << this->ci;
data["set"] << this->set;
data["name"] << this->name;
data["param"] << this->param;
data["setter"] << this->setter;
data.SetType("created", Serialize::Data::DT_INT); data["created"] << this->created;
data.Store("ci", this->ci);
data.Store("set", this->set);
data.Store("name", this->name);
data.Store("param", this->param);
data.Store("setter", this->setter);
data.Store("created", this->created);
}
Serializable *ModeLockImpl::Unserialize(Serializable *obj, Serialize::Data &data)
@@ -336,7 +336,7 @@ class CommandCSMode final
continue;
}
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "32"))
if (modelocks->GetMLock().size() >= Config->GetModule(this->owner)->Get<unsigned>("max", "50"))
{
source.Reply(_("The mode lock list of \002%s\002 is full."), ci->name.c_str());
continue;
@@ -658,7 +658,8 @@ class CommandCSMode final
}
else
{
for (const auto &mode : ci->c->GetModeList(cm->name))
std::vector<Anope::string> v = ci->c->GetModeList(cm->name);
for (const auto &mode : v)
{
if (Anope::Match(mode, param))
ci->c->RemoveMode(NULL, cm, mode);
@@ -716,7 +717,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("-" + stringify(cm->mchar));
new_params.push_back("-" + Anope::ToString(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(_("Sorry, channel registration is temporarily disabled."));
source.Reply(READ_ONLY_MODE);
else if (nc->HasExt("UNCONFIRMED"))
source.Reply(_("You must confirm your account before you can register a channel."));
else if (chan[0] == '&')
+10 -10
View File
@@ -19,7 +19,7 @@ enum TypeInfo
static bool simple;
struct SeenInfo;
static SeenInfo *FindInfo(const Anope::string &nick);
typedef Anope::hash_map<SeenInfo *> database_map;
typedef Anope::unordered_map<SeenInfo *> database_map;
database_map database;
struct SeenInfo final
@@ -46,13 +46,13 @@ struct SeenInfo final
void Serialize(Serialize::Data &data) const override
{
data["nick"] << nick;
data["vhost"] << vhost;
data["type"] << type;
data["nick2"] << nick2;
data["channel"] << channel;
data["message"] << message;
data.SetType("last", Serialize::Data::DT_INT); data["last"] << last;
data.Store("nick", nick);
data.Store("vhost", vhost);
data.Store("type", type);
data.Store("nick2", nick2);
data.Store("channel", channel);
data.Store("message", message);
data.Store("last", last);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
@@ -270,9 +270,9 @@ public:
if (simple)
return this->SimpleSeen(source, params);
if (target.length() > IRCD->GetMaxNick())
if (target.length() > IRCD->MaxNick)
{
source.Reply(_("Nick too long, max length is %zu characters."), IRCD->GetMaxNick());
source.Reply(_("Nick too long, max length is %zu characters."), IRCD->MaxNick);
return;
}
+9 -12
View File
@@ -165,19 +165,16 @@ public:
return;
}
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 &)
auto new_type = Anope::Convert<int16_t>(params[1], -1);
if (new_type < 0 || new_type > 3)
{
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
@@ -1071,7 +1068,7 @@ class CSSet final
if (!last_value.empty())
modes += "," + last_value;
}
data["last_modes"] << modes;
data.Store("last_modes", modes);
}
void ExtensibleUnserialize(Extensible *e, Serializable *s, Serialize::Data &data) override
@@ -1149,7 +1146,7 @@ public:
if (c->ci && keep_modes.HasExt(c->ci))
{
Channel::ModeList ml = c->ci->last_modes;
for (const auto &[last_mode, last_value] : c->ci->last_modes)
for (const auto &[last_mode, last_value] : ml)
c->SetMode(c->ci->WhoSends(), last_mode, last_value);
}
}
+3 -3
View File
@@ -46,9 +46,9 @@ struct CSMiscData final
void Serialize(Serialize::Data &sdata) const override
{
sdata["ci"] << this->object;
sdata["name"] << this->name;
sdata["data"] << this->data;
sdata.Store("ci", this->object);
sdata.Store("name", this->name);
sdata.Store("data", this->data);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
+26 -14
View File
@@ -20,11 +20,11 @@ struct CSSuspendInfo final
void Serialize(Serialize::Data &data) const override
{
data["chan"] << what;
data["by"] << by;
data["reason"] << reason;
data["time"] << when;
data["expires"] << expires;
data.Store("chan", what);
data.Store("by", by);
data.Store("reason", reason);
data.Store("time", when);
data.Store("expires", expires);
}
static Serializable *Unserialize(Serializable *obj, Serialize::Data &data)
@@ -67,7 +67,7 @@ public:
const Anope::string &chan = params[0];
Anope::string expiry = params[1];
Anope::string reason = params.size() > 2 ? params[2] : "";
time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("expire");
time_t expiry_secs = Config->GetModule(this->owner)->Get<time_t>("suspendexpire");
if (!expiry.empty() && expiry[0] != '+')
{
@@ -214,6 +214,13 @@ 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();
@@ -259,23 +266,28 @@ public:
expire = false;
if (!si->expires)
return;
if (si->expires < Anope::CurTime)
if (!Anope::NoExpire && si->expires && si->expires < Anope::CurTime)
{
ci->last_used = Anope::CurTime;
suspend.Unset(ci);
Log(this) << "Expiring suspend for " << ci->name;
Expire(ci);
}
}
EventReturn OnCheckKick(User *u, Channel *c, Anope::string &mask, Anope::string &reason) override
{
if (u->HasMode("OPER") || !c->ci || !suspend.HasExt(c->ci))
if (u->HasMode("OPER") || !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(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
source.Reply(READ_ONLY_MODE);
return;
}
@@ -208,7 +208,7 @@ private:
}
}
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1024");
unsigned access_max = Config->GetModule("chanserv")->Get<unsigned>("accessmax", "1000");
if (access_max && ci->GetDeepAccessCount() >= access_max)
{
source.Reply(_("Sorry, you can only have %d access entries on a channel, including access entries from other channels."), access_max);
@@ -246,7 +246,7 @@ private:
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
source.Reply(READ_ONLY_MODE);
return;
}
@@ -420,7 +420,7 @@ private:
return;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(Number);
entry["Number"] = Anope::ToString(Number);
entry["Mask"] = a->Mask();
entry["Description"] = a->description;
this->list.AddEntry(entry);
@@ -440,7 +440,7 @@ private:
continue;
ListFormatter::ListEntry entry;
entry["Number"] = stringify(i + 1);
entry["Number"] = Anope::ToString(i + 1);
entry["Mask"] = a->Mask();
entry["Description"] = a->description;
list.AddEntry(entry);
@@ -464,7 +464,7 @@ private:
{
if (Anope::ReadOnly)
{
source.Reply(_("Sorry, channel %s list modification is temporarily disabled."), source.command.c_str());
source.Reply(READ_ONLY_MODE);
return;
}
File diff suppressed because it is too large Load Diff
+11 -22
View File
@@ -52,12 +52,7 @@ public:
{
if (token.find("ID ") == 0)
{
try
{
this->id = convertTo<unsigned int>(token.substr(3));
}
catch (const ConvertException &) { }
this->id = Anope::Convert(token.substr(3), 0);
continue;
}
else if (token.find("DATA ") != 0)
@@ -76,14 +71,6 @@ public:
return this->ss;
}
std::set<Anope::string> KeySet() const override
{
std::set<Anope::string> keys;
for (const auto &[key, _]: this->data)
keys.insert(key);
return keys;
}
size_t Hash() const override
{
size_t hash = 0;
@@ -135,8 +122,8 @@ class DBFlatFile final
for (const auto &db : dbs)
{
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);
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));
/* Backup already exists or no database to backup */
if (Anope::IsFile(newname) || !Anope::IsFile(oldname))
@@ -221,7 +208,7 @@ public:
{
std::set<Anope::string> tried_dbs;
const Anope::string &db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
const auto db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
if (!fd.is_open())
@@ -301,9 +288,9 @@ public:
Anope::string db_name;
if (s_type->GetOwner())
db_name = Anope::DataDir + "/module_" + s_type->GetOwner()->name + ".db";
db_name = Anope::ExpandData("module_" + s_type->GetOwner()->name + ".db");
else
db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
std::fstream *fs = databases[s_type->GetOwner()] = new std::fstream((db_name + ".tmp").c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
@@ -316,6 +303,8 @@ public:
for (auto *base : items)
{
Serialize::Type *s_type = base->GetSerializableType();
if (!s_type)
continue;
data.fs = databases[s_type->GetOwner()];
if (!data.fs || !data.fs->is_open())
@@ -330,7 +319,7 @@ public:
for (auto &[mod, f] : databases)
{
const Anope::string &db_name = Anope::DataDir + "/" + (mod ? (mod->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
const auto db_name = Anope::ExpandData((mod ? (mod->name + ".db") : Config->GetModule(this)->Get<const Anope::string>("database", "anope.db")));
if (!f->is_open() || !f->good())
{
@@ -372,9 +361,9 @@ public:
Anope::string db_name;
if (stype->GetOwner())
db_name = Anope::DataDir + "/module_" + stype->GetOwner()->name + ".db";
db_name = Anope::ExpandData("module_" + stype->GetOwner()->name + ".db");
else
db_name = Anope::DataDir + "/" + Config->GetModule(this)->Get<const Anope::string>("database", "anope.db");
db_name = Anope::ExpandData(Config->GetModule(this)->Get<const Anope::string>("database", "anope.db"));
std::fstream fd(db_name.c_str(), std::ios_base::in | std::ios_base::binary);
if (!fd.is_open())
+11 -16
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 E-mail in INFO */
#define OLD_NI_HIDE_EMAIL 0x00000080 /* Don't show email 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, stringify(*limit));
ml->SetMLock(cm, status, Anope::ToString(*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";
std::string rv;
Anope::string rv;
for (size_t i = 0; i < l; ++i)
{
unsigned char c = data[i];
@@ -252,7 +252,7 @@ static Anope::string GetLevelName(int level)
case 15:
return "NOKICK";
case 16:
return "FANTASIA";
return "FANTASY";
case 17:
return "SAY";
case 18:
@@ -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::DataDir + "/" + filename).c_str(), sizeof(f->filename));
strscpy(f->filename, Anope::ExpandData(filename).c_str(), sizeof(f->filename));
f->mode = 'r';
fp = fopen(f->filename, "rb");
if (!fp)
@@ -537,24 +537,18 @@ static void LoadNicks()
case LANG_DE:
nc->language = "de_DE.UTF-8";
break;
case LANG_CAT:
nc->language = "ca_ES.UTF-8"; // yes, iso639 defines catalan as CA
break;
case LANG_GR:
nc->language = "el_GR.UTF-8";
break;
case LANG_NL:
nc->language = "nl_NL.UTF-8";
break;
case LANG_RU:
nc->language = "ru_RU.UTF-8";
break;
case LANG_HUN:
nc->language = "hu_HU.UTF-8";
break;
case LANG_PL:
nc->language = "pl_PL.UTF-8";
break;
case LANG_CAT:
case LANG_HUN:
case LANG_RU:
case LANG_EN_US:
case LANG_JA_JIS:
case LANG_JA_EUC:
@@ -690,7 +684,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 +883,7 @@ static void LoadChannels()
}
}
else
access->AccessUnserialize(stringify(level));
access->AccessUnserialize(Anope::ToString(level));
}
Anope::string mask;
@@ -1348,6 +1342,7 @@ public:
if (ci->c)
ci->c->CheckModes();
}
Anope::SaveDatabases();
}
};
+20 -38
View File
@@ -34,14 +34,6 @@ public:
return *stream;
}
std::set<Anope::string> KeySet() const override
{
std::set<Anope::string> keys;
for (const auto &[key, _] : this->data)
keys.insert(key);
return keys;
}
size_t Hash() const override
{
size_t hash = 0;
@@ -162,7 +154,7 @@ public:
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
/* Get object attrs to clear before updating */
redis->SendCommand(new Updater(this, t->GetName(), obj->id), args);
@@ -248,7 +240,7 @@ public:
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + t->GetName() + ":" + stringify(obj->id));
args.push_back("hash:" + t->GetName() + ":" + Anope::ToString(obj->id));
/* Get all of the attributes for this object */
redis->SendCommand(new Deleter(this, t->GetName(), obj->id), args);
@@ -278,19 +270,14 @@ void TypeLoader::OnResult(const Reply &r)
if (reply->type != Reply::BULK)
continue;
int64_t id;
try
{
id = convertTo<int64_t>(reply->bulk);
}
catch (const ConvertException &)
{
auto i = Anope::TryConvert<int64_t>(reply->bulk);
if (!i)
continue;
}
auto id = i.value();
std::vector<Anope::string> args;
args.emplace_back("HGETALL");
args.push_back("hash:" + this->type + ":" + stringify(id));
args.push_back("hash:" + this->type + ":" + Anope::ToString(id));
me->redis->SendCommand(new ObjectLoader(me, this->type, id), args);
}
@@ -364,7 +351,7 @@ void Deleter::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("DEL");
args.push_back("hash:" + this->type + ":" + stringify(this->id));
args.push_back("hash:" + this->type + ":" + Anope::ToString(this->id));
/* Delete hash object */
me->redis->SendCommand(NULL, args);
@@ -372,7 +359,7 @@ void Deleter::OnResult(const Reply &r)
args.clear();
args.emplace_back("SREM");
args.push_back("ids:" + this->type);
args.push_back(stringify(this->id));
args.push_back(Anope::ToString(this->id));
/* Delete id from ids set */
me->redis->SendCommand(NULL, args);
@@ -385,7 +372,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(stringify(this->id));
args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -428,7 +415,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(stringify(this->id));
args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -438,12 +425,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(stringify(obj->id));
args.push_back(Anope::ToString(obj->id));
me->redis->SendCommand(NULL, args);
args.clear();
args.emplace_back("HMSET");
args.push_back("hash:" + this->type + ":" + stringify(obj->id));
args.push_back("hash:" + this->type + ":" + Anope::ToString(obj->id));
for (const auto &[key, value] : data.data)
{
@@ -454,7 +441,7 @@ void Updater::OnResult(const Reply &r)
args2.emplace_back("SADD");
args2.push_back("value:" + this->type + ":" + key + ":" + value->str());
args2.push_back(stringify(obj->id));
args2.push_back(Anope::ToString(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args2);
@@ -505,16 +492,11 @@ void SubscriptionListener::OnResult(const Reply &r)
if (s_type == NULL)
return;
uint64_t obj_id;
try
{
obj_id = convertTo<uint64_t>(id);
}
catch (const ConvertException &)
{
auto oid = Anope::TryConvert<uint64_t>(id);
if (!oid.has_value())
return;
}
auto obj_id = oid.value();
if (op == "hset" || op == "hdel")
{
Serializable *s = s_type->objects[obj_id];
@@ -564,7 +546,7 @@ void SubscriptionListener::OnResult(const Reply &r)
std::vector<Anope::string> args;
args.emplace_back("SREM");
args.push_back("ids:" + type);
args.push_back(stringify(s->id));
args.push_back(Anope::ToString(s->id));
/* Delete object from id set */
me->redis->SendCommand(NULL, args);
@@ -604,7 +586,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(stringify(this->id));
args.push_back(Anope::ToString(this->id));
/* Delete value -> object id */
me->redis->SendCommand(NULL, args);
@@ -633,7 +615,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(stringify(obj->id));
args.push_back(Anope::ToString(obj->id));
/* Add to value -> object id set */
me->redis->SendCommand(NULL, args);
@@ -642,7 +624,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(stringify(obj->id));
args.push_back(Anope::ToString(obj->id));
/* Add to type -> id set */
me->redis->SendCommand(NULL, args);
+7 -11
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` = " + stringify(obj->id));
this->RunBackground("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
this->updated_items.erase(obj);
}
@@ -240,18 +240,14 @@ 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 -9
View File
@@ -37,7 +37,7 @@ private:
}
else
{
if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "5m") > lastwarn)
if (Anope::CurTime - Config->GetBlock("options")->Get<time_t>("updatetimeout", "2m") > lastwarn)
{
Log() << "Unable to locate SQL reference, going to readonly...";
Anope::ReadOnly = this->ro = true;
@@ -163,7 +163,7 @@ public:
if (s_type)
{
if (obj->id > 0)
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + stringify(obj->id));
this->RunQuery("DELETE FROM `" + this->prefix + s_type->GetName() + "` WHERE `id` = " + Anope::ToString(obj->id));
s_type->objects.erase(obj->id);
}
this->updated_items.erase(obj);
@@ -185,17 +185,16 @@ public:
{
const std::map<Anope::string, Anope::string> &row = res.Row(i);
unsigned int id;
try
{
id = convertTo<unsigned int>(res.Get(i, "id"));
}
catch (const ConvertException &)
auto oid = Anope::TryConvert<unsigned int>(res.Get(i, "id"));
if (!oid.has_value())
{
Log(LOG_DEBUG) << "Unable to convert id from " << obj->GetName();
continue;
}
auto id = oid.value();
if (res.Get(i, "timestamp").empty())
{
clear_null = true;
@@ -237,7 +236,7 @@ public:
else
{
if (!s)
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + stringify(id));
this->RunQuery("UPDATE `" + prefix + obj->GetName() + "` SET `timestamp` = " + this->SQL->FromUnixtime(obj->GetTimestamp()) + " WHERE `id` = " + Anope::ToString(id));
else
delete s;
}
+1 -1
View File
@@ -679,7 +679,7 @@ public:
: Manager(creator)
, Timer(300, true)
, serial(Anope::CurTime)
, cur_id(rand())
, cur_id(Anope::RandomNumber())
{
}
+116 -70
View File
@@ -8,100 +8,154 @@
*
*/
#include "module.h"
#include "modules/encryption.h"
#include <climits>
#include <random>
#include "bcrypt/crypt_blowfish.c"
class EBCRYPT final
: public Module
{
unsigned int rounds;
#include "module.h"
#include "modules/encryption.h"
Anope::string Salt()
class BCryptContext final
: public Encryption::Context
{
private:
Anope::string buffer;
Anope::string GenerateSalt()
{
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 (auto &chr : entropy)
chr = static_cast<char>(rand() % 0xFF);
for (size_t i = 0; i < sizeof(entropy); ++i)
entropy[i] = static_cast<char>(dist(engine));
char salt[32];
if (!_crypt_gensalt_blowfish_rn("$2a$", rounds, entropy, sizeof(entropy), salt, sizeof(salt)))
return "";
{
Log(LOG_DEBUG) << "Unable to generate a salt for Bcrypt: " << strerror(errno);
return {};
}
return salt;
}
static Anope::string Generate(const Anope::string &data, const Anope::string &salt)
public:
static unsigned long rounds;
static Anope::string Hash(const Anope::string &data, const Anope::string &salt)
{
char hash[64];
_crypt_blowfish_rn(data.c_str(), salt.c_str(), hash, sizeof(hash));
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 {};
}
return hash;
}
bool Compare(const Anope::string &string, const Anope::string &hash)
void Update(const unsigned char *data, size_t len) override
{
Anope::string ret = Generate(string, hash);
if (ret.empty())
return false;
return (ret == hash);
buffer.append(reinterpret_cast<const char *>(data), len);
}
public:
EBCRYPT(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
rounds(10)
Anope::string Finalize() override
{
// Test a pre-calculated hash
bool test = Compare("Test!", "$2a$10$x9AQFAQScY0v9KF2suqkEOepsHFrG.CXHbIXI.1F28SfSUb56A/7K");
auto salt = GenerateSalt();
if (salt.empty())
return {};
return Hash(this->buffer, salt);
}
};
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!");
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)
{
bcryptprovider.Check({
{ "$2a$10$c9lUAuJmTYXEfNuLOiyIp.lZTMM.Rw5qsSAyZhvGT9EC3JevkUuOu", "" },
{ "$2a$10$YV4jDSGs0ZtQbpL6IHtNO.lt5Q.uzghIohCcnERQVBGyw7QJMfyhe", "The quick brown fox jumps over the lazy dog" },
});
}
EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) override
{
dest = "bcrypt:" + Generate(src, Salt());
dest = "bcrypt:" + bcryptprovider.Encrypt(src);
Log(LOG_DEBUG_2) << "(enc_bcrypt) hashed password from [" << src << "] to [" << dest << "]";
return EVENT_ALLOW;
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
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 != "bcrypt")
if (!hash_method.equals_cs("bcrypt"))
return;
if (Compare(req->GetPassword(), nc->pass.substr(7)))
Anope::string hash_value(nc->pass.begin() + pos + 1, nc->pass.end());
if (bcryptprovider.Compare(hash_value, req->GetPassword()))
{
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
unsigned long rounds = 0;
unsigned int hashrounds = 0;
try
{
size_t roundspos = nc->pass.find('$', 11);
if (roundspos == Anope::string::npos)
throw ConvertException("Could not find hashrounds");
// 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);
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 (!rounds)
Log(LOG_DEBUG) << "Unable to determine the rounds of a bcrypt hash: " << hash_value;
if (ModuleManager::FindFirstOf(ENCRYPTION) != this || (hashrounds && hashrounds != rounds))
// 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))
Anope::Encrypt(req->GetPassword(), nc->pass);
req->Success(this);
}
@@ -109,28 +163,20 @@ public:
void OnReload(Configuration::Conf *conf) override
{
Configuration::Block *block = conf->GetModule(this);
rounds = block->Get<unsigned int>("rounds", "10");
auto *block = conf->GetModule(this);
if (rounds == 0)
auto rounds = block->Get<unsigned long>("rounds", "10");
if (rounds < 10 || rounds > 32)
{
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.";
Log(this) << "Bcrypt rounds MUST be between 10 and 32 inclusive; using 10 instead of " << rounds << '.';
BCryptContext::rounds = 10;
return;
}
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)
+29 -337
View File
@@ -5,7 +5,7 @@
* Contact us at team@anope.org
*
* Taken from IRC Services and is copyright (c) 1996-2002 Andrew Church.
* E-mail: <achurch@achurch.org>
* Email: <achurch@achurch.org>
* Parts written by Andrew Kempe and others.
* This program is free but copyrighted software; see the file COPYING for
* details.
@@ -14,381 +14,73 @@
#include "module.h"
#include "modules/encryption.h"
/* 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
};
#include "md5/md5.c"
class MD5Context final
: public Encryption::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);
}
private:
MD5_CTX context;
public:
MD5Context(Encryption::IV *iv = NULL)
MD5Context()
{
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_Init(&context);
}
/* 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
{
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);
MD5_Update(&context, input, len);
}
/* MD5 finalization. Ends an MD5 message-digest opera
* the message digest and zeroizing the context.
*/
void Finalize() override
Anope::string Finalize() override
{
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;
unsigned char digest[16];
MD5_Final(digest, &context);
return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
}
};
class EMD5 final
: public Module
{
MD5Provider md5provider;
private:
Encryption::SimpleProvider<MD5Context> md5provider;
public:
EMD5(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
md5provider(this)
EMD5(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, md5provider(this, "md5", 16, 64)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_md5 is deprecated and can not be used as a primary encryption method");
}
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;
md5provider.Check({
{ "d41d8cd98f00b204e9800998ecf8427e", "" },
{ "9e107d9d372bb6826bd81d3542a419d6", "The quick brown fox jumps over the lazy dog" },
});
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
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("md5"))
return;
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
auto enc = "md5:" + Anope::Hex(md5provider.Encrypt(req->GetPassword()));
if (nc->pass.equals_cs(enc))
{
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
// 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);
+13 -22
View File
@@ -13,44 +13,35 @@ 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 NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
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("plain"))
return;
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
Anope::string b64pass;
Anope::B64Encode(req->GetPassword(), b64pass);
auto enc = "plain:" + b64pass;
if (nc->pass.equals_cs(enc))
{
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
// 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);
+37 -65
View File
@@ -12,39 +12,41 @@
#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
{
OldMD5Provider oldmd5provider;
private:
ServiceReference<Encryption::Provider> md5;
inline static char XTOI(char c) { return c > 9 ? c - 'A' + 10 : c - '0'; }
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';
}
public:
EOld(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
oldmd5provider(this)
EOld(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, md5("Encryption::Provider", "md5")
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_old is deprecated and can not be used as a primary encryption method");
@@ -52,58 +54,28 @@ 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 NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
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;
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
auto enc = EncryptInternal(req->GetPassword());
if (!enc.empty() && nc->pass.equals_cs(enc))
{
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
// 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);
+26 -67
View File
@@ -60,7 +60,6 @@ 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])
{
@@ -108,22 +107,13 @@ class SHA1Context final
}
public:
SHA1Context(Encryption::IV *iv = NULL)
SHA1Context()
{
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];
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
@@ -147,7 +137,7 @@ public:
memcpy(&this->buffer[j], &data[i], len - i);
}
void Finalize() override
Anope::string Finalize() override
{
uint32_t i;
unsigned char finalcount[8];
@@ -158,8 +148,10 @@ 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)
this->digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
digest[i] = static_cast<unsigned char>((this->state[i>>2] >> ((3 - (i & 3)) * 8)) & 255);
/* Wipe variables */
memset(this->buffer, 0, sizeof(this->buffer));
@@ -168,84 +160,51 @@ public:
memset(&finalcount, 0, sizeof(finalcount));
this->Transform(this->buffer);
}
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;
return Anope::string(reinterpret_cast<const char *>(&digest), sizeof(digest));
}
};
class ESHA1 final
: public Module
{
SHA1Provider sha1provider;
private:
Encryption::SimpleProvider<SHA1Context> sha1provider;
public:
ESHA1(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR),
sha1provider(this)
ESHA1(const Anope::string &modname, const Anope::string &creator)
: Module(modname, creator, ENCRYPTION | VENDOR)
, sha1provider(this, "sha1", 20, 64)
{
if (ModuleManager::FindFirstOf(ENCRYPTION) == this)
throw ModuleException("enc_sha1 is deprecated and can not be used as a primary encryption method");
}
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;
sha1provider.Check({
{ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "" },
{ "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", "The quick brown fox jumps over the lazy dog" },
});
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
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("sha1"))
return;
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
auto enc = "sha1:" + Anope::Hex(sha1provider.Encrypt(req->GetPassword()));
if (nc->pass.equals_cs(enc))
{
// 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
@@ -0,0 +1,200 @@
/* 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)
+33 -262
View File
@@ -1,247 +1,21 @@
/* 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
*
* 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.
*
* This program is free but copyrighted software; see
* the file COPYING for details.
*/
/* 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 "sha2/sha2.c"
#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
{
SHA256Provider sha256provider;
private:
unsigned iv[8];
bool use_iv;
@@ -249,7 +23,7 @@ class ESHA256 final
void NewRandomIV()
{
for (auto &ivsegment : iv)
ivsegment = static_cast<uint32_t>(rand());
ivsegment = static_cast<uint32_t>(Anope::RandomNumber());
}
/* returns the IV as base64-encrypted string */
@@ -271,62 +45,59 @@ class ESHA256 final
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]);
}
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
Anope::string EncryptInternal(const Anope::string &src)
{
if (!use_iv)
NewRandomIV();
else
use_iv = false;
Encryption::IV initialization(this->iv, 8);
SHA256Context ctx(&initialization);
ctx.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length());
ctx.Finalize();
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::Hash hash = ctx.GetFinalizedHash();
return "sha256:" + Anope::Hex(hash) + ":" + GetIVString();
}
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;
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");
}
void OnCheckAuthentication(User *, IdentifyRequest *req) override
{
const NickAlias *na = NickAlias::Find(req->GetAccount());
if (na == NULL)
const auto *na = NickAlias::Find(req->GetAccount());
if (!na)
return;
NickCore *nc = na->nc;
size_t pos = nc->pass.find(':');
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("sha256"))
return;
GetIVFromPass(nc->pass);
use_iv = true;
Anope::string buf;
this->OnEncrypt(req->GetPassword(), buf);
if (nc->pass.equals_cs(buf))
auto enc = EncryptInternal(req->GetPassword());
if (nc->pass.equals_cs(enc))
{
/* if we are NOT the first module in the list,
* we want to re-encrypt the pass with the new encryption
*/
// 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);
+199
View File
@@ -0,0 +1,199 @@
/* 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
@@ -0,0 +1,53 @@
/* 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)
+70 -26
View File
@@ -121,6 +121,7 @@ class MySQLService final
Anope::string user;
Anope::string password;
unsigned int port;
Anope::string socket;
MYSQL *sql = nullptr;
@@ -136,7 +137,7 @@ public:
*/
std::mutex Lock;
MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po);
MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po, const Anope::string &so);
~MySQLService();
@@ -157,6 +158,29 @@ public:
Anope::string BuildQuery(const Query &q);
Anope::string FromUnixtime(time_t) override;
Anope::string GetColumnType(Serialize::DataType dt)
{
switch (dt)
{
case Serialize::DataType::BOOL:
return "TINYINT NOT NULL";
case Serialize::DataType::FLOAT:
return "DOUBLE PRECISION NOT NULL";
case Serialize::DataType::INT:
return "BIGINT NOT NULL";
case Serialize::DataType::TEXT:
return "TEXT";
case Serialize::DataType::UINT:
return "BIGINT UNSIGNED NOT NULL";
}
return "TEXT"; // Should never be reached
}
};
/** The SQL thread used to execute queries
@@ -248,13 +272,14 @@ public:
const Anope::string &user = block->Get<const Anope::string>("username", "anope");
const Anope::string &password = block->Get<const Anope::string>("password");
unsigned int port = block->Get<unsigned int>("port", "3306");
const Anope::string &socket = block->Get<const Anope::string>("socket");
try
{
auto *ss = new MySQLService(this, connname, database, server, user, password, port);
auto *ss = new MySQLService(this, connname, database, server, user, password, port, socket);
this->MySQLServices.emplace(connname, ss);
Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << server << ")";
Log(LOG_NORMAL, "mysql") << "MySQL: Successfully connected to server " << connname << " (" << (socket.empty() ? server + ":" + port : socket) << ")";
}
catch (const SQL::Exception &ex)
{
@@ -309,13 +334,14 @@ public:
}
};
MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po)
MySQLService::MySQLService(Module *o, const Anope::string &n, const Anope::string &d, const Anope::string &s, const Anope::string &u, const Anope::string &p, unsigned int po, const Anope::string &so)
: Provider(o, n)
, database(d)
, server(s)
, user(u)
, password(p)
, port(po)
, socket(so)
{
Connect();
}
@@ -354,9 +380,14 @@ Result MySQLService::RunQuery(const Query &query)
{
this->Lock.lock();
Anope::string real_query = this->BuildQuery(query);
if (!this->CheckConnection())
{
this->Lock.unlock();
return MySQLResult(query, query.query, mysql_error(this->sql));
}
if (this->CheckConnection() && !mysql_real_query(this->sql, real_query.c_str(), real_query.length()))
Anope::string real_query = this->BuildQuery(query);
if (!mysql_real_query(this->sql, real_query.c_str(), real_query.length()))
{
MYSQL_RES *res = mysql_store_result(this->sql);
unsigned int id = mysql_insert_id(this->sql);
@@ -402,19 +433,15 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
if (known_cols.empty())
{
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,"
Anope::string query_text = "CREATE TABLE `" + table + "` (`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,"
" `timestamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP";
for (const auto &[column, _] : data.data)
{
known_cols.insert(column);
query_text += ", `" + column + "` ";
if (data.GetType(column) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
query_text += ", `" + column + "` " + GetColumnType(data.GetType(column));
}
query_text += ", PRIMARY KEY (`id`), KEY `timestamp_idx` (`timestamp`))";
query_text += ", PRIMARY KEY (`id`), KEY `timestamp_idx` (`timestamp`)) ROW_FORMAT=DYNAMIC";
queries.push_back(query_text);
}
else
@@ -426,11 +453,7 @@ std::vector<Query> MySQLService::CreateTable(const Anope::string &table, const D
known_cols.insert(column);
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` ";
if (data.GetType(column) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumnType(data.GetType(column));
queries.push_back(query_text);
}
@@ -452,7 +475,7 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
for (const auto &[field, _] : data.data)
query_text += ",`" + field + "`";
query_text += ") VALUES (" + stringify(id);
query_text += ") VALUES (" + Anope::ToString(id);
for (const auto &[field, _] : data.data)
query_text += ",@" + field + "@";
query_text += ") ON DUPLICATE KEY UPDATE ";
@@ -466,11 +489,29 @@ Query MySQLService::BuildInsert(const Anope::string &table, unsigned int id, Dat
Anope::string buf;
*value >> buf;
bool escape = true;
if (buf.empty())
auto escape = true;
switch (data.GetType(field))
{
buf = "NULL";
escape = false;
case Serialize::DataType::BOOL:
case Serialize::DataType::FLOAT:
case Serialize::DataType::INT:
case Serialize::DataType::UINT:
{
if (buf.empty())
buf = "0";
escape = false;
break;
}
case Serialize::DataType::TEXT:
{
if (buf.empty())
{
buf = "NULL";
escape = false;
}
break;
}
}
query.SetValue(field, buf, escape);
@@ -491,12 +532,15 @@ void MySQLService::Connect()
const unsigned int timeout = 1;
mysql_options(this->sql, MYSQL_OPT_CONNECT_TIMEOUT, reinterpret_cast<const char *>(&timeout));
bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, NULL, CLIENT_MULTI_RESULTS);
bool connect = mysql_real_connect(this->sql, this->server.c_str(), this->user.c_str(), this->password.c_str(), this->database.c_str(), this->port, this->socket.empty() ? nullptr : this->socket.c_str(), CLIENT_MULTI_RESULTS);
if (!connect)
throw SQL::Exception("Unable to connect to MySQL service " + this->name + ": " + mysql_error(this->sql));
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
if (this->socket.empty())
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->server << ":" << this->port;
else
Log(LOG_DEBUG) << "Successfully connected to MySQL service " << this->name << " at " << this->socket;
}
@@ -536,7 +580,7 @@ Anope::string MySQLService::BuildQuery(const Query &q)
Anope::string MySQLService::FromUnixtime(time_t t)
{
return "FROM_UNIXTIME(" + stringify(t) + ")";
return "FROM_UNIXTIME(" + Anope::ToString(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 " + stringify(erroffset) + ": " + reinterpret_cast<const char*>(error));
throw RegexException("Error in regex " + expr + " at offset " + Anope::ToString(erroffset) + ": " + reinterpret_cast<const char*>(error));
}
}
+57 -15
View File
@@ -68,6 +68,31 @@ public:
Anope::string BuildQuery(const Query &q);
Anope::string FromUnixtime(time_t) override;
Anope::string GetColumnType(Serialize::DataType dt)
{
switch (dt)
{
case Serialize::DataType::BOOL:
return "INTEGER";
case Serialize::DataType::FLOAT:
return "REAL";
case Serialize::DataType::INT:
return "INTEGER";
case Serialize::DataType::TEXT:
return "TEXT";
// SQLite lacks support for 64-bit unsigned integers so we have to
// store them as text columns instead.
case Serialize::DataType::UINT:
return "TEXT";
}
return "TEXT"; // Should never be reached
}
};
class ModuleSQLite final
@@ -118,8 +143,7 @@ public:
if (this->SQLiteServices.find(connname) == this->SQLiteServices.end())
{
Anope::string database = Anope::DataDir + "/" + block->Get<const Anope::string>("database", "anope");
auto database = Anope::ExpandData(block->Get<const Anope::string>("database", "anope"));
try
{
auto *ss = new SQLiteService(this, connname, database);
@@ -238,11 +262,7 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
{
known_cols.insert(column);
query_text += ", `" + column + "` ";
if (data.GetType(column) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
query_text += ", `" + column + "` " + GetColumnType(data.GetType(column));
}
query_text += ")";
@@ -267,11 +287,7 @@ std::vector<Query> SQLiteService::CreateTable(const Anope::string &table, const
known_cols.insert(column);
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` ";
if (data.GetType(column) == Serialize::Data::DT_INT)
query_text += "int(11)";
else
query_text += "text";
Anope::string query_text = "ALTER TABLE `" + table + "` ADD `" + column + "` " + GetColumnType(data.GetType(column));;
queries.push_back(query_text);
}
@@ -297,7 +313,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 += stringify(id) + ",";
query_text += Anope::ToString(id) + ",";
for (const auto &[field, _] : data.data)
query_text += "@" + field + "@,";
query_text.erase(query_text.length() - 1);
@@ -308,7 +324,33 @@ Query SQLiteService::BuildInsert(const Anope::string &table, unsigned int id, Da
{
Anope::string buf;
*value >> buf;
query.SetValue(field, buf);
auto escape = true;
switch (data.GetType(field))
{
case Serialize::DataType::BOOL:
case Serialize::DataType::FLOAT:
case Serialize::DataType::INT:
{
if (buf.empty())
buf = "0";
escape = false;
break;
}
case Serialize::DataType::TEXT:
case Serialize::DataType::UINT:
{
if (buf.empty())
{
buf = "NULL";
escape = false;
}
break;
}
}
query.SetValue(field, buf, escape);
}
return query;
@@ -339,7 +381,7 @@ Anope::string SQLiteService::BuildQuery(const Query &q)
Anope::string SQLiteService::FromUnixtime(time_t t)
{
return "datetime('" + stringify(t) + "', 'unixepoch')";
return "datetime('" + Anope::ToString(t) + "', 'unixepoch')";
}
MODULE_INIT(ModuleSQLite)

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